pax_global_header00006660000000000000000000000064135757427470014537gustar00rootroot0000000000000052 comment=f90be6a2886bba1a1db67b4aacb810fb296b463f mapserver-7.4.3/000077500000000000000000000000001357574274700135565ustar00rootroot00000000000000mapserver-7.4.3/CMakeLists.txt000066400000000000000000001151501357574274700163210ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.6) project (MapServer) if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") message(FATAL_ERROR "In-source builds are not permitted. Make a separate folder for building: mkdir build; cd build; cmake .. Before that, remove the files created by this failed run: rm -rf CMakeCache.txt CMakeFiles") endif("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") include(CheckLibraryExists) include(CheckFunctionExists) include(CheckIncludeFile) include(CheckCSourceCompiles) set (MapServer_VERSION_MAJOR 7) set (MapServer_VERSION_MINOR 4) set (MapServer_VERSION_REVISION 3) set (MapServer_VERSION_SUFFIX "") set(TARGET_VERSION_MAJOR ${MapServer_VERSION_MAJOR}) set(TARGET_VERSION_MINOR ${MapServer_VERSION_MINOR}) MATH(EXPR MapServer_IS_DEV_VERSION "${MapServer_VERSION_MINOR}%2") if(MapServer_IS_DEV_VERSION) set (MapServer_VERSION_STRING "${MapServer_VERSION_MAJOR}.${MapServer_VERSION_MINOR}-dev") else(MapServer_IS_DEV_VERSION) set (MapServer_VERSION_STRING "${MapServer_VERSION_MAJOR}.${MapServer_VERSION_MINOR}.${MapServer_VERSION_REVISION}") set (MapServer_VERSION_STRING "${MapServer_VERSION_STRING}${MapServer_VERSION_SUFFIX}") endif(MapServer_IS_DEV_VERSION) MATH(EXPR MapServer_VERSION_NUM "${MapServer_VERSION_MAJOR}*10000+${MapServer_VERSION_MINOR}*100+${MapServer_VERSION_REVISION}") SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) # Add custom function to check Python modules are installed include(FindPythonModule) if (APPLE) set(CMAKE_FIND_FRAMEWORK "LAST") endif (APPLE) # Offer the user the choice of overriding the installation directories set(INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") if(WIN32 AND NOT CYGWIN) set(DEF_INSTALL_CMAKE_DIR CMake) else() set(DEF_INSTALL_CMAKE_DIR share/mapserver/cmake) endif() set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") # Make relative paths absolute (needed later on) foreach(p LIB BIN INCLUDE CMAKE) set(var INSTALL_${p}_DIR) if(NOT IS_ABSOLUTE "${${var}}") set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") endif() endforeach() macro (ms_link_libraries) if(BUILD_DYNAMIC) target_link_libraries(mapserver ${ARGV}) endif(BUILD_DYNAMIC) if(BUILD_STATIC) target_link_libraries(mapserver_static ${ARGV}) endif(BUILD_STATIC) endmacro() macro( report_optional_not_found component ) message(SEND_ERROR "${component} library/component/dependency could not be found. HINTS: - disable ${component} support by adding -DWITH_${component}=0 - add the ${component} install directory to the CMAKE_PREFIX_PATH variable (-DCMAKE_PREFIX_PATH=\"/path/to/${component}-install-dir;/path/to/other/dirs\"") endmacro() macro( report_mandatory_not_found component ) message(SEND_ERROR "${component} library/component could not be found and is a mandatory dependency HINT: - add the ${component} install directory to the CMAKE_PREFIX_PATH variable (-DCMAKE_PREFIX_PATH=\"/path/to/${component}-install-dir;/path/to/other/dirs\"") endmacro() macro( report_dependency_error component dependency) message(SEND_ERROR "${component} support requires ${dependency} support, however ${dependency} support has been disabled. HINTS: - re-run with -DWITH_${dependency}=1 (or without -DWITH_${dependency}=0) - disable ${component} support by adding -DWITH_${component}=0" ) endmacro() SET(CMAKE_REQUIRED_INCLUDES "math.h") if(NOT(WIN32)) SET(CMAKE_REQUIRED_LIBRARIES "m") endif(NOT(WIN32)) check_function_exists("strrstr" HAVE_STRRSTR) check_function_exists("strcasecmp" HAVE_STRCASECMP) check_function_exists("strcasestr" HAVE_STRCASESTR) check_function_exists("strlcat" HAVE_STRLCAT) check_function_exists("strlcpy" HAVE_STRLCPY) check_function_exists("strlen" HAVE_STRLEN) check_function_exists("strncasecmp" HAVE_STRNCASECMP) check_function_exists("vsnprintf" HAVE_VSNPRINTF) check_function_exists("lrintf" HAVE_LRINTF) check_function_exists("lrint" HAVE_LRINT) check_include_file(dlfcn.h HAVE_DLFCN_H) check_c_source_compiles(" int main(int argc, char **argv) { long x=0,y=0; for(x=0;x<5;x++) { if(y>1) break; y=__sync_fetch_and_add(&x,1); } }" HAVE_SYNC_FETCH_AND_ADD) include_directories(${CMAKE_CURRENT_BINARY_DIR}) #options suported by the cmake builder option(WITH_PROJ "Choose if reprojection support should be built in" ON) option(WITH_PROTOBUFC "Choose if protocol buffers support should be built in (required for vector tiles)" ON) option(WITH_KML "Enable native KML output support (requires libxml2 support)" OFF) option(WITH_SOS "Enable SOS Server support (requires PROJ and libxml2 support)" OFF) option(WITH_WMS "Enable WMS Server support (requires proj support)" ON) option(WITH_FRIBIDI "Choose if FriBidi glyph shaping support should be built in (usefull for right-to-left languages) (requires HARFBUZZ)" ON) option(WITH_HARFBUZZ "Choose if Harfbuzz complex text layout should be included (needed for e.g. arabic and hindi) (requires FRIBIDI)" ON) option(WITH_ICONV "Choose if Iconv Internationalization support should be built in" ON) option(WITH_CAIRO "Choose if CAIRO rendering support should be built in (required for SVG and PDF output)" ON) option(WITH_SVGCAIRO "Choose if SVG symbology support (via libsvgcairo) should be built in (requires cairo, libsvg, libsvg-cairo. Incompatible with librsvg)" OFF) option(WITH_RSVG "Choose if SVG symbology support (via librsvg) should be built in (requires cairo, librsvg. Incompatible with libsvg-cairo)" OFF) option(WITH_MYSQL "Choose if MYSQL joining support should be built in" OFF) option(WITH_FCGI "Choose if FastCGI support should be built in" ON) option(WITH_GEOS "Choose if GEOS geometry operations support should be built in" ON) option(WITH_POSTGIS "Choose if Postgis input support should be built in" ON) option(WITH_GDAL "Choose if GDAL input raster support should be built in" ON) option(WITH_OGR "Choose if OGR/GDAL input vector support should be built in" ON) option(WITH_CLIENT_WMS "Enable Client WMS Layer support (requires CURL and GDAL support)" OFF) option(WITH_CLIENT_WFS "Enable Client WMS Layer support (requires CURL and OGR support)" OFF) option(WITH_CURL "Enable Curl HTTP support (required for wms/wfs client, and remote SLD)" OFF) option(WITH_WFS "Enable WFS Server support (requires PROJ and OGR support)" ON) option(WITH_WCS "Enable WCS Server support (requires PROJ and GDAL support)" ON) option(WITH_LIBXML2 "Choose if libxml2 support should be built in (used for sos, wcs 1.1,2.0 and wfs 1.1)" ON) option(WITH_THREAD_SAFETY "Choose if a thread-safe version of libmapserver should be built (only recommended for some mapscripts)" OFF) option(WITH_GIF "Enable GIF support (for PIXMAP loading)" ON) option(WITH_PYTHON "Enable Python mapscript support" OFF) option(WITH_PHP "Enable PHP mapscript support" OFF) option(WITH_PHPNG "Enable PHPNG (SWIG) mapscript support" OFF) option(WITH_PERL "Enable Perl mapscript support" OFF) option(WITH_RUBY "Enable Ruby mapscript support" OFF) option(WITH_JAVA "Enable Java mapscript support" OFF) option(WITH_CSHARP "Enable C# mapscript support" OFF) option(WITH_POINT_Z_M "include Z and M coordinates in point structure (advanced, not recommended)" OFF) option(WITH_ORACLESPATIAL "include oracle spatial database input support" OFF) option(WITH_ORACLE_PLUGIN "include oracle spatial database input support as plugin" OFF) option(WITH_MSSQL2008 "include mssql 2008 database input support as plugin" OFF) option(WITH_EXEMPI "include xmp output metadata support" OFF) option(WITH_XMLMAPFILE "include native xml mapfile support (requires libxslt/libexslt)" OFF) option(WITH_V8 "include javacript v8 scripting" OFF) option(WITH_PIXMAN "use (experimental) support for pixman for layer compositing operations" OFF) option(BUILD_STATIC "Also build a static version of mapserver" OFF) option(LINK_STATIC_LIBMAPSERVER "Link to static version of libmapserver (also for mapscripts)" OFF) option(WITH_APACHE_MODULE "include (experimental) support for apache module" OFF) option(WITH_GENERIC_NINT "generic rounding" OFF) #TODO: USE_OGL? , USE_SDE, USE_CLUSTER_EXTERNAL USE_CLUSTER_PLUGIN, USE_MSSQL2008, USE_MSSQL2008_PLUGIN # SIGNORE_MISSING_DATA, CGI_CL_DEBUG_ARGS, EXTRA DEBUG FLAGS?, # PERLV_ld_DETECT? # Add compiler flags for warnings if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=format-security -Wdeclaration-after-statement") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror=format-security") endif() if(NOT DEFINED CMAKE_INSTALL_LIBDIR) set(_LIBDIR_DEFAULT "lib") # Override this default 'lib' with 'lib64' iff: # - we are on Linux system but NOT cross-compiling # - we are NOT on debian # - we are on a 64 bits system # reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf # Note that the future of multi-arch handling may be even # more complicated than that: http://wiki.debian.org/Multiarch if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT CMAKE_CROSSCOMPILING AND NOT EXISTS "/etc/debian_version") if(NOT DEFINED CMAKE_SIZEOF_VOID_P) message(AUTHOR_WARNING "Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. " "Please enable at least one language before including GNUInstallDirs.") else() if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(_LIBDIR_DEFAULT "lib64") endif() endif() endif() set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})") endif() SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) SET(CMAKE_MACOSX_RPATH ON) if(LINK_STATIC_LIBMAPSERVER) set(BUILD_STATIC 1) set(BUILD_DYNAMIC 0) set(MAPSERVER_LIBMAPSERVER mapserver_static) else(LINK_STATIC_LIBMAPSERVER) set(BUILD_DYNAMIC 1) set(MAPSERVER_LIBMAPSERVER mapserver) endif(LINK_STATIC_LIBMAPSERVER) set(agg_SOURCES renderers/agg/src/agg_arc.cpp renderers/agg/src/agg_vcgen_dash.cpp renderers/agg/src/agg_vcgen_contour.cpp renderers/agg/src/agg_curves.cpp renderers/agg/src/agg_embedded_raster_fonts.cpp renderers/agg/src/agg_trans_affine.cpp renderers/agg/src/agg_vcgen_stroke.cpp renderers/agg/src/agg_font_freetype.cpp renderers/agg/src/agg_line_aa_basics.cpp renderers/agg/src/clipper.cpp ) include_directories(renderers/agg/include) set(v8_SOURCES mapscript/v8/v8_object_wrap.hpp mapscript/v8/point.cpp mapscript/v8/line.cpp mapscript/v8/shape.cpp mapscript/v8/v8_mapscript.cpp mapv8.cpp ) include_directories(mapscript/v8/) #add_definitions(-DHASH_DEBUG=1) if(WIN32) set(REGEX_SOURCES ${REGEX_DIR}/regex.c) include_directories(${REGEX_DIR}) add_definitions(-DREGEX_MALLOC -DUSE_GENERIC_MS_NINT -DHAVE_STRING_H) add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) set(REGEX_MALLOC 1) set(USE_GENERIC_MS_NINT 1) set(HAVE_STRING_H 0) else(WIN32) set(REGEX_SOURCES "") endif(WIN32) set(mapserver_SOURCES fontcache.c cgiutil.c mapgeos.c maporaclespatial.c mapsearch.c mapwms.c classobject.c mapgml.c mapoutput.c mapwmslayer.c layerobject.c mapgraticule.c mapows.c mapservutil.c mapxbase.c maphash.c mapowscommon.c mapshape.c mapxml.c mapbits.c maphttp.c mapparser.c mapstring.c mapxmp.c mapcairo.c mapimageio.c mappluginlayer.c mapsymbol.c mapchart.c mapimagemap.c mappool.c maptclutf.c mapcluster.c mapio.c mappostgis.c maptemplate.c mapcontext.c mapjoin.c mappostgresql.c mapthread.c mapcopy.c maplabel.c mapprimitive.c maptile.c mapcpl.c maplayer.c mapproject.c maptime.c mapcrypto.c maplegend.c hittest.c mapprojhack.c maptree.c mapdebug.c maplexer.c mapquantization.c mapunion.c mapdraw.c maplibxml2.c mapquery.c maputil.c strptime.c mapdrawgdal.c mapraster.c mapuvraster.c mapdummyrenderer.c mapobject.c maprasterquery.c mapwcs.c maperror.c mapogcfilter.c mapregex.c mapwcs11.c mapfile.c mapogcfiltercommon.c maprendering.c mapwcs20.c mapogcsld.c mapmetadata.c mapresample.c mapwfs.c mapgdal.c mapogcsos.c mapscale.c mapwfs11.c mapwfs20.c mapgeomtransform.c mapogroutput.c mapwfslayer.c mapagg.cpp mapkml.cpp mapgeomutil.cpp mapkmlrenderer.cpp fontcache.c textlayout.c maputfgrid.cpp mapogr.cpp mapcontour.c mapsmoothing.c mapv8.cpp ${REGEX_SOURCES} kerneldensity.c mapcompositingfilter.c mapmvt.c) set(mapserver_HEADERS cgiutil.h dejavu-sans-condensed.h dxfcolor.h fontcache.h hittest.h mapagg.h mapaxisorder.h mapcopy.h mapentities.h maperror.h mapfile.h mapgml.h maphash.h maphttp.h mapio.h mapkmlrenderer.h maplibxml2.h mapogcfilter.h mapogcsld.h mapoglcontext.h mapoglrenderer.h mapowscommon.h mapows.h mapparser.h mappostgis.h mapprimitive.h mapproject.h mapraster.h mapregex.h mapresample.h mapserver-api.h mapserver.h mapserv.h mapshape.h mapsymbol.h maptemplate.h mapthread.h maptile.h maptime.h maptree.h maputfgrid.h mapwcs.h uthash.h) if(WIN32) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) set(mapserver_SOURCES ${mapserver_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) endif(WIN32) if(WITH_PROTOBUFC) find_package(ProtobufC) if(NOT PROTOBUFC_FOUND) report_optional_not_found(PROTOBUFC) else(NOT PROTOBUFC_FOUND) list(APPEND ALL_INCLUDE_DIRS ${PROTOBUFC_INCLUDE_DIR}) FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/renderers/mvt) # Create custom command for protoc-c ADD_CUSTOM_COMMAND( COMMAND ${PROTOBUFC_COMPILER} ARGS --c_out=${PROJECT_BINARY_DIR}/renderers/mvt --proto_path=${PROJECT_SOURCE_DIR}/renderers/mvt ${PROJECT_SOURCE_DIR}/renderers/mvt/vector_tile.proto OUTPUT ${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.c ${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.h ) SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.h ${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.c GENERATED) set (vectortile_SOURCES ${PROJECT_BINARY_DIR}/renderers/mvt/vector_tile.pb-c.c) set (USE_PBF 1) endif(NOT PROTOBUFC_FOUND) endif (WITH_PROTOBUFC) if(BUILD_DYNAMIC) add_library(mapserver SHARED ${vectortile_SOURCES} ${mapserver_SOURCES} ${agg_SOURCES} ${v8_SOURCES}) set_target_properties( mapserver PROPERTIES VERSION ${MapServer_VERSION_STRING} SOVERSION 2 ) endif(BUILD_DYNAMIC) if(BUILD_STATIC) add_library(mapserver_static STATIC ${vectortile_SOURCES} ${mapserver_SOURCES} ${agg_SOURCES} ${v8_SOURCES}) set_target_properties( mapserver_static PROPERTIES VERSION ${MapServer_VERSION_STRING} SOVERSION 2 ) endif(BUILD_STATIC) #SOVERSION is not necessarily the same as the #major version. The rule is that any breakage of the ABI must be #indicated by incrementing the SOVERSION. So, adding e.g. functions is no #problem, modifying argument lists or removing functions would required #the SOVERSION to be incremented. Similar rules hold of course for #non-opaque data-structures. add_executable(mapserv mapserv.c) target_link_libraries(mapserv ${MAPSERVER_LIBMAPSERVER}) add_executable(shp2img shp2img.c) target_link_libraries(shp2img ${MAPSERVER_LIBMAPSERVER}) add_executable(shptree shptree.c) target_link_libraries(shptree ${MAPSERVER_LIBMAPSERVER}) add_executable(shptreevis shptreevis.c) target_link_libraries(shptreevis ${MAPSERVER_LIBMAPSERVER}) add_executable(sortshp sortshp.c) target_link_libraries(sortshp ${MAPSERVER_LIBMAPSERVER}) add_executable(legend legend.c) target_link_libraries(legend ${MAPSERVER_LIBMAPSERVER}) add_executable(scalebar scalebar.c) target_link_libraries(scalebar ${MAPSERVER_LIBMAPSERVER}) add_executable(msencrypt msencrypt.c) target_link_libraries(msencrypt ${MAPSERVER_LIBMAPSERVER}) add_executable(tile4ms tile4ms.c) target_link_libraries(tile4ms ${MAPSERVER_LIBMAPSERVER}) add_executable(shptreetst shptreetst.c) target_link_libraries(shptreetst ${MAPSERVER_LIBMAPSERVER}) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(USE_EXTENDED_DEBUG 1) endif (CMAKE_BUILD_TYPE STREQUAL "Debug") find_package(PNG) if(PNG_FOUND) include_directories(${PNG_INCLUDE_DIR}) ms_link_libraries( ${PNG_LIBRARIES}) list(APPEND ALL_INCLUDE_DIRS ${PNG_INCLUDE_DIR}) set(USE_PNG 1) else(PNG_FOUND) report_mandatory_not_found(PNG) endif(PNG_FOUND) find_package(JPEG) if(JPEG_FOUND) include_directories(${JPEG_INCLUDE_DIR}) ms_link_libraries( ${JPEG_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${JPEG_INCLUDE_DIR}) set(USE_JPEG 1) else(JPEG_FOUND) report_mandatory_not_found(JPEG) endif(JPEG_FOUND) find_package(Freetype) if(NOT FREETYPE_FOUND) report_mandatory_not_found(FREETYPE) endif(NOT FREETYPE_FOUND) include_directories(${FREETYPE_INCLUDE_DIR}) ms_link_libraries( ${FREETYPE_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIR}) if(WITH_PROJ) find_package(Proj) if(NOT PROJ_FOUND) report_optional_not_found(PROJ) else(NOT PROJ_FOUND) include_directories(${PROJ_INCLUDE_DIR}) ms_link_libraries( ${PROJ_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) set (USE_PROJ 1) endif(NOT PROJ_FOUND) endif (WITH_PROJ) if(USE_PBF) include_directories(${PROJECT_BINARY_DIR}/renderers/mvt) include_directories(${PROTOBUFC_INCLUDE_DIR}) ms_link_libraries( ${PROTOBUFC_LIBRARY}) endif() if(WITH_PIXMAN) find_package(Pixman) if(PIXMAN_FOUND) include_directories(${PIXMAN_INCLUDE_DIR}) ms_link_libraries(${PIXMAN_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR}) set (USE_PIXMAN 1) else(PIXMAN_FOUND) report_optional_not_found(PIXMAN) endif(PIXMAN_FOUND) endif (WITH_PIXMAN) if(WITH_WMS) if(USE_PROJ) set(USE_WMS_SVR 1) else(USE_PROJ) report_dependency_error(WMS PROJ) endif(USE_PROJ) endif(WITH_WMS) if(WITH_FRIBIDI) find_package(FriBiDi) if(NOT FRIBIDI_FOUND) report_optional_not_found(FRIBIDI) else(NOT FRIBIDI_FOUND) include_directories(${FRIBIDI_INCLUDE_DIR}) ms_link_libraries( ${FRIBIDI_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${FRIBIDI_INCLUDE_DIR}) set (USE_FRIBIDI 1) if(FRIBIDI_LEGACY) message(WARNING "Old Fribidi found, upgrade recommended") endif(FRIBIDI_LEGACY) endif(NOT FRIBIDI_FOUND) endif (WITH_FRIBIDI) if(WITH_HARFBUZZ) find_package(HarfBuzz) if(NOT HARFBUZZ_FOUND) report_optional_not_found(HARFBUZZ) else(NOT HARFBUZZ_FOUND) include_directories(${HARFBUZZ_INCLUDE_DIR}) ms_link_libraries( ${HARFBUZZ_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${HARFBUZZ_INCLUDE_DIR}) set (USE_HARFBUZZ 1) endif(NOT HARFBUZZ_FOUND) endif (WITH_HARFBUZZ) if( USE_HARFBUZZ AND NOT(USE_FRIBIDI) ) report_dependency_error(HARFBUZZ FRIBIDI) endif( USE_HARFBUZZ AND NOT(USE_FRIBIDI) ) if( USE_FRIBIDI AND NOT(USE_HARFBUZZ) ) report_dependency_error(FRIBIDI HARFBUZZ) endif( USE_FRIBIDI AND NOT(USE_HARFBUZZ) ) if(WITH_ICONV) find_package(ICONV) if(ICONV_FOUND) include_directories(${ICONV_INCLUDE_DIR}) ms_link_libraries( ${ICONV_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${ICONV_INCLUDE_DIR}) set (USE_ICONV 1) else(ICONV_FOUND) report_optional_not_found(ICONV) endif(ICONV_FOUND) endif (WITH_ICONV) if(WITH_GENERIC_NINT) set(USE_GENERIC_MS_NINT 1) endif(WITH_GENERIC_NINT) if(WITH_CAIRO) find_package(Cairo) if(CAIRO_FOUND) include_directories(${CAIRO_INCLUDE_DIRS}) ms_link_libraries( ${CAIRO_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${CAIRO_INCLUDE_DIR}) set (USE_CAIRO 1) else(CAIRO_FOUND) report_optional_not_found(CAIRO) endif(CAIRO_FOUND) endif (WITH_CAIRO) if(WITH_MYSQL) find_package(MySQL) if(MYSQL_FOUND) include_directories(${MYSQL_INCLUDE_DIR}) ms_link_libraries( ${MYSQL_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${MYSQL_INCLUDE_DIR}) set (USE_MYSQL 1) else(MYSQL_FOUND) report_optional_not_found(MYSQL) endif(MYSQL_FOUND) endif (WITH_MYSQL) if(WITH_ORACLE_PLUGIN AND WITH_ORACLESPATIAL) message(SEND_ERROR "WITH_ORACLESPATIAL and WITH_ORACLE_PLUGIN cannot be used simultaneously") endif(WITH_ORACLE_PLUGIN AND WITH_ORACLESPATIAL) if(WITH_ORACLESPATIAL OR WITH_ORACLE_PLUGIN) if(NOT DEFINED ENV{ORACLE_HOME}) MESSAGE( SEND_ERROR "ORACLE_HOME environment variable not set, needed for detection") endif() find_package(Oracle) if(ORACLE_FOUND) include_directories(${ORACLE_INCLUDE_DIR}) list(APPEND ALL_INCLUDE_DIRS ${ORACLE_INCLUDE_DIR}) else(ORACLE_FOUND) report_optional_not_found(ORACLESPATIAL) #FIXME: error message here could be misleading, only states ORACLESPATIAL whereas #the request could have been for ORACLE_PLUGIN endif(ORACLE_FOUND) endif(WITH_ORACLESPATIAL OR WITH_ORACLE_PLUGIN) if(ORACLE_FOUND AND WITH_ORACLESPATIAL) ms_link_libraries( ${ORACLE_LIBRARY}) set (USE_ORACLESPATIAL 1) endif(ORACLE_FOUND AND WITH_ORACLESPATIAL) if(ORACLE_FOUND AND WITH_ORACLE_PLUGIN) add_library(msplugin_oracle MODULE maporaclespatial.c) target_link_libraries(msplugin_oracle ${ORACLE_LIBRARY} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(msplugin_oracle PROPERTIES COMPILE_FLAGS -DUSE_ORACLE_PLUGIN) set (USE_ORACLE_PLUGIN 1) endif(ORACLE_FOUND AND WITH_ORACLE_PLUGIN) if(WITH_MSSQL2008) find_package(ODBC) if(ODBC_FOUND) include_directories(${ODBC_INCLUDE_DIR}) add_library(msplugin_mssql2008 MODULE mapmssql2008.c) target_link_libraries(msplugin_mssql2008 ${ODBC_LIBRARY} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(msplugin_mssql2008 PROPERTIES COMPILE_FLAGS "-DUSE_MSSQL2008_PLUGIN -DUSE_MSSQL2008") list(APPEND ALL_INCLUDE_DIRS ${ODBC_INCLUDE_DIR}) set (USE_MSSQL2008 1) else(ODBC_FOUND) report_optional_not_found(ODBC) endif(ODBC_FOUND) endif(WITH_MSSQL2008) if(WITH_FCGI) find_package(FCGI) if(FCGI_FOUND) include_directories(${FCGI_INCLUDE_DIR}) target_link_libraries(mapserv ${FCGI_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${FCGI_INCLUDE_DIR}) set (USE_FASTCGI 1) else(FCGI_FOUND) report_optional_not_found(FCGI) endif(FCGI_FOUND) endif (WITH_FCGI) if(WITH_GEOS) find_package(GEOS) if(GEOS_FOUND) include_directories(${GEOS_INCLUDE_DIR}) ms_link_libraries( ${GEOS_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${GEOS_INCLUDE_DIR}) set (USE_GEOS 1) else(GEOS_FOUND) report_optional_not_found(GEOS) endif(GEOS_FOUND) endif (WITH_GEOS) if(WITH_POSTGIS) find_package(PostgreSQL) if(POSTGRESQL_FOUND) #uppercase our variables if ( NOT DEFINED POSTGRESQL_LIBRARY ) set( POSTGRESQL_LIBRARY ${PostgreSQL_LIBRARY}) endif() if ( NOT DEFINED POSTGRESQL_INCLUDE_DIR ) set( POSTGRESQL_INCLUDE_DIR ${PostgreSQL_INCLUDE_DIR}) endif() include_directories(${POSTGRESQL_INCLUDE_DIR}) ms_link_libraries( ${POSTGRESQL_LIBRARY}) CHECK_LIBRARY_EXISTS(pq "PQserverVersion" POSTGRESQL_LIBRARY POSTGIS_HAS_SERVER_VERSION) list(APPEND ALL_INCLUDE_DIRS ${POSTGRESQL_INCLUDE_DIR}) set (USE_POSTGIS 1) else(POSTGRESQL_FOUND) report_optional_not_found(POSTGIS) endif(POSTGRESQL_FOUND) endif (WITH_POSTGIS) if(WITH_GDAL) find_package(GDAL) if(GDAL_FOUND) include_directories(${GDAL_INCLUDE_DIR}) ms_link_libraries( ${GDAL_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR}) set (USE_GDAL 1) else(GDAL_FOUND) report_optional_not_found(GDAL) endif(GDAL_FOUND) endif (WITH_GDAL) if(WITH_SVGCAIRO) if(WITH_RSVG) message(SEND_ERROR "WITH_SVGCAIRO cannot be enabled with WITH_RSVG") endif(WITH_RSVG) find_package(SVGCairo) if(SVGCAIRO_FOUND) include_directories(${SVG_INCLUDE_DIR} ${SVGCAIRO_INCLUDE_DIR}) ms_link_libraries( ${SVG_LIBRARY} ${SVGCAIRO_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${SVG_INCLUDE_DIR} ${SVGCAIRO_INCLUDE_DIR}) set (USE_SVG_CAIRO 1) else(SVGCAIRO_FOUND) report_optional_not_found(SVGCAIRO) endif(SVGCAIRO_FOUND) endif (WITH_SVGCAIRO) if(WITH_RSVG) if(WITH_SVGCAIRO) message(SEND_ERROR "WITH_RSVG cannot be enabled with WITH_CAIROSVG") endif(WITH_SVGCAIRO) find_package(RSVG) if(RSVG_FOUND AND GOBJECT_FOUND) include_directories(${RSVG_INCLUDE_DIRS}) ms_link_libraries( ${RSVG_LIBRARY} ) list(APPEND ALL_INCLUDE_DIRS ${RSVG_INCLUDE_DIRS}) include_directories(${GOBJECT_INCLUDE_DIRS}) ms_link_libraries( ${GOBJECT_LIBRARY} ) list(APPEND ALL_INCLUDE_DIRS ${GOBJECT_INCLUDE_DIRS}) set (USE_RSVG 1) else(RSVG_FOUND AND GOBJECT_FOUND) report_optional_not_found(RSVG) endif(RSVG_FOUND AND GOBJECT_FOUND) endif (WITH_RSVG) if(WITH_OGR) if(GDAL_FOUND) set (USE_OGR 1) else(GDAL_FOUND) find_package(GDAL) if(GDAL_FOUND) include_directories(${GDAL_INCLUDE_DIR}) ms_link_libraries( ${GDAL_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR}) set (USE_OGR 1) else(GDAL_FOUND) message(SEND_ERROR "GDAL library could not be found and is needed for OGR support. HINTS: - disable OGR support by adding -DWITH_OGR=0 - add the GDAL install directory to the CMAKE_PREFIX_PATH variable (-DCMAKE_PREFIX_PATH=\"/path/to/${component}-install-dir;/path/to/other/dirs\"") endif(GDAL_FOUND) endif(GDAL_FOUND) endif(WITH_OGR) if(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) set(WITH_CURL ON) endif(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) if(WITH_CURL) find_package(CURL) if(CURL_FOUND) include_directories(${CURL_INCLUDE_DIR}) ms_link_libraries( ${CURL_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${CURL_INCLUDE_DIR}) set(USE_CURL 1) else(CURL_FOUND) report_optional_not_found(CURL) endif(CURL_FOUND) endif(WITH_CURL) if(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) if(NOT USE_CURL) if(WITH_CLIENT_WFS) report_dependency_error(CLIENT_WFS CURL) endif(WITH_CLIENT_WFS) if(WITH_CLIENT_WMS) report_dependency_error(CLIENT_WMS CURL) endif(WITH_CLIENT_WMS) endif(NOT USE_CURL) endif(WITH_CLIENT_WMS OR WITH_CLIENT_WFS) if(WITH_CLIENT_WMS) if(USE_GDAL AND USE_PROJ) set(USE_WMS_LYR 1) else(USE_GDAL AND USE_PROJ) if(NOT USE_GDAL) report_dependency_error(CLIENT_WMS GDAL) endif(NOT USE_GDAL) if( NOT USE_PROJ) report_dependency_error(CLIENT_WMS PROJ) endif(NOT USE_PROJ) endif(USE_GDAL AND USE_PROJ) endif(WITH_CLIENT_WMS) if(WITH_CLIENT_WFS) if(USE_OGR AND USE_PROJ) set(USE_WFS_LYR 1) else(USE_OGR AND USE_PROJ) if(NOT USE_OGR) report_dependency_error(CLIENT_WFS OGR) endif(NOT USE_OGR) if( NOT USE_PROJ) report_dependency_error(CLIENT_WFS PROJ) endif(NOT USE_PROJ) endif(USE_OGR AND USE_PROJ) endif(WITH_CLIENT_WFS) if(WITH_WFS) if(USE_PROJ AND USE_OGR) set(USE_WFS_SVR 1) #TODO: set WFS_USE_LIBXML2 ? else(USE_PROJ AND USE_OGR) if( NOT USE_OGR) report_dependency_error(WFS OGR) endif( NOT USE_OGR) if( NOT USE_PROJ) report_dependency_error(WFS PROJ) endif( NOT USE_PROJ) endif(USE_PROJ AND USE_OGR) endif(WITH_WFS) if(WITH_WCS) if(USE_PROJ AND USE_GDAL) set(USE_WCS_SVR 1) else(USE_PROJ AND USE_GDAL) if(NOT USE_GDAL) report_dependency_error(WCS GDAL) endif(NOT USE_GDAL) if(NOT USE_PROJ) report_dependency_error(WCS PROJ) endif(NOT USE_PROJ) endif(USE_PROJ AND USE_GDAL) endif(WITH_WCS) if(WITH_LIBXML2) find_package(LibXml2) if(LIBXML2_FOUND) include_directories(${LIBXML2_INCLUDE_DIR}) if(NOT DEFINED LIBXML2_LIBRARY) set(LIBXML2_LIBRARY ${LIBXML2_LIBRARIES}) endif() ms_link_libraries( ${LIBXML2_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR}) set (USE_LIBXML2 1) else(LIBXML2_FOUND) report_optional_not_found(LIBXML2) endif(LIBXML2_FOUND) endif (WITH_LIBXML2) if( USE_WCS_SVR AND NOT USE_LIBXML2 ) message(WARNING "WCS 1.1 and 2.0 require libxml2 support but it was not found. WCS 1.1 and 2.0 will not be supported by this build") endif( USE_WCS_SVR AND NOT USE_LIBXML2 ) if( USE_WFS_SVR AND NOT USE_LIBXML2 ) message(WARNING "WFS 1.1 and 2.0 require libxml2 support but it was not found. WFS 1.1 and 2.0 will not be supported by this build") endif( USE_WFS_SVR AND NOT USE_LIBXML2 ) if(WITH_SOS) if(NOT USE_OGR) report_dependency_error(WITH_SOS OGR) endif(NOT USE_OGR) if(USE_PROJ AND USE_LIBXML2) set(USE_SOS_SVR 1) else(USE_PROJ AND USE_LIBXML2) if(NOT USE_LIBXML2) report_dependency_error(SOS LIBXML2) endif(NOT USE_LIBXML2) if(NOT USE_PROJ) report_dependency_error(SOS PROJ) endif(NOT USE_PROJ) endif(USE_PROJ AND USE_LIBXML2) endif(WITH_SOS) if(WITH_POINT_Z_M) set(USE_POINT_Z_M 1) endif(WITH_POINT_Z_M) if(WITH_KML) if(USE_LIBXML2) set(USE_KML 1) else(USE_LIBXML2) report_dependency_error(KML LIBXML2) endif(USE_LIBXML2) endif(WITH_KML) if(WITH_THREAD_SAFETY) set( CMAKE_THREAD_PREFER_PTHREAD 1 ) find_package(Threads) if (THREADS_FOUND) ms_link_libraries( ${CMAKE_THREAD_LIBS_INIT}) set(USE_THREAD 1) endif (THREADS_FOUND) endif(WITH_THREAD_SAFETY) if(WITH_XMLMAPFILE) if(NOT USE_LIBXML2) report_dependency_error(KML LIBXML2) endif(NOT USE_LIBXML2) #check for xslt and exslt find_package(LibXslt) if(LIBXSLT_FOUND) if(NOT DEFINED LIBXSLT_LIBRARY) set(LIBXSLT_LIBRARY ${LIBXSLT_LIBRARIES}) endif() include_directories(${LIBXSLT_INCLUDE_DIR}) ms_link_libraries( ${LIBXSLT_LIBRARY} ${LIBXSLT_EXSLT_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${LIBXSLT_INCLUDE_DIR}) set(USE_XMLMAPFILE 1) else(LIBXSLT_FOUND) message(SEND_ERROR "Xml Mapfile support requires XSLT support which was not found. HINTS: - add the libxslt install directory to the CMAKE_PREFIX_PATH variable (-DCMAKE_PREFIX_PATH=\"/path/to/libxslt-install-dir;/path/to/other/dirs\" - disable Xml Mapfile support by adding -DWITH_XMLMAPFILE=0" ) endif(LIBXSLT_FOUND) endif(WITH_XMLMAPFILE) if(WITH_GIF) find_package(GIF) if(GIF_FOUND) include_directories(${GIF_INCLUDE_DIR}) ms_link_libraries( ${GIF_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${GIF_INCLUDE_DIR}) set(USE_GIF 1) else(GIF_FOUND) report_optional_not_found(GIF) endif(GIF_FOUND) endif(WITH_GIF) if(WITH_EXEMPI) find_package(Exempi) if(LIBEXEMPI_FOUND) include_directories(${LIBEXEMPI_INCLUDE_DIR}) ms_link_libraries( ${LIBEXEMPI_LIBRARY}) list(APPEND ALL_INCLUDE_DIRS ${LIBEXEMPI_INCLUDE_DIR}) set(USE_EXEMPI 1) else(LIBEXEMPI_FOUND) report_optional_not_found(EXEMPI) endif(LIBEXEMPI_FOUND) endif(WITH_EXEMPI) if(WITH_PYTHON) add_subdirectory("mapscript/python") set(USE_PYTHON_MAPSCRIPT 1) endif(WITH_PYTHON) if(WITH_V8) FIND_PACKAGE(V8) IF(V8_FOUND EQUAL 1) SET(USE_V8_MAPSCRIPT 1) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${V8_INCLUDE}) list(APPEND ALL_INCLUDE_DIRS ${V8_INCLUDE}) MS_LINK_LIBRARIES( ${V8_LIBS}) ELSE(V8_FOUND) MESSAGE(SEND_ERROR "V8 JavaScript support requested but not found. HINTS: - set V8_ROOT environment variable to the installation path of V8. - add the V8 install directory to the CMAKE_PREFIX_PATH variable (-DCMAKE_PREFIX_PATH=\"/path/to/${component}-install-dir;/path/to/other/dirs\") ") ENDIF() ENDIF(WITH_V8) if(WITH_PHP) add_subdirectory("mapscript/php") set(USE_PHP_MAPSCRIPT 1) endif(WITH_PHP) if(WITH_PHPNG) add_subdirectory("mapscript/phpng") set(USE_PHPNG_MAPSCRIPT 1) endif(WITH_PHPNG) if(WITH_APACHE_MODULE) add_subdirectory("apache") set(USE_APACHE_MODULE 1) endif(WITH_APACHE_MODULE) if(WITH_PERL) add_subdirectory("mapscript/perl") set(USE_PERL_MAPSCRIPT 1) endif(WITH_PERL) if(WITH_RUBY) add_subdirectory("mapscript/ruby") set(USE_RUBY_MAPSCRIPT 1) endif(WITH_RUBY) if(WITH_JAVA) add_subdirectory("mapscript/java") set(USE_JAVA_MAPSCRIPT 1) endif(WITH_JAVA) if(WITH_CSHARP) add_subdirectory("mapscript/csharp") set(USE_CSHARP_MAPSCRIPT 1) endif(WITH_CSHARP) if(UNIX) ms_link_libraries( ${CMAKE_DL_LIBS} m ) endif(UNIX) if (WIN32) ms_link_libraries( ${MS_EXTERNAL_LIBS} ws2_32.lib) if (MSVC) set_target_properties(mapserver PROPERTIES COMPILE_FLAGS "/wd4267 /wd4244 /wd4018") endif(MSVC) endif (WIN32) configure_file ( "${PROJECT_SOURCE_DIR}/mapserver-config.h.in" "${PROJECT_BINARY_DIR}/mapserver-config.h" ) configure_file ( "${PROJECT_SOURCE_DIR}/mapserver-version.h.in" "${PROJECT_BINARY_DIR}/mapserver-version.h" ) if(BUILD_DYNAMIC) set_target_properties(mapserver PROPERTIES PUBLIC_HEADER "${mapserver_HEADERS};${PROJECT_BINARY_DIR}/mapserver-config.h;${PROJECT_BINARY_DIR}/mapserver-version.h" ) endif(BUILD_DYNAMIC) macro(status_optional_component component enabled libpath) if("${enabled}" EQUAL "1") message(STATUS " * ${component}: ${libpath}") else() message(STATUS " * ${component}: disabled") endif() endmacro() macro(status_optional_feature feature enabled) if("${enabled}" EQUAL "1") message(STATUS " * ${feature}: ENABLED") else() message(STATUS " * ${feature}: disabled") endif() endmacro() message(STATUS "* Summary of configured options for this build") message(STATUS " * Mandatory components") message(STATUS " * png: ${PNG_LIBRARY}") message(STATUS " * jpeg: ${JPEG_LIBRARY}") message(STATUS " * freetype: ${FREETYPE_LIBRARY}") message(STATUS " * Optional components") status_optional_component("GDAL" "${USE_GDAL}" "${GDAL_LIBRARY}") status_optional_component("OGR" "${USE_OGR}" "${GDAL_LIBRARY}") status_optional_component("GIF" "${USE_GIF}" "${GIF_LIBRARY}") status_optional_component("MYSQL" "${USE_MYSQL}" "${MYSQL_LIBRARY}") status_optional_component("FRIBIDI" "${USE_FRIBIDI}" "${FRIBIDI_LIBRARY}") status_optional_component("HARFBUZZ" "${USE_HARFBUZZ}" "${HARFBUZZ_LIBRARY}") status_optional_component("GIF" "${USE_GIF}" "${GIF_LIBRARY}") status_optional_component("CAIRO" "${USE_CAIRO}" "${CAIRO_LIBRARY}") status_optional_component("SVGCAIRO" "${USE_SVG_CAIRO}" "${SVGCAIRO_LIBRARY}") status_optional_component("RSVG" "${USE_RSVG}" "${RSVG_LIBRARY}") status_optional_component("CURL" "${USE_CURL}" "${CURL_LIBRARY}") status_optional_component("PROJ" "${USE_PROJ}" "${PROJ_LIBRARY}") status_optional_component("PIXMAN" "${USE_PIXMAN}" "${PIXMAN_LIBRARY}") status_optional_component("LIBXML2" "${USE_LIBXML2}" "${LIBXML2_LIBRARY}") status_optional_component("POSTGIS" "${USE_POSTGIS}" "${POSTGRESQL_LIBRARY}") status_optional_component("GEOS" "${USE_GEOS}" "${GEOS_LIBRARY}") status_optional_component("FastCGI" "${USE_FASTCGI}" "${FCGI_LIBRARY}") status_optional_component("PROTOBUFC" "${USE_PBF}" "${PROTOBUFC_LIBRARY}") if(USE_ORACLESPATIAL OR USE_ORACLE_PLUGIN) if(USE_ORACLESPATIAL) status_optional_component("Oracle Spatial" "${USE_ORACLESPATIAL}" "${ORACLE_LIBRARY}") else(USE_ORACLESPATIAL) status_optional_component("Oracle Spatial (Built as plugin)" "${USE_ORACLE_PLUGIN}" "${ORACLE_LIBRARY}") endif(USE_ORACLESPATIAL) else(USE_ORACLESPATIAL OR USE_ORACLE_PLUGIN) status_optional_component("Oracle Spatial" "" "${ORACLE_LIBRARY}") endif(USE_ORACLESPATIAL OR USE_ORACLE_PLUGIN) if(USE_MSSQL2008) status_optional_component("MSSQL 2008 (Built as plugin)" "${USE_MSSQL2008}" "${ODBC_LIBRARY}") endif(USE_MSSQL2008) status_optional_component("Exempi XMP" "${USE_EXEMPI}" "${LIBEXEMPI_LIBRARY}") message(STATUS " * Optional features") status_optional_feature("WMS SERVER" "${USE_WMS_SVR}") status_optional_feature("WFS SERVER" "${USE_WFS_SVR}") status_optional_feature("WCS SERVER" "${USE_WCS_SVR}") status_optional_feature("SOS SERVER" "${USE_SOS_SVR}") status_optional_feature("WMS CLIENT" "${USE_WMS_LYR}") status_optional_feature("WFS CLIENT" "${USE_WFS_LYR}") status_optional_feature("ICONV" "${USE_ICONV}") status_optional_feature("Thread-safety support" "${USE_THREAD}") status_optional_feature("KML output" "${USE_KML}") status_optional_feature("Z+M point coordinate support" "${USE_POINT_Z_M}") status_optional_feature("XML Mapfile support" "${USE_XMLMAPFILE}") message(STATUS " * Mapscripts") status_optional_feature("Python" "${USE_PYTHON_MAPSCRIPT}") status_optional_feature("PHP" "${USE_PHP_MAPSCRIPT}") status_optional_feature("PHPNG" "${USE_PHPNG_MAPSCRIPT}") status_optional_feature("PERL" "${USE_PERL_MAPSCRIPT}") status_optional_feature("RUBY" "${USE_RUBY_MAPSCRIPT}") status_optional_feature("JAVA" "${USE_JAVA_MAPSCRIPT}") status_optional_feature("C#" "${USE_CSHARP_MAPSCRIPT}") status_optional_feature("V8 Javascript" "${USE_V8_MAPSCRIPT}") status_optional_feature("Apache Module (Experimental)" "${USE_APACHE_MODULE}") message(STATUS "") message(STATUS "Will install files to ${CMAKE_INSTALL_PREFIX}") message(STATUS "Will install libraries to ${INSTALL_LIB_DIR}") include_directories("${PROJECT_BINARY_DIR}") if(WIN32) set(REGEX_MALLOC 1) set(USE_GENERIC_MS_NINT 1) endif(WIN32) #INSTALL(FILES mapserver-api.h ${PROJECT_BINARY_DIR}/mapserver-version.h DESTINATION include) if(USE_ORACLE_PLUGIN) INSTALL(TARGETS msplugin_oracle DESTINATION ${INSTALL_LIB_DIR}) endif(USE_ORACLE_PLUGIN) if(USE_MSSQL2008) INSTALL(TARGETS msplugin_mssql2008 DESTINATION ${INSTALL_LIB_DIR}) endif(USE_MSSQL2008) INSTALL(TARGETS sortshp shptree shptreevis msencrypt legend scalebar tile4ms shptreetst shp2img mapserv RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin ) if(BUILD_STATIC) INSTALL(TARGETS mapserver_static DESTINATION ${INSTALL_LIB_DIR} COMPONENT staticlib ) endif(BUILD_STATIC) if(BUILD_DYNAMIC) INSTALL(TARGETS mapserver EXPORT mapserverTargets ARCHIVE DESTINATION ${INSTALL_LIB_DIR} COMPONENT shlib LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT shlib PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDE_DIR}/mapserver COMPONENT dev ) # Add all targets to the build-tree export set export(TARGETS mapserver FILE "${PROJECT_BINARY_DIR}/mapserverTargets.cmake" ) # Export the package for use from the build-tree # (this registers the build-tree with a global CMake-registry) export(PACKAGE mapserver) list(APPEND ALL_INCLUDE_DIRS ${INSTALL_INCLUDE_DIR}) list(APPEND ALL_INCLUDE_DIRS ${INSTALL_INCLUDE_DIR}/mapserver) list(REMOVE_DUPLICATES ALL_INCLUDE_DIRS) # Create the mapserver-config.cmake and mapserver-config-version files file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}" "${ALL_INCLUDE_DIRS}") # ... for the build tree set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}") configure_file(mapserver-config.cmake.in "${PROJECT_BINARY_DIR}/mapserver-config.cmake" @ONLY) # ... for the install tree set(CONF_INCLUDE_DIRS "\${MAPSERVER_CMAKE_DIR}/${REL_INCLUDE_DIR}") configure_file(mapserver-config.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/mapserver-config.cmake" @ONLY) # ... for both configure_file(mapserver-config-version.cmake.in "${PROJECT_BINARY_DIR}/mapserver-config-version.cmake" @ONLY) # Install the mapserver-config.cmake and mapserver-config-version.cmake install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/mapserver-config.cmake" "${PROJECT_BINARY_DIR}/mapserver-config-version.cmake" DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev ) # Install the export set for use with the install-tree install(EXPORT mapserverTargets DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev ) endif(BUILD_DYNAMIC) mapserver-7.4.3/CONTRIBUTING.md000066400000000000000000000037501357574274700160140ustar00rootroot00000000000000# How to contribute to MapServer Contributions to the MapServer project are most welcome, and can take many forms such as detailed bug reports, documentation, tests, features, and patches. Note that all contributions are managed by the MapServer [Project Steering Committee](https://mapserver.org/psc.html). ## Bugs and Help GitHub issues should only be created to log bugs. For general help and support the MapServer [mailing lists](http://mapserver.org/community/lists.html) should be used. If you are unsure if you have discovered a bug, or may need help with configuring MapServer please post to the [mapserver-users list](http://lists.osgeo.org/mailman/listinfo/mapserver-users). There is also a [MapServer FAQ](http://www.mapserver.org/faq.html) which may have a solution to your problem. If you have discovered a bug, please refer to the [Bug Submission page](http://mapserver.org/development/bugs.html) for guidelines on creating an issue on GitHub. Please also search the existing issues to see if the bug has already been reported, and add any further details to the existing issue. For professional support please see the [MapServer Service Providers page](http://mapserver.org/community/service_providers.html). ## Development A separate [mapserver-dev mailing list](http://lists.osgeo.org/mailman/listinfo/mapserver-dev) is available for developers working on the MapServer code. Details on using GitHub can be found on the [MapServer GitHub page](http://mapserver.org/development/git.html) Additional developer notes can be found in the [MapServer wiki](https://github.com/mapserver/mapserver/wiki#developer-notes), including coding style and guidelines, memory management, and working with Git. ## Documentation The MapServer documentation is stored in a [separate repository](https://github.com/mapserver/docs). Please submit any documentation issues or changes there. See the [Documentation Development Guide](http://mapserver.org/development/documentation.html) for further details. mapserver-7.4.3/HISTORY.TXT000066400000000000000000004601111357574274700153230ustar00rootroot00000000000000 MapServer Revision History ========================== This is a human-readable revision history which will attempt to document required changes for users to migrate from one version of MapServer to the next. Developers are strongly encouraged to document their changes and their impacts on the users here. (Please add the most recent changes to the top of the list.) For a complete change history, please see the Git log comments. For more details about recent point releases, please see the online changelog at: http://mapserver.org/development/changelog/ 7.4.3 release (2019-12-16) -------------------------- - No major changes, see detailed changelog for bug fixes 7.4.2 release (2019-9-13) ------------------------- - No major changes, see detailed changelog for bug fixes 7.4.1 release (2019-7-12) ------------------------- - No major changes, see detailed changelog for bug fixes 7.4.0 release (2019-5-14) ------------------------- - No major changes, see detailed changelog for bug fixes 7.4.0-rc2 release (2019-5-10) ---------------------------- - No major changes, see detailed changelog for bug fixes 7.4.0-rc1 release (2019-5-1) ---------------------------- - No major changes, see detailed changelog for bug fixes 7.4.0-beta2 release (2019-4-17) ------------------------------- - Addresses XSS issue with [layers] template tag (fix available in 6.4, 7.0 and 7.2 branches as well) - Added Perl/Mapscript to Travis CI - No other major changes, see detailed changelog for bug fixes 7.4.0-beta1 release (2019-3-29) ------------------------------- - Python MapScript binding is available as installable Wheels with a full test suite and examples - C# MapScript binding is now compatible with .NET Core - PHP 7 MapScript binding support - both PHP/MapScript and Swig/MapScript - Added workaround to allow compiling against Proj 6 (#5766) 7.2.2 release (2019-2-19) -------------------------- - No major changes, see detailed changelog for bug fixes 7.2.1 release (2018-10-1) -------------------------- - No major changes, see detailed changelog for bug fixes 7.2.0 release (2018-07-23) -------------------------- - Fixed issue with ring handling with polygons in MVT support (#5626) - No other major changes, see detailed changelog for bug fixes 7.2.0-beta2 release (2018-6-13) - Update beta1 release notes to remove reference to PHP7 support - No other major changes, see detailed changelog for bug fixes 7.2.0-beta1 release (2018-5-9) -------------------- - Support for Enhanced Layer Metadata Management (RFC82) - Calculate MINDISTANCE from label bounds instead of label center (#5369) - Reposition follow labels on maxoverlapangle colisions (RFC112) - Implement chainable compositing filters (RFC113) - Faster retrieval of shape count (RFC114) - WMS layer groups are now requestable - Support C-style multi-line content types (#5362) - Python 3.x support (#5561) - Support Vendor-Specific OGC FILTER parameter in WMS requests (RFC118) - Mapbox Vector Tile (MVT) Support (RFC119) - INSPIRE download service support for WCS 2.0 (RFC120) 7.0.0 release (2015/07/24) -------------------------- - No major changes, see detailed changelog for bug fixes 7.0.0-beta2 release (2015/06/29) -------------------------------- - No major changes, see detailed changelog for bug fixes 7.0.0-beta1 release (2015/02/12) -------------------------------- - RFC91 Layer Filter Normalization - Implement WCS20 Extensions (#4898) - Require validation of ExternalGraphic OnlineResource (#4883) - Require validation on the CGI queryfile parameter. (#4874) - Apply RFC86 scaletoken substitutions to layer->PROCESSING entries - RFC113 Layer Compositing Pipeline - RFC109 Optimizing Runtime Substitutions - RFC108 Heatmap / Kernel-Density Layers - RFC106 Support of Geomtransform JavaScript Plugin - RFC105 Support for WFS 2.0 (server side) - RFC104 Bitmap Label removal, replaced with inlined truetype font - RFC103 Layer Level Character Encoding - RFC102 Support of Styleitem JavaScript Plugin - RFC99 GD removal - RFC98 Complex Text Rendering / Text Rendering Overhaul - RFC93 UTF Grid Support 6.4 release (2013/09/17) --------------------------- - RFC 101: Support for Content Dependant Legend Rendering - Add Support for librsvg as an alternative to libsvg-cairo - RFC100: Add support for raster tile index with tiles of mixed SRS (TILESRS keyword) - RFC94: Shape Smoothing - RFC95 : add EXPRESSION {value1,value2,...} support to parser (#4648) - RFC92: Migration from autotools to cmake (#4617) - RFC88: Saving MapServer Objects to Strings (#4563) - RFC90: Enable/Disable Layers in OGC Web Services by IP Lists - RFC85,89 Added Simplify,SimplityPT and Generalize geomtransform, implementation of geomtransform at the layer level - RFC86: Scale-dependant token replacements (#4538) - Fix symbol scaling for vector symbols with no height (#4497,#3511) - Implementation of layer masking for WCS coverages (#4469) - Implementation of offsets on follow labels (#4399) 6.2.0 release (git branch-6-2) 2012/11/14: -------------------------------------------------- - Fix WFS GetFeature result bounds are not written in requested projection (#4494) - Fixed wrong size in LegendURL of root layer (#4441) - Fixed wms_style_name in GetMap requests (#4439) - Fix segfault in queryByFilter function in MapScript - Adjusted WCS 2.0 to WCS Core 2.0.1 and GMLCOV 1.0.1 corrigenda (#4003) - Adjusted mediatype to multipart/related in WCS 2.0 (#4003) - Fix symbolObj.getImage seg fault in PHP/MapScript - Fix bad handling of startindex in some drivers (#4011) WFSGetFeature also now uses a global maxfeatures and startindex to support maxfeatures across layers rather than within layers - Fixed bugs with WCS 1.1/2.0 with VSIMEM (#4369) - Add notable changes here. Less important changes should go only in the commit message and not appear here. - Fixed the OGR driver to use point or line spatial filter geometries in degenerated cases (#4420) - implement OFFSET x -99 on ANGLE FOLLOW labels (#4399) Version 6.2 (beta1: 20120629): ------------------------------------------------- - Fix WFS filter is produced as non-standard XML (#4171) - Fix pixmap symbol loading issue (#4329) - Added INSPIRE ExtendedCapabilities and DOCTYPE definition to WMS 1.1.1 (#3608) - Fix wms_enable_request-related errors are not properly tagged (#4187) - Fixed "msGetMarkerSize() called on unloaded pixmap symbol" in mapsymbol.c (#4225) - Fixed PHP MapScript support for PHP 5.4 (#4309) - Fix msOGREscapeSQLParam could return random data (#4335) - Fixed locations of supported and native formats in Capabilities and CoverageDescriptions for WCS 2.0 (#4003) - Made format parameter for WCS 2.0 GetCoverage requests optional (#4003) - Swig mapscript for multi-label support (#4310) - Fix creation of a vector symbolObj in mapscript (#4318) - Added coverage metadata in WCS (#4306) - Ignore unknown requets parameteres in WCS 2.0 (#4307). - Fixed getFeature request with custom output format fails on filter encoding (#4190) - Fixed resolution when UoM changes in WCS 2.0 (#4283) - Added missing DEFRESOLUTION parameter to msCopyMap() function (#4272) - Migrated svn to git, and issue tracking from trac to github - Fixed mapscript is unusable in a web application due to memory leaks (#4262) - Fixed legend image problem with annotation layers with label offsets (#4147) - Add support for mutiple labels per feature (RFC81) - Add support for INSPIRE view service (RFC 75) - Drop support for GDAL/OGR older than 1.5.0 (#4224) - PDF backend: add support for generating geospatial PDF, when GDAL 2.0 with PDF driver is used, and the GEO_ENCODING FORMATOPTION (set to ISO32000 or OGC_BP) is added to the OUTPUTFORMAT definition. (#4216) - Python mapscript: fix swig mappings to work with both python 2.5.and 2.6 (#3940) - Added classgroup CGI parameter support (#4207) - Java mapscript: renamed shared library and completed libtool support (#2595) - Fixed WCS 2.0 axis order (#4191) - Added MS_CJC_* constants in PHP/MapScript (#4183) - Fixed Memory Leak with Fribidi Strings (#4188) - Allow multiple label definitions within a class (RFC 77/#4127) - shp2img: make it possible to specify layers (with -l option) that match GROUP names. - reuse a pre-parsed mapfile across fastcgi loops in case the mapfile is specified with the MS_MAPFILE env variable. (#4018) - Ability to do use PropertyIsLike with a column of a different type than text (postgis) (#4176) - Fixed SLD with FILTER doesn't apply properly to database layers (#4112) - Fixed lexer buffer size issue with single quotes in a string (#4175) - WFS Quote Escape issue (#4087) - Raster layer fails to be drawn if the window is less than half a pixel (#4172) - shptree: Improvement to reduce size of .qix files (#4169) - avoid potential gd fontcache deadlock on fastcgi exit signals(#4093) - Adjusted WCS GetCapabilities for an empty list of layers (#4140) - Adjusted WMS GetCapabilities for an empty list of layers (#3755) - Refactor cgi masperv to not call exit on argument errors (#3099) - Add --with-apache-module configure option to build an apache dso module (#2565) - Use libtool to build object files and libraries - Dynamically link libmapserver to the created binaries by default (requires the make install step to be run) - Python mapscript builds with make instead of setuptools - Fix LABELPNT geomtransform position for non-cached labels (#4121) - Add RFC80 font fallback support (#4114) - Added POLAROFFSET style option for a different symbol transform (#4117) - automatically translate vector symbol points (#4116) - Add RFC79 Layer masking (#4111) - Fixed single pixel coverages in WCS 2.0 (#4110) - Add svg symbols support (#3671) - Fixed subsetting in WCS 2.0 (#4099) - Upgrade clipper library to 4.6.3 - Make openlayers wms template request images with mimetype of outputformat defined in the mapfile's imagetype - Fix memory leak in msSLDParseRasterSymbolizer() - Fix compilation error with clang in renderers/agg/include/agg_renderer_outline_aa.h - Add stable hatch rendering (#3847) - Added vector field rendering (#4094) - Add wms dimensions support (#3466) - Fixed segfault when calling classObj::updateFromString() with SYMBOL (#4062) - Use a renderer native follow text implementation if available. - Fixed layer with inline feature to support multiple classes (#4070) - Add support for rfc45 anchorpoint on marker symbols (#4066) - Add initial gap support for line marker symbols (#3879) - Fix center to center computation of gaps for line marker symbols and polygon tile patterns (#3867) - Add initial gap support for line patterns (#3879) - Fixed grid of thin lines in polygon symbol fills (#3868) - Fixed cannot add a style to a label in PHP/SWIG Mapscript (#4038) - Fixed schema validity issue for WCS 1.1 GetCoverage responses (#4047) - remove default compiler search paths from the GD CFLAGS/LDFLAGS (#4046) - Fixed Python Mapscript does not write COLOR to reference map (#4042) - Added XMP support for metadata embedding, RFC 76, (#3932) - Added GetLegendGraphic Cascading support (#3923) - Rewrite postgres TIME queries to take advantage of indexes (#3374) - Unified OWS requests and applied to WCS (defaults to version 2.0 now) (#3925) - WCS 1.0: Fix crash with some _rangeset_axes values (#4020) - WCS 2.0: Adjusted offset vector and origin (#4006) - Added addParameter() method to MapScript (#3973) - Changed msDrawVectorLayer() not to cache shapes if attribute binding is present after the first style (#3976) - Fix mapscript to build when TRUE macro is not defined (#3926) - Fix mapscript php build issues with MSVC (#4004) - PHP MapScript is missing many styleObj properties (#3901) - PHP/Mapscript: Segmentation fault when getting complex object using PHP 5.2 (#3930) - PHP/Mapscript: Fixed webObj->metadata returns a webObj (#3971) - WCS 1.1: Added check for imageCRS in msOWSCommonBoundingBox() (#3966) - Fixed contains operator in logical expresions (#3974) - WCS 1.0: WCS Exceptions raise mapscript exceptions (#3972) - WMS: LAYERS parameter is optional when sld is given (#1166) - Add runtime substitution for "filename" output format option (#3571) and allow setting defaults in either metadata or validation (preferred) blocks for both layer and output format. - Add non antialiased text rendering for GD (#3896) - Fixed OGC filter using expressions (#3481) - Fix incorrect rendering of GD lines between 1 and 2 pixels wide (#3962) - Add gamma correction to AGG polygon rendering (#3165) - Initialize the scalebar image color to transparent by default (#3957) - Do not divide by zero in io read/write funcs (#4135) IMPORTANT SECURITY FIX: - Fixes to prevent SQL injections through OGC filter encoding (in WMS, WFS and SOS), as well as a potential SQL injection in WMS time support. Your system may be vulnerable if it has MapServer with OGC protocols enabled, with layers connecting to an SQL RDBMS backend, either natively or via OGR (#3903) - Fix performance issue with Oracle and scrollable cursors (#3905) - Fix attribute binding for layer styles (#3941) - Added missing fclose() when writing query files (#3943) - Fix double-free in msAddImageSymbol() when filename is a http resource (#3939) - Fix rendering of lines with outlinewidth set if not on first style (#3935) - Correct SLD with spatial filters bbox and intersects (#3929) - Applied patch for ticket (symbol writing issues) (#3589) - Added WMS GetFeatureInfo Cascading (#3764) - Fixed png lib is not found on multiarch systems (#3921) - Fixed PHP MapScript opacity property of StyleObj no longer works (#3920) - Fixed Using STYLEITEM AUTO, loadExpression fails when the label text contains a space or begins with a double quote (#3481) - Fix for the cluster processing if the shape bounds doesn't overlap with the given extent (#3913) - Add support for dashes on polygon hatches (#3912) - Union layer 3 new processing options added (#3900) - Changed msRemoveStyle to allow removing all styles (#3895) - Fixed mssql2008 to return correct geometries with chart layer type (#3894) - Ensure msLayerSetProcessingKey() supports setting a NULL value to clear a processing key. - Write SYMBOLSET/END tags when saving a symbol file (#3885) - Make java threadtests work again (#3887) - Fix segfault on malformed filters (#3888) - Fixed the query handling problem with the Oracle spatial driver (#3878) - Fixed potential crash with AVERAGE resampling and crazy reprojection (#3886) - Adjusted OperationsMetadata for POST in WCS 2.0 GetCapabilities response - Fix for the warnings in mapunion.c (#3880) - SLD: correct when same layer is used with multiple styles (#1602) - Fixed the build problem in mapunion.c (#3877) - Implement to get all shapes with the clustered layer (#3873) - Union layer: Fixed the crash when styling source layers using attributes (#3870) - Added GEOS difference operator to expression support (#3871) - Improve rangeset item checking so that Bands=1,2,3 is supported with WCS 1.0 (#3919). - Fix GetMapserverUnitUsingProj() for proj=latlong (#3883) - Add support for OGR output of 2.5D geometries (#3906) Version 6.0.0 (2011-05-11) -------------------------- - apply fix for #3834 on legend icon rendering (#3866) - Union layer: Fixed a potential seg fault in msUnionLayerNextShape (#3859) - Cluster layer: Fixed the problem when returning undefined attribute (#3700) - Union layer: Fix for the item initialization at the source layer (#3859) - Union layer: Fixed the potential seg fault when STYLEITEM AUTO is used (#3859) Version 6.0.0-rc2 (2011-05-05) ------------------------------ - Fixed seg fault with [shpxy] tag... (#3860) - Removed obsolete msQueryByOperator() function - Call msLayerClose() before msLayerOpen() in the various query functions (#3692) - Fix WMS 1.3.0 to use full list of epsg codes with inverted axis (#3582) - PHP/Mapscript: Added getResultsBounds() method in layer object (#2967) - Fix SLD containing a PropertyIsLike filter (#3855) - Fixed msUnionLayerNextShape to return correct values (#3859) - Union layer: fix for the failure if one or more of the source layers are not in the current extent (#3858) - Fix memory leak in msResampleGDALToMap() (#3857) - Fix missing initialization of default formats in WCS 1.x. - Fix maxoverlapangle when value is set to 0 (#3856) Version 6.0.0-rc1 (2011-04-27) ------------------------------ - Fix for the styleitem handling with union layer (#3674) - Fixed mindistance label test to check layer indexes. (#3851) - Fixed segmentation fault in PHP/MapScript and improved the php object method calls (#3730) - Fix build issue related to unnecessary use of gdal-config --dep-libs (#3316) Version 6.0.0-beta7 (2011-04-20) -------------------------------- - Union Layer: fix for the STYLEITEM AUTO option (#3674) - Union Layer: Add support for the layer FILTER expressions, add "Union:SourceLayerVisible" predefined attribute (#3674) - fix circle layer drawing for edge case when point1.x==point2.x (#1356) - fix incorrect quantization for images with very large number of colors (#3848) - fix poor performance of polygon hatching (#3846) - upgrade clipper library to 4.2 (related to #3846) - Fix configure output for "WFS Client" (was reporting WMS info, #3842) - KML: latlon bbox for raster layers could end up being wrong for non-square requests (#3840) Version 6.0.0-beta6 (2011-04-13) -------------------------------- - define EQUAL/EQUALN macros if cpl_port.h was not included (#3844) - add configurable PNG/ZLIB compression level (#3841) - SLD: use pixmap size when parameter size is not specified (#2305) - fix memory leaks in mapgraticule.c (#3831) - fix runtime sub validation against web metadata, was using wrong lookup key - clean up the symbolset if we've used an alternate renderer for a layer (#3834,#3616) - fix crash on embeded legend with cairo raster renderer - fix crashes in SVG renderer on polygon symbol fills (#3837) - fix crash/corruptions with raster layers in pdf outputs (#3799) - fix memory leak in msFreeLabelCacheSlot (#3829) - use a circle brush for wide GD lines (#3835) - fix segmentation fault with transparent layers containing symbols (#3834) - fix memory leak on tiled vector polygons - fix segfault with marker symbols on short lines (#3823) - wms_getmap_formatlist causes first defined outputformat to be returned by getmap (#3826) - fix building of mapcluster.c when OGR support is disabled - fix some valgrind found memory leaks (offset symbols, and gd io contexts) - skip marker symbol with no defined SYMBOL (caused some memory leaks with uninitialized vector points) - fix crash in GD lines with floating point dash patterns (#3823) - Check renderer before using it when calculating label size (#3822) - allow palette file path to be relative to mapfile (#2115) - use supplied offset for brushed lines (#3825, #3792) - fix division by 0 error in bar charts for some ill-defined cases (#3218) - add GAP, POSITION and CAPS/JOINS to mapfile writer (#3797) - fix GEOMTRANSFORM rotation orientation for vector symbols (#3802) - GD Driver broken in FastCGI (#3813) - configure: look for libexslt.so under lib64 as well - Coding style and formatting fixes (#3819, #3820, #3821, and more) - More improvements to OpenGL error handling (#3791) - Added WMS GetFeatureInfo RADIUS=bbox vendor-specific option (#3561) Version 6.0.0-beta5 (2011-04-06) -------------------------------- - Fix setting of top-level mapObj member variables in PHP MapScript (#3815) - More robust OpenGL context creation on older video cards and drivers (#3791) - Allow users to set the maximum number of vector features to be drawn (#3739) - Fixed FCGI on Windows problem related to lexer (#3812) - KML: Add ows/kml_exclude_items (#3560) - Removed all refs left to MS_SYMBOL_CARTOLINE (#3798) - Removed GAP, PATTERN, LINECAP/JOIN and POSITION from symbolObj (#3797) - Fixed handling of STYLEITEM AUTO label position codes 10,11,12 (#3806) - Fixed msGEOSGeometry2Shape to handle 'GEOMETRYCOLLECTION EMPTY' as null geometry instead of raising an error (#3811) - Re-added the MYSQL JOIN support. Had been removed with the MYGIS deprecated driver. - Add opacity to legend (#3740) - Updated PHP/MapScript with the new objects properties (#3735) - KML: set layer's projection when it is not defined (#3809) - Updated xml mapfile schema and xsl with the new lexer properties (#3735) - Updated PHP/MapScript for MS RFC 69: clustering. (#3700) - Move allocation of cgiRequestObj paramNames/Values to msAllocCgiObj() (#1888) - Add support for simple aggregates for the cluster layer attributes (#3700) - Improved error reporting in msSaveImage() (#3733) - configure: look for libxslt.so under lib64 as well - added missing ';' before charset in WFS DescribeFeatureType header (#3793) - add brushed line support for agg renderer (#3792) - fix bug with marker symbols along offset line - fix for the cluster layer returning invalid feature count (#3794) - remove some compiler warnings - fix incorrect scaling of hatch symbol spacing (#3773) - fix incorrect background color for INIMAGE exceptions (#3790) Version 6.0.0-beta4 (2011-03-30) -------------------------------- - Fix shp2img's -i flag to honour map level transparent, image quality and interlace settings. - Make sure command-line programs use an exit status other than 0 when an error is encountered. (#3753) - Applied patch to filter unwanted fribidi characters (#3763) - Fixed lexer to set the proper state on URL variable substitutions - Fixed Memory leak in PostGIS driver (#3768) - Fixed PHP/MapScript symbol property setter method - fix memory leak in bar charts - fix some valgrind errors on agg rotated pixmap symbols - WCS 2.0: Adjusted definition of NilValues. - Fixed handling of PROJ_LIB value relative to mapfile path (#3094) - Fixed compilation error with opengl support (#3769) - add support for gml:Box for spatial filters (#3789) - fix query map generation error introduced in beta2 when output format initialized was made as needed. - fix incorrect PATTERN behavior on agg lines (#3787) - report SOS DescribeObservationType in Capabilities (#3777) - Updated lexer to detect time attribute bindings (e.g. `[item]`) in logical expressions - Fixed layer context expressions (REQUIRES/LABELREQUIRES) (#3737) - KML: Output ExtendedData (#3728) - Fixed OWS usage of multiple layers with same name (#3778) - WCS implementation should not lookup wms_* metadata (#3779) - WCS 2.0: Adjusted definition of rangeType. - Fixed OWS GetCapabilities to report only requests/operations that are enabled. - WCS 2.0: Report only bands in the range subset. - OWS requests should be completely blocked by default (#3755) - SLD: check for limit on dash arrays (#3772) - WMS: Apply sld after bbox and srs have been parsed (#3765) Version 6.0.0-beta3 (2011-03-23) -------------------------------- - apply min/max size/width style values to polygon spacing (vaguely related to #3132) - assure that a created tile has a non-zero width and height (#3370) - use png_sig_cmp instead of png_check_sig (#3762) - Rendering: scale style OFFSET and GAP the same way we scale other style attributes. Beforehand, we scaled them proportionaly to the computed width. - KML: fix rounding problem for point feautres (#3767) - KML: update code to reflect output changes. Fix true type symbols. (#3766) - SLD: Text Symbolizer now uses the new expression syntax (#3757) - WFS: correct bbox values for GetFeature with featureid request (#3761) - Mapscript Seg Fault on mapObj->getMetaData (#3738) - Correct double free in msCleanup(). - Initialize default formats in WCS. - Fix csharp Makefile.in (#3758) - Allow run-time subs in class->text (makes sense if you allow it in class->expression). - Fix build problem when --enable-cgi-cl-debug-args is enabled (#2853) Version 6.0.0-beta2 (2011-03-18) -------------------------------- - correct scaling of symbol GAP and PATTERN (#3752) - remove references to SWF/MING - CGI runtime substitution requires a validation pattern (was optional before) (#3522) - add a default png8 outputformat that uses AGG/PNG with quantization - change MS_INIT_COLOR to take alpha as a parameter - stop using style->opacity in rendering code, use alpha from colorObjs. - Fixed big Oracle memory leak when rendering in KML (#3719) - avoid linking in postgres dependencies unnecessarily (#3708) - don't initialize outputformats until they are selected - use "seamless" creation of tiles for polygon fills with vector symbols - Ability to escape single/double quotes inside a string (#3706) - Globally replace msCaseFindSubstring with strcasestr (#3255) - support GROUP layers in shp2img (#3746) - Honour MAXSIZE for WCS 2.0 responses (#3204). - fallback to ows_title for WCS ows:Title of CoverageDescription (#3528) - Added msIO_stripStdoutBufferContentHeaders() to strip off all Content-* headers from a buffer (#3673, #3665). - Added raster classification support for STYLE level OPACITY. - Allow attribute references, that is [itemname], within a TEXT string (#3736) - Fixed segmentation fault when parsing invalid extent arguments in shp2img (#3734) - Make "openlayers mode" work even without OWS support (#3732) - Add a static table to define the axis order for soem epsg codes (#3582) - Add possibility to use KML_NAME_ITEM (#3728) - Fixed mapfile parsing error when a label angle referenced an attribute (e.g. ANGLE [angle]) #3727 - Removed executable flag on some source files (#3726) - Fixed SQL Spatial to be able to use UniqueIdentifier field as unique key (#3722) - Fix PHP Windows build (#3714) - Fixed --with-opengl build issue: Look for OpenGL libs under /usr/lib64 as well (#3724) Version 6.0.0-beta1 (2011-03-09) -------------------------------- - Fixed Core Dump from Format=KML/Z with Oracle Spatial layers (#3713) - Call msPluginFreeVirtualTableFactory from msCleanup (#2164) - Avoid the crash if anglemode 'FOLLOW' is specified with bitmap fonts. (#3379) - Add argument check for processTemplate, processLegendTemplate and processQueryTemplate in the C# bindings (#3699) - Remove shapeObj.line, shapeObj.values, lineObj.point from the SWIG API which are redundant and undocumented. (#3269) - Remove map-oriented query modes (e.g. QUERYMAP). Use qformat parameter instead. (#3712) - Implement single-pass query handling in mssql2008 driver as per RFC 65. - Fixed Sql Server 2008 key column name truncation (#3654) - Added label position binding (#3612) and label shadow size binding (#2924) - Implement MS RFC 69: Support for clustering of features in point layers (#3700) - Implement MS RFC 68: Support for combining features from multiple layers (#3674) - Add support for WCS 1.1 Post (#3710) - Fixed OGR query handling according to RFC 65 (#3647) - Implement CLOSE_CONNECTION=ALWAYS to suppress the connection pooling for a particular layer. - Implemented RFC 67: Enable/Disable layers in ogc web services (#3703) - Class title can now be used in legends. It's value takes precedence over class name. Previously title was not used any place in the code but it is supported for read/write. (#3702) - Allow definition of nodata attribute for layers without results (via resultset tag). (#3701) - mapprojhack.c: restructure to avoid needing projects, or any internal knowledge of PROJ.4. - Fix newlines around part boundaries in WCS multipart results (#3672) - Added minfeaturesize support at layer or class level (#1340) - Implemented support in for classifying rasters using the new expression parsing (msGetClass()...) (#3663) - Implemented RFC 65 which improves and simplifies one-pass query support. This causes a few MapScript regressions with getShape/getFeature/getResultsShape. (#3647) - Support setting filenames for WCS GetCoverage results (#3665) - OGR auto-styling: use the color parameter and set the style's opacity when it is available. Allow symbols that can be stored externally (#3660) - Add possiblity to use symbols stored externally, accessed through http (#3662) - Better handling of temporary files (#3354) - Support curved features in PostGIS (#3621) - NODATA values now excluded from autoscaling min/max for non-eight scaling computations (#3650) - Fixed missing time in msDrawMap logging (#3651) - Fixed Auto Angle - incorrectly placed Labels (#3648) - Fixed Improper validation of symbol index values (#3641) - Removed BACKGROUNDCOLOR, BACKGROUNDSHADOWCOLOR and BACKGROUNDSHADOWOFFSET label parameters (#3609) - Fixed Transformation from XML to MapFile only handles one PROCESSING element (#3631) - Fixed 16bit classification support - problem introduced with new renderer architecture (#3624) - Cleanup open gdal datasets in msGDALCleanup() (if we have a very new GDAL). This makes it easier to identify memory leaks. - Add support for per layer tuning of the shape to pixel conversion (SIMPLIFY, ROUND, SNAPTOGRID, FULLRESOLUTION) - Fixed: Memory allocation results should always be checked (#3559) - Fixed free(): invalid next size in mapfile.c (#3604) - Added a built-in OpenLayers map viewer (#3549) - Fixed issues with static buffers and sprintf (#3537) - Fix for the memory corruption when mapping the string data type in the Java bindings (3491) - Fixed double free in shp2img.c (#3497) - Fixed number of CGI params is limited to 100 (#3583) - Fixed duplicated XML and HTML errors from WFS GetFeature (#3571) - Support group names for GetLegendGraphic and GetStyles (#3411) - apply patch (thanks rouault) to advertise resultType=hits in WFS 1.1 Capabilities (#3575) - mapshape.c: Fix writing of geometries with z/m and fail gracefully attempting to create such files if USE_POINT_Z_M is not enabled (#3564) - sortshp.c: improve error handling (#3564) - MSSQL2008: Add support for geography data type by extending the DATA syntax to 'geometry_column(geometry_type) from table_name' - Fixed ability to get the error message and code of an OWS exception (#3554) - Fixed msOGRGetSymbolId according to the changes in gdal 1.8 (#3556) - Support holding WMS client requests in RAM instead of writing to disk (#3555) - RFC-61: Enhance MapServer Feature Style Support (#3544) - Restrict cascaded WMS requests based on EXTENT (#3543) - Avoid EPSG lookups for WMS client layers if possible (#3533) - RFC-60: Add ability to skip ANGLE FOLLOW labels with too much character overlap (#3523) - Fixed SWF: not a valid Bitmap FillStyle (#3548) - Set dependency on libxml2 when building --with-wfs (#3512) - Fixed TRUE is undefined in shptreevis (#3545) - shptreevis: bug truncates visualization shapefile if there are more nodes in the tree than there are shapes being indexed! - Fixed multiple include tags not supported in xml mapfiles (#3530) - Support reading .dbf files between 2GB and 4GB (#3514) - Avoid warnings about ms_cvsid being unused with gcc. - Ensure the class is not marked BeforeFieldInit causing memory corruption with C#/CLR4 (#3438) - Fixed MSSQL2008 driver returning invalid extent (#3498) - Added coordinate scaling to shpxy tag via parameters scale, scale_x or scale_y. - Fix computation of shape bounds when the first line contains no points (#3119)(fixes #3383) - Allow map relative specification in the PROJ_LIB config item (#3094) - Try to report reprojection errors in SLD Filter evaluation (#3495) - Disabled some insecure (and potentially exploitable) mapserv command-line debug arguments (#3485). The --enable-cgi-cl-debug-args configure switch can be used to re-enable them for devs who really cannot get away without them and who understand the potential security risk (not recommended for production servers or those who don't understand the security implications). - Fixed segmentation fault in ogr driver when shape type is null - Fixed synchronized MS_UNITS and inchesPerUnits array (#3173) - Fixed possible buffer overflow in msTmpFile() (#3484) - Fixed Using STYLEITEM AUTO, loadExpression fails when the label text contains a double quote (#3481) - PHP/MapScript: Expose getGeomTransform/setGeomTransform instead of exposing the private vars for rfc48 (#2825) - PHP/MapScript: Fixed updateFromString functions to resolve symbol names (#3273) - PHP/MapScript: ability to use the php clone keyword (#3472) - Modified mapserver units enum order to fix some problems with external softwares (#3173) - Fixed configure does not detect libGD version dependencies (#3478) - Fixed Drawing inline text not working (bitmap) (#3475) - ensure well formed XML when msWCSGetCapabilities_CoverageOfferingBrief returns MS_FAILURE (#3469) - Fixed msQueryByRect does not use tolerance (#3453) - Fixed MapScript processTemplate and processQueryTemplate seg fault (#3468) - Fixed shapeObj->toWkt() returns single point for multipoint geometry (#2762) - Fixed Internal server error when Oracle returns ora-28002 code (#3457) - Fixed PHP/MapScript ms_iogetstdoutbufferbytes() always returning 0 bytes written (#3041) - MapScript resultsGetShape() method fails with a OracleSpatial layer (#3462) - PHP/MapScript circular references between objects (#3405) - Handle null results with gml:Null/gml:null according to version (#3299) - Reworked mapfile writing to use helper functions so that core types (e.g. numbers, strings, colors, keywords, etc...) are always written consistently. - Ensure mapwmslayer.c does not unlink file before closing connection on it (#3451) - Fix security exception issue in C# with MSVC2010 (#3438) - Write out join CONNECTIONTYPE when saving a mapfile. (#3435) - Fixed attribute queries to use an extent stored (and cached) as part of the queryObj rather than the map->extent. (#3424) - Reverted msLayerWhichItems() to 5.4-like behavior although still supporting retrieving all items (#3356,#3342) - Grid layer: remove drawing of unnecessary gird lines (#3433) - Avoid errors and debug output for CONNECTION-less OGR layers in mappool.c if they have a tileindex. - Implement support for raw imagemodes to use NULLVALUE formatoption to set the background value of result images, and to try and mark nodata (#1709) - Implement support for wcs_rangeset_nullvalue to set NULLVALUE and return null value definition in describe coverage result (#655) - Try to avoid exhausting the color table when rendering 24bit key images into 8bit results (#1594) - Avoid crash, and ensure error report when loading keyimage fails (#1594) - Improve the handling of simple string comparisons for raster classified values (#3425) - Generate good SQL when using !BOX! token and no filter. (#3422) - Implement non-shapefile tileindex support for raster query (#2796). - Improve support for [red/green/blue] classification expressions for raster query (#1021) - Fixed imageObj->saveImage() sends unnecessary headers (#3418) - Avoid automatically regenerating maplexer.c (#2310) - Change rounding rules for average resampling (#1932) - Implement support for filename encryption per RFC 18 for rasters (#3416) - Fixed segfault when using shapefile with empty geometry and tileindex (#3365) - Avoid race condition on core_lock on win32 mutex init (#3396) - Avoid use of inline keyword for C code (#3327) - Support WFS parsing through libxml2 (#3364) - Fixed PHP/MapScript imageObj->saveImage() function (#3410) - Implement wms_nonsquare_ok metadata item for WMS servers that do not support non-square pixels (#3409) - Fixed MapScript shape->classindex is always 0 (#3406) - Fixed PHP MapScript integer passing broken on 64bit systems (#3412) - Fix MS_NONSQUARE to work in mode=map (#3413) - Support inclusion of raster layers in query map drawing even if the results may not be that useful (#1842). - Fixed auto angle: incorrectly rotated Labels. Added AUTO2 angle mode. (#1688) - Preliminary implementation of validity mask (imageObj->img_mask) for raw raster data (#2181) - Added libgd < 2.0.30 compatibility (#3293) - Incorporate support for GDAL nodata on RGB images (#2404) - Incorporated support for GDAL masks (GDAL RFC 15) (#2640) - Fixed XML transformation issues with expressions and symbols (#3397) - Check error returns from mapstring functions (#2988) - Add support for multiliple srs in WFS 1.1.0 (#3227) - Fixed PHP/MapScript owsRequestObj->loadParams() method when using php in a non cgi/fcgi/cli mode. (#1975) - Ensure that non-file raster datasets work (#3253) - Correct mutex locking problem with rasters with no inherent georef. (#3368) - Correct ungeoreferenced defaults via GetExtent() on raster layer (#3368) - PHP Mapscript refactoring: take full advantage of PHP 5 / Zend Engine 2 (#3278)" - Fixed msRemoveHashTable() to return the proper value on failure/success. - Correct one pass query problems and OGC filter query (#3305) - Fixed msMSSQL2008CloseConnection() to free the statement handle properly (#3244) - Fixed the query handling with the MSSQL2008 driver (#3058) - Fixed swig zoomRectangle() method: the maxy in the rect object have to be < miny value (#3286) - Fix crash with GRID layers with no classes (#3352) - Remove "legacy" raster support, all raster rendering via GDAL now. - Very preliminary render plugin support for raster rendering. (RFC 54) - support correct MIME type output for WFS 1.1.0 (#3295) - add WMS 1.3.0 LayerLimit support (#3284) - fix WFS 1.1.0 exception attributes (#3301) - add more useful error message when query file extension test fails (#3302) - s/gml:null/gml:Null for empty WFS GetFeature responses (#3299) - Support metatiling and buffers in mode=tile (#3323) - Enhance error messages in msGetTruetypeTextBBox() (#3314) - Report parsing errors in INCUDEd files using the line number within the file (#3329) - Avoid memory error when building SQL bbox (#3324) - Reproject rectangles as polygons to get datelin wrapping (#3179) - Add support for the WMS capabilities items AuthorityURL, Identifier (#3251) - Added support to write a null shape in a shape file. (#3277) - Apply ON_MISSING_DATA to zero-length WMS client calls (#2785, #3243) - PHP/Mapscript: added labelCacheMember object and mapObj::getLabel() method (#1794) - Add shplabel tag support in templates (#3241) - Bumped GEOS requirement to version 3.0+ (#3215) - Fixed memory leak related to templates (#2996) - Added support of 44xx gtypes in oracle spatial driver (#2830) - Fixed curl proxy auth support for http connections (#571) - PHP/MapScript: removed deprecated class properties (#2170) - Fixed OGR datasource double free (#3261) - Fix compilation warnings around use of strcasestr (#3257) - Made %substitution% strings case insensitive (#3250) - Added support to get the extent of a raster layer that use a tileindex (#3252) - Fixed configure to support FTGL 2.1.2 (#3247) - Changed msSaveImageBufferGD to be in accordance with msSaveImageGD (#3201) - PHP/Mapscript: added layerObj units property (#3249) - Changed the query map rendering implementation without adding extra layers to the map (#3069) - SQL Server 2008 plugin is not handling null field values correctly (#2893) - Hatch symbol not properly saved (#2905) - Expose symbolObj.inmapfile to the SWIG API, have already been exposed to PHP (#3233) - Expose getGeomTransform/setGeomTransform to SWIG instead of exposing the private vars for rfc48 (#3214) - Fixed writeSymbol to support writing 'ANGLE AUTO' (#3214) - Fixed problems with point queries not working via the CGI (mode=query or mode=nquery) (#3246) - Support QueryByShape() with point and line geometries (#3248) - Honour MAXSIZE for WCS responses (#3204) - Implemented RFC 52 LayerResultsGetShape support for OGR connection type. - Fixed uninitialized variable with malloc used in osPointCluster() (#3236) - Oracle driver: remove BLOB columns instead of changing them to null (#3228) - Fixed ogc sld functions to return proper values (#2165) - MAP EXTENT truncates GetFeature requests for data outside bounds (#1287) - Added msStringSplitComplex function (#471) - Mapserver WFS should send maxfeatures to the spatial database (#2605) - WFS paging support (#2799) - Fixed joins do not accept crypted passwords (#2912) - Fixed HTML legend image samples truncated (#2636) - WMS GetFeatureInfo should respect the scale like GetMap does (#842) - Filter encoding: simple filters using propertyislike not applied properly #2720, #2840 - Fix VBAR Chart production when using GD for rendering (#3482) Version 5.6.0 (2009-12-04): --------------------------- - WFS hits count is incorrect if the request contain 2 layers or more (#3244) - Fixed a problem with layer plugin where copyVirtualTable didn't copy the LayerResultsGetShape function pointer (#3223) Version 5.6.0-rc1 (2009-11-27): ------------------------------- - Fixed a problem with shape-based queries against projected layers when using a tolerance (#3211) - Fixed long expression evaluation (#2123) - Added simplfy and topologyPreservingSimplify to MapScript (#2753) - Fixed Oracle FastCGI memory leak (#3187) - layer->project flag not being reset properly for drawquerylayer (#673 #2079) - OGC SLD: support multi-polygons geometries for filters embedded in an SLD (#3097) - [WMC] embedded SLD in context does not work with namespace prefix (#3115) - Support name aliases used in sld text symbolizer (#3114) - decode html and unicode entities for polygon truetype symbol fills (#3203) - Parse PropertyName parameter for wfs requests (#675) - Fixed when saving a map, layer->transform isn't written properly in all cases. (#3198) - Fixed buffer overflow in oracle spatial driver with large sql data (#2694) - Improve FastCGI include file finding logic (#3200) Version 5.6.0-beta5 (2009-11-04): --------------------------------- - Apply a minimum width on label outline (new outlines were too thin by default) - Don't apply scalefactor to polygon outline widths (but apply the resolutionfactor) - Fix vector symbol size calculation (#2896) - Applied code clean up patch for mapsearch.c. (#3189) - Fixed labels centering when the label is longer than the line (#2867) - Ensure Python MapScript building doesn't reorder the libraries, support the 'subprocess' module where available for setup.py, and default to using the "super" swig invocation described in the Python MapScript README when mapscript_wrap.c isn't available on the file system. #2663 contains the reordering issue. - Fixed memory leak with shapefiles associated with one-pass query implementation (#3188) - Fix abs/fabs usage that prevented angle follow labels to be discarded if they were too wrapped on themselves - Allow CGI mapshape and imgshape variables to consume WKT strings (#3185) - Added support for nautical miles unit (#3173) - Fixed encoding metadata ignored by a few wcs/wfs 1.1 and sos requests (#3182) - PHP/Mapscript: added "autofollow" and "repeatdistance" in labelObj (#3175) - Added charset in content-type http header for wms/wfs/sos/wcs requests (#2583) - Python/MapScript: improve compatibility for different swig versions (#3180) - maprasterquery.c: a few fixes since beta4 (#3181, #3168). - mapows.c: Generate WMS LatLongBoundingBox in WGS84 datum (#2578) Version 5.6.0-beta4 (2009-10-18): --------------------------------- - Allow processing of single shapefiles with no items (e.g. an empty dbf file) (#3147) - Added resolution scaling for swf, svg, pdf and imagemap drivers (#3157) - Correct cases where a valid WFS Layer might return errors if map extent does not overlap the layer extent (#3139) - fix problem with 0-length line patterns in AGG - Fixed problem of text/html WMS GetFeatureInfo which was returning HTML image map output instead of the expected text/html template output. This was done by changing the imagemap outputformat to use the "text/html; driver=imagemap" mime type (#3024) - more resolution fixes for resolution scaling (symbolscale case) (#3157) - Make sure layer extents are saved when a mapfile is written (#2969) - Fixed CurvePolygons from oracle not drawn (#2772) - Fixed raster queries (broken by RFC 52 changes) (#3166) - Fixed coordinate projection problem in some cases with WMS GetFeatureInfo output in GML2 format (#2989) - Added resolution scaling of some properties for GD driver (#3157) - Modified GD functions API to be consistent with all others drivers (#3157) - OGC Filter: strip all namespaces (not only ogc, gml) (#1350) - Use decimal values for size and width in SVG output format (#2835) - Correct invalid test when loading movies in an swf ouput (#2524) - Return WMS GetCapabilities v1.3.0 by default as required by spec (#3169) - Fixed mapObj.zoomScale() and mapobj.zoomRectangle() scaling problem in Mapscript (#3131) - Few more fixes for high res output (#3157) - Allow "DRIVER 'TEMPLATE'" or "DRIVER TEMPLATE" in output formats - Correct sld generated from mapserver classes (#3133) - Correct libjpeg v7 compatability issue in old jpeg interface code (#3167) - Correct FEATURE_COUNT limits on WMS GetFeatureInfo raster queries (#3168) - Correct SCALE_BUCKETS issue with 16bit raster scaling (#3174) Version 5.6.0-beta3 (2009-10-07): --------------------------------- - make RFC55 highres output be friendly with scaledependant rendering (#3157) - avoid fractured and overlapping glyphs with angle follow (#2812) - Fixed SDE layer seg fault (#3152) - Fixed placement of labels using ANGLE AUTO which were not always positioned correctly (#3160) - Enable output of geometry in GML GetFeatureInfo if wms_geometries and wms_geom_type are specified (#2989) - fix URN typo in mapwfs.c for urn:EPSG:geographicCRS:... - don't apply scalefactor to label outlines (#3157) - update namespaces and schema pointers (#2872) - add RFC49 and RFC40 keywords to copy functions (#2865) - minor fix to correct numberOfResults when maxfeatures is set in mapfile (#2907) - Fixed possible crash with WFS GetFeature when no projection is specified at the map level (#3129) - Fixed anchor point of vertically stacked bar graphs - Fixed TEXT property that cannot be removed in the CLASS object. PHP/Mapscript (#3063) - Fixed use of minfeaturesize auto with curved labels (#3151) - Fixed msRemoveHashTable function when 2 keys have the same hash (#3146) - Fix raster thread deadlock condition on posix/linux (#3145) - Do not route thread debug output through msDebug which requires locking. - Fix WCS coverage metadata handling if size/resolution missing (#2683). - Fix WCS crash with use of datasets that aren't physical files (#2901). - Fix WCS failure with WCS 1.1 OGC URN (urn:ogc:def:crs:OGC::CRS84) (#3161). Version 5.6.0-beta2 (2009-10-01): --------------------------------- - Fixed a couple of issues with Oracle Spatial and single pass queries (#3069) - Added layer.resultsGetShape() to PHP MapScript for use with queries (#3069) - Fixed query maps under the new single pass query process (#3069) - WFS Client seg fault (OGR layer not opened) (#3136) - Reduce use of sqrt() calls when determining distances (#3134) - support axis ordering for WFS 1.1 (#2899) - const changes to avoid warnings with msLoadProjectionString() - mapgd.c: removed unused drawVectorSymbolGD() function. - Use http://www.mapserver.org/mapserver namespace URI in XML mapfile schema (#3142) - Fixed issue with PHP_REGEX_INC in mapscript/php3/Makefile.in (#3078) Version 5.6.0-beta1 (2009-09-23): --------------------------------- - WMS 1.3.0 expects a CRS parameter instead of SRS (#2979) - Allow users to set wms getmap and getlegendgraphic image format list (#455) - Fixed MapScript shapeObj->toWkt() segfaults (#2763) - add vertical bar charts to dynamic charting (#3128) - Get the intersection points and labels #3101 - Fixed shp2img not to cause a crash when the map couldn't be loaded - Fix problem with overflowing shape->index for (most) query modes (#2850) - Useful error message when PK is missing and data is subselect (#3124) - Add WMS root Layer metadata support (#3121) - Fixed build problem of PHP/Mapscript when php is compiled with gd as a shared extension (#3117) - Improve safety of srcx/y checks in nearest neighbour raster resampler (#3120) - Added support for 4d geometry types and oci bind variables for Oracle (#3107) - Implement SECTION support for the WCS 1.1 GetCapabilities request (#3105) - Fixed WCS processing when both crs and response_crs are specified (#3083) - Fixed msFreeMap causing memory corruption in msFreeOutputFormat (#3113) - Fix WMC XML output when Dimension is used (#3110) - Enable LOAD_WHOLE_IMAGE processing option by default when rendering WMS client layer images (#3111). - add default values for CGI %key% substitutions (#3108) - fix clipping of polygon shapes in line layers (#3059) - RFC 51 implementation: XML Mapfiles Format (#2872) - Fix output for valid WCS 1.1 XML (#3086) - Avoid double free with postgresql joins. (#2936) - Don't attempt to project layers given in pixel coordinates (layer->transform != MS_TRUE) (#3096) - Modify loading imagery from GDAL to load all bands at once to avoid multiple passes through pixel interleaved data (mapdrawgdal.c). This is just an optimization - there should be no change in results or features. - Modern GDALs clear the config when destroying driver manager. Skip this call to avoid TLS leakage on cleanup (mapgdal.c). - Fixed msMSSQL2008LayerGetShape to retrieve proper wkb geometries (#3082) - Fixed the shape index for the inline layers (#3074) - Fixed MINDISTANCE not considering label size on lines (#3050) - Labeling enhancements: ability to repeat labels along a line/multiline (#3030) - Modified STYLEITEM code to use the new way of rendering thick lines (#3025) - Fixed template processor to respect layer order. (#2619) - Add MS_DEBUGLEVEL and MS_ERRORFILE commandline switches for mapserv.c. - Exposed msMapOffsetExtent, msMapScaleExtent and msMapSetCenter methods in PHP/Mapscript (#2460) - Removed ZEND_DEBUG define in PHP/Mapscript (#2717) - Fixed PHP/Mapscript to support PHP 5.3 (#3065, #3066) - remove -O optimization flags to configure script if configured with --enable-debug - Fixed performance bottleneck when computing a polygon center of gravity for label point computation. (#3053) - make WFS numberOfFeatures match maxFeatures if passed (#2907) - Add logging in layer visibility tests to help users find why layers don't draw (#3054) - include PNG libs first (#3046) - merge graphics branch: RFC54 implementation, cairo rendering (png, svg, pdf), opengl rendering (non functionnal yet) - Do pre-emptive test for map.extent/layer.extent interaction (#3043) - Add centroid geomtransform (#2825) - Test database connections before using them (#2932) - Support non-numeric join criteria (#2006) - Ensure there's enough room in the SQL to hold a long (#1284) - Fix filter error in multi-clause filters (#2937) - Fix agg freetype character lookup when no unicode charmap is present (#3018) - Fix memory leak in SQL building (#2997) - Fork AGG rendering library in our trunk - Fixed a memory leak when unescaping quotes in logical expressions (#2938) - Fixed template code for item, shpxy and extent tags to properly initialize tag arguments in cases where there are mutiple tags in one chunk of template (#2990) - Fix mapogcfilter.c not to cause syntax error if PROJ.4 is not compiled in (#2987) - Rework Python MapScript's setup.py to be more like Python's to fix a number of issues including (#2637) and to use mapserver-config and ditch the old mapscriptvars approach - Prevent from changing the connection type to MS_RASTER when setConnectionType(MS_WMS) is used (#2908) - Improve rounding logic for computing the src_xoff/yoff (#2976) - Fix filename path processing for raster queries and WCS get coverage so that non-filesystem filenames are not altered (#2901) - Improved security relative to untrusted directories and mapfiles (RFC 56) - Fixed several security issues found in an audit of the CGI application (#2939, #2941, #2942, #2943, #2944) - setConnectionType(MS_WMS) doesn't work with mapscript (#2908) - Perl Mapscript: improvement of imageObj wrapper (#2962) - Improve control of output resolution (RFC 55, #2948) - mapraster.c: use GDALOpenShared(), and CLOSE_CONNECTION=DEFERRED (#2815) - AGG font outline method change (#1243) - Change mapbit.c bitmask type from char to new 32bit ms_bitarray (#2930) - Added resolution writing in image files (#2891) - Try to save resolution values to GeoTIFF via GDAL (#2891) - Refactor legend icon drawing (remove renderer specific versions) Add label styling or markers for annotation layer legend icons (#2917) - Update EXTENT warning message (#2914) - add support for SRSNAME parameter (#2899) - add support for resultType (#2907) - WFS 1.1.0 should use OWS Common 1.0.0 (#2925) - clean up GEOS init and cleanup functions (#2929) - add support for disabling SLD (#1395) - fix to output gml:boundedBy again (#2907) - fix warning for change in bitmask type (#2930) - fix time advertising in WMS 1.3.0 (#2935) - fix SOS blockSeparator output (#3014) - fix MIME type support (#3020) Version 5.4.0-beta3 (2009-3-5): -------------------------------- - SLD: Correct crash with large class names (#2915) - Added Java MapScript WIN64 support (#2250) - Fixed a problem with long running processes, embedded scalebars/legends and AGG. (#2887) - Applied patch to deal with a couple of WCS issues (time ranges, #2487) and PostGIS tileindex-based time filters (#1856) - Adding -DUSE_GENERIC_MS_NINT to the WIN64 MapScript builds (#2250) - Fixed C# the compiler options for MSVC 2008 (#2910) - Fix build problem with mapogcsld.c when OWS services are not available (#473) - Fix build on windows (maputil.c) Version 5.4.0-beta2 (2009-2-25): -------------------------------- - Fixed a problem where default shade symbols (solid fill, no size) were being scaled and not rendered as expected (related to #2896 I believe) - Fixed a problem with offset polylines (AGG only) (#2868) - Generate SLD version 1.1.0 (#473) - Tracking original geometry type so we can make better decisions on what positions to use with POSITION AUTO and annotation layers. (#2770) - Setting up the same size units between the OGR auto-style and the OGR label attribute binding option (#2900) - Take better care of the extra items with the inline layers to prevent from memory corruption (#2870) - Fixed the compiler options for MSVC 2008 (#2898) Version 5.4.0-beta1 (2009-2-18): -------------------------------- - restored much of the pre-5.0 capabilities to update a mapfile via URL but in a more secure manner (RFC44) - WMS 1.3.0 support added (#473) - OWS GetCapabilities should skip layers with status == MS_DELETE (#2582) - Set the default symbol size to 1 instead of 0 (#2896) - fix WMS LegendURL to print sld_version for 1.3.0 Capabilities (#473) - add GetSchemaExtension to WMS to support GetStyles in Capabilities XML (#473) - move xlink declaration to root of WMS 1.3.0 DescribeLayerResponse - Fixed a scalebar rounding problem causing to draw zero scalebar width (#2890) - SLD: if it contains a Filter Encoding tag, try to always set the layer's FILTER element (#2889) - Add support for rendering INLINE layers with layer attributes (items) (#2870) - Fix mapserver crash when rendering a query map in HILITE mode and there are is no STYLE defined (#2803) - Added projection support to [...ext] tags for template output. - Removed the error generation when the OGR layer contains no fields (#2883) - Added enhancements to mapogr.cpp for style annotations (#2879) - Fixed memory leaks when using msUpdate*FromString methods. (#2857) - Fixed the problem when removing the attribute binding in mapscript. - SOS XML validity fixes (#2646) - add WFS calls for schema resolution (#2646) - add gml:id to om:Observation (#2646) - fix some XML validity issues (#2646) - Fixed endianness issues with wide character strings for ArcSDE (#2878). Thanks Russell McOrmond - Fixed WMS request with LAYERS parameter: may cause segmentation fault (#2871) - fix when layer status = DEFAULT and passing list of layers (#2066) - Fixed msAddLabel may cause access violation in certain conditions - Changed base type of labelObj size, minsize and maxsize from int to double (#2766) - add support for WMS Server title in LAYER object (#885) - Fixed build problem using --with-gd=static and freetype (#2697) - RFC49 implementation (#2865) - Fixed Blobs not filtered in OracleSpatial Attribute/WFS queries (#2829) - Fixed memory leak of map::setProjection in PHP/MapScript (#2861) - Fixed "internal PHP GC memory leaks" in PHP/MapScript (#2767) - Fixed bug with wms layer group hierarchy (#2810) - Added updateFromString() methods for several objects in PHP/Mapscript (#2298) - Added ms_newMapObjFromString mapObj constructor in PHP/Mapscript (#2399) - Add support to compile mssql2008 when SDE or ORACLE is not compiled (#2851) - Add support for creating debug builds for the plugins on Windows - Correct half pixel error in WMS layer's BBOX request to remote WMS (#2843) - Expose Map/Layer's Projection objects in PHP/MapScript (#2845) - Added getUnits() methods to projectionObj in Mapscript (#2798) - Improved Tag parsing in template code. (#2781) - Added hashtable object and metadata methods for php-mapscript (#2773) - mappostgis.c: Fix trailing spaces in fixed varchar fields (#2817) - RFC48 implementation: GEOMTRANSFORM on styleObj (#2825) - mapwms.c: cleanup warnings with recent gcc versions (#2822) - mapogcsos.c: Cleanup warning and error messages - mapagg.cpp: Fix center of rotation for truetype marker symbols - mapowscommon.c: use msLibXml2GenerateList to generate listed XML elements - mapowscommon.c: output version string correctly (#2821) - Added removeLayer function to mapObj in PHP/MapScript. (#762) - Exposed PIXELS value via URL configuration - Add Support for SLD TextSymbolizer HALO and ANGLE (#2806) - IGNORE_MISSING_DATA: largely replaced by run-time CONFIG property, ON_MISSING_DATA, which supports three modes: FAIL, LOG, and IGNORE. (#2785) ms-rfc-47.txt - mapstring.c: msStringTrim(*char str), front-and-back whitespace trimmer - mappostgis.c: re-write to remove binary cursors and break up logic into smaller parts, add support for maxfeatures - mapogcfilter.c: increase array size (code was assigning to out of bounds subscript) - MapScript: Added getBinding method to label and style object (#2670) - mapowscommon.c: use strcasecmp to check for language value - raster query fix for tileindex with relative paths (#2722) - Fixed msOGRGetValues function to return default values if the object type is not TEXT. (#2311) - Fix for the access violation caused by msMSSQL2008LayerGetShape (#2795) - Fixed msMSSQL2008LayerGetItems to retrieve the column names properly (#2791) - Prevent from calling msMSSQL2008CloseConnection from msMSSQL2008LayerClose causing memory corruption issues (#2790) - new polygon label placement algorithm (#2793) - stop drawing an artificial outline around polygons to ensure continuity - users needing this feature will have to explicitely add an outlinecolor of the same color as the fill color - added formatoption QUANTIZE_NEW to force going through the pngquant quantization algorithm instead of the GD one for imagemode RGB (the GD one can be kind of buggy) - fix some integer rounding errors in the agg line offseter (#2659) - fix a bug with shapes with duplicate end points. was causing nans in the angle follow placement code (#2695) - refactor msGetLabelSizeEx (now merged with msGetLabelSize) (#2390) - native label size computation for AGG when using angle follow (#2357) - memory leak in msInsertLayer, from Ned Harding (#2784) - label size computation refactoring (#2390) - don't draw label background if we're using angle follow. (#2726) - legend keyimage resampling with agg (#2715) - tileindexed rasters when DATA is manipulated via mapscript work (#2783) - styleObj width now supports attribute binding - RFC40 implementation: label text wrapping and alignment (#2383) - baseline adjustment for multiline labels (#1449) - Added support to access to the labelObj OUTLINEWIDTH property in PHP/MapScript - PHP paste image should also work with AGG (#2682) - Fixed bug when QUERYMAP hilite color is set and the shape's color in a layer is from a data source (#2769) - Decoupled AUTO label placement from the positions enum in mapserver.h. Added explicit case for POLYGON layers where CC is the default and then we try UC, LC, CL and CR. (#2770) - Changed base type of styleObj size and width from int to double (#2766) - Correct allocation error in mapmssql2008.c - Add possibility to use a full resolution setting for svg output (#1706) - Fixed GetFeature through tileindex bug: the tileindex of the shape found wasn't set properly in the resultcache object. (#2359) - Removed comma to correct WCS 1.1 Coverages formatting in payload directory. (#2764) - Correct bug when LABEL_NO_CLIP in combination with minfeaturesize (#2758) - Fix a label size computation for AGG bug when scalefactor is used (#2756) - various SOS updates for CITE compliance (#2646) - Added support for static linking with the lib gd in configure script (#2696) - Support OpenLayer's ol:opacity extension to OGC Web Map Context docs (#2746) - Added MS_VERSION_NUM for use with #if statements in code based on libmapserver (#2750) - Fixed the configure script: failed to detect php5 on ubuntu. (#2365) - Fixed a memory leak associated with not deleting the lexer buffer before parsing certain types of strings. (#2729) - Added legend graphics for layer of type annotation for the AGG and GD renderer (#1523) - Masking the out-of-range characters to avoid the crash in the AGG renderer (#2739) - Accept WMS requests in which the optional SERVICE parameter is missing. A new test was incorrectly added in 5.2.0 that resulted in the error "Incomplete WFS request: SERVICE parameter missing" when the SERVICE parameter was missing in WMS requests in which the SERVICE parameter is optional (#2737) - Support for the MapInfo style zoom layering option (#2738) - Implement Equals and GetHashCode properly for the mapscript C# classes - Expose msConnectLayer to the SWIG mapscript interface with a new layerObj.setConnectionType() method that should be used instead of setting the layerObj.connectiontype directly (#2735) - SLD: when creating well known symbols on the fly the pen-up value used should be -99. - SWF: Button names reflects the layer id and shape id (#2691) - Support reading projection parameter for OGC filters (#2712) - Several enhancements to STYLEITEM AUTO support for labels (#2708) and TTF symbols (#2721) in OGR layers - Expose special attributes OGR:LabelText, OGR:LAbelAngle, OGR:LabelSize and OGR:LabelColor to MapScript getShape() calls (#2719) Version 5.2.0 (2008-07-16): --------------------------- - mapfile.c: Fixed a bug that prevented using named symbols via URL configuration. (#2700) Version 5.2.0-rc1 (2008-07-09): ------------------------------- - mapowscommon.c: fix support multiple namespaces (#2690) - Fix OGC simple filters on SDE layers (#2685) - wfs11 getcapabilities: correct memory corruption (#2686) - Allow building against Curl 7.10.6 and older which lack CURLOPT_PROXYAUTH option required for *_proxy_auth_type metadata (#571) - Avoid fatal error when creating new ShapeFileObj with MapScript (#2674) - Fixed problem with WMS INIMAGE exceptions vs AGG output formats (#2438) - mapshape.c: Fixed integer pointer math being applied to uchars (#2667) - Fixed seg fault with saveImage() in PHP MapScript due to #2673 (#2677) - Fixed configure error related to new fribidi2 pkg-config support (#2664) - Fixed windows build problem (#2676) - Fix raster query bounds problem (#2679) Version 5.2.0-beta4 (2008-07-02): --------------------------------- - Added support in configure script for pkg-config for fribidi2 (#2664) - Added more debug/tuning output to mapserv and shp2img at debug level 2 (#2673) - maptemplate.c: removed extra line feeds from mime header output. (#2672) - mapresample.c: fix for bug 2540 when using raster resampling and AGG. - mapsde.c: Check at compile time that we have SE_connection_test_server, which appears to only be available for ArcSDE 9+ (#2665). - mapshape.c: restore old behavior of tiled shapes relative to shapepath with new behavior for when shapepath is undefined (#2369) - maputil.c: fix a bug for offset lines with agg, when the first segment was horizontal (#2659) - mapraster.c: fix for tiled rasters with relative shape paths defined, from dfurhy (#2369) - maptemplate.c: fixed a problem with extent tags with _esc extension not working (#2666) Version 5.2.0-beta3 (2008-06-26): --------------------------------- - mapsde.c: processing option added to allow using fully qualified names for attributes (#2423). - mapsde.c: Test for an active connection before closing it (#2498). - mapdraw.c: Fixed issue where path following labels were not being drawn if FORCEd. (#2600) - mapshape.c: Applied patch to make the location of tiled data relative to the tileindex directory if SHAPEPATH is not set. (#2369) - maptemplate.c: Fixed issues in RFC 36 implementation that prevented mapscript mapObj->processQueryTemplate() method from working. - WMS/WFS: extend warning message (#1396) - WFS: Respect units for the DWhitin parameter (#2297) - WFS: correct OGC Contains filter (#2306) - WMS: set srsName correctly for GetFeatureInfo (#2502) - SOS: detect invalid time strings (#2560) - SOS: more srsName support (#2558) - mapserv.c, maptemplate.c: fixed problem with arguments to msGenerateImages(). (#2655) - WMS: produce warning if layer extent is null (#1396) - WFS: project LatLongBoundingBox if required (#2579) - SOS: generate error for some invalid filters (#2604) - SLD: Use style's width paramater when generating sld (#1192) Version 5.2.0-beta2 (2008-06-18): --------------------------------- - mapogcsos.c: support invalid procedure in GetObservation (#2561) - Fixed possible buffer overrun with Oracle Spatial driver (#2572) - mapogcsos.c: support srsName in GetObservation (#2414) - Filter Encoding: Modify DWithin definition (#2564) - Added webObj legendformat and browseformat mapping in PHP MapScript (#2309) - Removed static buffer size limit in msIO_*printf() functions (#2214) - Fixed libiconv detection in configure for OSX 10.5 64 bit (#2396) - mapstring.c: possible buffer overflow in msGetPath (#2649) - maputil.c: Correct expression evaluation with text containing apostrophes (#2641) - mapwfs.c: Possibly generate an error message when applying filter encoding (#2444) - Added MS_LABEL_BINDING constants for SWIG MapScript (#2643) - mapogcsos.c: fix POST support (#2379) - maplibxml2.c: helper functions XML POST fix (#2379) - mapwfs.c: fix segfault when srsName is not passed on BBOX Filter (#2644) - mapwfs.c: do not return error for empty query results (#2444) - Remove C++-style comments and most other warnings thrown by -pedantic (#2598) - mapwfs.c/mapwfs11.c: set GML MIME type correctly - mapogcsos.c: advertise supported SRS list via MAP.WEB.METADATA.sos_srs (#2414) - mapwfs.c: set layer extent to map extent for default GetFeature requests with no spatial predicates (#1287) Version 5.2.0-beta1 (2008-06-11): --------------------------------- - WMS/WFS layers can now specify a proxy servert (#571) - mapwmslayer.c: set QUERY_LAYERS correctly (#2001) - mapwcs.c: handle PARAMETER values correctly (#2509) - SOS: fix various memory leaks (#2412) - mapwcs.c: advertise temporal support in GetCapabilities (#2487) - Fixed flaw in findTag() in maptemplate.c that prevented multiple tags on the same line being processed under certain conditions. (#2633) - Return results even when extents are missing (#2420) - Avoid displaying OGR connection strings in error messages (#2629) - WCS: respect wcs_name metadata for GetCoverage and DescribeCoverage requests (#2036) - CGI: added -nh option to allow for the suppression of content headers from the command line (#2594) - PostGIS: fix postgis idle-in-transaction problem (#2626) - AGG: enable ellipse symbol rotation for POINT/ANNOTATION layers (#2617) - RFC36: add more extensions to support templates (#2576) - AGG: allow dashed hatch symbols (#2614) - AGG: enable offset lines of type x -99 (#2588) - AGG: use an agg specific label size calculation function where possible (#2357) - mapogcsld.c: fetch TextSymbolizer/Label/ogc:PropertyName correctly (#2611) - Don't ignore .qix file when DATA reference includes .shp extension (#590) - CGI able to alter layers with space and underscores (#2516) - WFS Multipoint query with PostGIS bug fixed (#2443) - Tiling API (RFC 43) mode=tile, tilemode=spheremerc, tile=x y zoom (#2581) - Remove C++-style comments and most other warnings thrown by -pedantic (#2598) - Fix PostGIS transaction behavior in fcgi situations (#2497, #2613) - Improve performance for large shape files (#2282) - encode WMS parameters correctly (#1296) - Added alignment option within a scalebar (#2468) - RFC-42 HTTP Cookie Forwarding (#2566) - Fixed handling of encrypted connection strings in postgis driver (#2563) - mapagg.cpp: AGG: add opacity at the style level (#1155) - mapwms.c: add Cache-Control max-age HTTP header support (#2551) - mapogcsos.c: support URI encoded procedures correctly (#2547) - Added support for EMPTY template with WMS GetFeatureInfo (#546) - Throw an exception if the WCS request does not overlap layer (#2503) - Acquire TLOCK_PROJ for pj_transform() calls (#2533). - Fixed problem with large imagemaps generating no output (#2526) - mapwms.c: make version optional for GetCapabilities again (#2528) - support URN scheme for components of observed property elements (#2522) - Fixed gdImagePtr gdPImg memory leak in msSaveImageBufferGD() (#2525) - mapogcsos.c: handle invalid POST requests (#2521) - mapogcsos.c: handle ACCEPTVERSIONS parameter (#2515) - mapwcs.c/mapwcs11.c: s/neighbour/neighbor/g (#2518) - mapwms.c: relax FORMAT parameter restrictions for GetFeatureInfo (#2517) - mapwcs.c: support COVERAGE lists for DescribeCoverage (#2508) - mapwcs.c: fix lonLatEnvelope/@srsName (#2507) - mapwcs.c: omit VendorSpecificCapabilities (#2506) - mapwcs.c: test for either resx/resy OR width/height (#2505) - mapwcs.c: make GetCoverage demand one of TIME or BBOX (#2504) - mapwms.c: make GetLegendGraphic listen to TRANSPARENT in OUTPUTFORMAT (#2494) - OWS: support updatesequence (#2384) - mapwms.c: test VERSION after service=WMS (#2475) - OWS: output Capabilities XML updateSequence if set (#2384) - mapwcs.c: better handling of REQUEST parameter (#2490) - mapwcs.c: point to correct exception schema (#2481) - mapows.c: add version negotiation (#996) - mapwfs.c: return default GML2 when invalid OUTPUTFORMAT passed (#2479) - mapowscommon.c: add OWS Common style version negotiation (#996) - mapwcs.c: better section parameter handling for CITE (#2485) - mapwfs.c: point to the correct schema for exceptions (#2480) - shp2img.c/shp2pdf.c: clean up usage text, check for invalid layers (#2066) - completed implementation of RFC24 (#2442, #2032) - mapwcs.c: require VERSION parameter for DescribeCoverage and GetCoverage (#2473) - mapwcs.c: change error token to MS_WCSERR instead of MS_WMSERR (#2474) - mapwcs.c: set exception MIME type to application/vnd.ogc.se_xml for 1.0.0 (#2470) - mapwcs.c: Generate a decently formatted exception if an WCS XML POST request is received (#2476). - mapowscommon.c: support OWS Common 1.1.0 as well (#2071) - mapogcsos.c: support SOS 1.0.0 (#2246) - Implement mapObj.setCenter, mapObj.offsetExtent, mapObj.scaleExtent, rectObj.getCenter at the SWIG API (#2346) - mapogcfilter.c: use USE_LIBXML2 in ifdefs (#2416) - clean up naming conventions of Shapefile API (#599) - use msComputeBounds() instead, since it's already in the codebase (#2087) - set shapeObj bounds from WKT (#2087) - fixed issue where path following labels sometimes used the supplied setting for position. In all cases with ANGLE FOLLOW we want to force position MS_CC regardless of what is set in the mapfile. - enforce (-99 -99) to be the penup value for vector symbols (#1036) - Support for labeling features (polygon & line) prior to clipping. This results in stable label positions regardless of map extent. (#2447) - Support for quantization and forced palette png output with RGBA images (#2436) - SLD using a single BBOX filter should generate an SQL ststement for oracle/postgis/ogr (#2450) - Accurate Calculation of legend size for WMS LegendURL (#2435) - Converted mapogr.cpp to use OGR C API instead of C++ classes to allow GDAL/OGR updates without having to recompile MapServer (#545, #697) - add missing space on dashed polygon outlines with svg (#2429) - Restored behavior of MS 4.10 and made WMS STYLES parameter optional again in GetMap and GetFeatureInfo requests (#2427) - Speed up forced palette rendering (#2422) - WMS GetFeatureInfo: honour FEATURE_COUNT for any INFO_FORMAT and apply the FEATURE_COUNT per layer instead of globally (#2423, #1686) - enable soft outlines on truetype labels. This is triggered with a new keyword OUTLINEWIDTH for the LABEL block (#2417) - fix clipping rectangle to take width as well as size into account (#2411) - AGG: added and use a line and polygon adaptor to avoid copying shapeObj points to an agg path_storage. avoids a few mallocs and a few copies. - fixed symbolsetObj not to set the SWIG immutable flag permanently don't expose refcount and the symbol attributes (Ticket #2407) - fix for support of entity encoded text in angle follow text (#2403) - AGG: initial support for native computation of label sizes (#2357) - AGG: support text symbols specified by their character number (#2398) - AGG: fix angle orientation for various symbols - allow scientific notation for attributes binded to an int (#2394) - merge GD and AGG label cache drawing functions (#2390) - Enable AGG rendering of bitmap font labels instead of falling back to GD (#2387) - clean up treatment of encoding and wrap caracter - Fix legend label placement for multiline labels (#2382) - enforce WRAP parameter in legend label (#2382) - AGG: pixel level simplification for line and polygon shapes (#2381) - fixed blue/green color swapping for space delimited strings bound to an attribute. (bug 2378) - don't remove points that are checked as being colinear (#2366) - add initial(?) support for reading a pie chart's size from an attribute (#2136) - don't bail out in map parsing if the outputformat had to be modified (bug #2321) - use a renderer agnostic legend icon drawing function which switches to the GD or AGG specific one depending on the outputformat (#2348) - AGG: switch alpha buffer when drawing query layer - Fixed legend icons not drawing when using maxscaledenom - AGG: fix embedded scalebar rendering when using postlabelcache (#2327) - AGG: allow for fast and aliased rendering of simple lines and polygons thick lines and patterns (i.e. dashes)aren't supported. this is triggered when the symbol is of TYPE SYMBOL *and* its ANTIALIAS is off (wating to find a better solution to trigger this). - AGG: the pixmap of pixmap symbols is now cached in an agg-compatible state the first time it is accessed. this avoids rereading and retransforming it each time that symbol is used. - AGG: the imageObj now stores in what state it's alpha channel is in. The number ofmsAlphaGD2AGG/AGG2GD calls is now reduced, but most importantly each of these calls is usually just a check for this state and does no computation. - AGG: fixed a few artifacts in embedded legend rendering on rgba images. - Fixed modulus operator in the parser (#2323) - maprasterquery.c: Fix crash when queryies on done on raster layers with no styles (#2343) - maprasterquery.c: Modify msRASTERLayerOpen() to create a defaulted raster layer info if there isn't one, to avoid the errors about open only being supported after a query. Also wipe the raster layer info in case of an empty result set, or failures of a query to reduce likelyhood of leaking the raster layer info. - Improve out of memory handling in mapdrawgdal.c, and mapgd.c. (#2351) - Improve configuration logic for fastcgi (#2355). - WMS: image/wbmp should be image/vnd.wap.wbmp (#2360) - SOS: support maxfeatures for GetObservation requests (#2353) - mapdraw.c,mapquery.c: Reset layer->project flag for each full layer drawing or query so that need to reproject will be reconsidered (#673). - PHP MapScript: fix for getStdoutBufferString() and getStdoutBufferBytes() functions on win32 (#2401) - mapowscommon.c: fix namespace leak issues (#2375) - mapogcsos.c: add SWE DataBlock support (#2248) - mapogcsos.c: fix build warnings, namespace and schema pointers (#2248) - mappdf.c: support output in fastcgi case via msIO_fwrite() (#2406) - mapogcsos.c: Initial support for POST requests (#2379) and updated msSOSDispatch() handling - mapogr.cpp: Use pooling api to ensure per-thread sharing of connections only (#2408) - mapogcsos.c: change substituted variable from sensorid to procedure (#2409) - maplibxml2.c: Initial implementation of libxml2 convenience functions - configure: Modified so libxml2 support is requested for WCS and SOS, and is indicated by USE_LIBXML2 definition. Use @ALL_ENABLED@ in DEFINEs and mapscriptvars generation. - mapresample.c: Fixed support for multi-band data in RAW mode for bilinear and nearest neighbour resamplers (#2364). - mapdraw.c: Improve error reporting if a raster layer requested in a query map (#1842). - mapfile.c: add simple urn:ogc:def:crs:OGC::CRS84 support. Version 5.0.0 (2007-09-17) -------------------------- - AGG: Fix angle computation for truetype marker symbols on lines (#2316) - Fix support for bilinear resampling of raster data with AGG (#2303) Version 5.0.0-rc2 (2007-09-10) ------------------------------ - Prevent seg fault in msWMSLoadGetMapParams when request is missing (#2299) - Fixed calculation of scale in PHP MapScript mapObj.zoomScale() (#2300) - Fixed conflict between runtime substitution validation and qstring validation. - Fixed agg configure logic (now should work with --with-agg alone) (#2295) - Fixed interleaving of multi-band results for raster query (#2294). Version 5.0.0-rc1 (2007-09-05) ------------------------------ - Fixed "MinFeatureSize AUTO" labeling for polygon layers, works for polygon annotation layers too (#2232) - Fixed path following labels with short (2/3 character) strings (#2223) - AGG fix a bug when rendering polygons with tiled pixmaps - Added requirement to provide validation pattern for cgi-based attribute queries using the layer metadata key 'qstring_validation_pattern' (#2286) - Fixed msDebug causing a crash with VS2005 (#2287) - Added stronger checks on libpdf version in configure script (#2278) - Added msGetVersionInt() to MapScript (ms_GetVersionInt() in PHP) (#2279) - _isnan prototype for MSVC builds from #2277 - AGG: Fix a bug when rendering brushed lines with vector or pixmap symbols (artifacts could appear on outline) - AGG: Adjust symbol height when brushing a line with a vector symbol so that the line width isn't truncated - Only include process.h on win32 (non-cygwin) systems, moved from maptemplate.h to mapserver.h. (#2276) Version 5.0.0-beta6 (2007-08-29) -------------------------------- - Fixed problem with outline of polygons rendered twice with OGR STYLEITEM AUTO and AGG output (#2271) - Fixed problem compiling with only WMS/WFS client but none of the WMS, WFS, WCS or SOS server options enabled (#2272) - Fixed buffer overflow in handling of WMS SRS=AUTO:... (#1824) - AGG: render thick lines and polygon outlines with round caps and joins by default - Typo in mapfile writing (#2267) - Fixed mapping of class->keyimage in PHP MapScript (#2268) - Look for libagg under lib64 subdir as well in configure (#2265) - AGG: revert previous optimizations. now use caching of the rendering object to avoid the re-creation of some structures each time a shape is drawn - AGG: optimizations for faster rendering. we now do not initialize the font cache when no text is to be rendered - AGG: fixed rendering of polygons with holes (#2264) - AGG - raster layers: fix typo in mapresample.c that produced random background colors when using OFFSITE (#2263) - AGG: Fix a bug when rendering tiled polygons with truetype, pixmap or vector symbols (usually only affected bright colors) - Avoid passing null to msInsertHashTable in processLegendTemplate when layer.name or layer.group not specified (#2261) - Fixed problems with fonts in PDF output (#2142) - AGG: smooth font shadows Version 5.0.0-beta5 (2007-08-22) -------------------------------- - Fixed XSS vulnerabilities (#2256) - Allow building with AGG from source when libaggfontfreetype is missing. configure --with-agg=DIR now automatically tries to build agg_font_freetype.o from source if libaggfontfreetype is missing (#2215) - Fixed possible buffer overflow in template processing (#2252) - fix blending of transparent layers with RGBA images - AGG: speed up rendering of pixmap marker symbols - Implement OGR thread-safety via use of an OGR lock (#1977). - Fixed compile warnings (#2226) - Fixed mappdf.c compile warnings, PDF support was probably unusable before that fix (#2251) - Adding -DUSE_GENERIC_MS_NINT to the WIN64 builds (#2250) - Adding msSaveImageBuffer and use that function from the mapscript library instead of the renderer specific functions. (#2241) - Split each format into it's own element in WCS describe coverage results (#2244). - Support to run the mapscript c# examples on x64 platform (#2240) - Fixed problem introduced in 5.0.0-beta4: all HTML legend icons were empty white images (#2243) - Fixed WMS Client to always send STYLES parameter with WMS GetMap requests (#2242) - Fixed support for label encoding in SVG output (#2239) - Added support for label encoding in legend (#2239) - Fixed PHP MapScript layer->queryByAttributes() to not accept empty or null qitem arg (#480) - AGG: fixed incorrect rendering of pixmaps on MSB architectures (#2235) - Added layer.getFeature() in PHP MapScript with optional tileindex arg, and deprecated layer.getShape() to match what we had in SWIG (#900) - Added class.getTextString() and deprecated/renamed class.getExpression() and layer.getFilter() to class.getExpressionString() and layer.getFilterString() to match what we have in SWIG MapScript (#1892) Version 5.0.0-beta4 (2007-08-15) -------------------------------- - Updated msImageCreateAGG to only allow RGB or RGBA pixel models (#2231) - Fixed problem with symbol.setImagePath() when file doesn't exist (#1962) - Python MapScript failures (#2230) - msInsertLayer should not free the incoming layer anymore (#2229) - Include only parsed in the first mapfile (#2021) - Incorrect lookup of symbol in symbolset (#2227) - Mapfile includes and MapScript (#2089) - Fixed alignment of GetLegendGraphic output when mapfile contains no legend object (#966) - Fixed seg. fault when generaing HTML legend for raster layers with no classes (#2228). The same issue was also causing several Chameleon apps using HTML legend to seg fault (#2218) - Do not use case sensitive searches in string2list, which is used for msWhichItems (#2067) - Ensure that we can write AGG images with Python MapScript's write() method - Support unicode attributes for ArcSDE 9.2 and above (#2225) - GD: Truetype line symbolization should follow line orientation only if GAP is <=0 - AGG: Added truetype symbolization for lines and polygons - AGG: Draw an outline of size 1 of the fill color around polygons if an outlinecolor isn't specified (avoids faint outline) - Added summary of options at end of configure output (#1966) - Updated configure script to detect and require GEOS 2.2.2+ (#1896) - Renamed --enable-coverage configure option to --enable-gcov to avoid confusion with WCS or Arc/Info coverages (#2217) - Fixed --enable-gcov (formerly --enable-coverage) option to work with php_mapscript.so (#2216) - check for OGR support in if SLD is used (#1998) - msWMSLoadGetMapParams: fixed handling of required parameters (#1088) - if any of srs, bbox, format, width, height are NOT found, throw exception - if styles AND sld are NOT found, throw an exception - NOTE: this may cause issues with some existing clients who do not pass required parameters Version 5.0.0-beta3 (2007-08-08) -------------------------------- Known issues: - This beta contains significant improvements and fixes on the AGG rendering front. However some build issues remain on some platforms. Please see ticket #2215 if building with AGG support doesn't work with the default configure script: http://trac.osgeo.org/mapserver/ticket/2215 Bug fixes: - mapagg.cpp rewrite - the AGG renderer should now support all the GD features - Use AGG when requested for drawing the legend - Fixed problems with very large HTML legends producing no output (#1946) - Use OGR-specific destructors for objects that have them rather than 'delete' (#697) - Include style-related info in HTML legend icon filenames to solve issues with caching of icons when the class or style params are changed (#745) - Fixed issues with wms_layer_group metadata in WMS GetCapabilities (#2122) - Use msSaveImageBufferAGG for AGG formats in getBytes (#2205). - Make sure to emit $(AGG) to mapscriptvars because of conditional inclusion of stuct members to imageObj. (#2205) - Make imageextra field in imageObj not conditional (not #ifdef'ed) (#2205) - AGG/PNG and AGG/JPEG are the only valid agg drivers. Imagetypes aggpng24 and aggjpeg can be used to refer to the default output formats. (#2195) - Fix memory leak with labepath object (#2199) - Fix memory leak msImageTruetypePolyline (#2200) - SWF: Fix incorrect symbol assignements (#2198) - Fixed memory leaks in processing of WFS requests (#2077) - Avoid use of uninitialised memory in msCopySymbol() (#2194) Version 5.0.0-beta2 (2007-08-01) -------------------------------- - Oracle Spatial: Fixed some issues related with the maporaclespatial.c source code: warnings with calls in gcc 4.x versions (#1845), gtype translation error, generating memory problem (#2056), problems with items allocation (#1961 and #1736), and some memory-leaks errors (#1662). - AGG: Fixed a significant number of rendering issues including conflicts with OPACITY ALPHA and ANTIALIAS TRUE settings w/regards to polygon fills. Fixed ellipse and vector markers. Fixed AGG/GD alpha channel conflicts by writing conversion to/from functions. (#2191-partial, #2173, #2177) - SOS: Turn layer off if eventTime is not in the sos_offering_timeextent (#2154) - WFS: Correct bugs related to query by featureid support (#2102) - WMS: Add svg as a supported format for GetMap request (#1347) - WMS: Correct WMS time overriding Filter paramter (#1261) - Fix problem with LUT scaling ranges with explicit value for 255 (#2167). - WCS: Fixed resampling/reprojecting for tileindex datasets (#2180) - Fixed formatting of configure --help (#2182) - Fixed AGG configure option to use 'test -f' instead of 'test -e' which doesn't work on Solaris (#2183) - Fixed mapwms.c to support selecting AGG/ outputformats via FORMAT=. - Removed unused styleObj.isachild member (#2169) Version 5.0.0-beta1 (2007-07-25) -------------------------------- New features in 5.0: - MS RFC 19: Added Style and Label attribute binding - MS RFC 21: Raster Color Correction via color lookup table - MS RFC 27: Added label priority - MS RFC 29: Added dynamic charting (pie and bar charts) - MS RFC 31: New mechanism to load/set objects via URL using mapfile syntax - MS RFC 32: Added support for map rendering using the AGG library for better output quality Long time issues resolved in 5.0: - MS RFC 17: Use dynamic allocation for symbols, layers, classes and styles (got rid of the static limit on the number of instances of each in a map) - MS RFC 24: Improved memory management and garbage collection for MapScript - MS RFC 26: Terminology cleanup (layer transparency renamed to opacity, scale becomes scaledenom, symbol style becomes symbol pattern) - MS RFC 28: Enhanced the debug/logging mechanism to facilitate troubleshooting and tuning applications. Added support for multiple debug levels and more control on output location. Other fixes/enhancements in this beta: - Upgrade Filter encoding to use geos and support all missing operators (#2105) - Use of static color Palette support for gd output (#2096) - MapServer's main header file map.h has been renamed mapserver.h (#1437) - A mapserver-config script has been created - Single and double quotes escaping in string expressions used by FILTER. (Resolves tickets #2123 and #2141) - SLD: Support of Graphic Stroke for a Linesymbolizer (#2139) - GD : draw symbols along a line using pixmap symbols (#2121) - SVG : Polygons should not be filled if color is not given (#2055) - WMS : fixed request with a BBOX and and SLD containing Filter encoding (2079) - SWF : use highlight color from querymap (2074) - Support for embedding manifests as resources for the VS2005 builds. (ticket #2048) - Changed OGRLayerGetAutoStyle not to pass NULL pointer to GetRGBFromString causing access violation (bug 1950). - Fix SDE returning the row_id_column multiple times (bug 2040). - Fix text outline bug. (bug 2027) - Improve error reporting when OWS services are requested but the support is not compiled in. (bug 2025) - Fix support for OFFSITE for simple greyscale rasters (bug 2024). - [SLD] : Error on last class in raster class names based on the ColorMapEntry (bug 1844) - [Filter Encoding] : Check if Literal value in Filter is empty (bug 1995) - [SLD] : Else filters are now generated at the end of classes (bug 1925) - Enabled setting of a layer tileindex (e.g. map_layername_tileindex) via the CGI program. (bug 1992) - Added feature to the CGI to check runtime substitutions against patterns defined in layer metadata. (bug 1918) - Exposed label point computation to mapscript (bug 1979) - [SLD]: use the url as symbol name for external symbols (bug 1985) - [SLD] : support of mixing static text with column names (bug 1857) - maperror.c: fix for wrapping long in image errors, thanks to Chris Schmidt (bug 1963) - maperror.c: fix closing of stderr/stdout after writing error msg (bug 1970) - Preliminary implementation of RFC 21 (Raster Color Correction). - [SLD] : when reading an SLD, sequence of classes was reversed (Bug 1925) - Fixed a bug with SDE capability requests where we were double freeing because sde->row_id_column wasn't set to NULL in msSDELayerOpen - [OGC:SOS] : Fixed bugs realted to metadata and xml output (1731, 1739, 1740, 1741). Fixed bug with large xml output (bug 1938) - fixed performance problem in raster reprojection (bug 1944) - added msOWSGetLanguage function in mapows.c/h (bug 1955) - added mapowscommon.c/mapowscommon.h and updated mapogcsos.c to use mapowscommon.c functions (bug 1954) - added more Perl mapscript examples in mapscript/perl/examples/, most of which exemplify recently added GEOS functionality - php_mapscript.c: Fixed setRotation() method to check for MS_SUCCESS, not MS_TRUE (bug 1968) - mapobject.c: Fixed msMapSetExtent() to avoid trying to calcuate the scale if the map size hasn't been set yet (bug 1968) - mapobject.c: ensure msMapComputeGeotransform() returns MS_FAILURE, not MS_FALSE (bug 1968) - mapdraw.c: Actually report that we aren't configure with wms client support if that is why we can't draw a layer. - mapows.c: fixed XML error (bug 2070) - mapwms.c: Fixed text/plain output duplicate (bug 1379) - mapwms.c: Attribution element output in GetCapabilities only 1.0.7 and higher (bug 2080) - mapwms.c: UserDefinedSymbolization element output in GetCapabilities only 1.0.7 and higher (bug 2081) - mapwms.c: GetLegendGraphic and GetStyles only appear in 1.1.1 and higher responses (bug 1826) - mapwcs.c: - msWCSDescribeCoverage: throw Exception if Coverage doesn't exist (bug 649) - msWCSException: updated as per WCS 1.0 Appendix A.6 - mapogcsos.c: Added ability to output gml:id via MAP/LAYER/METADATA ows/sos/gml_featureid (bug 1754) - mapcontext.c: Added ogc namespace (#2002) - Note that starting with this release the source code is now managed in Subversion (SVN) instead of CVS and we have migrated from bugzilla to Trac for bug tracking. Version 4.10.0 (2006-10-04) --------------------------- - No source code changes since 4.10.0-rc1 Known issues in 4.10.0: - PHP5 not detected properly on Mandriva Linux (bug 1923) - Mapfile INCLUDE does not work with relative paths on Windows (bug 1880) - Curved labels don't work with multibyte character encodings (bug 1921) - Quotes in DATA or CONNECTION strings produce parsing errors (bug 1549) Version 4.10.0-RC1 (2006-09-27) ------------------------------- - SLD: quantity values for raster sld can be float values instead of just being integer - Hiding labelitemindex, labelsizeitemindex, labelangleitemindex from the SWIG interface (bug 1906) - Fixed computation of geotransform to match BBOX (to edges of image) not map.extent (to center of edge pixels). (bug 1916) - mapraster.c: Use msResampleGDALToMap() for "upside down" images. (bug 1904) Version 4.10.0-beta3 (2006-09-06) --------------------------------- - Web Map Context use format metadata when formatlist not available. (bug 1723) - Web Map Context boolean values true/false now interpreted. (bug 1692) - Added support for MULTIPOLYGON, MULTILINESTRING, and MULTIPOINT in msShapeFromWKT() when going through OGR (i.e. GEOS disabled) (bug 1891) - Fixed MapScript getExpressionString() that was failing on expressions longer that 256 chars (SWIG) and 512 chars (PHP). (bug 1428) - WMSSLD: use Title of Rule if Name not present (bug 1889) - Fixed syntax error (for visual c++) in mapimagemap.c. - Fixed mapgeos.c problems with multipoint and multilinestring WKT (bug 1897). - Implemented translation via OGR to WKT for multipoint, multiline and multipolygon (bug 1618) Version 4.10.0-beta2 (2006-08-28) --------------------------------- - Applied patch supplied by Vilson Farias for extra commas with imagemap output (bug 760). - Fixed possible heap overflow with oversized POST requests (bug 1885) - Set ./lib and ./include properly for MING support (bug 1866) - More robust library checking on OSX (bug 1867) - Removed mpatrol support (use valgrind instead for something similar and less intrusive). (bug 1883) - Added mapserver compilation flags to the SWIG c# command line (bug 1881) - Fix OSX shared library options for PHP (bug 1877). - Added setSymbolByName to styleObj for the SWIG mapscript in order to set both the symbol and the symbolname members (bug 1835) - Generate ogc filters now outputs the ocg name space (bug 1863) - Don't return a WCS ref in WMS DescribeLayer responses when layer type is CONNECTIONTYPE WMS (cascaded WMS layers not supported for WCS) (bug 1874) - Correct partly the problem of translating regex to ogc:Literal (bug 1644) - schemas.opengeospatial.net has been shutdown, use schemas.opengis.net instead as the default schema repository for OGC services (bug 1873) - MIGRATION_GUIDE.TXT has been created to document backwards incompatible changes between 4.8 and 4.10 - Modify mapgd.c to use MS_NINT_GENERIC to avoid rounding issues. (bug 1716) - added --disable-fast-nint configure directive (bug 1716) - Fixed php_mapscript Windows build that was broken in beta1 (bug 1872) - Supported tag in SLD label (Bug 1857) - Use the label element in the ColorMapEntry for the raster symbolizer (Bug 1844) - Adding Geos functions to php mapscript (bug 1327) - Added a type cast to msio.i so as to eliminate the warning with the SWIG unix/osx builds - Fixed csharp/Makefile.in for supporting the OSX builds and creating the platform dependent mapscript_csharp.dll.config file. - Fixed error in detection of libpdf.sl in configure.in (bug 1868). Version 4.10.0-beta1 (2006-08-17) --------------------------------- - Marking the following SWIG object members immutable (bug 1803) layerObj.metadata, classObj.label, classObj.metadata, fontSetObj.fonts, legendObj.label, mapObj.symbolset, mapObj.fontset, mapObj.labelcache, mapObj.reference, mapObj.scalebar, mapObj.legend, mapObj.querymap mapObj.web, mapObj.configoptions, webObj.metadata, imageObj.format, classObj.layer, legendObj.map, webObj.map, referenceMapObj.map labelPathObj was made completely hidden (according to Steve's suggestion) - Fixed problem with PHP MapScript's saveWebImage() filename collisions when mapscript was loaded in php.ini with PHP as an Apache DSO (bug 1322) - Produce warning in WFS GetFeature output if ???_featureid is specified but corresponding item is not found in layer (bug 1781). Also produce a warning in GetCapabilities if ???_featureid not set (bug 1782) - Removed the default preallocation of 4 values causing memory leaks. (related to bug 1801) Added initValues to achieve the similar functionality if needed. - Fixed error in msAddImageSymbol() where a symbol's imagepath was not set (bug 1832). - Added INCLUDE capability in mapfile parser (bug 279) - Revert changes to mapzoom.i that swapped miny and maxy (Bug 1817). - MapScript (swig) creation of an outputFormatObj will now set the inmapfile flag so that it gets written out to saved maps by default (Bug 1816). - Converted GEOS support to use the GEOS C-API (versiopn 2.2.2 and higher). Wrapped remaining relevant GEOS functionality and exposed via SWIG-based MapScript. - If a layer has wms_timedefault metadata, make sure it is applied even if there is no TIME= item in the url. (Bug 1810) - Support for GEOS/ICONV/XML2 use flags in Java Makefile.in (related to bug 1801) - Missing GEOS support caused heap corruption using shapeObj C# on linux (Bug 1801) - Fix time filter propogation for raster layers to their tileindex layers. New code in maprasterquery.c (bug 1809) - Added logic to collect LD_SHARED even if PHP not requested in configure. - Fix problems with msio/rfc16 stuff on windows. Don't depend on comparing function pointers or "stdio" handles. (mapio.c, mapio.h, msio.i) - Support WMC Min/Max scale in write mode (bug 1581) - Fixed leak of shapefile handles (shp/shx/dbf) on tiled layers (bug 1802) - Added webObj constructor and destructor to swig interface with calls to initWeb and freeWeb (bug 1798). - mapows.c: ensure msOWSDispatch() is always available even if there are no services to dispatch. This makes mapscript binding easier. - FLTAddToLayerResultCache wasn't properly closing the layer after it was done with it. - Added ability to encrypt tokens (passwords, etc.) in database connection strings (MS-RFC-18, bug 1792) - Fixed zoomRectangle in mapscript: miny and maxy were swapped, making it impossible to zoom by rect; also the error message was referring to the wrong rect. There were no open issues on bugzilla. Reverted because of 1817. - Implementation of RFC 16 mapio services (bug 1788). - Use lp->layerinfo for OGR connections (instead of ogrlayerinfo) (bug 331) - Support treating POLYGONZ as MS_SHAPE_POLYGON. (bug 1784) - Complete support for international languages in Java Mapscript (bug 1753) - Output feature id as @fid instead of @gml:id in WFS 1.0.0 / GML 2.1.2 GetFeature requests (bug 1759) - Allow use of wms/ows_include_items and wms/ows_exclude_items to control which items to output in text/plain GetFeatureInfo. Making the behavior of this INFO_FORMAT consistent with the new behavior of GML GetFeatureInfo output introduced in v4.8. (bug 1761) IMPORTANT NOTE: With this change if the *_include_items metadata is not specified for a given layer then no items are output for that layer (previous behavior was to always all items by default in text/plain) - Make sure mappostgis.c closes MYCURSOR in layer close function so that CLOSE_CONNECTION=DEFER works properly. (bug 1757) - Support large (>2GB) raster files relative to SHAPEPATH. (bug 1748) - Set User-Agent in HTTP headers of client WMS/WFS connections (bug 1749) - Detection of os-dependent Java headers for Java mapscript (bug 1209) - Preventing to take ownership of the memory when constructing objects with parent objects using C# mapscript (causing nullreference exception, Bug 1743) - SWF: Adding format option to turn off loading movies automatically (Bug 1696) - Fixed FP exception in mapgd.c when pixmap symbol 'sizey' not set (bug 1735) - Added config file for mapping the library file so the DllImport is looking for to its unix equivalent (Bug 1596) Thanks to Scott Ellington - Added /csharp/Makefile.in for supporting the creation of Makefile during configuration with MONO/Linux (fix for bug 1595 and 1597) - Added C# typemaps for char** and outputFormatObj** - Support for dispatching multiple error messages to the MapScript interface (bug 1704). - Fix inter-tile "cracking" problem (Bug 1715). - OGC FILTER: Correct bug when generating an sql expression containing an escape character. - Allow a user to set a PROCESSING directive for an SDE layer to specify using the attributes or spatial index first. (bug 1708). - Cheap and easy way of fudging the boundary extents for msSDEWhichShapes in the case where the rectangle is really a point (bug 1699). - Implement QUANTIZE options for GD/PNG driver (Bug 1690, Bug 1701). - WMS: Publish the GetStyles operation in the capabilities document. - PHP_MAPSCRIPT: Add antialias parameter in the style object (Bug 1685) - WFS: Add the possiblity to set wfs_maxfeatures to 0 (Bug 1678) - SLD: set the default color on the style when using default settings in PointSymbolizer. (bug 1681) - Incorporate range coloring support for rasters (bug 1673) - Fixed mapthread.c looking for the unix compiler symbol rather than just testing whether or not _WIN32 is defined for the usage of posix threads because unix is not defined on compilers like GCC 4.0.1 for OS X. - Fixed the fuzzy brush support so that the transition between 1 pixel aa lines and brushes is less obvious. The old code would not allow for a 3x3 fuzzy brush to be built. (bug 1659) - Added missing mapscript function msConnPoolCloseUnreferenced() (bug 1661) We need to make conn. pooling handling transparent to mapscript users so that they do not have to call this function once in a while, for instance by creating an evictor thread. - Added calls to msSetup/msCleanup() at MapScript load/unload time (bug 1665) - Reorganized nmake.opt to be more focused on functionality groups rather than the propensity of a section to be edited. Default values are now all set to be pointed at the MapServer Build Kit, which can be obtained at http://hobu.stat.iastate.edu/mapserver/ - configure.in/Makefile.in: Use PROJ_LIBS instead of PROJ_LIB. PROJ_LIB is sometimes defined in the environment, but points to $prefix/share/proj not the proj link libraries. - Update Web Map Context to 1.1.0, add the dimension support. (bug 1581) - Support SLD body in context document. (bug 887) - When generating an ogc filter for class regex expressions, use the backslah as the default escape character (Bug 1637) - Add connectiontype initialization logic when the layer's virtual table is initialized (Bug 1615) - Added modulus operator to mapparser.y. - Added new support for [item...] tag in CGI-based templates (bug 1636) - Reverted behaviour to pre-1.61: do not allow for use of the FILTERITEM attribute (bug 1629) - Treat classindex as an int instead of a char in resultCacheMemberObj to prevent problems with more than 128 classes (bug 1633) - WMS : SLD / stretch images when using FE (Bug 1627) - Add gml:lineStringMember in GML2 MultiLineString geometry (bug 1569). - PHP : add shape->sontainsshape that uses geos lib (Bug 1623). - Move gBYTE_ORDER inside the pg layerinfo structure to allow for differently byte ordered connections (bug 1587). - Fix the memory allocation bug in sdeShapeCopy (Bug 1606) - Fixed OGR WKT support (Bug 1614). - Added shapeObj::toWkt() and ms_shapeObjFromWkt() to PHP MapScript (bug 1466) - Finished implementation of OGR Shape2WKT function (Bug 1614). - Detect/add -DHAVE_VSNPRINTF in configure script and prevent systematic buffer overflow in imagemap code when vsnprintf() not available (bug 1613) - Default layer->project to MS_TRUE even if no projection is set, to allow geotransforms (nonsquare pixels, etc) to be applied (bug 1645). - Force stdin into binary mode on win32 when reading post bodies. (bug 1768) Version 4.8.0-rc2 (2006-01-09) ------------------------------ - Commit fix for GD on win32 when different heaps are in use. (Bug 1513) - Correct bound reprojection issue with ogc filer (Bug 1600) - Correct mapscript windows build problem when flag USE_WMS_SVR was not set (Bug 1529) - Fix up allocation of the SDE ROW_ID columns and how the functions that call it were using it. (bug 1605) - Fixed crash with 3D polygons in Oracle Spatial (bug 1593) Version 4.8.0-rc1 (2005-12-22) ------------------------------ - Fixed shape projection to recompute shape bounds. (Bug 1586) - Fixed segfault when copying/removing styles via MapScript. (Bug 1565) - Fixed segfault when doing attribute queries on layers with a FILTER already set but with no FILTERITEM. Version 4.8.0-beta3 (2005-12-16) -------------------------------- - Initialize properly variable in php mapscript (Bug 1584) - New support for pseudo anti-aliased fat lines using brushes with variable transparency. - Arbitrary rotation support for vector symbols courtesy of Map Media. - Support for user-defined mime-types for CGI-based browse and legend templates (bug 1518). - mapraster.c: Allow mapresample.c code to be called even if projections are not set on the map or layer object. This is no longer a requirement. (Bug 1562) - Fix problem with WMS 1.1.1 OGC test problem with get capabilites dtd (Bug 1576) - PDF : adding dash line support (Bug 492) - Fixed configure/build problem (empty include dir) when iconv.h is not found (bug 1419) - PDF : segfault on annotation layer when no style is set (Bug 1559) - PostGIS layer test cases and fix for broken views and sub-selects (bug 1443). - SDE: Removed (commented out) support for SDE rasters at this time. As far as I know, I'm the only one to ever get it to work, it hasn't kept up with the connection pooling stuff we did, and its utility is quite limited in comparison to regular gdal-based raster support (projections, resampling, etc) (HB - bug 1560). - SDE: Put msSDELayerGetRowIDColumn at the top of mapsde.c so things would compile correctly. This function is not included (or necessary) in the rest of the MS RFC 3 layer virtualization at this time. - WFS : TYPENAME is manadatory for GetFeature request (Bug 1554). - SLD : error parsing font parameters with the keyword "normal" (Bug 1552) - mapgraticule.c: Use MIN/MAXINTERVAL value when we define grid position and interval (bug 1530) - mapdrawgdal.c: Fix bug with nodata values not in the color table when rendering some raster layers (bug 1541). - mapogcsld.c : If a RULE name is not given, set the class name to "Unknown" (Bug 1451) Version 4.8.0-beta2 (2005-11-23) -------------------------------- - Use dynamic allocation for ellipse symbol's STYLE array, avoiding the static limitation on the STYLE argument values. (bug 1539) - Fix bug in mapproject.c when splitting over the horizon lines. - Fix Tcl mapscript's getBytes method (bug 1533). - Use mapscript.i in-place when building Ruby mapscript, copying not necessary (bug 1528). - Expose maximum lengths of layer, class, and style arrays in mapscript (bug 1522). - correct msGetVersion to indicate if mapserver was build with MYGIS support. - Fixed hang in msProjectRect() for very small rectangles due to round off problems (bug 1526). Version 4.8.0-beta1 (2005-11-04) -------------------------------- - Bug 1509: Fixed bounding box calculation in mapresample.c. The bottom right corner was being missed in the calculation. - MS RFC 2: added OGR based shape<->WKT implementation. - mapgdal.c: fixed some mutex lock release issues on error conditions. - MS RFC 8: External plugin layer providers (bug 1477) - SLD : syntax error when auto generating external symbols (Bug 1508). - MS RFC 3: Layer vtable architecture (bug 1477) - wms time : correct a problem when hadling wms times with tile index rasters (bug 1506). - WMS TIME : Add suuport for multiple interval extents (Bug 1498) - Removed deprecated --with-php-regex-dir switch (bug 1468) - support wms_attribution element for LAYER's (Bug 1502) - Correct php/mapscript bug : initialization of scale happens when preparequery is called (Bug 1334). - msProjectShape() will now project the lines it can, but completely delete lines that cannot be projected properly and "NULL" the shape if there are no lines left. (Bug 411) - Expose msLayerWhichShapes and msLayerNextShape in MapScript. (bug 1481) - Added support to MapScript to change images in a previously defined symbol. (bug 1471) - mapogcfiler.c : bug 1490. Crash when size of sld filters was huge. - Fixed --enable-point-z-m fix in configure.in (== -> =) (bug 1485). - Extra scalebar layer creation is prevented with a typo fix in mapscale.c. Good catch, Tamas (bug 1480). - mapwmslayer.c : use transparency set at the layer level on wms client layers (Bug 1458) - mapresample.c: added BILINEAR/AVERAGE resampling options. - mapfile.c: avoid tail recursion in freeFeatureList(). - maplegend.c: fixed leak of imageObj when embedding legends. - msGDALCleanup(): better error handler cleanup. - Modified msResetErrorList() to free the last error link too, to ensure msCleanup() scrubs all error related memory. - Fix in msGetGDALGetTransform() to use default geotransform even if GDALGetGeoTransform() fails but alters the geotransform array. - Typemaps for C# to enable imageObj.getBytes() method (bug 1389). - Enable -DUSE_ZLIB via configure for compressed SVG output (bug 1307). - maputil.c/msAddLine(): rewrite msAddLine() to call msAddLineDirectly, and use realloc() in msAddLineDirectly() to optimize growth of shapeObjs. (bug 1432) - msTmpFile: ensure counter is incremented to avoid duplicate temporary filenames. (bug 1312) - SLD external graphic symbol format tests now for mime type like image/gif instead of just GIF. (bug 1430) - Added support for OGR layers to use SQL type filers (bug 1292) - mapio/cgiutil - fixed POST support in fastcgi mode. (bug 1259) - mapresample.c - ensure that multi-band raw results can be resampled. (bug 1372) - Add support in OGC FE for matchCase attribute on PropertyIsEqual and PropertyIsLike (bug 1416) - Fixed sortshp.c to free shapes after processing to avoid major memory leak. (bug 1418) - fixed msHTTPInit() not ever being called which prevented msHTTPCleanup() from properly cleaning up cUrl with curl_global_cleanup(). (bug 1417) - mapsde.c: add thread locking in msSDELCacheAdd - fixed mappool.c so that any thread can release a connection, not just it's allocator. (bug 1402) - mapthread.c/h: Added TLOCK_SDE and TLOCK_ORACLE - not used yet. - Fixed copying of layer and join items. (bug 1403) - Fixed copying of processing directives within copy of a layer. (bug 1399) - Problems with string initialization. (bug 1312) - Fix svg output for multipolygons. (bug 1390) - Added querymapObj to PHP MapScript (bug 535) Version 4.6.0 (2005-06-14) -------------------------- - Bug 1163 : Filter Encoding spatial operator is Intersects and not Intersect. - Fixed GEOS to shapeObj for multipolgon geometries. Version 4.6.0-rc1 (2005-06-09) ------------------------------ - Bug 1375: Fixed seg fault in mapscript caused by the USE_POINT_Z_M flag. This flag was not carried to the mapscript Makefile(s). - Bug 1367: Fixed PHP MapScript's symbolObj->setPoints() to correctly set symbolObj->sizex/sizey - Bug 1373: Added $layerObj->removeClass() to PHP MapScript (was already in SWIG MapScript) Version 4.6.0-beta3 (2005-05-27) -------------------------------- - Bug 1298 : enable Attribution element in wms Capabilities XML - Bug 1354: Added a regex wrapper, allowing MapServer to build with PHP compiled with its builtin regex - Bug 1364: HTML legend templates: support [if] tests on "group_name" in leg_group_html blocks, and for "class_name" in leg_class_html blocks. - Bug 1149: From WMS 1.1.1, SRS are given in individual tags in root Layer element. - First pass at properly handling XML exceptions from CONNECTIONTYPE WMS layers. Still needs some work. (bug 1246) - map.h/mapdraw.c: removed MAX/MIN macros in favour of MS_MAX/MS_MIN. - Bug 1341, 1342 : Parse the unit parameter for DWithin filter request. Set the layer tolerance and toleranceunit with paramaters parsed. - Bug 1277 : Support of multiple logical operators in Filter Encoding. - mapwcs.c: If msDrawRasterLayerLow() fails, ensure that the error message is posted as a WCS exception. - Added experimental support for "labelcache_map_edge_buffer" metadata to define a buffer area with no labels around the edge of a map (bug 1353) Version 4.6.0-beta2 (2005-05-11) -------------------------------- - Bug 179 : add a small buffer around the cliping rectangle to avoid lines around the edges. - Finished code to convert back and forth between GEOS geometries. Buffer and convex hull operations are exposed in mapscript. - fontset.fonts hash now exposed in mapscript (bug 1345). - Bug 1336 : Retreive distance value for DWithin filter request done with line and polygon shapes/ - Bug 985 / 1015: Don't render raster layers as classified if none of the classes has an expression set (gdal renderer only). - Bug 1344: Fixed several issues in writing of inline SYMBOLS when saving mapfile (missing quotes around CHARACTER and other string members of SYMBOL object, check for NULLs, and write correct identifiers for POSITION, LINECAP and LINEJOIN). Version 4.6.0-beta1 (2005-04-26) -------------------------------- - Bug 1305: Added support for gradient coloring in class styles - Bug 1335 : missing call to msInitShape in function msQueryByShape - Bug 804 : SWF output : Make sure that the layer index is consistent when saving movies if some of the layers are not drawn (because the status is off or out of scale ...) - Bug 1332 - shptreevis.c: fixed setting of this_rec, as the output dbf file was not getting any records at all. - Fixed Makefile.vc to make .exe files depend on the DLL, so if the DLL fails to build, things will stop. Avoids the need for unnecessary cleans on win32. Also fixed the rule for MS_VERSION for mapscriptvars. - Bug 1262 : the SERVICE parameter is now required for wms and wfs GetCapbilities request. It is not required for other WMS requests. It is required for all WFS requests. - Bug 1302 : the wfs/ows_service parameter is not used any more. The service is always set to WFS for WFS layers. - Bug 791: initialize some fields in msDBFCreate() - avoids crashes in some circumstances. - Bug 1329 : Apply sld named layer on all layers of the same group - Bug 1328 : support style's width parameter for line and polygon layers. - Bug 564: Fixed old problem with labels occasionally drawn upside down - Bug 1325: php mapscript function $class->settext needs only 1 argument. - Bug 1319: Fixed mutex creation (was creator-owned) in mapthread.c. win32 issue only. - Bug 1103: Set the default tolerance value based on the layer type. The default is now 3 for point and line layers and 0 for all the others. - Bug 1244: Removing Z and M parameter from pointObj by default. A new compilation option is available to active those option --enable-point-z-m. This gives an overall performance gain around 7 to 10%. - Bug 1225: MapServer now requires GD 2.0.16 or more recent - MapScript: shapeObj allocates memory for 4 value strings, shapeObj.setValue() lets users set values of a shapeObj. - MapScript: imageObj.getBytes() replaces imageObj.write() (bugs 1176, 1064). - Bug 1308: Correction of SQL expression generated on wfs filters for postgis/oracle layers. - Bug 1304: Avoid extra white space in gml:coordinates for gml:Box. - mapogr.c: Insure that tile index reading is restarted in msOGRLayerInitItemInfo() or else fastcgi repeat requests for a layer may fail on subsequent renders. - mapogr.c: Set a real OGRPolygon spatial filter, not just an OGRLinearRing. Otherwise GEOS enabled OGR builds will do expensive, and incorrect Intersects() tests. - mapogr.cpp / mapprimitive.c: Optimize msAddLine() and add msAddLineDirectly() - mapprimitive.c: Optimizations in msTransformShapeToPixel() (avoid division) - map.h: Made MS_NINT inline assembly for win32, linux/i86. - mapprimitive.c: optimized msClipPolygonRect and msClipPolylineRect for case where the shape is completely inside the clip rect. - Add support for SVG output. See Bug 1281 for details. - Bug 1231: use mimetype "image/png; mode=24bits" for 24bit png format. This makes it seperately selectable by WMS. - Bug 1206: Applied locking patch for expression parser for rasters. - Bug 1273: Fixed case in msProjectPoint() were in or out are NULL and a failure occurs to return NULL. Fixed problem of WMS capabilities with 'inf' in it. - SLD generation bug 1150 : replacing tag to - Fixed bug 1118 in msOWSGetLayerExtent() (mapows.c). - Fixed ogcfilter bug #1252 - Turned all C++ (//) comments into C comments (bug 1238) - mapproject.h/configure.in: Don't check for USE_PROJ_API_H anymore. Assume we have a modern PROJ.4. - Bug 839: Fix memory leak of font name in label cache (in mapfile.c). - Added msForceTmpFileBase() and mapserv -tmpbase switch to allow overriding temporary file naming conventions. Mainly intended to make writing testscripts using mapserv easier. FrankW. - maporaclespatil.c: Bug fix for: #1109, #1110, #1111, #1112, #1136, #1210, #1211, #1212, #1213. Support for compound polygons, fixed internal sql to stay more accurate for geodetic data, added the support for getextent function. Added VERSION token for layer data string. - mapimagemap.c: Preliminary implementation of support for emitting MS_SYMBOL_VECTOR symbols in msDrawMarkerSymbolIM(). - Bug 1204: Added multi-threading support in mapthread.c. List of connections is managed within a mutex lock, and connections are only allowed to be used by one thread at a time. - Bug 1185 : php/mapscript : add constant MS_GD_ALPHA - Bug 1173: In HTML legend, added opt_flag support for layer groups. - Bug 1179: added --with-warnings configure switch, overhauled warning logic. - Bug 1168: Improve autoscaling through classification rounding issues. - Fixed bug writing RGB/RGBA images via GDAL output on bigendian systems. - Bug 1152 : Fix WMS style capabilities output for FastCGI enabled builds. - Bug 1135 : Added support for rotating labels with the map if they were rendered with some particular angle already. - Bug 1143 : Missing call to msInitShape. - Fixed PHP5 support for windows : Bug 1100. - Correct bug 1151 : generates twice a tag when generating an SLD. This was happening the style did not have a size set. - Oracle Spatial. Fixed problem with LayerClose function. Added token NONE for DATA statement. Thanks Valik with the hints about the LayerClose problem and Francois with the hints about NONE token. - numpoints and stylelength memebers of the symbol object needs to be in sync with the low level values after calles to setpoints ans setstyle (Bug 1137). - Use doubles instead of integers in function php3_ms_symbol_setPoints (Bug 1137). - Change the output of the expression when using a wild card for PropertyIsLike (Bug 1107). - Delete temporary sld file created on disk (Bug 1123) - Fixed msFreeFileCtx() to call free() instead of gdFree() as per bug 1125. Also renamed gdFreeFileCtx() to msFreeFileCtx(). - Ensure error stack is cleared before accepting another call in FastCGI mode in mapserv.c. Bug 1122 - Support translation of all geometry types to points in mapogr.cpp (now also supports multipolygon, multilinestring and geometrycollection. bug 1124. - Added support for passing OGR layer FILTER queries down to OGR via the SetAttributeFilter() method if prefixed with WHERE keyword. Bug 1126. - Fixed support for SIZEUNITS based scaling of text when map is rotated. Bug 1127. Version 4.4.0 (2004-11-29) -------------------------- - Fixed WMS GetCapabilities 1.1.0 crash when wms_style_<...>_legendurl_* metadata were used (bug 1096) - WCS GetCapabilities : Added ResponsibleParty support. - WMS GetCapabilities : Service online resource was not url encoded (bug 1093) - Fixed php mapscript problem with wfs_filter selection : Bug 1092. - Fixed encoding problem with WFS server when wfs_service_onlineresource was not explicitly specified (bug 1082) - Add trailing "?" or "&" to connection string when required in WFS client layers using GET method (bug 1082) - Fixed : SLD rasters was failing when there was Spatial Filter (Bug 1087) - Fixed mapwfslayer.c build error when WFS was not enabled (bug 1083) - Check that we have vsnprintf in mapimagemap.c before using it. Version 4.4.0-beta3 (2004-11-22) -------------------------------- - Added tests to mimimize the threat of recursion problems when evaluating LAYER REQUIRES or LABELREQUIRES expressions. Note that via MapScript it is possible to circumvent that test by defining layers with problems after running prepareImage. Other things crop up in that case too (symbol scaling dies) so it should be considered bad programming practice (bug 1059). - Added --with-sderaster configure option. - Make sure that msDrawWMSLayerLow calls msDrawLayer instead of msDrawRasterLayerLow directly ensuring that some logic (transparency) that are in msDrawLayer are applied (bug 541). - Force GD/JPEG outputFormatObjects to IMAGEMODE RGB and TRANSPARENT OFF if they are RGBA or ON. Makes user error such as in bug 1703 less likely. - Advertize only gd and gdal formats for wms capabilities (bug 455). - Pass config option GML_FIELDTYPES=ALWAYS_STRING to OGR so that all GML attributes are returned as strings to MapServer. This is most efficient and prevents problems with autodetection of some attribute types (bug 1043). - msOGCWKT2ProjectionObj() now uses the OGRSpatialReference::SetFromUserInput() method. This allows various convenient setting options, including the ability to handle ESRI WKT by prefixing the WKT string with "ESRI::". - Fixed GetLegendGraphic in WMS Capabilities that were missing the '?' or '&' separator if it was not included in wms_onlineresource (bug 1065). - Updated WMS/WFS client and server code to lookup "ows_*" metadata names in addition to the default "wms_*" (or "wfs_*") metadatas (WCS was already implemented this way). This reduces the amount of duplication in mapfiles that support multiple OGC interfaces since "ows_*" metadata can be used almost everywhere for common metadata items shared by multiple OGC interfaces (bug 568). - Added ows_service_onlineresource metadata for WMS/WFS to distinguish between service and GetMap/Capabilities onlineresources (bug 375). - Added map->setSize() to PHP MapScript (bug 1066). - Re-enabled building PHP MapScript using PHP's bundled regex/*.o. This is needed to build in an environment with PHP configured as an Apache DSO (bugs 990, 520). - Fixed problem with raster dither support on windows (related to ascii encoding pointers) (bug 722). - Moved PHP/SWIG MapScript layer->getExtent() logic down to msLayerGetExtent() to avoid code duplication (bug 1051). - Added SDE Raster drawing support (experimental). - HTML legends: Added [leg_header_html] and [leg_footer_html] (bug 1032). - Added "z" support in SWIG MapScript for pointObj (bug 871). - In PHP Mpascript when using ms_newrectobj, the members minx, miny, maxx, maxy are initialized to -1 (bug 788). - Write out proper world file with remote WMS result, it was off by half a pixel (bug 1050). - Send a warning in the wms capabilities if the layer status is set to default (bug 638). - Fixed PHP MapScript compile warnings: dereferencing type-punned pointer will break strict-aliasing rules (bug 1053). - Added $layer->isVisible() to PHP MapScript (bug 539). - Ported $layer->getExtent() to PHP MapScript (bug 826). - wms_group_abstract can now be used in the capabilities (bug 754). - If wms_stylelist is an empty string, do not output the tag for MapContexts (bug 595). - Avoid passing FILE* to GD library by utilizing GD's gdIOCtx interface (bug 1047). - Output warning in wms/wfs capabilities document if layer,group,map names have space in them (bug 486, bug 646). - maporaclespatial.c: fixed declarations problems (bug 1044). - Allow use of msOWSPrintURLType with no metadata. In this case the default parameters will be used (bug 1001). - Ensure the outputFormatObj attached to msImageLoadGDStream() results reflect the interlacedness of the loaded image. Also ensure that the RGB PNG reference images work (make imagemode match gdImg) (bug 1039). - Fixed support for non-square pixels in WCS (bug 1014). - Expose only GD formats for GetLegendGraphic in the capabilities (bug 1001). - Check for supported formats when process a GetLegendGraphic request (bug 1030). - mapraster.c: fixed problem with leaks in tileindexed case where the tile index is missing (bug 713). - Oracle Spatial: implemented connection pool support for Oracle Spatial. New layer data parameters to support query functions, added "using unique ". Added "FILTER", "RELATE" and "GEOMRELATE" parameters, now permit users to choose the Oracle Spatial Filter. Modified the internal SQL to always apply FILTER function. And improve the Oracle Spatial performance. - Centralize "stdout binary mode setting" for win32 in msIO_needBinaryStdout(). Use it when writing GDAL files to stdout in mapgdal.c. Fixes problems with output of binary files from GDAL outputformat drivers on win32 via WMS/WCS. - MapServer now provides one default style named (default), title and LegendURL when generating capabilities. Added also the possibility to use the keyword default for STYLES parameter when doing a GetMap (..&STYLES=default,defeault,...) (bug 1001). - Add xlink:type="simple" in WMS MetadataURL (bug 1027). Version 4.4.0-beta2 (2004-11-03) -------------------------------- - free mapServObj properly in mapserv.c in OWS dispatch case to fix minor memory leaks. - modified msCloseConnections() to also close raster layers so that held raster query results will be freed. - modified raster queries to properly set the classindex in the resultcache. - modified msDrawQueryCache() to be very careful to not try and lookup information on out-of-range classindex values. This seems to occur when default shapes come back witha classindex of 0 even if there are no classes. (ie. raster query results). - the loadmapcontext function has changed it behaviour. Before the 4.4 relase when loading layers from a map context, the layer name was built using a unique prefix + the name found in the context (eg for the 2nd layer in map context named park, the layer name generated would possibly be l:2:park). Now the loadmapcontext takes a 2nd optional argument to force the creation of the unique names. The default behaviour is now to have the layer name equals to the name found in the context file (bug 1023). - Fixed problem with WMS GetCapabilities aborting when wms_layer_group is used for some layers but not for all (bug 1024). - Changed raster queries to return the list of all pixel values as an attribute named "value_list" rather than "values" to avoid conflict with special [values] substitution rule in maptemplate.c. - Fixed raster queries to reproject results back to map projection, and to do point queries distance checking against the correct projection (bug 1021). - Get rid of WMS 1.0.8 support. It's not an officially supported verison of the spec anyway: it's synonymous for 1.1.0 (bug 1022). - Allow use of '=' inside HTML template tag parser (bug 978). - Use metadata ows_schema_location for WMS/WFS/WCS/SLD (bugs 999, 1013, 938). The default value if metadata is not found is http://schemas.opengeospatial.net. - Generate a RULE tag when generating an SLD (bug 1010). - WMS GetLegendGraphic uses now the RULE value to return an icon for a class that has the same name as the RULE value (bug 843). - Add msOWSPrintURLType: This funciton is a generic URL printing fuction for OGC specification metadata (WMS, WFS, WCS, WMC, etc.) (bug 944). - Support MetadataURL, DataURL and LegendURL tags in WMS capabilities document and MetadataURL in WFS capabilities. - SWIG mapscript: clone methods for layerObj, classObj, styleObj (bug 1012). - Implemented an intarray helper class for SWIG mapscript which allows for multi-language manipulation of layer drawing order (bugs 853, 1005). - Fixed WMS GetLegendGraphic which was returning an exception (GD error) when requested layer was out of scale (bug 1006). - Fixed maplexer.l to work with flex 2.5.31 (bug 975). - WMS GetMap requests now have MS_NONSQUARE enabled by default. This means that if the width/height ratio doesn't match the extent's x/y ratio then the map is stretched as stated in the WMS specification (bug 862). - In WMS, layers with no explicit projection defined will receive a copy of the map's projectionObj if a new SRS is specified in the GetMap request or if MS_NONSQUARE is enabled. This will prevent the problem with layers that don't show up in WMS request when the server administrator forgets to explicitly set projections on all the layers in a WMS mapfile (bug 947). - Implemented FastCGI cleanup support for win32 and unix in mapserv.c. - Solved configure/compile issues with libiconv (bugs 909, 1017). Version 4.4.0-beta1 (2004-10-21) -------------------------------- - "shared" compilation target now supports some kind of versioning, should at least prevent libmap.so version collisions when upgrading MapServer on a server (bug 982). - When no RULE parameter has been specified in the WMS request a legend should be returned with all classes for the specified LAYER. Changes has been made in mapwms.c (bug 653). Also if the SCALE parameter is provided in the WMS request is will be used to determine whether the legend of the specified layer should be drawn in the case that the layer is scale dependant (big 809). - Nested layers in the capabilities are supported by using a new metadata tag WMS_LAYER_GROUP (bug 776). - Added greyscale+alpha render support if mapdrawgdal.c (bug 965). - Added --with-fastcgi support to configure. - support OGC mapcontext through mapserver cgi (bug 946). - support for reading 3d shape file (z) (bug 869). - add php mapscript functions to expose the z element (bug 870). - imageObj::write() method for SWIG mapscript (bug 941). - Protect users from 3 potential sources of threading problems: parsing expression strings outside of msLoadMap, evaluating mapserver logical expressions, and loading symbol set files outside of msLoadMap (bug 339). - Various fixes allowing unit tests to run leak free under valgrind on i686. Memory is now properly freed when exiting from common error states (bug 927). - Restored ability to render transparent (indexed or alpha) pixmap symbols on RGB map images, including annotation layers and embedded scalebars. This feature remains OFF by default for map layers and is enabled by specifying TRANSPARENCY ALPHA (bugs 926, 490). - mapserv_fcgi.c removed. Committed new comprehensive FastCGI support. - New mapserver exceptions for Java mapscript thanks to Umberto Nicoletti (bug 895). - Removed mapindex.c, mapindex.h, shpindex.c components of old unused shapefile indexing method. - Use the symbol size instead of 1 for the default style size value. This is done by setting the default size to -1 and adding msSymbolGetDefaultSize() everywhere to get the default symbolsize (Bug 751). - Correct Bug with GML BBOX output when using a with a GetFeature request (Bug 913). - Encode all metadatas and mapfile parameters outputed in a xml document (Bug 802). - Implement the ENCODING label parameter to support internationalization. Note this require the iconv library (Bug 858). - New and improved Java mapscript build provided by unicoletti@prometeo.it and examples by Y.K. Choo (bug 876). - MapContext: Cleanup code to make future integration more easily and output SRS and DataURL in the order required by the spec. - Fixed issue with polygon outline colors and brush caching (bug 868). - New C# mapscript makefiles and examples provided by Y.K. Choo committed under mapscript/csharp/ (bug 867). - Renamed 'string' member of labelCacheMemberObj to 'text' to avoid conflicts in SWIG mapscript with C# and Java types (bug 852). - Fixed Bug 866 : problem when generating an sld on a pplygon layer - SWIG mapscript: map's output image width and height should be set simultaneously using new mapObj::setSize() method. This performs necessary map geotransform computation. Direct setting of map width and height is deprecated (bug 836). - Fixed bug 832 (validate srs value) : When the SRS parameter in a GetMap request contains a SRS that is valid for some, but not all of the layers being requested, then the server shall throw a Service Exception (code = "InvalidSRS"). Before this fix, mapserver use to reproject the layers to the requested SRS. - Fixed bug 834: SE_ROW_ID in SDE not initialized for unregistered SDE tables - Fixed bug 823 : adding a validation of the SRS parameter when doing a GetMap request on a wms server. Here is the OGC statement : 'When the SRS parameter in a GetMap request contains a SRS that is valid for some, but not all of the layers being requested, then the server shall throw a Service Exception (code = "InvalidSRS").' - Set the background color of polygons or circles when using transparent PIXMAP symbol. - SWIG mapscript class extensions are completely moved from mapscript.i into separate interface files under mapscript/swiginc. - Overhaul of mapscript unit testing framework with a comprehensive test runner mapscript/python/tests/runtests.py. - Modified the MS_VALID_EXTENT macro to take an extent as its argument instead of the quartet of members. MapServer now checks that extents input through the mapfile are valid in mapfile.c (web, map, reference, and layer). Modified msMapSetExtent in mapobject.c to use the new macro instead of its home-grown version. Modified all cases that used MS_VALID_EXTENT to the new use case. - Layers now accept an EXTENT through the mapfile (bug 786). Nothing is done with it at this point, and getExtent still queries the datasource rather than getting information from the mapfile-specified extent. - Fixed problem with WMS GetFeatureInfo when map was reprojected. Was a problem with msProjectRect and zero-size search rectangles (bug 794) - MapServer version now output to mapscriptvars and read by Perl Makefile.PL and Python setup.py (bug 795). - Map.web, layer, and class metadata are exposed in SWIG mapscript as first-class objects (bug 737). - Add support for spatial filters in the SLD (Bug 782) - A few fixes to allow php_mapscript to work with both PHP4 and PHP5. PHP5 support should still be considered experimental. (bug 718) - Fixed SDE only recognizing SE_ROW_ID as the unique column (bug 536). The code now autosenses the unique row id column. - Enhanced SDE support to include support for queries against user-specified versions. The version name can be specified as the last parameter of the CONNECTION string. - Fixed automated generation of onlineresource in OWS GetCapabilities when the xxx_onlineresource metadata is not specified: the map= parameter used to be omitted and is now included in the default onlineresource if it was explicitly set in QUERY_STRING (bug 643) - Fixed possible crash when producing WMS errors INIMAGE (bug 644) - Fixed automated generation of onlineresource in OWS GetCapabilities when the xxx_onlineresource metadata is not specified: the map= parameter used to be omitted and is now included in the default onlineresource if it was explicitly set in QUERY_STRING (bug 643) - Fixed an issue with annotation label overlap. There was an issue with the way msRectToPolygon was computing it's bounding box. (bug 618) - Removed "xbasewohoo" debug output when using JOINs and fixed a few error messages related to MySQL joins (bug 652) - Fixed "raster cracking" problem (bug 493) - Improvements to Makefile.vc, and nmake.opt so that a mapscriptvars file can be produced on windows. - Updated setup.py so Python MapScript builds on win32. - Added preliminary raster query support. - No more Python-stopping but otherwise benign errors raised from msDrawWMSLayer() (bug 650). - Finished prototyping all MapServer functions used by SWIG-Mapscript and added 'void' to prototypes of no-arg functions, eliminating all but two SWIG-Mapscript build warnings (bug 658). - Mapscript: resolved issue with pens and dynamic drawing of points (bug 663). - Mapscript: fixes to tests of shape copying and new image symbols. - Mapscript: new OWSRequest class based on cgiRequestObj structure in cgiutil.h is a first step to allow programming with MapServer's OWS dispatching (bug 670). - Mapscript: styles member of classObj structure is no longer exposed to SWIG (bug 611). - Implementation geotransform/rotation support in cgi core, and mapscript.i. - Testing: fixed syntax error, 'EPSG' -> 'epsg' in test.map (bug 687). Added an embedded scalebar which demonstrates that bug 519 is fixed. The test data package is also made more complete by including two fonts from Bitstream's open Vera fonts (bug 694). - Mapscript (SWIG): remove promote and demote methods from layerObj. Use of container's moveLayerUp/moveLayerDown is better, and this brings the module nearer to PHP-Mapscript (bug 692). - mapogr.cpp: Now echos CPLGetLastErrorMsg() results if OGR open fails. - mapraster.c: fixed tile index corruption problem (bug 698) - Mladen Turk's map copying macros in mapcopy.h clean up map cloning and allow for copying of fontset and symbolset. Added cloning tests in python/tests/testCloneMap.py and refactored testing suite (bugs 640 & 701). - Mapscript: removing obsolete python/setup_wnone.py file. - CONFIG MS_NONSQUARE YES now enables non-square pixel mode (mostly for WMS). Changes in mapdraw.c (msDrawMap()) to use the geotransform "hack" to allow non-square pixels. - When using the text/html mime type in a GetFeature request, if the layer's template is not set to a valid file, errors occur. Correction is : the text/html is not advertized by default and will only be advertized if the user has defined "WMS_FEATURE_INFO_MIME_TYPE" "text/html" (bug 736) - Make PHP MapScript's layer->open() produce a PHP Warning instead of a Fatal error (bug 742) - MapServer hash tables are now a structure containing a items pointer to hashObj. See maphash.h for new prototypes of hash table functions. In SWIG mapscript, Map, Layer, and Class metadata are now instances of the new hashTableObj class. fontset.fonts and Map.configoptions are also instances of hashTableObj. The older getMetaData/setMetaData and metadata iterator methods can be deprecated (bug 737). - Mapscript-SWIG: made the arguments of mapObj and layerObj constructors optional. A layerObj can now exist outside of a map and can be added to a mapObj using the insertLayer method. mapObj.removeLayer now returns a copy of the removed Layer rather than an integer (bug 759). - Fixed $map->processTemplate() which was always returning NULL. Bug introduced in version 4.0 in all flavours of MapScript (bug 410) Version 4.2-beta1 (2004-04-17) ------------------------------ - Added support for WMS 1.1.1 in the WMS interface. - Added support for WMS-SLD in client and server mode. - Added support for attribute filters in the WFS interface. - WMS Interface: several fixes to address issues found in running tests against the OGC testsuite. One of the side-effects is that incomplete GetMap requests that used to work in previous versions will produce errors now (see bug 622). - Modified configure scripts to be able to configure/build PHP MapScript using an installed PHP instead of requiring the full source tree. - Added ability to combine multiple WMS connections to the same server into a single request when the layers are adjacent and compatible. (bug 116) - Support POSTed requests without Content-Length set. - Added support for proper classification of non-8bit rasters. - Added support for BYTE rawmode output type. - Added support for multiple bands of output in rawmode. - MySQL joins available - Fixed problems with detection of OGRRegisterAll() with GDAL 1.1.9 in configure due to GDAL's library name change. Fixed a few other minor issues with GDAL/OGR in configure. - Modified configure to disable native TIFF/PNG/JPEG/GIF support by default if GDAL is enabled. You can still enable them explicitly if you like. - Replace wms_style_%s_legendurl, wms_logourl, wms_descriptionurl, wms_dataurl and wms_metadataurl metadata by four new metadata by metadata replaced. The new metadata are called legendurl_width, legendurl_height, legendurl_format, legendurl_href, logourl_width, etc... Old dependancy to the metadata with four value in it , space separated, are not kept. - Implement DataURL, MetadataURL and DescriptionURL metadata in mapcontext.c (bug 523) - PHP MapScript's pasteImage() now takes a hex color value (e.g. 0xrrggbb) for the transparent color instead of a color index. (bug 463) - OGR data sources with relative paths are now checked relative to SHAPEPATH first, and if not found then we try again relative to the mapfile location. (bug 295) - There is a new mapObj parameter called MAXSIZE to control maximum image size to serve via the CGI and WMS interfaces. The default is 2048 as before but it can be changed in the map file now. (bug 435) - Added simple dataset for unit and regression tests (bug 453) - PostGIS: added postresql_NOTICE_HANDLER() sending output via msDebug() and only when layer->debug is set (bug 418) - Added Apache version detection in configure and added non-blocking flag on stderr in msDebug() to work around Apache 2.x bug (bug 458) - MapScript rectObj: added optional bounding value args to constructor and extended rectObj class with a toPolygon method (bug 508). - MapScript pointObj: added optional x/y args to constructor (bug 508). - MapScript colorObj: added optional RGB color value args to colorObj constructor, and extended colorObj class with setRGB, setHex, and toHex methods. The hex methods use hex color strings like '#ffffff' rather than '0xffffff' for compatibility with HTML (bug 509). - MapScript outputFormatObj: extended with a getOption method (bug 510). - MapScript imageObj: added optional mapObj argument to the save method resolving bug 549 without breaking current API. Also added optional driver and filename arguments to constructor which allows imageObj instances to be created with a specified driver or from files on disk (bug 530). Added new code to Python MapScript which extends the filename option to Python file-like objects (bug 550). This means StringIO and urllib's network objects! - MapScript classObj and styleObj: added a new styleObj shadow class and extended classObj with getStyle, insertStyle, and removeStyle methods. MapScript now supports multiple styles for dynamically created classes (bug 548). - MapScript layerObj: added getExtent, getNumFeatures extension methods, allowing getShape to access inline features (bug 562). - Added fixes for AMD64/Linux in configure (bug 565) - Removed OGR_STATIC stuff in configure script that used to allow us to build with OGR statically by pointing to the OGR source tree. That means you can only build with OGR when *installed* as part of GDAL, but that's what everyone is doing these days anyway. - Mapscript outputFormatObj: extended constructor to allow format names, and mapObj methods to append and remove output formats from the outputformatlist (bug 511). - New SWIG mapscript development documentation in the spirit of the PHP-Mapscript readme file, but using reST (bug 576). - Paving way for future changes to SWIG mapscript API with new features enabled by NEXT_GENERATION_API symbol (bug 586). - Added ability to set string member variables to NULL in PHP MapScript (bug 591) - New key iterators for map, layer, and class metadata hash tables (bug 434) and fontset fonts hash table (bug 439). - Fixed potential crash when using nquery with a querymap enabled and some layers have a template set at the layer level instead of inside classes (bug 569). - New CONFIG keyword in the MAP object in a .map file to be used to set external configuration parameters such as PROJ_LIB and control of some GDAL and OGR driver behaviours (bug 619) Version 4.0 (2003-08-01) ------------------------ - Fixed problem with truncated expressions (bugs 242 and 340) - Attempt at fixing GD vs libiconv dependency problems (bug 348) - Fixed problem with invalid BoundingBox tag in WMS capabilities (bug 34) - Fixed problems with SIZEUNITS not working properly (bug 373) - Fixed MacOSX configure problems for linking php_mapscript (bug 208) - Fixed problem with reference map marker symbol not showing up (bug 378) - Use in WMS 1.0.0 capabilities instead of (bug 129) - One-to-one and one-to-many joins now work for Xbase files and are available to query templates. Low level one-to-one Xbase joins are available via OGR. Version 4.0-beta2 (2003-07-11) ------------------------------ - Added prototype of FastCGI support in mapserv_fcgi.c (not built by default). - Report full error stack in the mapserv CGI and PHP MapScript (bug 346) - Old index (.qix) format is deprecated (bug 273) - Fixed problem with embedded legend and scalebar that would result in layers being added to the HTML legends (bug 171) - Changed joins (XBase only at this point) over to the open-prepare-next... next-close way of doing things. Compiles fine, but needs more testing. One-to-many support should work now but it needs to be hooked into the template code yet. Last thing before a candidate 4.0 release. - Added ability to generate images in MapScript processQueryTemplate (bug 341) - Added saving of output formats in msSaveMap() - Fixed problem in PHP MapScript with variables that were not dereferenced before their values were changed by the MapScript wrappers (bug 323) - Added support for Web Map Context 1.0.0 - Treat zero-length template values as NULL so that it's possible to set("template", "") from MapScript to make layer non-queryable (bug 338) - Ditched the shapepath argument to the shapefileObj constructor - CARTOLINE join style default changed to MS_CJC_NONE - Tweaked code in legend builder to handle polygon layers slightly different. Now if a polygon layer contains only outlines and no fills (i.e. a polyline) then it is drawn using the zigzag legend shape rather than the box. I'll add legend outlines back in shortly. - Restored legend key outlines (triggered by setting OUTLINECOLOR). If an outline is requested then line symbols are clipped to the outline, otherwise lines are allowed to bleed a pixel or two beyond those boundaries- for most cases this looks fine but for fat lines it is gonna look goofy regardless. In those cases use the KEYIMAGE. - Fixed a bug in the scanline writer so that x coordinates can be in any order when passed in to the function. (bug 336) - Updated loadExpressionString in mapfile.c to be a bit more tolerant of input. Now if a string does not match the logical or regex pattern it is automatically cast as a string expression. Removes the need for silly quotes. Version 4.0-beta1 (2003-06-06) ------------------------------ - Added imagemap outputformat, which makes possible use of client-side imagemaps in browsers. - Added MySQL support for non-spatial OpenGIS Simple Features SQL stored data - msQueryByShape and msQueryByFeature honor layer tolerances. In effect you can to buffered queries now. At the momoment only polygon select features are supported, but there's nothing inherent in the underlying computations that says lines won't work as well. - Simple one-to-one joins are working again. Reworked the join code so that table connections are persistant within a join (across joins is a todo). Joins, like layers are wrapped with a connection neutral front end, that sets us up to do MySQL or whatever in addition to XBase. - Removed shapepath argument to all layer access functions (affects MapScript). It's still used but we leverage the layer pointer back to the parent mapObj so the API is cleaner. - Changed default presentation of feature attributes to escape a few problematic characters for HTML display (eg. > becomes >). Added [itemname_raw] substitution to allow access to unaltered data. - Added initial version of Jan Hartman's connection pooling code. - Replaced libwww with libcurl for WMS/WFS client HTTP requests. (libcurl 7.10 required, see http://curl.haxx.se/libcurl/c/) - Added CONNECTION to the list of mapfile parameters that can accept %variable% substitutions when processed by the cgi version. This is useful for passing in username and/or passwords to database data sources. - Added support for DATA and TEMPLATE (header/footer/etc...) filtering using an regex declared in the mapfile (DATAPATTERN and TEMPLATEPATTERN). Certain parameters in a mapfile cannot be changed via a URL without first being filtered. - Added support for enviroment variable MS_MAPFILE_PATTERN. This allows you to override the default regex in favor of one more restrictive (I would hope) of your own. - Disabled CGI SAVEMAP option. - Removed CGI TEMPLATE option since you can use the map_web_template syntax. Simplifies security maintenance by only having to deal with this option in a single place. - Added offset support (styleObj) for raster based output (GD for sure, not quite sure how OGR output is created although I believe is uses GD anyway). This allows for feature drop shadows and support for cool linear symbols like used to be supported in pre-3.4 versions. These offsets are not scalable at the moment. - Null shapes (attributes but no vertices) are skipped for shapefiles using the msLayerNextShape interface. Otherwise applications should check the shapeObj type member for MS_SHAPE_NULL. - Changed where label cache is allocated and cleared. Now it isn't allocated until drawing takes place. Any old cache is cleared before a new one is allocated. The cache is still intact following rendering for post-processing using MapScript. - Fixed screw up in pre-processing of logical expressions for item lists. Under certain circumstances that list could get corrupted and expressions would fail. - Added NOT operator to expression parser. - Added layer and map level DEBUG options to map file. - Major changes to support vector output (PDF, SWF, GML, ...): imageObj is used by all rendering functions instead of gdImagePtr, New msSaveImage() prototype - Support for GD-2.0, including 24 bits output. Dropped support for GD 1.x - Support for output to any GDAL-supported format via the new OUTPUTFORMAT object. - New styleObj to replace the OVERLAY* parameter in classes. - PostGIS: Added Sean Gillies 's patch for "using unique ". Added "using SRID=#" to specify a spatial reference for an arbitrary sql query. - ... and numerous fixes not listed here... Version 3.6.0-beta1 (2002-04-30) -------------------------------- - MapScript: qitem and qstring params added to layer->queryByAttribute(). Instead of being driven by the layer's FILTER/FILTERITEM, the query by attribute is now driven by the values passed via qitem,qstring, and the layer's FILTER/FILTERITEM are ignored. - Symbol and MapFile changes: ANTIALIAS and FILLED keywords now take a boolean (TRUE/FALSE) argument i.e. ANTIALIAS becomes ANTIALIAS TRUE and FILLED becomes FILLED TRUE - Reference Map: Added options to show a different marker when the reference box becomes too small. See the mapfile reference docs for more details on the new reference object parameters (MARKER, MARKERSIZE, MAXBOXSIZE, MINBOXSIZE) - Added MINSCALE/MAXSCALE at the CLASS level. - Support for tiled OGR datasets. - PHP 4.1.2 and 4.2.0 support for PHP MapScript. - Added LAYER TRANSPARENCY, value between 1-100 - Fixes to the SWIG interface for clean Java build. - New HTML legend templates for CGI and MapScript. See HTML-Legend-HOWTO. - WMS server now supports query results using HTML query templates instead of just plain/text. - Added support functions for thread safety (--with-thread). Still not 100% thread-safe. Version 3.5.0 (2002-12-18) -------------------------- - No Revision history before version 3.5 mapserver-7.4.3/INSTALL000066400000000000000000000006661357574274700146170ustar00rootroot00000000000000Visit http://www.mapserver.org/ for full documentation and installation instructions. Unix compilation instructions ----------------------------- See INSTALL.CMAKE or the document on the MapServer website at Win32 compilation instructions ------------------------------ See README.WIN32 or the document on the MapServer website at mapserver-7.4.3/INSTALL.CMAKE000066400000000000000000000224471357574274700154370ustar00rootroot00000000000000CMake Build Instructions ======================== Since version 6.4, MapServer is built with the CMake build tool instead of the previous autotools chain. CMake is opensource and free of charge and is usually included in distribution packages, or can be downloaded and compiled with no third party dependencies. CMake itself does not do the actual compiling of the MapServer source code, it mainly creates platform specific build files that can then be used by standard build utilities (make on unixes, visual studio on windows, xcode on osx, etc...) Install CMake ------------- MapServer requires at least CMake version 2.6.0, although the build process with such an old version has not been thouroughly tested. 2.8.0 and above are recommended. Distro Packaged Version ....................... Linux distributions usually include the cmake package, that can be installed with your usual package manager: apt-get, yum, yast, etc... Installing Your Own ................... Head over to http://www.cmake.org/cmake/resources/software.html to download a source tarball (for unixes) or a binary installer (for windows). If you are building from source, the build process is detailed in the tarball readme files, and consists only in $ tar xzf cmake-x.y.z.tar.gz $ cd cmake-x.y.z $ ./bootstrap $ make # make install Creating the MapServer platform specific project with CMake ----------------------------------------------------------- Although you can run and build from MapServer's source directory as created by downloading a tarball or using a git clone, it is **highly** recommended to run "out-of-source" builds, i.e. having all build files be compiled and created in a different directory than the actual MapServer sources. This allows to have different configurations running alongside each other (e.g. release and debug builds, cross-compiling, enabled features, etc...). Running CMake From the Command Line ................................... mkdir build cd build cmake .. ## fix dependency issues make Running the GUI version of cmake ................................ CMake can be run in graphical mode, in which case the list of available options are presented in a more user-friendly manner mkdir build cd build ccmake .. ## follow instructions, fix dependency issues make Options and Dependencies ........................ Depending on what packages are available in the default locations of your system, the previous "cmake .." step will most probably have failed with messages indicating missing dependencies (by default, MapServer has *many* of those). The error message that CMake prints out should give you a rather good idea of what steps you should take next, depending on wether the failed dependency is a feature you require in your build or not. - Either disable the dependency by rerunning cmake with -DWITH_DEPENDENCY=0, e.g. $ cmake .. -DWITH_CAIRO=0 - Or, if the failed dependency relates to a feature you want built in, and that cmake has not been able to find it's installation location, there are 3 possible reasons: 1 You have not installed the third party package, and/or the third party development headers. Use your standard package manager to install the failing package, along with it's development headers. The development packages on linux usually end with "-dev" or "-devel", e.g. libcairo2-devel , libpng-dev, etc... $ (sudo) apt-get install libcairo-dev $ cmake .. 2 You have installed the third party package in a non standard location, which you must give to cmake so it can find the required headers and libraries $ cmake .. -DCMAKE_PREFIX_PATH=/opt/cairo-1.18.2 Cmake expects these nonstandard prefixes to contain standard subdirectories, i.e. /opt/cairo-1.18.2/include/cairo.h and /opt/cairo-1.18.2/lib/libcairo.so. You can specify multiple prefixes on the cmake command line by separating them with the platform specific separator (e.g. ":" on unixes), e.g. $ cmake .. -DCMAKE_PREFIX_PATH=/opt/cairo-1.18.2:/opt/freeware 3 If you're certain that the packages development headers are installed, and/or that you pointed to a valid installation prefix, but cmake is still failing, then there's an issue with MapServer's cmake setup, and you can bring this up on the mailing list or issue tracker. Available Options ----------------- Following is a list of option, taken from MapServer's CMakeLists.txt configuration file. After the description of the option, the ON/OFF flag states if the option is enabled by default (in which case the cmake step will fail if the dependency cannot be found). All of these can be enabled or disabled by passing "-DWITH_XXX=0" or "-DWITH_XXX=1" to the "cmake .." invocation in order to override a default selection. This Readme file may be out of sync with the actual CMakeLists files shipped. Refer to the CMakeLists.txt file for up-to-date options. - option(WITH_PROJ "Choose if reprojection support should be built in" ON) - option(WITH_KML "Enable native KML output support (requires libxml2 support)" OFF) - option(WITH_SOS "Enable SOS Server support (requires PROJ and libxml2 support)" OFF) - option(WITH_WMS "Enable WMS Server support (requires proj support)" ON) - option(WITH_FRIBIDI "Choose if FriBidi glyph reordering should be enabled (usefull for left-to-right languages)(requires harfbuzz)" ON) - option(WITH_HARFBUZZ "Choose if Harfbuzz complex script glyph shaping support should be built in (requires fribidi)" ON) - option(WITH_ICONV "Choose if Iconv Internationalization support should be built in" ON) - option(WITH_CAIRO "Choose if CAIRO rendering support should be built in (required for SVG and PDF output)" ON) - option(WITH_SVGCAIRO "Choose if SVG symbology support (via libsvgcairo) should be built in (requires cairo, libsvg, libsvg-cairo. Incompatible with librsvg)" OFF) - option(WITH_RSVG "Choose if SVG symbology support (via librsvg) should be built in (requires cairo, librsvg. Incompatible with libsvg-cairo)" OFF) - option(WITH_MYSQL "Choose if MYSQL joining support should be built in" OFF) - option(WITH_FCGI "Choose if FastCGI support should be built in" ON) - option(WITH_GEOS "Choose if GEOS geometry operations support should be built in" ON) - option(WITH_POSTGIS "Choose if Postgis input support should be built in" ON) - option(WITH_GDAL "Choose if GDAL input raster support should be built in" ON) - option(WITH_OGR "Choose if OGR/GDAL input vector support should be built in" ON) - option(WITH_CURL "Enable Curl HTTP support (required for wms/wfs client, remote SLDs and pixmap symbols)" OFF) - option(WITH_CLIENT_WMS "Enable Client WMS Layer support (requires CURL and GDAL support)" OFF) - option(WITH_CLIENT_WFS "Enable Client WMS Layer support (requires CURL and OGR support)" OFF) - option(WITH_WFS "Enable WFS Server support (requires PROJ and OGR support)" ON) - option(WITH_WCS "Enable WCS Server support (requires PROJ and GDAL support)" ON) - option(WITH_LIBXML2 "Choose if libxml2 support should be built in (used for sos, wcs 1.1,2.0 and wfs 1.1)" ON) - option(WITH_THREAD_SAFETY "Choose if a thread-safe version of libmapserver should be built (only recommended for some mapscripts)" OFF) - option(WITH_GIF "Enable GIF support (for PIXMAP loading)" ON) - option(WITH_PYTHON "Enable Python mapscript support" OFF) - option(WITH_PHP "Enable PHP mapscript support" OFF) - option(WITH_PERL "Enable Perl mapscript support" OFF) - option(WITH_RUBY "Enable Ruby mapscript support" OFF) - option(WITH_JAVA "Enable Java mapscript support" OFF) - option(WITH_CSHARP "Enable C# mapscript support" OFF) - option(WITH_ORACLESPATIAL "include oracle spatial database input support" OFF) - option(WITH_ORACLE_PLUGIN "include oracle spatial database input support as plugin" OFF) - option(WITH_MSSQL2008 "include mssql 2008 database input support as plugin" OFF) - option(WITH_SDE_PLUGIN "include ArcSDE support as a plugin (must specify SDE_INCLUDE_DIR and SDE_LIBRARY_DIR)." OFF) - option(WITH_SDE "include ArcSDE support. Add -DSDE_VERSION=91 to use 9.1 arcSDE version" OFF) - option(WITH_EXEMPI "include xmp output metadata support" OFF) - option(WITH_XMLMAPFILE "include native xml mapfile support (requires libxslt/libexslt)" OFF) - option(WITH_V8 "include javacript v8 scripting" OFF) The following options are for advanced users, i.e. you should not enable them unless you know what you are doing: - option(BUILD_STATIC "Also build a static version of mapserver" OFF) - option(LINK_STATIC_LIBMAPSERVER "Link to static version of libmapserver (also for mapscripts)" OFF) - option(WITH_APACHE_MODULE "include (experimental) support for apache module" OFF) - option(WITH_GENERIC_NINT "generic rounding" OFF) - option(WITH_POINT_Z_M "include Z and M coordinates in point structure (advanced, not recommended)" OFF) The following are some common CMake options not specific to MapServer itself: - CMAKE_INSTALL_PREFIX : path where mapserver binaries and libraries should be installed. Defaults to /usr/local on unix. - CMAKE_PREFIX_PATH : platform-specific separator separated list of prefixes where dependencies will be looked for, e.g. "-DCMAKE_PREFIX_PATH=/opt/freeware:/opt/jdk-1.5.6" - CMAKE_BUILD_TYPE : Specify the build type. Usually one of 'Debug' or 'Release', e.g. "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_BUILD_TYPE=Debug" You can find a more extensive list of cmake variables here: http://www.cmake.org/Wiki/CMake_Useful_Variables mapserver-7.4.3/MIGRATION_GUIDE.txt000066400000000000000000000010521357574274700165630ustar00rootroot00000000000000***************************************************************************** MapServer Migration Guide ***************************************************************************** The current version of the MapServer Migration Guide is available online at http://www.mapserver.org/MIGRATION_GUIDE.html. For developers: The master copy of the MIGRATION_GUIDE is now located in the root of the mapserver/docs source tree (https://github.com/mapserver/docs). Developers are welcome and encouraged to edit/update the guide in the docs tree directly. mapserver-7.4.3/Makefile000066400000000000000000000065371357574274700152310ustar00rootroot00000000000000AUTOTEST_OPTS?=-strict -q PHP_MAPSCRIPT=build/mapscript/php/php_mapscript.so PYTHON_MAPSCRIPT_PATH=build/mapscript/python JAVA_MAPSCRIPT_PATH=build/mapscript/java CSHARP_MAPSCRIPT_PATH=build/mapscript/csharp PERL_MAPSCRIPT_PATH=build/mapscript/perl BUILDPATH=../../build FLEX=flex YACC=yacc CMAKEFLAGS=-DCMAKE_C_FLAGS="--coverage ${CMAKE_C_FLAGS}" -DCMAKE_CXX_FLAGS="--coverage ${CMAKE_CXX_FLAGS}" \ -DCMAKE_SHARED_LINKER_FLAGS="-lgcov" -DWITH_CLIENT_WMS=1 \ -DWITH_CLIENT_WFS=1 -DWITH_KML=1 -DWITH_SOS=1 -DWITH_CSHARP=1 -DWITH_PHP=1 -DWITH_PERL=1 \ -DWITH_PYTHON=1 -DWITH_JAVA=1 -DWITH_THREAD_SAFETY=1 -DWITH_FRIBIDI=1 -DWITH_FCGI=0 -DWITH_EXEMPI=1 \ -DCMAKE_BUILD_TYPE=Release -DWITH_RSVG=1 -DWITH_CURL=1 -DWITH_HARFBUZZ=1 -DWITH_POINT_Z_M=1 ${EXTRA_CMAKEFLAGS} all: cmakebuild cmakebuild: lexer parser if test ! -s build/Makefile; then mkdir -p build ; cd build ; cmake .. $(CMAKEFLAGS); fi cd build && $(MAKE) $(MFLAGS) warning: $(error "This Makefile is used to run the \"test\" target") wxs-testcase: cd msautotest/wxs && chmod 777 tmp && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) renderers-testcase: cd msautotest/renderers && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) misc-testcase: cd msautotest/misc && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) gdal-testcase: cd msautotest/gdal && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) query-testcase: cd msautotest/query && rm -f result/* && export PATH=$(BUILDPATH):$(PATH) && ./run_test.py $(AUTOTEST_OPTS) mspython-testcase: test -f "$(PYTHON_MAPSCRIPT_PATH)/_mapscript.so" && (export PYTHONPATH="../../$(PYTHON_MAPSCRIPT_PATH)" && cd msautotest/mspython && python run_all_tests.py) mspython-wheel: cd build && cmake --build . --target pythonmapscript-wheel php-testcase: test -f "$(PHP_MAPSCRIPT)" && (export PHP_MAPSCRIPT_SO="../../$(PHP_MAPSCRIPT)" && cd msautotest/php && ./run_test.sh) java-testcase: test -d "$(JAVA_MAPSCRIPT_PATH)" && (export JAVA_MAPSCRIPT_SO="../../$(JAVA_MAPSCRIPT_PATH)" && cd mapscript/java && ./run_test.sh) csharp-testcase: test -d "$(CSHARP_MAPSCRIPT_PATH)" && (export CSHARP_MAPSCRIPT_SO="../../$(CSHARP_MAPSCRIPT_PATH)" && cd mapscript/csharp && ./run_test.sh) perl-testcase: cd "$(PERL_MAPSCRIPT_PATH)" \ && PERL5LIB=`pwd` \ && prove tests \ && perl examples/RFC24.pl ../../../tests/test.map \ && perl examples/shp_in_shp.pl --infile1 ../../../tests/line.shp --infile1_shpid 0 --infile2 ../../../tests/polygon.shp --infile2_shpid 0 \ && perl examples/dump.pl --file ../../../tests/line.shp \ && perl examples/thin.pl --input ../../../tests/polygon --output examples/junk --tolerance=5 test: cmakebuild @$(MAKE) $(MFLAGS) wxs-testcase renderers-testcase misc-testcase gdal-testcase query-testcase mspython-testcase @./print-test-results.sh @$(MAKE) $(MFLAGS) php-testcase @$(MAKE) $(MFLAGS) csharp-testcase @$(MAKE) $(MFLAGS) perl-testcase asan_compatible_tests: cmakebuild @$(MAKE) $(MFLAGS) wxs-testcase renderers-testcase misc-testcase gdal-testcase query-testcase @./print-test-results.sh lexer: maplexer.c parser: mapparser.c maplexer.c: maplexer.l $(FLEX) --nounistd -Pmsyy -i -o$(CURDIR)/maplexer.c maplexer.l mapparser.c: mapparser.y $(YACC) -d -o$(CURDIR)/mapparser.c mapparser.y mapserver-7.4.3/Makefile.vc000066400000000000000000000162751357574274700156400ustar00rootroot00000000000000# # makefile.vc - Main MapServer makefile for MSVC++ # # This VC++ makefile will build MAPSERVER.LIB, MAPSERV.EXE, and the other # MapServer command-line programs. # # To use the makefile: # - Open a DOS prompt window # - Run the VCVARS32.BAT script to initialize the VC++ environment variables # - Start the build with: nmake /f makefile.vc # # $Id$ # MAPSERVER_ROOT = . !INCLUDE nmake.opt BASE_CFLAGS = $(OPTFLAGS) CFLAGS=$(BASE_CFLAGS) $(MS_CFLAGS) CC= cl LINK= link # # Main MapServer library. # MS_DLL = libmap.dll MS_OBJS = mapbits.obj maphash.obj mapshape.obj mapxbase.obj \ mapparser.obj maplexer.obj maptree.obj \ mapsearch.obj mapstring.obj mapsymbol.obj mapfile.obj \ maplegend.obj maputil.obj mapscale.obj mapquery.obj \ maplabel.obj maperror.obj mapprimitive.obj mapproject.obj\ mapraster.obj cgiutil.obj mapsde.obj mapogr.obj maptime.obj \ maptemplate.obj mappostgis.obj maplayer.obj mapresample.obj \ mapwms.obj mapwmslayer.obj mapgml.obj maporaclespatial.obj \ mapprojhack.obj mapdraw.obj mapgd.obj mapoutput.obj \ mapgdal.obj mapwfs.obj mapwfs11.obj mapwfslayer.obj mapows.obj maphttp.obj \ mapcontext.obj mapdrawgdal.obj mapjoin.obj mapgraticule.obj \ mapimagemap.obj mapcopy.obj maprasterquery.obj \ mapogcfilter.obj mapogcsld.obj mapthread.obj mapobject.obj \ classobject.obj layerobject.obj mapwcs.obj mapwcs11.obj mapwcs20.obj \ mapgeos.obj strptime.obj mapogroutput.obj \ mapcpl.obj mapio.obj mappool.obj mapregex.obj mappluginlayer.obj \ mapogcsos.obj mappostgresql.obj mapcrypto.obj mapowscommon.obj \ maplibxml2.obj mapdebug.obj mapchart.obj mapagg.obj maptclutf.obj \ maprendering.obj mapimageio.obj mapcairo.obj \ mapoglrenderer.obj mapoglcontext.obj mapogl.obj \ maptile.obj $(EPPL_OBJ) $(REGEX_OBJ) mapgeomtransform.obj mapunion.obj \ mapkmlrenderer.obj mapkml.obj mapdummyrenderer.obj mapgeomutil.obj mapquantization.obj \ mapogcfiltercommon.obj mapcluster.obj mapuvraster.obj mapcontour.obj mapsmoothing.obj mapservutil.obj hittest.obj $(AGG_OBJ) MS_HDRS = mapserver.h mapfile.h MS_EXE = mapserv.exe \ shp2img.exe legend.exe \ shptree.exe scalebar.exe sortshp.exe tile4ms.exe \ shptreevis.exe msencrypt.exe # # # default: all all: $(MS_LIB) $(MS_EXE) mapscriptvars $(MS_OBJS): $(MS_HDRS) $(MS_DLL) $(MS_LIB_DLL): $(MS_LIB) link /dll $(LDEBUG) \ $(MS_OBJS) $(EXTERNAL_LIBS) \ /out:$(MS_DLL) /implib:$(MS_LIB_DLL) if exist $(MS_DLL).manifest mt -manifest $(MS_DLL).manifest -outputresource:$(MS_DLL);2 $(MS_LIB): $(MS_OBJS) if exist $(GDAL_DIR)\gdal.pdb copy $(GDAL_DIR)\gdal.pdb . lib /out:$(MS_LIB) $(MS_OBJS) !IFDEF DLLBUILD $(MS_EXE): $(MS_DLL) $(MS_LIB_DLL) !ELSE $(MS_EXE): $(MS_LIB) !ENDIF gd:: cd gd-1.2 nmake /f makefile.nt OPTFLAGS="$(OPTFLAGS)" cd .. .c.obj: $(CC) $(CFLAGS) /c $*.c /Fo$*.obj .cpp.obj: $(CC) $(CFLAGS) /c $*.cpp /Fo$*.obj .c.exe: $(CC) $(CFLAGS) /c $*.c /Fo$*.obj !IFDEF DLLBUILD $(LINK) $(LDEBUG) $(LDFLAGS) $*.obj $(LIBS_DLL) !ELSE $(LINK) $(LDEBUG) $(LDFLAGS) $*.obj $(LIBS) !ENDIF if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 clean: del *.obj del $(REGEX_OBJ) del $(AGG_OBJ) del *.lib del *.dll del $(MS_EXE) del *.pdb del *.exp del *.ilk del *.manifest del renderers\agg\*.obj !IFDEF DOT_NET cd mapscript\csharp nmake /f makefile.vc clean cd ..\.. !ENDIF !IFDEF JAVA_HOME cd mapscript\java nmake /f makefile.vc clean cd ..\.. !ENDIF !IFDEF PHP_HOME cd mapscript\php nmake /f makefile.vc clean cd ..\.. !ENDIF !IFDEF PYTHON_HOME cd mapscript\python -del mapscript_wrap.c -rmdir /s /q build cd ..\.. !ENDIF mapscriptvars: makefile.vc nmake.opt -del mapscriptvars echo $(MS_CURRENT) > mapscriptvars !IFDEF WIN64 echo $(MS_DEFS) -DWIN32 -D_WIN32 -DUSE_GENERIC_MS_NINT >> mapscriptvars !ELSE echo $(MS_DEFS) -DWIN32 -D_WIN32 >> mapscriptvars !ENDIF echo $(INCLUDES) >> mapscriptvars echo $(LIBS_DLL) >> mapscriptvars echo $(LIBS) >> mapscriptvars findstr MS_VERSION mapserver-version.h | findstr define >> mapscriptvars #install: $(MS_DLL) $(MS_EXE) python csharp java php install: $(MS_DLL) $(MS_EXE) -mkdir $(BINDIR) xcopy /y /r /d /f $(MS_DLL) $(BINDIR) copy *.exe $(BINDIR) !IFDEF PYTHON_HOME -mkdir $(BINDIR)\mapscript\python xcopy /y /r /d /f .\mapscript\python\dist\*.zip $(BINDIR)\mapscript\python !ENDIF !IFDEF DOT_NET -mkdir $(BINDIR)\mapscript\csharp xcopy /y /r /d /f .\mapscript\csharp\*.dll $(BINDIR)\mapscript\csharp xcopy /y /r /d /f .\mapscript\csharp\*.exe $(BINDIR)\mapscript\csharp xcopy /y /r /d /f .\mapscript\csharp\*.manifest $(BINDIR)\mapscript\csharp xcopy /y /r /d /f .\mapscript\csharp\*.config $(BINDIR)\mapscript\csharp !ENDIF !IFDEF JAVA_HOME -mkdir $(BINDIR)\mapscript\java xcopy /y /r /d /f .\mapscript\java\*.dll $(BINDIR)\mapscript\java xcopy /y /r /d /f .\mapscript\java\*.jar $(BINDIR)\mapscript\java !ENDIF !IFDEF PHP_HOME -mkdir $(BINDIR)\mapscript\php xcopy /y /r /d /f .\mapscript\php\*.dll $(BINDIR)\mapscript\php !ENDIF !IFDEF PYTHON_HOME python: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) cd mapscript\python $(SWIG) -python -shadow -o mapscript_wrap.c ../mapscript.i $(PYTHON_HOME)\PCBuild\python.exe setup.py bdist cd ..\.. !ELSE python: !ENDIF !IFDEF DOT_NET csharp: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) cd mapscript\csharp nmake /f makefile.vc cd ..\.. !ELSE csharp: !ENDIF !IFDEF JAVA_HOME java: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) cd mapscript\java nmake /f makefile.vc cd ..\.. !ELSE java: !ENDIF !IFDEF PHP_HOME php: mapscriptvars $(MS_DLL) $(MS_LIB_DLL) cd mapscript\php nmake /f makefile.vc cd ..\.. !ELSE php: !ENDIF !IF DEFINED(SDE_OPT) || DEFINED(ORACLE) || DEFINED(MSSQL2008) !IFDEF ORACLE ORACLE_LIB=$(ORACLE_DIR)/lib/msvc/oci.lib !ENDIF !IFDEF SDE_OPT !IF $(SDE_VERSION) >= 92 SDE_LIB = $(SDE_DIR)\lib\pe.lib \ $(SDE_DIR)\lib\sde.lib \ $(SDE_DIR)\lib\sg.lib !ELSE SDE_LIB = $(SDE_DIR)\lib\pe$(SDE_VERSION).lib \ $(SDE_DIR)\lib\sde$(SDE_VERSION).lib \ $(SDE_DIR)\lib\sg$(SDE_VERSION).lib !ENDIF !ENDIF !ENDIF plugins: -del mapsde.obj -del maporaclespatial.obj -del mapmssql2008.obj !IFDEF SDE_OPT $(CC) $(CFLAGS) -DUSE_SDE /c mapsde.c /Fomapsde.obj link /dll $(LDEBUG) /out:msplugin_sde_$(SDE_VERSION).dll mapsde.obj mapthread.obj mapserver_i.lib $(SDE_LIB) if exist msplugin_sde_$(SDE_VERSION).dll.manifest mt -manifest msplugin_sde_$(SDE_VERSION).dll.manifest -outputresource:msplugin_sde_$(SDE_VERSION).dll;2 -del mapsde.obj !ENDIF !IFDEF ORACLE $(CC) $(CFLAGS) -DUSE_ORACLESPATIAL /c maporaclespatial.c /Fomaporaclespatial.obj link /dll $(LDEBUG) /out:msplugin_oracle.dll maporaclespatial.obj $(ORACLE_LIB) mapserver_i.lib if exist msplugin_oracle.dll.manifest mt -manifest msplugin_oracle.dll.manifest -outputresource:msplugin_oracle.dll;2 -del maporaclespatial.obj !ENDIF !IFDEF MSSQL2008 $(CC) $(CFLAGS) $(ODBC_INC) -DUSE_MSSQL2008 -DUSE_MSSQL2008_PLUGIN /c mapmssql2008.c /Fomapmssql2008.obj link /dll $(LDEBUG) /out:msplugin_mssql2008.dll mapmssql2008.obj $(ODBC_LIBS) mapserver_i.lib if exist msplugin_mssql2008.dll.manifest mt -manifest msplugin_mssql2008.dll.manifest -outputresource:msplugin_mssql2008.dll;2 -del mapmssql2008.obj !ENDIF mapserver-7.4.3/README.WIN32000066400000000000000000000256251357574274700152510ustar00rootroot00000000000000-------------------------------------------------------------------- README.WIN32 - Microsoft Visual C++ Build instructions for MapServer -------------------------------------------------------------------- IMPORTANT - READ THIS FIRST: ---------------------------- The Win32 build process is not very friendly for unexperienced users. So it is strongly recommended that you use one of the precompiled binaries available on the MapServer site: http://www.mapserver.org/download.html#windows There are precompiled Win32 binaries available for the last stable release and the latest nightly build and they include the most common options... so you shouldn't have to compile your own executables. If for some reason you still decide to compile Win32 binaries yourself, then don't do it unless you really know what you're doing... and hopefully the rest of this file contains some hints that may help you. Good Luck! -------------------------------------------------------------------- The easyest way to build Mapserver on Windows on your own is to use the build-system from http://gisinternals.com/. GISInternals provide a complete set of sources and dependencies and even makefiles for the full version of Visual Studio (not Express oder Community). You don't have to download and compile them all by your own. If you are not using full version of Visual Studio you can not use the makefiles from GISInternals but you can still use the downloads to make your life easier. Building with the full version of Visual Studio is easy. Download the SDK for you version and follow the readme inside the packages. This Readme will cover the compilation with Visual Studio 2012 Express on Windows with CMake and the GISInternals-Packages for the following reasons: - not everybody wants to buy Visual Studio and there is no reason to force you to buy it just tu build Mapserver on Windows - CMake is the configuration-system for Linux. Why should you use something else which needs to be maintainerd? - as of today, PHP-Mapscript is not suppored for PHP-7. PHP-5.6 is build with VC11. To make PHP-Mapscript compatible with the downloadable PHP-Version you need to build with VC11 wich is Visual Studio 2012. - GISInternals Downloads contain most dependencies. it's way easier If you want to compile Mapserver with any other version of Visual Studio you can for sure use this documentation as help but maybe, some things here won't work for you. -------------------------------------------------------------------- Prerequisites -------------------------------------------------------------------- To build Mapserver on Windows with Visual Studio 2012 Express you need Visual Studio 2012 Express installed. Install CMake (https://cmake.org/) and add CMake bin-directory to your PATH environment variable. You can even to this after opening VS2012 x86 Native Tools Command Prompt by entering: set PATH=%PATH%;"C:\Program Files\CMake\bin" ... if CMake is installed to "C:\Program Files\CMake" ;) -------------------------------------------------------------------- Downloading dependencies -------------------------------------------------------------------- For our first build, we will use stable releases to build mapserver. Download MSVC 2012 win32 Packages for GDAL-2.1.2 and Mapserver-7.0.2 from http://gisinternals.com/release.php. We need "Compiled binaries in a single .zip package", "GDAL and MapServer sources" and "Compiled libraries and headers". Download the MSVC 2012 win32 Developement Kit from http://gisinternals.com/sdk.php. Extract everything to C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2. There should be the directories inside now: bin, doc, gdal, include, lib, regex-0.12, relase-1700, ... After you got this done, feel free to use other packages which fit your needs better. -------------------------------------------------------------------- Mapserver-sources -------------------------------------------------------------------- Download at least Mapserver-7.0.3 or current 7.0-Branch from github and extract or clone from github to C:\dev\work\mapserver. -------------------------------------------------------------------- Building Mapserver -------------------------------------------------------------------- After downloading and extracting everything, to build Mapserver, follow this steps: 1. Open VS2012 x86 Native Tools Command Prompt (i'm german, hope it is translated correctly). 2. Add CMake-bin to your PATH: set PATH=%PATH%;"C:\Program Files\CMake\bin" 3. Create build-Directory: mkdir C:\dev\work\mapserver\build cd C:\dev\work\mapserver\build 4. Configure: cmake .. -G "NMake Makefiles" -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Release -Wno-dev cmake .. -DCMAKE_PREFIX_PATH=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\bin;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib;C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\include cmake .. -DREGEX_DIR=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\regex-0.12 cmake .. -DWITH_POSTGIS=0 -DWITH_SOS=1 -DWITH_KML=1 cmake .. -DWITH_CLIENT_WMS=1 -DWITH_CLIENT_WFS=1 cmake .. -DWITH_THREAD_SAFETY=1 -DWITH_FCGI=1 cmake .. -DWITH_CAIRO=1 -DCAIRO_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\cairo.lib cmake .. -DWITH_SVGCAIRO=1 -DSVGCAIRO_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\libsvg-cairo.lib cmake .. -DSVG_LIBRARY=1 -DSVG_LIBRARY=C:\dev\work\release-1700-gdal-2-1-2-mapserver-7-0-2\lib\libsvg.lib 5. build nmake Thats it. You can use all CMake parameters and options as you are used from CMake to fit mapserver to your needs from here. Enjoy! -------------------------------------------------------------------- MapScript -------------------------------------------------------------------- To compile the various versions of MapScript (Perl, PHP, etc) first compile the main mapserver directory and then see the README files in the mapscript/perl, mapscript/php or mapscript/python directory for specific instructions. -------------------------------------------------------------------- Dependencies Part 2 -------------------------------------------------------------------- The following sections descripe how to get mapserver dependencies when not downloading GISInternals packages. -------------------------------------------------------------------- GD library -------------------------------------------------------------------- - MapServer uses the GD library from http://boutell.com/ and the Win32 makefiles are set by default to work with the pre-built GD version 2.0.33 provided by Boutell.com. These predefine "gdwin32" binaries include freetype2, libpng, libjpeg, libz, and libgif built-in. This is very convenient to get a mapserver build going quickly. If you are building GD and it's supporting libraries (libpng, libjpeg, libgif, and freetype) from source then it is very important to make sure that you update the -DUSE_GD_* flags and various subcomponent paths in the nmake.opt. You will also have to take great care to build the various components in a way that is compatible with MapServer. For instance, if the various components are statically linked into MapServer you will need to use the same build options (ie. /MT or /MT) for all components. Here are some useful pointers: - The original GD library: http://boutell.com/gd/ - libpng: http://www.libpng.org/pub/png/libpng.html - zlib: http://www.info-zip.org/pub/infozip/zlib/ - libjpeg: ftp://ftp.uu.net/graphics/jpeg/ - Freetype: http://www.freetype.org/download.html -------------------------------------------------------------------- REGEX library -------------------------------------------------------------------- - MapServer uses the REGEX library which is standard on all the Unix systems that I know of, but does not come with VC++. If the MapServer distribution did not include a copy of the REGEX library, then you can get a copy from: ftp://ftp.gnu.org/pub/gnu/regex/regex-0.12.tar.gz The default in the nmake.opt is set to compile with GNU regex-0.12 located in the "regex-0.12" directory. - If you are planning to compile the PHP3_MAPSCRIPT.DLL module, then it is important to make sure that the main Makefile.vc creates MAPSERVER.LIB with the same version of REGEX that PHP uses. See the notes in the main Makefile.vc about that. -------------------------------------------------------------------- Notes on Freetype build. -------------------------------------------------------------------- - You can use the Visual Workspace in freetype/lib/arch/win32 to build the library. -------------------------------------------------------------------- Notes on the proj module -------------------------------------------------------------------- - The Proj.4 (cartographic projection routines) is located at http://www.remotesensing.org/proj/ Note on the epsg files location and the nad directory : * there is an environnemnt variable PROJ_LIB_DIR that can be set to locate the directory where the epsg file is located * if you build this module, at the top of the makefile (./src/makefile.vc), you can set the PROJ_LIB variable and this setting will be used to locate the proj support files. ---------------------------------------------------------------------- Notes on libcurl ---------------------------------------------------------------------- Notes libcurl : used to support WMS client connection Mapserver 5.x is using libcurl instead of libwww for WMS client support. - the library is located at http://curl.haxx.se/download.html Quick notes on how to build the library using MSVC++: - Download and extract the library (at this time it is known to work with version 7.10.2 or more recent) - Open the workspace curlib.dsw located under curl-XXX/lib - Build libcurl.dll. Note that the default active configuraion of the project is Win32 Debug. You can modify the configuarion to Release version (Build/Set Active Configuration) Notes on mapserver's nmake.opt modifications : - uncomment the flag WMSCLIENT= -DUSE_WMS_LYR - uncomment and modify according to your installation the flags related to libcurl : * CURL_INC = -I../curl-7.10.2/include * CURL_LIB = ../curl-7.10.2/lib/Relase/libcurl.lib * WINSOCK_LIB = "C:\Program Files\Microsoft Visual Studio\VC98\Lib\WSOCK32.LIB" You also need to install the libcurl.dll in your system directory. (The dll will be located in libc-XXX/lib/Relase abfter your build of the library) ------------------------------------------------------------ Notes on GDAL ------------------------------------------------------------ - If you are compiling the GDAL library (http://www.gdal.org/) with the PNG support, make sure that the libpng that you use in mapserver is the same as the one used in GDAL. $Id$ mapserver-7.4.3/README.rst000066400000000000000000000071561357574274700152560ustar00rootroot00000000000000MapServer ========= | |Build Status| |Appveyor Build Status| ------- Summary ------- MapServer is a system for developing web-based GIS applications. The basic system consists of a CGI program that can be configured to respond to a variety of spatial requests like making maps, scalebars, and point, area and feature queries. Virtually all aspects of an application, from web interface to map appearance can be developed without any programming. For the more ambitious user, MapServer applications can be enhanced using Java, JavaScript or many other web technologies. For more information and complete documentation please visit: http://www.mapserver.org/ Bug reports and enhancement submissions can be reported in the MapServer issue tracker at the following url. If you do make changes and/or enhancements, please let us know so that they might be incorporated into future releases. https://github.com/mapserver/mapserver/issues Join the MapServer user mailing list online at: http://www.mapserver.org/community/lists.html Credits ------- MapServer was originally written by Stephen Lime. Major funding for development of MapServer has been provided by NASA through cooperative argreements with the University of Minnesota, Department of Forest Resources. PHP/MapScript developed by DM Solutions Group. GDAL/OGR support and significant WMS support provided by DM Solutions Group which received funding support from Canadian Government's GeoConnections Program and the Canadian Forest Service. Raster support developed by Pete Olson of the State of Minnesota, Land Management Information Center, and maintained by Frank Warmerdam (DM Solutions). PostGIS spatial database support provided by Dave Blasby of Refractions Research. PDF support developed by Jeff Spielberg and Jamie Wall of Market Insite Group, Inc. OracleSpatial support developed by Rodrigo Cabral of CTTMAR/UNIVALI, Brazil. Portions Copyright (c) 1998 State of Minnesota, Land Management Information Center. Portions derived from Shapelib, Copyright 1995-1999 Frank Warmerdam. Supporting packages are covered by their own copyrights. License ------- :: Copyright (c) 2008-2019 Open Source Geospatial Foundation. Copyright (c) 1996-2008 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies of this Software or works derived from this Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. .. |Build Status| image:: https://travis-ci.org/mapserver/mapserver.svg?branch=master :target: https://travis-ci.org/mapserver/mapserver .. |Appveyor Build Status| image:: https://ci.appveyor.com/api/projects/status/vw1n07095a8bg23u?svg=true :target: https://ci.appveyor.com/project/mapserver/mapserver mapserver-7.4.3/Vagrantfile000066400000000000000000000024211357574274700157420ustar00rootroot00000000000000# -*- mode: ruby -*- # vi: set ft=ruby : require 'socket' # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "ubuntu/trusty64" config.vm.hostname = "mapserver-vagrant" config.vm.network :forwarded_port, guest: 80, host: 8080 config.vm.provider "virtualbox" do |v| v.customize ["modifyvm", :id, "--memory", 1024, "--cpus", 2] v.customize ["modifyvm", :id, "--ioapic", "on", "--largepages", "off", "--vtxvpid", "off"] v.name = "mapserver-vagrant" end # Unless explicitly declined, use the VM host's file system to cache # .deb files to avoid repeated downloads on each vagrant up unless File.exists?("../.no_apt_cache") cache_dir = "../apt-cache/#{config.vm.box}" FileUtils.mkdir_p(cache_dir) unless Dir.exists?(cache_dir) puts "Using local apt cache, #{cache_dir}" config.vm.synced_folder cache_dir, "/var/cache/apt/archives" end config.vm.provision "shell", path: "scripts/vagrant/virtualbox-fix.sh" config.vm.provision "shell", path: "scripts/vagrant/packages.sh" config.vm.provision "shell", path: "scripts/vagrant/postgis.sh" config.vm.provision "shell", path: "scripts/vagrant/mapserver.sh" end mapserver-7.4.3/apache/000077500000000000000000000000001357574274700147775ustar00rootroot00000000000000mapserver-7.4.3/apache/CMakeLists.txt000066400000000000000000000025571357574274700175500ustar00rootroot00000000000000add_library(mod_mapserver MODULE mod_mapserver.c) target_link_libraries(mod_mapserver ${MAPSERVER_LIBMAPSERVER}) set_target_properties(mod_mapserver PROPERTIES PREFIX "") IF(APPLE) if(HTTPD_EXECUTABLE) if(XCODE) SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -bundle_loader ${HTTPD_EXECUTABLE}") else(XCODE) SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -bundle_loader ${HTTPD_EXECUTABLE}") endif(XCODE) else(HTTPD_EXECUTABLE) if(XCODE) SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -undefined dynamic_lookup") else(XCODE) SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -Wl,-undefined,dynamic_lookup") endif(XCODE) endif(HTTPD_EXECUTABLE) ENDIF(APPLE) find_package(APACHE) if(APACHE_FOUND) include_directories(${APACHE_INCLUDE_DIR}) else(APACHE_FOUND) report_mandatory_not_found(APACHE) endif(APACHE_FOUND) find_package(APR) if(APR_FOUND) include_directories(${APR_INCLUDE_DIR}) target_link_libraries(mod_mapserver ${APR_LIBRARY}) if(DEFINED APR_CPPFLAGS) add_definitions("${APR_CPPFLAGS}") endif(DEFINED APR_CPPFLAGS) else(APR_FOUND) report_mandatory_not_found(APR) endif(APR_FOUND) if(APACHE_MODULE_DIR) INSTALL(TARGETS mod_mapserver DESTINATION ${APACHE_MODULE_DIR}) endif(APACHE_MODULE_DIR) mapserver-7.4.3/apache/mod_mapserver.c000066400000000000000000000335471357574274700200220ustar00rootroot00000000000000/* * mod_mapserver.c -- Apache sample wms module */ #include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include "http_log.h" #include "ap_config.h" #include "apr.h" #include "apr_strings.h" #include "apr_tables.h" #include "apr_file_info.h" #include "../mapserver.h" /* for mapObj */ #include "../cgiutil.h" #include "../mapserv.h" module AP_MODULE_DECLARE_DATA mapserver_module; typedef struct { apr_pool_t *config_pool; apr_time_t mtime; char *mapfile_name; char *uri; mapObj *map; } mapserver_dir_config; /* These are the IO redirection hooks. They are mostly copied over from * mapio.c. Note that cbData contains Apache's request_rec! */ static int msIO_apacheWrite (void *cbData, void *data, int byteCount) { /* simply use the block writing function which is very similiar to fwrite */ return ap_rwrite (data, byteCount, (request_rec*) cbData); } static int msIO_apacheError (void *cbData, void *data, int byteCount) { /* error reporting is done through the log file... */ ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s", (char*) data); return strlen ((char*) data); } int msIO_installApacheRedirect (request_rec *r) { msIOContext stdout_ctx, stderr_ctx; stdout_ctx.label = "apache"; stdout_ctx.write_channel = MS_TRUE; stdout_ctx.readWriteFunc = msIO_apacheWrite; stdout_ctx.cbData = (void*) r; stderr_ctx.label = "apache"; stderr_ctx.write_channel = MS_TRUE; stderr_ctx.readWriteFunc = msIO_apacheError; stderr_ctx.cbData = (void*) r; msIO_installHandlers (NULL, &stdout_ctx, &stderr_ctx); return MS_TRUE; } /* The maximum number of arguments we support. The number is taken from * cgiutil.h I think. It is only used for easier param decoding. */ #define WMS_MAX_ARGS 100 /* This is our simple query decoding function. Should be improved but for now * it works... */ static int mapserver_decode_args (apr_pool_t *p, char *args, char ***ParamNames, char ***ParamValues) { char **argv = NULL; int i; int n; int argc = 0; char *sep; /* alloc the name/value pointer list */ argv = (char**) apr_pcalloc (p, (WMS_MAX_ARGS + 1) * 2 * sizeof (char*)); *ParamNames = argv; *ParamValues = argv + WMS_MAX_ARGS + 1; /* No arguments? Then we're done */ if (!args) return 0; argv [0] = args; /* separate the arguments */ for (i = 1, n = 0; args [n] && (i < WMS_MAX_ARGS); n++) if (args [n] == '&') { argv [i++] = args + n + 1; args [n ] = '\0'; } /* eleminate empty args */ for (n = 0, i = 0; argv [i]; i++) if (*(argv [i]) != '\0') argv [n++] = argv [i]; else argv [i ] = NULL; /* argument count is the number of non-zero arguments! */ argc = n; /* split the name/value pairs */ for (i = 0; argv [i]; i++) { sep = strchr (argv [i], '='); if (!sep) continue; *sep = '\0'; argv [i + WMS_MAX_ARGS + 1] = (char*) apr_pstrdup (p, sep + 1); if (ap_unescape_url (argv [i + WMS_MAX_ARGS + 1]) == HTTP_BAD_REQUEST) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s: malformed URI, couldn't unescape parm %s", __func__, argv [i]); argv [i + WMS_MAX_ARGS + 1] = NULL; } else { plustospace (argv [i + WMS_MAX_ARGS + 1]); } } return argc; } static char* mapserver_read_post_data (request_rec *r) { int status; int size; long blen, rsize, rpos = 0; char *buffer = NULL; char buf [512]; if ((status = ap_setup_client_block (r, REQUEST_CHUNKED_ERROR)) != OK) return NULL; if (!ap_should_client_block (r)) return NULL; buffer = (char*) apr_palloc (r->pool, r->remaining + 1); size = r->remaining; buffer [size] = '\0'; if (!buffer) return NULL; while ((blen = ap_get_client_block (r, buf, sizeof (buf))) > 0) { if (rpos + blen > size) { rsize = blen - rpos; } else { rsize = blen; } memcpy ((char*) buffer + rpos, buf, rsize); rpos += rsize; } return buffer; } /* ** Extract Map File name from params and load it. ** Returns map object or NULL on error. */ static mapObj* msModuleLoadMap(mapservObj *mapserv, mapserver_dir_config *conf) { int i; /* OK, here's the magic: we take the mapObj from our stored config. * We will use a copy of it created by msCopyMap since MapServer * modifies the object at several places during request processing */ mapObj *map = msNewMapObj (); if(!map) return NULL; msCopyMap (map, conf->map); /* check for any %variable% substitutions here, also do any map_ changes, we do this here so WMS/WFS */ /* services can take advantage of these "vendor specific" extensions */ for(i=0; irequest->NumParams; i++) { /* ** a few CGI variables should be skipped altogether ** ** qstring: there is separate per layer validation for attribute queries and the substitution checks ** below conflict with that so we avoid it here */ if(strncasecmp(mapserv->request->ParamNames[i],"qstring",7) == 0) continue; if(strncasecmp(mapserv->request->ParamNames[i],"map_",4) == 0 || strncasecmp(mapserv->request->ParamNames[i],"map.",4) == 0) { /* check to see if there are any additions to the mapfile */ if(msUpdateMapFromURL(map, mapserv->request->ParamNames[i], mapserv->request->ParamValues[i]) != MS_SUCCESS) { msFreeMap(map); return NULL; } continue; } } msApplySubstitutions(map, mapserv->request->ParamNames, mapserv->request->ParamValues, mapserv->request->NumParams); msApplyDefaultSubstitutions(map); /* check to see if a ogc map context is passed as argument. if there */ /* is one load it */ for(i=0; irequest->NumParams; i++) { if(strcasecmp(mapserv->request->ParamNames[i],"context") == 0) { if(mapserv->request->ParamValues[i] && strlen(mapserv->request->ParamValues[i]) > 0) { if(strncasecmp(mapserv->request->ParamValues[i],"http",4) == 0) { if(msGetConfigOption(map, "CGI_CONTEXT_URL")) msLoadMapContextURL(map, mapserv->request->ParamValues[i], MS_FALSE); } else msLoadMapContext(map, mapserv->request->ParamValues[i], MS_FALSE); } } } /* * RFC-42 HTTP Cookie Forwarding * Here we set the http_cookie_data metadata to handle the * HTTP Cookie Forwarding. The content of this metadata is the cookie * content. In the future, this metadata will probably be replaced * by an object that is part of the mapObject that would contain * information on the application status (such as cookie). */ if( mapserv->request->httpcookiedata != NULL ) { msInsertHashTable( &(map->web.metadata), "http_cookie_data", mapserv->request->httpcookiedata ); } return map; } /*** * The main request handler. **/ static int mapserver_handler (request_rec *r) { /* aquire the apropriate configuration for this directory */ mapserver_dir_config *conf; conf = (mapserver_dir_config*) ap_get_module_config (r->per_dir_config, &mapserver_module); /* decline the request if there's no map configured */ if (!conf || !conf->map) return DECLINED; apr_finfo_t mapstat; if (apr_stat (&mapstat, conf->mapfile_name, APR_FINFO_MTIME, r->pool) == APR_SUCCESS) { if (apr_time_sec (mapstat.mtime) > apr_time_sec (conf->mtime)) { mapObj *newmap = msLoadMap (conf->mapfile_name, NULL); if (newmap) { msFreeMap (conf->map); conf->map = newmap; conf->mtime = mapstat.mtime; } else { ap_log_error (APLOG_MARK, APLOG_WARNING, 0, NULL, "unable to reload map file %s", conf->mapfile_name); } } } else { ap_log_error (APLOG_MARK, APLOG_WARNING, 0, NULL, "%s: unable to stat file %s", __func__, conf->mapfile_name); } /* make a copy of the URI so we can modify it safely */ char *uri = apr_pstrdup (r->pool, r->uri); int len = strlen (uri); int conf_uri_len = strlen (conf->uri); /* If the URI points to a subdirectory we want to decline. */ if (len > conf_uri_len) return DECLINED; int argc = 0; char **ParamNames = NULL; char **ParamValues = NULL; char *post_data = NULL; int szMethod = -1; char *szContentType = NULL; mapservObj *mapserv = NULL; /* Try decoding the query string */ if (r->method_number == M_GET) { argc = mapserver_decode_args (r->pool, (char*) apr_pstrdup (r->pool, r->args), &ParamNames, &ParamValues); szMethod = MS_GET_REQUEST; } else if (r->method_number == M_POST) { szContentType = (char*) apr_table_get (r->headers_in, "Content-Type"); post_data = mapserver_read_post_data (r); szMethod = MS_POST_REQUEST; if (strcmp (szContentType, "application/x-www-form-urlencoded") == 0) { argc = mapserver_decode_args (r->pool, (char*) apr_pstrdup (r->pool, r->args), &ParamNames, &ParamValues); } } else return HTTP_METHOD_NOT_ALLOWED; if (!argc && !post_data) return HTTP_BAD_REQUEST; /* Now we install the IO redirection. */ if (msIO_installApacheRedirect (r) != MS_TRUE) ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s: could not install apache redirect", __func__); mapserv = msAllocMapServObj(); mapserv->request->NumParams = argc; mapserv->request->ParamNames = ParamNames; mapserv->request->ParamValues = ParamValues; mapserv->request->type = (enum MS_REQUEST_TYPE) szMethod; mapserv->request->postrequest = post_data; mapserv->request->contenttype = szContentType; //mapserv->map = msModuleLoadMap(mapserv,conf); mapserv->map = conf->map; if(!mapserv->map) { msCGIWriteError(mapserv); goto end_request; } if(msCGIDispatchRequest(mapserv) != MS_SUCCESS) { msCGIWriteError(mapserv); goto end_request; } end_request: if(mapserv) { msCGIWriteLog(mapserv,MS_FALSE); mapserv->request->ParamNames = NULL; mapserv->request->ParamValues = NULL; mapserv->request->postrequest = NULL; mapserv->request->contenttype = NULL; mapserv->map = NULL; msFreeMapServObj(mapserv); } msResetErrorList(); /* Check if status was set inside MapServer functions. If it was, we * return it's value instead of simply OK. This is to support redirects * from maptemplate.c */ if (r->status == HTTP_MOVED_TEMPORARILY) return r->status; return OK; } /* This function will be called on startup to allow us to register our * handler. We don't do anything else yet... */ static void mapserver_register_hooks (apr_pool_t *p) { ap_hook_handler (mapserver_handler, NULL, NULL, APR_HOOK_MIDDLE); } /* That's the second part of the overall magic. This function will be called * when the configuration reaches the "WMS_Map" parameter. It will be passed * in as argument and should contain the full path and name of the map file. * We try to load it and store the resulting mapObj in the config of the * current directory. If we fail we throw a message... */ static const char* mapserver_set_map (cmd_parms *cmd, void *config, const char *arg) { mapserver_dir_config *conf = (mapserver_dir_config*) config; /* if the mapObj already exists the WMS_Map was given more than once - * may be the user forgot to comment something out... */ if (conf->map) { msWriteError (stderr); return (char*) apr_psprintf (cmd->temp_pool, "An MAP-file has already been registered for " "this URI - not accepting '%s'.", arg ); } /* Simply try loading the argument as map file. */ conf->mapfile_name = apr_pstrdup(cmd->pool, arg); conf->map = msLoadMap ((char*) arg, NULL); /* Ooops - we failed. We report it and fail. So beware: Always do a * configcheck before really restarting your web server! */ if (!conf->map) { msWriteError (stderr); return (char*) apr_psprintf (cmd->temp_pool, "The given MAP-file '%s' could not be loaded", arg); } apr_finfo_t status; if (apr_stat (&status, conf->mapfile_name, APR_FINFO_MTIME, cmd->pool) != APR_SUCCESS) { ap_log_error (APLOG_MARK, APLOG_WARNING, 0, NULL, "%s: unable to stat file %s", __func__, conf->mapfile_name); } conf->mtime = status.mtime; return NULL; } /* This function creates the (default) directory configuration. Well, we have * no defaults to set so we simply alloc the memory... */ static void* mapserver_create_dir_config (apr_pool_t *p, char *dir) { mapserver_dir_config *newconf; newconf = (mapserver_dir_config*) apr_pcalloc (p, sizeof (mapserver_dir_config)); newconf->config_pool = p; newconf->uri = apr_pstrdup (p, dir); newconf->map = NULL; newconf->mapfile_name = NULL; newconf->mtime = apr_time_from_sec (0); if (dir) { int len = strlen (dir); if (len > 1 && dir [len - 1] == '/' ) newconf->uri [len - 1] = '\0'; } return newconf; } /* This structure defines our single config option which takes exactly one * argument. */ static const command_rec mapserver_options[] = { AP_INIT_TAKE1( "Mapfile", mapserver_set_map, NULL, ACCESS_CONF, "WMS_Map " ), {NULL} }; /* The following structure declares everything Apache needs to treat us as * a module. Merging would mean inheriting from the parent directory but that * doesn't make much sense here since we would only inherit the map file... */ /* Dispatch list for API hooks */ module AP_MODULE_DECLARE_DATA mapserver_module = { STANDARD20_MODULE_STUFF, mapserver_create_dir_config, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ mapserver_options, /* table of config file commands */ mapserver_register_hooks /* register hooks */ }; mapserver-7.4.3/cgiutil.c000066400000000000000000000330151357574274700153640ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: cgiRequestObj and CGI parameter parsing. * Author: Steve Lime and the MapServer team. * * Notes: Portions derived from NCSA HTTPd Server's example CGI programs (util.c). * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include #include #include #include "mapserver.h" #include "cgiutil.h" #define LF 10 #define CR 13 int readPostBody( cgiRequestObj *request, char **data ) { size_t data_max, data_len; int chunk_size; msIO_needBinaryStdin(); /* -------------------------------------------------------------------- */ /* If the length is provided, read in one gulp. */ /* -------------------------------------------------------------------- */ if( getenv("CONTENT_LENGTH") != NULL ) { data_max = (size_t) atoi(getenv("CONTENT_LENGTH")); /* Test for suspicious CONTENT_LENGTH (negative value or SIZE_MAX) */ if( data_max >= SIZE_MAX ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("Suspicious Content-Length.\n"); return MS_FAILURE; } *data = (char *) malloc(data_max+1); if( *data == NULL ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("malloc() failed, Content-Length: %u unreasonably large?\n", (unsigned int)data_max ); return MS_FAILURE; } if( (int) msIO_fread(*data, 1, data_max, stdin) < data_max ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("POST body is short\n"); return MS_FAILURE; } (*data)[data_max] = '\0'; return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Otherwise read in chunks to the end. */ /* -------------------------------------------------------------------- */ #define DATA_ALLOC_SIZE 10000 data_max = DATA_ALLOC_SIZE; data_len = 0; *data = (char *) msSmallMalloc(data_max+1); while( (chunk_size = msIO_fread( *data + data_len, 1, data_max-data_len, stdin )) > 0 ) { data_len += chunk_size; if( data_len == data_max ) { /* Realloc buffer, making sure we check for possible size_t overflow */ if ( data_max > SIZE_MAX - (DATA_ALLOC_SIZE+1) ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("Possible size_t overflow, cannot reallocate input buffer, POST body too large?\n" ); return MS_FAILURE; } data_max = data_max + DATA_ALLOC_SIZE; *data = (char *) msSmallRealloc(*data, data_max+1); } } (*data)[data_len] = '\0'; return MS_SUCCESS; } static char* msGetEnv(const char *name, void* thread_context) { return getenv(name); } int loadParams(cgiRequestObj *request, char* (*getenv2)(const char*, void* thread_context), char *raw_post_data, ms_uint32 raw_post_data_length, void* thread_context) { register int x,m=0; char *s, *queryString = NULL, *httpCookie = NULL; int debuglevel; int maxParams = MS_DEFAULT_CGI_PARAMS; if (getenv2==NULL) getenv2 = &msGetEnv; if(getenv2("REQUEST_METHOD", thread_context)==NULL) { msIO_printf("This script can only be used to decode form results and \n"); msIO_printf("should be initiated as a CGI process via a httpd server.\n"); msIO_printf("For other options please try using the --help switch.\n"); return -1; } debuglevel = (int)msGetGlobalDebugLevel(); if(strcmp(getenv2("REQUEST_METHOD", thread_context),"POST") == 0) { /* we've got a post from a form */ char *post_data; int data_len; request->type = MS_POST_REQUEST; s = getenv2("CONTENT_TYPE", thread_context); if (s != NULL) request->contenttype = msStrdup(s); /* we've to set default Content-Type which is * application/octet-stream according to * W3 RFC 2626 section 7.2.1 */ else request->contenttype = msStrdup("application/octet-stream"); if (raw_post_data) { post_data = msStrdup(raw_post_data); data_len = raw_post_data_length; } else { if(MS_SUCCESS != readPostBody( request, &post_data )) return -1; data_len = strlen(post_data); } /* if the content_type is application/x-www-form-urlencoded, we have to parse it like the QUERY_STRING variable */ if(strncmp(request->contenttype, "application/x-www-form-urlencoded", strlen("application/x-www-form-urlencoded")) == 0) { while( data_len > 0 && isspace(post_data[data_len-1]) ) post_data[--data_len] = '\0'; while( post_data[0] ) { if(m >= maxParams) { maxParams *= 2; request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams); request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams); } request->ParamValues[m] = makeword(post_data,'&'); plustospace(request->ParamValues[m]); unescape_url(request->ParamValues[m]); request->ParamNames[m] = makeword(request->ParamValues[m],'='); m++; } free( post_data ); } else request->postrequest = post_data; /* check the QUERY_STRING even in the post request since it can contain information. Eg a wfs request with */ s = getenv2("QUERY_STRING", thread_context); if(s) { if (debuglevel >= MS_DEBUGLEVEL_DEBUG) msDebug("loadParams() QUERY_STRING: %s\n", s); queryString = msStrdup(s); for(x=0; queryString[0] != '\0'; x++) { if(m >= maxParams) { maxParams *= 2; request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams); request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams); } request->ParamValues[m] = makeword(queryString,'&'); plustospace(request->ParamValues[m]); unescape_url(request->ParamValues[m]); request->ParamNames[m] = makeword(request->ParamValues[m],'='); m++; } } } else { if(strcmp(getenv2("REQUEST_METHOD", thread_context),"GET") == 0) { /* we've got a get request */ request->type = MS_GET_REQUEST; s = getenv2("QUERY_STRING", thread_context); if(s == NULL) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("No query information to decode. QUERY_STRING not set.\n"); return -1; } if (debuglevel >= MS_DEBUGLEVEL_DEBUG) msDebug("loadParams() QUERY_STRING: %s\n", s); if(strlen(s)==0) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("No query information to decode. QUERY_STRING is set, but empty.\n"); return -1; } /* don't modify the string returned by getenv2 */ queryString = msStrdup(s); for(x=0; queryString[0] != '\0'; x++) { if(m >= maxParams) { maxParams *= 2; request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams); request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams); } request->ParamValues[m] = makeword(queryString,'&'); plustospace(request->ParamValues[m]); unescape_url(request->ParamValues[m]); request->ParamNames[m] = makeword(request->ParamValues[m],'='); m++; } } else { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("This script should be referenced with a METHOD of GET or METHOD of POST.\n"); return -1; } } /* check for any available cookies */ s = getenv2("HTTP_COOKIE", thread_context); if(s != NULL) { httpCookie = msStrdup(s); request->httpcookiedata = msStrdup(s); for(x=0; httpCookie[0] != '\0'; x++) { if(m >= maxParams) { maxParams *= 2; request->ParamNames = (char **) msSmallRealloc(request->ParamNames,sizeof(char *) * maxParams); request->ParamValues = (char **) msSmallRealloc(request->ParamValues,sizeof(char *) * maxParams); } request->ParamValues[m] = makeword(httpCookie,';'); plustospace(request->ParamValues[m]); unescape_url(request->ParamValues[m]); request->ParamNames[m] = makeword_skip(request->ParamValues[m],'=',' '); m++; } } if (queryString) free(queryString); if (httpCookie) free(httpCookie); return(m); } void getword(char *word, char *line, char stop) { int x = 0,y; for(x=0; ((line[x]) && (line[x] != stop)); x++) word[x] = line[x]; word[x] = '\0'; if(line[x]) ++x; y=0; while((line[y++] = line[x++])); } char *makeword_skip(char *line, char stop, char skip) { int x = 0,y,offset=0; char *word = (char *) msSmallMalloc(sizeof(char) * (strlen(line) + 1)); for(x=0; ((line[x]) && (line[x] == skip)); x++); offset = x; for(x=offset; ((line[x]) && (line[x] != stop)); x++) word[x-offset] = line[x]; word[x-offset] = '\0'; if(line[x]) ++x; y=0; while((line[y++] = line[x++])); return word; } char *makeword(char *line, char stop) { int x = 0,y; char *word = (char *) msSmallMalloc(sizeof(char) * (strlen(line) + 1)); for(x=0; ((line[x]) && (line[x] != stop)); x++) word[x] = line[x]; word[x] = '\0'; if(line[x]) ++x; y=0; while((line[y++] = line[x++])); return word; } char *fmakeword(FILE *f, char stop, int *cl) { int wsize; char *word; int ll; wsize = 102400; ll=0; word = (char *) msSmallMalloc(sizeof(char) * (wsize + 1)); while(1) { word[ll] = (char)fgetc(f); if(ll==wsize) { word[ll+1] = '\0'; wsize+=102400; word = (char *)msSmallRealloc(word,sizeof(char)*(wsize+1)); } --(*cl); if((word[ll] == stop) || (feof(f)) || (!(*cl))) { if(word[ll] != stop) ll++; word[ll] = '\0'; word = (char *) msSmallRealloc(word, ll+1); return word; } ++ll; } } char x2c(char *what) { register char digit; digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); digit *= 16; digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); return(digit); } void unescape_url(char *url) { register int x,y; for(x=0,y=0; url[y]; ++x,++y) { if((url[x] = url[y]) == '%') { url[x] = x2c(&url[y+1]); y+=2; } } url[x] = '\0'; } void plustospace(char *str) { register int x; for(x=0; str[x]; x++) if(str[x] == '+') str[x] = ' '; } int rind(char *s, char c) { register int x; for(x=strlen(s) - 1; x != -1; x--) if(s[x] == c) return x; return -1; } void send_fd(FILE *f, FILE *fd) { int c; while (1) { c = fgetc(f); if(c == EOF) return; fputc((char)c,fd); } } int ind(char *s, char c) { register int x; for(x=0; s[x]; x++) if(s[x] == c) return x; return -1; } /* ** patched version according to CERT advisory... */ void escape_shell_cmd(char *cmd) { register int x,y,l; l=strlen(cmd); for(x=0; cmd[x]; x++) { if(ind("&;`'\"|*?~<>^()[]{}$\\\n",cmd[x]) != -1) { for(y=l+1; y>x; y--) cmd[y] = cmd[y-1]; l++; /* length has been increased */ cmd[x] = '\\'; x++; /* skip the character */ } } } /* ** Allocate a new request holder structure */ cgiRequestObj *msAllocCgiObj() { cgiRequestObj *request = (cgiRequestObj *)malloc(sizeof(cgiRequestObj)); if(!request) return NULL; request->ParamNames = (char **) msSmallMalloc(MS_DEFAULT_CGI_PARAMS*sizeof(char*)); request->ParamValues = (char **) msSmallMalloc(MS_DEFAULT_CGI_PARAMS*sizeof(char*)); request->NumParams = 0; request->type = MS_GET_REQUEST; request->contenttype = NULL; request->postrequest = NULL; request->httpcookiedata = NULL; return request; } void msFreeCgiObj(cgiRequestObj *request) { msFreeCharArray(request->ParamNames, request->NumParams); msFreeCharArray(request->ParamValues, request->NumParams); request->ParamNames = NULL; request->ParamValues = NULL; request->NumParams = 0; request->type = -1; msFree(request->contenttype); msFree(request->postrequest); msFree(request->httpcookiedata); request->contenttype = NULL; request->postrequest = NULL; request->httpcookiedata = NULL; msFree(request); } mapserver-7.4.3/cgiutil.h000066400000000000000000000061711357574274700153740ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: cgiRequestObj and CGI parsing utility related declarations. * Author: Steve Lime and the MapServer team. * * Notes: Portions derived from NCSA HTTPd Server's example CGI programs (util.c). * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef CGIUTIL_H #define CGIUTIL_H #ifdef __cplusplus extern "C" { #endif #if defined(_WIN32) && !defined(__CYGWIN__) # define MS_DLL_EXPORT __declspec(dllexport) #else #define MS_DLL_EXPORT #endif /* ** Misc. defines */ #define MS_DEFAULT_CGI_PARAMS 100 enum MS_REQUEST_TYPE {MS_GET_REQUEST, MS_POST_REQUEST}; /* structure to hold request information */ typedef struct { #ifndef SWIG char **ParamNames; char **ParamValues; #endif #ifdef SWIG %immutable; #endif int NumParams; #ifdef SWIG %mutable; #endif enum MS_REQUEST_TYPE type; char *contenttype; char *postrequest; char *httpcookiedata; } cgiRequestObj; /* ** Function prototypes */ #ifndef SWIG MS_DLL_EXPORT int loadParams(cgiRequestObj *request, char* (*getenv2)(const char*, void* thread_context), char *raw_post_data, ms_uint32 raw_post_data_length, void* thread_context); MS_DLL_EXPORT void getword(char *, char *, char); MS_DLL_EXPORT char *makeword_skip(char *, char, char); MS_DLL_EXPORT char *makeword(char *, char); MS_DLL_EXPORT char *fmakeword(FILE *, char, int *); MS_DLL_EXPORT char x2c(char *); MS_DLL_EXPORT void unescape_url(char *); MS_DLL_EXPORT void plustospace(char *); MS_DLL_EXPORT int rind(char *, char); MS_DLL_EXPORT void send_fd(FILE *, FILE *); MS_DLL_EXPORT int ind(char *, char); MS_DLL_EXPORT void escape_shell_cmd(char *); MS_DLL_EXPORT cgiRequestObj *msAllocCgiObj(void); MS_DLL_EXPORT void msFreeCgiObj(cgiRequestObj *request); #endif /*SWIG*/ #ifdef __cplusplus } #endif #endif /* CGIUTIL_H */ mapserver-7.4.3/ci/000077500000000000000000000000001357574274700141515ustar00rootroot00000000000000mapserver-7.4.3/ci/travis/000077500000000000000000000000001357574274700154615ustar00rootroot00000000000000mapserver-7.4.3/ci/travis/after_success.sh000077500000000000000000000014741357574274700206570ustar00rootroot00000000000000#!/bin/sh set -eu if [ "$BUILD_NAME" != "PHP_7.2_WITH_ASAN" ]; then # Only run coverage when it is safe to do so (not on pull requests), and only on master branch echo "$TRAVIS_SECURE_ENV_VARS" echo "$TRAVIS_BRANCH" sh -c 'if test "$TRAVIS_SECURE_ENV_VARS" = "true" -a "$TRAVIS_BRANCH" = "master"; then echo "run coverage"; ./run_code_coverage_upload.sh; fi' coveralls --exclude renderers --exclude mapscript --exclude apache --exclude build/mapscript/mapscriptJAVA_wrap.c --exclude build/mapscript/mapscriptPYTHON_wrap.c --exclude shp2img.c --exclude legend.c --exclude scalebar.c --exclude msencrypt.c --exclude sortshp.c --exclude shptreevis.c --exclude shptree.c --exclude testexpr.c --exclude sym2img.c --exclude testcopy.c --exclude shptreetst.c --exclude tile4ms.c --extension .c --extension .cpp fi mapserver-7.4.3/ci/travis/before_install.sh000077500000000000000000000026001357574274700210060ustar00rootroot00000000000000#!/bin/sh set -eu sudo mv /etc/apt/sources.list.d/pgdg* /tmp dpkg -l | grep postgresql dpkg -l | grep postgis sudo apt-get remove postgresql* sudo add-apt-repository -y ppa:ubuntugis/ppa sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-testing sudo apt-get update sudo apt-get install --allow-unauthenticated protobuf-c-compiler libprotobuf-c0-dev bison flex python-lxml libfribidi-dev cmake librsvg2-dev colordiff libpq-dev libpng12-dev libjpeg-dev libgif-dev libgeos-dev libgd2-xpm-dev libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev libgdal1-dev libproj-dev libxml2-dev python-dev libexempi-dev lcov lftp postgis libharfbuzz-dev gdal-bin ccache sudo apt-get install --allow-unauthenticated libmono-system-drawing4.0-cil mono-mcs sudo apt-get install --allow-unauthenticated php5-dev || sudo apt-get install --allow-unauthenticated php7-dev sudo apt-get install --allow-unauthenticated libperl-dev sudo pip install git+git://github.com/tbonfort/cpp-coveralls.git@extensions # install swig 3.0.12 (defaults to 2.0.11 on trusty) wget http://prdownloads.sourceforge.net/swig/swig-3.0.12.tar.gz export CC="ccache gcc" export CXX="ccache g++" tar xf swig-3.0.12.tar.gz cd swig-3.0.12 && ./configure --prefix=/usr && make -j2 && sudo make install swig -version cd .. cd msautotest ./create_postgis_test_data.sh python -m SimpleHTTPServer &> /dev/null & cd .. touch maplexer.l touch mapparser.y mapserver-7.4.3/ci/travis/script.sh000077500000000000000000000013621357574274700173260ustar00rootroot00000000000000#!/bin/sh set -eu if [ "$BUILD_NAME" = "PHP_7.2_WITH_ASAN" ]; then export CC="ccache clang" export CXX="ccache clang++" # -DNDEBUG to avoid issues with cairo cleanup make cmakebuild MFLAGS="-j2" CMAKE_C_FLAGS="-g -fsanitize=address -DNDEBUG" CMAKE_CXX_FLAGS="-g -fsanitize=address -DNDEBUG" EXTRA_CMAKEFLAGS="-DCMAKE_BUILD_TYPE=None -DCMAKE_EXE_LINKER_FLAGS=-fsanitize=address" export AUTOTEST_OPTS="-q -strict -run_under_asan" # Only run tests that only involve mapserv/shp2img binaries. mspython, etc would require LD_PREOLOAD'ing the asan shared object make -j4 asan_compatible_tests else export CC="ccache gcc" export CXX="ccache g++" make cmakebuild MFLAGS="-j2" make mspython-wheel make -j4 test fi mapserver-7.4.3/classobject.c000066400000000000000000000150231357574274700162170ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions for operating on a classObj that don't belong in a * more specific file such as mapfile.c. * Adapted from mapobject.c. * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * Copyright (c) 2004, Sean Gillies * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #ifdef USE_GDAL # include "gdal.h" # include "cpl_conv.h" #endif /* ** Add a label to a classObj (order doesn't matter for labels like it does with styles) */ int msAddLabelToClass(classObj *class, labelObj *label) { if (!label) { msSetError(MS_CHILDERR, "Can't add a NULL label.", "msAddLabelToClass()"); return MS_FAILURE; } if (msGrowClassLabels(class) == NULL) return MS_FAILURE; /* msGrowClassLabels will alloc the label, free it in this case */ free(class->labels[class->numlabels]); class->labels[class->numlabels] = label; MS_REFCNT_INCR(label); class->numlabels++; return MS_SUCCESS; } /* ** Remove a label from a classObj. */ labelObj *msRemoveLabelFromClass(classObj *class, int nLabelIndex) { int i; labelObj *label; if (nLabelIndex < 0 || nLabelIndex >= class->numlabels) { msSetError(MS_CHILDERR, "Cannot remove label, invalid index %d", "msRemoveLabelFromClass()", nLabelIndex); return NULL; } else { label=class->labels[nLabelIndex]; for (i=nLabelIndex; inumlabels-1; i++) { class->labels[i]=class->labels[i+1]; } class->labels[class->numlabels-1]=NULL; class->numlabels--; MS_REFCNT_DECR(label); return label; } } /** * Move the style up inside the array of styles. */ int msMoveStyleUp(classObj *class, int nStyleIndex) { styleObj *psTmpStyle = NULL; if (class && nStyleIndex < class->numstyles && nStyleIndex >0) { psTmpStyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(psTmpStyle); msCopyStyle(psTmpStyle, class->styles[nStyleIndex]); msCopyStyle(class->styles[nStyleIndex], class->styles[nStyleIndex-1]); msCopyStyle(class->styles[nStyleIndex-1], psTmpStyle); return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveStyleUp()", nStyleIndex); return (MS_FAILURE); } /** * Move the style down inside the array of styles. */ int msMoveStyleDown(classObj *class, int nStyleIndex) { styleObj *psTmpStyle = NULL; if (class && nStyleIndex < class->numstyles-1 && nStyleIndex >=0) { psTmpStyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(psTmpStyle); msCopyStyle(psTmpStyle, class->styles[nStyleIndex]); msCopyStyle(class->styles[nStyleIndex], class->styles[nStyleIndex+1]); msCopyStyle(class->styles[nStyleIndex+1], psTmpStyle); return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveStyleDown()", nStyleIndex); return (MS_FAILURE); } /* Moved here from mapscript.i * * Returns the index at which the style was inserted * */ int msInsertStyle(classObj *class, styleObj *style, int nStyleIndex) { int i; if (!style) { msSetError(MS_CHILDERR, "Can't insert a NULL Style", "msInsertStyle()"); return -1; } /* Ensure there is room for a new style */ if (msGrowClassStyles(class) == NULL) { return -1; } /* Catch attempt to insert past end of styles array */ else if (nStyleIndex >= class->numstyles) { msSetError(MS_CHILDERR, "Cannot insert style beyond index %d", "insertStyle()", class->numstyles-1); return -1; } else if (nStyleIndex < 0) { /* Insert at the end by default */ class->styles[class->numstyles]=style; MS_REFCNT_INCR(style); class->numstyles++; return class->numstyles-1; } else if (nStyleIndex >= 0 && nStyleIndex < class->numstyles) { /* Move styles existing at the specified nStyleIndex or greater */ /* to a higher nStyleIndex */ for (i=class->numstyles-1; i>=nStyleIndex; i--) { class->styles[i+1] = class->styles[i]; } class->styles[nStyleIndex]=style; MS_REFCNT_INCR(style); class->numstyles++; return nStyleIndex; } else { msSetError(MS_CHILDERR, "Invalid nStyleIndex", "insertStyle()"); return -1; } } styleObj *msRemoveStyle(classObj *class, int nStyleIndex) { int i; styleObj *style; if (nStyleIndex < 0 || nStyleIndex >= class->numstyles) { msSetError(MS_CHILDERR, "Cannot remove style, invalid nStyleIndex %d", "removeStyle()", nStyleIndex); return NULL; } else { style=class->styles[nStyleIndex]; for (i=nStyleIndex; inumstyles-1; i++) { class->styles[i]=class->styles[i+1]; } class->styles[class->numstyles-1]=NULL; class->numstyles--; MS_REFCNT_DECR(style); return style; } } /** * Delete the style identified by the index and shift * styles that follows the deleted style. */ int msDeleteStyle(classObj *class, int nStyleIndex) { int i = 0; if (class && nStyleIndex < class->numstyles && nStyleIndex >=0) { if (freeStyle(class->styles[nStyleIndex]) == MS_SUCCESS) msFree(class->styles[nStyleIndex]); for (i=nStyleIndex; i< class->numstyles-1; i++) { class->styles[i] = class->styles[i+1]; } class->styles[class->numstyles-1] = NULL; class->numstyles--; return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msDeleteStyle()", nStyleIndex); return (MS_FAILURE); } mapserver-7.4.3/cmake/000077500000000000000000000000001357574274700146365ustar00rootroot00000000000000mapserver-7.4.3/cmake/FindAPACHE.cmake000066400000000000000000000016701357574274700173660ustar00rootroot00000000000000# # APACHE_FOUND - System has APACHE # APACHE_INCLUDE_DIR - The APACHE include directory # # APACHE_LOCATION # setting this enables search for apache libraries / headers in this location # # Include directories # find_path(APACHE_INCLUDE_DIR NAMES httpd.h PATH_SUFFIXES httpd apache apache2 ) find_program(APXS_BIN NAMES apxs apxs2 PATH_SUFFIXES httpd apache apache2 ) find_program(HTTPD_EXECUTABLE NAMES httpd PATHS /usr/sbin PATH_SUFFIXES httpd apache apache2 ) if(APXS_BIN) EXECUTE_PROCESS(COMMAND ${APXS_BIN} -q LIBEXECDIR OUTPUT_VARIABLE APACHE_MODULE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) endif(APXS_BIN) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set APACHE_FOUND to TRUE if # all listed variables are TRUE find_package_handle_standard_args(APACHE DEFAULT_MSG APACHE_INCLUDE_DIR ) mark_as_advanced(APACHE_INCLUDE_DIR) mapserver-7.4.3/cmake/FindAPR.cmake000066400000000000000000000046031357574274700170660ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # - Find Apache Portable Runtime # Find the APR includes and libraries # This module defines # APR_INCLUDE_DIR and APRUTIL_INCLUDE_DIR, where to find apr.h, etc. # APR_LIBRARIES and APRUTIL_LIBRARIES, the libraries needed to use APR. # APR_FOUND and APRUTIL_FOUND, If false, do not try to use APR. # also defined, but not for general use are # APR_LIBRARY and APRUTIL_LIBRARY, where to find the APR library. # APR first. FIND_PROGRAM(APR_CONFIG_BIN NAMES apr-config apr-1-config ) if(APR_CONFIG_BIN) execute_process( COMMAND ${APR_CONFIG_BIN} --includedir OUTPUT_VARIABLE HINT_APR_INCLUDE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND ${APR_CONFIG_BIN} --cppflags OUTPUT_VARIABLE APR_CPPFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ) endif(APR_CONFIG_BIN) FIND_PATH(APR_INCLUDE_DIR NAMES apr.h HINTS ${HINT_APR_INCLUDE_DIR} PATH_SUFFIXES apr-1 apr-1.0 apr ) FIND_LIBRARY(APR_LIBRARY NAMES apr-1 apr PATH_SUFFIXES apr-1 apr-1.0 apr ) set(APR_INCLUDE_DIRS ${APR_INCLUDE_DIR}) set(APR_LIBRARIES ${APR_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(APR DEFAULT_MSG APR_LIBRARY APR_INCLUDE_DIR) mark_as_advanced(APR_LIBRARY APR_INCLUDE_DIR) # Next, APRUTIL. FIND_PATH(APU_INCLUDE_DIR NAMES apu.h PATH_SUFFIXES apr-1 apr-1.0 apr ) FIND_LIBRARY(APU_LIBRARY NAMES aprutil-1 aprutil PATH_SUFFIXES apr-1 apr-1.0 apr ) set(APU_INCLUDE_DIRS ${APU_INCLUDE_DIR}) set(APU_LIBRARIES ${APU_LIBRARY}) find_package_handle_standard_args(APU DEFAULT_MSG APU_LIBRARY APU_INCLUDE_DIR) mark_as_advanced(APU_LIBRARY APU_INCLUDE_DIR) mapserver-7.4.3/cmake/FindCairo.cmake000066400000000000000000000063221357574274700175010ustar00rootroot00000000000000# - Try to find Cairo # Once done, this will define # # CAIRO_FOUND - system has Cairo # CAIRO_INCLUDE_DIR - the Cairo include directories # CAIRO_LIBRARY - link these to use Cairo # # Copyright (C) 2012 Raphael Kubo da Costa # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS # IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. FIND_PACKAGE(PkgConfig) PKG_CHECK_MODULES(PC_CAIRO cairo) # FIXME: After we require CMake 2.8.2 we can pass QUIET to this call. FIND_PATH(CAIRO_INCLUDE_DIR NAMES cairo.h HINTS ${PC_CAIRO_INCLUDEDIR} ${PC_CAIRO_INCLUDE_DIRS} PATH_SUFFIXES cairo ) IF(APPLE) #On Mountain Lion we need this for the XQuartz supplied version of cairo PKG_CHECK_MODULES(PC_FONTCONFIG fontconfig) # FIXME: After we require CMake 2.8.2 we can pass QUIET to this call. FIND_PATH(FC_INCLUDE_DIR NAMES fontconfig/fontconfig.h HINTS ${PC_FONTCONFIG_INCLUDEDIR} ) ENDIF(APPLE) FIND_LIBRARY(CAIRO_LIBRARY NAMES cairo HINTS ${PC_CAIRO_LIBDIR} ${PC_CAIRO_LIBRARY_DIRS} ) IF (CAIRO_INCLUDE_DIR) IF (EXISTS "${CAIRO_INCLUDE_DIR}/cairo-version.h") FILE(READ "${CAIRO_INCLUDE_DIR}/cairo-version.h" CAIRO_VERSION_CONTENT) STRING(REGEX MATCH "#define +CAIRO_VERSION_MAJOR +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}") SET(CAIRO_VERSION_MAJOR "${CMAKE_MATCH_1}") STRING(REGEX MATCH "#define +CAIRO_VERSION_MINOR +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}") SET(CAIRO_VERSION_MINOR "${CMAKE_MATCH_1}") STRING(REGEX MATCH "#define +CAIRO_VERSION_MICRO +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}") SET(CAIRO_VERSION_MICRO "${CMAKE_MATCH_1}") SET(CAIRO_VERSION "${CAIRO_VERSION_MAJOR}.${CAIRO_VERSION_MINOR}.${CAIRO_VERSION_MICRO}") ENDIF () ENDIF () set(CAIRO_INCLUDE_DIRS ${CAIRO_INCLUDE_DIR} ${FC_INCLUDE_DIR}) set(CAIRO_LIBRARIES ${CAIRO_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(CAIRO DEFAULT_MSG CAIRO_LIBRARY CAIRO_INCLUDE_DIR) mark_as_advanced(CAIRO_LIBRARY CAIRO_INCLUDE_DIR) mapserver-7.4.3/cmake/FindExempi.cmake000066400000000000000000000007241357574274700176730ustar00rootroot00000000000000# Look for the header file. find_path(LIBEXEMPI_INCLUDE_DIR NAMES xmp.h PATH_SUFFIXES exempi-2.0 exempi-2.0/exempi exempi ) find_library(LIBEXEMPI_LIBRARY NAMES exempi) set(LIBEXEMPI_LIBRARIES ${LIBEXEMPI_LIBRARY}) set(LIBEXEMPI_INCLUDE_DIRS ${LIBEXEMPI_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LIBEXEMPI DEFAULT_MSG LIBEXEMPI_LIBRARY LIBEXEMPI_INCLUDE_DIR) mark_as_advanced(LIBEXEMPI_INCLUDE_DIR LIBEXEMPI_LIBRARY) mapserver-7.4.3/cmake/FindFCGI.cmake000066400000000000000000000006101357574274700171460ustar00rootroot00000000000000# Look for the header file. find_path(FCGI_INCLUDE_DIR NAMES fastcgi.h) # Look for the library. find_library(FCGI_LIBRARY NAMES fcgi libfcgi) set(FCGI_INCLUDE_DIRS ${FCGI_INCLUDE_DIR}) set(FCGI_LIBRARIES ${FCGI_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(FCGI DEFAULT_MSG FCGI_LIBRARY FCGI_INCLUDE_DIR) mark_as_advanced(FCGI_LIBRARY FCGI_INCLUDE_DIR) mapserver-7.4.3/cmake/FindFreetype.cmake000066400000000000000000000066421357574274700202340ustar00rootroot00000000000000# - Locate FreeType library # This module defines # FREETYPE_LIBRARIES, the library to link against # FREETYPE_FOUND, if false, do not try to link to FREETYPE # FREETYPE_INCLUDE_DIR, where to find headers. # This is the concatenation of the paths: # FREETYPE_INCLUDE_DIR_ft2build # FREETYPE_INCLUDE_DIR_freetype2 # # $FREETYPE_DIR is an environment variable that would # correspond to the ./configure --prefix=$FREETYPE_DIR # used in building FREETYPE. #============================================================================= # Copyright 2007-2009 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distributed this file outside of CMake, substitute the full # License text for the above reference.) # Created by Eric Wing. # Modifications by Alexander Neundorf. # This file has been renamed to "FindFreetype.cmake" instead of the correct # "FindFreeType.cmake" in order to be compatible with the one from KDE4, Alex. # Ugh, FreeType seems to use some #include trickery which # makes this harder than it should be. It looks like they # put ft2build.h in a common/easier-to-find location which # then contains a #include to a more specific header in a # more specific location (#include ). # Then from there, they need to set a bunch of #define's # so you can do something like: # #include FT_FREETYPE_H # Unfortunately, using CMake's mechanisms like INCLUDE_DIRECTORIES() # wants explicit full paths and this trickery doesn't work too well. # I'm going to attempt to cut out the middleman and hope # everything still works. FIND_PATH(FREETYPE_INCLUDE_DIR_ft2build ft2build.h HINTS $ENV{FREETYPE_DIR} PATH_SUFFIXES include include/freetype2 PATHS /usr/local/X11R6/include /usr/local/X11/include /usr/X11/include /sw/include /opt/local/include /usr/freeware/include ) FIND_PATH(FREETYPE_INCLUDE_DIR_freetype2 freetype/config/ftheader.h config/ftheader.h HINTS $ENV{FREETYPE_DIR}/include/freetype2 PATHS /usr/local/X11R6/include /usr/local/X11/include /usr/X11/include /sw/include /opt/local/include /usr/freeware/include PATH_SUFFIXES freetype freetype2 ) set(FREETYPE_NAMES ${FREETYPE_NAMES} freetype libfreetype freetype219 freetype239 freetype241MT_D freetype2411) FIND_LIBRARY(FREETYPE_LIBRARY NAMES ${FREETYPE_NAMES} HINTS $ENV{FREETYPE_DIR} PATH_SUFFIXES lib64 lib x86_64-linux-gnu i386-linux-gnu PATHS /usr/local/X11R6 /usr/local/X11 /usr/X11 /sw /usr/freeware ) # set the user variables IF(FREETYPE_INCLUDE_DIR_ft2build AND FREETYPE_INCLUDE_DIR_freetype2) SET(FREETYPE_INCLUDE_DIR "${FREETYPE_INCLUDE_DIR_ft2build};${FREETYPE_INCLUDE_DIR_freetype2}") ENDIF(FREETYPE_INCLUDE_DIR_ft2build AND FREETYPE_INCLUDE_DIR_freetype2) SET(FREETYPE_LIBRARIES "${FREETYPE_LIBRARY}") # handle the QUIETLY and REQUIRED arguments and set FREETYPE_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Freetype DEFAULT_MSG FREETYPE_LIBRARY FREETYPE_INCLUDE_DIR) MARK_AS_ADVANCED(FREETYPE_LIBRARY FREETYPE_INCLUDE_DIR_freetype2 FREETYPE_INCLUDE_DIR_ft2build) mapserver-7.4.3/cmake/FindFriBiDi.cmake000066400000000000000000000015271357574274700177160ustar00rootroot00000000000000# - Find Fribidi # Find the Fribidi includes and libraries # # Following variables are provided: # FRIBIDI_FOUND # True if Fribidi has been found # FRIBIDI_INCLUDE_DIR # The include directories of Fribidi # FRIBIDI_LIBRARY # Fribidi library list find_package(PkgConfig) pkg_check_modules(PC_FRIBIDI QUIET fribidi>=0.19.0) find_path(FRIBIDI_INCLUDE_DIR NAMES fribidi.h HINTS ${PC_FRIBIDI_INCLUDE_DIR} ${PC_FRIBIDI_INCLUDE_DIRS} PATH_SUFFIXES fribidi ) find_library(FRIBIDI_LIBRARY NAME fribidi HINTS ${PC_FRIBIDI_LIBDIR} ${PC_FRIBIDI_LIBRARY_DIRS} ) set(FRIBIDI_INCLUDE_DIRS ${FRIBIDI_INCLUDE_DIR}) set(FRIBIDI_LIBRARIES ${FRIBIDI_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(FRIBIDI DEFAULT_MSG FRIBIDI_LIBRARY FRIBIDI_INCLUDE_DIR) mark_as_advanced(FRIBIDI_LIBRARY FRIBIDI_INCLUDE_DIR) mapserver-7.4.3/cmake/FindGD.cmake000066400000000000000000000057261357574274700167450ustar00rootroot00000000000000# - Find GD # Find the native GD includes and library # This module defines # GD_INCLUDE_DIR, where to find gd.h, etc. # GD_LIBRARIES, the libraries needed to use GD. # GD_FOUND, If false, do not try to use GD. # also defined, but not for general use are # GD_LIBRARY, where to find the GD library. # GD_SUPPORTS_PNG, GD_SUPPORTS_JPEG, GD_SUPPORTS_GIF, test # support for image formats in GD. FIND_PATH(GD_INCLUDE_DIR gd.h /usr/local/include /usr/include ) if(WIN32 AND NOT CYGWIN) SET(GD_NAMES ${GD_NAMES} bgd) else(WIN32) SET(GD_NAMES ${GD_NAMES} gd) endif(WIN32 AND NOT CYGWIN) FIND_LIBRARY(GD_LIBRARY NAMES ${GD_NAMES} PATHS /usr/lib64 /usr/lib /usr/local/lib ) IF (GD_LIBRARY AND GD_INCLUDE_DIR) SET(GD_LIBRARIES ${GD_LIBRARY}) SET(GD_FOUND "YES") ELSE (GD_LIBRARY AND GD_INCLUDE_DIR) SET(GD_FOUND "NO") ENDIF (GD_LIBRARY AND GD_INCLUDE_DIR) IF (GD_FOUND) IF (WIN32 AND NOT CYGWIN) SET(GD_SUPPORTS_PNG ON) SET(GD_SUPPORTS_JPEG ON) SET(GD_SUPPORTS_GIF ON) SET(GD_SUPPORTS_FREETYPE ON) get_filename_component(GD_LIBRARY_DIR ${GD_LIBRARY} PATH) ELSE (WIN32 AND NOT CYGWIN) INCLUDE(CheckLibraryExists) GET_FILENAME_COMPONENT(GD_LIB_PATH ${GD_LIBRARY} PATH) GET_FILENAME_COMPONENT(GD_LIB ${GD_LIBRARY} NAME) CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImagePng" "${GD_LIB_PATH}" GD_SUPPORTS_PNG) CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageJpeg" "${GD_LIB_PATH}" GD_SUPPORTS_JPEG) CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageGif" "${GD_LIB_PATH}" GD_SUPPORTS_GIF) CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdFontCacheSetup" "${GD_LIB_PATH}" GD_SUPPORTS_FREETYPE) # Trim the list of include directories SET(GDINCTRIM) FOREACH(GD_DIR ${GD_INCLUDE_DIR}) SET(GD_TMP_FOUND OFF) FOREACH(GD_TRIMMED ${GDINCTRIM}) IF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}") SET(GD_TMP_FOUND ON) ENDIF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}") ENDFOREACH(GD_TRIMMED ${GDINCTRIM}) IF (NOT GD_TMP_FOUND) SET(GDINCTRIM "${GDINCTRIM}" "${GD_DIR}") ENDIF (NOT GD_TMP_FOUND) ENDFOREACH(GD_DIR ${GD_INCLUDE_DIR}) SET(GD_INCLUDE_DIR ${GDINCTRIM}) SET(GD_LIBRARY_DIR) # Generate trimmed list of library directories and list of libraries FOREACH(GD_LIB ${GD_LIBRARIES}) GET_FILENAME_COMPONENT(GD_NEXTLIBDIR ${GD_LIB} PATH) SET(GD_TMP_FOUND OFF) FOREACH(GD_LIBDIR ${GD_LIBRARY_DIR}) IF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}") SET(GD_TMP_FOUND ON) ENDIF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}") ENDFOREACH(GD_LIBDIR ${GD_LIBRARIES}) IF (NOT GD_TMP_FOUND) SET(GD_LIBRARY_DIR "${GD_LIBRARY_DIR}" "${GD_NEXTLIBDIR}") ENDIF (NOT GD_TMP_FOUND) ENDFOREACH(GD_LIB ${GD_LIBRARIES}) ENDIF (WIN32 AND NOT CYGWIN) ENDIF (GD_FOUND) IF (!GD_FOUND) IF (GD_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find GD library") ENDIF (GD_FIND_REQUIRED) ENDIF (!GD_FOUND) MARK_AS_ADVANCED( GD_LIBRARY GD_LIBRARIES GD_INCLUDE_DIR GD_LIBRARY_DIR GD_SUPPORTS_PNG GD_SUPPORTS_JPEG GD_SUPPORTS_GIF GD_SUPPORTS_FREETYPE ) mapserver-7.4.3/cmake/FindGDAL.cmake000066400000000000000000000062621357574274700171560ustar00rootroot00000000000000# Locate gdal # # This module accepts the following environment variables: # # GDAL_DIR or GDAL_ROOT - Specify the location of GDAL # # This module defines the following CMake variables: # # GDAL_FOUND - True if libgdal is found # GDAL_LIBRARY - A variable pointing to the GDAL library # GDAL_INCLUDE_DIR - Where to find the headers #============================================================================= # Copyright 2007-2009 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # # $GDALDIR is an environment variable that would # correspond to the ./configure --prefix=$GDAL_DIR # used in building gdal. # # Created by Eric Wing. I'm not a gdal user, but OpenSceneGraph uses it # for osgTerrain so I whipped this module together for completeness. # I actually don't know the conventions or where files are typically # placed in distros. # Any real gdal users are encouraged to correct this (but please don't # break the OS X framework stuff when doing so which is what usually seems # to happen). # This makes the presumption that you are include gdal.h like # #include "gdal.h" find_path(GDAL_INCLUDE_DIR gdal.h HINTS ENV GDAL_DIR ENV GDAL_ROOT PATH_SUFFIXES gdal GDAL gdal1 PATHS /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt ) if(UNIX) # Use gdal-config to obtain the library version (this should hopefully # allow us to -lgdal1.x.y where x.y are correct version) # For some reason, libgdal development packages do not contain # libgdal.so... find_program(GDAL_CONFIG gdal-config HINTS ENV GDAL_DIR ENV GDAL_ROOT PATH_SUFFIXES bin PATHS /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt ) if(GDAL_CONFIG) exec_program(${GDAL_CONFIG} ARGS --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS) if(GDAL_CONFIG_LIBS) string(REGEX MATCHALL "-l[^ ]+" _gdal_dashl ${GDAL_CONFIG_LIBS}) string(REGEX REPLACE "-l" "" _gdal_lib "${_gdal_dashl}") string(REGEX MATCHALL "-L[^ ]+" _gdal_dashL ${GDAL_CONFIG_LIBS}) string(REGEX REPLACE "-L" "" _gdal_libpath "${_gdal_dashL}") endif() endif() endif() find_library(GDAL_LIBRARY NAMES ${_gdal_lib} gdal gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL HINTS ENV GDAL_DIR ENV GDAL_ROOT ${_gdal_libpath} PATH_SUFFIXES lib PATHS /sw /opt/local /opt/csw /opt /usr/freeware ) set(GDAL_LIBRARIES ${GDAL_LIBRARY}) set(GDAL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GDAL DEFAULT_MSG GDAL_LIBRARY GDAL_INCLUDE_DIR) MARK_AS_ADVANCED(GDAL_LIBRARY GDAL_INCLUDE_DIR GDAL_CONFIG) mapserver-7.4.3/cmake/FindGEOS.cmake000066400000000000000000000021061357574274700171750ustar00rootroot00000000000000# Find the native GEOS(Geometry Engine - Open Source) includes and libraries. # # This module defines: # # GEOS_INCLUDE_DIR, where to find geos.h, etc. # GEOS_LIBRARY, libraries to link against to use GEOS, using the geos_c library # GEOS_FOUND, True if found, false if one of the above are not found. #--- # Find include path: # Note: Version < 3.3.0 do not have geos.h in the geos sub directory; hence, # the check for both "geos/geos.h" and "geos.h". #--- find_path( GEOS_INCLUDE_DIR geos_c.h PATHS /usr/include /usr/local/include SUFFIXES geos) # Find GEOS C library: find_library( GEOS_LIBRARY NAMES geos_c geos_c_i PATHS /usr/lib64 /usr/lib /usr/local/lib ) set(GEOS_INCLUDE_DIRS ${GEOS_INCLUDE_DIR}) set(GEOS_LIBRARIES ${GEOS_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args( GEOS DEFAULT_MSG GEOS_LIBRARY GEOS_INCLUDE_DIR ) MARK_AS_ADVANCED(GEOS_LIBRARY GEOS_INCLUDE_DIR) mapserver-7.4.3/cmake/FindHarfBuzz.cmake000066400000000000000000000045071357574274700202020ustar00rootroot00000000000000# Original Licence: # Copyright (c) 2012, Intel Corporation # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of Intel Corporation nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Try to find Harfbuzz include and library directories. # # After successful discovery, this will set for inclusion where needed: # HARFBUZZ_INCLUDE_DIR - containg the HarfBuzz headers # HARFBUZZ_LIBRARY - containg the HarfBuzz library include(FindPkgConfig) pkg_check_modules(PC_HARFBUZZ harfbuzz>=0.9.18) find_path(HARFBUZZ_INCLUDE_DIR NAMES hb.h HINTS ${PC_HARFBUZZ_INCLUDE_DIRS} ${PC_HARFBUZZ_INCLUDEDIR} PATH_SUFFIXES harfbuzz ) find_library(HARFBUZZ_LIBRARY NAMES harfbuzz HINTS ${PC_HARFBUZZ_LIBRARY_DIRS} ${PC_HARFBUZZ_LIBDIR} ) set(HARFBUZZ_INCLUDE_DIRS ${HARFBUZZ_INCLUDE_DIR}) set(HARFBUZZ_LIBRARIES ${HARFBUZZ_LIBRARY}) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(HarfBuzz DEFAULT_MSG HARFBUZZ_INCLUDE_DIR HARFBUZZ_LIBRARY) mark_as_advanced(HARFBUZZ_LIBRARY HARFBUZZ_INCLUDE_DIR) mapserver-7.4.3/cmake/FindICONV.cmake000066400000000000000000000071041357574274700173210ustar00rootroot00000000000000# # Copyright (c) 2006, Peter Kümmel, # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) if (ICONV_INCLUDE_DIR) # Already in cache, be silent set(ICONV_FIND_QUIETLY TRUE) endif() find_path(ICONV_INCLUDE_DIR iconv.h PATHS /sw /opt/local ) set(POTENTIAL_ICONV_LIBS iconv libiconv libiconv2) find_library(ICONV_LIBRARY NAMES ${POTENTIAL_ICONV_LIBS} PATHS /sw /opt/local ) if(WIN32) set(ICONV_DLL_NAMES iconv.dll libiconv.dll libiconv2.dll) find_file(ICONV_DLL NAMES ${ICONV_DLL_NAMES} PATHS ENV PATH ${ICONV_INCLUDE_DIR}/../bin) find_file(ICONV_DLL_HELP NAMES ${ICONV_DLL_NAMES} PATHS ENV PATH ${ICONV_INCLUDE_DIR}/../bin) if(ICONV_FIND_REQUIRED) if(NOT ICONV_DLL AND NOT ICONV_DLL_HELP) message(FATAL_ERROR "Could not find iconv.dll, please add correct your PATH environment variable") endif() if(NOT ICONV_DLL AND ICONV_DLL_HELP) get_filename_component(ICONV_DLL_HELP ${ICONV_DLL_HELP} PATH) message(STATUS) message(STATUS "Could not find iconv.dll in standard search path, please add ") message(STATUS "${ICONV_DLL_HELP}") message(STATUS "to your PATH environment variable.") message(STATUS) message(FATAL_ERROR "exit cmake") endif() endif() if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY AND ICONV_DLL) set(ICONV_FOUND TRUE) endif() else() include(CheckFunctionExists) check_function_exists(iconv HAVE_ICONV_IN_LIBC) if(ICONV_INCLUDE_DIR AND HAVE_ICONV_IN_LIBC) set(ICONV_FOUND TRUE) set(ICONV_LIBRARY CACHE TYPE STRING FORCE) endif() if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY) set(ICONV_FOUND TRUE) endif() endif() if(ICONV_FOUND) if(NOT ICONV_FIND_QUIETLY) message(STATUS "Found iconv library: ${ICONV_LIBRARY}") #message(STATUS "Found iconv dll : ${ICONV_DLL}") endif() else() if(ICONV_FIND_REQUIRED) message(STATUS "Looked for iconv library named ${POTENTIAL_ICONV_LIBS}.") message(STATUS "Found no acceptable iconv library. This is fatal.") message(STATUS "iconv header: ${ICONV_INCLUDE_DIR}") message(STATUS "iconv lib : ${ICONV_LIBRARY}") message(FATAL_ERROR "Could NOT find iconv library") endif() endif() mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR) mapserver-7.4.3/cmake/FindMySQL.cmake000066400000000000000000000023661357574274700174150ustar00rootroot00000000000000# - Find mysqlclient # Find the native MySQL includes and library # # MYSQL_INCLUDE_DIR - where to find mysql.h, etc. # MYSQL_LIBRARIES - List of libraries when using MySQL. # MYSQL_FOUND - True if MySQL found. IF (MYSQL_INCLUDE_DIR) # Already in cache, be silent SET(MYSQL_FIND_QUIETLY TRUE) ENDIF (MYSQL_INCLUDE_DIR) FIND_PATH(MYSQL_INCLUDE_DIR mysql.h /usr/local/include/mysql /usr/include/mysql PATH_SUFFIXES mysql ) SET(MYSQL_NAMES mysqlclient mysqlclient_r libmysqlclient) FIND_LIBRARY(MYSQL_LIBRARY NAMES ${MYSQL_NAMES} PATHS /usr/lib /usr/local/lib PATH_SUFFIXES mysql ) IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) SET(MYSQL_FOUND TRUE) SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} ) ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) SET(MYSQL_FOUND FALSE) SET( MYSQL_LIBRARIES ) ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) IF (MYSQL_FOUND) IF (NOT MYSQL_FIND_QUIETLY) MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}") ENDIF (NOT MYSQL_FIND_QUIETLY) ELSE (MYSQL_FOUND) IF (MYSQL_FIND_REQUIRED) MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.") MESSAGE(FATAL_ERROR "Could NOT find MySQL library") ENDIF (MYSQL_FIND_REQUIRED) ENDIF (MYSQL_FOUND) MARK_AS_ADVANCED( MYSQL_LIBRARY MYSQL_INCLUDE_DIR ) mapserver-7.4.3/cmake/FindODBC.cmake000066400000000000000000000033561357574274700171570ustar00rootroot00000000000000# # Find the ODBC driver manager includes and library. # # ODBC is an open standard for connecting to different databases in a # semi-vendor-independent fashion. First you install the ODBC driver # manager. Then you need a driver for each separate database you want # to connect to (unless a generic one works). VTK includes neither # the driver manager nor the vendor-specific drivers: you have to find # those yourself. # # This module defines # ODBC_INCLUDE_DIRECTORIES, where to find sql.h # ODBC_LIBRARIES, the libraries to link against to use ODBC # ODBC_FOUND. If false, you cannot build anything that requires MySQL. # also defined, but not for general use is # ODBC_LIBRARY, where to find the ODBC driver manager library. set(ODBC_FOUND FALSE) find_path(ODBC_INCLUDE_DIR sql.h /usr/include /usr/include/odbc /usr/local/include /usr/local/include/odbc /usr/local/odbc/include "C:/Program Files/ODBC/include" "C:/Program Files/Microsoft SDKs/Windows/v7.0A/include" "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/include" "C:/Program Files/Microsoft SDKs/Windows/v6.0a/include" "C:/ODBC/include" DOC "Specify the directory containing sql.h." ) find_library(ODBC_LIBRARY NAMES iodbc odbc odbcinst odbc32 PATHS /usr/lib /usr/lib/odbc /usr/local/lib /usr/local/lib/odbc /usr/local/odbc/lib "C:/Program Files/ODBC/lib" "C:/ODBC/lib/debug" "C:/Program Files/Microsoft SDKs/Windows/v7.0A/Lib" "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib" DOC "Specify the ODBC driver manager library here." ) if(ODBC_LIBRARY) if(ODBC_INCLUDE_DIR) set( ODBC_FOUND 1 ) endif() endif() set(ODBC_LIBRARIES ${ODBC_LIBRARY}) mark_as_advanced(ODBC_FOUND ODBC_LIBRARY ODBC_EXTRA_LIBRARIES ODBC_INCLUDE_DIR) mapserver-7.4.3/cmake/FindOracle.cmake000066400000000000000000000056331357574274700176550ustar00rootroot00000000000000############################################################################### # # CMake module to search for Oracle client library (OCI) # # On success, the macro sets the following variables: # ORACLE_FOUND = if the library found # ORACLE_LIBRARY = full path to the library # ORACLE_LIBRARIES = full path to the library # ORACLE_INCLUDE_DIR = where to find the library headers also defined, # but not for general use are # ORACLE_VERSION = version of library which was found, e.g. "1.2.5" # # Copyright (c) 2009-2013 Mateusz Loskot # # Developed with inspiration from Petr Vanek # who wrote similar macro for TOra - http://torasql.com/ # # Module source: http://github.com/mloskot/workshop/tree/master/cmake/ # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # ############################################################################### # If ORACLE_HOME not defined, assume Oracle libraries not available if(DEFINED ENV{ORACLE_HOME}) set(ORACLE_HOME $ENV{ORACLE_HOME}) message("ORACLE_HOME=${ORACLE_HOME}") find_path(ORACLE_INCLUDE_DIR NAMES oci.h PATHS ${ORACLE_HOME}/rdbms/public ${ORACLE_HOME}/include ${ORACLE_HOME}/sdk/include # Oracle SDK ${ORACLE_HOME}/OCI/include) # Oracle XE on Windows set(ORACLE_OCI_NAMES clntsh libclntsh oci) set(ORACLE_NNZ_NAMES nnz10 libnnz10 nnz11 libnnz11 nnz12 libnnz12 nnz18 libnnz18 ociw32) set(ORACLE_OCCI_NAMES libocci occi oraocci10 oraocci11 oraocci12) set(ORACLE_LIB_DIR ${ORACLE_HOME} ${ORACLE_HOME}/lib ${ORACLE_HOME}/sdk/lib # Oracle SDK ${ORACLE_HOME}/sdk/lib/msvc ${ORACLE_HOME}/OCI/lib/msvc) # Oracle XE on Windows find_library(ORACLE_OCI_LIBRARY NAMES ${ORACLE_OCI_NAMES} PATHS ${ORACLE_LIB_DIR}) find_library(ORACLE_OCCI_LIBRARY NAMES ${ORACLE_OCCI_NAMES} PATHS ${ORACLE_LIB_DIR}) if (NOT CMAKE_CL_64) find_library(ORACLE_NNZ_LIBRARY NAMES ${ORACLE_NNZ_NAMES} PATHS ${ORACLE_LIB_DIR}) endif() set(ORACLE_LIBRARY ${ORACLE_OCI_LIBRARY} ${ORACLE_OCCI_LIBRARY} ${ORACLE_NNZ_LIBRARY}) if(APPLE) set(ORACLE_OCIEI_NAMES libociei ociei) find_library(ORACLE_OCIEI_LIBRARY NAMES libociei ociei PATHS ${ORACLE_LIB_DIR}) if(ORACLE_OCIEI_LIBRARY) set(ORACLE_LIBRARY ${ORACLE_LIBRARY} ${ORACLE_OCIEI_LIBRARY}) else(ORACLE_OCIEI_LIBRARY) message(STATUS "libociei.dylib is not found. It may cause crash if you are building BUNDLE") endif() endif() set(ORACLE_LIBRARIES ${ORACLE_LIBRARY}) endif(DEFINED ENV{ORACLE_HOME}) # Handle the QUIETLY and REQUIRED arguments and set ORACLE_FOUND to TRUE # if all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(ORACLE DEFAULT_MSG ORACLE_LIBRARY ORACLE_INCLUDE_DIR) mark_as_advanced(ORACLE_INCLUDE_DIR ORACLE_LIBRARY) mapserver-7.4.3/cmake/FindPHP.cmake000066400000000000000000000071151357574274700170740ustar00rootroot00000000000000# - Find PHP # This module finds if PHP is installed and determines where the include files # and libraries are. It also determines what the name of the library is. This # code sets the following variables: # # PHP_INCLUDE_PATH = path to where php.h can be found # PHP_EXECUTABLE = full path to the php binary # SET(PHP_FOUND "NO") SET(PHP_POSSIBLE_INCLUDE_PATHS /usr/include/php /usr/local/include/php /usr/include/php /usr/local/include/php /usr/local/apache/php ${PHP_INCLUDES} ) find_library(PHP_LIBRARY NAMES php5ts php5 php7ts php7 PATHS /sw /opt/local) if(WIN32) string(SUBSTRING $ENV{VSCMD_VER} 0 2 VSCMD_VER) SET(PHP_INCLUDE_PATH "C:/php-sdk/phpmaster/vc${VSCMD_VER}/$ENV{VSCMD_ARG_TGT_ARCH}/php-src") SET(PHP_POSSIBLE_INCLUDE_PATHS ${PHP_INCLUDE_PATH}) if(CMAKE_CL_64) SET(PHP_INCLUDE_PATH "${PHP_INCLUDE_PATH}/$ENV{PLATFORM}") endif(CMAKE_CL_64) if(WITH_THREAD_SAFETY) SET(PHP_INCLUDE_PATH "${PHP_INCLUDE_PATH}/Release_TS") SET(PHP_LIBRARY_NAMES php5ts php7ts) else(WITH_THREAD_SAFETY) SET(PHP_INCLUDE_PATH "${PHP_INCLUDE_PATH}/Release") SET(PHP_LIBRARY_NAMES php5 php7) endif(WITH_THREAD_SAFETY) find_library(PHP_LIBRARY NAMES ${PHP_LIBRARY_NAMES} PATHS ${PHP_INCLUDE_PATH}) endif(WIN32) FIND_PATH(PHP_FOUND_INCLUDE_PATH main/php.h ${PHP_POSSIBLE_INCLUDE_PATHS}) IF(PHP_FOUND_INCLUDE_PATH) SET(php_paths "${PHP_POSSIBLE_INCLUDE_PATHS}") FOREACH(php_path Zend main TSRM) SET(php_paths ${php_paths} "${PHP_FOUND_INCLUDE_PATH}/${php_path}") ENDFOREACH(php_path Zend main TSRM) SET(PHP_INCLUDE_PATH "${php_paths}" INTERNAL "PHP include paths") ENDIF(PHP_FOUND_INCLUDE_PATH) FIND_PROGRAM(PHP_EXECUTABLE NAMES php PATHS /usr/local/bin ) MARK_AS_ADVANCED( PHP_EXECUTABLE PHP_FOUND_INCLUDE_PATH ) IF( NOT PHP_CONFIG_EXECUTABLE ) FIND_PROGRAM(PHP_CONFIG_EXECUTABLE NAMES php-config ) ENDIF( NOT PHP_CONFIG_EXECUTABLE ) IF(PHP_CONFIG_EXECUTABLE) EXECUTE_PROCESS(COMMAND ${PHP_CONFIG_EXECUTABLE} --version OUTPUT_VARIABLE PHP_VERSION) STRING(REPLACE "\n" "" PHP_VERSION "${PHP_VERSION}") EXECUTE_PROCESS(COMMAND ${PHP_CONFIG_EXECUTABLE} --extension-dir OUTPUT_VARIABLE PHP_EXTENSION_DIR) STRING(REPLACE "\n" "" PHP_EXTENSION_DIR "${PHP_EXTENSION_DIR}") EXECUTE_PROCESS(COMMAND ${PHP_CONFIG_EXECUTABLE} --includes OUTPUT_VARIABLE PHP_INCLUDES) STRING(REPLACE "-I" "" PHP_INCLUDES "${PHP_INCLUDES}") STRING(REPLACE " " ";" PHP_INCLUDES "${PHP_INCLUDES}") STRING(REPLACE "\n" "" PHP_INCLUDES "${PHP_INCLUDES}") LIST(GET PHP_INCLUDES 0 PHP_INCLUDE_DIR) set(PHP_MAIN_INCLUDE_DIR ${PHP_INCLUDE_DIR}/main) set(PHP_TSRM_INCLUDE_DIR ${PHP_INCLUDE_DIR}/TSRM) set(PHP_ZEND_INCLUDE_DIR ${PHP_INCLUDE_DIR}/Zend) set(PHP_REGEX_INCLUDE_DIR ${PHP_INCLUDE_DIR}/regex) set(PHP_EXT_INCLUDE_DIR ${PHP_INCLUDE_DIR}/ext) set(PHP_DATE_INCLUDE_DIR ${PHP_INCLUDE_DIR}/ext/date/lib) set(PHP_STANDARD_INCLUDE_DIR ${PHP_INCLUDE_DIR}/ext/standard) MESSAGE(STATUS ${PHP_MAIN_INCLUDE_DIR}) IF(NOT PHP_INCLUDE_PATH) set(PHP_INCLUDE_PATH ${PHP_INCLUDES}) ENDIF(NOT PHP_INCLUDE_PATH) IF(PHP_VERSION LESS 5) MESSAGE(FATAL_ERROR "PHP version is not 5 or later") ENDIF(PHP_VERSION LESS 5) IF(PHP_EXECUTABLE AND PHP_INCLUDES) set(PHP_FOUND "yes") MESSAGE(STATUS "Found PHP-Version ${PHP_VERSION} (using ${PHP_CONFIG_EXECUTABLE})") ENDIF(PHP_EXECUTABLE AND PHP_INCLUDES) FIND_PROGRAM(PHPUNIT_EXECUTABLE NAMES phpunit phpunit2 PATHS /usr/local/bin ) IF(PHPUNIT_EXECUTABLE) MESSAGE(STATUS "Found phpunit: ${PHPUNIT_EXECUTABLE}") ENDIF(PHPUNIT_EXECUTABLE) ENDIF(PHP_CONFIG_EXECUTABLE) mapserver-7.4.3/cmake/FindPerlLibs.cmake000066400000000000000000000226121357574274700201600ustar00rootroot00000000000000# - Find Perl libraries # This module finds if PERL is installed and determines where the include files # and libraries are. It also determines what the name of the library is. This # code sets the following variables: # # PERLLIBS_FOUND = True if perl.h & libperl were found # PERL_INCLUDE_PATH = path to where perl.h is found # PERL_LIBRARY = path to libperl # PERL_EXECUTABLE = full path to the perl binary # # The minimum required version of Perl can be specified using the # standard syntax, e.g. find_package(PerlLibs 6.0) # # The following variables are also available if needed # (introduced after CMake 2.6.4) # # PERL_SITEARCH = path to the sitearch install dir # PERL_SITELIB = path to the sitelib install directory # PERL_VENDORARCH = path to the vendor arch install directory # PERL_VENDORLIB = path to the vendor lib install directory # PERL_ARCHLIB = path to the arch lib install directory # PERL_PRIVLIB = path to the priv lib install directory # PERL_EXTRA_C_FLAGS = Compilation flags used to build perl # #============================================================================= # Copyright 2004-2009 Kitware, Inc. # Copyright 2008 Andreas Schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # find the perl executable include(FindPerl) if (PERL_EXECUTABLE) if(NOT DEFINED PERL_VERSION_STRING) ### PERL_VERSION execute_process( COMMAND ${PERL_EXECUTABLE} -V:version OUTPUT_VARIABLE PERL_VERSION_OUTPUT_VARIABLE RESULT_VARIABLE PERL_VERSION_RESULT_VARIABLE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT PERL_VERSION_RESULT_VARIABLE AND NOT PERL_VERSION_OUTPUT_VARIABLE MATCHES "^version='UNKNOWN'") string(REGEX REPLACE "version='([^']+)'.*" "\\1" PERL_VERSION_STRING ${PERL_VERSION_OUTPUT_VARIABLE}) else() execute_process( COMMAND ${PERL_EXECUTABLE} -v OUTPUT_VARIABLE PERL_VERSION_OUTPUT_VARIABLE RESULT_VARIABLE PERL_VERSION_RESULT_VARIABLE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT PERL_VERSION_RESULT_VARIABLE AND PERL_VERSION_OUTPUT_VARIABLE MATCHES "This is perl.*[ \\(]v([0-9\\._]+)[ \\)]") string(REGEX REPLACE ".*This is perl.*[ \\(]v([0-9\\._]+)[ \\)].*" "\\1" PERL_VERSION_STRING ${PERL_VERSION_OUTPUT_VARIABLE}) elseif(NOT PERL_VERSION_RESULT_VARIABLE AND PERL_VERSION_OUTPUT_VARIABLE MATCHES "This is perl, version ([0-9\\._]+) +") string(REGEX REPLACE ".*This is perl, version ([0-9\\._]+) +.*" "\\1" PERL_VERSION_STRING ${PERL_VERSION_OUTPUT_VARIABLE}) endif() endif() endif() ### PERL_PREFIX execute_process( COMMAND ${PERL_EXECUTABLE} -V:prefix OUTPUT_VARIABLE PERL_PREFIX_OUTPUT_VARIABLE RESULT_VARIABLE PERL_PREFIX_RESULT_VARIABLE ) if (NOT PERL_PREFIX_RESULT_VARIABLE) string(REGEX REPLACE "prefix='([^']+)'.*" "\\1" PERL_PREFIX ${PERL_PREFIX_OUTPUT_VARIABLE}) endif () ### PERL_ARCHNAME execute_process( COMMAND ${PERL_EXECUTABLE} -V:archname OUTPUT_VARIABLE PERL_ARCHNAME_OUTPUT_VARIABLE RESULT_VARIABLE PERL_ARCHNAME_RESULT_VARIABLE ) if (NOT PERL_ARCHNAME_RESULT_VARIABLE) string(REGEX REPLACE "archname='([^']+)'.*" "\\1" PERL_ARCHNAME ${PERL_ARCHNAME_OUTPUT_VARIABLE}) endif () ### PERL_EXTRA_C_FLAGS execute_process( COMMAND ${PERL_EXECUTABLE} -V:cppflags OUTPUT_VARIABLE PERL_CPPFLAGS_OUTPUT_VARIABLE RESULT_VARIABLE PERL_CPPFLAGS_RESULT_VARIABLE ) if (NOT PERL_CPPFLAGS_RESULT_VARIABLE) string(REGEX REPLACE "cppflags='([^']+)'.*" "\\1" PERL_EXTRA_C_FLAGS ${PERL_CPPFLAGS_OUTPUT_VARIABLE}) endif () ### PERL_SITEARCH execute_process( COMMAND ${PERL_EXECUTABLE} -V:installsitearch OUTPUT_VARIABLE PERL_SITEARCH_OUTPUT_VARIABLE RESULT_VARIABLE PERL_SITEARCH_RESULT_VARIABLE ) if (NOT PERL_SITEARCH_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_SITEARCH ${PERL_SITEARCH_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_SITEARCH}" PERL_SITEARCH) endif () ### PERL_SITELIB execute_process( COMMAND ${PERL_EXECUTABLE} -V:installsitelib OUTPUT_VARIABLE PERL_SITELIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_SITELIB_RESULT_VARIABLE ) if (NOT PERL_SITELIB_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_SITELIB ${PERL_SITELIB_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_SITELIB}" PERL_SITELIB) endif () ### PERL_VENDORARCH execute_process( COMMAND ${PERL_EXECUTABLE} -V:installvendorarch OUTPUT_VARIABLE PERL_VENDORARCH_OUTPUT_VARIABLE RESULT_VARIABLE PERL_VENDORARCH_RESULT_VARIABLE ) if (NOT PERL_VENDORARCH_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_VENDORARCH ${PERL_VENDORARCH_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_VENDORARCH}" PERL_VENDORARCH) endif () ### PERL_VENDORLIB execute_process( COMMAND ${PERL_EXECUTABLE} -V:installvendorlib OUTPUT_VARIABLE PERL_VENDORLIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_VENDORLIB_RESULT_VARIABLE ) if (NOT PERL_VENDORLIB_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_VENDORLIB ${PERL_VENDORLIB_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_VENDORLIB}" PERL_VENDORLIB) endif () macro(perl_adjust_darwin_lib_variable varname) string( TOUPPER PERL_${varname} FINDPERL_VARNAME ) string( TOLOWER install${varname} PERL_VARNAME ) if (NOT PERL_MINUSV_OUTPUT_VARIABLE) execute_process( COMMAND ${PERL_EXECUTABLE} -V OUTPUT_VARIABLE PERL_MINUSV_OUTPUT_VARIABLE RESULT_VARIABLE PERL_MINUSV_RESULT_VARIABLE ) endif() if (NOT PERL_MINUSV_RESULT_VARIABLE) string(REGEX MATCH "(${PERL_VARNAME}.*points? to the Updates directory)" PERL_NEEDS_ADJUSTMENT ${PERL_MINUSV_OUTPUT_VARIABLE}) if (PERL_NEEDS_ADJUSTMENT) string(REGEX REPLACE "(.*)/Updates/" "/System/\\1/" ${FINDPERL_VARNAME} ${${FINDPERL_VARNAME}}) endif () endif () endmacro() ### PERL_ARCHLIB execute_process( COMMAND ${PERL_EXECUTABLE} -V:archlib OUTPUT_VARIABLE PERL_ARCHLIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_ARCHLIB_RESULT_VARIABLE ) if (NOT PERL_ARCHLIB_RESULT_VARIABLE) string(REGEX REPLACE "[a-z]+='([^']+)'.*" "\\1" PERL_ARCHLIB ${PERL_ARCHLIB_OUTPUT_VARIABLE}) perl_adjust_darwin_lib_variable( ARCHLIB ) file(TO_CMAKE_PATH "${PERL_ARCHLIB}" PERL_ARCHLIB) endif () ### PERL_PRIVLIB execute_process( COMMAND ${PERL_EXECUTABLE} -V:installprivlib OUTPUT_VARIABLE PERL_PRIVLIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_PRIVLIB_RESULT_VARIABLE ) if (NOT PERL_PRIVLIB_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_PRIVLIB ${PERL_PRIVLIB_OUTPUT_VARIABLE}) perl_adjust_darwin_lib_variable( PRIVLIB ) file(TO_CMAKE_PATH "${PERL_PRIVLIB}" PERL_PRIVLIB) endif () ### PERL_POSSIBLE_LIBRARY_NAMES execute_process( COMMAND ${PERL_EXECUTABLE} -V:libperl OUTPUT_VARIABLE PERL_LIBRARY_OUTPUT_VARIABLE RESULT_VARIABLE PERL_LIBRARY_RESULT_VARIABLE ) if (NOT PERL_LIBRARY_RESULT_VARIABLE) string(REGEX REPLACE "libperl='([^']+)'.*" "\\1" PERL_POSSIBLE_LIBRARY_NAMES ${PERL_LIBRARY_OUTPUT_VARIABLE}) else () set(PERL_POSSIBLE_LIBRARY_NAMES perl${PERL_VERSION_STRING} perl) endif () ### PERL_INCLUDE_PATH find_path(PERL_INCLUDE_PATH NAMES perl.h PATHS ${PERL_ARCHLIB}/CORE /System/${PERL_ARCHLIB}/CORE /usr/lib/perl5/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE /usr/lib/perl/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE /usr/lib/perl5/${PERL_VERSION_STRING}/CORE /usr/lib/perl/${PERL_VERSION_STRING}/CORE ) ### PERL_LIBRARY find_library(PERL_LIBRARY NAMES ${PERL_POSSIBLE_LIBRARY_NAMES} perl perl${PERL_VERSION_STRING} perl_i perl${PERL_VERSION_STRING}_i PATHS ${PERL_ARCHLIB}/CORE /System/${PERL_ARCHLIB}/CORE /usr/lib/perl5/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE /usr/lib/perl/${PERL_VERSION_STRING}/${PERL_ARCHNAME}/CORE /usr/lib/perl5/${PERL_VERSION_STRING}/CORE /usr/lib/perl/${PERL_VERSION_STRING}/CORE ) endif () # handle the QUIETLY and REQUIRED arguments and set PERLLIBS_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PerlLibs REQUIRED_VARS PERL_LIBRARY PERL_INCLUDE_PATH) # Introduced after CMake 2.6.4 to bring module into compliance set(PERL_INCLUDE_DIR ${PERL_INCLUDE_PATH}) set(PERL_INCLUDE_DIRS ${PERL_INCLUDE_PATH}) set(PERL_LIBRARIES ${PERL_LIBRARY}) # For backward compatibility with CMake before 2.8.8 set(PERL_VERSION ${PERL_VERSION_STRING}) mark_as_advanced( PERL_INCLUDE_PATH PERL_LIBRARY ) mapserver-7.4.3/cmake/FindPixman.cmake000066400000000000000000000012721357574274700176770ustar00rootroot00000000000000FIND_PACKAGE(PkgConfig) PKG_CHECK_MODULES(PC_PIXMAN pixman) if(NOT PC_PIXMAN_FOUND) PKG_CHECK_MODULES(PC_PIXMAN pixman-1) endif(NOT PC_PIXMAN_FOUND) FIND_PATH(PIXMAN_INCLUDE_DIR NAMES pixman.h HINTS ${PC_PIXMAN_INCLUDEDIR} ${PC_PIXMAN_INCLUDE_DIR} PATH_SUFFIXES pixman pixman-1 ) FIND_LIBRARY(PIXMAN_LIBRARY NAMES pixman pixman-1 HINTS ${PC_PIXMAN_LIBDIR} ${PC_PIXMAN_LIBRARY_DIRS} ) set(PIXMAN_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR}) set(PIXMAN_LIBRARIES ${PIXMAN_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PIXMAN DEFAULT_MSG PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR) mark_as_advanced(PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR) mapserver-7.4.3/cmake/FindPostgreSQL.cmake000066400000000000000000000032301357574274700204420ustar00rootroot00000000000000# - Find PostgreSQL # Find the PostgreSQL includes and client library # This module defines # POSTGRESQL_INCLUDE_DIR, where to find POSTGRESQL.h # POSTGRESQL_LIBRARY, the libraries needed to use POSTGRESQL. # POSTGRESQL_FOUND, If false, do not try to use PostgreSQL. # # Copyright (c) 2013 Thomas Bonfort, Andy Colson # find_program(PG_CONFIG NAMES pg_config PATHS $ENV{ProgramFiles}/PostgreSQL/*/bin $ENV{SystemDrive}/PostgreSQL/*/bin ) if (PG_CONFIG) exec_program( ${PG_CONFIG} ARGS "--includedir" OUTPUT_VARIABLE PG_INC_PATH ) exec_program( ${PG_CONFIG} ARGS "--libdir" OUTPUT_VARIABLE PG_LIB_PATH ) else() message(WARNING "pg_config not found, will try some defaults") endif() find_path(POSTGRESQL_INCLUDE_DIR libpq-fe.h ${PG_INC_PATH} /usr/include/server /usr/include/postgresql /usr/include/pgsql/server /usr/local/include/pgsql/server /usr/include/postgresql/server /usr/include/postgresql/*/server /usr/local/include/postgresql/server /usr/local/include/postgresql/*/server $ENV{ProgramFiles}/PostgreSQL/*/include/server $ENV{SystemDrive}/PostgreSQL/*/include/server ) find_library(POSTGRESQL_LIBRARY NAMES pq libpq PATHS ${PG_LIB_PATH} /usr/lib /usr/local/lib /usr/lib/postgresql /usr/lib64 /usr/local/lib64 /usr/lib64/postgresql $ENV{ProgramFiles}/PostgreSQL/*/lib/ms $ENV{SystemDrive}/PostgreSQL/*/lib/ms ) set(POSTGRESQL_INCLUDE_DIRS ${POSTGRESQL_INCLUDE_DIR}) set(POSTGRESQL_LIBRARIES ${POSTGRESQL_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(POSTGRESQL DEFAULT_MSG POSTGRESQL_LIBRARY POSTGRESQL_INCLUDE_DIR) mark_as_advanced(POSTGRESQL_LIBRARY POSTGRESQL_INCLUDE_DIR) mapserver-7.4.3/cmake/FindProj.cmake000066400000000000000000000007451357574274700173610ustar00rootroot00000000000000# Find Proj # # If it's found it sets PROJ_FOUND to TRUE # and following variables are set: # PROJ_INCLUDE_DIR # PROJ_LIBRARY FIND_PATH(PROJ_INCLUDE_DIR proj_api.h) FIND_LIBRARY(PROJ_LIBRARY NAMES proj proj_i) set(PROJ_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) set(PROJ_LIBRARIES ${PROJ_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PROJ DEFAULT_MSG PROJ_LIBRARY PROJ_INCLUDE_DIR) mark_as_advanced(PROJ_LIBRARY PROJ_INCLUDE_DIR) mapserver-7.4.3/cmake/FindProtobufC.cmake000066400000000000000000000105201357574274700203420ustar00rootroot00000000000000# - Find protobuf-c # Find protobuf c implementation libraries, includes and the protoc-c compiler # FindProtobufC was loosely based on FindProtobuf that is shipped with cmake # # Module defines: # PROTOBUFC_FOUND - library, includes and compiler where found # PROTOBUFC_INCLUDE_DIRS - include directories # PROTOBUFC_LIBRARIES - protobuf-c libraries # PROTOBUFC_EXECUTEABLE - protobuf-c compiler # # Environment variables: # PROTOBUFC_ROOTDIR - optional - rootdir of protobuf-c installation # # Cache entries: # PROTOBUFC_LIBRARY - detected protobuf-c library # PROTOBUF_INCLUDE_DIR - detected protobuf-c include dir(s) # PROTOBUF_COMPILER - detected protobuf-c compiler # #### # # ==================================================================== # Example: # # find_package(ProtobufC REQUIRED) # include_directories(${PROTOBUFC_INCLUDE_DIRS}) # include_directories(${CMAKE_CURRENT_BINARY_DIR}) # PROTOBUFC_GENERATE_C(PROTO_SOURCES PROTO_HEADERS protobuf.proto) # add_executable(bar bar.c ${PROTO_SRCn} ${PROTO_HDRS}) # target_link_libraries(bar ${PROTOBUF_LIBRARIES}) # # NOTE: You may need to link against pthreads, depending # on the platform. # # NOTE: The PROTOBUF_GENERATE_CPP macro & add_executable() or add_library() # calls only work properly within the same directory. # # ==================================================================== #============================================================================= # Copyright 2013 Thinstuff Technologies GmbH # Copyright 2013 Bernhard Miklautz # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #============================================================================= set(PROTBUFC_SOURCE_EXTENSION "pb-c.c") set(PROTBUFC_HEADER_EXTENSION "pb-c.h") function(PROTOBUFC_GENERATE_C SOURCES HEADERS) if(NOT ARGN) message(SEND_ERROR "Error: PROTOBUFC_GENERATE_C() called without any proto files") return() endif(NOT ARGN) foreach(FIL ${ARGN}) get_filename_component(ABS_FIL ${FIL} ABSOLUTE) get_filename_component(FIL_WE ${FIL} NAME_WE) get_filename_component(FIL_PATH ${ABS_FIL} PATH) list(APPEND ${SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.${PROTBUFC_SOURCE_EXTENSION}") list(APPEND ${HEADERS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.${PROTBUFC_HEADER_EXTENSION}") add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.${PROTBUFC_SOURCE_EXTENSION}" "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.${PROTBUFC_HEADER_EXTENSION}" COMMAND ${PROTOBUFC_COMPILER} ARGS --c_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} -I ${FIL_PATH} ${ABS_FIL} DEPENDS ${ABS_FIL} COMMENT "Running protobuf-c compiler on ${FIL}" VERBATIM ) endforeach() set_source_files_properties(${${SOURCES}} ${${HEADERS}} PROPERTIES GENERATED TRUE) set(${SOURCES} ${${SOURCES}} PARENT_SCOPE) set(${HEADERS} ${${HEADERS}} PARENT_SCOPE) endfunction() find_library(PROTOBUFC_LIBRARY NAMES "protobuf-c" PATHS "/usr" "/usr/local" "/opt" ENV PROTOBUFC_ROOTDIR PATH_SUFFIXES "lib") mark_as_advanced(PROTOBUFC_LIBRARY) find_path(PROTOBUFC_INCLUDE_DIR NAMES "google/protobuf-c/protobuf-c.h" PATHS "/usr" "/usr/local" "/opt" ENV PROTOBUFC_ROOTDIR PATH_SUFFIXES "include") mark_as_advanced(PROTOBUFC_INCLUDE_DIR) find_program(PROTOBUFC_COMPILER NAMES "protoc-c" PATHS "/usr" "/usr/local" "/opt" ENV PROTOBUFC_ROOTDIR PATH_SUFFIXES "bin") mark_as_advanced(PROTOBUFC_COMPILER) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(ProtobufC DEFAULT_MSG PROTOBUFC_LIBRARY PROTOBUFC_COMPILER PROTOBUFC_INCLUDE_DIR ) if (PROTOBUFC_FOUND) set(PROTOBUFC_LIBRARIES ${PROTOBUFC_LIBRARY}) set(PROTOBUFC_INCLUDE_DIRS ${PROTOBUFC_INCLUDE_DIR}) set(PROTOBUFC_EXECUTEABLE ${PROTOBUFC_COMPILER}) endif(PROTOBUFC_FOUND) mapserver-7.4.3/cmake/FindPythonModule.cmake000066400000000000000000000020151357574274700210660ustar00rootroot00000000000000# Find if a Python module is installed # Found at http://www.cmake.org/pipermail/cmake/2011-January/041666.html # To use do: find_python_module(PyQt4 REQUIRED) function(find_python_module module) string(TOUPPER ${module} module_upper) if(NOT PY_${module_upper}) if(ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED") set(${module}_FIND_REQUIRED TRUE) endif() # A module's location is usually a directory, but for binary modules # it's a .so file. execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import re, ${module}; print(re.compile('/__init__.py.*').sub('',${module}.__file__))" RESULT_VARIABLE _${module}_status OUTPUT_VARIABLE _${module}_location ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT _${module}_status) set(PY_${module_upper} ${_${module}_location} CACHE STRING "Location of Python module ${module}") endif(NOT _${module}_status) endif(NOT PY_${module_upper}) find_package_handle_standard_args(PY_${module} DEFAULT_MSG PY_${module_upper}) endfunction(find_python_module) mapserver-7.4.3/cmake/FindRSVG.cmake000066400000000000000000000017621357574274700172300ustar00rootroot00000000000000# - Find Rsvg # Find the Rsvg includes and libraries # # Following variables are provided: # RSVG_FOUND # True if Rsvg has been found # RSVG_INCLUDE_DIRS # The include directories of Rsvg # RSVG_LIBRARIES # Rsvg library list find_package(PkgConfig) pkg_check_modules(RSVG QUIET librsvg-2.0>=2.32.0) pkg_check_modules(GOBJECT QUIET gobject-2.0>=2.32.0) find_path(RSVG_INCLUDE_DIR NAMES rsvg-cairo.h HINTS ${RSVG_INCLUDE_DIRS} PATH_SUFFIXES librsvg ) find_library(RSVG_LIBRARY NAME rsvg-2 HINTS ${RSVG_LIBRARY_DIRS} ) find_path(GOBJECT_INCLUDE_DIR NAMES glib-object.h HINTS ${GOBJECT_INCLUDE_DIRS} ) find_library(GOBJECT_LIBRARY NAME gobject-2.0 HINTS ${GOBJECT_LIBRARY_DIRS} ) find_package_handle_standard_args(RSVG DEFAULT_MSG RSVG_LIBRARY RSVG_INCLUDE_DIR) find_package_handle_standard_args(GOBJECT DEFAULT_MSG GOBJECT_LIBRARY GOBJECT_INCLUDE_DIR) mark_as_advanced(RSVG_LIBRARY RSVG_INCLUDE_DIR RSVG_LIBRARIES RSVG_INCLUDE_DIRS GOBJECT_LIBRARY GOBJECT_INCLUDE_DIR)mapserver-7.4.3/cmake/FindSVGCairo.cmake000066400000000000000000000026671357574274700200710ustar00rootroot00000000000000# - Find LibSVG and LibSVG-Cairo # # Following variables are provided: # SVG_FOUND # True if libsvg has been found # SVG_INCLUDE_DIR # The include directories of libsvg # SVG_LIBRARY # libsvg library list # Following variables are provided: # SVGCAIRO_FOUND # True if libsvg-cairo has been found # SVGCAIRO_INCLUDE_DIR # The include directories of libsvg-cairo # SVGCAIRO_LIBRARY # libsvg-cairo library list find_package(PkgConfig) pkg_check_modules(PC_SVG QUIET libsvg>=0.1.4) pkg_check_modules(PC_SVGCAIRO QUIET libsvg-cairo>=0.1.6) find_path(SVG_INCLUDE_DIR NAMES svg.h HINTS ${PC_SVG_INCLUDE_DIR} ${PC_SVG_INCLUDE_DIRS} ) find_library(SVG_LIBRARY NAME svg HINTS ${PC_SVG_LIBDIR} ${PC_SVG_LIBRARY_DIRS} ) find_path(SVGCAIRO_INCLUDE_DIR NAMES svg-cairo.h HINTS ${PC_SVGCAIRO_INCLUDE_DIR} ${PC_SVGCAIRO_INCLUDE_DIRS} ) find_library(SVGCAIRO_LIBRARY NAME svg-cairo HINTS ${PC_SVGCAIRO_LIBDIR} ${PC_SVGCAIRO_LIBRARY_DIRS} ) include(FindPackageHandleStandardArgs) set(SVG_INCLUDE_DIRS ${SVG_INCLUDE_DIR}) set(SVG_LIBRARIES ${SVG_LIBRARY}) find_package_handle_standard_args(SVG DEFAULT_MSG SVG_LIBRARY SVG_INCLUDE_DIR) mark_as_advanced(SVG_LIBRARY SVG_INCLUDE_DIR) set(SVGCAIRO_INCLUDE_DIRS ${SVGCAIRO_INCLUDE_DIR}) set(SVGCAIRO_LIBRARIES ${SVGCAIRO_LIBRARY}) find_package_handle_standard_args(SVGCAIRO DEFAULT_MSG SVGCAIRO_LIBRARY SVGCAIRO_INCLUDE_DIR) mark_as_advanced(SVGCAIRO_LIBRARY SVGCAIRO_INCLUDE_DIR) mapserver-7.4.3/cmake/FindV8.cmake000066400000000000000000000026021357574274700167360ustar00rootroot00000000000000# - Find V8 # # V8_INCLUDE - Where to find v8.h # V8_LIBS - List of libraries when using V8. # V8_FOUND - True if V8 found. get_filename_component(module_file_path ${CMAKE_CURRENT_LIST_FILE} PATH) # Look for the header file. find_path(V8_INCLUDE NAMES v8.h PATHS $ENV{V8_ROOT}/include /opt/local/include /usr/local/include /usr/include DOC "Path in which the file v8.h is located." ) mark_as_advanced(V8_INCLUDE) # Look for the library. # Does this work on UNIX systems? (LINUX) find_library(V8_LIBS NAMES v8 PATHS /usr/lib $ENV{V8_ROOT}/lib DOC "Path to v8 library." ) mark_as_advanced(V8_LIBS) # Copy the results to the output variables. if (V8_INCLUDE AND V8_LIBS) message(STATUS "Found v8 in ${V8_INCLUDE} ${V8_LIBS}") set(V8_FOUND 1) include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_LIBRARIES ${V8_LIBS} pthread) set(CMAKE_REQUIRED_INCLUDES ${V8_INCLUDE}) check_cxx_source_compiles(" #include int main() { v8::Persistent ctx; ctx.Dispose(0); return 0; }" V8_DISPOSE_HAS_ISOLATE) else () set(V8_FOUND 0) endif () # Report the results. if (NOT V8_FOUND) set(V8_DIR_MESSAGE "V8 was not found. Make sure V8_LIBS and V8_INCLUDE are set.") if (V8_FIND_REQUIRED) message(FATAL_ERROR "${V8_DIR_MESSAGE}") elseif (NOT V8_FIND_QUIETLY) message(STATUS "${V8_DIR_MESSAGE}") endif () endif () mapserver-7.4.3/dejavu-sans-condensed.h000066400000000000000000150115301357574274700201150ustar00rootroot00000000000000/* Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) Bitstream Vera Fonts Copyright ------------------------------ Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org. Arev Fonts Copyright ------------------------------ Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the modifications to the Bitstream Vera Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Tavmjong Bah" or the word "Arev". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Tavmjong Bah Arev" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the name of Tavmjong Bah shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from Tavmjong Bah. For further information, contact: tavmjong @ free . fr. */ #ifndef _DEJAVU_SANS_CONDENSED_H #define _DEJAVU_SANS_CONDENSED_H /* to regenerate this file, use the `xxd -i` command */ unsigned char dejavu_sans_condensed_ttf[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x04, 0x00, 0x30, 0x46, 0x46, 0x54, 0x4d, 0x66, 0x09, 0x1f, 0xf9, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x00, 0x1c, 0x47, 0x44, 0x45, 0x46, 0xc3, 0x10, 0xc5, 0x70, 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x01, 0xc2, 0x47, 0x50, 0x4f, 0x53, 0xfc, 0xcc, 0xe2, 0x8c, 0x00, 0x00, 0x03, 0x1c, 0x00, 0x00, 0x70, 0xc4, 0x47, 0x53, 0x55, 0x42, 0x81, 0x22, 0xfe, 0xaf, 0x00, 0x00, 0x73, 0xe0, 0x00, 0x00, 0x0d, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x8d, 0x18, 0xe6, 0xc7, 0x00, 0x00, 0x81, 0x30, 0x00, 0x00, 0x00, 0x56, 0x63, 0x6d, 0x61, 0x70, 0x26, 0x77, 0xbd, 0xfb, 0x00, 0x00, 0x81, 0x88, 0x00, 0x00, 0x0e, 0x0e, 0x63, 0x76, 0x74, 0x20, 0x00, 0x69, 0x1d, 0x39, 0x00, 0x00, 0x8f, 0x98, 0x00, 0x00, 0x01, 0xfe, 0x66, 0x70, 0x67, 0x6d, 0x71, 0x34, 0x76, 0x6a, 0x00, 0x00, 0x91, 0x98, 0x00, 0x00, 0x00, 0xab, 0x67, 0x61, 0x73, 0x70, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x92, 0x44, 0x00, 0x00, 0x00, 0x0c, 0x67, 0x6c, 0x79, 0x66, 0xbf, 0x93, 0x97, 0x69, 0x00, 0x00, 0x92, 0x50, 0x00, 0x06, 0x16, 0x80, 0x68, 0x65, 0x61, 0x64, 0x00, 0x93, 0x52, 0xd5, 0x00, 0x06, 0xa8, 0xd0, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0x31, 0x19, 0x73, 0x00, 0x06, 0xa9, 0x08, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0xd6, 0x38, 0x75, 0x2e, 0x00, 0x06, 0xa9, 0x2c, 0x00, 0x00, 0x48, 0x38, 0x6b, 0x65, 0x72, 0x6e, 0x87, 0x38, 0x36, 0x5f, 0x00, 0x06, 0xf1, 0x64, 0x00, 0x00, 0x3f, 0xfc, 0x6c, 0x6f, 0x63, 0x61, 0x2b, 0x97, 0xe6, 0xcc, 0x00, 0x07, 0x31, 0x60, 0x00, 0x00, 0x48, 0x3c, 0x6d, 0x61, 0x78, 0x70, 0x16, 0x7b, 0x04, 0x5b, 0x00, 0x07, 0x79, 0x9c, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0xf0, 0xf9, 0x25, 0x82, 0x00, 0x07, 0x79, 0xbc, 0x00, 0x00, 0x3d, 0xc5, 0x70, 0x6f, 0x73, 0x74, 0x6b, 0x1b, 0xc9, 0x76, 0x00, 0x07, 0xb7, 0x84, 0x00, 0x00, 0xb1, 0xbd, 0x70, 0x72, 0x65, 0x70, 0x3b, 0x07, 0xf1, 0x00, 0x00, 0x08, 0x69, 0x44, 0x00, 0x00, 0x05, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x89, 0x6f, 0x31, 0x00, 0x00, 0x00, 0x00, 0xce, 0x3f, 0xd8, 0x63, 0x00, 0x00, 0x00, 0x00, 0xce, 0x3f, 0xd8, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x56, 0x01, 0x5e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x36, 0x00, 0x03, 0x02, 0xb0, 0x00, 0x01, 0x02, 0xb1, 0x02, 0xc5, 0x00, 0x03, 0x02, 0xc6, 0x02, 0xc6, 0x00, 0x01, 0x02, 0xc7, 0x02, 0xca, 0x00, 0x03, 0x02, 0xcb, 0x02, 0xcc, 0x00, 0x01, 0x02, 0xcd, 0x02, 0xd1, 0x00, 0x03, 0x02, 0xd2, 0x02, 0xd3, 0x00, 0x01, 0x02, 0xd4, 0x02, 0xe4, 0x00, 0x03, 0x02, 0xe5, 0x02, 0xe9, 0x00, 0x01, 0x02, 0xea, 0x02, 0xf3, 0x00, 0x03, 0x02, 0xf4, 0x02, 0xf4, 0x00, 0x01, 0x02, 0xf5, 0x02, 0xf5, 0x00, 0x03, 0x02, 0xf6, 0x02, 0xf6, 0x00, 0x01, 0x02, 0xf7, 0x02, 0xff, 0x00, 0x03, 0x03, 0x00, 0x03, 0x00, 0x00, 0x01, 0x03, 0x01, 0x03, 0x04, 0x00, 0x03, 0x03, 0x05, 0x03, 0x05, 0x00, 0x01, 0x03, 0x06, 0x03, 0x06, 0x00, 0x03, 0x03, 0x07, 0x03, 0x07, 0x00, 0x01, 0x03, 0x08, 0x03, 0x09, 0x00, 0x03, 0x03, 0x0a, 0x03, 0x0a, 0x00, 0x01, 0x03, 0x0b, 0x03, 0x0c, 0x00, 0x03, 0x03, 0x0d, 0x04, 0x16, 0x00, 0x01, 0x04, 0x17, 0x04, 0x1b, 0x00, 0x03, 0x04, 0x1c, 0x05, 0x49, 0x00, 0x01, 0x05, 0x4a, 0x05, 0x4f, 0x00, 0x03, 0x05, 0x50, 0x07, 0x70, 0x00, 0x01, 0x07, 0x71, 0x07, 0x71, 0x00, 0x02, 0x07, 0x72, 0x07, 0x7b, 0x00, 0x01, 0x07, 0x7c, 0x07, 0x7e, 0x00, 0x02, 0x07, 0x7f, 0x07, 0xd1, 0x00, 0x01, 0x07, 0xd2, 0x07, 0xd2, 0x00, 0x02, 0x07, 0xd3, 0x07, 0xe2, 0x00, 0x01, 0x07, 0xe3, 0x07, 0xe9, 0x00, 0x03, 0x07, 0xea, 0x07, 0xea, 0x00, 0x02, 0x07, 0xeb, 0x07, 0xee, 0x00, 0x01, 0x07, 0xef, 0x07, 0xf0, 0x00, 0x02, 0x07, 0xf1, 0x08, 0x08, 0x00, 0x01, 0x08, 0x09, 0x08, 0x0a, 0x00, 0x02, 0x08, 0x0b, 0x08, 0x23, 0x00, 0x01, 0x08, 0x24, 0x08, 0x24, 0x00, 0x02, 0x08, 0x25, 0x0f, 0x08, 0x00, 0x01, 0x0f, 0x09, 0x0f, 0x0f, 0x00, 0x02, 0x0f, 0x10, 0x0f, 0x10, 0x00, 0x01, 0x0f, 0x11, 0x0f, 0x11, 0x00, 0x03, 0x0f, 0x12, 0x0f, 0x12, 0x00, 0x01, 0x0f, 0x13, 0x0f, 0x13, 0x00, 0x03, 0x0f, 0x14, 0x10, 0xea, 0x00, 0x01, 0x10, 0xeb, 0x10, 0xf5, 0x00, 0x03, 0x10, 0xf6, 0x11, 0x49, 0x00, 0x01, 0x11, 0x4a, 0x11, 0x51, 0x00, 0x03, 0x11, 0x52, 0x11, 0xab, 0x00, 0x01, 0x11, 0xac, 0x11, 0xac, 0x00, 0x03, 0x11, 0xad, 0x12, 0x0d, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x02, 0xb1, 0x02, 0xc6, 0x00, 0x01, 0x02, 0xc7, 0x02, 0xca, 0x00, 0x02, 0x02, 0xcd, 0x02, 0xd7, 0x00, 0x02, 0x02, 0xd8, 0x02, 0xd8, 0x00, 0x03, 0x02, 0xd9, 0x02, 0xd9, 0x00, 0x04, 0x02, 0xda, 0x02, 0xe4, 0x00, 0x02, 0x02, 0xea, 0x02, 0xed, 0x00, 0x02, 0x02, 0xee, 0x02, 0xf5, 0x00, 0x01, 0x02, 0xf6, 0x02, 0xf6, 0x00, 0x02, 0x02, 0xf7, 0x02, 0xf7, 0x00, 0x01, 0x02, 0xf8, 0x02, 0xfa, 0x00, 0x02, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x01, 0x02, 0xfe, 0x02, 0xff, 0x00, 0x02, 0x03, 0x01, 0x03, 0x02, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x03, 0x04, 0x03, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x01, 0xd8, 0x02, 0x32, 0x00, 0x14, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x7a, 0x61, 0x72, 0x61, 0x62, 0x00, 0x86, 0x61, 0x72, 0x6d, 0x6e, 0x00, 0xa8, 0x62, 0x72, 0x61, 0x69, 0x00, 0xb4, 0x63, 0x61, 0x6e, 0x73, 0x00, 0xc0, 0x63, 0x68, 0x65, 0x72, 0x00, 0xcc, 0x63, 0x79, 0x72, 0x6c, 0x00, 0xd8, 0x67, 0x65, 0x6f, 0x72, 0x00, 0xf4, 0x67, 0x72, 0x65, 0x6b, 0x01, 0x00, 0x68, 0x61, 0x6e, 0x69, 0x01, 0x10, 0x68, 0x65, 0x62, 0x72, 0x01, 0x1c, 0x6b, 0x61, 0x6e, 0x61, 0x01, 0x2a, 0x6c, 0x61, 0x6f, 0x20, 0x01, 0x36, 0x6c, 0x61, 0x74, 0x6e, 0x01, 0x42, 0x6d, 0x61, 0x74, 0x68, 0x01, 0x82, 0x6e, 0x6b, 0x6f, 0x20, 0x01, 0x8e, 0x6f, 0x67, 0x61, 0x6d, 0x01, 0x9c, 0x72, 0x75, 0x6e, 0x72, 0x01, 0xa8, 0x74, 0x66, 0x6e, 0x67, 0x01, 0xb4, 0x74, 0x68, 0x61, 0x69, 0x01, 0xc2, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x4b, 0x55, 0x52, 0x20, 0x00, 0x16, 0x53, 0x4e, 0x44, 0x20, 0x00, 0x16, 0x55, 0x52, 0x44, 0x20, 0x00, 0x16, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x4d, 0x4b, 0x44, 0x20, 0x00, 0x10, 0x53, 0x52, 0x42, 0x20, 0x00, 0x10, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x34, 0x00, 0x08, 0x49, 0x53, 0x4d, 0x20, 0x00, 0x34, 0x4b, 0x53, 0x4d, 0x20, 0x00, 0x34, 0x4c, 0x53, 0x4d, 0x20, 0x00, 0x34, 0x4d, 0x4f, 0x4c, 0x20, 0x00, 0x34, 0x4e, 0x53, 0x4d, 0x20, 0x00, 0x34, 0x52, 0x4f, 0x4d, 0x20, 0x00, 0x34, 0x53, 0x4b, 0x53, 0x20, 0x00, 0x34, 0x53, 0x53, 0x4d, 0x20, 0x00, 0x34, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x2c, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x32, 0x6d, 0x61, 0x72, 0x6b, 0x00, 0x3a, 0x6d, 0x61, 0x72, 0x6b, 0x00, 0x40, 0x6d, 0x61, 0x72, 0x6b, 0x00, 0x48, 0x6d, 0x6b, 0x6d, 0x6b, 0x00, 0x4e, 0x6d, 0x6b, 0x6d, 0x6b, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x07, 0x00, 0x10, 0x00, 0x18, 0x00, 0x22, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x44, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x44, 0x00, 0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0xf0, 0x03, 0xd0, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, 0x08, 0x86, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xc0, 0x00, 0x04, 0x00, 0x04, 0x00, 0x06, 0x11, 0x72, 0x17, 0x1c, 0x17, 0x9c, 0x1b, 0x3a, 0x2c, 0x8e, 0x44, 0xde, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x46, 0x1c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x6d, 0xca, 0x00, 0x01, 0x00, 0x58, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x62, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x12, 0x00, 0x18, 0x00, 0x1e, 0x00, 0x24, 0x00, 0x2a, 0x00, 0x30, 0x00, 0x36, 0x00, 0x3c, 0x00, 0x01, 0x01, 0xcc, 0x08, 0xfc, 0x00, 0x01, 0x01, 0xcc, 0x09, 0xc4, 0x00, 0x01, 0x01, 0xcc, 0x08, 0xfc, 0x00, 0x01, 0x01, 0xcc, 0x08, 0x34, 0x00, 0x01, 0x01, 0xcc, 0x09, 0xc4, 0x00, 0x01, 0x01, 0xcc, 0x08, 0x34, 0x00, 0x01, 0x01, 0xcc, 0x07, 0xd0, 0x00, 0x01, 0x01, 0xcc, 0x09, 0x60, 0x00, 0x02, 0x00, 0x01, 0x11, 0x4a, 0x11, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x11, 0x4a, 0x11, 0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0x5a, 0x01, 0x26, 0x00, 0x01, 0x01, 0x94, 0x00, 0x0c, 0x00, 0x23, 0x00, 0x48, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x5a, 0x00, 0x60, 0x00, 0x66, 0x00, 0x6c, 0x00, 0x72, 0x00, 0x78, 0x00, 0x7e, 0x00, 0x84, 0x00, 0x8a, 0x00, 0x90, 0x00, 0x96, 0x00, 0x9c, 0x00, 0xa2, 0x00, 0xa8, 0x00, 0xae, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc0, 0x00, 0xc6, 0x00, 0xcc, 0x00, 0xd2, 0x00, 0xd8, 0x00, 0xde, 0x00, 0xe4, 0x00, 0xea, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfc, 0x01, 0x02, 0x01, 0x08, 0x01, 0x0e, 0x01, 0x14, 0x00, 0x01, 0xfe, 0x34, 0xfd, 0xde, 0x00, 0x01, 0xfe, 0x34, 0xfd, 0xde, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x15, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x15, 0x00, 0x01, 0xfe, 0x34, 0xfd, 0xda, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x15, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x15, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x15, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x89, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x89, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x89, 0x00, 0x01, 0xfe, 0x34, 0xfd, 0xda, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x14, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x74, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x74, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x15, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x1f, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x3b, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x18, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x15, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x38, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x38, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x38, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0xbf, 0x00, 0x01, 0xfe, 0x34, 0xfd, 0xda, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x1f, 0x00, 0x01, 0xfe, 0x35, 0xfe, 0x13, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x0b, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x0e, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x0e, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x0e, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x0e, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x0e, 0x00, 0x01, 0xfe, 0x34, 0xfe, 0x13, 0x00, 0x01, 0xfe, 0x34, 0xfd, 0xda, 0x00, 0x02, 0x00, 0x08, 0x02, 0xc7, 0x02, 0xca, 0x00, 0x00, 0x02, 0xcd, 0x02, 0xd1, 0x00, 0x04, 0x02, 0xd4, 0x02, 0xe2, 0x00, 0x09, 0x02, 0xea, 0x02, 0xed, 0x00, 0x18, 0x02, 0xf8, 0x02, 0xfa, 0x00, 0x1c, 0x02, 0xfe, 0x02, 0xff, 0x00, 0x1f, 0x03, 0x03, 0x03, 0x03, 0x00, 0x21, 0x03, 0x06, 0x03, 0x06, 0x00, 0x22, 0x00, 0x02, 0x00, 0x09, 0x02, 0xc7, 0x02, 0xca, 0x00, 0x00, 0x02, 0xcd, 0x02, 0xd1, 0x00, 0x04, 0x02, 0xd4, 0x02, 0xd7, 0x00, 0x09, 0x02, 0xda, 0x02, 0xe2, 0x00, 0x0d, 0x02, 0xea, 0x02, 0xed, 0x00, 0x16, 0x02, 0xf8, 0x02, 0xfa, 0x00, 0x1a, 0x02, 0xfe, 0x02, 0xff, 0x00, 0x1d, 0x03, 0x03, 0x03, 0x03, 0x00, 0x1f, 0x03, 0x06, 0x03, 0x06, 0x00, 0x20, 0x00, 0x21, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x46, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x35, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0x02, 0x42, 0x01, 0xde, 0x00, 0x01, 0x02, 0x8e, 0x00, 0x0c, 0x00, 0x3a, 0x00, 0x76, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x88, 0x00, 0x8e, 0x00, 0x94, 0x00, 0x9a, 0x00, 0xa0, 0x00, 0xa6, 0x00, 0xac, 0x00, 0xb2, 0x00, 0xb8, 0x00, 0xbe, 0x00, 0xc4, 0x00, 0xca, 0x00, 0xd0, 0x00, 0xd6, 0x00, 0xdc, 0x00, 0xe2, 0x00, 0xe8, 0x00, 0xee, 0x00, 0xf4, 0x00, 0xfa, 0x01, 0x00, 0x01, 0x06, 0x01, 0x0c, 0x01, 0x12, 0x01, 0x18, 0x01, 0x1e, 0x01, 0x24, 0x01, 0x2a, 0x01, 0x30, 0x01, 0x36, 0x01, 0x3c, 0x01, 0x42, 0x01, 0x48, 0x01, 0x4e, 0x01, 0x54, 0x01, 0x5a, 0x01, 0x60, 0x01, 0x66, 0x01, 0x6c, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7e, 0x01, 0x84, 0x01, 0x8a, 0x01, 0x90, 0x01, 0x96, 0x01, 0x9c, 0x01, 0xa2, 0x01, 0xa8, 0x01, 0xae, 0x01, 0xb4, 0x01, 0xba, 0x01, 0xc0, 0x01, 0xc6, 0x01, 0xcc, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x3d, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x44, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0xc5, 0x00, 0x01, 0xfe, 0x34, 0x07, 0x04, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0xa8, 0x00, 0x01, 0xfe, 0x34, 0x06, 0xa8, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x07, 0x56, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x44, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x93, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x3d, 0x00, 0x01, 0xfe, 0x34, 0x07, 0xd0, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x44, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x44, 0x00, 0x01, 0xfe, 0x34, 0x07, 0x04, 0x00, 0x01, 0xfe, 0x34, 0x07, 0x04, 0x00, 0x01, 0xfe, 0x34, 0x07, 0x04, 0x00, 0x01, 0xfe, 0x34, 0x06, 0xda, 0x00, 0x01, 0xfe, 0x34, 0x07, 0x04, 0x00, 0x01, 0x00, 0x00, 0x07, 0x6e, 0x00, 0x01, 0x00, 0x00, 0x07, 0x6e, 0x00, 0x01, 0x00, 0x00, 0x07, 0x6e, 0x00, 0x01, 0x00, 0x00, 0x07, 0x6e, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x68, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x14, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xf8, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xf8, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xf8, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xf8, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xf8, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xf8, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xdb, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xf8, 0x00, 0x01, 0xfe, 0x34, 0x05, 0xf8, 0x00, 0x01, 0xfe, 0x34, 0x06, 0x1e, 0x00, 0x02, 0x00, 0x10, 0x02, 0xb1, 0x02, 0xc2, 0x00, 0x00, 0x02, 0xee, 0x02, 0xee, 0x00, 0x12, 0x02, 0xf0, 0x02, 0xf3, 0x00, 0x13, 0x02, 0xf5, 0x02, 0xf5, 0x00, 0x17, 0x02, 0xf7, 0x02, 0xf7, 0x00, 0x18, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x19, 0x03, 0x01, 0x03, 0x02, 0x00, 0x1c, 0x03, 0x04, 0x03, 0x04, 0x00, 0x1e, 0x03, 0x08, 0x03, 0x09, 0x00, 0x1f, 0x03, 0x0b, 0x03, 0x0c, 0x00, 0x21, 0x05, 0x4a, 0x05, 0x4f, 0x00, 0x23, 0x07, 0xe3, 0x07, 0xe9, 0x00, 0x29, 0x10, 0xeb, 0x10, 0xeb, 0x00, 0x30, 0x10, 0xed, 0x10, 0xed, 0x00, 0x31, 0x10, 0xef, 0x10, 0xf5, 0x00, 0x32, 0x11, 0xac, 0x11, 0xac, 0x00, 0x39, 0x00, 0x02, 0x00, 0x0c, 0x02, 0xb1, 0x02, 0xc2, 0x00, 0x00, 0x02, 0xee, 0x02, 0xee, 0x00, 0x12, 0x02, 0xf0, 0x02, 0xf3, 0x00, 0x13, 0x02, 0xf5, 0x02, 0xf5, 0x00, 0x17, 0x02, 0xf7, 0x02, 0xf7, 0x00, 0x18, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x19, 0x03, 0x01, 0x03, 0x02, 0x00, 0x1c, 0x03, 0x04, 0x03, 0x04, 0x00, 0x1e, 0x05, 0x4a, 0x05, 0x4f, 0x00, 0x1f, 0x07, 0xe3, 0x07, 0xe9, 0x00, 0x25, 0x10, 0xeb, 0x10, 0xf5, 0x00, 0x2c, 0x11, 0xac, 0x11, 0xac, 0x00, 0x37, 0x00, 0x38, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x01, 0x4e, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x01, 0x5a, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x01, 0x8a, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x01, 0x96, 0x00, 0x00, 0x01, 0x9c, 0x00, 0x00, 0x01, 0xa2, 0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x01, 0xae, 0x00, 0x00, 0x01, 0xb4, 0x00, 0x00, 0x01, 0xba, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc6, 0x00, 0x00, 0x01, 0xcc, 0x00, 0x00, 0x01, 0xd2, 0x00, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x01, 0xde, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x01, 0xea, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x01, 0xf6, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x26, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0xb0, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0xb0, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x05, 0x02, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0x06, 0xe6, 0x06, 0xbe, 0x00, 0x01, 0x06, 0xf0, 0x00, 0x0c, 0x00, 0xd6, 0x01, 0xae, 0x01, 0xb4, 0x01, 0xba, 0x01, 0xc0, 0x01, 0xc6, 0x01, 0xcc, 0x01, 0xd2, 0x01, 0xd8, 0x01, 0xde, 0x01, 0xe4, 0x01, 0xea, 0x01, 0xf0, 0x01, 0xf6, 0x01, 0xfc, 0x02, 0x02, 0x02, 0x08, 0x02, 0x0e, 0x02, 0x14, 0x02, 0x1a, 0x02, 0x20, 0x02, 0x26, 0x02, 0x2c, 0x02, 0x32, 0x02, 0x38, 0x02, 0x3e, 0x02, 0x44, 0x02, 0x4a, 0x02, 0x50, 0x02, 0x56, 0x02, 0x5c, 0x02, 0x62, 0x02, 0x68, 0x02, 0x6e, 0x02, 0x74, 0x02, 0x7a, 0x02, 0x80, 0x02, 0x86, 0x02, 0x8c, 0x02, 0x92, 0x02, 0x98, 0x02, 0x9e, 0x02, 0xa4, 0x02, 0xaa, 0x02, 0xb0, 0x02, 0xb6, 0x02, 0xbc, 0x02, 0xc2, 0x02, 0xc8, 0x02, 0xce, 0x02, 0xd4, 0x02, 0xda, 0x02, 0xe0, 0x02, 0xe6, 0x02, 0xec, 0x02, 0xf2, 0x02, 0xf8, 0x02, 0xfe, 0x03, 0x04, 0x03, 0x0a, 0x03, 0x10, 0x03, 0x16, 0x03, 0x1c, 0x03, 0x22, 0x03, 0x28, 0x03, 0x2e, 0x03, 0x34, 0x03, 0x3a, 0x03, 0x40, 0x03, 0x46, 0x03, 0x4c, 0x03, 0x52, 0x03, 0x58, 0x03, 0x5e, 0x03, 0x64, 0x03, 0x6a, 0x03, 0x70, 0x03, 0x76, 0x03, 0x7c, 0x03, 0x82, 0x03, 0x88, 0x03, 0x8e, 0x03, 0x94, 0x03, 0x9a, 0x03, 0xa0, 0x03, 0xa6, 0x03, 0xac, 0x03, 0xb2, 0x03, 0xb8, 0x03, 0xbe, 0x03, 0xc4, 0x03, 0xca, 0x03, 0xd0, 0x03, 0xd6, 0x03, 0xdc, 0x03, 0xe2, 0x03, 0xe8, 0x03, 0xee, 0x03, 0xf4, 0x03, 0xfa, 0x04, 0x00, 0x04, 0x06, 0x04, 0x0c, 0x04, 0x12, 0x04, 0x18, 0x04, 0x1e, 0x04, 0x24, 0x04, 0x2a, 0x04, 0x30, 0x04, 0x36, 0x04, 0x3c, 0x04, 0x42, 0x04, 0x48, 0x04, 0x4e, 0x04, 0x54, 0x04, 0x5a, 0x04, 0x60, 0x04, 0x66, 0x04, 0x6c, 0x04, 0x72, 0x04, 0x78, 0x04, 0x7e, 0x04, 0x84, 0x04, 0x8a, 0x04, 0x90, 0x04, 0x96, 0x04, 0x9c, 0x04, 0xa2, 0x04, 0xa8, 0x04, 0xae, 0x04, 0xb4, 0x04, 0xba, 0x04, 0xc0, 0x04, 0xc6, 0x04, 0xcc, 0x04, 0xd2, 0x04, 0xd8, 0x04, 0xde, 0x04, 0xe4, 0x04, 0xea, 0x04, 0xf0, 0x04, 0xf6, 0x04, 0xfc, 0x05, 0x02, 0x05, 0x08, 0x05, 0x0e, 0x05, 0x14, 0x05, 0x1a, 0x05, 0x20, 0x05, 0x26, 0x05, 0x2c, 0x05, 0x32, 0x05, 0x38, 0x05, 0x3e, 0x05, 0x44, 0x05, 0x4a, 0x05, 0x50, 0x05, 0x56, 0x05, 0x5c, 0x05, 0x62, 0x05, 0x68, 0x05, 0x6e, 0x05, 0x74, 0x05, 0x7a, 0x05, 0x80, 0x05, 0x86, 0x05, 0x8c, 0x05, 0x92, 0x05, 0x98, 0x05, 0x9e, 0x05, 0xa4, 0x05, 0xaa, 0x05, 0xb0, 0x05, 0xb6, 0x05, 0xbc, 0x05, 0xc2, 0x05, 0xc8, 0x05, 0xce, 0x05, 0xd4, 0x05, 0xda, 0x05, 0xe0, 0x05, 0xe6, 0x05, 0xec, 0x05, 0xf2, 0x05, 0xf8, 0x05, 0xfe, 0x06, 0x04, 0x06, 0x0a, 0x06, 0x10, 0x06, 0x16, 0x06, 0x1c, 0x06, 0x22, 0x06, 0x28, 0x06, 0x2e, 0x06, 0x34, 0x06, 0x3a, 0x06, 0x40, 0x06, 0x46, 0x06, 0x4c, 0x06, 0x52, 0x06, 0x58, 0x06, 0x5e, 0x06, 0x64, 0x06, 0x6a, 0x06, 0x70, 0x06, 0x76, 0x06, 0x7c, 0x06, 0x82, 0x06, 0x88, 0x06, 0x8e, 0x06, 0x94, 0x06, 0x9a, 0x06, 0xa0, 0x06, 0xa6, 0x06, 0xac, 0x00, 0x01, 0x03, 0x2a, 0x03, 0xe8, 0x00, 0x01, 0x01, 0x0d, 0x03, 0xe8, 0x00, 0x01, 0x01, 0x0d, 0x03, 0xe8, 0x00, 0x01, 0x02, 0x76, 0x04, 0x4c, 0x00, 0x01, 0x01, 0xc2, 0x04, 0x4c, 0x00, 0x01, 0x01, 0xd2, 0x03, 0xb6, 0x00, 0x01, 0x01, 0xc2, 0x03, 0x52, 0x00, 0x01, 0x01, 0xc2, 0x04, 0x4c, 0x00, 0x01, 0x01, 0xd2, 0x03, 0xb6, 0x00, 0x01, 0x01, 0x0d, 0x04, 0x1a, 0x00, 0x01, 0x01, 0x0d, 0x04, 0x1a, 0x00, 0x01, 0x03, 0x2a, 0x03, 0x52, 0x00, 0x01, 0x01, 0x0d, 0x04, 0x1a, 0x00, 0x01, 0x01, 0x0d, 0x04, 0x1a, 0x00, 0x01, 0x03, 0x2a, 0x03, 0xe8, 0x00, 0x01, 0x01, 0x0d, 0x05, 0x14, 0x00, 0x01, 0x01, 0x0d, 0x05, 0x14, 0x00, 0x01, 0x02, 0x49, 0x06, 0x0e, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xaa, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xaa, 0x00, 0x01, 0x02, 0x49, 0x05, 0xdc, 0x00, 0x01, 0x02, 0x1c, 0x05, 0x78, 0x00, 0x01, 0x02, 0x1c, 0x05, 0x78, 0x00, 0x01, 0x02, 0x49, 0x05, 0xdc, 0x00, 0x01, 0x02, 0x1c, 0x05, 0x78, 0x00, 0x01, 0x02, 0x1c, 0x05, 0x78, 0x00, 0x01, 0x02, 0x49, 0x04, 0xe2, 0x00, 0x01, 0x02, 0x1c, 0x04, 0x7e, 0x00, 0x01, 0x02, 0x1c, 0x04, 0x7e, 0x00, 0x01, 0x02, 0x76, 0x02, 0xee, 0x00, 0x01, 0x02, 0x76, 0x02, 0xee, 0x00, 0x01, 0x04, 0x42, 0x08, 0x34, 0x00, 0x01, 0x01, 0x31, 0x08, 0x34, 0x00, 0x01, 0x01, 0x31, 0x08, 0x34, 0x00, 0x01, 0x02, 0x76, 0x03, 0xb6, 0x00, 0x01, 0x01, 0x0d, 0x04, 0xb0, 0x00, 0x01, 0x01, 0x0d, 0x04, 0xb0, 0x00, 0x01, 0x02, 0x76, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xef, 0x03, 0x52, 0x00, 0x01, 0x01, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x0e, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x0e, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x0e, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x80, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x80, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x80, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x21, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x21, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x21, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x23, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x23, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x23, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xb0, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xb0, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xb0, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xdd, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xdd, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xdd, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x63, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x63, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x63, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x7e, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x7e, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x7e, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x69, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x69, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x69, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xad, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xad, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xad, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd2, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd2, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd2, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf2, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf2, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xf2, 0x00, 0x01, 0x02, 0x40, 0x05, 0xf2, 0x00, 0x01, 0x02, 0x40, 0x05, 0xf2, 0x00, 0x01, 0x02, 0x40, 0x05, 0xf2, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x52, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x52, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x52, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xad, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xad, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xad, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x40, 0x05, 0xf2, 0x00, 0x01, 0x02, 0x40, 0x05, 0xf2, 0x00, 0x01, 0x02, 0x40, 0x05, 0xf2, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xca, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xe5, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xe5, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xe5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x68, 0x03, 0xe8, 0x00, 0x01, 0x01, 0x68, 0x03, 0xe8, 0x00, 0x01, 0x01, 0x95, 0x06, 0x40, 0x00, 0x01, 0x01, 0x95, 0x05, 0xaa, 0x00, 0x01, 0x01, 0x95, 0x05, 0xdc, 0x00, 0x01, 0x02, 0x76, 0x02, 0xee, 0x00, 0x01, 0x02, 0x76, 0x02, 0xee, 0x00, 0x01, 0x02, 0x76, 0x02, 0xee, 0x00, 0x01, 0x02, 0x76, 0x03, 0xe8, 0x00, 0x01, 0x02, 0x76, 0x04, 0xe2, 0x00, 0x01, 0x02, 0x1c, 0x03, 0x20, 0x00, 0x01, 0x02, 0xfd, 0x04, 0x1a, 0x00, 0x01, 0x02, 0xfd, 0x04, 0x1a, 0x00, 0x01, 0x02, 0x1c, 0x03, 0x20, 0x00, 0x01, 0x02, 0x49, 0x03, 0x84, 0x00, 0x01, 0x02, 0x49, 0x03, 0x84, 0x00, 0x01, 0x02, 0x1c, 0x03, 0x20, 0x00, 0x01, 0x02, 0xfd, 0x04, 0xe2, 0x00, 0x01, 0x02, 0xfd, 0x04, 0xe2, 0x00, 0x01, 0x02, 0x1c, 0x03, 0x20, 0x00, 0x01, 0x01, 0xef, 0x03, 0x20, 0x00, 0x01, 0x01, 0xef, 0x03, 0x20, 0x00, 0x01, 0x02, 0x1c, 0x03, 0x20, 0x00, 0x01, 0x02, 0x1c, 0x04, 0xe2, 0x00, 0x01, 0x02, 0x1c, 0x04, 0xe2, 0x00, 0x01, 0x02, 0x1e, 0x06, 0x72, 0x00, 0x01, 0x01, 0x31, 0x06, 0x72, 0x00, 0x01, 0x01, 0x31, 0x06, 0x72, 0x00, 0x01, 0x01, 0xc2, 0x05, 0x78, 0x00, 0x01, 0x01, 0xc2, 0x06, 0x72, 0x00, 0x01, 0x01, 0xbc, 0x05, 0x78, 0x00, 0x01, 0x02, 0x76, 0x04, 0x4c, 0x00, 0x01, 0x01, 0xc2, 0x04, 0x4c, 0x00, 0x01, 0x01, 0xd2, 0x03, 0xb6, 0x00, 0x01, 0x02, 0x76, 0x04, 0x4c, 0x00, 0x01, 0x01, 0xc2, 0x05, 0x46, 0x00, 0x01, 0x01, 0xd2, 0x04, 0xb0, 0x00, 0x01, 0x02, 0x76, 0x04, 0x4c, 0x00, 0x01, 0x01, 0xc2, 0x04, 0x4c, 0x00, 0x01, 0x01, 0xd2, 0x03, 0xb6, 0x00, 0x01, 0x01, 0xc2, 0x03, 0x52, 0x00, 0x01, 0x01, 0xc2, 0x05, 0x46, 0x00, 0x01, 0x01, 0xd2, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xc2, 0x03, 0x52, 0x00, 0x01, 0x01, 0xc2, 0x06, 0x40, 0x00, 0x01, 0x01, 0xd2, 0x05, 0xaa, 0x00, 0x01, 0x01, 0xc2, 0x05, 0x78, 0x00, 0x01, 0x00, 0x6c, 0x05, 0x78, 0x00, 0x01, 0x00, 0x6c, 0x05, 0x78, 0x00, 0x01, 0x01, 0xc2, 0x05, 0x78, 0x00, 0x01, 0x00, 0xe1, 0x06, 0x0e, 0x00, 0x01, 0x00, 0xe1, 0x06, 0x0e, 0x00, 0x01, 0x02, 0xe6, 0x06, 0x0e, 0x00, 0x01, 0x00, 0xf7, 0x06, 0xa4, 0x00, 0x01, 0x00, 0xf7, 0x06, 0xa4, 0x00, 0x01, 0x02, 0x76, 0x05, 0xdc, 0x00, 0x01, 0x00, 0xe1, 0x06, 0x0e, 0x00, 0x01, 0x00, 0xe1, 0x06, 0x0e, 0x00, 0x01, 0x01, 0xc2, 0x05, 0x78, 0x00, 0x01, 0x00, 0xe1, 0x06, 0xa4, 0x00, 0x01, 0x00, 0xe1, 0x06, 0xa4, 0x00, 0x01, 0x01, 0xc2, 0x05, 0x78, 0x00, 0x01, 0x00, 0xe1, 0x06, 0xa4, 0x00, 0x01, 0x00, 0xe1, 0x06, 0xa4, 0x00, 0x01, 0x01, 0xc2, 0x05, 0x78, 0x00, 0x01, 0x00, 0xf7, 0x08, 0x66, 0x00, 0x01, 0x00, 0xf7, 0x08, 0x66, 0x00, 0x01, 0x04, 0x42, 0x08, 0x34, 0x00, 0x01, 0x01, 0x31, 0x08, 0x34, 0x00, 0x01, 0x01, 0x31, 0x08, 0x34, 0x00, 0x01, 0x04, 0x42, 0x08, 0x66, 0x00, 0x01, 0x01, 0x31, 0x08, 0x66, 0x00, 0x01, 0x01, 0x31, 0x08, 0x66, 0x00, 0x01, 0x02, 0x49, 0x05, 0x14, 0x00, 0x01, 0x01, 0x31, 0x06, 0x72, 0x00, 0x01, 0x01, 0x31, 0x06, 0x72, 0x00, 0x01, 0x02, 0x49, 0x02, 0xee, 0x00, 0x01, 0x01, 0x0d, 0x04, 0x1a, 0x00, 0x01, 0x01, 0x0d, 0x04, 0x1a, 0x00, 0x01, 0x02, 0x49, 0x02, 0xee, 0x00, 0x01, 0x01, 0x0d, 0x04, 0x1a, 0x00, 0x01, 0x01, 0x0d, 0x04, 0x1a, 0x00, 0x01, 0x02, 0x76, 0x03, 0xe8, 0x00, 0x01, 0x01, 0x0d, 0x05, 0x14, 0x00, 0x01, 0x01, 0x0d, 0x05, 0x14, 0x00, 0x02, 0x00, 0x06, 0x10, 0xfc, 0x11, 0x06, 0x00, 0x00, 0x11, 0x08, 0x11, 0x19, 0x00, 0x0b, 0x11, 0x35, 0x11, 0x3d, 0x00, 0x1d, 0x11, 0x3f, 0x11, 0x3f, 0x00, 0x26, 0x11, 0x52, 0x11, 0xab, 0x00, 0x27, 0x11, 0xb9, 0x12, 0x0d, 0x00, 0x81, 0x00, 0x02, 0x00, 0x01, 0x11, 0x4a, 0x11, 0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x01, 0xcc, 0x04, 0xb0, 0x00, 0x01, 0x00, 0x20, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x00, 0x01, 0x00, 0xa9, 0x00, 0x02, 0x00, 0x09, 0x02, 0xc7, 0x02, 0xca, 0x00, 0x00, 0x02, 0xcd, 0x02, 0xd1, 0x00, 0x04, 0x02, 0xd4, 0x02, 0xd7, 0x00, 0x09, 0x02, 0xda, 0x02, 0xe4, 0x00, 0x0d, 0x02, 0xea, 0x02, 0xed, 0x00, 0x18, 0x02, 0xf8, 0x02, 0xfa, 0x00, 0x1c, 0x02, 0xfe, 0x02, 0xff, 0x00, 0x1f, 0x03, 0x03, 0x03, 0x03, 0x00, 0x21, 0x03, 0x06, 0x03, 0x06, 0x00, 0x22, 0x00, 0x23, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x01, 0x4e, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x01, 0x5a, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xfe, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xfe, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x35, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0x05, 0x8c, 0x04, 0xb6, 0x00, 0x01, 0x05, 0x94, 0x00, 0x0c, 0x00, 0x95, 0x01, 0x2c, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01, 0x44, 0x01, 0x4a, 0x01, 0x50, 0x01, 0x56, 0x01, 0x5c, 0x01, 0x62, 0x01, 0x68, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x7a, 0x01, 0x80, 0x01, 0x86, 0x01, 0x8c, 0x01, 0x92, 0x01, 0x98, 0x01, 0x9e, 0x01, 0xa4, 0x01, 0xaa, 0x01, 0xb0, 0x01, 0xb6, 0x01, 0xbc, 0x01, 0xc2, 0x01, 0xc8, 0x01, 0xce, 0x01, 0xd4, 0x01, 0xda, 0x01, 0xe0, 0x01, 0xe6, 0x01, 0xec, 0x01, 0xf2, 0x01, 0xf8, 0x01, 0xfe, 0x02, 0x04, 0x02, 0x0a, 0x02, 0x10, 0x02, 0x16, 0x02, 0x1c, 0x02, 0x22, 0x02, 0x28, 0x02, 0x2e, 0x02, 0x34, 0x02, 0x3a, 0x02, 0x40, 0x02, 0x46, 0x02, 0x4c, 0x02, 0x52, 0x02, 0x58, 0x02, 0x5e, 0x02, 0x64, 0x02, 0x6a, 0x02, 0x70, 0x02, 0x76, 0x02, 0x7c, 0x02, 0x82, 0x02, 0x88, 0x02, 0x8e, 0x02, 0x94, 0x02, 0x9a, 0x02, 0xa0, 0x02, 0xa6, 0x02, 0xac, 0x02, 0xb2, 0x02, 0xb8, 0x02, 0xbe, 0x02, 0xc4, 0x02, 0xca, 0x02, 0xd0, 0x02, 0xd6, 0x02, 0xdc, 0x02, 0xe2, 0x02, 0xe8, 0x02, 0xee, 0x02, 0xf4, 0x02, 0xfa, 0x03, 0x00, 0x03, 0x06, 0x03, 0x0c, 0x03, 0x12, 0x03, 0x18, 0x03, 0x1e, 0x03, 0x24, 0x03, 0x2a, 0x03, 0x30, 0x03, 0x36, 0x03, 0x3c, 0x03, 0x42, 0x03, 0x48, 0x03, 0x4e, 0x03, 0x54, 0x03, 0x5a, 0x03, 0x60, 0x03, 0x66, 0x03, 0x6c, 0x03, 0x72, 0x03, 0x78, 0x03, 0x7e, 0x03, 0x84, 0x03, 0x8a, 0x03, 0x90, 0x03, 0x96, 0x03, 0x9c, 0x03, 0xa2, 0x03, 0xa8, 0x03, 0xae, 0x03, 0xb4, 0x03, 0xba, 0x03, 0xc0, 0x03, 0xc6, 0x03, 0xcc, 0x03, 0xd2, 0x03, 0xd8, 0x03, 0xde, 0x03, 0xe4, 0x03, 0xea, 0x03, 0xf0, 0x03, 0xf6, 0x03, 0xfc, 0x04, 0x02, 0x04, 0x08, 0x04, 0x0e, 0x04, 0x14, 0x04, 0x1a, 0x04, 0x20, 0x04, 0x26, 0x04, 0x2c, 0x04, 0x32, 0x04, 0x38, 0x04, 0x3e, 0x04, 0x44, 0x04, 0x4a, 0x04, 0x50, 0x04, 0x56, 0x04, 0x5c, 0x04, 0x62, 0x04, 0x68, 0x04, 0x6e, 0x04, 0x74, 0x04, 0x7a, 0x04, 0x80, 0x04, 0x86, 0x04, 0x8c, 0x04, 0x92, 0x04, 0x98, 0x04, 0x9e, 0x04, 0xa4, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x02, 0x00, 0x23, 0x00, 0x24, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x44, 0x00, 0x5d, 0x00, 0x1a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x34, 0x00, 0xba, 0x00, 0xba, 0x00, 0x35, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0x36, 0x00, 0xd0, 0x00, 0xd1, 0x00, 0x38, 0x00, 0xf3, 0x00, 0xf3, 0x00, 0x3a, 0x01, 0x28, 0x01, 0x29, 0x00, 0x3b, 0x01, 0x41, 0x01, 0x41, 0x00, 0x3d, 0x01, 0x48, 0x01, 0x48, 0x00, 0x3e, 0x01, 0x51, 0x01, 0x52, 0x00, 0x3f, 0x01, 0x59, 0x01, 0x59, 0x00, 0x41, 0x01, 0x61, 0x01, 0x61, 0x00, 0x42, 0x01, 0x79, 0x01, 0x7b, 0x00, 0x43, 0x02, 0x12, 0x02, 0x12, 0x00, 0x46, 0x02, 0x16, 0x02, 0x16, 0x00, 0x47, 0x02, 0x1b, 0x02, 0x1b, 0x00, 0x48, 0x02, 0x1d, 0x02, 0x1d, 0x00, 0x49, 0x02, 0x2a, 0x02, 0x2a, 0x00, 0x4a, 0x02, 0x37, 0x02, 0x37, 0x00, 0x4b, 0x02, 0x54, 0x02, 0x54, 0x00, 0x4c, 0x05, 0x23, 0x05, 0x23, 0x00, 0x4d, 0x05, 0x5a, 0x05, 0x63, 0x00, 0x4e, 0x0e, 0x38, 0x0e, 0x3a, 0x00, 0x58, 0x0e, 0x3d, 0x0e, 0x3e, 0x00, 0x5b, 0x0e, 0x44, 0x0e, 0x44, 0x00, 0x5d, 0x0e, 0x48, 0x0e, 0x49, 0x00, 0x5e, 0x0e, 0x62, 0x0e, 0x65, 0x00, 0x60, 0x0e, 0x6b, 0x0e, 0x75, 0x00, 0x64, 0x0e, 0x78, 0x0e, 0x81, 0x00, 0x6f, 0x0e, 0x83, 0x0e, 0x87, 0x00, 0x79, 0x0e, 0x8c, 0x0e, 0x8f, 0x00, 0x7e, 0x0e, 0x96, 0x0e, 0xa2, 0x00, 0x82, 0x0e, 0xa4, 0x0e, 0xa8, 0x00, 0x8f, 0x11, 0x1c, 0x11, 0x1c, 0x00, 0x94, 0x00, 0x01, 0x00, 0x02, 0x0f, 0x11, 0x0f, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x00, 0x62, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x6a, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x12, 0x00, 0x18, 0x00, 0x1e, 0x00, 0x24, 0x00, 0x2a, 0x00, 0x30, 0x00, 0x36, 0x00, 0x3c, 0x00, 0x01, 0x02, 0x0f, 0x06, 0x14, 0x00, 0x01, 0x02, 0xa1, 0x07, 0x6d, 0x00, 0x01, 0x02, 0x53, 0x06, 0x14, 0x00, 0x01, 0x01, 0x02, 0x06, 0x14, 0x00, 0x01, 0x02, 0x34, 0x06, 0x14, 0x00, 0x01, 0x02, 0x3d, 0x06, 0x14, 0x00, 0x01, 0x02, 0xa1, 0x07, 0x50, 0x00, 0x01, 0x03, 0x97, 0x07, 0x89, 0x00, 0x01, 0x00, 0x08, 0x00, 0xc3, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xed, 0x01, 0x0f, 0x01, 0x2d, 0x05, 0x5a, 0x05, 0x5b, 0x00, 0x01, 0x00, 0x02, 0x02, 0xb1, 0x02, 0xb2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x8c, 0x02, 0xd6, 0x00, 0x01, 0x03, 0x92, 0x00, 0x0c, 0x00, 0x59, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc0, 0x00, 0xc6, 0x00, 0xcc, 0x00, 0xd2, 0x00, 0xd8, 0x00, 0xde, 0x00, 0xe4, 0x00, 0xea, 0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfc, 0x01, 0x02, 0x01, 0x08, 0x01, 0x0e, 0x01, 0x14, 0x01, 0x1a, 0x01, 0x20, 0x01, 0x26, 0x01, 0x2c, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3e, 0x01, 0x44, 0x01, 0x4a, 0x01, 0x50, 0x01, 0x56, 0x01, 0x5c, 0x01, 0x62, 0x01, 0x68, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x7a, 0x01, 0x80, 0x01, 0x86, 0x01, 0x8c, 0x01, 0x92, 0x01, 0x98, 0x01, 0x9e, 0x01, 0xa4, 0x01, 0xaa, 0x01, 0xb0, 0x01, 0xb6, 0x01, 0xbc, 0x01, 0xc2, 0x01, 0xc8, 0x01, 0xce, 0x01, 0xd4, 0x01, 0xda, 0x01, 0xe0, 0x01, 0xe6, 0x01, 0xec, 0x01, 0xf2, 0x01, 0xf8, 0x01, 0xfe, 0x02, 0x04, 0x02, 0x0a, 0x02, 0x10, 0x02, 0x16, 0x02, 0x1c, 0x02, 0x22, 0x02, 0x28, 0x02, 0x2e, 0x02, 0x34, 0x02, 0x3a, 0x02, 0x40, 0x02, 0x46, 0x02, 0x4c, 0x02, 0x52, 0x02, 0x58, 0x02, 0x5e, 0x02, 0x64, 0x02, 0x6a, 0x02, 0x70, 0x02, 0x76, 0x02, 0x7c, 0x02, 0x82, 0x02, 0x88, 0x02, 0x8e, 0x02, 0x94, 0x02, 0x9a, 0x02, 0xa0, 0x02, 0xa6, 0x02, 0xac, 0x02, 0xb2, 0x02, 0xb8, 0x02, 0xbe, 0x02, 0xc4, 0x00, 0x01, 0x04, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x02, 0xf7, 0x00, 0x00, 0x00, 0x01, 0x01, 0xf5, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5e, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x03, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x28, 0x00, 0x00, 0x00, 0x01, 0x02, 0x53, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x01, 0xf6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x03, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x04, 0x7f, 0xfe, 0x80, 0x00, 0x01, 0x03, 0x6f, 0xfe, 0x80, 0x00, 0x01, 0x02, 0x53, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x7d, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x02, 0x53, 0x00, 0x00, 0x00, 0x01, 0x02, 0x47, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x46, 0x00, 0x00, 0x00, 0x01, 0x01, 0x95, 0x00, 0x00, 0x00, 0x01, 0x02, 0x16, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x05, 0xd5, 0x00, 0x00, 0x00, 0x01, 0x04, 0xec, 0x00, 0x00, 0x00, 0x01, 0x05, 0x96, 0x00, 0x00, 0x00, 0x01, 0x04, 0xbd, 0x00, 0x00, 0x00, 0x01, 0x02, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x02, 0x85, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5e, 0x00, 0x00, 0x00, 0x01, 0x01, 0xf6, 0x00, 0x00, 0x00, 0x01, 0x01, 0x69, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0xfe, 0x52, 0x00, 0x01, 0x00, 0x59, 0x00, 0x24, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x2b, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x36, 0x00, 0x38, 0x00, 0x3d, 0x00, 0x44, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x56, 0x00, 0x58, 0x00, 0x5d, 0x00, 0x8e, 0x00, 0x8f, 0x00, 0x90, 0x00, 0x91, 0x00, 0x9a, 0x00, 0xae, 0x00, 0xaf, 0x00, 0xb0, 0x00, 0xb1, 0x00, 0xba, 0x00, 0xc3, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xd5, 0x00, 0xea, 0x00, 0xeb, 0x00, 0xec, 0x00, 0xed, 0x00, 0xee, 0x00, 0xef, 0x00, 0xf2, 0x00, 0xf3, 0x01, 0x0f, 0x01, 0x2d, 0x01, 0x48, 0x01, 0x51, 0x01, 0x52, 0x01, 0x59, 0x01, 0x61, 0x01, 0x79, 0x01, 0x7a, 0x01, 0x7b, 0x01, 0x91, 0x01, 0x92, 0x01, 0xca, 0x01, 0xcb, 0x01, 0xcc, 0x01, 0xcd, 0x02, 0x12, 0x02, 0x16, 0x02, 0x1b, 0x02, 0x1d, 0x02, 0x2a, 0x02, 0x37, 0x02, 0x54, 0x05, 0x7e, 0x05, 0x7f, 0x06, 0x18, 0x06, 0x19, 0x0e, 0x38, 0x0e, 0x44, 0x0e, 0x6c, 0x0e, 0x6d, 0x0e, 0x6e, 0x0e, 0x6f, 0x0e, 0x7e, 0x0e, 0x7f, 0x0e, 0x9c, 0x0e, 0x9d, 0x0e, 0xa0, 0x0e, 0xa1, 0x0e, 0xa2, 0x0e, 0xa7, 0x11, 0x1c, 0x11, 0xb8, 0x00, 0x01, 0x00, 0x01, 0x02, 0xd8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0xfe, 0x48, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xba, 0x0d, 0x8e, 0x00, 0x01, 0x0f, 0xf4, 0x00, 0x0c, 0x01, 0xb0, 0x03, 0x62, 0x03, 0x68, 0x03, 0x6e, 0x03, 0x74, 0x03, 0x7a, 0x03, 0x80, 0x03, 0x86, 0x03, 0x8c, 0x03, 0x92, 0x03, 0x98, 0x03, 0x9e, 0x03, 0xa4, 0x03, 0xaa, 0x03, 0xb0, 0x03, 0xb6, 0x03, 0xbc, 0x03, 0xc2, 0x03, 0xc8, 0x03, 0xce, 0x03, 0xd4, 0x03, 0xda, 0x03, 0xe0, 0x03, 0xe6, 0x03, 0xec, 0x03, 0xf2, 0x03, 0xf8, 0x03, 0xfe, 0x04, 0x04, 0x04, 0x0a, 0x04, 0x10, 0x04, 0x16, 0x04, 0x1c, 0x04, 0x22, 0x04, 0x28, 0x04, 0x2e, 0x04, 0x34, 0x04, 0x3a, 0x04, 0x40, 0x04, 0x46, 0x04, 0x4c, 0x04, 0x52, 0x04, 0x58, 0x04, 0x5e, 0x04, 0x64, 0x04, 0x6a, 0x04, 0x70, 0x04, 0x76, 0x04, 0x7c, 0x04, 0x82, 0x04, 0x88, 0x04, 0x8e, 0x04, 0x94, 0x04, 0x9a, 0x04, 0xa0, 0x04, 0xa6, 0x04, 0xac, 0x04, 0xb2, 0x04, 0xb8, 0x04, 0xbe, 0x04, 0xc4, 0x04, 0xca, 0x04, 0xd0, 0x04, 0xd6, 0x04, 0xdc, 0x04, 0xe2, 0x04, 0xe8, 0x04, 0xee, 0x04, 0xf4, 0x04, 0xfa, 0x05, 0x00, 0x05, 0x06, 0x05, 0x0c, 0x05, 0x12, 0x05, 0x18, 0x05, 0x1e, 0x05, 0x24, 0x05, 0x2a, 0x05, 0x30, 0x05, 0x36, 0x05, 0x3c, 0x05, 0x42, 0x05, 0x48, 0x05, 0x4e, 0x05, 0x54, 0x05, 0x5a, 0x05, 0x60, 0x05, 0x66, 0x05, 0x6c, 0x05, 0x72, 0x05, 0x78, 0x05, 0x7e, 0x05, 0x84, 0x05, 0x8a, 0x05, 0x90, 0x05, 0x96, 0x05, 0x9c, 0x05, 0xa2, 0x05, 0xa8, 0x05, 0xae, 0x05, 0xb4, 0x05, 0xba, 0x05, 0xc0, 0x05, 0xc6, 0x05, 0xcc, 0x05, 0xd2, 0x05, 0xd8, 0x05, 0xde, 0x05, 0xe4, 0x05, 0xea, 0x05, 0xf0, 0x05, 0xf6, 0x05, 0xfc, 0x06, 0x02, 0x06, 0x08, 0x06, 0x0e, 0x06, 0x14, 0x06, 0x1a, 0x06, 0x20, 0x06, 0x26, 0x06, 0x2c, 0x06, 0x32, 0x06, 0x38, 0x06, 0x3e, 0x06, 0x44, 0x06, 0x4a, 0x06, 0x50, 0x06, 0x56, 0x06, 0x5c, 0x06, 0x62, 0x06, 0x68, 0x06, 0x6e, 0x06, 0x74, 0x06, 0x7a, 0x06, 0x80, 0x06, 0x86, 0x06, 0x8c, 0x06, 0x92, 0x06, 0x98, 0x06, 0x9e, 0x06, 0xa4, 0x06, 0xaa, 0x06, 0xb0, 0x06, 0xb6, 0x06, 0xbc, 0x06, 0xc2, 0x06, 0xc8, 0x06, 0xce, 0x06, 0xd4, 0x06, 0xda, 0x06, 0xe0, 0x06, 0xe6, 0x06, 0xec, 0x06, 0xf2, 0x06, 0xf8, 0x06, 0xfe, 0x07, 0x04, 0x07, 0x0a, 0x07, 0x10, 0x07, 0x16, 0x07, 0x1c, 0x07, 0x22, 0x07, 0x28, 0x07, 0x2e, 0x07, 0x34, 0x07, 0x3a, 0x07, 0x40, 0x07, 0x46, 0x07, 0x4c, 0x07, 0x52, 0x07, 0x58, 0x07, 0x5e, 0x07, 0x64, 0x07, 0x6a, 0x07, 0x70, 0x07, 0x76, 0x07, 0x7c, 0x07, 0x82, 0x07, 0x88, 0x07, 0x8e, 0x07, 0x94, 0x07, 0x9a, 0x07, 0xa0, 0x07, 0xa6, 0x07, 0xac, 0x07, 0xb2, 0x07, 0xb8, 0x07, 0xbe, 0x07, 0xc4, 0x07, 0xca, 0x07, 0xd0, 0x07, 0xd6, 0x07, 0xdc, 0x07, 0xe2, 0x07, 0xe8, 0x07, 0xee, 0x07, 0xf4, 0x07, 0xfa, 0x08, 0x00, 0x08, 0x06, 0x08, 0x0c, 0x08, 0x12, 0x08, 0x18, 0x08, 0x1e, 0x08, 0x24, 0x08, 0x2a, 0x08, 0x30, 0x08, 0x36, 0x08, 0x3c, 0x08, 0x42, 0x08, 0x48, 0x08, 0x4e, 0x08, 0x54, 0x08, 0x5a, 0x08, 0x60, 0x08, 0x66, 0x08, 0x6c, 0x08, 0x72, 0x08, 0x78, 0x08, 0x7e, 0x08, 0x84, 0x08, 0x8a, 0x08, 0x90, 0x08, 0x96, 0x08, 0x9c, 0x08, 0xa2, 0x08, 0xa8, 0x08, 0xae, 0x08, 0xb4, 0x08, 0xba, 0x08, 0xc0, 0x08, 0xc6, 0x08, 0xcc, 0x08, 0xd2, 0x08, 0xd8, 0x08, 0xde, 0x08, 0xe4, 0x08, 0xea, 0x08, 0xf0, 0x08, 0xf6, 0x08, 0xfc, 0x09, 0x02, 0x09, 0x08, 0x09, 0x0e, 0x09, 0x14, 0x09, 0x1a, 0x09, 0x20, 0x09, 0x26, 0x09, 0x2c, 0x09, 0x32, 0x09, 0x38, 0x09, 0x3e, 0x09, 0x44, 0x09, 0x4a, 0x09, 0x50, 0x09, 0x56, 0x09, 0x5c, 0x09, 0x62, 0x09, 0x68, 0x09, 0x6e, 0x09, 0x74, 0x09, 0x7a, 0x09, 0x80, 0x09, 0x86, 0x09, 0x8c, 0x09, 0x92, 0x09, 0x98, 0x09, 0x9e, 0x09, 0xa4, 0x09, 0xaa, 0x09, 0xb0, 0x09, 0xb6, 0x09, 0xbc, 0x09, 0xc2, 0x09, 0xc8, 0x09, 0xce, 0x09, 0xd4, 0x09, 0xda, 0x09, 0xe0, 0x09, 0xe6, 0x09, 0xec, 0x09, 0xf2, 0x09, 0xf8, 0x09, 0xfe, 0x0a, 0x04, 0x0a, 0x0a, 0x0a, 0x10, 0x0a, 0x16, 0x0a, 0x1c, 0x0a, 0x22, 0x0a, 0x28, 0x0a, 0x2e, 0x0a, 0x34, 0x0a, 0x3a, 0x0a, 0x40, 0x0a, 0x46, 0x0a, 0x4c, 0x0a, 0x52, 0x0a, 0x58, 0x0a, 0x5e, 0x0a, 0x64, 0x0a, 0x6a, 0x0a, 0x70, 0x0a, 0x76, 0x0a, 0x7c, 0x0a, 0x82, 0x0a, 0x88, 0x0a, 0x8e, 0x0a, 0x94, 0x0a, 0x9a, 0x0a, 0xa0, 0x0a, 0xa6, 0x0a, 0xac, 0x0a, 0xb2, 0x0a, 0xb8, 0x0a, 0xbe, 0x0a, 0xc4, 0x0a, 0xca, 0x0a, 0xd0, 0x0a, 0xd6, 0x0a, 0xdc, 0x0a, 0xe2, 0x0a, 0xe8, 0x0a, 0xee, 0x0a, 0xf4, 0x0a, 0xfa, 0x0b, 0x00, 0x0b, 0x06, 0x0b, 0x0c, 0x0b, 0x12, 0x0b, 0x18, 0x0b, 0x1e, 0x0b, 0x24, 0x0b, 0x2a, 0x0b, 0x30, 0x0b, 0x36, 0x0b, 0x3c, 0x0b, 0x42, 0x0b, 0x48, 0x0b, 0x4e, 0x0b, 0x54, 0x0b, 0x5a, 0x0b, 0x60, 0x0b, 0x66, 0x0b, 0x6c, 0x0b, 0x72, 0x0b, 0x78, 0x0b, 0x7e, 0x0b, 0x84, 0x0b, 0x8a, 0x0b, 0x90, 0x0b, 0x96, 0x0b, 0x9c, 0x0b, 0xa2, 0x0b, 0xa8, 0x0b, 0xae, 0x0b, 0xb4, 0x0b, 0xba, 0x0b, 0xc0, 0x0b, 0xc6, 0x0b, 0xcc, 0x0b, 0xd2, 0x0b, 0xd8, 0x0b, 0xde, 0x0b, 0xe4, 0x0b, 0xea, 0x0b, 0xf0, 0x0b, 0xf6, 0x0b, 0xfc, 0x0c, 0x02, 0x0c, 0x08, 0x0c, 0x0e, 0x0c, 0x14, 0x0c, 0x1a, 0x0c, 0x20, 0x0c, 0x26, 0x0c, 0x2c, 0x0c, 0x32, 0x0c, 0x38, 0x0c, 0x3e, 0x0c, 0x44, 0x0c, 0x4a, 0x0c, 0x50, 0x0c, 0x56, 0x0c, 0x5c, 0x0c, 0x62, 0x0c, 0x68, 0x0c, 0x6e, 0x0c, 0x74, 0x0c, 0x7a, 0x0c, 0x80, 0x0c, 0x86, 0x0c, 0x8c, 0x0c, 0x92, 0x0c, 0x98, 0x0c, 0x9e, 0x0c, 0xa4, 0x0c, 0xaa, 0x0c, 0xb0, 0x0c, 0xb6, 0x0c, 0xbc, 0x0c, 0xc2, 0x0c, 0xc8, 0x0c, 0xce, 0x0c, 0xd4, 0x0c, 0xda, 0x0c, 0xe0, 0x0c, 0xe6, 0x0c, 0xec, 0x0c, 0xf2, 0x0c, 0xf8, 0x0c, 0xfe, 0x0d, 0x04, 0x0d, 0x0a, 0x0d, 0x10, 0x0d, 0x16, 0x0d, 0x1c, 0x0d, 0x22, 0x0d, 0x28, 0x0d, 0x2e, 0x0d, 0x34, 0x0d, 0x3a, 0x0d, 0x40, 0x0d, 0x46, 0x0d, 0x4c, 0x0d, 0x52, 0x0d, 0x58, 0x0d, 0x5e, 0x0d, 0x64, 0x0d, 0x6a, 0x0d, 0x70, 0x0d, 0x76, 0x0d, 0x7c, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x02, 0xf7, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa1, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb5, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0f, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x56, 0x00, 0x00, 0x00, 0x01, 0x03, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa9, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x51, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x03, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x85, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x71, 0x00, 0x00, 0x00, 0x01, 0x02, 0x60, 0x00, 0x00, 0x00, 0x01, 0x02, 0x28, 0x00, 0x00, 0x00, 0x01, 0x02, 0x53, 0x00, 0x00, 0x00, 0x01, 0x01, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x03, 0x84, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x47, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x01, 0xee, 0x00, 0x00, 0x00, 0x01, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00, 0x01, 0x02, 0xf3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x25, 0x00, 0x00, 0x00, 0x01, 0x02, 0x23, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x04, 0x7f, 0xfe, 0x80, 0x00, 0x01, 0x03, 0x6f, 0xfe, 0x80, 0x00, 0x01, 0x02, 0xa1, 0x00, 0x00, 0x00, 0x01, 0x02, 0x28, 0x00, 0x00, 0x00, 0x01, 0x02, 0x53, 0x00, 0x00, 0x00, 0x01, 0x02, 0x88, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x48, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x01, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x71, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x28, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x7d, 0x00, 0x00, 0x00, 0x01, 0x01, 0x17, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfa, 0xfe, 0x7a, 0x00, 0x01, 0x02, 0x23, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x02, 0x53, 0x00, 0x00, 0x00, 0x01, 0x02, 0x47, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x52, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0f, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x02, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x00, 0x01, 0x02, 0x23, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x46, 0x00, 0x00, 0x00, 0x01, 0x02, 0x18, 0x00, 0x00, 0x00, 0x01, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4b, 0x00, 0x00, 0x00, 0x01, 0x01, 0x95, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x18, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x18, 0x00, 0x00, 0x00, 0x01, 0x02, 0x25, 0x00, 0x00, 0x00, 0x01, 0x02, 0x16, 0x00, 0x00, 0x00, 0x01, 0x02, 0x16, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x06, 0x00, 0x00, 0x00, 0x01, 0x02, 0x06, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa3, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x2c, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x2c, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x25, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x25, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0xec, 0x00, 0x00, 0x00, 0x01, 0x01, 0x59, 0x00, 0x00, 0x00, 0x01, 0x01, 0x70, 0x00, 0x00, 0x00, 0x01, 0x01, 0xcb, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfa, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xa3, 0xfe, 0x52, 0x00, 0x01, 0x03, 0x84, 0x00, 0x00, 0x00, 0x01, 0x03, 0x84, 0xfe, 0x52, 0x00, 0x01, 0x03, 0x84, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x48, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x48, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x48, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x04, 0x18, 0x00, 0x00, 0x00, 0x01, 0x02, 0x9e, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x01, 0xfc, 0xfe, 0x52, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x24, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x5c, 0x00, 0x00, 0x00, 0x01, 0x02, 0x35, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x15, 0x00, 0x00, 0x00, 0x01, 0x01, 0xef, 0xfe, 0x52, 0x00, 0x01, 0x00, 0xfa, 0xfe, 0x52, 0x00, 0x01, 0x00, 0xfa, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xbf, 0xfe, 0x52, 0x00, 0x01, 0x00, 0xfa, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xd9, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xc2, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00, 0x01, 0x02, 0xf3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00, 0x01, 0x02, 0x26, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xe1, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x84, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x84, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x24, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5f, 0xff, 0xf6, 0x00, 0x01, 0x01, 0x02, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x66, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x22, 0x00, 0x00, 0x00, 0x01, 0x02, 0x47, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x84, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x97, 0x00, 0x00, 0x00, 0x01, 0x03, 0x97, 0xfe, 0x52, 0x00, 0x01, 0x03, 0x97, 0x00, 0x00, 0x00, 0x01, 0x02, 0xf3, 0xfe, 0x52, 0x00, 0x01, 0x04, 0x19, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd0, 0xfe, 0x52, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3e, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb5, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x02, 0x18, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x18, 0x00, 0x00, 0x00, 0x01, 0x02, 0x18, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x06, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb7, 0x00, 0x00, 0x00, 0x01, 0x02, 0x41, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x01, 0x85, 0x00, 0x00, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x02, 0x18, 0x00, 0x00, 0x00, 0x01, 0x02, 0x29, 0x00, 0x00, 0x00, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00, 0x01, 0x02, 0xf3, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x01, 0xcb, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xa1, 0x00, 0x00, 0x00, 0x01, 0x02, 0x28, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa1, 0xfe, 0x89, 0x00, 0x01, 0x02, 0x28, 0xfe, 0x89, 0x00, 0x01, 0x02, 0xa1, 0xfe, 0xbf, 0x00, 0x01, 0x02, 0x28, 0xfe, 0xbf, 0x00, 0x01, 0x02, 0xa1, 0xfe, 0x74, 0x00, 0x01, 0x02, 0x28, 0xfe, 0x74, 0x00, 0x01, 0x02, 0xa1, 0xfe, 0x15, 0x00, 0x01, 0x02, 0x28, 0xfe, 0x15, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x03, 0x37, 0x00, 0x00, 0x00, 0x01, 0x01, 0xb7, 0x00, 0x00, 0x00, 0x01, 0x02, 0xf7, 0x00, 0x00, 0x00, 0x01, 0x03, 0xd5, 0x00, 0x00, 0x00, 0x01, 0x02, 0xfd, 0xfe, 0x52, 0x00, 0x01, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x01, 0xda, 0x00, 0x00, 0x00, 0x01, 0x01, 0xa7, 0x00, 0x00, 0x00, 0x01, 0x02, 0x94, 0x00, 0x00, 0x00, 0x01, 0x02, 0xda, 0x00, 0x00, 0x00, 0x01, 0x02, 0xe2, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd3, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xbf, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x03, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x03, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x03, 0x08, 0x00, 0x00, 0x00, 0x01, 0x02, 0xad, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3a, 0xfe, 0x52, 0x00, 0x01, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0xe2, 0x00, 0x00, 0x00, 0x01, 0x01, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x02, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x03, 0x33, 0x00, 0x00, 0x00, 0x01, 0x03, 0xde, 0x00, 0x00, 0x00, 0x01, 0x02, 0xc7, 0x00, 0x00, 0x00, 0x01, 0x02, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x01, 0xc1, 0x00, 0x08, 0x00, 0x01, 0x02, 0x5a, 0x00, 0x07, 0x00, 0x01, 0x01, 0x56, 0x00, 0x00, 0x00, 0x01, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x03, 0x09, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xaf, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x02, 0x71, 0x00, 0x00, 0x00, 0x01, 0x02, 0x56, 0x00, 0x00, 0x00, 0x01, 0x02, 0x56, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x18, 0x00, 0x00, 0x00, 0x01, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb5, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x03, 0x1a, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x76, 0x00, 0x00, 0x00, 0x01, 0x02, 0x7c, 0xff, 0xe4, 0x00, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00, 0x01, 0x03, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x02, 0xf3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb5, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5f, 0x00, 0x00, 0x00, 0x01, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x02, 0x34, 0x00, 0x00, 0x00, 0x01, 0x01, 0xa5, 0x00, 0x00, 0x00, 0x01, 0x02, 0x51, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x77, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xb5, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x48, 0xfe, 0x52, 0x00, 0x01, 0x03, 0x1e, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x5b, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x0f, 0xfe, 0x56, 0x00, 0x01, 0x01, 0xe3, 0x00, 0x00, 0x00, 0x01, 0x04, 0x80, 0x00, 0x00, 0x00, 0x01, 0x03, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x03, 0xc5, 0x00, 0x00, 0x00, 0x01, 0x03, 0x74, 0x00, 0x00, 0x00, 0x01, 0x04, 0x4a, 0x00, 0x00, 0x00, 0x01, 0x03, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x03, 0x96, 0x00, 0x00, 0x00, 0x01, 0x03, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x03, 0x96, 0x00, 0x00, 0x00, 0x01, 0x03, 0x1d, 0xff, 0xf6, 0x00, 0x01, 0x03, 0x96, 0x00, 0x00, 0x00, 0x01, 0x03, 0x1d, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x69, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39, 0x00, 0x00, 0x00, 0x01, 0x01, 0x69, 0x00, 0x00, 0x00, 0x01, 0x02, 0x83, 0x00, 0x00, 0x00, 0x01, 0x01, 0x83, 0x00, 0x00, 0x00, 0x01, 0x02, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x02, 0x85, 0x00, 0x00, 0x00, 0x01, 0x04, 0xe3, 0x00, 0x00, 0x00, 0x01, 0x03, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x03, 0x63, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x47, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xab, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xbe, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x01, 0xc4, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xa9, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa9, 0x00, 0x00, 0x00, 0x01, 0x02, 0x62, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x02, 0x51, 0x00, 0x00, 0x00, 0x01, 0x01, 0xee, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x03, 0x4b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x00, 0x00, 0x01, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x03, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x04, 0x51, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa9, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa3, 0x00, 0x00, 0x00, 0x01, 0x02, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb9, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb9, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x69, 0x00, 0x00, 0x00, 0x01, 0x01, 0x68, 0xfe, 0x52, 0x00, 0x01, 0x02, 0xb5, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x03, 0xb0, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd5, 0x00, 0x00, 0x00, 0x01, 0x02, 0x40, 0x00, 0x00, 0x00, 0x01, 0x02, 0x8c, 0x00, 0x00, 0x00, 0x01, 0x02, 0xfd, 0x00, 0x00, 0x00, 0x01, 0x02, 0x9a, 0x00, 0x00, 0x00, 0x01, 0x04, 0x05, 0x00, 0x00, 0x00, 0x01, 0x02, 0xe6, 0x00, 0x00, 0x00, 0x01, 0x02, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x02, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x37, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x02, 0x49, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe, 0x52, 0x00, 0x01, 0x01, 0x62, 0x00, 0x01, 0x00, 0x01, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x01, 0x99, 0x00, 0x00, 0x00, 0x01, 0x02, 0x3d, 0xfe, 0x52, 0x00, 0x02, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3d, 0x00, 0x0a, 0x00, 0x44, 0x00, 0x5d, 0x00, 0x24, 0x00, 0x8e, 0x00, 0x91, 0x00, 0x3e, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x42, 0x00, 0xa8, 0x00, 0xa8, 0x00, 0x43, 0x00, 0xae, 0x00, 0xb2, 0x00, 0x44, 0x00, 0xba, 0x00, 0xba, 0x00, 0x49, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0x4a, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0x4b, 0x00, 0xd0, 0x00, 0xd1, 0x00, 0x4d, 0x00, 0xd5, 0x00, 0xd5, 0x00, 0x4f, 0x00, 0xe9, 0x00, 0xef, 0x00, 0x50, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0x57, 0x00, 0xfa, 0x00, 0xfa, 0x00, 0x59, 0x01, 0x0d, 0x01, 0x0d, 0x00, 0x5a, 0x01, 0x0f, 0x01, 0x0f, 0x00, 0x5b, 0x01, 0x28, 0x01, 0x29, 0x00, 0x5c, 0x01, 0x2d, 0x01, 0x2d, 0x00, 0x5e, 0x01, 0x41, 0x01, 0x41, 0x00, 0x5f, 0x01, 0x45, 0x01, 0x45, 0x00, 0x60, 0x01, 0x48, 0x01, 0x48, 0x00, 0x61, 0x01, 0x4e, 0x01, 0x4e, 0x00, 0x62, 0x01, 0x51, 0x01, 0x52, 0x00, 0x63, 0x01, 0x54, 0x01, 0x54, 0x00, 0x65, 0x01, 0x59, 0x01, 0x59, 0x00, 0x66, 0x01, 0x61, 0x01, 0x61, 0x00, 0x67, 0x01, 0x6c, 0x01, 0x6c, 0x00, 0x68, 0x01, 0x76, 0x01, 0x76, 0x00, 0x69, 0x01, 0x79, 0x01, 0x7b, 0x00, 0x6a, 0x01, 0x91, 0x01, 0x92, 0x00, 0x6d, 0x01, 0xca, 0x01, 0xcd, 0x00, 0x6f, 0x01, 0xf6, 0x01, 0xf8, 0x00, 0x73, 0x02, 0x05, 0x02, 0x0c, 0x00, 0x76, 0x02, 0x0e, 0x02, 0x4a, 0x00, 0x7e, 0x02, 0x4c, 0x02, 0x67, 0x00, 0xbb, 0x02, 0x69, 0x02, 0x6b, 0x00, 0xd7, 0x02, 0x6d, 0x02, 0x6d, 0x00, 0xda, 0x03, 0x46, 0x03, 0x46, 0x00, 0xdb, 0x03, 0x49, 0x03, 0x49, 0x00, 0xdc, 0x03, 0x4c, 0x03, 0x4c, 0x00, 0xdd, 0x03, 0x88, 0x03, 0x88, 0x00, 0xde, 0x03, 0x9a, 0x03, 0x9a, 0x00, 0xdf, 0x03, 0xea, 0x03, 0xeb, 0x00, 0xe0, 0x04, 0x06, 0x04, 0x07, 0x00, 0xe2, 0x04, 0x22, 0x04, 0x22, 0x00, 0xe4, 0x04, 0x33, 0x04, 0x33, 0x00, 0xe5, 0x04, 0x36, 0x04, 0x36, 0x00, 0xe6, 0x04, 0x7c, 0x04, 0x7d, 0x00, 0xe7, 0x04, 0xba, 0x04, 0xbb, 0x00, 0xe9, 0x04, 0xbd, 0x04, 0xc2, 0x00, 0xeb, 0x04, 0xc5, 0x04, 0xcd, 0x00, 0xf1, 0x04, 0xd1, 0x04, 0xd5, 0x00, 0xfa, 0x04, 0xd9, 0x04, 0xde, 0x00, 0xff, 0x05, 0x23, 0x05, 0x23, 0x01, 0x05, 0x05, 0x5a, 0x05, 0x63, 0x01, 0x06, 0x05, 0x7e, 0x05, 0x7f, 0x01, 0x10, 0x06, 0x18, 0x06, 0x19, 0x01, 0x12, 0x06, 0x4a, 0x06, 0x4b, 0x01, 0x14, 0x07, 0xec, 0x07, 0xec, 0x01, 0x16, 0x07, 0xf4, 0x07, 0xf7, 0x01, 0x17, 0x07, 0xf9, 0x07, 0xfb, 0x01, 0x1b, 0x07, 0xfe, 0x07, 0xfe, 0x01, 0x1e, 0x08, 0x01, 0x08, 0x06, 0x01, 0x1f, 0x08, 0x0d, 0x08, 0x0d, 0x01, 0x25, 0x08, 0x11, 0x08, 0x11, 0x01, 0x26, 0x08, 0x15, 0x08, 0x16, 0x01, 0x27, 0x08, 0x18, 0x08, 0x1a, 0x01, 0x29, 0x08, 0x1c, 0x08, 0x1c, 0x01, 0x2c, 0x08, 0x1e, 0x08, 0x22, 0x01, 0x2d, 0x08, 0x25, 0x08, 0x28, 0x01, 0x32, 0x0a, 0x1d, 0x0a, 0x1d, 0x01, 0x36, 0x0e, 0x2b, 0x0e, 0x2b, 0x01, 0x37, 0x0e, 0x2d, 0x0e, 0x2e, 0x01, 0x38, 0x0e, 0x30, 0x0e, 0x41, 0x01, 0x3a, 0x0e, 0x43, 0x0e, 0x45, 0x01, 0x4c, 0x0e, 0x48, 0x0e, 0x49, 0x01, 0x4f, 0x0e, 0x62, 0x0e, 0x65, 0x01, 0x51, 0x0e, 0x67, 0x0e, 0x68, 0x01, 0x55, 0x0e, 0x6a, 0x0e, 0x75, 0x01, 0x57, 0x0e, 0x78, 0x0e, 0x87, 0x01, 0x63, 0x0e, 0x8c, 0x0e, 0x8f, 0x01, 0x73, 0x0e, 0x95, 0x0e, 0xa8, 0x01, 0x77, 0x0f, 0x93, 0x0f, 0xa5, 0x01, 0x8b, 0x0f, 0xbd, 0x0f, 0xbd, 0x01, 0x9e, 0x0f, 0xbf, 0x0f, 0xbf, 0x01, 0x9f, 0x0f, 0xf4, 0x0f, 0xfd, 0x01, 0xa0, 0x11, 0x1c, 0x11, 0x1d, 0x01, 0xaa, 0x11, 0x34, 0x11, 0x34, 0x01, 0xac, 0x11, 0x3e, 0x11, 0x3e, 0x01, 0xad, 0x11, 0x48, 0x11, 0x48, 0x01, 0xae, 0x11, 0xb8, 0x11, 0xb8, 0x01, 0xaf, 0x00, 0x02, 0x00, 0x09, 0x02, 0xc7, 0x02, 0xca, 0x00, 0x00, 0x02, 0xcd, 0x02, 0xd1, 0x00, 0x04, 0x02, 0xd4, 0x02, 0xd7, 0x00, 0x09, 0x02, 0xda, 0x02, 0xe4, 0x00, 0x0d, 0x02, 0xea, 0x02, 0xed, 0x00, 0x18, 0x02, 0xf8, 0x02, 0xfa, 0x00, 0x1c, 0x02, 0xfe, 0x02, 0xff, 0x00, 0x1f, 0x03, 0x03, 0x03, 0x03, 0x00, 0x21, 0x03, 0x06, 0x03, 0x06, 0x00, 0x22, 0x00, 0x23, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x01, 0x4e, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x01, 0x5a, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xfe, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xfe, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x35, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x34, 0xff, 0xff, 0x00, 0x01, 0x15, 0x68, 0x12, 0xca, 0x00, 0x01, 0x15, 0xb4, 0x00, 0x0c, 0x02, 0x53, 0x04, 0xa8, 0x04, 0xae, 0x04, 0xb4, 0x04, 0xba, 0x04, 0xc0, 0x04, 0xc6, 0x04, 0xcc, 0x04, 0xd2, 0x04, 0xd8, 0x04, 0xde, 0x04, 0xe4, 0x04, 0xea, 0x04, 0xf0, 0x04, 0xf6, 0x04, 0xfc, 0x05, 0x02, 0x05, 0x08, 0x05, 0x0e, 0x05, 0x14, 0x05, 0x1a, 0x05, 0x20, 0x05, 0x26, 0x05, 0x2c, 0x05, 0x32, 0x05, 0x38, 0x05, 0x3e, 0x05, 0x44, 0x05, 0x4a, 0x05, 0x50, 0x05, 0x56, 0x05, 0x5c, 0x05, 0x62, 0x05, 0x68, 0x05, 0x6e, 0x05, 0x74, 0x05, 0x7a, 0x05, 0x80, 0x05, 0x88, 0x05, 0x8e, 0x05, 0x96, 0x05, 0x9c, 0x05, 0xa4, 0x05, 0xaa, 0x05, 0xb0, 0x05, 0xb6, 0x05, 0xbc, 0x05, 0xc2, 0x05, 0xc8, 0x05, 0xce, 0x05, 0xd4, 0x05, 0xda, 0x05, 0xe2, 0x05, 0xe8, 0x05, 0xee, 0x05, 0xf4, 0x05, 0xfa, 0x06, 0x00, 0x06, 0x08, 0x06, 0x0e, 0x06, 0x14, 0x06, 0x1a, 0x06, 0x20, 0x06, 0x26, 0x06, 0x2c, 0x06, 0x32, 0x06, 0x38, 0x06, 0x3e, 0x06, 0x46, 0x06, 0x4c, 0x06, 0x52, 0x06, 0x5a, 0x06, 0x60, 0x06, 0x66, 0x06, 0x6c, 0x06, 0x74, 0x06, 0x7a, 0x06, 0x80, 0x06, 0x86, 0x06, 0x8c, 0x06, 0x92, 0x06, 0x98, 0x06, 0x9e, 0x06, 0xa4, 0x06, 0xaa, 0x06, 0xb0, 0x06, 0xb6, 0x06, 0xbc, 0x06, 0xc2, 0x06, 0xc8, 0x06, 0xce, 0x06, 0xd4, 0x06, 0xda, 0x06, 0xe0, 0x06, 0xe6, 0x06, 0xec, 0x06, 0xf2, 0x06, 0xf8, 0x06, 0xfe, 0x07, 0x04, 0x07, 0x0a, 0x07, 0x10, 0x07, 0x16, 0x07, 0x1c, 0x07, 0x22, 0x07, 0x28, 0x07, 0x2e, 0x07, 0x34, 0x07, 0x3a, 0x07, 0x40, 0x07, 0x46, 0x07, 0x4c, 0x07, 0x52, 0x07, 0x58, 0x07, 0x5e, 0x07, 0x64, 0x07, 0x6a, 0x07, 0x70, 0x07, 0x76, 0x07, 0x7c, 0x07, 0x82, 0x07, 0x88, 0x07, 0x8e, 0x07, 0x94, 0x07, 0x9a, 0x07, 0xa0, 0x07, 0xa6, 0x07, 0xac, 0x07, 0xb2, 0x07, 0xb8, 0x07, 0xbe, 0x07, 0xc4, 0x07, 0xca, 0x07, 0xd0, 0x07, 0xd6, 0x07, 0xdc, 0x07, 0xe2, 0x07, 0xe8, 0x07, 0xee, 0x07, 0xf6, 0x07, 0xfc, 0x08, 0x02, 0x08, 0x08, 0x08, 0x0e, 0x08, 0x14, 0x08, 0x1a, 0x08, 0x22, 0x08, 0x28, 0x08, 0x2e, 0x08, 0x34, 0x08, 0x3a, 0x08, 0x40, 0x08, 0x46, 0x08, 0x4c, 0x08, 0x52, 0x08, 0x58, 0x08, 0x5e, 0x08, 0x64, 0x08, 0x6a, 0x08, 0x70, 0x08, 0x76, 0x08, 0x7c, 0x08, 0x82, 0x08, 0x88, 0x08, 0x8e, 0x08, 0x94, 0x08, 0x9a, 0x08, 0xa0, 0x08, 0xa6, 0x08, 0xac, 0x08, 0xb2, 0x08, 0xb8, 0x08, 0xc0, 0x08, 0xc6, 0x08, 0xcc, 0x08, 0xd2, 0x08, 0xd8, 0x08, 0xde, 0x08, 0xe4, 0x08, 0xea, 0x08, 0xf0, 0x08, 0xf6, 0x08, 0xfc, 0x09, 0x02, 0x09, 0x08, 0x09, 0x0e, 0x09, 0x14, 0x09, 0x1a, 0x09, 0x20, 0x09, 0x26, 0x09, 0x2c, 0x09, 0x32, 0x09, 0x38, 0x09, 0x3e, 0x09, 0x44, 0x09, 0x4a, 0x09, 0x50, 0x09, 0x56, 0x09, 0x5c, 0x09, 0x62, 0x09, 0x68, 0x09, 0x6e, 0x09, 0x74, 0x09, 0x7a, 0x09, 0x80, 0x09, 0x86, 0x09, 0x8c, 0x09, 0x92, 0x09, 0x98, 0x09, 0x9e, 0x09, 0xa4, 0x09, 0xaa, 0x09, 0xb0, 0x09, 0xb6, 0x09, 0xbc, 0x09, 0xc2, 0x09, 0xc8, 0x09, 0xce, 0x09, 0xd4, 0x09, 0xda, 0x09, 0xe0, 0x09, 0xe6, 0x09, 0xec, 0x09, 0xf2, 0x09, 0xf8, 0x09, 0xfe, 0x0a, 0x04, 0x0a, 0x0a, 0x0a, 0x12, 0x0a, 0x18, 0x0a, 0x1e, 0x0a, 0x24, 0x0a, 0x2a, 0x0a, 0x30, 0x0a, 0x36, 0x0a, 0x3c, 0x0a, 0x42, 0x0a, 0x48, 0x0a, 0x4e, 0x0a, 0x54, 0x0a, 0x5a, 0x0a, 0x60, 0x0a, 0x66, 0x0a, 0x6c, 0x0a, 0x72, 0x0a, 0x78, 0x0a, 0x7e, 0x0a, 0x84, 0x0a, 0x8a, 0x0a, 0x90, 0x0a, 0x96, 0x0a, 0x9c, 0x0a, 0xa2, 0x0a, 0xa8, 0x0a, 0xae, 0x0a, 0xb4, 0x0a, 0xba, 0x0a, 0xc0, 0x0a, 0xc6, 0x0a, 0xcc, 0x0a, 0xd2, 0x0a, 0xd8, 0x0a, 0xde, 0x0a, 0xe4, 0x0a, 0xea, 0x0a, 0xf0, 0x0a, 0xf6, 0x0a, 0xfc, 0x0b, 0x02, 0x0b, 0x08, 0x0b, 0x0e, 0x0b, 0x14, 0x0b, 0x1a, 0x0b, 0x20, 0x0b, 0x26, 0x0b, 0x2c, 0x0b, 0x32, 0x0b, 0x38, 0x0b, 0x3e, 0x0b, 0x44, 0x0b, 0x4a, 0x0b, 0x50, 0x0b, 0x56, 0x0b, 0x5c, 0x0b, 0x62, 0x0b, 0x68, 0x0b, 0x6e, 0x0b, 0x74, 0x0b, 0x7a, 0x0b, 0x80, 0x0b, 0x86, 0x0b, 0x8c, 0x0b, 0x92, 0x0b, 0x98, 0x0b, 0x9e, 0x0b, 0xa4, 0x0b, 0xaa, 0x0b, 0xb0, 0x0b, 0xb6, 0x0b, 0xbc, 0x0b, 0xc2, 0x0b, 0xc8, 0x0b, 0xce, 0x0b, 0xd4, 0x0b, 0xda, 0x0b, 0xe0, 0x0b, 0xe6, 0x0b, 0xec, 0x0b, 0xf2, 0x0b, 0xf8, 0x0b, 0xfe, 0x0c, 0x04, 0x0c, 0x0a, 0x0c, 0x10, 0x0c, 0x16, 0x0c, 0x1c, 0x0c, 0x22, 0x0c, 0x28, 0x0c, 0x2e, 0x0c, 0x34, 0x0c, 0x3a, 0x0c, 0x40, 0x0c, 0x46, 0x0c, 0x4c, 0x0c, 0x52, 0x0c, 0x58, 0x0c, 0x5e, 0x0c, 0x64, 0x0c, 0x6a, 0x0c, 0x70, 0x0c, 0x76, 0x0c, 0x7c, 0x0c, 0x82, 0x0c, 0x88, 0x0c, 0x8e, 0x0c, 0x94, 0x0c, 0x9a, 0x0c, 0xa0, 0x0c, 0xa6, 0x0c, 0xac, 0x0c, 0xb2, 0x0c, 0xb8, 0x0c, 0xbe, 0x0c, 0xc4, 0x0c, 0xca, 0x0c, 0xd0, 0x0c, 0xd6, 0x0c, 0xdc, 0x0c, 0xe2, 0x0c, 0xe8, 0x0c, 0xee, 0x0c, 0xf4, 0x0c, 0xfa, 0x0d, 0x00, 0x0d, 0x06, 0x0d, 0x0c, 0x0d, 0x12, 0x0d, 0x18, 0x0d, 0x1e, 0x0d, 0x24, 0x0d, 0x2a, 0x0d, 0x30, 0x0d, 0x36, 0x0d, 0x3c, 0x0d, 0x42, 0x0d, 0x48, 0x0d, 0x4e, 0x0d, 0x54, 0x0d, 0x5a, 0x0d, 0x60, 0x0d, 0x66, 0x0d, 0x6c, 0x0d, 0x72, 0x0d, 0x78, 0x0d, 0x7e, 0x0d, 0x84, 0x0d, 0x8a, 0x0d, 0x90, 0x0d, 0x96, 0x0d, 0x9c, 0x0d, 0xa2, 0x0d, 0xa8, 0x0d, 0xae, 0x0d, 0xb4, 0x0d, 0xba, 0x0d, 0xc0, 0x0d, 0xc6, 0x0d, 0xcc, 0x0d, 0xd2, 0x0d, 0xd8, 0x0d, 0xde, 0x0d, 0xe4, 0x0d, 0xea, 0x0d, 0xf0, 0x0d, 0xf6, 0x0d, 0xfc, 0x0e, 0x02, 0x0e, 0x08, 0x0e, 0x0e, 0x0e, 0x14, 0x0e, 0x1a, 0x0e, 0x20, 0x0e, 0x26, 0x0e, 0x2c, 0x0e, 0x32, 0x0e, 0x38, 0x0e, 0x3e, 0x0e, 0x44, 0x0e, 0x4a, 0x0e, 0x50, 0x0e, 0x56, 0x0e, 0x5c, 0x0e, 0x62, 0x0e, 0x68, 0x0e, 0x6e, 0x0e, 0x74, 0x0e, 0x7a, 0x0e, 0x80, 0x0e, 0x86, 0x0e, 0x8c, 0x0e, 0x92, 0x0e, 0x98, 0x0e, 0x9e, 0x0e, 0xa4, 0x0e, 0xaa, 0x0e, 0xb0, 0x0e, 0xb6, 0x0e, 0xbc, 0x0e, 0xc2, 0x0e, 0xc8, 0x0e, 0xce, 0x0e, 0xd4, 0x0e, 0xda, 0x0e, 0xe2, 0x0e, 0xe8, 0x0e, 0xee, 0x0e, 0xf4, 0x0e, 0xfa, 0x0f, 0x00, 0x0f, 0x06, 0x0f, 0x0c, 0x0f, 0x12, 0x0f, 0x18, 0x0f, 0x1e, 0x0f, 0x26, 0x0f, 0x2c, 0x0f, 0x32, 0x0f, 0x38, 0x0f, 0x3e, 0x0f, 0x44, 0x0f, 0x4a, 0x0f, 0x50, 0x0f, 0x56, 0x0f, 0x5c, 0x0f, 0x62, 0x0f, 0x68, 0x0f, 0x6e, 0x0f, 0x74, 0x0f, 0x7a, 0x0f, 0x80, 0x0f, 0x86, 0x0f, 0x8c, 0x0f, 0x92, 0x0f, 0x98, 0x0f, 0x9e, 0x0f, 0xa4, 0x0f, 0xaa, 0x0f, 0xb0, 0x0f, 0xb6, 0x0f, 0xbc, 0x0f, 0xc2, 0x0f, 0xc8, 0x0f, 0xce, 0x0f, 0xd4, 0x0f, 0xda, 0x0f, 0xe0, 0x0f, 0xe6, 0x0f, 0xec, 0x0f, 0xf2, 0x0f, 0xf8, 0x0f, 0xfe, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x10, 0x10, 0x16, 0x10, 0x1c, 0x10, 0x22, 0x10, 0x28, 0x10, 0x2e, 0x10, 0x34, 0x10, 0x3a, 0x10, 0x40, 0x10, 0x46, 0x10, 0x4c, 0x10, 0x52, 0x10, 0x58, 0x10, 0x5e, 0x10, 0x64, 0x10, 0x6a, 0x10, 0x72, 0x10, 0x78, 0x10, 0x7e, 0x10, 0x84, 0x10, 0x8a, 0x10, 0x90, 0x10, 0x96, 0x10, 0x9c, 0x10, 0xa2, 0x10, 0xa8, 0x10, 0xae, 0x10, 0xb4, 0x10, 0xba, 0x10, 0xc0, 0x10, 0xc6, 0x10, 0xcc, 0x10, 0xd2, 0x10, 0xd8, 0x10, 0xde, 0x10, 0xe4, 0x10, 0xea, 0x10, 0xf2, 0x10, 0xf8, 0x10, 0xfe, 0x11, 0x04, 0x11, 0x0a, 0x11, 0x10, 0x11, 0x16, 0x11, 0x1c, 0x11, 0x22, 0x11, 0x28, 0x11, 0x2e, 0x11, 0x34, 0x11, 0x3c, 0x11, 0x42, 0x11, 0x48, 0x11, 0x4e, 0x11, 0x54, 0x11, 0x5a, 0x11, 0x60, 0x11, 0x66, 0x11, 0x6c, 0x11, 0x72, 0x11, 0x78, 0x11, 0x7e, 0x11, 0x84, 0x11, 0x8a, 0x11, 0x90, 0x11, 0x96, 0x11, 0x9c, 0x11, 0xa2, 0x11, 0xa8, 0x11, 0xae, 0x11, 0xb4, 0x11, 0xba, 0x11, 0xc0, 0x11, 0xc6, 0x11, 0xcc, 0x11, 0xd2, 0x11, 0xd8, 0x11, 0xde, 0x11, 0xe4, 0x11, 0xea, 0x11, 0xf0, 0x11, 0xf6, 0x11, 0xfc, 0x12, 0x02, 0x12, 0x08, 0x12, 0x0e, 0x12, 0x14, 0x12, 0x1a, 0x12, 0x20, 0x12, 0x26, 0x12, 0x2c, 0x12, 0x32, 0x12, 0x38, 0x12, 0x3e, 0x12, 0x44, 0x12, 0x4a, 0x12, 0x50, 0x12, 0x56, 0x12, 0x5c, 0x12, 0x62, 0x12, 0x68, 0x12, 0x6e, 0x12, 0x74, 0x12, 0x7a, 0x12, 0x80, 0x12, 0x86, 0x12, 0x8c, 0x12, 0x92, 0x12, 0x98, 0x12, 0x9e, 0x12, 0xa4, 0x12, 0xaa, 0x12, 0xb0, 0x12, 0xb6, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xf7, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa1, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x06, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x10, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x0f, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x0c, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa9, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3d, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x51, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x34, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x8f, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x85, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x33, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x77, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x0f, 0x04, 0x7b, 0x00, 0x23, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x60, 0x04, 0x7b, 0x00, 0x17, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x53, 0x04, 0x7b, 0x00, 0x12, 0x00, 0x01, 0x01, 0xb0, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x2c, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x02, 0x06, 0x2f, 0x00, 0x01, 0x01, 0x02, 0x06, 0x2f, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x02, 0x02, 0x34, 0x04, 0x7b, 0x00, 0x0c, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x30, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xef, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfd, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x14, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xf3, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x25, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x23, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x7f, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x34, 0x04, 0x7b, 0x00, 0x1a, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x0f, 0x04, 0x7b, 0x00, 0x23, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x4c, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x2f, 0x05, 0xf0, 0x00, 0x02, 0x01, 0x00, 0x04, 0x7b, 0x00, 0x04, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x03, 0xab, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x34, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfd, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xb0, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1f, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xf7, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x7d, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x1b, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x06, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x78, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x10, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x10, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfb, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x41, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa9, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x79, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xef, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfd, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x34, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfd, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x34, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x63, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x33, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x23, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x77, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x77, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x53, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x47, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xf3, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfd, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x02, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x4b, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x0f, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x02, 0x06, 0x2f, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3d, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x33, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x23, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x46, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x18, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x8d, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x02, 0x01, 0x9f, 0x04, 0x7b, 0x00, 0x03, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x25, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x16, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x16, 0x04, 0x7b, 0x00, 0x02, 0x02, 0x0f, 0x04, 0x7c, 0x00, 0x08, 0x00, 0x01, 0x02, 0x06, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x06, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xa3, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x02, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x2c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x2c, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x25, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x25, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x01, 0x06, 0x2f, 0x00, 0x01, 0x00, 0xec, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x59, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x70, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xcb, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x02, 0x02, 0x34, 0x04, 0x7b, 0x00, 0x0e, 0x00, 0x01, 0x04, 0x18, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x9e, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xfa, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xfa, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x24, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x31, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x5b, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x01, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x15, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xef, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xbf, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xd9, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfd, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xf3, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x21, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x26, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x84, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x01, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x84, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x01, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x24, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x0d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5f, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x02, 0x06, 0x2f, 0x00, 0x01, 0x02, 0x66, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x02, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x2c, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x84, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x01, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xf3, 0x05, 0xf0, 0x00, 0x01, 0x04, 0x19, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xd0, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x0f, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3e, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x0f, 0x04, 0x7c, 0x00, 0x08, 0x00, 0x01, 0x02, 0x0a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xf4, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x5f, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x41, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x46, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe0, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x0a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x31, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x35, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x2c, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe4, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x65, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x25, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x60, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x07, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3e, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3e, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa3, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x35, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x07, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xa3, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x02, 0x06, 0x2f, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xc0, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xf4, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x51, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x10, 0x05, 0xf0, 0x00, 0x01, 0x04, 0x59, 0x05, 0xf0, 0x00, 0x01, 0x04, 0x00, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x56, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1b, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x03, 0xe0, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x34, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa9, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x23, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xf7, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x34, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x30, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x18, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x85, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x6d, 0x05, 0xf0, 0x00, 0x01, 0x03, 0xd9, 0x05, 0xf0, 0x00, 0x01, 0x03, 0xd9, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x1c, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x2c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x13, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x96, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x18, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x58, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x24, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x0a, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xaa, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x4b, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x3e, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x06, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x41, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x35, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xac, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xb7, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x41, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x5a, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x18, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x23, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x13, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x25, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x5a, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x10, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x4b, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x4b, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xd2, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xcd, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x86, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xaa, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x35, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xef, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x02, 0x06, 0x2f, 0x00, 0x01, 0x01, 0x02, 0x06, 0x2f, 0x00, 0x01, 0x01, 0x02, 0x06, 0x2f, 0x00, 0x01, 0x03, 0x94, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x8d, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x15, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5a, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x5c, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x07, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xc1, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x0c, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x1a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xaa, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x2a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd1, 0x04, 0x7b, 0x00, 0x01, 0x03, 0xe0, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x3a, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xda, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x34, 0x04, 0x7b, 0x00, 0x01, 0x03, 0xe0, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x3a, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xc5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd4, 0x05, 0xfa, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xcf, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x52, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x03, 0xe0, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x3e, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x35, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x35, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x03, 0xb1, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x0e, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x34, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x10, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x5f, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xb7, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x0a, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x85, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x25, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xac, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x35, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xac, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x41, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe4, 0x04, 0x7b, 0x00, 0x01, 0x03, 0xab, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x18, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x18, 0x04, 0x83, 0x00, 0x01, 0x02, 0x18, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe3, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x06, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfc, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xb7, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x41, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x85, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x76, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x76, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x76, 0x04, 0x7b, 0x00, 0x01, 0x03, 0xab, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe0, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x4e, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x4e, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x18, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x29, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x25, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xf3, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xcb, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfc, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xac, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xa1, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa1, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa1, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa1, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x97, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x37, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xb7, 0x05, 0xf0, 0x00, 0x02, 0x02, 0xf7, 0x05, 0xf0, 0x00, 0x16, 0x00, 0x01, 0x03, 0xd5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xfd, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x0f, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x98, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xa7, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x94, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xda, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xe2, 0x05, 0xe2, 0x00, 0x01, 0x02, 0xd3, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xbf, 0x05, 0xf0, 0x00, 0x02, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x0c, 0x00, 0x01, 0x03, 0x2a, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x3c, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x08, 0x05, 0xe2, 0x00, 0x01, 0x02, 0xad, 0x05, 0xe2, 0x00, 0x01, 0x02, 0x3a, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x0f, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xe2, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x82, 0x04, 0x44, 0x00, 0x01, 0x02, 0x7f, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x33, 0x05, 0xf0, 0x00, 0x01, 0x03, 0xde, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xc7, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x7f, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xc1, 0x05, 0xe7, 0x00, 0x01, 0x02, 0x5a, 0x05, 0xe7, 0x00, 0x01, 0x01, 0x56, 0x06, 0x31, 0x00, 0x01, 0x02, 0xab, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x09, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xaf, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x0e, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x0c, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x0c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x3d, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x18, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfd, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x77, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1a, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x76, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x7c, 0x05, 0xd3, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x8f, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xf3, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x21, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5f, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x65, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x34, 0x04, 0x7b, 0x00, 0x01, 0x01, 0xa5, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x51, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x77, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1e, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x0f, 0x04, 0x7b, 0x00, 0x08, 0x00, 0x01, 0x01, 0xe3, 0x04, 0x7b, 0x00, 0x01, 0x04, 0x80, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x6f, 0x04, 0x7b, 0x00, 0x01, 0x03, 0xc5, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x74, 0x04, 0x7b, 0x00, 0x01, 0x04, 0x4a, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x6f, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x96, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1d, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x96, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1d, 0x04, 0x71, 0x00, 0x01, 0x03, 0x96, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1d, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x01, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x0c, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x69, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x39, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x83, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xe8, 0x05, 0xf0, 0x00, 0x02, 0x02, 0x85, 0x04, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x04, 0xe3, 0x05, 0xf0, 0x00, 0x01, 0x03, 0xaa, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x62, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x4c, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x63, 0x04, 0x7b, 0x00, 0x01, 0x02, 0xd6, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x30, 0x04, 0x7b, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xab, 0x05, 0xf0, 0x00, 0x02, 0x01, 0x00, 0x04, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa4, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x6d, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xc4, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa9, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x06, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x2c, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x5b, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa9, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x48, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x3d, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xe1, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x51, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xef, 0x04, 0x7b, 0x00, 0x01, 0x03, 0x0f, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x4b, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x11, 0x05, 0xf0, 0x00, 0x01, 0x01, 0xfc, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x1a, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x10, 0x07, 0x88, 0x00, 0x01, 0x04, 0x51, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa9, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xe9, 0x06, 0x04, 0x00, 0x01, 0x02, 0xb9, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb9, 0x05, 0xf0, 0x00, 0x01, 0x03, 0x06, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x69, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x68, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xb5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa8, 0x05, 0xf0, 0x00, 0x01, 0x03, 0xb0, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xd5, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x40, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x8c, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xfd, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x9a, 0x05, 0xf0, 0x00, 0x01, 0x04, 0x05, 0x05, 0xf7, 0x00, 0x01, 0x02, 0xe6, 0x05, 0xf7, 0x00, 0x01, 0x02, 0x8b, 0x05, 0xf7, 0x00, 0x01, 0x02, 0x6e, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x1f, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x37, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0x49, 0x05, 0xf0, 0x00, 0x01, 0x02, 0xa9, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x01, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x02, 0x04, 0x7b, 0x00, 0x01, 0x02, 0x9f, 0x05, 0xf0, 0x00, 0x01, 0x00, 0xfa, 0x05, 0xf0, 0x00, 0x01, 0x01, 0x02, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x02, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x02, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x99, 0x05, 0xf0, 0x00, 0x02, 0x03, 0x43, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6f, 0x00, 0x13, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3d, 0x00, 0x0a, 0x00, 0x44, 0x00, 0x5d, 0x00, 0x24, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x3e, 0x00, 0xa8, 0x00, 0xa9, 0x00, 0x3f, 0x00, 0xb2, 0x00, 0xb2, 0x00, 0x41, 0x00, 0xba, 0x00, 0xba, 0x00, 0x42, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x43, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0x44, 0x00, 0xd1, 0x00, 0xd1, 0x00, 0x46, 0x00, 0xe8, 0x00, 0xe9, 0x00, 0x47, 0x00, 0xf3, 0x00, 0xf3, 0x00, 0x49, 0x00, 0xfa, 0x00, 0xfa, 0x00, 0x4a, 0x01, 0x0d, 0x01, 0x0d, 0x00, 0x4b, 0x01, 0x15, 0x01, 0x15, 0x00, 0x4c, 0x01, 0x28, 0x01, 0x29, 0x00, 0x4d, 0x01, 0x35, 0x01, 0x35, 0x00, 0x4f, 0x01, 0x41, 0x01, 0x42, 0x00, 0x50, 0x01, 0x45, 0x01, 0x45, 0x00, 0x52, 0x01, 0x48, 0x01, 0x49, 0x00, 0x53, 0x01, 0x4e, 0x01, 0x4e, 0x00, 0x55, 0x01, 0x50, 0x01, 0x56, 0x00, 0x56, 0x01, 0x58, 0x01, 0x59, 0x00, 0x5d, 0x01, 0x5b, 0x01, 0x5d, 0x00, 0x5f, 0x01, 0x5f, 0x01, 0x5f, 0x00, 0x62, 0x01, 0x61, 0x01, 0x61, 0x00, 0x63, 0x01, 0x66, 0x01, 0x66, 0x00, 0x64, 0x01, 0x69, 0x01, 0x6a, 0x00, 0x65, 0x01, 0x6c, 0x01, 0x70, 0x00, 0x67, 0x01, 0x74, 0x01, 0x7b, 0x00, 0x6c, 0x01, 0xac, 0x01, 0xac, 0x00, 0x74, 0x01, 0xf6, 0x01, 0xf9, 0x00, 0x75, 0x02, 0x05, 0x02, 0x0c, 0x00, 0x79, 0x02, 0x0e, 0x02, 0x4a, 0x00, 0x81, 0x02, 0x4c, 0x02, 0x67, 0x00, 0xbe, 0x02, 0x69, 0x02, 0x6b, 0x00, 0xda, 0x02, 0x6d, 0x02, 0x6d, 0x00, 0xdd, 0x03, 0x45, 0x03, 0x5d, 0x00, 0xde, 0x03, 0x64, 0x03, 0x65, 0x00, 0xf7, 0x03, 0x69, 0x03, 0x69, 0x00, 0xf9, 0x03, 0x6b, 0x03, 0x6b, 0x00, 0xfa, 0x03, 0x6d, 0x03, 0x6d, 0x00, 0xfb, 0x03, 0x6f, 0x03, 0x6f, 0x00, 0xfc, 0x03, 0x77, 0x03, 0x77, 0x00, 0xfd, 0x03, 0x84, 0x03, 0x8a, 0x00, 0xfe, 0x03, 0x8c, 0x03, 0x8c, 0x01, 0x05, 0x03, 0x90, 0x03, 0x90, 0x01, 0x06, 0x03, 0x98, 0x03, 0x9a, 0x01, 0x07, 0x03, 0x9d, 0x03, 0x9e, 0x01, 0x0a, 0x03, 0xa3, 0x03, 0xac, 0x01, 0x0c, 0x03, 0xae, 0x03, 0xcc, 0x01, 0x16, 0x03, 0xce, 0x03, 0xe3, 0x01, 0x35, 0x03, 0xe8, 0x03, 0xef, 0x01, 0x4b, 0x03, 0xf3, 0x04, 0x01, 0x01, 0x53, 0x04, 0x04, 0x04, 0x09, 0x01, 0x62, 0x04, 0x22, 0x04, 0x23, 0x01, 0x68, 0x04, 0x2a, 0x04, 0x2b, 0x01, 0x6a, 0x04, 0x2e, 0x04, 0x36, 0x01, 0x6c, 0x04, 0x40, 0x04, 0x40, 0x01, 0x75, 0x04, 0x4d, 0x04, 0x4d, 0x01, 0x76, 0x04, 0x58, 0x04, 0x58, 0x01, 0x77, 0x04, 0x5e, 0x04, 0x5e, 0x01, 0x78, 0x04, 0x62, 0x04, 0x62, 0x01, 0x79, 0x04, 0x7c, 0x04, 0x7d, 0x01, 0x7a, 0x04, 0x8b, 0x04, 0x8b, 0x01, 0x7c, 0x04, 0x92, 0x04, 0x93, 0x01, 0x7d, 0x04, 0xa7, 0x04, 0xa7, 0x01, 0x7f, 0x04, 0xb2, 0x04, 0xb3, 0x01, 0x80, 0x04, 0xb5, 0x04, 0xb5, 0x01, 0x82, 0x04, 0xb7, 0x04, 0xb7, 0x01, 0x83, 0x04, 0xba, 0x04, 0xc2, 0x01, 0x84, 0x04, 0xc5, 0x04, 0xce, 0x01, 0x8d, 0x04, 0xd1, 0x04, 0xd5, 0x01, 0x97, 0x04, 0xd8, 0x04, 0xde, 0x01, 0x9c, 0x04, 0xe2, 0x04, 0xe2, 0x01, 0xa3, 0x05, 0x23, 0x05, 0x23, 0x01, 0xa4, 0x05, 0x5c, 0x05, 0x63, 0x01, 0xa5, 0x06, 0x4a, 0x06, 0x4b, 0x01, 0xad, 0x07, 0xec, 0x07, 0xec, 0x01, 0xaf, 0x07, 0xf4, 0x07, 0xf7, 0x01, 0xb0, 0x07, 0xf9, 0x07, 0xfb, 0x01, 0xb4, 0x07, 0xfe, 0x07, 0xfe, 0x01, 0xb7, 0x08, 0x01, 0x08, 0x06, 0x01, 0xb8, 0x08, 0x0d, 0x08, 0x0d, 0x01, 0xbe, 0x08, 0x11, 0x08, 0x11, 0x01, 0xbf, 0x08, 0x15, 0x08, 0x16, 0x01, 0xc0, 0x08, 0x18, 0x08, 0x1a, 0x01, 0xc2, 0x08, 0x1c, 0x08, 0x1c, 0x01, 0xc5, 0x08, 0x1e, 0x08, 0x22, 0x01, 0xc6, 0x08, 0x25, 0x08, 0x28, 0x01, 0xcb, 0x0a, 0x1d, 0x0a, 0x1d, 0x01, 0xcf, 0x0e, 0x2b, 0x0e, 0x45, 0x01, 0xd0, 0x0e, 0x48, 0x0e, 0x49, 0x01, 0xeb, 0x0e, 0x62, 0x0e, 0x65, 0x01, 0xed, 0x0e, 0x67, 0x0e, 0x68, 0x01, 0xf1, 0x0e, 0x6a, 0x0e, 0x75, 0x01, 0xf3, 0x0e, 0x78, 0x0e, 0x87, 0x01, 0xff, 0x0e, 0x89, 0x0e, 0x89, 0x02, 0x0f, 0x0e, 0x8b, 0x0e, 0x8f, 0x02, 0x10, 0x0e, 0x94, 0x0e, 0xa8, 0x02, 0x15, 0x0f, 0x93, 0x0f, 0xa5, 0x02, 0x2a, 0x0f, 0xbd, 0x0f, 0xbd, 0x02, 0x3d, 0x0f, 0xbf, 0x0f, 0xbf, 0x02, 0x3e, 0x0f, 0xf4, 0x0f, 0xfd, 0x02, 0x3f, 0x11, 0x1b, 0x11, 0x1d, 0x02, 0x49, 0x11, 0x34, 0x11, 0x34, 0x02, 0x4c, 0x11, 0x3e, 0x11, 0x3e, 0x02, 0x4d, 0x11, 0x42, 0x11, 0x42, 0x02, 0x4e, 0x11, 0x45, 0x11, 0x46, 0x02, 0x4f, 0x11, 0x48, 0x11, 0x48, 0x02, 0x51, 0x11, 0xb8, 0x11, 0xb8, 0x02, 0x52, 0x00, 0x02, 0x00, 0x0c, 0x02, 0xb1, 0x02, 0xc5, 0x00, 0x00, 0x02, 0xee, 0x02, 0xf3, 0x00, 0x15, 0x02, 0xf5, 0x02, 0xf5, 0x00, 0x1b, 0x02, 0xf7, 0x02, 0xf7, 0x00, 0x1c, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x1d, 0x03, 0x01, 0x03, 0x02, 0x00, 0x20, 0x03, 0x04, 0x03, 0x04, 0x00, 0x22, 0x04, 0x17, 0x04, 0x1b, 0x00, 0x23, 0x05, 0x4a, 0x05, 0x4f, 0x00, 0x28, 0x07, 0xe3, 0x07, 0xe9, 0x00, 0x2e, 0x10, 0xeb, 0x10, 0xf5, 0x00, 0x35, 0x11, 0xac, 0x11, 0xac, 0x00, 0x40, 0x00, 0x41, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x01, 0x46, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x52, 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x01, 0x8a, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x01, 0x96, 0x00, 0x00, 0x01, 0x9c, 0x00, 0x00, 0x01, 0xa2, 0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x01, 0xae, 0x00, 0x00, 0x01, 0xb4, 0x00, 0x00, 0x01, 0xba, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc6, 0x00, 0x00, 0x01, 0xcc, 0x00, 0x00, 0x01, 0xd2, 0x00, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x01, 0xde, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x01, 0xea, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x01, 0xf6, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x26, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0x02, 0x66, 0x00, 0x00, 0x02, 0x6c, 0x00, 0x00, 0x02, 0x72, 0x00, 0x00, 0x02, 0x78, 0x00, 0x00, 0x02, 0x7e, 0x00, 0x00, 0x02, 0x84, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x00, 0x02, 0x90, 0x00, 0x00, 0x02, 0x96, 0x00, 0x02, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x04, 0x00, 0x02, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x04, 0x00, 0x02, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x07, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x02, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x04, 0x00, 0x02, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x08, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x02, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x07, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0xb0, 0x03, 0x6f, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x72, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x72, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0xb0, 0x04, 0x72, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfd, 0xcd, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0xa6, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x6e, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x48, 0x04, 0x7b, 0x00, 0x01, 0xfd, 0x39, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x02, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x0c, 0x00, 0x02, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x10, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0xfe, 0x34, 0x04, 0x7b, 0x00, 0x01, 0x01, 0x3e, 0x00, 0xfe, 0x00, 0x01, 0x01, 0x44, 0x00, 0x0c, 0x00, 0x1e, 0x00, 0x3e, 0x00, 0x44, 0x00, 0x4a, 0x00, 0x50, 0x00, 0x56, 0x00, 0x5c, 0x00, 0x62, 0x00, 0x68, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x7a, 0x00, 0x80, 0x00, 0x86, 0x00, 0x8c, 0x00, 0x92, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xa4, 0x00, 0xaa, 0x00, 0xb0, 0x00, 0xb6, 0x00, 0xbc, 0x00, 0xc2, 0x00, 0xc8, 0x00, 0xce, 0x00, 0xd4, 0x00, 0xda, 0x00, 0xe0, 0x00, 0xe6, 0x00, 0xec, 0x00, 0x01, 0x04, 0x5c, 0x00, 0x00, 0x00, 0x01, 0x03, 0x60, 0x00, 0x00, 0x00, 0x01, 0x01, 0x35, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd7, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa3, 0x00, 0x00, 0x00, 0x01, 0x02, 0x59, 0x00, 0x00, 0x00, 0x01, 0x02, 0x77, 0xff, 0xfe, 0x00, 0x01, 0x03, 0x54, 0x00, 0x00, 0x00, 0x01, 0x03, 0x14, 0x00, 0x00, 0x00, 0x01, 0x01, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x02, 0x35, 0x00, 0x00, 0x00, 0x01, 0x03, 0xb1, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe1, 0xfe, 0x56, 0x00, 0x01, 0x01, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd7, 0x00, 0x00, 0x00, 0x01, 0x02, 0x35, 0x00, 0x00, 0x00, 0x01, 0x01, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x01, 0x35, 0x00, 0x00, 0x00, 0x01, 0x02, 0xd7, 0x00, 0x00, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x02, 0x53, 0x00, 0x00, 0x00, 0x01, 0x02, 0x47, 0xfe, 0x52, 0x00, 0x01, 0x02, 0x46, 0x00, 0x00, 0x00, 0x01, 0x01, 0x95, 0x00, 0x00, 0x00, 0x01, 0x01, 0x23, 0x00, 0x00, 0x00, 0x01, 0x02, 0x35, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe1, 0xfe, 0x52, 0x00, 0x01, 0x04, 0xb6, 0x00, 0x00, 0x00, 0x01, 0x01, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1e, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x32, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x44, 0x00, 0x48, 0x00, 0x4c, 0x00, 0x52, 0x00, 0x58, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x9a, 0x00, 0xba, 0x00, 0xf3, 0x01, 0x48, 0x01, 0x59, 0x01, 0x61, 0x01, 0x79, 0x01, 0x7a, 0x01, 0x7b, 0x02, 0x12, 0x02, 0x16, 0x02, 0x2a, 0x02, 0x37, 0x02, 0x54, 0x0e, 0x38, 0x11, 0x1c, 0x00, 0x01, 0x00, 0x01, 0x02, 0xd9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0xfe, 0x29, 0x00, 0x00, 0x00, 0x02, 0x26, 0xf0, 0x00, 0x04, 0x00, 0x00, 0x21, 0x30, 0x23, 0x20, 0x00, 0x35, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x72, 0x00, 0x39, 0x00, 0x4b, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0xff, 0x88, 0xff, 0xad, 0xff, 0x9a, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc9, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x90, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x88, 0xff, 0xad, 0x00, 0x00, 0xff, 0x75, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0xad, 0xff, 0x61, 0xff, 0x75, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0x61, 0x00, 0x00, 0xff, 0x61, 0xff, 0x75, 0xff, 0xad, 0xff, 0x90, 0xfe, 0xf8, 0xff, 0x03, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0xff, 0xb7, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0x90, 0xff, 0x90, 0xff, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xc9, 0xff, 0x44, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0xff, 0x61, 0xff, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0x6b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x44, 0xff, 0x90, 0x00, 0x00, 0xff, 0xb7, 0xff, 0x90, 0xff, 0x44, 0xff, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0xff, 0xb7, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xdc, 0xff, 0xb7, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0xfe, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xd3, 0xff, 0xc9, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xc1, 0xff, 0xb7, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xc1, 0xff, 0x90, 0x00, 0x00, 0xff, 0x29, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0xff, 0x61, 0xff, 0xc9, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0xff, 0x7d, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0xdc, 0xff, 0x9a, 0x00, 0x00, 0xff, 0x9a, 0xff, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xe6, 0xff, 0x9a, 0xff, 0x1f, 0xff, 0x44, 0x00, 0x00, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x61, 0xfd, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xff, 0xad, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0x44, 0x00, 0x00, 0xff, 0xd3, 0xfe, 0xc1, 0x00, 0x00, 0xff, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xb7, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xa4, 0xff, 0xb7, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x26, 0xfe, 0xb7, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0x7d, 0x00, 0x00, 0xff, 0xad, 0xff, 0xb7, 0xff, 0xc1, 0xff, 0xad, 0x00, 0x00, 0xff, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0x00, 0x00, 0xff, 0x90, 0xff, 0xad, 0x00, 0x00, 0xff, 0x7d, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0x90, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x9a, 0xff, 0xd3, 0xff, 0xa4, 0x00, 0x00, 0xff, 0xa4, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0xff, 0x7d, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x44, 0xff, 0x0d, 0xff, 0x1f, 0xff, 0x61, 0x00, 0x00, 0xff, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xad, 0xfe, 0xa4, 0x00, 0x00, 0xfe, 0xa4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xa4, 0xfe, 0xd3, 0xfe, 0xad, 0x00, 0x00, 0xfe, 0xc9, 0x00, 0x00, 0xfe, 0xad, 0x00, 0x00, 0xfe, 0xc1, 0xff, 0x44, 0xff, 0x90, 0x00, 0x00, 0xff, 0x88, 0xff, 0x11, 0xfe, 0xe0, 0x00, 0x00, 0xfe, 0xf4, 0xfe, 0xe7, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xfe, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xfe, 0xf8, 0xff, 0x59, 0xff, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc9, 0xff, 0x4e, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0xff, 0x61, 0xff, 0x61, 0x00, 0x00, 0xff, 0x61, 0xff, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xe6, 0x00, 0x00, 0xff, 0xad, 0xff, 0x15, 0xff, 0x88, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7d, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0x90, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x88, 0x00, 0x00, 0xff, 0x88, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xfe, 0xf8, 0x00, 0x00, 0xff, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7d, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0x00, 0x00, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x61, 0xff, 0xad, 0xff, 0xd3, 0x00, 0x00, 0xff, 0x0d, 0xfe, 0x61, 0xfe, 0xf0, 0xff, 0x61, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xe6, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xff, 0x6b, 0x00, 0x00, 0xff, 0x90, 0xfe, 0xe6, 0xfe, 0xf0, 0x00, 0x00, 0xfe, 0xf0, 0xff, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0xdc, 0xfe, 0xf8, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0x6b, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xb7, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0xff, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xb7, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0xff, 0x90, 0xff, 0xa4, 0x00, 0x00, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0xff, 0xb7, 0xff, 0x7d, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x44, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0xd3, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xd3, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc9, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xfe, 0xc9, 0x00, 0x00, 0xff, 0xc9, 0xff, 0x61, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0x44, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xfe, 0xdc, 0xff, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0xff, 0x90, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0xff, 0x4e, 0xff, 0x90, 0xff, 0x90, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x90, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x88, 0xff, 0xad, 0x00, 0x00, 0xff, 0x75, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0xad, 0xff, 0x61, 0xff, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf8, 0xff, 0x03, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x90, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x88, 0xff, 0xad, 0x00, 0x00, 0xff, 0x75, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0xad, 0xff, 0x61, 0xff, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xfe, 0xf8, 0xff, 0x03, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x90, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x88, 0xff, 0xad, 0x00, 0x00, 0xff, 0x75, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0xad, 0xff, 0x61, 0xff, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xfe, 0xf8, 0xff, 0x03, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xad, 0xff, 0xa4, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6b, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0x90, 0xff, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xa4, 0xff, 0x90, 0xff, 0xb7, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x90, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x88, 0xff, 0xad, 0x00, 0x00, 0xff, 0x75, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0xad, 0xff, 0x61, 0xff, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xfe, 0xf8, 0xff, 0x02, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x90, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x88, 0xff, 0xad, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0xad, 0xff, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xfe, 0xf8, 0xff, 0x02, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xc9, 0xff, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7d, 0xff, 0x44, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xdc, 0xff, 0xd3, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0xff, 0xd3, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc9, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xfe, 0xc9, 0x00, 0x00, 0xff, 0x44, 0xff, 0x0d, 0xff, 0x1f, 0xff, 0x61, 0x00, 0x00, 0xff, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xad, 0xfe, 0xa4, 0x00, 0x00, 0xfe, 0xa4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xa4, 0xfe, 0xd3, 0xfe, 0xad, 0x00, 0x00, 0xfe, 0xc9, 0x00, 0x00, 0xfe, 0xad, 0x00, 0x00, 0xfe, 0xc1, 0xff, 0x44, 0xff, 0x90, 0x00, 0x00, 0xff, 0x88, 0xfe, 0xad, 0xfe, 0xa4, 0x00, 0x00, 0xfe, 0xa4, 0xfe, 0xc9, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xfe, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd3, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x72, 0x00, 0x39, 0x00, 0x4b, 0x00, 0x00, 0xff, 0x44, 0x00, 0x00, 0xff, 0x88, 0xff, 0xad, 0xff, 0x9a, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc9, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf8, 0xff, 0xc1, 0xff, 0xb7, 0xff, 0xc1, 0xff, 0xc1, 0xff, 0xb7, 0xff, 0xc1, 0xff, 0xb7, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x90, 0xff, 0x6b, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xb7, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7d, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xff, 0xb7, 0xff, 0x90, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xb7, 0x00, 0x2f, 0xff, 0x90, 0xff, 0x90, 0x00, 0x00, 0xfe, 0xe6, 0x00, 0x00, 0xfe, 0x88, 0xff, 0x03, 0xff, 0xb7, 0xfe, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xb7, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x15, 0xff, 0x3c, 0x00, 0x00, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0x00, 0x10, 0x00, 0x10, 0x00, 0x01, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x26, 0x00, 0x26, 0x00, 0x04, 0x00, 0x27, 0x00, 0x27, 0x00, 0x05, 0x00, 0x29, 0x00, 0x29, 0x00, 0x06, 0x00, 0x2a, 0x00, 0x2a, 0x00, 0x07, 0x00, 0x2b, 0x00, 0x2b, 0x00, 0x08, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x09, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x0b, 0x00, 0x32, 0x00, 0x32, 0x00, 0x0c, 0x00, 0x33, 0x00, 0x33, 0x00, 0x0d, 0x00, 0x34, 0x00, 0x34, 0x00, 0x0e, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0f, 0x00, 0x36, 0x00, 0x36, 0x00, 0x10, 0x00, 0x37, 0x00, 0x37, 0x00, 0x11, 0x00, 0x38, 0x00, 0x38, 0x00, 0x12, 0x00, 0x39, 0x00, 0x39, 0x00, 0x13, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x14, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x15, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x16, 0x00, 0x3d, 0x00, 0x3d, 0x00, 0x17, 0x00, 0x48, 0x00, 0x48, 0x00, 0x18, 0x00, 0x49, 0x00, 0x49, 0x00, 0x19, 0x00, 0x4e, 0x00, 0x4e, 0x00, 0x1a, 0x00, 0x51, 0x00, 0x51, 0x00, 0x1b, 0x00, 0x52, 0x00, 0x52, 0x00, 0x1c, 0x00, 0x55, 0x00, 0x55, 0x00, 0x1d, 0x00, 0x59, 0x00, 0x59, 0x00, 0x1e, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x1f, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x20, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x21, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x22, 0x00, 0x7d, 0x00, 0x7d, 0x00, 0x23, 0x00, 0x82, 0x00, 0x82, 0x00, 0x24, 0x00, 0x83, 0x00, 0x84, 0x00, 0x25, 0x00, 0x85, 0x00, 0x85, 0x00, 0x26, 0x00, 0x86, 0x00, 0x86, 0x00, 0x25, 0x00, 0x88, 0x00, 0x88, 0x00, 0x27, 0x00, 0x89, 0x00, 0x89, 0x00, 0x28, 0x00, 0x92, 0x00, 0x92, 0x00, 0x05, 0x00, 0x94, 0x00, 0x98, 0x00, 0x0c, 0x00, 0x9b, 0x00, 0x9e, 0x00, 0x12, 0x00, 0x9f, 0x00, 0x9f, 0x00, 0x16, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x29, 0x00, 0xa1, 0x00, 0xa1, 0x00, 0x2a, 0x00, 0xaa, 0x00, 0xad, 0x00, 0x18, 0x00, 0xb2, 0x00, 0xb2, 0x00, 0x2b, 0x00, 0xb3, 0x00, 0xb3, 0x00, 0x1b, 0x00, 0xb4, 0x00, 0xb8, 0x00, 0x1c, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0x21, 0x00, 0xc1, 0x00, 0xc1, 0x00, 0x21, 0x00, 0xc2, 0x00, 0xc2, 0x00, 0x2c, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0x2c, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0x2d, 0x00, 0xc8, 0x00, 0xc8, 0x00, 0x28, 0x00, 0xce, 0x00, 0xce, 0x00, 0x28, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x05, 0x00, 0xd2, 0x00, 0xd2, 0x00, 0x2e, 0x00, 0xdd, 0x00, 0xdd, 0x00, 0x18, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x07, 0x00, 0xfb, 0x00, 0xfb, 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0b, 0x01, 0x02, 0x01, 0x02, 0x00, 0x2f, 0x01, 0x0a, 0x01, 0x0a, 0x00, 0x1b, 0x01, 0x16, 0x01, 0x16, 0x00, 0x0f, 0x01, 0x17, 0x01, 0x17, 0x00, 0x1d, 0x01, 0x1a, 0x01, 0x1a, 0x00, 0x0f, 0x01, 0x1b, 0x01, 0x1b, 0x00, 0x30, 0x01, 0x20, 0x01, 0x20, 0x00, 0x10, 0x01, 0x22, 0x01, 0x22, 0x00, 0x10, 0x01, 0x26, 0x01, 0x26, 0x00, 0x31, 0x01, 0x30, 0x01, 0x30, 0x00, 0x12, 0x01, 0x3a, 0x01, 0x3a, 0x00, 0x16, 0x01, 0x3f, 0x01, 0x3f, 0x00, 0x17, 0x07, 0x45, 0x07, 0x45, 0x00, 0x32, 0x07, 0x51, 0x07, 0x51, 0x00, 0x33, 0x07, 0x53, 0x07, 0x53, 0x00, 0x34, 0x0e, 0x60, 0x0e, 0x60, 0x00, 0x11, 0x0e, 0x78, 0x0e, 0x78, 0x00, 0x0a, 0x0e, 0x79, 0x0e, 0x79, 0x00, 0x1a, 0x00, 0x02, 0x00, 0xa2, 0x00, 0x10, 0x00, 0x10, 0x00, 0x01, 0x00, 0x11, 0x00, 0x11, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x03, 0x00, 0x24, 0x00, 0x24, 0x00, 0x04, 0x00, 0x25, 0x00, 0x25, 0x00, 0x05, 0x00, 0x26, 0x00, 0x26, 0x00, 0x06, 0x00, 0x27, 0x00, 0x27, 0x00, 0x07, 0x00, 0x29, 0x00, 0x29, 0x00, 0x08, 0x00, 0x2a, 0x00, 0x2a, 0x00, 0x09, 0x00, 0x2b, 0x00, 0x2b, 0x00, 0x08, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x0a, 0x00, 0x2e, 0x00, 0x2f, 0x00, 0x08, 0x00, 0x32, 0x00, 0x32, 0x00, 0x0b, 0x00, 0x33, 0x00, 0x33, 0x00, 0x08, 0x00, 0x34, 0x00, 0x34, 0x00, 0x0c, 0x00, 0x35, 0x00, 0x35, 0x00, 0x08, 0x00, 0x36, 0x00, 0x36, 0x00, 0x0d, 0x00, 0x37, 0x00, 0x37, 0x00, 0x0e, 0x00, 0x38, 0x00, 0x38, 0x00, 0x0f, 0x00, 0x39, 0x00, 0x39, 0x00, 0x10, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x11, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x12, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x3d, 0x00, 0x3d, 0x00, 0x14, 0x00, 0x44, 0x00, 0x44, 0x00, 0x15, 0x00, 0x46, 0x00, 0x46, 0x00, 0x16, 0x00, 0x47, 0x00, 0x47, 0x00, 0x17, 0x00, 0x48, 0x00, 0x48, 0x00, 0x18, 0x00, 0x49, 0x00, 0x49, 0x00, 0x19, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x1a, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x1b, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x1c, 0x00, 0x50, 0x00, 0x50, 0x00, 0x1a, 0x00, 0x51, 0x00, 0x51, 0x00, 0x1d, 0x00, 0x52, 0x00, 0x52, 0x00, 0x1e, 0x00, 0x54, 0x00, 0x54, 0x00, 0x17, 0x00, 0x55, 0x00, 0x55, 0x00, 0x1f, 0x00, 0x56, 0x00, 0x56, 0x00, 0x20, 0x00, 0x57, 0x00, 0x57, 0x00, 0x21, 0x00, 0x58, 0x00, 0x58, 0x00, 0x22, 0x00, 0x59, 0x00, 0x59, 0x00, 0x23, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x24, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x25, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x26, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x27, 0x00, 0x7d, 0x00, 0x7d, 0x00, 0x28, 0x00, 0x82, 0x00, 0x86, 0x00, 0x04, 0x00, 0x88, 0x00, 0x88, 0x00, 0x29, 0x00, 0x89, 0x00, 0x89, 0x00, 0x2a, 0x00, 0x94, 0x00, 0x98, 0x00, 0x0b, 0x00, 0x9b, 0x00, 0x9e, 0x00, 0x0f, 0x00, 0x9f, 0x00, 0x9f, 0x00, 0x13, 0x00, 0xa0, 0x00, 0xa1, 0x00, 0x08, 0x00, 0xa2, 0x00, 0xa2, 0x00, 0x2b, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0x15, 0x00, 0xa4, 0x00, 0xa7, 0x00, 0x2b, 0x00, 0xa9, 0x00, 0xa9, 0x00, 0x16, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0x2c, 0x00, 0xab, 0x00, 0xab, 0x00, 0x18, 0x00, 0xac, 0x00, 0xad, 0x00, 0x2c, 0x00, 0xb2, 0x00, 0xb2, 0x00, 0x2d, 0x00, 0xb3, 0x00, 0xb3, 0x00, 0x1d, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0x2e, 0x00, 0xb5, 0x00, 0xb5, 0x00, 0x1e, 0x00, 0xb6, 0x00, 0xb8, 0x00, 0x2e, 0x00, 0xbb, 0x00, 0xbb, 0x00, 0x2f, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0x22, 0x00, 0xbd, 0x00, 0xbe, 0x00, 0x2f, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0x26, 0x00, 0xc1, 0x00, 0xc1, 0x00, 0x26, 0x00, 0xc2, 0x00, 0xc2, 0x00, 0x30, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0x31, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0x30, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0x31, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0x30, 0x00, 0xc7, 0x00, 0xc7, 0x00, 0x31, 0x00, 0xc8, 0x00, 0xc8, 0x00, 0x06, 0x00, 0xc9, 0x00, 0xc9, 0x00, 0x32, 0x00, 0xca, 0x00, 0xca, 0x00, 0x33, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0x34, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0x33, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x35, 0x00, 0xce, 0x00, 0xce, 0x00, 0x06, 0x00, 0xcf, 0x00, 0xcf, 0x00, 0x32, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x07, 0x00, 0xd1, 0x00, 0xd1, 0x00, 0x36, 0x00, 0xd3, 0x00, 0xd3, 0x00, 0x37, 0x00, 0xd5, 0x00, 0xd5, 0x00, 0x38, 0x00, 0xd7, 0x00, 0xd7, 0x00, 0x38, 0x00, 0xd9, 0x00, 0xd9, 0x00, 0x38, 0x00, 0xdb, 0x00, 0xdb, 0x00, 0x38, 0x00, 0xdd, 0x00, 0xdd, 0x00, 0x18, 0x00, 0xde, 0x00, 0xde, 0x00, 0x33, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x39, 0x00, 0xe1, 0x00, 0xe1, 0x00, 0x1a, 0x00, 0xe2, 0x00, 0xe2, 0x00, 0x33, 0x00, 0xe4, 0x00, 0xe4, 0x00, 0x3a, 0x00, 0xf1, 0x00, 0xf1, 0x00, 0x3b, 0x00, 0xf5, 0x00, 0xf5, 0x00, 0x3b, 0x00, 0xfb, 0x00, 0xfb, 0x00, 0x08, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x01, 0x0a, 0x01, 0x0a, 0x00, 0x1d, 0x01, 0x0e, 0x01, 0x0e, 0x00, 0x33, 0x01, 0x0f, 0x01, 0x0f, 0x00, 0x3c, 0x01, 0x10, 0x01, 0x10, 0x00, 0x33, 0x01, 0x11, 0x01, 0x11, 0x00, 0x3c, 0x01, 0x12, 0x01, 0x12, 0x00, 0x3d, 0x01, 0x13, 0x01, 0x13, 0x00, 0x3c, 0x01, 0x16, 0x01, 0x16, 0x00, 0x08, 0x01, 0x17, 0x01, 0x17, 0x00, 0x1f, 0x01, 0x19, 0x01, 0x19, 0x00, 0x3b, 0x01, 0x1a, 0x01, 0x1a, 0x00, 0x08, 0x01, 0x1b, 0x01, 0x1b, 0x00, 0x1f, 0x01, 0x1c, 0x01, 0x1c, 0x00, 0x0d, 0x01, 0x1e, 0x01, 0x1e, 0x00, 0x0d, 0x01, 0x20, 0x01, 0x20, 0x00, 0x0d, 0x01, 0x21, 0x01, 0x21, 0x00, 0x20, 0x01, 0x22, 0x01, 0x22, 0x00, 0x0d, 0x01, 0x23, 0x01, 0x23, 0x00, 0x20, 0x01, 0x24, 0x01, 0x24, 0x00, 0x3e, 0x01, 0x25, 0x01, 0x25, 0x00, 0x35, 0x01, 0x26, 0x01, 0x26, 0x00, 0x0e, 0x01, 0x27, 0x01, 0x27, 0x00, 0x21, 0x01, 0x28, 0x01, 0x28, 0x00, 0x3f, 0x01, 0x2b, 0x01, 0x2b, 0x00, 0x40, 0x01, 0x2d, 0x01, 0x2d, 0x00, 0x40, 0x01, 0x2f, 0x01, 0x2f, 0x00, 0x40, 0x01, 0x30, 0x01, 0x30, 0x00, 0x0f, 0x01, 0x31, 0x01, 0x31, 0x00, 0x22, 0x01, 0x33, 0x01, 0x33, 0x00, 0x40, 0x01, 0x35, 0x01, 0x35, 0x00, 0x40, 0x01, 0x36, 0x01, 0x36, 0x00, 0x41, 0x01, 0x37, 0x01, 0x37, 0x00, 0x42, 0x01, 0x38, 0x01, 0x38, 0x00, 0x43, 0x01, 0x39, 0x01, 0x39, 0x00, 0x44, 0x01, 0x3a, 0x01, 0x3a, 0x00, 0x13, 0x01, 0x3f, 0x01, 0x3f, 0x00, 0x14, 0x01, 0x88, 0x01, 0x88, 0x00, 0x34, 0x01, 0xac, 0x01, 0xac, 0x00, 0x45, 0x01, 0xad, 0x01, 0xad, 0x00, 0x46, 0x01, 0xae, 0x01, 0xae, 0x00, 0x45, 0x01, 0xaf, 0x01, 0xaf, 0x00, 0x46, 0x01, 0xda, 0x01, 0xda, 0x00, 0x0d, 0x01, 0xdc, 0x01, 0xdc, 0x00, 0x47, 0x01, 0xdd, 0x01, 0xdd, 0x00, 0x34, 0x01, 0xf0, 0x01, 0xf0, 0x00, 0x33, 0x01, 0xf1, 0x01, 0xf1, 0x00, 0x48, 0x01, 0xf3, 0x01, 0xf3, 0x00, 0x34, 0x01, 0xf4, 0x01, 0xf4, 0x00, 0x49, 0x01, 0xf5, 0x01, 0xf5, 0x00, 0x4a, 0x05, 0xd0, 0x05, 0xd0, 0x00, 0x41, 0x05, 0xd1, 0x05, 0xd1, 0x00, 0x4b, 0x05, 0xd2, 0x05, 0xd2, 0x00, 0x4c, 0x05, 0xd3, 0x05, 0xd3, 0x00, 0x42, 0x05, 0xd4, 0x05, 0xd4, 0x00, 0x41, 0x05, 0xd5, 0x05, 0xd5, 0x00, 0x42, 0x06, 0x42, 0x06, 0x42, 0x00, 0x43, 0x06, 0x43, 0x06, 0x43, 0x00, 0x44, 0x07, 0x51, 0x07, 0x51, 0x00, 0x4d, 0x07, 0x52, 0x07, 0x52, 0x00, 0x4e, 0x07, 0x53, 0x07, 0x53, 0x00, 0x4f, 0x0e, 0x78, 0x0e, 0x78, 0x00, 0x08, 0x00, 0x01, 0x00, 0x61, 0x00, 0x10, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x29, 0x00, 0x2a, 0x00, 0x2b, 0x00, 0x2d, 0x00, 0x2e, 0x00, 0x2f, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x51, 0x00, 0x52, 0x00, 0x55, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x5c, 0x00, 0x6d, 0x00, 0x7d, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x88, 0x00, 0x89, 0x00, 0x92, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0x98, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x9e, 0x00, 0x9f, 0x00, 0xa0, 0x00, 0xa1, 0x00, 0xaa, 0x00, 0xab, 0x00, 0xac, 0x00, 0xad, 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb4, 0x00, 0xb5, 0x00, 0xb6, 0x00, 0xb7, 0x00, 0xb8, 0x00, 0xbf, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xc8, 0x00, 0xce, 0x00, 0xd0, 0x00, 0xd2, 0x00, 0xdd, 0x00, 0xe0, 0x00, 0xfb, 0x00, 0xff, 0x01, 0x02, 0x01, 0x0a, 0x01, 0x16, 0x01, 0x17, 0x01, 0x1a, 0x01, 0x1b, 0x01, 0x20, 0x01, 0x22, 0x01, 0x26, 0x01, 0x30, 0x01, 0x3a, 0x01, 0x3f, 0x07, 0x45, 0x07, 0x51, 0x07, 0x53, 0x0e, 0x60, 0x0e, 0x78, 0x0e, 0x79, 0x00, 0x02, 0x00, 0x60, 0x00, 0x04, 0x00, 0x00, 0x00, 0x24, 0x00, 0x58, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xb1, 0x00, 0x00, 0xff, 0xa3, 0x00, 0x00, 0xff, 0x9c, 0x00, 0x01, 0x0e, 0xaa, 0x00, 0x17, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x0e, 0xc2, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x0e, 0xaa, 0x0e, 0xae, 0x00, 0x00, 0x0e, 0xb0, 0x0e, 0xb4, 0x00, 0x05, 0x0e, 0xb6, 0x0e, 0xba, 0x00, 0x0a, 0x0e, 0xbc, 0x0e, 0xc0, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x01, 0xf0, 0x02, 0x9e, 0x00, 0x14, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x7a, 0x61, 0x72, 0x61, 0x62, 0x00, 0x88, 0x61, 0x72, 0x6d, 0x6e, 0x00, 0xa6, 0x62, 0x72, 0x61, 0x69, 0x00, 0xb2, 0x63, 0x61, 0x6e, 0x73, 0x00, 0xbe, 0x63, 0x68, 0x65, 0x72, 0x00, 0xca, 0x63, 0x79, 0x72, 0x6c, 0x00, 0xd6, 0x67, 0x65, 0x6f, 0x72, 0x00, 0xf8, 0x67, 0x72, 0x65, 0x6b, 0x01, 0x04, 0x68, 0x61, 0x6e, 0x69, 0x01, 0x14, 0x68, 0x65, 0x62, 0x72, 0x01, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x01, 0x2c, 0x6c, 0x61, 0x6f, 0x20, 0x01, 0x38, 0x6c, 0x61, 0x74, 0x6e, 0x01, 0x44, 0x6d, 0x61, 0x74, 0x68, 0x01, 0x9e, 0x6e, 0x6b, 0x6f, 0x20, 0x01, 0xaa, 0x6f, 0x67, 0x61, 0x6d, 0x01, 0xb6, 0x72, 0x75, 0x6e, 0x72, 0x01, 0xc2, 0x74, 0x66, 0x6e, 0x67, 0x01, 0xce, 0x74, 0x68, 0x61, 0x69, 0x01, 0xda, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x06, 0x00, 0x16, 0x00, 0x03, 0x4b, 0x55, 0x52, 0x20, 0x00, 0x16, 0x53, 0x4e, 0x44, 0x20, 0x00, 0x16, 0x55, 0x52, 0x44, 0x20, 0x00, 0x16, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x10, 0x00, 0x02, 0x4d, 0x4b, 0x44, 0x20, 0x00, 0x18, 0x53, 0x52, 0x42, 0x20, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0xff, 0xff, 0x00, 0x02, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x01, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x34, 0x00, 0x08, 0x49, 0x53, 0x4d, 0x20, 0x00, 0x46, 0x4b, 0x53, 0x4d, 0x20, 0x00, 0x46, 0x4c, 0x53, 0x4d, 0x20, 0x00, 0x46, 0x4d, 0x4f, 0x4c, 0x20, 0x00, 0x34, 0x4e, 0x53, 0x4d, 0x20, 0x00, 0x46, 0x52, 0x4f, 0x4d, 0x20, 0x00, 0x34, 0x53, 0x4b, 0x53, 0x20, 0x00, 0x46, 0x53, 0x53, 0x4d, 0x20, 0x00, 0x46, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x02, 0x00, 0x05, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0e, 0x20, 0x52, 0x51, 0x44, 0x00, 0x56, 0x61, 0x61, 0x6c, 0x74, 0x00, 0x5c, 0x61, 0x61, 0x6c, 0x74, 0x00, 0x62, 0x63, 0x63, 0x6d, 0x70, 0x00, 0x68, 0x63, 0x63, 0x6d, 0x70, 0x00, 0x6e, 0x63, 0x63, 0x6d, 0x70, 0x00, 0x76, 0x64, 0x6c, 0x69, 0x67, 0x00, 0x7e, 0x64, 0x6c, 0x69, 0x67, 0x00, 0x84, 0x68, 0x6c, 0x69, 0x67, 0x00, 0x8a, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x90, 0x6c, 0x6f, 0x63, 0x6c, 0x00, 0x96, 0x6c, 0x6f, 0x63, 0x6c, 0x00, 0x9c, 0x73, 0x61, 0x6c, 0x74, 0x00, 0xa2, 0x73, 0x61, 0x6c, 0x74, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x16, 0x00, 0x2e, 0x00, 0x36, 0x00, 0x3e, 0x00, 0x46, 0x00, 0x60, 0x00, 0x68, 0x00, 0x70, 0x00, 0x78, 0x00, 0x80, 0x00, 0x88, 0x00, 0x90, 0x00, 0x98, 0x00, 0xa0, 0x00, 0xa8, 0x00, 0xb0, 0x00, 0xb8, 0x00, 0xc0, 0x00, 0xc8, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xe0, 0x00, 0xe8, 0x00, 0x06, 0x00, 0x09, 0x00, 0x01, 0x00, 0xc2, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x01, 0x12, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x3e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x04, 0xb2, 0x05, 0x0a, 0x05, 0x62, 0x05, 0xba, 0x06, 0x12, 0x06, 0x6a, 0x06, 0xac, 0x06, 0xf4, 0x07, 0x3c, 0x07, 0x84, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0xac, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0xb0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x07, 0xb4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x07, 0xe8, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x07, 0xf8, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x08, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x9c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0xba, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0xd8, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x08, 0xee, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x52, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x88, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x90, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x98, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0xa0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0xa8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0xb0, 0x00, 0x02, 0x00, 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x02, 0x07, 0x42, 0x07, 0x42, 0x00, 0x00, 0x11, 0x52, 0x11, 0xab, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x07, 0x42, 0x07, 0x42, 0x00, 0x01, 0x11, 0x52, 0x11, 0xab, 0x00, 0x01, 0x00, 0x03, 0x00, 0x08, 0x00, 0x14, 0x00, 0x1e, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00, 0x16, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x16, 0x00, 0x8c, 0x00, 0x8c, 0x00, 0x8c, 0x00, 0x05, 0x00, 0x00, 0x03, 0x0c, 0x03, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x39, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0xf1, 0x02, 0x0b, 0x02, 0x2a, 0x02, 0x5f, 0x02, 0xb1, 0x02, 0xb2, 0x02, 0xb3, 0x02, 0xb4, 0x02, 0xb5, 0x02, 0xb6, 0x02, 0xb7, 0x02, 0xb8, 0x02, 0xb9, 0x02, 0xba, 0x02, 0xbb, 0x02, 0xbc, 0x02, 0xbd, 0x02, 0xbe, 0x02, 0xbf, 0x02, 0xc0, 0x02, 0xc1, 0x02, 0xc2, 0x02, 0xc3, 0x02, 0xc4, 0x02, 0xc5, 0x02, 0xee, 0x02, 0xef, 0x02, 0xf0, 0x02, 0xf1, 0x02, 0xf2, 0x02, 0xf3, 0x02, 0xf4, 0x02, 0xf5, 0x02, 0xf7, 0x02, 0xfb, 0x02, 0xfc, 0x02, 0xfd, 0x03, 0x01, 0x03, 0x02, 0x03, 0x04, 0x03, 0x87, 0x03, 0xea, 0x03, 0xec, 0x04, 0x17, 0x04, 0x18, 0x04, 0x19, 0x04, 0x1a, 0x05, 0x7d, 0x06, 0x1b, 0x07, 0xe3, 0x07, 0xe4, 0x07, 0xe5, 0x07, 0xe6, 0x08, 0x31, 0x08, 0x32, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x24, 0x00, 0x3d, 0x00, 0x03, 0x00, 0x45, 0x00, 0x45, 0x00, 0x03, 0x00, 0x47, 0x00, 0x47, 0x00, 0x03, 0x00, 0x49, 0x00, 0x49, 0x00, 0x03, 0x00, 0x4b, 0x00, 0x4b, 0x00, 0x03, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x01, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x03, 0x00, 0x57, 0x00, 0x57, 0x00, 0x03, 0x00, 0x82, 0x00, 0x98, 0x00, 0x03, 0x00, 0x9a, 0x00, 0xa1, 0x00, 0x03, 0x00, 0xc2, 0x00, 0xc2, 0x00, 0x03, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0x03, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0x03, 0x00, 0xc8, 0x00, 0xc8, 0x00, 0x03, 0x00, 0xca, 0x00, 0xca, 0x00, 0x03, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0x03, 0x00, 0xce, 0x00, 0xce, 0x00, 0x03, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x03, 0x00, 0xd2, 0x00, 0xd2, 0x00, 0x03, 0x00, 0xd4, 0x00, 0xd4, 0x00, 0x03, 0x00, 0xd6, 0x00, 0xd6, 0x00, 0x03, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x03, 0x00, 0xda, 0x00, 0xda, 0x00, 0x03, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0x03, 0x00, 0xde, 0x00, 0xde, 0x00, 0x03, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x03, 0x00, 0xe2, 0x00, 0xe2, 0x00, 0x03, 0x00, 0xe4, 0x00, 0xe4, 0x00, 0x03, 0x00, 0xe6, 0x00, 0xea, 0x00, 0x03, 0x00, 0xec, 0x00, 0xec, 0x00, 0x03, 0x00, 0xee, 0x00, 0xee, 0x00, 0x03, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x03, 0x00, 0xf1, 0x00, 0xf1, 0x00, 0x01, 0x00, 0xf2, 0x00, 0xf2, 0x00, 0x03, 0x00, 0xf4, 0x00, 0xf4, 0x00, 0x03, 0x00, 0xf6, 0x00, 0xf6, 0x00, 0x03, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x03, 0x00, 0xfb, 0x01, 0x05, 0x00, 0x03, 0x01, 0x07, 0x01, 0x07, 0x00, 0x03, 0x01, 0x09, 0x01, 0x09, 0x00, 0x03, 0x01, 0x0c, 0x01, 0x0c, 0x00, 0x03, 0x01, 0x0e, 0x01, 0x0e, 0x00, 0x03, 0x01, 0x10, 0x01, 0x10, 0x00, 0x03, 0x01, 0x12, 0x01, 0x12, 0x00, 0x03, 0x01, 0x14, 0x01, 0x14, 0x00, 0x03, 0x01, 0x16, 0x01, 0x16, 0x00, 0x03, 0x01, 0x18, 0x01, 0x18, 0x00, 0x03, 0x01, 0x1a, 0x01, 0x1a, 0x00, 0x03, 0x01, 0x1c, 0x01, 0x1c, 0x00, 0x03, 0x01, 0x1e, 0x01, 0x1e, 0x00, 0x03, 0x01, 0x20, 0x01, 0x20, 0x00, 0x03, 0x01, 0x22, 0x01, 0x22, 0x00, 0x03, 0x01, 0x24, 0x01, 0x24, 0x00, 0x03, 0x01, 0x26, 0x01, 0x26, 0x00, 0x03, 0x01, 0x28, 0x01, 0x28, 0x00, 0x03, 0x01, 0x2a, 0x01, 0x2a, 0x00, 0x03, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x03, 0x01, 0x2e, 0x01, 0x2e, 0x00, 0x03, 0x01, 0x30, 0x01, 0x30, 0x00, 0x03, 0x01, 0x32, 0x01, 0x32, 0x00, 0x03, 0x01, 0x34, 0x01, 0x34, 0x00, 0x03, 0x01, 0x36, 0x01, 0x36, 0x00, 0x03, 0x01, 0x38, 0x01, 0x38, 0x00, 0x03, 0x01, 0x3a, 0x01, 0x3b, 0x00, 0x03, 0x01, 0x3d, 0x01, 0x3d, 0x00, 0x03, 0x01, 0x3f, 0x01, 0x3f, 0x00, 0x03, 0x01, 0x41, 0x01, 0x41, 0x00, 0x03, 0x01, 0x48, 0x01, 0x48, 0x00, 0x03, 0x01, 0x52, 0x01, 0x52, 0x00, 0x03, 0x01, 0x54, 0x01, 0x54, 0x00, 0x03, 0x01, 0x56, 0x01, 0x56, 0x00, 0x03, 0x01, 0x79, 0x01, 0x7a, 0x00, 0x03, 0x01, 0x8f, 0x01, 0x8f, 0x00, 0x03, 0x01, 0x91, 0x01, 0x93, 0x00, 0x03, 0x01, 0x95, 0x01, 0x95, 0x00, 0x03, 0x01, 0xa4, 0x01, 0xa4, 0x00, 0x03, 0x01, 0xac, 0x01, 0xac, 0x00, 0x03, 0x01, 0xae, 0x01, 0xae, 0x00, 0x03, 0x01, 0xda, 0x01, 0xda, 0x00, 0x03, 0x01, 0xdc, 0x01, 0xdc, 0x00, 0x03, 0x01, 0xf0, 0x01, 0xf0, 0x00, 0x03, 0x01, 0xf4, 0x01, 0xf4, 0x00, 0x03, 0x02, 0x0b, 0x02, 0x0b, 0x00, 0x01, 0x02, 0x2a, 0x02, 0x2a, 0x00, 0x01, 0x02, 0x5f, 0x02, 0x5f, 0x00, 0x01, 0x02, 0xb1, 0x02, 0xc5, 0x00, 0x02, 0x02, 0xc7, 0x02, 0xca, 0x00, 0x04, 0x02, 0xcd, 0x02, 0xe4, 0x00, 0x04, 0x02, 0xea, 0x02, 0xed, 0x00, 0x04, 0x02, 0xee, 0x02, 0xf5, 0x00, 0x02, 0x02, 0xf6, 0x02, 0xf6, 0x00, 0x04, 0x02, 0xf7, 0x02, 0xf7, 0x00, 0x02, 0x02, 0xf8, 0x02, 0xfa, 0x00, 0x04, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x02, 0x02, 0xfe, 0x02, 0xff, 0x00, 0x04, 0x03, 0x01, 0x03, 0x02, 0x00, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x04, 0x03, 0x04, 0x03, 0x04, 0x00, 0x02, 0x03, 0x87, 0x03, 0x87, 0x00, 0x01, 0x03, 0xea, 0x03, 0xea, 0x00, 0x01, 0x03, 0xec, 0x03, 0xec, 0x00, 0x01, 0x04, 0x17, 0x04, 0x1a, 0x00, 0x02, 0x05, 0x7d, 0x05, 0x7d, 0x00, 0x01, 0x06, 0x1b, 0x06, 0x1b, 0x00, 0x01, 0x07, 0xe3, 0x07, 0xe6, 0x00, 0x02, 0x08, 0x31, 0x08, 0x32, 0x00, 0x01, 0x00, 0x03, 0x00, 0x08, 0x00, 0x16, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x08, 0x00, 0x16, 0x00, 0x26, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x02, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x24, 0x00, 0x24, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x46, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0xa7, 0x02, 0xa7, 0x00, 0x01, 0x02, 0xa8, 0x02, 0xab, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x24, 0x00, 0x24, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x46, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa7, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x24, 0x00, 0x24, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x46, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa7, 0x00, 0x05, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x24, 0x00, 0x24, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x46, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa7, 0x00, 0x05, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x24, 0x00, 0x24, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x46, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0xa7, 0x02, 0xaa, 0x00, 0x02, 0x02, 0xab, 0x02, 0xab, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x12, 0x00, 0x18, 0x00, 0x18, 0x00, 0x28, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0xa7, 0x00, 0x02, 0x00, 0x02, 0x02, 0xa7, 0x02, 0xa7, 0x00, 0x01, 0x0e, 0xaa, 0x0e, 0xad, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x02, 0x00, 0x12, 0x00, 0x18, 0x00, 0x18, 0x00, 0x2e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0xa8, 0x00, 0x02, 0x00, 0x03, 0x02, 0xa8, 0x02, 0xa8, 0x00, 0x01, 0x0e, 0xae, 0x0e, 0xae, 0x00, 0x02, 0x0e, 0xb0, 0x0e, 0xb2, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x02, 0x00, 0x12, 0x00, 0x18, 0x00, 0x18, 0x00, 0x2e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0xa9, 0x00, 0x02, 0x00, 0x03, 0x02, 0xa9, 0x02, 0xa9, 0x00, 0x01, 0x0e, 0xb3, 0x0e, 0xb4, 0x00, 0x02, 0x0e, 0xb6, 0x0e, 0xb7, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x02, 0x00, 0x12, 0x00, 0x18, 0x00, 0x18, 0x00, 0x2e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0xaa, 0x00, 0x02, 0x00, 0x03, 0x02, 0xaa, 0x02, 0xaa, 0x00, 0x01, 0x0e, 0xb8, 0x0e, 0xba, 0x00, 0x02, 0x0e, 0xbc, 0x0e, 0xbc, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x02, 0x00, 0x12, 0x00, 0x18, 0x00, 0x18, 0x00, 0x28, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0xab, 0x00, 0x02, 0x00, 0x02, 0x02, 0xab, 0x02, 0xab, 0x00, 0x01, 0x0e, 0xbd, 0x0e, 0xc0, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x01, 0x00, 0x06, 0x0b, 0x43, 0x00, 0x01, 0x00, 0x01, 0x03, 0xc5, 0x00, 0x01, 0x00, 0x06, 0x10, 0x0f, 0x00, 0x01, 0x00, 0x01, 0x01, 0x0c, 0x00, 0x01, 0x00, 0x36, 0x00, 0x01, 0x00, 0x08, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x0f, 0x0d, 0x00, 0x03, 0x00, 0x49, 0x00, 0x4f, 0x0f, 0x0c, 0x00, 0x03, 0x00, 0x49, 0x00, 0x4c, 0x0f, 0x0b, 0x00, 0x02, 0x00, 0x4f, 0x0f, 0x0a, 0x00, 0x02, 0x00, 0x4c, 0x0f, 0x09, 0x00, 0x02, 0x00, 0x49, 0x00, 0x01, 0x00, 0x01, 0x00, 0x49, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x04, 0x0f, 0x0f, 0x00, 0x02, 0x00, 0x57, 0x00, 0x01, 0x00, 0x01, 0x00, 0x56, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x04, 0x0f, 0x0e, 0x00, 0x02, 0x00, 0x57, 0x00, 0x01, 0x00, 0x01, 0x01, 0x41, 0x00, 0x01, 0x00, 0x88, 0x00, 0x08, 0x00, 0x16, 0x00, 0x28, 0x00, 0x3a, 0x00, 0x46, 0x00, 0x50, 0x00, 0x5a, 0x00, 0x66, 0x00, 0x72, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0c, 0x07, 0x7e, 0x00, 0x02, 0x00, 0x22, 0x07, 0x71, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0c, 0x07, 0x7d, 0x00, 0x02, 0x00, 0x04, 0x07, 0x7c, 0x00, 0x02, 0x00, 0x22, 0x00, 0x01, 0x00, 0x04, 0x08, 0x24, 0x00, 0x03, 0x00, 0x24, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x04, 0x07, 0xd2, 0x00, 0x02, 0x00, 0x56, 0x00, 0x01, 0x00, 0x04, 0x08, 0x09, 0x00, 0x02, 0x00, 0x30, 0x00, 0x01, 0x00, 0x04, 0x08, 0x0a, 0x00, 0x03, 0x00, 0x28, 0x00, 0x2f, 0x00, 0x01, 0x00, 0x04, 0x07, 0xea, 0x00, 0x03, 0x00, 0x12, 0x00, 0x46, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0e, 0x07, 0xf0, 0x00, 0x03, 0x00, 0x12, 0x00, 0x58, 0x07, 0xef, 0x00, 0x03, 0x00, 0x12, 0x00, 0x52, 0x00, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00, 0x22, 0x00, 0x29, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x44, 0x00, 0x46, 0x00, 0x02, 0x00, 0x14, 0x00, 0x07, 0x03, 0x67, 0x03, 0x66, 0x03, 0x68, 0x03, 0x64, 0x03, 0x65, 0x03, 0x6a, 0x03, 0x69, 0x00, 0x01, 0x00, 0x07, 0x03, 0x23, 0x03, 0x39, 0x03, 0x3f, 0x03, 0x46, 0x03, 0x4c, 0x03, 0x54, 0x03, 0x5a, 0x00, 0x02, 0x00, 0x14, 0x00, 0x07, 0x03, 0x67, 0x03, 0x66, 0x03, 0x68, 0x03, 0x64, 0x03, 0x65, 0x03, 0x6a, 0x03, 0x69, 0x00, 0x01, 0x00, 0x07, 0x03, 0x23, 0x03, 0x39, 0x03, 0x3f, 0x03, 0x46, 0x03, 0x4c, 0x03, 0x54, 0x03, 0x5a, 0x00, 0x02, 0x00, 0x10, 0x00, 0x05, 0x11, 0x48, 0x11, 0x34, 0x02, 0x13, 0x11, 0x3e, 0x11, 0x1b, 0x00, 0x01, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x44, 0x00, 0x4f, 0x01, 0x0c, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x12, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x01, 0x11, 0x48, 0x00, 0x01, 0x11, 0x34, 0x00, 0x01, 0x02, 0x13, 0x00, 0x01, 0x11, 0x3e, 0x00, 0x01, 0x11, 0xb8, 0x00, 0x01, 0x11, 0x1b, 0x00, 0x01, 0x00, 0x06, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x5c, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x0c, 0x10, 0xee, 0x10, 0xec, 0x10, 0xef, 0x10, 0xed, 0x10, 0xf2, 0x10, 0xf3, 0x10, 0xeb, 0x11, 0xac, 0x10, 0xf4, 0x10, 0xf0, 0x10, 0xf5, 0x10, 0xf1, 0x00, 0x01, 0x00, 0x0c, 0x02, 0xb1, 0x02, 0xb2, 0x02, 0xb3, 0x02, 0xb4, 0x02, 0xb7, 0x02, 0xb8, 0x02, 0xb9, 0x02, 0xbb, 0x02, 0xbc, 0x02, 0xbd, 0x02, 0xc0, 0x02, 0xc2, 0x00, 0x02, 0x00, 0x20, 0x00, 0x0d, 0x00, 0xf3, 0x01, 0xf9, 0x11, 0x42, 0x02, 0x21, 0x11, 0x1c, 0x11, 0x1d, 0x01, 0xf9, 0x00, 0xf3, 0x01, 0xf9, 0x11, 0x45, 0x11, 0x46, 0x11, 0x43, 0x11, 0x44, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0xf1, 0x02, 0x0b, 0x02, 0x2a, 0x02, 0x5f, 0x03, 0x87, 0x03, 0xea, 0x03, 0xec, 0x05, 0x7d, 0x06, 0x1b, 0x08, 0x31, 0x08, 0x32, 0x00, 0x01, 0x00, 0x06, 0x0c, 0x02, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x0c, 0x07, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x0c, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x0c, 0x11, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x0c, 0x16, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x05, 0x0e, 0xc2, 0x0e, 0xc2, 0x0e, 0xc2, 0x0e, 0xc2, 0x0e, 0xc2, 0x00, 0x02, 0x00, 0x01, 0x02, 0xa7, 0x02, 0xab, 0x00, 0x00, 0x00, 0x01, 0x03, 0xa6, 0x01, 0x90, 0x00, 0x04, 0x00, 0x00, 0x05, 0x33, 0x05, 0x99, 0x00, 0x00, 0x01, 0x1e, 0x05, 0x33, 0x05, 0x99, 0x00, 0x00, 0x03, 0xd7, 0x00, 0x66, 0x02, 0x12, 0x00, 0x00, 0x02, 0x0b, 0x06, 0x06, 0x03, 0x08, 0x04, 0x02, 0x02, 0x04, 0xe0, 0x00, 0x02, 0xff, 0x52, 0x00, 0xfd, 0xff, 0x02, 0x24, 0x00, 0x21, 0x04, 0x00, 0x20, 0x00, 0x50, 0x66, 0x45, 0x64, 0x00, 0x40, 0x00, 0x20, 0xff, 0xff, 0x06, 0x14, 0xfe, 0x14, 0x01, 0x9a, 0x07, 0x6d, 0x01, 0xe3, 0x60, 0x00, 0x01, 0xff, 0xdf, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x8c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x04, 0x8c, 0x00, 0x04, 0x04, 0x60, 0x00, 0x00, 0x01, 0x14, 0x01, 0x00, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x7e, 0x02, 0xe9, 0x02, 0xee, 0x02, 0xf3, 0x02, 0xf7, 0x03, 0x4f, 0x03, 0x53, 0x03, 0x58, 0x03, 0x5a, 0x03, 0x62, 0x03, 0x77, 0x03, 0x7e, 0x03, 0x8a, 0x03, 0x8c, 0x03, 0xa1, 0x05, 0x25, 0x1d, 0x14, 0x1d, 0x23, 0x1d, 0x2e, 0x1d, 0x5b, 0x1d, 0x6a, 0x1d, 0x78, 0x1d, 0x7b, 0x1d, 0x7d, 0x1d, 0x85, 0x1d, 0xbf, 0x1d, 0xc9, 0x1e, 0xfb, 0x1f, 0x15, 0x1f, 0x1d, 0x1f, 0x45, 0x1f, 0x4d, 0x1f, 0x57, 0x1f, 0x59, 0x1f, 0x5b, 0x1f, 0x5d, 0x1f, 0x7d, 0x1f, 0xb4, 0x1f, 0xc4, 0x1f, 0xd3, 0x1f, 0xdb, 0x1f, 0xef, 0x1f, 0xf4, 0x1f, 0xfe, 0x20, 0x64, 0x20, 0x71, 0x20, 0x8e, 0x20, 0x9c, 0x20, 0xb5, 0x20, 0xba, 0x20, 0xd1, 0x20, 0xd7, 0x20, 0xdc, 0x20, 0xe1, 0x21, 0x09, 0x21, 0x49, 0x21, 0x4b, 0x21, 0x4e, 0x21, 0x85, 0x21, 0x89, 0x23, 0x11, 0x23, 0x19, 0x23, 0x21, 0x23, 0x28, 0x23, 0x2c, 0x23, 0x75, 0x23, 0x7a, 0x23, 0x7d, 0x23, 0x87, 0x23, 0x94, 0x23, 0xae, 0x23, 0xcf, 0x23, 0xe3, 0x23, 0xe5, 0x23, 0xe8, 0x24, 0x23, 0x24, 0x69, 0x26, 0x9c, 0x26, 0xb8, 0x26, 0xc3, 0x26, 0xe2, 0x27, 0x04, 0x27, 0x09, 0x27, 0x27, 0x27, 0x4b, 0x27, 0x4d, 0x27, 0x52, 0x27, 0x56, 0x27, 0x5e, 0x27, 0x94, 0x27, 0xaf, 0x27, 0xbe, 0x27, 0xc6, 0x27, 0xe0, 0x27, 0xeb, 0x28, 0xff, 0x29, 0x07, 0x29, 0x0b, 0x29, 0x41, 0x29, 0x84, 0x29, 0xd5, 0x29, 0xeb, 0x29, 0xfb, 0x2a, 0x02, 0x2a, 0x1c, 0x2a, 0x2f, 0x2a, 0x6b, 0x2a, 0xa0, 0x2a, 0xba, 0x2a, 0xfa, 0x2b, 0x1a, 0x2b, 0x24, 0x2b, 0x54, 0x2c, 0x77, 0x2c, 0x7f, 0xa7, 0x16, 0xa7, 0x1f, 0xa7, 0x2b, 0xa7, 0x41, 0xa7, 0x4b, 0xa7, 0x53, 0xa7, 0x57, 0xa7, 0x67, 0xa7, 0x83, 0xa7, 0x8e, 0xa7, 0x91, 0xa7, 0xaa, 0xa7, 0xff, 0xef, 0x19, 0xf0, 0x03, 0xf4, 0x26, 0xf4, 0x41, 0xf6, 0xc5, 0xfb, 0x06, 0xfe, 0x23, 0xff, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xa0, 0x02, 0xec, 0x02, 0xf3, 0x02, 0xf7, 0x03, 0x00, 0x03, 0x51, 0x03, 0x57, 0x03, 0x5a, 0x03, 0x5c, 0x03, 0x70, 0x03, 0x7a, 0x03, 0x84, 0x03, 0x8c, 0x03, 0x8e, 0x03, 0xa3, 0x1d, 0x00, 0x1d, 0x16, 0x1d, 0x26, 0x1d, 0x30, 0x1d, 0x5d, 0x1d, 0x77, 0x1d, 0x7b, 0x1d, 0x7d, 0x1d, 0x85, 0x1d, 0x9b, 0x1d, 0xc4, 0x1e, 0x00, 0x1f, 0x00, 0x1f, 0x18, 0x1f, 0x20, 0x1f, 0x48, 0x1f, 0x50, 0x1f, 0x59, 0x1f, 0x5b, 0x1f, 0x5d, 0x1f, 0x5f, 0x1f, 0x80, 0x1f, 0xb6, 0x1f, 0xc6, 0x1f, 0xd6, 0x1f, 0xdd, 0x1f, 0xf2, 0x1f, 0xf6, 0x20, 0x00, 0x20, 0x6a, 0x20, 0x74, 0x20, 0x90, 0x20, 0xa0, 0x20, 0xb8, 0x20, 0xd0, 0x20, 0xd6, 0x20, 0xdb, 0x20, 0xe1, 0x21, 0x00, 0x21, 0x0b, 0x21, 0x4b, 0x21, 0x4e, 0x21, 0x50, 0x21, 0x89, 0x21, 0x90, 0x23, 0x18, 0x23, 0x1c, 0x23, 0x24, 0x23, 0x2b, 0x23, 0x73, 0x23, 0x7a, 0x23, 0x7d, 0x23, 0x87, 0x23, 0x94, 0x23, 0x9b, 0x23, 0xce, 0x23, 0xe3, 0x23, 0xe5, 0x23, 0xe8, 0x24, 0x22, 0x24, 0x60, 0x25, 0x00, 0x26, 0xa0, 0x26, 0xc0, 0x26, 0xe2, 0x27, 0x01, 0x27, 0x06, 0x27, 0x0c, 0x27, 0x29, 0x27, 0x4d, 0x27, 0x4f, 0x27, 0x56, 0x27, 0x58, 0x27, 0x61, 0x27, 0x98, 0x27, 0xb1, 0x27, 0xc5, 0x27, 0xe0, 0x27, 0xe6, 0x27, 0xf0, 0x29, 0x06, 0x29, 0x0a, 0x29, 0x40, 0x29, 0x83, 0x29, 0xce, 0x29, 0xeb, 0x29, 0xfa, 0x2a, 0x00, 0x2a, 0x0c, 0x2a, 0x2f, 0x2a, 0x6a, 0x2a, 0x7d, 0x2a, 0xae, 0x2a, 0xf9, 0x2b, 0x00, 0x2b, 0x1f, 0x2b, 0x53, 0x2c, 0x60, 0x2c, 0x79, 0xa7, 0x08, 0xa7, 0x1b, 0xa7, 0x22, 0xa7, 0x30, 0xa7, 0x46, 0xa7, 0x4e, 0xa7, 0x56, 0xa7, 0x64, 0xa7, 0x80, 0xa7, 0x89, 0xa7, 0x90, 0xa7, 0xa0, 0xa7, 0xfa, 0xef, 0x00, 0xf0, 0x00, 0xf4, 0x00, 0xf4, 0x28, 0xf6, 0xc5, 0xfb, 0x00, 0xfe, 0x20, 0xff, 0xf9, 0xff, 0xff, 0x00, 0x00, 0xff, 0xe3, 0xff, 0xc2, 0xff, 0xc0, 0xff, 0xbc, 0xff, 0xb9, 0xff, 0xb1, 0xff, 0xb0, 0xff, 0xad, 0xff, 0xac, 0xff, 0xab, 0xff, 0x9e, 0xff, 0x9c, 0xff, 0x97, 0xff, 0x96, 0xff, 0x95, 0xff, 0x94, 0xe7, 0xba, 0xe7, 0xb9, 0xe7, 0xb7, 0xe7, 0xb6, 0xe7, 0xb5, 0xe7, 0xa9, 0xe7, 0xa7, 0xe7, 0xa6, 0xe7, 0x9f, 0xe7, 0x8a, 0xe7, 0x86, 0xe7, 0x50, 0xe7, 0x4c, 0xe7, 0x4a, 0xe7, 0x48, 0xe7, 0x46, 0xe7, 0x44, 0xe7, 0x43, 0xe7, 0x42, 0xe7, 0x41, 0xe7, 0x40, 0xe7, 0x3e, 0xe7, 0x3d, 0xe7, 0x3c, 0xe7, 0x3a, 0xe7, 0x39, 0xe7, 0x37, 0xe7, 0x36, 0xe7, 0x35, 0xe7, 0x30, 0xe7, 0x2e, 0xe7, 0x2d, 0xe7, 0x2a, 0xe7, 0x28, 0xe7, 0x13, 0xe7, 0x0f, 0xe7, 0x0c, 0xe7, 0x08, 0xe6, 0xea, 0xe6, 0xe9, 0xe6, 0xe8, 0xe6, 0xe6, 0xe6, 0xe5, 0xe6, 0xe2, 0xe6, 0xdc, 0xe6, 0xd6, 0xe6, 0xd4, 0xe6, 0xd2, 0xe6, 0xd0, 0xe6, 0x8a, 0xe6, 0x86, 0xe6, 0x84, 0xe6, 0x7b, 0xe6, 0x6f, 0xe6, 0x69, 0xe6, 0x4a, 0xe6, 0x37, 0xe6, 0x36, 0xe6, 0x34, 0xe5, 0xfb, 0xe5, 0xbf, 0xe5, 0x29, 0xe5, 0x26, 0xe5, 0x1f, 0xe5, 0x01, 0xe4, 0xe3, 0xe4, 0xe2, 0xe4, 0xe0, 0xe4, 0xdf, 0xe4, 0xde, 0xe4, 0xdd, 0xe4, 0xda, 0xe4, 0xd9, 0xe4, 0xd7, 0xe4, 0xd4, 0xe4, 0xd3, 0xe4, 0xcd, 0xe4, 0xb4, 0xe4, 0xaf, 0xe4, 0xab, 0xe4, 0xa5, 0xe4, 0xa3, 0xe4, 0x6f, 0xe4, 0x2e, 0xe3, 0xe5, 0xe3, 0xd0, 0xe3, 0xc2, 0xe3, 0xbe, 0xe3, 0xb5, 0xe3, 0xa3, 0xe3, 0x69, 0xe3, 0x58, 0xe3, 0x4b, 0xe3, 0x0d, 0xe3, 0x08, 0xe3, 0x04, 0xe2, 0xd6, 0xe1, 0xcb, 0xe1, 0xca, 0x67, 0x42, 0x67, 0x3e, 0x67, 0x3c, 0x67, 0x38, 0x67, 0x34, 0x67, 0x32, 0x67, 0x30, 0x67, 0x24, 0x67, 0x0c, 0x67, 0x07, 0x67, 0x06, 0x66, 0xf8, 0x66, 0xa9, 0x1f, 0xa9, 0x1e, 0xc3, 0x1a, 0xc7, 0x1a, 0xc6, 0x18, 0x43, 0x14, 0x09, 0x10, 0xf0, 0x0f, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x07, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x02, 0xe9, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x02, 0xec, 0x00, 0x00, 0x02, 0xee, 0x00, 0x00, 0x02, 0xac, 0x00, 0x00, 0x02, 0xf3, 0x00, 0x00, 0x02, 0xf3, 0x00, 0x00, 0x02, 0xaf, 0x00, 0x00, 0x02, 0xf7, 0x00, 0x00, 0x02, 0xf7, 0x00, 0x00, 0x02, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x4f, 0x00, 0x00, 0x02, 0xb1, 0x00, 0x00, 0x03, 0x51, 0x00, 0x00, 0x03, 0x53, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x57, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x03, 0x5a, 0x00, 0x00, 0x03, 0x5a, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x03, 0x5c, 0x00, 0x00, 0x03, 0x62, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x03, 0x70, 0x00, 0x00, 0x03, 0x77, 0x00, 0x00, 0x03, 0x0e, 0x00, 0x00, 0x03, 0x7a, 0x00, 0x00, 0x03, 0x7e, 0x00, 0x00, 0x03, 0x16, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03, 0x8a, 0x00, 0x00, 0x03, 0x1b, 0x00, 0x00, 0x03, 0x8c, 0x00, 0x00, 0x03, 0x8c, 0x00, 0x00, 0x03, 0x22, 0x00, 0x00, 0x03, 0x8e, 0x00, 0x00, 0x03, 0xa1, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x03, 0xa3, 0x00, 0x00, 0x05, 0x25, 0x00, 0x00, 0x03, 0x37, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1d, 0x14, 0x00, 0x00, 0x04, 0xba, 0x00, 0x00, 0x1d, 0x16, 0x00, 0x00, 0x1d, 0x23, 0x00, 0x00, 0x04, 0xcf, 0x00, 0x00, 0x1d, 0x26, 0x00, 0x00, 0x1d, 0x2e, 0x00, 0x00, 0x04, 0xdd, 0x00, 0x00, 0x1d, 0x30, 0x00, 0x00, 0x1d, 0x5b, 0x00, 0x00, 0x04, 0xe6, 0x00, 0x00, 0x1d, 0x5d, 0x00, 0x00, 0x1d, 0x6a, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x1d, 0x77, 0x00, 0x00, 0x1d, 0x78, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x1d, 0x7b, 0x00, 0x00, 0x1d, 0x7b, 0x00, 0x00, 0x05, 0x22, 0x00, 0x00, 0x1d, 0x7d, 0x00, 0x00, 0x1d, 0x7d, 0x00, 0x00, 0x05, 0x23, 0x00, 0x00, 0x1d, 0x85, 0x00, 0x00, 0x1d, 0x85, 0x00, 0x00, 0x05, 0x24, 0x00, 0x00, 0x1d, 0x9b, 0x00, 0x00, 0x1d, 0xbf, 0x00, 0x00, 0x05, 0x25, 0x00, 0x00, 0x1d, 0xc4, 0x00, 0x00, 0x1d, 0xc9, 0x00, 0x00, 0x05, 0x4a, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1e, 0xfb, 0x00, 0x00, 0x05, 0x50, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x15, 0x00, 0x00, 0x06, 0x4c, 0x00, 0x00, 0x1f, 0x18, 0x00, 0x00, 0x1f, 0x1d, 0x00, 0x00, 0x06, 0x62, 0x00, 0x00, 0x1f, 0x20, 0x00, 0x00, 0x1f, 0x45, 0x00, 0x00, 0x06, 0x68, 0x00, 0x00, 0x1f, 0x48, 0x00, 0x00, 0x1f, 0x4d, 0x00, 0x00, 0x06, 0x8e, 0x00, 0x00, 0x1f, 0x50, 0x00, 0x00, 0x1f, 0x57, 0x00, 0x00, 0x06, 0x94, 0x00, 0x00, 0x1f, 0x59, 0x00, 0x00, 0x1f, 0x59, 0x00, 0x00, 0x06, 0x9c, 0x00, 0x00, 0x1f, 0x5b, 0x00, 0x00, 0x1f, 0x5b, 0x00, 0x00, 0x06, 0x9d, 0x00, 0x00, 0x1f, 0x5d, 0x00, 0x00, 0x1f, 0x5d, 0x00, 0x00, 0x06, 0x9e, 0x00, 0x00, 0x1f, 0x5f, 0x00, 0x00, 0x1f, 0x7d, 0x00, 0x00, 0x06, 0x9f, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x1f, 0xb4, 0x00, 0x00, 0x06, 0xbe, 0x00, 0x00, 0x1f, 0xb6, 0x00, 0x00, 0x1f, 0xc4, 0x00, 0x00, 0x06, 0xf3, 0x00, 0x00, 0x1f, 0xc6, 0x00, 0x00, 0x1f, 0xd3, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0x1f, 0xd6, 0x00, 0x00, 0x1f, 0xdb, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x1f, 0xdd, 0x00, 0x00, 0x1f, 0xef, 0x00, 0x00, 0x07, 0x16, 0x00, 0x00, 0x1f, 0xf2, 0x00, 0x00, 0x1f, 0xf4, 0x00, 0x00, 0x07, 0x29, 0x00, 0x00, 0x1f, 0xf6, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x07, 0x2c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x64, 0x00, 0x00, 0x07, 0x35, 0x00, 0x00, 0x20, 0x6a, 0x00, 0x00, 0x20, 0x71, 0x00, 0x00, 0x07, 0x9a, 0x00, 0x00, 0x20, 0x74, 0x00, 0x00, 0x20, 0x8e, 0x00, 0x00, 0x07, 0xa2, 0x00, 0x00, 0x20, 0x90, 0x00, 0x00, 0x20, 0x9c, 0x00, 0x00, 0x07, 0xbd, 0x00, 0x00, 0x20, 0xa0, 0x00, 0x00, 0x20, 0xb5, 0x00, 0x00, 0x07, 0xca, 0x00, 0x00, 0x20, 0xb8, 0x00, 0x00, 0x20, 0xba, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x20, 0xd0, 0x00, 0x00, 0x20, 0xd1, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x20, 0xd6, 0x00, 0x00, 0x20, 0xd7, 0x00, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x20, 0xdb, 0x00, 0x00, 0x20, 0xdc, 0x00, 0x00, 0x07, 0xe7, 0x00, 0x00, 0x20, 0xe1, 0x00, 0x00, 0x20, 0xe1, 0x00, 0x00, 0x07, 0xe9, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x21, 0x09, 0x00, 0x00, 0x07, 0xea, 0x00, 0x00, 0x21, 0x0b, 0x00, 0x00, 0x21, 0x49, 0x00, 0x00, 0x07, 0xf4, 0x00, 0x00, 0x21, 0x4b, 0x00, 0x00, 0x21, 0x4b, 0x00, 0x00, 0x08, 0x33, 0x00, 0x00, 0x21, 0x4e, 0x00, 0x00, 0x21, 0x4e, 0x00, 0x00, 0x08, 0x34, 0x00, 0x00, 0x21, 0x50, 0x00, 0x00, 0x21, 0x85, 0x00, 0x00, 0x08, 0x35, 0x00, 0x00, 0x21, 0x89, 0x00, 0x00, 0x21, 0x89, 0x00, 0x00, 0x08, 0x6b, 0x00, 0x00, 0x21, 0x90, 0x00, 0x00, 0x23, 0x11, 0x00, 0x00, 0x08, 0x6c, 0x00, 0x00, 0x23, 0x18, 0x00, 0x00, 0x23, 0x19, 0x00, 0x00, 0x09, 0xee, 0x00, 0x00, 0x23, 0x1c, 0x00, 0x00, 0x23, 0x21, 0x00, 0x00, 0x09, 0xf0, 0x00, 0x00, 0x23, 0x24, 0x00, 0x00, 0x23, 0x28, 0x00, 0x00, 0x09, 0xf6, 0x00, 0x00, 0x23, 0x2b, 0x00, 0x00, 0x23, 0x2c, 0x00, 0x00, 0x09, 0xfb, 0x00, 0x00, 0x23, 0x73, 0x00, 0x00, 0x23, 0x75, 0x00, 0x00, 0x09, 0xfd, 0x00, 0x00, 0x23, 0x7a, 0x00, 0x00, 0x23, 0x7a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x23, 0x7d, 0x00, 0x00, 0x23, 0x7d, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x23, 0x87, 0x00, 0x00, 0x23, 0x87, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x00, 0x23, 0x94, 0x00, 0x00, 0x23, 0x94, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x23, 0x9b, 0x00, 0x00, 0x23, 0xae, 0x00, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x23, 0xce, 0x00, 0x00, 0x23, 0xcf, 0x00, 0x00, 0x0a, 0x18, 0x00, 0x00, 0x23, 0xe3, 0x00, 0x00, 0x23, 0xe3, 0x00, 0x00, 0x0a, 0x1a, 0x00, 0x00, 0x23, 0xe5, 0x00, 0x00, 0x23, 0xe5, 0x00, 0x00, 0x0a, 0x1b, 0x00, 0x00, 0x23, 0xe8, 0x00, 0x00, 0x23, 0xe8, 0x00, 0x00, 0x0a, 0x1c, 0x00, 0x00, 0x24, 0x22, 0x00, 0x00, 0x24, 0x23, 0x00, 0x00, 0x0a, 0x1d, 0x00, 0x00, 0x24, 0x60, 0x00, 0x00, 0x24, 0x69, 0x00, 0x00, 0x0a, 0x1f, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x9c, 0x00, 0x00, 0x0a, 0x29, 0x00, 0x00, 0x26, 0xa0, 0x00, 0x00, 0x26, 0xb8, 0x00, 0x00, 0x0b, 0xc6, 0x00, 0x00, 0x26, 0xc0, 0x00, 0x00, 0x26, 0xc3, 0x00, 0x00, 0x0b, 0xdf, 0x00, 0x00, 0x26, 0xe2, 0x00, 0x00, 0x26, 0xe2, 0x00, 0x00, 0x0b, 0xe3, 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x27, 0x04, 0x00, 0x00, 0x0b, 0xe4, 0x00, 0x00, 0x27, 0x06, 0x00, 0x00, 0x27, 0x09, 0x00, 0x00, 0x0b, 0xe8, 0x00, 0x00, 0x27, 0x0c, 0x00, 0x00, 0x27, 0x27, 0x00, 0x00, 0x0b, 0xec, 0x00, 0x00, 0x27, 0x29, 0x00, 0x00, 0x27, 0x4b, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x27, 0x4d, 0x00, 0x00, 0x27, 0x4d, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x00, 0x27, 0x4f, 0x00, 0x00, 0x27, 0x52, 0x00, 0x00, 0x0c, 0x2c, 0x00, 0x00, 0x27, 0x56, 0x00, 0x00, 0x27, 0x56, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x27, 0x58, 0x00, 0x00, 0x27, 0x5e, 0x00, 0x00, 0x0c, 0x31, 0x00, 0x00, 0x27, 0x61, 0x00, 0x00, 0x27, 0x94, 0x00, 0x00, 0x0c, 0x38, 0x00, 0x00, 0x27, 0x98, 0x00, 0x00, 0x27, 0xaf, 0x00, 0x00, 0x0c, 0x6c, 0x00, 0x00, 0x27, 0xb1, 0x00, 0x00, 0x27, 0xbe, 0x00, 0x00, 0x0c, 0x84, 0x00, 0x00, 0x27, 0xc5, 0x00, 0x00, 0x27, 0xc6, 0x00, 0x00, 0x0c, 0x92, 0x00, 0x00, 0x27, 0xe0, 0x00, 0x00, 0x27, 0xe0, 0x00, 0x00, 0x0c, 0x94, 0x00, 0x00, 0x27, 0xe6, 0x00, 0x00, 0x27, 0xeb, 0x00, 0x00, 0x0c, 0x95, 0x00, 0x00, 0x27, 0xf0, 0x00, 0x00, 0x28, 0xff, 0x00, 0x00, 0x0c, 0x9b, 0x00, 0x00, 0x29, 0x06, 0x00, 0x00, 0x29, 0x07, 0x00, 0x00, 0x0d, 0xab, 0x00, 0x00, 0x29, 0x0a, 0x00, 0x00, 0x29, 0x0b, 0x00, 0x00, 0x0d, 0xad, 0x00, 0x00, 0x29, 0x40, 0x00, 0x00, 0x29, 0x41, 0x00, 0x00, 0x0d, 0xaf, 0x00, 0x00, 0x29, 0x83, 0x00, 0x00, 0x29, 0x84, 0x00, 0x00, 0x0d, 0xb1, 0x00, 0x00, 0x29, 0xce, 0x00, 0x00, 0x29, 0xd5, 0x00, 0x00, 0x0d, 0xb3, 0x00, 0x00, 0x29, 0xeb, 0x00, 0x00, 0x29, 0xeb, 0x00, 0x00, 0x0d, 0xbb, 0x00, 0x00, 0x29, 0xfa, 0x00, 0x00, 0x29, 0xfb, 0x00, 0x00, 0x0d, 0xbc, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, 0x0d, 0xbe, 0x00, 0x00, 0x2a, 0x0c, 0x00, 0x00, 0x2a, 0x1c, 0x00, 0x00, 0x0d, 0xc1, 0x00, 0x00, 0x2a, 0x2f, 0x00, 0x00, 0x2a, 0x2f, 0x00, 0x00, 0x0d, 0xd2, 0x00, 0x00, 0x2a, 0x6a, 0x00, 0x00, 0x2a, 0x6b, 0x00, 0x00, 0x0d, 0xd3, 0x00, 0x00, 0x2a, 0x7d, 0x00, 0x00, 0x2a, 0xa0, 0x00, 0x00, 0x0d, 0xd5, 0x00, 0x00, 0x2a, 0xae, 0x00, 0x00, 0x2a, 0xba, 0x00, 0x00, 0x0d, 0xf9, 0x00, 0x00, 0x2a, 0xf9, 0x00, 0x00, 0x2a, 0xfa, 0x00, 0x00, 0x0e, 0x06, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2b, 0x1a, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x2b, 0x1f, 0x00, 0x00, 0x2b, 0x24, 0x00, 0x00, 0x0e, 0x23, 0x00, 0x00, 0x2b, 0x53, 0x00, 0x00, 0x2b, 0x54, 0x00, 0x00, 0x0e, 0x29, 0x00, 0x00, 0x2c, 0x60, 0x00, 0x00, 0x2c, 0x77, 0x00, 0x00, 0x0e, 0x2b, 0x00, 0x00, 0x2c, 0x79, 0x00, 0x00, 0x2c, 0x7f, 0x00, 0x00, 0x0e, 0x43, 0x00, 0x00, 0xa7, 0x08, 0x00, 0x00, 0xa7, 0x16, 0x00, 0x00, 0x0e, 0x4a, 0x00, 0x00, 0xa7, 0x1b, 0x00, 0x00, 0xa7, 0x1f, 0x00, 0x00, 0x0e, 0x59, 0x00, 0x00, 0xa7, 0x22, 0x00, 0x00, 0xa7, 0x2b, 0x00, 0x00, 0x0e, 0x5e, 0x00, 0x00, 0xa7, 0x30, 0x00, 0x00, 0xa7, 0x41, 0x00, 0x00, 0x0e, 0x68, 0x00, 0x00, 0xa7, 0x46, 0x00, 0x00, 0xa7, 0x4b, 0x00, 0x00, 0x0e, 0x7a, 0x00, 0x00, 0xa7, 0x4e, 0x00, 0x00, 0xa7, 0x53, 0x00, 0x00, 0x0e, 0x80, 0x00, 0x00, 0xa7, 0x56, 0x00, 0x00, 0xa7, 0x57, 0x00, 0x00, 0x0e, 0x86, 0x00, 0x00, 0xa7, 0x64, 0x00, 0x00, 0xa7, 0x67, 0x00, 0x00, 0x0e, 0x88, 0x00, 0x00, 0xa7, 0x80, 0x00, 0x00, 0xa7, 0x83, 0x00, 0x00, 0x0e, 0x8c, 0x00, 0x00, 0xa7, 0x89, 0x00, 0x00, 0xa7, 0x8e, 0x00, 0x00, 0x0e, 0x90, 0x00, 0x00, 0xa7, 0x90, 0x00, 0x00, 0xa7, 0x91, 0x00, 0x00, 0x0e, 0x96, 0x00, 0x00, 0xa7, 0xa0, 0x00, 0x00, 0xa7, 0xaa, 0x00, 0x00, 0x0e, 0x98, 0x00, 0x00, 0xa7, 0xfa, 0x00, 0x00, 0xa7, 0xff, 0x00, 0x00, 0x0e, 0xa3, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0xef, 0x19, 0x00, 0x00, 0x0e, 0xa9, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x0e, 0xc3, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf4, 0x26, 0x00, 0x00, 0x0e, 0xc7, 0x00, 0x00, 0xf4, 0x28, 0x00, 0x00, 0xf4, 0x41, 0x00, 0x00, 0x0e, 0xee, 0x00, 0x00, 0xf6, 0xc5, 0x00, 0x00, 0xf6, 0xc5, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0xfb, 0x06, 0x00, 0x00, 0x0f, 0x09, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0xfe, 0x23, 0x00, 0x00, 0x0f, 0x10, 0x00, 0x00, 0xff, 0xf9, 0x00, 0x00, 0xff, 0xfd, 0x00, 0x00, 0x0f, 0x14, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x03, 0x1e, 0x00, 0x00, 0x0f, 0x19, 0x00, 0x01, 0x03, 0x20, 0x00, 0x01, 0x03, 0x23, 0x00, 0x00, 0x0f, 0x38, 0x00, 0x01, 0xd3, 0x00, 0x00, 0x01, 0xd3, 0x56, 0x00, 0x00, 0x0f, 0x3c, 0x00, 0x01, 0xd5, 0x38, 0x00, 0x01, 0xd5, 0x39, 0x00, 0x00, 0x0f, 0x93, 0x00, 0x01, 0xd5, 0x3b, 0x00, 0x01, 0xd5, 0x3e, 0x00, 0x00, 0x0f, 0x95, 0x00, 0x01, 0xd5, 0x40, 0x00, 0x01, 0xd5, 0x44, 0x00, 0x00, 0x0f, 0x99, 0x00, 0x01, 0xd5, 0x46, 0x00, 0x01, 0xd5, 0x46, 0x00, 0x00, 0x0f, 0x9e, 0x00, 0x01, 0xd5, 0x4a, 0x00, 0x01, 0xd5, 0x50, 0x00, 0x00, 0x0f, 0x9f, 0x00, 0x01, 0xd5, 0x52, 0x00, 0x01, 0xd5, 0x6b, 0x00, 0x00, 0x0f, 0xa6, 0x00, 0x01, 0xd5, 0xa0, 0x00, 0x01, 0xd5, 0xd3, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x01, 0xd7, 0xd8, 0x00, 0x01, 0xd7, 0xeb, 0x00, 0x00, 0x0f, 0xf4, 0x00, 0x01, 0xf0, 0x30, 0x00, 0x01, 0xf0, 0x93, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0xf0, 0xa0, 0x00, 0x01, 0xf0, 0xae, 0x00, 0x00, 0x10, 0x6c, 0x00, 0x01, 0xf0, 0xb1, 0x00, 0x01, 0xf0, 0xbe, 0x00, 0x00, 0x10, 0x7b, 0x00, 0x01, 0xf0, 0xc1, 0x00, 0x01, 0xf0, 0xcf, 0x00, 0x00, 0x10, 0x89, 0x00, 0x01, 0xf0, 0xd1, 0x00, 0x01, 0xf0, 0xdf, 0x00, 0x00, 0x10, 0x98, 0x00, 0x01, 0xf4, 0x2d, 0x00, 0x01, 0xf4, 0x2e, 0x00, 0x00, 0x10, 0xa7, 0x00, 0x01, 0xf4, 0x31, 0x00, 0x01, 0xf4, 0x31, 0x00, 0x00, 0x10, 0xa9, 0x00, 0x01, 0xf4, 0x35, 0x00, 0x01, 0xf4, 0x35, 0x00, 0x00, 0x10, 0xaa, 0x00, 0x01, 0xf6, 0x00, 0x00, 0x01, 0xf6, 0x23, 0x00, 0x00, 0x10, 0xab, 0x00, 0x01, 0xf6, 0x25, 0x00, 0x01, 0xf6, 0x2b, 0x00, 0x00, 0x10, 0xcf, 0x00, 0x01, 0xf6, 0x2d, 0x00, 0x01, 0xf6, 0x40, 0x00, 0x00, 0x10, 0xd6, 0x00, 0x06, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x2e, 0x00, 0x2f, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x5e, 0x00, 0x5f, 0x00, 0x60, 0x00, 0x61, 0x00, 0x00, 0x00, 0x86, 0x00, 0x87, 0x00, 0x89, 0x00, 0x8b, 0x00, 0x93, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xa3, 0x00, 0xa2, 0x00, 0xa4, 0x00, 0xa6, 0x00, 0xa5, 0x00, 0xa7, 0x00, 0xa9, 0x00, 0xab, 0x00, 0xaa, 0x00, 0xac, 0x00, 0xad, 0x00, 0xaf, 0x00, 0xae, 0x00, 0xb0, 0x00, 0xb1, 0x00, 0xb3, 0x00, 0xb5, 0x00, 0xb4, 0x00, 0xb6, 0x00, 0xb8, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xbb, 0x00, 0xbd, 0x00, 0xbe, 0x07, 0x55, 0x00, 0x72, 0x00, 0x64, 0x00, 0x65, 0x00, 0x69, 0x07, 0x57, 0x00, 0x78, 0x00, 0xa1, 0x00, 0x70, 0x00, 0x6b, 0x08, 0x0b, 0x00, 0x76, 0x00, 0x6a, 0x09, 0x3c, 0x00, 0x88, 0x00, 0x9a, 0x08, 0xfa, 0x00, 0x73, 0x09, 0x40, 0x09, 0x41, 0x00, 0x67, 0x00, 0x77, 0x08, 0xde, 0x08, 0xed, 0x08, 0xeb, 0x03, 0x54, 0x09, 0x07, 0x00, 0x6c, 0x00, 0x7c, 0x03, 0x3d, 0x00, 0xa8, 0x00, 0xba, 0x00, 0x81, 0x00, 0x63, 0x00, 0x6e, 0x08, 0xf6, 0x01, 0x54, 0x09, 0x24, 0x08, 0xe2, 0x00, 0x6d, 0x00, 0x7d, 0x07, 0x5b, 0x00, 0x62, 0x00, 0x82, 0x00, 0x85, 0x00, 0x97, 0x01, 0x14, 0x01, 0x15, 0x07, 0x48, 0x07, 0x49, 0x07, 0x51, 0x07, 0x52, 0x07, 0x4d, 0x07, 0x4e, 0x00, 0xb9, 0x0a, 0xf3, 0x00, 0xc1, 0x01, 0x3a, 0x07, 0x79, 0x07, 0xd6, 0x07, 0x6e, 0x07, 0x6f, 0x0f, 0x0a, 0x0f, 0x0b, 0x07, 0x56, 0x00, 0x79, 0x07, 0x4f, 0x07, 0x53, 0x07, 0x65, 0x00, 0x84, 0x00, 0x8c, 0x00, 0x83, 0x00, 0x8d, 0x00, 0x8a, 0x00, 0x8f, 0x00, 0x90, 0x00, 0x91, 0x00, 0x8e, 0x00, 0x95, 0x00, 0x96, 0x00, 0x00, 0x00, 0x94, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x9b, 0x00, 0xf3, 0x02, 0x88, 0x02, 0x9e, 0x00, 0x71, 0x02, 0x9a, 0x02, 0x9b, 0x02, 0x9c, 0x00, 0x7a, 0x02, 0x9f, 0x02, 0x9d, 0x02, 0x89, 0x00, 0x00, 0x01, 0x35, 0x00, 0xb8, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xc1, 0x00, 0xaa, 0x00, 0x9c, 0x01, 0xa6, 0x00, 0xb8, 0x00, 0x66, 0x00, 0x00, 0x00, 0x71, 0x00, 0xcb, 0x00, 0xa0, 0x02, 0xb2, 0x00, 0x85, 0x00, 0x75, 0x00, 0xb8, 0x00, 0xc3, 0x01, 0xcb, 0x01, 0x89, 0x02, 0x2d, 0x00, 0xcb, 0x00, 0xa6, 0x00, 0xf0, 0x00, 0xd3, 0x00, 0xaa, 0x00, 0x87, 0x00, 0xcb, 0x03, 0xaa, 0x04, 0x00, 0x01, 0x4a, 0x00, 0x33, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xd9, 0x05, 0x02, 0x00, 0xf4, 0x01, 0x54, 0x00, 0xb4, 0x00, 0x9c, 0x01, 0x39, 0x01, 0x14, 0x01, 0x39, 0x07, 0x06, 0x04, 0x00, 0x04, 0x4e, 0x04, 0xb4, 0x04, 0x52, 0x04, 0xb8, 0x04, 0xe7, 0x04, 0xcd, 0x00, 0x37, 0x04, 0x73, 0x04, 0xcd, 0x04, 0x60, 0x04, 0x73, 0x01, 0x33, 0x03, 0xa2, 0x05, 0x56, 0x05, 0xa6, 0x05, 0x56, 0x05, 0x39, 0x03, 0xc5, 0x02, 0x12, 0x00, 0xc9, 0x00, 0x1f, 0x00, 0xb8, 0x01, 0xdf, 0x00, 0x73, 0x00, 0xba, 0x03, 0xe9, 0x03, 0x33, 0x03, 0xbc, 0x04, 0x44, 0x04, 0x0e, 0x00, 0xdf, 0x03, 0xcd, 0x03, 0xaa, 0x00, 0xe5, 0x03, 0xaa, 0x04, 0x04, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x8f, 0x00, 0xa4, 0x00, 0x7b, 0x00, 0xb8, 0x00, 0x14, 0x01, 0x6f, 0x00, 0x7f, 0x02, 0x7b, 0x02, 0x52, 0x00, 0x8f, 0x00, 0xc7, 0x05, 0xcd, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x6f, 0x00, 0xcb, 0x00, 0xcd, 0x01, 0x9e, 0x01, 0xd3, 0x00, 0xf0, 0x00, 0xba, 0x01, 0x83, 0x00, 0xd5, 0x00, 0x98, 0x03, 0x04, 0x02, 0x48, 0x00, 0x9e, 0x01, 0xd5, 0x00, 0xc1, 0x00, 0xcb, 0x00, 0xf6, 0x00, 0x83, 0x03, 0x54, 0x02, 0x7f, 0x00, 0x00, 0x03, 0x33, 0x02, 0x66, 0x00, 0xd3, 0x00, 0xc7, 0x00, 0xa4, 0x00, 0xcd, 0x00, 0x8f, 0x00, 0x9a, 0x00, 0x73, 0x04, 0x00, 0x05, 0xd5, 0x01, 0x0a, 0x00, 0xfe, 0x02, 0x2b, 0x00, 0xa4, 0x00, 0xb4, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x62, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x1d, 0x03, 0x2d, 0x05, 0xd5, 0x05, 0xd5, 0x05, 0xd5, 0x05, 0xf0, 0x00, 0x7f, 0x00, 0x7b, 0x00, 0x54, 0x00, 0xa4, 0x06, 0xb8, 0x06, 0x14, 0x07, 0x23, 0x01, 0xd3, 0x00, 0xb8, 0x00, 0xcb, 0x00, 0xa6, 0x01, 0xc3, 0x01, 0xec, 0x06, 0x93, 0x00, 0xa0, 0x00, 0xd3, 0x03, 0x5c, 0x03, 0x71, 0x03, 0xdb, 0x01, 0x85, 0x04, 0x23, 0x04, 0xa8, 0x04, 0x48, 0x00, 0x8f, 0x01, 0x39, 0x01, 0x14, 0x01, 0x39, 0x03, 0x60, 0x00, 0x8f, 0x05, 0xd5, 0x01, 0x9a, 0x06, 0x14, 0x07, 0x23, 0x06, 0x66, 0x01, 0x79, 0x04, 0x60, 0x04, 0x60, 0x04, 0x60, 0x04, 0x7b, 0x00, 0x9c, 0x00, 0x00, 0x02, 0x77, 0x04, 0x60, 0x01, 0xaa, 0x00, 0xe9, 0x04, 0x60, 0x07, 0x62, 0x00, 0x7b, 0x00, 0xc5, 0x00, 0x7f, 0x02, 0x7b, 0x00, 0x00, 0x00, 0xb4, 0x02, 0x52, 0x05, 0xcd, 0x00, 0x66, 0x00, 0xbc, 0x00, 0x66, 0x00, 0x77, 0x06, 0x10, 0x00, 0xcd, 0x01, 0x3b, 0x01, 0x85, 0x03, 0x89, 0x00, 0x8f, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0xcd, 0x07, 0x4a, 0x04, 0x2f, 0x00, 0x9c, 0x00, 0x9c, 0x00, 0x00, 0x07, 0x7d, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x6f, 0x03, 0x35, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x7b, 0x00, 0xae, 0x00, 0xb2, 0x00, 0x2d, 0x03, 0x96, 0x00, 0x8f, 0x02, 0x7b, 0x00, 0xf6, 0x00, 0x83, 0x03, 0x54, 0x06, 0x37, 0x05, 0xf6, 0x00, 0x8f, 0x00, 0x9c, 0x04, 0xe1, 0x02, 0x66, 0x00, 0x8f, 0x01, 0x8d, 0x02, 0xf6, 0x00, 0xcd, 0x03, 0x44, 0x00, 0x29, 0x00, 0x66, 0x04, 0xee, 0x00, 0x73, 0x00, 0x00, 0x14, 0x00, 0x00, 0x96, 0x00, 0x00, 0xb7, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x2c, 0x20, 0x10, 0xb0, 0x02, 0x25, 0x49, 0x64, 0xb0, 0x40, 0x51, 0x58, 0x20, 0xc8, 0x59, 0x21, 0x2d, 0x2c, 0xb0, 0x02, 0x25, 0x49, 0x64, 0xb0, 0x40, 0x51, 0x58, 0x20, 0xc8, 0x59, 0x21, 0x2d, 0x2c, 0x20, 0x10, 0x07, 0x20, 0xb0, 0x00, 0x50, 0xb0, 0x0d, 0x79, 0x20, 0xb8, 0xff, 0xff, 0x50, 0x58, 0x04, 0x1b, 0x05, 0x59, 0xb0, 0x05, 0x1c, 0xb0, 0x03, 0x25, 0x08, 0xb0, 0x04, 0x25, 0x23, 0xe1, 0x20, 0xb0, 0x00, 0x50, 0xb0, 0x0d, 0x79, 0x20, 0xb8, 0xff, 0xff, 0x50, 0x58, 0x04, 0x1b, 0x05, 0x59, 0xb0, 0x05, 0x1c, 0xb0, 0x03, 0x25, 0x08, 0xe1, 0x2d, 0x2c, 0x4b, 0x50, 0x58, 0x20, 0xb0, 0xfd, 0x45, 0x44, 0x59, 0x21, 0x2d, 0x2c, 0xb0, 0x02, 0x25, 0x45, 0x60, 0x44, 0x2d, 0x2c, 0x4b, 0x53, 0x58, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x45, 0x44, 0x59, 0x21, 0x21, 0x2d, 0x2c, 0x45, 0x44, 0x2d, 0x2c, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x49, 0xb0, 0x05, 0x25, 0xb0, 0x05, 0x25, 0x49, 0x60, 0xb0, 0x20, 0x63, 0x68, 0x20, 0x8a, 0x10, 0x8a, 0x23, 0x3a, 0x8a, 0x10, 0x65, 0x3a, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x03, 0x00, 0x02, 0x00, 0x5b, 0xfe, 0x96, 0x03, 0xf6, 0x05, 0xa4, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x5c, 0x03, 0x99, 0xfc, 0xce, 0x02, 0xcc, 0xfd, 0x34, 0xfe, 0x96, 0x07, 0x0e, 0xf8, 0xf2, 0x72, 0x06, 0x29, 0x00, 0x00, 0x00, 0x02, 0x01, 0x16, 0x00, 0x00, 0x01, 0xcd, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x25, 0x33, 0x15, 0x23, 0x11, 0x33, 0x11, 0x03, 0x23, 0x03, 0x01, 0x16, 0xb7, 0xb7, 0xb7, 0x12, 0x92, 0x13, 0xfe, 0xfe, 0x05, 0xd5, 0xfd, 0x71, 0xfe, 0x9b, 0x01, 0x65, 0x00, 0x02, 0x00, 0xb1, 0x03, 0xaa, 0x02, 0x9f, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x01, 0x4a, 0x99, 0x01, 0xed, 0x98, 0x05, 0xd5, 0xfd, 0xd5, 0x02, 0x2b, 0xfd, 0xd5, 0x02, 0x2b, 0x00, 0x02, 0x00, 0x8e, 0x00, 0x00, 0x05, 0x7c, 0x05, 0xbe, 0x00, 0x03, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x21, 0x03, 0x21, 0x0b, 0x01, 0x21, 0x13, 0x33, 0x03, 0x21, 0x15, 0x21, 0x03, 0x21, 0x15, 0x21, 0x03, 0x23, 0x13, 0x21, 0x03, 0x23, 0x13, 0x21, 0x35, 0x21, 0x13, 0x21, 0x35, 0x21, 0x13, 0x03, 0xae, 0xfe, 0xfa, 0x4b, 0x01, 0x07, 0x3d, 0x5d, 0x01, 0x06, 0x5f, 0x90, 0x5d, 0x01, 0x19, 0xfe, 0xc4, 0x4a, 0x01, 0x1f, 0xfe, 0xbe, 0x5d, 0x90, 0x5c, 0xfe, 0xf9, 0x5d, 0x91, 0x5e, 0xfe, 0xe4, 0x01, 0x3d, 0x4c, 0xfe, 0xde, 0x01, 0x45, 0x5c, 0x03, 0x85, 0xfe, 0xb2, 0x03, 0x87, 0xfe, 0x61, 0x01, 0x9f, 0xfe, 0x61, 0x9a, 0xfe, 0xb2, 0x99, 0xfe, 0x62, 0x01, 0x9e, 0xfe, 0x62, 0x01, 0x9e, 0x99, 0x01, 0x4e, 0x9a, 0x01, 0x9f, 0x00, 0x00, 0x03, 0x00, 0x99, 0xfe, 0xd3, 0x03, 0xfc, 0x06, 0x14, 0x00, 0x21, 0x00, 0x28, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x23, 0x03, 0x2e, 0x01, 0x27, 0x35, 0x1e, 0x01, 0x17, 0x11, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, 0x15, 0x1e, 0x01, 0x17, 0x15, 0x2e, 0x01, 0x27, 0x11, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x03, 0x11, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x11, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x02, 0x6f, 0x5a, 0x01, 0x5f, 0xbd, 0x5f, 0x5c, 0xbc, 0x64, 0xc7, 0xb5, 0xc4, 0xb8, 0x5a, 0x53, 0x9d, 0x4b, 0x4b, 0x9d, 0x53, 0xcc, 0xc1, 0xcd, 0xc0, 0x5a, 0x69, 0x6d, 0x65, 0xcb, 0x72, 0x74, 0x6f, 0xfe, 0xd3, 0x01, 0x2d, 0x02, 0x2d, 0x2d, 0xb4, 0x40, 0x41, 0x01, 0x01, 0xc8, 0x24, 0xac, 0x96, 0xa3, 0xbc, 0x0e, 0xeb, 0xe8, 0x04, 0x1f, 0x1b, 0xaf, 0x2a, 0x2e, 0x04, 0xfe, 0x55, 0x23, 0xb4, 0x9c, 0xa9, 0xc3, 0x0f, 0x03, 0x00, 0x01, 0x9a, 0x0d, 0x6a, 0x58, 0x56, 0x60, 0xd5, 0xfe, 0x4f, 0x11, 0x6e, 0x5a, 0x58, 0x68, 0x00, 0x05, 0x00, 0x65, 0xff, 0xe3, 0x06, 0x72, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x27, 0x00, 0x33, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x25, 0x33, 0x01, 0x23, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0x3c, 0x4e, 0x59, 0x59, 0x4e, 0x4d, 0x59, 0x59, 0x4d, 0x8e, 0xa8, 0xa9, 0x8d, 0x90, 0xa7, 0xa8, 0xfc, 0xee, 0x4d, 0x59, 0x58, 0x4e, 0x4f, 0x59, 0x5a, 0x02, 0xdf, 0x90, 0xfc, 0xb7, 0x90, 0x1c, 0x8f, 0xa9, 0xa9, 0x8f, 0x8f, 0xa6, 0xa7, 0x02, 0x91, 0x94, 0x84, 0x82, 0x95, 0x95, 0x82, 0x83, 0x95, 0x7f, 0xdc, 0xbb, 0xbb, 0xdb, 0xdb, 0xbb, 0xbc, 0xdb, 0x02, 0x61, 0x95, 0x82, 0x84, 0x94, 0x94, 0x84, 0x81, 0x96, 0x7f, 0xf9, 0xf3, 0x06, 0x0d, 0xdb, 0xbb, 0xbd, 0xda, 0xdb, 0xbc, 0xba, 0xdc, 0x00, 0x02, 0x00, 0x74, 0xff, 0xe3, 0x05, 0x65, 0x05, 0xf0, 0x00, 0x09, 0x00, 0x30, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x09, 0x01, 0x3e, 0x01, 0x37, 0x33, 0x06, 0x02, 0x07, 0x13, 0x23, 0x27, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x35, 0x34, 0x36, 0x37, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0xc0, 0x52, 0x4c, 0xbf, 0x90, 0x55, 0x96, 0x41, 0xfe, 0xa2, 0x01, 0xc9, 0x35, 0x3c, 0x05, 0xa8, 0x0b, 0x5e, 0x53, 0xfb, 0xe3, 0x81, 0x5d, 0xce, 0x76, 0xd8, 0xfe, 0xec, 0x79, 0x78, 0x2b, 0x2d, 0xc8, 0xa5, 0x4b, 0x95, 0x4c, 0x4e, 0x8e, 0x3e, 0x5e, 0x76, 0x35, 0x03, 0x23, 0x51, 0xa1, 0x58, 0x92, 0xc2, 0x3f, 0x40, 0x02, 0x8f, 0xfd, 0xf8, 0x59, 0xcb, 0x72, 0x84, 0xfe, 0xfe, 0x7e, 0xfe, 0xe3, 0x93, 0x59, 0x57, 0x01, 0x13, 0xd7, 0x80, 0xe1, 0x63, 0x3f, 0x7d, 0x3c, 0xa2, 0xc5, 0x24, 0x24, 0xb6, 0x2f, 0x31, 0x6f, 0x58, 0x33, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb1, 0x03, 0xaa, 0x01, 0x4b, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x01, 0x4a, 0x99, 0x05, 0xd5, 0xfd, 0xd5, 0x02, 0x2b, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0xf2, 0x02, 0x3c, 0x06, 0x12, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x23, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x02, 0x3c, 0x79, 0x75, 0x76, 0x78, 0x90, 0x88, 0x86, 0x86, 0x88, 0x06, 0x12, 0xe6, 0xfe, 0x3e, 0xe7, 0xe7, 0xfe, 0x3b, 0xe5, 0xeb, 0x01, 0xc6, 0xe0, 0xdf, 0x01, 0xc4, 0xec, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x93, 0xfe, 0xf2, 0x02, 0x31, 0x06, 0x12, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x23, 0x36, 0x12, 0x35, 0x34, 0x02, 0x94, 0x90, 0x87, 0x86, 0x86, 0x87, 0x90, 0x77, 0x76, 0x76, 0x06, 0x12, 0xec, 0xfe, 0x3c, 0xdf, 0xe0, 0xfe, 0x3a, 0xeb, 0xe5, 0x01, 0xc5, 0xe7, 0xe7, 0x01, 0xc2, 0x00, 0x00, 0x01, 0x00, 0x36, 0x02, 0x4a, 0x03, 0x63, 0x05, 0xf0, 0x00, 0x11, 0x00, 0x00, 0x01, 0x0d, 0x01, 0x07, 0x25, 0x11, 0x23, 0x11, 0x05, 0x27, 0x2d, 0x01, 0x37, 0x05, 0x11, 0x33, 0x11, 0x25, 0x03, 0x63, 0xfe, 0xbd, 0x01, 0x43, 0x35, 0xfe, 0xd2, 0x66, 0xfe, 0xd1, 0x34, 0x01, 0x43, 0xfe, 0xbd, 0x34, 0x01, 0x2f, 0x66, 0x01, 0x2e, 0x04, 0xdf, 0xc2, 0xc3, 0x62, 0xcb, 0xfe, 0x87, 0x01, 0x79, 0xcb, 0x62, 0xc3, 0xc2, 0x63, 0xcb, 0x01, 0x79, 0xfe, 0x87, 0xcb, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x05, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x03, 0x50, 0x01, 0xf5, 0xfe, 0x0b, 0x97, 0xfe, 0x0a, 0x01, 0xf6, 0x05, 0x04, 0xfd, 0xd3, 0xaa, 0xfd, 0xd3, 0x02, 0x2d, 0xaa, 0x02, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8e, 0xff, 0x12, 0x01, 0x96, 0x00, 0xfe, 0x00, 0x05, 0x00, 0x00, 0x37, 0x33, 0x15, 0x03, 0x23, 0x13, 0xd8, 0xbe, 0x94, 0x74, 0x4a, 0xfe, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x01, 0xdf, 0x02, 0x40, 0x02, 0x83, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x5a, 0x01, 0xe5, 0xfe, 0x1b, 0x02, 0x83, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc5, 0x00, 0x00, 0x01, 0x83, 0x00, 0xfe, 0x00, 0x03, 0x00, 0x00, 0x37, 0x33, 0x15, 0x23, 0xc5, 0xbe, 0xbe, 0xfe, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x42, 0x02, 0x6d, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x01, 0x23, 0x01, 0xd4, 0x99, 0xfe, 0x2c, 0x99, 0x05, 0xd5, 0xf9, 0x6d, 0x00, 0x02, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x1b, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x27, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x02, 0x4a, 0x8c, 0x8e, 0x8e, 0x8c, 0x8d, 0x8d, 0x8d, 0x8d, 0xe2, 0xee, 0xee, 0xe2, 0xe2, 0xee, 0xee, 0x05, 0x50, 0xfe, 0xcd, 0xfe, 0xcc, 0xfe, 0xcd, 0xfe, 0xcd, 0x01, 0x33, 0x01, 0x33, 0x01, 0x34, 0x01, 0x33, 0xa0, 0xfe, 0x73, 0xfe, 0x86, 0xfe, 0x87, 0xfe, 0x73, 0x01, 0x8d, 0x01, 0x79, 0x01, 0x7a, 0x01, 0x8d, 0x00, 0x01, 0x00, 0xca, 0x00, 0x00, 0x03, 0xeb, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x00, 0x37, 0x21, 0x11, 0x05, 0x35, 0x25, 0x33, 0x11, 0x21, 0x15, 0x21, 0xe5, 0x01, 0x29, 0xfe, 0xbc, 0x01, 0x42, 0xb6, 0x01, 0x29, 0xfc, 0xfa, 0xaa, 0x04, 0x73, 0x48, 0xb8, 0x48, 0xfa, 0xd5, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x87, 0x00, 0x00, 0x03, 0xdd, 0x05, 0xf0, 0x00, 0x1c, 0x00, 0x00, 0x25, 0x21, 0x15, 0x21, 0x35, 0x36, 0x00, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x06, 0x02, 0x01, 0x62, 0x02, 0x7a, 0xfc, 0xab, 0x67, 0x01, 0x66, 0x2e, 0x57, 0x45, 0x96, 0x79, 0x55, 0xbe, 0x6c, 0x6e, 0xbf, 0x4f, 0xd1, 0xf8, 0x3e, 0x52, 0x17, 0xf1, 0xaa, 0xaa, 0xaa, 0x77, 0x01, 0x91, 0x3a, 0x6d, 0x97, 0x49, 0x77, 0x96, 0x42, 0x43, 0xcc, 0x31, 0x32, 0xe8, 0xc2, 0x5c, 0xa5, 0x70, 0x1d, 0xfe, 0xeb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8c, 0xff, 0xe3, 0x04, 0x02, 0x05, 0xf0, 0x00, 0x28, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x04, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x02, 0xec, 0x82, 0x93, 0xfe, 0xef, 0xfc, 0x55, 0xb3, 0x60, 0x4c, 0xb4, 0x62, 0xab, 0xb3, 0xa6, 0x95, 0x9c, 0xa3, 0x86, 0x8f, 0x93, 0x89, 0x4b, 0xaa, 0x67, 0x67, 0xb5, 0x50, 0xcf, 0xf2, 0x80, 0x03, 0x25, 0x1f, 0xc4, 0x90, 0xdd, 0xf2, 0x25, 0x25, 0xc3, 0x31, 0x32, 0x96, 0x8f, 0x84, 0x95, 0xa6, 0x77, 0x70, 0x73, 0x7b, 0x24, 0x26, 0xb4, 0x20, 0x20, 0xd1, 0xb2, 0x7c, 0xab, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x00, 0x04, 0x2e, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x00, 0x09, 0x01, 0x21, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x21, 0x35, 0x02, 0xb9, 0xfe, 0x35, 0x01, 0xcb, 0x30, 0xe5, 0xbf, 0xbf, 0xb5, 0xfd, 0xa1, 0x05, 0x25, 0xfc, 0xe3, 0x03, 0xcd, 0xfc, 0x33, 0xa8, 0xfe, 0xa0, 0x01, 0x60, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8e, 0xff, 0xe3, 0x03, 0xf4, 0x05, 0xd5, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x00, 0x15, 0x14, 0x00, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0xc7, 0x02, 0xca, 0xfd, 0xdc, 0x28, 0x4f, 0x28, 0xe1, 0x01, 0x07, 0xfe, 0xf2, 0xf6, 0x55, 0xaf, 0x5e, 0x51, 0xad, 0x60, 0x9c, 0xb6, 0xb6, 0x9c, 0x49, 0x91, 0x4b, 0x05, 0xd5, 0xaa, 0xfe, 0x92, 0x0f, 0x0f, 0xfe, 0xee, 0xea, 0xf1, 0xfe, 0xf5, 0x20, 0x20, 0xcb, 0x31, 0x30, 0xb6, 0x9c, 0x9c, 0xb6, 0x24, 0x26, 0x00, 0x00, 0x02, 0x00, 0x80, 0xff, 0xe3, 0x04, 0x21, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x13, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x03, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x15, 0x14, 0x02, 0x23, 0x22, 0x02, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x02, 0x60, 0x7a, 0x8f, 0x8f, 0x7a, 0x7b, 0x8f, 0x8f, 0xee, 0x44, 0x8c, 0x44, 0xb4, 0xbe, 0x0d, 0x35, 0xa0, 0x60, 0xcb, 0xeb, 0xf5, 0xcc, 0xe9, 0xf6, 0x01, 0x2e, 0x00, 0xff, 0x44, 0x8c, 0x03, 0x3b, 0xba, 0xa2, 0xa1, 0xbb, 0xbb, 0xa1, 0xa2, 0xba, 0x02, 0x79, 0xb8, 0x24, 0x26, 0xfe, 0xf2, 0xfe, 0xef, 0x57, 0x5d, 0xfe, 0xef, 0xeb, 0xe6, 0xfe, 0xea, 0x01, 0x8d, 0x01, 0x79, 0x01, 0x62, 0x01, 0xa5, 0x1e, 0x00, 0x01, 0x00, 0x97, 0x00, 0x00, 0x03, 0xf8, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x23, 0x01, 0x21, 0x97, 0x03, 0x60, 0xfe, 0x18, 0xbd, 0x01, 0xca, 0xfd, 0x7b, 0x05, 0xd5, 0x56, 0xfa, 0x81, 0x05, 0x2b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x7d, 0xff, 0xe3, 0x04, 0x17, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x25, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x13, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x4a, 0x82, 0x94, 0x94, 0x82, 0x82, 0x95, 0x95, 0xfe, 0xc8, 0x75, 0x82, 0xe5, 0xc8, 0xc9, 0xe4, 0x82, 0x74, 0x83, 0x93, 0xef, 0xde, 0xde, 0xef, 0x94, 0x41, 0x82, 0x76, 0x75, 0x84, 0x84, 0x75, 0x76, 0x82, 0x02, 0xc5, 0x9a, 0x87, 0x87, 0x9a, 0x9b, 0x86, 0x87, 0x9a, 0x56, 0x20, 0xb2, 0x80, 0xb3, 0xd0, 0xd0, 0xb3, 0x80, 0xb2, 0x20, 0x22, 0xc6, 0x8f, 0xd9, 0xe8, 0xe8, 0xd9, 0x8f, 0xc6, 0x01, 0x61, 0x74, 0x82, 0x82, 0x74, 0x74, 0x82, 0x82, 0x00, 0x02, 0x00, 0x74, 0xff, 0xe3, 0x04, 0x14, 0x05, 0xf0, 0x00, 0x18, 0x00, 0x24, 0x00, 0x00, 0x37, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x12, 0x13, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x35, 0x34, 0x12, 0x33, 0x32, 0x12, 0x11, 0x10, 0x00, 0x23, 0x22, 0x26, 0x01, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0xca, 0x45, 0x8c, 0x44, 0xb4, 0xbe, 0x0d, 0x34, 0xa0, 0x61, 0xca, 0xeb, 0xf5, 0xcb, 0xe9, 0xf6, 0xfe, 0xd3, 0xff, 0x45, 0x8c, 0x01, 0x1e, 0x7b, 0x8f, 0x8f, 0x7b, 0x7a, 0x8f, 0x8f, 0x1f, 0xb8, 0x24, 0x26, 0x01, 0x0d, 0x01, 0x12, 0x56, 0x5c, 0x01, 0x0f, 0xeb, 0xe6, 0x01, 0x16, 0xfe, 0x73, 0xfe, 0x86, 0xfe, 0x9f, 0xfe, 0x5b, 0x1e, 0x02, 0x97, 0xba, 0xa2, 0xa1, 0xbb, 0xbb, 0xa1, 0xa2, 0xba, 0x00, 0x00, 0x00, 0x02, 0x00, 0xd8, 0x00, 0x00, 0x01, 0x96, 0x04, 0x23, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x37, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0xd8, 0xbe, 0xbe, 0xbe, 0xbe, 0xfe, 0xfe, 0x04, 0x23, 0xfe, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8e, 0xff, 0x12, 0x01, 0x96, 0x04, 0x23, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x03, 0x23, 0x13, 0xd8, 0xbe, 0xbe, 0xbe, 0x94, 0x74, 0x4a, 0x04, 0x23, 0xfe, 0xfd, 0xd9, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x5e, 0x05, 0x46, 0x04, 0xa6, 0x00, 0x06, 0x00, 0x00, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x05, 0x45, 0xfc, 0x5f, 0x03, 0xa1, 0xfb, 0x7e, 0x04, 0x82, 0x03, 0xf0, 0xfe, 0x91, 0xfe, 0x93, 0xb6, 0x01, 0xd1, 0xa6, 0x01, 0xd1, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x03, 0xa2, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x5e, 0x05, 0x46, 0x04, 0xa6, 0x00, 0x06, 0x00, 0x00, 0x13, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x9f, 0x03, 0xf0, 0xb6, 0xfe, 0x2f, 0xa6, 0xfe, 0x2f, 0xb6, 0x01, 0x6d, 0x00, 0x00, 0x02, 0x00, 0x84, 0x00, 0x00, 0x03, 0x52, 0x05, 0xf0, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x25, 0x33, 0x15, 0x23, 0x13, 0x23, 0x35, 0x34, 0x36, 0x3f, 0x01, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x0f, 0x01, 0x0e, 0x01, 0x07, 0x0e, 0x01, 0x15, 0x01, 0x60, 0xb7, 0xb7, 0xb1, 0xac, 0x33, 0x51, 0x51, 0x33, 0x2e, 0x76, 0x61, 0x47, 0xa1, 0x58, 0x55, 0xae, 0x5c, 0xa6, 0xc9, 0x41, 0x51, 0x4f, 0x2b, 0x23, 0x07, 0x05, 0x06, 0xfe, 0xfe, 0x01, 0x91, 0x9a, 0x65, 0x82, 0x56, 0x59, 0x35, 0x5e, 0x31, 0x59, 0x6e, 0x46, 0x43, 0xbc, 0x39, 0x38, 0xc2, 0x9f, 0x4c, 0x89, 0x56, 0x56, 0x2f, 0x35, 0x19, 0x15, 0x3c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x79, 0xfe, 0x9c, 0x06, 0xb3, 0x05, 0xa2, 0x00, 0x0b, 0x00, 0x4c, 0x00, 0x00, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x35, 0x33, 0x11, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x24, 0x23, 0x22, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x17, 0x06, 0x04, 0x23, 0x22, 0x24, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x24, 0x33, 0x32, 0x04, 0x17, 0x1e, 0x01, 0x15, 0x10, 0x00, 0x07, 0x02, 0xae, 0x80, 0x6f, 0x6f, 0x7f, 0x82, 0x6e, 0x6d, 0x80, 0x01, 0xea, 0x36, 0x8b, 0x5d, 0x9b, 0xc1, 0xc2, 0x9a, 0x5d, 0x8c, 0x35, 0x81, 0x83, 0x95, 0x39, 0x39, 0x5e, 0xfe, 0xf3, 0x9e, 0x6f, 0xcc, 0x56, 0x8d, 0xa0, 0x68, 0x62, 0x5e, 0xf9, 0x8d, 0x74, 0xe0, 0x5e, 0x51, 0x71, 0xfe, 0xf7, 0x89, 0xa6, 0xfe, 0xd8, 0x73, 0x73, 0x78, 0x7a, 0x71, 0x74, 0x01, 0x31, 0xaa, 0xbe, 0x01, 0x47, 0x6f, 0x43, 0x47, 0xfe, 0xe2, 0xfc, 0x02, 0x19, 0x8f, 0xa3, 0xa4, 0x8e, 0x8c, 0xa5, 0xa4, 0xfe, 0x48, 0x4d, 0x49, 0xf9, 0xc8, 0xc8, 0xfa, 0x4b, 0x4c, 0x83, 0xfd, 0x20, 0x16, 0xdf, 0xb1, 0x6b, 0xbc, 0x50, 0x83, 0x8b, 0x41, 0x40, 0x66, 0xfe, 0xb5, 0xc1, 0x9f, 0xfe, 0xea, 0x6a, 0x68, 0x6d, 0x57, 0x51, 0x6f, 0x61, 0x67, 0x83, 0x7d, 0x7d, 0x01, 0x49, 0xbd, 0xb6, 0x01, 0x4a, 0x7d, 0x7f, 0x87, 0xae, 0xa0, 0x62, 0xe6, 0x7b, 0xfe, 0xf9, 0xfe, 0xd0, 0x06, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x03, 0x21, 0x01, 0x33, 0x01, 0x23, 0x03, 0x21, 0x03, 0x23, 0x02, 0x76, 0xf7, 0x01, 0xef, 0xfe, 0xa1, 0xcf, 0x02, 0x00, 0xbd, 0x7b, 0xfd, 0xa2, 0x7a, 0xc0, 0x05, 0x0e, 0xfd, 0x19, 0x03, 0xae, 0xfa, 0x2b, 0x01, 0x7f, 0xfe, 0x81, 0x00, 0x00, 0x03, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x01, 0x11, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x11, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0x01, 0x6b, 0x01, 0x23, 0x93, 0x8d, 0x8d, 0x93, 0xfe, 0xdd, 0x01, 0x0d, 0x85, 0x83, 0x83, 0x85, 0xfe, 0x3d, 0x01, 0xd0, 0xd0, 0xe1, 0x73, 0x70, 0x87, 0x94, 0xf5, 0xe2, 0xfe, 0x1e, 0x02, 0xc9, 0xfd, 0xdd, 0x87, 0x8b, 0x8c, 0x85, 0x02, 0x66, 0xfe, 0x3e, 0x6f, 0x72, 0x71, 0x70, 0xa6, 0xc0, 0xb1, 0x89, 0xa2, 0x14, 0x20, 0xcb, 0x98, 0xc8, 0xda, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x00, 0x19, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x04, 0xa3, 0x5c, 0xd0, 0x75, 0xe6, 0xf5, 0xf5, 0xe6, 0x75, 0xd0, 0x5c, 0x5f, 0xd6, 0x76, 0xfe, 0xce, 0xfe, 0xa2, 0x01, 0x5e, 0x01, 0x32, 0x78, 0xd6, 0x05, 0x62, 0xd5, 0x5f, 0x5e, 0xfe, 0xc7, 0xfe, 0xd8, 0xfe, 0xd9, 0xfe, 0xc7, 0x5e, 0x5f, 0xd3, 0x48, 0x48, 0x01, 0x9f, 0x01, 0x67, 0x01, 0x68, 0x01, 0x9f, 0x47, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x1f, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x11, 0x00, 0x00, 0x01, 0x11, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x25, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x01, 0x6b, 0xdb, 0x01, 0x16, 0x01, 0x03, 0xfe, 0xfd, 0xfe, 0xea, 0xfe, 0x6f, 0x01, 0x75, 0x01, 0x87, 0x01, 0x6d, 0xfe, 0x91, 0xfe, 0x7b, 0xfe, 0x8b, 0x05, 0x2f, 0xfb, 0x77, 0x01, 0x18, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x17, 0xa6, 0xfe, 0x97, 0xfe, 0x80, 0xfe, 0x7e, 0xfe, 0x96, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0xb5, 0x03, 0x51, 0xfd, 0x65, 0x02, 0x80, 0xfd, 0x80, 0x02, 0xac, 0xfc, 0x9e, 0x05, 0xd5, 0xaa, 0xfe, 0x46, 0xaa, 0xfd, 0xe3, 0xaa, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xba, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0xb5, 0x03, 0x04, 0xfd, 0xb2, 0x02, 0x15, 0xfd, 0xeb, 0xb6, 0x05, 0xd5, 0xaa, 0xfe, 0x48, 0xaa, 0xfd, 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x05, 0xf0, 0x00, 0x1d, 0x00, 0x00, 0x25, 0x11, 0x21, 0x35, 0x21, 0x11, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x36, 0x04, 0x49, 0xfe, 0xd7, 0x01, 0xdd, 0x69, 0xfe, 0x90, 0xfe, 0xc5, 0xfe, 0x9d, 0x01, 0x63, 0x01, 0x3b, 0x83, 0xed, 0x64, 0x65, 0xe3, 0x7d, 0xf6, 0xf8, 0xf8, 0xf6, 0x61, 0x97, 0xd5, 0x01, 0x91, 0xa6, 0xfd, 0x7f, 0x53, 0x55, 0x01, 0x99, 0x01, 0x6d, 0x01, 0x6e, 0x01, 0x99, 0x48, 0x46, 0xd7, 0x5f, 0x60, 0xfe, 0xce, 0xfe, 0xd1, 0xfe, 0xd2, 0xfe, 0xce, 0x25, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x94, 0xb6, 0xb6, 0xfd, 0x6c, 0xb6, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfa, 0x2b, 0x02, 0xc7, 0xfd, 0x39, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x6b, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0xb5, 0xb6, 0xb6, 0x05, 0xd5, 0xfa, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xa0, 0xfe, 0x66, 0x01, 0x6b, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0xb5, 0xb6, 0xb9, 0xcc, 0x45, 0x38, 0x79, 0x63, 0x05, 0xd5, 0xfa, 0x93, 0xfe, 0xf2, 0xf4, 0xaa, 0x96, 0xc2, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xe0, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x5b, 0xea, 0xfd, 0x65, 0x02, 0xca, 0xef, 0xfd, 0x7b, 0xb6, 0x05, 0xd5, 0xfd, 0x89, 0x02, 0x77, 0xfd, 0x48, 0xfc, 0xe3, 0x02, 0xcf, 0xfd, 0x31, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x15, 0x21, 0xb5, 0xb6, 0x02, 0x8e, 0xfc, 0xbc, 0x05, 0xd5, 0xfa, 0xd5, 0xaa, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x21, 0x09, 0x01, 0x21, 0x11, 0x23, 0x11, 0x01, 0x23, 0x01, 0x11, 0x23, 0xb5, 0x01, 0x0f, 0x01, 0x57, 0x01, 0x58, 0x01, 0x0f, 0xb1, 0xfe, 0xa5, 0xb6, 0xfe, 0xa5, 0xb0, 0x05, 0xd5, 0xfc, 0x08, 0x03, 0xf8, 0xfa, 0x2b, 0x05, 0x1f, 0xfc, 0x00, 0x04, 0x00, 0xfa, 0xe1, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x13, 0x33, 0x01, 0x11, 0x33, 0x11, 0x23, 0x01, 0x11, 0x23, 0xb5, 0xf5, 0x02, 0x54, 0xb0, 0xf5, 0xfd, 0xac, 0xb0, 0x05, 0xd5, 0xfb, 0x1f, 0x04, 0xe1, 0xfa, 0x2b, 0x04, 0xe1, 0xfb, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x27, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x02, 0xd6, 0xc6, 0xe9, 0xe9, 0xc6, 0xc6, 0xe8, 0xe8, 0xc6, 0x01, 0x1b, 0x01, 0x52, 0xfe, 0xae, 0xfe, 0xe5, 0xfe, 0xe5, 0xfe, 0xad, 0x01, 0x53, 0x05, 0x4c, 0xfe, 0xb8, 0xfe, 0xe5, 0xfe, 0xe6, 0xfe, 0xb8, 0x01, 0x48, 0x01, 0x1a, 0x01, 0x1b, 0x01, 0x48, 0xa4, 0xfe, 0x5b, 0xfe, 0x9e, 0xfe, 0x9f, 0xfe, 0x5b, 0x01, 0xa4, 0x01, 0x62, 0x01, 0x62, 0x01, 0xa5, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x01, 0x6b, 0xe4, 0x7f, 0x8b, 0x8b, 0x7f, 0xfe, 0x66, 0x01, 0x9a, 0xe2, 0xe7, 0xe7, 0xe2, 0xe4, 0xb6, 0x05, 0x2f, 0xfd, 0xcf, 0x92, 0x87, 0x86, 0x92, 0xa6, 0xe3, 0xdb, 0xdd, 0xe2, 0xfd, 0xa8, 0x00, 0x02, 0x00, 0x67, 0xfe, 0xf8, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x1b, 0x01, 0x23, 0x27, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x02, 0x02, 0xd6, 0xc6, 0xe9, 0xe9, 0xc6, 0xc6, 0xe8, 0xe8, 0x39, 0xef, 0xdb, 0xc7, 0x1e, 0x1f, 0x0f, 0xfe, 0xe5, 0xfe, 0xad, 0x01, 0x53, 0x01, 0x1b, 0x01, 0x1b, 0x01, 0x52, 0xbc, 0x05, 0x4c, 0xfe, 0xb8, 0xfe, 0xe5, 0xfe, 0xe6, 0xfe, 0xb8, 0x01, 0x48, 0x01, 0x1a, 0x01, 0x1b, 0x01, 0x48, 0xfa, 0xcf, 0xfe, 0xdd, 0xef, 0x02, 0x02, 0x01, 0xa5, 0x01, 0x61, 0x01, 0x62, 0x01, 0xa5, 0xfe, 0x5b, 0xfe, 0x9e, 0xfe, 0xfc, 0xfe, 0x8e, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xcc, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x17, 0x13, 0x23, 0x03, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x03, 0x32, 0x3b, 0x6e, 0x38, 0xb9, 0xc4, 0xac, 0x42, 0x7d, 0x6c, 0xc6, 0xb6, 0x01, 0x9a, 0xe7, 0xe2, 0x75, 0xfd, 0xc8, 0xe4, 0x84, 0x86, 0x86, 0x84, 0x02, 0xbc, 0x16, 0x90, 0x7e, 0xfe, 0x68, 0x01, 0x7f, 0x96, 0x62, 0xfd, 0x89, 0x05, 0xd5, 0xd6, 0xd8, 0x8d, 0xba, 0x02, 0x4f, 0xfd, 0xee, 0x87, 0x83, 0x83, 0x85, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x05, 0xf0, 0x00, 0x27, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x04, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x03, 0xda, 0x67, 0xb8, 0x55, 0x95, 0xa1, 0x6b, 0x96, 0x6d, 0xcc, 0xc1, 0xfe, 0xfb, 0xfd, 0x60, 0xd7, 0x73, 0x6f, 0xd4, 0x67, 0x9b, 0xaa, 0x7a, 0x8b, 0x6e, 0xcc, 0xb5, 0xfb, 0xdc, 0x5f, 0xc4, 0x05, 0xa4, 0xc5, 0x37, 0x36, 0x80, 0x76, 0x63, 0x65, 0x1f, 0x19, 0x2b, 0xd9, 0xb6, 0xd9, 0xe0, 0x30, 0x2f, 0xd0, 0x45, 0x46, 0x88, 0x7e, 0x6e, 0x7c, 0x1f, 0x18, 0x2d, 0xc0, 0xab, 0xc6, 0xe4, 0x26, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x00, 0x00, 0x04, 0x6c, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x00, 0x03, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x05, 0x04, 0x70, 0xfe, 0x23, 0xb6, 0xfe, 0x23, 0x05, 0xd5, 0xaa, 0xfa, 0xd5, 0x05, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x13, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x00, 0x23, 0x22, 0x00, 0x11, 0xa0, 0xb7, 0x9d, 0xaf, 0xaf, 0x9c, 0xb7, 0xfe, 0xfc, 0xfe, 0xff, 0xfe, 0xfc, 0x05, 0xd5, 0xfc, 0x75, 0xf0, 0xd3, 0xd3, 0xf0, 0x03, 0x8b, 0xfc, 0x5c, 0xfe, 0xdc, 0xfe, 0xd6, 0x01, 0x2a, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x21, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x02, 0x0f, 0xfd, 0xff, 0xbe, 0x01, 0xaa, 0x01, 0xab, 0xbd, 0xfe, 0x00, 0x05, 0xd5, 0xfb, 0x17, 0x04, 0xe9, 0xfa, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x06, 0xe3, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x09, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x23, 0x09, 0x01, 0x23, 0x3d, 0xb8, 0x01, 0x1a, 0x01, 0x1a, 0xcc, 0x01, 0x1b, 0x01, 0x1a, 0xb8, 0xfe, 0xaf, 0xe5, 0xfe, 0xe5, 0xfe, 0xe1, 0xe4, 0x05, 0xd5, 0xfb, 0x12, 0x04, 0xee, 0xfb, 0x12, 0x04, 0xee, 0xfa, 0x2b, 0x05, 0x10, 0xfa, 0xf0, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x09, 0x01, 0x33, 0x09, 0x01, 0x23, 0x09, 0x01, 0x23, 0x01, 0x74, 0xc3, 0x01, 0x4e, 0x01, 0x50, 0xc3, 0xfe, 0x50, 0x01, 0xcd, 0xc3, 0xfe, 0x86, 0xfe, 0x83, 0xc4, 0x01, 0xe0, 0x05, 0xd5, 0xfd, 0xd5, 0x02, 0x2b, 0xfd, 0x33, 0xfc, 0xf8, 0x02, 0x7b, 0xfd, 0x85, 0x03, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x00, 0x03, 0x33, 0x09, 0x01, 0x33, 0x01, 0x11, 0x23, 0x11, 0x04, 0xc4, 0x01, 0x74, 0x01, 0x72, 0xc4, 0xfe, 0x24, 0xb6, 0x05, 0xd5, 0xfd, 0x9a, 0x02, 0x66, 0xfc, 0xf2, 0xfd, 0x39, 0x02, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x52, 0x00, 0x00, 0x04, 0x9c, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x21, 0x68, 0x04, 0x1f, 0xfc, 0xaf, 0x03, 0x66, 0xfb, 0xb7, 0x03, 0x51, 0xfc, 0xc4, 0x05, 0xd5, 0x9a, 0xfb, 0x6f, 0xaa, 0x9a, 0x04, 0x91, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0xf2, 0x02, 0x1c, 0x06, 0x14, 0x00, 0x07, 0x00, 0x00, 0x13, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x9e, 0x01, 0x7e, 0xd8, 0xd8, 0xfe, 0x82, 0x06, 0x14, 0x8f, 0xf9, 0xfc, 0x8f, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x42, 0x02, 0x6d, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x13, 0x01, 0x23, 0x01, 0x99, 0x01, 0xd4, 0x99, 0xfe, 0x2c, 0x05, 0xd5, 0xf9, 0x6d, 0x06, 0x93, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb3, 0xfe, 0xf2, 0x02, 0x31, 0x06, 0x14, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x33, 0x11, 0x23, 0x35, 0x02, 0x31, 0xfe, 0x82, 0xd7, 0xd7, 0x06, 0x14, 0xf8, 0xde, 0x8f, 0x06, 0x04, 0x8f, 0x00, 0x01, 0x00, 0xc3, 0x03, 0xa8, 0x05, 0x46, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x23, 0x09, 0x01, 0x23, 0x01, 0x03, 0x5c, 0x01, 0xe9, 0xb5, 0xfe, 0x74, 0xfe, 0x74, 0xb5, 0x01, 0xe9, 0x05, 0xd5, 0xfd, 0xd3, 0x01, 0x8b, 0xfe, 0x75, 0x02, 0x2d, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x1d, 0x03, 0xac, 0xfe, 0xac, 0x00, 0x03, 0x00, 0x00, 0x01, 0x15, 0x21, 0x35, 0x03, 0xac, 0xfc, 0x42, 0xfe, 0xac, 0x8f, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x99, 0x04, 0xf0, 0x02, 0x49, 0x06, 0x66, 0x00, 0x03, 0x00, 0x00, 0x01, 0x13, 0x23, 0x01, 0x01, 0x4a, 0xfe, 0x8a, 0xfe, 0xdb, 0x06, 0x66, 0xfe, 0x8a, 0x01, 0x76, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x04, 0x7b, 0x00, 0x0a, 0x00, 0x25, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x37, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x02, 0x78, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0xa6, 0xa6, 0x38, 0xa9, 0x7b, 0x9b, 0xb6, 0xe3, 0xe2, 0xe8, 0x96, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0xdb, 0xd8, 0x02, 0x33, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0x4c, 0xfd, 0x81, 0xaa, 0x66, 0x61, 0xc1, 0xa2, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0xfc, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0xe3, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x15, 0x23, 0x11, 0x33, 0x03, 0x81, 0x96, 0x83, 0x84, 0x96, 0x96, 0x84, 0x83, 0x96, 0xfd, 0xcd, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x34, 0xa7, 0xa7, 0x02, 0x2f, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x02, 0x52, 0x64, 0x61, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xf8, 0xfe, 0xbc, 0x61, 0x64, 0xa8, 0x06, 0x14, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x19, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x16, 0x03, 0x83, 0x46, 0x8d, 0x48, 0xa2, 0xb2, 0xb2, 0xa2, 0x48, 0x8d, 0x46, 0x45, 0x95, 0x53, 0xe4, 0xfe, 0xf4, 0x01, 0x0f, 0xeb, 0x4d, 0x92, 0x04, 0x35, 0xac, 0x2b, 0x2b, 0xe3, 0xcd, 0xcd, 0xe3, 0x2b, 0x2b, 0xaa, 0x24, 0x24, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x12, 0x01, 0x3a, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xeb, 0x06, 0x14, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x03, 0x45, 0xa6, 0xa6, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0xfe, 0x00, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0x03, 0xb6, 0x02, 0x5e, 0xf9, 0xec, 0xa8, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0xfe, 0x15, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x04, 0x7b, 0x00, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x15, 0x21, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x12, 0x07, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x04, 0x0c, 0xfd, 0x06, 0x0b, 0xb9, 0xa4, 0x60, 0xb3, 0x58, 0x59, 0xbb, 0x60, 0xf2, 0xfe, 0xe7, 0x01, 0x0b, 0xe3, 0xcb, 0xed, 0xa6, 0x02, 0x94, 0x7a, 0x8b, 0xa7, 0x0c, 0x02, 0x5e, 0x5a, 0xbe, 0xc7, 0x34, 0x34, 0xae, 0x2a, 0x2c, 0x01, 0x38, 0x01, 0x0a, 0x01, 0x13, 0x01, 0x43, 0xfe, 0xdd, 0xc4, 0x97, 0xb4, 0xae, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, 0x06, 0x14, 0x00, 0x13, 0x00, 0x00, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x33, 0x02, 0xac, 0x9e, 0x5a, 0x45, 0x01, 0x11, 0xfe, 0xef, 0xa6, 0x9f, 0x9f, 0x9c, 0xaa, 0x06, 0x14, 0x99, 0x50, 0x68, 0x63, 0x8f, 0xfc, 0x2f, 0x03, 0xd1, 0x8f, 0x4e, 0xbb, 0xab, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x04, 0x7b, 0x00, 0x0b, 0x00, 0x28, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x17, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x33, 0x03, 0x45, 0x95, 0x86, 0x85, 0x94, 0x94, 0x85, 0x86, 0x95, 0xa6, 0xe5, 0xec, 0x57, 0x9b, 0x49, 0x49, 0x8e, 0x4a, 0xa3, 0xa2, 0x33, 0xa0, 0x70, 0xba, 0xe2, 0xe2, 0xba, 0x70, 0xa0, 0x33, 0xa6, 0x02, 0x3d, 0xc8, 0xdc, 0xdc, 0xc8, 0xc7, 0xdc, 0xdc, 0xeb, 0xfe, 0xe2, 0xfe, 0xe9, 0x1d, 0x1e, 0xb3, 0x2c, 0x2a, 0xbd, 0xbf, 0x5b, 0x63, 0x62, 0x01, 0x3a, 0x01, 0x03, 0x01, 0x04, 0x01, 0x3a, 0x62, 0x63, 0xaa, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x14, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x03, 0xf4, 0xa6, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0xa1, 0x6a, 0xad, 0xb3, 0x02, 0xa4, 0xfd, 0x5c, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x06, 0x14, 0xfd, 0x9e, 0x65, 0x64, 0xef, 0x00, 0x00, 0x02, 0x00, 0xad, 0x00, 0x00, 0x01, 0x54, 0x06, 0x14, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x11, 0x33, 0x15, 0x23, 0xae, 0xa5, 0xa5, 0xa5, 0xa5, 0x04, 0x60, 0xfb, 0xa0, 0x06, 0x14, 0xe9, 0x00, 0x02, 0xff, 0xde, 0xfe, 0x56, 0x01, 0x54, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x15, 0x23, 0xae, 0xa5, 0x92, 0xa3, 0x3f, 0x2c, 0x5e, 0x45, 0xa5, 0xa5, 0x04, 0x60, 0xfb, 0x8c, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0x06, 0x28, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x26, 0x06, 0x14, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0xa7, 0xa7, 0x01, 0xee, 0xd4, 0xfd, 0xe9, 0x02, 0x2d, 0xd8, 0xfe, 0x00, 0xa7, 0x06, 0x14, 0xfc, 0x69, 0x01, 0xe3, 0xfd, 0xf4, 0xfd, 0xac, 0x02, 0x23, 0xfd, 0xdd, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x01, 0x54, 0x06, 0x14, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0xae, 0xa5, 0xa5, 0x06, 0x14, 0xf9, 0xec, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x06, 0x67, 0x04, 0x7b, 0x00, 0x22, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x03, 0xbe, 0x3f, 0xac, 0x75, 0x9e, 0xab, 0xa7, 0x66, 0x6a, 0x80, 0x96, 0xa6, 0x67, 0x6b, 0x7f, 0x95, 0xa7, 0xa7, 0x39, 0x9e, 0x6d, 0x6e, 0x9a, 0x03, 0x89, 0x7c, 0x76, 0xf5, 0xe2, 0xfd, 0x5c, 0x02, 0x9e, 0xa1, 0x9c, 0xbe, 0xa4, 0xfd, 0x87, 0x02, 0x9e, 0xa2, 0x9b, 0xbf, 0xa3, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x67, 0x62, 0x7c, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x04, 0x7b, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x03, 0xf4, 0xa6, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0xa1, 0x6a, 0xad, 0xb3, 0x02, 0xa4, 0xfd, 0x5c, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x65, 0x64, 0xef, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x02, 0x34, 0x85, 0x9b, 0x9a, 0x86, 0x85, 0x9a, 0x9a, 0x85, 0xd8, 0xf7, 0xf7, 0xd8, 0xd9, 0xf5, 0xf5, 0x03, 0xdf, 0xe7, 0xc9, 0xc9, 0xe7, 0xe8, 0xc8, 0xc7, 0xe9, 0x9c, 0xfe, 0xc8, 0xfe, 0xec, 0xfe, 0xed, 0xfe, 0xc7, 0x01, 0x39, 0x01, 0x13, 0x01, 0x14, 0x01, 0x38, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x25, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x01, 0x4e, 0xa7, 0xa7, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x01, 0xff, 0x96, 0x83, 0x84, 0x96, 0x96, 0x84, 0x83, 0x96, 0xa8, 0xfd, 0xae, 0x06, 0x0a, 0xaa, 0x64, 0x61, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xf8, 0xfe, 0xbc, 0x61, 0x01, 0xeb, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x04, 0x7b, 0x00, 0x0b, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x33, 0x11, 0x23, 0x01, 0x11, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0x02, 0x34, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0xa6, 0xa6, 0x02, 0x2f, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0xfd, 0xae, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0x64, 0xaa, 0xf9, 0xf6, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x02, 0xf6, 0x04, 0x7b, 0x00, 0x11, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x02, 0xf6, 0x1c, 0x42, 0x27, 0x8d, 0x96, 0xa7, 0xa7, 0x34, 0xa8, 0x77, 0x11, 0x2a, 0x19, 0x03, 0xb4, 0x12, 0x11, 0xcb, 0xbe, 0xfd, 0xb2, 0x04, 0x60, 0xae, 0x66, 0x63, 0x05, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x04, 0x7b, 0x00, 0x27, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x03, 0x30, 0x46, 0x97, 0x51, 0x7b, 0x7c, 0x59, 0x85, 0x38, 0xb1, 0x94, 0xde, 0xc2, 0x51, 0xb0, 0x61, 0x5c, 0xb2, 0x57, 0x75, 0x7e, 0x5b, 0x9a, 0x39, 0x9a, 0x89, 0xca, 0xb9, 0x5c, 0xa2, 0x04, 0x3f, 0xae, 0x28, 0x28, 0x54, 0x54, 0x40, 0x49, 0x21, 0x0e, 0x2a, 0x99, 0x89, 0x9c, 0xb6, 0x23, 0x23, 0xbe, 0x35, 0x35, 0x59, 0x51, 0x4b, 0x50, 0x25, 0x0f, 0x24, 0x95, 0x82, 0x9e, 0xac, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0x00, 0x00, 0x02, 0xa7, 0x05, 0x9e, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x01, 0x52, 0x01, 0x55, 0xfe, 0xab, 0x43, 0x67, 0xab, 0xab, 0xbf, 0x92, 0x79, 0x79, 0x05, 0x9e, 0xfe, 0xc2, 0x8f, 0xfd, 0xa0, 0x89, 0x4e, 0x9a, 0x9f, 0xd2, 0x02, 0x60, 0x8f, 0x01, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x04, 0x7b, 0x00, 0x13, 0x00, 0x14, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x01, 0x9d, 0xa5, 0x70, 0x6f, 0x87, 0x9b, 0xa6, 0xa6, 0x3c, 0x9f, 0x6a, 0xad, 0xb4, 0x01, 0xa0, 0x01, 0xba, 0x02, 0xa6, 0xfd, 0x61, 0x9f, 0x9f, 0xbe, 0xa4, 0x02, 0x7b, 0xfb, 0xa0, 0xac, 0x66, 0x63, 0xf0, 0x03, 0xa8, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x04, 0x60, 0x00, 0x06, 0x00, 0x00, 0x13, 0x33, 0x09, 0x01, 0x33, 0x01, 0x23, 0x37, 0xaf, 0x01, 0x3b, 0x01, 0x3b, 0xb0, 0xfe, 0x86, 0xe1, 0x04, 0x60, 0xfc, 0x54, 0x03, 0xac, 0xfb, 0xa0, 0x00, 0x00, 0x01, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x04, 0x60, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x1b, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x01, 0x23, 0x0b, 0x01, 0x23, 0x4d, 0xa6, 0xcf, 0xce, 0xc3, 0xcf, 0xce, 0xa6, 0xfe, 0xf8, 0xc3, 0xd9, 0xda, 0xc3, 0x04, 0x60, 0xfc, 0x96, 0x03, 0x6a, 0xfc, 0x96, 0x03, 0x6a, 0xfb, 0xa0, 0x03, 0x96, 0xfc, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x35, 0x00, 0x00, 0x04, 0x07, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x02, 0x23, 0x09, 0x01, 0x23, 0x09, 0x01, 0x33, 0x09, 0x01, 0x03, 0xf4, 0xfe, 0x93, 0x01, 0x7f, 0xc3, 0xfe, 0xdb, 0xfe, 0xda, 0xc3, 0x01, 0x88, 0xfe, 0x99, 0xc4, 0x01, 0x0b, 0x01, 0x0b, 0x04, 0x60, 0xfd, 0xdf, 0xfd, 0xc1, 0x01, 0xb8, 0xfe, 0x48, 0x02, 0x4a, 0x02, 0x16, 0xfe, 0x71, 0x01, 0x8f, 0x00, 0x01, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x00, 0x05, 0x0e, 0x01, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x3f, 0x01, 0x01, 0x33, 0x09, 0x01, 0x33, 0x02, 0x51, 0x46, 0x85, 0x70, 0x84, 0x61, 0x44, 0x4c, 0x2e, 0x1e, 0xfe, 0x68, 0xaf, 0x01, 0x3b, 0x01, 0x3b, 0xb0, 0x68, 0xc8, 0x7a, 0x9a, 0x48, 0x86, 0x54, 0x04, 0x4e, 0xfc, 0x94, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x79, 0x04, 0x60, 0x00, 0x09, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x21, 0x66, 0x03, 0x12, 0xfd, 0x92, 0x02, 0x6e, 0xfc, 0xd7, 0x02, 0x6f, 0xfd, 0xa8, 0x04, 0x60, 0xa8, 0xfc, 0xdb, 0x93, 0xa8, 0x03, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe6, 0xfe, 0xb2, 0x03, 0xaf, 0x06, 0x14, 0x00, 0x24, 0x00, 0x00, 0x05, 0x15, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x1d, 0x01, 0x14, 0x16, 0x33, 0x03, 0xae, 0x38, 0xe0, 0x98, 0x61, 0x80, 0x37, 0x37, 0x81, 0x60, 0x98, 0xe0, 0x38, 0x3d, 0x7f, 0x4d, 0x52, 0x63, 0x64, 0x51, 0x4d, 0x7f, 0xbe, 0x90, 0x94, 0xdd, 0xef, 0x97, 0x74, 0x8f, 0x73, 0x95, 0xf0, 0xdd, 0x93, 0x8f, 0x58, 0x8d, 0xf8, 0x9d, 0x8e, 0x19, 0x1b, 0x8e, 0x9c, 0xf8, 0x8d, 0x58, 0x00, 0x01, 0x00, 0xea, 0xfe, 0x1d, 0x01, 0x83, 0x06, 0x1d, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x01, 0x83, 0x99, 0x06, 0x1d, 0xf8, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe6, 0xfe, 0xb2, 0x03, 0xaf, 0x06, 0x14, 0x00, 0x24, 0x00, 0x00, 0x17, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x34, 0x36, 0x37, 0x2e, 0x01, 0x3d, 0x01, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x16, 0x1d, 0x01, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x14, 0x06, 0x2b, 0x01, 0xe6, 0x3f, 0x7e, 0x4d, 0x51, 0x64, 0x64, 0x51, 0x4d, 0x7e, 0x3f, 0x39, 0xe0, 0x97, 0x61, 0x7f, 0x38, 0x38, 0x7f, 0x61, 0x97, 0xe0, 0x39, 0xbe, 0x56, 0x8f, 0xf8, 0x9c, 0x8e, 0x1b, 0x19, 0x8e, 0x9d, 0xf8, 0x8e, 0x57, 0x8f, 0x93, 0xdd, 0xf0, 0x95, 0x73, 0x8f, 0x74, 0x97, 0xef, 0xdd, 0x94, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x01, 0xd3, 0x05, 0x46, 0x03, 0x31, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x0a, 0x05, 0x06, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x08, 0x05, 0x07, 0x0d, 0x8b, 0x55, 0x4d, 0x98, 0x03, 0x31, 0xb2, 0x4f, 0x44, 0x3b, 0x04, 0x02, 0x03, 0x05, 0x3e, 0x4d, 0x53, 0xb2, 0x4f, 0x45, 0x3c, 0x04, 0x02, 0x03, 0x05, 0x3e, 0x4c, 0x00, 0x02, 0x01, 0x16, 0x00, 0x00, 0x01, 0xcd, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x01, 0x23, 0x35, 0x33, 0x11, 0x23, 0x11, 0x13, 0x33, 0x13, 0x01, 0xcd, 0xb7, 0xb7, 0xb7, 0x13, 0x92, 0x12, 0x04, 0xd7, 0xfe, 0xfa, 0x2b, 0x02, 0x8f, 0x01, 0x65, 0xfe, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9a, 0xfe, 0xc7, 0x03, 0xba, 0x05, 0x98, 0x00, 0x06, 0x00, 0x21, 0x00, 0x00, 0x25, 0x11, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x01, 0x15, 0x2e, 0x01, 0x27, 0x03, 0x3e, 0x01, 0x37, 0x15, 0x0e, 0x01, 0x07, 0x11, 0x23, 0x11, 0x26, 0x02, 0x11, 0x10, 0x12, 0x37, 0x11, 0x33, 0x13, 0x1e, 0x01, 0x02, 0x62, 0x84, 0x94, 0x94, 0x01, 0xdb, 0x43, 0x7a, 0x3d, 0x01, 0x3f, 0x7b, 0x41, 0x3a, 0x7c, 0x45, 0x5c, 0xd9, 0xee, 0xee, 0xd9, 0x5c, 0x01, 0x42, 0x7b, 0x83, 0x03, 0x58, 0x12, 0xe2, 0xb8, 0xb9, 0xe2, 0x03, 0xa1, 0xac, 0x29, 0x2a, 0x03, 0xfc, 0xa0, 0x05, 0x2a, 0x27, 0xaa, 0x1e, 0x23, 0x07, 0xfe, 0xe4, 0x01, 0x20, 0x14, 0x01, 0x33, 0x01, 0x01, 0x01, 0x02, 0x01, 0x32, 0x16, 0x01, 0x1f, 0xfe, 0xe1, 0x04, 0x21, 0x00, 0x00, 0x01, 0x00, 0x74, 0x00, 0x00, 0x03, 0xf2, 0x05, 0xf0, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x35, 0x33, 0x11, 0x23, 0x35, 0x33, 0x35, 0x10, 0x36, 0x33, 0x32, 0x16, 0x03, 0xe0, 0x45, 0x7a, 0x37, 0x85, 0x69, 0x01, 0x60, 0xfe, 0xa0, 0x01, 0xf6, 0xfc, 0x82, 0xd4, 0xb3, 0xb3, 0xc1, 0xd1, 0x37, 0x88, 0x05, 0xb4, 0xb6, 0x29, 0x29, 0x9b, 0xd4, 0xd7, 0x8f, 0xfe, 0x2f, 0xaa, 0xaa, 0x01, 0xd1, 0x8f, 0xee, 0x01, 0x05, 0xf3, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x54, 0x00, 0x52, 0x04, 0x43, 0x04, 0xb2, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x37, 0x17, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x17, 0x07, 0x27, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x07, 0x27, 0x37, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x27, 0x37, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x13, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x03, 0x22, 0xba, 0x67, 0xba, 0x22, 0x20, 0x22, 0x24, 0xbc, 0x67, 0xba, 0x35, 0x68, 0x37, 0x34, 0x6c, 0x37, 0xbb, 0x65, 0xba, 0x21, 0x22, 0x22, 0x23, 0xbb, 0x68, 0xba, 0x32, 0x68, 0x3a, 0x36, 0x69, 0x53, 0x8c, 0x66, 0x65, 0x8e, 0x8d, 0x66, 0x65, 0x8d, 0x03, 0xe1, 0xd1, 0x73, 0xce, 0x3b, 0x77, 0x3e, 0x3f, 0x73, 0x39, 0xcf, 0x71, 0xcf, 0x28, 0x26, 0x25, 0x25, 0xcf, 0x73, 0xce, 0x3e, 0x76, 0x3a, 0x40, 0x74, 0x38, 0xce, 0x73, 0xcf, 0x27, 0x25, 0x24, 0xfe, 0x7c, 0x70, 0x9a, 0x9a, 0x70, 0x72, 0x9c, 0x9d, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x04, 0x4a, 0x05, 0xd5, 0x00, 0x18, 0x00, 0x00, 0x01, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x35, 0x27, 0x21, 0x35, 0x33, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x33, 0x15, 0x21, 0x07, 0x15, 0x21, 0x04, 0x18, 0xfe, 0x8d, 0xb5, 0xfe, 0x8a, 0x01, 0x76, 0x4c, 0xfe, 0xd6, 0xed, 0xfe, 0xe3, 0xab, 0x01, 0x55, 0x01, 0x53, 0xac, 0xfe, 0xe2, 0xed, 0xfe, 0xd7, 0x4c, 0x01, 0x75, 0x01, 0xc7, 0xfe, 0x39, 0x01, 0xc7, 0x7b, 0x33, 0x9b, 0x7b, 0x02, 0x4a, 0xfd, 0x44, 0x02, 0xbc, 0xfd, 0xb6, 0x7b, 0x9b, 0x33, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xea, 0xfe, 0xa2, 0x01, 0x83, 0x05, 0x98, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x13, 0x11, 0x23, 0x11, 0x01, 0x83, 0x99, 0x99, 0x99, 0x01, 0x98, 0xfd, 0x0a, 0x02, 0xf6, 0x04, 0x00, 0xfd, 0x0a, 0x02, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0xff, 0x3d, 0x03, 0x45, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x13, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x01, 0x55, 0x39, 0x37, 0x7d, 0xe1, 0x38, 0x38, 0x81, 0xb8, 0x4b, 0x80, 0x33, 0x57, 0x61, 0xb9, 0x18, 0x0c, 0xbe, 0x76, 0x53, 0x54, 0x38, 0x34, 0xb8, 0x9c, 0x41, 0x8b, 0x4f, 0x4e, 0x85, 0x34, 0x5c, 0x66, 0xc7, 0x16, 0xc1, 0x73, 0x53, 0x52, 0x35, 0x35, 0xb4, 0x96, 0x41, 0x8a, 0x03, 0xa8, 0x2e, 0x5a, 0x2e, 0x4c, 0x85, 0x87, 0x2d, 0x5b, 0x2e, 0x4b, 0x88, 0x02, 0x93, 0xa4, 0x27, 0x27, 0x50, 0x47, 0x5a, 0x73, 0x0f, 0x08, 0x77, 0x9a, 0x65, 0x5a, 0x8c, 0x35, 0x34, 0x6d, 0x40, 0x8e, 0xa8, 0x1d, 0x1d, 0xa4, 0x27, 0x27, 0x54, 0x4c, 0x66, 0x7b, 0x0e, 0x78, 0x99, 0x66, 0x5b, 0x8f, 0x31, 0x2c, 0x70, 0x45, 0x82, 0x9f, 0x1d, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc1, 0x05, 0x46, 0x02, 0xd9, 0x06, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x02, 0x21, 0xb7, 0xb7, 0xfe, 0xa1, 0xb6, 0xb6, 0x06, 0x10, 0xca, 0xca, 0xca, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xfe, 0x00, 0x00, 0x06, 0x35, 0x05, 0xcd, 0x00, 0x17, 0x00, 0x2f, 0x00, 0x49, 0x00, 0x00, 0x01, 0x32, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x3e, 0x01, 0x17, 0x22, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x01, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x03, 0x9a, 0x88, 0xed, 0x62, 0x62, 0x61, 0x61, 0x62, 0x62, 0xed, 0x88, 0x89, 0xed, 0x62, 0x62, 0x61, 0x61, 0x62, 0x62, 0xed, 0x89, 0x76, 0xcc, 0x54, 0x55, 0x56, 0x56, 0x55, 0x54, 0xcc, 0x76, 0x76, 0xcd, 0x54, 0x54, 0x54, 0x55, 0x53, 0x54, 0xcd, 0x97, 0x3c, 0x75, 0x3b, 0x86, 0x97, 0x9a, 0x8c, 0x3a, 0x6d, 0x3c, 0x3d, 0x7b, 0x3f, 0xc2, 0xe2, 0xe2, 0xc2, 0x42, 0x7a, 0x05, 0xcd, 0x6e, 0x6d, 0x6d, 0xfe, 0xfa, 0x9a, 0x98, 0xfe, 0xfb, 0x6d, 0x6d, 0x6e, 0x6e, 0x6d, 0x6d, 0x01, 0x05, 0x98, 0x9a, 0x01, 0x06, 0x6d, 0x6d, 0x6e, 0x67, 0x5e, 0x5e, 0x5e, 0xe5, 0x82, 0x81, 0xe3, 0x5e, 0x5e, 0x5f, 0x5f, 0x5e, 0x5d, 0xe2, 0x83, 0x85, 0xe3, 0x5d, 0x5e, 0x5e, 0xf5, 0x81, 0x21, 0x20, 0xaf, 0x9d, 0x9f, 0xae, 0x1f, 0x22, 0x7f, 0x1d, 0x1c, 0xf4, 0xd0, 0xd1, 0xf2, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x67, 0x01, 0xd5, 0x02, 0xe9, 0x05, 0xf0, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x29, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x01, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x07, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x7d, 0x02, 0x6b, 0xfd, 0x95, 0x02, 0x69, 0x86, 0x27, 0x82, 0x53, 0x74, 0x88, 0xab, 0xaa, 0xa3, 0x69, 0x69, 0x38, 0x7a, 0x3e, 0x42, 0x83, 0x3e, 0xa4, 0xa1, 0xf8, 0x91, 0x71, 0x58, 0x4a, 0x5d, 0x75, 0x02, 0x50, 0x7b, 0x02, 0xb8, 0xfe, 0x40, 0x70, 0x3f, 0x44, 0x87, 0x71, 0x87, 0x8a, 0x04, 0x5b, 0x5b, 0x22, 0x22, 0x7f, 0x1c, 0x1c, 0xb0, 0xf0, 0x43, 0x4f, 0x40, 0x4d, 0x90, 0x72, 0x1d, 0x00, 0x02, 0x00, 0x8e, 0x00, 0x8d, 0x03, 0xbb, 0x04, 0x23, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x15, 0x09, 0x01, 0x15, 0x01, 0x35, 0x13, 0x15, 0x09, 0x01, 0x15, 0x01, 0x35, 0x03, 0xbb, 0xfe, 0xf1, 0x01, 0x0f, 0xfe, 0x5a, 0x1f, 0xfe, 0xf1, 0x01, 0x0f, 0xfe, 0x5a, 0x04, 0x23, 0xbf, 0xfe, 0xf4, 0xfe, 0xf4, 0xbf, 0x01, 0xa2, 0x52, 0x01, 0xa2, 0xbf, 0xfe, 0xf4, 0xfe, 0xf4, 0xbf, 0x01, 0xa2, 0x52, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x01, 0x1f, 0x05, 0x46, 0x03, 0x5e, 0x00, 0x05, 0x00, 0x00, 0x13, 0x21, 0x11, 0x23, 0x11, 0x21, 0xc3, 0x04, 0x82, 0x97, 0xfc, 0x15, 0x03, 0x5e, 0xfd, 0xc1, 0x01, 0x95, 0x00, 0x01, 0x00, 0x5a, 0x01, 0xdf, 0x02, 0x40, 0x02, 0x83, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x5a, 0x01, 0xe5, 0xfe, 0x1b, 0x02, 0x83, 0xa4, 0x00, 0x00, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x00, 0x06, 0x35, 0x05, 0xcd, 0x00, 0x17, 0x00, 0x2f, 0x00, 0x38, 0x00, 0x4c, 0x00, 0x00, 0x01, 0x22, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x01, 0x27, 0x32, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x3e, 0x01, 0x13, 0x23, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x1f, 0x01, 0x23, 0x27, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x03, 0x9a, 0x76, 0xcc, 0x54, 0x55, 0x56, 0x56, 0x55, 0x54, 0xcc, 0x76, 0x76, 0xcd, 0x54, 0x54, 0x54, 0x55, 0x53, 0x54, 0xcd, 0x76, 0x88, 0xed, 0x62, 0x62, 0x61, 0x61, 0x62, 0x62, 0xed, 0x88, 0x89, 0xed, 0x62, 0x62, 0x61, 0x61, 0x62, 0x62, 0xed, 0x70, 0x6e, 0x6e, 0x63, 0x4f, 0x50, 0x5b, 0x9e, 0x9d, 0x5f, 0x56, 0x15, 0x3d, 0x29, 0x7b, 0x9a, 0x75, 0x35, 0x41, 0x31, 0x3b, 0x8c, 0x05, 0x66, 0x5e, 0x5e, 0x5e, 0xe5, 0x82, 0x81, 0xe3, 0x5e, 0x5e, 0x5f, 0x5f, 0x5e, 0x5d, 0xe2, 0x83, 0x85, 0xe3, 0x5d, 0x5e, 0x5e, 0x67, 0x6e, 0x6d, 0x6d, 0xfe, 0xfa, 0x9a, 0x98, 0xfe, 0xfb, 0x6d, 0x6d, 0x6e, 0x6e, 0x6d, 0x6d, 0x01, 0x05, 0x98, 0x9a, 0x01, 0x06, 0x6d, 0x6d, 0x6e, 0xfe, 0x62, 0xfe, 0xec, 0x3e, 0x4b, 0x4c, 0x3f, 0x67, 0x77, 0x79, 0x56, 0x70, 0x11, 0x08, 0x4d, 0x49, 0xdf, 0xd1, 0x60, 0x33, 0xfe, 0x9c, 0x03, 0x44, 0x00, 0x01, 0x00, 0xbf, 0x05, 0x62, 0x02, 0xda, 0x05, 0xf6, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0xc0, 0x02, 0x1a, 0xfd, 0xe6, 0x05, 0xf6, 0x94, 0x00, 0x00, 0x00, 0x02, 0x00, 0xaf, 0x03, 0x75, 0x02, 0xeb, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0xcd, 0x48, 0x63, 0x63, 0x48, 0x48, 0x63, 0x64, 0x47, 0x39, 0x6b, 0x26, 0x2a, 0x29, 0xa6, 0x79, 0x79, 0xa2, 0xa5, 0x05, 0x6f, 0x6f, 0x50, 0x4f, 0x6d, 0x6d, 0x4f, 0x4f, 0x70, 0x81, 0x31, 0x2e, 0x2d, 0x72, 0x42, 0x84, 0xb7, 0xb4, 0x87, 0x86, 0xba, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x05, 0x04, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x01, 0x21, 0x15, 0x21, 0x03, 0x50, 0x01, 0xf5, 0xfe, 0x0b, 0x97, 0xfe, 0x0a, 0x01, 0xf6, 0xfe, 0x0a, 0x04, 0x82, 0xfb, 0x7e, 0x05, 0x04, 0xfe, 0x7d, 0xaa, 0xfe, 0x7d, 0x01, 0x83, 0xaa, 0x01, 0x83, 0xfb, 0xa6, 0xaa, 0x00, 0x01, 0x00, 0x54, 0x02, 0x9c, 0x02, 0x6f, 0x05, 0xf0, 0x00, 0x18, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x35, 0x36, 0x37, 0x00, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x01, 0x06, 0xf1, 0x01, 0x7e, 0xfd, 0xe6, 0x1e, 0x39, 0x01, 0x36, 0x5e, 0x4d, 0x2e, 0x6e, 0x41, 0x45, 0x78, 0x33, 0x83, 0x9c, 0xfe, 0xd7, 0x33, 0x03, 0x0e, 0x72, 0x6e, 0x1f, 0x38, 0x01, 0x31, 0x5e, 0x42, 0x51, 0x23, 0x23, 0x7b, 0x1c, 0x1c, 0x84, 0x6c, 0x8b, 0xfe, 0xe4, 0x30, 0x00, 0x00, 0x01, 0x00, 0x58, 0x02, 0x8d, 0x02, 0x86, 0x05, 0xf0, 0x00, 0x28, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0xd8, 0x52, 0x5b, 0xab, 0x9f, 0x33, 0x71, 0x3f, 0x2f, 0x6b, 0x3c, 0x62, 0x6c, 0x63, 0x62, 0x4d, 0x55, 0x54, 0x57, 0x5a, 0x55, 0x24, 0x5c, 0x49, 0x42, 0x73, 0x32, 0x81, 0x98, 0x51, 0x04, 0x60, 0x12, 0x6d, 0x52, 0x7c, 0x86, 0x15, 0x14, 0x79, 0x1b, 0x1a, 0x4f, 0x46, 0x4a, 0x4c, 0x6c, 0x3f, 0x3c, 0x3a, 0x3d, 0x12, 0x17, 0x73, 0x11, 0x12, 0x76, 0x63, 0x45, 0x60, 0x00, 0x01, 0x01, 0x4d, 0x04, 0xee, 0x02, 0xfd, 0x06, 0x66, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x01, 0x23, 0x02, 0x4a, 0xb3, 0xfe, 0xdb, 0x8a, 0x06, 0x66, 0xfe, 0x88, 0x00, 0x01, 0x00, 0x9c, 0xfe, 0x56, 0x04, 0x68, 0x04, 0x60, 0x00, 0x20, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x11, 0x9d, 0xa5, 0x7c, 0x7a, 0x85, 0x86, 0xa6, 0x1f, 0x22, 0x08, 0x1c, 0x1a, 0x25, 0x42, 0x1f, 0x3e, 0x4a, 0x0e, 0x2d, 0x82, 0x59, 0x5b, 0x81, 0x26, 0xfe, 0x56, 0x06, 0x0a, 0xfd, 0x48, 0x91, 0x94, 0xa8, 0xa8, 0x02, 0x8d, 0xfc, 0xa2, 0x3c, 0x39, 0x0b, 0x0c, 0x94, 0x17, 0x16, 0x4e, 0x50, 0x4f, 0x4f, 0x4e, 0x4e, 0xfd, 0xd7, 0x00, 0x01, 0x00, 0x8e, 0xff, 0x3b, 0x03, 0xcd, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x02, 0x3a, 0x01, 0x93, 0x7f, 0xab, 0x80, 0xc1, 0xd4, 0xea, 0x05, 0xd5, 0xf9, 0x66, 0x06, 0x1f, 0xf9, 0xe1, 0x03, 0x4e, 0x11, 0xdd, 0xb8, 0xbe, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc5, 0x02, 0x48, 0x01, 0x83, 0x03, 0x46, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0xc5, 0xbe, 0xbe, 0x03, 0x46, 0xfe, 0x00, 0x01, 0x01, 0x05, 0xfe, 0x75, 0x02, 0x7b, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x21, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x02, 0x18, 0x32, 0x30, 0x6c, 0x6a, 0x29, 0x4e, 0x27, 0x1e, 0x43, 0x2a, 0x35, 0x36, 0x26, 0x29, 0x3e, 0x69, 0x30, 0x59, 0x5b, 0x0c, 0x0c, 0x83, 0x11, 0x0f, 0x30, 0x2e, 0x1e, 0x57, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7b, 0x02, 0x9c, 0x02, 0x7f, 0x05, 0xdf, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x33, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x33, 0x15, 0x21, 0x8c, 0xb8, 0xc9, 0xcf, 0x7c, 0xb8, 0xfe, 0x0e, 0x03, 0x0a, 0x02, 0x63, 0x29, 0x74, 0x27, 0xfd, 0x2b, 0x6e, 0x00, 0x00, 0x03, 0x00, 0x56, 0x01, 0xd5, 0x03, 0x0e, 0x05, 0xf0, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x7d, 0x02, 0x6b, 0xfd, 0x95, 0x01, 0x36, 0xa1, 0xb9, 0xb9, 0xa1, 0xa1, 0xbc, 0xbc, 0xa1, 0x5f, 0x71, 0x72, 0x5e, 0x5e, 0x71, 0x70, 0x02, 0x50, 0x7b, 0x04, 0x1b, 0xdd, 0xbf, 0xbf, 0xdb, 0xdc, 0xbe, 0xbf, 0xdd, 0x73, 0xa1, 0x88, 0x85, 0xa0, 0xa0, 0x85, 0x89, 0xa0, 0x00, 0x00, 0x00, 0x02, 0x00, 0xad, 0x00, 0x8d, 0x03, 0xdb, 0x04, 0x23, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x01, 0x15, 0x01, 0x35, 0x09, 0x01, 0x25, 0x01, 0x15, 0x01, 0x35, 0x09, 0x01, 0xae, 0x01, 0xa6, 0xfe, 0x5a, 0x01, 0x0f, 0xfe, 0xf1, 0x01, 0x86, 0x01, 0xa6, 0xfe, 0x5a, 0x01, 0x0f, 0xfe, 0xf1, 0x04, 0x23, 0xfe, 0x5e, 0x52, 0xfe, 0x5e, 0xbf, 0x01, 0x0c, 0x01, 0x0c, 0xbf, 0xfe, 0x5e, 0x52, 0xfe, 0x5e, 0xbf, 0x01, 0x0c, 0x01, 0x0c, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x06, 0xc0, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x27, 0x07, 0xa2, 0x04, 0x17, 0xfd, 0x64, 0x10, 0x07, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x06, 0x86, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x27, 0x00, 0x74, 0x04, 0x17, 0xfd, 0x64, 0x10, 0x07, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x58, 0xff, 0xe3, 0x06, 0xc0, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x75, 0x00, 0x00, 0x10, 0x27, 0x07, 0xa2, 0x04, 0x17, 0xfd, 0x64, 0x10, 0x07, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x00, 0x02, 0x00, 0x80, 0xff, 0xe3, 0x03, 0x4e, 0x05, 0xd5, 0x00, 0x20, 0x00, 0x24, 0x00, 0x00, 0x01, 0x33, 0x15, 0x14, 0x06, 0x0f, 0x01, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3f, 0x01, 0x3e, 0x01, 0x37, 0x3e, 0x01, 0x35, 0x13, 0x23, 0x35, 0x33, 0x01, 0xc2, 0xab, 0x31, 0x52, 0x50, 0x35, 0x2e, 0x76, 0x62, 0x47, 0xa2, 0x56, 0x55, 0xac, 0x5d, 0xa6, 0xc9, 0x41, 0x50, 0x50, 0x2b, 0x22, 0x07, 0x07, 0x05, 0xb0, 0xb5, 0xb5, 0x04, 0x44, 0x9c, 0x65, 0x82, 0x57, 0x58, 0x35, 0x5e, 0x31, 0x59, 0x6e, 0x46, 0x43, 0xbc, 0x39, 0x38, 0xc2, 0x9f, 0x4c, 0x89, 0x56, 0x56, 0x2f, 0x35, 0x19, 0x15, 0x3c, 0x36, 0x01, 0x0e, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x07, 0x10, 0xee, 0x04, 0x43, 0x01, 0x75, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x04, 0x43, 0x01, 0x75, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x11, 0x07, 0x10, 0xef, 0x04, 0x43, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x5e, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x11, 0x07, 0x10, 0xed, 0x04, 0x43, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x4e, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x04, 0x43, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x6d, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x21, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x0b, 0x01, 0x21, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x01, 0x23, 0x03, 0x21, 0x03, 0x23, 0x02, 0xff, 0x50, 0x39, 0x3a, 0x4e, 0x4f, 0x39, 0x39, 0x50, 0x89, 0xf5, 0x01, 0xeb, 0xfe, 0x82, 0x37, 0x38, 0x8f, 0x68, 0x67, 0x91, 0x39, 0x36, 0x01, 0xdf, 0xbd, 0x7b, 0xfd, 0xa2, 0x7a, 0xc0, 0x06, 0x5a, 0x3f, 0x59, 0x57, 0x41, 0x3f, 0x58, 0x58, 0xfe, 0xf3, 0xfd, 0x19, 0x03, 0x4e, 0x29, 0x73, 0x49, 0x73, 0xa0, 0xa1, 0x72, 0x46, 0x76, 0x29, 0xfa, 0x8b, 0x01, 0x7f, 0xfe, 0x81, 0x00, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x06, 0x8e, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x01, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x03, 0x23, 0x01, 0x17, 0x01, 0x21, 0x11, 0x06, 0x7c, 0xfd, 0x66, 0x02, 0x80, 0xfd, 0x80, 0x02, 0xac, 0xfc, 0x9d, 0xfe, 0x25, 0x90, 0xb9, 0x02, 0x33, 0x7d, 0xfe, 0xd7, 0x01, 0x9d, 0x05, 0xd5, 0xaa, 0xfe, 0x46, 0xaa, 0xfd, 0xe3, 0xaa, 0x01, 0x7f, 0xfe, 0x81, 0x05, 0xd5, 0x9e, 0xfc, 0xf0, 0x03, 0x10, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0x75, 0x04, 0xa4, 0x05, 0xf0, 0x12, 0x26, 0x00, 0x26, 0x00, 0x00, 0x10, 0x07, 0x00, 0x7a, 0x01, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x10, 0xee, 0x04, 0x28, 0x01, 0x75, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x04, 0x28, 0x01, 0x75, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x11, 0x07, 0x10, 0xef, 0x04, 0x28, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x4e, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x04, 0x28, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x35, 0x00, 0x00, 0x01, 0x8e, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x10, 0xee, 0x02, 0xde, 0x01, 0x75, 0xff, 0xff, 0x00, 0x91, 0x00, 0x00, 0x01, 0xe9, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x02, 0xde, 0x01, 0x75, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x02, 0x24, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x11, 0x07, 0x10, 0xef, 0x02, 0xde, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x02, 0x1c, 0x07, 0x4e, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x02, 0xde, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x05, 0x28, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x00, 0x13, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x11, 0x23, 0x35, 0x33, 0x13, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0xbe, 0x01, 0x76, 0x01, 0x86, 0x01, 0x6d, 0xfe, 0x92, 0xfe, 0x7b, 0xfe, 0x8a, 0xb5, 0xb5, 0xb7, 0x01, 0x2e, 0xfe, 0xd2, 0xda, 0x01, 0x16, 0x01, 0x03, 0xfe, 0xfd, 0xfe, 0xea, 0x05, 0xd5, 0xfe, 0x97, 0xfe, 0x80, 0xfe, 0x7e, 0xfe, 0x96, 0x02, 0xbc, 0x90, 0x01, 0xe3, 0xfe, 0x1d, 0x90, 0xfd, 0xea, 0x01, 0x18, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x17, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x5e, 0x12, 0x26, 0x00, 0x31, 0x00, 0x00, 0x11, 0x07, 0x10, 0xed, 0x04, 0x7e, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x07, 0x10, 0xee, 0x04, 0xa3, 0x01, 0x75, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x04, 0xa3, 0x01, 0x75, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x11, 0x07, 0x10, 0xef, 0x04, 0xa3, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x5e, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x11, 0x07, 0x10, 0xed, 0x04, 0xa3, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x4e, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x04, 0xa3, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfc, 0x00, 0x3f, 0x05, 0x0d, 0x04, 0xc5, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x02, 0x07, 0x09, 0x01, 0x27, 0x09, 0x01, 0x37, 0x09, 0x01, 0x05, 0x0c, 0xfe, 0x65, 0x01, 0x9b, 0x6b, 0xfe, 0x63, 0xfe, 0x63, 0x6a, 0x01, 0x9a, 0xfe, 0x66, 0x6a, 0x01, 0x9d, 0x01, 0x9d, 0x04, 0x4c, 0xfe, 0x35, 0xfe, 0x37, 0x79, 0x01, 0xcb, 0xfe, 0x35, 0x79, 0x01, 0xc9, 0x01, 0xcb, 0x79, 0xfe, 0x35, 0x01, 0xcb, 0x00, 0x00, 0x03, 0x00, 0x5b, 0xff, 0xba, 0x05, 0x4f, 0x06, 0x17, 0x00, 0x09, 0x00, 0x13, 0x00, 0x2b, 0x00, 0x00, 0x09, 0x01, 0x1e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x34, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x14, 0x16, 0x17, 0x07, 0x26, 0x02, 0x35, 0x10, 0x00, 0x21, 0x32, 0x16, 0x17, 0x37, 0x17, 0x07, 0x16, 0x12, 0x15, 0x10, 0x00, 0x21, 0x22, 0x26, 0x27, 0x07, 0x27, 0x04, 0x3d, 0xfd, 0x7b, 0x38, 0x91, 0x55, 0xc6, 0xe8, 0x24, 0x6c, 0x37, 0x91, 0x56, 0xc6, 0xe9, 0x23, 0x23, 0x78, 0x46, 0x47, 0x01, 0x53, 0x01, 0x1b, 0x75, 0xc7, 0x4e, 0x92, 0x5c, 0x99, 0x46, 0x48, 0xfe, 0xae, 0xfe, 0xe5, 0x73, 0xc7, 0x52, 0x92, 0x5c, 0x04, 0x58, 0xfc, 0xb2, 0x40, 0x43, 0x01, 0x48, 0x01, 0x1a, 0x70, 0xb8, 0xb8, 0x40, 0x43, 0xfe, 0xb8, 0xfe, 0xe5, 0x70, 0xbc, 0x44, 0x9e, 0x66, 0x01, 0x08, 0xa0, 0x01, 0x62, 0x01, 0xa5, 0x4d, 0x4b, 0xbf, 0x59, 0xc6, 0x67, 0xfe, 0xf6, 0x9e, 0xfe, 0x9f, 0xfe, 0x5b, 0x4b, 0x4b, 0xbf, 0x58, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x10, 0xee, 0x04, 0x70, 0x01, 0x75, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x04, 0x70, 0x01, 0x75, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x11, 0x07, 0x10, 0xef, 0x04, 0x70, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x4e, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x04, 0x70, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x3c, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x04, 0x01, 0x01, 0x75, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x13, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0xb5, 0xb6, 0xe4, 0xe2, 0xe7, 0xe7, 0xe2, 0xe4, 0xb6, 0xb6, 0xe4, 0x7f, 0x8b, 0x8a, 0x80, 0x05, 0xd5, 0xfe, 0xf8, 0xe1, 0xdc, 0xdc, 0xe2, 0xfe, 0xae, 0x04, 0x27, 0xfd, 0xd1, 0x92, 0x86, 0x86, 0x91, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xff, 0xe3, 0x04, 0x35, 0x06, 0x14, 0x00, 0x2f, 0x00, 0x00, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0xa7, 0xd7, 0xc5, 0xbb, 0xc5, 0x03, 0x88, 0x97, 0x34, 0x3a, 0x34, 0x95, 0x56, 0xca, 0xbe, 0x3a, 0x7a, 0x42, 0x48, 0x7e, 0x3b, 0x68, 0x6c, 0x35, 0x5b, 0x53, 0x56, 0x4e, 0x96, 0x88, 0x07, 0x76, 0x66, 0x75, 0x7a, 0xa9, 0x04, 0x71, 0xc8, 0xdb, 0xe8, 0xe0, 0x08, 0x73, 0x60, 0x2f, 0x51, 0x2a, 0x25, 0x6a, 0x8e, 0x64, 0xac, 0xb7, 0x19, 0x18, 0xa4, 0x1e, 0x1d, 0x5f, 0x5b, 0x3f, 0x54, 0x3e, 0x37, 0x3b, 0x87, 0x5b, 0x7f, 0xac, 0x1d, 0x67, 0x70, 0x8b, 0x83, 0xfb, 0x93, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x66, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x11, 0x06, 0x00, 0x43, 0x4a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x66, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x11, 0x06, 0x00, 0x76, 0x4a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x66, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x11, 0x06, 0x02, 0x88, 0x4a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x37, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x11, 0x06, 0x02, 0x9e, 0x4a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x10, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x11, 0x06, 0x00, 0x6a, 0x4a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x07, 0x06, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x11, 0x06, 0x02, 0x9c, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6e, 0xff, 0xe3, 0x06, 0xb1, 0x04, 0x7b, 0x00, 0x06, 0x00, 0x33, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x03, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x1d, 0x01, 0x21, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x03, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x06, 0x0a, 0x01, 0x94, 0x7b, 0x8a, 0xa7, 0x0c, 0x3d, 0x42, 0xbf, 0x77, 0xcb, 0xee, 0xfd, 0x06, 0x0b, 0xb8, 0xa4, 0x5e, 0xb4, 0x5a, 0x5a, 0xbb, 0x60, 0x96, 0xdf, 0x45, 0x42, 0xc3, 0x80, 0xaa, 0xbd, 0xe3, 0xe2, 0xe8, 0x96, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0x80, 0xc0, 0xd7, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0x02, 0x94, 0x97, 0xb4, 0xae, 0x9e, 0x01, 0x30, 0x5a, 0x5e, 0xfe, 0xdd, 0xfa, 0x5a, 0xbf, 0xc8, 0x35, 0x35, 0xae, 0x2a, 0x2c, 0x79, 0x77, 0x78, 0x78, 0xbb, 0xa8, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0x60, 0xfe, 0x18, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x03, 0x84, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x46, 0x00, 0x00, 0x10, 0x07, 0x00, 0x7a, 0x00, 0x81, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x66, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x06, 0x00, 0x43, 0x7d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x66, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x7d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x66, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x11, 0x06, 0x02, 0x88, 0x7d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x10, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x11, 0x06, 0x00, 0x6a, 0x7d, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xcc, 0x00, 0x00, 0x01, 0x7c, 0x06, 0x66, 0x10, 0x27, 0x00, 0x43, 0xff, 0x34, 0x00, 0x00, 0x12, 0x06, 0x00, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x81, 0x00, 0x00, 0x02, 0x31, 0x06, 0x66, 0x10, 0x27, 0x00, 0x76, 0xff, 0x34, 0x00, 0x00, 0x12, 0x06, 0x00, 0xf3, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x00, 0x02, 0x20, 0x06, 0x66, 0x12, 0x26, 0x00, 0xf3, 0x00, 0x00, 0x11, 0x07, 0x02, 0x88, 0xff, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf5, 0x00, 0x00, 0x02, 0x0c, 0x06, 0x10, 0x12, 0x26, 0x00, 0xf3, 0x00, 0x00, 0x11, 0x07, 0x00, 0x6a, 0xff, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x14, 0x00, 0x0e, 0x00, 0x28, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x13, 0x16, 0x12, 0x15, 0x14, 0x00, 0x23, 0x22, 0x02, 0x11, 0x34, 0x12, 0x33, 0x32, 0x16, 0x17, 0x27, 0x05, 0x27, 0x37, 0x27, 0x33, 0x17, 0x25, 0x17, 0x05, 0x02, 0xf2, 0x2d, 0x4f, 0x25, 0x96, 0xa7, 0x9d, 0x83, 0x83, 0x9c, 0x30, 0x08, 0x71, 0x67, 0xff, 0x00, 0xcf, 0xd0, 0xfe, 0xf8, 0xc7, 0x10, 0x2f, 0x26, 0x8f, 0xfe, 0xe1, 0x1e, 0xfd, 0xa3, 0xcd, 0x72, 0x01, 0x2c, 0x1e, 0xfe, 0xf6, 0x03, 0x93, 0x11, 0x10, 0xd8, 0xc3, 0xbc, 0xde, 0xde, 0xbc, 0x7a, 0xbc, 0x01, 0x26, 0x8f, 0xfe, 0xe0, 0xad, 0xff, 0xfe, 0xc9, 0x01, 0x37, 0x00, 0xff, 0xfa, 0x01, 0x37, 0x05, 0x05, 0xb4, 0x6b, 0x63, 0x5c, 0xcc, 0x91, 0x6f, 0x61, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x37, 0x12, 0x26, 0x00, 0x51, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9e, 0x00, 0x89, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x10, 0x06, 0x00, 0x43, 0x68, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x68, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x11, 0x06, 0x02, 0x88, 0x68, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x37, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x11, 0x06, 0x02, 0x9e, 0x68, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x10, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x11, 0x06, 0x00, 0x6a, 0x68, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0x96, 0x05, 0x46, 0x04, 0x6f, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x01, 0x21, 0x15, 0x21, 0x02, 0x96, 0xdd, 0xdd, 0xdd, 0xdd, 0xfe, 0x2d, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x6f, 0xf6, 0xfe, 0x12, 0xf5, 0x02, 0x41, 0xaa, 0x00, 0x00, 0x03, 0x00, 0x40, 0xff, 0xa2, 0x04, 0x26, 0x04, 0xbc, 0x00, 0x09, 0x00, 0x13, 0x00, 0x2b, 0x00, 0x00, 0x09, 0x01, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x07, 0x2e, 0x01, 0x35, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x37, 0x17, 0x07, 0x1e, 0x01, 0x15, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x07, 0x27, 0x03, 0x2e, 0xfe, 0x4a, 0x25, 0x5d, 0x3a, 0x85, 0x9a, 0x12, 0x52, 0x26, 0x5d, 0x38, 0x88, 0x98, 0x11, 0x12, 0x70, 0x31, 0x30, 0xf5, 0xd9, 0x54, 0x8f, 0x3c, 0x7d, 0x56, 0x83, 0x2f, 0x31, 0xf7, 0xd8, 0x56, 0x91, 0x39, 0x7d, 0x56, 0x03, 0x21, 0xfd, 0xb0, 0x2a, 0x28, 0xe8, 0xc8, 0x4f, 0x75, 0x9a, 0x29, 0x29, 0xeb, 0xd3, 0x48, 0x6e, 0x2e, 0x97, 0x4d, 0xc5, 0x77, 0x01, 0x14, 0x01, 0x38, 0x33, 0x34, 0xa8, 0x4f, 0xb3, 0x4d, 0xc6, 0x78, 0xfe, 0xed, 0xfe, 0xc7, 0x34, 0x33, 0xa8, 0x4e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x66, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x06, 0x00, 0x43, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x66, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x66, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x11, 0x06, 0x02, 0x88, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x10, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x11, 0x06, 0x00, 0x6a, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x66, 0x12, 0x26, 0x00, 0x5c, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x55, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x25, 0x11, 0x23, 0x11, 0x33, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x01, 0x4e, 0xa7, 0xa7, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x01, 0xff, 0x96, 0x83, 0x84, 0x96, 0x96, 0x84, 0x83, 0x96, 0xa8, 0xfd, 0xae, 0x07, 0xbe, 0xfd, 0xa2, 0x64, 0x61, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xf8, 0xfe, 0xbc, 0x61, 0x01, 0xeb, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x10, 0x12, 0x26, 0x00, 0x5c, 0x00, 0x00, 0x11, 0x06, 0x00, 0x6a, 0x55, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x00, 0xaa, 0x01, 0x3b, 0x13, 0x06, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x05, 0xf6, 0x10, 0x26, 0x00, 0x71, 0x43, 0x00, 0x13, 0x06, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x92, 0x10, 0x27, 0x02, 0x9a, 0x00, 0xb9, 0x01, 0x4a, 0x13, 0x06, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x1f, 0x10, 0x26, 0x02, 0x9a, 0x47, 0xd7, 0x13, 0x06, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x75, 0x05, 0x15, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9d, 0x02, 0x9a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xfe, 0x75, 0x04, 0x0d, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9d, 0x01, 0x92, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x07, 0x6b, 0x12, 0x26, 0x00, 0x26, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x04, 0xa8, 0x01, 0x75, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x06, 0x66, 0x12, 0x26, 0x00, 0x46, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x7b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xef, 0x04, 0xc4, 0x01, 0x75, 0x13, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x06, 0x66, 0x12, 0x26, 0x00, 0x46, 0x00, 0x00, 0x10, 0x07, 0x02, 0x88, 0x00, 0x94, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0xc4, 0x01, 0x75, 0x12, 0x06, 0x00, 0x26, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x04, 0x2d, 0x00, 0x00, 0x12, 0x06, 0x00, 0x46, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x26, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0xa8, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x06, 0x66, 0x12, 0x26, 0x00, 0x46, 0x00, 0x00, 0x10, 0x06, 0x02, 0x89, 0x7b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x1f, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf0, 0x04, 0x6e, 0x01, 0x75, 0x12, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x05, 0x46, 0x06, 0x14, 0x12, 0x26, 0x00, 0x47, 0x00, 0x00, 0x11, 0x07, 0x10, 0xea, 0x04, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x00, 0x05, 0x28, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x92, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x76, 0x06, 0x14, 0x00, 0x18, 0x00, 0x24, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x03, 0x45, 0xfe, 0xdb, 0x01, 0x25, 0xa6, 0x8a, 0x8a, 0xa6, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0xfe, 0x00, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0x03, 0xb6, 0x01, 0x4e, 0x7d, 0x93, 0x93, 0x7d, 0xfa, 0xfc, 0xa8, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0xfe, 0x15, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x33, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x00, 0x71, 0x00, 0x91, 0x01, 0x3d, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x05, 0xf6, 0x10, 0x27, 0x00, 0x71, 0x00, 0x87, 0x00, 0x00, 0x13, 0x06, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf2, 0x04, 0x2a, 0x01, 0x75, 0x13, 0x06, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x48, 0x10, 0x27, 0x02, 0x9a, 0x00, 0x87, 0x00, 0x00, 0x13, 0x06, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x28, 0x01, 0x75, 0x12, 0x06, 0x00, 0x28, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x04, 0x21, 0x00, 0x00, 0x12, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x75, 0x04, 0x19, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9d, 0x01, 0x9e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x04, 0x0c, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9d, 0x01, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x67, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0x2f, 0x01, 0x6f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x61, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x11, 0x07, 0x02, 0x89, 0x00, 0x85, 0xff, 0xfb, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xef, 0x04, 0xd3, 0x01, 0x75, 0x13, 0x06, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x06, 0x66, 0x10, 0x26, 0x02, 0x88, 0x5e, 0x00, 0x13, 0x06, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x2a, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf2, 0x04, 0x98, 0x01, 0x75, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x06, 0x48, 0x12, 0x26, 0x00, 0x4a, 0x00, 0x00, 0x10, 0x06, 0x02, 0x9a, 0x7d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0xd3, 0x01, 0x75, 0x13, 0x06, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xf9, 0x00, 0x00, 0x12, 0x06, 0x00, 0x4a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0x01, 0x04, 0xfe, 0x05, 0xf0, 0x10, 0x27, 0x02, 0xd7, 0x04, 0xd4, 0xff, 0xed, 0x12, 0x06, 0x00, 0x2a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x06, 0x34, 0x10, 0x27, 0x02, 0xc3, 0x03, 0x7c, 0x01, 0x0c, 0x12, 0x06, 0x00, 0x4a, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xef, 0x04, 0x82, 0x01, 0x75, 0x13, 0x06, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe7, 0x00, 0x00, 0x03, 0xf4, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xef, 0x02, 0xc7, 0x01, 0x75, 0x13, 0x06, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x05, 0xe4, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x17, 0x00, 0x00, 0x01, 0x33, 0x15, 0x21, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x17, 0x15, 0x21, 0x35, 0x01, 0x4c, 0xb6, 0x02, 0x94, 0xb6, 0x98, 0x98, 0xb6, 0xfd, 0x6c, 0xb6, 0x97, 0x97, 0xb6, 0x02, 0x94, 0x05, 0xd5, 0xe0, 0xe0, 0xe0, 0xa4, 0xfb, 0xaf, 0x02, 0xc7, 0xfd, 0x39, 0x04, 0x51, 0xa4, 0xa4, 0xe0, 0xe0, 0x00, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x04, 0x29, 0x06, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x33, 0x15, 0x21, 0x15, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x04, 0x29, 0xa6, 0x6f, 0x70, 0x86, 0x9b, 0xa7, 0x70, 0x70, 0xa7, 0x01, 0x3d, 0xfe, 0xc3, 0x3b, 0xa2, 0x69, 0xad, 0xb3, 0x02, 0xa4, 0xfd, 0x5c, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0xf6, 0xa4, 0x7a, 0x7a, 0xa4, 0xfe, 0xbc, 0x65, 0x64, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe6, 0x00, 0x00, 0x02, 0x39, 0x07, 0x5e, 0x10, 0x27, 0x10, 0xed, 0x02, 0xdd, 0x01, 0x75, 0x13, 0x06, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xd7, 0x00, 0x00, 0x02, 0x2a, 0x06, 0x37, 0x10, 0x27, 0x02, 0x9e, 0xff, 0x34, 0x00, 0x00, 0x13, 0x06, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x02, 0x00, 0x00, 0x02, 0x1d, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0xff, 0x43, 0x01, 0x3b, 0x13, 0x06, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf3, 0x00, 0x00, 0x02, 0x0e, 0x05, 0xf5, 0x10, 0x27, 0x00, 0x71, 0xff, 0x34, 0xff, 0xff, 0x13, 0x06, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf6, 0x00, 0x00, 0x02, 0x2a, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf2, 0x02, 0xdd, 0x01, 0x75, 0x13, 0x06, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe6, 0x00, 0x00, 0x02, 0x1b, 0x06, 0x48, 0x10, 0x27, 0x02, 0x9a, 0xff, 0x34, 0x00, 0x00, 0x13, 0x06, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9e, 0xfe, 0x75, 0x01, 0xef, 0x05, 0xd5, 0x10, 0x27, 0x02, 0x9d, 0xff, 0x74, 0x00, 0x00, 0x12, 0x06, 0x00, 0x2c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x87, 0xfe, 0x75, 0x01, 0xd7, 0x06, 0x14, 0x10, 0x27, 0x02, 0x9d, 0xff, 0x5c, 0x00, 0x00, 0x12, 0x06, 0x00, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x6d, 0x07, 0x50, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf3, 0x02, 0xde, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xad, 0x00, 0x00, 0x01, 0x54, 0x04, 0x7b, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x13, 0xae, 0xa5, 0xa5, 0x52, 0x04, 0x60, 0xfb, 0xa0, 0x04, 0x7b, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x66, 0x03, 0x8b, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x2d, 0x02, 0x20, 0x00, 0x00, 0x11, 0x06, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0xfe, 0x56, 0x03, 0x53, 0x06, 0x14, 0x10, 0x27, 0x00, 0x4d, 0x01, 0xff, 0x00, 0x00, 0x11, 0x06, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xa0, 0xfe, 0x66, 0x02, 0x23, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xef, 0x02, 0xdd, 0x01, 0x75, 0x13, 0x06, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xde, 0xfe, 0x56, 0x02, 0x20, 0x06, 0x66, 0x10, 0x27, 0x02, 0x88, 0xff, 0x34, 0x00, 0x00, 0x13, 0x06, 0x01, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x1e, 0x04, 0xe0, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd7, 0x04, 0x98, 0x00, 0x0a, 0x12, 0x06, 0x00, 0x2e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x1e, 0x04, 0x26, 0x06, 0x14, 0x10, 0x27, 0x02, 0xd7, 0x04, 0x35, 0x00, 0x0a, 0x12, 0x06, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x26, 0x04, 0x60, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0xa7, 0xa7, 0x01, 0xee, 0xd4, 0xfd, 0xe9, 0x02, 0x2d, 0xd8, 0xfe, 0x00, 0xa7, 0x04, 0x60, 0xfe, 0x1b, 0x01, 0xe5, 0xfd, 0xf2, 0xfd, 0xae, 0x02, 0x21, 0xfd, 0xdf, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x03, 0x16, 0x01, 0x76, 0x12, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x02, 0x10, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x03, 0x04, 0x01, 0x76, 0x13, 0x06, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x1e, 0x03, 0xf9, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd7, 0x04, 0x25, 0x00, 0x0a, 0x12, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7a, 0xfe, 0x1e, 0x01, 0x83, 0x06, 0x14, 0x10, 0x27, 0x02, 0xd7, 0x02, 0xce, 0x00, 0x0a, 0x13, 0x06, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x10, 0x27, 0x10, 0xea, 0x02, 0x5c, 0xff, 0xc3, 0x12, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x02, 0xb4, 0x06, 0x14, 0x10, 0x27, 0x10, 0xea, 0x02, 0x00, 0x00, 0x02, 0x11, 0x06, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x79, 0x01, 0xf9, 0x00, 0x77, 0x12, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x02, 0x44, 0x06, 0x14, 0x10, 0x27, 0x00, 0x79, 0x00, 0xc1, 0x00, 0x73, 0x11, 0x06, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf3, 0x00, 0x00, 0x04, 0x03, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x11, 0x25, 0x17, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x07, 0x27, 0x37, 0xbe, 0xb7, 0x01, 0x19, 0x48, 0xfe, 0x9f, 0x02, 0x8e, 0xfc, 0xbb, 0x85, 0x46, 0xcb, 0x05, 0xd5, 0xfd, 0x98, 0xdb, 0x6f, 0xfe, 0xee, 0xfd, 0xe3, 0xaa, 0x02, 0x3b, 0x6a, 0x6e, 0x9e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x0e, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x37, 0x17, 0x07, 0x11, 0x23, 0x11, 0x07, 0x27, 0x37, 0xb3, 0xa6, 0x70, 0x45, 0xb5, 0xa6, 0x6f, 0x42, 0xb1, 0x06, 0x14, 0xfd, 0xa6, 0x5a, 0x6a, 0x8d, 0xfc, 0xe3, 0x02, 0x9a, 0x58, 0x6a, 0x8d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0x4b, 0x01, 0x76, 0x13, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x6d, 0x10, 0x26, 0x00, 0x76, 0x3c, 0x07, 0x13, 0x06, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x1e, 0x04, 0xae, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd7, 0x04, 0x80, 0x00, 0x0a, 0x12, 0x06, 0x00, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x1e, 0x03, 0xf4, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd7, 0x04, 0x1c, 0x00, 0x0a, 0x12, 0x06, 0x00, 0x51, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x5f, 0x12, 0x26, 0x00, 0x31, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0x76, 0x01, 0x67, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x66, 0x12, 0x26, 0x00, 0x51, 0x00, 0x00, 0x11, 0x06, 0x02, 0x89, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb8, 0x00, 0x00, 0x05, 0x27, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x51, 0x01, 0x33, 0x00, 0x00, 0x10, 0x06, 0x02, 0x7e, 0x18, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x04, 0x97, 0x05, 0xf0, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x10, 0x21, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x12, 0x19, 0x01, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x03, 0xe2, 0xfe, 0xeb, 0xa1, 0xc1, 0xb6, 0xb6, 0x46, 0x5e, 0x60, 0x89, 0xcd, 0xd1, 0x49, 0x49, 0xa3, 0x4e, 0x2c, 0x5c, 0x47, 0x03, 0x7f, 0x01, 0xac, 0xff, 0xde, 0xfc, 0xb2, 0x05, 0xd5, 0xf1, 0x86, 0x43, 0x43, 0xfe, 0xc1, 0xfe, 0xcc, 0xfc, 0x6f, 0xd5, 0x61, 0x60, 0x9c, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x04, 0x7b, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x03, 0xf4, 0x4a, 0x49, 0xa3, 0xe5, 0xd2, 0x5f, 0x22, 0x22, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0x50, 0x51, 0x6a, 0xad, 0x59, 0x5a, 0x02, 0xa4, 0xfd, 0x48, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x31, 0x99, 0x02, 0xb2, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x65, 0x32, 0x32, 0x77, 0x78, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x01, 0x0a, 0x01, 0x3b, 0x13, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x05, 0xf5, 0x10, 0x26, 0x00, 0x71, 0x68, 0xff, 0x13, 0x06, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf2, 0x04, 0xa3, 0x01, 0x75, 0x13, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x48, 0x10, 0x26, 0x02, 0x9a, 0x68, 0x00, 0x13, 0x06, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x6b, 0x10, 0x27, 0x10, 0xf4, 0x04, 0xa3, 0x01, 0x75, 0x12, 0x06, 0x00, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x10, 0x27, 0x02, 0x9f, 0x00, 0x90, 0x00, 0x00, 0x12, 0x06, 0x00, 0x52, 0x00, 0x00, 0x00, 0x02, 0x00, 0x67, 0x00, 0x00, 0x07, 0x3e, 0x05, 0xd5, 0x00, 0x10, 0x00, 0x19, 0x00, 0x00, 0x01, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x17, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x33, 0x07, 0x2e, 0xfd, 0x64, 0x02, 0x80, 0xfd, 0x80, 0x02, 0xac, 0xfc, 0x42, 0xfe, 0x7a, 0xfe, 0x6e, 0x01, 0x92, 0x01, 0x86, 0x5c, 0x74, 0xfe, 0xdf, 0xfe, 0xe0, 0x01, 0x20, 0x01, 0x21, 0x74, 0x05, 0xd5, 0xaa, 0xfe, 0x46, 0xaa, 0xfd, 0xe3, 0xaa, 0x01, 0x7c, 0x01, 0x70, 0x01, 0x6d, 0x01, 0x7c, 0xaa, 0xfe, 0xe1, 0xfe, 0xe0, 0xfe, 0xdf, 0xfe, 0xdf, 0x00, 0x00, 0x03, 0x00, 0x65, 0xff, 0xe3, 0x06, 0xfd, 0x04, 0x7b, 0x00, 0x06, 0x00, 0x27, 0x00, 0x33, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x05, 0x15, 0x21, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x25, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x06, 0x56, 0x02, 0x94, 0x7b, 0x8a, 0xa6, 0x0d, 0x02, 0xf4, 0xfd, 0x07, 0x0b, 0xb7, 0xa5, 0x5f, 0xb4, 0x59, 0x5a, 0xbc, 0x5f, 0x90, 0xda, 0x49, 0x40, 0xbc, 0x7e, 0xd9, 0xf5, 0xf5, 0xd9, 0x7e, 0xbe, 0x3c, 0x46, 0xd1, 0x80, 0xcc, 0xed, 0xfb, 0x38, 0x85, 0x9b, 0x9a, 0x86, 0x85, 0x9a, 0x9a, 0x02, 0x94, 0x98, 0xb3, 0xae, 0x9e, 0x35, 0x5a, 0xbe, 0xc7, 0x34, 0x34, 0xae, 0x2a, 0x2c, 0x6e, 0x6d, 0x6e, 0x6d, 0x01, 0x39, 0x01, 0x13, 0x01, 0x14, 0x01, 0x38, 0x6f, 0x6c, 0x6b, 0x70, 0xfe, 0xdd, 0x87, 0xe7, 0xc9, 0xc9, 0xe7, 0xe8, 0xc8, 0xc7, 0xe9, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xcc, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0x20, 0x01, 0x76, 0x12, 0x06, 0x00, 0x35, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x39, 0x06, 0x6d, 0x10, 0x26, 0x00, 0x76, 0x3b, 0x07, 0x12, 0x06, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x1e, 0x04, 0xcc, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd7, 0x04, 0x8e, 0x00, 0x0a, 0x12, 0x06, 0x00, 0x35, 0x00, 0x00, 0xff, 0xff, 0x00, 0x75, 0xfe, 0x1e, 0x02, 0xf6, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd7, 0x02, 0xc9, 0x00, 0x0a, 0x12, 0x06, 0x00, 0x55, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xcc, 0x07, 0x5f, 0x12, 0x26, 0x00, 0x35, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0x0a, 0x01, 0x67, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x05, 0x06, 0x66, 0x12, 0x26, 0x00, 0x55, 0x00, 0x00, 0x11, 0x06, 0x02, 0x89, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0x20, 0x01, 0x76, 0x12, 0x06, 0x00, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x06, 0x6d, 0x10, 0x26, 0x00, 0x76, 0x3c, 0x07, 0x12, 0x06, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xef, 0x04, 0x1e, 0x01, 0x75, 0x13, 0x06, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x06, 0x66, 0x10, 0x26, 0x02, 0x88, 0x21, 0x00, 0x13, 0x06, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x75, 0x04, 0x2c, 0x05, 0xf0, 0x12, 0x26, 0x00, 0x36, 0x00, 0x00, 0x10, 0x06, 0x00, 0x7a, 0x7d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xfe, 0x75, 0x03, 0x67, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x56, 0x00, 0x00, 0x10, 0x06, 0x00, 0x7a, 0x15, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x36, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0x17, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x06, 0x66, 0x12, 0x26, 0x00, 0x56, 0x00, 0x00, 0x11, 0x07, 0x02, 0xbd, 0x03, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0xfe, 0x75, 0x04, 0x6c, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x7a, 0x48, 0x00, 0x12, 0x06, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0xfe, 0x75, 0x02, 0xa7, 0x05, 0x9e, 0x10, 0x26, 0x00, 0x7a, 0xe4, 0x00, 0x12, 0x06, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0x00, 0x00, 0x04, 0x6c, 0x07, 0x5f, 0x12, 0x26, 0x00, 0x37, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0x01, 0x01, 0x67, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0x00, 0x00, 0x02, 0xb2, 0x06, 0x82, 0x12, 0x26, 0x00, 0x57, 0x00, 0x00, 0x11, 0x07, 0x10, 0xea, 0x01, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x00, 0x00, 0x04, 0x6c, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x21, 0x15, 0x21, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x21, 0x05, 0x04, 0x70, 0xfe, 0x23, 0xef, 0xef, 0xb6, 0xef, 0xef, 0xfe, 0x23, 0x05, 0xd5, 0xaa, 0xfd, 0xc0, 0xaa, 0xfd, 0xbf, 0x02, 0x41, 0xaa, 0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x31, 0x00, 0x00, 0x02, 0xa7, 0x05, 0x9e, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x23, 0x35, 0x33, 0x35, 0x23, 0x35, 0x33, 0x11, 0x01, 0x52, 0x01, 0x55, 0xfe, 0xab, 0x01, 0x55, 0xfe, 0xab, 0x21, 0x22, 0x67, 0xab, 0xab, 0xbf, 0x49, 0x49, 0x79, 0x79, 0x79, 0x79, 0x05, 0x9e, 0xfe, 0xc2, 0x8f, 0xe9, 0x8e, 0xe9, 0x89, 0x27, 0x27, 0x9a, 0x50, 0x4f, 0xd2, 0xe9, 0x8e, 0xe9, 0x8f, 0x01, 0x3e, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x5e, 0x10, 0x27, 0x10, 0xed, 0x04, 0x70, 0x01, 0x75, 0x13, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x37, 0x10, 0x26, 0x02, 0x9e, 0x76, 0x00, 0x13, 0x06, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x00, 0xd6, 0x01, 0x3b, 0x13, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x05, 0xf5, 0x10, 0x26, 0x00, 0x71, 0x76, 0xff, 0x13, 0x06, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf2, 0x04, 0x70, 0x01, 0x75, 0x13, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x48, 0x10, 0x26, 0x02, 0x9a, 0x76, 0x00, 0x13, 0x06, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x6f, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9c, 0x00, 0xd8, 0x00, 0x69, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0xca, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x11, 0x06, 0x02, 0x9c, 0x70, 0xc4, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x6b, 0x10, 0x27, 0x10, 0xf4, 0x04, 0x70, 0x01, 0x75, 0x12, 0x06, 0x00, 0x38, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xef, 0x06, 0x66, 0x10, 0x27, 0x02, 0x9f, 0x00, 0x9e, 0x00, 0x00, 0x12, 0x06, 0x00, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xfe, 0x75, 0x04, 0xa5, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9d, 0x00, 0xe1, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xfe, 0x75, 0x04, 0x6b, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9d, 0x01, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0x00, 0x00, 0x06, 0xe3, 0x07, 0x74, 0x10, 0x27, 0x10, 0xef, 0x05, 0x5c, 0x01, 0x7c, 0x13, 0x06, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x06, 0x6d, 0x10, 0x27, 0x02, 0x88, 0x01, 0x24, 0x00, 0x07, 0x13, 0x06, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x74, 0x10, 0x27, 0x10, 0xef, 0x04, 0x00, 0x01, 0x7c, 0x13, 0x06, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x6d, 0x10, 0x26, 0x02, 0x88, 0x55, 0x07, 0x13, 0x06, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x4e, 0x12, 0x26, 0x00, 0x3c, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x04, 0x01, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0x00, 0x00, 0x04, 0x9c, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0x20, 0x01, 0x76, 0x12, 0x06, 0x00, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x79, 0x06, 0x6d, 0x10, 0x26, 0x00, 0x76, 0x3c, 0x07, 0x12, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0x00, 0x00, 0x04, 0x9c, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x45, 0x01, 0x75, 0x12, 0x06, 0x00, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x79, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xae, 0x00, 0x00, 0x13, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0x00, 0x00, 0x04, 0x9c, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x3d, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf0, 0x04, 0x45, 0x01, 0x75, 0xff, 0xff, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x79, 0x06, 0x66, 0x12, 0x26, 0x00, 0x5d, 0x00, 0x00, 0x11, 0x06, 0x02, 0x89, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, 0x06, 0x14, 0x00, 0x10, 0x00, 0x00, 0x21, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x01, 0x6f, 0xa6, 0x9f, 0x9f, 0x9c, 0xaa, 0x9d, 0x9e, 0x5a, 0x22, 0x23, 0x03, 0xd1, 0x8f, 0x4e, 0xbb, 0xab, 0x99, 0x28, 0x29, 0x67, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1c, 0xff, 0xe3, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x0f, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x15, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x33, 0x15, 0x21, 0x15, 0x21, 0x03, 0x81, 0x4b, 0x4b, 0x83, 0x84, 0x4b, 0x4b, 0x4b, 0x4b, 0x84, 0x83, 0x4b, 0x4b, 0xfd, 0xcd, 0x34, 0x50, 0x4f, 0x6f, 0xb8, 0x72, 0x73, 0x73, 0x72, 0xb8, 0x6f, 0x4f, 0x50, 0x34, 0xa7, 0x8a, 0x8a, 0xa7, 0x01, 0x24, 0xfe, 0xdc, 0x02, 0x2f, 0xcb, 0x74, 0x73, 0x73, 0x74, 0xcb, 0xcb, 0x74, 0x73, 0x73, 0x74, 0x02, 0x52, 0x64, 0x30, 0x31, 0xa2, 0xa2, 0xfe, 0xf8, 0xfe, 0xf8, 0xa2, 0xa2, 0x31, 0x30, 0x64, 0xa8, 0x05, 0x04, 0x7d, 0x93, 0x93, 0x7d, 0x00, 0x00, 0x03, 0xff, 0xa1, 0x00, 0x00, 0x04, 0xc8, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x11, 0x00, 0x29, 0x00, 0x00, 0x01, 0x11, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x11, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x22, 0x06, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x36, 0x01, 0xc5, 0x01, 0x23, 0x93, 0x8d, 0x8d, 0x93, 0xfe, 0xdd, 0x01, 0x0d, 0x85, 0x83, 0x83, 0x85, 0xfe, 0x3d, 0x01, 0xd0, 0xd0, 0xe1, 0x73, 0x70, 0x87, 0x94, 0xf5, 0xe2, 0xfe, 0x1e, 0x77, 0x6a, 0x8c, 0xac, 0x02, 0xc9, 0xfd, 0xdd, 0x87, 0x8b, 0x8c, 0x85, 0x02, 0x66, 0xfe, 0x3e, 0x6f, 0x72, 0x71, 0x70, 0xa6, 0xc0, 0xb1, 0x89, 0xa2, 0x14, 0x20, 0xcb, 0x98, 0xc8, 0xda, 0x05, 0x30, 0x5f, 0x69, 0x31, 0x46, 0xb5, 0xa3, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x12, 0x06, 0x03, 0xa5, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0xe3, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x16, 0x00, 0x26, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x15, 0x23, 0x11, 0x21, 0x15, 0x25, 0x01, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x01, 0x4e, 0x34, 0x50, 0x4f, 0x6f, 0xb8, 0x72, 0x73, 0x73, 0x72, 0xb8, 0x6f, 0x4f, 0x50, 0x34, 0xa7, 0x02, 0xfa, 0xfd, 0xad, 0x02, 0x33, 0x4b, 0x4b, 0x83, 0x84, 0x4b, 0x4b, 0x4b, 0x4b, 0x84, 0x83, 0x4b, 0x4b, 0x03, 0xb6, 0x64, 0x30, 0x31, 0xa2, 0xa2, 0xfe, 0xf8, 0xfe, 0xf8, 0xa2, 0xa2, 0x31, 0x30, 0x64, 0xa8, 0x06, 0x14, 0xa6, 0x01, 0xfc, 0xc0, 0xcb, 0x74, 0x73, 0x73, 0x74, 0xcb, 0xcb, 0x74, 0x73, 0x73, 0x74, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x17, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x23, 0x21, 0x11, 0x21, 0x32, 0x37, 0x36, 0x01, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x23, 0x01, 0x03, 0xae, 0x47, 0x46, 0x93, 0xfe, 0xdd, 0x01, 0x23, 0x93, 0x46, 0x47, 0xfd, 0xbd, 0x01, 0x2c, 0xe2, 0xf5, 0xf5, 0xe2, 0xfe, 0x1e, 0xb5, 0x01, 0x19, 0x01, 0xb7, 0x8b, 0x44, 0x43, 0xfd, 0xdd, 0x44, 0x43, 0x04, 0xa8, 0xfd, 0x9a, 0xda, 0xde, 0xdd, 0xda, 0x04, 0x44, 0x01, 0x91, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff, 0xe3, 0x04, 0x2e, 0x06, 0x15, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x15, 0x23, 0x11, 0x23, 0x01, 0x33, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x01, 0x4e, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x34, 0xa7, 0xa7, 0x01, 0x05, 0x49, 0x02, 0x33, 0x96, 0x83, 0x84, 0x96, 0x96, 0x84, 0x83, 0x96, 0x03, 0xb6, 0x64, 0x61, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xf8, 0xfe, 0xbc, 0x61, 0x64, 0xa8, 0x04, 0x44, 0x01, 0xd1, 0xfc, 0x1a, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x00, 0x19, 0x00, 0x00, 0x13, 0x3e, 0x01, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x06, 0x07, 0x68, 0x5d, 0xd5, 0x79, 0x01, 0x31, 0x01, 0x5f, 0xfe, 0xa1, 0xfe, 0xcf, 0x77, 0xd5, 0x5f, 0x5b, 0xd0, 0x75, 0xe7, 0xf4, 0xf4, 0xe7, 0x75, 0xd0, 0x5b, 0x05, 0x62, 0x47, 0x47, 0xfe, 0x61, 0xfe, 0x98, 0xfe, 0x99, 0xfe, 0x61, 0x48, 0x48, 0xd3, 0x5f, 0x5e, 0x01, 0x39, 0x01, 0x27, 0x01, 0x28, 0x01, 0x39, 0x5e, 0x5f, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x05, 0xb8, 0x07, 0x64, 0x00, 0x24, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x04, 0xa3, 0x5c, 0xd0, 0x75, 0xe6, 0xf5, 0xf5, 0xe6, 0x75, 0xd0, 0x5c, 0x5f, 0xd6, 0x76, 0xfe, 0xce, 0xfe, 0xa2, 0x01, 0x5e, 0x01, 0x32, 0x56, 0x8c, 0x0c, 0x0b, 0x0e, 0x4b, 0x5c, 0xcc, 0x45, 0x38, 0x79, 0x63, 0x05, 0x62, 0xd5, 0x5f, 0x5e, 0xfe, 0xc7, 0xfe, 0xd8, 0xfe, 0xd9, 0xfe, 0xc7, 0x5e, 0x5f, 0xd3, 0x48, 0x48, 0x01, 0x9f, 0x01, 0x67, 0x01, 0x68, 0x01, 0x9f, 0x24, 0x03, 0x04, 0xc3, 0x62, 0x7a, 0xaa, 0x96, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x52, 0x06, 0x14, 0x00, 0x22, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x17, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x03, 0x83, 0x46, 0x8d, 0x48, 0xa2, 0xb2, 0xb2, 0xa2, 0x48, 0x8d, 0x46, 0x45, 0x95, 0x53, 0xe4, 0xfe, 0xf4, 0x01, 0x0f, 0xeb, 0x40, 0x3f, 0x91, 0xa3, 0x3e, 0x2b, 0x5e, 0x45, 0x04, 0x7e, 0xf5, 0x2b, 0x2b, 0xe3, 0xcd, 0xcd, 0xe3, 0x2b, 0x2b, 0xaa, 0x24, 0x24, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x12, 0x01, 0x3a, 0x0c, 0x0f, 0xd6, 0xc0, 0x9c, 0x61, 0x00, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x00, 0x05, 0x28, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x92, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa1, 0x00, 0x00, 0x05, 0x79, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x11, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x25, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x11, 0x22, 0x06, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x36, 0x01, 0xc5, 0xdb, 0x01, 0x16, 0x01, 0x03, 0xfe, 0xfd, 0xfe, 0xea, 0xfe, 0x6f, 0x01, 0x75, 0x01, 0x87, 0x01, 0x6d, 0xfe, 0x91, 0xfe, 0x7b, 0xfe, 0x8b, 0x77, 0x6a, 0x8c, 0xac, 0x05, 0x2f, 0xfb, 0x77, 0x01, 0x18, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x17, 0xa6, 0xfe, 0x97, 0xfe, 0x80, 0xfe, 0x7e, 0xfe, 0x96, 0x05, 0x30, 0x5f, 0x69, 0x31, 0x46, 0xb5, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x01, 0x10, 0x29, 0x01, 0x11, 0x21, 0x22, 0x06, 0x11, 0x21, 0x11, 0x21, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x21, 0x11, 0x21, 0x01, 0x75, 0x01, 0x20, 0x01, 0x23, 0xfe, 0xdd, 0x93, 0x8d, 0x02, 0xf9, 0xfe, 0x1e, 0xe2, 0xf5, 0xf5, 0xe2, 0x01, 0x2c, 0xfd, 0xbd, 0x01, 0xb7, 0xfe, 0xef, 0x02, 0x23, 0x87, 0x03, 0x93, 0xfa, 0x2b, 0xda, 0xde, 0xdd, 0xda, 0x01, 0xc0, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xeb, 0x06, 0x14, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x00, 0x13, 0x35, 0x21, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x11, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0xf2, 0x02, 0xf9, 0xa6, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0xfd, 0xcc, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0x05, 0x6e, 0xa6, 0xf9, 0xec, 0xa8, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0x64, 0x01, 0xb9, 0xfc, 0xc0, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x02, 0x04, 0x63, 0x00, 0x19, 0x00, 0x27, 0x00, 0x00, 0x25, 0x16, 0x15, 0x10, 0x21, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x11, 0x10, 0x12, 0x33, 0x32, 0x12, 0x03, 0x14, 0x02, 0x03, 0x36, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x3e, 0x01, 0x03, 0x14, 0x8d, 0xfe, 0x73, 0xc7, 0x6c, 0x5c, 0xdd, 0xde, 0xee, 0xbb, 0x69, 0x80, 0xf6, 0xd8, 0xd7, 0xf8, 0x01, 0x8c, 0x23, 0x01, 0x9a, 0x85, 0x85, 0x9b, 0xa9, 0x72, 0x39, 0x2e, 0x59, 0x63, 0x42, 0x4f, 0x8d, 0xfe, 0xf0, 0x46, 0x99, 0x46, 0x75, 0x5c, 0x30, 0x25, 0x70, 0x87, 0x01, 0x0f, 0x01, 0x0f, 0x01, 0x39, 0xfe, 0xc7, 0xfe, 0xed, 0x9c, 0xfe, 0xfc, 0x01, 0xa0, 0xcb, 0xe5, 0xe8, 0xc3, 0xc2, 0xc7, 0x0b, 0x06, 0x0e, 0x2a, 0xdc, 0x00, 0x01, 0x00, 0x75, 0x00, 0x00, 0x03, 0xd8, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x03, 0xd8, 0xfc, 0x9e, 0x02, 0xac, 0xfd, 0x80, 0x02, 0x80, 0xfd, 0x64, 0x05, 0xd5, 0xfa, 0x2b, 0xaa, 0x02, 0x1d, 0xaa, 0x01, 0xba, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x13, 0x00, 0x1a, 0x00, 0x00, 0x13, 0x21, 0x10, 0x02, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x37, 0x16, 0x12, 0x33, 0x32, 0x12, 0x37, 0x69, 0x04, 0x1b, 0xf8, 0xf6, 0x7e, 0xe2, 0x65, 0x64, 0xec, 0x84, 0x01, 0x3b, 0x01, 0x63, 0xfe, 0xae, 0xfe, 0xe5, 0xfe, 0xd8, 0xfe, 0xbb, 0xc6, 0x0c, 0xe5, 0xb6, 0xb6, 0xe6, 0x0b, 0x03, 0x0c, 0x01, 0x0c, 0x01, 0x32, 0x60, 0x5f, 0xd7, 0x46, 0x48, 0xfe, 0x67, 0xfe, 0x92, 0xfe, 0x9f, 0xfe, 0x5b, 0x01, 0xb7, 0xcc, 0xc3, 0xfe, 0xe4, 0x01, 0x1c, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x93, 0xff, 0xe3, 0x04, 0x09, 0x05, 0xf0, 0x00, 0x28, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x24, 0x35, 0x34, 0x36, 0x01, 0xa9, 0x76, 0x80, 0xf1, 0xcf, 0x50, 0xb5, 0x68, 0x67, 0xab, 0x4a, 0x89, 0x93, 0x8e, 0x86, 0xa4, 0x9c, 0x95, 0xa7, 0xb4, 0xab, 0x62, 0xb4, 0x4b, 0x5f, 0xb3, 0x55, 0xfc, 0xfe, 0xef, 0x92, 0x03, 0x25, 0x21, 0xab, 0x7c, 0xb2, 0xd1, 0x20, 0x20, 0xb4, 0x26, 0x24, 0x7b, 0x73, 0x70, 0x77, 0xa6, 0x95, 0x84, 0x8f, 0x96, 0x32, 0x31, 0xc3, 0x25, 0x25, 0xf2, 0xdd, 0x90, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xa0, 0xfe, 0x66, 0x03, 0xba, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0xb5, 0x03, 0x04, 0xfd, 0xb2, 0x02, 0x15, 0xfd, 0xeb, 0xb9, 0xcc, 0x45, 0x38, 0x79, 0x63, 0x05, 0xd5, 0xaa, 0xfe, 0x48, 0xaa, 0xfd, 0x9f, 0xfe, 0xf2, 0xf4, 0xaa, 0x96, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x8b, 0xfe, 0x56, 0x02, 0xac, 0x06, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x33, 0x02, 0xac, 0x9e, 0x5a, 0x45, 0x01, 0x11, 0xfe, 0xef, 0x9c, 0xab, 0x9c, 0x9e, 0x59, 0x46, 0x9f, 0x9f, 0x9c, 0xaa, 0x06, 0x14, 0x99, 0x50, 0x68, 0x63, 0x8f, 0xfb, 0xeb, 0xbb, 0xab, 0x99, 0x50, 0x68, 0x04, 0x2a, 0x8f, 0x4e, 0xbb, 0xab, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x05, 0xef, 0x07, 0x64, 0x00, 0x26, 0x00, 0x00, 0x25, 0x11, 0x21, 0x35, 0x21, 0x11, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x17, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x36, 0x04, 0x49, 0xfe, 0xd7, 0x01, 0xdd, 0x69, 0xfe, 0x90, 0xfe, 0xc5, 0xfe, 0x9d, 0x01, 0x63, 0x01, 0x3b, 0x51, 0x93, 0x3e, 0xb5, 0xcc, 0x45, 0x38, 0x79, 0x63, 0x65, 0xe3, 0x7d, 0xf6, 0xf8, 0xf8, 0xf6, 0x61, 0x97, 0xd5, 0x01, 0x91, 0xa6, 0xfd, 0x7f, 0x53, 0x55, 0x01, 0x99, 0x01, 0x6d, 0x01, 0x6e, 0x01, 0x99, 0x19, 0x19, 0xbc, 0xea, 0xaa, 0x96, 0xc2, 0xd7, 0x5f, 0x60, 0xfe, 0xce, 0xfe, 0xd1, 0xfe, 0xd2, 0xfe, 0xce, 0x25, 0x00, 0x00, 0x02, 0x00, 0x07, 0xfe, 0x52, 0x04, 0xeb, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x25, 0x00, 0x00, 0x01, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x13, 0x01, 0x33, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x33, 0x02, 0x79, 0x31, 0x27, 0x19, 0x1c, 0x2e, 0x27, 0x28, 0x2e, 0x1c, 0x19, 0x28, 0x31, 0x01, 0xa9, 0xc8, 0xfd, 0xf5, 0x5d, 0x3c, 0x2a, 0x44, 0x5a, 0x8b, 0x8b, 0x5b, 0x43, 0x29, 0x3d, 0x5d, 0xfd, 0xf4, 0xc8, 0xfe, 0xfd, 0x20, 0x14, 0x42, 0x39, 0x49, 0x79, 0x5c, 0x5c, 0x79, 0x49, 0x39, 0x42, 0x14, 0x20, 0x03, 0x7a, 0x03, 0x5e, 0xfb, 0xcf, 0xc8, 0xae, 0x77, 0x42, 0x8b, 0x41, 0x57, 0x57, 0x41, 0x8b, 0x42, 0x77, 0xae, 0xc8, 0x04, 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x06, 0x8d, 0x06, 0x14, 0x00, 0x2a, 0x00, 0x00, 0x25, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x11, 0x14, 0x00, 0x2b, 0x01, 0x22, 0x26, 0x35, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x14, 0x16, 0x33, 0x04, 0xc4, 0x86, 0x4c, 0x4e, 0x42, 0x38, 0x6d, 0xca, 0x62, 0x64, 0xfe, 0xfd, 0xc7, 0x3f, 0xa9, 0x8d, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0xa1, 0x6a, 0xad, 0xb3, 0x44, 0x5e, 0x9c, 0x62, 0x65, 0x9b, 0xde, 0x70, 0x5f, 0x21, 0x94, 0x1d, 0x8f, 0x91, 0xfe, 0xec, 0xf5, 0xfe, 0xe6, 0xc8, 0xce, 0x01, 0x08, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x06, 0x14, 0xfd, 0x9e, 0x65, 0x64, 0xef, 0xe8, 0xfe, 0xf2, 0x93, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x02, 0x7f, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x11, 0xb5, 0xb6, 0x63, 0x78, 0x39, 0x45, 0xcd, 0xb8, 0x05, 0xd5, 0xfc, 0x2d, 0xc2, 0x96, 0xaa, 0xf4, 0x01, 0x0e, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x02, 0x17, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0xb5, 0xb6, 0xac, 0xac, 0xb6, 0xac, 0xac, 0x05, 0xd5, 0xfd, 0x16, 0xaa, 0xfd, 0xbf, 0x02, 0x41, 0xaa, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x5f, 0x05, 0xf0, 0x00, 0x17, 0x00, 0x00, 0x01, 0x23, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x05, 0x5e, 0x99, 0x41, 0x23, 0x3f, 0x21, 0xfe, 0x14, 0x02, 0xca, 0xef, 0xfd, 0x7b, 0xb6, 0xb6, 0x02, 0x2e, 0x4c, 0x66, 0x7a, 0x4d, 0x4c, 0x04, 0x48, 0x79, 0x36, 0x50, 0x23, 0xfd, 0xf9, 0xfc, 0xe3, 0x02, 0xcf, 0xfd, 0x31, 0x05, 0xd5, 0xfd, 0x89, 0x02, 0x43, 0x4f, 0x5c, 0x5b, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa6, 0x00, 0x00, 0x04, 0x26, 0x06, 0x14, 0x00, 0x12, 0x00, 0x00, 0x13, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0xa6, 0x93, 0xa3, 0xac, 0x97, 0x5f, 0x44, 0x01, 0xee, 0xd4, 0xfd, 0xe9, 0x02, 0x2d, 0xd8, 0xfe, 0x00, 0xa7, 0x04, 0x7e, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0xfd, 0xff, 0x01, 0xe3, 0xfd, 0xf4, 0xfd, 0xac, 0x02, 0x23, 0xfd, 0xdd, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0xf3, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0xae, 0xa5, 0xa0, 0xa0, 0xa5, 0xa5, 0xa5, 0x06, 0x14, 0xfd, 0x38, 0x90, 0xfd, 0x44, 0x02, 0xbc, 0x90, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x06, 0x14, 0x00, 0x0f, 0x00, 0x00, 0x33, 0x01, 0x27, 0x05, 0x27, 0x25, 0x27, 0x33, 0x17, 0x25, 0x17, 0x05, 0x01, 0x23, 0x09, 0x01, 0x37, 0x01, 0xba, 0x40, 0xfe, 0xf2, 0x1e, 0x01, 0x0b, 0x43, 0xb4, 0x2f, 0x01, 0x1a, 0x1e, 0xfe, 0xe8, 0x01, 0xbc, 0xb0, 0xfe, 0xe6, 0xfe, 0xa4, 0x04, 0x32, 0xbc, 0x65, 0x63, 0x63, 0xc5, 0x8a, 0x68, 0x61, 0x68, 0xfa, 0xd7, 0x03, 0x3c, 0xfc, 0xc4, 0x00, 0x00, 0x01, 0x00, 0xa0, 0xff, 0xe3, 0x06, 0x70, 0x05, 0xd5, 0x00, 0x27, 0x00, 0x00, 0x25, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x03, 0x49, 0x3f, 0xac, 0x75, 0x9e, 0x55, 0x56, 0xb7, 0x23, 0x33, 0x6a, 0x80, 0x96, 0xb6, 0x34, 0x33, 0x6b, 0x6f, 0x4a, 0x4b, 0xb7, 0xb7, 0x39, 0x9e, 0x6d, 0x6e, 0x4d, 0x4c, 0xd5, 0x7c, 0x76, 0x7b, 0x7a, 0xe2, 0x04, 0x1b, 0xfb, 0xef, 0xba, 0x35, 0x4e, 0xbe, 0xa4, 0x03, 0xec, 0xfb, 0xef, 0xa2, 0x4e, 0x4d, 0x5f, 0x60, 0xa3, 0x03, 0xec, 0xfa, 0x29, 0xae, 0x67, 0x62, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xa0, 0xfe, 0x66, 0x04, 0xae, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x13, 0x33, 0x01, 0x11, 0x33, 0x11, 0x23, 0x01, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0xb5, 0xf5, 0x02, 0x54, 0xb0, 0xf5, 0xfd, 0xac, 0xb8, 0xcc, 0x40, 0x38, 0x79, 0x63, 0x05, 0xd5, 0xfb, 0x1f, 0x04, 0xe1, 0xfa, 0x2b, 0x04, 0xe1, 0xfb, 0x87, 0xfe, 0xf2, 0xf4, 0xaa, 0x96, 0xc2, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x04, 0x7b, 0x10, 0x06, 0x03, 0x4b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x12, 0x00, 0x19, 0x00, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x22, 0x02, 0x07, 0x21, 0x26, 0x02, 0x01, 0x1a, 0x01, 0x33, 0x32, 0x12, 0x13, 0x68, 0x01, 0x53, 0x01, 0x1b, 0x01, 0x1b, 0x01, 0x52, 0xfe, 0xae, 0xfe, 0xe5, 0xfe, 0xe5, 0xfe, 0xad, 0x02, 0x6f, 0xb6, 0xe6, 0x0b, 0x03, 0x4e, 0x0c, 0xe5, 0xfd, 0x9a, 0x07, 0xe2, 0xc6, 0xc6, 0xe0, 0x07, 0x02, 0xe9, 0x01, 0x62, 0x01, 0xa5, 0xfe, 0x5b, 0xfe, 0x9f, 0xfe, 0x9e, 0xfe, 0x5b, 0x01, 0xa4, 0x03, 0xc5, 0xfe, 0xe4, 0xc3, 0xc3, 0x01, 0x1c, 0xfd, 0x7a, 0xfe, 0xff, 0xfe, 0xc2, 0x01, 0x3d, 0x01, 0x02, 0xff, 0xff, 0x00, 0x5c, 0xff, 0xe3, 0x05, 0x81, 0x06, 0x14, 0x10, 0x26, 0x00, 0x32, 0xf5, 0x00, 0x10, 0x07, 0x02, 0xcc, 0x05, 0x11, 0x01, 0x34, 0xff, 0xff, 0x00, 0x6a, 0xff, 0xe3, 0x04, 0x58, 0x04, 0xeb, 0x10, 0x27, 0x02, 0xcc, 0x03, 0xe9, 0x00, 0x0b, 0x10, 0x06, 0x00, 0x52, 0x04, 0x00, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x06, 0x21, 0x05, 0xf0, 0x00, 0x14, 0x00, 0x1f, 0x00, 0x00, 0x21, 0x11, 0x34, 0x26, 0x23, 0x11, 0x06, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x17, 0x21, 0x32, 0x16, 0x19, 0x01, 0x01, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x37, 0x11, 0x26, 0x05, 0x6b, 0x63, 0x6e, 0xa9, 0xfe, 0xe4, 0xfe, 0xe6, 0xfe, 0xad, 0x01, 0x53, 0x01, 0x1b, 0x65, 0x57, 0x01, 0x0a, 0xcc, 0xb9, 0xfc, 0xb5, 0xc6, 0xe9, 0xe9, 0xc6, 0x9e, 0x73, 0x7c, 0x03, 0xd3, 0xc2, 0x96, 0xfb, 0x8b, 0xd3, 0x01, 0xa4, 0x01, 0x62, 0x01, 0x62, 0x01, 0xa5, 0x1b, 0xf4, 0xfe, 0xf2, 0xfc, 0x2d, 0x05, 0x4c, 0xfe, 0xb8, 0xfe, 0xe6, 0xfe, 0xe5, 0xfe, 0xb8, 0x67, 0x04, 0x18, 0x46, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x04, 0xd1, 0x04, 0x7b, 0x00, 0x16, 0x00, 0x21, 0x00, 0x00, 0x01, 0x11, 0x34, 0x27, 0x26, 0x23, 0x11, 0x06, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x17, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x11, 0x26, 0x04, 0x2a, 0x22, 0x22, 0x5e, 0x7c, 0xd8, 0xd9, 0xf5, 0xf5, 0xd9, 0x5a, 0x4a, 0xc2, 0xa3, 0x4a, 0x49, 0xfd, 0x64, 0x85, 0x9b, 0x9a, 0x86, 0x74, 0x3a, 0x4c, 0xfe, 0x56, 0x04, 0x74, 0x99, 0x31, 0x30, 0xfc, 0xbc, 0x9d, 0x01, 0x39, 0x01, 0x13, 0x01, 0x14, 0x01, 0x38, 0x1b, 0x60, 0x60, 0xd6, 0xfb, 0x8c, 0x05, 0x89, 0xe7, 0xc9, 0xc9, 0xe7, 0x3a, 0x02, 0xf0, 0x36, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa1, 0x00, 0x00, 0x04, 0x73, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x22, 0x06, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x36, 0x01, 0xc5, 0xe4, 0x7f, 0x8b, 0x8b, 0x7f, 0xfe, 0x66, 0x01, 0x9a, 0xe2, 0xe7, 0xe7, 0xe2, 0xe4, 0xb6, 0x77, 0x6a, 0x8c, 0xac, 0x05, 0x2f, 0xfd, 0xcf, 0x92, 0x87, 0x86, 0x92, 0xa6, 0xe3, 0xdb, 0xdd, 0xe2, 0xfd, 0xa8, 0x05, 0x30, 0x5f, 0x69, 0x31, 0x46, 0xb5, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa6, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x18, 0x00, 0x24, 0x00, 0x00, 0x25, 0x11, 0x23, 0x11, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x01, 0x4e, 0xa8, 0x93, 0xa3, 0xe5, 0xd0, 0x5f, 0x44, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x01, 0xff, 0x96, 0x83, 0x84, 0x96, 0x96, 0x84, 0x83, 0x96, 0xa8, 0xfd, 0xae, 0x06, 0x28, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0xc8, 0x64, 0x61, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xf8, 0xfe, 0xbc, 0x61, 0x01, 0xeb, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x02, 0x00, 0xb4, 0xfe, 0xf8, 0x04, 0xcc, 0x05, 0xd5, 0x00, 0x15, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x17, 0x13, 0x23, 0x03, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x11, 0x33, 0x32, 0x36, 0x10, 0x26, 0x23, 0x03, 0x32, 0x3b, 0x6e, 0x38, 0xb9, 0xc4, 0xac, 0x42, 0x7d, 0x6c, 0xc6, 0xb6, 0xb6, 0xe4, 0xe7, 0xe2, 0x75, 0xfd, 0xc8, 0xe4, 0x7f, 0x8b, 0x8a, 0x80, 0x01, 0xb4, 0x16, 0x90, 0x7e, 0xfe, 0x68, 0x01, 0x7f, 0x96, 0x62, 0xfe, 0x91, 0x05, 0xd5, 0xfe, 0xf8, 0xd6, 0xd8, 0x8d, 0xba, 0x02, 0x4f, 0xfd, 0xd1, 0x92, 0x01, 0x0c, 0x91, 0x00, 0x01, 0x00, 0x66, 0xff, 0xe3, 0x04, 0x19, 0x05, 0xf0, 0x00, 0x21, 0x00, 0x00, 0x13, 0x36, 0x20, 0x16, 0x10, 0x06, 0x0f, 0x01, 0x0e, 0x01, 0x14, 0x16, 0x33, 0x32, 0x37, 0x15, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x36, 0x3f, 0x01, 0x36, 0x37, 0x36, 0x34, 0x27, 0x26, 0x20, 0x07, 0xb8, 0xcd, 0x01, 0x98, 0xfb, 0xb5, 0xcc, 0x6e, 0x8b, 0x7a, 0xaa, 0x9b, 0xcb, 0xdf, 0xe9, 0xc1, 0xfd, 0x83, 0x82, 0xc1, 0xcc, 0x6d, 0x96, 0x36, 0x35, 0x50, 0x51, 0xfe, 0xc4, 0xcd, 0x05, 0xa4, 0x4c, 0xe4, 0xfe, 0x8f, 0xc0, 0x2d, 0x18, 0x1f, 0x7c, 0xec, 0x88, 0x8b, 0xd0, 0x5f, 0x70, 0x70, 0xd9, 0xb6, 0xd9, 0x2b, 0x19, 0x1f, 0x32, 0x33, 0xd9, 0x40, 0x40, 0x6d, 0x00, 0x01, 0x00, 0x5a, 0xff, 0xe3, 0x03, 0x5d, 0x04, 0x7b, 0x00, 0x27, 0x00, 0x00, 0x13, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x0f, 0x01, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3f, 0x01, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x90, 0x44, 0xa2, 0x5c, 0xba, 0xc9, 0x89, 0x9a, 0x39, 0x9a, 0x5b, 0x7e, 0x75, 0x57, 0xb3, 0x5b, 0x61, 0xaf, 0x51, 0xc3, 0xde, 0x94, 0xb1, 0x39, 0x85, 0x58, 0x7b, 0x7c, 0x51, 0x97, 0x46, 0x04, 0x3f, 0x1e, 0x1e, 0xac, 0x9e, 0x82, 0x95, 0x24, 0x0f, 0x25, 0x50, 0x4b, 0x51, 0x59, 0x35, 0x35, 0xbe, 0x23, 0x23, 0xb6, 0x9c, 0x89, 0x99, 0x2a, 0x0e, 0x21, 0x49, 0x40, 0x54, 0x54, 0x28, 0x28, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x05, 0xd5, 0x10, 0x06, 0x03, 0x37, 0x00, 0x00, 0x00, 0x02, 0xff, 0x0d, 0xfe, 0x56, 0x02, 0x8f, 0x06, 0x14, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x11, 0x23, 0x22, 0x35, 0x34, 0x21, 0x32, 0x17, 0x16, 0x17, 0x33, 0x15, 0x25, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x33, 0x01, 0x52, 0x45, 0x59, 0x9e, 0x9c, 0xaa, 0x9d, 0xab, 0xf3, 0x01, 0x11, 0xa3, 0x49, 0x30, 0x10, 0xac, 0xfe, 0xac, 0x08, 0x0e, 0x1e, 0x63, 0x70, 0x03, 0x02, 0x6b, 0x04, 0x6a, 0xfb, 0x3d, 0x68, 0x50, 0x99, 0xab, 0xbb, 0x04, 0xae, 0xd2, 0xd8, 0x60, 0x40, 0x6f, 0x9b, 0x9a, 0x2c, 0x18, 0x30, 0x41, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0xfe, 0x56, 0x02, 0xa7, 0x05, 0x9e, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x22, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x01, 0x52, 0x01, 0x55, 0xfe, 0xab, 0x43, 0x67, 0xab, 0x94, 0xa2, 0x3f, 0x2b, 0x60, 0x22, 0x22, 0xc0, 0x96, 0x79, 0x79, 0x05, 0x9e, 0xfe, 0xc2, 0x8f, 0xfd, 0xa0, 0x89, 0x4e, 0xae, 0xd6, 0xc0, 0x9c, 0x30, 0x31, 0x99, 0x14, 0x9f, 0xd2, 0x02, 0x60, 0x8f, 0x01, 0x3e, 0x00, 0x01, 0x00, 0x15, 0x00, 0x00, 0x04, 0x6c, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x36, 0x01, 0x83, 0x02, 0xe8, 0xfe, 0x23, 0xb6, 0x55, 0x77, 0x6a, 0x8c, 0xac, 0x05, 0xd5, 0xaa, 0xfa, 0xd5, 0x05, 0x2b, 0x5a, 0x69, 0x31, 0x46, 0xb5, 0xa3, 0x00, 0x00, 0x01, 0x00, 0x31, 0x00, 0x00, 0x02, 0xa7, 0x06, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x15, 0x21, 0x15, 0x21, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x01, 0x52, 0x01, 0x55, 0xfe, 0xab, 0x43, 0x67, 0xab, 0xab, 0xbf, 0x92, 0x79, 0x79, 0x9d, 0xaa, 0x9c, 0x9e, 0x59, 0x45, 0x04, 0xc3, 0x63, 0x8f, 0xfd, 0xa0, 0x89, 0x4e, 0x9a, 0x9f, 0xd2, 0x02, 0x60, 0x8f, 0x4e, 0xbb, 0xab, 0x99, 0x51, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0xfe, 0x66, 0x04, 0x6c, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x21, 0x15, 0x21, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x19, 0x01, 0x21, 0x05, 0x04, 0x70, 0xfe, 0x23, 0x63, 0x79, 0x39, 0x47, 0xcc, 0xb8, 0xfe, 0x23, 0x05, 0xd5, 0xaa, 0xfb, 0x3d, 0xc2, 0x96, 0xaa, 0xf4, 0x01, 0x0e, 0x04, 0xc3, 0xff, 0xff, 0x00, 0x9b, 0xff, 0xf7, 0x05, 0xbc, 0x06, 0x14, 0x10, 0x26, 0x00, 0x38, 0xfc, 0x14, 0x10, 0x07, 0x02, 0xcc, 0x05, 0x4d, 0x01, 0x34, 0xff, 0xff, 0x00, 0x9e, 0xff, 0xe3, 0x04, 0xdf, 0x04, 0xeb, 0x10, 0x27, 0x02, 0xcc, 0x04, 0x70, 0x00, 0x0b, 0x10, 0x06, 0x00, 0x58, 0x02, 0x00, 0x00, 0x01, 0x00, 0x46, 0xff, 0xe3, 0x05, 0x3b, 0x05, 0xca, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x21, 0x16, 0x12, 0x15, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x37, 0x21, 0x35, 0x21, 0x15, 0x06, 0x02, 0x15, 0x14, 0x12, 0x33, 0x32, 0x12, 0x35, 0x34, 0x02, 0x27, 0x35, 0x21, 0x05, 0x3a, 0xfe, 0xe0, 0x91, 0x80, 0xfe, 0xa6, 0xfe, 0xef, 0xfe, 0xed, 0xfe, 0xa8, 0x82, 0x8e, 0xfe, 0xe1, 0x02, 0x1c, 0xa0, 0xb3, 0xee, 0xc3, 0xc2, 0xee, 0xb2, 0xa0, 0x02, 0x1c, 0x05, 0x18, 0x8d, 0xfe, 0xd8, 0xc2, 0xfe, 0xcb, 0xfe, 0x77, 0x01, 0x8a, 0x01, 0x3e, 0xb8, 0x01, 0x2a, 0x8b, 0xb2, 0xb2, 0x61, 0xfe, 0xb4, 0xca, 0xef, 0xfe, 0xdd, 0x01, 0x22, 0xf0, 0xca, 0x01, 0x4c, 0x61, 0xb2, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xff, 0xe1, 0x04, 0xeb, 0x05, 0xd5, 0x00, 0x1b, 0x00, 0x00, 0x25, 0x32, 0x12, 0x35, 0x34, 0x27, 0x26, 0x27, 0x35, 0x17, 0x16, 0x12, 0x15, 0x10, 0x07, 0x06, 0x21, 0x27, 0x26, 0x27, 0x26, 0x19, 0x01, 0x33, 0x11, 0x14, 0x16, 0x33, 0x02, 0x7f, 0xc2, 0xee, 0x59, 0x3b, 0x63, 0xa2, 0x90, 0x80, 0xad, 0xac, 0xfe, 0xee, 0x45, 0xd1, 0x57, 0x5d, 0xb6, 0x63, 0x78, 0x8d, 0x01, 0x22, 0xf0, 0xca, 0xa6, 0x6d, 0x57, 0x44, 0x01, 0x8d, 0xfe, 0xd8, 0xc2, 0xfe, 0xcb, 0xc5, 0xc4, 0x02, 0x06, 0x74, 0x7a, 0x01, 0x0e, 0x03, 0xf0, 0xfc, 0x10, 0xc2, 0x96, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x05, 0x58, 0x05, 0xf0, 0x00, 0x17, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x07, 0x01, 0x11, 0x23, 0x11, 0x01, 0x33, 0x09, 0x01, 0x36, 0x33, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x26, 0x04, 0x5b, 0x33, 0x13, 0x22, 0x0f, 0xfe, 0xaa, 0xb6, 0xfe, 0x24, 0xc4, 0x01, 0x74, 0x01, 0x2d, 0x51, 0x93, 0x7a, 0x4d, 0x4c, 0x99, 0x42, 0x05, 0x47, 0x0e, 0x18, 0x19, 0xfd, 0xbf, 0xfd, 0x39, 0x02, 0xc7, 0x03, 0x0e, 0xfd, 0x9a, 0x01, 0xf9, 0x88, 0x5c, 0x5b, 0x6e, 0x83, 0x79, 0x36, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0xfe, 0x56, 0x05, 0x43, 0x04, 0x7b, 0x00, 0x1f, 0x00, 0x00, 0x05, 0x0e, 0x01, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x3f, 0x01, 0x01, 0x33, 0x01, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x02, 0x51, 0x46, 0x85, 0x70, 0x84, 0x61, 0x44, 0x4c, 0x2e, 0x1e, 0xfe, 0x68, 0xaf, 0x01, 0x3b, 0xfe, 0x13, 0x2b, 0x4f, 0x7a, 0x76, 0xa6, 0xa0, 0x49, 0x33, 0x33, 0x25, 0x12, 0x09, 0x68, 0xc8, 0x7a, 0x9a, 0x48, 0x86, 0x54, 0x04, 0x4e, 0xfc, 0x94, 0x02, 0xc0, 0x34, 0x33, 0x60, 0xbf, 0x86, 0x72, 0x72, 0x3a, 0x54, 0x2a, 0x14, 0x19, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x52, 0x00, 0x00, 0x04, 0x9c, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x33, 0x15, 0x21, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x01, 0x21, 0x68, 0x04, 0x1f, 0xfe, 0x98, 0xfd, 0xfe, 0x9b, 0xfe, 0x7f, 0x03, 0x66, 0xfb, 0xb7, 0x01, 0x8d, 0xfe, 0xf3, 0x01, 0x75, 0x01, 0x5c, 0xfc, 0xc4, 0x05, 0xd5, 0x9a, 0xfe, 0x11, 0x90, 0xfd, 0xee, 0xaa, 0x9a, 0x02, 0x22, 0x90, 0x01, 0xdf, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x79, 0x04, 0x60, 0x00, 0x11, 0x00, 0x00, 0x13, 0x21, 0x15, 0x03, 0x33, 0x15, 0x21, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x23, 0x35, 0x21, 0x13, 0x21, 0x66, 0x03, 0x12, 0xe2, 0xaf, 0xfe, 0xe2, 0xfe, 0xe3, 0x02, 0x6e, 0xfc, 0xd7, 0x01, 0x0d, 0xbe, 0x01, 0x2e, 0xf2, 0xfd, 0xa8, 0x04, 0x60, 0xa8, 0xfe, 0xdc, 0x90, 0xfe, 0x8f, 0x93, 0xa8, 0x01, 0x5c, 0x90, 0x01, 0x39, 0x00, 0x01, 0x00, 0x90, 0xff, 0xc1, 0x04, 0x79, 0x05, 0xd5, 0x00, 0x22, 0x00, 0x00, 0x25, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x02, 0x64, 0xad, 0x59, 0x5a, 0x53, 0x54, 0x94, 0x9d, 0x01, 0x5b, 0xfd, 0x49, 0x03, 0x9a, 0xfe, 0x8e, 0x5f, 0x73, 0x58, 0x4e, 0x49, 0x89, 0x89, 0xfc, 0x6b, 0x70, 0x72, 0x78, 0x5f, 0x72, 0x72, 0x6b, 0x4b, 0x4b, 0x8f, 0x86, 0x49, 0x4a, 0x98, 0x01, 0xea, 0xaa, 0x9a, 0xfe, 0x16, 0x38, 0x2a, 0x6d, 0x68, 0x8a, 0xdc, 0x7a, 0x79, 0x13, 0x12, 0x25, 0xc3, 0x31, 0x19, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x52, 0xff, 0xc1, 0x04, 0x3c, 0x05, 0xd5, 0x00, 0x22, 0x00, 0x00, 0x25, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x01, 0x35, 0x21, 0x15, 0x21, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x02, 0x68, 0x7b, 0x71, 0x73, 0x5f, 0x79, 0x71, 0x70, 0x6c, 0xfc, 0x88, 0x89, 0x49, 0x4d, 0x58, 0x73, 0x60, 0xfe, 0x8e, 0x03, 0x9a, 0xfd, 0x49, 0x01, 0x5a, 0x9c, 0x95, 0x54, 0x52, 0x5a, 0x59, 0x6b, 0x19, 0x19, 0x31, 0xc3, 0x25, 0x12, 0x13, 0x79, 0x7a, 0xdc, 0x8a, 0x68, 0x6d, 0x2a, 0x38, 0x01, 0xea, 0x9a, 0xaa, 0xfe, 0x16, 0x98, 0x4a, 0x49, 0x86, 0x8f, 0x4b, 0x4b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5d, 0xfe, 0x4c, 0x03, 0xd3, 0x04, 0x60, 0x00, 0x20, 0x00, 0x00, 0x09, 0x01, 0x35, 0x21, 0x15, 0x21, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x24, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x02, 0x1f, 0xfe, 0x8e, 0x03, 0x12, 0xfd, 0xa8, 0x01, 0x83, 0x9c, 0x95, 0x54, 0x53, 0x5a, 0x5a, 0xab, 0x62, 0xb4, 0x4b, 0x5f, 0x5a, 0x59, 0x55, 0xfc, 0xfe, 0xef, 0x48, 0x4e, 0x58, 0x73, 0x01, 0xdc, 0x01, 0xdc, 0xa8, 0x93, 0xfe, 0x0d, 0xa6, 0x4a, 0x4b, 0x84, 0x8f, 0x4b, 0x4b, 0x32, 0x31, 0xc3, 0x25, 0x13, 0x12, 0xf2, 0xdd, 0x8a, 0x68, 0x6d, 0x2a, 0x38, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xfe, 0x56, 0x03, 0x84, 0x04, 0x60, 0x00, 0x20, 0x00, 0x00, 0x01, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x20, 0x11, 0x34, 0x25, 0x24, 0x35, 0x34, 0x23, 0x30, 0x21, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x20, 0x15, 0x10, 0x05, 0x06, 0x15, 0x14, 0x02, 0x3f, 0x4c, 0x45, 0x47, 0x49, 0x4e, 0x48, 0x4e, 0x57, 0xfe, 0x50, 0x01, 0x6d, 0x01, 0x00, 0xd4, 0xfe, 0xfc, 0x01, 0xb4, 0xfd, 0xa8, 0x03, 0x12, 0xfe, 0xc2, 0x01, 0x4a, 0xfe, 0x5e, 0xcb, 0xfe, 0xee, 0x15, 0x15, 0x2c, 0xb3, 0x20, 0x0d, 0x0e, 0x01, 0x19, 0xee, 0x35, 0x25, 0x62, 0x7c, 0x02, 0x38, 0x93, 0xa8, 0xfe, 0x64, 0xe5, 0xfe, 0xec, 0x31, 0x18, 0x61, 0x8b, 0x00, 0x01, 0x00, 0x87, 0x00, 0x00, 0x03, 0xdd, 0x05, 0xf0, 0x00, 0x24, 0x00, 0x00, 0x25, 0x21, 0x15, 0x21, 0x35, 0x01, 0x37, 0x21, 0x35, 0x21, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x33, 0x15, 0x23, 0x07, 0x01, 0x62, 0x02, 0x7a, 0xfc, 0xab, 0x01, 0x1b, 0x67, 0xfe, 0xca, 0x01, 0xb1, 0x56, 0x21, 0x23, 0x4a, 0x4c, 0x79, 0x55, 0x5f, 0x5f, 0x6c, 0x6e, 0xbf, 0x4f, 0xd1, 0xf8, 0x1f, 0x1c, 0x42, 0x5e, 0xd5, 0x2b, 0xaa, 0xaa, 0xaa, 0x01, 0x40, 0x75, 0x90, 0x6d, 0x48, 0x4c, 0x49, 0x77, 0x4b, 0x4b, 0x21, 0x21, 0x43, 0xcc, 0x31, 0x32, 0xe8, 0xc2, 0x5c, 0x52, 0x49, 0x60, 0x90, 0x31, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x53, 0xff, 0xc1, 0x04, 0x7a, 0x05, 0xd5, 0x00, 0x19, 0x00, 0x00, 0x01, 0x10, 0x20, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x25, 0x36, 0x17, 0x16, 0x10, 0x0f, 0x01, 0x06, 0x07, 0x06, 0x20, 0x24, 0x35, 0x01, 0x09, 0x02, 0xbc, 0xa7, 0x94, 0xfe, 0x2b, 0x03, 0x44, 0xfd, 0x72, 0x01, 0x4e, 0xe6, 0x92, 0x49, 0x35, 0x1a, 0x11, 0x29, 0x89, 0xfd, 0xfd, 0xfe, 0xef, 0x01, 0x90, 0xfe, 0xdb, 0x01, 0x25, 0x86, 0x93, 0x03, 0x2c, 0xaa, 0xfe, 0x25, 0x01, 0x01, 0xd0, 0x68, 0xfe, 0xe0, 0x56, 0x29, 0x1d, 0x24, 0x79, 0xf2, 0xdd, 0x00, 0x01, 0x00, 0x5d, 0xfe, 0x4c, 0x03, 0xd3, 0x04, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x17, 0x16, 0x33, 0x20, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x32, 0x1e, 0x01, 0x10, 0x0f, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x5e, 0x98, 0xba, 0x01, 0x6d, 0xa6, 0x95, 0xfe, 0xc3, 0x02, 0xc9, 0xfd, 0xdc, 0xc7, 0x5f, 0xcd, 0x95, 0x35, 0x19, 0x12, 0x28, 0x89, 0xfc, 0xa9, 0xbe, 0xa7, 0x63, 0x01, 0x25, 0x86, 0x93, 0x03, 0x2c, 0xaa, 0xfe, 0x26, 0x63, 0xd4, 0xfe, 0xe0, 0x56, 0x29, 0x1d, 0x24, 0x79, 0x4a, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xe3, 0x03, 0x48, 0x05, 0x9e, 0x00, 0x24, 0x00, 0x00, 0x01, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x13, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0x01, 0xea, 0x01, 0x99, 0x64, 0x62, 0x63, 0x7c, 0xf7, 0x4d, 0x49, 0x48, 0x45, 0x42, 0x4b, 0x47, 0x48, 0xa1, 0x59, 0x33, 0x01, 0x34, 0x4d, 0xad, 0x38, 0x02, 0xce, 0xce, 0xb5, 0xd0, 0x03, 0xe6, 0x7d, 0x1e, 0x77, 0x73, 0xaa, 0xba, 0x7d, 0x9d, 0x12, 0x11, 0x23, 0xac, 0x28, 0x18, 0x16, 0x72, 0x41, 0x85, 0x62, 0x4c, 0x72, 0x01, 0x0f, 0xa4, 0x01, 0x14, 0xfe, 0xec, 0xa4, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x00, 0x0e, 0x00, 0x17, 0x00, 0x00, 0x05, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x10, 0x01, 0x00, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x01, 0x4e, 0xa7, 0xa7, 0x2f, 0x79, 0x49, 0xbd, 0xa6, 0x45, 0x46, 0xfd, 0x21, 0x02, 0x33, 0x33, 0x32, 0x6c, 0xc6, 0x9c, 0x7a, 0xfe, 0xd0, 0x06, 0x0a, 0xaa, 0x42, 0x52, 0x31, 0x70, 0x71, 0x99, 0xfe, 0x57, 0xfe, 0xe4, 0x01, 0x90, 0xf9, 0x85, 0x42, 0x41, 0xef, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x01, 0x6b, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0xb5, 0xb6, 0xb6, 0x05, 0xd5, 0xf8, 0x81, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x56, 0x02, 0xd7, 0x05, 0xd5, 0x10, 0x27, 0x01, 0x82, 0x01, 0x6c, 0x00, 0x00, 0x10, 0x06, 0x01, 0x82, 0x00, 0x00, 0x00, 0x01, 0x00, 0x12, 0xfe, 0x56, 0x03, 0x40, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x01, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x01, 0x4e, 0xb6, 0x01, 0x3c, 0xfe, 0xc4, 0x01, 0x3c, 0xfe, 0xc4, 0xb6, 0xfe, 0xc4, 0x01, 0x3c, 0xfe, 0xc4, 0x01, 0x3c, 0x05, 0xd5, 0xfd, 0x97, 0xa8, 0xf0, 0xaa, 0xfd, 0x2c, 0x02, 0xd4, 0xaa, 0xf0, 0xa8, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x6c, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x04, 0x9f, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x09, 0xbc, 0x07, 0x6d, 0x10, 0x27, 0x01, 0x3f, 0x05, 0x1f, 0x00, 0x00, 0x10, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x08, 0xb8, 0x06, 0x66, 0x10, 0x27, 0x01, 0x40, 0x05, 0x40, 0x00, 0x00, 0x10, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x07, 0xb6, 0x06, 0x66, 0x10, 0x27, 0x01, 0x40, 0x04, 0x3d, 0x00, 0x00, 0x10, 0x06, 0x00, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x66, 0x05, 0x87, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x2d, 0x04, 0x1c, 0x00, 0x00, 0x10, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x56, 0x05, 0x48, 0x06, 0x14, 0x10, 0x27, 0x00, 0x4d, 0x03, 0xf4, 0x00, 0x00, 0x10, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0xfe, 0x56, 0x02, 0xa4, 0x06, 0x14, 0x10, 0x27, 0x00, 0x4d, 0x01, 0x51, 0x00, 0x00, 0x10, 0x06, 0x00, 0x4f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x66, 0x06, 0x41, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x2d, 0x04, 0xd6, 0x00, 0x00, 0x10, 0x06, 0x00, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x56, 0x06, 0x0c, 0x06, 0x14, 0x10, 0x27, 0x00, 0x4d, 0x04, 0xb8, 0x00, 0x00, 0x10, 0x06, 0x00, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x05, 0x48, 0x06, 0x14, 0x10, 0x27, 0x00, 0x4d, 0x03, 0xf4, 0x00, 0x00, 0x10, 0x06, 0x00, 0x51, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0x45, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x66, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x11, 0x06, 0x02, 0x89, 0x51, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x02, 0x24, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x02, 0xde, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe3, 0x00, 0x00, 0x02, 0x22, 0x06, 0x66, 0x12, 0x26, 0x00, 0xf3, 0x00, 0x00, 0x11, 0x07, 0x02, 0x89, 0xff, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf0, 0x04, 0xa3, 0x01, 0x75, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x11, 0x06, 0x02, 0x89, 0x6a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0x77, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x66, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x11, 0x06, 0x02, 0x89, 0x6a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x08, 0x33, 0x10, 0x26, 0x11, 0x1e, 0x2b, 0x00, 0x12, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x00, 0x6f, 0x01, 0x3b, 0x12, 0x06, 0x00, 0xbe, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x06, 0x11, 0x21, 0x31, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x07, 0x22, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x07, 0x11, 0x21, 0xff, 0xc5, 0xfe, 0xc8, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x06, 0x11, 0x26, 0x2b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x07, 0x22, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x07, 0x11, 0x26, 0xff, 0xca, 0xfe, 0xc8, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x08, 0x60, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x06, 0x11, 0x22, 0x2b, 0x06, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x07, 0x22, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x07, 0x11, 0x22, 0xff, 0xc5, 0xfe, 0xc8, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x04, 0x7b, 0x12, 0x06, 0x02, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x33, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x1e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x07, 0x31, 0x12, 0x26, 0x00, 0xa6, 0x00, 0x00, 0x10, 0x07, 0x00, 0x71, 0x00, 0x4a, 0x01, 0x3b, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x33, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0xf4, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x10, 0x07, 0x11, 0x20, 0xff, 0x9e, 0xfe, 0xc1, 0xff, 0xff, 0x00, 0x07, 0x00, 0x00, 0x06, 0x8e, 0x07, 0x34, 0x10, 0x27, 0x00, 0x71, 0x02, 0x8e, 0x01, 0x3e, 0x12, 0x06, 0x00, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x06, 0xb1, 0x05, 0xf2, 0x10, 0x27, 0x00, 0x71, 0x01, 0xb7, 0xff, 0xfc, 0x12, 0x06, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x6a, 0x05, 0xf0, 0x00, 0x25, 0x00, 0x00, 0x01, 0x11, 0x33, 0x15, 0x23, 0x15, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x36, 0x37, 0x35, 0x23, 0x35, 0x33, 0x35, 0x21, 0x35, 0x04, 0xfd, 0x6d, 0x6d, 0x69, 0xfe, 0x90, 0xfe, 0xc5, 0xfe, 0x9d, 0x01, 0x63, 0x01, 0x3b, 0x83, 0xed, 0x64, 0x65, 0xe3, 0x7d, 0xf6, 0xf8, 0xf8, 0xf6, 0x61, 0x97, 0x3c, 0xe4, 0xe4, 0xfe, 0xd7, 0x03, 0x0c, 0xfe, 0xd6, 0x58, 0xff, 0x53, 0x55, 0x01, 0x99, 0x01, 0x6d, 0x01, 0x6e, 0x01, 0x99, 0x48, 0x46, 0xd7, 0x5f, 0x60, 0xfe, 0xce, 0xfe, 0xd1, 0xfe, 0xd2, 0xfe, 0xce, 0x25, 0x27, 0xb5, 0x58, 0x84, 0xa6, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x7b, 0x04, 0x7b, 0x00, 0x0b, 0x00, 0x34, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x17, 0x14, 0x07, 0x33, 0x15, 0x23, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x37, 0x21, 0x35, 0x21, 0x36, 0x3d, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x33, 0x03, 0x45, 0x95, 0x86, 0x85, 0x94, 0x94, 0x85, 0x86, 0x95, 0xa6, 0x11, 0xa1, 0xb3, 0x1c, 0x34, 0x72, 0xec, 0x57, 0x9b, 0x49, 0x49, 0x8e, 0x4a, 0xa3, 0x51, 0x13, 0x0f, 0xfd, 0xc4, 0x02, 0x57, 0x14, 0x33, 0xa0, 0x70, 0xba, 0xe2, 0xe2, 0xba, 0x70, 0xa0, 0x33, 0xa6, 0x02, 0x3d, 0xc8, 0xdc, 0xdc, 0xc8, 0xc7, 0xdc, 0xdc, 0xeb, 0x6e, 0x58, 0x46, 0x5d, 0x40, 0x8c, 0x1d, 0x1e, 0xb3, 0x2c, 0x2a, 0x5f, 0x17, 0x1c, 0x45, 0x47, 0x5e, 0x5b, 0x63, 0x62, 0x01, 0x3a, 0x01, 0x03, 0x01, 0x04, 0x01, 0x3a, 0x62, 0x63, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x2a, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x04, 0xc3, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x06, 0x63, 0x10, 0x26, 0x02, 0x89, 0x43, 0xfd, 0x12, 0x06, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xe0, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf0, 0x04, 0x2b, 0x01, 0x75, 0x12, 0x06, 0x00, 0x2e, 0x00, 0x00, 0xff, 0xff, 0xff, 0xeb, 0x00, 0x00, 0x04, 0x26, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x4e, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf0, 0x02, 0xcb, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0x75, 0x05, 0x44, 0x05, 0xf0, 0x10, 0x27, 0x02, 0x9d, 0x01, 0x15, 0x00, 0x00, 0x12, 0x06, 0x00, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x04, 0x03, 0x04, 0x7b, 0x10, 0x26, 0x02, 0x9d, 0x73, 0x00, 0x12, 0x06, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0x75, 0x05, 0x44, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x01, 0x0a, 0x01, 0x3b, 0x12, 0x06, 0x01, 0xac, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x04, 0x03, 0x05, 0xf5, 0x10, 0x26, 0x00, 0x71, 0x68, 0xff, 0x12, 0x06, 0x01, 0xad, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x90, 0xff, 0xc1, 0x04, 0x79, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf0, 0x04, 0x45, 0x01, 0x75, 0x12, 0x06, 0x01, 0x79, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0xfe, 0x4c, 0x03, 0xc4, 0x06, 0x66, 0x10, 0x26, 0x02, 0x89, 0x18, 0x00, 0x10, 0x06, 0x02, 0x54, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xde, 0xfe, 0x56, 0x02, 0x27, 0x06, 0x66, 0x10, 0x27, 0x02, 0x89, 0xff, 0x3b, 0x00, 0x00, 0x11, 0x06, 0x01, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x09, 0xbc, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x3d, 0x05, 0x1f, 0x00, 0x00, 0x10, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x08, 0xb8, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x5d, 0x05, 0x40, 0x00, 0x00, 0x10, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x07, 0xb6, 0x06, 0x14, 0x10, 0x27, 0x00, 0x5d, 0x04, 0x3d, 0x00, 0x00, 0x10, 0x06, 0x00, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0x98, 0x01, 0x76, 0x12, 0x06, 0x00, 0x2a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x06, 0x63, 0x12, 0x26, 0x00, 0x4a, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x18, 0xfd, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xff, 0xe3, 0x07, 0x5c, 0x05, 0xd5, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x17, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x21, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x94, 0xb6, 0x38, 0x37, 0x8a, 0x85, 0x3b, 0x38, 0xb6, 0x5a, 0x57, 0xfd, 0xf8, 0x5d, 0x5a, 0xfd, 0x6c, 0xb6, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfb, 0xec, 0x9f, 0x50, 0x4e, 0x01, 0x4f, 0x4b, 0xa4, 0x02, 0x9f, 0xfd, 0x5a, 0xdf, 0x80, 0x78, 0x78, 0x76, 0xe9, 0x01, 0x0d, 0xfd, 0x39, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0xfe, 0x56, 0x04, 0x82, 0x05, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x00, 0x00, 0x25, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x10, 0x01, 0x00, 0x11, 0x34, 0x27, 0x26, 0x23, 0x22, 0x03, 0x01, 0x6b, 0xb6, 0xb6, 0x32, 0x83, 0x4e, 0xcb, 0xb3, 0x4a, 0x4c, 0xfc, 0xe9, 0x02, 0x5d, 0x36, 0x36, 0x75, 0xd5, 0xa7, 0x9c, 0xfd, 0xba, 0x07, 0x7f, 0xb9, 0x48, 0x57, 0x35, 0x78, 0x7a, 0xa4, 0xfe, 0x37, 0xfe, 0xce, 0x01, 0xae, 0x01, 0x0c, 0x8f, 0x47, 0x46, 0xfe, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x6b, 0x10, 0x27, 0x10, 0xee, 0x04, 0x9b, 0x01, 0x75, 0x12, 0x06, 0x00, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x64, 0x12, 0x26, 0x00, 0x51, 0x00, 0x00, 0x10, 0x07, 0x00, 0x43, 0x00, 0xfc, 0xff, 0xfe, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x73, 0x12, 0x26, 0x00, 0x87, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x05, 0xb9, 0x01, 0x7d, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x04, 0x60, 0x07, 0x73, 0x12, 0x26, 0x00, 0xa7, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x05, 0x54, 0x01, 0x7d, 0xff, 0xff, 0x00, 0x07, 0x00, 0x00, 0x06, 0x8e, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x05, 0xb9, 0x01, 0x76, 0x12, 0x06, 0x00, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x06, 0xb1, 0x06, 0x63, 0x12, 0x26, 0x00, 0xa8, 0x00, 0x00, 0x10, 0x07, 0x00, 0x76, 0x01, 0x41, 0xff, 0xfd, 0xff, 0xff, 0x00, 0x5b, 0xff, 0xba, 0x05, 0x4f, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0x7e, 0x01, 0x76, 0x12, 0x06, 0x00, 0x9a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x40, 0xff, 0xa2, 0x04, 0x26, 0x06, 0x63, 0x12, 0x26, 0x00, 0xba, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x19, 0xfd, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x70, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf5, 0x04, 0x68, 0x01, 0x7a, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x64, 0x10, 0x27, 0x02, 0xc0, 0x04, 0x22, 0xff, 0xfe, 0x12, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x36, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf1, 0x04, 0x43, 0x01, 0x3e, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x48, 0x10, 0x27, 0x02, 0xc2, 0x03, 0xf4, 0x00, 0x00, 0x12, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x70, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf5, 0x04, 0x2e, 0x01, 0x7a, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x63, 0x10, 0x27, 0x02, 0xc0, 0x04, 0x41, 0xff, 0xfd, 0x12, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x36, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf1, 0x04, 0x2f, 0x01, 0x3e, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x48, 0x10, 0x27, 0x02, 0xc2, 0x04, 0x32, 0x00, 0x00, 0x12, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0xff, 0xaf, 0x00, 0x00, 0x02, 0x35, 0x07, 0x70, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf5, 0x03, 0x03, 0x01, 0x7a, 0xff, 0xff, 0xff, 0xc9, 0x00, 0x00, 0x02, 0x41, 0x06, 0x63, 0x10, 0x27, 0x02, 0xc0, 0x03, 0x0f, 0xff, 0xfd, 0x12, 0x06, 0x00, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x02, 0x38, 0x07, 0x36, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf1, 0x02, 0xeb, 0x01, 0x3e, 0xff, 0xff, 0xff, 0xe5, 0x00, 0x00, 0x02, 0x1a, 0x06, 0x48, 0x10, 0x27, 0x02, 0xc2, 0x02, 0xd4, 0x00, 0x00, 0x12, 0x06, 0x00, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x70, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf5, 0x04, 0xba, 0x01, 0x7a, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x64, 0x10, 0x27, 0x02, 0xc0, 0x04, 0x29, 0xff, 0xfe, 0x12, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x36, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf1, 0x04, 0x99, 0x01, 0x3e, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x48, 0x10, 0x27, 0x02, 0xc2, 0x04, 0x22, 0x00, 0x00, 0x12, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb3, 0x00, 0x00, 0x04, 0xcc, 0x07, 0x70, 0x12, 0x26, 0x00, 0x35, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf5, 0x04, 0x06, 0x01, 0x7a, 0xff, 0xff, 0x00, 0x75, 0x00, 0x00, 0x02, 0xf6, 0x06, 0x63, 0x10, 0x27, 0x02, 0xc0, 0x03, 0xbb, 0xff, 0xfd, 0x12, 0x06, 0x00, 0x55, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xcc, 0x07, 0x36, 0x12, 0x26, 0x00, 0x35, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf1, 0x04, 0x0d, 0x01, 0x3e, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x08, 0x06, 0x48, 0x10, 0x27, 0x02, 0xc2, 0x03, 0xc2, 0x00, 0x00, 0x12, 0x06, 0x00, 0x55, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x70, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf5, 0x04, 0x93, 0x01, 0x7a, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x64, 0x10, 0x27, 0x02, 0xc0, 0x04, 0x58, 0xff, 0xfe, 0x12, 0x06, 0x00, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0x36, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf1, 0x04, 0x6e, 0x01, 0x3e, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x48, 0x10, 0x27, 0x02, 0xc2, 0x04, 0x34, 0x00, 0x00, 0x12, 0x06, 0x00, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x14, 0x04, 0x2c, 0x05, 0xf0, 0x10, 0x27, 0x02, 0xd7, 0x04, 0x04, 0x00, 0x00, 0x12, 0x06, 0x00, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xfe, 0x14, 0x03, 0x67, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd7, 0x03, 0xc1, 0x00, 0x00, 0x12, 0x06, 0x00, 0x56, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0xfe, 0x14, 0x04, 0x6c, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd7, 0x03, 0xe4, 0x00, 0x00, 0x12, 0x06, 0x00, 0x37, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0xfe, 0x14, 0x02, 0xa7, 0x05, 0x9e, 0x10, 0x27, 0x02, 0xd7, 0x03, 0x9a, 0x00, 0x00, 0x12, 0x06, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8c, 0xfe, 0x52, 0x04, 0x02, 0x05, 0xf0, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x04, 0x11, 0x14, 0x0e, 0x03, 0x07, 0x35, 0x36, 0x24, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x35, 0x37, 0x3e, 0x03, 0x35, 0x34, 0x2e, 0x03, 0x23, 0x22, 0x07, 0x35, 0x36, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x0e, 0x02, 0x02, 0xec, 0x01, 0x15, 0x64, 0xa6, 0xe7, 0xfa, 0x8a, 0xb4, 0x01, 0x13, 0xa6, 0x53, 0x70, 0x65, 0x56, 0x67, 0x93, 0xdf, 0x36, 0x5c, 0x5e, 0x37, 0x20, 0x31, 0x44, 0x41, 0x22, 0xa5, 0xdb, 0xd7, 0xb9, 0x76, 0xb7, 0x70, 0x15, 0x34, 0x63, 0x02, 0xa2, 0x43, 0xfe, 0xdb, 0x70, 0xce, 0xa0, 0x88, 0x60, 0x22, 0xa0, 0x37, 0x8c, 0x99, 0x9d, 0x4f, 0x65, 0x84, 0x33, 0x48, 0xab, 0x6a, 0x1a, 0x41, 0x63, 0x8b, 0x52, 0x37, 0x56, 0x33, 0x22, 0x0c, 0xb8, 0xbe, 0xa4, 0x56, 0xb6, 0x80, 0x3c, 0x66, 0x71, 0x74, 0x00, 0x01, 0x00, 0x3f, 0xfe, 0x4f, 0x03, 0x5d, 0x04, 0x7b, 0x00, 0x34, 0x00, 0x00, 0x01, 0x1e, 0x03, 0x15, 0x14, 0x0e, 0x05, 0x07, 0x35, 0x3e, 0x04, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x35, 0x37, 0x3e, 0x04, 0x35, 0x34, 0x2e, 0x03, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x02, 0x63, 0x3f, 0x65, 0x38, 0x1d, 0x3b, 0x61, 0x89, 0x8d, 0xa1, 0x87, 0x42, 0x92, 0xdc, 0x8e, 0x5a, 0x24, 0x6b, 0x53, 0x36, 0x38, 0xc3, 0xc9, 0x1f, 0x3a, 0x4f, 0x38, 0x29, 0x1c, 0x2c, 0x3d, 0x3a, 0x20, 0x3e, 0x97, 0x84, 0xef, 0x79, 0x65, 0xa5, 0x69, 0x5d, 0x01, 0xcd, 0x08, 0x44, 0x5a, 0x58, 0x25, 0x4b, 0x8a, 0x6c, 0x61, 0x46, 0x3d, 0x27, 0x0f, 0x82, 0x2e, 0x60, 0x5b, 0x62, 0x5b, 0x33, 0x58, 0x70, 0x19, 0x56, 0x8b, 0x55, 0x0d, 0x20, 0x3c, 0x45, 0x66, 0x39, 0x2c, 0x46, 0x2a, 0x1b, 0x0a, 0x3b, 0x5a, 0x9a, 0x85, 0x47, 0x92, 0x61, 0x6e, 0x99, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf0, 0x04, 0x84, 0x01, 0x75, 0x12, 0x06, 0x00, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf1, 0x00, 0x00, 0x03, 0xf4, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf0, 0x02, 0xd1, 0x01, 0x75, 0x13, 0x06, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x04, 0x97, 0x05, 0xf0, 0x00, 0x13, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x17, 0x32, 0x12, 0x19, 0x01, 0x23, 0x03, 0xe2, 0x8b, 0x8a, 0xa1, 0xc1, 0xb6, 0xb6, 0x48, 0xb9, 0x8c, 0xcd, 0xd1, 0xb4, 0x03, 0x7f, 0xd7, 0xd5, 0xff, 0xde, 0xfc, 0xb2, 0x05, 0xd5, 0xf1, 0x87, 0x86, 0x01, 0xfe, 0xc1, 0xfe, 0xcc, 0xfa, 0xd9, 0x00, 0x03, 0x00, 0x65, 0xff, 0x70, 0x05, 0xa4, 0x06, 0x14, 0x00, 0x07, 0x00, 0x28, 0x00, 0x34, 0x00, 0x00, 0x25, 0x16, 0x33, 0x32, 0x35, 0x34, 0x27, 0x22, 0x07, 0x36, 0x33, 0x32, 0x15, 0x10, 0x21, 0x22, 0x27, 0x06, 0x07, 0x23, 0x36, 0x37, 0x26, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x11, 0x33, 0x00, 0x10, 0x17, 0x16, 0x20, 0x37, 0x36, 0x10, 0x27, 0x26, 0x20, 0x07, 0x04, 0x3d, 0x10, 0x21, 0x90, 0x2f, 0x2f, 0xb5, 0x63, 0x7a, 0xdc, 0xfe, 0xcc, 0x42, 0x30, 0x1e, 0x16, 0xb0, 0x1a, 0x3c, 0x2b, 0x34, 0x4f, 0x50, 0x70, 0xb7, 0x73, 0x72, 0x72, 0x73, 0xb7, 0x70, 0x50, 0x4f, 0x34, 0xa6, 0xfd, 0x26, 0x4a, 0x4c, 0x01, 0x07, 0x4b, 0x4c, 0x4c, 0x4b, 0xfe, 0xf9, 0x4c, 0x82, 0x05, 0xaf, 0x2d, 0x01, 0x20, 0xb8, 0xce, 0xfe, 0xbf, 0x0f, 0x48, 0x3a, 0x45, 0x93, 0x3c, 0x24, 0x64, 0x30, 0x31, 0xa2, 0xa2, 0x02, 0x10, 0xa2, 0xa2, 0x31, 0x30, 0x64, 0x02, 0x5e, 0xfc, 0xe6, 0xfe, 0x6a, 0x74, 0x73, 0x73, 0x74, 0x01, 0x96, 0x74, 0x73, 0x73, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0xa2, 0x05, 0xf0, 0x00, 0x0c, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x10, 0x17, 0x16, 0x20, 0x37, 0x36, 0x35, 0x34, 0x26, 0x03, 0x0e, 0x01, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x35, 0x32, 0x17, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x20, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x02, 0x84, 0xa6, 0x60, 0x60, 0x60, 0x60, 0x01, 0x4b, 0x60, 0x61, 0xbf, 0xdc, 0x75, 0x99, 0x56, 0x35, 0xb8, 0x97, 0x55, 0x57, 0x45, 0x62, 0x75, 0xcd, 0x87, 0x7d, 0x99, 0x88, 0x9a, 0x56, 0x56, 0x8c, 0x8c, 0xfd, 0xf5, 0x8c, 0x8c, 0x56, 0x57, 0x9a, 0x9a, 0x3c, 0x4c, 0x75, 0x68, 0xe7, 0x02, 0xc5, 0x4d, 0x4d, 0xfe, 0xf2, 0x4d, 0x4d, 0x4d, 0x4e, 0x86, 0x87, 0x9a, 0x02, 0x27, 0x03, 0x7c, 0x4f, 0x45, 0x48, 0x2d, 0x41, 0x41, 0x88, 0x9e, 0x2b, 0x4d, 0x08, 0x64, 0x68, 0x61, 0xba, 0x80, 0xb2, 0x20, 0x22, 0x63, 0x63, 0x8f, 0xd9, 0x74, 0x74, 0x74, 0x74, 0xd9, 0x8f, 0x63, 0x63, 0x22, 0x1f, 0x46, 0x59, 0x58, 0x82, 0x53, 0x4a, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x00, 0x05, 0x0f, 0x00, 0x0d, 0x00, 0x34, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x10, 0x17, 0x16, 0x20, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x13, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x20, 0x27, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x33, 0x06, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x02, 0x32, 0x81, 0x4b, 0x4a, 0x4a, 0x4b, 0x01, 0x03, 0x4b, 0x4b, 0x4b, 0x4a, 0xe5, 0x34, 0x2f, 0x41, 0x75, 0x84, 0x49, 0x49, 0x77, 0x77, 0xfe, 0x43, 0x77, 0x77, 0x93, 0x84, 0x82, 0x35, 0x2f, 0x39, 0x91, 0x27, 0x42, 0x41, 0x75, 0x76, 0x41, 0x43, 0x28, 0x02, 0xc5, 0x4d, 0x4d, 0xfe, 0xf2, 0x4d, 0x4d, 0x4d, 0x4e, 0x86, 0x87, 0x4d, 0x4d, 0x02, 0x4a, 0x40, 0x62, 0x99, 0x40, 0x59, 0x20, 0x22, 0x63, 0x63, 0x8f, 0xd9, 0x74, 0x74, 0x74, 0x74, 0xd9, 0x8f, 0xc6, 0x22, 0x23, 0x56, 0x4b, 0x8e, 0x59, 0x49, 0x41, 0xe8, 0x41, 0x41, 0x41, 0x41, 0x74, 0x77, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x52, 0xfe, 0x56, 0x04, 0x9c, 0x05, 0xd5, 0x00, 0x15, 0x00, 0x00, 0x05, 0x10, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x04, 0x9c, 0x8e, 0x41, 0x67, 0xe4, 0xd1, 0x5f, 0x22, 0x22, 0xfc, 0x5d, 0x03, 0x51, 0xfc, 0xc4, 0x04, 0x1f, 0xfc, 0xaf, 0x03, 0x66, 0x14, 0xfe, 0xdf, 0x50, 0x25, 0x9c, 0x30, 0x31, 0x99, 0x14, 0x9a, 0x04, 0x91, 0xaa, 0x9a, 0xfb, 0x6f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xfe, 0x56, 0x03, 0x79, 0x04, 0x60, 0x00, 0x15, 0x00, 0x00, 0x05, 0x10, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x03, 0x78, 0x8e, 0x41, 0x66, 0xe5, 0xd2, 0x5e, 0x22, 0x23, 0xfd, 0x7c, 0x02, 0x6f, 0xfd, 0xa8, 0x03, 0x12, 0xfd, 0x92, 0x02, 0x6e, 0x14, 0xfe, 0xdf, 0x50, 0x25, 0x9c, 0x30, 0x31, 0x99, 0x14, 0xa8, 0x03, 0x25, 0x93, 0xa8, 0xfc, 0xdb, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x43, 0x01, 0x75, 0x12, 0x06, 0x00, 0x24, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xdc, 0x00, 0x00, 0x12, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x75, 0x04, 0x17, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x00, 0x7a, 0x00, 0x92, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x04, 0x0c, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x06, 0x00, 0x7a, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x33, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x1e, 0x58, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x07, 0x31, 0x12, 0x26, 0x00, 0xb8, 0x00, 0x00, 0x10, 0x07, 0x00, 0x71, 0x00, 0x68, 0x01, 0x3b, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x33, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x25, 0x5e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0xe9, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x10, 0x07, 0x11, 0x25, 0xff, 0xbc, 0xfe, 0xb6, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0xa3, 0x01, 0x75, 0x12, 0x06, 0x00, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x04, 0x01, 0x00, 0x00, 0x12, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x33, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x20, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x07, 0x31, 0x12, 0x26, 0x01, 0xf1, 0x00, 0x00, 0x10, 0x07, 0x00, 0x71, 0x00, 0x68, 0x01, 0x3b, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x00, 0x66, 0x01, 0x3b, 0x12, 0x06, 0x00, 0x3c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x05, 0xf5, 0x10, 0x26, 0x00, 0x71, 0x55, 0xff, 0x12, 0x06, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x7c, 0xff, 0x70, 0x03, 0x06, 0x06, 0x0e, 0x00, 0x07, 0x00, 0x19, 0x00, 0x00, 0x25, 0x16, 0x33, 0x32, 0x35, 0x34, 0x27, 0x22, 0x07, 0x36, 0x33, 0x32, 0x15, 0x10, 0x21, 0x22, 0x27, 0x06, 0x07, 0x23, 0x36, 0x37, 0x26, 0x37, 0x11, 0x33, 0x01, 0xa0, 0x0f, 0x21, 0x90, 0x2e, 0x2f, 0xb6, 0x63, 0x7a, 0xdc, 0xfe, 0xcc, 0x42, 0x2f, 0x1f, 0x15, 0xb1, 0x1a, 0x3d, 0x2d, 0x01, 0xa6, 0x82, 0x05, 0xaf, 0x2d, 0x01, 0x20, 0xb8, 0xce, 0xfe, 0xbf, 0x0f, 0x48, 0x3a, 0x45, 0x93, 0x3c, 0x5a, 0x05, 0x30, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x70, 0x05, 0xad, 0x04, 0x7b, 0x00, 0x07, 0x00, 0x2b, 0x00, 0x00, 0x25, 0x16, 0x33, 0x32, 0x35, 0x34, 0x27, 0x22, 0x07, 0x36, 0x33, 0x32, 0x15, 0x10, 0x21, 0x22, 0x27, 0x06, 0x07, 0x23, 0x36, 0x37, 0x26, 0x37, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x04, 0x46, 0x10, 0x21, 0x90, 0x2f, 0x2f, 0xb5, 0x63, 0x7a, 0xdc, 0xfe, 0xcc, 0x42, 0x30, 0x1e, 0x16, 0xb0, 0x1a, 0x3c, 0x2c, 0x01, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0x50, 0x51, 0x6a, 0xad, 0x59, 0x5a, 0x82, 0x05, 0xaf, 0x2d, 0x01, 0x20, 0xb8, 0xce, 0xfe, 0xbf, 0x0f, 0x48, 0x3a, 0x45, 0x93, 0x3c, 0x5a, 0x01, 0xc0, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x65, 0x32, 0x32, 0x77, 0x78, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x31, 0xff, 0x70, 0x03, 0x0b, 0x05, 0x9e, 0x00, 0x07, 0x00, 0x21, 0x00, 0x00, 0x25, 0x16, 0x33, 0x32, 0x35, 0x34, 0x27, 0x22, 0x07, 0x36, 0x33, 0x32, 0x15, 0x10, 0x21, 0x22, 0x27, 0x06, 0x07, 0x23, 0x36, 0x37, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x01, 0xa4, 0x10, 0x21, 0x90, 0x2f, 0x2f, 0xb5, 0x62, 0x7b, 0xdb, 0xfe, 0xcd, 0x42, 0x31, 0x1d, 0x16, 0xb0, 0x1a, 0x3c, 0x2c, 0x79, 0x79, 0xa7, 0x01, 0x55, 0xfe, 0xab, 0x82, 0x05, 0xaf, 0x2d, 0x01, 0x20, 0xb8, 0xce, 0xfe, 0xbf, 0x0f, 0x48, 0x3a, 0x45, 0x93, 0x3c, 0x5a, 0x02, 0xf3, 0x8f, 0x01, 0x3e, 0xfe, 0xc2, 0x8f, 0x00, 0x00, 0x01, 0xff, 0xde, 0xfe, 0x56, 0x01, 0x54, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0xae, 0xa5, 0x92, 0xa3, 0x3f, 0x2c, 0x5e, 0x45, 0x04, 0x60, 0xfb, 0x8c, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0x00, 0x00, 0x03, 0x00, 0x65, 0xff, 0xe3, 0x06, 0xcb, 0x06, 0x14, 0x00, 0x09, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x10, 0x17, 0x16, 0x20, 0x36, 0x10, 0x26, 0x20, 0x07, 0x13, 0x32, 0x17, 0x11, 0x33, 0x11, 0x36, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x27, 0x15, 0x23, 0x35, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x00, 0x10, 0x27, 0x26, 0x20, 0x07, 0x06, 0x10, 0x17, 0x16, 0x20, 0x37, 0x01, 0x11, 0x4a, 0x4c, 0x01, 0x07, 0x97, 0x97, 0xfe, 0xf9, 0x4c, 0xa7, 0xdc, 0x67, 0xa7, 0x66, 0xdc, 0xb7, 0xe6, 0xe6, 0xb7, 0xdc, 0x66, 0xa7, 0x67, 0xdc, 0xb7, 0x73, 0x72, 0x72, 0x73, 0x04, 0xd4, 0x4b, 0x4b, 0xfe, 0xf9, 0x4c, 0x4a, 0x4a, 0x4c, 0x01, 0x07, 0x4b, 0x02, 0xfa, 0xfe, 0x6a, 0x74, 0x73, 0xe7, 0x01, 0x96, 0xe7, 0x73, 0x01, 0x0d, 0xc5, 0x02, 0x5e, 0xfd, 0xa2, 0xc5, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0xc5, 0xa8, 0xa8, 0xc5, 0xa2, 0xa2, 0x02, 0x10, 0xa2, 0xa2, 0xfc, 0xe9, 0x01, 0x96, 0x74, 0x73, 0x73, 0x74, 0xfe, 0x6a, 0x74, 0x73, 0x73, 0x00, 0x00, 0x00, 0x03, 0x00, 0x65, 0xfe, 0x56, 0x06, 0xcb, 0x04, 0x7b, 0x00, 0x0b, 0x00, 0x25, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x10, 0x27, 0x26, 0x20, 0x07, 0x06, 0x10, 0x17, 0x16, 0x20, 0x37, 0x03, 0x22, 0x27, 0x11, 0x23, 0x11, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x35, 0x33, 0x15, 0x36, 0x33, 0x32, 0x12, 0x10, 0x02, 0x00, 0x10, 0x17, 0x16, 0x20, 0x36, 0x10, 0x26, 0x20, 0x07, 0x06, 0x1f, 0x4b, 0x4b, 0xfe, 0xf9, 0x4c, 0x4a, 0x4a, 0x4c, 0x01, 0x07, 0x4b, 0xa6, 0xdc, 0x66, 0xa7, 0x67, 0xdc, 0xb7, 0x73, 0x72, 0x72, 0x73, 0xb7, 0xdc, 0x67, 0xa7, 0x66, 0xdc, 0xb7, 0xe6, 0xe6, 0xfb, 0x2c, 0x4a, 0x4c, 0x01, 0x07, 0x97, 0x97, 0xfe, 0xf9, 0x4c, 0x01, 0x64, 0x01, 0x96, 0x74, 0x73, 0x73, 0x74, 0xfe, 0x6a, 0x74, 0x73, 0x73, 0xfe, 0xf3, 0xc5, 0xfd, 0xae, 0x02, 0x52, 0xc5, 0xa2, 0xa2, 0x02, 0x10, 0xa2, 0xa2, 0xc5, 0xaa, 0xaa, 0xc5, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x03, 0x17, 0xfe, 0x6a, 0x74, 0x73, 0xe7, 0x01, 0x96, 0xe7, 0x73, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfd, 0xff, 0xba, 0x04, 0xf0, 0x06, 0x17, 0x00, 0x12, 0x00, 0x16, 0x00, 0x19, 0x00, 0x00, 0x01, 0x33, 0x13, 0x01, 0x17, 0x09, 0x01, 0x23, 0x03, 0x21, 0x0f, 0x01, 0x23, 0x07, 0x27, 0x23, 0x37, 0x27, 0x37, 0x01, 0x03, 0x33, 0x01, 0x03, 0x21, 0x03, 0x02, 0x0f, 0xcf, 0x78, 0x01, 0x3e, 0x5c, 0xfe, 0x98, 0x01, 0x56, 0xbd, 0x7b, 0xfe, 0x0e, 0xb9, 0x2d, 0x3f, 0x35, 0x4a, 0x02, 0x01, 0x12, 0x2b, 0x02, 0x4e, 0xf7, 0x14, 0x01, 0x4b, 0xab, 0x01, 0x3b, 0x60, 0x05, 0xd5, 0xfe, 0xa1, 0x01, 0xa1, 0x59, 0xfe, 0x27, 0xfc, 0x1b, 0x01, 0x7f, 0xf1, 0x8e, 0x46, 0x46, 0x01, 0x11, 0x38, 0x04, 0xc4, 0xfd, 0x19, 0x01, 0xb1, 0xfe, 0x4f, 0x01, 0x1f, 0x00, 0x02, 0x00, 0x0a, 0xff, 0xba, 0x04, 0xfd, 0x06, 0x17, 0x00, 0x22, 0x00, 0x2c, 0x00, 0x00, 0x17, 0x27, 0x13, 0x26, 0x11, 0x10, 0x37, 0x36, 0x21, 0x32, 0x17, 0x16, 0x17, 0x37, 0x17, 0x07, 0x15, 0x26, 0x27, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x20, 0x27, 0x13, 0x01, 0x23, 0x26, 0x23, 0x22, 0x07, 0x06, 0x11, 0x14, 0x67, 0x5c, 0xc6, 0x69, 0xaf, 0xaf, 0x01, 0x32, 0x78, 0x6a, 0x37, 0x35, 0x5a, 0x5c, 0x59, 0x29, 0x2c, 0xfd, 0x42, 0x08, 0x0a, 0x7a, 0xe6, 0x75, 0x69, 0x67, 0x5c, 0x5f, 0x6b, 0x6b, 0x76, 0xfe, 0xd5, 0xaf, 0x34, 0x02, 0x8f, 0x01, 0x69, 0x75, 0xe6, 0x7a, 0x7b, 0x46, 0x58, 0x01, 0x05, 0xbb, 0x01, 0x17, 0x01, 0x68, 0xcf, 0xd0, 0x24, 0x12, 0x1b, 0x78, 0x59, 0x76, 0xbb, 0x2b, 0x21, 0xfc, 0x66, 0x0d, 0x0c, 0x9d, 0x2f, 0x2f, 0x5f, 0xd3, 0x48, 0x24, 0x24, 0xc7, 0x01, 0x15, 0x03, 0x5c, 0x2f, 0x9c, 0x9d, 0xfe, 0xd8, 0xad, 0x00, 0x00, 0x02, 0x00, 0x08, 0xff, 0xa2, 0x03, 0xee, 0x04, 0xbc, 0x00, 0x22, 0x00, 0x2b, 0x00, 0x00, 0x17, 0x27, 0x37, 0x26, 0x35, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x37, 0x17, 0x07, 0x15, 0x26, 0x27, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x13, 0x01, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x5e, 0x56, 0xaa, 0x4c, 0x88, 0x87, 0xeb, 0x4d, 0x49, 0x29, 0x29, 0x50, 0x55, 0x6a, 0x16, 0x16, 0xfe, 0x0b, 0x06, 0x05, 0x59, 0xa2, 0x48, 0x46, 0x47, 0x46, 0x45, 0x4a, 0x4b, 0x53, 0xd8, 0x85, 0x32, 0x01, 0xbc, 0x3f, 0x40, 0xa2, 0x59, 0x59, 0x5e, 0x4e, 0xe6, 0x8d, 0xcc, 0x01, 0x12, 0x9d, 0x9d, 0x11, 0x0a, 0x10, 0x6c, 0x4f, 0x8f, 0x55, 0x0e, 0x0b, 0xfd, 0x5e, 0x08, 0x08, 0x71, 0x15, 0x16, 0x2b, 0xaa, 0x24, 0x12, 0x12, 0x90, 0x01, 0x05, 0x02, 0x56, 0x11, 0x71, 0x72, 0xcd, 0x67, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x35, 0x33, 0xb5, 0xb6, 0xac, 0xac, 0x02, 0x8e, 0xfc, 0xbc, 0xac, 0xac, 0x05, 0xd5, 0xfd, 0x77, 0x90, 0xfd, 0xee, 0xaa, 0x02, 0xbc, 0x90, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb9, 0xff, 0xba, 0x04, 0xad, 0x06, 0x17, 0x00, 0x0f, 0x00, 0x12, 0x00, 0x00, 0x01, 0x15, 0x23, 0x01, 0x11, 0x23, 0x11, 0x01, 0x27, 0x01, 0x11, 0x21, 0x35, 0x21, 0x37, 0x17, 0x09, 0x01, 0x21, 0x04, 0x6b, 0x2f, 0xfe, 0x52, 0xb6, 0xfe, 0x3e, 0x5c, 0x02, 0x1e, 0xfe, 0x23, 0x04, 0x23, 0x32, 0x5c, 0xfd, 0xe2, 0x01, 0x0e, 0xfe, 0xf2, 0x05, 0x69, 0x3e, 0xfd, 0xcc, 0xfd, 0x09, 0x02, 0x07, 0xfd, 0xb3, 0x58, 0x02, 0xc7, 0x02, 0x52, 0xaa, 0x42, 0x59, 0xfe, 0x0b, 0x01, 0x62, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xfe, 0x10, 0x03, 0xb1, 0x04, 0x7b, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x1f, 0x01, 0x16, 0x33, 0x15, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x02, 0xbc, 0x2d, 0x2e, 0x9a, 0x39, 0x9a, 0x44, 0x45, 0xca, 0xb9, 0x5c, 0xa2, 0x44, 0x46, 0x97, 0x51, 0x7b, 0x3e, 0x3e, 0x2c, 0x2d, 0x85, 0x38, 0xb3, 0x48, 0x4a, 0x6e, 0x4f, 0x77, 0x90, 0x84, 0x26, 0x44, 0x23, 0x4c, 0x66, 0x40, 0x50, 0xd5, 0x1c, 0x20, 0x0e, 0x10, 0x57, 0x61, 0x5c, 0x59, 0x59, 0x57, 0x75, 0x3f, 0x3f, 0x01, 0x27, 0x4b, 0x28, 0x28, 0x25, 0x0f, 0x24, 0x4a, 0x4b, 0x82, 0x9e, 0xac, 0x1e, 0x1e, 0xae, 0x28, 0x28, 0x2a, 0x2a, 0x54, 0x40, 0x25, 0x24, 0x21, 0x0e, 0x2c, 0x4b, 0x4c, 0x89, 0x9c, 0x5b, 0x40, 0x13, 0x9f, 0x7e, 0x24, 0x9a, 0x3d, 0x26, 0x5b, 0xf3, 0x1e, 0x10, 0x03, 0x02, 0x12, 0x23, 0xbe, 0x35, 0x1a, 0x1b, 0x2d, 0x2c, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xfe, 0x10, 0x03, 0xc8, 0x04, 0x60, 0x00, 0x18, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x16, 0x17, 0x13, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x2b, 0x01, 0x3d, 0x01, 0x01, 0x21, 0x66, 0x03, 0x12, 0xfd, 0x93, 0x53, 0x2c, 0xee, 0x84, 0x26, 0x44, 0x62, 0x85, 0x4b, 0x67, 0x40, 0x50, 0xd5, 0x37, 0x51, 0x55, 0x02, 0x6f, 0xfd, 0xa8, 0x04, 0x60, 0xa8, 0xfc, 0xdd, 0x10, 0x31, 0xfe, 0xf8, 0x7e, 0x24, 0x9a, 0x3d, 0x26, 0x5b, 0xf3, 0x3f, 0x9c, 0x0c, 0x03, 0x25, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x00, 0x18, 0x00, 0x00, 0x01, 0x23, 0x11, 0x23, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x22, 0x06, 0x07, 0x35, 0x36, 0x3b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x02, 0x4f, 0x23, 0xb6, 0xd9, 0x7f, 0x8b, 0x8b, 0x7f, 0xe4, 0x3e, 0x9e, 0x47, 0x89, 0x9a, 0xe4, 0xdc, 0xed, 0xee, 0x02, 0x5a, 0xfd, 0xa6, 0x03, 0x00, 0x91, 0x87, 0x88, 0x8f, 0x2a, 0x2c, 0xb6, 0x46, 0xdc, 0xe1, 0xd7, 0xe7, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x03, 0x34, 0x04, 0x7b, 0x00, 0x18, 0x00, 0x00, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x06, 0x23, 0x11, 0x23, 0x01, 0x11, 0x5a, 0x7f, 0x8a, 0x44, 0x4c, 0x79, 0x42, 0x4d, 0x4e, 0x46, 0x89, 0x9a, 0xe2, 0x70, 0x77, 0xbf, 0xaf, 0xb5, 0x01, 0xa6, 0x91, 0x87, 0x8d, 0x41, 0x48, 0x15, 0x15, 0x2b, 0xb6, 0x46, 0x6e, 0x74, 0xdb, 0xd5, 0xe5, 0xfe, 0xfc, 0x00, 0x00, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x28, 0x00, 0x00, 0x01, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x11, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x23, 0x35, 0x33, 0x01, 0x6b, 0x01, 0x38, 0xfe, 0xc8, 0x01, 0x23, 0x93, 0x8d, 0x8d, 0x93, 0xfe, 0xdd, 0x01, 0x0d, 0x85, 0x83, 0x83, 0x85, 0xfe, 0x3d, 0x01, 0xd0, 0xd0, 0xe1, 0x73, 0x70, 0x87, 0x94, 0xf5, 0xe2, 0xfe, 0x1e, 0xac, 0xac, 0x02, 0xc9, 0xc9, 0x90, 0xca, 0x87, 0x8b, 0x8c, 0x85, 0x02, 0x66, 0xfe, 0x3e, 0x6f, 0x72, 0x71, 0x70, 0xa6, 0xc0, 0xb1, 0x89, 0xa2, 0x14, 0x20, 0xcb, 0x98, 0xc8, 0xda, 0x01, 0x70, 0x90, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0xff, 0xe3, 0x05, 0x3a, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x10, 0x00, 0x23, 0x22, 0x00, 0x11, 0x35, 0x23, 0x35, 0x33, 0x05, 0x21, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0xa0, 0xb7, 0x02, 0x97, 0xb7, 0x94, 0x94, 0xfe, 0xfc, 0xfe, 0xff, 0xfe, 0xfc, 0x95, 0x95, 0x03, 0x4e, 0xfd, 0x69, 0x9d, 0xaf, 0xaf, 0x9c, 0x05, 0xd5, 0xfd, 0x96, 0x02, 0x6a, 0xfd, 0x96, 0xa4, 0x96, 0xfe, 0xdc, 0xfe, 0xd6, 0x01, 0x2a, 0x01, 0x24, 0x96, 0xa4, 0xa4, 0x7d, 0xf0, 0xd3, 0xd3, 0xf0, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x10, 0x06, 0x03, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0xff, 0x42, 0x04, 0x17, 0x06, 0x93, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x33, 0x07, 0x33, 0x15, 0x23, 0x03, 0x33, 0x15, 0x21, 0x03, 0x21, 0x15, 0x21, 0x07, 0x23, 0x37, 0x23, 0x11, 0x21, 0x01, 0x13, 0x23, 0x11, 0x1b, 0x01, 0x21, 0x11, 0x03, 0x59, 0x99, 0x3b, 0x4f, 0x83, 0x88, 0xf0, 0xfe, 0xdc, 0xa6, 0x01, 0xf6, 0xfd, 0xd5, 0x3a, 0x99, 0x3a, 0x9e, 0x02, 0x69, 0xfe, 0x6a, 0xa6, 0xc3, 0xf7, 0x88, 0xfe, 0x81, 0x06, 0x93, 0xbe, 0xaa, 0xfe, 0x46, 0xaa, 0xfd, 0xe3, 0xaa, 0xbe, 0xbe, 0x05, 0xd5, 0xfa, 0xd5, 0x02, 0x1d, 0xfd, 0xe3, 0x02, 0xc7, 0x01, 0xba, 0xfe, 0x46, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x65, 0xff, 0x42, 0x04, 0x0c, 0x05, 0x1e, 0x00, 0x05, 0x00, 0x26, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x03, 0x05, 0x15, 0x21, 0x03, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x23, 0x13, 0x26, 0x27, 0x26, 0x11, 0x10, 0x00, 0x33, 0x32, 0x17, 0x37, 0x33, 0x07, 0x16, 0x17, 0x16, 0x05, 0x13, 0x26, 0x23, 0x22, 0x06, 0x07, 0x1b, 0x01, 0x23, 0x16, 0x03, 0x66, 0x02, 0x4a, 0x0d, 0x0e, 0x64, 0x01, 0x71, 0xfe, 0x5a, 0x86, 0x43, 0x57, 0x60, 0xb3, 0x58, 0x59, 0xbb, 0x60, 0x6f, 0x5a, 0x47, 0x99, 0x62, 0x1e, 0x19, 0x8d, 0x01, 0x0b, 0xe3, 0x32, 0x2d, 0x3f, 0x99, 0x53, 0x34, 0x2a, 0x76, 0xfd, 0xf6, 0x79, 0x12, 0x13, 0x8b, 0xa7, 0x0c, 0x51, 0x64, 0xbb, 0x0a, 0x02, 0x94, 0x97, 0x5a, 0x10, 0x0d, 0xfe, 0xf2, 0x36, 0x5a, 0xfe, 0x97, 0x1c, 0x34, 0x34, 0xae, 0x2a, 0x2c, 0x21, 0xc2, 0x01, 0x09, 0x17, 0x1d, 0x9c, 0x01, 0x0a, 0x01, 0x13, 0x01, 0x43, 0x09, 0xac, 0xe0, 0x22, 0x32, 0x92, 0xc5, 0x01, 0x4a, 0x02, 0xae, 0x9e, 0xfe, 0x63, 0x01, 0x0e, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xa0, 0xfe, 0x66, 0x02, 0x17, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x01, 0x23, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x33, 0x02, 0x17, 0xac, 0xb9, 0xcc, 0x45, 0x38, 0x79, 0x63, 0xac, 0xac, 0xb6, 0xac, 0x02, 0x77, 0xfd, 0xf1, 0xfe, 0xf2, 0xf4, 0xaa, 0x96, 0xc2, 0x02, 0x0f, 0xa6, 0x02, 0xb8, 0xfd, 0x48, 0x00, 0x02, 0xff, 0xde, 0xfe, 0x56, 0x01, 0xe6, 0x06, 0x14, 0x00, 0x13, 0x00, 0x17, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x15, 0x23, 0xae, 0xa5, 0x93, 0x93, 0x92, 0xa3, 0x3f, 0x2c, 0x5e, 0x45, 0xa3, 0xa3, 0xa5, 0xa5, 0x04, 0x60, 0xfe, 0x08, 0xa4, 0xfe, 0x28, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0x01, 0xd8, 0xa4, 0x03, 0xac, 0xe9, 0x00, 0x02, 0x00, 0x67, 0xfe, 0x66, 0x06, 0x05, 0x05, 0xf1, 0x00, 0x18, 0x00, 0x24, 0x00, 0x00, 0x01, 0x35, 0x33, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x11, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x16, 0x01, 0x10, 0x12, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x04, 0x3b, 0xb0, 0x63, 0x79, 0x3e, 0x45, 0xcd, 0xb8, 0x46, 0xd4, 0x95, 0xf2, 0xfe, 0xce, 0x01, 0x32, 0xf2, 0x95, 0xd4, 0xfd, 0x2f, 0xd3, 0xb8, 0xb8, 0xd4, 0xd4, 0xb8, 0xb8, 0xd3, 0x04, 0xed, 0xe8, 0xfa, 0x93, 0xc2, 0x96, 0xaa, 0xf4, 0x01, 0x0e, 0x7f, 0x84, 0x80, 0x01, 0xab, 0x01, 0x5c, 0x01, 0x5c, 0x01, 0xab, 0x80, 0xfd, 0x78, 0xfe, 0xe3, 0xfe, 0xbb, 0x01, 0x45, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x45, 0xfe, 0xbb, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x04, 0xba, 0x04, 0x7b, 0x00, 0x18, 0x00, 0x24, 0x00, 0x00, 0x01, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x33, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x04, 0xba, 0x3f, 0xa3, 0x93, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0xa6, 0x44, 0x5f, 0x2c, 0xfc, 0x57, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0xfe, 0x56, 0xc0, 0xd6, 0xbc, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0x64, 0xaa, 0xfb, 0x8c, 0x99, 0x61, 0x03, 0x3d, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x04, 0xcc, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x20, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x17, 0x13, 0x23, 0x03, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x03, 0x32, 0x3b, 0x6e, 0x38, 0xb9, 0xc4, 0xac, 0x42, 0x7d, 0x6c, 0xc6, 0xb6, 0xac, 0xac, 0x01, 0x9a, 0xe7, 0xe2, 0x75, 0xfd, 0xc8, 0xe4, 0x84, 0x86, 0x86, 0x84, 0x02, 0xbc, 0x16, 0x90, 0x7e, 0xfe, 0x68, 0x01, 0x7f, 0x96, 0x62, 0xfd, 0x89, 0x02, 0x77, 0xa6, 0x02, 0xb8, 0xd6, 0xd8, 0x8d, 0xba, 0x02, 0x4f, 0xfd, 0xee, 0x87, 0x83, 0x83, 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x02, 0xf6, 0x04, 0x7b, 0x00, 0x18, 0x00, 0x00, 0x01, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x1f, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x01, 0xe8, 0x9a, 0xa7, 0x9a, 0x9a, 0xa7, 0x34, 0xa8, 0x77, 0x11, 0x2a, 0x19, 0x01, 0x1c, 0x42, 0x27, 0x8d, 0x96, 0x02, 0x68, 0xa4, 0xfe, 0x3c, 0x01, 0xc4, 0xa4, 0x01, 0xf8, 0xae, 0x66, 0x63, 0x05, 0x05, 0xbd, 0x12, 0x11, 0xce, 0xa1, 0x00, 0x00, 0x00, 0x02, 0xff, 0xf7, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x14, 0x00, 0x00, 0x03, 0x33, 0x17, 0x21, 0x37, 0x33, 0x07, 0x33, 0x15, 0x23, 0x03, 0x11, 0x23, 0x11, 0x03, 0x23, 0x35, 0x33, 0x05, 0x21, 0x17, 0x04, 0xc4, 0x88, 0x01, 0xd7, 0x87, 0xc4, 0x88, 0x8c, 0xf0, 0xf0, 0xb6, 0xf0, 0xf1, 0x8d, 0x02, 0x38, 0xfe, 0xf0, 0x88, 0x05, 0xd5, 0xe0, 0xe0, 0xe0, 0xa4, 0xfe, 0x76, 0xfd, 0x39, 0x02, 0xc7, 0x01, 0x8a, 0xa4, 0xa4, 0xe2, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0xfe, 0x56, 0x04, 0x3d, 0x04, 0x60, 0x00, 0x18, 0x00, 0x1b, 0x00, 0x00, 0x05, 0x0e, 0x01, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x3f, 0x01, 0x03, 0x21, 0x35, 0x33, 0x03, 0x33, 0x13, 0x21, 0x13, 0x33, 0x03, 0x33, 0x15, 0x21, 0x2b, 0x01, 0x13, 0x02, 0x51, 0x46, 0x85, 0x70, 0x84, 0x61, 0x44, 0x4c, 0x2e, 0x1e, 0xb9, 0xfe, 0xf4, 0xd8, 0xab, 0xaf, 0xa6, 0x01, 0x2b, 0xa5, 0xb0, 0xa7, 0xd7, 0xfe, 0xf5, 0xad, 0xc5, 0x62, 0x68, 0xc8, 0x7a, 0x9a, 0x48, 0x86, 0x54, 0x01, 0xf2, 0x8f, 0x01, 0xcd, 0xfe, 0x33, 0x01, 0xcd, 0xfe, 0x33, 0x8f, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xf0, 0x04, 0x7b, 0x00, 0x0a, 0x00, 0x25, 0x00, 0x00, 0x01, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x07, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x01, 0xe7, 0xc9, 0x9a, 0x74, 0x64, 0x89, 0xa7, 0xa5, 0xa5, 0x39, 0xa9, 0x7a, 0x9b, 0xb7, 0xe4, 0xe2, 0xe8, 0x96, 0x88, 0x57, 0xa4, 0x4b, 0x5b, 0xab, 0x51, 0xda, 0xd8, 0x02, 0x2b, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0x4c, 0x02, 0x7f, 0xaa, 0x66, 0x61, 0xc1, 0xa2, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0xfc, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xeb, 0x04, 0x7b, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x35, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x03, 0x45, 0xa6, 0xa6, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0xfe, 0x00, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0x03, 0xb6, 0xaa, 0xfb, 0xa0, 0xa8, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0xfe, 0x15, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0xe3, 0x04, 0x2d, 0x04, 0x7b, 0x00, 0x0b, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x15, 0x23, 0x11, 0x33, 0x03, 0x81, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0xfd, 0xcc, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0xa6, 0xa6, 0x02, 0x2f, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x02, 0x52, 0x64, 0x61, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xf8, 0xfe, 0xbc, 0x61, 0x64, 0xaa, 0x04, 0x60, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0xe3, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x15, 0x23, 0x11, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x03, 0x81, 0x96, 0x83, 0x84, 0x96, 0x96, 0x84, 0x83, 0x96, 0xfd, 0xcd, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x34, 0xa7, 0xa1, 0x95, 0xe5, 0xd2, 0x51, 0x52, 0x02, 0x2f, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x02, 0x52, 0x64, 0x61, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xf8, 0xfe, 0xbc, 0x61, 0x64, 0xa8, 0x04, 0x7e, 0xc3, 0xd3, 0x9c, 0x7d, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x72, 0xff, 0xe3, 0x03, 0x90, 0x04, 0x7b, 0x00, 0x19, 0x00, 0x00, 0x13, 0x3e, 0x01, 0x33, 0x32, 0x00, 0x11, 0x10, 0x00, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x72, 0x46, 0x94, 0x54, 0xe4, 0x01, 0x0c, 0xfe, 0xf1, 0xec, 0x4d, 0x91, 0x45, 0x46, 0x8e, 0x48, 0xa1, 0xb2, 0xb2, 0xa1, 0x48, 0x8e, 0x46, 0x04, 0x33, 0x24, 0x24, 0xfe, 0xc2, 0xfe, 0xf2, 0xfe, 0xee, 0xfe, 0xc6, 0x23, 0x23, 0xac, 0x2b, 0x2b, 0xe3, 0xcd, 0xcd, 0xe3, 0x2b, 0x2b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0x73, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x27, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x06, 0x15, 0x23, 0x34, 0x37, 0x26, 0x27, 0x26, 0x11, 0x10, 0x00, 0x33, 0x32, 0x16, 0x01, 0x16, 0x33, 0x32, 0x35, 0x34, 0x23, 0x22, 0x03, 0x83, 0x46, 0x8d, 0x48, 0xa2, 0xb2, 0x59, 0x06, 0x06, 0x23, 0x38, 0x42, 0x5f, 0x92, 0x43, 0x39, 0x55, 0x4b, 0x8c, 0x48, 0x41, 0x06, 0x89, 0x0a, 0x32, 0x2b, 0x86, 0x01, 0x0f, 0xeb, 0x4d, 0x92, 0xfe, 0xaf, 0x34, 0x46, 0x83, 0x77, 0x5b, 0x04, 0x35, 0xac, 0x2b, 0x2b, 0xe3, 0xcd, 0xcd, 0x72, 0x08, 0x06, 0x51, 0x2c, 0x33, 0x48, 0x3d, 0x59, 0x7d, 0x2f, 0x29, 0x11, 0x39, 0x44, 0x68, 0x51, 0x23, 0x33, 0xa1, 0x01, 0x0c, 0x01, 0x12, 0x01, 0x3a, 0x23, 0xfc, 0x3a, 0x13, 0x39, 0x4b, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x04, 0xba, 0x06, 0x14, 0x00, 0x18, 0x00, 0x24, 0x00, 0x00, 0x01, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x11, 0x33, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x04, 0xba, 0x3f, 0xa3, 0x93, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0xa6, 0x44, 0x5f, 0x2c, 0xfc, 0x57, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0xfe, 0x56, 0xc0, 0xd6, 0xbc, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0x64, 0x02, 0x5e, 0xf9, 0xd8, 0x99, 0x61, 0x03, 0x3d, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x05, 0x27, 0x06, 0x14, 0x00, 0x18, 0x00, 0x24, 0x00, 0x00, 0x01, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x03, 0x45, 0x93, 0xa3, 0xab, 0x98, 0x5f, 0x44, 0xa6, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0xfe, 0x00, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0x03, 0xb6, 0xc8, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0xfb, 0x82, 0xa8, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0xfe, 0x15, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x04, 0x7b, 0x00, 0x19, 0x00, 0x22, 0x00, 0x00, 0x13, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x21, 0x37, 0x05, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x66, 0x76, 0x76, 0xcc, 0xe3, 0x85, 0x86, 0x8d, 0x8d, 0xf1, 0x60, 0xbb, 0x5a, 0x59, 0x5a, 0x59, 0x5f, 0xa5, 0x5c, 0x5c, 0x0b, 0xfd, 0x07, 0xa5, 0x02, 0x4f, 0x0d, 0x54, 0x52, 0x8b, 0x7a, 0x4a, 0x4b, 0x02, 0x5e, 0xfa, 0x92, 0x91, 0xa1, 0xa2, 0xfe, 0xed, 0xfe, 0xf6, 0x9c, 0x9c, 0x2c, 0x2a, 0xae, 0x34, 0x1a, 0x1a, 0x63, 0x64, 0xbe, 0x90, 0x01, 0x9e, 0x57, 0x57, 0x5a, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x04, 0x7b, 0x00, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x35, 0x21, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x00, 0x11, 0x10, 0x00, 0x23, 0x22, 0x02, 0x37, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x66, 0x02, 0xf9, 0x0b, 0xb8, 0xa5, 0x5f, 0xb3, 0x59, 0x5a, 0xbb, 0x60, 0xf1, 0x01, 0x1a, 0xfe, 0xf5, 0xe3, 0xcc, 0xec, 0xa5, 0x02, 0x95, 0x7a, 0x8b, 0xa6, 0x0d, 0x02, 0x00, 0x5a, 0xbe, 0xc7, 0x34, 0x34, 0xae, 0x2a, 0x2c, 0xfe, 0xc8, 0xfe, 0xf6, 0xfe, 0xed, 0xfe, 0xbd, 0x01, 0x23, 0xc4, 0x97, 0xb4, 0xae, 0x9e, 0x00, 0x02, 0x00, 0x6f, 0xff, 0xe3, 0x05, 0xde, 0x04, 0x7b, 0x00, 0x0a, 0x00, 0x34, 0x00, 0x00, 0x25, 0x36, 0x27, 0x36, 0x27, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x01, 0x16, 0x15, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x26, 0x27, 0x26, 0x07, 0x06, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x37, 0x33, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x02, 0xf9, 0x5c, 0x02, 0x01, 0x09, 0xfd, 0xd5, 0x1b, 0x1d, 0x4a, 0x7a, 0x97, 0x01, 0x3d, 0x1c, 0x86, 0x85, 0xe3, 0xcd, 0x75, 0x54, 0x18, 0x02, 0xb1, 0x11, 0x18, 0x44, 0xbd, 0x61, 0x57, 0x5a, 0x59, 0x5a, 0xbb, 0x60, 0xf1, 0x8d, 0x20, 0x18, 0xb7, 0xa6, 0x22, 0x22, 0x5e, 0x27, 0x39, 0x9d, 0x4f, 0x4a, 0xd6, 0x8a, 0xcf, 0x3e, 0x38, 0xfe, 0x9c, 0x45, 0x23, 0x5a, 0x02, 0x90, 0x60, 0x76, 0xfe, 0xed, 0xa2, 0xa1, 0x91, 0x67, 0x9c, 0x01, 0xbb, 0x27, 0x23, 0x64, 0x01, 0x01, 0x19, 0x1a, 0x34, 0xae, 0x2a, 0x2c, 0x9c, 0x23, 0x29, 0x75, 0x94, 0x99, 0x31, 0x30, 0x9c, 0x60, 0x5a, 0xc8, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x04, 0x7c, 0x12, 0x06, 0x03, 0x49, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x04, 0x7c, 0x12, 0x06, 0x03, 0xcb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x77, 0xff, 0xe3, 0x05, 0x8d, 0x04, 0x7c, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x37, 0x33, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x05, 0x06, 0x02, 0x7b, 0x70, 0x7c, 0xe8, 0xd6, 0x48, 0x4d, 0x4b, 0x51, 0x40, 0x4c, 0x4d, 0x53, 0x88, 0x4d, 0x4b, 0x46, 0x41, 0x7b, 0x85, 0x8b, 0x69, 0x3c, 0x3d, 0x3f, 0x3e, 0x6b, 0x40, 0x49, 0x48, 0x57, 0x58, 0x99, 0x45, 0xb0, 0x66, 0x55, 0x0e, 0xd4, 0xa6, 0x22, 0x22, 0x5f, 0x26, 0x39, 0x9d, 0x4f, 0x4a, 0xfe, 0xfd, 0x3a, 0x02, 0x5c, 0x18, 0x92, 0x6c, 0xad, 0xb6, 0x0e, 0x0e, 0x1c, 0xab, 0x25, 0x13, 0x12, 0x38, 0x38, 0x5a, 0x58, 0x38, 0x33, 0x98, 0x2c, 0x2d, 0x46, 0x40, 0x2e, 0x2e, 0x0d, 0x0d, 0x1d, 0xa7, 0x18, 0x18, 0x4e, 0x42, 0x6a, 0x86, 0x94, 0x99, 0x31, 0x30, 0x9c, 0x60, 0x5a, 0xc8, 0xa6, 0x46, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x4b, 0x04, 0x7c, 0x00, 0x1a, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x20, 0x00, 0x11, 0x10, 0x37, 0x36, 0x02, 0xa6, 0xe2, 0x57, 0x59, 0x59, 0x5e, 0xbd, 0x88, 0x4c, 0x4c, 0x46, 0x41, 0x7b, 0x86, 0x8c, 0x68, 0x3d, 0x3d, 0x3f, 0x3e, 0x5e, 0xb1, 0x65, 0x67, 0x36, 0x36, 0x65, 0x70, 0x7c, 0xe8, 0xd7, 0xfe, 0xe6, 0xfe, 0xf4, 0x87, 0x88, 0x03, 0xdc, 0x6e, 0x72, 0xcd, 0xd0, 0x6f, 0x74, 0x38, 0x38, 0x5a, 0x58, 0x38, 0x33, 0x98, 0x2c, 0x2d, 0x46, 0x40, 0x2e, 0x2e, 0xa0, 0x4e, 0x4f, 0x8d, 0x5d, 0x40, 0x41, 0x18, 0x18, 0x92, 0x6c, 0xad, 0xb6, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x12, 0x9d, 0x9e, 0x00, 0x01, 0xff, 0xde, 0xfe, 0x56, 0x01, 0xe6, 0x04, 0x60, 0x00, 0x13, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x23, 0x35, 0x33, 0xae, 0xa5, 0x93, 0x93, 0x92, 0xa3, 0x3f, 0x2c, 0x5e, 0x45, 0xa3, 0xa3, 0x04, 0x60, 0xfe, 0x08, 0xa4, 0xfe, 0x28, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0x01, 0xd8, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x05, 0x26, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x30, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x17, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x03, 0x45, 0x95, 0x86, 0x85, 0x94, 0x94, 0x85, 0x86, 0x95, 0xa6, 0xe5, 0xec, 0x57, 0x9b, 0x49, 0x49, 0x8e, 0x4a, 0xa3, 0xa2, 0x33, 0xa0, 0x70, 0xba, 0xe2, 0xe2, 0xba, 0x70, 0xa0, 0x33, 0x93, 0xa3, 0xab, 0x98, 0x5f, 0x44, 0x02, 0x3d, 0xc8, 0xdc, 0xdc, 0xc8, 0xc7, 0xdc, 0xdc, 0xeb, 0xfe, 0xe2, 0xfe, 0xe9, 0x1d, 0x1e, 0xb3, 0x2c, 0x2a, 0xbd, 0xbf, 0x5b, 0x63, 0x62, 0x01, 0x3a, 0x01, 0x03, 0x01, 0x04, 0x01, 0x3a, 0x62, 0x63, 0xc8, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x04, 0x60, 0x00, 0x0a, 0x00, 0x23, 0x00, 0x00, 0x01, 0x11, 0x21, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x17, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x34, 0x12, 0x33, 0x21, 0x03, 0x45, 0xfe, 0xcc, 0x79, 0x87, 0x94, 0x85, 0x86, 0x95, 0xa6, 0xe5, 0xec, 0x57, 0x9b, 0x49, 0x49, 0x8e, 0x4a, 0xa3, 0xa2, 0x33, 0xa0, 0x70, 0xba, 0xe2, 0xe2, 0xba, 0x01, 0xe9, 0x02, 0x3d, 0x01, 0x88, 0xcd, 0xbb, 0xc7, 0xdc, 0xdc, 0xeb, 0xfe, 0xe2, 0xfe, 0xe9, 0x1d, 0x1e, 0xb3, 0x2c, 0x2a, 0xbd, 0xbf, 0x5b, 0x63, 0x62, 0x01, 0x3a, 0x01, 0x03, 0xf9, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xe1, 0x04, 0x7b, 0x00, 0x1d, 0x00, 0x00, 0x25, 0x11, 0x23, 0x35, 0x21, 0x11, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x03, 0x4b, 0x8b, 0x01, 0x21, 0x5b, 0xc2, 0x6e, 0xe4, 0xfe, 0xf4, 0x01, 0x0f, 0xeb, 0x5e, 0xb1, 0x54, 0x55, 0xad, 0x59, 0xa2, 0xb2, 0xb2, 0xa2, 0x47, 0x6f, 0x9e, 0x01, 0x11, 0x8c, 0xfd, 0xf0, 0x24, 0x24, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x12, 0x01, 0x3a, 0x37, 0x37, 0xaa, 0x3e, 0x3e, 0xe3, 0xcd, 0xcd, 0xe3, 0x0f, 0x00, 0x02, 0x00, 0x56, 0xfe, 0x52, 0x03, 0xf4, 0x04, 0x60, 0x00, 0x13, 0x00, 0x23, 0x00, 0x00, 0x09, 0x01, 0x33, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x33, 0x01, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x02, 0x25, 0x01, 0x22, 0xad, 0xfe, 0x88, 0x5f, 0x23, 0x35, 0x87, 0x87, 0x87, 0x87, 0x35, 0x23, 0x5f, 0xfe, 0x88, 0xad, 0x01, 0x22, 0x3c, 0x1c, 0x19, 0x19, 0x24, 0x34, 0x34, 0x24, 0x19, 0x19, 0x1c, 0x01, 0xe8, 0x02, 0x78, 0xfc, 0xdc, 0xb1, 0x53, 0x80, 0x63, 0x81, 0x82, 0x82, 0x81, 0x63, 0x80, 0x53, 0xb1, 0x03, 0x24, 0xfa, 0x8e, 0x1b, 0x18, 0x2d, 0x45, 0x49, 0x64, 0x63, 0x63, 0x64, 0x49, 0x45, 0x2d, 0x18, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x56, 0xff, 0xe3, 0x03, 0xf4, 0x04, 0x60, 0x00, 0x13, 0x00, 0x23, 0x00, 0x00, 0x09, 0x01, 0x33, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x33, 0x01, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x02, 0x25, 0x01, 0x0b, 0xc4, 0xfe, 0x99, 0x41, 0x27, 0x3e, 0x87, 0x87, 0x87, 0x87, 0x3e, 0x27, 0x41, 0xfe, 0x99, 0xc4, 0x01, 0x0b, 0x3c, 0x1c, 0x19, 0x23, 0x1c, 0x32, 0x32, 0x1c, 0x23, 0x19, 0x1c, 0x02, 0xd1, 0x01, 0x8f, 0xfd, 0xea, 0x62, 0x4c, 0x78, 0x3e, 0x82, 0x81, 0x81, 0x82, 0x3e, 0x78, 0x4c, 0x62, 0x02, 0x16, 0xfc, 0x1f, 0x1b, 0x18, 0x2d, 0x21, 0x40, 0x32, 0x46, 0x46, 0x32, 0x40, 0x21, 0x2d, 0x18, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9c, 0xfe, 0x56, 0x03, 0xe9, 0x04, 0x60, 0x00, 0x13, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x11, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x9d, 0xa5, 0x70, 0x6f, 0x87, 0x9b, 0xa6, 0xa6, 0x3c, 0x9f, 0x6a, 0xad, 0xb4, 0x01, 0xba, 0x02, 0xa6, 0xfd, 0x61, 0x9f, 0x9f, 0xbe, 0xa4, 0x02, 0x7b, 0xf9, 0xf6, 0x02, 0x56, 0x66, 0x63, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x03, 0xf4, 0xa6, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0x93, 0xa3, 0xe5, 0xd0, 0x5f, 0x45, 0x3b, 0xa1, 0x6a, 0xad, 0xb3, 0x02, 0xa4, 0xfd, 0x5c, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x7e, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0xcc, 0x65, 0x64, 0xef, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x14, 0x00, 0x21, 0x00, 0x00, 0x01, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x10, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x36, 0x33, 0x32, 0x16, 0x03, 0xf4, 0x93, 0xa3, 0xe5, 0xd2, 0x5f, 0x44, 0xdf, 0x86, 0x9b, 0xa7, 0x93, 0xa3, 0xe5, 0xd0, 0x5f, 0x45, 0x76, 0xd0, 0xad, 0xb3, 0x02, 0xa4, 0xfd, 0x48, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0x02, 0xb2, 0x01, 0x3d, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x7e, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0xcc, 0xc9, 0xef, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x01, 0xe8, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x15, 0x23, 0xaf, 0xa5, 0x94, 0x94, 0xa5, 0xa2, 0xa2, 0xa5, 0xa5, 0x04, 0x60, 0xfe, 0x08, 0xa4, 0xfe, 0x3c, 0x01, 0xc4, 0xa4, 0x03, 0xac, 0xe9, 0x00, 0x00, 0xff, 0xff, 0x00, 0x95, 0x00, 0x00, 0x02, 0x30, 0x04, 0x60, 0x10, 0x06, 0x03, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x00, 0x02, 0x44, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x35, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x68, 0x01, 0xdc, 0x98, 0x98, 0xfe, 0x24, 0x9f, 0x03, 0xbc, 0xa4, 0xa4, 0xfc, 0xe8, 0xa4, 0xa4, 0x03, 0x18, 0x00, 0x01, 0x00, 0x43, 0x00, 0x00, 0x02, 0x96, 0x06, 0x14, 0x00, 0x23, 0x00, 0x00, 0x01, 0x33, 0x11, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x11, 0x23, 0x11, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x23, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x01, 0x1d, 0xa6, 0x01, 0x02, 0x0f, 0x0c, 0x22, 0x10, 0x10, 0x02, 0x71, 0x02, 0x2e, 0x2e, 0x52, 0x12, 0x11, 0xa6, 0x05, 0x05, 0x0f, 0x0c, 0x22, 0x10, 0x10, 0x02, 0x70, 0x01, 0x2e, 0x2e, 0x52, 0x16, 0x14, 0x06, 0x14, 0xfc, 0xed, 0x01, 0x01, 0x09, 0x25, 0x24, 0x52, 0x87, 0x49, 0x4a, 0x04, 0xfd, 0x85, 0x03, 0x02, 0x04, 0x03, 0x09, 0x25, 0x24, 0x52, 0x87, 0x49, 0x4a, 0x06, 0x00, 0x02, 0x00, 0x45, 0x00, 0x00, 0x02, 0xff, 0x06, 0x14, 0x00, 0x11, 0x00, 0x18, 0x00, 0x00, 0x01, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x34, 0x27, 0x23, 0x22, 0x37, 0x36, 0x33, 0x32, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x14, 0x33, 0x01, 0x78, 0xa6, 0xe1, 0xe1, 0xa6, 0x01, 0x37, 0xfc, 0x01, 0x01, 0xdd, 0x30, 0x25, 0x0e, 0x15, 0x31, 0x46, 0x01, 0x53, 0x06, 0x14, 0xfc, 0xfe, 0xa0, 0xfd, 0x8e, 0x02, 0x54, 0x0f, 0x0f, 0xbd, 0xf6, 0x19, 0xfa, 0x84, 0x4b, 0x39, 0x00, 0x00, 0x01, 0x00, 0xad, 0xfe, 0x56, 0x02, 0x23, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x11, 0x01, 0x53, 0x37, 0x6c, 0x2c, 0x3f, 0xac, 0x89, 0x06, 0x14, 0xf9, 0xce, 0x7c, 0x74, 0x9c, 0xcc, 0xca, 0x06, 0x28, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0xfe, 0x4c, 0x04, 0xb1, 0x06, 0x14, 0x00, 0x24, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x04, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x15, 0x02, 0xf0, 0x5e, 0x74, 0x59, 0x4d, 0x49, 0xfe, 0xee, 0xfc, 0x55, 0x59, 0x5a, 0x5f, 0x4c, 0xb4, 0x62, 0xaa, 0x5a, 0x5a, 0x53, 0x52, 0x96, 0x9d, 0x01, 0x83, 0xfd, 0xac, 0xa5, 0xa5, 0x03, 0x0e, 0x01, 0xdc, 0x38, 0x2b, 0x6c, 0x68, 0x8a, 0xdd, 0xf2, 0x12, 0x13, 0x25, 0xc3, 0x31, 0x32, 0x4b, 0x4b, 0x8f, 0x84, 0x4b, 0x4a, 0xa6, 0x01, 0xf3, 0xfc, 0x33, 0x06, 0x14, 0xfe, 0x4c, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xff, 0xe6, 0x06, 0x67, 0x04, 0x62, 0x00, 0x26, 0x00, 0x00, 0x25, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x03, 0x50, 0x3d, 0x58, 0x56, 0x75, 0x9e, 0xab, 0xa7, 0x66, 0x6a, 0x80, 0x4b, 0x4b, 0xa6, 0x67, 0x6b, 0x7f, 0x95, 0xa7, 0xa7, 0x37, 0x51, 0x4f, 0x6d, 0x6d, 0x4e, 0x4c, 0xd8, 0x79, 0x3d, 0x3c, 0xf6, 0xe2, 0x02, 0xa4, 0xfd, 0x62, 0xa2, 0x9c, 0x60, 0x5e, 0xa4, 0x02, 0x7a, 0xfd, 0x62, 0xa2, 0x9c, 0xc0, 0xa2, 0x02, 0x7a, 0xfb, 0x9e, 0xb0, 0x65, 0x33, 0x32, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x06, 0x67, 0x04, 0x62, 0x00, 0x26, 0x00, 0x00, 0x25, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x03, 0x50, 0x3d, 0x58, 0x56, 0x75, 0x9e, 0xab, 0xa7, 0x66, 0x6a, 0x80, 0x4b, 0x4b, 0xa6, 0x67, 0x6b, 0x7f, 0x95, 0xa7, 0xa7, 0x37, 0x51, 0x4f, 0x6d, 0x6d, 0x4e, 0x4c, 0xd8, 0x79, 0x3d, 0x3c, 0xf6, 0xe2, 0x02, 0xa4, 0xfd, 0x62, 0xa2, 0x9c, 0x60, 0x5e, 0xa4, 0x02, 0x7a, 0xfd, 0x62, 0xa2, 0x9c, 0xc0, 0xa2, 0x02, 0x7a, 0xf9, 0xf4, 0x02, 0x5a, 0x65, 0x33, 0x32, 0x3e, 0x3e, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x06, 0x67, 0x04, 0x7b, 0x00, 0x30, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x03, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x03, 0xbe, 0x3f, 0xac, 0x75, 0x9e, 0x55, 0x56, 0x4a, 0x49, 0xa3, 0xe4, 0xd1, 0x5f, 0x22, 0x22, 0x01, 0x66, 0x6a, 0x80, 0x96, 0xa6, 0x33, 0x34, 0x6b, 0x7f, 0x4a, 0x4b, 0xa7, 0xa7, 0x39, 0x9e, 0x6d, 0x6e, 0x4c, 0x4e, 0x03, 0x89, 0x7c, 0x76, 0x7b, 0x7a, 0xe2, 0xfd, 0x48, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x31, 0x99, 0x02, 0xb2, 0xa1, 0x9c, 0xbe, 0xa4, 0xfd, 0x87, 0x02, 0x9e, 0xa2, 0x4e, 0x4d, 0x5f, 0x60, 0xa3, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x67, 0x62, 0x3e, 0x3e, 0x00, 0x01, 0xff, 0xde, 0xfe, 0x56, 0x03, 0xfa, 0x04, 0x7b, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x03, 0xfa, 0xa6, 0x6f, 0x70, 0x86, 0x9c, 0x92, 0xa3, 0x3f, 0x2c, 0x5e, 0x45, 0xa6, 0x3c, 0xa1, 0x69, 0xae, 0xb2, 0x02, 0xa4, 0xfd, 0x5c, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x73, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0x04, 0x74, 0xae, 0x65, 0x64, 0xef, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0xc3, 0x04, 0x7b, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x26, 0x35, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x03, 0x98, 0x4a, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0xa1, 0x6a, 0xad, 0xb3, 0x22, 0x22, 0x5e, 0x2d, 0x3f, 0xa3, 0xfe, 0xb6, 0x60, 0xd6, 0x02, 0xb2, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x65, 0x64, 0xef, 0xe8, 0xfd, 0x48, 0x99, 0x31, 0x30, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa1, 0x00, 0x00, 0x03, 0xf4, 0x04, 0x60, 0x00, 0x09, 0x00, 0x00, 0x13, 0x33, 0x01, 0x11, 0x33, 0x11, 0x23, 0x01, 0x11, 0x23, 0xa1, 0xf5, 0x01, 0xad, 0xb1, 0xf5, 0xfe, 0x53, 0xb1, 0x04, 0x60, 0xfc, 0x79, 0x03, 0x87, 0xfb, 0xa0, 0x03, 0x6c, 0xfc, 0x94, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x00, 0x01, 0x22, 0x06, 0x07, 0x21, 0x2e, 0x01, 0x03, 0x32, 0x36, 0x35, 0x21, 0x14, 0x16, 0x13, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x02, 0x32, 0x84, 0x86, 0x10, 0x02, 0x35, 0x10, 0x86, 0x84, 0x87, 0x97, 0xfd, 0xc5, 0x97, 0x87, 0xd8, 0xf7, 0xf7, 0xd8, 0xd9, 0xf5, 0xf5, 0x03, 0xdf, 0xc1, 0x7f, 0x7f, 0xc1, 0xfc, 0xa0, 0xe8, 0x94, 0x94, 0xe8, 0x03, 0xfc, 0xfe, 0xc8, 0xfe, 0xec, 0xfe, 0xed, 0xfe, 0xc7, 0x01, 0x39, 0x01, 0x13, 0x01, 0x14, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x05, 0x87, 0x04, 0x60, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x20, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x21, 0x17, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x05, 0x7a, 0xfe, 0x0c, 0x01, 0xe0, 0xfe, 0x20, 0x02, 0x01, 0xfd, 0x31, 0xfe, 0xdb, 0x96, 0x97, 0x97, 0x96, 0x01, 0x25, 0x26, 0x22, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0xd8, 0x22, 0x04, 0x60, 0x9a, 0xfe, 0xdd, 0x9b, 0xfe, 0x94, 0x9c, 0x8e, 0x8f, 0x01, 0x14, 0x01, 0x12, 0x8e, 0x8f, 0x82, 0x6c, 0x6b, 0xd8, 0xd9, 0x6c, 0x6d, 0x00, 0x00, 0x02, 0x00, 0x85, 0xff, 0xdc, 0x04, 0xb8, 0x04, 0x7c, 0x00, 0x13, 0x00, 0x24, 0x00, 0x00, 0x01, 0x15, 0x14, 0x16, 0x32, 0x37, 0x36, 0x35, 0x10, 0x02, 0x20, 0x02, 0x11, 0x14, 0x17, 0x16, 0x32, 0x36, 0x3d, 0x01, 0x05, 0x10, 0x00, 0x20, 0x00, 0x11, 0x14, 0x06, 0x07, 0x06, 0x22, 0x26, 0x27, 0x0e, 0x01, 0x22, 0x26, 0x02, 0xf4, 0x56, 0x61, 0x22, 0x42, 0xbc, 0xfe, 0x97, 0xb6, 0x42, 0x22, 0x60, 0x56, 0xfe, 0x37, 0x01, 0x22, 0x01, 0xec, 0x01, 0x25, 0x34, 0x2a, 0x57, 0xc2, 0x91, 0x0b, 0x10, 0x8e, 0xc0, 0xc2, 0x02, 0x94, 0xc4, 0xa3, 0xb5, 0x30, 0x5b, 0x9d, 0x01, 0x0f, 0x01, 0x31, 0xfe, 0xd0, 0xfe, 0xf0, 0x9d, 0x5b, 0x30, 0xb5, 0xa3, 0xc4, 0xc8, 0x01, 0x54, 0x01, 0x5c, 0xfe, 0xa4, 0xfe, 0x80, 0x6c, 0xb2, 0x36, 0x70, 0xa3, 0x75, 0x79, 0x9f, 0xed, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x64, 0xfe, 0x56, 0x04, 0x56, 0x06, 0x14, 0x12, 0x06, 0x03, 0x69, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0xe5, 0x02, 0x4f, 0x04, 0x60, 0x00, 0x0e, 0x00, 0x00, 0x25, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x01, 0xa8, 0x67, 0xec, 0x22, 0x32, 0x01, 0x36, 0x4f, 0x8d, 0x96, 0xa6, 0xa6, 0xae, 0xc9, 0x0a, 0xbd, 0x23, 0xcb, 0xbe, 0x02, 0x4e, 0xfb, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0xe5, 0x02, 0x4f, 0x06, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x25, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x01, 0xa8, 0x67, 0xec, 0x22, 0x32, 0x01, 0x36, 0x4f, 0x8f, 0x94, 0xa6, 0xa6, 0xae, 0xc9, 0x0a, 0xbd, 0x23, 0xce, 0xbb, 0x03, 0xf8, 0xf9, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x56, 0x03, 0x1e, 0x04, 0x60, 0x00, 0x16, 0x00, 0x00, 0x25, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x01, 0xa8, 0x67, 0xec, 0x22, 0x32, 0x01, 0x36, 0x4f, 0x8d, 0x96, 0xa6, 0x45, 0x5e, 0x2c, 0x3f, 0xa2, 0x93, 0xae, 0xc9, 0x0a, 0xbd, 0x23, 0xcb, 0xbe, 0x02, 0x4e, 0xfb, 0x8c, 0x99, 0x61, 0x9c, 0xc0, 0xd6, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x58, 0x02, 0xf6, 0x04, 0x7b, 0x00, 0x11, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x02, 0xf6, 0x1c, 0x42, 0x27, 0x8d, 0x96, 0xa7, 0xa7, 0x34, 0xa8, 0x77, 0x11, 0x2a, 0x19, 0x03, 0xb4, 0x12, 0x11, 0xcb, 0xbe, 0xfc, 0x0a, 0x06, 0x08, 0xae, 0x66, 0x63, 0x05, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x02, 0xf6, 0x04, 0x7b, 0x00, 0x19, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x02, 0xf6, 0x1c, 0x42, 0x27, 0x8e, 0x96, 0x44, 0x5f, 0xd2, 0xe5, 0xa3, 0x93, 0xa7, 0x34, 0xa8, 0x77, 0x11, 0x2a, 0x19, 0x03, 0xb4, 0x12, 0x11, 0xcb, 0xbe, 0xfd, 0x9e, 0x99, 0x61, 0x9c, 0xc0, 0xd6, 0x04, 0x74, 0xae, 0x66, 0x63, 0x05, 0x05, 0x00, 0x01, 0x00, 0x76, 0x00, 0x00, 0x03, 0x25, 0x04, 0x7b, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x01, 0xb0, 0x94, 0xfe, 0x33, 0x93, 0x93, 0xa3, 0xe5, 0xd2, 0x5f, 0x44, 0x02, 0xe5, 0xfd, 0xbf, 0xa4, 0xa4, 0x02, 0x41, 0xd6, 0xc0, 0x9c, 0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x00, 0x03, 0x25, 0x04, 0x7b, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x16, 0x02, 0x83, 0xa2, 0xfe, 0x24, 0x94, 0x44, 0x5f, 0xd2, 0xe5, 0xa3, 0x93, 0x02, 0xe5, 0xfd, 0xbf, 0xa4, 0xa4, 0x02, 0x41, 0x99, 0x61, 0x9c, 0xc0, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x22, 0x04, 0x60, 0x00, 0x13, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x17, 0x13, 0x23, 0x03, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x02, 0xc5, 0x2b, 0x68, 0x2d, 0x9d, 0xb0, 0x92, 0x42, 0x6f, 0x49, 0x98, 0xa7, 0x01, 0x5e, 0xc4, 0xc0, 0x64, 0xfe, 0x29, 0xb2, 0x6b, 0x73, 0x6a, 0x74, 0x02, 0x0d, 0x0a, 0x74, 0x5d, 0xfe, 0xce, 0x01, 0x1f, 0x80, 0x3a, 0xfe, 0x27, 0x04, 0x60, 0x9e, 0xa5, 0x69, 0x8c, 0x01, 0x9d, 0xfe, 0xaf, 0x56, 0x4e, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x22, 0x04, 0x60, 0x00, 0x13, 0x00, 0x1c, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x01, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0x13, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0xa7, 0xa7, 0x98, 0x49, 0x6f, 0x42, 0x92, 0xb0, 0x9d, 0x2d, 0x68, 0x2b, 0x60, 0x64, 0xc0, 0xc4, 0xfe, 0xa2, 0xa7, 0xb2, 0x74, 0x6a, 0x73, 0x6b, 0x04, 0x60, 0xfe, 0x27, 0x3a, 0x80, 0x01, 0x1f, 0xfe, 0xce, 0x5d, 0x74, 0x0a, 0x1b, 0x8c, 0x69, 0xa5, 0x9e, 0x01, 0xec, 0xfe, 0xaf, 0x60, 0x4d, 0x4e, 0x56, 0x00, 0x00, 0x01, 0x00, 0x63, 0xfe, 0x56, 0x03, 0x67, 0x04, 0x7b, 0x00, 0x30, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x15, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x03, 0x30, 0x46, 0x97, 0x51, 0x7b, 0x7c, 0x59, 0x85, 0x38, 0xb1, 0x94, 0xde, 0xc2, 0x5b, 0x4f, 0x12, 0x44, 0x5e, 0xd2, 0xe4, 0xa3, 0x93, 0xb7, 0xae, 0x75, 0x7e, 0x5b, 0x9a, 0x39, 0x9a, 0x89, 0xca, 0xb9, 0x5c, 0xa2, 0x04, 0x3f, 0xae, 0x28, 0x28, 0x54, 0x54, 0x40, 0x49, 0x21, 0x0e, 0x2a, 0x99, 0x89, 0x9c, 0xb6, 0x11, 0x04, 0x0c, 0x99, 0x61, 0x9c, 0xc0, 0xd6, 0xfb, 0x6a, 0x59, 0x51, 0x4b, 0x50, 0x25, 0x0f, 0x24, 0x95, 0x82, 0x9e, 0xac, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xdc, 0xfe, 0x56, 0x02, 0x8f, 0x06, 0x14, 0x00, 0x13, 0x00, 0x00, 0x17, 0x11, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0xab, 0x9d, 0xaa, 0x9c, 0x9e, 0x59, 0x45, 0x93, 0xa3, 0x3f, 0x2c, 0x5f, 0x43, 0x14, 0x04, 0xc2, 0xbb, 0xab, 0x99, 0x50, 0x68, 0xfb, 0x29, 0xd6, 0xc0, 0x9c, 0x61, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xdc, 0xfe, 0x56, 0x02, 0x8f, 0x06, 0x14, 0x00, 0x20, 0x00, 0x00, 0x13, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x11, 0x15, 0x33, 0x15, 0x23, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x35, 0xab, 0x9d, 0xaa, 0x9c, 0x9e, 0x59, 0x45, 0x92, 0x92, 0x93, 0xa3, 0x3f, 0x2c, 0x5f, 0x43, 0xa2, 0xa2, 0x9e, 0x04, 0x60, 0x4e, 0xbb, 0xab, 0x99, 0x50, 0x68, 0xfd, 0xa8, 0x03, 0xa4, 0xfe, 0x28, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0x01, 0xd8, 0xa4, 0x01, 0x69, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0xfe, 0x56, 0x02, 0xe3, 0x04, 0x65, 0x00, 0x13, 0x00, 0x00, 0x05, 0x11, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x16, 0x15, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x01, 0x6e, 0x45, 0x59, 0x9e, 0x9c, 0xaa, 0x9d, 0x43, 0x5f, 0x2c, 0x3f, 0xa3, 0x93, 0x14, 0x03, 0x28, 0x68, 0x50, 0x99, 0xab, 0xbb, 0xfc, 0xed, 0x99, 0x61, 0x9c, 0xc0, 0x00, 0x00, 0x00, 0x02, 0xff, 0x0d, 0xfe, 0x56, 0x02, 0x8f, 0x06, 0x14, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x00, 0x21, 0x33, 0x15, 0x23, 0x06, 0x07, 0x06, 0x23, 0x20, 0x35, 0x34, 0x3b, 0x01, 0x11, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x03, 0x23, 0x22, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x01, 0x52, 0xa4, 0xac, 0x10, 0x30, 0x49, 0xa3, 0xfe, 0xef, 0xf3, 0xab, 0x9d, 0xaa, 0x9c, 0x9e, 0x59, 0x45, 0xb0, 0xa1, 0x6b, 0x02, 0x03, 0x70, 0x63, 0x1e, 0x0e, 0x9b, 0x6f, 0x40, 0x60, 0xd8, 0xd2, 0x04, 0xae, 0xbb, 0xab, 0x99, 0x50, 0x68, 0xfa, 0xa3, 0x33, 0x41, 0x30, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0xfe, 0xc0, 0x02, 0xa7, 0x04, 0x5e, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x16, 0x15, 0x11, 0x33, 0x15, 0x23, 0x11, 0x01, 0x87, 0xfe, 0xab, 0x01, 0x55, 0x44, 0x67, 0xaa, 0xaa, 0xbf, 0x92, 0x7a, 0x7a, 0xfe, 0xc0, 0x01, 0x3e, 0x8f, 0x02, 0x60, 0x89, 0x4e, 0x9a, 0x9f, 0xd2, 0xfd, 0xa0, 0x8f, 0xfe, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0xfe, 0x56, 0x02, 0xab, 0x05, 0x9e, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x01, 0x52, 0x01, 0x55, 0xfe, 0xab, 0x44, 0x5e, 0xb6, 0xc9, 0xa3, 0x93, 0x79, 0x79, 0x05, 0x9e, 0xfe, 0xc2, 0x8f, 0xfc, 0x1b, 0x99, 0x61, 0x9c, 0xc0, 0xd6, 0x03, 0xe5, 0x8f, 0x01, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff, 0xe3, 0x04, 0x91, 0x04, 0x60, 0x00, 0x16, 0x00, 0x1e, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x23, 0x35, 0x05, 0x21, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x9d, 0xa5, 0x02, 0x01, 0xa6, 0xa7, 0xa7, 0xa6, 0x3c, 0x9f, 0x6a, 0xad, 0xb4, 0x9d, 0x03, 0x42, 0xfe, 0x00, 0x70, 0x6f, 0x81, 0xa0, 0x02, 0x68, 0x01, 0xf8, 0xfe, 0x08, 0x01, 0xf8, 0xfe, 0x08, 0xa4, 0xfe, 0x3c, 0xac, 0x66, 0x63, 0xf0, 0xe7, 0x0a, 0xa4, 0xa5, 0x02, 0x9f, 0x9f, 0xba, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe2, 0x04, 0x11, 0x04, 0x60, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x23, 0x1e, 0x01, 0x15, 0x14, 0x00, 0x23, 0x22, 0x00, 0x35, 0x34, 0x36, 0x37, 0x23, 0x35, 0x21, 0x15, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x37, 0x21, 0x04, 0x10, 0xd4, 0x57, 0x73, 0xff, 0x00, 0xca, 0xcb, 0xff, 0x00, 0x73, 0x57, 0xd5, 0x01, 0x8e, 0x5c, 0x7b, 0x9f, 0x81, 0x82, 0x9e, 0x7a, 0x5c, 0x01, 0x01, 0x88, 0x03, 0xbc, 0x48, 0xeb, 0x98, 0xeb, 0xfe, 0xdc, 0x01, 0x24, 0xeb, 0x98, 0xeb, 0x48, 0xa4, 0xdc, 0x42, 0xd7, 0x8b, 0x9f, 0xc2, 0xc2, 0x9f, 0x8b, 0xd7, 0x42, 0xdc, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x03, 0xed, 0x04, 0x62, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x37, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x17, 0x16, 0x03, 0xec, 0x7f, 0x83, 0xc8, 0x3f, 0xa3, 0x49, 0x49, 0xa5, 0x23, 0x24, 0x5c, 0x2e, 0x82, 0x9e, 0x42, 0x42, 0x63, 0x5d, 0x50, 0x96, 0x2e, 0x1e, 0x02, 0x0f, 0xee, 0x8f, 0x92, 0x60, 0x60, 0xd6, 0x02, 0xca, 0xfd, 0x36, 0x99, 0x31, 0x32, 0x02, 0xc4, 0x9e, 0xe8, 0x65, 0x63, 0x1e, 0x96, 0x08, 0x30, 0x5b, 0xab, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x04, 0x60, 0x00, 0x06, 0x00, 0x00, 0x33, 0x01, 0x33, 0x01, 0x23, 0x09, 0x01, 0x37, 0x01, 0x7a, 0xe1, 0x01, 0x7a, 0xb0, 0xfe, 0xc5, 0xfe, 0xc5, 0x04, 0x60, 0xfb, 0xa0, 0x03, 0xac, 0xfc, 0x54, 0x00, 0x01, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x04, 0x60, 0x00, 0x0c, 0x00, 0x00, 0x21, 0x23, 0x0b, 0x01, 0x23, 0x0b, 0x01, 0x23, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x05, 0x96, 0xa6, 0xce, 0xcf, 0xc3, 0xcf, 0xce, 0xa6, 0x01, 0x08, 0xc3, 0xd9, 0xda, 0xc3, 0x03, 0x6a, 0xfc, 0x96, 0x03, 0x6a, 0xfc, 0x96, 0x04, 0x60, 0xfc, 0x6a, 0x03, 0x96, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x06, 0x14, 0x00, 0x11, 0x00, 0x00, 0x33, 0x01, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x0f, 0x01, 0x01, 0x23, 0x09, 0x01, 0x37, 0x01, 0xbb, 0x47, 0x41, 0x43, 0x70, 0x84, 0x61, 0x45, 0x25, 0x29, 0x2b, 0x1e, 0x01, 0x98, 0xb0, 0xfe, 0xc4, 0xfe, 0xc6, 0x04, 0xd2, 0xc7, 0x3e, 0x3d, 0x9a, 0x24, 0x23, 0x87, 0x5e, 0xfb, 0xb2, 0x03, 0x6c, 0xfc, 0x94, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5b, 0x00, 0x00, 0x03, 0xfa, 0x04, 0x60, 0x00, 0x08, 0x00, 0x00, 0x13, 0x33, 0x09, 0x01, 0x33, 0x01, 0x11, 0x23, 0x11, 0x5c, 0xc3, 0x01, 0x08, 0x01, 0x10, 0xc3, 0xfe, 0x87, 0xb7, 0x04, 0x60, 0xfe, 0x38, 0x01, 0xc8, 0xfd, 0x90, 0xfe, 0x10, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xfe, 0x56, 0x04, 0x46, 0x04, 0x60, 0x00, 0x13, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x21, 0x15, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x21, 0x35, 0x01, 0x21, 0x66, 0x03, 0x12, 0xfd, 0x92, 0x02, 0x6e, 0x45, 0x5e, 0x2b, 0x40, 0xa2, 0x93, 0xfd, 0x7e, 0x02, 0x6f, 0xfd, 0xa8, 0x04, 0x60, 0xa8, 0xfc, 0xdb, 0xa7, 0x99, 0x61, 0x9c, 0xc0, 0xd6, 0x14, 0xa8, 0x03, 0x25, 0x00, 0x02, 0x00, 0x4f, 0xff, 0x91, 0x03, 0x79, 0x04, 0x60, 0x00, 0x1a, 0x00, 0x21, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x33, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x16, 0x07, 0x06, 0x2b, 0x01, 0x06, 0x15, 0x23, 0x34, 0x37, 0x21, 0x35, 0x01, 0x21, 0x01, 0x33, 0x32, 0x35, 0x34, 0x07, 0x06, 0x66, 0x03, 0x12, 0xfd, 0x92, 0x9d, 0x1e, 0x4c, 0x3b, 0x56, 0x77, 0x34, 0x22, 0x01, 0x38, 0x49, 0x72, 0x5e, 0x03, 0x8a, 0x03, 0xfe, 0xba, 0x02, 0x6f, 0xfd, 0xa8, 0x01, 0xcc, 0x32, 0x7c, 0x3f, 0x4f, 0x04, 0x60, 0xa8, 0xfc, 0xdb, 0xa2, 0x47, 0x37, 0x57, 0x39, 0x57, 0x60, 0x2f, 0x3d, 0x33, 0x3c, 0x3b, 0x34, 0xa8, 0x03, 0x25, 0xfc, 0xc6, 0x36, 0x5d, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xfe, 0x4c, 0x03, 0xc4, 0x04, 0x60, 0x00, 0x20, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x04, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x02, 0x03, 0x5f, 0x73, 0x59, 0x4d, 0x49, 0xfe, 0xee, 0xfc, 0x54, 0x59, 0x5a, 0x60, 0x4c, 0xb4, 0x62, 0xab, 0x59, 0x5a, 0x53, 0x54, 0x94, 0x9d, 0x01, 0x83, 0xfd, 0xa8, 0x03, 0x13, 0x01, 0xdc, 0x38, 0x2a, 0x6d, 0x68, 0x8a, 0xdd, 0xf2, 0x12, 0x13, 0x25, 0xc3, 0x31, 0x32, 0x4b, 0x4b, 0x8f, 0x84, 0x4b, 0x4a, 0xa6, 0x01, 0xf3, 0x93, 0xa8, 0x00, 0x00, 0x02, 0x00, 0x62, 0xfe, 0x4c, 0x03, 0xfb, 0x04, 0x60, 0x00, 0x24, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x20, 0x37, 0x36, 0x05, 0x16, 0x17, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x15, 0x23, 0x34, 0x27, 0x30, 0x07, 0x06, 0x37, 0x26, 0x23, 0x22, 0x07, 0x14, 0x33, 0x32, 0x37, 0x01, 0xb6, 0xfe, 0xd3, 0x02, 0x01, 0x01, 0x0d, 0xdd, 0x8e, 0x0b, 0x53, 0x54, 0x94, 0x9d, 0x01, 0x83, 0xfd, 0xa8, 0x03, 0x13, 0xfe, 0x8e, 0x5e, 0x74, 0x5a, 0x4c, 0x49, 0x23, 0x5a, 0x8a, 0x24, 0x12, 0x88, 0x08, 0x70, 0xb1, 0x76, 0x01, 0x8e, 0xab, 0x59, 0xfe, 0x4c, 0xbd, 0xfb, 0x05, 0x04, 0x3b, 0x2a, 0x31, 0x85, 0x4a, 0x4a, 0xa6, 0x01, 0xf3, 0x93, 0xa8, 0xfe, 0x24, 0x38, 0x2b, 0x6c, 0x67, 0x8b, 0x71, 0x55, 0x65, 0xa4, 0x52, 0x38, 0x11, 0x79, 0xfa, 0x2a, 0x4b, 0x2f, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x48, 0x06, 0x12, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x11, 0x23, 0x01, 0x32, 0x39, 0xad, 0x4d, 0x34, 0x01, 0x33, 0x59, 0xa1, 0x48, 0x47, 0x47, 0x46, 0x45, 0x48, 0x49, 0x4d, 0xf7, 0x7d, 0x62, 0x62, 0x64, 0x99, 0xb6, 0x03, 0x1e, 0x72, 0x4c, 0x62, 0x85, 0x41, 0x72, 0x16, 0x15, 0x2b, 0xac, 0x23, 0x11, 0x12, 0x9d, 0x7d, 0xba, 0xaa, 0x73, 0x77, 0x1e, 0xfd, 0x74, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x48, 0x06, 0x12, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x14, 0x17, 0x16, 0x33, 0x02, 0x64, 0xb6, 0x99, 0x65, 0x61, 0x63, 0x7c, 0xf7, 0x4d, 0x48, 0x49, 0x45, 0x46, 0x48, 0x46, 0x48, 0xa1, 0x59, 0x33, 0x01, 0x34, 0x4d, 0xad, 0x03, 0x1e, 0xfc, 0xe2, 0x02, 0x8c, 0x1e, 0x77, 0x73, 0xaa, 0xba, 0x7d, 0x9d, 0x12, 0x11, 0x23, 0xac, 0x2b, 0x15, 0x16, 0x72, 0x41, 0x85, 0x62, 0x4c, 0x72, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x48, 0x06, 0x12, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x13, 0x33, 0x11, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x34, 0x27, 0x26, 0x23, 0x01, 0x32, 0x01, 0xb6, 0x99, 0x64, 0x62, 0x62, 0x7d, 0xf7, 0x4d, 0x49, 0x48, 0x45, 0x46, 0x47, 0x47, 0x48, 0xa1, 0x59, 0x33, 0x01, 0x34, 0x4d, 0xad, 0x02, 0xf4, 0x03, 0x1e, 0xfd, 0x74, 0x1e, 0x77, 0x73, 0xaa, 0xba, 0x7d, 0x9d, 0x12, 0x11, 0x23, 0xac, 0x2b, 0x15, 0x16, 0x72, 0x41, 0x85, 0x62, 0x4c, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xfe, 0x4c, 0x03, 0x48, 0x06, 0x14, 0x00, 0x23, 0x00, 0x00, 0x13, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x4f, 0x63, 0x7c, 0xf7, 0x4d, 0x48, 0x49, 0x45, 0x42, 0x4c, 0x46, 0x48, 0x9f, 0x5b, 0x34, 0x34, 0x5c, 0x9e, 0x48, 0x46, 0x48, 0x46, 0x45, 0x49, 0x48, 0x4d, 0xf7, 0x7c, 0x63, 0x04, 0x40, 0xba, 0x7d, 0x9d, 0x12, 0x11, 0x23, 0xac, 0x28, 0x18, 0x16, 0x72, 0x41, 0x85, 0xfb, 0xe0, 0x85, 0x41, 0x72, 0x16, 0x15, 0x2b, 0xac, 0x23, 0x11, 0x12, 0x9d, 0x7d, 0xba, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x0d, 0x00, 0x17, 0x00, 0x22, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x06, 0x22, 0x27, 0x26, 0x00, 0x20, 0x02, 0x11, 0x10, 0x12, 0x20, 0x12, 0x11, 0x10, 0x01, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x10, 0x00, 0x02, 0x70, 0x1e, 0x1d, 0x2b, 0x2a, 0x1e, 0x1d, 0x3b, 0x55, 0x1d, 0x1e, 0x01, 0x2c, 0xfe, 0x74, 0xe9, 0xe9, 0x01, 0x8c, 0xe8, 0xfe, 0x52, 0x01, 0x1b, 0x01, 0x52, 0xfe, 0xae, 0xfe, 0xe5, 0xfe, 0xe5, 0xfe, 0xad, 0x01, 0x53, 0x02, 0xe9, 0x2e, 0x22, 0x22, 0x22, 0x22, 0x2e, 0x2f, 0x42, 0x21, 0x21, 0x02, 0x92, 0xfe, 0xb8, 0xfe, 0xe5, 0xfe, 0xe6, 0xfe, 0xb8, 0x01, 0x48, 0x01, 0x1a, 0x01, 0x1b, 0x01, 0xec, 0xfe, 0x5b, 0xfe, 0x9e, 0xfe, 0x9f, 0xfe, 0x5b, 0x01, 0xa4, 0x02, 0xc4, 0x01, 0xa5, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xd2, 0x04, 0x60, 0x10, 0x06, 0x03, 0xc6, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x4b, 0x04, 0x7c, 0x00, 0x1a, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x20, 0x17, 0x16, 0x11, 0x10, 0x00, 0x21, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x02, 0x0b, 0x6b, 0x3e, 0x3f, 0x3d, 0x3c, 0x69, 0x8b, 0x85, 0x7b, 0x41, 0x46, 0x4b, 0x4d, 0x88, 0xbd, 0x5d, 0x59, 0x59, 0x57, 0xef, 0x01, 0x3e, 0x88, 0x88, 0xfe, 0xf4, 0xfe, 0xe5, 0xd6, 0xe8, 0x7c, 0x70, 0x65, 0x36, 0x36, 0x66, 0x66, 0x03, 0xdc, 0x2e, 0x2e, 0x40, 0x46, 0x2d, 0x2c, 0x98, 0x33, 0x38, 0x58, 0x5a, 0x38, 0x38, 0x74, 0x6f, 0xd0, 0xcd, 0x72, 0x6e, 0xa0, 0x9e, 0x9d, 0xfe, 0xee, 0xfe, 0xf2, 0xfe, 0xc2, 0xb6, 0xad, 0x6c, 0x92, 0x18, 0x18, 0x41, 0x40, 0x5d, 0x8d, 0x4f, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x05, 0x37, 0x06, 0x14, 0x00, 0x27, 0x00, 0x00, 0x25, 0x11, 0x23, 0x35, 0x21, 0x11, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x16, 0x17, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x11, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x03, 0x4b, 0x8b, 0x01, 0x21, 0x5b, 0xc2, 0x6e, 0xe4, 0xfe, 0xf4, 0x01, 0x0f, 0xeb, 0x32, 0x5e, 0x2c, 0x93, 0xa3, 0xe5, 0xd0, 0x5f, 0x45, 0x55, 0xad, 0x59, 0xa2, 0xb2, 0xb2, 0xa2, 0x47, 0x6f, 0x9e, 0x01, 0x11, 0x8c, 0xfd, 0xf0, 0x24, 0x24, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x12, 0x01, 0x3a, 0x0f, 0x0f, 0x21, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0xfe, 0xe5, 0x3e, 0x3e, 0xe3, 0xcd, 0xcd, 0xe3, 0x0f, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x0e, 0x04, 0x60, 0x10, 0x06, 0x03, 0xd1, 0x00, 0x00, 0x00, 0x03, 0xff, 0x0d, 0xfe, 0x56, 0x01, 0xf7, 0x06, 0x14, 0x00, 0x03, 0x00, 0x12, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x15, 0x33, 0x11, 0x33, 0x15, 0x23, 0x06, 0x07, 0x06, 0x23, 0x20, 0x35, 0x34, 0x3b, 0x01, 0x07, 0x23, 0x22, 0x15, 0x14, 0x33, 0x32, 0x37, 0x36, 0xae, 0xa5, 0xa5, 0xa5, 0xa3, 0xaa, 0x10, 0x32, 0x43, 0xa9, 0xfe, 0xef, 0xf3, 0xae, 0x08, 0xa5, 0x69, 0x73, 0x56, 0x26, 0x1a, 0x06, 0x14, 0xe9, 0xcb, 0xfb, 0xa0, 0x8b, 0x78, 0x47, 0x60, 0xdd, 0xcd, 0x8b, 0x42, 0x41, 0x30, 0x20, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x4c, 0x04, 0x26, 0x04, 0x60, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x23, 0x11, 0x01, 0x23, 0x09, 0x01, 0x33, 0x01, 0x11, 0x33, 0x04, 0x26, 0xa6, 0xfe, 0x11, 0xd3, 0x02, 0x16, 0xfd, 0xd3, 0xd8, 0x02, 0x01, 0xa6, 0xfe, 0x4c, 0x03, 0x97, 0xfe, 0x1d, 0x02, 0x0c, 0x02, 0x54, 0xfd, 0xdd, 0x02, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x8d, 0x04, 0x60, 0x00, 0x05, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x15, 0x21, 0xa7, 0xa6, 0x02, 0x3f, 0xfd, 0x1b, 0x04, 0x60, 0xfc, 0x33, 0x93, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x05, 0x60, 0x06, 0x12, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x00, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x01, 0x11, 0x96, 0x83, 0x84, 0x97, 0x97, 0x84, 0x83, 0x96, 0x02, 0x34, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0x93, 0xa3, 0xe4, 0xd0, 0x5e, 0x45, 0xa7, 0x02, 0x2f, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0xfd, 0xae, 0x64, 0x61, 0x01, 0x44, 0x01, 0x08, 0x01, 0x08, 0x01, 0x44, 0x61, 0x64, 0xc6, 0xd6, 0xc0, 0x9c, 0x61, 0x99, 0xf9, 0xda, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x48, 0x06, 0x12, 0x00, 0x24, 0x00, 0x00, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x15, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x01, 0x32, 0x39, 0xac, 0x4e, 0x34, 0x01, 0x33, 0x59, 0xa1, 0x48, 0x47, 0x47, 0x46, 0x45, 0x48, 0x49, 0x4d, 0xf7, 0x7d, 0x62, 0x62, 0x64, 0x99, 0xd0, 0xd0, 0xb6, 0xce, 0xcd, 0x03, 0x1e, 0x72, 0x4c, 0x62, 0x85, 0x41, 0x72, 0x16, 0x15, 0x2b, 0xac, 0x23, 0x11, 0x12, 0x9d, 0x7d, 0xba, 0xaa, 0x73, 0x77, 0x1e, 0xd4, 0xa4, 0xfe, 0xec, 0x01, 0x14, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x48, 0x06, 0x12, 0x00, 0x24, 0x00, 0x00, 0x13, 0x35, 0x33, 0x35, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0xde, 0xd0, 0x99, 0x65, 0x61, 0x63, 0x7c, 0xf7, 0x4d, 0x48, 0x49, 0x45, 0x47, 0x47, 0x46, 0x48, 0xa1, 0x59, 0x33, 0x01, 0x34, 0x4d, 0xad, 0x38, 0xce, 0xce, 0xb6, 0x01, 0x14, 0xa4, 0xd4, 0x1e, 0x77, 0x73, 0xaa, 0xba, 0x7d, 0x9d, 0x12, 0x11, 0x23, 0xac, 0x2b, 0x15, 0x16, 0x72, 0x41, 0x85, 0x62, 0x4c, 0x72, 0xfe, 0x9a, 0xa4, 0xfe, 0xec, 0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x65, 0xff, 0xe3, 0x06, 0xfd, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x26, 0x00, 0x29, 0x00, 0x00, 0x00, 0x10, 0x17, 0x16, 0x20, 0x37, 0x36, 0x10, 0x27, 0x26, 0x20, 0x07, 0x25, 0x11, 0x33, 0x11, 0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x2b, 0x01, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x11, 0x01, 0x01, 0x11, 0x4a, 0x4c, 0x01, 0x07, 0x4b, 0x4c, 0x4c, 0x4b, 0xfe, 0xf9, 0x4c, 0x01, 0xea, 0xa6, 0x03, 0x11, 0xfd, 0x92, 0x02, 0x6e, 0xfc, 0xef, 0x18, 0x8e, 0x34, 0x4f, 0x50, 0x70, 0xb7, 0x73, 0x72, 0x72, 0x73, 0xb7, 0x70, 0x50, 0x4f, 0xda, 0x02, 0x57, 0x02, 0xfa, 0xfe, 0x6a, 0x74, 0x73, 0x73, 0x74, 0x01, 0x96, 0x74, 0x73, 0x73, 0x48, 0x02, 0x5e, 0xfe, 0x4c, 0xa8, 0xfc, 0xdb, 0x93, 0xa8, 0x64, 0x30, 0x31, 0xa2, 0xa2, 0x02, 0x10, 0xa2, 0xa2, 0x31, 0x30, 0x4d, 0xfc, 0xf9, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x4c, 0x07, 0x4d, 0x06, 0x14, 0x00, 0x34, 0x00, 0x40, 0x00, 0x00, 0x01, 0x11, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x11, 0x33, 0x11, 0x21, 0x15, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x04, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x04, 0x10, 0x17, 0x16, 0x20, 0x37, 0x36, 0x10, 0x27, 0x26, 0x20, 0x07, 0x03, 0xeb, 0xa6, 0x34, 0x4f, 0x50, 0x70, 0xb7, 0x73, 0x72, 0x72, 0x73, 0xb7, 0x70, 0x50, 0x4f, 0x34, 0xa6, 0x03, 0x12, 0xfe, 0x8e, 0x60, 0x73, 0x58, 0x4e, 0x48, 0xfe, 0xef, 0xfc, 0x55, 0x59, 0x5a, 0x5f, 0x4b, 0xb4, 0x62, 0xab, 0x5a, 0x5a, 0x53, 0x54, 0x95, 0x9c, 0x01, 0x83, 0xfa, 0xce, 0x4a, 0x4c, 0x01, 0x07, 0x4b, 0x4c, 0x4c, 0x4b, 0xfe, 0xf9, 0x4c, 0x03, 0xcd, 0xfc, 0x33, 0xa8, 0x64, 0x30, 0x31, 0xa2, 0xa2, 0x02, 0x10, 0xa2, 0xa2, 0x31, 0x30, 0x64, 0x02, 0x5e, 0xfe, 0x4c, 0xa8, 0xfe, 0x24, 0x38, 0x2a, 0x6d, 0x68, 0x8a, 0xdd, 0xf2, 0x12, 0x13, 0x25, 0xc3, 0x31, 0x32, 0x4b, 0x4b, 0x8f, 0x84, 0x4b, 0x4a, 0xa6, 0x01, 0xf3, 0xd3, 0xfe, 0x6a, 0x74, 0x73, 0x73, 0x74, 0x01, 0x96, 0x74, 0x73, 0x73, 0x00, 0x00, 0x00, 0x04, 0x00, 0x65, 0xff, 0x91, 0x06, 0xfc, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x33, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x10, 0x17, 0x16, 0x20, 0x37, 0x36, 0x10, 0x27, 0x26, 0x20, 0x07, 0x25, 0x11, 0x01, 0x25, 0x21, 0x15, 0x01, 0x33, 0x12, 0x33, 0x32, 0x15, 0x16, 0x21, 0x23, 0x06, 0x15, 0x23, 0x34, 0x37, 0x21, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x11, 0x33, 0x01, 0x33, 0x32, 0x35, 0x34, 0x23, 0x06, 0x01, 0x11, 0x4a, 0x4c, 0x01, 0x07, 0x4b, 0x4c, 0x4c, 0x4b, 0xfe, 0xf9, 0x4c, 0x02, 0x90, 0x02, 0x56, 0xfd, 0xaa, 0x03, 0x10, 0xfd, 0x92, 0x9d, 0x36, 0xc5, 0xcd, 0x01, 0xfe, 0xd4, 0x25, 0x03, 0x8a, 0x03, 0xfe, 0xba, 0x8d, 0x34, 0x4f, 0x50, 0x70, 0xb7, 0x73, 0x72, 0x72, 0x73, 0xb7, 0x70, 0x50, 0x4f, 0x34, 0xa6, 0x01, 0xca, 0x12, 0x9c, 0x3f, 0x4f, 0x02, 0xfa, 0xfe, 0x6a, 0x74, 0x73, 0x73, 0x74, 0x01, 0x96, 0x74, 0x73, 0x73, 0x5f, 0xfc, 0xfa, 0x03, 0x06, 0x93, 0xa8, 0xfc, 0xdb, 0x01, 0x20, 0xf6, 0xbd, 0x33, 0x3c, 0x3b, 0x34, 0xa8, 0x64, 0x30, 0x31, 0xa2, 0xa2, 0x02, 0x10, 0xa2, 0xa2, 0x31, 0x30, 0x64, 0x02, 0x5e, 0xfa, 0x7f, 0x36, 0x5b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x31, 0x00, 0x00, 0x05, 0xa0, 0x05, 0x9e, 0x00, 0x37, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x14, 0x17, 0x16, 0x33, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x23, 0x21, 0x22, 0x27, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x01, 0x52, 0x01, 0x55, 0xfe, 0xab, 0x21, 0x22, 0x67, 0x02, 0x07, 0x75, 0x3f, 0x3f, 0x55, 0xa0, 0x39, 0x9a, 0x89, 0xc9, 0xba, 0x5c, 0xa2, 0x44, 0x46, 0x97, 0x51, 0x7c, 0x7b, 0x58, 0x85, 0x39, 0xb2, 0x93, 0x70, 0x44, 0xed, 0xfd, 0xfd, 0xbf, 0x49, 0x49, 0x79, 0x79, 0x05, 0x9e, 0xfe, 0xc2, 0x8f, 0xfd, 0xa0, 0x89, 0x27, 0x27, 0x2d, 0x2c, 0x34, 0x49, 0x4d, 0x2a, 0x0f, 0x24, 0x95, 0x82, 0x9e, 0xac, 0x1e, 0x1e, 0xae, 0x28, 0x28, 0x54, 0x54, 0x40, 0x49, 0x21, 0x0e, 0x2c, 0x97, 0x89, 0x92, 0x65, 0x3e, 0x50, 0x4f, 0xd2, 0x02, 0x60, 0x8f, 0x01, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x31, 0xfe, 0x56, 0x04, 0x88, 0x06, 0x14, 0x00, 0x26, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x11, 0x21, 0x30, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x13, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x01, 0x02, 0x11, 0x21, 0x11, 0x14, 0x17, 0x16, 0x33, 0x01, 0x52, 0x01, 0x52, 0x4e, 0x49, 0xb0, 0x9c, 0x9e, 0x59, 0x22, 0x24, 0x02, 0x49, 0x49, 0xa3, 0x3f, 0x2c, 0x5e, 0x22, 0x23, 0xab, 0xbf, 0x49, 0x49, 0x79, 0x79, 0x01, 0xfb, 0x02, 0xfe, 0xae, 0x21, 0x22, 0x67, 0x05, 0x9e, 0xfe, 0xc2, 0x4e, 0xb5, 0x5b, 0x56, 0x99, 0x28, 0x28, 0x68, 0xfb, 0x29, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x31, 0x99, 0x14, 0x50, 0x4f, 0xd2, 0x02, 0x60, 0x8f, 0x01, 0x3e, 0xfa, 0xfc, 0x01, 0xa2, 0x01, 0x95, 0xfd, 0xa0, 0x89, 0x27, 0x27, 0x00, 0x03, 0x00, 0x31, 0xff, 0x70, 0x05, 0x35, 0x05, 0x9e, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x44, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x10, 0x1f, 0x01, 0x36, 0x33, 0x20, 0x17, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x06, 0x15, 0x07, 0x34, 0x37, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x01, 0x16, 0x33, 0x32, 0x37, 0x36, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x05, 0x26, 0x35, 0x10, 0x37, 0x21, 0x11, 0x14, 0x17, 0x16, 0x33, 0x01, 0x52, 0x01, 0x55, 0x86, 0xe5, 0x4d, 0x49, 0x48, 0x45, 0x46, 0x47, 0x47, 0x48, 0xa1, 0x59, 0x59, 0x59, 0x07, 0x48, 0xb9, 0x01, 0x0d, 0x01, 0x5b, 0x44, 0x8d, 0x4b, 0x42, 0x02, 0x8a, 0x06, 0xfa, 0xbf, 0x49, 0x49, 0x79, 0x79, 0x02, 0xe8, 0x3c, 0x4a, 0x56, 0x13, 0x1c, 0x01, 0x01, 0x76, 0x67, 0x24, 0x04, 0xfe, 0xf4, 0x73, 0x7d, 0xfe, 0xbd, 0x21, 0x22, 0x67, 0x05, 0x9e, 0xfe, 0xc2, 0x7a, 0x95, 0x11, 0x12, 0x23, 0xac, 0x2b, 0x16, 0x15, 0x71, 0x72, 0xfe, 0x66, 0x72, 0x09, 0xab, 0xf6, 0x76, 0x29, 0x1e, 0x12, 0x32, 0x4c, 0x03, 0x4f, 0x41, 0x50, 0x4f, 0xd2, 0x02, 0x60, 0x8f, 0x01, 0x3e, 0xfa, 0xf9, 0x18, 0x07, 0x0b, 0x27, 0x4b, 0x56, 0x0a, 0x09, 0x9d, 0xf8, 0x01, 0x07, 0x9b, 0xfd, 0xa0, 0x89, 0x27, 0x27, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2a, 0xfe, 0x56, 0x05, 0xcb, 0x06, 0x14, 0x00, 0x35, 0x00, 0x00, 0x01, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x21, 0x3b, 0x01, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x05, 0xca, 0x4a, 0x48, 0xa3, 0xe5, 0xd2, 0x5e, 0x22, 0x23, 0x70, 0x6f, 0x87, 0x9a, 0xa7, 0xfe, 0xf1, 0xa6, 0x9f, 0x9f, 0x4e, 0x4e, 0xaa, 0x9d, 0x9e, 0x5a, 0x23, 0x22, 0x01, 0x0f, 0x02, 0xa5, 0x3b, 0x50, 0x51, 0x69, 0xae, 0x59, 0x59, 0x02, 0xa4, 0xfd, 0x48, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x31, 0x99, 0x02, 0xb2, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x03, 0xd1, 0xfc, 0x2f, 0x03, 0xd1, 0x8f, 0x4e, 0xbb, 0x55, 0x56, 0x99, 0x28, 0x28, 0x68, 0x63, 0xae, 0x65, 0x32, 0x32, 0x77, 0x78, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x04, 0xbb, 0x06, 0x14, 0x00, 0x27, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x23, 0x21, 0xae, 0xa5, 0x01, 0xca, 0x75, 0x3f, 0x3f, 0x54, 0xa0, 0x3a, 0x9a, 0x89, 0xca, 0xb9, 0x5c, 0xa2, 0x44, 0x46, 0x97, 0x51, 0x7b, 0x7b, 0x58, 0x85, 0x39, 0xb2, 0x92, 0x6f, 0x45, 0xec, 0xfd, 0x94, 0x06, 0x14, 0xfa, 0x86, 0x2d, 0x2c, 0x34, 0x49, 0x4d, 0x2a, 0x0f, 0x24, 0x95, 0x82, 0x9e, 0xac, 0x1e, 0x1e, 0xae, 0x28, 0x28, 0x54, 0x54, 0x40, 0x49, 0x21, 0x0e, 0x2c, 0x97, 0x89, 0x92, 0x65, 0x3e, 0x00, 0x00, 0x02, 0x00, 0xad, 0x00, 0x00, 0x04, 0x65, 0x06, 0x14, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x2b, 0x01, 0x13, 0x11, 0x01, 0xae, 0xa5, 0x03, 0x12, 0xfd, 0x91, 0x02, 0x6f, 0xfc, 0xee, 0x17, 0x8e, 0xa5, 0x02, 0x58, 0x06, 0x14, 0xfe, 0x4c, 0xa8, 0xfc, 0xdb, 0x93, 0x03, 0xcd, 0xfc, 0xf9, 0x03, 0x07, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xe2, 0x03, 0x85, 0x05, 0x1f, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x00, 0x13, 0x33, 0x1b, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x23, 0x0b, 0x01, 0x23, 0x03, 0x33, 0x1b, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x23, 0x0b, 0x01, 0x23, 0x31, 0x68, 0x83, 0x81, 0x7b, 0x83, 0x81, 0x69, 0xa7, 0x7a, 0x89, 0x89, 0x7b, 0xa6, 0x68, 0x83, 0x81, 0x7b, 0x83, 0x81, 0x69, 0xa7, 0x7a, 0x89, 0x89, 0x7b, 0x02, 0x55, 0xfe, 0x17, 0x01, 0xe9, 0xfe, 0x17, 0x01, 0xe9, 0xfd, 0x8d, 0x02, 0x02, 0xfd, 0xfe, 0x05, 0x3d, 0xfe, 0x17, 0x01, 0xe9, 0xfe, 0x17, 0x01, 0xe9, 0xfd, 0x8d, 0x02, 0x02, 0xfd, 0xfe, 0x00, 0x02, 0x00, 0x30, 0x00, 0xad, 0x03, 0x85, 0x05, 0x1f, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x31, 0x03, 0x54, 0x81, 0xfd, 0xad, 0x80, 0x03, 0x54, 0x81, 0xfd, 0xad, 0x80, 0x02, 0x55, 0xfe, 0x58, 0x01, 0x05, 0xfe, 0xfb, 0x04, 0x72, 0xfe, 0x58, 0x01, 0x05, 0xfe, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x4a, 0x04, 0x1c, 0x06, 0x14, 0x00, 0x19, 0x00, 0x00, 0x25, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x16, 0x15, 0x11, 0x10, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x03, 0x75, 0x77, 0xcf, 0xae, 0xb2, 0x44, 0x5f, 0x2c, 0x3f, 0xa3, 0x93, 0xdf, 0x86, 0x9b, 0xa6, 0xa6, 0xac, 0xc9, 0xef, 0xe8, 0x02, 0xc4, 0x99, 0x61, 0x9c, 0xc0, 0xd6, 0xfd, 0x42, 0xfe, 0xc3, 0xbe, 0xa4, 0x02, 0x79, 0xf9, 0xec, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x56, 0x04, 0xeb, 0x06, 0x14, 0x00, 0x21, 0x00, 0x00, 0x25, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x16, 0x15, 0x11, 0x10, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x06, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x27, 0x03, 0x75, 0x77, 0xcf, 0xae, 0xb2, 0x44, 0x5f, 0x2c, 0x3f, 0xa3, 0x93, 0xdf, 0x86, 0x9b, 0xa6, 0x03, 0x48, 0x5d, 0x2d, 0x3f, 0xa4, 0x8e, 0x04, 0xac, 0xc9, 0xef, 0xe8, 0x02, 0xc4, 0x99, 0x61, 0x9c, 0xc0, 0xd6, 0xfd, 0x42, 0xfe, 0xc3, 0xbe, 0xa4, 0x02, 0x79, 0xfb, 0x8e, 0x94, 0x66, 0x9c, 0xb9, 0xdd, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x02, 0x7e, 0x06, 0x03, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x02, 0x7d, 0x68, 0x46, 0x47, 0x54, 0x61, 0x6a, 0x6a, 0x25, 0x65, 0x43, 0x6d, 0x70, 0x04, 0x17, 0xfe, 0x85, 0x01, 0x77, 0x59, 0x59, 0x6b, 0x5c, 0xfe, 0x9e, 0x03, 0x67, 0xfe, 0xab, 0x38, 0x38, 0x86, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x02, 0x7e, 0x06, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x02, 0x7d, 0x68, 0x46, 0x47, 0x54, 0x61, 0x6a, 0x5d, 0x67, 0x90, 0x84, 0x3b, 0x2b, 0x25, 0x65, 0x43, 0x6d, 0x70, 0x04, 0x17, 0xfe, 0x85, 0x01, 0x77, 0x59, 0x59, 0x6b, 0x5c, 0xfe, 0x9e, 0x02, 0x84, 0x78, 0x6b, 0x57, 0x36, 0x56, 0x72, 0x38, 0x38, 0x86, 0x00, 0x02, 0xff, 0xeb, 0x01, 0xad, 0x00, 0xd7, 0x06, 0x03, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x00, 0x13, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x15, 0x23, 0x6e, 0x68, 0x2f, 0x2d, 0x67, 0x28, 0x1c, 0x3c, 0x15, 0x16, 0x68, 0x68, 0x05, 0x0f, 0xfd, 0x82, 0x78, 0x36, 0x36, 0x58, 0x1b, 0x1b, 0x56, 0x03, 0x72, 0x82, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x01, 0xdd, 0x05, 0x1e, 0x00, 0x11, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x01, 0xdd, 0x11, 0x2a, 0x19, 0x58, 0x5e, 0x6a, 0x6a, 0x20, 0x69, 0x4c, 0x0b, 0x1a, 0x10, 0x04, 0xaf, 0x0a, 0x09, 0x71, 0x6b, 0xfe, 0xb6, 0x02, 0x73, 0x61, 0x39, 0x37, 0x02, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x02, 0x8d, 0x01, 0xb4, 0x05, 0x0f, 0x00, 0x11, 0x00, 0x00, 0x13, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x41, 0x11, 0x29, 0x19, 0x59, 0x5e, 0x69, 0x69, 0x20, 0x69, 0x4c, 0x0b, 0x1a, 0x10, 0x02, 0xfc, 0x0a, 0x09, 0x71, 0x6b, 0x01, 0x4a, 0xfd, 0x8d, 0x61, 0x39, 0x37, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x01, 0xad, 0x02, 0x37, 0x05, 0x0f, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x15, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x3d, 0x02, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x41, 0x11, 0x29, 0x19, 0x59, 0x5e, 0x69, 0x2b, 0x3b, 0x1c, 0x28, 0x66, 0x5d, 0x20, 0x69, 0x4c, 0x0b, 0x1a, 0x10, 0x02, 0xfc, 0x0a, 0x09, 0x71, 0x6b, 0x01, 0x4a, 0xfd, 0x8d, 0x0b, 0x56, 0x36, 0x58, 0x6c, 0x78, 0x0b, 0x61, 0x39, 0x37, 0x02, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1c, 0x02, 0x9c, 0x02, 0x4e, 0x05, 0x0f, 0x00, 0x16, 0x00, 0x21, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x11, 0x33, 0x11, 0x33, 0x32, 0x37, 0x36, 0x3f, 0x01, 0x33, 0x07, 0x06, 0x07, 0x06, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x01, 0x72, 0x3c, 0x3f, 0x3c, 0x3d, 0x7c, 0xdb, 0x68, 0x61, 0x36, 0x22, 0x21, 0x24, 0x5c, 0x6f, 0x64, 0x1d, 0x1e, 0x1f, 0xfe, 0xf5, 0x71, 0x43, 0x23, 0x25, 0x25, 0x23, 0x43, 0x71, 0x03, 0xe9, 0x0f, 0x4e, 0x3b, 0x5b, 0x2d, 0x2d, 0x02, 0x73, 0xfe, 0xf7, 0x15, 0x14, 0x3f, 0xa1, 0xab, 0x35, 0x1e, 0x1e, 0xff, 0x00, 0x17, 0x18, 0x2f, 0x2e, 0x18, 0x19, 0x00, 0x01, 0x00, 0x30, 0x02, 0x9c, 0x03, 0x85, 0x05, 0x0f, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x1b, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x23, 0x0b, 0x01, 0x23, 0x31, 0x68, 0x83, 0x81, 0x7b, 0x83, 0x81, 0x69, 0xa7, 0x7a, 0x89, 0x89, 0x7b, 0x05, 0x0f, 0xfe, 0x17, 0x01, 0xe9, 0xfe, 0x17, 0x01, 0xe9, 0xfd, 0x8d, 0x02, 0x02, 0xfd, 0xfe, 0x00, 0x01, 0x00, 0x22, 0x01, 0xad, 0x02, 0x8d, 0x05, 0x0f, 0x00, 0x11, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3f, 0x01, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x01, 0x76, 0x2d, 0x2a, 0x29, 0x46, 0x54, 0x3d, 0x2b, 0x18, 0x18, 0x1d, 0x13, 0xfe, 0xfe, 0x6f, 0xc7, 0xc6, 0x6e, 0x02, 0x62, 0x70, 0x22, 0x23, 0x57, 0x14, 0x14, 0x4b, 0x2f, 0x02, 0x69, 0xfe, 0x16, 0x01, 0xea, 0x00, 0xff, 0xff, 0x00, 0x90, 0x04, 0x74, 0x01, 0x76, 0x06, 0x66, 0x10, 0x06, 0x03, 0x12, 0x00, 0x00, 0xff, 0xff, 0x00, 0x90, 0x04, 0x74, 0x02, 0xc5, 0x06, 0x66, 0x10, 0x26, 0x03, 0x12, 0x00, 0x00, 0x10, 0x07, 0x03, 0x12, 0x01, 0x4f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0x03, 0xe9, 0x01, 0xa5, 0x05, 0xd5, 0x10, 0x06, 0x07, 0x4d, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0x03, 0xfe, 0x01, 0xa8, 0x05, 0xd5, 0x10, 0x06, 0x07, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x04, 0xee, 0x01, 0xb9, 0x06, 0xda, 0x00, 0x05, 0x00, 0x00, 0x01, 0x15, 0x13, 0x23, 0x03, 0x35, 0x01, 0x6e, 0x4a, 0x74, 0x94, 0x06, 0xda, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x03, 0xef, 0x01, 0x60, 0x06, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x35, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x35, 0x32, 0x17, 0x16, 0x14, 0x07, 0x06, 0x69, 0x3a, 0x4f, 0x4f, 0x3a, 0x68, 0x48, 0x47, 0x47, 0x48, 0x03, 0xef, 0x7b, 0x58, 0x40, 0x3f, 0x58, 0x7b, 0x50, 0x4f, 0xe6, 0x50, 0x50, 0x00, 0x01, 0x00, 0x69, 0x03, 0xef, 0x01, 0x60, 0x06, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x33, 0x15, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x01, 0x60, 0x68, 0x48, 0x47, 0x47, 0x48, 0x68, 0x3a, 0x4f, 0x4f, 0x3a, 0x03, 0xef, 0x50, 0x50, 0xe6, 0x4f, 0x50, 0x7b, 0x58, 0x3f, 0x40, 0x58, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x02, 0x49, 0x06, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x13, 0x33, 0x32, 0x37, 0x36, 0x35, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x11, 0x23, 0xf8, 0x24, 0x6c, 0x32, 0x20, 0x01, 0x1f, 0x39, 0x65, 0x2e, 0x2c, 0x2d, 0x2c, 0x2b, 0x2e, 0x2e, 0x30, 0x9d, 0x4e, 0x3d, 0x3d, 0x3f, 0x60, 0x74, 0x04, 0x5b, 0x40, 0x2a, 0x37, 0x4b, 0x24, 0x40, 0x0c, 0x0c, 0x18, 0x60, 0x14, 0x09, 0x0a, 0x58, 0x46, 0x68, 0x5f, 0x40, 0x43, 0x11, 0xfe, 0x93, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x02, 0x49, 0x06, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x14, 0x17, 0x16, 0x33, 0x01, 0xb9, 0x72, 0x61, 0x40, 0x3d, 0x3e, 0x4f, 0x9b, 0x30, 0x2e, 0x2e, 0x2b, 0x2c, 0x2d, 0x2c, 0x2d, 0x66, 0x38, 0x20, 0x01, 0x21, 0x31, 0x6d, 0x04, 0x5b, 0xfe, 0x41, 0x01, 0x6d, 0x11, 0x43, 0x40, 0x5f, 0x68, 0x46, 0x58, 0x0a, 0x09, 0x14, 0x60, 0x18, 0x0c, 0x0c, 0x40, 0x24, 0x4b, 0x37, 0x2a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf0, 0x04, 0x32, 0x02, 0xaa, 0x06, 0xb0, 0x00, 0x06, 0x00, 0x00, 0x13, 0x25, 0x15, 0x0d, 0x01, 0x15, 0x25, 0xf0, 0x01, 0xb9, 0xfe, 0xbd, 0x01, 0x43, 0xfe, 0x47, 0x05, 0xbb, 0xf5, 0x8b, 0xb4, 0xb4, 0x8b, 0xf5, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf0, 0x04, 0x32, 0x02, 0xaa, 0x06, 0xb0, 0x00, 0x06, 0x00, 0x00, 0x01, 0x05, 0x35, 0x2d, 0x01, 0x35, 0x05, 0x02, 0xa9, 0xfe, 0x47, 0x01, 0x43, 0xfe, 0xbd, 0x01, 0xb9, 0x05, 0x27, 0xf5, 0x8b, 0xb4, 0xb4, 0x8b, 0xf5, 0x00, 0x00, 0x01, 0x00, 0xad, 0x04, 0x7c, 0x02, 0xec, 0x06, 0x66, 0x00, 0x06, 0x00, 0x00, 0x01, 0x33, 0x13, 0x23, 0x0b, 0x01, 0x23, 0x01, 0x8a, 0x85, 0xdd, 0x7d, 0xa2, 0xa2, 0x7d, 0x06, 0x66, 0xfe, 0x16, 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0x04, 0x7c, 0x02, 0xec, 0x06, 0x66, 0x00, 0x06, 0x00, 0x00, 0x01, 0x03, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x01, 0x8a, 0xdc, 0x7d, 0xa2, 0xa2, 0x7d, 0xdd, 0x04, 0x7c, 0x01, 0xea, 0xfe, 0x99, 0x01, 0x67, 0xfe, 0x16, 0x00, 0x00, 0x01, 0x00, 0xad, 0x04, 0xee, 0x02, 0xec, 0x06, 0x66, 0x00, 0x06, 0x00, 0x00, 0x01, 0x33, 0x13, 0x23, 0x27, 0x07, 0x23, 0x01, 0x8a, 0x85, 0xdd, 0x7d, 0xa2, 0xa2, 0x7d, 0x06, 0x66, 0xfe, 0x88, 0xf5, 0xf5, 0x00, 0x00, 0x01, 0x00, 0xad, 0x04, 0xee, 0x02, 0xec, 0x06, 0x66, 0x00, 0x06, 0x00, 0x00, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x01, 0x8a, 0xdc, 0x7d, 0xa2, 0xa2, 0x7d, 0xdd, 0x04, 0xee, 0x01, 0x78, 0xf5, 0xf5, 0xfe, 0x88, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x03, 0xe7, 0x01, 0x3b, 0x06, 0x12, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x01, 0x3b, 0x7a, 0x06, 0x12, 0xfd, 0xd5, 0x02, 0x2b, 0x00, 0xff, 0xff, 0x00, 0xbf, 0x05, 0x62, 0x02, 0xda, 0x05, 0xf6, 0x10, 0x06, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x01, 0x4d, 0x04, 0xee, 0x02, 0xfd, 0x06, 0x66, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x01, 0x23, 0x02, 0x4a, 0xb3, 0xfe, 0xdb, 0x8a, 0x06, 0x66, 0xfe, 0x88, 0x00, 0x01, 0x00, 0x99, 0x04, 0xf0, 0x02, 0x49, 0x06, 0x66, 0x00, 0x03, 0x00, 0x00, 0x01, 0x13, 0x23, 0x01, 0x01, 0x4a, 0xfe, 0x8a, 0xfe, 0xdb, 0x06, 0x66, 0xfe, 0x8a, 0x01, 0x76, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0xfe, 0xd1, 0x01, 0x3b, 0x00, 0xfc, 0x00, 0x03, 0x00, 0x00, 0x25, 0x11, 0x23, 0x11, 0x01, 0x3b, 0x7a, 0xfc, 0xfd, 0xd5, 0x02, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x00, 0xbf, 0xfe, 0xc0, 0x02, 0xda, 0xff, 0x54, 0x10, 0x07, 0x00, 0x71, 0x00, 0x00, 0xf9, 0x5e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x99, 0xfe, 0x1c, 0x02, 0x49, 0xff, 0x92, 0x00, 0x03, 0x00, 0x00, 0x05, 0x13, 0x23, 0x01, 0x01, 0x4a, 0xfe, 0x8a, 0xfe, 0xdb, 0x6e, 0xfe, 0x8a, 0x01, 0x76, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x4d, 0xfe, 0x1c, 0x02, 0xfd, 0xff, 0x94, 0x00, 0x03, 0x00, 0x00, 0x05, 0x33, 0x01, 0x23, 0x02, 0x4a, 0xb3, 0xfe, 0xdb, 0x8a, 0x6c, 0xfe, 0x88, 0x00, 0x00, 0x02, 0x00, 0x63, 0x00, 0x00, 0x01, 0xa6, 0x04, 0x23, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x01, 0x03, 0x21, 0x03, 0x13, 0x21, 0x01, 0x04, 0xa0, 0x01, 0x41, 0xa1, 0xa1, 0xfe, 0xbf, 0x02, 0xd9, 0x01, 0x4a, 0xfd, 0x27, 0xfe, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x63, 0x02, 0xd9, 0x01, 0xa6, 0x04, 0x23, 0x00, 0x02, 0x00, 0x00, 0x01, 0x03, 0x21, 0x01, 0x04, 0xa0, 0x01, 0x41, 0x02, 0xd9, 0x01, 0x4a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x01, 0xfe, 0x01, 0x60, 0x04, 0x23, 0x10, 0x07, 0x02, 0x80, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x01, 0xfe, 0x01, 0x60, 0x04, 0x23, 0x10, 0x07, 0x02, 0x81, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0xd4, 0x02, 0x98, 0x03, 0x96, 0x00, 0x07, 0x00, 0x00, 0x01, 0x15, 0x21, 0x35, 0x33, 0x11, 0x33, 0x11, 0x02, 0x97, 0xfe, 0x6b, 0x87, 0x87, 0x02, 0x6a, 0x96, 0x96, 0x01, 0x2c, 0xfe, 0xd4, 0x00, 0x01, 0x01, 0x02, 0x01, 0xd4, 0x02, 0x98, 0x03, 0x96, 0x00, 0x07, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x23, 0x11, 0x23, 0x11, 0x01, 0x02, 0x01, 0x95, 0x87, 0x87, 0x03, 0x00, 0x96, 0x96, 0xfe, 0xd4, 0x01, 0x2c, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xff, 0x02, 0x75, 0x03, 0x55, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x01, 0x24, 0x87, 0xc9, 0xc9, 0x87, 0xca, 0x02, 0x75, 0xe0, 0xe0, 0x96, 0xe0, 0xe0, 0x96, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x01, 0xdf, 0x01, 0xef, 0x02, 0x75, 0x00, 0x03, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x01, 0xef, 0xfe, 0x6b, 0x01, 0x95, 0x01, 0xdf, 0x96, 0x00, 0x00, 0x01, 0x00, 0xb3, 0x05, 0x29, 0x02, 0xe7, 0x06, 0x48, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x33, 0x0e, 0x01, 0x23, 0x22, 0x26, 0xb3, 0x6a, 0x0a, 0x57, 0x4f, 0x4d, 0x57, 0x0b, 0x6a, 0x08, 0x8f, 0x82, 0x83, 0x8e, 0x06, 0x48, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0x00, 0x00, 0x01, 0x01, 0x71, 0x05, 0x44, 0x02, 0x29, 0x06, 0x10, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x01, 0x71, 0xb8, 0xb8, 0x06, 0x10, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xd6, 0x04, 0xe1, 0x02, 0xc4, 0x07, 0x06, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x02, 0x56, 0x50, 0x39, 0x3b, 0x4e, 0x4e, 0x3b, 0x39, 0x50, 0x6d, 0x8f, 0x67, 0x68, 0x8f, 0x8f, 0x68, 0x67, 0x8f, 0x05, 0xf4, 0x3f, 0x58, 0x57, 0x40, 0x41, 0x57, 0x58, 0x40, 0x73, 0xa0, 0xa0, 0x73, 0x73, 0x9f, 0x9f, 0x00, 0x01, 0x01, 0x2a, 0xfe, 0x75, 0x02, 0x7b, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x21, 0x33, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x8c, 0x6b, 0x28, 0x27, 0x31, 0x31, 0x1d, 0x38, 0x1b, 0x22, 0x3d, 0x1b, 0x6e, 0x67, 0x2f, 0x3d, 0x58, 0x1f, 0x2e, 0x2e, 0x0f, 0x0f, 0x85, 0x0a, 0x0a, 0x57, 0x5d, 0x30, 0x69, 0x00, 0x01, 0x00, 0xa3, 0x05, 0x1d, 0x02, 0xf6, 0x06, 0x37, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x33, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x01, 0xc9, 0x33, 0x14, 0x1e, 0x0b, 0x23, 0x20, 0x02, 0x70, 0x02, 0x5b, 0x52, 0x23, 0x39, 0x21, 0x34, 0x14, 0x1d, 0x0c, 0x22, 0x21, 0x01, 0x71, 0x02, 0x5c, 0x52, 0x22, 0x3a, 0x05, 0x5a, 0x37, 0x14, 0x13, 0x49, 0x52, 0x87, 0x93, 0x1c, 0x21, 0x37, 0x14, 0x13, 0x49, 0x52, 0x87, 0x93, 0x1c, 0x00, 0x00, 0x00, 0x02, 0x00, 0xd8, 0x04, 0xee, 0x03, 0x50, 0x06, 0x66, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x03, 0x23, 0x03, 0x33, 0x03, 0x23, 0x02, 0xb0, 0xa0, 0xdf, 0x7a, 0x74, 0x99, 0xc9, 0x7b, 0x06, 0x66, 0xfe, 0x88, 0x01, 0x78, 0xfe, 0x88, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x01, 0xde, 0x02, 0x69, 0x04, 0x08, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x37, 0x33, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x07, 0x01, 0xfa, 0xa6, 0x22, 0x22, 0x5f, 0x26, 0x39, 0x9e, 0x4e, 0x4a, 0xf9, 0x03, 0x64, 0xa4, 0x94, 0x99, 0x31, 0x30, 0x9c, 0x60, 0x5a, 0xc8, 0xa2, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd7, 0x04, 0xee, 0x02, 0xc2, 0x06, 0x66, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x27, 0x07, 0x23, 0x37, 0x27, 0x33, 0x17, 0x37, 0x33, 0x07, 0x17, 0x02, 0x20, 0x53, 0x54, 0xa2, 0xa3, 0xa3, 0xa2, 0x54, 0x53, 0xa2, 0xa4, 0xa4, 0x04, 0xee, 0x61, 0x61, 0xbb, 0xbd, 0x60, 0x60, 0xbd, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0x01, 0xab, 0x02, 0xb1, 0x05, 0x0f, 0x00, 0x0d, 0x00, 0x15, 0x00, 0x00, 0x01, 0x16, 0x15, 0x14, 0x23, 0x22, 0x35, 0x34, 0x37, 0x03, 0x33, 0x17, 0x37, 0x33, 0x01, 0x06, 0x15, 0x14, 0x33, 0x32, 0x35, 0x34, 0x01, 0xd1, 0xa1, 0xda, 0xf1, 0xa3, 0xe1, 0x7c, 0xab, 0xa5, 0x7b, 0xfe, 0xdd, 0x7b, 0x7a, 0x74, 0x03, 0xdc, 0xf9, 0xb4, 0x84, 0x84, 0xbf, 0xf2, 0x01, 0x2f, 0xe0, 0xe0, 0xfe, 0x8a, 0xae, 0x98, 0x4d, 0x4d, 0x89, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6d, 0x02, 0x9c, 0x00, 0xd7, 0x06, 0x03, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x6e, 0x68, 0x68, 0x06, 0x03, 0xfc, 0x99, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x02, 0x4f, 0x05, 0x2f, 0x00, 0x32, 0x00, 0x00, 0x01, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x02, 0x2c, 0x2c, 0x30, 0x2e, 0x34, 0x4e, 0x27, 0x26, 0x1b, 0x1c, 0x54, 0x24, 0x71, 0x2d, 0x2e, 0x46, 0x45, 0x7b, 0x33, 0x38, 0x37, 0x3d, 0x3a, 0x39, 0x37, 0x37, 0x4a, 0x4f, 0x1d, 0x19, 0x64, 0x24, 0x61, 0x2b, 0x2b, 0x40, 0x3f, 0x75, 0x39, 0x34, 0x33, 0x05, 0x0d, 0x61, 0x16, 0x0b, 0x0b, 0x17, 0x18, 0x2f, 0x24, 0x14, 0x15, 0x12, 0x08, 0x18, 0x2a, 0x2b, 0x4d, 0x57, 0x33, 0x33, 0x0a, 0x0a, 0x13, 0x6b, 0x1e, 0x0f, 0x0f, 0x32, 0x2d, 0x2a, 0x17, 0x14, 0x17, 0x08, 0x15, 0x29, 0x2a, 0x49, 0x58, 0x30, 0x31, 0x09, 0x08, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x02, 0xd1, 0x05, 0x0f, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x02, 0xc5, 0xe5, 0xf1, 0x7b, 0xb9, 0xb8, 0x7c, 0xf7, 0xe2, 0x7b, 0xa9, 0xa8, 0x05, 0x0f, 0xfe, 0xcf, 0xfe, 0xbe, 0xf6, 0xf6, 0x01, 0x48, 0x01, 0x2b, 0xdf, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x02, 0x9c, 0x02, 0x49, 0x06, 0x02, 0x10, 0x06, 0x02, 0x83, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x02, 0x53, 0xfe, 0x6e, 0x02, 0x0c, 0x04, 0xd0, 0x88, 0xfa, 0xa8, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x07, 0x00, 0x00, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x02, 0x53, 0xfe, 0x6e, 0x01, 0x92, 0x7a, 0x03, 0x9c, 0x88, 0x01, 0x34, 0xfa, 0xa8, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x07, 0x00, 0x00, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x02, 0x53, 0xfe, 0x6e, 0x01, 0x92, 0x7a, 0x02, 0x68, 0x88, 0x02, 0x68, 0xfa, 0xa8, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x07, 0x00, 0x00, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x02, 0x53, 0xfe, 0x6e, 0x01, 0x92, 0x7a, 0x01, 0x34, 0x88, 0x03, 0x9c, 0xfa, 0xa8, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x25, 0x11, 0x33, 0x11, 0x21, 0x35, 0x02, 0x53, 0x7a, 0xfd, 0xf4, 0x88, 0x04, 0xd0, 0xfa, 0xa8, 0x88, 0x00, 0xff, 0xff, 0x00, 0xad, 0xfd, 0xec, 0x02, 0xec, 0xff, 0xd6, 0x10, 0x07, 0x02, 0x87, 0x00, 0x00, 0xf9, 0x70, 0x00, 0x00, 0xff, 0xff, 0x00, 0xbf, 0x04, 0xe2, 0x02, 0xda, 0x06, 0x76, 0x12, 0x27, 0x00, 0x71, 0x00, 0x00, 0x00, 0x80, 0x12, 0x06, 0x00, 0x71, 0x00, 0x80, 0xff, 0xff, 0x00, 0x9c, 0x03, 0xe9, 0x03, 0x16, 0x05, 0xd5, 0x12, 0x06, 0x07, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0xd6, 0xfe, 0x14, 0x02, 0xc4, 0x00, 0x39, 0x10, 0x07, 0x02, 0x9c, 0x00, 0x00, 0xf9, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa3, 0xfe, 0x76, 0x02, 0xf6, 0xff, 0x90, 0x00, 0x21, 0x00, 0x00, 0x01, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x23, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x01, 0xc9, 0x33, 0x14, 0x0f, 0x0f, 0x0b, 0x23, 0x10, 0x10, 0x02, 0x70, 0x02, 0x2e, 0x2d, 0x52, 0x23, 0x39, 0x21, 0x34, 0x14, 0x0f, 0x0e, 0x0c, 0x22, 0x10, 0x11, 0x01, 0x71, 0x02, 0x2e, 0x2e, 0x52, 0x22, 0x3a, 0xfe, 0xb3, 0x37, 0x14, 0x0a, 0x09, 0x25, 0x24, 0x52, 0x87, 0x49, 0x4a, 0x1c, 0x21, 0x37, 0x14, 0x0a, 0x09, 0x25, 0x24, 0x52, 0x87, 0x49, 0x4a, 0x1c, 0x00, 0x02, 0xfc, 0xfd, 0x04, 0x7b, 0xfe, 0xad, 0x06, 0x66, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x01, 0x13, 0x23, 0x09, 0x01, 0xfd, 0xaf, 0xfe, 0x8a, 0xfe, 0xdb, 0x01, 0x35, 0x06, 0x66, 0xfe, 0x8a, 0x01, 0x76, 0xfe, 0x15, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0xb2, 0x04, 0x7b, 0xff, 0x62, 0x06, 0x66, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x01, 0x33, 0x01, 0x23, 0x17, 0xfe, 0xae, 0xb4, 0xfe, 0xda, 0x8a, 0x81, 0x06, 0x66, 0xfe, 0x88, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x14, 0x04, 0x7b, 0xff, 0x53, 0x06, 0x66, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x13, 0x23, 0x27, 0x07, 0x23, 0x05, 0xfd, 0xf1, 0x85, 0xdc, 0x7d, 0xa2, 0xa2, 0x7d, 0x01, 0x1f, 0x06, 0x66, 0xfe, 0x88, 0xf5, 0xf5, 0x73, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x08, 0x05, 0x1d, 0xff, 0x5b, 0x06, 0x37, 0x10, 0x07, 0x02, 0x9e, 0xfc, 0x65, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x29, 0x05, 0x62, 0xff, 0x44, 0x05, 0xf6, 0x10, 0x07, 0x00, 0x71, 0xfc, 0x6a, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x54, 0x05, 0x7c, 0x00, 0x12, 0x06, 0x0b, 0x10, 0x07, 0x07, 0x73, 0xfc, 0x66, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x12, 0x05, 0x29, 0xff, 0x46, 0x06, 0x48, 0x10, 0x07, 0x02, 0x9a, 0xfc, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0xde, 0x04, 0x7b, 0xfe, 0x85, 0x06, 0x14, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x17, 0xfd, 0xdf, 0xa5, 0xa5, 0x54, 0x06, 0x14, 0xe9, 0xb0, 0x00, 0x00, 0x00, 0x03, 0xfd, 0x27, 0x04, 0x7b, 0xff, 0x3f, 0x06, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x05, 0xfe, 0x88, 0xb6, 0xb6, 0xfe, 0xa0, 0xb7, 0xb7, 0x01, 0x0b, 0x06, 0x10, 0xca, 0xca, 0xca, 0xcb, 0x00, 0x00, 0x01, 0xfd, 0x7e, 0x04, 0xf2, 0xff, 0x12, 0x06, 0x7b, 0x00, 0x19, 0x00, 0x00, 0x01, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0f, 0x01, 0x06, 0x07, 0x06, 0x15, 0x23, 0x35, 0x34, 0x36, 0x3f, 0x01, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0xfd, 0x7e, 0x65, 0x5e, 0x5e, 0x73, 0x50, 0x27, 0x20, 0x03, 0x07, 0x6b, 0x1c, 0x2d, 0x29, 0x29, 0x38, 0x40, 0x51, 0x5a, 0x06, 0x48, 0x33, 0x55, 0x43, 0x3d, 0x41, 0x20, 0x1a, 0x09, 0x10, 0x20, 0x0c, 0x28, 0x36, 0x25, 0x22, 0x22, 0x28, 0x15, 0x24, 0x34, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x3a, 0x04, 0xe1, 0xff, 0x28, 0x07, 0x06, 0x10, 0x07, 0x02, 0x9c, 0xfc, 0x65, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x42, 0x04, 0xee, 0xff, 0xba, 0x06, 0x66, 0x10, 0x07, 0x02, 0x9f, 0xfc, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x17, 0x04, 0x7b, 0xff, 0x56, 0x06, 0x66, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x07, 0xfd, 0xf4, 0xdc, 0x7d, 0xa2, 0xa2, 0x7d, 0xdd, 0x46, 0x04, 0xee, 0x01, 0x78, 0xf5, 0xf5, 0xfe, 0x88, 0x73, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xf6, 0x04, 0xec, 0xfe, 0x71, 0x06, 0xa8, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0xfe, 0x70, 0x7a, 0x06, 0xa8, 0xfe, 0x44, 0x01, 0xbc, 0x00, 0xff, 0xff, 0xfd, 0x3e, 0x04, 0xec, 0xff, 0x28, 0x06, 0xa8, 0x10, 0x27, 0x02, 0xbe, 0xff, 0x48, 0x00, 0x00, 0x10, 0x07, 0x02, 0xbe, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfc, 0xba, 0x04, 0xee, 0xff, 0x32, 0x06, 0x66, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x13, 0x23, 0x03, 0x21, 0x13, 0x23, 0x03, 0xfd, 0x5a, 0xb9, 0x7a, 0xdf, 0x01, 0xcd, 0xab, 0x7b, 0xc9, 0x06, 0x66, 0xfe, 0x88, 0x01, 0x78, 0xfe, 0x88, 0x01, 0x78, 0xff, 0xff, 0xfd, 0x12, 0x05, 0x29, 0xff, 0x46, 0x07, 0x56, 0x10, 0x27, 0x02, 0xb8, 0x00, 0x00, 0x01, 0x42, 0x10, 0x07, 0x02, 0x9a, 0xfc, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x12, 0x05, 0x29, 0xff, 0x46, 0x06, 0x48, 0x00, 0x0c, 0x00, 0x00, 0x03, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0xba, 0x6a, 0x0a, 0x58, 0x4e, 0x4d, 0x57, 0x0c, 0x6a, 0x09, 0x8f, 0x01, 0x04, 0x8f, 0x05, 0x29, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x4f, 0x03, 0xe9, 0xff, 0x57, 0x05, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x23, 0x13, 0x33, 0xf3, 0xbe, 0x94, 0x74, 0x03, 0xe9, 0x01, 0x3f, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xce, 0x04, 0xc2, 0xfe, 0xa8, 0x06, 0xc1, 0x00, 0x08, 0x00, 0x00, 0x01, 0x10, 0x23, 0x35, 0x16, 0x35, 0x23, 0x35, 0x33, 0xfe, 0xa8, 0xda, 0x65, 0x64, 0xd9, 0x05, 0xc3, 0xfe, 0xff, 0x7b, 0x03, 0x89, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xce, 0x04, 0xc2, 0xfe, 0xa8, 0x06, 0xc1, 0x00, 0x08, 0x00, 0x00, 0x01, 0x35, 0x33, 0x15, 0x23, 0x14, 0x37, 0x15, 0x22, 0xfd, 0xce, 0xd9, 0x64, 0x65, 0xda, 0x05, 0xc3, 0xfe, 0xfe, 0x89, 0x03, 0x7b, 0x00, 0x01, 0xff, 0x86, 0x04, 0x9a, 0x00, 0x7a, 0x06, 0x12, 0x00, 0x03, 0x00, 0x00, 0x03, 0x33, 0x03, 0x23, 0x3a, 0xb4, 0x6a, 0x8a, 0x06, 0x12, 0xfe, 0x88, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xfd, 0xfd, 0xdf, 0xfe, 0xad, 0xff, 0x55, 0x10, 0x07, 0x00, 0x43, 0xfc, 0x65, 0xf8, 0xef, 0x00, 0x00, 0xff, 0xff, 0xfd, 0xb2, 0xfd, 0xdd, 0xff, 0x62, 0xff, 0x55, 0x10, 0x07, 0x00, 0x76, 0xfc, 0x65, 0xf8, 0xef, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x6d, 0xfe, 0x14, 0xfe, 0x6a, 0xff, 0xce, 0x00, 0x07, 0x00, 0x00, 0x01, 0x23, 0x35, 0x33, 0x35, 0x33, 0x11, 0x23, 0xfd, 0xfd, 0x90, 0x90, 0x6c, 0x6c, 0xfe, 0xb5, 0x78, 0xa1, 0xfe, 0x46, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xfd, 0xfe, 0x14, 0xfe, 0xfa, 0xff, 0xce, 0x00, 0x07, 0x00, 0x00, 0x05, 0x33, 0x15, 0x33, 0x15, 0x23, 0x15, 0x23, 0xfd, 0xfd, 0x6c, 0x90, 0x90, 0x6c, 0x32, 0xa1, 0x78, 0xa1, 0x00, 0x01, 0xfe, 0x7f, 0x05, 0x86, 0x00, 0x39, 0x07, 0x70, 0x00, 0x05, 0x00, 0x00, 0x03, 0x21, 0x35, 0x21, 0x11, 0x23, 0x42, 0xfe, 0xc2, 0x01, 0xb9, 0x7b, 0x06, 0xe8, 0x88, 0xfe, 0x16, 0x00, 0x00, 0x01, 0xff, 0x0b, 0x03, 0x6b, 0x00, 0x6f, 0x04, 0xe0, 0x00, 0x13, 0x00, 0x00, 0x03, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0xf5, 0x37, 0x4f, 0x1c, 0x2a, 0x29, 0x0e, 0x0d, 0x78, 0x09, 0x09, 0x4f, 0x53, 0x2b, 0x5f, 0x03, 0xd7, 0x77, 0x2d, 0x2b, 0x37, 0x36, 0x20, 0x3e, 0x1f, 0x26, 0x44, 0x1e, 0x7a, 0x73, 0x35, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xc0, 0xfe, 0x12, 0xfe, 0x81, 0xff, 0xbe, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x15, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0xfe, 0x81, 0x51, 0x70, 0x70, 0x51, 0x24, 0x30, 0x30, 0x24, 0xfe, 0x12, 0x7d, 0x5a, 0x59, 0x7c, 0x78, 0x35, 0x27, 0x28, 0x35, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x56, 0xfe, 0x14, 0xff, 0x10, 0xff, 0x4d, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x15, 0x21, 0x35, 0x33, 0x35, 0x33, 0xfe, 0x70, 0xa0, 0xfe, 0x47, 0x9f, 0x7a, 0xfe, 0x9c, 0x88, 0x88, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x56, 0xfe, 0x14, 0xff, 0x10, 0xff, 0x4d, 0x00, 0x07, 0x00, 0x00, 0x01, 0x23, 0x35, 0x21, 0x15, 0x23, 0x15, 0x23, 0xfd, 0xf6, 0x9f, 0x01, 0xb9, 0xa0, 0x7a, 0xfe, 0xc5, 0x88, 0x88, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x6d, 0xfe, 0x14, 0xfe, 0xfa, 0xff, 0xce, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x23, 0x35, 0x33, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x15, 0x23, 0xfd, 0xfd, 0x90, 0x90, 0x6c, 0x90, 0x90, 0x6c, 0xfe, 0xb5, 0x78, 0xa1, 0xa1, 0x78, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x56, 0xfe, 0x88, 0xff, 0x10, 0xff, 0x10, 0x00, 0x03, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0xfd, 0x57, 0x01, 0xb9, 0xfe, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xba, 0xfe, 0x56, 0xff, 0xd5, 0x00, 0x80, 0x00, 0x0d, 0x00, 0x00, 0x27, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x2b, 0x4a, 0x49, 0xa3, 0xe4, 0xd1, 0x5f, 0x22, 0x22, 0x80, 0x94, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x31, 0x99, 0x94, 0x00, 0x00, 0x01, 0xfd, 0xb7, 0xfe, 0x56, 0xff, 0xd3, 0x00, 0x80, 0x00, 0x0d, 0x00, 0x00, 0x25, 0x33, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0xfd, 0xb8, 0xa6, 0x22, 0x22, 0x5e, 0xd2, 0xe4, 0xa3, 0x49, 0x4a, 0x80, 0x94, 0x99, 0x31, 0x30, 0x9c, 0x60, 0x60, 0xd6, 0x00, 0x01, 0xfd, 0xde, 0xfe, 0x89, 0xfe, 0x85, 0xff, 0x73, 0x00, 0x03, 0x00, 0x00, 0x05, 0x33, 0x15, 0x23, 0xfd, 0xdf, 0xa5, 0xa5, 0x8d, 0xea, 0xff, 0xff, 0xfd, 0x26, 0xfe, 0x89, 0xff, 0x3d, 0xff, 0x53, 0x10, 0x07, 0x00, 0x6a, 0xfc, 0x65, 0xf9, 0x43, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x70, 0xfe, 0x12, 0xfe, 0xf2, 0xff, 0xbe, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0xfe, 0x85, 0x31, 0x23, 0x24, 0x2f, 0x2f, 0x24, 0x23, 0x31, 0x6d, 0x70, 0x51, 0x51, 0x6f, 0x6f, 0x51, 0x51, 0x70, 0xfe, 0xea, 0x26, 0x36, 0x35, 0x27, 0x28, 0x35, 0x36, 0x26, 0x5a, 0x7d, 0x7d, 0x5a, 0x59, 0x7c, 0x7c, 0x00, 0x01, 0xfd, 0xac, 0xfe, 0x14, 0xfe, 0xb4, 0xff, 0x54, 0x00, 0x03, 0x00, 0x00, 0x05, 0x33, 0x03, 0x23, 0xfd, 0xf6, 0xbe, 0x94, 0x74, 0xac, 0xfe, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x6c, 0xfe, 0x75, 0xfe, 0xe1, 0x00, 0x00, 0x10, 0x07, 0x00, 0x7a, 0xfc, 0x66, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x91, 0xfe, 0x75, 0xfe, 0xe1, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9d, 0xfc, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xf6, 0xfe, 0x14, 0xfe, 0x71, 0xff, 0xa0, 0x00, 0x03, 0x00, 0x00, 0x05, 0x11, 0x23, 0x11, 0xfe, 0x70, 0x7a, 0x60, 0xfe, 0x74, 0x01, 0x8c, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x3e, 0xfe, 0x50, 0xff, 0x2f, 0xff, 0x9a, 0x00, 0x07, 0x00, 0x00, 0x07, 0x11, 0x23, 0x35, 0x23, 0x15, 0x23, 0x11, 0xd2, 0x7b, 0xf9, 0x7c, 0x66, 0xfe, 0xb6, 0xc2, 0xc2, 0x01, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xbf, 0xfe, 0x39, 0xff, 0xa3, 0xff, 0x58, 0x00, 0x14, 0x00, 0x00, 0x01, 0x06, 0x23, 0x22, 0x03, 0x34, 0x35, 0x33, 0x16, 0x33, 0x32, 0x37, 0x33, 0x16, 0x17, 0x32, 0x37, 0x33, 0x02, 0x07, 0x22, 0xfe, 0x31, 0x36, 0x68, 0xc4, 0x0f, 0x69, 0x0c, 0x5e, 0x5b, 0x0e, 0x6a, 0x0b, 0x5e, 0x5b, 0x0e, 0x6a, 0x0d, 0xc6, 0x68, 0xfe, 0x8b, 0x52, 0x01, 0x1a, 0x02, 0x03, 0x96, 0x96, 0x95, 0x01, 0x96, 0xfe, 0xe2, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x17, 0xfe, 0x14, 0xff, 0x56, 0xff, 0x8c, 0x11, 0x07, 0x02, 0x89, 0xfc, 0x6a, 0xf9, 0x26, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x12, 0xfe, 0x14, 0xff, 0x51, 0xff, 0x8c, 0x11, 0x07, 0x02, 0x88, 0xfc, 0x65, 0xf9, 0x26, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x12, 0xfe, 0x39, 0xff, 0x46, 0xff, 0x58, 0x10, 0x07, 0x02, 0x9a, 0xfc, 0x5f, 0xf9, 0x10, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x12, 0xfe, 0x36, 0xff, 0x46, 0xff, 0x55, 0x00, 0x0c, 0x00, 0x00, 0x03, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0xba, 0x6a, 0x0a, 0x58, 0x4e, 0x4d, 0x57, 0x0c, 0x6a, 0x09, 0x8f, 0x01, 0x04, 0x8f, 0xfe, 0x36, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x08, 0xfe, 0x39, 0xff, 0x5b, 0xff, 0x53, 0x10, 0x07, 0x02, 0x9e, 0xfc, 0x65, 0xf9, 0x1c, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x29, 0xfe, 0xc0, 0xff, 0x44, 0xff, 0x54, 0x10, 0x07, 0x02, 0x8f, 0xfc, 0x6a, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x54, 0xfe, 0x1d, 0x00, 0x12, 0xfe, 0xac, 0x10, 0x07, 0x00, 0x42, 0xfc, 0x66, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x54, 0xfe, 0x1d, 0x00, 0x12, 0xff, 0xee, 0x10, 0x07, 0x07, 0x4c, 0xfc, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfb, 0xfe, 0x01, 0xec, 0xff, 0xb6, 0x03, 0x0c, 0x00, 0x1b, 0x00, 0x00, 0x03, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x4b, 0x43, 0x81, 0x47, 0x51, 0x66, 0x13, 0x0a, 0x46, 0x5c, 0x2e, 0x47, 0x7f, 0x42, 0x46, 0x84, 0x4a, 0x30, 0x5a, 0x43, 0x0a, 0x13, 0x69, 0x53, 0x3f, 0x7c, 0x03, 0x0c, 0xae, 0x3b, 0x37, 0x33, 0x0a, 0x04, 0x21, 0x18, 0x3b, 0x3f, 0xae, 0x3c, 0x36, 0x16, 0x1f, 0x05, 0x0a, 0x37, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xb8, 0x01, 0xc4, 0xff, 0x94, 0x02, 0x68, 0x00, 0x03, 0x00, 0x00, 0x03, 0x15, 0x21, 0x35, 0x6c, 0xfe, 0x25, 0x02, 0x68, 0xa4, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfb, 0x6e, 0x01, 0xc4, 0x00, 0x00, 0x02, 0x68, 0x00, 0x03, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0xfb, 0x6f, 0x04, 0x90, 0x01, 0xc4, 0xa4, 0xa4, 0x00, 0x00, 0x00, 0x01, 0xfb, 0xdd, 0xff, 0xa2, 0xff, 0xc3, 0x04, 0xbc, 0x00, 0x03, 0x00, 0x00, 0x05, 0x27, 0x01, 0x17, 0xfc, 0x34, 0x56, 0x03, 0x8f, 0x56, 0x5e, 0x4e, 0x04, 0xcc, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfa, 0xa9, 0xff, 0xba, 0xff, 0x9d, 0x06, 0x17, 0x00, 0x03, 0x00, 0x00, 0x05, 0x27, 0x01, 0x17, 0xfb, 0x06, 0x5c, 0x04, 0x96, 0x5c, 0x46, 0x58, 0x06, 0x05, 0x59, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xe7, 0xfe, 0x12, 0xfe, 0xa9, 0xff, 0xbe, 0x00, 0x0d, 0x00, 0x00, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x35, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0xfd, 0xe8, 0x51, 0x6f, 0x6f, 0x51, 0x24, 0x2f, 0x2f, 0x24, 0x42, 0x7d, 0x5a, 0x59, 0x7c, 0x78, 0x35, 0x27, 0x28, 0x35, 0x00, 0x01, 0xfd, 0x3f, 0xfe, 0x5b, 0xff, 0x30, 0xff, 0xa5, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x33, 0x15, 0x33, 0x35, 0x33, 0x11, 0xfd, 0x3f, 0x7c, 0xf9, 0x7b, 0xfe, 0x5b, 0x01, 0x4a, 0xc2, 0xc2, 0xfe, 0xb6, 0x00, 0x00, 0x02, 0xfd, 0x6a, 0xfe, 0x14, 0xff, 0x00, 0xff, 0xd6, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x05, 0x11, 0x21, 0x11, 0x01, 0x35, 0x23, 0x15, 0xff, 0x00, 0xfe, 0x6a, 0x01, 0x2a, 0xbe, 0x2a, 0xfe, 0x3e, 0x01, 0xc2, 0xfe, 0xb6, 0xd2, 0xd2, 0x00, 0x01, 0xfc, 0xbf, 0xfe, 0x39, 0xff, 0xa3, 0xff, 0x58, 0x00, 0x14, 0x00, 0x00, 0x05, 0x36, 0x33, 0x32, 0x13, 0x14, 0x15, 0x23, 0x26, 0x23, 0x22, 0x07, 0x23, 0x26, 0x27, 0x22, 0x07, 0x23, 0x12, 0x37, 0x32, 0xfe, 0x31, 0x36, 0x68, 0xc4, 0x0f, 0x69, 0x0c, 0x5e, 0x5b, 0x0e, 0x6a, 0x0b, 0x5e, 0x5b, 0x0e, 0x6a, 0x0d, 0xc6, 0x68, 0xfa, 0x52, 0xfe, 0xe6, 0x02, 0x03, 0x96, 0x96, 0x95, 0x01, 0x96, 0x01, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x73, 0x04, 0xf3, 0xff, 0x02, 0x06, 0xad, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x17, 0x07, 0xfe, 0x3a, 0x70, 0x56, 0x70, 0x70, 0x56, 0x70, 0x71, 0x56, 0x70, 0x70, 0x56, 0x05, 0x70, 0x7d, 0x60, 0x7d, 0x7d, 0x60, 0x7d, 0x7d, 0x60, 0x7d, 0x7d, 0x60, 0x00, 0x01, 0xfe, 0x38, 0x04, 0xc2, 0xff, 0x37, 0x06, 0xd2, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x26, 0x27, 0xfe, 0x70, 0x1e, 0x19, 0x84, 0x79, 0x49, 0x42, 0x08, 0x0b, 0x10, 0x32, 0x1d, 0x19, 0x84, 0x79, 0x49, 0x42, 0x08, 0x0b, 0x10, 0x05, 0xc7, 0x1c, 0x30, 0x1c, 0x50, 0x51, 0x02, 0x6e, 0x02, 0x1b, 0x1c, 0x0a, 0x0c, 0x0f, 0x0e, 0x2b, 0x1c, 0x30, 0x1c, 0x50, 0x51, 0x02, 0x6e, 0x02, 0x1b, 0x1c, 0x0a, 0x0c, 0x0f, 0x0e, 0xff, 0xff, 0xfc, 0x54, 0x04, 0x3a, 0x00, 0x12, 0x06, 0x0b, 0x10, 0x27, 0x07, 0x73, 0xfc, 0x66, 0x00, 0x00, 0x10, 0x07, 0x07, 0x73, 0xfc, 0x66, 0xfe, 0xbe, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xfd, 0x04, 0xf0, 0xfe, 0xad, 0x06, 0x66, 0x10, 0x07, 0x00, 0x43, 0xfc, 0x65, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0xb2, 0x04, 0xee, 0xff, 0x62, 0x06, 0x66, 0x10, 0x07, 0x00, 0x76, 0xfc, 0x65, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x08, 0x05, 0x1d, 0xff, 0x5b, 0x06, 0x37, 0x10, 0x07, 0x02, 0x9e, 0xfc, 0x65, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0xce, 0x04, 0xc2, 0xfe, 0xa8, 0x06, 0xc1, 0x10, 0x06, 0x02, 0xc4, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x36, 0x05, 0x46, 0xff, 0x72, 0x07, 0xd2, 0x10, 0x07, 0x03, 0x1c, 0xfc, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0xff, 0xfe, 0x56, 0xfe, 0xc5, 0xff, 0xa4, 0x10, 0x07, 0x03, 0x16, 0xfc, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x26, 0x05, 0x1d, 0xff, 0x41, 0x06, 0x49, 0x00, 0x07, 0x00, 0x00, 0x03, 0x23, 0x35, 0x21, 0x15, 0x23, 0x11, 0x21, 0xc0, 0x87, 0xfe, 0xf4, 0x87, 0x02, 0x1a, 0x05, 0x1d, 0x96, 0x96, 0x01, 0x2c, 0x00, 0x00, 0x02, 0xfd, 0x68, 0xfe, 0x32, 0xfe, 0xfe, 0xff, 0xb8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0xfe, 0xfe, 0xfe, 0x6b, 0x01, 0x95, 0xfe, 0x6b, 0x01, 0x95, 0xfe, 0x32, 0x78, 0x96, 0x78, 0x00, 0x00, 0x02, 0xfd, 0x5f, 0xfe, 0x14, 0xff, 0x07, 0xff, 0xa0, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x05, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0xfd, 0x60, 0x87, 0x87, 0x01, 0x20, 0x87, 0x87, 0x60, 0xfe, 0x74, 0x01, 0x8c, 0xfe, 0x74, 0x00, 0x00, 0x01, 0xfd, 0x68, 0xfe, 0x14, 0xfe, 0xfe, 0xff, 0xd6, 0x00, 0x05, 0x00, 0x00, 0x05, 0x21, 0x11, 0x23, 0x11, 0x21, 0xfd, 0x69, 0x01, 0x95, 0x87, 0xfe, 0xf2, 0x2a, 0xfe, 0x3e, 0x01, 0x2c, 0x00, 0x01, 0xfd, 0x0a, 0x04, 0xee, 0xff, 0x5d, 0x06, 0x66, 0x00, 0x27, 0x00, 0x00, 0x01, 0x37, 0x33, 0x07, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x07, 0x23, 0x37, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x23, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0xfe, 0x32, 0x3c, 0x62, 0x60, 0x09, 0x14, 0x0f, 0x0b, 0x23, 0x10, 0x10, 0x02, 0x70, 0x02, 0x2e, 0x2d, 0x52, 0x23, 0x1c, 0x1b, 0x1e, 0x3b, 0x63, 0x60, 0x0c, 0x12, 0x0e, 0x0c, 0x22, 0x10, 0x11, 0x01, 0x71, 0x02, 0x2e, 0x2e, 0x52, 0x22, 0x1d, 0x1b, 0x05, 0xff, 0x67, 0xa9, 0x09, 0x0e, 0x0a, 0x24, 0x25, 0x52, 0x87, 0x4a, 0x49, 0x0e, 0x0d, 0x1d, 0x67, 0xa8, 0x0b, 0x0d, 0x0a, 0x24, 0x25, 0x52, 0x87, 0x4a, 0x49, 0x0e, 0x0d, 0x00, 0x03, 0xfd, 0x0a, 0x04, 0x89, 0xff, 0x5d, 0x06, 0xcc, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x25, 0x00, 0x00, 0x01, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x23, 0x34, 0x36, 0x33, 0x32, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x33, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x07, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0xfe, 0x30, 0x34, 0x16, 0x1c, 0x0b, 0x20, 0x24, 0x71, 0x5d, 0x4d, 0x21, 0x37, 0x2b, 0x33, 0x15, 0x1e, 0x0e, 0x1d, 0x24, 0x70, 0x02, 0x5c, 0x4c, 0x1e, 0x36, 0xd0, 0x87, 0x87, 0xbd, 0x87, 0x87, 0x05, 0x68, 0x21, 0x0e, 0x0b, 0x32, 0x2d, 0x06, 0x65, 0x76, 0x10, 0x1b, 0x1e, 0x0d, 0x0c, 0x33, 0x29, 0x06, 0x64, 0x77, 0x10, 0x2e, 0x96, 0x02, 0x43, 0x96, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x0a, 0x04, 0xc5, 0xff, 0x5d, 0x06, 0x90, 0x10, 0x22, 0x10, 0xed, 0x00, 0xb7, 0x10, 0x03, 0x10, 0xed, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x01, 0xfc, 0xbf, 0xfe, 0x28, 0xff, 0xa7, 0xff, 0xc2, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x37, 0x21, 0x17, 0x23, 0x27, 0x37, 0x33, 0x07, 0x21, 0x27, 0x33, 0x17, 0x07, 0xfe, 0x98, 0x77, 0xfe, 0x49, 0x77, 0x72, 0x9d, 0x9d, 0x72, 0x77, 0x01, 0xb7, 0x77, 0x71, 0x9e, 0x9e, 0xfe, 0x28, 0x9b, 0x9b, 0xcd, 0xcd, 0x9b, 0x9b, 0xcd, 0xcd, 0x00, 0x00, 0x01, 0xfd, 0x7a, 0xfe, 0x14, 0xfe, 0xec, 0xff, 0xa4, 0x00, 0x08, 0x00, 0x00, 0x01, 0x23, 0x35, 0x07, 0x35, 0x37, 0x17, 0x15, 0x27, 0xfe, 0x60, 0x5a, 0x8b, 0xb8, 0xb9, 0x8c, 0xfe, 0x14, 0xe7, 0x84, 0x7e, 0xaf, 0xaf, 0x7e, 0x84, 0x00, 0x00, 0x01, 0xfd, 0xb8, 0x04, 0xe1, 0xfe, 0xae, 0x07, 0x06, 0x00, 0x10, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0xfe, 0xae, 0x3a, 0x26, 0x27, 0x27, 0x26, 0x3a, 0x67, 0x46, 0x48, 0x48, 0x46, 0x67, 0x06, 0x8b, 0x01, 0x2a, 0x2c, 0x40, 0x41, 0x2b, 0x2b, 0x01, 0x7b, 0x01, 0x4f, 0x50, 0xe6, 0x50, 0x4e, 0x01, 0x00, 0xff, 0xff, 0xfd, 0x12, 0x04, 0x60, 0xff, 0x46, 0x06, 0xd8, 0x10, 0x27, 0x02, 0xc2, 0x00, 0x00, 0x00, 0x90, 0x10, 0x06, 0x02, 0xb8, 0x00, 0xe5, 0xff, 0xff, 0xfd, 0x73, 0xfe, 0x14, 0xff, 0x02, 0xff, 0xce, 0x10, 0x07, 0x02, 0xee, 0x00, 0x00, 0xf9, 0x21, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xb8, 0x04, 0xe1, 0xfe, 0xae, 0x07, 0x06, 0x00, 0x12, 0x00, 0x00, 0x01, 0x30, 0x35, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x30, 0x35, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0xfd, 0xb9, 0x66, 0x47, 0x48, 0x48, 0x47, 0x66, 0x39, 0x26, 0x28, 0x28, 0x26, 0x06, 0x8b, 0x7b, 0x01, 0x4e, 0x50, 0xe6, 0x50, 0x4f, 0x01, 0x7b, 0x01, 0x2b, 0x2b, 0x41, 0x40, 0x2c, 0x2a, 0xff, 0xff, 0xff, 0x43, 0x05, 0x44, 0xff, 0xfb, 0x06, 0x10, 0x10, 0x07, 0x02, 0x9b, 0xfd, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0xe8, 0xfe, 0x12, 0xff, 0x7e, 0xff, 0xbf, 0x00, 0x07, 0x00, 0x15, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x16, 0x32, 0x3e, 0x01, 0x26, 0x22, 0x06, 0x37, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x27, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x12, 0x36, 0x34, 0x26, 0x22, 0x06, 0x14, 0x16, 0xfd, 0x55, 0x30, 0x47, 0x2f, 0x02, 0x31, 0x47, 0x30, 0xde, 0x38, 0xa3, 0x70, 0x70, 0xa4, 0x37, 0x38, 0xa3, 0x70, 0x70, 0xa3, 0xe5, 0x31, 0x31, 0x47, 0x30, 0x30, 0xfe, 0xc3, 0x35, 0x35, 0x4d, 0x37, 0x35, 0x6d, 0x3f, 0x7c, 0xb3, 0x7d, 0x41, 0x40, 0x7d, 0xb3, 0x7c, 0xfe, 0xce, 0x36, 0x4d, 0x36, 0x35, 0x4f, 0x35, 0xff, 0xff, 0xfc, 0xcb, 0xfe, 0x1b, 0x03, 0x35, 0xff, 0x85, 0x10, 0x07, 0x07, 0x74, 0xfd, 0x1b, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xcb, 0x06, 0x6b, 0x03, 0x35, 0x07, 0xd5, 0x10, 0x07, 0x07, 0x74, 0xfd, 0x1b, 0x08, 0x50, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xcb, 0x06, 0xd7, 0x03, 0x35, 0x07, 0x6b, 0x00, 0x03, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0xfc, 0xcb, 0x06, 0x6a, 0xf9, 0x96, 0x07, 0x6b, 0x94, 0x00, 0x00, 0x01, 0xfc, 0xcb, 0xfe, 0xc0, 0x03, 0x35, 0xff, 0x54, 0x00, 0x03, 0x00, 0x00, 0x05, 0x21, 0x15, 0x21, 0xfc, 0xcb, 0x06, 0x6a, 0xf9, 0x96, 0xac, 0x94, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x72, 0x06, 0x0d, 0x02, 0x8e, 0x07, 0x27, 0x00, 0x23, 0x00, 0x00, 0x03, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x23, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x04, 0x81, 0x19, 0x48, 0x27, 0x21, 0x5a, 0x30, 0x3f, 0x05, 0x91, 0x03, 0x66, 0x65, 0xb4, 0x52, 0x38, 0x34, 0x51, 0x81, 0x19, 0x48, 0x27, 0x21, 0x57, 0x33, 0x40, 0x04, 0x91, 0x03, 0x66, 0x65, 0xb4, 0x52, 0x38, 0x34, 0x06, 0x4a, 0x37, 0x0b, 0x12, 0x0a, 0x24, 0x30, 0x47, 0x87, 0x4a, 0x49, 0x0e, 0x0d, 0x22, 0x37, 0x0b, 0x12, 0x0a, 0x24, 0x2c, 0x4b, 0x87, 0x4a, 0x49, 0x0e, 0x0d, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xcb, 0x06, 0x04, 0x03, 0x35, 0x07, 0x6e, 0x10, 0x07, 0x07, 0x75, 0xfd, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xd1, 0xfe, 0x28, 0x03, 0x38, 0xff, 0xc2, 0x00, 0x08, 0x00, 0x00, 0x01, 0x35, 0x21, 0x27, 0x33, 0x17, 0x07, 0x23, 0x37, 0xfc, 0xd2, 0x05, 0xcd, 0x76, 0x71, 0x9e, 0x9e, 0x71, 0x76, 0xfe, 0xc3, 0x64, 0x9b, 0xcd, 0xcd, 0x9b, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x00, 0x05, 0xd5, 0x10, 0x06, 0x0e, 0x40, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x03, 0x6f, 0x04, 0x60, 0x10, 0x06, 0x0e, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x80, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xb5, 0x04, 0xcb, 0xb6, 0xfe, 0xac, 0xb7, 0xfe, 0xac, 0xb6, 0x05, 0xd5, 0xfc, 0xf4, 0x02, 0x62, 0xfa, 0xd5, 0x05, 0x2b, 0xfd, 0x9e, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf5, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0xb5, 0x03, 0x3f, 0xa5, 0xa7, 0xa6, 0xa7, 0xa6, 0x05, 0xd5, 0xfc, 0xf4, 0x02, 0x62, 0xfa, 0xd5, 0x05, 0x2b, 0xfd, 0x9e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x90, 0x04, 0x74, 0x01, 0x76, 0x06, 0x66, 0x00, 0x03, 0x00, 0x00, 0x1b, 0x01, 0x33, 0x03, 0x90, 0x3a, 0xac, 0x64, 0x04, 0x74, 0x01, 0xf2, 0xfe, 0x0e, 0x00, 0x01, 0x00, 0x90, 0xfe, 0x56, 0x01, 0x76, 0x00, 0x48, 0x00, 0x03, 0x00, 0x00, 0x25, 0x03, 0x23, 0x13, 0x01, 0x76, 0x3b, 0xab, 0x63, 0x48, 0xfe, 0x0e, 0x01, 0xf2, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x05, 0xd5, 0x10, 0x06, 0x03, 0xac, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x07, 0x04, 0x60, 0x10, 0x06, 0x03, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8a, 0xfe, 0x56, 0x02, 0x51, 0xff, 0xa4, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x23, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x02, 0x50, 0x85, 0x17, 0x18, 0x12, 0x86, 0x09, 0x0b, 0x0d, 0x1f, 0xfe, 0x56, 0x21, 0x1a, 0x2e, 0xe5, 0xe5, 0x0e, 0x0c, 0x0d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x72, 0xff, 0xe3, 0x03, 0x90, 0x04, 0x7b, 0x10, 0x06, 0x02, 0x16, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x10, 0x27, 0x00, 0x79, 0x01, 0x2e, 0xff, 0x84, 0x10, 0x06, 0x00, 0x46, 0x00, 0x00, 0xff, 0xff, 0x00, 0x72, 0xff, 0xe3, 0x03, 0x90, 0x04, 0x7b, 0x10, 0x27, 0x00, 0x79, 0x00, 0x80, 0xff, 0x84, 0x10, 0x06, 0x02, 0x16, 0x00, 0x00, 0xff, 0xff, 0x00, 0x8e, 0xff, 0x12, 0x01, 0x96, 0x04, 0x23, 0x12, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x01, 0x4d, 0x04, 0xee, 0x02, 0xfd, 0x06, 0x66, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x01, 0x23, 0x02, 0x4a, 0xb3, 0xfe, 0xdb, 0x8a, 0x06, 0x66, 0xfe, 0x88, 0xff, 0xff, 0x00, 0xc1, 0x05, 0x46, 0x02, 0xfd, 0x07, 0xd2, 0x12, 0x26, 0x00, 0x6a, 0x00, 0x00, 0x11, 0x07, 0x03, 0x1b, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0xfe, 0xf7, 0x00, 0x00, 0x10, 0x06, 0x03, 0x26, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc5, 0x02, 0x48, 0x01, 0x83, 0x03, 0x46, 0x12, 0x06, 0x00, 0x79, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe9, 0x00, 0x00, 0x04, 0xea, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0xfe, 0x9c, 0x00, 0x00, 0x10, 0x07, 0x03, 0x2a, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf4, 0x00, 0x00, 0x05, 0x83, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0xfe, 0xa6, 0x00, 0x00, 0x10, 0x07, 0x03, 0x2c, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x02, 0x3e, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0xfe, 0xa1, 0x00, 0x00, 0x10, 0x07, 0x03, 0x2e, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xe3, 0x05, 0x68, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0xfe, 0xa6, 0x00, 0x00, 0x10, 0x06, 0x03, 0x34, 0x24, 0x00, 0xff, 0xff, 0xff, 0xe4, 0x00, 0x00, 0x05, 0xe9, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0xfe, 0x96, 0x00, 0x00, 0x10, 0x07, 0x03, 0x39, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xde, 0x00, 0x00, 0x05, 0x6b, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0xfe, 0x91, 0x00, 0x00, 0x10, 0x06, 0x03, 0x3d, 0x31, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x02, 0x40, 0x07, 0xd2, 0x10, 0x27, 0x03, 0x1c, 0xff, 0x43, 0x00, 0x00, 0x12, 0x06, 0x03, 0x4d, 0x0e, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x24, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0xb5, 0x03, 0x44, 0xfd, 0x72, 0x05, 0xd5, 0xaa, 0xfa, 0xd5, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x21, 0x05, 0x01, 0x33, 0x01, 0x02, 0x76, 0xfe, 0x8f, 0x02, 0xe3, 0xfc, 0x26, 0x02, 0x01, 0xcf, 0x02, 0x00, 0x05, 0x0e, 0xfb, 0x9a, 0xa8, 0x05, 0xd5, 0xfa, 0x2b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x28, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0x00, 0x00, 0x04, 0x9c, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x03, 0x00, 0x12, 0x00, 0x21, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x01, 0x22, 0x07, 0x06, 0x11, 0x10, 0x12, 0x33, 0x32, 0x37, 0x36, 0x11, 0x10, 0x27, 0x26, 0x27, 0x20, 0x00, 0x11, 0x10, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x01, 0x98, 0x02, 0x7b, 0xfd, 0x85, 0x01, 0x3e, 0xc6, 0x74, 0x75, 0xe9, 0xc6, 0xc6, 0x74, 0x74, 0x74, 0x74, 0xc6, 0x01, 0x1b, 0x01, 0x52, 0xa9, 0xa9, 0xfe, 0xe5, 0xfe, 0xe5, 0xaa, 0xa9, 0xa9, 0xaa, 0x03, 0x70, 0xaa, 0x02, 0x86, 0xa4, 0xa4, 0xfe, 0xe5, 0xfe, 0xe6, 0xfe, 0xb8, 0xa4, 0xa4, 0x01, 0x1a, 0x01, 0x1b, 0xa4, 0xa4, 0xa4, 0xfe, 0x5b, 0xfe, 0x9e, 0xfe, 0x9f, 0xd2, 0xd3, 0xd2, 0xd2, 0x01, 0x62, 0x01, 0x62, 0xd3, 0xd2, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x6b, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x2c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xe0, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x33, 0x23, 0x01, 0x33, 0x01, 0x23, 0x01, 0xce, 0xc0, 0x02, 0x01, 0xcf, 0x02, 0x00, 0xbd, 0xfe, 0x55, 0x05, 0xd5, 0xfa, 0x2b, 0x05, 0x0e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x30, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf2, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x03, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x01, 0x13, 0x02, 0x80, 0xfd, 0x80, 0x5e, 0x03, 0x3d, 0xfc, 0xc3, 0x03, 0x3d, 0xfc, 0xc3, 0x03, 0x71, 0xaa, 0x03, 0x0e, 0xaa, 0xfb, 0x7f, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x12, 0x06, 0x00, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x12, 0x06, 0x03, 0xb3, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x21, 0x15, 0x21, 0x35, 0x09, 0x01, 0x35, 0x21, 0x15, 0x21, 0x01, 0x01, 0x86, 0x02, 0x91, 0xfc, 0x9e, 0x01, 0xaf, 0xfe, 0x51, 0x03, 0x51, 0xfd, 0x80, 0x01, 0xaf, 0xaa, 0xaa, 0xaa, 0x02, 0x70, 0x02, 0x11, 0xaa, 0xaa, 0xfd, 0xf3, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0x00, 0x00, 0x04, 0x6c, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x37, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x67, 0x00, 0x00, 0x05, 0x44, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x11, 0x00, 0x27, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x03, 0x26, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x07, 0x15, 0x23, 0x02, 0x7b, 0x87, 0x58, 0x75, 0x75, 0x58, 0x87, 0xb6, 0x87, 0x58, 0x74, 0x74, 0x58, 0x87, 0xb6, 0xdb, 0x8e, 0xaa, 0xaa, 0x8d, 0xdc, 0xb6, 0xdc, 0x8d, 0xa9, 0xa9, 0x8d, 0xdc, 0xb6, 0x04, 0x8e, 0x15, 0x57, 0x73, 0xc6, 0xc5, 0x73, 0x57, 0x15, 0x15, 0x57, 0x73, 0xc5, 0xc6, 0x73, 0x57, 0x15, 0xfc, 0x10, 0x16, 0x86, 0xa0, 0x01, 0x0f, 0x01, 0x0f, 0xa1, 0x87, 0x16, 0x9f, 0x9f, 0x17, 0x86, 0xa1, 0xfe, 0xf1, 0xfe, 0xf2, 0xa1, 0x86, 0x17, 0x9d, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0x00, 0x00, 0x05, 0x46, 0x05, 0xd5, 0x00, 0x1d, 0x00, 0x00, 0x21, 0x36, 0x27, 0x22, 0x27, 0x26, 0x03, 0x11, 0x33, 0x11, 0x10, 0x17, 0x16, 0x17, 0x11, 0x33, 0x11, 0x36, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x02, 0x07, 0x06, 0x23, 0x06, 0x17, 0x02, 0x7b, 0x01, 0x01, 0xc0, 0xaa, 0xa5, 0x04, 0xbf, 0x75, 0x63, 0x7c, 0xb6, 0x7d, 0x63, 0x74, 0xc0, 0x05, 0xa5, 0xa9, 0xc1, 0x01, 0x01, 0x86, 0xb0, 0xd2, 0xcc, 0x01, 0x68, 0x01, 0x99, 0xfe, 0x67, 0xfe, 0xe6, 0xa4, 0x8c, 0x0e, 0x03, 0xf1, 0xfc, 0x0f, 0x0e, 0x8c, 0xa4, 0x01, 0x1a, 0x01, 0x99, 0xfe, 0x67, 0xfe, 0x98, 0xcc, 0xd2, 0x48, 0xee, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00, 0x00, 0x05, 0x3b, 0x05, 0xe7, 0x00, 0x26, 0x00, 0x00, 0x25, 0x15, 0x21, 0x35, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x02, 0x15, 0x14, 0x17, 0x16, 0x17, 0x15, 0x21, 0x35, 0x21, 0x26, 0x27, 0x26, 0x35, 0x10, 0x37, 0x36, 0x21, 0x20, 0x17, 0x16, 0x11, 0x14, 0x07, 0x06, 0x07, 0x05, 0x3a, 0xfd, 0xe4, 0xa0, 0x59, 0x59, 0x77, 0x77, 0xc2, 0xc3, 0xee, 0x59, 0x5a, 0xa0, 0xfd, 0xe4, 0x01, 0x1f, 0x8e, 0x41, 0x41, 0xac, 0xac, 0x01, 0x13, 0x01, 0x11, 0xad, 0xad, 0x40, 0x40, 0x91, 0xb2, 0xb2, 0xb2, 0x61, 0xa6, 0xa6, 0xca, 0xf0, 0x91, 0x91, 0xfe, 0xdd, 0xef, 0xca, 0xa6, 0xa6, 0x61, 0xb2, 0xb2, 0x8b, 0x95, 0x95, 0xb8, 0x01, 0x3e, 0xc5, 0xc5, 0xc5, 0xc4, 0xfe, 0xcb, 0xc2, 0x94, 0x94, 0x8d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x02, 0x1c, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x02, 0xde, 0x01, 0x75, 0x13, 0x06, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x03, 0xff, 0x01, 0x75, 0x13, 0x06, 0x03, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x66, 0x12, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x03, 0x1b, 0x63, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x06, 0x66, 0x10, 0x26, 0x03, 0x1b, 0x48, 0x00, 0x12, 0x06, 0x03, 0x49, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0x00, 0xb2, 0x00, 0x00, 0x12, 0x06, 0x03, 0x4b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x95, 0x00, 0x00, 0x02, 0x56, 0x06, 0x66, 0x12, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x03, 0x1b, 0xff, 0x59, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x07, 0xd2, 0x12, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x03, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x04, 0x79, 0x00, 0x0d, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x1b, 0x01, 0x33, 0x03, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x33, 0x20, 0x02, 0xf9, 0x27, 0x29, 0xa0, 0x78, 0x37, 0x46, 0x43, 0x45, 0x6d, 0x79, 0x40, 0x94, 0x59, 0x94, 0xb9, 0x24, 0x08, 0x20, 0x25, 0x1d, 0x4f, 0x63, 0x55, 0x4b, 0x25, 0x10, 0x29, 0x54, 0x29, 0x80, 0xd3, 0x67, 0x69, 0x72, 0x7f, 0xb2, 0x01, 0x18, 0x02, 0x09, 0xe7, 0xed, 0x6e, 0x8a, 0xb6, 0xdc, 0x69, 0x6b, 0xd5, 0x01, 0xe7, 0x01, 0x25, 0xfd, 0xa1, 0xdb, 0x31, 0x29, 0x30, 0x9c, 0x54, 0x2a, 0x58, 0x6f, 0x57, 0x29, 0x98, 0x9d, 0x01, 0x13, 0x01, 0x26, 0x8a, 0x9a, 0x00, 0x00, 0x02, 0x00, 0xac, 0xfe, 0x56, 0x04, 0x14, 0x06, 0x21, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x25, 0x11, 0x23, 0x11, 0x10, 0x21, 0x20, 0x11, 0x10, 0x07, 0x16, 0x11, 0x10, 0x21, 0x22, 0x03, 0x16, 0x33, 0x20, 0x11, 0x10, 0x05, 0x35, 0x20, 0x11, 0x34, 0x23, 0x22, 0x11, 0x01, 0x53, 0xa6, 0x01, 0x7f, 0x01, 0x87, 0x9b, 0xfc, 0xfe, 0x4e, 0xbf, 0x50, 0x64, 0xb1, 0x01, 0x04, 0xfe, 0x5e, 0x01, 0x47, 0xd3, 0xeb, 0x45, 0xfe, 0x11, 0x06, 0x03, 0x01, 0xc8, 0xfe, 0x7f, 0xfe, 0xee, 0x64, 0x5a, 0xfe, 0xf5, 0xfe, 0x26, 0x01, 0x4a, 0xad, 0x01, 0x3a, 0x01, 0x1a, 0x16, 0xaa, 0x01, 0x40, 0xdb, 0xfe, 0xc8, 0x00, 0x00, 0x01, 0x00, 0x1c, 0xfe, 0x56, 0x04, 0x0c, 0x04, 0x60, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x13, 0x01, 0x33, 0x01, 0x11, 0x23, 0x11, 0x01, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x01, 0x45, 0xdc, 0x01, 0x3b, 0xb0, 0xfe, 0x68, 0xa5, 0xfe, 0xf7, 0x27, 0x56, 0x2c, 0x3f, 0xb1, 0x03, 0xb0, 0xfd, 0x4c, 0x03, 0x64, 0xfb, 0xa0, 0xfe, 0x56, 0x01, 0xaa, 0x03, 0x44, 0x7e, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x05, 0xf0, 0x00, 0x1c, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x11, 0x34, 0x37, 0x36, 0x37, 0x26, 0x35, 0x10, 0x21, 0x32, 0x17, 0x01, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x03, 0x88, 0x5c, 0xd7, 0xe4, 0xee, 0xba, 0x6a, 0x80, 0x7b, 0x7c, 0xd8, 0xd7, 0x7c, 0x7b, 0x7b, 0x30, 0x43, 0x8c, 0x01, 0x8d, 0xc7, 0x6c, 0xfe, 0x48, 0x3d, 0x31, 0x4e, 0x4d, 0x4d, 0x86, 0x85, 0x9a, 0x51, 0x58, 0x71, 0x3a, 0x05, 0x11, 0x46, 0x75, 0x5c, 0x30, 0x25, 0x70, 0x87, 0xfe, 0xeb, 0xfe, 0xf7, 0x9c, 0x9d, 0x9d, 0x9c, 0x01, 0x13, 0xcc, 0xa5, 0x40, 0x24, 0x4f, 0x8d, 0x01, 0x10, 0x46, 0xfe, 0x28, 0x1d, 0x49, 0x71, 0xcc, 0xcb, 0x72, 0x73, 0xe8, 0xbe, 0xc7, 0x60, 0x67, 0x0b, 0x06, 0x00, 0x00, 0x01, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x04, 0x7c, 0x00, 0x32, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x36, 0x01, 0x64, 0x65, 0x36, 0x36, 0x66, 0x66, 0xb0, 0x45, 0x99, 0x58, 0x57, 0x48, 0x49, 0x40, 0x6b, 0x3e, 0x3f, 0x3d, 0x3c, 0x69, 0x8b, 0x85, 0x7b, 0x41, 0x46, 0x4b, 0x4d, 0x88, 0x53, 0x4d, 0x4c, 0x40, 0x51, 0x4b, 0x4d, 0x48, 0xd6, 0x74, 0x74, 0x7c, 0x02, 0x5c, 0x18, 0x41, 0x40, 0x5d, 0x8d, 0x4f, 0x4e, 0x18, 0x18, 0xa7, 0x1d, 0x0d, 0x0d, 0x2e, 0x2e, 0x40, 0x46, 0x2d, 0x2c, 0x98, 0x33, 0x38, 0x58, 0x5a, 0x38, 0x38, 0x12, 0x13, 0x25, 0xab, 0x1c, 0x0e, 0x0e, 0x5b, 0x5b, 0xad, 0x6c, 0x92, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0xfe, 0x52, 0x03, 0x93, 0x06, 0x14, 0x00, 0x1d, 0x00, 0x00, 0x25, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x34, 0x35, 0x16, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x20, 0x03, 0x10, 0x01, 0x21, 0x35, 0x21, 0x15, 0x00, 0x11, 0x10, 0x02, 0x83, 0x76, 0x47, 0x4c, 0x42, 0x49, 0x92, 0x3e, 0x26, 0x1d, 0x1d, 0x1d, 0x33, 0xfd, 0xde, 0x01, 0x02, 0x02, 0xfe, 0x21, 0x03, 0x0f, 0xfd, 0x75, 0x7f, 0x01, 0x4b, 0x4f, 0x78, 0x73, 0x50, 0x57, 0x4b, 0x4c, 0x05, 0x2c, 0x23, 0x25, 0x35, 0x2c, 0x2a, 0x02, 0x33, 0x01, 0xec, 0x01, 0x59, 0xb9, 0xb9, 0xfe, 0x94, 0xfe, 0x27, 0xfe, 0x69, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x04, 0x7b, 0x00, 0x15, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x03, 0xf4, 0xa6, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0x51, 0x50, 0x6a, 0xad, 0x59, 0x5a, 0x02, 0xa4, 0xfb, 0xb2, 0x04, 0x48, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x65, 0x32, 0x32, 0x77, 0x78, 0x00, 0x03, 0x00, 0x65, 0xff, 0xe9, 0x04, 0x03, 0x06, 0x24, 0x00, 0x08, 0x00, 0x11, 0x00, 0x21, 0x00, 0x00, 0x01, 0x21, 0x12, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x13, 0x02, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x03, 0x01, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x03, 0x52, 0xfd, 0xc3, 0x0e, 0x3e, 0x4d, 0x86, 0x87, 0x4b, 0x42, 0x08, 0x1a, 0x30, 0x4d, 0x85, 0x8a, 0x48, 0x3a, 0x11, 0x01, 0x1d, 0xd8, 0x7c, 0x7b, 0x7b, 0x7c, 0xd8, 0xd9, 0x7a, 0x7b, 0x7b, 0x7a, 0x02, 0xc6, 0xfe, 0xd5, 0x7f, 0x9c, 0x9d, 0x8a, 0x01, 0xc9, 0x01, 0x1c, 0x64, 0x9e, 0x9c, 0x7e, 0xfe, 0xfc, 0x02, 0xb4, 0xd4, 0xd3, 0xfe, 0x8a, 0xfe, 0x8b, 0xd4, 0xd5, 0xd5, 0xd4, 0x01, 0x75, 0x01, 0x76, 0xd3, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x95, 0x00, 0x00, 0x02, 0x30, 0x04, 0x60, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x03, 0x01, 0x40, 0x1e, 0x20, 0x62, 0x50, 0x64, 0xa2, 0x4a, 0x4a, 0x01, 0x04, 0x60, 0xfd, 0x2b, 0x91, 0x2e, 0x30, 0x9c, 0x60, 0x62, 0xd4, 0x02, 0xca, 0x00, 0x01, 0x00, 0xab, 0x00, 0x00, 0x04, 0x12, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x07, 0x11, 0x23, 0xac, 0xab, 0x01, 0xb3, 0xc9, 0xfe, 0x73, 0x01, 0xcb, 0xca, 0xfe, 0x8b, 0x7b, 0xab, 0x04, 0x60, 0xfe, 0x2f, 0x01, 0xd1, 0xfe, 0x5a, 0xfd, 0x46, 0x02, 0x42, 0x81, 0xfe, 0x3f, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x06, 0x14, 0x00, 0x0d, 0x00, 0x00, 0x09, 0x01, 0x23, 0x09, 0x01, 0x23, 0x01, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x17, 0x16, 0x02, 0x3b, 0x01, 0xd1, 0xb0, 0xfe, 0xe6, 0xfe, 0xa4, 0xaf, 0x01, 0xba, 0x43, 0x2a, 0x60, 0x57, 0x69, 0xcc, 0x05, 0x65, 0xfa, 0x9b, 0x03, 0x3c, 0xfc, 0xc4, 0x04, 0x32, 0xc6, 0x7e, 0x9e, 0x02, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xfe, 0x56, 0x04, 0x68, 0x04, 0x60, 0x10, 0x06, 0x00, 0x77, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x03, 0xb0, 0x04, 0x60, 0x00, 0x15, 0x00, 0x00, 0x21, 0x01, 0x33, 0x01, 0x36, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x27, 0x33, 0x31, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x01, 0x76, 0xfe, 0xcd, 0xb2, 0x01, 0x04, 0x6c, 0x5a, 0x45, 0x03, 0x02, 0x16, 0x19, 0x60, 0xa8, 0x3e, 0x29, 0x26, 0x7a, 0xa0, 0x6e, 0x04, 0x60, 0xfc, 0x54, 0x7c, 0xac, 0x81, 0x70, 0x35, 0x64, 0x77, 0x83, 0x59, 0x7c, 0x72, 0x4e, 0xc4, 0xaf, 0xe4, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0xfe, 0x52, 0x03, 0x9b, 0x06, 0x14, 0x00, 0x26, 0x00, 0x00, 0x25, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x34, 0x35, 0x16, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x20, 0x11, 0x10, 0x25, 0x26, 0x11, 0x34, 0x37, 0x23, 0x35, 0x21, 0x15, 0x20, 0x11, 0x14, 0x05, 0x15, 0x24, 0x13, 0x12, 0x02, 0x91, 0x77, 0x47, 0x4b, 0x42, 0x49, 0x92, 0x3e, 0x26, 0x1d, 0x1d, 0x1c, 0x34, 0xfd, 0xcf, 0x01, 0x2c, 0xfc, 0xc6, 0xbb, 0x02, 0xc6, 0xfd, 0xca, 0x01, 0xdb, 0xfd, 0xff, 0x02, 0x01, 0x7f, 0x01, 0x4b, 0x4f, 0x78, 0x73, 0x50, 0x57, 0x4b, 0x4c, 0x05, 0x2c, 0x23, 0x25, 0x35, 0x2c, 0x2a, 0x01, 0xb5, 0x01, 0x2c, 0x58, 0x24, 0x01, 0x04, 0xc5, 0x52, 0xb9, 0xb9, 0xfe, 0xdd, 0xbf, 0x09, 0xaa, 0x16, 0xfe, 0xbc, 0xfe, 0xf1, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x12, 0x06, 0x00, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0xff, 0xd9, 0x04, 0x23, 0x04, 0x60, 0x00, 0x17, 0x00, 0x00, 0x13, 0x21, 0x15, 0x23, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x43, 0x03, 0xc5, 0x7f, 0x2d, 0x31, 0x0d, 0x28, 0x06, 0x1f, 0x43, 0x21, 0x6c, 0x53, 0xfe, 0x8c, 0xa9, 0x80, 0x04, 0x60, 0xb8, 0xfd, 0x50, 0x48, 0x3f, 0x05, 0x01, 0x85, 0x0d, 0x0c, 0x83, 0xb0, 0x02, 0x9c, 0xfc, 0x58, 0x03, 0xa8, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x11, 0x23, 0x11, 0x34, 0x05, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0xf8, 0x37, 0x88, 0x35, 0xa4, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x34, 0xa7, 0x02, 0xda, 0x96, 0x83, 0x84, 0x96, 0x96, 0x84, 0x83, 0x96, 0x03, 0x98, 0x66, 0x5a, 0x23, 0xfe, 0xbc, 0xfe, 0xf8, 0xfe, 0xf8, 0xfe, 0xbc, 0x61, 0x64, 0xfd, 0xae, 0x03, 0xcf, 0xe7, 0xdd, 0xcb, 0xe7, 0xe7, 0xcb, 0xcb, 0xe7, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xfe, 0x52, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x24, 0x00, 0x00, 0x05, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x34, 0x35, 0x16, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x02, 0x64, 0xf2, 0xfe, 0xf4, 0x01, 0x0f, 0xeb, 0x4d, 0x92, 0x44, 0x46, 0x8d, 0x48, 0xa2, 0xb2, 0xb2, 0x9e, 0x76, 0x48, 0x4c, 0x43, 0x49, 0x92, 0x3e, 0x26, 0x1d, 0x1d, 0x1c, 0x1d, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x12, 0x01, 0x3a, 0x23, 0x23, 0xac, 0x2b, 0x2b, 0xe3, 0xcd, 0xcd, 0xe3, 0x4c, 0x4f, 0x78, 0x73, 0x50, 0x57, 0x4b, 0x4c, 0x05, 0x2c, 0x23, 0x25, 0x35, 0x2c, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x5b, 0x04, 0x60, 0x00, 0x0d, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x21, 0x15, 0x23, 0x16, 0x15, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x02, 0x34, 0x89, 0x49, 0x4e, 0x9a, 0x86, 0x85, 0x9a, 0x4d, 0x47, 0x8b, 0x02, 0x26, 0xb9, 0x62, 0x7b, 0x7c, 0xd8, 0xd9, 0x7a, 0x7b, 0x7b, 0x66, 0x03, 0xce, 0x6e, 0x73, 0xbe, 0xc9, 0xe7, 0xe8, 0xc8, 0xb7, 0x7a, 0x6e, 0x92, 0xb8, 0x9c, 0xdd, 0xfe, 0xed, 0x9c, 0x9d, 0x9d, 0x9c, 0x01, 0x13, 0x01, 0x15, 0x9b, 0x81, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0xfc, 0x04, 0x60, 0x00, 0x11, 0x00, 0x00, 0x25, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x14, 0x02, 0x9c, 0x20, 0x62, 0x50, 0x64, 0xa2, 0x4a, 0x4a, 0xfe, 0x86, 0x03, 0xa2, 0xfe, 0x82, 0xcc, 0x30, 0x9c, 0x60, 0x62, 0xd4, 0x02, 0x12, 0xb8, 0xb8, 0xfd, 0xe3, 0x91, 0x00, 0x01, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x04, 0x60, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x27, 0x33, 0x31, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x27, 0x22, 0x27, 0x26, 0x35, 0x03, 0x01, 0x30, 0x2e, 0x31, 0x60, 0x87, 0x5e, 0x36, 0x0d, 0x07, 0x1b, 0x19, 0x5f, 0xa7, 0x3f, 0x29, 0x25, 0x73, 0x8c, 0xe5, 0xa1, 0x5a, 0x59, 0x01, 0x04, 0x60, 0xfd, 0x2b, 0x87, 0x40, 0x45, 0xd0, 0x76, 0xbb, 0x66, 0x80, 0x77, 0x83, 0x5a, 0x7b, 0x73, 0x9a, 0xfd, 0xbb, 0xe4, 0x01, 0x78, 0x76, 0xc5, 0x02, 0xca, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0xfe, 0x56, 0x04, 0x56, 0x04, 0x68, 0x00, 0x0a, 0x00, 0x29, 0x00, 0x00, 0x01, 0x22, 0x15, 0x11, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x11, 0x23, 0x11, 0x22, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x11, 0x10, 0x02, 0xea, 0x3a, 0x55, 0x55, 0x4d, 0x4d, 0x40, 0x30, 0x7e, 0x73, 0x7b, 0x7b, 0x75, 0xb6, 0xa5, 0xb4, 0x77, 0x7b, 0x7b, 0x5b, 0x95, 0x3b, 0x34, 0x4e, 0x4d, 0x46, 0x65, 0x03, 0xcb, 0x91, 0xfd, 0x52, 0x68, 0x5d, 0xdf, 0xd0, 0x70, 0x5b, 0x9d, 0x84, 0x8d, 0xfe, 0xd9, 0xfe, 0xf1, 0xa1, 0x98, 0xfe, 0x6e, 0x01, 0x91, 0x99, 0x9c, 0x01, 0x13, 0x01, 0x1e, 0x92, 0x6d, 0x1c, 0xa3, 0x17, 0x4e, 0x73, 0xbe, 0xca, 0x73, 0x67, 0x02, 0xaf, 0x01, 0x2e, 0x00, 0x00, 0x01, 0x00, 0x35, 0xfe, 0x55, 0x03, 0xf4, 0x04, 0x61, 0x00, 0x17, 0x00, 0x00, 0x05, 0x03, 0x01, 0x23, 0x01, 0x03, 0x26, 0x2b, 0x01, 0x35, 0x17, 0x16, 0x17, 0x13, 0x01, 0x33, 0x01, 0x13, 0x16, 0x3b, 0x01, 0x15, 0x27, 0x26, 0x02, 0x92, 0x85, 0xfe, 0xeb, 0xc3, 0x01, 0x87, 0xa4, 0x2c, 0x8b, 0x2c, 0x3f, 0xe8, 0x3a, 0x86, 0x01, 0x14, 0xc4, 0xfe, 0x79, 0xa4, 0x2c, 0x8b, 0x2c, 0x3f, 0xe9, 0xfa, 0x01, 0x7f, 0xfd, 0xd0, 0x03, 0x18, 0x01, 0xd7, 0x7e, 0x9e, 0x02, 0x07, 0xa7, 0xfe, 0x81, 0x02, 0x30, 0xfc, 0xe8, 0xfe, 0x29, 0x7e, 0x9e, 0x02, 0x07, 0x00, 0x00, 0x01, 0x00, 0x64, 0xfe, 0x56, 0x04, 0x56, 0x04, 0x60, 0x00, 0x1b, 0x00, 0x00, 0x05, 0x26, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x17, 0x11, 0x33, 0x11, 0x36, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x07, 0x11, 0x23, 0x02, 0x0b, 0xd0, 0x60, 0x76, 0xa7, 0x4d, 0x43, 0x6f, 0xa5, 0x76, 0x3c, 0x4c, 0xa8, 0x76, 0x6a, 0xc6, 0xa5, 0x19, 0x25, 0x61, 0x77, 0xf3, 0x02, 0x89, 0xfd, 0x7e, 0xb7, 0x4c, 0x42, 0x0e, 0x03, 0xd5, 0xfc, 0x2c, 0x0e, 0x42, 0x54, 0xaf, 0x02, 0x81, 0xfd, 0x78, 0xfc, 0x6e, 0x63, 0x23, 0xfe, 0x6e, 0x00, 0x00, 0x01, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x04, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x05, 0x20, 0x11, 0x34, 0x13, 0x33, 0x02, 0x15, 0x10, 0x33, 0x32, 0x11, 0x33, 0x10, 0x33, 0x32, 0x11, 0x34, 0x03, 0x33, 0x12, 0x15, 0x10, 0x21, 0x22, 0x03, 0x02, 0x01, 0xef, 0xfe, 0x8b, 0x8b, 0xb2, 0x81, 0xc8, 0xb7, 0x99, 0xb7, 0xc7, 0x80, 0xb2, 0x8c, 0xfe, 0x8a, 0xf5, 0x1d, 0x25, 0x1d, 0x02, 0x52, 0xeb, 0x01, 0x40, 0xfe, 0xc0, 0xf0, 0xfe, 0x4f, 0x02, 0x1a, 0xfd, 0xe6, 0x01, 0xb1, 0xf0, 0x01, 0x40, 0xfe, 0xc0, 0xeb, 0xfd, 0xae, 0x01, 0x2b, 0xfe, 0xd5, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x02, 0x3e, 0x06, 0x10, 0x12, 0x26, 0x03, 0x4d, 0x0e, 0x00, 0x10, 0x07, 0x00, 0x6a, 0xff, 0x43, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x10, 0x10, 0x26, 0x00, 0x6a, 0x1a, 0x00, 0x12, 0x06, 0x03, 0x59, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x10, 0x26, 0x03, 0x1b, 0x70, 0x00, 0x12, 0x06, 0x03, 0x53, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x66, 0x10, 0x26, 0x03, 0x1b, 0x1f, 0x00, 0x12, 0x06, 0x03, 0x59, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x66, 0x12, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x03, 0x1b, 0x01, 0x36, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x04, 0xe0, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x02, 0x23, 0x13, 0x01, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x5b, 0xea, 0xfd, 0x65, 0x02, 0xca, 0xfe, 0xb7, 0x79, 0xf5, 0xfd, 0x59, 0xb6, 0x05, 0xd5, 0xfd, 0x89, 0x02, 0x77, 0xfd, 0x48, 0xfc, 0xe3, 0xfe, 0x56, 0x01, 0x84, 0x02, 0xf5, 0xfd, 0x31, 0x00, 0x03, 0x00, 0x96, 0xff, 0xe9, 0x03, 0xdf, 0x06, 0x24, 0x00, 0x0a, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x00, 0x01, 0x32, 0x36, 0x37, 0x36, 0x37, 0x34, 0x23, 0x22, 0x07, 0x06, 0x01, 0x16, 0x15, 0x14, 0x07, 0x06, 0x20, 0x27, 0x26, 0x02, 0x37, 0x36, 0x17, 0x1e, 0x01, 0x12, 0x06, 0x07, 0x06, 0x23, 0x10, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x34, 0x26, 0x01, 0x45, 0x48, 0xb7, 0x3d, 0x6c, 0x01, 0xb7, 0x6e, 0x53, 0x31, 0x01, 0xbd, 0xdd, 0x35, 0x72, 0xfe, 0x40, 0x7d, 0x64, 0x02, 0x6c, 0x79, 0xbd, 0x94, 0xc4, 0x02, 0x54, 0xe2, 0x50, 0xc9, 0x34, 0x48, 0x9d, 0x81, 0x4e, 0x16, 0x9b, 0x03, 0x70, 0x04, 0x3d, 0x6c, 0x93, 0xde, 0xba, 0x6c, 0xfe, 0xc7, 0xa7, 0xe9, 0x82, 0x5f, 0xd5, 0xd5, 0xa8, 0x03, 0x2c, 0xbe, 0xd5, 0x01, 0x01, 0xe2, 0xfe, 0xe5, 0xb6, 0x96, 0x14, 0xfe, 0xea, 0x80, 0xb0, 0x9c, 0x2d, 0xd1, 0x9e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe9, 0x04, 0x03, 0x06, 0x24, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x20, 0x27, 0x26, 0x11, 0x34, 0x36, 0x33, 0x32, 0x12, 0x10, 0x00, 0x20, 0x02, 0x11, 0x17, 0x15, 0x10, 0x12, 0x20, 0x12, 0x03, 0x50, 0x2c, 0x3c, 0x86, 0x4a, 0x6c, 0x6c, 0x43, 0xf7, 0xfe, 0xeb, 0x76, 0xbd, 0xbb, 0x9d, 0xc4, 0xdd, 0xff, 0x00, 0xfe, 0x53, 0xf0, 0xa9, 0x9e, 0x01, 0x11, 0x94, 0x03, 0x70, 0xf6, 0x7e, 0xaa, 0x89, 0x5a, 0xaa, 0x5a, 0x37, 0xaa, 0x41, 0x69, 0x01, 0x36, 0xa0, 0xde, 0xfe, 0x64, 0xfc, 0xfc, 0xfe, 0x65, 0x01, 0xb6, 0x01, 0xd2, 0x01, 0xa0, 0xfe, 0xf3, 0xfe, 0xbd, 0x01, 0x42, 0x00, 0x00, 0x01, 0x00, 0x4e, 0x00, 0x00, 0x04, 0xc9, 0x05, 0xdf, 0x00, 0x20, 0x00, 0x00, 0x01, 0x06, 0x03, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x27, 0x02, 0x27, 0x26, 0x22, 0x07, 0x35, 0x36, 0x32, 0x17, 0x04, 0x13, 0x12, 0x25, 0x36, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x03, 0xd9, 0x90, 0x4a, 0x26, 0xb7, 0x26, 0x49, 0x90, 0x46, 0x6b, 0x24, 0x1c, 0x64, 0x4d, 0x01, 0x22, 0x41, 0x60, 0x01, 0x03, 0x22, 0x56, 0x25, 0x4b, 0x0f, 0x17, 0x44, 0x77, 0x05, 0x11, 0x48, 0xfe, 0xf3, 0x8d, 0xa5, 0xfd, 0x76, 0x02, 0x8a, 0xa5, 0x8d, 0x01, 0x0d, 0x48, 0x23, 0x09, 0xaa, 0x0a, 0x0d, 0x30, 0xfe, 0x72, 0x01, 0x7b, 0x43, 0x09, 0x20, 0x40, 0x5b, 0x29, 0x2f, 0x42, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe4, 0x00, 0x00, 0x05, 0xf8, 0x06, 0x66, 0x10, 0x27, 0x03, 0x1b, 0xfe, 0x96, 0x00, 0x00, 0x10, 0x07, 0x03, 0x66, 0x01, 0x2e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4e, 0x00, 0x00, 0x04, 0xc9, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x04, 0x4b, 0x01, 0x75, 0x12, 0x06, 0x03, 0x66, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0xfe, 0x56, 0x04, 0x56, 0x06, 0x14, 0x00, 0x15, 0x00, 0x1e, 0x00, 0x27, 0x00, 0x00, 0x01, 0x11, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x11, 0x23, 0x11, 0x22, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x33, 0x11, 0x13, 0x32, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x23, 0x03, 0x11, 0x22, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x02, 0xb0, 0xb3, 0x78, 0x7b, 0x7b, 0x78, 0xb3, 0xa5, 0xb4, 0x77, 0x7b, 0x7b, 0x77, 0xb4, 0xa5, 0x65, 0x45, 0x4c, 0x01, 0x01, 0x4e, 0x45, 0x65, 0xa5, 0x66, 0x45, 0x4e, 0x01, 0x01, 0x4c, 0x45, 0x06, 0x14, 0xfe, 0x63, 0x99, 0x9c, 0xfe, 0xed, 0xfe, 0xed, 0x9c, 0x99, 0xfe, 0x6f, 0x01, 0x91, 0x99, 0x9c, 0x01, 0x13, 0x01, 0x13, 0x9c, 0x99, 0x01, 0x9d, 0xfa, 0x77, 0x67, 0x73, 0xca, 0xc8, 0x75, 0x67, 0xfc, 0xb8, 0x03, 0x48, 0x67, 0x75, 0xc8, 0xca, 0x73, 0x67, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3a, 0xff, 0xe3, 0x05, 0xc9, 0x04, 0x60, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x00, 0x13, 0x35, 0x21, 0x15, 0x23, 0x16, 0x15, 0x10, 0x25, 0x26, 0x03, 0x02, 0x23, 0x20, 0x11, 0x34, 0x37, 0x29, 0x01, 0x06, 0x15, 0x10, 0x33, 0x32, 0x03, 0x33, 0x02, 0x37, 0x36, 0x11, 0x34, 0x3a, 0x05, 0x8e, 0x84, 0x46, 0xfe, 0x8a, 0xf4, 0x1e, 0x25, 0xee, 0xfe, 0x8b, 0x45, 0x03, 0xce, 0xfc, 0xe9, 0x40, 0xc8, 0xbb, 0x04, 0x99, 0x04, 0xbb, 0xc7, 0x03, 0xa8, 0xb8, 0xb8, 0xcf, 0xa4, 0xfd, 0xad, 0x01, 0x01, 0x01, 0x2a, 0xfe, 0xd5, 0x02, 0x52, 0xa4, 0xcf, 0xd1, 0xa7, 0xfe, 0x4f, 0x02, 0x1a, 0xfd, 0xe3, 0x03, 0x03, 0x01, 0xae, 0xa7, 0x00, 0x01, 0x00, 0x64, 0xfe, 0x5b, 0x04, 0x53, 0x04, 0x67, 0x00, 0x39, 0x00, 0x00, 0x05, 0x26, 0x27, 0x26, 0x34, 0x37, 0x07, 0x02, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x01, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x35, 0x36, 0x33, 0x32, 0x17, 0x04, 0x11, 0x14, 0x07, 0x37, 0x12, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x01, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x02, 0x07, 0x06, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x03, 0x93, 0xdd, 0x1e, 0x09, 0x0c, 0xaa, 0x57, 0xb4, 0x31, 0x1f, 0x31, 0x01, 0x07, 0x37, 0x0c, 0x18, 0x7f, 0x34, 0x52, 0x3a, 0x52, 0x17, 0x19, 0x01, 0x00, 0x1a, 0xaa, 0x56, 0xb4, 0x32, 0x1f, 0x31, 0xfe, 0xf9, 0x37, 0x0c, 0x18, 0x7f, 0x34, 0x51, 0x22, 0xb8, 0x3f, 0x92, 0x54, 0x56, 0x41, 0x94, 0x0a, 0x20, 0xf0, 0x49, 0x81, 0x35, 0x6c, 0xfe, 0xf7, 0x7c, 0x22, 0x4f, 0x9a, 0x01, 0x09, 0x8a, 0x7a, 0x3a, 0x36, 0x68, 0x6c, 0xe0, 0x30, 0x04, 0x27, 0xfe, 0xc3, 0x5b, 0x4d, 0x6c, 0x01, 0x09, 0x7c, 0x22, 0x4f, 0x9a, 0xfe, 0xf7, 0x8a, 0x7a, 0x3a, 0x36, 0x68, 0x6c, 0xfd, 0xe0, 0x66, 0x24, 0x31, 0xa0, 0x31, 0x00, 0x02, 0x00, 0x67, 0xfe, 0x58, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x11, 0x00, 0x1f, 0x00, 0x00, 0x05, 0x11, 0x23, 0x11, 0x26, 0x27, 0x26, 0x10, 0x37, 0x36, 0x21, 0x20, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x02, 0x20, 0x07, 0x06, 0x11, 0x10, 0x17, 0x16, 0x20, 0x37, 0x36, 0x11, 0x10, 0x27, 0x03, 0x2a, 0xa6, 0xe2, 0x90, 0xaa, 0xaa, 0xa9, 0x01, 0x1b, 0x01, 0x1b, 0xa9, 0xa9, 0xa9, 0x8f, 0x6f, 0xfe, 0x74, 0x74, 0x75, 0x75, 0x74, 0x01, 0x8c, 0x74, 0x74, 0x74, 0x18, 0xfe, 0x70, 0x01, 0x90, 0x1a, 0xb3, 0xd2, 0x02, 0xc4, 0xd3, 0xd2, 0xd2, 0xd3, 0xfe, 0x9e, 0xfe, 0x9f, 0xd2, 0xb3, 0x05, 0x49, 0xa4, 0xa4, 0xfe, 0xe5, 0xfe, 0xe6, 0xa4, 0xa4, 0xa4, 0xa4, 0x01, 0x1a, 0x01, 0x1b, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x03, 0x04, 0x7b, 0x00, 0x0d, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x10, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x03, 0x11, 0x23, 0x11, 0x26, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x33, 0x32, 0x12, 0x11, 0x10, 0x07, 0x06, 0x02, 0x34, 0x85, 0x4d, 0x4e, 0x4d, 0x4d, 0x86, 0x85, 0x9a, 0x4d, 0x4d, 0x34, 0x99, 0xab, 0x60, 0x7b, 0x7b, 0x7a, 0xd9, 0xd8, 0xf7, 0x7b, 0x60, 0x03, 0xdf, 0x73, 0x74, 0xfe, 0x6e, 0x74, 0x73, 0xe8, 0xc8, 0xc7, 0x74, 0x75, 0xfc, 0x09, 0xfe, 0x6e, 0x01, 0x92, 0x1b, 0x7d, 0x9c, 0x01, 0x13, 0x01, 0x14, 0x9c, 0x9c, 0xfe, 0xc8, 0xfe, 0xec, 0xfe, 0xed, 0x9c, 0x7b, 0x00, 0x01, 0x00, 0x7d, 0xfe, 0x52, 0x04, 0x34, 0x05, 0xd5, 0x00, 0x24, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x11, 0x10, 0x17, 0x16, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x34, 0x35, 0x16, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x20, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x29, 0x01, 0x15, 0x02, 0xf2, 0xf2, 0x56, 0x6f, 0x52, 0x62, 0xb4, 0x6e, 0x50, 0x4b, 0x42, 0x48, 0x93, 0x3e, 0x26, 0x1d, 0x1d, 0x1c, 0x34, 0xfe, 0xe0, 0x80, 0x86, 0xa7, 0x7c, 0x01, 0x52, 0x01, 0x42, 0x05, 0x2b, 0x77, 0x98, 0xfe, 0xcd, 0xfe, 0xb5, 0x7f, 0x98, 0x54, 0x4f, 0x78, 0x73, 0x50, 0x57, 0x4b, 0x4c, 0x05, 0x2c, 0x23, 0x25, 0x35, 0x2c, 0x2a, 0xcb, 0xd6, 0x01, 0x65, 0x01, 0x4e, 0xed, 0xb1, 0xaa, 0x00, 0x00, 0x01, 0x00, 0x65, 0xfe, 0x52, 0x03, 0xe3, 0x04, 0x60, 0x00, 0x20, 0x00, 0x00, 0x05, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x21, 0x15, 0x21, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x34, 0x35, 0x16, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x02, 0x2a, 0xb8, 0xfe, 0xf4, 0x01, 0x0f, 0xeb, 0x01, 0x82, 0xfe, 0x86, 0xa2, 0xb2, 0xb2, 0x64, 0x75, 0x48, 0x4c, 0x43, 0x48, 0x92, 0x3e, 0x26, 0x1c, 0x1c, 0x1d, 0x1d, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x12, 0x01, 0x1f, 0x9c, 0xc7, 0xce, 0xcd, 0xe3, 0x4c, 0x4f, 0x78, 0x73, 0x50, 0x57, 0x4b, 0x4c, 0x05, 0x2c, 0x23, 0x25, 0x35, 0x2c, 0x2a, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xba, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0xff, 0x53, 0xfe, 0x56, 0x02, 0xf3, 0x06, 0x14, 0x00, 0x27, 0x00, 0x00, 0x33, 0x11, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x21, 0x15, 0x21, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0xd6, 0x7b, 0x56, 0x98, 0x2c, 0x2d, 0x2c, 0x2e, 0x20, 0x25, 0x25, 0x28, 0x6c, 0x34, 0x43, 0x01, 0x21, 0xfe, 0xdf, 0x7d, 0x59, 0x9b, 0x34, 0x2e, 0x2d, 0x2a, 0x2c, 0x2d, 0x2d, 0x2b, 0x4f, 0x39, 0x4a, 0x04, 0x82, 0xa0, 0x8e, 0x64, 0x09, 0x09, 0x12, 0xa4, 0x1c, 0x0e, 0x0f, 0x3e, 0x51, 0x6f, 0xfe, 0xc9, 0x8f, 0xfd, 0x3f, 0x92, 0xa5, 0x73, 0x0a, 0x0b, 0x16, 0xa4, 0x1f, 0x10, 0x11, 0x4b, 0x5f, 0x00, 0x00, 0x01, 0x00, 0xa1, 0xff, 0xfc, 0x04, 0x59, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x00, 0x01, 0x03, 0x01, 0x03, 0x06, 0x17, 0x16, 0x37, 0x15, 0x22, 0x27, 0x26, 0x37, 0x13, 0x01, 0x13, 0x36, 0x27, 0x26, 0x07, 0x35, 0x32, 0x17, 0x16, 0x01, 0xfd, 0x63, 0x02, 0xbe, 0xd2, 0x23, 0x18, 0x3b, 0x76, 0xcf, 0x49, 0x55, 0x11, 0x8b, 0xfd, 0x52, 0x9b, 0x23, 0x19, 0x3b, 0x76, 0xcf, 0x49, 0x55, 0x04, 0x87, 0xfe, 0x5b, 0x01, 0x7e, 0xfd, 0x2c, 0x60, 0x2a, 0x6c, 0x23, 0xbd, 0x46, 0x52, 0xb6, 0x01, 0xda, 0xfe, 0x91, 0x02, 0x90, 0x60, 0x2a, 0x6c, 0x23, 0xbd, 0x46, 0x52, 0x00, 0x01, 0x00, 0xab, 0x00, 0x00, 0x04, 0x14, 0x06, 0x13, 0x00, 0x07, 0x00, 0x00, 0x01, 0x03, 0x23, 0x13, 0x21, 0x13, 0x33, 0x03, 0x04, 0x14, 0xfd, 0xa5, 0xcb, 0xfd, 0x6f, 0xfd, 0xa5, 0xcb, 0x03, 0x70, 0xfc, 0x90, 0x02, 0xc6, 0x03, 0x4d, 0xfd, 0x5d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x66, 0xfe, 0x56, 0x05, 0xbd, 0x05, 0xf0, 0x00, 0x21, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x06, 0x07, 0x35, 0x36, 0x21, 0x20, 0x13, 0x12, 0x11, 0x10, 0x03, 0x23, 0x12, 0x11, 0x10, 0x27, 0x06, 0x07, 0x06, 0x15, 0x11, 0x23, 0x36, 0x11, 0x34, 0x3f, 0x01, 0x02, 0x21, 0x22, 0x02, 0x16, 0x99, 0xb9, 0x5d, 0xbb, 0x01, 0x5b, 0x01, 0xaa, 0xd5, 0xc1, 0xde, 0xca, 0xea, 0x4a, 0x4a, 0x55, 0x3a, 0xb8, 0x02, 0xa3, 0xa9, 0xbb, 0xfe, 0xc6, 0x2b, 0x05, 0x3a, 0xfd, 0x8c, 0x02, 0x49, 0x4b, 0x69, 0xc6, 0xcf, 0xfe, 0xce, 0xfe, 0xec, 0xfd, 0xc2, 0xfe, 0x58, 0xfe, 0x92, 0x01, 0x4c, 0x01, 0xca, 0x01, 0xd1, 0x7d, 0x2f, 0x4d, 0x34, 0xd0, 0xfd, 0xc6, 0x21, 0x02, 0x14, 0xf7, 0x8f, 0x8d, 0x01, 0x04, 0x00, 0x01, 0x00, 0x6b, 0xfe, 0x90, 0x04, 0x21, 0x04, 0x78, 0x00, 0x16, 0x00, 0x00, 0x01, 0x03, 0x23, 0x01, 0x26, 0x27, 0x01, 0x23, 0x01, 0x26, 0x27, 0x26, 0x23, 0x35, 0x20, 0x17, 0x16, 0x13, 0x12, 0x11, 0x23, 0x10, 0x27, 0x03, 0x16, 0xd7, 0xa6, 0x01, 0x40, 0x0d, 0x2d, 0xfe, 0x73, 0xa7, 0x01, 0xe9, 0x58, 0x2a, 0xa9, 0xbe, 0x01, 0x0f, 0xda, 0xc9, 0x9b, 0x69, 0x98, 0x56, 0x01, 0x34, 0xfe, 0xcc, 0x01, 0xc0, 0x23, 0x4d, 0xfd, 0xd0, 0x02, 0xb0, 0x7f, 0x21, 0x84, 0xa4, 0xd8, 0xc8, 0xfe, 0x50, 0xfe, 0xdf, 0xfe, 0x89, 0x01, 0x5e, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0xfe, 0x4b, 0x06, 0x52, 0x05, 0xd5, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x10, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x27, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x11, 0x34, 0x13, 0x36, 0x37, 0x33, 0x06, 0x03, 0x06, 0x15, 0x10, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x11, 0x34, 0x27, 0x02, 0x27, 0x33, 0x16, 0x17, 0x12, 0x06, 0x51, 0x37, 0x3d, 0xc5, 0xa2, 0xf8, 0x6a, 0x7e, 0x58, 0x7c, 0x6d, 0xb9, 0x93, 0x5c, 0x3d, 0x5a, 0x24, 0x23, 0x5a, 0x5b, 0x83, 0xbe, 0x6d, 0x6e, 0x5a, 0x35, 0x53, 0xe0, 0x4b, 0x7a, 0x3c, 0x41, 0x42, 0x70, 0x67, 0x40, 0x40, 0xb3, 0x3f, 0x3f, 0x69, 0x78, 0x3b, 0x40, 0x3c, 0x7a, 0x4c, 0xe1, 0x56, 0x32, 0x5a, 0x02, 0xe0, 0xfe, 0xef, 0xcb, 0xe6, 0xa6, 0x88, 0x64, 0x2a, 0x17, 0x85, 0x18, 0x30, 0x51, 0x80, 0x17, 0x41, 0x5e, 0xad, 0xad, 0x5e, 0x5e, 0xb1, 0xb4, 0x01, 0x98, 0xc9, 0x01, 0x0e, 0x9f, 0x7f, 0x46, 0xfe, 0xbf, 0x9f, 0xb7, 0xfe, 0xcd, 0x6b, 0x6d, 0x69, 0x68, 0xc6, 0xf1, 0xf1, 0xc6, 0x68, 0x69, 0x6d, 0x77, 0x01, 0x27, 0xb7, 0x9f, 0x01, 0x41, 0x46, 0x82, 0x9c, 0xfe, 0xeb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x79, 0xfe, 0x55, 0x05, 0x8a, 0x04, 0x60, 0x00, 0x25, 0x00, 0x00, 0x21, 0x26, 0x03, 0x02, 0x23, 0x20, 0x11, 0x34, 0x13, 0x33, 0x02, 0x15, 0x10, 0x17, 0x16, 0x03, 0x33, 0x02, 0x37, 0x36, 0x11, 0x34, 0x03, 0x33, 0x12, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x27, 0x36, 0x37, 0x36, 0x04, 0x14, 0xf8, 0x1a, 0x20, 0xf3, 0xfe, 0x8b, 0x79, 0xc4, 0x81, 0xc8, 0xbc, 0x05, 0x99, 0x03, 0xba, 0xc7, 0x80, 0xc4, 0x7a, 0x33, 0x5e, 0xb2, 0x8a, 0xbd, 0x61, 0x64, 0x52, 0x49, 0x7d, 0xb3, 0x01, 0x01, 0x0d, 0xfe, 0xed, 0x02, 0x3a, 0xeb, 0x01, 0x40, 0xfe, 0xc0, 0xf0, 0xfe, 0x97, 0x01, 0x01, 0x01, 0xd4, 0xfe, 0x2b, 0x02, 0x02, 0x01, 0x68, 0xf0, 0x01, 0x40, 0xfe, 0xc0, 0xeb, 0xd1, 0x84, 0xf4, 0x9e, 0x7b, 0x49, 0x25, 0x10, 0x6c, 0x0b, 0x2b, 0x3f, 0x00, 0x00, 0x01, 0x00, 0x67, 0xfe, 0x56, 0x04, 0xc1, 0x05, 0xf0, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x11, 0x10, 0x13, 0x36, 0x25, 0x02, 0xa1, 0xa2, 0x56, 0x78, 0x63, 0x58, 0xb0, 0xb0, 0x58, 0x5a, 0xc3, 0xc3, 0x3e, 0x5d, 0x5e, 0x99, 0xe6, 0x8d, 0x91, 0xa7, 0x88, 0x01, 0x0a, 0x05, 0x4a, 0x12, 0x84, 0xb9, 0xfe, 0xee, 0xf9, 0xab, 0x98, 0x98, 0x99, 0x01, 0x0b, 0x02, 0xec, 0xf8, 0x81, 0x02, 0x90, 0x84, 0x40, 0x3f, 0xd5, 0xdd, 0x01, 0x47, 0x01, 0x36, 0x01, 0x08, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x18, 0x04, 0x7b, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x02, 0x4a, 0x8b, 0x48, 0x66, 0x54, 0x4b, 0x01, 0x2b, 0x4b, 0x4c, 0xa6, 0xa6, 0x34, 0x4f, 0x51, 0x81, 0xc4, 0x78, 0x7b, 0x8e, 0x72, 0xe4, 0x03, 0xfd, 0x0e, 0x63, 0x8d, 0xd0, 0xbd, 0x81, 0x74, 0x73, 0x74, 0xcb, 0x02, 0x31, 0xf9, 0xf6, 0x02, 0x52, 0x64, 0x30, 0x31, 0xa2, 0xa8, 0xf8, 0xec, 0xc8, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x4b, 0x05, 0x4c, 0x05, 0xd5, 0x00, 0x25, 0x00, 0x00, 0x01, 0x20, 0x17, 0x16, 0x11, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x27, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x11, 0x36, 0x37, 0x36, 0x02, 0xf8, 0x01, 0x09, 0x9f, 0xab, 0x36, 0x3c, 0x99, 0xaf, 0xd9, 0xa7, 0x41, 0x58, 0x79, 0x70, 0xc4, 0x88, 0x7b, 0x27, 0x31, 0x71, 0x68, 0xb8, 0xb7, 0x68, 0x65, 0xb6, 0xb6, 0x46, 0x5e, 0x5f, 0x04, 0x7b, 0xb3, 0xc2, 0xfe, 0xfd, 0xcc, 0xa1, 0xb2, 0x80, 0x93, 0x45, 0x35, 0x0c, 0x85, 0x16, 0x32, 0x57, 0x7a, 0x6d, 0x68, 0x7f, 0xc0, 0x9d, 0x96, 0x86, 0x81, 0x7e, 0xde, 0xfe, 0x27, 0x05, 0xd5, 0xfd, 0x9a, 0x87, 0x42, 0x43, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0xff, 0xe3, 0x04, 0x1d, 0x04, 0x9a, 0x00, 0x17, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x36, 0x37, 0x17, 0x06, 0x02, 0xdb, 0x73, 0x7e, 0x1c, 0x32, 0x1a, 0x21, 0x1a, 0x0f, 0x0c, 0x0a, 0x0e, 0x16, 0x17, 0x1f, 0x1d, 0x1b, 0x17, 0x40, 0x35, 0x42, 0x20, 0xf0, 0x61, 0x72, 0x64, 0xee, 0x7f, 0x59, 0x44, 0x2f, 0x3b, 0x49, 0x4c, 0x7a, 0x56, 0x74, 0x4a, 0x39, 0x52, 0x8d, 0x47, 0x44, 0x2c, 0x19, 0x1c, 0x3e, 0x6a, 0x5c, 0x40, 0x24, 0x41, 0x2d, 0x3a, 0x2b, 0x25, 0x1b, 0x1a, 0x1c, 0x29, 0x38, 0x48, 0x5b, 0x55, 0xbd, 0x81, 0x33, 0x26, 0x7a, 0x31, 0x03, 0x44, 0x98, 0x16, 0x0b, 0x21, 0x1a, 0x20, 0x1b, 0x21, 0x20, 0x15, 0x1c, 0x11, 0x14, 0x06, 0x05, 0x19, 0x14, 0x31, 0x18, 0x32, 0xc0, 0xd4, 0xb0, 0x9c, 0x88, 0x2e, 0x23, 0x41, 0x93, 0x4c, 0x2e, 0x23, 0x5e, 0x59, 0x7f, 0x8c, 0x71, 0x19, 0x17, 0x34, 0x2b, 0x26, 0x02, 0x01, 0x0a, 0x07, 0x22, 0x1a, 0x48, 0x34, 0x42, 0x3b, 0x3b, 0x3d, 0x2f, 0x3f, 0x22, 0x2b, 0x9f, 0x56, 0x68, 0x50, 0x92, 0x00, 0x00, 0x00, 0x01, 0x00, 0x47, 0xfe, 0x56, 0x04, 0x8a, 0x05, 0xf6, 0x00, 0x21, 0x00, 0x00, 0x05, 0x06, 0x23, 0x20, 0x01, 0x00, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x23, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x02, 0x01, 0x16, 0x33, 0x20, 0x37, 0x04, 0x7b, 0xe7, 0xf7, 0xfe, 0xd0, 0xfe, 0xda, 0x02, 0x74, 0xa1, 0x62, 0x62, 0x59, 0x93, 0xa2, 0x55, 0x1f, 0x16, 0xd8, 0x28, 0x4d, 0x93, 0xfc, 0xf7, 0x91, 0x92, 0x92, 0xee, 0xfe, 0x48, 0x8d, 0xbf, 0x01, 0x0c, 0xd1, 0xec, 0xbe, 0x01, 0xa3, 0x01, 0xf1, 0xdb, 0x84, 0x9c, 0x8d, 0x65, 0x5d, 0x92, 0x36, 0x3f, 0xa1, 0x66, 0xc2, 0x90, 0x91, 0xf1, 0xd8, 0xb6, 0xfe, 0xf2, 0xfe, 0x85, 0xb5, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0xfe, 0x56, 0x03, 0xf9, 0x04, 0x7b, 0x00, 0x20, 0x00, 0x00, 0x01, 0x06, 0x23, 0x22, 0x01, 0x00, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x23, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x06, 0x01, 0x16, 0x33, 0x32, 0x37, 0x03, 0xec, 0xc4, 0xd2, 0xf7, 0xfe, 0xfb, 0x02, 0x08, 0x96, 0x53, 0x53, 0x4b, 0x7d, 0x8a, 0x48, 0x1b, 0x12, 0xb7, 0x21, 0x41, 0x7e, 0xd6, 0xd1, 0xf8, 0x7c, 0x9e, 0xfe, 0x5e, 0x82, 0x98, 0xe4, 0xb1, 0xfe, 0xef, 0x99, 0x01, 0x79, 0x01, 0x59, 0xc2, 0x6b, 0x7d, 0x6f, 0x53, 0x4b, 0x75, 0x2c, 0x32, 0x81, 0x52, 0x9c, 0xe8, 0xc2, 0xa4, 0x9c, 0xc5, 0xfe, 0xe0, 0xba, 0x90, 0x00, 0x02, 0x00, 0x67, 0x00, 0x00, 0x05, 0x24, 0x05, 0xef, 0x00, 0x02, 0x00, 0x35, 0x00, 0x00, 0x25, 0x21, 0x09, 0x03, 0x26, 0x27, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1b, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x09, 0x01, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x21, 0x35, 0x33, 0x32, 0x37, 0x36, 0x01, 0xab, 0x02, 0x2f, 0xfe, 0xec, 0xfe, 0x45, 0x01, 0x5a, 0xfe, 0xf9, 0x11, 0x17, 0x1f, 0x39, 0x16, 0x14, 0x3e, 0x1e, 0x1c, 0x1c, 0x1a, 0x66, 0x44, 0x27, 0x2b, 0xe8, 0xee, 0x2f, 0x23, 0x44, 0x66, 0x1a, 0x1b, 0x1d, 0x1e, 0x3d, 0x15, 0x16, 0x36, 0x22, 0x11, 0x17, 0xfe, 0xf0, 0x01, 0x4f, 0x05, 0x06, 0x1a, 0x3e, 0x40, 0xfb, 0x4a, 0x3f, 0x41, 0x18, 0x0a, 0xaa, 0x01, 0xca, 0xfe, 0x68, 0x02, 0x3d, 0x01, 0xbb, 0x1d, 0x1a, 0x22, 0x04, 0x0a, 0xbb, 0x0b, 0x05, 0x05, 0x43, 0x28, 0x46, 0xfe, 0x81, 0x01, 0x7f, 0x4b, 0x23, 0x43, 0x05, 0x05, 0x0b, 0xbb, 0x0a, 0x04, 0x22, 0x11, 0x26, 0xfe, 0x45, 0xfd, 0xc3, 0x09, 0x08, 0x21, 0xaa, 0xaa, 0x21, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, 0x04, 0x51, 0x04, 0x7b, 0x00, 0x02, 0x00, 0x35, 0x00, 0x00, 0x25, 0x21, 0x03, 0x09, 0x01, 0x03, 0x26, 0x27, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1b, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x01, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x21, 0x35, 0x33, 0x32, 0x37, 0x36, 0x01, 0x71, 0x01, 0x9e, 0xcd, 0xfe, 0x85, 0x01, 0x1a, 0xd7, 0x13, 0x10, 0x1a, 0x30, 0x13, 0x11, 0x35, 0x1a, 0x18, 0x17, 0x16, 0x76, 0x39, 0x22, 0x24, 0xb1, 0xb1, 0x24, 0x22, 0x39, 0x76, 0x16, 0x17, 0x18, 0x1a, 0x35, 0x11, 0x13, 0x30, 0x1a, 0x10, 0x13, 0xdd, 0x01, 0x0f, 0x05, 0x05, 0x16, 0x35, 0x41, 0xfb, 0xe1, 0x41, 0x34, 0x17, 0x05, 0x9e, 0x01, 0x38, 0xfe, 0xee, 0x01, 0xa4, 0x01, 0x3d, 0x1c, 0x0e, 0x19, 0x03, 0x07, 0x8d, 0x08, 0x04, 0x04, 0x33, 0x1e, 0x35, 0xfe, 0xfa, 0x01, 0x06, 0x35, 0x1e, 0x33, 0x04, 0x04, 0x08, 0x8d, 0x07, 0x03, 0x19, 0x0e, 0x1c, 0xfe, 0xb8, 0xfe, 0x67, 0x08, 0x05, 0x19, 0x9e, 0x9e, 0x19, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa2, 0x06, 0x10, 0x00, 0x1d, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x24, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x00, 0x10, 0x00, 0x23, 0x20, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x21, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x12, 0x10, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x02, 0xd9, 0xfe, 0xf4, 0x4f, 0x32, 0x14, 0x49, 0x4d, 0x6e, 0x75, 0xdd, 0x01, 0x13, 0xfe, 0xed, 0xed, 0xfe, 0xed, 0x94, 0x92, 0x7d, 0x6f, 0x01, 0x85, 0x67, 0x87, 0x90, 0x43, 0x54, 0x88, 0x62, 0x80, 0xb4, 0xa7, 0xa9, 0x5e, 0x5e, 0x5e, 0x5b, 0xac, 0xa9, 0x58, 0x05, 0x2d, 0x02, 0x73, 0x4a, 0xa0, 0x56, 0x22, 0x31, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x9c, 0x9b, 0x01, 0x50, 0x01, 0xde, 0xd2, 0xbb, 0x0a, 0x0a, 0x27, 0xb1, 0x24, 0x08, 0x06, 0xfc, 0x41, 0x01, 0x82, 0xe6, 0x73, 0x74, 0xc0, 0xbd, 0x78, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xec, 0x06, 0x10, 0x00, 0x1f, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x26, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x21, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x13, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x02, 0x58, 0xcc, 0x42, 0x27, 0x12, 0x25, 0x5a, 0x52, 0x6c, 0xb8, 0x72, 0x74, 0x74, 0x72, 0xc5, 0xe6, 0x7b, 0x7a, 0x68, 0x5d, 0x01, 0x2d, 0x56, 0x53, 0x4a, 0x40, 0x53, 0x3f, 0x51, 0x98, 0x4b, 0x4c, 0x83, 0x86, 0x4e, 0x4f, 0x4f, 0x4c, 0x88, 0x85, 0x4a, 0x4b, 0x05, 0x37, 0x02, 0x78, 0x4a, 0xa9, 0x46, 0x36, 0x31, 0xa2, 0xa2, 0xfd, 0xf0, 0xa2, 0xa2, 0x9c, 0x9b, 0x01, 0x50, 0x01, 0xde, 0xd2, 0xbb, 0x0a, 0x0a, 0x27, 0xa7, 0x27, 0x05, 0x06, 0xfc, 0xf8, 0xcd, 0x72, 0x73, 0x73, 0x74, 0xcb, 0xc7, 0x78, 0x73, 0x73, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x27, 0xfe, 0x56, 0x04, 0x3f, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x23, 0x35, 0x23, 0x11, 0x23, 0x11, 0x23, 0x15, 0x23, 0x11, 0x21, 0x11, 0x33, 0x11, 0x04, 0x3e, 0xb6, 0xfa, 0xb6, 0xfa, 0xb6, 0x01, 0xb0, 0xb6, 0x04, 0x60, 0xfe, 0xf2, 0x64, 0xfa, 0xa0, 0x05, 0x60, 0x64, 0x01, 0x0e, 0x01, 0x75, 0xfe, 0x8b, 0x00, 0x01, 0x00, 0x31, 0xfe, 0x55, 0x03, 0xac, 0x05, 0xcf, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x23, 0x35, 0x23, 0x11, 0x23, 0x11, 0x23, 0x15, 0x23, 0x11, 0x21, 0x11, 0x33, 0x11, 0x03, 0xac, 0x9c, 0xce, 0xa7, 0xce, 0x9b, 0x01, 0x69, 0xa7, 0x04, 0x5f, 0xff, 0x00, 0x70, 0xfa, 0x86, 0x05, 0x7a, 0x70, 0x01, 0x00, 0x01, 0x70, 0xfe, 0x90, 0x00, 0x01, 0x00, 0x64, 0xff, 0xf2, 0x04, 0x53, 0x04, 0x67, 0x00, 0x33, 0x00, 0x00, 0x01, 0x02, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x01, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x35, 0x36, 0x33, 0x32, 0x17, 0x04, 0x11, 0x14, 0x07, 0x37, 0x12, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x01, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x15, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x34, 0x37, 0x01, 0xf1, 0x57, 0xb4, 0x31, 0x1f, 0x31, 0x01, 0x07, 0x37, 0x0c, 0x18, 0x7f, 0x34, 0x52, 0x3a, 0x52, 0x17, 0x19, 0x01, 0x00, 0x1a, 0xaa, 0x56, 0xb4, 0x32, 0x1f, 0x31, 0xfe, 0xf9, 0x37, 0x0c, 0x18, 0x7f, 0x34, 0x51, 0x39, 0x52, 0x17, 0x19, 0xff, 0x00, 0x1a, 0x01, 0x99, 0xfe, 0xf7, 0x7c, 0x22, 0x4f, 0x9a, 0x01, 0x09, 0x8a, 0x7a, 0x3a, 0x36, 0x68, 0x6c, 0xe0, 0x30, 0x04, 0x25, 0xfe, 0xc1, 0x5b, 0x4d, 0x6c, 0x01, 0x09, 0x7c, 0x22, 0x4f, 0x9a, 0xfe, 0xf7, 0x8a, 0x7a, 0x3a, 0x36, 0x68, 0x6c, 0xe0, 0x30, 0x04, 0x25, 0x01, 0x3f, 0x5b, 0x4d, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x00, 0x18, 0x00, 0x24, 0x00, 0x00, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x12, 0x29, 0x01, 0x15, 0x21, 0x20, 0x11, 0x24, 0x10, 0x27, 0x26, 0x20, 0x07, 0x06, 0x10, 0x17, 0x16, 0x20, 0x37, 0xa7, 0x51, 0x31, 0x8e, 0x35, 0xa4, 0xb8, 0x72, 0x73, 0x73, 0x72, 0xb8, 0x6c, 0x52, 0x50, 0x34, 0x04, 0x01, 0x04, 0x01, 0xc2, 0xfe, 0x4c, 0xfe, 0x43, 0x02, 0xda, 0x4a, 0x4c, 0xfe, 0xf9, 0x4b, 0x4b, 0x4b, 0x4b, 0x01, 0x07, 0x4c, 0x02, 0x25, 0xd0, 0xa3, 0x62, 0x5e, 0x23, 0xa2, 0xa2, 0xfd, 0xf0, 0xa2, 0xa2, 0x31, 0x30, 0x64, 0xfe, 0x58, 0xaa, 0x02, 0xda, 0x34, 0x01, 0x96, 0x74, 0x73, 0x73, 0x74, 0xfe, 0x6a, 0x74, 0x73, 0x73, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x12, 0x06, 0x00, 0x46, 0x00, 0x00, 0xff, 0xff, 0xff, 0xde, 0xfe, 0x56, 0x01, 0x54, 0x06, 0x14, 0x12, 0x06, 0x00, 0x4d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x12, 0x06, 0x01, 0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x76, 0x04, 0x7b, 0x00, 0x21, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x21, 0x15, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x3f, 0x01, 0x15, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x03, 0x76, 0x22, 0x21, 0x59, 0x60, 0xa4, 0x5c, 0x56, 0x10, 0x02, 0x62, 0xfd, 0x9e, 0x10, 0x56, 0x5c, 0xa4, 0x74, 0x45, 0x43, 0x48, 0x5d, 0x60, 0xf2, 0x8c, 0x8d, 0x8d, 0x8c, 0xf2, 0x5b, 0x62, 0x24, 0x24, 0x03, 0xae, 0x0d, 0x0a, 0x1a, 0x63, 0x5c, 0xa9, 0x90, 0xa9, 0x5c, 0x63, 0x1a, 0x19, 0xa7, 0x12, 0x16, 0x9c, 0x9c, 0x02, 0x28, 0x9c, 0x9c, 0x16, 0x08, 0x0c, 0x00, 0x01, 0x00, 0xb0, 0xff, 0xe3, 0x03, 0xc1, 0x04, 0x7b, 0x00, 0x21, 0x00, 0x00, 0x13, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x21, 0x35, 0x21, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0xb0, 0x24, 0x24, 0x62, 0x5b, 0xf2, 0x8c, 0x8d, 0x8d, 0x8c, 0xf2, 0x60, 0x5d, 0x48, 0x43, 0x45, 0x74, 0xa4, 0x5c, 0x56, 0x10, 0xfd, 0x9e, 0x02, 0x62, 0x10, 0x56, 0x5c, 0xa4, 0x60, 0x59, 0x21, 0x03, 0xae, 0xa3, 0x0c, 0x08, 0x16, 0x9c, 0x9c, 0xfd, 0xd8, 0x9c, 0x9c, 0x16, 0x12, 0xa7, 0x19, 0x1a, 0x63, 0x5c, 0xa9, 0x90, 0xa9, 0x5c, 0x63, 0x1a, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x12, 0x06, 0x00, 0xa0, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x14, 0x12, 0x06, 0x00, 0xc0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x12, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x21, 0x09, 0x01, 0x21, 0x11, 0x23, 0x11, 0x01, 0x23, 0x01, 0x11, 0x23, 0xb5, 0x01, 0x0f, 0x01, 0x57, 0x01, 0x58, 0x01, 0x0f, 0xb1, 0xfe, 0xa5, 0xb6, 0xfe, 0xa5, 0xb0, 0x05, 0xd5, 0xfe, 0x21, 0x01, 0xdf, 0xfa, 0x2b, 0x05, 0x1f, 0xfe, 0x19, 0x01, 0xe7, 0xfa, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x72, 0xfe, 0x56, 0x04, 0x3b, 0x04, 0x60, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x21, 0x1b, 0x01, 0x21, 0x11, 0x23, 0x11, 0x03, 0x23, 0x03, 0x11, 0x23, 0x72, 0x00, 0xff, 0xe5, 0xe6, 0x00, 0xff, 0xa7, 0xf8, 0x8a, 0xf9, 0xa7, 0x04, 0x60, 0xfe, 0x7b, 0x01, 0x85, 0xfb, 0xa0, 0x03, 0xb2, 0xfe, 0x60, 0x01, 0xa0, 0xfa, 0xa4, 0x00, 0x00, 0x02, 0x00, 0x4c, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x00, 0x17, 0x11, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x11, 0x21, 0x15, 0x21, 0x15, 0x23, 0x35, 0x23, 0x35, 0x00, 0x10, 0x27, 0x26, 0x20, 0x07, 0x06, 0x10, 0x17, 0x16, 0x20, 0x37, 0xa7, 0x51, 0x37, 0x88, 0x35, 0xa4, 0xb8, 0x72, 0x73, 0x73, 0x72, 0xb8, 0x6f, 0x4f, 0x50, 0x34, 0x01, 0xb4, 0xfe, 0x4c, 0xa7, 0x5b, 0x03, 0x35, 0x4a, 0x4c, 0xfe, 0xf9, 0x4b, 0x4b, 0x4b, 0x4b, 0x01, 0x07, 0x4c, 0x90, 0x02, 0xb5, 0xe7, 0x8c, 0x66, 0x5a, 0x23, 0xa2, 0xa2, 0xfd, 0xf0, 0xa2, 0xa2, 0x31, 0x30, 0x64, 0xfe, 0xc8, 0xaa, 0x70, 0x70, 0xaa, 0x01, 0xf4, 0x01, 0x96, 0x74, 0x73, 0x73, 0x74, 0xfe, 0x6a, 0x74, 0x73, 0x73, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x12, 0x06, 0x01, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x12, 0x26, 0x03, 0x8d, 0x00, 0x00, 0x10, 0x07, 0x00, 0x79, 0x01, 0xfb, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x10, 0x27, 0x00, 0x79, 0x00, 0xcd, 0x00, 0x00, 0x12, 0x06, 0x03, 0x91, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x6b, 0x12, 0x26, 0x03, 0xa9, 0x00, 0x00, 0x10, 0x07, 0x10, 0xee, 0x04, 0x70, 0x01, 0x75, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x4e, 0x12, 0x26, 0x03, 0xa9, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x04, 0x27, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0xfe, 0x66, 0x05, 0x1b, 0x05, 0xd5, 0x00, 0x1b, 0x00, 0x00, 0x25, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x21, 0x32, 0x16, 0x15, 0x05, 0x1b, 0xb8, 0xcd, 0x44, 0x37, 0x79, 0x64, 0x70, 0x6f, 0xfe, 0xad, 0xb6, 0xfe, 0x7d, 0x04, 0x16, 0xfe, 0x23, 0x01, 0x78, 0xa7, 0xc8, 0x68, 0xfe, 0xf2, 0xf4, 0xaa, 0x96, 0xc2, 0x01, 0x22, 0x9f, 0x9e, 0xfd, 0x39, 0x05, 0x2b, 0xaa, 0xaa, 0xfe, 0x46, 0xe9, 0xee, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x07, 0x6b, 0x12, 0x26, 0x03, 0xa7, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x04, 0x36, 0x01, 0x75, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x00, 0x18, 0x00, 0x00, 0x01, 0x15, 0x06, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x02, 0x07, 0x21, 0x15, 0x21, 0x16, 0x12, 0x33, 0x32, 0x04, 0xa3, 0xbf, 0xf0, 0xfe, 0xd2, 0xfe, 0xa2, 0x01, 0x5e, 0x01, 0x2e, 0xf4, 0xbb, 0xbe, 0xe6, 0xee, 0xd6, 0x14, 0x02, 0xce, 0xfd, 0x32, 0x14, 0xd6, 0xee, 0xe6, 0x01, 0x46, 0xd3, 0x90, 0x01, 0x9f, 0x01, 0x68, 0x01, 0x67, 0x01, 0x9f, 0x8e, 0xd5, 0xbd, 0xfe, 0xe3, 0xef, 0xaa, 0xef, 0xfe, 0xe4, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x05, 0xf0, 0x12, 0x06, 0x00, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x6b, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x2c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x02, 0x1c, 0x07, 0x4e, 0x10, 0x06, 0x00, 0x91, 0x00, 0x00, 0xff, 0xff, 0xff, 0xa0, 0xfe, 0x66, 0x01, 0x6b, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4b, 0x00, 0x00, 0x07, 0x5e, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x21, 0x15, 0x10, 0x02, 0x05, 0x35, 0x36, 0x12, 0x11, 0x35, 0x21, 0x11, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x25, 0x20, 0x11, 0x34, 0x26, 0x2b, 0x01, 0x11, 0x03, 0xfe, 0xfe, 0x4c, 0xb4, 0xfe, 0xb6, 0xc3, 0x86, 0x03, 0x1f, 0xd3, 0xe2, 0xf5, 0xf5, 0xe2, 0xfe, 0x77, 0x01, 0x80, 0x01, 0x20, 0x8e, 0x92, 0xca, 0x05, 0x2b, 0xb8, 0xfd, 0xca, 0xfd, 0xfb, 0x38, 0xaa, 0x2f, 0x01, 0xa6, 0x02, 0x58, 0xfe, 0xfd, 0x9a, 0xda, 0xdd, 0xde, 0xda, 0xa6, 0x01, 0x11, 0x8b, 0x87, 0xfd, 0xdd, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x07, 0x05, 0x05, 0xd5, 0x00, 0x12, 0x00, 0x1b, 0x00, 0x00, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x01, 0x34, 0x26, 0x2b, 0x01, 0x11, 0x33, 0x32, 0x36, 0x03, 0xa5, 0xfd, 0xc6, 0xb6, 0xb6, 0x02, 0x3a, 0xb6, 0xd3, 0xe2, 0xf4, 0xf4, 0xe2, 0x01, 0x17, 0x8e, 0x92, 0xca, 0xca, 0x90, 0x90, 0x02, 0xc7, 0xfd, 0x39, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfd, 0x9a, 0xda, 0xde, 0xdd, 0xda, 0x01, 0xb7, 0x8b, 0x87, 0xfd, 0xdd, 0x87, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0x00, 0x00, 0x05, 0x1b, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x03, 0xac, 0xa7, 0xc8, 0xb5, 0x70, 0x6f, 0xfe, 0xad, 0xb6, 0xfe, 0x7d, 0x04, 0x16, 0xfe, 0x23, 0x03, 0x71, 0xe9, 0xee, 0xfe, 0x66, 0x01, 0x8a, 0x9f, 0x9e, 0xfd, 0x39, 0x05, 0x2b, 0xaa, 0xaa, 0xfe, 0x46, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xf9, 0x07, 0x6b, 0x12, 0x26, 0x03, 0xae, 0x00, 0x00, 0x10, 0x07, 0x10, 0xec, 0x04, 0x70, 0x01, 0x75, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x6b, 0x12, 0x26, 0x03, 0xac, 0x00, 0x00, 0x10, 0x07, 0x10, 0xee, 0x04, 0x68, 0x01, 0x75, 0xff, 0xff, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x44, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf2, 0x04, 0x00, 0x01, 0x75, 0x12, 0x06, 0x03, 0xb7, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x04, 0xb6, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x23, 0x02, 0x68, 0xfe, 0x4d, 0xb6, 0x02, 0x94, 0xb6, 0xfe, 0x4d, 0x9a, 0x05, 0xd5, 0xfa, 0xd5, 0x05, 0x2b, 0xfa, 0x2b, 0xfe, 0xbf, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x15, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x21, 0x11, 0x21, 0x32, 0x36, 0x13, 0x15, 0x21, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x03, 0xae, 0x8d, 0x93, 0xfe, 0xdd, 0x01, 0x23, 0x93, 0x8d, 0x62, 0xfd, 0x5b, 0x01, 0x2c, 0xe2, 0xf5, 0xed, 0xea, 0xfe, 0x1e, 0x01, 0xb7, 0x8b, 0x87, 0xfd, 0xdd, 0x87, 0x04, 0xa8, 0xa6, 0xfe, 0x40, 0xda, 0xde, 0xdd, 0xda, 0x05, 0xd5, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0xb5, 0x03, 0x44, 0xfd, 0x72, 0x05, 0xd5, 0xaa, 0xfa, 0xd5, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xfe, 0xbf, 0x05, 0x46, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x17, 0x00, 0x00, 0x25, 0x21, 0x11, 0x21, 0x15, 0x10, 0x03, 0x06, 0x05, 0x36, 0x37, 0x12, 0x19, 0x01, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x01, 0xa4, 0x02, 0x52, 0xfe, 0x4c, 0x65, 0x15, 0xfe, 0xd3, 0x78, 0x23, 0x57, 0x03, 0x1f, 0x99, 0x99, 0xfc, 0x48, 0x99, 0xaa, 0x04, 0x81, 0xd4, 0xfe, 0x0d, 0xfe, 0xb5, 0x44, 0x2b, 0x3f, 0x78, 0x01, 0x34, 0x02, 0x26, 0x01, 0x1a, 0xfa, 0xd5, 0xfe, 0x15, 0x01, 0x41, 0xfe, 0xbf, 0x01, 0xeb, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x24, 0x00, 0x00, 0x07, 0x9e, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x01, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x03, 0x11, 0x23, 0x11, 0x03, 0x01, 0x23, 0x09, 0x01, 0x33, 0x01, 0x03, 0x86, 0xb6, 0x02, 0x65, 0xdd, 0xfe, 0x15, 0x02, 0x0a, 0xbd, 0xfe, 0x44, 0xe8, 0xb6, 0xe8, 0xfe, 0x44, 0xbe, 0x02, 0x0a, 0xfe, 0x16, 0xdc, 0x02, 0x66, 0x05, 0xd5, 0xfd, 0x1e, 0x02, 0xe2, 0xfd, 0xb3, 0xfc, 0x78, 0x03, 0x01, 0xfe, 0xe9, 0xfe, 0x16, 0x01, 0xea, 0x01, 0x17, 0xfc, 0xff, 0x03, 0x88, 0x02, 0x4d, 0xfd, 0x1e, 0x00, 0x01, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x25, 0x05, 0xf0, 0x00, 0x28, 0x00, 0x00, 0x01, 0x32, 0x04, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x04, 0x23, 0x22, 0x24, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x02, 0x0e, 0xde, 0x01, 0x19, 0x80, 0x76, 0x83, 0x92, 0xfe, 0xc1, 0xd7, 0x6d, 0xff, 0x00, 0x27, 0x89, 0x98, 0x70, 0xa9, 0xbb, 0xa6, 0xb0, 0xb7, 0xbe, 0xa2, 0x8e, 0x93, 0xb2, 0x79, 0x52, 0xb9, 0x66, 0xd4, 0x05, 0xf0, 0xd1, 0xb2, 0x7c, 0xab, 0x21, 0x1f, 0xc4, 0x90, 0xe6, 0xe9, 0x42, 0x1c, 0xd0, 0x59, 0x2b, 0x90, 0x95, 0x84, 0x95, 0xa6, 0x77, 0x70, 0x73, 0x7b, 0x18, 0x4d, 0xc5, 0x28, 0x22, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x01, 0x23, 0x11, 0x33, 0x11, 0x01, 0x04, 0xae, 0xb0, 0xfd, 0xac, 0xf5, 0xb0, 0x02, 0x54, 0x05, 0xd5, 0xfa, 0x2b, 0x04, 0xe1, 0xfb, 0x1f, 0x05, 0xd5, 0xfb, 0x1f, 0x04, 0xe1, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x6d, 0x12, 0x26, 0x03, 0xac, 0x00, 0x00, 0x11, 0x07, 0x10, 0xf2, 0x04, 0x76, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xf9, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x03, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x89, 0xea, 0xfd, 0xf8, 0x02, 0x23, 0xc6, 0xfe, 0x2d, 0xf5, 0xb6, 0x05, 0xd5, 0xfd, 0x1e, 0x02, 0xe2, 0xfd, 0xb2, 0xfc, 0x79, 0x03, 0x01, 0xfe, 0xe9, 0xfe, 0x16, 0x00, 0x01, 0x00, 0x4b, 0x00, 0x00, 0x04, 0xb5, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x33, 0x35, 0x36, 0x37, 0x12, 0x11, 0x35, 0x21, 0x11, 0x23, 0x11, 0x21, 0x15, 0x10, 0x03, 0x06, 0x4c, 0xc3, 0x38, 0x4e, 0x03, 0x1f, 0xb6, 0xfe, 0x4c, 0x5c, 0x58, 0xaa, 0x2f, 0xa4, 0x01, 0x02, 0x02, 0x58, 0xfe, 0xfa, 0x2b, 0x05, 0x2b, 0xb8, 0xfd, 0xca, 0xfe, 0xf8, 0xfd, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x30, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x12, 0x06, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x04, 0xb5, 0xb6, 0xfd, 0x6c, 0xb6, 0x05, 0xd5, 0xfa, 0x2b, 0x05, 0x2b, 0xfa, 0xd5, 0x05, 0xd5, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x33, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x12, 0x06, 0x00, 0x26, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0x00, 0x00, 0x04, 0x6c, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x44, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x25, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3f, 0x01, 0x01, 0x33, 0x09, 0x01, 0x33, 0x02, 0x4e, 0x13, 0x1d, 0x47, 0xe2, 0x45, 0x38, 0x6b, 0x2a, 0x19, 0x10, 0x29, 0xfe, 0x51, 0xc3, 0x01, 0x4e, 0x01, 0x4f, 0xc4, 0xb5, 0x32, 0x26, 0x5d, 0xaa, 0x1b, 0x11, 0x2a, 0x6a, 0x04, 0x6b, 0xfc, 0x94, 0x03, 0x6c, 0x00, 0x03, 0x00, 0x6c, 0x00, 0x00, 0x05, 0xc6, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x33, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x03, 0x24, 0x00, 0x11, 0x10, 0x00, 0x25, 0x35, 0x33, 0x15, 0x04, 0x00, 0x11, 0x10, 0x00, 0x05, 0x15, 0x23, 0x02, 0xbf, 0xc3, 0xcf, 0xcf, 0xc3, 0xb7, 0xc3, 0xcd, 0xcd, 0xc3, 0xb7, 0xfe, 0xe3, 0xfe, 0xcb, 0x01, 0x35, 0x01, 0x1d, 0xb7, 0x01, 0x1d, 0x01, 0x33, 0xfe, 0xcd, 0xfe, 0xe3, 0xb7, 0x04, 0xa2, 0x14, 0xcc, 0xc5, 0xc5, 0xcb, 0x14, 0x14, 0xcb, 0xc5, 0xc5, 0xcc, 0x14, 0xfc, 0x10, 0x17, 0x01, 0x2b, 0x01, 0x09, 0x01, 0x09, 0x01, 0x2d, 0x17, 0x8b, 0x8b, 0x17, 0xfe, 0xd5, 0xfe, 0xf5, 0xfe, 0xf7, 0xfe, 0xd5, 0x17, 0xb2, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x05, 0x4f, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x04, 0xb5, 0xfc, 0x00, 0xb6, 0x02, 0x94, 0xb6, 0x99, 0x99, 0x05, 0xd5, 0xfa, 0xd5, 0x05, 0x2b, 0xfa, 0xd5, 0xfe, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x04, 0x3b, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x21, 0x11, 0x21, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x21, 0x11, 0x33, 0x11, 0x03, 0x84, 0xfe, 0x89, 0xa8, 0xc7, 0xb4, 0x70, 0x70, 0x01, 0x52, 0xb7, 0x02, 0x64, 0xe9, 0xee, 0x01, 0x9a, 0xfe, 0x76, 0x9f, 0x9e, 0x02, 0xc7, 0xfa, 0x2b, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x06, 0xff, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x04, 0x34, 0x02, 0x14, 0xb6, 0xf9, 0xb7, 0xb6, 0x02, 0x14, 0xb5, 0xaa, 0x05, 0x2b, 0xfa, 0x2b, 0x05, 0xd5, 0xfa, 0xd5, 0x05, 0x2b, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x07, 0x98, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x06, 0xfe, 0xf9, 0xb7, 0xb6, 0x02, 0x14, 0xb5, 0x02, 0x14, 0xb6, 0x99, 0x99, 0x05, 0xd5, 0xfa, 0xd5, 0x05, 0x2b, 0xfa, 0xd5, 0x05, 0x2b, 0xfa, 0xd5, 0xfe, 0x15, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x05, 0x7c, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x17, 0x00, 0x00, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x01, 0x34, 0x27, 0x26, 0x23, 0x21, 0x11, 0x21, 0x32, 0x37, 0x36, 0x01, 0xc3, 0xfe, 0x73, 0x02, 0x43, 0x01, 0x2c, 0xe2, 0xf5, 0xf5, 0xe2, 0x01, 0x17, 0x47, 0x46, 0x93, 0xfe, 0xdd, 0x01, 0x23, 0x91, 0x48, 0x47, 0x05, 0x2b, 0xaa, 0xfd, 0x9a, 0xda, 0xde, 0xdd, 0xda, 0x01, 0xb7, 0x8b, 0x44, 0x43, 0xfd, 0xdd, 0x44, 0x43, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0xa6, 0x05, 0xd5, 0x10, 0x26, 0x03, 0xc0, 0x00, 0x00, 0x10, 0x07, 0x00, 0x2c, 0x04, 0x3b, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x23, 0x21, 0x11, 0x21, 0x32, 0x37, 0x36, 0x01, 0x33, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x03, 0xae, 0x47, 0x46, 0x93, 0xfe, 0xdd, 0x01, 0x23, 0x93, 0x46, 0x47, 0xfd, 0x07, 0xb6, 0x01, 0x2c, 0xe2, 0xf5, 0xf5, 0xe2, 0xfe, 0x1e, 0x01, 0xb7, 0x8b, 0x44, 0x43, 0xfd, 0xdd, 0x44, 0x43, 0x04, 0xa8, 0xfd, 0x9a, 0xda, 0xde, 0xdd, 0xda, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe3, 0x04, 0xa0, 0x05, 0xf0, 0x00, 0x18, 0x00, 0x00, 0x13, 0x16, 0x33, 0x32, 0x12, 0x37, 0x21, 0x35, 0x21, 0x26, 0x02, 0x23, 0x22, 0x07, 0x35, 0x36, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x22, 0x27, 0x64, 0xbe, 0xe6, 0xee, 0xd6, 0x14, 0xfd, 0x32, 0x02, 0xce, 0x14, 0xd6, 0xee, 0xe6, 0xbe, 0xbb, 0xf4, 0x01, 0x2d, 0x01, 0x60, 0xfe, 0xa0, 0xfe, 0xd3, 0xf0, 0xbf, 0x01, 0x46, 0xbd, 0x01, 0x1c, 0xef, 0xaa, 0xef, 0x01, 0x1d, 0xbd, 0xd5, 0x8e, 0xfe, 0x61, 0xfe, 0x99, 0xfe, 0x98, 0xfe, 0x61, 0x90, 0x00, 0x02, 0x00, 0xbd, 0xff, 0xe3, 0x07, 0x5f, 0x05, 0xf0, 0x00, 0x0f, 0x00, 0x26, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x11, 0x10, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x11, 0x10, 0x27, 0x26, 0x01, 0x12, 0x37, 0x36, 0x21, 0x20, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x04, 0xf1, 0xc6, 0x74, 0x75, 0x75, 0x74, 0xc6, 0xc6, 0x74, 0x74, 0x74, 0x74, 0xfc, 0xce, 0x0d, 0xa2, 0xa2, 0x01, 0x1b, 0x01, 0x1b, 0xa9, 0xa9, 0xa9, 0xa9, 0xfe, 0xe5, 0xfe, 0xe5, 0xa2, 0xa2, 0x0d, 0xfe, 0xef, 0xb6, 0xb6, 0x05, 0x4c, 0xa4, 0xa4, 0xfe, 0xe5, 0xfe, 0xe6, 0xa4, 0xa4, 0xa4, 0xa4, 0x01, 0x1a, 0x01, 0x1b, 0xa4, 0xa4, 0xfd, 0xf3, 0x01, 0x18, 0xcd, 0xcc, 0xd2, 0xd3, 0xfe, 0x9e, 0xfe, 0x9f, 0xd2, 0xd3, 0xcd, 0xcd, 0x01, 0x18, 0xfd, 0x6b, 0x05, 0xd5, 0xfd, 0x6a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x00, 0x04, 0x4c, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x16, 0x00, 0x00, 0x01, 0x14, 0x16, 0x33, 0x21, 0x11, 0x21, 0x22, 0x06, 0x03, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x21, 0x11, 0x23, 0x11, 0x23, 0x01, 0x01, 0x72, 0x86, 0x83, 0x01, 0x1b, 0xfe, 0xe5, 0x83, 0x86, 0xf8, 0x01, 0x70, 0x5a, 0xe7, 0xea, 0xe8, 0x01, 0xd1, 0xb6, 0xf3, 0xfe, 0x9d, 0x04, 0x27, 0x83, 0x87, 0x02, 0x12, 0x85, 0xfb, 0x56, 0x02, 0x8d, 0x1a, 0xa9, 0xd7, 0xce, 0xe0, 0xfa, 0x2b, 0x02, 0x77, 0xfd, 0x89, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x04, 0x7b, 0x12, 0x06, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x37, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x00, 0x01, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x03, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x24, 0x37, 0x36, 0x37, 0x17, 0x06, 0x0f, 0x01, 0x06, 0x07, 0x06, 0x0f, 0x01, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x02, 0x3d, 0xd8, 0xf7, 0xf7, 0xd8, 0xd9, 0xef, 0x06, 0x06, 0x04, 0x34, 0x52, 0x01, 0x1b, 0xee, 0x6e, 0x30, 0x2e, 0x2c, 0x28, 0xe1, 0x72, 0x44, 0xb3, 0x11, 0x07, 0x75, 0xbe, 0x85, 0x9b, 0x9a, 0x86, 0x85, 0x9a, 0x9a, 0x04, 0x7b, 0xfe, 0xc8, 0xfe, 0xec, 0xfe, 0xed, 0xfe, 0xc7, 0x01, 0x30, 0x01, 0x1c, 0xe5, 0x77, 0x29, 0xa0, 0x76, 0xb9, 0xa0, 0x02, 0x01, 0x11, 0x92, 0x14, 0x01, 0x11, 0x09, 0x2c, 0x75, 0x99, 0x38, 0x77, 0x9c, 0xe7, 0xc9, 0xc9, 0xe7, 0xe8, 0xc8, 0xc7, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xd2, 0x04, 0x60, 0x00, 0x08, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x03, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0x01, 0x4d, 0xec, 0x71, 0x77, 0x77, 0x71, 0xec, 0xda, 0x5d, 0x77, 0x77, 0x5d, 0xfe, 0x80, 0x01, 0x8b, 0xb1, 0xbf, 0x62, 0x5f, 0x72, 0x7e, 0xcf, 0xc1, 0xfe, 0x66, 0x02, 0x04, 0xfe, 0x8f, 0x5f, 0x5a, 0x5a, 0x5e, 0x01, 0xc9, 0xfe, 0xca, 0x53, 0x4a, 0x4a, 0x4f, 0x93, 0x90, 0x85, 0x67, 0x79, 0x0f, 0x18, 0x98, 0x72, 0x96, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x6f, 0x04, 0x60, 0x00, 0x05, 0x00, 0x00, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0xa7, 0x02, 0xc7, 0xfd, 0xe0, 0x04, 0x60, 0x93, 0xfc, 0x33, 0x00, 0x00, 0x00, 0x02, 0x00, 0x60, 0xfe, 0xe5, 0x04, 0x9b, 0x04, 0x60, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x25, 0x21, 0x11, 0x21, 0x15, 0x10, 0x07, 0x05, 0x36, 0x37, 0x36, 0x11, 0x35, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x01, 0x8f, 0x01, 0xe0, 0xfe, 0xa4, 0x6a, 0xfe, 0xf5, 0x52, 0x24, 0x58, 0x02, 0xaa, 0x84, 0x84, 0xfc, 0xcf, 0x85, 0x93, 0x03, 0x3a, 0x8c, 0xfe, 0x64, 0xdc, 0x36, 0x28, 0x55, 0xd3, 0x01, 0xa9, 0xd4, 0xfc, 0x33, 0xfe, 0x52, 0x01, 0x1b, 0xfe, 0xe5, 0x01, 0xae, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x04, 0x7b, 0x12, 0x06, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3f, 0x00, 0x00, 0x06, 0x3e, 0x04, 0x60, 0x00, 0x13, 0x00, 0x00, 0x01, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x07, 0x11, 0x23, 0x11, 0x27, 0x01, 0x23, 0x09, 0x01, 0x33, 0x01, 0x02, 0xec, 0xa5, 0x01, 0xb8, 0xc0, 0xfe, 0x97, 0x01, 0x9e, 0xb2, 0xfe, 0xad, 0xa8, 0xa5, 0xa8, 0xfe, 0xac, 0xb1, 0x01, 0x9e, 0xfe, 0x96, 0xc1, 0x01, 0xb8, 0x04, 0x60, 0xfd, 0xf2, 0x02, 0x0e, 0xfe, 0x51, 0xfd, 0x4f, 0x02, 0x36, 0xc9, 0xfe, 0x93, 0x01, 0x6d, 0xc9, 0xfd, 0xca, 0x02, 0xb1, 0x01, 0xaf, 0xfd, 0xf2, 0x00, 0x00, 0x00, 0x01, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x04, 0x7c, 0x00, 0x28, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x02, 0x7b, 0x70, 0x7c, 0xe8, 0xd6, 0x48, 0x98, 0x51, 0x40, 0x99, 0x53, 0x88, 0x98, 0x87, 0x7b, 0x85, 0x8b, 0x69, 0x79, 0x7d, 0x6b, 0x40, 0x91, 0x57, 0x58, 0x99, 0x45, 0xb0, 0xcc, 0x6c, 0x02, 0x5c, 0x18, 0x92, 0x6c, 0xad, 0xb6, 0x1c, 0x1c, 0xab, 0x25, 0x25, 0x70, 0x5a, 0x58, 0x6b, 0x98, 0x59, 0x46, 0x40, 0x5c, 0x1a, 0x1d, 0xa7, 0x18, 0x18, 0x9d, 0x8d, 0x5d, 0x81, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x07, 0x04, 0x60, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x01, 0x23, 0x11, 0x33, 0x11, 0x01, 0x04, 0x06, 0xa4, 0xfe, 0x1a, 0xd5, 0xa5, 0x01, 0xe5, 0x04, 0x60, 0xfb, 0xa0, 0x03, 0x83, 0xfc, 0x7d, 0x04, 0x60, 0xfc, 0x7f, 0x03, 0x81, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x07, 0x06, 0x14, 0x12, 0x26, 0x03, 0xcc, 0x00, 0x00, 0x11, 0x07, 0x02, 0x9a, 0x00, 0x8a, 0xff, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x1d, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x07, 0x11, 0x23, 0xa7, 0xa5, 0x01, 0xd3, 0xcc, 0xfe, 0x7e, 0x01, 0xb3, 0xb9, 0xfe, 0x9a, 0xb1, 0xa5, 0x04, 0x60, 0xfd, 0xf2, 0x02, 0x0e, 0xfe, 0x4f, 0xfd, 0x51, 0x02, 0x35, 0xc8, 0xfe, 0x93, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x00, 0x04, 0x02, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x00, 0x33, 0x35, 0x36, 0x37, 0x36, 0x11, 0x35, 0x21, 0x11, 0x23, 0x11, 0x21, 0x15, 0x10, 0x07, 0x06, 0x44, 0xa4, 0x33, 0x3d, 0x02, 0xa9, 0xa5, 0xfe, 0xa1, 0x4f, 0x54, 0x99, 0x1c, 0x7e, 0xb1, 0x01, 0xc5, 0xb7, 0xfb, 0xa0, 0x03, 0xcd, 0x6f, 0xfe, 0x50, 0xc2, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xc8, 0x04, 0x60, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x11, 0x01, 0x23, 0x01, 0x11, 0x23, 0xa7, 0xf3, 0x01, 0x1e, 0x01, 0x1f, 0xf0, 0xa6, 0xfe, 0xe9, 0xa5, 0xfe, 0xe9, 0xa7, 0x04, 0x60, 0xfd, 0x12, 0x02, 0xee, 0xfb, 0xa0, 0x03, 0xb0, 0xfd, 0x27, 0x02, 0xd9, 0xfc, 0x50, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x0e, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xa7, 0xa7, 0x02, 0x19, 0xa7, 0xa7, 0xfd, 0xe7, 0xa7, 0x04, 0x60, 0xfe, 0x37, 0x01, 0xc9, 0xfb, 0xa0, 0x02, 0x04, 0xfd, 0xfc, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x12, 0x06, 0x00, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x0e, 0x04, 0x60, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x04, 0x0e, 0xa7, 0xfd, 0xe7, 0xa7, 0x04, 0x60, 0xfb, 0xa0, 0x03, 0xcd, 0xfc, 0x33, 0x04, 0x60, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x12, 0x06, 0x00, 0x53, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x12, 0x06, 0x00, 0x46, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x03, 0xfc, 0x04, 0x60, 0x00, 0x07, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x36, 0x03, 0xc6, 0xfe, 0x6e, 0xa3, 0xfe, 0x6f, 0x04, 0x60, 0x93, 0xfc, 0x33, 0x03, 0xcd, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x04, 0x60, 0x12, 0x06, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0xfe, 0x56, 0x05, 0xc4, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x33, 0x00, 0x00, 0x01, 0x14, 0x16, 0x33, 0x32, 0x37, 0x11, 0x26, 0x23, 0x22, 0x06, 0x01, 0x11, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x11, 0x33, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x11, 0x01, 0x34, 0x26, 0x23, 0x22, 0x07, 0x11, 0x16, 0x33, 0x32, 0x36, 0x01, 0x11, 0x82, 0x6f, 0x58, 0x67, 0x67, 0x58, 0x6f, 0x82, 0x01, 0xb0, 0x34, 0x75, 0x4b, 0x97, 0xd1, 0xd1, 0x97, 0x4b, 0x75, 0x34, 0xa6, 0x33, 0x76, 0x4b, 0x96, 0xd2, 0xd2, 0x96, 0x4b, 0x76, 0x33, 0x01, 0xb0, 0x82, 0x6f, 0x58, 0x67, 0x67, 0x58, 0x6f, 0x82, 0x02, 0x2f, 0xeb, 0xc7, 0xa8, 0x02, 0x14, 0xa8, 0xc7, 0xfb, 0x3c, 0x02, 0x39, 0x5e, 0x4e, 0x01, 0x35, 0x01, 0x13, 0x01, 0x13, 0x01, 0x3d, 0x4c, 0x5e, 0x02, 0x04, 0xfd, 0xfc, 0x5e, 0x4c, 0xfe, 0xc3, 0xfe, 0xed, 0xfe, 0xed, 0xfe, 0xcb, 0x4e, 0x5e, 0xfd, 0xc7, 0x03, 0xd9, 0xeb, 0xc7, 0xa8, 0xfd, 0xec, 0xa8, 0xc7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x35, 0x00, 0x00, 0x04, 0x07, 0x04, 0x60, 0x12, 0x06, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x04, 0x92, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x04, 0x0e, 0xfc, 0x99, 0xa7, 0x02, 0x19, 0xa7, 0x84, 0x84, 0x04, 0x60, 0xfc, 0x33, 0x03, 0xcd, 0xfc, 0x33, 0xfe, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x87, 0x00, 0x00, 0x03, 0x9a, 0x04, 0x60, 0x00, 0x11, 0x00, 0x00, 0x21, 0x11, 0x21, 0x22, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x21, 0x11, 0x33, 0x11, 0x02, 0xf4, 0xfe, 0xcb, 0x89, 0x5c, 0x53, 0xa6, 0x2e, 0x30, 0x5e, 0x01, 0x0b, 0xa6, 0x01, 0xd7, 0x5f, 0x56, 0xb8, 0x01, 0x1c, 0xfe, 0xf5, 0x75, 0x3b, 0x3b, 0x01, 0xf6, 0xfb, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x05, 0xf0, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x03, 0x9e, 0x01, 0xab, 0xa6, 0xfa, 0xb8, 0xa7, 0x01, 0xaa, 0xa6, 0x93, 0x03, 0xcd, 0xfb, 0xa0, 0x04, 0x60, 0xfc, 0x33, 0x03, 0xcd, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x06, 0x74, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x05, 0xef, 0xfa, 0xb8, 0xa7, 0x01, 0xaa, 0xa6, 0x01, 0xab, 0xa6, 0x85, 0x85, 0x04, 0x60, 0xfc, 0x33, 0x03, 0xcd, 0xfc, 0x33, 0x03, 0xcd, 0xfc, 0x33, 0xfe, 0x52, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x00, 0x04, 0xaa, 0x04, 0x60, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x00, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x17, 0x23, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x03, 0x19, 0xc1, 0xcf, 0xcf, 0xc1, 0xfe, 0x65, 0xfe, 0xba, 0x01, 0xed, 0xed, 0xed, 0xed, 0x71, 0x76, 0x76, 0x02, 0x97, 0xa3, 0xa8, 0xa8, 0xa4, 0x03, 0xcd, 0x93, 0xfe, 0x37, 0x93, 0xfe, 0x8f, 0x5f, 0x5a, 0x5a, 0x5e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x05, 0x0c, 0x04, 0x7b, 0x10, 0x27, 0x00, 0xf3, 0x03, 0xb8, 0x00, 0x00, 0x10, 0x06, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xd2, 0x04, 0x60, 0x00, 0x08, 0x00, 0x13, 0x00, 0x00, 0x01, 0x34, 0x26, 0x2b, 0x01, 0x11, 0x33, 0x32, 0x36, 0x01, 0x33, 0x11, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x03, 0x21, 0x76, 0x71, 0xec, 0xec, 0x71, 0x76, 0xfd, 0x86, 0xa7, 0xf3, 0xc1, 0xcf, 0xcf, 0xc1, 0xfe, 0x66, 0x01, 0x4c, 0x5a, 0x5e, 0xfe, 0x8f, 0x5f, 0x03, 0x6e, 0xfe, 0x37, 0xa3, 0xa8, 0xa8, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x18, 0x00, 0x00, 0x37, 0x16, 0x33, 0x32, 0x36, 0x37, 0x21, 0x35, 0x21, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x35, 0x36, 0x33, 0x32, 0x00, 0x11, 0x10, 0x00, 0x23, 0x22, 0x27, 0x66, 0x8e, 0x8d, 0x85, 0xbc, 0x12, 0xfe, 0x00, 0x01, 0xfa, 0x0b, 0x8f, 0xb3, 0x8a, 0x91, 0x8d, 0x95, 0xec, 0x01, 0x0f, 0xfe, 0xf8, 0xe7, 0xaa, 0x84, 0xd5, 0x56, 0xab, 0xda, 0x93, 0x69, 0xdf, 0x56, 0xac, 0x46, 0xfe, 0xc3, 0xfe, 0xf1, 0xfe, 0xf2, 0xfe, 0xc2, 0x48, 0x00, 0x00, 0x02, 0x00, 0xad, 0xff, 0xe3, 0x05, 0xab, 0x04, 0x7b, 0x00, 0x0b, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x36, 0x12, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x27, 0x23, 0x11, 0x23, 0x11, 0x33, 0x11, 0x03, 0xdc, 0x85, 0x9b, 0x9a, 0x86, 0x84, 0x9b, 0x9b, 0xfd, 0xb3, 0x11, 0xe0, 0xd8, 0xd8, 0xf7, 0xf7, 0xd8, 0xd9, 0xec, 0x09, 0xbb, 0xa5, 0xa5, 0x03, 0xdf, 0xe7, 0xc9, 0xc9, 0xe7, 0xe8, 0xc8, 0xc7, 0xe9, 0xfe, 0xc2, 0xbe, 0x01, 0x1c, 0xfe, 0xc8, 0xfe, 0xec, 0xfe, 0xed, 0xfe, 0xc7, 0x01, 0x2e, 0xf8, 0xfd, 0xf7, 0x04, 0x60, 0xfe, 0x41, 0x00, 0x00, 0x02, 0x00, 0x68, 0x00, 0x00, 0x03, 0xb9, 0x04, 0x60, 0x00, 0x08, 0x00, 0x16, 0x00, 0x00, 0x01, 0x14, 0x16, 0x3b, 0x01, 0x11, 0x23, 0x22, 0x06, 0x03, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x21, 0x11, 0x23, 0x11, 0x23, 0x01, 0x01, 0x54, 0x73, 0x6b, 0xe0, 0xe0, 0x6b, 0x73, 0xec, 0x01, 0x34, 0x68, 0x8b, 0xc2, 0xc3, 0x01, 0x8a, 0xa6, 0xce, 0xfe, 0xd7, 0x03, 0x1d, 0x53, 0x5e, 0x01, 0x61, 0x5c, 0xfc, 0x8f, 0x01, 0xeb, 0x1a, 0x89, 0x8f, 0xa2, 0xa1, 0xfb, 0xa0, 0x01, 0xd9, 0xfe, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x6b, 0x12, 0x26, 0x03, 0xc9, 0x00, 0x00, 0x10, 0x06, 0x00, 0x43, 0x51, 0x05, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x10, 0x12, 0x26, 0x03, 0xc9, 0x00, 0x00, 0x11, 0x07, 0x00, 0x6a, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2a, 0xfe, 0x56, 0x04, 0x1c, 0x06, 0x14, 0x00, 0x1f, 0x00, 0x00, 0x13, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x11, 0x14, 0x00, 0x07, 0x35, 0x36, 0x12, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0xc9, 0x9f, 0x9f, 0xa6, 0x01, 0xe7, 0xfe, 0x19, 0x3c, 0xa0, 0x6a, 0xa4, 0xc2, 0xfe, 0xcb, 0xc1, 0x6e, 0xdc, 0x6f, 0x70, 0x8a, 0x97, 0xa6, 0x03, 0xd1, 0x8f, 0x01, 0xb4, 0xfe, 0x4c, 0x8f, 0xfe, 0x6d, 0x65, 0x64, 0xe9, 0xfe, 0xea, 0xe2, 0xfe, 0x59, 0x29, 0x8c, 0x16, 0x01, 0x2e, 0xd2, 0xd0, 0x9f, 0xc4, 0x9e, 0xfe, 0xfb, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x76, 0x06, 0x6d, 0x12, 0x26, 0x03, 0xc7, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x78, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x18, 0x00, 0x00, 0x01, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x06, 0x07, 0x21, 0x15, 0x21, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x15, 0x06, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x02, 0x60, 0x96, 0x8d, 0x91, 0x8a, 0xb4, 0x8f, 0x0a, 0x01, 0xf9, 0xfe, 0x01, 0x11, 0xbd, 0x85, 0x8d, 0x8e, 0x84, 0xaa, 0xe8, 0xfe, 0xf9, 0x01, 0x0f, 0x04, 0x7b, 0x46, 0xac, 0x56, 0xdf, 0x69, 0x93, 0xda, 0xab, 0x56, 0xaa, 0x48, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x3d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x04, 0x7b, 0x12, 0x06, 0x00, 0x56, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x01, 0x54, 0x06, 0x14, 0x12, 0x06, 0x00, 0x4c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf5, 0x00, 0x00, 0x02, 0x0c, 0x06, 0x10, 0x10, 0x06, 0x00, 0xb1, 0x00, 0x00, 0xff, 0xff, 0xff, 0xde, 0xfe, 0x56, 0x01, 0x54, 0x06, 0x14, 0x12, 0x06, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x44, 0x00, 0x00, 0x06, 0x13, 0x04, 0x60, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x00, 0x33, 0x35, 0x36, 0x37, 0x36, 0x11, 0x35, 0x21, 0x11, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x21, 0x15, 0x10, 0x07, 0x06, 0x25, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x11, 0x44, 0xa4, 0x33, 0x3d, 0x02, 0x8f, 0x9a, 0xc1, 0xd0, 0xd0, 0xc0, 0xfe, 0xbe, 0xfe, 0xbe, 0x4f, 0x55, 0x03, 0x20, 0x71, 0x77, 0x77, 0x71, 0x93, 0x99, 0x1c, 0x7e, 0xb1, 0x01, 0xc5, 0xb7, 0xfe, 0x37, 0xa3, 0xa8, 0xa8, 0xa4, 0x03, 0xcd, 0x6f, 0xfe, 0x50, 0xc2, 0xcf, 0x76, 0x5f, 0x5a, 0x5a, 0x5e, 0xfe, 0x8f, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x06, 0x0c, 0x04, 0x60, 0x00, 0x12, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x01, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x11, 0x03, 0xe0, 0x9a, 0xc0, 0xd1, 0xd0, 0xc0, 0xfe, 0xbe, 0xfe, 0x15, 0xa7, 0xa7, 0x01, 0xeb, 0x01, 0x39, 0x72, 0x77, 0x77, 0x72, 0x92, 0x04, 0x60, 0xfe, 0x37, 0xa3, 0xa8, 0xa8, 0xa4, 0x02, 0x04, 0xfd, 0xfc, 0x04, 0x60, 0xfe, 0x37, 0x01, 0xc9, 0xfc, 0x33, 0x5f, 0x5a, 0x5a, 0x5e, 0xfe, 0x8f, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x04, 0x15, 0x06, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0xc9, 0x9f, 0x9f, 0xa6, 0x01, 0xe7, 0xfe, 0x19, 0x3c, 0xa1, 0x69, 0xaa, 0xb6, 0xa6, 0x6f, 0x70, 0x89, 0x98, 0xa6, 0x03, 0xd1, 0x8f, 0x01, 0xb4, 0xfe, 0x4c, 0x8f, 0xfe, 0x6d, 0x65, 0x64, 0xea, 0xed, 0xfe, 0xd0, 0x01, 0x2a, 0x9f, 0x9e, 0xc1, 0xa1, 0xfe, 0xfb, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x1d, 0x06, 0x6d, 0x12, 0x26, 0x03, 0xce, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x64, 0x07, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x07, 0x06, 0x6b, 0x12, 0x26, 0x03, 0xcc, 0x00, 0x00, 0x10, 0x06, 0x00, 0x43, 0x54, 0x05, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x14, 0x12, 0x26, 0x03, 0xd7, 0x00, 0x00, 0x10, 0x06, 0x02, 0x9a, 0x55, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x04, 0x0e, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x23, 0x02, 0x18, 0xfe, 0x8f, 0xa7, 0x02, 0x19, 0xa7, 0xfe, 0x8f, 0x85, 0x04, 0x60, 0xfc, 0x33, 0x03, 0xcd, 0xfb, 0xa0, 0xfe, 0xe5, 0x00, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x06, 0x52, 0x05, 0xd5, 0x00, 0x34, 0x00, 0x00, 0x05, 0x22, 0x27, 0x26, 0x11, 0x34, 0x13, 0x36, 0x37, 0x33, 0x06, 0x03, 0x06, 0x15, 0x10, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x11, 0x34, 0x27, 0x02, 0x27, 0x33, 0x16, 0x17, 0x12, 0x15, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x02, 0x01, 0xbe, 0x6d, 0x6e, 0x5a, 0x35, 0x53, 0xe0, 0x4b, 0x7a, 0x3c, 0x41, 0x42, 0x70, 0x67, 0x40, 0x40, 0xb3, 0x3f, 0x3f, 0x69, 0x78, 0x3b, 0x40, 0x3c, 0x7a, 0x4c, 0xe1, 0x56, 0x32, 0x5a, 0x6e, 0x6f, 0xbc, 0x84, 0x5a, 0x5a, 0x24, 0x23, 0x5a, 0x5b, 0x1d, 0xb1, 0xb4, 0x01, 0x98, 0xc9, 0x01, 0x0e, 0x9f, 0x7f, 0x46, 0xfe, 0xbf, 0x9f, 0xb7, 0xfe, 0xcd, 0x6b, 0x6d, 0x69, 0x68, 0xc6, 0xf1, 0xf1, 0xc6, 0x68, 0x69, 0x6d, 0x77, 0x01, 0x27, 0xb7, 0x9f, 0x01, 0x41, 0x46, 0x82, 0x9c, 0xfe, 0xe7, 0xbe, 0xfe, 0x66, 0xb2, 0xb1, 0x5e, 0x5e, 0xad, 0xad, 0x5e, 0x5e, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x04, 0x60, 0x10, 0x06, 0x03, 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x05, 0x20, 0x05, 0xd5, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x15, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x21, 0x35, 0x21, 0x35, 0x33, 0x15, 0x21, 0x15, 0x13, 0x34, 0x27, 0x26, 0x23, 0x21, 0x11, 0x21, 0x32, 0x37, 0x36, 0x02, 0x1c, 0x01, 0x2d, 0xe1, 0xf5, 0xf5, 0xe1, 0xfe, 0x1d, 0xfe, 0xb5, 0x01, 0x4b, 0xb6, 0x01, 0x4c, 0xf8, 0x48, 0x46, 0x92, 0xfe, 0xdc, 0x01, 0x24, 0x92, 0x46, 0x48, 0x04, 0x51, 0xe2, 0xda, 0xde, 0xdd, 0xda, 0x04, 0x51, 0xa4, 0xe0, 0xe0, 0xa4, 0xfd, 0x66, 0x8b, 0x44, 0x43, 0xfd, 0xdd, 0x44, 0x43, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x04, 0x6a, 0x06, 0x14, 0x00, 0x07, 0x00, 0x19, 0x00, 0x00, 0x24, 0x34, 0x26, 0x2b, 0x01, 0x11, 0x33, 0x32, 0x05, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x32, 0x16, 0x10, 0x06, 0x23, 0x03, 0xb9, 0x76, 0x71, 0xec, 0xec, 0x71, 0xfd, 0xfd, 0xfe, 0xdb, 0x01, 0x25, 0xa6, 0x01, 0x7e, 0xfe, 0x82, 0xf3, 0xc1, 0xd0, 0xd0, 0xc1, 0xf2, 0xb4, 0x5e, 0xfe, 0x8f, 0x93, 0x03, 0xcd, 0x93, 0x01, 0xb4, 0xfe, 0x4c, 0x93, 0xfe, 0xca, 0xa3, 0xfe, 0xb0, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xbd, 0xff, 0xe3, 0x06, 0x66, 0x05, 0xf0, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x33, 0x12, 0x37, 0x36, 0x21, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x21, 0x15, 0x21, 0x12, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x20, 0x27, 0x26, 0x03, 0x01, 0x74, 0xb6, 0xb6, 0xbd, 0x1b, 0x8d, 0xaf, 0x01, 0x32, 0x78, 0x6a, 0x6c, 0x5d, 0x5c, 0x67, 0x69, 0x75, 0xe6, 0x7a, 0x5d, 0x17, 0x02, 0x6d, 0xfd, 0x8c, 0x07, 0x74, 0x7b, 0xe5, 0x75, 0x69, 0x67, 0x5c, 0x5f, 0x6b, 0x6b, 0x76, 0xfe, 0xce, 0xaf, 0xa7, 0x08, 0x02, 0xc7, 0xfd, 0x39, 0x05, 0xd5, 0xfd, 0x9c, 0x01, 0x08, 0xa7, 0xd0, 0x24, 0x23, 0x47, 0xd5, 0x5f, 0x2f, 0x2f, 0x9c, 0x77, 0xc6, 0xaa, 0xfe, 0xf3, 0x94, 0x9d, 0x2f, 0x2f, 0x5f, 0xd3, 0x48, 0x24, 0x24, 0xcf, 0xc6, 0x01, 0x4f, 0x00, 0x00, 0x01, 0x00, 0xad, 0xff, 0xe3, 0x04, 0xf5, 0x04, 0x7b, 0x00, 0x23, 0x00, 0x00, 0x01, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x21, 0x15, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x15, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x23, 0x11, 0x23, 0x11, 0x33, 0x11, 0x33, 0x36, 0x37, 0x36, 0x03, 0xd1, 0x96, 0x8d, 0x91, 0x8a, 0xcf, 0x53, 0x1f, 0x0b, 0x01, 0x9e, 0xfe, 0x5b, 0x0c, 0x8e, 0x4d, 0x6c, 0x8d, 0x8e, 0x84, 0xa9, 0xf3, 0x85, 0x6e, 0x09, 0x85, 0xa5, 0xa5, 0x89, 0x15, 0x6e, 0x87, 0x04, 0x7b, 0x46, 0xac, 0x56, 0xb4, 0x41, 0x57, 0x8f, 0xf4, 0x5e, 0x33, 0x56, 0xaa, 0x48, 0xad, 0x90, 0xe4, 0xfd, 0xfc, 0x04, 0x60, 0xfe, 0x33, 0xca, 0x80, 0x9e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x06, 0x46, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x00, 0x21, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x23, 0x03, 0x23, 0x01, 0x33, 0x13, 0x09, 0x01, 0x06, 0x46, 0xcb, 0xfa, 0xfb, 0xb6, 0xfd, 0xfa, 0xcb, 0x02, 0xb5, 0xcf, 0x9f, 0xfe, 0xf9, 0xfe, 0xf9, 0x02, 0x1b, 0xfd, 0xe5, 0x02, 0x1b, 0xfd, 0xe5, 0x05, 0xd5, 0xfc, 0xf3, 0x02, 0x37, 0xfd, 0xc9, 0x00, 0x02, 0x00, 0x2d, 0x00, 0x00, 0x05, 0x76, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x00, 0x21, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x23, 0x03, 0x23, 0x01, 0x33, 0x13, 0x0b, 0x01, 0x05, 0x76, 0xb0, 0xd4, 0xcc, 0xa6, 0xce, 0xd5, 0xaf, 0x02, 0x4c, 0xb0, 0x82, 0xda, 0xdb, 0x01, 0x95, 0xfe, 0x6b, 0x01, 0x95, 0xfe, 0x6b, 0x04, 0x60, 0xfd, 0xb9, 0x01, 0xa1, 0xfe, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x08, 0x2c, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x16, 0x00, 0x00, 0x21, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x23, 0x03, 0x23, 0x01, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x01, 0x33, 0x13, 0x09, 0x01, 0x08, 0x2c, 0xcb, 0xfa, 0xfb, 0xb6, 0xfd, 0xfa, 0xcb, 0x01, 0x4b, 0xfe, 0x2c, 0xb6, 0xb6, 0x02, 0x22, 0x01, 0x1c, 0xcf, 0x9f, 0xfe, 0xf9, 0xfe, 0xf9, 0x02, 0x1b, 0xfd, 0xe5, 0x02, 0x1b, 0xfd, 0xe5, 0x02, 0xc7, 0xfd, 0x39, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfc, 0xf3, 0x02, 0x37, 0xfd, 0xc9, 0x00, 0x02, 0x00, 0xad, 0x00, 0x00, 0x07, 0x08, 0x04, 0x60, 0x00, 0x13, 0x00, 0x16, 0x00, 0x00, 0x21, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x23, 0x03, 0x23, 0x01, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x01, 0x33, 0x13, 0x0b, 0x01, 0x07, 0x08, 0xb0, 0xd4, 0xcc, 0xa6, 0xce, 0xd4, 0xb0, 0x01, 0x00, 0xfe, 0x93, 0xa5, 0xa5, 0x01, 0xb8, 0x01, 0x02, 0xaf, 0x83, 0xdb, 0xdb, 0x01, 0x95, 0xfe, 0x6b, 0x01, 0x95, 0xfe, 0x6b, 0x01, 0xe7, 0xfe, 0x19, 0x04, 0x60, 0xfe, 0x17, 0x01, 0xe9, 0xfd, 0xb9, 0x01, 0xa1, 0xfe, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x67, 0x00, 0x00, 0x05, 0x44, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x11, 0x23, 0x10, 0x37, 0x36, 0x37, 0x01, 0x21, 0x01, 0x16, 0x17, 0x16, 0x11, 0x23, 0x10, 0x27, 0x26, 0x27, 0x01, 0x21, 0x03, 0x30, 0xb6, 0x84, 0x5a, 0x75, 0xbf, 0xaa, 0x6c, 0x99, 0xfe, 0x7c, 0x04, 0x90, 0xfe, 0x7b, 0x94, 0x68, 0xa9, 0xbf, 0x74, 0x56, 0xdf, 0x01, 0x1e, 0xfd, 0xc3, 0x02, 0x59, 0xfd, 0xa7, 0x02, 0x59, 0x1c, 0x7e, 0xa4, 0xfe, 0xe5, 0x01, 0x62, 0xd2, 0x86, 0x31, 0x02, 0xea, 0xfd, 0x13, 0x32, 0x82, 0xd2, 0xfe, 0x9e, 0x01, 0x1e, 0xa1, 0x7a, 0xca, 0x02, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x60, 0x00, 0x00, 0x04, 0x09, 0x04, 0x60, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x21, 0x13, 0x09, 0x01, 0x16, 0x17, 0x16, 0x11, 0x23, 0x34, 0x27, 0x26, 0x27, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x15, 0x23, 0x10, 0x37, 0x36, 0x37, 0x01, 0x02, 0xf1, 0xfe, 0x87, 0xbc, 0x01, 0xd4, 0xfe, 0xdc, 0x60, 0x44, 0x7b, 0xb0, 0x4d, 0x34, 0x4e, 0xa5, 0x4b, 0x32, 0x4e, 0xae, 0x7b, 0x43, 0x61, 0xfe, 0xdb, 0x03, 0xb6, 0xfe, 0x96, 0x02, 0x14, 0xfd, 0xcc, 0x26, 0x56, 0x9c, 0xfe, 0xec, 0xc7, 0x74, 0x4f, 0x1a, 0xfe, 0x5c, 0x01, 0xa2, 0x1a, 0x4b, 0x74, 0xc9, 0x01, 0x14, 0x9c, 0x55, 0x27, 0x02, 0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x06, 0xfe, 0x05, 0xd5, 0x00, 0x1e, 0x00, 0x21, 0x00, 0x00, 0x09, 0x01, 0x21, 0x01, 0x16, 0x17, 0x16, 0x11, 0x23, 0x10, 0x27, 0x26, 0x27, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x11, 0x23, 0x10, 0x37, 0x36, 0x37, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x05, 0x01, 0x21, 0x03, 0x8a, 0xfe, 0xc3, 0x04, 0x90, 0xfe, 0x7b, 0x94, 0x68, 0xa9, 0xbf, 0x74, 0x56, 0x8a, 0xb6, 0x84, 0x5a, 0x75, 0xc0, 0xab, 0x4c, 0x63, 0xfd, 0xf0, 0xb6, 0xb6, 0x03, 0x2a, 0x01, 0x1e, 0xfd, 0xc3, 0x03, 0x71, 0x02, 0x64, 0xfd, 0x13, 0x32, 0x82, 0xd2, 0xfe, 0x9e, 0x01, 0x1e, 0xa1, 0x7a, 0x20, 0xfd, 0xa7, 0x02, 0x59, 0x1c, 0x7e, 0xa4, 0xfe, 0xe5, 0x01, 0x62, 0xd2, 0x5f, 0x34, 0xfd, 0x39, 0x05, 0xd5, 0xfd, 0x9c, 0x6e, 0x02, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0xad, 0x00, 0x00, 0x05, 0x90, 0x04, 0x60, 0x00, 0x1e, 0x00, 0x21, 0x00, 0x00, 0x01, 0x03, 0x21, 0x01, 0x16, 0x17, 0x16, 0x11, 0x23, 0x34, 0x27, 0x26, 0x27, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x15, 0x23, 0x10, 0x37, 0x36, 0x37, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x21, 0x13, 0x02, 0xe5, 0xfd, 0x03, 0xa8, 0xfe, 0xdb, 0x61, 0x43, 0x7b, 0xaf, 0x4d, 0x35, 0x4d, 0xa6, 0x4a, 0x33, 0x4d, 0xaf, 0x7b, 0x19, 0x1c, 0xfe, 0xb6, 0xa5, 0xa5, 0x03, 0x26, 0xfe, 0x87, 0xbc, 0x02, 0x77, 0x01, 0xe9, 0xfd, 0xcc, 0x26, 0x56, 0x9c, 0xfe, 0xec, 0xc7, 0x74, 0x4f, 0x1a, 0xfe, 0x5c, 0x01, 0xa2, 0x1a, 0x4b, 0x74, 0xc9, 0x01, 0x14, 0x9c, 0x1f, 0x18, 0xfe, 0x19, 0x04, 0x60, 0xfe, 0x17, 0x01, 0x3f, 0xfe, 0x96, 0x00, 0x00, 0x01, 0x00, 0x67, 0xfe, 0x56, 0x04, 0x02, 0x07, 0x7a, 0x00, 0x53, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x23, 0x22, 0x15, 0x14, 0x33, 0x32, 0x37, 0x36, 0x17, 0x16, 0x17, 0x15, 0x26, 0x23, 0x22, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x35, 0x32, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x21, 0x22, 0x07, 0x35, 0x36, 0x37, 0x03, 0x33, 0x13, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x15, 0x27, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x16, 0x17, 0x16, 0x15, 0x10, 0x07, 0x16, 0x17, 0x16, 0x04, 0x01, 0x67, 0x89, 0xb2, 0x3e, 0xa7, 0x20, 0x56, 0xc6, 0x3b, 0x73, 0x68, 0x1d, 0x58, 0x4c, 0x3d, 0x69, 0x35, 0xe3, 0x36, 0x70, 0x43, 0x92, 0x2f, 0x39, 0x69, 0x01, 0x3c, 0x5e, 0x3f, 0x3a, 0xa8, 0x4f, 0xe0, 0x10, 0x4d, 0x15, 0x93, 0x49, 0x6a, 0xfe, 0xe4, 0x94, 0xc8, 0x90, 0x74, 0x8f, 0x67, 0x90, 0x60, 0x1b, 0x0d, 0x15, 0x15, 0x1f, 0x3c, 0x17, 0x1f, 0x23, 0x09, 0x0e, 0x1f, 0x2d, 0x51, 0x96, 0x58, 0x67, 0xf6, 0x7f, 0x4a, 0x4c, 0x01, 0xbe, 0xcf, 0x67, 0x88, 0x08, 0x82, 0x72, 0x0c, 0x0b, 0x02, 0x07, 0x25, 0xa7, 0x27, 0x1b, 0x2c, 0x61, 0x92, 0x7a, 0x51, 0x5e, 0x58, 0x52, 0x6a, 0xbd, 0x37, 0x19, 0xa6, 0x02, 0x26, 0x36, 0x8d, 0xee, 0x4a, 0xb4, 0x2d, 0x0d, 0x01, 0x83, 0xfe, 0x83, 0xde, 0x40, 0x18, 0x27, 0x12, 0x1b, 0x0a, 0x57, 0x05, 0x02, 0x6f, 0xca, 0x18, 0x57, 0x64, 0xa7, 0xfe, 0xfd, 0x45, 0x1e, 0x5c, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x51, 0xfe, 0x74, 0x03, 0x68, 0x06, 0x06, 0x00, 0x4f, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x23, 0x22, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x33, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x10, 0x33, 0x21, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x22, 0x23, 0x35, 0x32, 0x17, 0x32, 0x33, 0x20, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x35, 0x36, 0x37, 0x03, 0x33, 0x13, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x04, 0x15, 0x14, 0x07, 0x16, 0x17, 0x16, 0x03, 0x67, 0x6a, 0x62, 0x92, 0x3d, 0x97, 0x17, 0x48, 0x58, 0x1e, 0x23, 0x28, 0xa0, 0x29, 0x59, 0x4f, 0x35, 0x59, 0x2c, 0xbd, 0x2d, 0x5e, 0x39, 0x7b, 0xb0, 0x01, 0x0e, 0x51, 0x63, 0x46, 0x36, 0x66, 0x05, 0xa0, 0x0a, 0x1d, 0x1d, 0x13, 0x01, 0x16, 0x54, 0x41, 0x53, 0x82, 0xa6, 0x71, 0x5c, 0x8f, 0x68, 0x90, 0x5f, 0x2a, 0x13, 0x27, 0x49, 0x17, 0x20, 0x2d, 0x0e, 0x1e, 0x2e, 0x51, 0x01, 0x11, 0xd1, 0x64, 0x40, 0x48, 0x01, 0x52, 0x9e, 0x5e, 0x56, 0x08, 0x81, 0x61, 0x1b, 0x09, 0x24, 0x27, 0x8b, 0x22, 0x17, 0x25, 0x52, 0x97, 0x01, 0x0c, 0x60, 0x59, 0x4c, 0x38, 0x2b, 0x08, 0x98, 0x01, 0xa0, 0x51, 0x2a, 0x21, 0x37, 0xa7, 0x1f, 0x0b, 0x01, 0x83, 0xfe, 0x83, 0xde, 0x63, 0x17, 0x32, 0x0a, 0x57, 0x07, 0x6f, 0xca, 0x2f, 0xf2, 0xc4, 0x32, 0x16, 0x40, 0x49, 0x00, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x06, 0x15, 0x05, 0xd5, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x01, 0x33, 0x01, 0x33, 0x11, 0x33, 0x11, 0x33, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x06, 0x14, 0x34, 0x17, 0x1c, 0x22, 0x1a, 0x3b, 0x36, 0xff, 0x00, 0xe1, 0xb6, 0xe1, 0xfe, 0x86, 0xb0, 0x01, 0x3b, 0x70, 0xb6, 0x71, 0xd0, 0x47, 0x5d, 0x3c, 0x74, 0x2e, 0x32, 0x05, 0x14, 0x07, 0x03, 0x19, 0x38, 0xa1, 0xfd, 0x0a, 0xfe, 0xca, 0x01, 0x36, 0x04, 0x60, 0xfc, 0x54, 0x03, 0xeb, 0xfc, 0x13, 0x02, 0x72, 0xd4, 0x50, 0x33, 0x10, 0x00, 0x00, 0x01, 0x00, 0x2d, 0xfe, 0x56, 0x06, 0x22, 0x06, 0x1e, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x23, 0x11, 0x23, 0x11, 0x23, 0x01, 0x33, 0x01, 0x33, 0x11, 0x33, 0x11, 0x33, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x06, 0x22, 0x35, 0x16, 0x1d, 0x21, 0x1a, 0x3c, 0x36, 0xff, 0xe1, 0xa5, 0xe1, 0xfe, 0x86, 0xaf, 0x01, 0x3c, 0x70, 0xa5, 0x70, 0xd1, 0x46, 0x5e, 0x3b, 0x74, 0x2e, 0x33, 0x03, 0xde, 0x07, 0x03, 0x19, 0x38, 0xa1, 0xfd, 0x0a, 0xfe, 0x56, 0x01, 0xaa, 0x04, 0x60, 0xfc, 0x54, 0x05, 0x6a, 0xfa, 0x94, 0x02, 0x72, 0xd4, 0x50, 0x33, 0x10, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x12, 0x06, 0x01, 0x61, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x12, 0x06, 0x02, 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x05, 0x8a, 0x05, 0xf0, 0x00, 0x12, 0x00, 0x00, 0x01, 0x32, 0x17, 0x15, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x01, 0x23, 0x01, 0x33, 0x09, 0x01, 0x12, 0x36, 0x05, 0x18, 0x39, 0x39, 0x3e, 0x14, 0x16, 0x42, 0x1e, 0x40, 0x4c, 0xfe, 0xa8, 0xcf, 0xfd, 0xff, 0xbe, 0x01, 0xaa, 0x01, 0x19, 0x67, 0x9d, 0x05, 0xf0, 0x15, 0xbb, 0x0a, 0x04, 0x22, 0x43, 0xdd, 0xfc, 0x14, 0x05, 0xd5, 0xfb, 0x17, 0x03, 0x3d, 0x01, 0x32, 0x95, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x04, 0x9c, 0x04, 0x7b, 0x00, 0x13, 0x00, 0x00, 0x01, 0x32, 0x17, 0x15, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x01, 0x23, 0x01, 0x33, 0x01, 0x13, 0x36, 0x37, 0x36, 0x04, 0x3c, 0x2e, 0x32, 0x34, 0x11, 0x23, 0x21, 0x1a, 0x3b, 0x36, 0xff, 0x00, 0xe1, 0xfe, 0x86, 0xaf, 0x01, 0x3c, 0xd0, 0x48, 0x5c, 0x3c, 0x04, 0x7b, 0x10, 0x8d, 0x07, 0x03, 0x19, 0x37, 0xa2, 0xfd, 0x0a, 0x04, 0x60, 0xfc, 0x54, 0x02, 0x70, 0xd5, 0x4f, 0x33, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x05, 0x8a, 0x07, 0x70, 0x10, 0x27, 0x10, 0xf5, 0x04, 0x67, 0x01, 0x7a, 0x12, 0x06, 0x04, 0x08, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2d, 0x00, 0x00, 0x04, 0x9c, 0x06, 0x66, 0x10, 0x27, 0x02, 0xc0, 0x04, 0x48, 0x00, 0x00, 0x12, 0x06, 0x04, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x67, 0xfe, 0x56, 0x06, 0xee, 0x05, 0xf0, 0x00, 0x11, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x00, 0x09, 0x01, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x13, 0x01, 0x33, 0x1b, 0x01, 0x01, 0x10, 0x07, 0x02, 0x20, 0x03, 0x26, 0x10, 0x37, 0x12, 0x20, 0x13, 0x16, 0x03, 0x10, 0x27, 0x26, 0x20, 0x07, 0x06, 0x11, 0x10, 0x17, 0x16, 0x20, 0x37, 0x36, 0x06, 0xee, 0xfe, 0x45, 0x4a, 0x3f, 0x42, 0x70, 0x84, 0x61, 0x44, 0x26, 0x22, 0x32, 0x6f, 0xfe, 0xc6, 0xaf, 0xe4, 0xe3, 0xfd, 0x86, 0x56, 0x71, 0xfe, 0x33, 0x72, 0x56, 0x56, 0x72, 0x01, 0xcd, 0x71, 0x56, 0xc0, 0x19, 0x32, 0xfe, 0xbc, 0x35, 0x19, 0x1a, 0x34, 0x01, 0x44, 0x33, 0x18, 0x04, 0x60, 0xfb, 0x38, 0xcb, 0x3a, 0x3d, 0x9a, 0x24, 0x21, 0x89, 0x01, 0x37, 0x03, 0x6b, 0xfd, 0x8a, 0x02, 0x76, 0xfe, 0x8a, 0xfe, 0xdd, 0xd0, 0xfe, 0xec, 0x01, 0x13, 0xd1, 0x02, 0x44, 0xd1, 0x01, 0x14, 0xfe, 0xed, 0xd1, 0xfe, 0xde, 0x01, 0x06, 0x72, 0xea, 0xea, 0x74, 0xfe, 0xfb, 0xfe, 0xfc, 0x74, 0xea, 0xea, 0x72, 0x00, 0x00, 0x03, 0x00, 0x65, 0xfe, 0x56, 0x06, 0x4c, 0x04, 0x7b, 0x00, 0x11, 0x00, 0x1f, 0x00, 0x25, 0x00, 0x00, 0x09, 0x01, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x13, 0x01, 0x33, 0x1b, 0x01, 0x00, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x02, 0x10, 0x23, 0x22, 0x10, 0x33, 0x06, 0x4c, 0xfe, 0x45, 0x4a, 0x3f, 0x42, 0x70, 0x84, 0x61, 0x44, 0x26, 0x22, 0x32, 0x6f, 0xfe, 0xc6, 0xaf, 0xe4, 0xe3, 0xfd, 0xb6, 0x55, 0x67, 0xb8, 0xba, 0x68, 0x56, 0x56, 0x68, 0xba, 0xb8, 0x67, 0x5a, 0xc5, 0xca, 0xca, 0x04, 0x60, 0xfb, 0x38, 0xcb, 0x3a, 0x3d, 0x9a, 0x24, 0x21, 0x89, 0x01, 0x37, 0x03, 0x6b, 0xfd, 0x8a, 0x02, 0x76, 0xfe, 0xab, 0xfe, 0x48, 0xa7, 0xc9, 0xc8, 0xa6, 0x01, 0xbc, 0xa6, 0xc8, 0xc9, 0xfc, 0xcd, 0x03, 0x60, 0xfc, 0xa0, 0x00, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x06, 0x76, 0x05, 0xf0, 0x00, 0x29, 0x00, 0x52, 0x00, 0x00, 0x25, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x07, 0x23, 0x20, 0x27, 0x26, 0x10, 0x37, 0x36, 0x21, 0x33, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x33, 0x20, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x21, 0x23, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x03, 0xed, 0x1b, 0xd4, 0x66, 0x74, 0x74, 0x66, 0xd4, 0x1b, 0x0a, 0x0d, 0x14, 0x18, 0x18, 0x37, 0x18, 0x18, 0x14, 0x0e, 0x09, 0x2a, 0xd3, 0x67, 0x75, 0x75, 0x67, 0xd3, 0x2a, 0x09, 0x0e, 0x14, 0x18, 0x18, 0x37, 0x18, 0x18, 0x14, 0x0e, 0xe4, 0x2a, 0xfe, 0xc4, 0x88, 0xaa, 0xaa, 0x88, 0x01, 0x3c, 0x29, 0x0a, 0x0e, 0x14, 0x18, 0x18, 0x37, 0x18, 0x1c, 0x10, 0x0e, 0x0a, 0x1a, 0x01, 0x3b, 0x89, 0xa9, 0xa9, 0x89, 0xfe, 0xc5, 0x1a, 0x09, 0x0f, 0x14, 0x18, 0x18, 0x37, 0x18, 0x1c, 0x10, 0x0e, 0xc2, 0x91, 0xa4, 0xf2, 0xf3, 0xa4, 0x91, 0x14, 0x0e, 0x15, 0x0c, 0x0b, 0x0b, 0x0c, 0x15, 0x10, 0x12, 0x91, 0xa4, 0xf3, 0xf2, 0xa4, 0x91, 0x12, 0x10, 0x15, 0x0c, 0x0b, 0x0b, 0x0c, 0x15, 0x10, 0xa1, 0xaa, 0xd2, 0x02, 0x74, 0xd3, 0xaa, 0x15, 0x0f, 0x15, 0x0c, 0x0b, 0x0b, 0x0e, 0x13, 0x11, 0x13, 0xaa, 0xd3, 0xfe, 0xc6, 0xfe, 0xc7, 0xd2, 0xab, 0x13, 0x11, 0x15, 0x0c, 0x0b, 0x0b, 0x0e, 0x13, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x05, 0x11, 0x04, 0x7b, 0x00, 0x26, 0x00, 0x50, 0x00, 0x00, 0x25, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x36, 0x37, 0x3e, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x07, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x03, 0x1a, 0x28, 0x91, 0x41, 0x4d, 0x4d, 0x39, 0x99, 0x28, 0x06, 0x0a, 0x10, 0x27, 0x2f, 0x28, 0x10, 0x09, 0x06, 0x29, 0x92, 0x40, 0x4e, 0x4d, 0x41, 0x92, 0x29, 0x06, 0x09, 0x10, 0x28, 0x2f, 0x13, 0x19, 0x0b, 0x09, 0xb5, 0x2a, 0xe7, 0x6c, 0x7b, 0x7b, 0x68, 0xeb, 0x2a, 0x06, 0x08, 0x0c, 0x18, 0x14, 0x2f, 0x13, 0x19, 0x0b, 0x09, 0x06, 0x29, 0xe8, 0x6c, 0x7b, 0x7b, 0x69, 0xeb, 0x29, 0x06, 0x09, 0x0b, 0x19, 0x13, 0x2f, 0x14, 0x18, 0x0c, 0x08, 0xa4, 0x60, 0x74, 0xb7, 0xa7, 0x83, 0x61, 0x0b, 0x0a, 0x11, 0x14, 0x14, 0x11, 0x0a, 0x0b, 0x5f, 0x74, 0xb8, 0xbc, 0x70, 0x5f, 0x0b, 0x0a, 0x11, 0x14, 0x0a, 0x0c, 0x0f, 0x0a, 0x93, 0x89, 0x9c, 0xee, 0xe9, 0xa2, 0x88, 0x0a, 0x0a, 0x0f, 0x0c, 0x0a, 0x0a, 0x0c, 0x0f, 0x0a, 0x0a, 0x88, 0x9c, 0xef, 0xe8, 0xa2, 0x89, 0x0a, 0x0a, 0x0f, 0x0c, 0x0a, 0x0a, 0x0c, 0x0f, 0x0a, 0x00, 0x03, 0x00, 0x6a, 0xff, 0xe3, 0x08, 0x15, 0x07, 0x74, 0x00, 0x34, 0x00, 0x3d, 0x00, 0x4b, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x15, 0x10, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x11, 0x34, 0x27, 0x26, 0x27, 0x33, 0x16, 0x17, 0x16, 0x01, 0x10, 0x23, 0x35, 0x16, 0x35, 0x23, 0x35, 0x33, 0x17, 0x23, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x20, 0x08, 0x14, 0x5c, 0x68, 0xd3, 0x51, 0x64, 0x57, 0x56, 0x6e, 0x6c, 0x6e, 0x6f, 0xae, 0x63, 0x52, 0xd3, 0x68, 0x5c, 0x3c, 0x40, 0x64, 0xe0, 0x71, 0x52, 0x4c, 0xe6, 0x7c, 0x54, 0x44, 0x44, 0x5c, 0x8d, 0x8b, 0x5a, 0x44, 0x43, 0x53, 0x7c, 0xe7, 0x4d, 0x52, 0x71, 0xe1, 0x64, 0x3f, 0x3c, 0xfc, 0xa2, 0xda, 0x79, 0x78, 0xd9, 0xe4, 0x6a, 0x15, 0x92, 0x54, 0x52, 0x84, 0x7a, 0x7d, 0x42, 0x6c, 0x70, 0x01, 0x07, 0x01, 0xfe, 0xf2, 0x8b, 0x9e, 0x44, 0x40, 0x40, 0x44, 0x44, 0x80, 0x44, 0x9d, 0x8b, 0xf2, 0xc6, 0xe2, 0xec, 0x98, 0x6b, 0xf3, 0xe2, 0xb6, 0xfe, 0xba, 0x36, 0x33, 0x33, 0x36, 0x36, 0x33, 0x33, 0x36, 0x01, 0x46, 0xb6, 0xe2, 0xf3, 0x6b, 0x98, 0xec, 0xe2, 0x03, 0x0a, 0xfe, 0xf5, 0x67, 0x03, 0x9d, 0x9e, 0x11, 0x9b, 0x2f, 0x4b, 0x17, 0x86, 0x27, 0x2a, 0x43, 0x00, 0x03, 0x00, 0x88, 0xff, 0xe3, 0x06, 0xde, 0x06, 0x10, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x38, 0x00, 0x00, 0x01, 0x12, 0x11, 0x10, 0x21, 0x22, 0x24, 0x22, 0x04, 0x23, 0x20, 0x11, 0x10, 0x13, 0x33, 0x02, 0x15, 0x10, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x11, 0x34, 0x03, 0x25, 0x10, 0x23, 0x35, 0x16, 0x35, 0x23, 0x35, 0x33, 0x17, 0x23, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x20, 0x06, 0x62, 0x7c, 0xfe, 0x9a, 0x4c, 0xfe, 0xf3, 0xd8, 0xfe, 0xf2, 0x4a, 0xfe, 0x9a, 0x7c, 0xb2, 0x83, 0xbb, 0x38, 0x41, 0x6c, 0x13, 0x5a, 0xe3, 0x5a, 0x12, 0x6d, 0x42, 0x39, 0xbb, 0x84, 0xfe, 0x7b, 0xd9, 0x78, 0x77, 0xd8, 0xe4, 0x6a, 0x15, 0x91, 0x54, 0x52, 0x84, 0x7b, 0x7d, 0x43, 0x6b, 0x70, 0x01, 0x07, 0x03, 0xc5, 0xfe, 0xe3, 0xfe, 0xeb, 0xfe, 0x50, 0xe2, 0xe2, 0x01, 0xb1, 0x01, 0x14, 0x01, 0x1d, 0xfe, 0xb9, 0xfa, 0xfe, 0xfb, 0x38, 0x5b, 0x0c, 0x37, 0x37, 0x0c, 0x5b, 0x38, 0x01, 0x07, 0xf8, 0x01, 0x47, 0xa4, 0xfe, 0xf5, 0x67, 0x03, 0x9d, 0x9e, 0x11, 0x9b, 0x2f, 0x4b, 0x17, 0x86, 0x27, 0x2a, 0x43, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x06, 0x52, 0x07, 0x33, 0x10, 0x27, 0x11, 0xb5, 0x00, 0x59, 0x01, 0x53, 0x10, 0x06, 0x03, 0xf4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x05, 0xe0, 0x10, 0x26, 0x11, 0xb5, 0x00, 0x00, 0x10, 0x06, 0x03, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0xfe, 0x56, 0x04, 0xa4, 0x05, 0xf0, 0x00, 0x1d, 0x00, 0x00, 0x21, 0x23, 0x20, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x21, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x11, 0x10, 0x17, 0x16, 0x33, 0x21, 0x11, 0x23, 0x03, 0x94, 0x9c, 0xfe, 0xc7, 0xa8, 0xaf, 0xaf, 0xaf, 0x01, 0x32, 0x78, 0x6a, 0x6c, 0x5d, 0x5c, 0x67, 0x69, 0x75, 0xe6, 0x7a, 0x7b, 0x7b, 0x88, 0xd8, 0x01, 0x47, 0xb5, 0xc6, 0xd0, 0x01, 0x53, 0x01, 0x68, 0xcf, 0xd0, 0x24, 0x23, 0x47, 0xd5, 0x5f, 0x2f, 0x2f, 0x9c, 0x9d, 0xfe, 0xd8, 0xfe, 0xd3, 0x82, 0x94, 0xfd, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xfe, 0x56, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x1d, 0x00, 0x00, 0x21, 0x22, 0x27, 0x26, 0x35, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x11, 0x23, 0x11, 0x02, 0x56, 0xeb, 0x7f, 0x86, 0x88, 0x87, 0xeb, 0x4d, 0x49, 0x49, 0x44, 0x46, 0x47, 0x46, 0x48, 0xa2, 0x59, 0x59, 0x59, 0x59, 0xa2, 0xdc, 0xb5, 0x96, 0x9f, 0xfa, 0x01, 0x12, 0x9d, 0x9d, 0x11, 0x12, 0x23, 0xac, 0x2b, 0x16, 0x15, 0x71, 0x72, 0xcd, 0xb9, 0x72, 0x71, 0xfd, 0xc3, 0x01, 0xaa, 0x00, 0x01, 0x00, 0x35, 0xff, 0xa5, 0x03, 0x69, 0x03, 0xa7, 0x00, 0x13, 0x00, 0x00, 0x01, 0x07, 0x27, 0x07, 0x17, 0x07, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x03, 0x69, 0x5a, 0xc2, 0x5f, 0xc2, 0x5a, 0xc2, 0x70, 0x9d, 0x71, 0xc3, 0x5a, 0xc3, 0x5e, 0xc2, 0x5a, 0xc2, 0x5e, 0x9d, 0x5e, 0x02, 0x11, 0xae, 0x7d, 0xb5, 0x7d, 0xae, 0x7d, 0xd8, 0x64, 0xd8, 0x7d, 0xae, 0x7d, 0xb5, 0x7d, 0xae, 0x7d, 0xb5, 0x64, 0xb5, 0x00, 0x01, 0xfc, 0x44, 0x04, 0xde, 0xff, 0x55, 0x06, 0x7a, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x21, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x21, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0xfe, 0xda, 0xfe, 0x61, 0x09, 0x0a, 0x11, 0x12, 0x17, 0x15, 0x33, 0x15, 0x17, 0x12, 0x11, 0x0a, 0x09, 0x09, 0x0a, 0x11, 0x12, 0x17, 0x15, 0x1a, 0x01, 0x9e, 0x09, 0x0a, 0x11, 0x12, 0x17, 0x15, 0x33, 0x15, 0x17, 0x12, 0x12, 0x09, 0x09, 0x09, 0x0a, 0x11, 0x12, 0x17, 0x15, 0x05, 0x67, 0x1b, 0x19, 0x1b, 0x12, 0x13, 0x0b, 0x0a, 0x0a, 0x0b, 0x13, 0x12, 0x1b, 0x19, 0x1b, 0x1c, 0x19, 0x1b, 0x12, 0x13, 0x0b, 0x0a, 0x1b, 0x19, 0x1b, 0x12, 0x13, 0x0b, 0x0a, 0x0a, 0x0b, 0x13, 0x15, 0x18, 0x19, 0x1c, 0x1b, 0x19, 0x1b, 0x12, 0x13, 0x0b, 0x0a, 0x00, 0x00, 0x01, 0xfd, 0x53, 0x05, 0x29, 0x00, 0x09, 0x06, 0x4d, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x23, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x20, 0x08, 0x6a, 0x15, 0x92, 0x53, 0x52, 0x84, 0x7b, 0x7d, 0x43, 0x6b, 0x70, 0x01, 0x07, 0x05, 0x29, 0x9b, 0x2f, 0x4b, 0x17, 0x86, 0x27, 0x2a, 0x43, 0x00, 0x01, 0xfd, 0xed, 0x04, 0xc2, 0xfe, 0xc8, 0x06, 0x61, 0x00, 0x08, 0x00, 0x00, 0x01, 0x22, 0x11, 0x35, 0x33, 0x15, 0x23, 0x14, 0x37, 0xfe, 0xc8, 0xda, 0xd9, 0x78, 0x79, 0x04, 0xc2, 0x01, 0x0b, 0x94, 0x9e, 0x9d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xed, 0x04, 0xc2, 0xfe, 0xc8, 0x06, 0x61, 0x00, 0x08, 0x00, 0x00, 0x01, 0x10, 0x23, 0x35, 0x16, 0x35, 0x23, 0x35, 0x33, 0xfe, 0xc8, 0xda, 0x78, 0x77, 0xd9, 0x05, 0xcd, 0xfe, 0xf5, 0x67, 0x03, 0x9d, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x69, 0x04, 0xd9, 0x00, 0x09, 0x06, 0x4d, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x12, 0x21, 0x32, 0x05, 0x04, 0x25, 0x15, 0x24, 0x27, 0x24, 0x27, 0x26, 0x07, 0xfa, 0x69, 0x79, 0x01, 0x84, 0x67, 0x01, 0x25, 0x01, 0x13, 0x01, 0x03, 0xfe, 0x89, 0xd7, 0xfe, 0xf6, 0x5c, 0xc6, 0x89, 0x05, 0x01, 0x01, 0x4c, 0x7b, 0x74, 0x01, 0x86, 0x17, 0x5c, 0x71, 0x07, 0x0c, 0xcf, 0x00, 0x00, 0x00, 0x08, 0xf8, 0xa7, 0xfe, 0x90, 0x02, 0xf3, 0x07, 0x60, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x26, 0x00, 0x33, 0x00, 0x40, 0x00, 0x4d, 0x00, 0x5a, 0x00, 0x67, 0x00, 0x00, 0x01, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0x01, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0x05, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0x01, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0x05, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0x01, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0x05, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0x01, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x20, 0x16, 0xfe, 0xe6, 0x6a, 0x0a, 0x57, 0x4e, 0x4e, 0x56, 0x0c, 0x6a, 0x09, 0x8e, 0x01, 0x05, 0x8e, 0x02, 0xe6, 0x6a, 0x0a, 0x57, 0x4f, 0x4d, 0x57, 0x0b, 0x6a, 0x08, 0x8f, 0x01, 0x05, 0x8e, 0xfa, 0x50, 0x6a, 0x0a, 0x58, 0x4e, 0x4d, 0x57, 0x0c, 0x6a, 0x09, 0x8f, 0x01, 0x04, 0x8f, 0x05, 0xc2, 0x6a, 0x0a, 0x57, 0x4f, 0x4d, 0x57, 0x0b, 0x6a, 0x08, 0x8f, 0x01, 0x05, 0x8e, 0xfa, 0x50, 0x6a, 0x0a, 0x58, 0x4e, 0x4d, 0x57, 0x0c, 0x6a, 0x09, 0x8f, 0x01, 0x04, 0x8f, 0x06, 0xf1, 0x6a, 0x0a, 0x57, 0x4f, 0x4d, 0x56, 0x0c, 0x6a, 0x09, 0x8e, 0x01, 0x05, 0x8e, 0xf7, 0xf1, 0x6a, 0x0a, 0x57, 0x4e, 0x4e, 0x56, 0x0c, 0x6a, 0x09, 0x8e, 0x01, 0x05, 0x8e, 0x04, 0x15, 0x6a, 0x0a, 0x57, 0x4e, 0x4e, 0x56, 0x0c, 0x6a, 0x09, 0x8e, 0x01, 0x05, 0x8e, 0x06, 0x41, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0xfe, 0x51, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0x8f, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0xfa, 0x01, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0x8f, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0x02, 0x29, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0x8f, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0xfb, 0x98, 0x4b, 0x4b, 0x4a, 0x4c, 0x8f, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf9, 0x1c, 0xfd, 0xc3, 0x02, 0x7c, 0x08, 0x2d, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x11, 0x00, 0x17, 0x00, 0x1d, 0x00, 0x23, 0x00, 0x29, 0x00, 0x2f, 0x00, 0x00, 0x27, 0x37, 0x17, 0x13, 0x07, 0x03, 0x01, 0x07, 0x27, 0x03, 0x37, 0x13, 0x01, 0x27, 0x37, 0x25, 0x17, 0x05, 0x01, 0x17, 0x07, 0x05, 0x27, 0x25, 0x01, 0x35, 0x33, 0x05, 0x15, 0x2d, 0x01, 0x15, 0x23, 0x25, 0x35, 0x05, 0x01, 0x23, 0x35, 0x13, 0x33, 0x0b, 0x01, 0x33, 0x15, 0x03, 0x23, 0x13, 0x60, 0x87, 0x6d, 0x64, 0x53, 0x98, 0xfb, 0xeb, 0x87, 0x6d, 0x64, 0x53, 0x98, 0x04, 0x9c, 0x87, 0x6e, 0x01, 0x33, 0x53, 0xff, 0x00, 0xfa, 0xde, 0x86, 0x6d, 0xfe, 0xcb, 0x52, 0x01, 0x00, 0x05, 0xbd, 0x9a, 0x01, 0x20, 0xfe, 0xe0, 0xf9, 0x7c, 0x9b, 0xfe, 0xe0, 0x01, 0x20, 0x03, 0xef, 0xbe, 0x94, 0x74, 0x4a, 0xbe, 0xbe, 0x93, 0x75, 0x4a, 0x5a, 0x96, 0x79, 0xfe, 0xa9, 0x5c, 0x01, 0x1d, 0x05, 0xb5, 0x96, 0x79, 0x01, 0x57, 0x5c, 0xfe, 0xe3, 0xfe, 0xf1, 0x95, 0x7a, 0x6e, 0x5b, 0xa9, 0xfb, 0x77, 0x96, 0x79, 0x6f, 0x5c, 0xa8, 0x02, 0x18, 0xd4, 0xa4, 0x82, 0x52, 0xd4, 0xd4, 0xa4, 0x82, 0x52, 0x02, 0xdf, 0xac, 0x01, 0x40, 0xfe, 0xc0, 0xf8, 0xc2, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x56, 0x05, 0x63, 0x07, 0x6d, 0x10, 0x26, 0x11, 0xb6, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf2, 0x04, 0x76, 0x01, 0x75, 0xff, 0xff, 0x00, 0xad, 0xfe, 0x56, 0x04, 0xb3, 0x06, 0x14, 0x10, 0x26, 0x11, 0xb7, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9a, 0x00, 0x90, 0xff, 0xcc, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x15, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x23, 0x35, 0x33, 0x35, 0x33, 0x15, 0x33, 0x15, 0x01, 0x34, 0x27, 0x26, 0x23, 0x21, 0x11, 0x21, 0x32, 0x37, 0x36, 0x01, 0x6b, 0x01, 0x2c, 0xe2, 0xf5, 0xf5, 0xe2, 0xfe, 0x1e, 0x97, 0x97, 0xb6, 0x97, 0x01, 0xac, 0x47, 0x46, 0x93, 0xfe, 0xdd, 0x01, 0x23, 0x93, 0x46, 0x47, 0x04, 0x51, 0xe2, 0xda, 0xde, 0xdd, 0xda, 0x04, 0x51, 0xa4, 0xe0, 0xe0, 0xa4, 0xfd, 0x66, 0x8b, 0x44, 0x43, 0xfd, 0xdd, 0x44, 0x43, 0x00, 0x00, 0x00, 0x02, 0x00, 0x22, 0x00, 0x00, 0x03, 0xd8, 0x05, 0x9e, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x11, 0x33, 0x32, 0x37, 0x36, 0x01, 0x11, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x21, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0x03, 0x27, 0x37, 0x3d, 0x73, 0xed, 0xed, 0x74, 0x3c, 0x37, 0xfe, 0x2c, 0xf4, 0xbb, 0x6d, 0x69, 0x69, 0x67, 0xc1, 0xfe, 0x67, 0x8c, 0x8c, 0xa5, 0x8e, 0x01, 0x4c, 0x5e, 0x2a, 0x2e, 0xfe, 0x97, 0x2e, 0x2b, 0x02, 0xdf, 0xfe, 0xca, 0x55, 0x52, 0xfe, 0xb0, 0x52, 0x52, 0x03, 0xd1, 0x8f, 0x01, 0x3e, 0xfe, 0xc2, 0x8f, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x65, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x17, 0x07, 0x27, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x27, 0x36, 0x37, 0x34, 0x26, 0x2b, 0x01, 0x11, 0x33, 0x32, 0x37, 0x27, 0x37, 0x03, 0xe6, 0x7e, 0x5f, 0x84, 0x71, 0xc1, 0xe4, 0xb6, 0x01, 0x9a, 0xe2, 0x73, 0x74, 0xcb, 0x0b, 0x01, 0x8b, 0x7f, 0xe4, 0xe4, 0x67, 0x40, 0xc2, 0x60, 0x03, 0x23, 0x75, 0x7e, 0x7b, 0x53, 0xfd, 0xa8, 0x05, 0xd5, 0x71, 0x72, 0xdb, 0x92, 0x2d, 0x2c, 0x39, 0x86, 0x92, 0xfd, 0xcf, 0x2f, 0xb4, 0x7e, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x00, 0x10, 0x00, 0x29, 0x00, 0x00, 0x25, 0x27, 0x37, 0x17, 0x36, 0x35, 0x34, 0x27, 0x26, 0x20, 0x07, 0x06, 0x10, 0x17, 0x16, 0x33, 0x32, 0x1f, 0x01, 0x07, 0x27, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x02, 0xd9, 0x7e, 0x63, 0x7c, 0x47, 0x4a, 0x4c, 0xfe, 0xf9, 0x4b, 0x4b, 0x4b, 0x4b, 0x84, 0x3f, 0xfe, 0x85, 0x64, 0x86, 0x4f, 0x61, 0x6f, 0x4f, 0x50, 0x34, 0xa7, 0xa7, 0x34, 0x50, 0x4f, 0x6f, 0xb8, 0x72, 0x73, 0x73, 0x0b, 0x98, 0xa7, 0x5d, 0xa5, 0x73, 0xc5, 0xcb, 0x74, 0x73, 0x74, 0x73, 0xfe, 0x6a, 0x74, 0x73, 0x14, 0xae, 0x5d, 0xb3, 0x2e, 0x30, 0x31, 0x64, 0xfd, 0xae, 0x06, 0x0a, 0xaa, 0x64, 0x30, 0x31, 0xa2, 0xa2, 0xfd, 0xf0, 0xa2, 0x0f, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x07, 0x07, 0x00, 0x07, 0x00, 0x00, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0xb5, 0x02, 0xab, 0x99, 0xfd, 0x72, 0x05, 0xd5, 0x01, 0x32, 0xfe, 0x24, 0xfa, 0xd5, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x6f, 0x05, 0x9a, 0x00, 0x07, 0x00, 0x00, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0xa7, 0x02, 0x43, 0x84, 0xfd, 0xdf, 0x04, 0x60, 0x01, 0x3a, 0xfe, 0x33, 0xfc, 0x33, 0x00, 0x01, 0x00, 0x3f, 0x00, 0x00, 0x04, 0x71, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x21, 0x11, 0x23, 0x35, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x2d, 0xed, 0xed, 0x03, 0x44, 0xfd, 0x71, 0x01, 0xed, 0xfe, 0x13, 0x02, 0x94, 0xaa, 0x02, 0x97, 0xaa, 0xfe, 0x13, 0xaa, 0xfd, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x32, 0x00, 0x00, 0x03, 0xe7, 0x04, 0x60, 0x00, 0x0d, 0x00, 0x00, 0x21, 0x11, 0x23, 0x35, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x1f, 0xed, 0xed, 0x02, 0xc7, 0xfd, 0xdf, 0x01, 0x76, 0xfe, 0x8a, 0x01, 0xf4, 0xaa, 0x01, 0xc2, 0x9d, 0xfe, 0xdb, 0xaa, 0xfe, 0x0c, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x66, 0x04, 0x52, 0x05, 0xd5, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x01, 0x6b, 0xb6, 0x03, 0x44, 0xfd, 0x72, 0x01, 0x77, 0xa7, 0x66, 0x62, 0xb7, 0xce, 0x44, 0x38, 0x78, 0x33, 0x31, 0x6f, 0x70, 0x02, 0xc7, 0xfd, 0x39, 0x05, 0xd5, 0xaa, 0xfe, 0x46, 0x77, 0x72, 0xee, 0xfe, 0xce, 0xfe, 0xf2, 0xf4, 0xaa, 0x4b, 0x4b, 0xc2, 0x01, 0x22, 0x9f, 0x9e, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xa4, 0x04, 0x60, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x27, 0x26, 0x23, 0x01, 0x4d, 0xa6, 0x02, 0xc7, 0xfd, 0xdf, 0xe1, 0xed, 0x3f, 0x4a, 0x4a, 0x49, 0xa3, 0xae, 0x9b, 0x63, 0x1e, 0x22, 0x22, 0x2c, 0x79, 0x01, 0xe7, 0xfe, 0x19, 0x04, 0x60, 0xaa, 0xfe, 0xc1, 0x47, 0x51, 0xe5, 0xfe, 0xf2, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x37, 0x93, 0x01, 0x08, 0xaa, 0x20, 0x29, 0x00, 0x01, 0x00, 0x24, 0xfe, 0xbf, 0x07, 0xb6, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x00, 0x01, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x11, 0x23, 0x01, 0x03, 0x11, 0x23, 0x11, 0x03, 0x01, 0x23, 0x09, 0x01, 0x33, 0x01, 0x03, 0x86, 0xb6, 0x02, 0x65, 0xdd, 0xfe, 0x15, 0x01, 0xa8, 0x7b, 0xb2, 0x24, 0xfe, 0x44, 0xe8, 0xb6, 0xe8, 0xfe, 0x44, 0xbe, 0x02, 0x0a, 0xfe, 0x16, 0xdc, 0x02, 0x66, 0x05, 0xd5, 0xfd, 0x1e, 0x02, 0xe2, 0xfd, 0xb3, 0xfd, 0x22, 0xfe, 0x15, 0x01, 0x41, 0x03, 0x01, 0xfe, 0xe9, 0xfe, 0x16, 0x01, 0xea, 0x01, 0x17, 0xfc, 0xff, 0x03, 0x88, 0x02, 0x4d, 0xfd, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3f, 0xfe, 0xe5, 0x06, 0x50, 0x04, 0x60, 0x00, 0x17, 0x00, 0x00, 0x01, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x11, 0x23, 0x01, 0x07, 0x11, 0x23, 0x11, 0x27, 0x01, 0x23, 0x09, 0x01, 0x33, 0x01, 0x02, 0xec, 0xa5, 0x01, 0xb8, 0xc0, 0xfe, 0x97, 0x01, 0x42, 0x6e, 0xa6, 0x1e, 0xfe, 0xad, 0xa8, 0xa5, 0xa8, 0xfe, 0xac, 0xb1, 0x01, 0x9e, 0xfe, 0x96, 0xc1, 0x01, 0xb8, 0x04, 0x60, 0xfd, 0xf2, 0x02, 0x0e, 0xfe, 0x51, 0xfd, 0xe8, 0xfe, 0x4c, 0x01, 0x1b, 0x02, 0x36, 0xc9, 0xfe, 0x93, 0x01, 0x6d, 0xc9, 0xfd, 0xca, 0x02, 0xb1, 0x01, 0xaf, 0xfd, 0xf2, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x75, 0x04, 0x25, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x7a, 0x33, 0x00, 0x12, 0x06, 0x03, 0xab, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xfe, 0x75, 0x03, 0x68, 0x04, 0x7c, 0x10, 0x26, 0x00, 0x7a, 0xd3, 0x00, 0x12, 0x06, 0x03, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x05, 0x22, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x11, 0x23, 0x01, 0x03, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x89, 0xea, 0xfd, 0xf8, 0x01, 0xbc, 0x90, 0xb1, 0x3e, 0xfe, 0x2d, 0xf5, 0xb6, 0x05, 0xd5, 0xfd, 0x1e, 0x02, 0xe2, 0xfd, 0xb2, 0xfd, 0x23, 0xfe, 0x15, 0x01, 0x41, 0x03, 0x01, 0xfe, 0xe9, 0xfe, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x04, 0x3b, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x11, 0x23, 0x01, 0x07, 0x11, 0x23, 0xa7, 0xa5, 0x01, 0xd3, 0xcc, 0xfe, 0x7e, 0x01, 0x52, 0x80, 0xa6, 0x32, 0xfe, 0x9a, 0xb1, 0xa5, 0x04, 0x60, 0xfd, 0xf2, 0x02, 0x0e, 0xfe, 0x4f, 0xfd, 0xea, 0xfe, 0x4c, 0x01, 0x1b, 0x02, 0x35, 0xc8, 0xfe, 0x93, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xf9, 0x05, 0xd5, 0x00, 0x12, 0x00, 0x00, 0x13, 0x33, 0x11, 0x37, 0x11, 0x33, 0x15, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x11, 0x07, 0x11, 0x23, 0xb5, 0xb6, 0x9b, 0x5a, 0x01, 0x94, 0xea, 0xfd, 0xf8, 0x02, 0x23, 0xc6, 0xfe, 0x2d, 0x5a, 0x9b, 0xb6, 0x05, 0xd5, 0xfd, 0x1e, 0xb1, 0x01, 0x54, 0xee, 0x01, 0xcb, 0xfd, 0xb2, 0xfc, 0x79, 0x03, 0x01, 0xfe, 0x25, 0x01, 0x75, 0xb1, 0xfe, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x1d, 0x04, 0x60, 0x00, 0x12, 0x00, 0x00, 0x13, 0x33, 0x11, 0x37, 0x35, 0x33, 0x15, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x35, 0x07, 0x11, 0x23, 0xa7, 0xa5, 0x56, 0x5b, 0x01, 0x22, 0xcc, 0xfe, 0x7e, 0x01, 0xb3, 0xb9, 0xfe, 0x9a, 0x5b, 0x56, 0xa5, 0x04, 0x60, 0xfd, 0xf2, 0x61, 0xdd, 0x76, 0x01, 0x46, 0xfe, 0x4f, 0xfd, 0x51, 0x02, 0x35, 0xfe, 0xc5, 0xd4, 0x61, 0xfe, 0x93, 0x00, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0x04, 0xf9, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x13, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x03, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0xb5, 0xb6, 0x97, 0x97, 0x02, 0x89, 0xea, 0xfd, 0xf8, 0x02, 0x23, 0xc6, 0xfe, 0x2d, 0xf5, 0xb6, 0x97, 0x97, 0x05, 0xd5, 0xe0, 0x90, 0xfe, 0x8e, 0x02, 0xe2, 0xfd, 0xb2, 0xfc, 0x79, 0x03, 0x01, 0xfe, 0xe9, 0xfe, 0x16, 0x04, 0x65, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0x1d, 0x06, 0x14, 0x00, 0x13, 0x00, 0x00, 0x13, 0x33, 0x15, 0x21, 0x15, 0x21, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x07, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0xa7, 0xa5, 0x01, 0x40, 0xfe, 0xc0, 0x01, 0xd3, 0xcc, 0xfe, 0x7e, 0x01, 0xb3, 0xb9, 0xfe, 0x9a, 0xb1, 0xa5, 0x70, 0x70, 0x06, 0x14, 0x7a, 0x7d, 0xfd, 0x35, 0x02, 0x0e, 0xfe, 0x4f, 0xfd, 0x51, 0x02, 0x35, 0xc8, 0xfe, 0x93, 0x05, 0x1d, 0x7d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x06, 0x07, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x21, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x03, 0x11, 0x23, 0x11, 0x21, 0x2d, 0x02, 0x4c, 0x02, 0x89, 0xea, 0xfd, 0xf8, 0x02, 0x23, 0xc6, 0xfe, 0x2d, 0xf5, 0xb6, 0xfe, 0x6a, 0x05, 0xd5, 0xfd, 0x1e, 0x02, 0xe2, 0xfd, 0xb2, 0xfc, 0x79, 0x03, 0x01, 0xfe, 0xe9, 0xfe, 0x16, 0x05, 0x2b, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x00, 0x04, 0xf5, 0x04, 0x60, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x21, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x07, 0x11, 0x23, 0x11, 0x21, 0x26, 0x01, 0xff, 0x01, 0xd3, 0xcc, 0xfe, 0x7e, 0x01, 0xb3, 0xb9, 0xfe, 0x9a, 0xb1, 0xa5, 0xfe, 0xa6, 0x04, 0x60, 0xfd, 0xf2, 0x02, 0x0e, 0xfe, 0x4f, 0xfd, 0x51, 0x02, 0x35, 0xc8, 0xfe, 0x93, 0x03, 0xc6, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x05, 0x6a, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x94, 0xb6, 0xb5, 0xb5, 0xb6, 0xfd, 0x6c, 0xb6, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfa, 0xd5, 0xfe, 0x15, 0x01, 0x41, 0x02, 0xc7, 0xfd, 0x39, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0xfe, 0xe5, 0x04, 0xba, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xae, 0xa5, 0x02, 0x1b, 0xa6, 0xa6, 0xa6, 0xa6, 0xfd, 0xe5, 0xa5, 0x04, 0x60, 0xfe, 0x33, 0x01, 0xcd, 0xfc, 0x39, 0xfe, 0x4c, 0x01, 0x1b, 0x02, 0x04, 0xfd, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x07, 0x44, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x94, 0x03, 0x44, 0xfd, 0x72, 0xb6, 0xfd, 0x6c, 0xb6, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xaa, 0xfa, 0xd5, 0x02, 0xc7, 0xfd, 0x39, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x06, 0x36, 0x04, 0x60, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xae, 0xa5, 0x02, 0x1b, 0x02, 0xc7, 0xfd, 0xdf, 0xa6, 0xfd, 0xe5, 0xa5, 0x04, 0x60, 0xfe, 0x33, 0x01, 0xcd, 0xaa, 0xfc, 0x4a, 0x02, 0x04, 0xfd, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x66, 0x07, 0x9c, 0x05, 0xd5, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x04, 0xb5, 0xb6, 0xfd, 0x6c, 0xb6, 0x04, 0x00, 0x01, 0x77, 0xa8, 0x66, 0x62, 0xb8, 0xcd, 0x45, 0x38, 0x79, 0x32, 0x32, 0x70, 0x6f, 0x02, 0xc7, 0xfd, 0x39, 0x05, 0x2b, 0xfa, 0xd5, 0x05, 0xd5, 0xfd, 0x9c, 0x77, 0x72, 0xee, 0xfe, 0xce, 0xfe, 0xf2, 0xf4, 0xaa, 0x4b, 0x4b, 0xc2, 0x01, 0x22, 0x9f, 0x9e, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0xfe, 0x56, 0x06, 0x6b, 0x04, 0x60, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x27, 0x26, 0x07, 0x04, 0x14, 0xa6, 0xfd, 0xe5, 0xa5, 0x03, 0x66, 0xe1, 0xed, 0x3f, 0x49, 0x49, 0x49, 0xa3, 0xae, 0x9b, 0x63, 0x1e, 0x22, 0x22, 0x2c, 0x79, 0x01, 0xe7, 0xfe, 0x19, 0x03, 0xc6, 0xfc, 0x3a, 0x04, 0x60, 0xfe, 0x17, 0x47, 0x51, 0xe5, 0xfe, 0xf2, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x37, 0x93, 0x01, 0x08, 0xa4, 0x26, 0x2e, 0x05, 0x00, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x06, 0x45, 0x05, 0xf1, 0x00, 0x41, 0x00, 0x59, 0x00, 0x00, 0x25, 0x2e, 0x03, 0x35, 0x34, 0x3e, 0x04, 0x33, 0x32, 0x1e, 0x04, 0x15, 0x14, 0x0e, 0x02, 0x07, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2e, 0x02, 0x27, 0x0e, 0x01, 0x23, 0x22, 0x2e, 0x01, 0x02, 0x35, 0x34, 0x12, 0x3e, 0x01, 0x37, 0x15, 0x0e, 0x03, 0x15, 0x14, 0x1e, 0x02, 0x33, 0x32, 0x36, 0x37, 0x3e, 0x03, 0x35, 0x34, 0x2e, 0x04, 0x23, 0x22, 0x0e, 0x04, 0x15, 0x14, 0x1e, 0x02, 0x03, 0xc0, 0x33, 0x61, 0x4a, 0x2d, 0x11, 0x26, 0x3d, 0x57, 0x74, 0x4b, 0x46, 0x71, 0x57, 0x3f, 0x29, 0x13, 0x18, 0x38, 0x60, 0x49, 0x22, 0x5e, 0x35, 0x38, 0x5b, 0x2e, 0x2a, 0x6c, 0x37, 0x22, 0x49, 0x4c, 0x4f, 0x26, 0x3c, 0xaf, 0x6d, 0x99, 0xf1, 0xa9, 0x59, 0x51, 0x9b, 0xde, 0x8e, 0x68, 0x9a, 0x64, 0x33, 0x36, 0x6f, 0xab, 0x74, 0x4a, 0x73, 0x9f, 0x39, 0x4b, 0x2b, 0x12, 0x0a, 0x15, 0x20, 0x2b, 0x38, 0x22, 0x2c, 0x41, 0x2e, 0x1e, 0x10, 0x06, 0x24, 0x3b, 0x4c, 0xae, 0x31, 0x89, 0xaa, 0xc4, 0x6b, 0x42, 0x8a, 0x83, 0x74, 0x57, 0x32, 0x32, 0x54, 0x70, 0x7b, 0x7f, 0x3a, 0x53, 0xb4, 0xb2, 0xaa, 0x4a, 0x1a, 0x15, 0x13, 0x1a, 0xa8, 0x17, 0x12, 0x08, 0x14, 0x23, 0x1b, 0x26, 0x34, 0x74, 0xcf, 0x01, 0x1d, 0xa8, 0xa0, 0x01, 0x10, 0xcb, 0x7d, 0x0e, 0xa7, 0x16, 0x66, 0x9a, 0xcd, 0x7c, 0x7d, 0xde, 0xa7, 0x62, 0x19, 0x6d, 0x3a, 0x86, 0x8e, 0x91, 0x45, 0x2f, 0x66, 0x63, 0x59, 0x43, 0x28, 0x2b, 0x47, 0x5b, 0x60, 0x5f, 0x26, 0x62, 0xab, 0x8e, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0xec, 0x04, 0x7a, 0x00, 0x3f, 0x00, 0x50, 0x00, 0x00, 0x13, 0x34, 0x3e, 0x02, 0x37, 0x15, 0x0e, 0x03, 0x15, 0x14, 0x1e, 0x02, 0x33, 0x32, 0x36, 0x37, 0x2e, 0x03, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x02, 0x37, 0x15, 0x0e, 0x03, 0x23, 0x22, 0x26, 0x27, 0x0e, 0x03, 0x23, 0x22, 0x2e, 0x02, 0x05, 0x3e, 0x03, 0x35, 0x34, 0x2e, 0x02, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x66, 0x43, 0x81, 0xbc, 0x79, 0x54, 0x7c, 0x52, 0x29, 0x2d, 0x57, 0x7c, 0x4f, 0x23, 0x4e, 0x19, 0x21, 0x38, 0x2b, 0x18, 0x24, 0x48, 0x69, 0x45, 0x3b, 0x65, 0x48, 0x29, 0x53, 0x56, 0x20, 0x3d, 0x1b, 0x18, 0x29, 0x25, 0x25, 0x16, 0x0f, 0x22, 0x28, 0x33, 0x21, 0x31, 0x75, 0x3d, 0x1b, 0x3f, 0x41, 0x40, 0x1c, 0x7a, 0xbe, 0x83, 0x44, 0x03, 0x00, 0x1f, 0x28, 0x18, 0x0a, 0x14, 0x1e, 0x24, 0x10, 0x17, 0x28, 0x1e, 0x11, 0x02, 0x28, 0x83, 0xd8, 0x9c, 0x58, 0x03, 0x9b, 0x06, 0x46, 0x72, 0x98, 0x58, 0x62, 0xa0, 0x72, 0x3e, 0x0b, 0x11, 0x25, 0x67, 0x78, 0x82, 0x40, 0x5d, 0x9f, 0x73, 0x41, 0x39, 0x68, 0x92, 0x59, 0x9b, 0xf1, 0x5e, 0x13, 0x0a, 0x04, 0x0a, 0x13, 0x0f, 0x9d, 0x0a, 0x11, 0x0c, 0x07, 0x1c, 0x2c, 0x12, 0x1b, 0x12, 0x09, 0x54, 0x99, 0xd6, 0xb8, 0x26, 0x5e, 0x64, 0x63, 0x2b, 0x4b, 0x69, 0x42, 0x1f, 0x26, 0x48, 0x69, 0x43, 0xf7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0x75, 0x04, 0xa4, 0x05, 0xf0, 0x10, 0x27, 0x00, 0x7a, 0x01, 0x0f, 0x00, 0x00, 0x12, 0x06, 0x03, 0xb5, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x03, 0x84, 0x04, 0x7b, 0x10, 0x27, 0x00, 0x7a, 0x00, 0x81, 0x00, 0x00, 0x12, 0x06, 0x03, 0xd5, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0xfe, 0xbf, 0x04, 0x6c, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x02, 0x8e, 0xb5, 0xb5, 0xb6, 0xfe, 0x23, 0x04, 0x70, 0xfe, 0x23, 0xaa, 0xfe, 0x15, 0x01, 0x41, 0x05, 0x2b, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0xfe, 0xe5, 0x03, 0xfc, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x02, 0x6a, 0xa6, 0xa6, 0xa3, 0xfe, 0x6f, 0x03, 0xc6, 0xfe, 0x6e, 0x99, 0xfe, 0x4c, 0x01, 0x1b, 0x03, 0xb6, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x04, 0x60, 0x00, 0x08, 0x00, 0x00, 0x25, 0x11, 0x23, 0x11, 0x01, 0x33, 0x09, 0x01, 0x33, 0x02, 0x7e, 0xaf, 0xfe, 0x68, 0xaf, 0x01, 0x3b, 0x01, 0x3b, 0xb0, 0x12, 0xfe, 0x44, 0x01, 0xbc, 0x04, 0x4e, 0xfc, 0x94, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x05, 0xd5, 0x00, 0x10, 0x00, 0x00, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x15, 0x33, 0x03, 0x7c, 0xee, 0xb6, 0xed, 0xed, 0xfe, 0x24, 0xc4, 0x01, 0x74, 0x01, 0x72, 0xc4, 0xfe, 0x24, 0xee, 0x01, 0x73, 0xfe, 0x8d, 0x01, 0x73, 0xaa, 0xaa, 0x03, 0x0e, 0xfd, 0x9a, 0x02, 0x66, 0xfc, 0xf2, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x04, 0x60, 0x00, 0x10, 0x00, 0x00, 0x09, 0x01, 0x15, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x01, 0x33, 0x09, 0x01, 0x04, 0x0c, 0xfe, 0x72, 0xec, 0xec, 0xaf, 0xf6, 0xf6, 0xfe, 0x68, 0xaf, 0x01, 0x3b, 0x01, 0x3b, 0x04, 0x60, 0xfb, 0xb2, 0x58, 0xaa, 0xba, 0xba, 0xaa, 0x58, 0x04, 0x4e, 0xfc, 0x94, 0x03, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x36, 0xfe, 0xbf, 0x04, 0xb6, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x25, 0x33, 0x11, 0x23, 0x11, 0x23, 0x09, 0x01, 0x23, 0x09, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x04, 0x50, 0x65, 0xb1, 0x12, 0xfe, 0x86, 0xfe, 0x83, 0xc4, 0x01, 0xe0, 0xfe, 0x5d, 0xc3, 0x01, 0x4e, 0x01, 0x50, 0xc3, 0xfe, 0x50, 0xaa, 0xfe, 0x15, 0x01, 0x41, 0x02, 0x7b, 0xfd, 0x85, 0x03, 0x1d, 0x02, 0xb8, 0xfd, 0xd5, 0x02, 0x2b, 0xfd, 0x33, 0x00, 0x00, 0x01, 0x00, 0x35, 0xfe, 0xe5, 0x04, 0x07, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x00, 0x25, 0x33, 0x11, 0x23, 0x11, 0x23, 0x09, 0x01, 0x23, 0x09, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x03, 0xa1, 0x65, 0xa5, 0x1e, 0xfe, 0xdb, 0xfe, 0xda, 0xc3, 0x01, 0x88, 0xfe, 0x99, 0xc4, 0x01, 0x0b, 0x01, 0x0b, 0xc4, 0xfe, 0x93, 0x99, 0xfe, 0x4c, 0x01, 0x1b, 0x01, 0xb8, 0xfe, 0x48, 0x02, 0x4a, 0x02, 0x16, 0xfe, 0x71, 0x01, 0x8f, 0xfd, 0xdf, 0x00, 0x00, 0x01, 0xff, 0xfa, 0xfe, 0xbf, 0x06, 0x8d, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x25, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x02, 0x8d, 0x02, 0x95, 0xb6, 0xb5, 0xb5, 0xfc, 0x00, 0xfe, 0x23, 0x04, 0x70, 0xfe, 0x23, 0xaa, 0x05, 0x2b, 0xfa, 0xd5, 0xfe, 0x15, 0x01, 0x41, 0x05, 0x2b, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0xfe, 0xe5, 0x05, 0xa2, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x00, 0x25, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x02, 0x39, 0x02, 0x1e, 0xa5, 0xa6, 0xa6, 0xfc, 0x9a, 0xfe, 0x6e, 0x03, 0xc6, 0xfe, 0x6f, 0x99, 0x03, 0xc7, 0xfc, 0x39, 0xfe, 0x4c, 0x01, 0x1b, 0x03, 0xb6, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0xfe, 0xbf, 0x04, 0xf0, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x00, 0x25, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x22, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x21, 0x11, 0x33, 0x04, 0x3b, 0xb5, 0xb5, 0xb7, 0xfe, 0x89, 0xa8, 0x65, 0x62, 0xb4, 0x70, 0x70, 0x01, 0x52, 0xb7, 0xaa, 0xfe, 0x15, 0x01, 0x41, 0x02, 0xc7, 0x77, 0x72, 0xee, 0x01, 0x37, 0xfe, 0xd9, 0x9f, 0x9e, 0x02, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x87, 0xfe, 0xe5, 0x04, 0x40, 0x04, 0x60, 0x00, 0x15, 0x00, 0x00, 0x25, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x21, 0x11, 0x33, 0x03, 0x9a, 0xa5, 0xa5, 0xa6, 0xfe, 0xcb, 0x89, 0x5c, 0x53, 0xa6, 0x2e, 0x30, 0x5e, 0x01, 0x0b, 0xa6, 0x99, 0xfe, 0x4c, 0x01, 0x1b, 0x02, 0x09, 0x5f, 0x56, 0xb8, 0xea, 0xd3, 0x75, 0x3b, 0x3b, 0x01, 0xbe, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x04, 0x3b, 0x05, 0xd5, 0x00, 0x18, 0x00, 0x00, 0x01, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x02, 0x42, 0x35, 0xa8, 0x65, 0x62, 0xb4, 0x70, 0x70, 0x10, 0x81, 0xc1, 0xb7, 0xb7, 0xc1, 0x81, 0x02, 0xc7, 0x77, 0x72, 0xee, 0x01, 0x37, 0xfe, 0xd9, 0x9f, 0x9e, 0x01, 0x39, 0xfe, 0xc7, 0x02, 0x64, 0xfa, 0x2b, 0x02, 0xc7, 0xfe, 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x87, 0x00, 0x00, 0x03, 0x9a, 0x04, 0x60, 0x00, 0x18, 0x00, 0x00, 0x01, 0x35, 0x33, 0x15, 0x33, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x15, 0x23, 0x35, 0x23, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x01, 0xc6, 0x90, 0x9e, 0xa6, 0xa6, 0x9e, 0x90, 0x07, 0x89, 0x5c, 0x53, 0xa6, 0x2e, 0x27, 0x02, 0xa4, 0xc2, 0xc4, 0x01, 0xbe, 0xfb, 0xa0, 0x02, 0x09, 0xc4, 0xc4, 0x5f, 0x56, 0xb8, 0xea, 0xd3, 0x75, 0x3b, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x04, 0x3b, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x21, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x23, 0x11, 0x01, 0x54, 0x01, 0x78, 0xa7, 0xc8, 0xb5, 0x70, 0x6f, 0xfe, 0xad, 0xb6, 0x05, 0xd5, 0xfd, 0x9c, 0xe9, 0xee, 0xfe, 0x66, 0x01, 0x8a, 0x9f, 0x9e, 0xfd, 0x39, 0x05, 0xd5, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x14, 0x12, 0x06, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0xff, 0xe3, 0x06, 0x5f, 0x05, 0xf0, 0x00, 0x22, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x12, 0x37, 0x36, 0x21, 0x20, 0x17, 0x16, 0x13, 0x21, 0x10, 0x12, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x20, 0x27, 0x26, 0x03, 0x06, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x25, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x01, 0x87, 0x1e, 0x87, 0xa9, 0x01, 0x1b, 0x01, 0x23, 0xa3, 0xa8, 0x01, 0xfb, 0xe5, 0xf6, 0xf7, 0x7d, 0xe3, 0x65, 0x64, 0x76, 0x77, 0x83, 0xfe, 0xc4, 0xb1, 0xa9, 0x09, 0x99, 0x6a, 0x6e, 0x99, 0x43, 0x3c, 0x01, 0x20, 0x03, 0x4f, 0x16, 0x58, 0x75, 0xfe, 0x74, 0x73, 0x57, 0x03, 0x6d, 0x01, 0x0a, 0xa7, 0xd2, 0xd2, 0xdb, 0xfe, 0x84, 0xfe, 0xf4, 0xfe, 0xce, 0x60, 0x5f, 0xd7, 0x46, 0x24, 0x24, 0xcd, 0xc2, 0x01, 0x55, 0x01, 0x67, 0x6b, 0xdf, 0x4c, 0x3e, 0xa0, 0x41, 0x39, 0x02, 0xbf, 0x7c, 0xa4, 0xa4, 0x7c, 0x00, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xe3, 0x04, 0xdc, 0x04, 0x7b, 0x00, 0x25, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x01, 0x36, 0x82, 0x50, 0x56, 0x8c, 0x2b, 0x33, 0x43, 0x17, 0x69, 0x83, 0xe6, 0xcb, 0x76, 0x77, 0xfd, 0x06, 0x0b, 0x5c, 0x5d, 0xa4, 0x60, 0x5a, 0x59, 0x58, 0x5d, 0x5a, 0x63, 0x5b, 0xf2, 0x8c, 0x85, 0x02, 0xf9, 0x02, 0x49, 0x4b, 0x7a, 0x8b, 0x54, 0x53, 0x0c, 0x02, 0x04, 0x52, 0x5a, 0xac, 0x46, 0x31, 0x97, 0x21, 0x26, 0xc5, 0x82, 0xa1, 0x91, 0x92, 0xfa, 0x5a, 0xbe, 0x64, 0x63, 0x1a, 0x1a, 0x34, 0xae, 0x2c, 0x14, 0x16, 0x9c, 0x94, 0x01, 0x81, 0x97, 0x5a, 0x5a, 0x57, 0x57, 0x9e, 0x00, 0x00, 0x02, 0x00, 0x12, 0xfe, 0x87, 0x06, 0x5f, 0x05, 0xf0, 0x00, 0x07, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x07, 0x12, 0x37, 0x36, 0x21, 0x20, 0x17, 0x16, 0x13, 0x21, 0x10, 0x12, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x07, 0x11, 0x23, 0x11, 0x26, 0x27, 0x26, 0x03, 0x06, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x02, 0x4a, 0x03, 0x4f, 0x16, 0x58, 0x75, 0xfe, 0x74, 0x73, 0x57, 0xd9, 0x1e, 0x87, 0xa9, 0x01, 0x1b, 0x01, 0x23, 0xa3, 0xa8, 0x01, 0xfb, 0xe5, 0xf6, 0xf7, 0x7d, 0xe3, 0x65, 0x64, 0x76, 0x62, 0x6c, 0xa0, 0xe9, 0x90, 0xa9, 0x09, 0x99, 0x6a, 0x6e, 0x99, 0x43, 0x3c, 0x03, 0x6d, 0xbf, 0x7c, 0xa4, 0xa4, 0x7c, 0xbf, 0x01, 0x0a, 0xa7, 0xd2, 0xd2, 0xdb, 0xfe, 0x84, 0xfe, 0xf4, 0xfe, 0xce, 0x60, 0x5f, 0xd7, 0x46, 0x24, 0x1e, 0x05, 0xfe, 0xa3, 0x01, 0x63, 0x20, 0xa6, 0xc3, 0x01, 0x54, 0x01, 0x67, 0x6b, 0xdf, 0x4c, 0x3e, 0xa0, 0x41, 0x39, 0x00, 0x00, 0x02, 0x00, 0x0d, 0xfe, 0xb7, 0x04, 0xdc, 0x04, 0x7b, 0x00, 0x08, 0x00, 0x31, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x0f, 0x01, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x07, 0x11, 0x23, 0x11, 0x26, 0x27, 0x26, 0x04, 0x36, 0x02, 0x49, 0x4b, 0x7a, 0x8b, 0x54, 0x53, 0x0c, 0xb2, 0x82, 0x50, 0x56, 0x8c, 0x2b, 0x33, 0x43, 0x17, 0x69, 0x83, 0xe6, 0xcb, 0x76, 0x77, 0xfd, 0x06, 0x0b, 0x5c, 0x5d, 0xa4, 0x60, 0x5a, 0x59, 0x58, 0x5d, 0x5a, 0x47, 0x42, 0x96, 0xae, 0x6f, 0x85, 0x02, 0x94, 0x97, 0x5a, 0x5a, 0x57, 0x57, 0x9e, 0x8f, 0x52, 0x5a, 0xac, 0x46, 0x31, 0x97, 0x21, 0x26, 0xc5, 0x82, 0xa1, 0x91, 0x92, 0xfa, 0x5a, 0xbe, 0x64, 0x63, 0x1a, 0x1a, 0x34, 0xae, 0x2c, 0x14, 0x10, 0x04, 0xfe, 0xd2, 0x01, 0x33, 0x1a, 0x7b, 0x94, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x6b, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x2c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x07, 0x9e, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf2, 0x05, 0xb8, 0x01, 0x75, 0x12, 0x06, 0x03, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3f, 0x00, 0x00, 0x06, 0x3e, 0x06, 0x48, 0x10, 0x27, 0x02, 0x9a, 0x01, 0x7e, 0x00, 0x00, 0x12, 0x06, 0x03, 0xca, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x66, 0x04, 0xb0, 0x05, 0xd5, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x33, 0x02, 0x65, 0x7d, 0xa7, 0x66, 0x62, 0xb7, 0xce, 0x44, 0x38, 0x78, 0x33, 0x31, 0x6f, 0x70, 0xfe, 0xae, 0xb6, 0xb6, 0x02, 0x5b, 0xea, 0x03, 0x71, 0x77, 0x72, 0xee, 0xfe, 0xce, 0xfe, 0xf2, 0xf4, 0xaa, 0x4b, 0x4b, 0xc2, 0x01, 0x22, 0x9f, 0x9e, 0xfd, 0x39, 0x05, 0xd5, 0xfd, 0x89, 0x02, 0x77, 0x00, 0x00, 0x01, 0x00, 0xab, 0xfe, 0x56, 0x04, 0x14, 0x04, 0x60, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x33, 0x02, 0x21, 0x12, 0xeb, 0x41, 0x4a, 0x4a, 0x49, 0xa3, 0xad, 0x9a, 0x63, 0x1e, 0x22, 0x22, 0x27, 0x7e, 0xea, 0xa6, 0xa6, 0x01, 0xee, 0xd4, 0x02, 0x77, 0x47, 0x51, 0xe5, 0xfe, 0xf2, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x37, 0x93, 0x01, 0x08, 0xa6, 0x24, 0x29, 0xfe, 0x19, 0x04, 0x60, 0xfe, 0x1d, 0x01, 0xe3, 0x00, 0x00, 0x01, 0x00, 0x30, 0xfe, 0x56, 0x05, 0x6a, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x00, 0x21, 0x23, 0x11, 0x21, 0x15, 0x10, 0x03, 0x06, 0x05, 0x35, 0x36, 0x37, 0x12, 0x19, 0x01, 0x21, 0x11, 0x33, 0x15, 0x01, 0x23, 0x04, 0xb4, 0xb6, 0xfe, 0x4c, 0x77, 0x58, 0xfe, 0xb6, 0xbe, 0x3d, 0x69, 0x03, 0x1f, 0xb5, 0xfe, 0xb7, 0x79, 0x05, 0x2b, 0xd4, 0xfe, 0x18, 0xfe, 0xaa, 0xfd, 0x38, 0xa7, 0x2e, 0xa8, 0x01, 0x25, 0x02, 0x35, 0x01, 0x1a, 0xfa, 0xd5, 0xaa, 0xfe, 0x56, 0x00, 0x01, 0x00, 0x29, 0xfe, 0x56, 0x04, 0xa7, 0x04, 0x60, 0x00, 0x14, 0x00, 0x00, 0x25, 0x33, 0x15, 0x01, 0x23, 0x13, 0x23, 0x11, 0x21, 0x15, 0x10, 0x03, 0x06, 0x05, 0x35, 0x36, 0x37, 0x36, 0x11, 0x35, 0x21, 0x04, 0x01, 0xa6, 0xfe, 0xfb, 0x6f, 0xce, 0xa5, 0xfe, 0xa1, 0x6a, 0x54, 0xfe, 0xea, 0xa1, 0x36, 0x58, 0x02, 0xa9, 0x99, 0x99, 0xfe, 0x56, 0x01, 0xaa, 0x03, 0xc7, 0x86, 0xfe, 0x92, 0xfe, 0xfc, 0xcf, 0x1d, 0x99, 0x1b, 0x7f, 0xcf, 0x01, 0xa7, 0xd4, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x66, 0x04, 0xb6, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x03, 0xff, 0xfd, 0x6c, 0xb6, 0xb6, 0x02, 0x94, 0xb6, 0xb9, 0xcd, 0x44, 0x38, 0x78, 0x33, 0x31, 0x68, 0x02, 0x5f, 0xfd, 0x39, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfa, 0x93, 0xfe, 0xf2, 0xf4, 0xaa, 0x4b, 0x4b, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0xfe, 0x56, 0x04, 0x14, 0x04, 0x60, 0x00, 0x15, 0x00, 0x00, 0x05, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x03, 0x6e, 0xfd, 0xe5, 0xa5, 0xa5, 0x02, 0x1b, 0xa6, 0x4a, 0x49, 0xa3, 0xad, 0x9b, 0x62, 0x1e, 0x22, 0x14, 0x02, 0x18, 0xfd, 0xfc, 0x04, 0x60, 0xfe, 0x33, 0x01, 0xcd, 0xfb, 0x8c, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x37, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x05, 0x6a, 0x05, 0xd5, 0x00, 0x10, 0x00, 0x00, 0x21, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x15, 0x01, 0x23, 0x04, 0xb5, 0xb6, 0xfd, 0x6c, 0xb6, 0xb6, 0x02, 0x94, 0xb6, 0xb5, 0xfe, 0xb7, 0x79, 0x02, 0xc7, 0xfd, 0x39, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfa, 0xd5, 0xaa, 0xfe, 0x56, 0x00, 0x01, 0x00, 0xad, 0xfe, 0x56, 0x04, 0xba, 0x04, 0x60, 0x00, 0x10, 0x00, 0x00, 0x21, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x15, 0x01, 0x23, 0x04, 0x14, 0xa6, 0xfd, 0xe5, 0xa5, 0xa5, 0x02, 0x1b, 0xa6, 0xa6, 0xfe, 0xfb, 0x6f, 0x02, 0x04, 0xfd, 0xfc, 0x04, 0x60, 0xfe, 0x33, 0x01, 0xcd, 0xfc, 0x39, 0x99, 0xfe, 0x56, 0x00, 0x01, 0x00, 0x9d, 0xfe, 0xbf, 0x04, 0x3b, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x00, 0x25, 0x11, 0x21, 0x22, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x03, 0x84, 0xfe, 0x89, 0xa8, 0x65, 0x62, 0xb4, 0x70, 0x70, 0x01, 0x52, 0xb7, 0xb7, 0xb5, 0xaa, 0x02, 0x1d, 0x77, 0x72, 0xee, 0x01, 0x37, 0xfe, 0xd9, 0x9f, 0x9e, 0x02, 0x64, 0xfa, 0x2b, 0xfe, 0xbf, 0x01, 0xeb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x87, 0xfe, 0xe5, 0x03, 0x9a, 0x04, 0x60, 0x00, 0x15, 0x00, 0x00, 0x25, 0x11, 0x21, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x02, 0xf4, 0xfe, 0xcb, 0x89, 0x5c, 0x53, 0xa6, 0x2e, 0x30, 0x5e, 0x01, 0x0b, 0xa6, 0xa6, 0xa6, 0x99, 0x01, 0x70, 0x5f, 0x56, 0xb8, 0xea, 0xd3, 0x75, 0x3b, 0x3b, 0x01, 0xbe, 0xfb, 0xa0, 0xfe, 0xe5, 0x01, 0xb4, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x06, 0x38, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x25, 0x33, 0x15, 0x01, 0x23, 0x01, 0x23, 0x11, 0x01, 0x23, 0x01, 0x11, 0x23, 0x11, 0x21, 0x09, 0x01, 0x21, 0x05, 0x82, 0xb5, 0xfe, 0xb7, 0x79, 0x01, 0x0d, 0xb1, 0xfe, 0xa5, 0xb6, 0xfe, 0xa5, 0xb0, 0x01, 0x0f, 0x01, 0x57, 0x01, 0x58, 0x01, 0x0f, 0xaa, 0xaa, 0xfe, 0x56, 0x01, 0xaa, 0x05, 0x1f, 0xfc, 0x00, 0x04, 0x00, 0xfa, 0xe1, 0x05, 0xd5, 0xfc, 0x08, 0x03, 0xf8, 0x00, 0x00, 0x01, 0x00, 0xad, 0xfe, 0x56, 0x05, 0x67, 0x04, 0x60, 0x00, 0x11, 0x00, 0x00, 0x25, 0x33, 0x15, 0x01, 0x23, 0x13, 0x23, 0x11, 0x01, 0x23, 0x01, 0x11, 0x23, 0x11, 0x33, 0x09, 0x01, 0x33, 0x04, 0xc1, 0xa5, 0xfe, 0xfb, 0x6e, 0xce, 0xa0, 0xfe, 0xe9, 0xa5, 0xfe, 0xe9, 0xa0, 0xec, 0x01, 0x1e, 0x01, 0x1f, 0xea, 0x99, 0x99, 0xfe, 0x56, 0x01, 0xaa, 0x03, 0xb0, 0xfd, 0x27, 0x02, 0xd9, 0xfc, 0x50, 0x04, 0x60, 0xfd, 0x12, 0x02, 0xee, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x01, 0x54, 0x06, 0x14, 0x12, 0x06, 0x00, 0x4f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x92, 0x10, 0x27, 0x02, 0x9a, 0x00, 0xb9, 0x01, 0x4a, 0x13, 0x06, 0x03, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x1f, 0x10, 0x26, 0x02, 0x9a, 0x47, 0xd7, 0x13, 0x06, 0x03, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x4e, 0x12, 0x26, 0x03, 0xa4, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x04, 0x43, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x10, 0x12, 0x26, 0x03, 0xc4, 0x00, 0x00, 0x11, 0x06, 0x00, 0x6a, 0x4a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x00, 0x06, 0x8e, 0x05, 0xd5, 0x12, 0x06, 0x00, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x06, 0xb1, 0x04, 0x7b, 0x12, 0x06, 0x00, 0xa8, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf2, 0x04, 0x2a, 0x01, 0x75, 0x13, 0x06, 0x03, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x48, 0x10, 0x27, 0x02, 0x9a, 0x00, 0x87, 0x00, 0x00, 0x13, 0x06, 0x03, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x12, 0x06, 0x01, 0x51, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x04, 0x7b, 0x12, 0x06, 0x02, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x04, 0x9d, 0x01, 0x75, 0x12, 0x06, 0x04, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x10, 0x10, 0x26, 0x00, 0x6a, 0x4c, 0x00, 0x12, 0x06, 0x04, 0x6d, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x07, 0x9e, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x05, 0xaf, 0x01, 0x75, 0x12, 0x06, 0x03, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3f, 0x00, 0x00, 0x06, 0x3e, 0x06, 0x10, 0x10, 0x27, 0x00, 0x6a, 0x01, 0x75, 0x00, 0x00, 0x12, 0x06, 0x03, 0xca, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x25, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x04, 0x13, 0x01, 0x75, 0x12, 0x06, 0x03, 0xab, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x06, 0x10, 0x10, 0x26, 0x00, 0x6a, 0x34, 0x00, 0x12, 0x06, 0x03, 0xcb, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x90, 0xff, 0xc1, 0x04, 0x79, 0x05, 0xd5, 0x12, 0x06, 0x01, 0x79, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0xfe, 0x4c, 0x03, 0xc4, 0x04, 0x60, 0x12, 0x06, 0x02, 0x54, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x00, 0xdc, 0x01, 0x3b, 0x12, 0x06, 0x03, 0xac, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x07, 0x05, 0xf5, 0x10, 0x27, 0x00, 0x71, 0x00, 0x83, 0xff, 0xff, 0x12, 0x06, 0x03, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x04, 0x76, 0x01, 0x75, 0x12, 0x06, 0x03, 0xac, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x07, 0x06, 0x10, 0x10, 0x27, 0x00, 0x6a, 0x00, 0x83, 0x00, 0x00, 0x12, 0x06, 0x03, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x4e, 0x12, 0x26, 0x03, 0xb2, 0x00, 0x00, 0x11, 0x07, 0x10, 0xeb, 0x04, 0xa3, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x10, 0x12, 0x26, 0x03, 0xd2, 0x00, 0x00, 0x11, 0x06, 0x00, 0x6a, 0x68, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x12, 0x06, 0x01, 0x61, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x12, 0x06, 0x02, 0x37, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0x4e, 0x12, 0x26, 0x04, 0x7c, 0x00, 0x00, 0x10, 0x07, 0x10, 0xeb, 0x04, 0xa3, 0x01, 0x75, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x10, 0x12, 0x26, 0x04, 0x7d, 0x00, 0x00, 0x10, 0x06, 0x00, 0x6a, 0x68, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x04, 0xa0, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x03, 0xf6, 0x01, 0x75, 0x12, 0x06, 0x03, 0xc1, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x06, 0x10, 0x10, 0x26, 0x00, 0x6a, 0xe5, 0x00, 0x12, 0x06, 0x03, 0xe1, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x44, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x00, 0x67, 0x01, 0x3b, 0x12, 0x06, 0x03, 0xb7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x05, 0xf5, 0x10, 0x26, 0x00, 0x71, 0x55, 0xff, 0x12, 0x06, 0x03, 0xd7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x44, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x04, 0x00, 0x01, 0x75, 0x12, 0x06, 0x03, 0xb7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x10, 0x10, 0x26, 0x00, 0x6a, 0x55, 0x00, 0x12, 0x06, 0x03, 0xd7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x44, 0x07, 0x6b, 0x10, 0x27, 0x10, 0xf4, 0x04, 0x00, 0x01, 0x75, 0x12, 0x06, 0x03, 0xb7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x66, 0x10, 0x26, 0x02, 0x9f, 0x55, 0x00, 0x12, 0x06, 0x03, 0xd7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9d, 0x00, 0x00, 0x04, 0x3b, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xeb, 0x04, 0x51, 0x01, 0x75, 0x12, 0x06, 0x03, 0xbb, 0x00, 0x00, 0xff, 0xff, 0x00, 0x87, 0x00, 0x00, 0x03, 0x9a, 0x06, 0x10, 0x10, 0x26, 0x00, 0x6a, 0x55, 0x00, 0x12, 0x06, 0x03, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x03, 0xf9, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0xb5, 0x03, 0x44, 0xfd, 0x72, 0xb5, 0xb5, 0x05, 0xd5, 0xaa, 0xfb, 0x7f, 0xfe, 0x15, 0x01, 0x41, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x03, 0x6f, 0x04, 0x60, 0x00, 0x09, 0x00, 0x00, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0xa7, 0x02, 0xc7, 0xfd, 0xdf, 0xa6, 0xa6, 0x04, 0x60, 0xaa, 0xfc, 0xe3, 0xfe, 0x4c, 0x01, 0x1b, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0xa6, 0x07, 0x4e, 0x12, 0x26, 0x03, 0xbf, 0x00, 0x00, 0x10, 0x07, 0x10, 0xeb, 0x05, 0x25, 0x01, 0x75, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x05, 0x0c, 0x06, 0x10, 0x12, 0x26, 0x03, 0xdf, 0x00, 0x00, 0x10, 0x07, 0x00, 0x6a, 0x00, 0xee, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3f, 0xfe, 0x56, 0x04, 0x71, 0x05, 0xd5, 0x00, 0x19, 0x00, 0x00, 0x21, 0x11, 0x23, 0x35, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x01, 0x2d, 0xed, 0xed, 0x03, 0x44, 0xfd, 0x71, 0x01, 0xed, 0xfe, 0x13, 0x01, 0x45, 0x40, 0x49, 0xac, 0xe5, 0xd2, 0x5e, 0x45, 0x02, 0x94, 0xaa, 0x02, 0x97, 0xaa, 0xfe, 0x13, 0xaa, 0xfd, 0xec, 0x94, 0xc8, 0x60, 0x6e, 0x9c, 0x61, 0xad, 0x00, 0x00, 0x01, 0x00, 0x32, 0xfe, 0x56, 0x03, 0xe7, 0x04, 0x60, 0x00, 0x19, 0x00, 0x00, 0x21, 0x11, 0x23, 0x35, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x01, 0x1f, 0xed, 0xed, 0x02, 0xc7, 0xfd, 0xdf, 0x01, 0x76, 0xfe, 0x8a, 0x01, 0x49, 0x3f, 0x4a, 0xad, 0xe4, 0xd2, 0x5f, 0x43, 0x01, 0xf4, 0xaa, 0x01, 0xc2, 0x9d, 0xfe, 0xdb, 0xaa, 0xfe, 0x8c, 0x94, 0xc8, 0x60, 0x6e, 0x9c, 0x61, 0xad, 0x00, 0x00, 0x01, 0x00, 0x36, 0xfe, 0x66, 0x04, 0xa6, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x00, 0x25, 0x16, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x09, 0x01, 0x23, 0x09, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x04, 0xa6, 0x01, 0x02, 0x0e, 0x4a, 0x5c, 0xcd, 0x45, 0x38, 0x7a, 0x31, 0x24, 0x0a, 0xfe, 0x88, 0xfe, 0x83, 0xc4, 0x01, 0xe0, 0xfe, 0x5d, 0xc3, 0x01, 0x4e, 0x01, 0x50, 0xc3, 0xfe, 0x50, 0x1a, 0x02, 0x18, 0xbe, 0x62, 0x7a, 0xaa, 0x4b, 0x35, 0x73, 0x02, 0x78, 0xfd, 0x85, 0x03, 0x1d, 0x02, 0xb8, 0xfd, 0xd5, 0x02, 0x2b, 0xfd, 0x33, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x35, 0xfe, 0x56, 0x03, 0xf4, 0x04, 0x60, 0x00, 0x17, 0x00, 0x00, 0x09, 0x02, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x32, 0x37, 0x3e, 0x01, 0x35, 0x09, 0x01, 0x23, 0x09, 0x01, 0x33, 0x09, 0x01, 0x03, 0xf4, 0xfe, 0x93, 0x01, 0x47, 0x18, 0x3c, 0x49, 0xb1, 0xad, 0xb0, 0x17, 0x47, 0x2f, 0xfe, 0xde, 0xfe, 0xda, 0xc3, 0x01, 0x88, 0xfe, 0x99, 0xc4, 0x01, 0x0b, 0x01, 0x0b, 0x04, 0x60, 0xfd, 0xdf, 0xfe, 0x17, 0x26, 0x39, 0xcd, 0x61, 0x73, 0x9c, 0x03, 0x0a, 0x6d, 0x98, 0x01, 0xb4, 0xfe, 0x48, 0x02, 0x4a, 0x02, 0x16, 0xfe, 0x71, 0x01, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x13, 0x33, 0x09, 0x01, 0x33, 0x01, 0x21, 0x15, 0x21, 0x01, 0x23, 0x09, 0x01, 0x23, 0x01, 0x21, 0x35, 0x21, 0x74, 0xc3, 0x01, 0x4e, 0x01, 0x50, 0xc3, 0xfe, 0x7a, 0x01, 0x4e, 0xfe, 0xb5, 0x01, 0xa0, 0xc3, 0xfe, 0x86, 0xfe, 0x83, 0xc4, 0x01, 0xa5, 0xfe, 0xb1, 0x01, 0x6e, 0x05, 0xd5, 0xfd, 0xd5, 0x02, 0x2b, 0xfd, 0x77, 0x90, 0xfd, 0x44, 0x02, 0x7b, 0xfd, 0x85, 0x02, 0xbc, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x35, 0x00, 0x00, 0x04, 0x07, 0x04, 0x60, 0x00, 0x11, 0x00, 0x00, 0x09, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x33, 0x15, 0x21, 0x01, 0x23, 0x09, 0x01, 0x23, 0x01, 0x21, 0x35, 0x01, 0x8b, 0xfe, 0xcb, 0xc4, 0x01, 0x0b, 0x01, 0x0b, 0xc4, 0xfe, 0xcc, 0xf2, 0xfe, 0xfd, 0x01, 0x57, 0xc3, 0xfe, 0xdb, 0xfe, 0xda, 0xc3, 0x01, 0x59, 0xfe, 0xfc, 0x02, 0x94, 0x01, 0xcc, 0xfe, 0x71, 0x01, 0x8f, 0xfe, 0x34, 0x90, 0xfd, 0xfc, 0x01, 0xb8, 0xfe, 0x48, 0x02, 0x04, 0x90, 0x00, 0x00, 0x02, 0x00, 0x82, 0x00, 0x00, 0x04, 0x3c, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x00, 0x01, 0x14, 0x17, 0x16, 0x33, 0x21, 0x11, 0x21, 0x22, 0x07, 0x06, 0x01, 0x11, 0x21, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x21, 0x11, 0x01, 0x42, 0x47, 0x47, 0x92, 0x01, 0x24, 0xfe, 0xdc, 0x92, 0x47, 0x47, 0x02, 0xfa, 0xfe, 0x1d, 0xe2, 0xf5, 0xf5, 0xe2, 0x01, 0x2d, 0x01, 0xb7, 0x8a, 0x43, 0x44, 0x02, 0x23, 0x43, 0x44, 0x03, 0x93, 0xfa, 0x2b, 0xda, 0xdd, 0xde, 0xda, 0x02, 0x66, 0x00, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x03, 0x90, 0x04, 0x60, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x00, 0x01, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x11, 0x23, 0x22, 0x07, 0x06, 0x01, 0x11, 0x21, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x3b, 0x01, 0x11, 0x01, 0x16, 0x38, 0x3b, 0x74, 0xed, 0xed, 0x73, 0x3c, 0x38, 0x02, 0x7a, 0xfe, 0x66, 0xc0, 0x68, 0x68, 0x68, 0x6d, 0xbb, 0xf4, 0x01, 0x4c, 0x5a, 0x2b, 0x2e, 0x01, 0x69, 0x2e, 0x2a, 0x02, 0xb6, 0xfb, 0xa0, 0x52, 0x52, 0x01, 0x50, 0x52, 0x55, 0x01, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x82, 0xff, 0xe3, 0x06, 0x8a, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x30, 0x00, 0x00, 0x01, 0x21, 0x22, 0x07, 0x06, 0x10, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x13, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x21, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x03, 0x86, 0xfe, 0xdc, 0x92, 0x47, 0x47, 0x47, 0x56, 0x74, 0xa2, 0x43, 0x4e, 0x1e, 0x0b, 0x0d, 0x2e, 0x5f, 0x55, 0x63, 0xd6, 0x74, 0x7b, 0xf5, 0xe2, 0x01, 0x2d, 0xb5, 0x38, 0x2f, 0x65, 0x5f, 0x35, 0x38, 0xb6, 0x63, 0x5e, 0xc1, 0xc3, 0x5c, 0x2c, 0x02, 0xc9, 0x43, 0x44, 0xfe, 0xea, 0x50, 0x5f, 0x6d, 0x7d, 0x9f, 0xfe, 0xdd, 0x1d, 0x1c, 0x60, 0x36, 0x31, 0x81, 0x89, 0xca, 0xde, 0xda, 0x02, 0x66, 0xfb, 0xec, 0x8f, 0x5b, 0x4a, 0x4a, 0x4f, 0x9b, 0x02, 0x9f, 0xfd, 0x5a, 0xe0, 0x7f, 0x78, 0x78, 0x39, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x05, 0xce, 0x04, 0x60, 0x00, 0x0d, 0x00, 0x30, 0x00, 0x00, 0x01, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x13, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x02, 0xea, 0xed, 0x73, 0x3c, 0x38, 0x3b, 0x39, 0x60, 0x85, 0x53, 0x28, 0x2c, 0x3c, 0x54, 0x54, 0x7b, 0x9b, 0x5b, 0x5b, 0x68, 0x6d, 0xbb, 0xf4, 0xa6, 0x38, 0x36, 0x5f, 0x5d, 0x36, 0x38, 0xa6, 0x5a, 0x5e, 0xb9, 0xbe, 0x5a, 0x1c, 0x02, 0x02, 0x2e, 0x2a, 0x5e, 0x5c, 0x3a, 0x39, 0x6d, 0x34, 0x9c, 0xfe, 0xf6, 0x6c, 0x30, 0x31, 0x61, 0x60, 0xa6, 0xaa, 0x52, 0x55, 0x01, 0xc5, 0xfd, 0x61, 0x9f, 0x50, 0x4f, 0x4f, 0x52, 0x9d, 0x01, 0x41, 0xfe, 0xb8, 0xec, 0x73, 0x78, 0x78, 0x25, 0x00, 0x01, 0x00, 0xb4, 0xff, 0xe3, 0x06, 0x50, 0x05, 0xf0, 0x00, 0x37, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x03, 0x4c, 0x53, 0x53, 0x95, 0x9c, 0xa3, 0x86, 0x48, 0x47, 0x49, 0x4a, 0x89, 0x4b, 0xaa, 0x67, 0x67, 0x5a, 0x5b, 0x50, 0xcf, 0x79, 0x79, 0x40, 0x40, 0x76, 0x82, 0x4a, 0x49, 0x39, 0x2f, 0x64, 0x5f, 0x35, 0x39, 0xb6, 0x64, 0x5d, 0xc2, 0xc3, 0x5c, 0x2b, 0x19, 0x1e, 0x01, 0xb2, 0x84, 0x4a, 0x4b, 0xa6, 0x3b, 0x3c, 0x70, 0x73, 0x3d, 0x3e, 0x24, 0x26, 0xb4, 0x20, 0x10, 0x10, 0x68, 0x69, 0xb2, 0x7c, 0x55, 0x56, 0x21, 0x1f, 0x62, 0x62, 0x90, 0x80, 0x5b, 0x4a, 0x4a, 0x4f, 0x9b, 0x02, 0x9f, 0xfd, 0x5a, 0xe0, 0x7f, 0x78, 0x78, 0x38, 0x50, 0x61, 0x00, 0x01, 0x00, 0x99, 0xff, 0xe3, 0x05, 0xa6, 0x04, 0x7c, 0x00, 0x35, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x02, 0xc4, 0x46, 0x41, 0x7b, 0x85, 0x8b, 0x69, 0x3c, 0x3d, 0x3f, 0x3e, 0x6b, 0x40, 0x49, 0x48, 0x57, 0x58, 0x99, 0x45, 0xb0, 0x66, 0x66, 0x36, 0x36, 0x65, 0x75, 0x39, 0x3e, 0x38, 0x37, 0x5e, 0x5e, 0x36, 0x38, 0xa5, 0x5a, 0x5d, 0xba, 0xb3, 0x65, 0x58, 0x01, 0x38, 0x66, 0x38, 0x33, 0x98, 0x2c, 0x2d, 0x46, 0x40, 0x2e, 0x2e, 0x0d, 0x0d, 0x1d, 0xa7, 0x18, 0x18, 0x4e, 0x4f, 0x8d, 0x5d, 0x40, 0x41, 0x18, 0x19, 0x48, 0x4f, 0x48, 0x58, 0x44, 0x45, 0x4f, 0x52, 0x9d, 0x01, 0x41, 0xfe, 0xb8, 0xec, 0x73, 0x78, 0x75, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x04, 0xb6, 0x05, 0xf0, 0x00, 0x29, 0x00, 0x00, 0x21, 0x23, 0x11, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x11, 0x33, 0x11, 0x23, 0x04, 0x01, 0xb5, 0x53, 0x53, 0x95, 0x9c, 0xa3, 0x86, 0x48, 0x47, 0x49, 0x4a, 0x89, 0x4b, 0xaa, 0x67, 0x67, 0x5a, 0x5b, 0x50, 0xcf, 0x79, 0x79, 0x40, 0x40, 0x76, 0x82, 0x4a, 0x49, 0xb5, 0xb5, 0x01, 0xb1, 0x85, 0x4a, 0x4b, 0xa6, 0x3b, 0x3c, 0x70, 0x73, 0x3d, 0x3e, 0x24, 0x26, 0xb4, 0x20, 0x10, 0x10, 0x68, 0x69, 0xb2, 0x7c, 0x55, 0x56, 0x21, 0x1f, 0x62, 0x61, 0x92, 0xfe, 0xf9, 0xfd, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x99, 0xfe, 0x56, 0x04, 0x10, 0x04, 0x7c, 0x00, 0x29, 0x00, 0x00, 0x25, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x03, 0x67, 0xa9, 0xa6, 0xa6, 0x46, 0x41, 0x7b, 0x85, 0x8b, 0x69, 0x3c, 0x3d, 0x3f, 0x3e, 0x6b, 0x40, 0x49, 0x48, 0x57, 0x58, 0x99, 0x45, 0xb0, 0x66, 0x66, 0x36, 0x36, 0x65, 0x72, 0x3c, 0x3e, 0x99, 0xfd, 0xbd, 0x01, 0xaa, 0x01, 0x46, 0x58, 0x38, 0x33, 0x98, 0x2c, 0x2d, 0x46, 0x40, 0x2e, 0x2e, 0x0d, 0x0d, 0x1d, 0xa7, 0x18, 0x18, 0x4e, 0x4f, 0x8d, 0x5d, 0x40, 0x41, 0x18, 0x18, 0x49, 0x4b, 0x6a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x30, 0xff, 0xe3, 0x07, 0x03, 0x05, 0xd5, 0x00, 0x21, 0x00, 0x00, 0x01, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x21, 0x15, 0x10, 0x03, 0x06, 0x05, 0x35, 0x36, 0x37, 0x12, 0x19, 0x01, 0x04, 0xb4, 0x39, 0x2f, 0x64, 0x5f, 0x35, 0x39, 0xb6, 0x63, 0x5e, 0xc2, 0xc0, 0x5f, 0x63, 0xfe, 0x4c, 0x77, 0x58, 0xfe, 0xb6, 0xbe, 0x3d, 0x69, 0x05, 0xd5, 0xfb, 0xec, 0x8f, 0x5b, 0x4a, 0x4a, 0x4f, 0x9b, 0x02, 0x9f, 0xfd, 0x5a, 0xe0, 0x7f, 0x78, 0x78, 0x7d, 0xe2, 0x03, 0x71, 0xd4, 0xfe, 0x18, 0xfe, 0xaa, 0xfd, 0x38, 0xa7, 0x2e, 0xa8, 0x01, 0x25, 0x02, 0x35, 0x01, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x29, 0xff, 0xe3, 0x06, 0x3d, 0x04, 0x60, 0x00, 0x20, 0x00, 0x00, 0x01, 0x11, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x21, 0x15, 0x10, 0x03, 0x06, 0x05, 0x35, 0x36, 0x37, 0x36, 0x11, 0x35, 0x04, 0x01, 0x6e, 0x5d, 0x5d, 0x36, 0x38, 0xa6, 0x5a, 0x5e, 0xb9, 0xb4, 0x64, 0x58, 0xfe, 0xa1, 0x6a, 0x54, 0xfe, 0xea, 0xa1, 0x36, 0x58, 0x04, 0x60, 0xfd, 0x04, 0x57, 0x8a, 0x4f, 0x52, 0x9d, 0x01, 0x41, 0xfe, 0xb8, 0xec, 0x73, 0x78, 0x75, 0x65, 0x7b, 0x02, 0x8f, 0x86, 0xfe, 0x92, 0xfe, 0xfc, 0xcf, 0x1d, 0x99, 0x1b, 0x7f, 0xcf, 0x01, 0xa7, 0xd4, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xff, 0xe3, 0x07, 0x5c, 0x05, 0xd5, 0x12, 0x06, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0xff, 0xe3, 0x06, 0x50, 0x04, 0x60, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x11, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x04, 0x14, 0x6e, 0x5c, 0x5e, 0x36, 0x38, 0xa6, 0x5a, 0x5e, 0xba, 0xb3, 0x64, 0x59, 0xfd, 0xe5, 0xa5, 0xa5, 0x02, 0x1b, 0x04, 0x60, 0xfd, 0x04, 0x57, 0x8a, 0x4f, 0x52, 0x9d, 0x01, 0x41, 0xfe, 0xb8, 0xec, 0x73, 0x78, 0x75, 0x65, 0x7b, 0xcc, 0xfd, 0xfc, 0x04, 0x60, 0xfe, 0x33, 0x01, 0xcd, 0x00, 0x00, 0x01, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfc, 0x05, 0xf0, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x20, 0x27, 0x26, 0x10, 0x37, 0x36, 0x21, 0x20, 0x17, 0x15, 0x26, 0x23, 0x20, 0x11, 0x10, 0x21, 0x32, 0x36, 0x35, 0x11, 0x33, 0x04, 0xfb, 0x5a, 0x28, 0x7b, 0x70, 0x88, 0xfe, 0xbf, 0xb1, 0xac, 0xab, 0xb2, 0x01, 0x41, 0x01, 0x0a, 0xca, 0xca, 0xfb, 0xfe, 0x12, 0x01, 0xee, 0xc2, 0x6f, 0xb5, 0x01, 0xba, 0xe0, 0x7f, 0x39, 0x21, 0x1e, 0xd2, 0xcc, 0x02, 0xd0, 0xcd, 0xd2, 0x8e, 0xd7, 0xbf, 0xfd, 0x9f, 0xfd, 0xa0, 0x94, 0xa4, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xd9, 0x04, 0x7b, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x07, 0x06, 0x10, 0x17, 0x16, 0x33, 0x32, 0x11, 0x35, 0x33, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x26, 0x66, 0x83, 0x87, 0xf0, 0xbc, 0xa7, 0xab, 0xb0, 0xaa, 0x59, 0x51, 0x51, 0x59, 0xaa, 0xcb, 0xa6, 0xb5, 0xce, 0xea, 0x86, 0x80, 0x02, 0x2f, 0x01, 0x0e, 0x9d, 0xa1, 0x6e, 0xaa, 0x7c, 0x7c, 0x72, 0xfe, 0x7c, 0x72, 0x7c, 0x01, 0x3e, 0xbe, 0xc5, 0xec, 0xe7, 0xa6, 0x9e, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0xff, 0xe3, 0x04, 0xdc, 0x05, 0xd5, 0x00, 0x19, 0x00, 0x00, 0x01, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x21, 0x35, 0x21, 0x15, 0x02, 0x8e, 0x39, 0x2f, 0x64, 0x5e, 0x35, 0x39, 0xb6, 0x63, 0x5e, 0xc1, 0xc1, 0x5e, 0x63, 0xfe, 0x23, 0x04, 0x70, 0x05, 0x2b, 0xfc, 0x96, 0x8f, 0x5b, 0x4a, 0x4a, 0x4f, 0x9b, 0x02, 0x9f, 0xfd, 0x5a, 0xe0, 0x7f, 0x78, 0x78, 0x7d, 0xe2, 0x03, 0x71, 0xaa, 0xaa, 0x00, 0x00, 0x01, 0x00, 0x04, 0xff, 0xe3, 0x04, 0x77, 0x04, 0x60, 0x00, 0x19, 0x00, 0x00, 0x01, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x21, 0x35, 0x21, 0x15, 0x02, 0x39, 0x38, 0x37, 0x5e, 0x5e, 0x36, 0x37, 0xa6, 0x5a, 0x5e, 0xb9, 0xb3, 0x65, 0x58, 0xfe, 0x6e, 0x03, 0xc6, 0x03, 0xb6, 0xfd, 0xae, 0x56, 0x46, 0x45, 0x4f, 0x52, 0x9d, 0x01, 0x41, 0xfe, 0xb8, 0xec, 0x73, 0x78, 0x75, 0x65, 0x7b, 0x02, 0x7e, 0xaa, 0xaa, 0x00, 0xff, 0xff, 0x00, 0x93, 0xff, 0xe3, 0x04, 0x09, 0x05, 0xf0, 0x12, 0x06, 0x01, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x04, 0x7c, 0x12, 0x06, 0x03, 0x49, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4b, 0xfe, 0x66, 0x04, 0xb5, 0x05, 0xd5, 0x00, 0x18, 0x00, 0x00, 0x33, 0x35, 0x36, 0x37, 0x36, 0x11, 0x35, 0x21, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x21, 0x15, 0x10, 0x03, 0x06, 0x4c, 0xc7, 0x34, 0x4e, 0x03, 0x1f, 0xb8, 0xcd, 0x45, 0x39, 0x78, 0x32, 0x31, 0xfe, 0x4c, 0x5c, 0x58, 0xaa, 0x30, 0xa3, 0xf6, 0x02, 0x64, 0xfe, 0xfa, 0x93, 0xfe, 0xf2, 0xf4, 0xaa, 0x4b, 0x4c, 0xc1, 0x04, 0xc3, 0xb8, 0xfd, 0xca, 0xfe, 0xf8, 0xfd, 0x00, 0x01, 0x00, 0x44, 0xfe, 0x56, 0x04, 0x02, 0x04, 0x60, 0x00, 0x18, 0x00, 0x00, 0x33, 0x35, 0x36, 0x37, 0x36, 0x11, 0x35, 0x21, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x21, 0x15, 0x10, 0x07, 0x06, 0x44, 0xa8, 0x2f, 0x3d, 0x02, 0xa9, 0x93, 0xa2, 0x40, 0x2d, 0x57, 0x29, 0x23, 0xfe, 0xa1, 0x4f, 0x54, 0x99, 0x1d, 0x7d, 0xa6, 0x01, 0xd0, 0xb7, 0xfb, 0x8c, 0xd6, 0xc0, 0x9c, 0x30, 0x29, 0xa1, 0x03, 0xe1, 0x6f, 0xfe, 0x50, 0xc2, 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4b, 0x00, 0x00, 0x08, 0x33, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x00, 0x33, 0x35, 0x36, 0x37, 0x12, 0x11, 0x35, 0x21, 0x09, 0x01, 0x33, 0x09, 0x01, 0x23, 0x09, 0x01, 0x23, 0x09, 0x01, 0x21, 0x15, 0x10, 0x03, 0x06, 0x4c, 0xc3, 0x38, 0x4e, 0x03, 0x20, 0x01, 0x4e, 0x01, 0x50, 0xc3, 0xfe, 0x50, 0x01, 0xcd, 0xc3, 0xfe, 0x86, 0xfe, 0x83, 0xc4, 0x01, 0xdf, 0xfe, 0xc4, 0xfd, 0xf2, 0x5c, 0x58, 0xaa, 0x2f, 0xa4, 0x01, 0x02, 0x02, 0x58, 0xfe, 0xfd, 0xd5, 0x02, 0x2b, 0xfd, 0x33, 0xfc, 0xf8, 0x02, 0x7b, 0xfd, 0x85, 0x03, 0x1d, 0x02, 0x0e, 0xb8, 0xfd, 0xca, 0xfe, 0xf8, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x00, 0x06, 0xed, 0x04, 0x60, 0x00, 0x18, 0x00, 0x00, 0x09, 0x02, 0x23, 0x09, 0x01, 0x23, 0x09, 0x01, 0x21, 0x15, 0x10, 0x07, 0x06, 0x05, 0x35, 0x36, 0x37, 0x36, 0x11, 0x35, 0x21, 0x17, 0x09, 0x01, 0x06, 0xda, 0xfe, 0x94, 0x01, 0x7f, 0xc3, 0xfe, 0xda, 0xfe, 0xdb, 0xc3, 0x01, 0x87, 0xfe, 0xfc, 0xfe, 0x5e, 0x4f, 0x54, 0xfe, 0xea, 0xa4, 0x33, 0x3d, 0x02, 0xa9, 0x01, 0x01, 0x0a, 0x01, 0x0b, 0x04, 0x60, 0xfd, 0xdf, 0xfd, 0xc1, 0x01, 0xb8, 0xfe, 0x48, 0x02, 0x4a, 0x01, 0x83, 0x6f, 0xfe, 0x50, 0xc2, 0xcf, 0x1d, 0x99, 0x1c, 0x7e, 0xb1, 0x01, 0xc5, 0xb7, 0x03, 0xfe, 0x74, 0x01, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x06, 0x38, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x07, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x6b, 0xe4, 0x7f, 0x8b, 0x8b, 0x7f, 0x01, 0x6d, 0x73, 0xfa, 0xe4, 0xb6, 0x01, 0x9a, 0xe2, 0xe7, 0x05, 0x01, 0x44, 0xc3, 0xfe, 0x50, 0x01, 0xcd, 0xc3, 0x05, 0x2f, 0xfd, 0xcf, 0x92, 0x87, 0x86, 0x92, 0xfd, 0xb3, 0x8a, 0xfd, 0xa8, 0x05, 0xd5, 0xe3, 0xdb, 0x30, 0x2a, 0x02, 0x18, 0xfd, 0x33, 0xfc, 0xf8, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x56, 0x05, 0xfe, 0x04, 0x7b, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x09, 0x02, 0x23, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x01, 0x00, 0x10, 0x26, 0x20, 0x06, 0x10, 0x16, 0x20, 0x05, 0xeb, 0xfe, 0x93, 0x01, 0x80, 0xc4, 0xfe, 0xea, 0x17, 0x53, 0x72, 0xb8, 0x6f, 0x9f, 0x34, 0xa7, 0xa7, 0x34, 0x9f, 0x6f, 0xb8, 0x72, 0x4c, 0x1a, 0x01, 0x07, 0xfe, 0x5a, 0x96, 0xfe, 0xf9, 0x96, 0x96, 0x01, 0x07, 0x04, 0x60, 0xfd, 0xdf, 0xfd, 0xc1, 0x01, 0xa1, 0xa8, 0x74, 0xa2, 0x61, 0x64, 0xfd, 0xae, 0x06, 0x0a, 0xaa, 0x64, 0x61, 0xa2, 0x6b, 0x97, 0x01, 0x89, 0xfd, 0x04, 0x01, 0x96, 0xe7, 0xe7, 0xfe, 0x6a, 0xe7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x00, 0x06, 0xf6, 0x05, 0xd5, 0x00, 0x15, 0x00, 0x1d, 0x00, 0x00, 0x33, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x01, 0x12, 0x10, 0x16, 0x33, 0x21, 0x11, 0x21, 0x22, 0x7a, 0x01, 0x70, 0x5a, 0xe7, 0xea, 0xe8, 0x04, 0x6b, 0xfd, 0x66, 0x02, 0x7e, 0xfd, 0x82, 0x02, 0xaa, 0xfc, 0x9e, 0xf1, 0xfe, 0x9d, 0x32, 0x86, 0x83, 0x01, 0x19, 0xfe, 0xe7, 0x83, 0x02, 0x8d, 0x1a, 0xa9, 0xd7, 0xce, 0xe0, 0xaa, 0xfe, 0x46, 0xaa, 0xfd, 0xe3, 0xaa, 0x02, 0x77, 0xfd, 0x89, 0x04, 0xaa, 0xfe, 0xfa, 0x87, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x68, 0xff, 0xe3, 0x06, 0xb8, 0x04, 0x7b, 0x00, 0x1f, 0x00, 0x26, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x15, 0x21, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x23, 0x01, 0x23, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x21, 0x36, 0x33, 0x32, 0x12, 0x07, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x25, 0x14, 0x16, 0x3b, 0x01, 0x11, 0x23, 0x22, 0x06, 0x06, 0xb8, 0xfd, 0x06, 0x0b, 0xb9, 0xa4, 0x60, 0xb3, 0x58, 0x59, 0xbb, 0x60, 0xf2, 0x8d, 0x89, 0x03, 0xce, 0xfe, 0xd7, 0xb3, 0x01, 0x34, 0x68, 0x8b, 0xc2, 0xc3, 0x02, 0x28, 0x4d, 0x5d, 0xcb, 0xed, 0xa6, 0x02, 0x94, 0x7a, 0x8b, 0xa7, 0x0c, 0xfd, 0x90, 0x73, 0x6b, 0xe0, 0xe0, 0x6b, 0x73, 0x02, 0x5e, 0x5a, 0xbe, 0xc7, 0x34, 0x34, 0xae, 0x2a, 0x2c, 0x9c, 0x98, 0xc2, 0xfe, 0x27, 0x01, 0xeb, 0x1a, 0x89, 0x8f, 0xa2, 0xa1, 0x1b, 0xfe, 0xdd, 0xc4, 0x97, 0xb4, 0xae, 0x9e, 0x8a, 0x53, 0x5e, 0x01, 0x61, 0x5c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0xf8, 0x05, 0x44, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x34, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x54, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0x00, 0x00, 0x06, 0xe3, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x3a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x04, 0x60, 0x10, 0x06, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xf9, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x00, 0x01, 0x33, 0x17, 0x37, 0x33, 0x01, 0x17, 0x23, 0x27, 0x07, 0x01, 0x23, 0x01, 0x03, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x27, 0x02, 0x2c, 0x7a, 0x88, 0xc6, 0xea, 0xfe, 0xc6, 0xb4, 0x80, 0x74, 0x8e, 0x02, 0x23, 0xc6, 0xfe, 0x2d, 0xf5, 0xb6, 0xb6, 0x01, 0x84, 0xc5, 0x05, 0x8a, 0x97, 0xe2, 0xfe, 0x9b, 0xc8, 0x80, 0xa1, 0xfc, 0x79, 0x03, 0x01, 0xfe, 0xe9, 0xfe, 0x16, 0x05, 0xd5, 0xfd, 0x1e, 0x01, 0xb8, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x1d, 0x04, 0x60, 0x00, 0x13, 0x00, 0x00, 0x01, 0x33, 0x17, 0x37, 0x33, 0x07, 0x17, 0x23, 0x27, 0x07, 0x01, 0x23, 0x01, 0x07, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x01, 0xfc, 0x7e, 0x3b, 0x6a, 0xcc, 0xcf, 0x84, 0x80, 0x44, 0x73, 0x01, 0xb3, 0xb9, 0xfe, 0x9a, 0xb1, 0xa5, 0xa5, 0x01, 0x2a, 0x04, 0x29, 0x40, 0x77, 0xe9, 0x93, 0x4c, 0x81, 0xfd, 0x51, 0x02, 0x35, 0xc8, 0xfe, 0x93, 0x04, 0x60, 0xfd, 0xf2, 0x01, 0x50, 0x00, 0x01, 0x00, 0x4b, 0xfe, 0x66, 0x07, 0x9b, 0x05, 0xd5, 0x00, 0x25, 0x00, 0x00, 0x33, 0x35, 0x36, 0x37, 0x12, 0x11, 0x35, 0x21, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x23, 0x11, 0x21, 0x15, 0x10, 0x03, 0x06, 0x4c, 0xc3, 0x38, 0x4e, 0x03, 0x1f, 0x01, 0x78, 0xa7, 0x66, 0x62, 0xb8, 0xcd, 0x44, 0x37, 0x79, 0x32, 0x32, 0x70, 0x6f, 0xfe, 0xad, 0xb6, 0xfe, 0x4c, 0x5c, 0x58, 0xaa, 0x2f, 0xa4, 0x01, 0x02, 0x02, 0x58, 0xfe, 0xfd, 0x9c, 0x77, 0x72, 0xee, 0xfe, 0xce, 0xfe, 0xf2, 0xf4, 0xaa, 0x4b, 0x4b, 0xc2, 0x01, 0x22, 0x9f, 0x9e, 0xfd, 0x39, 0x05, 0x2b, 0xb8, 0xfd, 0xca, 0xfe, 0xf8, 0xfd, 0x00, 0x00, 0x01, 0x00, 0x44, 0xfe, 0x56, 0x06, 0x58, 0x04, 0x60, 0x00, 0x27, 0x00, 0x00, 0x33, 0x35, 0x36, 0x37, 0x36, 0x11, 0x35, 0x21, 0x11, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x15, 0x10, 0x07, 0x06, 0x44, 0xa4, 0x33, 0x3d, 0x02, 0xa9, 0xe1, 0xed, 0x3f, 0x4a, 0x4a, 0x49, 0xa3, 0xae, 0x9b, 0x63, 0x1e, 0x22, 0x22, 0x28, 0x7d, 0xea, 0xa5, 0xfe, 0xa1, 0x4f, 0x54, 0x99, 0x1c, 0x7e, 0xb1, 0x01, 0xc5, 0xb7, 0xfe, 0x17, 0x47, 0x51, 0xe5, 0xfe, 0xf2, 0xd5, 0x61, 0x60, 0x9c, 0x30, 0x37, 0x93, 0x01, 0x08, 0xa6, 0x24, 0x29, 0xfe, 0x19, 0x03, 0xcd, 0x6f, 0xfe, 0x50, 0xc2, 0xcf, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x66, 0x07, 0x9c, 0x05, 0xd5, 0x00, 0x21, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x94, 0xb6, 0x01, 0x77, 0xa8, 0x66, 0x62, 0xb8, 0xcd, 0x45, 0x38, 0x79, 0x32, 0x32, 0x70, 0x6f, 0xfe, 0xad, 0xb6, 0xfd, 0x6c, 0xb6, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfd, 0x9c, 0x77, 0x72, 0xee, 0xfe, 0xce, 0xfe, 0xf2, 0xf4, 0xaa, 0x4b, 0x4b, 0xc2, 0x01, 0x22, 0x9f, 0x9e, 0xfd, 0x39, 0x02, 0xc7, 0xfd, 0x39, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x06, 0x65, 0x04, 0x60, 0x00, 0x23, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0xa7, 0xa7, 0x02, 0x19, 0xa7, 0xe1, 0xec, 0x3f, 0x4a, 0x4a, 0x49, 0xa2, 0xae, 0x9b, 0x63, 0x1d, 0x23, 0x23, 0x27, 0x7d, 0xea, 0xa7, 0xfd, 0xe7, 0xa7, 0x04, 0x60, 0xfe, 0x37, 0x01, 0xc9, 0xfe, 0x17, 0x47, 0x51, 0xe5, 0xfe, 0xf2, 0xd5, 0x61, 0x60, 0x9c, 0x30, 0x37, 0x93, 0x01, 0x08, 0xa6, 0x24, 0x29, 0xfe, 0x19, 0x02, 0x04, 0xfd, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x05, 0x6a, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x03, 0xff, 0xfd, 0x6c, 0xb6, 0x04, 0x00, 0xb5, 0xb5, 0x05, 0x2b, 0xfa, 0xd5, 0x05, 0xd5, 0xfa, 0xd5, 0xfe, 0x15, 0x01, 0x41, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x04, 0xb4, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x04, 0x0e, 0xa5, 0xa5, 0xa7, 0xfd, 0xe7, 0xa7, 0x04, 0x60, 0xfc, 0x39, 0xfe, 0x4c, 0x01, 0x1b, 0x03, 0xcd, 0xfc, 0x33, 0x04, 0x60, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x04, 0x60, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x00, 0x21, 0x23, 0x03, 0x21, 0x03, 0x23, 0x01, 0x33, 0x01, 0x21, 0x03, 0x04, 0x0c, 0xb0, 0x5b, 0xfe, 0x41, 0x5c, 0xaf, 0x01, 0x7a, 0xe1, 0xfe, 0xe3, 0x01, 0x59, 0xad, 0x01, 0x13, 0xfe, 0xed, 0x04, 0x60, 0xfd, 0x47, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x04, 0xd2, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x33, 0x01, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x03, 0x01, 0x03, 0x33, 0x11, 0x0a, 0x01, 0xaa, 0x03, 0x12, 0xfe, 0x2a, 0x01, 0xc2, 0xfe, 0x3e, 0x01, 0xe2, 0xfd, 0x77, 0xfe, 0xde, 0x68, 0x01, 0x71, 0xd1, 0xea, 0x04, 0x60, 0x94, 0xfe, 0xd3, 0x94, 0xfe, 0x88, 0x93, 0x01, 0x13, 0xfe, 0xed, 0x03, 0xcd, 0xfd, 0xda, 0x02, 0x26, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6e, 0xff, 0xe3, 0x06, 0xb1, 0x04, 0x7b, 0x00, 0x34, 0x00, 0x3d, 0x00, 0x4a, 0x00, 0x00, 0x25, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x21, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x25, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x03, 0xa0, 0x43, 0xbf, 0x76, 0xcc, 0x76, 0x77, 0x02, 0xf9, 0x0b, 0xb7, 0xa5, 0x5e, 0x5a, 0x5a, 0x5a, 0x5a, 0xbc, 0x5f, 0x96, 0x70, 0x70, 0x45, 0x41, 0xc3, 0x81, 0xaa, 0x5e, 0x5f, 0x73, 0x71, 0xe2, 0xe8, 0x4b, 0x4b, 0x88, 0x57, 0xa3, 0x4c, 0x5b, 0x56, 0x55, 0x51, 0x80, 0x5f, 0x61, 0xfd, 0x45, 0x01, 0x4b, 0x4a, 0x7b, 0x8a, 0x52, 0x54, 0x0d, 0x01, 0x45, 0xc8, 0x9b, 0x3a, 0x3a, 0x64, 0x8a, 0x52, 0x54, 0x9b, 0x5a, 0x5e, 0x91, 0x92, 0xfa, 0x5a, 0xbf, 0xc8, 0x1b, 0x1a, 0x35, 0xae, 0x2a, 0x2c, 0x3d, 0x3c, 0x77, 0x78, 0x78, 0x5d, 0x5e, 0xa8, 0xbd, 0x60, 0x60, 0x12, 0x7f, 0x46, 0x45, 0x2e, 0x2e, 0xaa, 0x27, 0x14, 0x13, 0x30, 0x30, 0x01, 0x87, 0x97, 0x5a, 0x5a, 0x57, 0x57, 0x9e, 0x60, 0x66, 0x7b, 0x62, 0x3a, 0x39, 0x6d, 0x6c, 0xb4, 0x29, 0x00, 0x03, 0x00, 0x37, 0x00, 0x00, 0x03, 0xd2, 0x04, 0x60, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x23, 0x00, 0x00, 0x25, 0x32, 0x35, 0x34, 0x2b, 0x01, 0x15, 0x33, 0x15, 0x23, 0x15, 0x01, 0x34, 0x2b, 0x01, 0x11, 0x33, 0x32, 0x37, 0x14, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0x35, 0x23, 0x35, 0x33, 0x11, 0x21, 0x32, 0x16, 0x02, 0x39, 0xe8, 0xe8, 0xec, 0xc6, 0xc6, 0x01, 0xae, 0xd4, 0xda, 0xda, 0xd4, 0xa7, 0xc1, 0x72, 0x7e, 0xcf, 0xc1, 0xfe, 0x66, 0x6f, 0x6f, 0x01, 0x8b, 0xb1, 0xbf, 0x99, 0xb5, 0xb4, 0x66, 0xa4, 0x5f, 0x02, 0x9d, 0x91, 0xfe, 0xda, 0xaa, 0xd0, 0x1f, 0x18, 0x98, 0x72, 0x96, 0xa4, 0xf8, 0xa4, 0x02, 0xc4, 0x90, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x46, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf7, 0x04, 0x60, 0x00, 0x08, 0x00, 0x11, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x01, 0x4e, 0x7f, 0xc3, 0xb7, 0xb7, 0xc3, 0xfe, 0xda, 0x01, 0x18, 0x01, 0x26, 0x01, 0x11, 0xfe, 0xed, 0xfe, 0xdc, 0xfe, 0xe8, 0x03, 0xcd, 0xfc, 0xc7, 0xc7, 0xd6, 0xd5, 0xc7, 0x93, 0xfe, 0xf1, 0xfe, 0xe0, 0xfe, 0xdf, 0xfe, 0xf0, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x03, 0xf7, 0x04, 0x60, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x00, 0x13, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x11, 0x23, 0x35, 0x33, 0x21, 0x15, 0x23, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x11, 0xa7, 0x01, 0x18, 0x01, 0x26, 0x01, 0x11, 0xfe, 0xed, 0xfe, 0xdc, 0xfe, 0xe8, 0x87, 0x87, 0x01, 0x55, 0xae, 0x7f, 0xc3, 0xb7, 0xb7, 0xc3, 0x7f, 0x04, 0x60, 0xfe, 0xf1, 0xfe, 0xe0, 0xfe, 0xdf, 0xfe, 0xf0, 0x01, 0xf5, 0xa4, 0xa4, 0xfe, 0x9f, 0xc7, 0xd6, 0xd5, 0xc7, 0xfe, 0xcc, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x31, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0xa7, 0x02, 0x7e, 0xfe, 0x2a, 0x01, 0xc1, 0xfe, 0x3f, 0x01, 0xe1, 0xfd, 0x77, 0x04, 0x60, 0x94, 0xfe, 0xd3, 0x94, 0xfe, 0x88, 0x93, 0x00, 0x01, 0x00, 0x75, 0xff, 0xe3, 0x03, 0x65, 0x04, 0x7c, 0x00, 0x31, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x02, 0x79, 0x65, 0x36, 0x36, 0x67, 0x66, 0xb0, 0x45, 0x99, 0x58, 0x57, 0x48, 0x49, 0x40, 0x6b, 0x3e, 0x40, 0x3e, 0x3c, 0x68, 0x8c, 0x85, 0x7c, 0x40, 0x47, 0x4c, 0x4c, 0x88, 0x54, 0x4d, 0x4c, 0x40, 0x51, 0x4c, 0x4c, 0x48, 0xd6, 0xe8, 0x7c, 0x02, 0x03, 0x18, 0x41, 0x40, 0x5d, 0x8d, 0x4f, 0x4e, 0x18, 0x18, 0xa7, 0x1d, 0x0d, 0x0d, 0x2e, 0x2e, 0x40, 0x46, 0x2d, 0x2c, 0x98, 0x33, 0x38, 0x58, 0x5a, 0x38, 0x38, 0x12, 0x13, 0x25, 0xab, 0x1c, 0x0e, 0x0e, 0xb6, 0xad, 0x6c, 0x92, 0x00, 0x00, 0x02, 0x00, 0xad, 0xfe, 0x4c, 0x01, 0x54, 0x04, 0x60, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x11, 0x35, 0x33, 0x15, 0xae, 0xa5, 0xa5, 0xa5, 0x04, 0x60, 0xfb, 0xa0, 0xfe, 0x4c, 0xe9, 0xe9, 0x00, 0x01, 0x00, 0x00, 0xff, 0xe3, 0x02, 0x3c, 0x04, 0x60, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x01, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x06, 0x23, 0x22, 0x26, 0x3d, 0x84, 0x46, 0x5d, 0x29, 0x27, 0x88, 0x8f, 0xa7, 0x40, 0x81, 0x3d, 0xb9, 0x3c, 0x3d, 0x4d, 0x46, 0xd7, 0x02, 0x79, 0xfd, 0x87, 0xfe, 0xe6, 0xea, 0x2c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x26, 0x04, 0x60, 0x10, 0x06, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x03, 0x96, 0x04, 0x7b, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x11, 0x37, 0x17, 0x07, 0x11, 0x21, 0x15, 0x21, 0x11, 0x07, 0x27, 0x37, 0xa7, 0xa7, 0x7b, 0x45, 0xc0, 0x02, 0x48, 0xfd, 0x11, 0x63, 0x42, 0xa5, 0x04, 0x7b, 0xfe, 0x64, 0x61, 0x6a, 0x97, 0xfe, 0x6b, 0xaa, 0x01, 0xbc, 0x4e, 0x6a, 0x83, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xc8, 0x04, 0x60, 0x10, 0x06, 0x03, 0xd0, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x07, 0x04, 0x60, 0x10, 0x06, 0x03, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x72, 0xff, 0xe3, 0x03, 0x90, 0x04, 0x7b, 0x10, 0x06, 0x02, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0x00, 0x2d, 0x04, 0x89, 0x04, 0x31, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x00, 0x01, 0x34, 0x26, 0x20, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x14, 0x00, 0x23, 0x22, 0x00, 0x35, 0x34, 0x00, 0x33, 0x32, 0x00, 0x03, 0xfc, 0xd0, 0xfe, 0x96, 0xd0, 0xd1, 0xb4, 0xb3, 0xd2, 0x8c, 0xfe, 0xe7, 0xf8, 0xf8, 0xfe, 0xe7, 0x01, 0x19, 0xf8, 0xf8, 0x01, 0x19, 0x02, 0x2f, 0x94, 0xac, 0xab, 0x95, 0x93, 0xac, 0xac, 0x93, 0xf0, 0xfe, 0xee, 0x01, 0x12, 0xf0, 0xf1, 0x01, 0x11, 0xfe, 0xef, 0x00, 0x00, 0x01, 0x00, 0x65, 0x00, 0x74, 0x04, 0x89, 0x03, 0xea, 0x00, 0x18, 0x00, 0x00, 0x25, 0x23, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x20, 0x06, 0x15, 0x14, 0x16, 0x17, 0x23, 0x2e, 0x01, 0x35, 0x34, 0x00, 0x33, 0x32, 0x00, 0x11, 0x14, 0x06, 0x04, 0x49, 0x9b, 0x27, 0x27, 0xcd, 0xfe, 0x8f, 0xcc, 0x27, 0x27, 0x9a, 0x20, 0x20, 0x01, 0x1e, 0xf3, 0xf7, 0x01, 0x1a, 0x1f, 0x74, 0x4e, 0x9d, 0x50, 0xb3, 0xc6, 0xc6, 0xb3, 0x50, 0x9d, 0x4e, 0x4d, 0xa5, 0x5d, 0xfd, 0x01, 0x2a, 0xfe, 0xd3, 0xfe, 0xfa, 0x55, 0xa2, 0x00, 0x00, 0x03, 0x00, 0x2d, 0x00, 0x05, 0x04, 0xc6, 0x04, 0x59, 0x00, 0x09, 0x00, 0x13, 0x00, 0x2b, 0x00, 0x00, 0x09, 0x01, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x3e, 0x01, 0x33, 0x32, 0x00, 0x15, 0x14, 0x06, 0x07, 0x17, 0x07, 0x27, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x35, 0x34, 0x36, 0x37, 0x27, 0x37, 0x03, 0x53, 0xfd, 0xec, 0x26, 0x24, 0xd1, 0xb4, 0x47, 0x69, 0x8b, 0x25, 0x24, 0xd3, 0xbe, 0x41, 0x63, 0x29, 0x88, 0x45, 0xb1, 0x6c, 0xf8, 0x01, 0x19, 0x2e, 0x2f, 0x97, 0x47, 0xa1, 0x45, 0xb2, 0x6c, 0xf8, 0xfe, 0xe6, 0x2f, 0x2e, 0x97, 0x46, 0x01, 0x18, 0x01, 0xe7, 0x29, 0x67, 0x41, 0x93, 0xac, 0x14, 0x5c, 0x2a, 0x67, 0x3e, 0x97, 0xa9, 0x13, 0x14, 0x7d, 0x36, 0x36, 0xfe, 0xef, 0xf1, 0x5d, 0x9f, 0x43, 0x8b, 0x5f, 0x92, 0x35, 0x36, 0x01, 0x12, 0xf0, 0x60, 0xa1, 0x3f, 0x8b, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x65, 0xff, 0xe3, 0x06, 0xfd, 0x04, 0x7b, 0x00, 0x26, 0x00, 0x2f, 0x00, 0x3d, 0x00, 0x00, 0x13, 0x35, 0x21, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x37, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x01, 0x32, 0x37, 0x36, 0x10, 0x27, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x66, 0x02, 0xf9, 0x0b, 0x5c, 0x5b, 0xa5, 0x5f, 0xb4, 0x59, 0x5a, 0xbc, 0x5f, 0x90, 0xda, 0x49, 0x40, 0x5d, 0x5f, 0x7e, 0xd9, 0x7a, 0x7b, 0x7b, 0x7a, 0xd9, 0x7e, 0x5f, 0x5f, 0x3c, 0x46, 0xd1, 0x80, 0xcc, 0x77, 0x76, 0xa6, 0x02, 0x4a, 0x4a, 0x7b, 0x8a, 0x52, 0x54, 0x0d, 0x01, 0xd4, 0x85, 0x4d, 0x4e, 0x4d, 0x4d, 0x86, 0x85, 0x9a, 0x4d, 0x4d, 0x02, 0x00, 0x5a, 0xbe, 0x64, 0x63, 0x34, 0x34, 0xae, 0x2a, 0x2c, 0x6e, 0x6d, 0x6e, 0x36, 0x37, 0x9d, 0x9c, 0xfe, 0xed, 0xfe, 0xec, 0x9c, 0x9c, 0x37, 0x38, 0x6c, 0x6b, 0x70, 0x91, 0x92, 0xc4, 0x98, 0x5a, 0x59, 0x57, 0x57, 0x9e, 0xfe, 0xb4, 0x73, 0x74, 0x01, 0x92, 0x74, 0x73, 0xe8, 0xc8, 0xc7, 0x74, 0x75, 0x00, 0x01, 0x00, 0x65, 0x02, 0x2f, 0x04, 0x03, 0x04, 0x7b, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x23, 0x10, 0x12, 0x33, 0x32, 0x12, 0x11, 0x03, 0x53, 0x9a, 0x85, 0x85, 0x9b, 0xae, 0xf5, 0xd9, 0xd8, 0xf7, 0x02, 0x2f, 0xc7, 0xe9, 0xe7, 0xc9, 0x01, 0x14, 0x01, 0x38, 0xfe, 0xc8, 0xfe, 0xec, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x02, 0x2f, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x33, 0x10, 0x02, 0x23, 0x22, 0x02, 0x11, 0x01, 0x15, 0x9b, 0x84, 0x86, 0x9a, 0xaf, 0xf6, 0xd9, 0xd8, 0xf6, 0x02, 0x2f, 0xc7, 0xe9, 0xe7, 0xc9, 0xfe, 0xec, 0xfe, 0xc8, 0x01, 0x38, 0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x87, 0x00, 0x00, 0x03, 0x6b, 0x04, 0x60, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x10, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x01, 0x2d, 0xe7, 0x52, 0x59, 0x59, 0x52, 0xfe, 0x74, 0x01, 0x8c, 0xa9, 0xae, 0xae, 0xa9, 0xe7, 0xa5, 0x03, 0xc5, 0xfe, 0x98, 0x5e, 0xac, 0x5e, 0x9b, 0xaa, 0xfe, 0xb6, 0xaa, 0xfe, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x2d, 0x00, 0x00, 0x03, 0xa8, 0x04, 0x60, 0x00, 0x16, 0x00, 0x21, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x11, 0x23, 0x11, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x37, 0x36, 0x01, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x01, 0x89, 0x5f, 0x65, 0x60, 0x62, 0xc3, 0x01, 0x5d, 0xa6, 0x99, 0x57, 0x35, 0x35, 0x39, 0x92, 0xaf, 0x9d, 0x2f, 0x2f, 0x30, 0x01, 0xa9, 0xb3, 0x6b, 0x38, 0x3a, 0x3a, 0x38, 0x6b, 0xb3, 0x02, 0x0d, 0x1b, 0x8c, 0x69, 0xa2, 0x51, 0x50, 0xfb, 0xa0, 0x01, 0xd9, 0x25, 0x24, 0x71, 0xfe, 0xe1, 0x01, 0x32, 0x5e, 0x36, 0x36, 0x01, 0xc9, 0x2a, 0x2a, 0x54, 0x53, 0x2b, 0x2b, 0x00, 0x00, 0x02, 0x00, 0x2d, 0x00, 0x00, 0x03, 0xa8, 0x04, 0x60, 0x00, 0x16, 0x00, 0x21, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x03, 0x33, 0x13, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x11, 0x33, 0x11, 0x21, 0x22, 0x27, 0x26, 0x35, 0x34, 0x36, 0x01, 0x11, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x01, 0x89, 0x31, 0x30, 0x2f, 0x2f, 0x9d, 0xaf, 0x92, 0x39, 0x35, 0x35, 0x57, 0x99, 0xa6, 0xfe, 0xa3, 0xc3, 0x62, 0x60, 0x65, 0x01, 0xd7, 0xb3, 0x6b, 0x38, 0x3a, 0x3a, 0x38, 0x6b, 0x02, 0x53, 0x11, 0x36, 0x36, 0x5e, 0x01, 0x32, 0xfe, 0xe1, 0x71, 0x24, 0x25, 0x01, 0xd9, 0xfb, 0xa0, 0x50, 0x51, 0xa2, 0x69, 0x8c, 0xfe, 0x63, 0x01, 0x51, 0x2b, 0x2b, 0x53, 0x54, 0x2a, 0x2a, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x03, 0xfc, 0x04, 0x60, 0x10, 0x06, 0x03, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xff, 0xe0, 0x03, 0xac, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x00, 0x24, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x20, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x01, 0xb5, 0xe9, 0x67, 0xa7, 0xc4, 0xfe, 0x83, 0xc4, 0xa7, 0x7d, 0x8e, 0xa2, 0x02, 0xb3, 0xfd, 0x3b, 0xdb, 0xe0, 0xe0, 0xdb, 0x02, 0xc5, 0xfd, 0x4d, 0xa2, 0x00, 0x01, 0x00, 0x9c, 0x00, 0x4c, 0x04, 0xa7, 0x03, 0xf6, 0x00, 0x13, 0x00, 0x00, 0x25, 0x21, 0x35, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x21, 0x35, 0x21, 0x15, 0x23, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x02, 0xff, 0xfd, 0x9e, 0x02, 0x5b, 0x90, 0x8f, 0xab, 0x94, 0xfd, 0xc5, 0x03, 0xf0, 0x9b, 0x5c, 0x59, 0xd8, 0x4c, 0xb8, 0x7c, 0x7c, 0x96, 0xac, 0xb8, 0xb8, 0x42, 0xb2, 0x74, 0xc2, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x9c, 0x00, 0x4e, 0x06, 0x2c, 0x03, 0xf8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x35, 0x33, 0x15, 0x03, 0x35, 0x33, 0x15, 0x05, 0x21, 0x35, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x21, 0x35, 0x21, 0x15, 0x23, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x9d, 0xb5, 0xb5, 0xb5, 0x03, 0x32, 0xfd, 0x9d, 0x02, 0x5c, 0x8f, 0x90, 0xac, 0x93, 0xfd, 0xc4, 0x03, 0xf0, 0x9a, 0x5b, 0x5a, 0xd8, 0x02, 0x78, 0xcc, 0xcc, 0xfe, 0x7a, 0xca, 0xca, 0xa4, 0xb8, 0x7c, 0x7c, 0x94, 0xae, 0xb8, 0xb8, 0x44, 0xb0, 0x76, 0xc0, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2a, 0xfe, 0x18, 0x04, 0x33, 0x04, 0x7b, 0x00, 0x26, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x23, 0x21, 0x35, 0x21, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x21, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x21, 0x35, 0x21, 0x15, 0x23, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x03, 0x59, 0x6f, 0x6b, 0x6e, 0x6f, 0xcb, 0xfd, 0x9f, 0x02, 0x5b, 0x91, 0x8d, 0xab, 0x94, 0xfd, 0xc6, 0x02, 0x5b, 0x92, 0x45, 0x47, 0x57, 0x55, 0x93, 0xfd, 0xc6, 0x03, 0xf0, 0x9c, 0x5c, 0x59, 0x38, 0x38, 0x01, 0x0c, 0x45, 0xc0, 0x82, 0xaf, 0x5f, 0x5f, 0xb9, 0x72, 0x75, 0x8f, 0xa6, 0xb9, 0x39, 0x39, 0x77, 0x8d, 0x53, 0x53, 0xb9, 0xb9, 0x3f, 0xb0, 0x79, 0x7a, 0x56, 0x55, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x04, 0x60, 0x10, 0x06, 0x00, 0x59, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x04, 0x60, 0x10, 0x06, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x79, 0x04, 0x60, 0x10, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6c, 0xff, 0xe3, 0x03, 0x5b, 0x04, 0x60, 0x00, 0x17, 0x00, 0x00, 0x37, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x13, 0x25, 0x35, 0x21, 0x15, 0x03, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x20, 0x27, 0x7c, 0x91, 0xbe, 0x73, 0x77, 0x6f, 0x63, 0x72, 0xef, 0xfe, 0x0c, 0x02, 0xb3, 0xef, 0x3f, 0x88, 0x64, 0xce, 0xfe, 0xa4, 0xb5, 0xbd, 0x42, 0x64, 0xbb, 0x64, 0x90, 0x01, 0x3e, 0x01, 0x93, 0x93, 0xfe, 0xc2, 0x4a, 0x9f, 0x6d, 0xa0, 0xb6, 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa1, 0x00, 0x00, 0x03, 0x96, 0x04, 0x7b, 0x00, 0x05, 0x00, 0x00, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0xa1, 0x02, 0xf5, 0xfd, 0xc1, 0x04, 0x7b, 0xaa, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x04, 0x60, 0x10, 0x06, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x87, 0x00, 0x00, 0x03, 0x88, 0x04, 0x60, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x03, 0x88, 0xa4, 0xfe, 0x48, 0xa4, 0x04, 0x60, 0xfb, 0xa0, 0x03, 0xb7, 0xfc, 0x49, 0x04, 0x60, 0x00, 0x00, 0xff, 0xff, 0x00, 0x87, 0x00, 0x00, 0x03, 0x6b, 0x04, 0x60, 0x10, 0x06, 0x04, 0xd1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x03, 0xef, 0x04, 0x60, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x33, 0x11, 0x36, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x07, 0x06, 0x07, 0x15, 0x23, 0x35, 0x26, 0x27, 0x26, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x17, 0x01, 0xcd, 0xa5, 0x4d, 0x33, 0x4e, 0xae, 0x7a, 0x62, 0xa0, 0xa5, 0x9e, 0x62, 0x7c, 0xb0, 0x4e, 0x33, 0x4b, 0x04, 0x60, 0xfd, 0x31, 0x1a, 0x4d, 0x73, 0xc9, 0x01, 0x2c, 0xfe, 0xd4, 0xfe, 0xec, 0x9c, 0x7d, 0x19, 0xee, 0xee, 0x19, 0x7d, 0x9c, 0x01, 0x14, 0x01, 0x2c, 0xfe, 0xd4, 0xc7, 0x75, 0x4d, 0x1a, 0xff, 0xff, 0x00, 0x44, 0x00, 0x00, 0x04, 0x02, 0x04, 0x60, 0x10, 0x06, 0x03, 0xcf, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x02, 0x9c, 0x03, 0x11, 0x05, 0xe0, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x03, 0x21, 0x03, 0x33, 0x01, 0x23, 0x27, 0x21, 0x07, 0x23, 0x01, 0x8d, 0x9c, 0x01, 0x38, 0xdd, 0x82, 0x01, 0x43, 0x77, 0x4d, 0xfe, 0x82, 0x4d, 0x79, 0x05, 0x71, 0xfe, 0x60, 0x02, 0x0f, 0xfc, 0xbc, 0xd6, 0xd6, 0x00, 0x02, 0x00, 0x04, 0x02, 0x9c, 0x04, 0x21, 0x05, 0xe0, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x01, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x35, 0x21, 0x07, 0x23, 0x01, 0x17, 0x03, 0x21, 0x11, 0x04, 0x16, 0xfe, 0x5c, 0x01, 0x93, 0xfe, 0x6d, 0x01, 0xaf, 0xfd, 0xde, 0xfe, 0xd5, 0x5b, 0x75, 0x01, 0x63, 0x4e, 0xbb, 0x01, 0x05, 0x05, 0xe0, 0x5f, 0xf8, 0x5f, 0xfe, 0xd1, 0x5f, 0xd6, 0xd6, 0x03, 0x44, 0x58, 0xfe, 0x49, 0x01, 0xb7, 0x00, 0x00, 0x03, 0x00, 0x72, 0x02, 0x9c, 0x02, 0xcb, 0x05, 0xe0, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x26, 0x00, 0x00, 0x13, 0x11, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x03, 0x15, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x25, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0xe5, 0xb7, 0x5d, 0x2c, 0x2d, 0x2d, 0x2c, 0x5d, 0xb7, 0xa9, 0x54, 0x29, 0x29, 0x29, 0x29, 0x54, 0xfe, 0xe4, 0x01, 0x25, 0x82, 0x47, 0x48, 0x25, 0x24, 0x47, 0x55, 0x5e, 0x9b, 0x8e, 0xfe, 0xd0, 0x04, 0x2b, 0xfe, 0xce, 0x26, 0x26, 0x4d, 0x4f, 0x25, 0x25, 0x01, 0x58, 0xfc, 0x1f, 0x1f, 0x40, 0x3f, 0x20, 0x1f, 0x5d, 0x36, 0x35, 0x64, 0x4c, 0x2e, 0x2d, 0x0b, 0x12, 0x72, 0x55, 0x70, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x72, 0x02, 0x9c, 0x03, 0x3a, 0x05, 0xe0, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x00, 0x13, 0x11, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x27, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0xe5, 0x8a, 0xaf, 0x52, 0x51, 0x51, 0x52, 0xaf, 0xfd, 0xeb, 0xf7, 0x72, 0x73, 0x73, 0x74, 0xf5, 0xeb, 0x05, 0x83, 0xfd, 0x76, 0x4e, 0x4f, 0xa9, 0xa8, 0x4e, 0x4e, 0x5d, 0x65, 0x65, 0xd7, 0xd8, 0x66, 0x65, 0x00, 0x01, 0x00, 0x72, 0x02, 0x9c, 0x02, 0x94, 0x05, 0xe0, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x72, 0x02, 0x17, 0xfe, 0x5c, 0x01, 0x93, 0xfe, 0x6d, 0x01, 0xaf, 0xfd, 0xde, 0x05, 0xe0, 0x5f, 0xf8, 0x5f, 0xfe, 0xd1, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4a, 0x02, 0x9c, 0x02, 0x6d, 0x05, 0xe0, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x02, 0x6c, 0xfd, 0xdf, 0x01, 0xae, 0xfe, 0x6d, 0x01, 0x93, 0xfe, 0x5c, 0x05, 0xe0, 0xfc, 0xbc, 0x5f, 0x01, 0x2f, 0x5f, 0xf8, 0x5f, 0x00, 0x01, 0x00, 0x40, 0x02, 0x8c, 0x03, 0x25, 0x05, 0xef, 0x00, 0x24, 0x00, 0x00, 0x01, 0x35, 0x23, 0x35, 0x21, 0x11, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x02, 0xb3, 0xbb, 0x01, 0x2d, 0x43, 0x50, 0x4f, 0x5b, 0xc7, 0x70, 0x70, 0x70, 0x70, 0xc7, 0x53, 0x4a, 0x4a, 0x3f, 0x3f, 0x48, 0x47, 0x4e, 0x9c, 0x4e, 0x4e, 0x4e, 0x4e, 0x9c, 0x3c, 0x5f, 0x03, 0x13, 0xe1, 0x5d, 0xfe, 0x99, 0x2f, 0x17, 0x18, 0x72, 0x73, 0xcc, 0xcd, 0x73, 0x72, 0x14, 0x14, 0x27, 0x79, 0x35, 0x1b, 0x1b, 0x55, 0x56, 0xaa, 0xa9, 0x56, 0x55, 0x14, 0x00, 0x00, 0x01, 0x00, 0x72, 0x02, 0x9c, 0x02, 0xf8, 0x05, 0xe0, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x72, 0x73, 0x01, 0x9f, 0x74, 0x74, 0xfe, 0x61, 0x73, 0x05, 0xe0, 0xfe, 0xa9, 0x01, 0x57, 0xfc, 0xbc, 0x01, 0x8e, 0xfe, 0x72, 0x00, 0x00, 0x01, 0x00, 0x72, 0x02, 0x9c, 0x00, 0xe5, 0x05, 0xe0, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x72, 0x73, 0x73, 0x05, 0xe0, 0xfc, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xc3, 0x01, 0xb6, 0x00, 0xe5, 0x05, 0xe0, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x72, 0x73, 0x3b, 0x3a, 0x80, 0x2c, 0x24, 0x4b, 0x3f, 0x05, 0xe0, 0xfc, 0xf6, 0x97, 0x44, 0x45, 0x60, 0x54, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x72, 0x02, 0x9c, 0x03, 0x12, 0x05, 0xe0, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x72, 0x73, 0x01, 0x7b, 0x94, 0xfe, 0x5c, 0x01, 0xc2, 0x97, 0xfe, 0x6a, 0x73, 0x05, 0xe0, 0xfe, 0x9f, 0x01, 0x61, 0xfe, 0x7a, 0xfe, 0x42, 0x01, 0x93, 0xfe, 0x6d, 0x00, 0x01, 0x00, 0x72, 0x02, 0x9c, 0x02, 0x81, 0x05, 0xe0, 0x00, 0x05, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x15, 0x21, 0x72, 0x73, 0x01, 0x9c, 0xfd, 0xf1, 0x05, 0xe0, 0xfd, 0x1b, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x72, 0x02, 0x9c, 0x03, 0x79, 0x05, 0xe0, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x1b, 0x01, 0x33, 0x11, 0x23, 0x11, 0x03, 0x23, 0x03, 0x11, 0x23, 0x72, 0xaa, 0xd8, 0xda, 0xaa, 0x6f, 0xda, 0x73, 0xdb, 0x6f, 0x05, 0xe0, 0xfd, 0xc7, 0x02, 0x39, 0xfc, 0xbc, 0x02, 0xde, 0xfd, 0xc3, 0x02, 0x3d, 0xfd, 0x22, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x72, 0x02, 0x9c, 0x02, 0xf4, 0x05, 0xe0, 0x00, 0x09, 0x00, 0x00, 0x13, 0x33, 0x01, 0x11, 0x33, 0x11, 0x23, 0x01, 0x11, 0x23, 0x72, 0x9a, 0x01, 0x78, 0x6f, 0x9b, 0xfe, 0x89, 0x6f, 0x05, 0xe0, 0xfd, 0x45, 0x02, 0xbb, 0xfc, 0xbc, 0x02, 0xbb, 0xfd, 0x45, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x72, 0x02, 0x9c, 0x02, 0xf4, 0x05, 0xe0, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x01, 0x23, 0x11, 0x33, 0x11, 0x01, 0x02, 0xf3, 0x6f, 0xfe, 0x88, 0x9a, 0x6f, 0x01, 0x77, 0x05, 0xe0, 0xfc, 0xbc, 0x02, 0xbb, 0xfd, 0x45, 0x03, 0x44, 0xfd, 0x45, 0x02, 0xbb, 0x00, 0x00, 0x02, 0x00, 0x40, 0x02, 0x8c, 0x03, 0x51, 0x05, 0xef, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x24, 0x20, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x20, 0x27, 0x26, 0x10, 0x01, 0xc9, 0x7c, 0x4a, 0x49, 0x49, 0x4a, 0x7c, 0x7d, 0x49, 0x49, 0x49, 0x49, 0xfe, 0xd1, 0x01, 0x64, 0x6b, 0x6b, 0x6b, 0x6b, 0xfe, 0x9c, 0x6b, 0x6b, 0x05, 0x93, 0x5b, 0x5c, 0x9f, 0x9e, 0x5c, 0x5b, 0x5b, 0x5c, 0x9e, 0x9f, 0x5c, 0x5b, 0x5c, 0x76, 0x76, 0xc6, 0xc5, 0x76, 0x76, 0x75, 0x76, 0x01, 0x8c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0xeb, 0x05, 0xef, 0x00, 0x0f, 0x00, 0x40, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x03, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x35, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x01, 0x95, 0x67, 0x3d, 0x3d, 0x3d, 0x3d, 0x67, 0x68, 0x3e, 0x3c, 0x3c, 0x3c, 0x8a, 0x4a, 0x31, 0x30, 0x36, 0x22, 0x73, 0x5f, 0x36, 0x37, 0x2b, 0x3e, 0x4a, 0x82, 0x54, 0x50, 0x31, 0x30, 0x56, 0x61, 0x36, 0x37, 0x59, 0x57, 0xa6, 0xa5, 0xb0, 0x37, 0x37, 0x61, 0x61, 0x26, 0x31, 0x4a, 0x42, 0x92, 0x04, 0x29, 0x2b, 0x2b, 0x4c, 0x4b, 0x2c, 0x2b, 0x2b, 0x2c, 0x4b, 0x4c, 0x2b, 0x2b, 0x01, 0x35, 0x02, 0x23, 0x23, 0x2c, 0x26, 0x29, 0x19, 0x24, 0x25, 0x4c, 0x59, 0x18, 0x2b, 0x04, 0x38, 0x3a, 0x36, 0x69, 0x47, 0x32, 0x32, 0x12, 0x13, 0x37, 0x38, 0x50, 0x79, 0x41, 0x41, 0x82, 0x79, 0x50, 0x38, 0x37, 0x13, 0x12, 0x27, 0x32, 0x31, 0x49, 0x2e, 0x2a, 0x00, 0x02, 0x00, 0x72, 0x02, 0x9c, 0x02, 0x95, 0x05, 0xe0, 0x00, 0x09, 0x00, 0x15, 0x00, 0x00, 0x13, 0x11, 0x33, 0x32, 0x37, 0x36, 0x34, 0x27, 0x26, 0x23, 0x25, 0x21, 0x32, 0x17, 0x16, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x11, 0x23, 0xe5, 0x90, 0x50, 0x2b, 0x2c, 0x2c, 0x2b, 0x50, 0xfe, 0xfd, 0x01, 0x03, 0x8e, 0x49, 0x49, 0x49, 0x49, 0x8e, 0x90, 0x73, 0x05, 0x83, 0xfe, 0xc6, 0x29, 0x29, 0x96, 0x29, 0x29, 0x5d, 0x3f, 0x40, 0xf6, 0x40, 0x3f, 0xfe, 0xb0, 0x00, 0x00, 0x02, 0x00, 0x72, 0x02, 0x9c, 0x03, 0x06, 0x05, 0xe0, 0x00, 0x17, 0x00, 0x20, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x23, 0x27, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x02, 0x04, 0x25, 0x22, 0x23, 0x23, 0x74, 0x7a, 0x6d, 0x2a, 0x27, 0x28, 0x44, 0x7c, 0x73, 0x01, 0x03, 0x91, 0x48, 0x47, 0x25, 0x26, 0xfe, 0x9b, 0x90, 0x52, 0x55, 0x55, 0x52, 0x04, 0x24, 0x0c, 0x29, 0x28, 0x47, 0xe4, 0xd6, 0x54, 0x1c, 0x1b, 0xfe, 0x9f, 0x03, 0x44, 0x3c, 0x3c, 0x79, 0x4f, 0x34, 0x34, 0x01, 0x4b, 0xfe, 0xd7, 0x4c, 0x49, 0x4a, 0x4a, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x02, 0x9c, 0x02, 0xc9, 0x05, 0xe0, 0x00, 0x07, 0x00, 0x00, 0x03, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x04, 0x02, 0xcd, 0xfe, 0xd3, 0x73, 0xfe, 0xd3, 0x05, 0xe0, 0x5f, 0xfd, 0x1b, 0x02, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x64, 0x02, 0x8c, 0x02, 0xed, 0x05, 0xe0, 0x00, 0x13, 0x00, 0x00, 0x13, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x20, 0x27, 0x26, 0x35, 0x65, 0x73, 0x63, 0x6e, 0x6f, 0x31, 0x31, 0x73, 0x52, 0x52, 0xfe, 0xc0, 0x52, 0x52, 0x05, 0xe0, 0xfe, 0x04, 0x86, 0x76, 0x3b, 0x3b, 0x86, 0x01, 0xfc, 0xfd, 0xf6, 0xa3, 0x54, 0x53, 0x53, 0x54, 0xa3, 0x00, 0x00, 0x01, 0x00, 0x26, 0x02, 0x9c, 0x04, 0x57, 0x05, 0xe0, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x1b, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x23, 0x0b, 0x01, 0x23, 0x27, 0x73, 0xb2, 0xb1, 0x81, 0xb2, 0xb2, 0x75, 0xd6, 0x90, 0xb2, 0xb5, 0x90, 0x05, 0xe0, 0xfd, 0x3d, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0xc3, 0xfc, 0xbc, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x02, 0x00, 0x45, 0x02, 0x8c, 0x02, 0x5e, 0x05, 0x1e, 0x00, 0x0c, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x37, 0x11, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x8e, 0x7e, 0x31, 0x31, 0x4a, 0x3e, 0x57, 0x34, 0x35, 0x68, 0x68, 0x24, 0x35, 0x36, 0x4c, 0x63, 0x73, 0x90, 0x8f, 0x92, 0x5f, 0x56, 0x36, 0x34, 0x33, 0x30, 0x3a, 0x36, 0x35, 0x33, 0x8a, 0x44, 0x44, 0x03, 0xd7, 0x1c, 0x1d, 0x45, 0x37, 0x40, 0x3d, 0x3d, 0x64, 0x17, 0x2b, 0xfe, 0x9a, 0x5f, 0x39, 0x1b, 0x1b, 0x6c, 0x5b, 0x69, 0x6c, 0x0a, 0x47, 0x4e, 0x0d, 0x0d, 0x1a, 0x60, 0x15, 0x0b, 0x0b, 0x46, 0x47, 0x00, 0x02, 0x00, 0x45, 0x02, 0x8c, 0x02, 0x5e, 0x05, 0x1e, 0x00, 0x0c, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x07, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x01, 0x16, 0x7e, 0x31, 0x31, 0x4a, 0x3f, 0x56, 0x34, 0x35, 0x69, 0x69, 0x24, 0x35, 0x36, 0x4c, 0x62, 0x3a, 0x39, 0x48, 0x47, 0x8f, 0x92, 0x5f, 0x56, 0x36, 0x34, 0x33, 0x30, 0x3a, 0x36, 0x36, 0x32, 0x8a, 0x44, 0x45, 0x03, 0xd3, 0x1c, 0x1d, 0x45, 0x37, 0x40, 0x3d, 0x3c, 0x65, 0x17, 0x2b, 0x01, 0x66, 0x5f, 0x39, 0x1b, 0x1b, 0x36, 0x36, 0x5a, 0x6a, 0x36, 0x36, 0x0a, 0x47, 0x4e, 0x0d, 0x0d, 0x1a, 0x60, 0x15, 0x0c, 0x0a, 0x46, 0x47, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x78, 0x05, 0x1e, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x35, 0x33, 0x11, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x04, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x34, 0x27, 0x26, 0x22, 0x07, 0x02, 0x0f, 0x69, 0x69, 0x21, 0x31, 0x33, 0x46, 0x73, 0x49, 0x48, 0x48, 0x49, 0x73, 0x46, 0x33, 0x31, 0xfe, 0xbe, 0x2f, 0x2f, 0xa6, 0x30, 0x2f, 0x2f, 0x30, 0xa6, 0x2f, 0x04, 0xb0, 0x5f, 0xfd, 0x8d, 0x5e, 0x38, 0x1b, 0x1b, 0x5a, 0x5b, 0x01, 0x28, 0x5b, 0x5a, 0x1b, 0x1b, 0xa1, 0xe4, 0x41, 0x40, 0x40, 0x41, 0xe4, 0x41, 0x40, 0x40, 0x00, 0x00, 0x03, 0x00, 0x45, 0x02, 0x8c, 0x04, 0x38, 0x05, 0x1e, 0x00, 0x33, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x21, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x25, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x3f, 0x01, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x02, 0x49, 0x2a, 0x79, 0x4b, 0x7f, 0x4b, 0x4c, 0x01, 0xe0, 0x06, 0x3a, 0x3a, 0x68, 0x3a, 0x72, 0x39, 0x39, 0x3b, 0x3b, 0x3b, 0x60, 0x46, 0x46, 0x2c, 0x29, 0x3d, 0x3d, 0x52, 0x6b, 0x77, 0x48, 0x47, 0x8f, 0x92, 0x2f, 0x30, 0x55, 0x37, 0x67, 0x2f, 0x38, 0x6c, 0x34, 0x50, 0x78, 0xfe, 0x47, 0x01, 0x2e, 0x2f, 0x4d, 0x57, 0x35, 0x34, 0x08, 0xcd, 0x7f, 0x30, 0x31, 0x25, 0x24, 0x3f, 0x57, 0x35, 0x34, 0x02, 0xf3, 0x33, 0x34, 0x51, 0x52, 0x8c, 0x32, 0x6b, 0x38, 0x38, 0x1e, 0x1d, 0x61, 0x18, 0x0c, 0x0c, 0x22, 0x21, 0x43, 0x43, 0x22, 0x21, 0x68, 0x5e, 0x6a, 0x36, 0x36, 0x0a, 0x47, 0x27, 0x27, 0x1a, 0x1a, 0x60, 0x15, 0x16, 0x36, 0xda, 0x54, 0x32, 0x33, 0x31, 0x31, 0x58, 0x36, 0x1c, 0x1d, 0x45, 0x37, 0x20, 0x20, 0x3d, 0x3c, 0x65, 0x17, 0x00, 0x00, 0x02, 0x00, 0x69, 0x02, 0x8c, 0x02, 0xa2, 0x06, 0x03, 0x00, 0x0b, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x14, 0x17, 0x16, 0x32, 0x37, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x15, 0x23, 0x11, 0x33, 0x02, 0x35, 0x2f, 0x2f, 0xa6, 0x30, 0x2e, 0x2e, 0x30, 0xa6, 0x2f, 0xfe, 0xcd, 0x20, 0x65, 0x45, 0x74, 0x48, 0x48, 0x48, 0x48, 0x74, 0x45, 0x65, 0x20, 0x6a, 0x6a, 0x03, 0x63, 0xe4, 0x40, 0x41, 0x41, 0x40, 0xe4, 0x40, 0x41, 0x41, 0x01, 0x8d, 0x38, 0x36, 0x5a, 0x5b, 0xfe, 0xd8, 0x5b, 0x5a, 0x36, 0x38, 0x5e, 0x03, 0x67, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x78, 0x06, 0x03, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x04, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x34, 0x27, 0x26, 0x22, 0x07, 0x02, 0x0f, 0x69, 0x69, 0x21, 0x31, 0x33, 0x46, 0x73, 0x48, 0x49, 0x49, 0x48, 0x73, 0x46, 0x33, 0x31, 0xfe, 0xbe, 0x2f, 0x2f, 0xa6, 0x30, 0x2f, 0x2f, 0x30, 0xa6, 0x2f, 0x04, 0xb0, 0x01, 0x53, 0xfc, 0x99, 0x5e, 0x38, 0x1b, 0x1b, 0x5a, 0x5b, 0x01, 0x28, 0x5b, 0x5a, 0x1b, 0x1b, 0xa1, 0xe4, 0x40, 0x41, 0x41, 0x40, 0xe4, 0x40, 0x41, 0x41, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x8d, 0x05, 0x1e, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x00, 0x01, 0x15, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x07, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x02, 0x8c, 0xfe, 0x21, 0x07, 0x3a, 0x3a, 0x68, 0x3c, 0x39, 0x37, 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x98, 0x58, 0x59, 0x54, 0x54, 0x8f, 0x80, 0x4b, 0x4a, 0x68, 0x01, 0x2f, 0x2e, 0x4e, 0x57, 0x34, 0x35, 0x08, 0x03, 0xef, 0x32, 0x6a, 0x38, 0x38, 0x0f, 0x0e, 0x1d, 0x61, 0x18, 0x0c, 0x0c, 0x57, 0x57, 0x95, 0x9a, 0x5b, 0x5a, 0x51, 0x52, 0x6d, 0x54, 0x33, 0x32, 0x31, 0x30, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x8d, 0x05, 0x1e, 0x00, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x35, 0x21, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x37, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x40, 0x01, 0xe0, 0x07, 0x75, 0x67, 0x3d, 0x70, 0x38, 0x39, 0x76, 0x3c, 0x98, 0xb1, 0xa8, 0x8f, 0x80, 0x95, 0x68, 0x01, 0x5e, 0x4d, 0x58, 0x69, 0x07, 0x03, 0xbb, 0x32, 0x6b, 0x6f, 0x1d, 0x1d, 0x61, 0x18, 0x18, 0xae, 0x95, 0x9a, 0xb5, 0xa3, 0x6d, 0x54, 0x65, 0x62, 0x58, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4b, 0x02, 0x8c, 0x02, 0x25, 0x05, 0x1f, 0x00, 0x32, 0x00, 0x00, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0xe0, 0x40, 0x22, 0x21, 0x41, 0x3f, 0x6f, 0x2b, 0x31, 0x30, 0x37, 0x37, 0x5b, 0x28, 0x43, 0x28, 0x28, 0x27, 0x26, 0x42, 0x58, 0x54, 0x4e, 0x29, 0x2c, 0x30, 0x30, 0x55, 0x35, 0x31, 0x2f, 0x29, 0x33, 0x30, 0x30, 0x2e, 0x87, 0x91, 0x26, 0x28, 0x03, 0xee, 0x0e, 0x24, 0x24, 0x34, 0x4f, 0x2c, 0x2c, 0x07, 0x07, 0x0d, 0x5e, 0x11, 0x0e, 0x19, 0x1a, 0x24, 0x27, 0x19, 0x19, 0x55, 0x1d, 0x1f, 0x31, 0x33, 0x1f, 0x20, 0x0b, 0x0a, 0x15, 0x60, 0x10, 0x07, 0x08, 0x66, 0x61, 0x3c, 0x29, 0x29, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x49, 0x02, 0x8c, 0x02, 0x24, 0x05, 0x1f, 0x00, 0x31, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x01, 0x8f, 0x3f, 0x44, 0x41, 0x40, 0x6e, 0x2b, 0x31, 0x30, 0x38, 0x37, 0x2d, 0x2e, 0x29, 0x43, 0x4f, 0x26, 0x26, 0x42, 0x58, 0x54, 0x4d, 0x29, 0x2d, 0x30, 0x31, 0x55, 0x34, 0x31, 0x30, 0x28, 0x33, 0x5f, 0x2e, 0x86, 0x4a, 0x49, 0x27, 0x27, 0x03, 0xbc, 0x0d, 0x48, 0x34, 0x4f, 0x2d, 0x2b, 0x06, 0x07, 0x0e, 0x5d, 0x10, 0x07, 0x08, 0x34, 0x24, 0x27, 0x19, 0x19, 0x55, 0x1c, 0x20, 0x31, 0x32, 0x20, 0x1f, 0x0a, 0x0b, 0x14, 0x60, 0x0f, 0x10, 0x33, 0x33, 0x61, 0x3c, 0x29, 0x29, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x01, 0xad, 0x02, 0x78, 0x05, 0x1e, 0x00, 0x0d, 0x00, 0x31, 0x00, 0x00, 0x00, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x17, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x35, 0x33, 0x02, 0x0f, 0x2e, 0x2f, 0x55, 0x53, 0x2f, 0x2f, 0x2f, 0x2f, 0x53, 0x55, 0x2f, 0x97, 0x48, 0x48, 0x95, 0x37, 0x31, 0x31, 0x2e, 0x2e, 0x2d, 0x2d, 0x2e, 0x67, 0x33, 0x33, 0x20, 0x32, 0x33, 0x46, 0x75, 0x47, 0x48, 0x48, 0x47, 0x75, 0x46, 0x33, 0x32, 0x20, 0x69, 0x03, 0x6d, 0xe0, 0x3d, 0x3e, 0x3e, 0x3d, 0xe0, 0x3d, 0x3e, 0x3e, 0x46, 0xa0, 0x4e, 0x4f, 0x09, 0x08, 0x10, 0x65, 0x19, 0x0c, 0x0b, 0x34, 0x35, 0x6b, 0x33, 0x37, 0x1c, 0x1b, 0x58, 0x58, 0x01, 0x22, 0x58, 0x58, 0x1b, 0x1c, 0x37, 0x5f, 0x00, 0x02, 0x00, 0x6d, 0x01, 0xa8, 0x00, 0xd7, 0x05, 0x0f, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x15, 0x35, 0x33, 0x15, 0x6e, 0x68, 0x68, 0x68, 0x05, 0x0f, 0xfd, 0x8d, 0xf4, 0x82, 0x82, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x02, 0x9d, 0x06, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x69, 0x6a, 0x01, 0x37, 0x85, 0xfe, 0xaf, 0x01, 0x5f, 0x88, 0xfe, 0xbe, 0x6a, 0x06, 0x03, 0xfd, 0xfe, 0x01, 0x0e, 0xfe, 0xdb, 0xfe, 0xb2, 0x01, 0x32, 0xfe, 0xce, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x04, 0x09, 0x05, 0x1e, 0x00, 0x22, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x6d, 0x68, 0x41, 0x44, 0x50, 0x5d, 0x6a, 0x6a, 0x23, 0x64, 0x45, 0x44, 0x61, 0x18, 0x27, 0x6d, 0x49, 0x64, 0x6b, 0x68, 0x41, 0x43, 0x50, 0x5f, 0x03, 0xfe, 0xfe, 0x9e, 0x01, 0x77, 0x5b, 0x57, 0x6b, 0x5c, 0xfe, 0x9e, 0x02, 0x73, 0x61, 0x39, 0x37, 0x45, 0x42, 0x45, 0x42, 0x89, 0x7e, 0xfe, 0x85, 0x01, 0x77, 0x5a, 0x58, 0x6b, 0x00, 0x01, 0x00, 0x69, 0x01, 0xad, 0x02, 0x7e, 0x05, 0x1e, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x02, 0x7d, 0x2f, 0x2e, 0x66, 0x90, 0x84, 0x3c, 0x2b, 0x46, 0x47, 0x54, 0x61, 0x6a, 0x6a, 0x25, 0x32, 0x33, 0x43, 0x6d, 0x38, 0x38, 0x04, 0x17, 0xfe, 0x7a, 0x78, 0x36, 0x36, 0x58, 0x36, 0x56, 0x01, 0x82, 0x59, 0x59, 0x6b, 0x5c, 0xfe, 0x9e, 0x02, 0x73, 0x61, 0x38, 0x1c, 0x1c, 0x42, 0x44, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x88, 0x05, 0x1e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x64, 0x54, 0x62, 0x61, 0x55, 0x53, 0x61, 0x61, 0x53, 0x87, 0x9c, 0x9c, 0x87, 0x89, 0x9b, 0x9b, 0x04, 0xc7, 0x81, 0x71, 0x71, 0x81, 0x82, 0x70, 0x6f, 0x83, 0x57, 0xae, 0x9b, 0x9a, 0xaf, 0xaf, 0x9a, 0x9b, 0xae, 0x00, 0x01, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x37, 0x05, 0x1e, 0x00, 0x20, 0x00, 0x00, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x40, 0x2b, 0x2e, 0x2e, 0x31, 0x94, 0x55, 0x55, 0x54, 0x54, 0x90, 0x34, 0x30, 0x2e, 0x2c, 0x2c, 0x2d, 0x2c, 0x2e, 0x65, 0x38, 0x38, 0x38, 0x38, 0x65, 0x2e, 0x2c, 0x2d, 0x2c, 0x04, 0xf7, 0x14, 0x0a, 0x09, 0x58, 0x58, 0x99, 0x97, 0x59, 0x59, 0x0a, 0x0a, 0x14, 0x5f, 0x18, 0x0c, 0x0c, 0x3f, 0x40, 0xe6, 0x40, 0x3f, 0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3f, 0x03, 0xd5, 0x02, 0x88, 0x05, 0x1e, 0x00, 0x10, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x15, 0x23, 0x34, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x30, 0x02, 0x18, 0x30, 0x31, 0xa7, 0x31, 0x31, 0x6e, 0x9b, 0x89, 0x87, 0x4f, 0x4d, 0x03, 0xd5, 0x6f, 0x42, 0x41, 0x41, 0x40, 0x71, 0x9b, 0xae, 0x57, 0x57, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x88, 0x03, 0xd5, 0x00, 0x10, 0x00, 0x00, 0x13, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x35, 0x33, 0x14, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x30, 0xaf, 0x30, 0x31, 0xa7, 0x31, 0x31, 0x6e, 0x9b, 0x88, 0x88, 0x4e, 0x4e, 0x03, 0xd5, 0x6f, 0x42, 0x41, 0x41, 0x40, 0x71, 0x9b, 0xae, 0x57, 0x57, 0x9b, 0x00, 0x02, 0x00, 0x69, 0x01, 0xad, 0x02, 0xa2, 0x05, 0x1e, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x26, 0x24, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x14, 0x17, 0x16, 0x32, 0x37, 0xd3, 0x6a, 0x6a, 0x20, 0x65, 0x45, 0x74, 0x48, 0x48, 0x48, 0x48, 0x74, 0x45, 0x65, 0x01, 0x42, 0x2f, 0x2f, 0xa6, 0x30, 0x2e, 0x2e, 0x30, 0xa6, 0x2f, 0x02, 0xfa, 0xfe, 0xb3, 0x03, 0x62, 0x5f, 0x38, 0x36, 0x5a, 0x5b, 0xfe, 0xd8, 0x5b, 0x5a, 0x36, 0xa1, 0xe4, 0x40, 0x41, 0x41, 0x40, 0xe4, 0x40, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1f, 0x02, 0x9c, 0x01, 0xac, 0x05, 0xc1, 0x00, 0x14, 0x00, 0x00, 0x13, 0x15, 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x35, 0xd4, 0xd8, 0xd8, 0x2c, 0x40, 0x6c, 0x6c, 0x78, 0x2e, 0x2e, 0x4c, 0x4c, 0x05, 0xc1, 0xb2, 0x50, 0xfe, 0xac, 0x4d, 0x2c, 0x56, 0x2d, 0x2c, 0x76, 0x01, 0x54, 0x50, 0xb2, 0x00, 0x00, 0x01, 0x00, 0x63, 0x02, 0x8c, 0x02, 0x77, 0x05, 0x0f, 0x00, 0x16, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x63, 0x68, 0x23, 0x24, 0x46, 0x54, 0x31, 0x31, 0x69, 0x69, 0x26, 0x32, 0x32, 0x43, 0x6d, 0x71, 0x03, 0x94, 0x01, 0x7b, 0xfe, 0x88, 0x59, 0x2c, 0x2d, 0x36, 0x35, 0x5c, 0x01, 0x63, 0xfd, 0x8d, 0x60, 0x39, 0x1c, 0x1b, 0x86, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x02, 0xc7, 0x02, 0xee, 0x04, 0xd4, 0x00, 0x16, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x21, 0x35, 0x21, 0x15, 0x23, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x01, 0xe3, 0xfe, 0x80, 0x01, 0x7c, 0x5b, 0x2d, 0x2d, 0x36, 0x36, 0x5d, 0xfe, 0x98, 0x02, 0x7b, 0x62, 0x3a, 0x38, 0x44, 0x44, 0x02, 0xc7, 0x67, 0x23, 0x22, 0x46, 0x53, 0x31, 0x30, 0x67, 0x67, 0x25, 0x64, 0x41, 0x6c, 0x38, 0x38, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x8d, 0x04, 0x09, 0x05, 0x10, 0x00, 0x28, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x02, 0x16, 0x27, 0x36, 0x37, 0x4a, 0x63, 0x6c, 0x6a, 0x20, 0x20, 0x42, 0x51, 0x30, 0x2f, 0x68, 0x20, 0x21, 0x43, 0x50, 0x2f, 0x30, 0x68, 0x68, 0x24, 0x32, 0x32, 0x44, 0x46, 0x61, 0x03, 0x15, 0x45, 0x21, 0x22, 0x8a, 0x7f, 0x01, 0x7a, 0xfe, 0x89, 0x5b, 0x2b, 0x2c, 0x36, 0x34, 0x5c, 0x01, 0x63, 0xfe, 0x89, 0x5b, 0x2b, 0x2c, 0x36, 0x36, 0x5a, 0x01, 0x63, 0xfd, 0x8d, 0x62, 0x3b, 0x1b, 0x1c, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x22, 0x02, 0x9c, 0x02, 0x8d, 0x05, 0x0f, 0x00, 0x06, 0x00, 0x00, 0x13, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x23, 0x22, 0x6f, 0xc7, 0xc6, 0x6e, 0xed, 0x8e, 0x05, 0x0f, 0xfd, 0xf2, 0x02, 0x0e, 0xfd, 0x8d, 0x00, 0x02, 0x00, 0x6c, 0x01, 0xad, 0x02, 0x92, 0x06, 0x0b, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x13, 0x11, 0x23, 0x11, 0x10, 0x33, 0x32, 0x17, 0x16, 0x07, 0x16, 0x17, 0x12, 0x21, 0x26, 0x27, 0x16, 0x33, 0x32, 0x35, 0x34, 0x05, 0x35, 0x16, 0x35, 0x34, 0x23, 0x22, 0x15, 0xd5, 0x68, 0xf1, 0xf6, 0x01, 0x01, 0x63, 0x9e, 0x01, 0x01, 0xfe, 0xed, 0x77, 0x34, 0x3f, 0x71, 0xa3, 0xfe, 0xf8, 0xcf, 0x85, 0x95, 0x02, 0xc3, 0xfe, 0xea, 0x03, 0x5e, 0x01, 0x00, 0xd8, 0x99, 0x38, 0x33, 0x95, 0xfe, 0xf6, 0x01, 0xb8, 0x61, 0xb0, 0x9e, 0x0c, 0x5f, 0x04, 0xb7, 0x7b, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x12, 0x01, 0xad, 0x02, 0x8d, 0x05, 0x0f, 0x00, 0x0e, 0x00, 0x00, 0x1b, 0x02, 0x33, 0x01, 0x15, 0x23, 0x35, 0x03, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0xcc, 0x8c, 0xc6, 0x6e, 0xff, 0x00, 0x68, 0xa7, 0x19, 0x36, 0x1c, 0x28, 0x6f, 0x04, 0xad, 0xfe, 0x7c, 0x01, 0xe6, 0xfd, 0x8d, 0xef, 0xef, 0x01, 0xd4, 0x47, 0x58, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x88, 0x05, 0xef, 0x00, 0x1b, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x20, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x35, 0x34, 0x33, 0x32, 0x17, 0x01, 0x06, 0x07, 0x06, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x02, 0x3a, 0x3b, 0x87, 0x90, 0x96, 0x76, 0x42, 0x51, 0x4d, 0x4f, 0xfe, 0xf1, 0x4e, 0x4e, 0x4e, 0x1e, 0x2a, 0x58, 0xfa, 0x7d, 0x45, 0xfe, 0xea, 0x26, 0x1f, 0x31, 0x30, 0x31, 0x55, 0x53, 0x61, 0x33, 0x37, 0x48, 0x24, 0x05, 0x72, 0x28, 0x42, 0x34, 0x1a, 0x15, 0x3f, 0x4b, 0x9c, 0x94, 0x57, 0x58, 0x58, 0x57, 0x9a, 0x72, 0x5d, 0x24, 0x14, 0x2c, 0x4f, 0x98, 0x27, 0xfe, 0xf8, 0x11, 0x28, 0x40, 0xe4, 0x3f, 0x41, 0x82, 0x6a, 0x70, 0x36, 0x39, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x01, 0xad, 0x02, 0xbc, 0x05, 0x14, 0x00, 0x0a, 0x00, 0x29, 0x00, 0x00, 0x01, 0x22, 0x15, 0x11, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x15, 0x23, 0x35, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x11, 0x34, 0x01, 0xd6, 0x25, 0x37, 0x35, 0x31, 0x32, 0x28, 0x1e, 0x4f, 0x49, 0x4d, 0x4d, 0x49, 0x74, 0x68, 0x71, 0x4b, 0x4d, 0x4d, 0x3a, 0x5d, 0x25, 0x21, 0x30, 0x30, 0x2c, 0x3f, 0x04, 0xbc, 0x51, 0xfe, 0x7f, 0x3a, 0x35, 0x7d, 0x74, 0x3f, 0x33, 0x58, 0x4a, 0x4f, 0xa5, 0x98, 0x5a, 0x55, 0xe2, 0xe1, 0x55, 0x58, 0x9a, 0xa0, 0x52, 0x3d, 0x10, 0x5c, 0x0c, 0x2c, 0x41, 0x6a, 0x71, 0x40, 0x3a, 0x01, 0x81, 0xa9, 0x00, 0x01, 0x00, 0x21, 0x01, 0xad, 0x02, 0x7e, 0x05, 0x10, 0x00, 0x17, 0x00, 0x00, 0x01, 0x27, 0x03, 0x23, 0x13, 0x03, 0x26, 0x2b, 0x01, 0x35, 0x17, 0x16, 0x1f, 0x01, 0x13, 0x33, 0x03, 0x13, 0x16, 0x3b, 0x01, 0x15, 0x27, 0x26, 0x01, 0x9f, 0x55, 0xad, 0x7c, 0xf7, 0x68, 0x1c, 0x57, 0x1c, 0x28, 0x93, 0x24, 0x54, 0xae, 0x7b, 0xf5, 0x66, 0x1c, 0x57, 0x1c, 0x27, 0x93, 0x02, 0x10, 0xd7, 0xfe, 0xc6, 0x01, 0xbc, 0x01, 0x07, 0x47, 0x58, 0x01, 0x04, 0x5d, 0xd7, 0x01, 0x3a, 0xfe, 0x44, 0xfe, 0xf8, 0x46, 0x59, 0x02, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6d, 0x00, 0x00, 0x00, 0xd7, 0x03, 0x67, 0x12, 0x07, 0x07, 0xa1, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x00, 0x00, 0x01, 0xdd, 0x02, 0x82, 0x12, 0x07, 0x02, 0x75, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xf0, 0x02, 0x77, 0x02, 0x73, 0x12, 0x07, 0x05, 0x0e, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x22, 0x00, 0x00, 0x02, 0x8d, 0x02, 0x73, 0x12, 0x07, 0x05, 0x11, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6c, 0xff, 0x11, 0x02, 0x92, 0x03, 0x6f, 0x12, 0x07, 0x05, 0x12, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x12, 0xff, 0x11, 0x02, 0x8d, 0x02, 0x73, 0x12, 0x07, 0x05, 0x13, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6c, 0xff, 0x11, 0x02, 0xa4, 0x02, 0x82, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x10, 0x06, 0x23, 0x22, 0x26, 0x27, 0x11, 0x23, 0x11, 0x34, 0x05, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0xa0, 0x22, 0x56, 0x21, 0x68, 0x73, 0x90, 0x90, 0x73, 0x47, 0x63, 0x22, 0x68, 0x01, 0xcb, 0x5f, 0x52, 0x52, 0x60, 0x60, 0x52, 0x52, 0x5f, 0x02, 0x03, 0x39, 0x32, 0x14, 0xb5, 0xfe, 0xd8, 0xb6, 0x37, 0x38, 0xfe, 0xb3, 0x02, 0x22, 0x81, 0x7b, 0x71, 0x82, 0x82, 0x71, 0x72, 0x81, 0x81, 0xff, 0xff, 0x00, 0x3f, 0xff, 0x11, 0x02, 0xbc, 0x02, 0x78, 0x12, 0x07, 0x05, 0x15, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x21, 0xff, 0x11, 0x02, 0x7e, 0x02, 0x74, 0x12, 0x07, 0x05, 0x16, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2d, 0x04, 0x7b, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x00, 0x13, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x15, 0x23, 0x13, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0xa7, 0xe5, 0xec, 0x57, 0x9b, 0x49, 0x49, 0x8e, 0x4a, 0xa3, 0xa2, 0x33, 0xa0, 0x70, 0xba, 0xe2, 0xe3, 0xb9, 0x70, 0xa0, 0x33, 0xa6, 0xa6, 0x95, 0x86, 0x85, 0x94, 0x94, 0x85, 0x86, 0x95, 0x02, 0x46, 0x01, 0x1e, 0x01, 0x17, 0x1d, 0x1e, 0xb3, 0x2c, 0x2a, 0xbd, 0xbf, 0x5b, 0x63, 0x62, 0xfe, 0xc6, 0xfe, 0xfd, 0xfe, 0xfc, 0xfe, 0xc6, 0x62, 0x63, 0xaa, 0x02, 0x23, 0xc8, 0xdc, 0xdc, 0xc8, 0xc7, 0xdc, 0xdc, 0xff, 0xff, 0x00, 0x72, 0x02, 0x9c, 0x02, 0xf8, 0x05, 0xe0, 0x10, 0x06, 0x04, 0xea, 0x00, 0x00, 0x00, 0x01, 0x00, 0x68, 0x00, 0x00, 0x02, 0x44, 0x04, 0x60, 0x00, 0x13, 0x00, 0x00, 0x13, 0x35, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x68, 0x01, 0xdc, 0x98, 0x98, 0x98, 0x98, 0xfe, 0x24, 0x9f, 0x9f, 0x9f, 0x03, 0xbc, 0xa4, 0xa4, 0xfe, 0xac, 0xa4, 0xfe, 0xe0, 0xa4, 0xa4, 0x01, 0x20, 0xa4, 0x01, 0x54, 0x00, 0x00, 0x00, 0x03, 0x00, 0x2d, 0xfe, 0x56, 0x04, 0xa1, 0x04, 0x7b, 0x00, 0x19, 0x00, 0x22, 0x00, 0x2b, 0x00, 0x00, 0x25, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x33, 0x15, 0x23, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x01, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x01, 0x21, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x01, 0x4e, 0xa7, 0x7a, 0x7a, 0xa7, 0x34, 0x9f, 0x6f, 0xb7, 0x73, 0x5c, 0x13, 0x77, 0x74, 0x0a, 0x68, 0x73, 0xb7, 0x6f, 0x9f, 0x01, 0xfe, 0xfd, 0xcf, 0x07, 0x43, 0x4b, 0x84, 0x83, 0x4c, 0x42, 0xfd, 0xda, 0x02, 0x29, 0x0e, 0x37, 0x4c, 0x83, 0x84, 0x4b, 0x38, 0xa8, 0xfd, 0xae, 0x03, 0xae, 0x90, 0x01, 0xcc, 0xaa, 0x64, 0x61, 0xa2, 0x82, 0xc3, 0x90, 0xea, 0x95, 0xa2, 0x61, 0x01, 0xc0, 0xae, 0x66, 0x74, 0x74, 0x66, 0x01, 0x3e, 0x84, 0x56, 0x74, 0x74, 0x56, 0x00, 0x00, 0x00, 0x01, 0x00, 0x82, 0xfe, 0x56, 0x01, 0xf8, 0x06, 0x14, 0x00, 0x10, 0x00, 0x00, 0x25, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x27, 0x37, 0x23, 0x11, 0x33, 0x11, 0x01, 0xf7, 0x93, 0xa2, 0x40, 0x2c, 0x5f, 0x22, 0x26, 0x03, 0x01, 0xa5, 0xa5, 0x9a, 0xae, 0xd6, 0xc0, 0x9c, 0x30, 0x36, 0x94, 0x14, 0x06, 0x14, 0xfa, 0x86, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x78, 0x05, 0x1e, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x00, 0x13, 0x15, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x24, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x14, 0x17, 0x16, 0x32, 0x37, 0xa8, 0x68, 0x68, 0x22, 0x32, 0x32, 0x46, 0x73, 0x48, 0x49, 0x49, 0x48, 0x73, 0x46, 0x32, 0x32, 0x01, 0x42, 0x30, 0x2f, 0xa5, 0x30, 0x30, 0x30, 0x30, 0xa5, 0x2f, 0x02, 0xfa, 0x5f, 0x02, 0x73, 0x5e, 0x38, 0x1b, 0x1b, 0x5a, 0x5b, 0xfe, 0xd8, 0x5b, 0x5a, 0x1b, 0x1b, 0xa1, 0xe4, 0x41, 0x40, 0x40, 0x41, 0xe4, 0x41, 0x40, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x37, 0x05, 0x1e, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x17, 0x16, 0x02, 0x36, 0x2c, 0x2c, 0x2d, 0x2d, 0x66, 0x38, 0x38, 0x38, 0x38, 0x66, 0x2d, 0x2d, 0x2c, 0x2c, 0x2b, 0x5e, 0x35, 0x8f, 0xa9, 0xab, 0x94, 0x30, 0x2e, 0x2e, 0x04, 0xf7, 0x60, 0x18, 0x0c, 0x0c, 0x40, 0x3f, 0xe6, 0x3f, 0x40, 0x0c, 0x0c, 0x18, 0x5f, 0x14, 0x14, 0xb2, 0x97, 0x99, 0xb0, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x4b, 0x02, 0x37, 0x05, 0x1e, 0x00, 0x07, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x16, 0x33, 0x32, 0x35, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x07, 0x34, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x14, 0x17, 0x16, 0x17, 0x36, 0x33, 0x32, 0x17, 0x16, 0x23, 0x22, 0x01, 0x37, 0x22, 0x2b, 0x53, 0x01, 0x4a, 0x3a, 0x2f, 0x04, 0x56, 0x07, 0x20, 0x1c, 0x54, 0xab, 0x94, 0x2f, 0x2f, 0x2c, 0x2d, 0x2a, 0x2f, 0x2c, 0x2d, 0x66, 0x38, 0x38, 0x38, 0x02, 0x06, 0x2f, 0x6f, 0xa9, 0x01, 0x01, 0xbd, 0x2e, 0x02, 0xee, 0x0b, 0x20, 0x2a, 0x9a, 0x20, 0x26, 0x02, 0x3b, 0x2f, 0x13, 0x1d, 0x5a, 0x96, 0x99, 0xb0, 0x09, 0x0a, 0x14, 0x60, 0x17, 0x0d, 0x0c, 0x3f, 0x40, 0xe6, 0x40, 0x02, 0x05, 0x62, 0x8a, 0x69, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x88, 0x06, 0x03, 0x00, 0x11, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x37, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x27, 0x07, 0x27, 0x37, 0x27, 0x33, 0x17, 0x37, 0x17, 0x07, 0x01, 0xdb, 0x1d, 0x18, 0x19, 0x17, 0x5f, 0x34, 0x35, 0x63, 0x53, 0x51, 0x63, 0x0f, 0x0f, 0x05, 0x47, 0x21, 0x20, 0x51, 0x50, 0x82, 0x84, 0xa0, 0x9c, 0x7e, 0x0a, 0x0f, 0x0e, 0x19, 0x5a, 0xb5, 0x13, 0x9f, 0x67, 0x82, 0x48, 0xbc, 0x13, 0xa7, 0x04, 0x9c, 0x0a, 0x04, 0x05, 0x3d, 0x3c, 0x6d, 0x6a, 0x7c, 0x7c, 0x6a, 0x44, 0x35, 0x34, 0xa5, 0x50, 0x51, 0x50, 0x61, 0x8f, 0x57, 0x57, 0xae, 0x8f, 0x8c, 0xae, 0x02, 0x01, 0x03, 0x65, 0x3c, 0x38, 0x33, 0x72, 0x51, 0x3e, 0x36, 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4b, 0x02, 0x8c, 0x02, 0x25, 0x05, 0x1f, 0x00, 0x31, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x06, 0x01, 0x90, 0x47, 0x26, 0x28, 0x49, 0x4a, 0x87, 0x2d, 0x30, 0x30, 0x32, 0x28, 0x30, 0x30, 0x35, 0x55, 0x31, 0x2f, 0x2c, 0x29, 0x4d, 0x54, 0x57, 0x42, 0x4d, 0x28, 0x27, 0x43, 0x29, 0x2e, 0x2d, 0x37, 0x37, 0x61, 0x2b, 0x6f, 0x40, 0x41, 0x44, 0x03, 0xee, 0x0d, 0x29, 0x29, 0x3c, 0x61, 0x33, 0x33, 0x08, 0x07, 0x10, 0x60, 0x15, 0x0a, 0x0b, 0x20, 0x1f, 0x33, 0x31, 0x1f, 0x1d, 0x55, 0x32, 0x27, 0x24, 0x1a, 0x19, 0x07, 0x07, 0x11, 0x5e, 0x0d, 0x0e, 0x2c, 0x2c, 0x4f, 0x34, 0x48, 0x00, 0x00, 0x01, 0x00, 0x1b, 0x02, 0x9c, 0x01, 0xb0, 0x06, 0x03, 0x00, 0x15, 0x00, 0x00, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x37, 0x36, 0x33, 0x01, 0xaf, 0x64, 0x38, 0x16, 0x16, 0xac, 0xac, 0x69, 0x63, 0x63, 0x32, 0x31, 0x6b, 0x06, 0x03, 0x55, 0x17, 0x16, 0x3a, 0x38, 0x50, 0xfd, 0xdd, 0x02, 0x23, 0x50, 0x2c, 0x69, 0x2f, 0x30, 0x00, 0x00, 0x01, 0xff, 0xeb, 0x01, 0xad, 0x01, 0x3a, 0x05, 0x0f, 0x00, 0x15, 0x00, 0x00, 0x13, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0xd6, 0x2f, 0x2d, 0x67, 0x28, 0x1c, 0x3c, 0x15, 0x16, 0x67, 0x67, 0x68, 0x63, 0x02, 0x9c, 0x0b, 0x78, 0x36, 0x36, 0x58, 0x1b, 0x1c, 0x55, 0x0b, 0x50, 0x02, 0x23, 0xfd, 0xdd, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x01, 0xad, 0x02, 0x78, 0x05, 0x0f, 0x00, 0x0c, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x35, 0x23, 0x22, 0x07, 0x06, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x13, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x02, 0x0f, 0xb2, 0x53, 0x2f, 0x2f, 0x2f, 0x2f, 0x53, 0x55, 0x2f, 0x2e, 0x69, 0x48, 0x48, 0x95, 0x37, 0x31, 0x31, 0x2e, 0x2e, 0x2d, 0x2d, 0x2e, 0x67, 0x33, 0x33, 0x20, 0x32, 0x33, 0x46, 0x75, 0x47, 0x48, 0x48, 0x47, 0x75, 0x03, 0xdd, 0xeb, 0x3e, 0x3d, 0xe0, 0x3d, 0x3e, 0x3e, 0x3d, 0x01, 0xa2, 0xfd, 0xdb, 0xa0, 0x4e, 0x4f, 0x08, 0x09, 0x10, 0x65, 0x19, 0x0c, 0x0b, 0x34, 0x35, 0x6b, 0x33, 0x37, 0x1c, 0x1b, 0x58, 0x58, 0x91, 0x82, 0x58, 0x58, 0x00, 0x00, 0x01, 0x00, 0x63, 0x01, 0xad, 0x02, 0x77, 0x05, 0x0f, 0x00, 0x16, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x63, 0x68, 0x23, 0x24, 0x46, 0x54, 0x31, 0x31, 0x69, 0x69, 0x26, 0x33, 0x31, 0x43, 0x6d, 0x71, 0x03, 0x94, 0x01, 0x7b, 0xfe, 0x88, 0x59, 0x2c, 0x2d, 0x36, 0x35, 0x5c, 0x01, 0x63, 0xfc, 0x9e, 0x01, 0x4f, 0x39, 0x1c, 0x1b, 0x86, 0x00, 0x00, 0x02, 0x00, 0x41, 0x02, 0x9c, 0x01, 0x6e, 0x06, 0x03, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x35, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x11, 0x33, 0x15, 0x23, 0x42, 0x66, 0x69, 0x5c, 0x5c, 0x69, 0x69, 0x69, 0x03, 0x99, 0x5c, 0x01, 0x1a, 0xfe, 0xe6, 0x5c, 0xfd, 0xfd, 0x02, 0x6a, 0x82, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6d, 0x02, 0x9c, 0x01, 0x58, 0x05, 0x0f, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x11, 0xd6, 0x15, 0x15, 0x3d, 0x1b, 0x28, 0x66, 0x5c, 0x05, 0x0f, 0xfe, 0x70, 0x55, 0x1c, 0x1b, 0x57, 0x6c, 0x77, 0x01, 0x90, 0x00, 0x00, 0x01, 0x00, 0x41, 0x02, 0x9c, 0x01, 0x6e, 0x05, 0x0f, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x35, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x42, 0x01, 0x2b, 0x5f, 0x5f, 0xfe, 0xd5, 0x64, 0x04, 0xb3, 0x5c, 0x5c, 0xfe, 0x45, 0x5c, 0x5c, 0x01, 0xbb, 0x00, 0x01, 0x00, 0x41, 0x02, 0x9c, 0x01, 0x6e, 0x05, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x13, 0x35, 0x21, 0x15, 0x23, 0x15, 0x33, 0x15, 0x23, 0x15, 0x33, 0x15, 0x21, 0x35, 0x33, 0x35, 0x23, 0x35, 0x33, 0x35, 0x42, 0x01, 0x2b, 0x5f, 0x5f, 0x5f, 0x5f, 0xfe, 0xd5, 0x64, 0x64, 0x64, 0x04, 0xb3, 0x5c, 0x5c, 0xbe, 0x5c, 0xa1, 0x5c, 0x5c, 0xa1, 0x5c, 0xbe, 0x00, 0x00, 0x00, 0x03, 0xff, 0x67, 0x01, 0xad, 0x01, 0x3d, 0x06, 0x03, 0x00, 0x03, 0x00, 0x12, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x03, 0x22, 0x35, 0x34, 0x3b, 0x01, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x06, 0x07, 0x06, 0x27, 0x23, 0x22, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x6e, 0x68, 0x68, 0x5b, 0xac, 0x99, 0x6e, 0x68, 0x67, 0x6d, 0x0a, 0x1f, 0x2d, 0x12, 0x67, 0x44, 0x02, 0x02, 0x46, 0x3c, 0x15, 0x0a, 0x06, 0x03, 0x82, 0xfc, 0x2c, 0x7c, 0x73, 0x02, 0x73, 0xfd, 0x8d, 0x57, 0x3f, 0x23, 0x35, 0x98, 0x1d, 0x24, 0x1b, 0x0d, 0x00, 0x01, 0x00, 0x6d, 0x01, 0xad, 0x01, 0x58, 0x06, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x6e, 0x68, 0x15, 0x15, 0x3d, 0x1b, 0x28, 0x66, 0x5c, 0x02, 0xe4, 0x03, 0x1f, 0xfc, 0xe1, 0x53, 0x56, 0x1b, 0x1b, 0x58, 0x6c, 0x78, 0x00, 0x00, 0x01, 0x00, 0x51, 0x01, 0xad, 0x01, 0x3d, 0x06, 0x03, 0x00, 0x11, 0x00, 0x00, 0x01, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x27, 0x37, 0x23, 0x11, 0x33, 0x11, 0x01, 0x3d, 0x2e, 0x2f, 0x66, 0x28, 0x1c, 0x3b, 0x16, 0x18, 0x03, 0x02, 0x68, 0x68, 0x02, 0xf2, 0x61, 0x78, 0x36, 0x36, 0x58, 0x1b, 0x1e, 0x53, 0x0b, 0x03, 0x67, 0xfc, 0xef, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0x02, 0x9c, 0x02, 0x43, 0x05, 0x1e, 0x00, 0x05, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x15, 0x21, 0x66, 0x72, 0x01, 0x6b, 0xfe, 0x23, 0x05, 0x1e, 0xfd, 0xdd, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x69, 0x01, 0xad, 0x04, 0x09, 0x05, 0x1e, 0x00, 0x34, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x26, 0x37, 0x34, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x02, 0x5c, 0x27, 0x37, 0x36, 0x49, 0x64, 0x35, 0x36, 0x5c, 0x66, 0x91, 0x84, 0x3c, 0x2b, 0x01, 0x01, 0x41, 0x43, 0x50, 0x2f, 0x30, 0x68, 0x21, 0x20, 0x44, 0x50, 0x2f, 0x2e, 0x6a, 0x6a, 0x23, 0x32, 0x32, 0x45, 0x44, 0x31, 0x30, 0x04, 0x97, 0x45, 0x21, 0x21, 0x45, 0x44, 0x7e, 0xfe, 0x7a, 0x78, 0x6c, 0x58, 0x36, 0x56, 0x30, 0xe8, 0x3d, 0x2d, 0x5a, 0x58, 0x35, 0x36, 0x5c, 0xfe, 0x9e, 0x01, 0x77, 0x5b, 0x2c, 0x2b, 0x35, 0x36, 0x5c, 0xfe, 0x9e, 0x02, 0x73, 0x61, 0x39, 0x1c, 0x1b, 0x22, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x01, 0xad, 0x04, 0x09, 0x05, 0x10, 0x00, 0x28, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x02, 0x16, 0x27, 0x36, 0x37, 0x4a, 0x63, 0x6c, 0x6a, 0x20, 0x20, 0x42, 0x51, 0x30, 0x2f, 0x68, 0x20, 0x21, 0x43, 0x50, 0x2f, 0x30, 0x68, 0x68, 0x24, 0x32, 0x32, 0x44, 0x46, 0x61, 0x03, 0x15, 0x45, 0x22, 0x21, 0x8a, 0x7e, 0x01, 0x7b, 0xfe, 0x89, 0x5b, 0x2b, 0x2c, 0x35, 0x35, 0x5c, 0x01, 0x63, 0xfe, 0x89, 0x5b, 0x2b, 0x2c, 0x36, 0x35, 0x5b, 0x01, 0x63, 0xfc, 0x9d, 0x01, 0x51, 0x3a, 0x1b, 0x1c, 0x46, 0x00, 0x00, 0x00, 0x01, 0xff, 0xeb, 0x01, 0xad, 0x02, 0x82, 0x05, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0x13, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0xd6, 0x2f, 0x2d, 0x67, 0x28, 0x1c, 0x3c, 0x2b, 0x68, 0x26, 0x65, 0x42, 0x6e, 0x38, 0x39, 0x69, 0x23, 0x24, 0x46, 0x55, 0x30, 0x31, 0x02, 0x91, 0x78, 0x36, 0x36, 0x58, 0x36, 0x56, 0x02, 0x7e, 0x61, 0x38, 0x38, 0x42, 0x44, 0x81, 0xfe, 0x85, 0x01, 0x77, 0x59, 0x2c, 0x2d, 0x35, 0x36, 0x5c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x01, 0xad, 0x03, 0x00, 0x05, 0x1e, 0x00, 0x20, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x02, 0x15, 0x23, 0x23, 0x47, 0x54, 0x31, 0x30, 0x6a, 0x6a, 0x25, 0x32, 0x33, 0x43, 0x6d, 0x38, 0x38, 0x2b, 0x3c, 0x1c, 0x28, 0x66, 0x2e, 0x2f, 0x04, 0x13, 0x59, 0x2c, 0x2d, 0x35, 0x36, 0x5c, 0xfe, 0x9e, 0x02, 0x73, 0x61, 0x38, 0x1c, 0x1c, 0x42, 0x44, 0x81, 0xfe, 0x7a, 0x56, 0x36, 0x58, 0x36, 0x36, 0x78, 0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0x02, 0x9c, 0x02, 0x7e, 0x05, 0x1e, 0x00, 0x09, 0x00, 0x00, 0x13, 0x33, 0x01, 0x11, 0x33, 0x11, 0x23, 0x01, 0x11, 0x23, 0x66, 0x9a, 0x01, 0x0e, 0x6f, 0x9a, 0xfe, 0xf1, 0x6e, 0x05, 0x1e, 0xfe, 0x07, 0x01, 0xf9, 0xfd, 0x7e, 0x01, 0xfa, 0xfe, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x3f, 0x02, 0x8c, 0x02, 0x88, 0x05, 0x1e, 0x00, 0x0f, 0x00, 0x17, 0x00, 0x20, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x16, 0x22, 0x07, 0x06, 0x07, 0x21, 0x26, 0x27, 0x17, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x01, 0x64, 0x87, 0x4f, 0x4d, 0x4d, 0x4f, 0x87, 0x89, 0x4d, 0x4e, 0x4e, 0x4d, 0xdc, 0xa7, 0x31, 0x2a, 0x06, 0x01, 0x69, 0x06, 0x2a, 0x2c, 0xfe, 0x9e, 0x0a, 0x22, 0x31, 0x55, 0x53, 0x31, 0x22, 0x05, 0x1e, 0x57, 0x57, 0x9b, 0x9a, 0x57, 0x58, 0x58, 0x57, 0x9a, 0x9b, 0x57, 0x57, 0x57, 0x40, 0x39, 0x5c, 0x5b, 0x38, 0xef, 0x45, 0x2d, 0x41, 0x41, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x3f, 0x01, 0xae, 0x02, 0x88, 0x06, 0x03, 0x00, 0x1d, 0x00, 0x26, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x23, 0x35, 0x21, 0x15, 0x23, 0x15, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x15, 0x33, 0x15, 0x21, 0x35, 0x33, 0x35, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x17, 0x11, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x03, 0x11, 0x06, 0x07, 0x06, 0x14, 0x17, 0x16, 0x01, 0x2e, 0x88, 0x01, 0x78, 0x88, 0x65, 0x3f, 0x4d, 0x4d, 0x3f, 0x65, 0x88, 0xfe, 0x88, 0x88, 0x64, 0x3c, 0x4e, 0x4e, 0x3c, 0x64, 0x68, 0x30, 0x22, 0x30, 0x30, 0x22, 0x98, 0x2f, 0x20, 0x31, 0x30, 0x21, 0x05, 0xa7, 0x5c, 0x5c, 0x8c, 0x0e, 0x46, 0x57, 0x9b, 0x9a, 0x57, 0x47, 0x0e, 0x85, 0x5c, 0x5c, 0x86, 0x0e, 0x46, 0x57, 0x9a, 0x9b, 0x57, 0x45, 0x0f, 0x5b, 0xfe, 0x2a, 0x0e, 0x2c, 0x41, 0x70, 0x6f, 0x41, 0x2d, 0xfe, 0x39, 0x01, 0xd4, 0x0e, 0x2a, 0x41, 0xe2, 0x40, 0x2b, 0x00, 0x01, 0x00, 0x3f, 0x01, 0xad, 0x02, 0x25, 0x05, 0x1e, 0x00, 0x3a, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x15, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x3d, 0x02, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x02, 0x02, 0x2c, 0x60, 0x32, 0x4e, 0x26, 0x28, 0x1c, 0x1c, 0x54, 0x24, 0x6e, 0x2f, 0x2f, 0x45, 0x46, 0x7b, 0x33, 0x38, 0x0c, 0x2c, 0x3b, 0x84, 0x90, 0x66, 0x2e, 0x2f, 0x3a, 0x38, 0x38, 0x37, 0x4a, 0x4f, 0x1c, 0x1d, 0x61, 0x25, 0x60, 0x56, 0x3f, 0x3f, 0x75, 0x3a, 0x67, 0x04, 0xfd, 0x62, 0x17, 0x16, 0x17, 0x18, 0x2f, 0x24, 0x15, 0x14, 0x12, 0x08, 0x18, 0x2b, 0x2a, 0x4d, 0x57, 0x33, 0x33, 0x09, 0x03, 0x07, 0x56, 0x36, 0x58, 0x36, 0x36, 0x78, 0x22, 0x6a, 0x1d, 0x0f, 0x0f, 0x32, 0x2d, 0x2a, 0x17, 0x16, 0x15, 0x08, 0x14, 0x54, 0x49, 0x58, 0x30, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xeb, 0x01, 0xad, 0x01, 0x9d, 0x06, 0x03, 0x00, 0x17, 0x00, 0x00, 0x13, 0x02, 0x03, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x13, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x6e, 0x01, 0x01, 0x32, 0x2d, 0x6e, 0x63, 0x64, 0x38, 0x15, 0x17, 0x02, 0x2f, 0x2d, 0x67, 0x28, 0x1c, 0x3c, 0x2b, 0x02, 0x91, 0x01, 0x5d, 0x01, 0x4d, 0x65, 0x33, 0x30, 0x55, 0x17, 0x16, 0x3a, 0xfd, 0x4a, 0x78, 0x36, 0x36, 0x58, 0x36, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1f, 0x01, 0xad, 0x01, 0xac, 0x05, 0xc1, 0x00, 0x1f, 0x00, 0x00, 0x13, 0x15, 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x35, 0xd4, 0xd8, 0xd8, 0x2c, 0x40, 0x6c, 0x2f, 0x2e, 0x67, 0x27, 0x1b, 0x3c, 0x2b, 0x03, 0x78, 0x2e, 0x2e, 0x4c, 0x4c, 0x05, 0xc1, 0xb2, 0x50, 0xfe, 0xac, 0x4d, 0x2c, 0x61, 0x78, 0x36, 0x36, 0x58, 0x36, 0x56, 0x0b, 0x2d, 0x2c, 0x76, 0x01, 0x54, 0x50, 0xb2, 0x00, 0x02, 0x00, 0x54, 0x02, 0x8c, 0x03, 0x35, 0x05, 0x0f, 0x00, 0x17, 0x00, 0x21, 0x00, 0x00, 0x13, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x29, 0x01, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x55, 0x63, 0x68, 0x01, 0x43, 0x69, 0x69, 0x69, 0x69, 0x27, 0x32, 0x32, 0x42, 0x6d, 0x71, 0x01, 0xaa, 0xfe, 0xbe, 0x23, 0x23, 0x46, 0x55, 0x31, 0x2c, 0x03, 0x99, 0x5c, 0x01, 0x1a, 0xfe, 0xe6, 0x01, 0x1a, 0xfe, 0xe6, 0x5c, 0xfd, 0x60, 0x39, 0x1c, 0x1b, 0x86, 0x82, 0x05, 0x02, 0x59, 0x2c, 0x2d, 0x36, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3f, 0x02, 0x8b, 0x02, 0x90, 0x05, 0x0f, 0x00, 0x26, 0x00, 0x00, 0x13, 0x35, 0x33, 0x15, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x35, 0x33, 0x15, 0x23, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x20, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x40, 0xfb, 0x3e, 0x24, 0x25, 0x32, 0x32, 0x51, 0x52, 0x31, 0x33, 0x26, 0x28, 0x38, 0xf6, 0x85, 0x40, 0x20, 0x1f, 0x51, 0x50, 0xff, 0x00, 0x50, 0x51, 0x1e, 0x1e, 0x43, 0x04, 0xb3, 0x5c, 0x7b, 0x27, 0x3a, 0x3f, 0x4b, 0x59, 0x37, 0x36, 0x36, 0x37, 0x59, 0x52, 0x38, 0x3e, 0x23, 0x7b, 0x5c, 0x38, 0x3f, 0x3e, 0x4c, 0x83, 0x52, 0x52, 0x51, 0x52, 0x80, 0x52, 0x3c, 0x3d, 0x3a, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x8a, 0x02, 0x51, 0x05, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x01, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x01, 0x5d, 0x49, 0x41, 0x69, 0x3d, 0x3e, 0x78, 0x78, 0x3f, 0x3d, 0x6a, 0x40, 0x02, 0xe2, 0x50, 0x5a, 0x01, 0x83, 0xfe, 0x73, 0x7b, 0x3e, 0x3f, 0x3f, 0x3e, 0x7b, 0x01, 0x8d, 0xfe, 0x7d, 0x5a, 0x50, 0x00, 0x00, 0x01, 0x00, 0x6d, 0x02, 0x9c, 0x02, 0x79, 0x05, 0x0f, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x33, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3f, 0x01, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x01, 0x43, 0xb7, 0x41, 0x1f, 0x1f, 0x50, 0x51, 0x80, 0x28, 0x66, 0x5c, 0x68, 0x15, 0x17, 0x3b, 0x1d, 0x51, 0x32, 0x31, 0x24, 0x2d, 0x35, 0x2b, 0x04, 0xc4, 0x38, 0x3f, 0x3e, 0x4c, 0x83, 0x52, 0x52, 0x6c, 0x77, 0x01, 0x90, 0xfe, 0x70, 0x55, 0x1c, 0x1c, 0x01, 0x01, 0x36, 0x37, 0x59, 0x51, 0x38, 0x43, 0x1f, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x22, 0x02, 0x9c, 0x02, 0x8d, 0x05, 0x0f, 0x00, 0x06, 0x00, 0x00, 0x01, 0x23, 0x0b, 0x01, 0x23, 0x13, 0x33, 0x02, 0x8c, 0x6e, 0xc6, 0xc7, 0x6f, 0xef, 0x8e, 0x02, 0x9c, 0x02, 0x0e, 0xfd, 0xf2, 0x02, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0x02, 0x9c, 0x02, 0x30, 0x05, 0x0f, 0x00, 0x09, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x21, 0x40, 0x01, 0xf0, 0xfe, 0x77, 0x01, 0x89, 0xfe, 0x02, 0x01, 0x88, 0xfe, 0x86, 0x05, 0x0f, 0x5e, 0xfe, 0x3d, 0x52, 0x5e, 0x01, 0xc3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0x01, 0xad, 0x02, 0xb1, 0x05, 0x0f, 0x00, 0x16, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x21, 0x15, 0x23, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x21, 0x35, 0x01, 0x21, 0x40, 0x01, 0xf0, 0xfe, 0x77, 0x01, 0x89, 0x01, 0x15, 0x15, 0x3d, 0x1a, 0x27, 0x67, 0x5c, 0xfe, 0x6c, 0x01, 0x88, 0xfe, 0x86, 0x05, 0x0f, 0x5e, 0xfe, 0x3d, 0x52, 0x0b, 0x56, 0x1b, 0x1b, 0x58, 0x6c, 0x78, 0x0b, 0x5e, 0x01, 0xc3, 0x00, 0x00, 0x02, 0x00, 0x31, 0x02, 0x5e, 0x02, 0x30, 0x05, 0x0f, 0x00, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x06, 0x15, 0x23, 0x34, 0x37, 0x23, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x33, 0x36, 0x33, 0x32, 0x15, 0x14, 0x23, 0x27, 0x33, 0x32, 0x35, 0x34, 0x23, 0x06, 0x01, 0x56, 0x02, 0x56, 0x02, 0xce, 0x01, 0x88, 0xfe, 0x86, 0x01, 0xf0, 0xfe, 0x77, 0x63, 0x23, 0x7c, 0x81, 0xbd, 0x0b, 0x0b, 0x63, 0x28, 0x32, 0x02, 0x9c, 0x1d, 0x21, 0x21, 0x1d, 0x5e, 0x01, 0xc3, 0x52, 0x5e, 0xfe, 0x3d, 0xa2, 0x8a, 0x6a, 0x52, 0x1f, 0x33, 0x01, 0x00, 0x01, 0x00, 0x31, 0x01, 0xa8, 0x02, 0x60, 0x05, 0x0f, 0x00, 0x21, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x13, 0x21, 0x35, 0x21, 0x15, 0x01, 0x44, 0x3c, 0x49, 0x38, 0x31, 0x2e, 0x57, 0x56, 0x9f, 0x35, 0x39, 0x38, 0x3c, 0x2f, 0x72, 0x3e, 0x6c, 0x37, 0x39, 0x34, 0x34, 0x5e, 0x63, 0xf4, 0xfe, 0x86, 0x01, 0xef, 0x03, 0xa7, 0x20, 0x17, 0x3d, 0x3b, 0x4d, 0x7c, 0x43, 0x44, 0x0a, 0x0b, 0x14, 0x6d, 0x1b, 0x1c, 0x2a, 0x2a, 0x50, 0x4a, 0x2a, 0x29, 0x5d, 0x01, 0x18, 0x52, 0x5e, 0x00, 0x03, 0x00, 0x3f, 0x02, 0x8f, 0x02, 0x88, 0x06, 0x0c, 0x00, 0x08, 0x00, 0x10, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x13, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x26, 0x10, 0x37, 0x36, 0x02, 0x18, 0xfe, 0x97, 0x05, 0x2a, 0x31, 0x55, 0x53, 0x31, 0x2a, 0x05, 0x09, 0x26, 0x31, 0xa7, 0x31, 0x27, 0x08, 0xb4, 0x87, 0x4f, 0x4d, 0x4d, 0x4f, 0x87, 0x89, 0x9b, 0x4d, 0x4e, 0x04, 0x2a, 0x80, 0x4d, 0x57, 0x58, 0x4d, 0xde, 0x6d, 0x47, 0x59, 0x58, 0x46, 0x6f, 0x01, 0x83, 0x76, 0x77, 0xfe, 0x5e, 0x77, 0x77, 0xee, 0x01, 0xa2, 0x77, 0x76, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xb8, 0x04, 0xee, 0xff, 0xaf, 0x06, 0x66, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x37, 0x33, 0xfe, 0xd2, 0xfd, 0xe6, 0x01, 0xe2, 0x97, 0x7d, 0x04, 0xee, 0x94, 0xe4, 0x00, 0x01, 0xfc, 0xb8, 0x04, 0xee, 0xff, 0xaf, 0x06, 0x66, 0x00, 0x05, 0x00, 0x00, 0x01, 0x03, 0x33, 0x17, 0x21, 0x15, 0xfd, 0x95, 0xdd, 0x7d, 0x98, 0x01, 0xe1, 0x04, 0xee, 0x01, 0x78, 0xe4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xb8, 0x04, 0xee, 0xff, 0xaf, 0x06, 0x66, 0x00, 0x05, 0x00, 0x00, 0x01, 0x13, 0x23, 0x27, 0x21, 0x35, 0xfe, 0xd2, 0xdc, 0x7d, 0x97, 0xfe, 0x1e, 0x06, 0x66, 0xfe, 0x88, 0xe4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0xb8, 0x04, 0xee, 0xff, 0xaf, 0x06, 0x66, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x07, 0x23, 0xfd, 0x95, 0x02, 0x19, 0xfe, 0x1f, 0x98, 0x7d, 0x06, 0x66, 0x94, 0xe4, 0x00, 0x01, 0xfc, 0xa1, 0x04, 0xee, 0xff, 0xc5, 0x06, 0x66, 0x00, 0x09, 0x00, 0x00, 0x01, 0x33, 0x13, 0x23, 0x27, 0x07, 0x23, 0x03, 0x33, 0x17, 0xfe, 0x63, 0x85, 0xdd, 0x7d, 0xa2, 0xa2, 0x86, 0xdc, 0x7d, 0xa2, 0x06, 0x66, 0xfe, 0x88, 0xf5, 0xf5, 0x01, 0x78, 0xf5, 0x00, 0x01, 0xfc, 0xa1, 0x04, 0xee, 0xff, 0xc5, 0x06, 0x66, 0x00, 0x09, 0x00, 0x00, 0x01, 0x17, 0x37, 0x33, 0x03, 0x23, 0x27, 0x07, 0x23, 0x13, 0xfe, 0x04, 0xa2, 0xa2, 0x7d, 0xdd, 0x85, 0xa2, 0xa2, 0x7d, 0xdc, 0x06, 0x66, 0xf5, 0xf5, 0xfe, 0x88, 0xf5, 0xf5, 0x01, 0x78, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x13, 0x04, 0xde, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd6, 0x04, 0x43, 0x00, 0x01, 0x12, 0x06, 0x00, 0x24, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xfe, 0x13, 0x03, 0xc3, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd6, 0x03, 0xe5, 0x00, 0x01, 0x12, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x43, 0x01, 0x75, 0x12, 0x06, 0x00, 0x25, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa5, 0xff, 0xe3, 0x04, 0x2e, 0x07, 0x52, 0x10, 0x27, 0x02, 0xb8, 0x02, 0xc7, 0x01, 0x3e, 0x12, 0x06, 0x00, 0x45, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x04, 0x6e, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x25, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x2e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x89, 0x04, 0x2e, 0x06, 0x14, 0x12, 0x26, 0x00, 0x45, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x24, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0xc0, 0x04, 0x6e, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x25, 0x00, 0x00, 0x10, 0x07, 0x02, 0x8f, 0x00, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0xc0, 0x04, 0x2e, 0x06, 0x14, 0x12, 0x26, 0x00, 0x45, 0x00, 0x00, 0x10, 0x07, 0x02, 0x8f, 0x00, 0x81, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0x75, 0x04, 0xa4, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0xc4, 0x01, 0x76, 0x12, 0x06, 0x00, 0x89, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x03, 0x84, 0x06, 0x66, 0x12, 0x26, 0x00, 0xa9, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x3c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x1f, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x6e, 0x01, 0x75, 0x12, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xeb, 0x07, 0x89, 0x10, 0x27, 0x02, 0xb8, 0x05, 0x65, 0x01, 0x75, 0x12, 0x06, 0x00, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x8a, 0x05, 0x1f, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x6e, 0x00, 0x01, 0x12, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x8a, 0x03, 0xeb, 0x06, 0x14, 0x10, 0x27, 0x02, 0xd4, 0x03, 0xf5, 0x00, 0x01, 0x12, 0x06, 0x00, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0xc1, 0x05, 0x1f, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xe2, 0x04, 0x6e, 0x00, 0x01, 0x12, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0xc1, 0x03, 0xeb, 0x06, 0x14, 0x10, 0x27, 0x02, 0xe2, 0x03, 0xf5, 0x00, 0x01, 0x12, 0x06, 0x00, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x77, 0x05, 0x1f, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x27, 0x00, 0x00, 0x10, 0x06, 0x00, 0x7a, 0x52, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x03, 0xeb, 0x06, 0x14, 0x12, 0x26, 0x00, 0x47, 0x00, 0x00, 0x10, 0x06, 0x00, 0x7a, 0xf7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x15, 0x05, 0x1f, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xde, 0x04, 0x6e, 0x00, 0x01, 0x12, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x15, 0x03, 0xeb, 0x06, 0x14, 0x10, 0x27, 0x02, 0xde, 0x03, 0xf5, 0x00, 0x01, 0x12, 0x06, 0x00, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x06, 0x11, 0x24, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x07, 0x5e, 0x10, 0x27, 0x11, 0x24, 0xff, 0xdd, 0xff, 0x04, 0x12, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x06, 0x11, 0x23, 0xee, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x07, 0x5e, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x07, 0x11, 0x23, 0xff, 0xdb, 0xff, 0x04, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x4b, 0x04, 0x17, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x02, 0xde, 0x04, 0x39, 0x00, 0x37, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x4b, 0x04, 0x0c, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x07, 0x02, 0xde, 0x04, 0x38, 0x00, 0x37, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x76, 0x04, 0x17, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x02, 0xb0, 0x00, 0xa1, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x76, 0x04, 0x0c, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x07, 0x02, 0xb0, 0x00, 0x8c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x75, 0x04, 0x17, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xf2, 0x04, 0x2a, 0x01, 0x75, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x00, 0x7a, 0x00, 0xab, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x75, 0x04, 0x0c, 0x06, 0x48, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x26, 0x02, 0x9a, 0x7a, 0x00, 0x10, 0x06, 0x00, 0x7a, 0x44, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xba, 0x07, 0x4f, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x04, 0x01, 0x74, 0x12, 0x06, 0x00, 0x29, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, 0x07, 0x89, 0x10, 0x27, 0x02, 0xb8, 0x03, 0x7d, 0x01, 0x75, 0x12, 0x06, 0x00, 0x49, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x07, 0x18, 0x12, 0x26, 0x00, 0x2a, 0x00, 0x00, 0x10, 0x07, 0x02, 0x8b, 0x01, 0x13, 0x01, 0x22, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x05, 0xf6, 0x12, 0x26, 0x00, 0x4a, 0x00, 0x00, 0x10, 0x06, 0x02, 0x8b, 0x42, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x92, 0x01, 0x73, 0x12, 0x06, 0x00, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa5, 0x00, 0x00, 0x03, 0xf4, 0x07, 0x52, 0x10, 0x27, 0x02, 0xb8, 0x02, 0xc7, 0x01, 0x3e, 0x12, 0x06, 0x00, 0x4b, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x04, 0xb6, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x82, 0x00, 0x00, 0x12, 0x06, 0x00, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x89, 0x03, 0xf4, 0x06, 0x14, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x1a, 0x00, 0x00, 0x12, 0x06, 0x00, 0x4b, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x07, 0x50, 0x12, 0x26, 0x00, 0x2b, 0x00, 0x00, 0x10, 0x07, 0x00, 0x6a, 0x00, 0xee, 0x01, 0x40, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x03, 0xf4, 0x07, 0x4e, 0x10, 0x27, 0x02, 0xb9, 0x02, 0xc7, 0x01, 0x3e, 0x12, 0x06, 0x00, 0x4b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0xfe, 0x74, 0x04, 0xb6, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x2b, 0x00, 0x00, 0x10, 0x07, 0x00, 0x7a, 0xff, 0x09, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xfe, 0x74, 0x03, 0xf4, 0x06, 0x14, 0x12, 0x26, 0x00, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x00, 0x7a, 0xfe, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x39, 0x04, 0xb6, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x2b, 0x00, 0x00, 0x10, 0x07, 0x02, 0xdf, 0x04, 0x89, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x39, 0x03, 0xf4, 0x06, 0x14, 0x12, 0x26, 0x00, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x02, 0xdf, 0x04, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xfe, 0x76, 0x02, 0x52, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x02, 0xb0, 0xff, 0x5c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xd7, 0xfe, 0x76, 0x02, 0x2a, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb0, 0xff, 0x34, 0x00, 0x00, 0x12, 0x06, 0x00, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x02, 0x1d, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x11, 0x21, 0xfe, 0x9c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf5, 0x00, 0x00, 0x02, 0x0c, 0x07, 0x16, 0x12, 0x26, 0x00, 0xf3, 0x00, 0x00, 0x10, 0x07, 0x11, 0x21, 0xfe, 0x8a, 0xfe, 0xbc, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xe0, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0x65, 0x01, 0x76, 0x12, 0x06, 0x00, 0x2e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x26, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x03, 0x04, 0x01, 0x76, 0x12, 0x06, 0x00, 0x4e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x04, 0xe0, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x2e, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x60, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x89, 0x04, 0x26, 0x06, 0x14, 0x12, 0x26, 0x00, 0x4e, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x1c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0xc0, 0x04, 0xe0, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x2e, 0x00, 0x00, 0x10, 0x07, 0x02, 0x8f, 0x00, 0xf2, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0xc0, 0x04, 0x26, 0x06, 0x14, 0x12, 0x26, 0x00, 0x4e, 0x00, 0x00, 0x10, 0x06, 0x02, 0x8f, 0x6a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x03, 0xf9, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x24, 0x00, 0x00, 0x10, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x01, 0x5e, 0x06, 0x14, 0x10, 0x27, 0x02, 0xd4, 0x02, 0xd6, 0x00, 0x00, 0x10, 0x06, 0x00, 0x4f, 0x0a, 0x00, 0xff, 0xff, 0x00, 0x02, 0xfe, 0x8a, 0x03, 0xf9, 0x07, 0x6b, 0x10, 0x27, 0x02, 0xb5, 0x02, 0xd9, 0x01, 0x75, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x23, 0x00, 0x01, 0x12, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfd, 0xfe, 0x89, 0x02, 0x18, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0xff, 0x3e, 0x01, 0x3b, 0x10, 0x06, 0x05, 0x87, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0xc0, 0x03, 0xf9, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x2f, 0x00, 0x00, 0x10, 0x07, 0x02, 0x8f, 0x00, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf5, 0xfe, 0xc0, 0x02, 0x10, 0x06, 0x14, 0x10, 0x27, 0x02, 0x8f, 0xff, 0x36, 0x00, 0x00, 0x12, 0x06, 0x00, 0x4f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x14, 0x03, 0xf9, 0x05, 0xd5, 0x10, 0x27, 0x02, 0x88, 0x00, 0x88, 0xf9, 0x26, 0x12, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe1, 0xfe, 0x14, 0x02, 0x20, 0x06, 0x14, 0x10, 0x27, 0x02, 0x88, 0xff, 0x34, 0xf9, 0x26, 0x12, 0x06, 0x00, 0x4f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0xe8, 0x01, 0x76, 0x12, 0x06, 0x00, 0x30, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x06, 0x67, 0x06, 0x66, 0x12, 0x26, 0x00, 0x50, 0x00, 0x00, 0x10, 0x07, 0x00, 0x76, 0x01, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x07, 0x4f, 0x10, 0x27, 0x10, 0xf3, 0x04, 0xeb, 0x01, 0x74, 0x12, 0x06, 0x00, 0x30, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x06, 0x67, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x05, 0x52, 0x00, 0x00, 0x12, 0x06, 0x00, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x05, 0x83, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x04, 0xe8, 0x00, 0x00, 0x10, 0x06, 0x00, 0x30, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x89, 0x06, 0x67, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd4, 0x05, 0x4f, 0x00, 0x00, 0x10, 0x06, 0x00, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x76, 0x01, 0x75, 0x12, 0x06, 0x00, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x04, 0x15, 0x00, 0x00, 0x12, 0x06, 0x00, 0x51, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x04, 0xae, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x7e, 0x00, 0x00, 0x10, 0x06, 0x00, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x89, 0x03, 0xf4, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x1a, 0x00, 0x00, 0x10, 0x06, 0x00, 0x51, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0xc0, 0x04, 0xae, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x31, 0x00, 0x00, 0x10, 0x07, 0x02, 0x8f, 0x00, 0xde, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0xc0, 0x03, 0xf4, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x51, 0x00, 0x00, 0x10, 0x06, 0x02, 0x8f, 0x7e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x14, 0x04, 0xae, 0x05, 0xd5, 0x10, 0x27, 0x02, 0x88, 0x00, 0xe5, 0xf9, 0x26, 0x12, 0x06, 0x00, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x14, 0x03, 0xf4, 0x04, 0x7b, 0x10, 0x27, 0x02, 0x88, 0x00, 0x86, 0xf9, 0x26, 0x12, 0x06, 0x00, 0x51, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x29, 0x5c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x07, 0x0c, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x10, 0x07, 0x11, 0x29, 0xff, 0xba, 0xfe, 0xb2, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x56, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x27, 0x61, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x07, 0x0f, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x10, 0x27, 0x00, 0x6a, 0x00, 0x64, 0x00, 0xff, 0x10, 0x07, 0x10, 0xed, 0x04, 0x00, 0x00, 0x12, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x24, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x07, 0x5e, 0x10, 0x26, 0x00, 0x52, 0x00, 0x00, 0x10, 0x07, 0x11, 0x24, 0xff, 0xbc, 0xff, 0x04, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x23, 0x5e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x07, 0x5e, 0x10, 0x27, 0x11, 0x23, 0xff, 0xc0, 0xff, 0x04, 0x10, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x19, 0x07, 0x6c, 0x10, 0x27, 0x10, 0xec, 0x04, 0x28, 0x01, 0x76, 0x12, 0x06, 0x00, 0x33, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x66, 0x12, 0x26, 0x00, 0x53, 0x00, 0x00, 0x10, 0x06, 0x00, 0x76, 0x2d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x19, 0x07, 0x4f, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x10, 0x01, 0x74, 0x12, 0x06, 0x00, 0x33, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x04, 0x2f, 0x00, 0x00, 0x12, 0x06, 0x00, 0x53, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xcc, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x10, 0x01, 0x73, 0x12, 0x06, 0x00, 0x35, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x02, 0xf6, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xae, 0x00, 0x00, 0x12, 0x06, 0x00, 0x55, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x04, 0xcc, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x0a, 0x00, 0x00, 0x10, 0x06, 0x00, 0x35, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x89, 0x02, 0xf6, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd4, 0x02, 0xd0, 0x00, 0x00, 0x10, 0x06, 0x00, 0x55, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x04, 0xcc, 0x07, 0x31, 0x10, 0x27, 0x00, 0x71, 0x00, 0x70, 0x01, 0x3b, 0x10, 0x06, 0x05, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x89, 0x02, 0xf6, 0x05, 0xf5, 0x10, 0x26, 0x00, 0x71, 0x15, 0xff, 0x10, 0x06, 0x05, 0xab, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0xc0, 0x04, 0xcc, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x35, 0x00, 0x00, 0x10, 0x07, 0x02, 0x8f, 0x00, 0xce, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, 0xfe, 0xc0, 0x02, 0xf6, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x55, 0x00, 0x00, 0x10, 0x06, 0x02, 0x8f, 0x8c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x07, 0x4f, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x3f, 0x01, 0x74, 0x12, 0x06, 0x00, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xbd, 0x00, 0x00, 0x12, 0x06, 0x00, 0x56, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x89, 0x04, 0x2c, 0x05, 0xf0, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x16, 0x00, 0x00, 0x10, 0x06, 0x00, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xfe, 0x8a, 0x03, 0x67, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd4, 0x03, 0xbb, 0x00, 0x01, 0x12, 0x06, 0x00, 0x56, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xec, 0x04, 0x65, 0x01, 0x76, 0x10, 0x27, 0x10, 0xf3, 0x03, 0x47, 0x01, 0x92, 0x12, 0x06, 0x00, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x7f, 0x06, 0x66, 0x12, 0x26, 0x00, 0x56, 0x00, 0x00, 0x10, 0x26, 0x02, 0x9b, 0x98, 0x56, 0x10, 0x07, 0x00, 0x76, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x08, 0x57, 0x10, 0x26, 0x11, 0x28, 0xe7, 0x00, 0x12, 0x06, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x07, 0xc9, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xc2, 0x01, 0xb5, 0x12, 0x06, 0x01, 0x23, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x89, 0x04, 0x2c, 0x07, 0x4f, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x25, 0x01, 0x74, 0x12, 0x06, 0x05, 0xb2, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xfe, 0x8a, 0x03, 0x67, 0x05, 0xde, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xbd, 0xff, 0xca, 0x12, 0x06, 0x05, 0xb3, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0x00, 0x00, 0x04, 0x6c, 0x07, 0x4f, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x00, 0x01, 0x74, 0x12, 0x06, 0x00, 0x37, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0x00, 0x00, 0x02, 0xa7, 0x07, 0x89, 0x10, 0x27, 0x02, 0xb8, 0x02, 0xcb, 0x01, 0x75, 0x12, 0x06, 0x00, 0x57, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0xfe, 0x89, 0x04, 0x6c, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x03, 0xff, 0x00, 0x00, 0x10, 0x06, 0x00, 0x37, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0xfe, 0x89, 0x02, 0xa7, 0x05, 0x9e, 0x10, 0x27, 0x02, 0xd4, 0x03, 0x84, 0x00, 0x00, 0x10, 0x06, 0x00, 0x57, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0xfe, 0xc0, 0x04, 0x6c, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x37, 0x00, 0x00, 0x10, 0x06, 0x02, 0x8f, 0x58, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0xfe, 0xc0, 0x02, 0xd0, 0x05, 0x9e, 0x10, 0x26, 0x02, 0x8f, 0xf5, 0x00, 0x12, 0x06, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0xfe, 0x14, 0x04, 0x6c, 0x05, 0xd5, 0x10, 0x27, 0x02, 0x88, 0x00, 0x67, 0xf9, 0x26, 0x12, 0x06, 0x00, 0x37, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0xfe, 0x14, 0x02, 0xd6, 0x05, 0x9e, 0x10, 0x27, 0x02, 0x88, 0xff, 0xea, 0xf9, 0x26, 0x12, 0x06, 0x00, 0x57, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xfe, 0x89, 0x04, 0xa5, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd5, 0x04, 0x72, 0x00, 0x00, 0x12, 0x06, 0x00, 0x38, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xfe, 0x89, 0x03, 0xe9, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd5, 0x04, 0x08, 0x00, 0x00, 0x12, 0x06, 0x00, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xfe, 0x76, 0x04, 0xa5, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x02, 0xb0, 0x00, 0xda, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xfe, 0x76, 0x03, 0xe9, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x07, 0x02, 0xb0, 0x00, 0x81, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xfe, 0x4b, 0x04, 0xa5, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x02, 0xde, 0x04, 0x63, 0x00, 0x37, 0xff, 0xff, 0x00, 0x9c, 0xfe, 0x4b, 0x03, 0xe9, 0x04, 0x7b, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x07, 0x02, 0xde, 0x04, 0x03, 0x00, 0x37, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x08, 0x5a, 0x10, 0x26, 0x11, 0x29, 0x29, 0x00, 0x12, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x07, 0xec, 0x10, 0x26, 0x01, 0x2b, 0x00, 0x00, 0x10, 0x07, 0x00, 0x76, 0x00, 0x87, 0x01, 0x86, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x08, 0x34, 0x10, 0x26, 0x11, 0x1f, 0x2d, 0x00, 0x12, 0x06, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0xf4, 0x10, 0x27, 0x11, 0x1f, 0xff, 0xce, 0xfe, 0xc0, 0x12, 0x06, 0x00, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x7d, 0x12, 0x26, 0x00, 0x39, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9e, 0x00, 0xd5, 0x01, 0x46, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x06, 0x37, 0x12, 0x26, 0x00, 0x59, 0x00, 0x00, 0x10, 0x06, 0x02, 0x9e, 0x62, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x89, 0x04, 0xde, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x39, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x43, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x89, 0x04, 0x0c, 0x04, 0x60, 0x10, 0x26, 0x00, 0x59, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x03, 0xee, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0x00, 0x00, 0x06, 0xe3, 0x07, 0x72, 0x10, 0x27, 0x10, 0xee, 0x05, 0x5c, 0x01, 0x7c, 0x12, 0x06, 0x00, 0x3a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x06, 0x6b, 0x10, 0x27, 0x00, 0x43, 0x00, 0xee, 0x00, 0x05, 0x12, 0x06, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0x00, 0x00, 0x06, 0xe3, 0x07, 0x72, 0x10, 0x27, 0x10, 0xec, 0x05, 0x5c, 0x01, 0x7c, 0x12, 0x06, 0x00, 0x3a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x06, 0x6d, 0x10, 0x27, 0x00, 0x76, 0x01, 0x5f, 0x00, 0x07, 0x12, 0x06, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0x00, 0x00, 0x06, 0xe3, 0x07, 0x4e, 0x10, 0x27, 0x00, 0x6a, 0x01, 0xc3, 0x01, 0x3e, 0x12, 0x06, 0x00, 0x3a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x06, 0x10, 0x10, 0x27, 0x00, 0x6a, 0x01, 0x24, 0x00, 0x00, 0x12, 0x06, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0x00, 0x00, 0x06, 0xe3, 0x07, 0x4e, 0x10, 0x27, 0x10, 0xf3, 0x05, 0x5c, 0x01, 0x73, 0x12, 0x06, 0x00, 0x3a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x04, 0xc0, 0x00, 0x00, 0x12, 0x06, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0xfe, 0x89, 0x06, 0xe3, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x3a, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x05, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0xfe, 0x89, 0x05, 0x97, 0x04, 0x60, 0x12, 0x26, 0x00, 0x5a, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0xc3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0xb6, 0x07, 0x4f, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x4f, 0x01, 0x73, 0x12, 0x06, 0x00, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x35, 0x00, 0x00, 0x04, 0x07, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xf2, 0x00, 0x00, 0x12, 0x06, 0x00, 0x5b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0xb6, 0x07, 0x4e, 0x12, 0x26, 0x00, 0x3b, 0x00, 0x00, 0x10, 0x07, 0x00, 0x6a, 0x00, 0xb6, 0x01, 0x3e, 0xff, 0xff, 0x00, 0x35, 0x00, 0x00, 0x04, 0x07, 0x06, 0x10, 0x12, 0x26, 0x00, 0x5b, 0x00, 0x00, 0x10, 0x06, 0x00, 0x6a, 0x5c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x50, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x00, 0x01, 0x75, 0x12, 0x06, 0x00, 0x3c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x14, 0x10, 0x27, 0x02, 0xb8, 0x03, 0xf0, 0x00, 0x00, 0x12, 0x06, 0x00, 0x5c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0x00, 0x00, 0x04, 0x9c, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xef, 0x04, 0x45, 0x01, 0x75, 0x12, 0x06, 0x00, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x79, 0x06, 0x66, 0x12, 0x26, 0x00, 0x5d, 0x00, 0x00, 0x10, 0x06, 0x02, 0x88, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0xfe, 0x89, 0x04, 0x9c, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x3d, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x5d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0xfe, 0x89, 0x03, 0x79, 0x04, 0x60, 0x12, 0x26, 0x00, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x03, 0xc6, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0xfe, 0xc0, 0x04, 0x9c, 0x05, 0xd5, 0x12, 0x26, 0x00, 0x3d, 0x00, 0x00, 0x10, 0x07, 0x02, 0x8f, 0x00, 0xb3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0xfe, 0xc0, 0x03, 0x79, 0x04, 0x60, 0x12, 0x26, 0x00, 0x5d, 0x00, 0x00, 0x10, 0x06, 0x02, 0x8f, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0xc0, 0x03, 0xf4, 0x06, 0x14, 0x12, 0x26, 0x00, 0x4b, 0x00, 0x00, 0x10, 0x06, 0x02, 0x8f, 0x5c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x02, 0xa7, 0x07, 0x4e, 0x12, 0x26, 0x00, 0x57, 0x00, 0x00, 0x10, 0x07, 0x00, 0x6a, 0xff, 0x42, 0x01, 0x3e, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x07, 0x06, 0x12, 0x26, 0x00, 0x5a, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9c, 0x01, 0x22, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x07, 0x06, 0x12, 0x26, 0x00, 0x5c, 0x00, 0x00, 0x10, 0x06, 0x02, 0x9c, 0x74, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x04, 0xd8, 0x06, 0x14, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x10, 0x07, 0x02, 0x80, 0x03, 0x77, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, 0x07, 0x89, 0x10, 0x27, 0x02, 0xb8, 0x03, 0x7d, 0x01, 0x75, 0x12, 0x06, 0x01, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0xac, 0x06, 0x14, 0x00, 0x18, 0x00, 0x00, 0x21, 0x23, 0x11, 0x07, 0x27, 0x37, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x37, 0x17, 0x05, 0x01, 0x6f, 0xa6, 0x85, 0x42, 0xc7, 0x9f, 0x9f, 0x9c, 0xaa, 0x9d, 0x9e, 0x5a, 0x23, 0x22, 0xc1, 0x43, 0xfe, 0xfc, 0x02, 0x14, 0x68, 0x6a, 0x9d, 0x01, 0x1e, 0x8f, 0x4e, 0xbb, 0xab, 0x99, 0x28, 0x29, 0x67, 0xfe, 0x74, 0x98, 0x69, 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, 0x06, 0x14, 0x00, 0x17, 0x00, 0x00, 0x21, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x23, 0x35, 0x33, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x07, 0x33, 0x15, 0x23, 0x01, 0x6f, 0xa6, 0x9f, 0x9f, 0x9f, 0xa1, 0x0c, 0x40, 0x4e, 0xaa, 0x9d, 0x9e, 0x5a, 0x23, 0x1b, 0x05, 0xe4, 0xe6, 0x03, 0x45, 0x8f, 0x8c, 0x8f, 0x89, 0x46, 0x56, 0x99, 0x28, 0x20, 0x44, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa0, 0xff, 0xe3, 0x05, 0x22, 0x05, 0xf2, 0x00, 0x37, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x11, 0x23, 0x11, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x04, 0x17, 0x22, 0x06, 0x15, 0x14, 0x1e, 0x05, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x2e, 0x07, 0x35, 0x34, 0x36, 0x03, 0x9c, 0x62, 0x9c, 0x3a, 0x5c, 0x55, 0x3a, 0x22, 0xb7, 0x34, 0x5a, 0x81, 0x95, 0x5a, 0xc3, 0x01, 0x11, 0x32, 0xba, 0xe8, 0x3d, 0x5f, 0x74, 0x74, 0x60, 0x3c, 0xee, 0xbe, 0xa2, 0xb5, 0x62, 0x9f, 0x64, 0x58, 0x88, 0x25, 0x3f, 0x52, 0x5a, 0x5a, 0x52, 0x3f, 0x25, 0xc9, 0x04, 0xf4, 0x5a, 0x18, 0x40, 0x68, 0xa7, 0x6f, 0xfc, 0x88, 0x03, 0x91, 0x83, 0xcf, 0x8b, 0x5c, 0x28, 0xc5, 0xbd, 0x7d, 0x5f, 0x2d, 0x43, 0x2d, 0x2d, 0x3e, 0x54, 0x8c, 0x5c, 0xa4, 0xc9, 0x5f, 0xd0, 0x45, 0x46, 0x76, 0x58, 0x35, 0x50, 0x33, 0x29, 0x20, 0x24, 0x32, 0x42, 0x67, 0x43, 0x8f, 0xbb, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x05, 0xf0, 0x10, 0x06, 0x03, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x89, 0x04, 0xde, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x3e, 0x00, 0x00, 0x12, 0x06, 0x00, 0x24, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xfe, 0x89, 0x03, 0xc3, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xd4, 0x03, 0xb7, 0x00, 0x00, 0x12, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0xf0, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x43, 0x01, 0x75, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0x7b, 0x12, 0x26, 0x00, 0x44, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x03, 0xe5, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x3a, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2a, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x04, 0x37, 0x06, 0xc5, 0x10, 0x27, 0x11, 0x2a, 0xff, 0xa1, 0xfe, 0x8b, 0x10, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x3a, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2b, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x06, 0xc6, 0x10, 0x26, 0x00, 0x44, 0x00, 0x00, 0x10, 0x07, 0x11, 0x2b, 0xff, 0x9f, 0xfe, 0x8c, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x5b, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x04, 0x27, 0x06, 0xe6, 0x10, 0x27, 0x11, 0x31, 0xff, 0xa1, 0xfe, 0x8b, 0x10, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x75, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x07, 0x00, 0x10, 0x27, 0x11, 0x2c, 0xff, 0xa1, 0xfe, 0x8b, 0x10, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x89, 0x04, 0xde, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x84, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x37, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xfe, 0x89, 0x03, 0xc3, 0x06, 0x66, 0x12, 0x26, 0x00, 0xa4, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x03, 0xb8, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x07, 0x04, 0x10, 0x27, 0x11, 0x2e, 0xff, 0x9c, 0xfe, 0xaa, 0x10, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x5a, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x07, 0x04, 0x10, 0x27, 0x11, 0x2f, 0xff, 0x9d, 0xfe, 0xaa, 0x10, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x8b, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x30, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x07, 0x35, 0x10, 0x27, 0x11, 0x30, 0xff, 0x9f, 0xfe, 0xaa, 0x10, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x08, 0x59, 0x12, 0x26, 0x00, 0x24, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2d, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x07, 0x03, 0x10, 0x26, 0x00, 0x44, 0x00, 0x00, 0x10, 0x07, 0x11, 0x2d, 0xff, 0x9d, 0xfe, 0xaa, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x89, 0x04, 0xde, 0x07, 0x92, 0x12, 0x26, 0x00, 0xc4, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x46, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xfe, 0x89, 0x03, 0xc3, 0x06, 0x1f, 0x12, 0x26, 0x00, 0xc5, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x03, 0xc8, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x04, 0x17, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x28, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x89, 0x04, 0x0c, 0x04, 0x7b, 0x10, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x17, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0xf0, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x28, 0x01, 0x75, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x7b, 0x12, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x07, 0x5e, 0x10, 0x27, 0x10, 0xed, 0x04, 0x28, 0x01, 0x75, 0x12, 0x06, 0x00, 0x28, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0x37, 0x10, 0x27, 0x02, 0x9e, 0x00, 0x88, 0x00, 0x00, 0x12, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x96, 0x08, 0x3a, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2a, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x6b, 0x06, 0xc5, 0x10, 0x27, 0x11, 0x2a, 0xff, 0xd5, 0xfe, 0x8b, 0x10, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x08, 0x3a, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2b, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x06, 0xc6, 0x10, 0x27, 0x11, 0x2b, 0xff, 0xd5, 0xfe, 0x8c, 0x10, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x77, 0x08, 0x5b, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x06, 0x11, 0x31, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x5c, 0x06, 0xe6, 0x10, 0x26, 0x00, 0x48, 0x00, 0x00, 0x10, 0x07, 0x11, 0x31, 0xff, 0xd5, 0xfe, 0x8b, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x08, 0x75, 0x12, 0x26, 0x00, 0x28, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2c, 0xec, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x07, 0x00, 0x10, 0x27, 0x11, 0x2c, 0xff, 0xd6, 0xfe, 0x8b, 0x10, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x04, 0x17, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x8c, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x28, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x89, 0x04, 0x0c, 0x06, 0x66, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x17, 0x00, 0x00, 0x10, 0x26, 0x06, 0x09, 0x00, 0x00, 0x10, 0x06, 0x02, 0x88, 0x7d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x51, 0x00, 0x00, 0x01, 0xe5, 0x07, 0xf0, 0x12, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x02, 0xd3, 0x01, 0x75, 0xff, 0xff, 0x00, 0x3d, 0x00, 0x00, 0x01, 0xd1, 0x06, 0x7c, 0x12, 0x26, 0x00, 0xf3, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x02, 0xbf, 0x00, 0x01, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x89, 0x01, 0x6b, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x00, 0xab, 0xfe, 0x89, 0x01, 0x54, 0x06, 0x14, 0x10, 0x26, 0x00, 0x4c, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x02, 0xcd, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0x89, 0x05, 0x44, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0xa3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x89, 0x04, 0x03, 0x04, 0x7b, 0x10, 0x26, 0x00, 0x52, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x07, 0xf0, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0xa3, 0x01, 0x75, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x7b, 0x12, 0x26, 0x00, 0x52, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x3a, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2a, 0x61, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x53, 0x06, 0xc5, 0x10, 0x27, 0x11, 0x2a, 0xff, 0xbd, 0xfe, 0x8b, 0x10, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x3a, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2b, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0xc6, 0x10, 0x27, 0x11, 0x2b, 0xff, 0xbc, 0xfe, 0x8c, 0x10, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x5b, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x31, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x44, 0x06, 0xe6, 0x10, 0x27, 0x11, 0x31, 0xff, 0xbd, 0xfe, 0x8b, 0x10, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x08, 0x75, 0x12, 0x26, 0x00, 0x32, 0x00, 0x00, 0x10, 0x06, 0x11, 0x2c, 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x07, 0x00, 0x10, 0x27, 0x11, 0x2c, 0xff, 0xbd, 0xfe, 0x8b, 0x10, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0x89, 0x05, 0x44, 0x07, 0x6d, 0x12, 0x26, 0x00, 0x96, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0xa3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x89, 0x04, 0x03, 0x06, 0x66, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x01, 0x00, 0x00, 0x10, 0x26, 0x06, 0x1d, 0x00, 0x00, 0x10, 0x06, 0x02, 0x88, 0x68, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5c, 0xff, 0xe3, 0x05, 0x81, 0x07, 0x6b, 0x10, 0x27, 0x10, 0xec, 0x04, 0xa3, 0x01, 0x75, 0x12, 0x06, 0x01, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6a, 0xff, 0xe3, 0x04, 0x58, 0x06, 0x66, 0x10, 0x26, 0x00, 0x76, 0x68, 0x00, 0x12, 0x06, 0x01, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5c, 0xff, 0xe3, 0x05, 0x81, 0x07, 0x6b, 0x10, 0x27, 0x10, 0xee, 0x04, 0xa3, 0x01, 0x75, 0x12, 0x06, 0x01, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6a, 0xff, 0xe3, 0x04, 0x58, 0x06, 0x66, 0x10, 0x26, 0x00, 0x43, 0x68, 0x00, 0x12, 0x06, 0x01, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5c, 0xff, 0xe3, 0x05, 0x81, 0x07, 0xf0, 0x12, 0x26, 0x01, 0x62, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0xa3, 0x01, 0x75, 0xff, 0xff, 0x00, 0x6a, 0xff, 0xe3, 0x04, 0x58, 0x06, 0x7b, 0x12, 0x26, 0x01, 0x63, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5c, 0xff, 0xe3, 0x05, 0x81, 0x07, 0x5e, 0x10, 0x27, 0x10, 0xed, 0x04, 0xa3, 0x01, 0x75, 0x12, 0x06, 0x01, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6a, 0xff, 0xe3, 0x04, 0x58, 0x06, 0x37, 0x10, 0x26, 0x02, 0x9e, 0x68, 0x00, 0x12, 0x06, 0x01, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5c, 0xfe, 0x89, 0x05, 0x81, 0x06, 0x14, 0x12, 0x26, 0x01, 0x62, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0xa3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6a, 0xfe, 0x89, 0x04, 0x58, 0x04, 0xeb, 0x12, 0x26, 0x01, 0x63, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xfe, 0x89, 0x04, 0xa5, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x76, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xfe, 0x89, 0x03, 0xe9, 0x04, 0x7b, 0x10, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x08, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x07, 0xf0, 0x12, 0x26, 0x00, 0x38, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x70, 0x01, 0x75, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x06, 0x7b, 0x12, 0x26, 0x00, 0x58, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9b, 0xff, 0xf7, 0x05, 0xbc, 0x07, 0x6b, 0x10, 0x27, 0x10, 0xec, 0x04, 0x70, 0x01, 0x75, 0x12, 0x06, 0x01, 0x71, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9e, 0xff, 0xe3, 0x04, 0xdf, 0x06, 0x66, 0x10, 0x26, 0x00, 0x76, 0x6f, 0x00, 0x12, 0x06, 0x01, 0x72, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9b, 0xff, 0xf7, 0x05, 0xbc, 0x07, 0x6b, 0x10, 0x27, 0x10, 0xee, 0x04, 0x70, 0x01, 0x75, 0x12, 0x06, 0x01, 0x71, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9e, 0xff, 0xe3, 0x04, 0xdf, 0x06, 0x66, 0x10, 0x26, 0x00, 0x43, 0x6f, 0x00, 0x12, 0x06, 0x01, 0x72, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9b, 0xff, 0xf7, 0x05, 0xbc, 0x07, 0xf0, 0x12, 0x26, 0x01, 0x71, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x70, 0x01, 0x75, 0xff, 0xff, 0x00, 0x9e, 0xff, 0xe3, 0x04, 0xdf, 0x06, 0x7b, 0x12, 0x26, 0x01, 0x72, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9b, 0xff, 0xf7, 0x05, 0xbc, 0x07, 0x5e, 0x10, 0x27, 0x10, 0xed, 0x04, 0x70, 0x01, 0x75, 0x12, 0x06, 0x01, 0x71, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9e, 0xff, 0xe3, 0x04, 0xdf, 0x06, 0x37, 0x10, 0x26, 0x02, 0x9e, 0x73, 0x00, 0x12, 0x06, 0x01, 0x72, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9b, 0xfe, 0x89, 0x05, 0xbc, 0x06, 0x14, 0x12, 0x26, 0x01, 0x71, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x76, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9e, 0xfe, 0x89, 0x04, 0xdf, 0x04, 0xeb, 0x12, 0x26, 0x01, 0x72, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x04, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x72, 0x12, 0x26, 0x00, 0x3c, 0x00, 0x00, 0x10, 0x07, 0x10, 0xee, 0x04, 0x00, 0x01, 0x7c, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x6b, 0x12, 0x26, 0x00, 0x5c, 0x00, 0x00, 0x10, 0x06, 0x00, 0x43, 0x1e, 0x05, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0xfe, 0x89, 0x04, 0x6a, 0x05, 0xd5, 0x10, 0x27, 0x02, 0xd4, 0x04, 0x04, 0x00, 0x00, 0x12, 0x06, 0x00, 0x3c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x04, 0x60, 0x10, 0x27, 0x02, 0xd4, 0x04, 0xe8, 0x00, 0x00, 0x12, 0x06, 0x00, 0x5c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0xf7, 0x12, 0x26, 0x00, 0x3c, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x04, 0x00, 0x01, 0x7c, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x82, 0x12, 0x26, 0x00, 0x5c, 0x00, 0x00, 0x10, 0x07, 0x02, 0xba, 0x03, 0xf0, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x5e, 0x10, 0x27, 0x10, 0xed, 0x04, 0x00, 0x01, 0x75, 0x12, 0x06, 0x00, 0x3c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x06, 0x37, 0x10, 0x26, 0x02, 0x9e, 0x6b, 0x00, 0x12, 0x06, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x80, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0xb5, 0xb6, 0xd1, 0xb5, 0x02, 0x8f, 0xfb, 0x35, 0x05, 0xd5, 0xfa, 0xd5, 0x05, 0x2b, 0xfa, 0xd5, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x54, 0x06, 0x14, 0x00, 0x13, 0x00, 0x00, 0x13, 0x33, 0x15, 0x33, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0xae, 0xa5, 0xca, 0xa5, 0x91, 0x91, 0xa5, 0xca, 0xa5, 0x91, 0x91, 0x06, 0x14, 0x93, 0x93, 0x93, 0x7d, 0xfa, 0xfc, 0x05, 0x04, 0xfa, 0xfc, 0x05, 0x04, 0x7d, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x61, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x06, 0xfc, 0x65, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x61, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x07, 0x34, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x07, 0x07, 0x09, 0x00, 0x85, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x07, 0x0a, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0x00, 0x90, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x07, 0x0b, 0x6a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x07, 0x18, 0x3d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x06, 0x61, 0x10, 0x26, 0x03, 0x26, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfc, 0xff, 0x39, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x06, 0x61, 0x10, 0x26, 0x03, 0x26, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x06, 0x42, 0x06, 0x66, 0x10, 0x27, 0x03, 0x26, 0x01, 0x64, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x89, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x06, 0x42, 0x06, 0x66, 0x10, 0x27, 0x03, 0x26, 0x01, 0x64, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x94, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x05, 0x7b, 0x06, 0x66, 0x10, 0x27, 0x03, 0x26, 0x00, 0x9d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0a, 0xff, 0x64, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x05, 0xb6, 0x06, 0x66, 0x10, 0x27, 0x03, 0x26, 0x00, 0xd8, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x05, 0x0a, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x26, 0x2c, 0x00, 0x10, 0x07, 0x07, 0x0b, 0xff, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x05, 0x4a, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x26, 0x6c, 0x00, 0x10, 0x07, 0x07, 0x18, 0xff, 0x60, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x06, 0x61, 0x10, 0x26, 0x03, 0x49, 0x00, 0x00, 0x10, 0x06, 0x06, 0xfc, 0x3d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x06, 0x61, 0x10, 0x26, 0x03, 0x49, 0x00, 0x00, 0x10, 0x06, 0x07, 0x34, 0x33, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x06, 0x66, 0x10, 0x26, 0x03, 0x49, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x1d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x06, 0x66, 0x10, 0x26, 0x03, 0x49, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x21, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x80, 0x06, 0x66, 0x10, 0x26, 0x03, 0x49, 0x00, 0x00, 0x10, 0x06, 0x07, 0x0a, 0x47, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x9d, 0x06, 0x66, 0x10, 0x26, 0x03, 0x49, 0x00, 0x00, 0x10, 0x06, 0x07, 0x17, 0x4a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x04, 0xa9, 0x06, 0x61, 0x10, 0x27, 0x03, 0x2a, 0x00, 0x92, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfc, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x04, 0xa9, 0x06, 0x61, 0x10, 0x27, 0x03, 0x2a, 0x00, 0x92, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x06, 0x7f, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2a, 0x02, 0x68, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x89, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x06, 0x8f, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2a, 0x02, 0x78, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x94, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x06, 0x03, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2a, 0x01, 0xeb, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0a, 0xff, 0x64, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x06, 0x39, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2a, 0x02, 0x21, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x61, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfc, 0x00, 0x95, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x61, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0x00, 0x92, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x73, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x65, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x06, 0x07, 0x0a, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0x00, 0x9d, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0b, 0x00, 0x8c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x06, 0x07, 0x18, 0x7a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x05, 0x52, 0x06, 0x61, 0x10, 0x27, 0x03, 0x2c, 0x00, 0x9d, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfc, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x05, 0x4f, 0x06, 0x61, 0x10, 0x27, 0x03, 0x2c, 0x00, 0x9a, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x07, 0x1d, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2c, 0x02, 0x68, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x89, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x07, 0x23, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2c, 0x02, 0x6d, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x94, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x06, 0xb0, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2c, 0x01, 0xfb, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0a, 0xff, 0x64, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x06, 0xdc, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2c, 0x02, 0x27, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x06, 0x04, 0x07, 0x6d, 0x10, 0x27, 0x03, 0x2c, 0x01, 0x4f, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0b, 0xff, 0x62, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x06, 0x1d, 0x07, 0x6d, 0x10, 0x27, 0x03, 0x2c, 0x01, 0x67, 0x00, 0x00, 0x10, 0x07, 0x07, 0x18, 0xff, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x8b, 0x00, 0x00, 0x02, 0x30, 0x06, 0x61, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfc, 0xff, 0x2c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x82, 0x00, 0x00, 0x02, 0x30, 0x06, 0x61, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0xff, 0x24, 0x00, 0x00, 0xff, 0xff, 0xff, 0xb8, 0x00, 0x00, 0x02, 0x74, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x09, 0xff, 0x3d, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x02, 0x80, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x16, 0xff, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x02, 0x9b, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0a, 0xff, 0x62, 0x00, 0x00, 0xff, 0xff, 0xff, 0xd7, 0x00, 0x00, 0x02, 0xa3, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0xff, 0x50, 0x00, 0x00, 0xff, 0xff, 0xff, 0xd0, 0x00, 0x00, 0x02, 0x30, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0b, 0xff, 0x2c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xcb, 0x00, 0x00, 0x02, 0x30, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x18, 0xff, 0x28, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x02, 0x08, 0x06, 0x61, 0x10, 0x27, 0x03, 0x2e, 0x00, 0x9d, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfc, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x01, 0xfd, 0x06, 0x61, 0x10, 0x27, 0x03, 0x2e, 0x00, 0x92, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x03, 0xde, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2e, 0x02, 0x72, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x89, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x03, 0xde, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2e, 0x02, 0x72, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x94, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x03, 0x67, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2e, 0x01, 0xfc, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0a, 0xff, 0x64, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x03, 0x9d, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2e, 0x02, 0x32, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x02, 0xd2, 0x07, 0x6d, 0x10, 0x27, 0x03, 0x2e, 0x01, 0x67, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0b, 0xff, 0x62, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x02, 0xd9, 0x07, 0x6d, 0x10, 0x27, 0x03, 0x2e, 0x01, 0x6d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x18, 0xff, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x61, 0x10, 0x26, 0x03, 0x53, 0x00, 0x00, 0x10, 0x06, 0x06, 0xfc, 0x6c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x61, 0x10, 0x26, 0x03, 0x53, 0x00, 0x00, 0x10, 0x06, 0x07, 0x34, 0x63, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x10, 0x26, 0x03, 0x53, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x10, 0x26, 0x03, 0x53, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x4c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x10, 0x26, 0x03, 0x53, 0x00, 0x00, 0x10, 0x06, 0x07, 0x0a, 0x7a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x10, 0x26, 0x03, 0x53, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0x00, 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xff, 0xe3, 0x05, 0x63, 0x06, 0x61, 0x10, 0x26, 0x03, 0x34, 0x20, 0x00, 0x10, 0x07, 0x06, 0xfc, 0xfe, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xff, 0xe3, 0x05, 0xb4, 0x06, 0x61, 0x10, 0x26, 0x03, 0x34, 0x70, 0x00, 0x10, 0x07, 0x07, 0x34, 0xfe, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0xff, 0xe3, 0x07, 0x7b, 0x06, 0x66, 0x10, 0x27, 0x03, 0x34, 0x02, 0x37, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x89, 0x00, 0xff, 0xff, 0x00, 0x05, 0xff, 0xe3, 0x07, 0x84, 0x06, 0x66, 0x10, 0x27, 0x03, 0x34, 0x02, 0x40, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x94, 0x00, 0xff, 0xff, 0x00, 0x06, 0xff, 0xe3, 0x06, 0x5b, 0x06, 0x66, 0x10, 0x27, 0x03, 0x34, 0x01, 0x17, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0a, 0xff, 0x64, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0xff, 0xe3, 0x06, 0x95, 0x06, 0x66, 0x10, 0x27, 0x03, 0x34, 0x01, 0x52, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x61, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x06, 0xfc, 0x37, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x61, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x34, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x66, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x23, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x66, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x1e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x66, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x0a, 0x56, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x66, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x17, 0x4e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x0b, 0x32, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x18, 0x16, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x05, 0xa9, 0x06, 0x61, 0x10, 0x27, 0x03, 0x39, 0x01, 0x3f, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x07, 0x33, 0x06, 0x66, 0x10, 0x27, 0x03, 0x39, 0x02, 0xc9, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x94, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x07, 0x4e, 0x06, 0x66, 0x10, 0x27, 0x03, 0x39, 0x02, 0xe4, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x06, 0x7b, 0x07, 0x6d, 0x10, 0x27, 0x03, 0x39, 0x02, 0x11, 0x00, 0x00, 0x10, 0x07, 0x07, 0x18, 0xff, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x61, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfc, 0x01, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x61, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0x01, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x09, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x16, 0x01, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0a, 0x01, 0x7a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0x01, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0b, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x18, 0x01, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x05, 0x81, 0x06, 0x61, 0x10, 0x26, 0x03, 0x3d, 0x46, 0x00, 0x10, 0x07, 0x06, 0xfc, 0xfe, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x05, 0xcd, 0x06, 0x61, 0x10, 0x27, 0x03, 0x3d, 0x00, 0x92, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x07, 0x92, 0x06, 0x66, 0x10, 0x27, 0x03, 0x3d, 0x02, 0x57, 0x00, 0x00, 0x10, 0x06, 0x07, 0x09, 0x89, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x07, 0x9d, 0x06, 0x66, 0x10, 0x27, 0x03, 0x3d, 0x02, 0x62, 0x00, 0x00, 0x10, 0x06, 0x07, 0x16, 0x94, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x06, 0x8a, 0x06, 0x66, 0x10, 0x27, 0x03, 0x3d, 0x01, 0x4f, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0a, 0xff, 0x64, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x06, 0xba, 0x06, 0x66, 0x10, 0x27, 0x03, 0x3d, 0x01, 0x7f, 0x00, 0x00, 0x10, 0x07, 0x07, 0x17, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x06, 0x5d, 0x07, 0x6d, 0x10, 0x27, 0x03, 0x3d, 0x01, 0x22, 0x00, 0x00, 0x10, 0x07, 0x07, 0x0b, 0xff, 0x62, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x06, 0x95, 0x07, 0x6d, 0x10, 0x27, 0x03, 0x3d, 0x01, 0x5a, 0x00, 0x00, 0x10, 0x07, 0x07, 0x18, 0xff, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x07, 0x28, 0x68, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x66, 0x10, 0x06, 0x03, 0x40, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x06, 0x66, 0x10, 0x26, 0x03, 0x49, 0x00, 0x00, 0x10, 0x06, 0x07, 0x28, 0x4c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x77, 0xff, 0xe3, 0x03, 0x68, 0x06, 0x66, 0x10, 0x06, 0x03, 0x41, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0x00, 0xb2, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x06, 0x03, 0x42, 0x00, 0x00, 0xff, 0xff, 0xff, 0x98, 0x00, 0x00, 0x02, 0x30, 0x06, 0x66, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x95, 0x00, 0x00, 0x02, 0x56, 0x06, 0x66, 0x10, 0x06, 0x03, 0x43, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x10, 0x26, 0x03, 0x53, 0x00, 0x00, 0x10, 0x06, 0x07, 0x28, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x66, 0x10, 0x06, 0x03, 0x60, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x66, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x28, 0x2b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x66, 0x10, 0x06, 0x03, 0x61, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0x01, 0x2c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x06, 0x03, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x61, 0x10, 0x26, 0x06, 0x4c, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x61, 0x10, 0x26, 0x06, 0x4d, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x06, 0x4e, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x06, 0x4f, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x06, 0x50, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x06, 0x51, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x07, 0x6d, 0x10, 0x26, 0x06, 0x52, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x07, 0x6d, 0x10, 0x26, 0x06, 0x53, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x56, 0x04, 0xde, 0x06, 0x61, 0x10, 0x26, 0x06, 0x54, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x56, 0x04, 0xde, 0x06, 0x61, 0x10, 0x26, 0x06, 0x55, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0xfe, 0x56, 0x06, 0x42, 0x06, 0x66, 0x10, 0x26, 0x06, 0x56, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0xfe, 0x56, 0x06, 0x42, 0x06, 0x66, 0x10, 0x26, 0x06, 0x57, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x05, 0x7b, 0x06, 0x66, 0x10, 0x26, 0x06, 0x58, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x01, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0xfe, 0x56, 0x05, 0xb6, 0x06, 0x66, 0x10, 0x26, 0x06, 0x59, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x01, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x05, 0x0a, 0x07, 0x6d, 0x10, 0x26, 0x06, 0x5a, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x00, 0xd4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xfe, 0x56, 0x05, 0x4a, 0x07, 0x6d, 0x10, 0x26, 0x06, 0x5b, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x01, 0x13, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x61, 0x10, 0x26, 0x06, 0x68, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x61, 0x10, 0x26, 0x06, 0x69, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x06, 0x6a, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x06, 0x6b, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x06, 0x6c, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x06, 0x6d, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x07, 0x6d, 0x10, 0x26, 0x06, 0x6e, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x07, 0x6d, 0x10, 0x26, 0x06, 0x6f, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x05, 0x52, 0x06, 0x61, 0x10, 0x26, 0x06, 0x70, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x05, 0x4f, 0x06, 0x61, 0x10, 0x26, 0x06, 0x71, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x01, 0x72, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0xfe, 0x56, 0x07, 0x1d, 0x06, 0x66, 0x10, 0x26, 0x06, 0x72, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x03, 0x40, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0xfe, 0x56, 0x07, 0x23, 0x06, 0x66, 0x10, 0x26, 0x06, 0x73, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x03, 0x45, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x06, 0xb0, 0x06, 0x66, 0x10, 0x26, 0x06, 0x74, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0xd3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0xfe, 0x56, 0x06, 0xdc, 0x06, 0x66, 0x10, 0x26, 0x06, 0x75, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x06, 0x04, 0x07, 0x6d, 0x10, 0x26, 0x06, 0x76, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xfe, 0x56, 0x06, 0x1d, 0x07, 0x6d, 0x10, 0x26, 0x06, 0x77, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x61, 0x10, 0x26, 0x06, 0xa0, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x61, 0x10, 0x26, 0x06, 0xa1, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x06, 0xa2, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x06, 0xa3, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x06, 0xa4, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x06, 0xa5, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x07, 0x6d, 0x10, 0x26, 0x06, 0xa6, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x07, 0x6d, 0x10, 0x26, 0x06, 0xa7, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x05, 0x81, 0x06, 0x61, 0x10, 0x26, 0x06, 0xa8, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x01, 0x39, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x05, 0xcd, 0x06, 0x61, 0x10, 0x26, 0x06, 0xa9, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x01, 0x85, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0xfe, 0x56, 0x07, 0x92, 0x06, 0x66, 0x10, 0x26, 0x06, 0xaa, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x03, 0x4a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0xfe, 0x56, 0x07, 0x9d, 0x06, 0x66, 0x10, 0x26, 0x06, 0xab, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x03, 0x55, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x06, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x06, 0xac, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0x42, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0xfe, 0x56, 0x06, 0xba, 0x06, 0x66, 0x10, 0x26, 0x06, 0xad, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0x72, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0xfe, 0x56, 0x06, 0x5d, 0x07, 0x6d, 0x10, 0x26, 0x06, 0xae, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0x15, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xfe, 0x56, 0x06, 0x95, 0x07, 0x6d, 0x10, 0x26, 0x06, 0xaf, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x02, 0x4e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x48, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x02, 0x9a, 0x6e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x05, 0xf6, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x00, 0x71, 0x6d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x06, 0xb0, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x04, 0x79, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x66, 0x10, 0x26, 0x03, 0x40, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x06, 0x37, 0x10, 0x26, 0x03, 0x45, 0x00, 0x00, 0x10, 0x06, 0x06, 0xfd, 0x63, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x67, 0x06, 0x37, 0x10, 0x26, 0x06, 0xf3, 0x00, 0x00, 0x10, 0x06, 0x03, 0x16, 0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x26, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf2, 0x04, 0x41, 0x01, 0x75, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x31, 0x10, 0x26, 0x03, 0x26, 0x00, 0x00, 0x10, 0x07, 0x00, 0x71, 0x00, 0xaa, 0x01, 0x3b, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x05, 0x19, 0x06, 0x66, 0x10, 0x26, 0x03, 0x26, 0x3b, 0x00, 0x10, 0x07, 0x07, 0x28, 0xff, 0x63, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x06, 0x66, 0x10, 0x06, 0x03, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0xfe, 0x56, 0x04, 0xde, 0x05, 0xd5, 0x10, 0x26, 0x03, 0x26, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x5f, 0x04, 0xc2, 0x02, 0x39, 0x06, 0x61, 0x10, 0x06, 0x06, 0xfc, 0x00, 0x00, 0xff, 0xff, 0x01, 0x8a, 0xfe, 0x56, 0x02, 0x51, 0xff, 0xa4, 0x10, 0x06, 0x03, 0x16, 0x00, 0x00, 0x00, 0x01, 0x01, 0x5f, 0x04, 0xc2, 0x02, 0x39, 0x06, 0x61, 0x00, 0x08, 0x00, 0x00, 0x01, 0x10, 0x23, 0x35, 0x16, 0x35, 0x23, 0x35, 0x33, 0x02, 0x39, 0xda, 0x79, 0x78, 0xd9, 0x05, 0xcd, 0xfe, 0xf5, 0x67, 0x03, 0x9d, 0x9e, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa3, 0x05, 0x1d, 0x02, 0xf6, 0x06, 0x37, 0x10, 0x06, 0x02, 0x9e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa3, 0x05, 0x46, 0x02, 0xf6, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xed, 0x03, 0x9a, 0x01, 0x84, 0x12, 0x06, 0x00, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x06, 0xb4, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x04, 0x7b, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x66, 0x10, 0x26, 0x03, 0x42, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x37, 0x10, 0x26, 0x03, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfd, 0x00, 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x37, 0x10, 0x26, 0x07, 0x02, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0xff, 0x4c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x05, 0x56, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2a, 0x01, 0x3f, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0xff, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe9, 0x00, 0x00, 0x04, 0xea, 0x06, 0x66, 0x10, 0x06, 0x03, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x05, 0xff, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2c, 0x01, 0x49, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0xff, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf4, 0x00, 0x00, 0x05, 0x83, 0x06, 0x66, 0x10, 0x06, 0x03, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0x56, 0x04, 0xb6, 0x05, 0xd5, 0x10, 0x26, 0x03, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x00, 0xe6, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7b, 0x04, 0xc2, 0x03, 0x37, 0x06, 0x66, 0x10, 0x27, 0x06, 0xfc, 0xff, 0x1c, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa2, 0x04, 0xc2, 0x03, 0x39, 0x06, 0x66, 0x10, 0x27, 0x06, 0xfc, 0xff, 0x43, 0x00, 0x00, 0x10, 0x06, 0x07, 0x33, 0x3b, 0x00, 0xff, 0xff, 0x00, 0xa3, 0x04, 0xc2, 0x02, 0xf6, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xed, 0x03, 0x9a, 0x01, 0x84, 0x10, 0x06, 0x06, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 0xed, 0x00, 0x00, 0x02, 0x30, 0x06, 0x48, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9a, 0xff, 0x3a, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe5, 0x00, 0x00, 0x02, 0x30, 0x05, 0xf6, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x00, 0x71, 0xff, 0x26, 0x00, 0x00, 0xff, 0xff, 0xff, 0xdc, 0x00, 0x00, 0x02, 0x30, 0x07, 0xd2, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x07, 0x26, 0xff, 0x43, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x02, 0x40, 0x07, 0xd2, 0x10, 0x06, 0x03, 0x25, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe6, 0x00, 0x00, 0x02, 0x39, 0x06, 0x37, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfd, 0xff, 0x43, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe8, 0x00, 0x00, 0x02, 0x3b, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x4d, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfe, 0xff, 0x45, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf6, 0x00, 0x00, 0x02, 0x2a, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x2e, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf2, 0x02, 0xdd, 0x01, 0x75, 0xff, 0xff, 0x00, 0x02, 0x00, 0x00, 0x02, 0x1d, 0x07, 0x31, 0x10, 0x26, 0x03, 0x2e, 0x00, 0x00, 0x10, 0x07, 0x00, 0x71, 0xff, 0x43, 0x01, 0x3b, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x02, 0xb7, 0x06, 0x66, 0x10, 0x27, 0x03, 0x2e, 0x01, 0x4c, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0xff, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x02, 0x3e, 0x06, 0x66, 0x10, 0x06, 0x03, 0x21, 0x00, 0x00, 0xff, 0xff, 0x00, 0x71, 0x04, 0xc2, 0x03, 0x31, 0x06, 0x66, 0x10, 0x27, 0x07, 0x34, 0xff, 0x12, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0x04, 0xc2, 0x03, 0x53, 0x06, 0x66, 0x10, 0x27, 0x07, 0x34, 0xff, 0x27, 0x00, 0x00, 0x10, 0x06, 0x07, 0x33, 0x56, 0x00, 0xff, 0xff, 0x00, 0xa3, 0x04, 0xc2, 0x02, 0xf6, 0x07, 0x6d, 0x10, 0x27, 0x10, 0xed, 0x03, 0x9a, 0x01, 0x84, 0x10, 0x06, 0x07, 0x34, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x48, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x02, 0x9a, 0x23, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x05, 0xf6, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x00, 0x71, 0x20, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x07, 0xd2, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x07, 0x26, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x07, 0xd2, 0x10, 0x06, 0x03, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x61, 0x10, 0x26, 0x03, 0x55, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfc, 0x00, 0xa8, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x61, 0x10, 0x26, 0x03, 0x55, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0x00, 0x9f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x06, 0x37, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x06, 0xfd, 0x23, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x86, 0xff, 0xe3, 0x03, 0xc0, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x59, 0x00, 0x00, 0x10, 0x06, 0x06, 0xfe, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x6d, 0x10, 0x26, 0x03, 0x39, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf2, 0x04, 0x04, 0x01, 0x75, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x07, 0x31, 0x10, 0x26, 0x03, 0x39, 0x00, 0x00, 0x10, 0x07, 0x00, 0x71, 0x00, 0x74, 0x01, 0x3b, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x06, 0x1a, 0x06, 0x66, 0x10, 0x27, 0x03, 0x39, 0x01, 0xb0, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0xff, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe4, 0x00, 0x00, 0x05, 0xe9, 0x06, 0x66, 0x10, 0x06, 0x03, 0x23, 0x00, 0x00, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0x04, 0xb0, 0x06, 0x61, 0x10, 0x27, 0x03, 0x36, 0x00, 0x97, 0x00, 0x00, 0x10, 0x07, 0x07, 0x34, 0xfe, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x05, 0x46, 0x02, 0xd9, 0x07, 0xd2, 0x12, 0x26, 0x00, 0x6a, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0x00, 0x00, 0x01, 0x6c, 0xff, 0xff, 0x00, 0xc1, 0x05, 0x46, 0x02, 0xfd, 0x07, 0xd2, 0x10, 0x06, 0x03, 0x1c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x04, 0xf0, 0x02, 0x49, 0x06, 0x66, 0x10, 0x06, 0x00, 0x43, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x06, 0xbc, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x04, 0x60, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x66, 0x10, 0x26, 0x03, 0x62, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x06, 0x37, 0x10, 0x26, 0x03, 0x5d, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfd, 0x01, 0x2e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xfe, 0x56, 0x05, 0x8a, 0x06, 0x37, 0x10, 0x26, 0x07, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x03, 0x16, 0x01, 0x36, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xe3, 0x06, 0x5f, 0x06, 0x66, 0x10, 0x27, 0x03, 0x34, 0x01, 0x1c, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0xff, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xe3, 0x05, 0x68, 0x06, 0x66, 0x10, 0x06, 0x03, 0x22, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x06, 0x5e, 0x06, 0x66, 0x10, 0x27, 0x03, 0x3d, 0x01, 0x24, 0x00, 0x00, 0x10, 0x07, 0x07, 0x28, 0xff, 0x63, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xde, 0x00, 0x00, 0x05, 0x6b, 0x06, 0x66, 0x10, 0x06, 0x03, 0x24, 0x00, 0x00, 0xff, 0xff, 0x00, 0x46, 0xfe, 0x56, 0x05, 0x3b, 0x05, 0xe7, 0x10, 0x26, 0x03, 0x3d, 0x00, 0x00, 0x10, 0x07, 0x06, 0xfb, 0x00, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x01, 0x4d, 0x04, 0xee, 0x02, 0xfd, 0x06, 0x66, 0x10, 0x06, 0x00, 0x76, 0x00, 0x00, 0x00, 0x01, 0x01, 0x5f, 0x04, 0xc2, 0x02, 0x39, 0x06, 0x61, 0x00, 0x08, 0x00, 0x00, 0x01, 0x35, 0x33, 0x15, 0x23, 0x14, 0x37, 0x15, 0x22, 0x01, 0x5f, 0xd9, 0x78, 0x79, 0xda, 0x05, 0xcd, 0x94, 0x9e, 0x9d, 0x03, 0x67, 0x00, 0x01, 0x00, 0x5a, 0x01, 0xdf, 0x02, 0x40, 0x02, 0x83, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x5a, 0x01, 0xe5, 0xfe, 0x1b, 0x02, 0x83, 0xa4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5a, 0x01, 0xdf, 0x02, 0x40, 0x02, 0x83, 0x12, 0x06, 0x07, 0x45, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x01, 0xe9, 0x04, 0x3b, 0x02, 0x79, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x5a, 0x03, 0xe1, 0xfc, 0x1f, 0x02, 0x79, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x01, 0xe9, 0x03, 0x40, 0x02, 0x79, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x5a, 0x02, 0xe6, 0xfd, 0x1a, 0x02, 0x79, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x01, 0xe9, 0x06, 0xda, 0x02, 0x79, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x5a, 0x06, 0x7f, 0xf9, 0x81, 0x02, 0x79, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0xe9, 0x07, 0x34, 0x02, 0x79, 0x00, 0x03, 0x00, 0x00, 0x11, 0x21, 0x15, 0x21, 0x07, 0x33, 0xf8, 0xcd, 0x02, 0x79, 0x90, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xea, 0xfe, 0x1d, 0x02, 0xac, 0x06, 0x1d, 0x10, 0x26, 0x00, 0x5f, 0x00, 0x00, 0x10, 0x07, 0x00, 0x5f, 0x01, 0x29, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0xfe, 0x1d, 0x03, 0xac, 0xff, 0xee, 0x10, 0x26, 0x00, 0x42, 0x00, 0x00, 0x10, 0x07, 0x00, 0x42, 0x00, 0x00, 0x01, 0x42, 0x00, 0x01, 0x00, 0x9c, 0x03, 0xe9, 0x01, 0xa5, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x01, 0x23, 0x35, 0x13, 0x33, 0x03, 0x01, 0x5a, 0xbd, 0x93, 0x74, 0x4a, 0x03, 0xe9, 0xad, 0x01, 0x3f, 0xfe, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa0, 0x03, 0xfe, 0x01, 0xa8, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x13, 0x33, 0x15, 0x03, 0x23, 0x13, 0xea, 0xbe, 0x94, 0x74, 0x4a, 0x05, 0xd5, 0x98, 0xfe, 0xc1, 0x01, 0x3f, 0x00, 0x01, 0x00, 0x9c, 0xff, 0x12, 0x01, 0xa5, 0x00, 0xfe, 0x00, 0x05, 0x00, 0x00, 0x37, 0x33, 0x15, 0x03, 0x23, 0x13, 0xe6, 0xbe, 0x93, 0x74, 0x49, 0xfe, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0xa0, 0x03, 0xfe, 0x01, 0xa8, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x01, 0x15, 0x13, 0x23, 0x03, 0x35, 0x01, 0x5e, 0x4a, 0x74, 0x94, 0x05, 0xd5, 0x98, 0xfe, 0xc1, 0x01, 0x3f, 0x98, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9c, 0x03, 0xe9, 0x03, 0x16, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x23, 0x35, 0x13, 0x33, 0x03, 0x05, 0x23, 0x35, 0x13, 0x33, 0x03, 0x01, 0x5a, 0xbd, 0x93, 0x74, 0x4a, 0x01, 0x72, 0xbe, 0x93, 0x74, 0x49, 0x03, 0xe9, 0xad, 0x01, 0x3f, 0xfe, 0xc1, 0xad, 0xad, 0x01, 0x3f, 0xfe, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9c, 0x03, 0xe9, 0x03, 0x16, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x15, 0x03, 0x23, 0x13, 0x25, 0x33, 0x15, 0x03, 0x23, 0x13, 0xe6, 0xbe, 0x93, 0x74, 0x49, 0x01, 0x71, 0xbe, 0x93, 0x74, 0x49, 0x05, 0xd5, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0xac, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0x00, 0x02, 0x00, 0x9c, 0xff, 0x12, 0x03, 0x16, 0x00, 0xfe, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x33, 0x15, 0x03, 0x23, 0x13, 0x25, 0x33, 0x15, 0x03, 0x23, 0x13, 0x02, 0x57, 0xbe, 0x93, 0x74, 0x49, 0xfe, 0x8f, 0xbe, 0x93, 0x74, 0x49, 0xfe, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0xac, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0x00, 0x02, 0x00, 0x9c, 0x03, 0xe9, 0x03, 0x16, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x15, 0x13, 0x23, 0x03, 0x35, 0x21, 0x15, 0x13, 0x23, 0x03, 0x35, 0x01, 0x5a, 0x4a, 0x74, 0x93, 0x02, 0x2f, 0x49, 0x74, 0x93, 0x05, 0xd5, 0xad, 0xfe, 0xc1, 0x01, 0x3f, 0xad, 0xad, 0xfe, 0xc1, 0x01, 0x3f, 0xad, 0x00, 0x01, 0x00, 0x33, 0xff, 0x3b, 0x03, 0x67, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x01, 0x7e, 0x9e, 0x01, 0x4a, 0xfe, 0xb6, 0x9e, 0xfe, 0xb5, 0x01, 0x4b, 0x05, 0xd5, 0xfe, 0x5c, 0x99, 0xfb, 0xa3, 0x04, 0x5d, 0x99, 0x00, 0x01, 0x00, 0x33, 0xff, 0x3b, 0x03, 0x67, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x25, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x03, 0x66, 0xfe, 0xb6, 0x9e, 0xfe, 0xb5, 0x01, 0x4b, 0xfe, 0xb5, 0x01, 0x4b, 0x9e, 0x01, 0x4a, 0xfe, 0xb6, 0x01, 0x4a, 0xdf, 0xfe, 0x5c, 0x01, 0xa4, 0x9a, 0x02, 0x1f, 0x99, 0x01, 0xa4, 0xfe, 0x5c, 0x99, 0xfd, 0xe1, 0x00, 0x00, 0x00, 0x01, 0x01, 0x14, 0x01, 0xd1, 0x03, 0x2b, 0x04, 0x21, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x01, 0x14, 0x9c, 0x71, 0x70, 0x9a, 0x9b, 0x70, 0x71, 0x9b, 0x02, 0xfa, 0x7c, 0xab, 0xab, 0x7c, 0x7d, 0xac, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x14, 0x01, 0x81, 0x03, 0x73, 0x04, 0x71, 0x00, 0x02, 0x00, 0x00, 0x01, 0x11, 0x01, 0x01, 0x14, 0x02, 0x5f, 0x01, 0x81, 0x02, 0xf0, 0xfe, 0x88, 0x00, 0x00, 0x01, 0x00, 0xd4, 0x00, 0x00, 0x01, 0x95, 0x00, 0xfe, 0x00, 0x03, 0x00, 0x00, 0x37, 0x33, 0x15, 0x23, 0xd4, 0xc0, 0xc0, 0xfe, 0xfe, 0x00, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x00, 0x03, 0xfa, 0x00, 0xfe, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x25, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x03, 0x3a, 0xc0, 0xc0, 0xfd, 0x9a, 0xc0, 0xc0, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x03, 0x00, 0xd4, 0x00, 0x00, 0x06, 0x5f, 0x00, 0xfe, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x03, 0x3a, 0xbf, 0xbf, 0x02, 0x65, 0xc0, 0xc0, 0xfb, 0x35, 0xc0, 0xc0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x01, 0x00, 0xc6, 0x02, 0x6b, 0x01, 0x84, 0x03, 0x69, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0xc6, 0xbe, 0xbe, 0x03, 0x69, 0xfe, 0x00, 0x07, 0x00, 0x65, 0xff, 0xe3, 0x09, 0x45, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x27, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x4b, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x21, 0x33, 0x01, 0x23, 0x13, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x08, 0x0f, 0x4f, 0x5a, 0x5a, 0x4f, 0x4c, 0x59, 0x59, 0x4c, 0x8e, 0xa7, 0xa8, 0x8d, 0x90, 0xa8, 0xa9, 0xfa, 0x1b, 0x8f, 0xa9, 0xa9, 0x8f, 0x8f, 0xa6, 0xa7, 0x03, 0xbb, 0x90, 0xfc, 0xb7, 0x90, 0x1c, 0x4d, 0x59, 0x58, 0x4e, 0x4f, 0x59, 0x5a, 0x03, 0x53, 0x8e, 0xa8, 0xa9, 0x8d, 0x90, 0xa7, 0xa8, 0x8f, 0x4e, 0x59, 0x59, 0x4e, 0x4d, 0x59, 0x59, 0x02, 0x91, 0x94, 0x84, 0x82, 0x95, 0x95, 0x82, 0x83, 0x95, 0x7f, 0xdc, 0xbb, 0xbb, 0xdb, 0xdb, 0xbb, 0xbc, 0xdb, 0x02, 0xe0, 0xdb, 0xbb, 0xbd, 0xda, 0xdb, 0xbc, 0xba, 0xdc, 0xf9, 0xf3, 0x05, 0x8e, 0x95, 0x82, 0x84, 0x94, 0x94, 0x84, 0x81, 0x96, 0xfd, 0x9f, 0xdc, 0xbb, 0xbb, 0xdb, 0xdb, 0xbb, 0xbc, 0xdb, 0x7f, 0x94, 0x84, 0x82, 0x95, 0x95, 0x82, 0x83, 0x95, 0x00, 0x00, 0x09, 0x00, 0x65, 0xff, 0xe3, 0x0c, 0x1a, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x3b, 0x00, 0x45, 0x00, 0x50, 0x00, 0x5c, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x16, 0x10, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x16, 0x10, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x00, 0x20, 0x16, 0x15, 0x14, 0x06, 0x20, 0x26, 0x35, 0x34, 0x25, 0x33, 0x01, 0x23, 0x12, 0x22, 0x06, 0x15, 0x14, 0x16, 0x32, 0x36, 0x35, 0x34, 0x01, 0x32, 0x16, 0x10, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x0a, 0xe4, 0x4e, 0x5a, 0x5a, 0x4e, 0x4d, 0x59, 0x59, 0x4d, 0x8e, 0xa8, 0xa8, 0x8e, 0x90, 0xa7, 0xa8, 0xfd, 0xba, 0x4f, 0x5a, 0x5a, 0x4f, 0x4c, 0x59, 0x59, 0x4c, 0x8e, 0xa7, 0xa8, 0x8d, 0x90, 0xa8, 0xa9, 0xf9, 0x8d, 0x01, 0x1d, 0xa9, 0xa9, 0xfe, 0xe2, 0xa6, 0x04, 0x62, 0x90, 0xfc, 0xb7, 0x90, 0x6a, 0x9b, 0x59, 0x58, 0x9d, 0x59, 0x02, 0xf9, 0x8e, 0xa8, 0xa9, 0x8d, 0x90, 0xa7, 0xa8, 0x8f, 0x4e, 0x59, 0x59, 0x4e, 0x4d, 0x59, 0x59, 0x02, 0x91, 0x94, 0x84, 0x82, 0x95, 0x95, 0x82, 0x83, 0x95, 0x7f, 0xdc, 0xfe, 0x8a, 0xdb, 0xdb, 0xbb, 0xbc, 0xdb, 0x7f, 0x94, 0x84, 0x82, 0x95, 0x95, 0x82, 0x83, 0x95, 0x7f, 0xdc, 0xfe, 0x8a, 0xdb, 0xdb, 0xbb, 0xbc, 0xdb, 0x02, 0xe0, 0xdb, 0xbb, 0xbd, 0xda, 0xdb, 0xbc, 0xba, 0xdc, 0xf9, 0xf3, 0x05, 0x8e, 0x95, 0x82, 0x84, 0x94, 0x94, 0x84, 0x81, 0xfe, 0x35, 0xdc, 0xfe, 0x8a, 0xdb, 0xdb, 0xbb, 0xbc, 0xdb, 0x7f, 0x94, 0x84, 0x82, 0x95, 0x95, 0x82, 0x83, 0x95, 0x00, 0x01, 0x00, 0x24, 0x04, 0x60, 0x01, 0x77, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x1b, 0x01, 0x33, 0x01, 0x24, 0x9c, 0xb6, 0xfe, 0xfc, 0x04, 0x60, 0x01, 0x75, 0xfe, 0x8b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x24, 0x04, 0x60, 0x02, 0x85, 0x05, 0xd5, 0x10, 0x26, 0x07, 0x67, 0x00, 0x00, 0x10, 0x07, 0x07, 0x67, 0x01, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x24, 0x04, 0x60, 0x03, 0x93, 0x05, 0xd5, 0x10, 0x27, 0x07, 0x67, 0x01, 0x0e, 0x00, 0x00, 0x10, 0x26, 0x07, 0x67, 0x00, 0x00, 0x10, 0x07, 0x07, 0x67, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x24, 0x04, 0x60, 0x01, 0x77, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x01, 0x23, 0x01, 0x33, 0x01, 0x76, 0x4e, 0xfe, 0xfc, 0xb7, 0x04, 0x60, 0x01, 0x75, 0xff, 0xff, 0x00, 0x24, 0x04, 0x60, 0x02, 0x85, 0x05, 0xd5, 0x10, 0x26, 0x07, 0x6a, 0x00, 0x00, 0x10, 0x07, 0x07, 0x6a, 0x01, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x24, 0x04, 0x60, 0x03, 0x93, 0x05, 0xd5, 0x10, 0x26, 0x07, 0x6a, 0x00, 0x00, 0x10, 0x27, 0x07, 0x6a, 0x02, 0x1c, 0x00, 0x00, 0x10, 0x07, 0x07, 0x6a, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0xfe, 0x1d, 0x02, 0x67, 0xff, 0xc3, 0x00, 0x05, 0x00, 0x00, 0x01, 0x23, 0x27, 0x07, 0x23, 0x01, 0x02, 0x67, 0x85, 0xa9, 0xa9, 0x86, 0x01, 0x30, 0xfe, 0x1d, 0xf9, 0xf9, 0x01, 0xa6, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8e, 0x00, 0x8d, 0x02, 0x35, 0x04, 0x23, 0x00, 0x06, 0x00, 0x00, 0x01, 0x15, 0x09, 0x01, 0x15, 0x01, 0x35, 0x02, 0x34, 0xfe, 0xf1, 0x01, 0x0f, 0xfe, 0x5a, 0x04, 0x23, 0xbf, 0xfe, 0xf4, 0xfe, 0xf4, 0xbf, 0x01, 0xa2, 0x52, 0x00, 0x01, 0x00, 0xad, 0x00, 0x8d, 0x02, 0x54, 0x04, 0x23, 0x00, 0x06, 0x00, 0x00, 0x13, 0x01, 0x15, 0x01, 0x35, 0x09, 0x01, 0xae, 0x01, 0xa6, 0xfe, 0x5a, 0x01, 0x0f, 0xfe, 0xf1, 0x04, 0x23, 0xfe, 0x5e, 0x52, 0xfe, 0x5e, 0xbf, 0x01, 0x0c, 0x01, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xaf, 0x00, 0x04, 0x05, 0x54, 0x05, 0xcc, 0x12, 0x26, 0x00, 0x99, 0x00, 0x4b, 0x10, 0x27, 0x00, 0x11, 0xff, 0xea, 0x02, 0x4e, 0x10, 0x27, 0x00, 0x11, 0x01, 0xe1, 0x00, 0x04, 0x10, 0x27, 0x00, 0x11, 0x03, 0xd0, 0x02, 0x4e, 0x10, 0x07, 0x00, 0x11, 0x01, 0xe1, 0x04, 0xce, 0xff, 0xff, 0x00, 0x84, 0x00, 0x00, 0x02, 0xfb, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x04, 0xff, 0x6e, 0x00, 0x00, 0x10, 0x07, 0x00, 0x04, 0x01, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x84, 0x00, 0x00, 0x03, 0x52, 0x05, 0xf0, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x24, 0x00, 0x00, 0x01, 0x23, 0x11, 0x06, 0x07, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x0f, 0x01, 0x0e, 0x01, 0x07, 0x0e, 0x01, 0x15, 0x03, 0x33, 0x15, 0x23, 0x13, 0x11, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x26, 0x02, 0x11, 0xac, 0x1c, 0x1d, 0x50, 0x58, 0x55, 0xae, 0x5c, 0xa6, 0xc9, 0x41, 0x51, 0x4f, 0x2b, 0x23, 0x07, 0x05, 0x06, 0xb1, 0xb7, 0xb7, 0xb1, 0x29, 0x33, 0x2e, 0x3b, 0x21, 0x01, 0x91, 0x03, 0xad, 0x08, 0x0d, 0x23, 0x43, 0xbc, 0x39, 0x38, 0xc2, 0x9f, 0x4c, 0x89, 0x56, 0x56, 0x2f, 0x35, 0x19, 0x15, 0x3c, 0x34, 0xfe, 0xf2, 0xfe, 0x05, 0x42, 0xfe, 0x52, 0x2d, 0x35, 0x5e, 0x31, 0x59, 0x37, 0x1f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x05, 0x7c, 0x03, 0xac, 0x06, 0x0b, 0x10, 0x07, 0x00, 0x42, 0x00, 0x00, 0x07, 0x5f, 0x00, 0x00, 0x00, 0x01, 0xff, 0xaf, 0xfe, 0x1b, 0x06, 0x1a, 0xff, 0x85, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x32, 0x24, 0x37, 0x15, 0x06, 0x04, 0x23, 0x22, 0x24, 0x27, 0x35, 0x16, 0x04, 0x02, 0xe4, 0xd0, 0x01, 0x97, 0xcf, 0xd4, 0xfe, 0x67, 0xc9, 0xc9, 0xfe, 0x69, 0xd4, 0xcf, 0x01, 0x95, 0xfe, 0xb5, 0x68, 0x68, 0x7e, 0x76, 0x76, 0x75, 0x77, 0x7e, 0x69, 0x67, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xaf, 0x06, 0x04, 0x06, 0x1a, 0x07, 0x6e, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x32, 0x04, 0x17, 0x15, 0x26, 0x24, 0x23, 0x22, 0x04, 0x07, 0x35, 0x36, 0x24, 0x02, 0xe4, 0xc9, 0x01, 0x99, 0xd4, 0xcf, 0xfe, 0x69, 0xd0, 0xd0, 0xfe, 0x6b, 0xcf, 0xd4, 0x01, 0x97, 0x07, 0x6e, 0x76, 0x76, 0x7e, 0x68, 0x68, 0x67, 0x69, 0x7e, 0x77, 0x75, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xb2, 0xfe, 0x1d, 0x02, 0x0f, 0x01, 0xd5, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x09, 0x01, 0x23, 0x0b, 0x01, 0x23, 0x01, 0xb6, 0x58, 0xfe, 0xff, 0x01, 0x01, 0x58, 0xd5, 0xd5, 0x59, 0x01, 0xd5, 0xfe, 0x24, 0xfe, 0x24, 0x01, 0x8a, 0xfe, 0x76, 0x00, 0xff, 0xff, 0x00, 0x36, 0xff, 0xc5, 0x06, 0xfd, 0x06, 0x83, 0x10, 0x27, 0x00, 0x0d, 0x00, 0x00, 0xfd, 0x7b, 0x10, 0x27, 0x00, 0x0d, 0x03, 0x9a, 0xfd, 0x7b, 0x10, 0x07, 0x00, 0x0d, 0x01, 0xcd, 0x00, 0x93, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc6, 0x02, 0x81, 0x02, 0xe2, 0x03, 0x5f, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0xc7, 0x02, 0x1a, 0xfd, 0xe6, 0x03, 0x5f, 0xde, 0x00, 0x00, 0x00, 0x01, 0xfe, 0xae, 0xff, 0xe3, 0x02, 0x86, 0x05, 0xf0, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x01, 0x23, 0x01, 0xf5, 0x90, 0xfc, 0xb9, 0x90, 0x05, 0xf0, 0xf9, 0xf3, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0xf2, 0x02, 0x1c, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x15, 0x21, 0x11, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x01, 0x44, 0xd8, 0xfe, 0x82, 0x01, 0x7e, 0xd8, 0xd8, 0x02, 0x5e, 0xfd, 0x23, 0x8f, 0x07, 0x22, 0x8f, 0xfd, 0x23, 0x4a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0xf2, 0x02, 0x1c, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x35, 0x33, 0x11, 0x23, 0x35, 0x21, 0x11, 0x21, 0x35, 0x33, 0x11, 0x9e, 0xd8, 0xd8, 0x01, 0x7e, 0xfe, 0x82, 0xd8, 0x02, 0x5e, 0x4a, 0x02, 0xdd, 0x8f, 0xf8, 0xde, 0x8f, 0x02, 0xdd, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x42, 0x00, 0x00, 0x06, 0x62, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x22, 0xbe, 0x00, 0x10, 0x07, 0x00, 0x22, 0x03, 0x10, 0x00, 0x00, 0xff, 0xff, 0x00, 0x84, 0x00, 0x00, 0x04, 0xc3, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x22, 0x00, 0x00, 0x10, 0x07, 0x00, 0x04, 0x02, 0xf6, 0x00, 0x00, 0xff, 0xff, 0x00, 0x84, 0x00, 0x00, 0x04, 0xc3, 0x05, 0xf0, 0x10, 0x27, 0x00, 0x04, 0xff, 0x6e, 0x00, 0x00, 0x10, 0x07, 0x00, 0x22, 0x01, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0xff, 0x05, 0x03, 0x3b, 0x04, 0x5d, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x16, 0x33, 0x32, 0x37, 0x07, 0x01, 0x23, 0x13, 0x06, 0x20, 0x27, 0x5a, 0x8b, 0xd2, 0xe2, 0xa1, 0x07, 0xfe, 0xfd, 0x89, 0xee, 0x6a, 0xfe, 0xe3, 0xb4, 0x04, 0x5d, 0x10, 0x10, 0x80, 0xfb, 0x28, 0x04, 0xae, 0x0f, 0x0f, 0x00, 0x00, 0x01, 0x00, 0xd4, 0xff, 0x3b, 0x04, 0x14, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x02, 0x68, 0xc1, 0xea, 0xd3, 0xc2, 0x80, 0xab, 0x7f, 0x05, 0xd5, 0xe8, 0xbe, 0xb8, 0xdd, 0x11, 0xfc, 0xb2, 0x06, 0x1f, 0xf9, 0xe1, 0x06, 0x9a, 0x00, 0x02, 0x00, 0xc2, 0x01, 0xc2, 0x02, 0xd8, 0x04, 0x12, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x11, 0x07, 0x2b, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x02, 0x3a, 0x9d, 0x9d, 0x6a, 0x02, 0x71, 0x9b, 0x9c, 0x72, 0x04, 0x12, 0xfd, 0xb1, 0x01, 0xac, 0x7d, 0x7c, 0xab, 0x00, 0x00, 0x02, 0x00, 0xc2, 0x01, 0xc2, 0x02, 0xd8, 0x04, 0x12, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x27, 0x11, 0x3b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x01, 0x60, 0x9e, 0x9e, 0x6a, 0x72, 0x9b, 0x9b, 0x70, 0x02, 0x01, 0xc2, 0x01, 0x02, 0x4f, 0xab, 0x7c, 0x7d, 0xac, 0x00, 0xff, 0xff, 0x00, 0x36, 0xff, 0xc5, 0x03, 0x63, 0x03, 0x6b, 0x12, 0x07, 0x00, 0x0d, 0x00, 0x00, 0xfd, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0xff, 0x12, 0x02, 0x09, 0x04, 0x23, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x01, 0x15, 0x23, 0x35, 0x13, 0x15, 0x13, 0x23, 0x03, 0x35, 0x01, 0xbe, 0xbe, 0xbe, 0x4a, 0x74, 0x94, 0x04, 0x23, 0xfe, 0xfe, 0xfc, 0xdb, 0xac, 0xfe, 0xc0, 0x01, 0x40, 0xac, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xaf, 0xfe, 0x1b, 0x06, 0x1a, 0x07, 0x6e, 0x10, 0x26, 0x07, 0x74, 0x00, 0x00, 0x10, 0x06, 0x07, 0x75, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xff, 0xf2, 0x03, 0x63, 0x07, 0x6f, 0x12, 0x27, 0x00, 0x0d, 0x00, 0x00, 0xfd, 0xa8, 0x10, 0x07, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x82, 0xff, 0x42, 0x02, 0xf0, 0x05, 0xd5, 0x10, 0x27, 0x00, 0x12, 0x00, 0x82, 0x00, 0x00, 0x10, 0x27, 0x00, 0x11, 0x01, 0x66, 0x00, 0x00, 0x10, 0x07, 0x00, 0x11, 0xff, 0xdd, 0x04, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x01, 0xd3, 0x06, 0xda, 0x03, 0x31, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x06, 0xd9, 0x8e, 0xcf, 0x83, 0x86, 0xd4, 0x0e, 0x08, 0x09, 0x14, 0xd2, 0x7e, 0x77, 0xc6, 0x85, 0x8e, 0xcf, 0x84, 0x9e, 0xbd, 0x0d, 0x07, 0x0b, 0x13, 0xd1, 0x7e, 0x75, 0xc2, 0x03, 0x31, 0xb2, 0x4f, 0x44, 0x3b, 0x04, 0x02, 0x02, 0x06, 0x3e, 0x4d, 0x53, 0xb2, 0x4f, 0x45, 0x3c, 0x04, 0x02, 0x03, 0x05, 0x3e, 0x4c, 0xff, 0xff, 0xff, 0xaf, 0xfe, 0x14, 0x06, 0x1a, 0xff, 0x7e, 0x10, 0x07, 0x07, 0x75, 0x00, 0x00, 0xf8, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x18, 0x00, 0xc8, 0x04, 0xf0, 0x05, 0x0d, 0x00, 0x17, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x17, 0x11, 0x33, 0x11, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x17, 0x07, 0x03, 0x4c, 0x90, 0xe0, 0x66, 0xe0, 0xfe, 0xc3, 0x01, 0x3d, 0xe0, 0x65, 0xe1, 0x90, 0xe1, 0x66, 0xe1, 0x01, 0x3e, 0xfe, 0xc2, 0xe1, 0x66, 0x02, 0x29, 0xfe, 0x9f, 0x01, 0x60, 0xf9, 0x72, 0xf9, 0xa0, 0xfa, 0x72, 0xfb, 0x01, 0x62, 0xfe, 0x9e, 0xfa, 0x71, 0xfa, 0xa0, 0xf9, 0x72, 0x00, 0x03, 0x00, 0xe1, 0x01, 0x32, 0x03, 0x57, 0x04, 0xb6, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x35, 0x33, 0x15, 0x01, 0x35, 0x33, 0x15, 0x03, 0x35, 0x33, 0x15, 0xe1, 0xb4, 0x01, 0x0e, 0xb4, 0xb4, 0xb4, 0x02, 0x90, 0xc8, 0xc8, 0xfe, 0xa2, 0xc8, 0xc8, 0x02, 0xbc, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x24, 0x04, 0x60, 0x04, 0xa1, 0x05, 0xd5, 0x10, 0x27, 0x07, 0x67, 0x01, 0x0e, 0x00, 0x00, 0x10, 0x26, 0x07, 0x67, 0x00, 0x00, 0x10, 0x27, 0x07, 0x67, 0x03, 0x2a, 0x00, 0x00, 0x10, 0x07, 0x07, 0x67, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x01, 0x42, 0x01, 0x00, 0x04, 0xc7, 0x04, 0xe8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x35, 0x33, 0x15, 0x21, 0x35, 0x33, 0x15, 0x01, 0x35, 0x33, 0x15, 0x03, 0x35, 0x33, 0x15, 0x01, 0x42, 0xb4, 0x02, 0x1c, 0xb4, 0xfd, 0xe4, 0xb4, 0xb4, 0xb4, 0x02, 0x90, 0xc8, 0xc8, 0xc8, 0xc8, 0xfe, 0x70, 0xc8, 0xc8, 0x03, 0x20, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x42, 0x00, 0xf6, 0x04, 0xc7, 0x04, 0xde, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x01, 0x35, 0x33, 0x15, 0x13, 0x35, 0x33, 0x15, 0x03, 0x35, 0x33, 0x15, 0x01, 0x35, 0x33, 0x15, 0x03, 0x35, 0x33, 0x15, 0x02, 0xaa, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xfc, 0x8e, 0xb4, 0xc6, 0xb4, 0x02, 0x86, 0xc8, 0xc8, 0xfe, 0x70, 0xc8, 0xc8, 0x03, 0x20, 0xc8, 0xc8, 0xfc, 0xf4, 0xc8, 0xc8, 0x03, 0x0c, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc5, 0x00, 0x00, 0x01, 0x83, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0xc5, 0xbe, 0xbe, 0xbe, 0xbe, 0x05, 0xd5, 0xfe, 0xfc, 0x27, 0xfe, 0x00, 0x00, 0x04, 0x00, 0x5a, 0xfe, 0xe5, 0x05, 0x64, 0x06, 0xef, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x01, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x5a, 0xbe, 0xbe, 0x04, 0x4c, 0xbe, 0xbe, 0xfd, 0xda, 0xbe, 0xbe, 0xbe, 0xbe, 0x03, 0x69, 0xfe, 0xfe, 0xfe, 0x04, 0x84, 0xfe, 0xf9, 0xf2, 0xfe, 0x00, 0x05, 0x00, 0x64, 0x00, 0x00, 0x05, 0xa4, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x00, 0x25, 0x35, 0x33, 0x15, 0x03, 0x35, 0x33, 0x15, 0x01, 0x35, 0x33, 0x15, 0x03, 0x35, 0x33, 0x15, 0x01, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x04, 0x12, 0xb4, 0xb4, 0xb4, 0xfc, 0x8e, 0xb4, 0xc6, 0xb4, 0x01, 0x56, 0x90, 0xfd, 0xa9, 0x02, 0x57, 0x90, 0x02, 0x58, 0xf6, 0xc8, 0xc8, 0x03, 0x20, 0xc8, 0xc8, 0xfc, 0xf4, 0xc8, 0xc8, 0x03, 0x0c, 0xc8, 0xc8, 0xfe, 0x84, 0xfd, 0x66, 0x02, 0x9a, 0xa0, 0x02, 0x9b, 0xfd, 0x65, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc5, 0x00, 0x50, 0x01, 0x83, 0x05, 0x3e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0xc5, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x05, 0x3e, 0xfe, 0xfd, 0x0e, 0xfe, 0x02, 0xf6, 0xfe, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc5, 0x00, 0x11, 0x01, 0x83, 0x05, 0x77, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0xc5, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x02, 0x89, 0xfe, 0x03, 0xec, 0xfe, 0xfc, 0x96, 0xfe, 0x03, 0xf0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4e, 0x02, 0x8d, 0x02, 0xa3, 0x05, 0xf0, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0xd4, 0xb6, 0x2d, 0x2e, 0x2e, 0x2d, 0xb6, 0x2d, 0x2e, 0x2e, 0x88, 0x91, 0x99, 0x99, 0x91, 0x92, 0x99, 0x99, 0x05, 0x97, 0x56, 0x56, 0xac, 0xad, 0x56, 0x56, 0x56, 0x56, 0xad, 0xac, 0x56, 0xaf, 0xde, 0xd3, 0xd4, 0xde, 0xde, 0xd4, 0xd3, 0xde, 0x00, 0x00, 0x02, 0x00, 0x6d, 0x02, 0x9c, 0x00, 0xd7, 0x06, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x11, 0x33, 0x15, 0x23, 0x6e, 0x68, 0x68, 0x68, 0x68, 0x05, 0x0f, 0xfd, 0x8d, 0x03, 0x67, 0x82, 0x00, 0x02, 0x00, 0x38, 0x02, 0x9c, 0x02, 0xa9, 0x05, 0xdf, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x00, 0x09, 0x01, 0x21, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x01, 0xad, 0xfe, 0xea, 0x01, 0x16, 0x13, 0x95, 0x79, 0x79, 0x82, 0xfe, 0x8c, 0x05, 0x66, 0xfe, 0x5d, 0x02, 0x1c, 0xfd, 0xe4, 0x6d, 0xba, 0xba, 0x79, 0x00, 0x00, 0x01, 0x00, 0x5b, 0x02, 0x8d, 0x02, 0x8b, 0x05, 0xdf, 0x00, 0x20, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x80, 0x01, 0xcb, 0xfe, 0xa0, 0x19, 0x1a, 0x19, 0x1a, 0x90, 0x55, 0x55, 0x58, 0x56, 0x9e, 0x36, 0x72, 0x3b, 0x33, 0x38, 0x38, 0x3e, 0x64, 0x75, 0x75, 0x64, 0x2f, 0x5e, 0x30, 0x05, 0xdf, 0x5f, 0xcc, 0x09, 0x04, 0x04, 0x4d, 0x4c, 0x83, 0x87, 0x4b, 0x4a, 0x12, 0x12, 0x71, 0x1b, 0x0e, 0x0d, 0x66, 0xae, 0x66, 0x14, 0x15, 0x00, 0x02, 0x00, 0x52, 0x02, 0x8d, 0x02, 0xa8, 0x05, 0xf0, 0x00, 0x0f, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x13, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x88, 0x50, 0x2e, 0x2e, 0x2e, 0x2e, 0x50, 0x4e, 0x2e, 0x2e, 0x2e, 0x2e, 0x9a, 0x2c, 0x2d, 0x2d, 0x2c, 0x74, 0x3d, 0x3d, 0x09, 0x22, 0x33, 0x35, 0x3d, 0x82, 0x4c, 0x4c, 0x50, 0x4e, 0x82, 0x97, 0x9e, 0x61, 0x61, 0xa4, 0x2c, 0x2d, 0x2d, 0x04, 0x6d, 0x34, 0x35, 0x5b, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5b, 0x35, 0x34, 0x01, 0x62, 0x67, 0x14, 0x0a, 0x0b, 0x4b, 0x4c, 0x99, 0x31, 0x1a, 0x1a, 0x4c, 0x4d, 0x84, 0x7f, 0x4f, 0x4e, 0xde, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x00, 0x00, 0x01, 0x00, 0x61, 0x02, 0x9c, 0x02, 0x8d, 0x05, 0xdf, 0x00, 0x06, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x23, 0x01, 0x21, 0x61, 0x02, 0x2b, 0xfe, 0xc7, 0x7a, 0x01, 0x27, 0xfe, 0x61, 0x05, 0xdf, 0x30, 0xfc, 0xed, 0x02, 0xe4, 0x00, 0x00, 0x00, 0x03, 0x00, 0x50, 0x02, 0x8d, 0x02, 0xa2, 0x05, 0xf0, 0x00, 0x0c, 0x00, 0x2a, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x34, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x20, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x01, 0xcd, 0xa8, 0x2f, 0x30, 0x5f, 0x54, 0x53, 0x30, 0x30, 0x30, 0xf8, 0x4c, 0x29, 0x2a, 0x93, 0x01, 0x02, 0x4a, 0x48, 0x29, 0x2a, 0x4b, 0x51, 0x33, 0x2f, 0x4c, 0x4e, 0x8e, 0x8f, 0x4c, 0x4e, 0x30, 0x31, 0x28, 0x2a, 0x2a, 0x4c, 0x49, 0x2c, 0x2b, 0x2b, 0x2a, 0x4b, 0x4a, 0x2c, 0x2a, 0x04, 0x2a, 0x2c, 0x2b, 0x4b, 0x4c, 0x56, 0x2c, 0x2b, 0x96, 0x2b, 0x5d, 0x12, 0x31, 0x32, 0x48, 0x64, 0x74, 0x3a, 0x3a, 0x64, 0x4a, 0x30, 0x31, 0x12, 0x12, 0x3a, 0x37, 0x50, 0x79, 0x41, 0x41, 0x41, 0x41, 0x79, 0x4e, 0x39, 0x38, 0xc6, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x41, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4a, 0x02, 0x8d, 0x02, 0x9f, 0x05, 0xf0, 0x00, 0x1f, 0x00, 0x2e, 0x00, 0x00, 0x13, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x13, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x82, 0x2d, 0x2d, 0x2d, 0x2b, 0x74, 0x3d, 0x3c, 0x09, 0x1f, 0x36, 0x33, 0x3e, 0x82, 0x97, 0x4e, 0x4f, 0x83, 0x96, 0x4e, 0x4f, 0x60, 0x61, 0xa4, 0x2c, 0x2d, 0x2d, 0xb8, 0x4f, 0x5c, 0x2e, 0x2e, 0x4f, 0x4d, 0x30, 0x2e, 0x2e, 0x2e, 0x02, 0xae, 0x67, 0x14, 0x0b, 0x0a, 0x4b, 0x4b, 0x9a, 0x2f, 0x1b, 0x1a, 0x98, 0x84, 0x81, 0x4d, 0x4e, 0x6f, 0x6f, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x01, 0x72, 0x68, 0x5c, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5c, 0x34, 0x34, 0x00, 0x00, 0x01, 0x00, 0x7b, 0x02, 0x9c, 0x03, 0x52, 0x05, 0x6b, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x02, 0x16, 0x01, 0x3c, 0xfe, 0xc4, 0x5f, 0xfe, 0xc4, 0x01, 0x3c, 0x05, 0x6b, 0xfe, 0xc8, 0x5f, 0xfe, 0xc8, 0x01, 0x38, 0x5f, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7b, 0x03, 0xd4, 0x03, 0x52, 0x04, 0x33, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x7b, 0x02, 0xd7, 0xfd, 0x29, 0x04, 0x33, 0x5f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x7b, 0x03, 0x61, 0x03, 0x52, 0x04, 0xa5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x7b, 0x02, 0xd7, 0xfd, 0x29, 0x02, 0xd7, 0xfd, 0x29, 0x04, 0xa5, 0x5e, 0x87, 0x5f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x02, 0x05, 0x01, 0x68, 0x06, 0x02, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x10, 0x16, 0x17, 0x23, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x01, 0x68, 0x4c, 0x49, 0x49, 0x4c, 0x5b, 0x55, 0x2a, 0x2a, 0x2a, 0x2a, 0x55, 0x06, 0x02, 0x81, 0xfc, 0xfe, 0xfe, 0xfe, 0x80, 0x83, 0x80, 0x7f, 0xfa, 0x7f, 0x7e, 0x84, 0x00, 0x01, 0x00, 0x5c, 0x02, 0x05, 0x01, 0x61, 0x06, 0x02, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x33, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x23, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x5d, 0x5b, 0x55, 0x2a, 0x2a, 0x2a, 0x2a, 0x55, 0x5b, 0x4b, 0x25, 0x26, 0x26, 0x25, 0x06, 0x02, 0x84, 0x7e, 0x7f, 0xfa, 0x7f, 0x80, 0x83, 0x80, 0x7f, 0x7f, 0x01, 0x02, 0x7e, 0x7e, 0x00, 0x01, 0x00, 0x69, 0x02, 0x9c, 0x02, 0x7e, 0x05, 0x1e, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x02, 0x7d, 0x68, 0x46, 0x47, 0x54, 0x61, 0x6a, 0x6a, 0x25, 0x65, 0x43, 0x6d, 0x70, 0x04, 0x17, 0xfe, 0x85, 0x01, 0x77, 0x59, 0x59, 0x6b, 0x5c, 0xfe, 0x9e, 0x02, 0x73, 0x61, 0x38, 0x38, 0x86, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4e, 0xff, 0xf1, 0x02, 0xa3, 0x03, 0x54, 0x12, 0x07, 0x07, 0xa0, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7b, 0x00, 0x00, 0x02, 0x7f, 0x03, 0x43, 0x12, 0x07, 0x00, 0x7b, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x54, 0x00, 0x00, 0x02, 0x6f, 0x03, 0x54, 0x12, 0x07, 0x00, 0x74, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x58, 0xff, 0xf1, 0x02, 0x86, 0x03, 0x54, 0x12, 0x07, 0x00, 0x75, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x38, 0x00, 0x00, 0x02, 0xa9, 0x03, 0x43, 0x12, 0x07, 0x07, 0xa2, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5b, 0xff, 0xf1, 0x02, 0x8b, 0x03, 0x43, 0x12, 0x07, 0x07, 0xa3, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0xff, 0xf1, 0x02, 0xa8, 0x03, 0x54, 0x12, 0x07, 0x07, 0xa4, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x61, 0x00, 0x00, 0x02, 0x8d, 0x03, 0x43, 0x12, 0x07, 0x07, 0xa5, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x50, 0xff, 0xf1, 0x02, 0xa2, 0x03, 0x54, 0x12, 0x07, 0x07, 0xa6, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4a, 0xff, 0xf1, 0x02, 0x9f, 0x03, 0x54, 0x12, 0x07, 0x07, 0xa7, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7b, 0x00, 0x00, 0x03, 0x52, 0x02, 0xcf, 0x12, 0x07, 0x07, 0xa8, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7b, 0x01, 0x38, 0x03, 0x52, 0x01, 0x97, 0x12, 0x07, 0x07, 0xa9, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7b, 0x00, 0xc5, 0x03, 0x52, 0x02, 0x09, 0x12, 0x07, 0x07, 0xaa, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0x69, 0x01, 0x68, 0x03, 0x66, 0x12, 0x07, 0x07, 0xab, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5c, 0xff, 0x69, 0x01, 0x61, 0x03, 0x66, 0x12, 0x07, 0x07, 0xac, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x45, 0xff, 0xf0, 0x02, 0x5e, 0x02, 0x82, 0x12, 0x07, 0x04, 0xf9, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xf0, 0x02, 0x8d, 0x02, 0x82, 0x12, 0x07, 0x04, 0xff, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xf0, 0x02, 0x88, 0x02, 0x82, 0x12, 0x07, 0x05, 0x08, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x00, 0x00, 0x02, 0xd1, 0x02, 0x73, 0x12, 0x07, 0x02, 0xa5, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xf0, 0x02, 0x8d, 0x02, 0x82, 0x12, 0x07, 0x05, 0x00, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x00, 0x00, 0x02, 0x7e, 0x03, 0x67, 0x12, 0x07, 0x02, 0x72, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x00, 0x00, 0x02, 0x9d, 0x03, 0x67, 0x12, 0x07, 0x05, 0x05, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6d, 0x00, 0x00, 0x00, 0xd7, 0x03, 0x67, 0x12, 0x07, 0x02, 0xa3, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x00, 0x00, 0x04, 0x09, 0x02, 0x82, 0x12, 0x07, 0x05, 0x06, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x00, 0x00, 0x02, 0x7e, 0x02, 0x82, 0x12, 0x07, 0x07, 0xad, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0xff, 0x11, 0x02, 0xa2, 0x02, 0x82, 0x12, 0x07, 0x05, 0x0c, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0x00, 0x00, 0x02, 0x4f, 0x02, 0x93, 0x12, 0x07, 0x02, 0xa4, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1f, 0x00, 0x00, 0x01, 0xac, 0x03, 0x25, 0x12, 0x07, 0x05, 0x0d, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4d, 0x00, 0x00, 0x06, 0x03, 0x05, 0xd6, 0x00, 0x23, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x10, 0x00, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x36, 0x37, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x03, 0x7a, 0x47, 0xa0, 0x59, 0xe5, 0xfe, 0xf8, 0x01, 0x08, 0xe5, 0x5b, 0x9f, 0x46, 0x44, 0x9c, 0x58, 0xad, 0xb8, 0xb8, 0xad, 0x58, 0x9c, 0x44, 0x02, 0x7d, 0xfe, 0x0b, 0x01, 0xe1, 0xfe, 0x1f, 0x02, 0x01, 0xfd, 0x77, 0x01, 0xb8, 0x36, 0x36, 0x01, 0x37, 0x02, 0x1c, 0x01, 0x37, 0x35, 0x36, 0x9f, 0x47, 0x46, 0xea, 0xfe, 0x44, 0xea, 0x46, 0x47, 0x02, 0x0a, 0x80, 0xfe, 0xb5, 0x80, 0xfe, 0x6b, 0x80, 0x00, 0x03, 0x00, 0x67, 0xff, 0xa6, 0x04, 0x45, 0x06, 0x39, 0x00, 0x27, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x00, 0x01, 0x16, 0x17, 0x37, 0x33, 0x07, 0x16, 0x17, 0x15, 0x26, 0x27, 0x01, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x23, 0x37, 0x26, 0x27, 0x07, 0x23, 0x37, 0x26, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x3f, 0x01, 0x33, 0x07, 0x06, 0x07, 0x06, 0x11, 0x14, 0x17, 0x01, 0x26, 0x27, 0x01, 0x16, 0x17, 0x03, 0x11, 0x3a, 0x38, 0x1b, 0x8c, 0x2b, 0x24, 0x22, 0x35, 0x39, 0xfe, 0xe1, 0x10, 0x6b, 0xbe, 0x54, 0x58, 0xc2, 0x6d, 0x18, 0x18, 0x10, 0x8b, 0x16, 0x3a, 0x34, 0x22, 0x8b, 0x3a, 0x11, 0x0f, 0xa0, 0xa0, 0x90, 0xed, 0x13, 0x8d, 0xcd, 0x82, 0x4f, 0x71, 0x4a, 0x01, 0xfc, 0x38, 0x3d, 0xfe, 0xe1, 0x30, 0x3a, 0x05, 0xeb, 0x08, 0x13, 0x69, 0xa5, 0x16, 0x1c, 0xd5, 0x3c, 0x29, 0xfb, 0x97, 0x5e, 0x5f, 0xd3, 0x48, 0x48, 0x02, 0x3f, 0x57, 0x12, 0x1e, 0x87, 0xe6, 0x12, 0x15, 0xcf, 0x01, 0x67, 0x01, 0x68, 0xd0, 0xb9, 0x14, 0x4b, 0xfc, 0x1f, 0x70, 0x9d, 0xfe, 0xd8, 0xee, 0x94, 0x03, 0xcb, 0x13, 0x04, 0xfb, 0x95, 0x28, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0xff, 0xe4, 0x04, 0x3b, 0x05, 0xf0, 0x00, 0x2c, 0x00, 0x00, 0x25, 0x36, 0x37, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x17, 0x16, 0x17, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x1f, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x02, 0xdd, 0x57, 0x4f, 0x5f, 0x54, 0x57, 0xc3, 0x6d, 0xfe, 0xe9, 0xfe, 0xbe, 0x01, 0x42, 0x01, 0x17, 0x6e, 0xc4, 0x55, 0x54, 0xbe, 0x6b, 0xd3, 0xe0, 0x70, 0x54, 0x8a, 0x89, 0x2b, 0x8a, 0x63, 0x0e, 0x22, 0x15, 0x01, 0x18, 0x36, 0x20, 0x73, 0x7d, 0x8a, 0x07, 0x27, 0x2f, 0x5f, 0xd3, 0x48, 0x47, 0x01, 0x9e, 0x01, 0x67, 0x01, 0x68, 0x01, 0x9f, 0x47, 0x47, 0xd5, 0x5f, 0x5e, 0xfe, 0xc7, 0xfe, 0xd8, 0xfe, 0xd9, 0x9c, 0x75, 0x1e, 0x03, 0x5d, 0x9d, 0x5c, 0x59, 0x04, 0x05, 0xaa, 0x10, 0x0f, 0xb6, 0xab, 0x00, 0x00, 0x00, 0x01, 0x00, 0x77, 0x00, 0x00, 0x04, 0x51, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x01, 0x4c, 0x03, 0x04, 0xfd, 0xb2, 0x02, 0x15, 0xfd, 0xeb, 0xe1, 0xe1, 0xb6, 0xd4, 0x01, 0x7e, 0x04, 0x57, 0xaa, 0xfe, 0x48, 0xaa, 0xfe, 0xb5, 0x45, 0xfe, 0xc7, 0x01, 0x39, 0x45, 0x00, 0x00, 0x00, 0x01, 0x00, 0x74, 0x00, 0x00, 0x03, 0xf2, 0x05, 0xf0, 0x00, 0x23, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x35, 0x33, 0x11, 0x23, 0x35, 0x33, 0x35, 0x23, 0x35, 0x33, 0x35, 0x10, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x01, 0xfc, 0x01, 0xf6, 0xfc, 0x82, 0xd4, 0xab, 0xab, 0xb3, 0xb3, 0xc1, 0xd1, 0x37, 0x88, 0x47, 0x45, 0x7a, 0x37, 0x85, 0x69, 0x01, 0x60, 0xfe, 0xa0, 0x01, 0x68, 0x01, 0xec, 0xfe, 0xbe, 0xaa, 0xaa, 0x01, 0x42, 0x8f, 0x8f, 0x8f, 0x5f, 0x01, 0x05, 0xf3, 0x1f, 0x1d, 0xb6, 0x29, 0x29, 0x9b, 0xd4, 0x48, 0x8f, 0x8f, 0x8f, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xff, 0x42, 0x06, 0x67, 0x05, 0x1e, 0x00, 0x2b, 0x00, 0x00, 0x05, 0x23, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x13, 0x33, 0x07, 0x36, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x02, 0x84, 0x99, 0x01, 0x49, 0x05, 0x2e, 0x34, 0x6b, 0x7f, 0x4a, 0x4b, 0xa7, 0xa7, 0x38, 0x50, 0x4f, 0x6d, 0x6e, 0x4c, 0x31, 0x21, 0x78, 0x99, 0x4f, 0x52, 0x6c, 0x9e, 0xab, 0xa7, 0x66, 0x6a, 0x80, 0x96, 0xa6, 0xbe, 0x03, 0x78, 0x8d, 0x47, 0x4d, 0x5f, 0x61, 0xa2, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x66, 0x32, 0x31, 0x3e, 0x26, 0x3e, 0x01, 0x45, 0xd6, 0x33, 0xf6, 0xe1, 0xfd, 0x5c, 0x02, 0x9e, 0xa1, 0x9c, 0xbe, 0xa4, 0xfd, 0x87, 0x01, 0x1d, 0x00, 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x04, 0xfa, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x06, 0x00, 0x22, 0x00, 0x26, 0x00, 0x29, 0x00, 0x00, 0x01, 0x27, 0x15, 0x13, 0x27, 0x23, 0x15, 0x03, 0x33, 0x13, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x33, 0x15, 0x23, 0x11, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x23, 0x35, 0x33, 0x05, 0x17, 0x33, 0x35, 0x03, 0x17, 0x35, 0x02, 0x10, 0x47, 0xa4, 0x33, 0x71, 0xb1, 0xf5, 0xbe, 0xcf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xf4, 0xbe, 0xcf, 0xb1, 0xaf, 0xaf, 0xaf, 0xaf, 0x01, 0xde, 0x32, 0x72, 0x47, 0x47, 0x03, 0xaf, 0xce, 0xce, 0xfe, 0xf2, 0x93, 0x93, 0x03, 0x34, 0xfd, 0xda, 0x02, 0x26, 0xfd, 0xda, 0x7b, 0x93, 0x7b, 0xfd, 0xda, 0x02, 0x26, 0xfd, 0xda, 0x02, 0x26, 0x7b, 0x93, 0x7b, 0x7b, 0x93, 0x93, 0xfe, 0xf2, 0xce, 0xce, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0xff, 0xe3, 0x08, 0xd3, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x50, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x32, 0x17, 0x16, 0x17, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x23, 0x22, 0x26, 0x35, 0x11, 0x01, 0x60, 0xd7, 0x78, 0x82, 0x82, 0x78, 0x01, 0xad, 0x05, 0x66, 0x6e, 0xd4, 0xd7, 0xab, 0x01, 0x82, 0xd4, 0x6e, 0x4f, 0x15, 0x49, 0x9d, 0x01, 0x41, 0xfe, 0xbf, 0x3f, 0x62, 0x9a, 0x56, 0xa8, 0x52, 0x6e, 0x77, 0x56, 0x91, 0x36, 0x90, 0x81, 0xbe, 0xae, 0x57, 0x98, 0x41, 0x43, 0x8e, 0x4d, 0x74, 0x74, 0x54, 0x7d, 0x35, 0xa7, 0x8b, 0xd2, 0xb6, 0x4d, 0xa5, 0x5b, 0x9a, 0xb5, 0x89, 0x05, 0x2f, 0xfd, 0xcf, 0x92, 0x87, 0x86, 0x92, 0xfe, 0xcc, 0xc8, 0x6a, 0x71, 0xfd, 0xa8, 0x05, 0xd5, 0x71, 0x52, 0x88, 0x01, 0x3e, 0xfe, 0xc2, 0x8f, 0xfd, 0xa0, 0x89, 0x4e, 0x23, 0x35, 0x35, 0x59, 0x51, 0x4b, 0x50, 0x25, 0x0f, 0x24, 0x95, 0x82, 0x9e, 0xac, 0x1e, 0x1e, 0xae, 0x28, 0x28, 0x54, 0x54, 0x40, 0x49, 0x21, 0x0e, 0x2a, 0x99, 0x89, 0x9c, 0xb6, 0x23, 0x23, 0x01, 0x9f, 0xd2, 0x02, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0xff, 0xe3, 0x07, 0x62, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x45, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x10, 0x26, 0x23, 0x01, 0x17, 0x23, 0x03, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x26, 0x01, 0x6b, 0xe4, 0x84, 0x86, 0x86, 0x84, 0x02, 0x79, 0x04, 0xc4, 0xac, 0x42, 0x7d, 0x6c, 0xc6, 0xb6, 0x01, 0x9a, 0xe7, 0xe2, 0x75, 0x71, 0x3b, 0x6e, 0x38, 0x52, 0x58, 0x57, 0x59, 0x57, 0x75, 0x7e, 0x5b, 0x9a, 0x39, 0x9a, 0x89, 0xca, 0xb9, 0x5c, 0xa2, 0x44, 0x46, 0x97, 0x51, 0x7c, 0x7b, 0x58, 0x86, 0x38, 0xb1, 0x94, 0xde, 0xc3, 0x51, 0x57, 0x28, 0x05, 0x2f, 0xfd, 0xee, 0x87, 0x01, 0x06, 0x85, 0xfa, 0xd8, 0x07, 0x01, 0x7f, 0x96, 0x62, 0xfd, 0x89, 0x05, 0xd5, 0xd6, 0xd8, 0x8d, 0xba, 0x24, 0x16, 0x90, 0x7e, 0xb4, 0x33, 0x19, 0x1b, 0x59, 0x51, 0x4b, 0x50, 0x25, 0x0f, 0x24, 0x95, 0x82, 0x9e, 0xac, 0x1e, 0x1e, 0xae, 0x28, 0x28, 0x54, 0x54, 0x40, 0x49, 0x21, 0x0e, 0x2a, 0x99, 0x89, 0x9c, 0xb6, 0x12, 0x08, 0x00, 0x06, 0x00, 0x35, 0x00, 0x00, 0x06, 0xea, 0x05, 0xd5, 0x00, 0x1f, 0x00, 0x22, 0x00, 0x26, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x00, 0x13, 0x27, 0x23, 0x35, 0x33, 0x27, 0x33, 0x17, 0x21, 0x37, 0x33, 0x17, 0x21, 0x37, 0x33, 0x07, 0x33, 0x15, 0x23, 0x07, 0x33, 0x15, 0x23, 0x03, 0x23, 0x03, 0x23, 0x03, 0x23, 0x03, 0x23, 0x35, 0x05, 0x1b, 0x01, 0x01, 0x17, 0x21, 0x37, 0x01, 0x1b, 0x02, 0x07, 0x33, 0x27, 0x21, 0x17, 0x21, 0x37, 0xa4, 0x1b, 0x54, 0x34, 0x2c, 0xb8, 0x2b, 0x01, 0xde, 0x2b, 0xcc, 0x2c, 0x01, 0xdd, 0x2c, 0xb8, 0x2c, 0x33, 0x53, 0x1a, 0x6d, 0x8e, 0xca, 0xe5, 0xc4, 0xb0, 0xc6, 0xe4, 0xca, 0x8f, 0x04, 0x47, 0x94, 0x94, 0xfe, 0x9d, 0x1a, 0x01, 0x69, 0x1a, 0xfb, 0x9d, 0x94, 0x95, 0xce, 0x1a, 0x70, 0x19, 0xfd, 0x91, 0x1a, 0x01, 0x69, 0x1b, 0x04, 0x0f, 0x75, 0x8f, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0x8f, 0x75, 0x8f, 0xfc, 0x80, 0x03, 0x80, 0xfc, 0x80, 0x03, 0x80, 0x8f, 0x8f, 0xfd, 0x67, 0x02, 0x99, 0x01, 0x04, 0x75, 0x75, 0xfe, 0xfc, 0xfd, 0x67, 0x02, 0x99, 0x01, 0x04, 0x75, 0x75, 0x75, 0x75, 0x00, 0x00, 0x00, 0x02, 0x00, 0x55, 0xff, 0xe3, 0x05, 0x59, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x25, 0x32, 0x12, 0x19, 0x01, 0x23, 0x11, 0x34, 0x26, 0x23, 0x21, 0x11, 0x23, 0x29, 0x01, 0x22, 0x02, 0x19, 0x01, 0x33, 0x11, 0x14, 0x16, 0x33, 0x21, 0x03, 0x33, 0x56, 0x01, 0xd3, 0xe5, 0xec, 0xa6, 0x8d, 0x9e, 0xfe, 0xd2, 0xa5, 0x04, 0xff, 0xfe, 0x31, 0xe6, 0xec, 0xa6, 0x8d, 0x9f, 0x01, 0x31, 0x04, 0xa6, 0x05, 0xd2, 0x03, 0xfe, 0xd6, 0xfe, 0xdc, 0xfe, 0x91, 0x01, 0x56, 0xf0, 0xd3, 0xfa, 0xb2, 0x01, 0x2a, 0x01, 0x24, 0x01, 0x6f, 0xfe, 0xaa, 0xf0, 0xd3, 0x05, 0x4e, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0xc0, 0x04, 0x76, 0x06, 0x14, 0x10, 0x26, 0x00, 0xd3, 0x00, 0x00, 0x10, 0x06, 0x02, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0xe3, 0x04, 0x1b, 0x05, 0xf0, 0x00, 0x31, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x21, 0x07, 0x21, 0x06, 0x14, 0x15, 0x1c, 0x01, 0x17, 0x21, 0x07, 0x21, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x03, 0x23, 0x37, 0x33, 0x34, 0x26, 0x35, 0x34, 0x36, 0x35, 0x23, 0x37, 0x33, 0x12, 0x00, 0x33, 0x32, 0x16, 0x04, 0x1a, 0x52, 0x98, 0x5c, 0x8d, 0xb6, 0x1c, 0x02, 0x07, 0x32, 0xfe, 0x1c, 0x02, 0x02, 0x01, 0x92, 0x33, 0xfe, 0xb0, 0x1c, 0xb6, 0x8d, 0x5c, 0x98, 0x52, 0x50, 0xa6, 0x57, 0xd5, 0xfe, 0xea, 0x24, 0xbe, 0x32, 0x7d, 0x01, 0x01, 0xaf, 0x32, 0x8c, 0x24, 0x01, 0x17, 0xd4, 0x59, 0xa6, 0x05, 0x62, 0xd5, 0x69, 0x5a, 0xc8, 0xbb, 0x7b, 0x18, 0x2e, 0x23, 0x20, 0x2e, 0x18, 0x7b, 0xbb, 0xca, 0x5a, 0x69, 0xd3, 0x48, 0x48, 0x01, 0x22, 0x01, 0x03, 0x7b, 0x17, 0x2f, 0x20, 0x23, 0x2f, 0x17, 0x7b, 0x01, 0x01, 0x01, 0x22, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x24, 0x00, 0x00, 0x04, 0x94, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x01, 0x33, 0x01, 0x21, 0x15, 0x21, 0x01, 0x23, 0x01, 0x11, 0x23, 0x11, 0x23, 0x35, 0xac, 0xaa, 0x02, 0x36, 0xdb, 0xfd, 0xc0, 0x01, 0x7f, 0xfe, 0x83, 0x02, 0x6b, 0xe0, 0xfd, 0xa2, 0xaa, 0x88, 0x03, 0x54, 0x02, 0x81, 0xfd, 0x89, 0x02, 0x77, 0xfd, 0x7f, 0x73, 0xfd, 0x1f, 0x02, 0xcf, 0xfd, 0x31, 0x02, 0xe1, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x04, 0x83, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x37, 0x17, 0x05, 0x15, 0x37, 0x17, 0x05, 0x11, 0x23, 0x11, 0x07, 0x27, 0x25, 0x35, 0x07, 0x27, 0x01, 0xef, 0xfe, 0x23, 0x04, 0x71, 0xfe, 0x23, 0xce, 0x48, 0xfe, 0xea, 0xcf, 0x48, 0xfe, 0xe9, 0xb7, 0xd0, 0x45, 0x01, 0x15, 0xd1, 0x45, 0x03, 0x8d, 0x01, 0x9e, 0xaa, 0xaa, 0xfe, 0xf1, 0xa1, 0x6f, 0xd8, 0x88, 0xa2, 0x6f, 0xd9, 0xfd, 0xb8, 0x01, 0xba, 0xa1, 0x6e, 0xd9, 0x88, 0xa2, 0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0xbb, 0xfe, 0x39, 0x08, 0xae, 0x05, 0xf0, 0x00, 0x16, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x77, 0x00, 0x83, 0x00, 0x00, 0x01, 0x27, 0x13, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x13, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x05, 0x36, 0x37, 0x13, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x27, 0x3e, 0x01, 0x37, 0x36, 0x33, 0x32, 0x04, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x2f, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x01, 0x03, 0x06, 0x07, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x01, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x06, 0x54, 0xa6, 0x91, 0x1f, 0x38, 0x2c, 0x87, 0x57, 0x43, 0x6e, 0x22, 0x3a, 0x2b, 0x2c, 0x49, 0x52, 0x4e, 0x32, 0x37, 0x2b, 0x1b, 0xde, 0x4e, 0x2c, 0x0b, 0x0e, 0x09, 0x15, 0x1c, 0x38, 0x21, 0x36, 0x15, 0x12, 0x11, 0x10, 0x1a, 0x0b, 0x16, 0x12, 0xfa, 0x5a, 0x0b, 0x0a, 0xa2, 0x2a, 0x1d, 0x1f, 0x16, 0x13, 0x0f, 0x9d, 0x18, 0x5a, 0x3c, 0x6b, 0x9e, 0xb6, 0x01, 0x0f, 0x55, 0x4c, 0x4a, 0x19, 0x17, 0x3c, 0x20, 0x57, 0x37, 0x3e, 0x44, 0x56, 0x43, 0x38, 0x29, 0x2e, 0x58, 0x1d, 0x3a, 0x0d, 0x0e, 0x10, 0x13, 0x46, 0x53, 0x69, 0x45, 0x45, 0x77, 0x5e, 0x42, 0x01, 0xb4, 0xa0, 0x16, 0x13, 0x24, 0x4b, 0x2e, 0x33, 0x30, 0x61, 0x8a, 0x34, 0x27, 0x1a, 0x15, 0x1b, 0x1c, 0x32, 0x77, 0xfd, 0x8d, 0x24, 0x2b, 0x22, 0x0c, 0x0c, 0x15, 0x14, 0x1d, 0x29, 0xfe, 0x39, 0x29, 0x02, 0xd0, 0x97, 0x69, 0x52, 0x6d, 0x3a, 0x33, 0x58, 0x92, 0x77, 0x64, 0x67, 0x37, 0x3f, 0x20, 0x17, 0x32, 0x01, 0xf8, 0x6a, 0x1a, 0x37, 0x23, 0x3d, 0x35, 0x28, 0x36, 0x24, 0x20, 0x1b, 0x36, 0x32, 0x39, 0x54, 0x2f, 0x14, 0x0c, 0x0b, 0xb7, 0x28, 0x32, 0x03, 0x4d, 0x0a, 0x14, 0x16, 0x21, 0x1d, 0x3a, 0x35, 0x53, 0x7d, 0x24, 0x40, 0x7b, 0x6d, 0x62, 0xf5, 0x81, 0x71, 0x8c, 0x82, 0x7e, 0x45, 0x73, 0x2f, 0x34, 0x18, 0x1d, 0x09, 0x0a, 0x2d, 0x13, 0x26, 0x0a, 0x0a, 0x22, 0x17, 0x54, 0x41, 0x42, 0x60, 0x5d, 0x85, 0x03, 0x92, 0xfc, 0x9b, 0x7c, 0x40, 0x1b, 0x38, 0x16, 0x19, 0x86, 0x6e, 0x52, 0x80, 0x6b, 0x63, 0x64, 0x5d, 0x61, 0x43, 0x9c, 0xfb, 0xa0, 0x22, 0x0e, 0x0e, 0x0f, 0x18, 0x0f, 0x0e, 0x00, 0x00, 0x02, 0x00, 0x29, 0xff, 0xe3, 0x04, 0x1a, 0x05, 0xf0, 0x00, 0x29, 0x00, 0x35, 0x00, 0x00, 0x13, 0x27, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x35, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x25, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0xa6, 0x7d, 0x85, 0x64, 0x6f, 0x3a, 0x4f, 0x1f, 0x2b, 0x31, 0xcc, 0x48, 0x50, 0x7b, 0x68, 0x57, 0x4c, 0x61, 0xa3, 0x71, 0x5f, 0xe3, 0x78, 0x52, 0x42, 0x6b, 0x7b, 0x62, 0x66, 0x43, 0x2d, 0x30, 0x2d, 0x01, 0xf8, 0x3d, 0x18, 0x20, 0x2d, 0x2f, 0x1e, 0x16, 0x02, 0x04, 0x60, 0xf0, 0x4e, 0x6b, 0x42, 0xb1, 0xfe, 0xac, 0x58, 0x60, 0x60, 0x53, 0xb1, 0xe3, 0xab, 0xa3, 0xbf, 0xc2, 0x86, 0x71, 0xa2, 0x4a, 0x3c, 0x93, 0x58, 0x72, 0x7e, 0x68, 0x46, 0xd9, 0x6c, 0xaf, 0x56, 0x31, 0x3f, 0x3f, 0x30, 0x57, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x3d, 0x00, 0x00, 0x04, 0x2c, 0x05, 0xd5, 0x00, 0x1d, 0x00, 0x24, 0x00, 0x2b, 0x00, 0x31, 0x00, 0x00, 0x13, 0x35, 0x23, 0x35, 0x33, 0x11, 0x21, 0x32, 0x17, 0x16, 0x17, 0x33, 0x15, 0x23, 0x16, 0x14, 0x07, 0x33, 0x15, 0x23, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x23, 0x35, 0x05, 0x21, 0x15, 0x33, 0x32, 0x37, 0x36, 0x01, 0x21, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x05, 0x21, 0x15, 0x21, 0x36, 0x34, 0x88, 0x4a, 0x4a, 0x01, 0x9a, 0xe2, 0x74, 0x45, 0x1c, 0x52, 0x40, 0x01, 0x01, 0x3f, 0x50, 0x1c, 0x46, 0x74, 0xe2, 0xe4, 0xb6, 0x4b, 0x02, 0xcd, 0xfe, 0x34, 0xe4, 0x7f, 0x45, 0x15, 0xfe, 0x43, 0x01, 0xcc, 0x0f, 0x15, 0x45, 0x7f, 0xe4, 0x01, 0xec, 0xfe, 0x14, 0x01, 0xec, 0x02, 0x03, 0xec, 0x56, 0x74, 0x01, 0x1f, 0x71, 0x44, 0x6a, 0x74, 0x15, 0x2c, 0x15, 0x74, 0x6b, 0x44, 0x71, 0xfd, 0xa8, 0x03, 0x78, 0x74, 0x74, 0x7a, 0x49, 0x16, 0x01, 0x59, 0x1b, 0x15, 0x49, 0xed, 0x56, 0x15, 0x2c, 0x00, 0x00, 0x02, 0x00, 0x53, 0xff, 0x5b, 0x04, 0x39, 0x06, 0x78, 0x00, 0x24, 0x00, 0x2d, 0x00, 0x00, 0x05, 0x23, 0x35, 0x26, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x27, 0x11, 0x36, 0x37, 0x36, 0x37, 0x11, 0x23, 0x35, 0x21, 0x11, 0x06, 0x07, 0x06, 0x07, 0x27, 0x11, 0x06, 0x07, 0x06, 0x11, 0x10, 0x17, 0x16, 0x02, 0xad, 0x7e, 0xc9, 0x7b, 0x97, 0x97, 0x7b, 0xc9, 0x7e, 0x5e, 0x57, 0x65, 0x54, 0x55, 0x61, 0x58, 0x60, 0x46, 0x39, 0x41, 0x33, 0x6c, 0x01, 0x05, 0x59, 0x6c, 0x5e, 0x69, 0x7e, 0x78, 0x47, 0x64, 0x64, 0x47, 0xa5, 0x8f, 0x1f, 0xa7, 0xcc, 0x01, 0x6d, 0x01, 0x6e, 0xcd, 0xa6, 0x1f, 0x8f, 0x89, 0x04, 0x1f, 0x24, 0x46, 0xd7, 0x5f, 0x30, 0x2c, 0x04, 0xfb, 0x3f, 0x02, 0x11, 0x12, 0x27, 0x01, 0x91, 0xa6, 0xfd, 0x7f, 0x53, 0x2a, 0x25, 0x05, 0xb2, 0x04, 0xa7, 0x20, 0x6c, 0x99, 0xfe, 0xd1, 0xfe, 0xd2, 0x99, 0x6c, 0x00, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x04, 0x85, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x1e, 0x00, 0x00, 0x13, 0x35, 0x21, 0x13, 0x33, 0x13, 0x21, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x13, 0x23, 0x03, 0x21, 0x03, 0x23, 0x13, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x21, 0x2f, 0x01, 0x33, 0x03, 0x2e, 0x01, 0x12, 0xa3, 0xce, 0xa3, 0x01, 0x12, 0xeb, 0x40, 0xab, 0x84, 0xa2, 0xbc, 0x9a, 0xfe, 0x39, 0x99, 0xc0, 0xa3, 0x83, 0xaa, 0x42, 0xad, 0x3c, 0x01, 0x7f, 0x3e, 0xe1, 0xbd, 0x5e, 0x03, 0x52, 0x7b, 0x02, 0x08, 0xfd, 0xf8, 0x7b, 0xcf, 0x7b, 0xfd, 0xf8, 0x02, 0x08, 0xfd, 0xf8, 0x02, 0x08, 0x7b, 0xcf, 0xcf, 0xcf, 0x7b, 0x01, 0x41, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0xff, 0xe3, 0x05, 0x2a, 0x05, 0xf0, 0x00, 0x36, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x37, 0x21, 0x35, 0x21, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x33, 0x15, 0x23, 0x06, 0x0f, 0x01, 0x21, 0x15, 0x21, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x24, 0x35, 0x34, 0x37, 0x23, 0x35, 0x01, 0x39, 0x04, 0x14, 0x42, 0x74, 0xfe, 0x62, 0x03, 0x37, 0x0b, 0x0b, 0x36, 0xa2, 0x94, 0x56, 0xb7, 0x68, 0x67, 0xc4, 0x5f, 0xdc, 0xfb, 0x16, 0x9d, 0xe9, 0x5c, 0xc3, 0x3c, 0x02, 0x44, 0xfc, 0xb2, 0x2d, 0xa9, 0x9c, 0x67, 0xd4, 0x6f, 0x73, 0xd8, 0x5f, 0xfd, 0xfe, 0xfa, 0x11, 0x98, 0x02, 0xa1, 0x07, 0x16, 0x4a, 0x2c, 0x7b, 0x08, 0x09, 0x2b, 0x6b, 0x76, 0x80, 0x36, 0x37, 0xc5, 0x26, 0x26, 0xe4, 0xc6, 0x55, 0x42, 0x7b, 0x5c, 0x2a, 0x0d, 0x7b, 0x3b, 0x5e, 0x7e, 0x88, 0x46, 0x45, 0xd0, 0x2f, 0x30, 0xe0, 0xd9, 0x4b, 0x3f, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x94, 0xfe, 0xd3, 0x04, 0x01, 0x06, 0x14, 0x00, 0x1f, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x11, 0x32, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x07, 0x11, 0x23, 0x11, 0x26, 0x27, 0x26, 0x11, 0x35, 0x10, 0x37, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x17, 0x16, 0x01, 0x03, 0x06, 0x07, 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x04, 0x00, 0x53, 0x97, 0x5b, 0x5b, 0x97, 0x53, 0x51, 0x53, 0x4f, 0x52, 0x5a, 0xa6, 0x69, 0xbe, 0xbf, 0x6d, 0xa0, 0x5b, 0x54, 0x4f, 0x53, 0xfe, 0xb0, 0x01, 0x52, 0x3c, 0x6a, 0x0e, 0x0c, 0x0c, 0x17, 0x61, 0x3c, 0x04, 0xa4, 0xd5, 0x69, 0x5a, 0xfb, 0xf1, 0x5a, 0x69, 0xd3, 0x48, 0x24, 0x22, 0x02, 0xfe, 0xf0, 0x01, 0x15, 0x16, 0x76, 0xd6, 0x01, 0x39, 0x11, 0x01, 0x42, 0xcb, 0x74, 0x17, 0xe8, 0xe2, 0x02, 0x22, 0x24, 0xfb, 0xa4, 0x03, 0xf9, 0x16, 0x43, 0x75, 0xaa, 0xa1, 0x66, 0xb4, 0x6c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x04, 0x83, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x12, 0x04, 0x71, 0xfb, 0x8f, 0x04, 0x71, 0xfe, 0x23, 0xb7, 0xfe, 0x23, 0x05, 0xd5, 0xaa, 0x78, 0xaa, 0xfb, 0xf7, 0x04, 0x09, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x04, 0x38, 0x05, 0xd5, 0x00, 0x26, 0x00, 0x00, 0x13, 0x37, 0x21, 0x07, 0x21, 0x16, 0x17, 0x21, 0x07, 0x23, 0x06, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x17, 0x13, 0x23, 0x03, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x21, 0x37, 0x21, 0x26, 0x27, 0x26, 0x23, 0x5f, 0x32, 0x03, 0xa6, 0x31, 0xfe, 0xc1, 0x47, 0x13, 0x01, 0x16, 0x31, 0xde, 0x05, 0x36, 0x3b, 0x70, 0x3a, 0x38, 0x34, 0x3b, 0xb8, 0xc3, 0xac, 0x44, 0x3d, 0x3f, 0x6c, 0xc6, 0xe5, 0x83, 0x43, 0x3d, 0x06, 0xfd, 0xf7, 0x32, 0x01, 0xcc, 0x10, 0x28, 0x43, 0x83, 0x05, 0x5a, 0x7b, 0x7b, 0x4e, 0x81, 0x7b, 0x7e, 0x55, 0x5d, 0x24, 0x16, 0x48, 0x44, 0x82, 0xfe, 0x68, 0x01, 0x7f, 0x97, 0x30, 0x31, 0xa6, 0x43, 0x3e, 0x72, 0x7b, 0x43, 0x34, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x05, 0x04, 0xad, 0x05, 0xda, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x10, 0x07, 0x06, 0x21, 0x23, 0x11, 0x07, 0x27, 0x25, 0x35, 0x07, 0x27, 0x25, 0x11, 0x33, 0x11, 0x37, 0x17, 0x05, 0x15, 0x37, 0x17, 0x05, 0x11, 0x20, 0x00, 0x11, 0x04, 0xad, 0xb8, 0xb7, 0xfe, 0x7b, 0x9b, 0xcf, 0x46, 0x01, 0x15, 0xd1, 0x44, 0x01, 0x15, 0xb6, 0xcf, 0x48, 0xfe, 0xe9, 0xd1, 0x48, 0xfe, 0xe7, 0x01, 0x16, 0x01, 0x02, 0x02, 0xf1, 0xfe, 0x7e, 0xb5, 0xb5, 0x02, 0x1e, 0xa1, 0x6e, 0xd8, 0x89, 0xa2, 0x6e, 0xd9, 0x01, 0xe4, 0xfe, 0xaa, 0xa2, 0x6f, 0xd9, 0x88, 0xa3, 0x6f, 0xda, 0xfd, 0xfb, 0x01, 0x18, 0x01, 0x2e, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x76, 0x05, 0x15, 0xff, 0xd1, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x01, 0x13, 0x33, 0x07, 0x21, 0x15, 0xfc, 0x77, 0xc4, 0x71, 0x77, 0x02, 0x9b, 0x05, 0x15, 0x00, 0xff, 0x9b, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x9d, 0x05, 0x15, 0xff, 0xf7, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x03, 0x21, 0x35, 0x21, 0x27, 0x33, 0x09, 0xfc, 0xa6, 0x02, 0x9b, 0x77, 0x72, 0x05, 0x15, 0x64, 0x9b, 0x00, 0x00, 0x01, 0xfc, 0x9d, 0x04, 0x7a, 0xff, 0xd1, 0x06, 0x14, 0x00, 0x08, 0x00, 0x00, 0x03, 0x21, 0x17, 0x23, 0x27, 0x37, 0x33, 0x07, 0x21, 0x30, 0xfd, 0x65, 0x77, 0x71, 0x9e, 0x9e, 0x71, 0x77, 0x02, 0x9b, 0x05, 0x15, 0x9b, 0xcd, 0xcd, 0x9b, 0x00, 0x01, 0xfc, 0x9d, 0x04, 0x7a, 0xff, 0xd1, 0x06, 0x14, 0x00, 0x08, 0x00, 0x00, 0x01, 0x35, 0x21, 0x27, 0x33, 0x17, 0x07, 0x23, 0x37, 0xfc, 0x9d, 0x02, 0x9b, 0x77, 0x72, 0x9d, 0x9d, 0x72, 0x77, 0x05, 0x15, 0x64, 0x9b, 0xcd, 0xcd, 0x9b, 0x00, 0x04, 0xfc, 0x77, 0x04, 0x7b, 0xff, 0xee, 0x06, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x17, 0xfc, 0x78, 0xb6, 0xb6, 0x02, 0xbf, 0xb7, 0xb7, 0xfe, 0xa0, 0xb7, 0xb7, 0x5c, 0x06, 0x10, 0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0x00, 0x00, 0x00, 0x05, 0xfb, 0xc8, 0x04, 0x7b, 0x00, 0x9f, 0x06, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x00, 0x03, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x05, 0x18, 0xb6, 0xb6, 0xfb, 0xe0, 0xb7, 0xb7, 0x02, 0xc0, 0xb6, 0xb6, 0xfe, 0xa0, 0xb7, 0xb7, 0x01, 0x0b, 0x06, 0x10, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x9d, 0x04, 0x7a, 0xff, 0xd1, 0x06, 0x14, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x17, 0x23, 0x27, 0x37, 0x33, 0x07, 0x21, 0x27, 0x33, 0x17, 0x07, 0x23, 0x37, 0xfd, 0x35, 0x77, 0x71, 0x9e, 0x9e, 0x71, 0x77, 0x02, 0x03, 0x77, 0x72, 0x9d, 0x9d, 0x72, 0x77, 0x05, 0x15, 0x9b, 0xcd, 0xcd, 0x9b, 0x9b, 0xcd, 0xcd, 0x9b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x3c, 0xff, 0xcf, 0x07, 0x10, 0x06, 0x04, 0x00, 0x0a, 0x00, 0x24, 0x00, 0x28, 0x00, 0x42, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x37, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x17, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x25, 0x33, 0x01, 0x23, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x01, 0xda, 0x90, 0x64, 0x4a, 0x41, 0x5c, 0x72, 0xa9, 0xa9, 0x03, 0x89, 0x62, 0x7f, 0x96, 0xb9, 0xb2, 0x98, 0x64, 0x5d, 0x3d, 0x74, 0x59, 0x53, 0x85, 0x40, 0xaf, 0xad, 0x02, 0x6c, 0xc2, 0xfc, 0xa4, 0xc3, 0x05, 0x18, 0x54, 0x64, 0x33, 0x6d, 0x7b, 0x7b, 0x6d, 0x33, 0x64, 0x54, 0x41, 0x76, 0x41, 0xb6, 0xd4, 0xd6, 0xbc, 0x3c, 0x73, 0x03, 0xf6, 0x42, 0x52, 0x43, 0x49, 0x94, 0x82, 0x0a, 0x4d, 0xfe, 0x0d, 0x3e, 0x05, 0x4f, 0x9e, 0x81, 0x96, 0x9b, 0x06, 0x57, 0x5c, 0x20, 0x37, 0xb2, 0x24, 0x1e, 0xca, 0xfa, 0xf9, 0xcb, 0x03, 0x84, 0xb2, 0x34, 0x1e, 0x9c, 0x94, 0x93, 0x9d, 0x1f, 0x34, 0xb1, 0x22, 0x1b, 0xfa, 0xd1, 0xd4, 0xf9, 0x1b, 0x00, 0x04, 0x00, 0x3c, 0xff, 0xcf, 0x07, 0x32, 0x06, 0x04, 0x00, 0x20, 0x00, 0x2b, 0x00, 0x45, 0x00, 0x49, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x34, 0x36, 0x04, 0x17, 0x15, 0x27, 0x26, 0x23, 0x22, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x14, 0x06, 0x23, 0x26, 0x27, 0x35, 0x17, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x27, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x37, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x17, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x25, 0x33, 0x01, 0x23, 0x05, 0xb4, 0x7a, 0x72, 0xa6, 0x01, 0x2d, 0x6e, 0x21, 0x64, 0x74, 0xa2, 0x35, 0x5e, 0x2b, 0x8a, 0x7b, 0xb5, 0x99, 0x9e, 0x82, 0x21, 0x84, 0x7d, 0xa0, 0x37, 0x6f, 0xfb, 0xfb, 0x90, 0x64, 0x4a, 0x41, 0x5c, 0x72, 0xa9, 0xa9, 0x03, 0x89, 0x62, 0x7f, 0x96, 0xb9, 0xb2, 0x98, 0x64, 0x5d, 0x3d, 0x74, 0x59, 0x53, 0x85, 0x40, 0xaf, 0xad, 0x02, 0x6c, 0xc2, 0xfc, 0xa4, 0xc3, 0x01, 0x7d, 0x1c, 0x7c, 0xef, 0x8e, 0x01, 0x34, 0xbc, 0x12, 0x39, 0x64, 0x24, 0x2c, 0x18, 0x0a, 0x21, 0x7f, 0xf3, 0x95, 0x06, 0x35, 0xca, 0x13, 0x4c, 0x66, 0x2c, 0x31, 0x1b, 0x02, 0x84, 0x42, 0x52, 0x43, 0x49, 0x94, 0x82, 0x0a, 0x4d, 0xfe, 0x0d, 0x3e, 0x05, 0x4f, 0x9e, 0x81, 0x96, 0x9b, 0x06, 0x57, 0x5c, 0x20, 0x37, 0xb2, 0x24, 0x1e, 0xca, 0xfa, 0xf9, 0xcb, 0x00, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x00, 0x18, 0x00, 0x21, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x11, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x01, 0x11, 0x06, 0x07, 0x06, 0x11, 0x10, 0x17, 0x16, 0x04, 0xa3, 0x50, 0xd1, 0x88, 0x92, 0x6d, 0x6d, 0x92, 0x88, 0xd1, 0x50, 0x5f, 0xd6, 0x76, 0xfe, 0xce, 0xfe, 0xa2, 0x01, 0x5e, 0x01, 0x32, 0x78, 0xd6, 0xfd, 0x56, 0x1f, 0x1c, 0x8d, 0x8d, 0x1c, 0x05, 0x62, 0x76, 0x41, 0x5a, 0x34, 0xfb, 0x2d, 0x34, 0x5a, 0x42, 0x75, 0x48, 0x48, 0x01, 0x9f, 0x01, 0x67, 0x01, 0x68, 0x01, 0x9f, 0x47, 0xfb, 0x13, 0x04, 0x5b, 0x1b, 0x21, 0xac, 0xfe, 0xba, 0xfe, 0xbb, 0xac, 0x21, 0x00, 0x00, 0xff, 0xff, 0x00, 0xaf, 0xff, 0xe3, 0x07, 0x96, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x72, 0x00, 0x00, 0x10, 0x07, 0x00, 0x26, 0x02, 0xf2, 0x00, 0x00, 0x00, 0x02, 0xff, 0xda, 0x00, 0x00, 0x04, 0x96, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x11, 0x35, 0x33, 0x15, 0x16, 0x17, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x27, 0x11, 0x36, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x07, 0x15, 0x21, 0x15, 0x21, 0x35, 0x26, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x01, 0x52, 0x42, 0x2e, 0x59, 0x59, 0x2e, 0x42, 0xb5, 0x33, 0x30, 0x49, 0x45, 0x47, 0x46, 0x31, 0x33, 0x33, 0x31, 0x46, 0x47, 0x46, 0x4a, 0x2e, 0x33, 0x02, 0x8f, 0xfc, 0xbc, 0x91, 0x61, 0x86, 0x88, 0x5f, 0x04, 0xb3, 0x1d, 0x3a, 0x72, 0xcd, 0xcd, 0x71, 0x3b, 0x1d, 0x03, 0xd4, 0x7a, 0x6e, 0x04, 0x0b, 0x12, 0x23, 0xac, 0x2b, 0x16, 0x0f, 0x04, 0xfc, 0xa4, 0x04, 0x10, 0x15, 0x2b, 0xaa, 0x24, 0x12, 0x0b, 0x04, 0x2a, 0xaa, 0xde, 0x20, 0x72, 0x9f, 0x01, 0x0e, 0x01, 0x12, 0x9d, 0x6e, 0x00, 0x04, 0x00, 0x36, 0xff, 0xcf, 0x07, 0x1b, 0x06, 0x04, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x28, 0x00, 0x32, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x25, 0x33, 0x01, 0x23, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x10, 0x26, 0x24, 0x20, 0x16, 0x15, 0x14, 0x06, 0x20, 0x26, 0x35, 0x34, 0x02, 0xb9, 0x55, 0x64, 0x32, 0x6d, 0x7b, 0x7b, 0x6d, 0x32, 0x64, 0x55, 0x42, 0x75, 0x42, 0xb6, 0xd4, 0xd6, 0xbc, 0x3d, 0x73, 0x02, 0x94, 0xc2, 0xfc, 0xa4, 0xc3, 0x03, 0xfa, 0x57, 0x6a, 0x6a, 0x57, 0x56, 0x6b, 0x6b, 0xfe, 0xfc, 0x01, 0x5c, 0xc4, 0xc4, 0xfe, 0xa4, 0xc3, 0x05, 0x97, 0xb2, 0x34, 0x1e, 0x9c, 0x94, 0x93, 0x9d, 0x1f, 0x34, 0xb1, 0x22, 0x1d, 0xfc, 0xd1, 0xd4, 0xf9, 0x1b, 0x4b, 0xf9, 0xcb, 0x03, 0x04, 0x9e, 0x92, 0x91, 0x9f, 0xa0, 0x01, 0x20, 0xa0, 0x9d, 0xf8, 0xd5, 0xd4, 0xf8, 0xf8, 0xd4, 0xd5, 0x00, 0x03, 0x00, 0x36, 0xff, 0xcf, 0x07, 0x79, 0x06, 0x04, 0x00, 0x13, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x25, 0x33, 0x01, 0x23, 0x04, 0xd3, 0xa9, 0x49, 0x48, 0x59, 0x69, 0xa9, 0xa9, 0x05, 0x82, 0x56, 0x8e, 0x91, 0xfd, 0xe6, 0x55, 0x64, 0x32, 0x6d, 0x7b, 0x7b, 0x6d, 0x32, 0x64, 0x55, 0x42, 0x75, 0x42, 0xb6, 0xd4, 0xd6, 0xbc, 0x3d, 0x73, 0x02, 0x94, 0xc2, 0xfc, 0xa4, 0xc3, 0x01, 0x4c, 0x02, 0x10, 0xfd, 0xf5, 0x72, 0x69, 0x81, 0x75, 0x01, 0xf0, 0xfc, 0x90, 0x44, 0x09, 0x50, 0xc1, 0x04, 0xff, 0xb2, 0x34, 0x1e, 0x9c, 0x94, 0x93, 0x9d, 0x1f, 0x34, 0xb1, 0x22, 0x1d, 0xfc, 0xd1, 0xd4, 0xf9, 0x1b, 0x4b, 0xf9, 0xcb, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x93, 0xff, 0xe3, 0x04, 0x09, 0x05, 0xf0, 0x10, 0x06, 0x01, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xfe, 0xd6, 0x04, 0xa0, 0x04, 0xe3, 0x10, 0x07, 0x03, 0xc1, 0x00, 0x00, 0xfe, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x00, 0xaf, 0x00, 0x00, 0x06, 0x6f, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x72, 0x00, 0x00, 0x10, 0x07, 0x00, 0x29, 0x02, 0xb6, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0xff, 0xe3, 0x06, 0xcb, 0x05, 0xfb, 0x00, 0x6f, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x11, 0x21, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x11, 0x14, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x21, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x19, 0x01, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x03, 0x5f, 0x02, 0x61, 0x01, 0xc6, 0x24, 0x33, 0x3b, 0x44, 0x59, 0x6f, 0x37, 0x12, 0x22, 0x19, 0x21, 0x12, 0x14, 0x1a, 0x21, 0x2b, 0x2e, 0x1e, 0x24, 0x17, 0x14, 0x17, 0x24, 0x17, 0x1e, 0x27, 0x14, 0x32, 0x1a, 0x2e, 0x33, 0x1c, 0x21, 0x31, 0x1a, 0x57, 0x61, 0x40, 0x35, 0x32, 0x1a, 0x19, 0x0c, 0xfe, 0x44, 0x2d, 0x30, 0x53, 0x9c, 0xa6, 0x5e, 0x3c, 0x2e, 0x27, 0x23, 0x30, 0x0e, 0x10, 0x0a, 0x14, 0x08, 0x23, 0x3b, 0x52, 0x49, 0x3f, 0x20, 0x22, 0x7b, 0x53, 0x5a, 0x23, 0x40, 0x09, 0x01, 0x08, 0x09, 0x11, 0x21, 0x1e, 0x15, 0x1a, 0x12, 0x09, 0x07, 0x71, 0x43, 0x67, 0x71, 0x85, 0x27, 0x97, 0x05, 0xea, 0x1f, 0x31, 0xfd, 0xbc, 0xd1, 0x8c, 0x98, 0x49, 0x67, 0x14, 0x29, 0x1d, 0x2a, 0x1a, 0x21, 0x1c, 0x26, 0x21, 0x28, 0x44, 0x3b, 0x77, 0xd6, 0xfe, 0xbd, 0xa5, 0x82, 0x7d, 0x2c, 0x16, 0x37, 0x35, 0x3b, 0x21, 0x5f, 0x27, 0x5d, 0x37, 0x3a, 0x79, 0x7d, 0xa9, 0x5b, 0xb4, 0xcf, 0x9e, 0xa3, 0x5c, 0xae, 0x40, 0x34, 0x3e, 0x23, 0x2c, 0x0f, 0x12, 0x21, 0x2c, 0x0b, 0x27, 0x51, 0x46, 0xaa, 0xa7, 0x00, 0xff, 0x02, 0x6a, 0x16, 0x1a, 0x28, 0x4a, 0x47, 0x1f, 0x34, 0x10, 0x24, 0x24, 0x2c, 0x10, 0x2a, 0x1d, 0x12, 0x29, 0x2f, 0x39, 0x84, 0x79, 0x4b, 0x23, 0x25, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xfe, 0xf9, 0x04, 0xfe, 0x05, 0xd9, 0x00, 0x50, 0x00, 0x00, 0x05, 0x37, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x16, 0x17, 0x16, 0x07, 0x02, 0x07, 0x26, 0x27, 0x26, 0x22, 0x07, 0x27, 0x36, 0x33, 0x32, 0x17, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x16, 0x17, 0x16, 0x37, 0x36, 0x37, 0x15, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x36, 0x37, 0x32, 0x17, 0x16, 0x15, 0x10, 0x07, 0x02, 0x23, 0x22, 0x02, 0xd9, 0x5f, 0x24, 0x4f, 0x21, 0x1c, 0x1f, 0x19, 0x17, 0x10, 0x0c, 0x18, 0x19, 0x2d, 0x3f, 0x75, 0x4a, 0x9f, 0x3e, 0x2a, 0x0a, 0x0c, 0x16, 0xb6, 0x47, 0x2a, 0x2f, 0x30, 0x3f, 0x69, 0x14, 0xaa, 0x48, 0x4c, 0x52, 0x49, 0x3f, 0x52, 0x2b, 0x2b, 0x66, 0x62, 0xbe, 0x71, 0x8c, 0x18, 0x1f, 0x05, 0x82, 0x43, 0x42, 0x70, 0x1e, 0x35, 0x42, 0x3f, 0x67, 0x35, 0x1c, 0x1c, 0x63, 0x91, 0xd5, 0xda, 0x8d, 0x35, 0x55, 0xfc, 0x4b, 0x55, 0xcd, 0x8c, 0x51, 0x1f, 0x1f, 0x37, 0x39, 0x7d, 0x77, 0xb2, 0x96, 0x5e, 0x6c, 0x2e, 0x47, 0x89, 0x79, 0x72, 0x5c, 0x5b, 0x34, 0xfe, 0xfa, 0x4f, 0x39, 0x25, 0x23, 0x69, 0x23, 0xde, 0x5e, 0x4d, 0x58, 0x3b, 0x80, 0xa5, 0x79, 0x76, 0x40, 0x63, 0x8d, 0x84, 0x93, 0x7d, 0x07, 0x01, 0x1a, 0x02, 0x65, 0x2e, 0x49, 0x44, 0x5c, 0x1a, 0x16, 0x37, 0x49, 0x3b, 0x3e, 0x32, 0x56, 0xe7, 0xa7, 0x89, 0x75, 0xd3, 0xb0, 0xfe, 0xa2, 0xd3, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x6a, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x25, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x04, 0x59, 0xb6, 0xfc, 0x00, 0xb6, 0xfe, 0xf0, 0x01, 0x6a, 0x01, 0xe0, 0x01, 0x6a, 0xfe, 0x96, 0xfe, 0x20, 0xfe, 0x96, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0xfd, 0x88, 0x02, 0x78, 0xfa, 0x2b, 0x02, 0xdb, 0xfd, 0x25, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x04, 0x14, 0x06, 0x14, 0x00, 0x19, 0x00, 0x00, 0x01, 0x03, 0x23, 0x13, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x03, 0x23, 0x01, 0x33, 0x03, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x04, 0x03, 0x76, 0xa7, 0x76, 0x08, 0x0a, 0x60, 0x55, 0x86, 0xc3, 0x1d, 0x6d, 0xa5, 0x01, 0x11, 0xa5, 0x6b, 0x3f, 0xc4, 0x6c, 0x85, 0x93, 0x08, 0x02, 0xa4, 0xfd, 0x5c, 0x02, 0x9d, 0x2f, 0x48, 0x15, 0x54, 0x5e, 0xc8, 0xa6, 0xfd, 0x93, 0x06, 0x14, 0xfd, 0x9c, 0x5e, 0x6d, 0xa0, 0x91, 0x24, 0x52, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x04, 0x14, 0x06, 0x14, 0x00, 0x19, 0x00, 0x00, 0x01, 0x33, 0x07, 0x25, 0x17, 0x05, 0x03, 0x36, 0x33, 0x32, 0x16, 0x07, 0x03, 0x23, 0x13, 0x12, 0x23, 0x22, 0x06, 0x07, 0x03, 0x23, 0x13, 0x07, 0x27, 0x37, 0x01, 0x61, 0xa6, 0x28, 0x01, 0x65, 0x0d, 0xfe, 0x7b, 0x2f, 0x99, 0xd0, 0xae, 0x88, 0x29, 0x76, 0xa5, 0x75, 0x37, 0xdf, 0x86, 0xbc, 0x1d, 0x6e, 0xa7, 0xc9, 0xbc, 0x0d, 0xdd, 0x06, 0x14, 0xea, 0x7c, 0x61, 0x88, 0xfe, 0xf5, 0xc9, 0xef, 0xe8, 0xfd, 0x5c, 0x02, 0x9e, 0x01, 0x3d, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x7f, 0x42, 0x63, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x35, 0xff, 0xe1, 0x03, 0x1c, 0x05, 0xf0, 0x00, 0x39, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x11, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x11, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x14, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x03, 0x1c, 0x1b, 0x5e, 0xae, 0x75, 0x80, 0x63, 0x36, 0x32, 0x0f, 0x17, 0x1f, 0x19, 0x1c, 0x07, 0x0a, 0x0a, 0x18, 0x12, 0x35, 0x43, 0x49, 0x38, 0x1e, 0x1c, 0x70, 0x51, 0x57, 0x28, 0x2f, 0x06, 0x12, 0x1c, 0x14, 0x15, 0x18, 0x14, 0x24, 0x50, 0x45, 0x7d, 0x86, 0xa3, 0x1e, 0x70, 0x05, 0xe3, 0x2c, 0x16, 0xfc, 0xfe, 0xfe, 0x86, 0xc2, 0x82, 0x3c, 0x37, 0x44, 0x39, 0x0f, 0x1b, 0x23, 0x07, 0x37, 0x2e, 0x1b, 0x13, 0x4d, 0x3d, 0x86, 0x84, 0xbe, 0x03, 0x11, 0x1a, 0x1d, 0x2e, 0x31, 0x3f, 0x1b, 0x16, 0x04, 0x40, 0x09, 0x27, 0x1f, 0x12, 0x16, 0x28, 0x4d, 0x7f, 0x58, 0x49, 0x28, 0x27, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5f, 0xff, 0xe3, 0x04, 0xbf, 0x05, 0xf0, 0x00, 0x21, 0x00, 0x32, 0x00, 0x00, 0x3f, 0x01, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x06, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x13, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x07, 0x06, 0x23, 0x22, 0x26, 0x23, 0x22, 0x07, 0x5f, 0x7e, 0x64, 0x6a, 0x33, 0x77, 0x81, 0x1e, 0x6d, 0x5a, 0x40, 0x38, 0x48, 0x48, 0xc0, 0x48, 0x48, 0x2f, 0xb5, 0xa8, 0xda, 0x30, 0x74, 0x78, 0x32, 0x55, 0x63, 0x62, 0x7f, 0x6f, 0x72, 0x6e, 0x73, 0x70, 0x71, 0xb4, 0x7d, 0x64, 0x81, 0xc0, 0x81, 0x6e, 0x73, 0x5a, 0xa5, 0x27, 0x50, 0x56, 0x89, 0x61, 0x4b, 0x7e, 0x70, 0x92, 0x6d, 0x64, 0xa0, 0x8c, 0x8b, 0x79, 0x6b, 0x94, 0x62, 0xbc, 0x5e, 0xf2, 0xde, 0x4f, 0x50, 0x05, 0x36, 0x38, 0x31, 0x2f, 0x3a, 0xaa, 0x3a, 0x62, 0x3a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xe3, 0x04, 0xe3, 0x05, 0xf2, 0x00, 0x4a, 0x00, 0x00, 0x01, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x37, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x23, 0x35, 0x22, 0x07, 0x06, 0x07, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x13, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x17, 0x33, 0x32, 0x01, 0xac, 0xe8, 0x63, 0x51, 0x4a, 0x36, 0x5d, 0x4d, 0x3c, 0x08, 0x27, 0x16, 0x63, 0x6d, 0x6d, 0x2f, 0x5b, 0x50, 0x80, 0xeb, 0x4a, 0x3d, 0x32, 0x2f, 0x0c, 0x30, 0x42, 0x17, 0x2c, 0x22, 0x2b, 0x31, 0x0a, 0x05, 0x1f, 0x1e, 0x3a, 0x59, 0xbc, 0x66, 0x40, 0x3c, 0x0d, 0x25, 0x1c, 0x27, 0x1a, 0x0c, 0x0a, 0x06, 0x25, 0x2e, 0x33, 0x44, 0x29, 0x20, 0x20, 0x04, 0x03, 0x12, 0x14, 0x22, 0x32, 0x3b, 0x02, 0x0e, 0x38, 0x01, 0x5f, 0x6e, 0x30, 0x18, 0x19, 0x56, 0x42, 0x9a, 0x52, 0x1e, 0x0e, 0x84, 0x0e, 0xe4, 0x6e, 0x79, 0x23, 0x1f, 0x48, 0x89, 0x08, 0x42, 0x3f, 0x84, 0x18, 0xc1, 0x58, 0x21, 0x24, 0x18, 0x39, 0x42, 0x01, 0x7f, 0xa9, 0x84, 0x80, 0x4d, 0x77, 0x3e, 0x37, 0x6c, 0x1a, 0x10, 0x2e, 0x1b, 0x0b, 0x3b, 0x37, 0x25, 0x2c, 0x3b, 0x28, 0xd3, 0xa7, 0xbd, 0x75, 0x79, 0x2c, 0x44, 0x30, 0x03, 0x00, 0x02, 0xff, 0xe6, 0xff, 0xe3, 0x02, 0x8a, 0x05, 0xf0, 0x00, 0x1c, 0x00, 0x26, 0x00, 0x00, 0x01, 0x16, 0x33, 0x32, 0x37, 0x33, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x07, 0x23, 0x36, 0x37, 0x26, 0x35, 0x34, 0x37, 0x12, 0x37, 0x36, 0x33, 0x32, 0x15, 0x06, 0x07, 0x02, 0x01, 0x12, 0x13, 0x36, 0x35, 0x34, 0x23, 0x06, 0x03, 0x06, 0x01, 0x12, 0x24, 0x4f, 0x34, 0x43, 0x78, 0x36, 0x3f, 0x44, 0x3f, 0x8d, 0x38, 0x44, 0x8c, 0x61, 0x48, 0x09, 0x1c, 0x69, 0x5e, 0x41, 0x6e, 0x71, 0x01, 0x10, 0x41, 0xfe, 0xd9, 0xa8, 0x33, 0x1b, 0x16, 0x62, 0x58, 0x18, 0x01, 0x0c, 0xc8, 0x73, 0x66, 0x35, 0x39, 0x8b, 0x6e, 0x93, 0x89, 0x4e, 0x55, 0x98, 0x98, 0x02, 0x3b, 0x75, 0x51, 0xad, 0x4e, 0x5d, 0xfe, 0x83, 0xfe, 0xf7, 0x01, 0x5c, 0x01, 0x16, 0x93, 0x26, 0x45, 0x57, 0xfd, 0xfa, 0x91, 0x00, 0x02, 0x00, 0x1c, 0xff, 0xe3, 0x05, 0x7f, 0x06, 0x14, 0x00, 0x1f, 0x00, 0x27, 0x00, 0x00, 0x13, 0x33, 0x15, 0x33, 0x35, 0x33, 0x15, 0x21, 0x15, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x00, 0x10, 0x26, 0x20, 0x06, 0x10, 0x16, 0x20, 0xae, 0xa5, 0xa6, 0xa6, 0x02, 0x6d, 0xfd, 0x93, 0x35, 0x9f, 0x6f, 0xb7, 0xe6, 0xe6, 0xb7, 0x6f, 0x9f, 0x35, 0xa6, 0xa6, 0xa5, 0x91, 0x91, 0x04, 0x25, 0x97, 0xfe, 0xfa, 0x97, 0x97, 0x01, 0x06, 0x06, 0x14, 0x93, 0x93, 0x93, 0x7d, 0xfe, 0xb2, 0x64, 0x61, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x61, 0x64, 0xa8, 0x05, 0x04, 0xfa, 0xfc, 0x05, 0x04, 0x7d, 0xfb, 0xe3, 0x01, 0x96, 0xe7, 0xe7, 0xfe, 0x6a, 0xe7, 0x00, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x00, 0x05, 0x12, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x25, 0x01, 0x23, 0x09, 0x01, 0x21, 0x01, 0x11, 0x33, 0x11, 0x21, 0x01, 0x11, 0x23, 0x04, 0x9c, 0xfd, 0x62, 0xd6, 0x02, 0x9e, 0xfc, 0xed, 0x01, 0x7c, 0x02, 0x88, 0x5a, 0xfe, 0x84, 0xfd, 0x78, 0x5a, 0x64, 0x05, 0x0d, 0xfa, 0xf3, 0x05, 0x71, 0xfb, 0x1f, 0x04, 0xe1, 0xfa, 0x2b, 0x04, 0xe1, 0xfb, 0x1f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x06, 0xfb, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x00, 0x33, 0x35, 0x32, 0x35, 0x11, 0x33, 0x01, 0x11, 0x34, 0x36, 0x33, 0x15, 0x22, 0x15, 0x11, 0x23, 0x01, 0x11, 0x14, 0x06, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x37, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x03, 0x35, 0x21, 0x15, 0x31, 0x84, 0xf5, 0x02, 0x54, 0x8d, 0xa7, 0x84, 0xf5, 0xfd, 0xac, 0x8d, 0x04, 0x66, 0x82, 0x5c, 0x5d, 0x81, 0x81, 0x5d, 0x5c, 0x82, 0x7e, 0x33, 0x2d, 0x2d, 0x33, 0x33, 0x2d, 0x2d, 0x33, 0x7e, 0x01, 0xbc, 0xaa, 0x6b, 0x04, 0xc0, 0xfb, 0x1f, 0x03, 0xcc, 0x80, 0x95, 0xaa, 0x6b, 0xfb, 0x40, 0x04, 0xe1, 0xfc, 0x34, 0x80, 0x95, 0x02, 0x6e, 0x8a, 0xbf, 0xbf, 0x8a, 0x8a, 0xbf, 0xbf, 0x8a, 0x4e, 0x67, 0x67, 0x4e, 0x4e, 0x67, 0x67, 0xfd, 0x44, 0x7b, 0x7b, 0x00, 0x00, 0x04, 0x00, 0xfe, 0x00, 0x00, 0x06, 0x35, 0x05, 0xca, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x16, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x06, 0x23, 0x22, 0x00, 0x11, 0x12, 0x00, 0x33, 0x32, 0x00, 0x11, 0x10, 0x27, 0x05, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x05, 0x70, 0xc4, 0xfe, 0x76, 0xfe, 0xf0, 0xfe, 0xed, 0xfe, 0x7d, 0x05, 0x01, 0x88, 0x01, 0x13, 0x01, 0x13, 0x25, 0xee, 0xec, 0xfe, 0xac, 0x04, 0x01, 0x50, 0xec, 0xec, 0x01, 0x54, 0xa9, 0xfe, 0x0b, 0xa0, 0x59, 0x61, 0x61, 0x59, 0xfe, 0xe1, 0x01, 0x1f, 0x9f, 0xa2, 0xa2, 0x9f, 0xa0, 0x7f, 0x04, 0xf1, 0xdb, 0xfe, 0xce, 0xfe, 0xd0, 0xfe, 0x4c, 0x01, 0xb4, 0x01, 0x30, 0x01, 0x30, 0x01, 0xb6, 0x65, 0xfe, 0x85, 0xfe, 0xf9, 0xfe, 0xfb, 0xfe, 0x87, 0x01, 0x79, 0x01, 0x05, 0x01, 0x09, 0xbb, 0x77, 0xfe, 0xaf, 0x58, 0x51, 0x50, 0x58, 0x64, 0x89, 0x83, 0x85, 0x87, 0xfe, 0x98, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x63, 0xfe, 0x3b, 0x04, 0xbd, 0x03, 0xf6, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x06, 0x15, 0x14, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x36, 0x37, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x01, 0x12, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x10, 0x37, 0x26, 0x35, 0x34, 0x37, 0x03, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x32, 0x37, 0x36, 0x35, 0x34, 0x01, 0xfc, 0x7a, 0x1c, 0x52, 0x9a, 0xc5, 0x77, 0x76, 0x3f, 0x41, 0x8c, 0x6d, 0x9d, 0x5a, 0x45, 0x10, 0x08, 0x25, 0x66, 0x6e, 0x54, 0x3e, 0x23, 0x1c, 0x43, 0xaa, 0xfe, 0xc2, 0x7a, 0x3e, 0x50, 0x76, 0x66, 0x34, 0x39, 0xc9, 0x2a, 0xd1, 0x85, 0x74, 0x1c, 0x2b, 0x29, 0x3b, 0x19, 0x1d, 0x03, 0xc6, 0x82, 0xbe, 0x4d, 0x6b, 0x65, 0x94, 0xbd, 0x4c, 0x50, 0xab, 0xda, 0xd7, 0xa7, 0x3c, 0x2b, 0x1d, 0x28, 0x8c, 0x68, 0xc3, 0x7c, 0x48, 0x3d, 0xfe, 0x79, 0xfe, 0xde, 0x7c, 0x9d, 0x6e, 0x8e, 0x3d, 0x42, 0x86, 0x01, 0x0b, 0xfc, 0x9e, 0x7f, 0xee, 0xa4, 0xfc, 0xef, 0xc6, 0x7b, 0x75, 0x2e, 0x46, 0x01, 0x2f, 0x34, 0x5f, 0x4e, 0x00, 0x00, 0x04, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xcc, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x32, 0x37, 0x11, 0x26, 0x23, 0x25, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x11, 0x21, 0x01, 0x11, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x01, 0x0e, 0xb6, 0x5a, 0x01, 0x10, 0x15, 0x15, 0x15, 0x15, 0xfd, 0x86, 0x02, 0x4f, 0xe1, 0xe8, 0xe8, 0xe2, 0xe4, 0xfe, 0x96, 0x03, 0x02, 0x36, 0x29, 0x54, 0x53, 0x28, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0xfd, 0x6a, 0x02, 0x02, 0x92, 0x02, 0x64, 0xdb, 0xd3, 0xd5, 0xda, 0xfd, 0x88, 0x05, 0x5a, 0xfd, 0x99, 0x16, 0x29, 0x56, 0x9f, 0x9e, 0x56, 0x29, 0x00, 0x00, 0x00, 0x04, 0x00, 0x67, 0xfe, 0xf8, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x11, 0x00, 0x19, 0x00, 0x21, 0x00, 0x29, 0x00, 0x00, 0x25, 0x13, 0x23, 0x27, 0x07, 0x06, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x02, 0x25, 0x16, 0x32, 0x37, 0x11, 0x26, 0x22, 0x07, 0x03, 0x11, 0x06, 0x07, 0x06, 0x10, 0x17, 0x16, 0x01, 0x11, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x03, 0xd5, 0xef, 0xdb, 0xc7, 0x2e, 0x0f, 0x0f, 0xfe, 0xe5, 0xfe, 0xad, 0x01, 0x53, 0x01, 0x1b, 0x01, 0x1b, 0x01, 0x52, 0xbc, 0xfd, 0x74, 0x61, 0xf5, 0x61, 0x61, 0xf5, 0x61, 0x5f, 0x20, 0x1d, 0x8b, 0x8b, 0x1d, 0x02, 0x94, 0x20, 0x1c, 0x8b, 0x8b, 0x1c, 0x1b, 0xfe, 0xdd, 0xef, 0x03, 0x01, 0x01, 0xa5, 0x01, 0x61, 0x01, 0x62, 0x01, 0xa5, 0xfe, 0x5b, 0xfe, 0x9e, 0xfe, 0xfc, 0xfe, 0x8e, 0x0b, 0x32, 0x32, 0x04, 0xd7, 0x32, 0x32, 0xfb, 0x6a, 0x04, 0x54, 0x1d, 0x25, 0xb6, 0xfd, 0x9c, 0xb5, 0x25, 0x04, 0x35, 0xfb, 0xaf, 0x1d, 0x24, 0xb6, 0x02, 0x63, 0xb6, 0x24, 0x00, 0x00, 0x02, 0x00, 0x3b, 0xff, 0xee, 0x05, 0x80, 0x06, 0x32, 0x00, 0x0c, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x11, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x13, 0x03, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x11, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x21, 0x36, 0x3f, 0x01, 0x15, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x02, 0xef, 0x1b, 0x37, 0x81, 0x54, 0x5e, 0x4a, 0x19, 0x53, 0x50, 0x87, 0xb9, 0x4d, 0x1c, 0x2e, 0x2b, 0x3f, 0x8f, 0xa7, 0x63, 0x32, 0x35, 0x18, 0x16, 0x20, 0x17, 0x14, 0x18, 0x10, 0x13, 0x0f, 0x17, 0x3f, 0x5c, 0x4b, 0x33, 0x1e, 0x1d, 0xcf, 0x75, 0x36, 0x09, 0x01, 0x0f, 0x1a, 0x20, 0x30, 0x1a, 0x27, 0x5d, 0xaa, 0x01, 0x05, 0x1b, 0x35, 0x36, 0xa3, 0x7c, 0x76, 0x2e, 0x4f, 0x63, 0x5d, 0x8b, 0x51, 0x4a, 0x6f, 0x17, 0x28, 0x1a, 0x1c, 0x1f, 0x10, 0x1c, 0x20, 0x33, 0x38, 0x35, 0x44, 0x1d, 0x49, 0x05, 0xa1, 0xfd, 0x49, 0x07, 0x61, 0x67, 0xc2, 0xa3, 0x53, 0x1b, 0x14, 0x0f, 0xfb, 0x16, 0x01, 0xe6, 0x09, 0xc0, 0x88, 0x89, 0x44, 0xa3, 0x35, 0x40, 0x37, 0x2a, 0x1a, 0x18, 0x16, 0x1a, 0x1f, 0x27, 0x10, 0x1a, 0x53, 0x3a, 0x79, 0x7d, 0x9e, 0x03, 0x2a, 0x82, 0x37, 0x48, 0x19, 0x30, 0x09, 0x35, 0x0f, 0x23, 0x21, 0x1f, 0x18, 0x2c, 0x49, 0x91, 0x6c, 0xbb, 0x0d, 0x1d, 0x1c, 0x40, 0x1c, 0x1f, 0x33, 0x58, 0xa7, 0xbf, 0x6e, 0x68, 0x30, 0xde, 0xcd, 0x7b, 0x1f, 0x1f, 0x28, 0x32, 0x18, 0x72, 0x3a, 0x3d, 0x1f, 0x4f, 0x00, 0x00, 0x02, 0x00, 0x4a, 0xff, 0xe3, 0x05, 0xc8, 0x05, 0xf1, 0x00, 0x49, 0x00, 0x58, 0x00, 0x00, 0x05, 0x26, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x16, 0x17, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x35, 0x11, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x14, 0x17, 0x16, 0x33, 0x17, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x17, 0x37, 0x17, 0x01, 0x16, 0x15, 0x11, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x04, 0x82, 0x4a, 0x14, 0x24, 0x47, 0x26, 0x53, 0x6c, 0x5c, 0x5d, 0x7e, 0x7f, 0x5c, 0x5c, 0x28, 0x2a, 0x39, 0x3a, 0x81, 0x39, 0x3a, 0x3a, 0x39, 0x52, 0x49, 0x3b, 0x39, 0x39, 0x3a, 0x4a, 0x31, 0x88, 0x5c, 0x5c, 0x5c, 0x5c, 0x88, 0x92, 0x5b, 0x1b, 0x0e, 0xbe, 0xa8, 0x65, 0x2a, 0x21, 0x71, 0x3a, 0x3c, 0x70, 0x34, 0x2c, 0x21, 0x18, 0x1d, 0x28, 0x82, 0x26, 0xfc, 0xfa, 0x12, 0x8b, 0x82, 0x45, 0x43, 0x43, 0x16, 0x1c, 0x39, 0x5c, 0x1d, 0xb7, 0x9f, 0x8c, 0x5b, 0xa6, 0x2b, 0x38, 0xc7, 0xce, 0x76, 0x75, 0x75, 0x76, 0xb0, 0x0c, 0x0c, 0x7a, 0x56, 0x57, 0x57, 0x57, 0x96, 0x02, 0x9b, 0x95, 0x58, 0x57, 0x57, 0x56, 0xca, 0x56, 0x57, 0x5c, 0x75, 0x76, 0x9c, 0x9d, 0x75, 0x75, 0x75, 0x23, 0x20, 0x62, 0x57, 0x0e, 0x31, 0xb1, 0x57, 0x7b, 0x7c, 0x5e, 0x31, 0x24, 0x68, 0x7b, 0x83, 0x80, 0x76, 0x43, 0x5b, 0x04, 0x53, 0x4b, 0x5c, 0xfe, 0x95, 0x47, 0x43, 0x68, 0x66, 0x79, 0x97, 0x20, 0x0a, 0x2f, 0x00, 0x05, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x94, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x1e, 0x00, 0x26, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x16, 0x17, 0x13, 0x33, 0x03, 0x1e, 0x01, 0x17, 0x13, 0x21, 0x03, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x21, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x07, 0x06, 0x01, 0x11, 0x21, 0x32, 0x37, 0x11, 0x26, 0x23, 0x17, 0x11, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x25, 0x11, 0x33, 0x11, 0x04, 0x7c, 0x45, 0x3d, 0x3e, 0x6c, 0x29, 0x46, 0x5b, 0x80, 0xb3, 0xed, 0x2f, 0x66, 0x38, 0xb8, 0xfe, 0x74, 0xab, 0x43, 0x7d, 0x6c, 0x12, 0xfe, 0x96, 0x02, 0x63, 0xe7, 0xe2, 0x69, 0x2c, 0xfd, 0xd3, 0x01, 0x24, 0x16, 0x15, 0x15, 0x16, 0x89, 0x3b, 0x26, 0x51, 0x50, 0x26, 0xfd, 0x07, 0xb6, 0x01, 0x7f, 0x97, 0x30, 0x31, 0x2f, 0xc9, 0xfe, 0xe5, 0x02, 0x4f, 0x19, 0x84, 0x7e, 0xfe, 0x68, 0x01, 0x7f, 0x96, 0x62, 0xfd, 0x89, 0x05, 0xd5, 0xd6, 0xd8, 0xd0, 0x62, 0x29, 0x02, 0xa5, 0xfd, 0x6a, 0x02, 0x02, 0x92, 0x02, 0x17, 0xfd, 0x99, 0x16, 0x29, 0x56, 0x01, 0x3e, 0x55, 0x29, 0x2d, 0xfa, 0xf3, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x98, 0x00, 0x00, 0x05, 0xdd, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x07, 0x17, 0x37, 0x33, 0x09, 0x01, 0x23, 0x0b, 0x01, 0x23, 0x01, 0x01, 0x4e, 0xe4, 0x7f, 0x8b, 0x8b, 0x7f, 0x01, 0x04, 0x68, 0x9c, 0xe4, 0xb6, 0x01, 0x9a, 0xe2, 0xe8, 0x46, 0x9c, 0xab, 0xd1, 0xfe, 0xec, 0x01, 0x22, 0xd1, 0xbb, 0xbe, 0xd1, 0x01, 0x28, 0x05, 0x2f, 0xfd, 0xcf, 0x92, 0x87, 0x86, 0x92, 0xfd, 0x5f, 0x36, 0xfd, 0xa8, 0x05, 0xd5, 0xe3, 0xdb, 0xac, 0x6b, 0xdb, 0xea, 0xfe, 0x86, 0xfe, 0x6b, 0x01, 0x04, 0xfe, 0xfc, 0x01, 0x95, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xff, 0x25, 0x04, 0xcc, 0x06, 0xc7, 0x00, 0x05, 0x00, 0x24, 0x00, 0x2b, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x11, 0x33, 0x13, 0x26, 0x23, 0x13, 0x16, 0x17, 0x16, 0x17, 0x13, 0x23, 0x03, 0x26, 0x27, 0x26, 0x27, 0x01, 0x27, 0x37, 0x23, 0x11, 0x21, 0x32, 0x17, 0x37, 0x25, 0x37, 0x05, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x0b, 0x01, 0x36, 0x37, 0x36, 0x35, 0x34, 0x01, 0x13, 0x23, 0x01, 0x6b, 0xbc, 0xb4, 0x39, 0x53, 0xe3, 0x3b, 0x37, 0x34, 0x3b, 0xb9, 0xc4, 0xac, 0x43, 0x3e, 0x30, 0x4d, 0xfe, 0xd0, 0x64, 0x3f, 0x54, 0x01, 0x9a, 0x72, 0x55, 0x0a, 0xfe, 0xdb, 0x27, 0x01, 0x8a, 0x32, 0x19, 0x14, 0x71, 0x75, 0x70, 0x96, 0x4b, 0x2e, 0x43, 0xfe, 0x12, 0x80, 0x80, 0x05, 0x2f, 0xfd, 0xee, 0x01, 0xf8, 0x1a, 0xfd, 0x8d, 0x16, 0x48, 0x44, 0x82, 0xfe, 0x68, 0x01, 0x7f, 0x97, 0x30, 0x26, 0x09, 0xfc, 0xb0, 0x2c, 0xaf, 0x05, 0xd5, 0x1a, 0x1b, 0x82, 0x6f, 0xae, 0x8c, 0x10, 0x13, 0x6b, 0xd8, 0x8d, 0xba, 0x01, 0xe7, 0xfe, 0x5d, 0x0f, 0x2d, 0x44, 0x83, 0x62, 0xfc, 0x87, 0x01, 0x67, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe9, 0x03, 0x8b, 0x05, 0x8b, 0x05, 0xd8, 0x00, 0x27, 0x00, 0x34, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x37, 0x33, 0x1b, 0x01, 0x33, 0x11, 0x23, 0x11, 0x03, 0x23, 0x03, 0x11, 0x23, 0x02, 0x9c, 0x4d, 0x4e, 0x23, 0x3b, 0x3f, 0x2a, 0x3e, 0x32, 0x65, 0x5f, 0x82, 0x7e, 0x2f, 0x67, 0x40, 0x52, 0x5a, 0x2a, 0x3e, 0x44, 0x32, 0x39, 0x32, 0x65, 0x59, 0x7c, 0x70, 0x2e, 0x5e, 0xbb, 0xa6, 0x91, 0x92, 0xa5, 0x7c, 0x7e, 0x79, 0x7f, 0x7c, 0x05, 0xb7, 0x59, 0x22, 0x13, 0x2a, 0x2f, 0x28, 0x20, 0x0b, 0x09, 0x12, 0x56, 0x41, 0x4f, 0x5b, 0x13, 0x15, 0x60, 0x2a, 0x18, 0x2c, 0x32, 0x2c, 0x2a, 0x0a, 0x09, 0x12, 0x4d, 0x3d, 0x48, 0x5c, 0x0f, 0x05, 0xfe, 0xac, 0x01, 0x54, 0xfd, 0xc8, 0x01, 0x94, 0xfe, 0xd8, 0x01, 0x28, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x07, 0x5f, 0x04, 0x60, 0x00, 0x07, 0x00, 0x13, 0x00, 0x19, 0x00, 0x00, 0x03, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x05, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x01, 0x33, 0x11, 0x21, 0x15, 0x21, 0x04, 0x03, 0x55, 0xfe, 0x99, 0x88, 0xfe, 0x9a, 0x02, 0x97, 0x02, 0x31, 0xfe, 0x46, 0x01, 0xa7, 0xfe, 0x59, 0x01, 0xc4, 0xfd, 0xc5, 0x02, 0xa4, 0x77, 0x01, 0xb0, 0xfd, 0xd9, 0x04, 0x60, 0x80, 0xfc, 0x20, 0x03, 0xe0, 0x60, 0x66, 0xfe, 0xf7, 0x66, 0xfe, 0xbb, 0x66, 0x03, 0x80, 0xfc, 0xe6, 0x66, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x09, 0x03, 0x93, 0x05, 0xa6, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x00, 0x01, 0x1b, 0x01, 0x33, 0x11, 0x23, 0x11, 0x03, 0x23, 0x03, 0x11, 0x23, 0x11, 0x23, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x03, 0xdc, 0x9d, 0x93, 0x99, 0x65, 0xb0, 0x31, 0xb7, 0x67, 0x65, 0xb7, 0x67, 0xb4, 0x05, 0xd5, 0xff, 0x00, 0x01, 0x00, 0xfd, 0xbe, 0x01, 0xe4, 0xfe, 0xd1, 0x01, 0x2f, 0xfe, 0x1c, 0x02, 0x42, 0x5e, 0xfe, 0x1c, 0x01, 0xe4, 0x5e, 0x00, 0x00, 0x01, 0x00, 0x0e, 0xff, 0x22, 0x04, 0xde, 0x06, 0xc4, 0x00, 0x10, 0x00, 0x00, 0x01, 0x13, 0x25, 0x37, 0x05, 0x01, 0x13, 0x01, 0x33, 0x01, 0x23, 0x0b, 0x01, 0x27, 0x09, 0x01, 0x33, 0x01, 0xa8, 0xe7, 0xfe, 0xdb, 0x27, 0x01, 0x8b, 0xfe, 0xc4, 0x96, 0x01, 0xab, 0xbd, 0xfe, 0x00, 0xcf, 0x8e, 0xe3, 0x64, 0x01, 0x0f, 0xfe, 0xc5, 0xbe, 0x03, 0x4d, 0x02, 0x86, 0x82, 0x6f, 0xae, 0xfc, 0x90, 0xfe, 0x46, 0x04, 0xe9, 0xfa, 0x2b, 0x01, 0x9e, 0xfd, 0x84, 0x2c, 0x02, 0xf5, 0x03, 0x92, 0x00, 0x02, 0x00, 0x52, 0x00, 0x00, 0x05, 0x0a, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x25, 0x01, 0x23, 0x01, 0x03, 0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x21, 0x01, 0x9a, 0x02, 0xe6, 0xd3, 0xfd, 0x1b, 0x60, 0x04, 0x8d, 0xfd, 0x1a, 0x02, 0xfb, 0xfb, 0x49, 0x02, 0xe5, 0xfd, 0x30, 0x64, 0x05, 0x0d, 0xfa, 0xf3, 0x05, 0x71, 0x64, 0xfa, 0xf3, 0x64, 0x64, 0x05, 0x0d, 0x00, 0x01, 0x00, 0x4f, 0xfe, 0x4c, 0x03, 0xc4, 0x06, 0x14, 0x00, 0x1f, 0x00, 0x00, 0x17, 0x16, 0x20, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x15, 0x01, 0x32, 0x1e, 0x01, 0x15, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x4f, 0x99, 0x01, 0x79, 0xae, 0xa7, 0x94, 0xf5, 0x01, 0xc5, 0xfe, 0x3b, 0x01, 0xc5, 0xfd, 0xfd, 0x02, 0xd4, 0xfe, 0x56, 0x01, 0xaa, 0xfe, 0x56, 0x9a, 0xc9, 0x96, 0x7f, 0xa7, 0xe8, 0xa8, 0xbf, 0xa7, 0x63, 0xa3, 0xcc, 0x86, 0x93, 0xa6, 0x01, 0x65, 0x93, 0x01, 0x65, 0x93, 0xa8, 0xfe, 0xb0, 0xa8, 0xfe, 0xb0, 0x61, 0xd4, 0x8a, 0xfe, 0xd3, 0x66, 0x86, 0x4a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x46, 0x00, 0x00, 0x05, 0x3b, 0x05, 0xe7, 0x10, 0x06, 0x03, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x46, 0xff, 0xe3, 0x05, 0x3b, 0x05, 0xca, 0x10, 0x06, 0x01, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0xfe, 0xce, 0x04, 0x20, 0x06, 0x44, 0x00, 0x55, 0x00, 0x00, 0x01, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x37, 0x33, 0x06, 0x17, 0x16, 0x33, 0x32, 0x37, 0x32, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x17, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x10, 0x03, 0x06, 0x21, 0x22, 0x27, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x01, 0x66, 0x56, 0x70, 0x6d, 0x5f, 0x1f, 0x2c, 0x49, 0x16, 0x73, 0x87, 0x17, 0x53, 0x20, 0x16, 0x89, 0x1f, 0x1f, 0x1f, 0x20, 0x75, 0x27, 0x4c, 0x0f, 0x40, 0x0f, 0x40, 0x53, 0x16, 0x36, 0x75, 0x77, 0x61, 0x02, 0x40, 0x2c, 0xe2, 0x5b, 0x21, 0x9f, 0xd9, 0xfe, 0xf4, 0x67, 0x58, 0x01, 0x04, 0x0e, 0x16, 0x20, 0x2b, 0x3e, 0x15, 0x43, 0x4f, 0x49, 0x36, 0x45, 0x10, 0x0a, 0x16, 0x1b, 0x3a, 0x89, 0x69, 0x43, 0x22, 0x23, 0x0f, 0x12, 0x1e, 0x5d, 0x9e, 0x61, 0x54, 0x02, 0xa8, 0x8a, 0x09, 0x79, 0x6a, 0x8d, 0x2e, 0x23, 0x2e, 0x0b, 0x0b, 0x23, 0x19, 0x21, 0xd3, 0x3c, 0x23, 0x21, 0x05, 0x06, 0x16, 0x18, 0x3b, 0x47, 0xa3, 0x81, 0x84, 0x42, 0x03, 0x0e, 0x98, 0x77, 0x80, 0xfe, 0xeb, 0xfe, 0xfa, 0xc8, 0x18, 0x87, 0x1c, 0x2c, 0x10, 0x18, 0x3c, 0x24, 0x3d, 0x2c, 0x23, 0x23, 0x16, 0x77, 0x55, 0x19, 0x1e, 0x74, 0x4b, 0x79, 0x79, 0x98, 0x56, 0x3f, 0x40, 0x21, 0x6a, 0x2e, 0x00, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x01, 0xd6, 0x04, 0x60, 0x00, 0x0d, 0x00, 0x00, 0x21, 0x11, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x01, 0x2d, 0x1f, 0x20, 0x62, 0x4f, 0x63, 0xa4, 0x48, 0x4a, 0x02, 0xd5, 0x91, 0x2e, 0x30, 0x9c, 0x60, 0x62, 0xd4, 0xfd, 0x36, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xe0, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x2e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x07, 0x6d, 0x10, 0x06, 0x00, 0x87, 0x00, 0x00, 0x00, 0x03, 0x00, 0x52, 0x00, 0x00, 0x05, 0x49, 0x06, 0x2e, 0x00, 0x32, 0x00, 0x3f, 0x00, 0x52, 0x00, 0x00, 0x01, 0x17, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x29, 0x01, 0x37, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x11, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x14, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x05, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x11, 0x14, 0x03, 0x05, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x03, 0xff, 0x07, 0x98, 0x55, 0x56, 0x6d, 0xc6, 0xfe, 0xd4, 0xfd, 0xb4, 0x36, 0x86, 0x79, 0x33, 0x1a, 0x1c, 0xa6, 0x75, 0x45, 0x0a, 0x0b, 0x11, 0x1e, 0x27, 0x17, 0x0f, 0x22, 0x65, 0x90, 0xee, 0x89, 0x08, 0xb2, 0x83, 0x80, 0x2c, 0x41, 0x5c, 0x44, 0xfe, 0xaf, 0xb8, 0x66, 0x4a, 0x3e, 0x26, 0x5b, 0x61, 0x79, 0xfc, 0x01, 0x39, 0x7b, 0x61, 0x5d, 0x2c, 0x4f, 0x4e, 0x29, 0x4c, 0x45, 0x6a, 0x44, 0x41, 0x1c, 0x2a, 0x4f, 0x03, 0x54, 0x10, 0x61, 0x5e, 0x80, 0xae, 0x7d, 0xda, 0x75, 0x86, 0x3b, 0x8b, 0x84, 0xd3, 0x02, 0x83, 0x82, 0x49, 0x4d, 0x0b, 0x3d, 0x05, 0x2c, 0x0d, 0x33, 0x13, 0x21, 0x16, 0x23, 0x56, 0x86, 0x74, 0x9f, 0x27, 0x49, 0x40, 0x1c, 0x1f, 0x33, 0x48, 0x6c, 0x9a, 0x68, 0x4a, 0x33, 0x70, 0x52, 0x81, 0x75, 0x46, 0x2a, 0x1b, 0x18, 0xfd, 0xc2, 0x1d, 0xfd, 0x28, 0x02, 0x1a, 0x1d, 0x30, 0x58, 0xb9, 0x72, 0x56, 0x2c, 0x18, 0x18, 0x06, 0xec, 0x6e, 0xce, 0x00, 0x01, 0x00, 0x75, 0xff, 0xe8, 0x04, 0xb2, 0x05, 0xf0, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x17, 0x36, 0x25, 0x1e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x37, 0x15, 0x06, 0x07, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x27, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x37, 0x22, 0x07, 0x06, 0x15, 0x10, 0x17, 0x16, 0x25, 0x37, 0x15, 0x06, 0x07, 0x06, 0x24, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x02, 0x10, 0x40, 0x89, 0x01, 0x11, 0x0a, 0x24, 0x0a, 0x0f, 0x0e, 0x14, 0x5f, 0x7e, 0x5e, 0x35, 0x69, 0x25, 0x1b, 0x15, 0x0a, 0x03, 0x0d, 0x0d, 0x0e, 0x3f, 0x67, 0xb3, 0x17, 0x51, 0x42, 0x1f, 0x29, 0x1e, 0x11, 0x70, 0x42, 0x5f, 0x9f, 0xc8, 0x01, 0x46, 0xe8, 0xc2, 0x5b, 0xad, 0xfe, 0xb4, 0x75, 0x53, 0x2a, 0x2b, 0x55, 0xac, 0x05, 0x35, 0x23, 0x6c, 0x72, 0x1c, 0x77, 0x1f, 0x28, 0x0f, 0x16, 0x21, 0x2e, 0x44, 0x0e, 0x24, 0xbb, 0x0d, 0x22, 0x1c, 0x39, 0x42, 0x47, 0x16, 0x33, 0x32, 0x4b, 0x25, 0x8d, 0x46, 0x6e, 0x1f, 0x23, 0x16, 0x49, 0x23, 0x74, 0x33, 0xb9, 0x74, 0x52, 0x5d, 0x86, 0xda, 0xfe, 0xb9, 0xb0, 0xe1, 0x26, 0x7f, 0x39, 0x88, 0x4b, 0x28, 0x56, 0x82, 0x5c, 0x8f, 0x91, 0xb5, 0xd1, 0xbd, 0x93, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0xff, 0xe7, 0x05, 0xb7, 0x05, 0x2d, 0x00, 0x1a, 0x00, 0x29, 0x00, 0x00, 0x25, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x20, 0x24, 0x02, 0x35, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x15, 0x21, 0x22, 0x15, 0x35, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x01, 0x68, 0x3c, 0x54, 0x87, 0x01, 0x29, 0x89, 0x5f, 0x46, 0x63, 0x55, 0x80, 0xa1, 0xfe, 0xa1, 0xfe, 0xbf, 0xb3, 0xb5, 0x01, 0x43, 0xac, 0xaa, 0x01, 0x43, 0xb5, 0xfb, 0xc3, 0x11, 0x11, 0x03, 0x35, 0x12, 0x3f, 0x56, 0x88, 0x8f, 0x90, 0x89, 0x56, 0x3d, 0xe4, 0x4d, 0x33, 0x54, 0x54, 0x3c, 0x60, 0x78, 0x47, 0x5a, 0xb3, 0x01, 0x41, 0xaf, 0xb0, 0x01, 0x45, 0xae, 0xae, 0xfe, 0xbb, 0xb0, 0x13, 0x49, 0x13, 0x13, 0x01, 0x70, 0x50, 0x33, 0x52, 0x51, 0x34, 0x4f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4e, 0xff, 0xe3, 0x03, 0xf0, 0x04, 0x44, 0x00, 0x1c, 0x00, 0x25, 0x00, 0x00, 0x01, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x00, 0x33, 0x20, 0x11, 0x14, 0x07, 0x06, 0x37, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x03, 0x20, 0x01, 0x0e, 0x04, 0x1f, 0x35, 0x8e, 0x69, 0x33, 0x5c, 0x15, 0x7a, 0x24, 0x86, 0x5e, 0xfe, 0x8d, 0x64, 0x46, 0x0e, 0x2c, 0x01, 0x30, 0xd8, 0x01, 0x60, 0xb8, 0xbd, 0x61, 0x64, 0xcc, 0x78, 0xa8, 0x33, 0x01, 0x21, 0x01, 0x98, 0x26, 0x22, 0x5e, 0x3e, 0x6e, 0x23, 0x3f, 0x51, 0x7f, 0x59, 0x3e, 0x99, 0x6b, 0x9b, 0x44, 0x4d, 0xfd, 0x01, 0x34, 0xfe, 0xeb, 0xc7, 0x67, 0x69, 0xe0, 0x4d, 0x71, 0xab, 0xcc, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x01, 0x00, 0x91, 0xff, 0xe3, 0x04, 0x13, 0x05, 0xf0, 0x00, 0x45, 0x00, 0x00, 0x01, 0x17, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x33, 0x15, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x03, 0xbd, 0x55, 0x1c, 0x0e, 0xa0, 0xe2, 0x81, 0x5e, 0x62, 0x3e, 0x55, 0x78, 0x62, 0xa1, 0x01, 0x61, 0x37, 0x47, 0x59, 0x6f, 0xd9, 0x7a, 0x4c, 0x2e, 0x29, 0x2d, 0x1e, 0x25, 0x15, 0x0c, 0x1a, 0x17, 0x21, 0x27, 0x5c, 0x57, 0x3a, 0x57, 0x48, 0x2a, 0x51, 0x56, 0x70, 0x9a, 0x6f, 0x6b, 0x34, 0x62, 0x57, 0x51, 0xae, 0x74, 0x6a, 0x38, 0x0b, 0x01, 0x49, 0x68, 0x41, 0x11, 0xac, 0x22, 0x25, 0x40, 0x5f, 0xa9, 0xae, 0x8a, 0x6c, 0x18, 0x15, 0x24, 0x3d, 0x50, 0x94, 0x8b, 0x63, 0x7a, 0x53, 0x32, 0x56, 0x4e, 0x2d, 0x32, 0x16, 0x0e, 0x21, 0x1c, 0x24, 0x2b, 0x1f, 0x25, 0x24, 0x2b, 0x40, 0x65, 0x97, 0x7d, 0x4e, 0x30, 0x17, 0x1a, 0x36, 0x1e, 0x1d, 0x39, 0x6e, 0x99, 0xa6, 0x61, 0x5b, 0x75, 0x3e, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4b, 0xff, 0xdf, 0x05, 0x76, 0x06, 0x0b, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x17, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x11, 0x21, 0x07, 0x23, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x3d, 0x01, 0x21, 0x37, 0x21, 0x11, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x1f, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x21, 0x32, 0x17, 0x37, 0x15, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x05, 0x56, 0x20, 0x50, 0x23, 0x34, 0x23, 0x31, 0xcb, 0x39, 0x01, 0x1d, 0x37, 0xe6, 0x25, 0x26, 0x46, 0xb2, 0xf1, 0x73, 0x56, 0x2e, 0x1b, 0x18, 0x29, 0x1c, 0x0c, 0x10, 0x14, 0x11, 0x18, 0x3c, 0x54, 0x61, 0x6f, 0x38, 0x1a, 0x1e, 0xfe, 0xbb, 0x23, 0x01, 0x22, 0x57, 0x38, 0xae, 0x63, 0x40, 0x06, 0x12, 0x16, 0x20, 0x17, 0x22, 0x20, 0x1c, 0x6c, 0x96, 0x01, 0x15, 0x20, 0x3c, 0x8a, 0xa9, 0x80, 0x2c, 0x13, 0x2c, 0x1d, 0x05, 0xf2, 0x13, 0xa3, 0x4b, 0x14, 0x3d, 0x19, 0xfd, 0xdc, 0x44, 0x63, 0x98, 0x84, 0x80, 0x4b, 0xca, 0x5f, 0x34, 0x42, 0x28, 0x1f, 0x1a, 0x0b, 0x14, 0x30, 0x33, 0x1a, 0x42, 0x7b, 0x3e, 0x63, 0x65, 0x82, 0xb9, 0x44, 0x02, 0x49, 0x18, 0x6e, 0x46, 0x54, 0x3d, 0x1f, 0x49, 0x2c, 0x1a, 0x1f, 0x1f, 0x1f, 0x46, 0xb4, 0x77, 0xa7, 0x08, 0x37, 0x4b, 0x2e, 0x16, 0x09, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xba, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x03, 0xb9, 0xfc, 0xfc, 0x02, 0x4e, 0xfd, 0xeb, 0x02, 0x15, 0xb6, 0xaa, 0x01, 0xb8, 0xaa, 0x02, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x33, 0xff, 0xc7, 0x07, 0x6f, 0x06, 0x02, 0x00, 0x6b, 0x00, 0x00, 0x01, 0x11, 0x14, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x11, 0x34, 0x02, 0x37, 0x06, 0x03, 0x02, 0x03, 0x07, 0x27, 0x02, 0x03, 0x26, 0x27, 0x26, 0x27, 0x11, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x36, 0x35, 0x11, 0x26, 0x23, 0x22, 0x07, 0x06, 0x0f, 0x01, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x33, 0x16, 0x13, 0x12, 0x13, 0x17, 0x12, 0x37, 0x12, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x06, 0x28, 0x14, 0x14, 0x27, 0x18, 0x1a, 0x2f, 0x24, 0x2a, 0x23, 0x26, 0x23, 0x3f, 0x56, 0x8f, 0x33, 0x32, 0x10, 0x05, 0x07, 0x05, 0x9d, 0x6d, 0x6e, 0x32, 0x57, 0x12, 0x35, 0x5c, 0x32, 0x35, 0x38, 0x3f, 0x2e, 0x29, 0x55, 0x48, 0x5a, 0x46, 0x3d, 0x26, 0x1a, 0x16, 0x1f, 0x32, 0x1a, 0x19, 0x3a, 0x27, 0x60, 0x1e, 0x19, 0x41, 0x5e, 0x40, 0x36, 0x37, 0x12, 0x2a, 0x0e, 0x15, 0x19, 0x21, 0x56, 0x6c, 0x81, 0x5f, 0x06, 0x94, 0x65, 0x65, 0x2e, 0x0a, 0x4b, 0x71, 0x73, 0x8d, 0x88, 0xa0, 0x3c, 0x23, 0x1a, 0x10, 0x1b, 0x28, 0x20, 0x07, 0x14, 0x06, 0x0a, 0x04, 0x16, 0x18, 0x1a, 0x17, 0x26, 0x05, 0x1d, 0xfd, 0x35, 0xdc, 0x80, 0x81, 0x2f, 0x16, 0x2c, 0x2c, 0x40, 0x21, 0x3b, 0x44, 0x61, 0x39, 0x37, 0x9e, 0x54, 0x02, 0x01, 0x1e, 0x01, 0x91, 0x1f, 0xb3, 0xfe, 0xc4, 0xfe, 0xc9, 0xfe, 0x56, 0x4d, 0x0f, 0x01, 0xe6, 0x01, 0x3b, 0xa9, 0x6e, 0x77, 0x46, 0xfe, 0x0f, 0xed, 0xbb, 0xb3, 0x5e, 0x4f, 0x3f, 0x2f, 0x2c, 0x25, 0x21, 0x18, 0x3b, 0x3e, 0x6a, 0x79, 0x74, 0x9f, 0x02, 0xd6, 0x58, 0x3c, 0x3b, 0x7d, 0x03, 0x66, 0x3f, 0x45, 0x27, 0x5f, 0x6e, 0xa5, 0xfe, 0xfa, 0xfe, 0xf4, 0xfe, 0xb1, 0x0b, 0x01, 0x48, 0xf4, 0x01, 0x02, 0x97, 0x98, 0x27, 0x1d, 0x1d, 0x27, 0x10, 0x23, 0x09, 0x16, 0x0d, 0x1d, 0x04, 0x18, 0x16, 0x2e, 0x00, 0x00, 0x02, 0x00, 0x5d, 0xff, 0xe7, 0x02, 0xf6, 0x03, 0x29, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x12, 0x03, 0x32, 0x16, 0x15, 0x14, 0x02, 0x23, 0x22, 0x26, 0x35, 0x34, 0x12, 0x02, 0x65, 0x4e, 0x47, 0x63, 0x7f, 0x4e, 0x48, 0x62, 0x7f, 0xaf, 0x89, 0xb7, 0xc7, 0x92, 0x89, 0xb6, 0xc6, 0x01, 0xf7, 0x74, 0x7d, 0xfe, 0xfe, 0xcf, 0x74, 0x7b, 0x01, 0x04, 0x01, 0xfd, 0xd8, 0xa3, 0xc6, 0xfe, 0xff, 0xd8, 0xa3, 0xc6, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5c, 0xff, 0xe3, 0x05, 0x21, 0x05, 0xf0, 0x00, 0x34, 0x00, 0x00, 0x09, 0x01, 0x16, 0x15, 0x14, 0x07, 0x34, 0x27, 0x01, 0x07, 0x06, 0x1f, 0x01, 0x16, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x26, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x37, 0x14, 0x17, 0x01, 0x13, 0x27, 0x26, 0x35, 0x34, 0x37, 0x14, 0x1f, 0x01, 0x16, 0x15, 0x14, 0x07, 0x34, 0x2f, 0x01, 0x03, 0x64, 0x01, 0x63, 0x59, 0x81, 0x2d, 0xfd, 0x48, 0x8c, 0x37, 0x3b, 0x9b, 0x5a, 0x37, 0x4e, 0x3e, 0xdc, 0xb0, 0x2a, 0x58, 0x30, 0x7e, 0x8b, 0xd9, 0x59, 0x81, 0x2d, 0x02, 0x2e, 0xfd, 0x68, 0x59, 0x81, 0x2d, 0xa4, 0x59, 0x81, 0x2d, 0x11, 0x02, 0xd0, 0xfe, 0x75, 0x63, 0x31, 0x82, 0x4c, 0x53, 0x32, 0x03, 0x05, 0x9c, 0x3f, 0x42, 0xac, 0x64, 0xd6, 0x2c, 0x3e, 0x38, 0x3f, 0x5d, 0x1d, 0x2f, 0x63, 0x36, 0xbc, 0x8d, 0x9b, 0xf1, 0x63, 0x31, 0x82, 0x4c, 0x53, 0x32, 0xfd, 0x96, 0x01, 0x19, 0x74, 0x63, 0x31, 0x82, 0x4c, 0x53, 0x32, 0xb6, 0x63, 0x31, 0x82, 0x4c, 0x53, 0x32, 0x12, 0x00, 0x00, 0x01, 0xff, 0xfb, 0xff, 0xe3, 0x04, 0xb4, 0x05, 0xf1, 0x00, 0x30, 0x00, 0x00, 0x01, 0x11, 0x33, 0x16, 0x15, 0x14, 0x0f, 0x01, 0x0e, 0x01, 0x23, 0x21, 0x22, 0x2e, 0x01, 0x35, 0x34, 0x3f, 0x01, 0x3e, 0x01, 0x33, 0x21, 0x11, 0x34, 0x27, 0x2e, 0x01, 0x23, 0x21, 0x22, 0x2e, 0x03, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x1e, 0x02, 0x33, 0x21, 0x32, 0x16, 0x04, 0x45, 0x47, 0x27, 0x1b, 0x79, 0x0f, 0x12, 0x1f, 0xfc, 0x5b, 0x13, 0x16, 0x15, 0x1e, 0x78, 0x0f, 0x12, 0x21, 0x03, 0x2a, 0x12, 0x12, 0x22, 0x39, 0xfd, 0xbf, 0x35, 0x30, 0x41, 0x1a, 0x14, 0x04, 0x0e, 0x12, 0x17, 0x0b, 0x0a, 0x26, 0x1c, 0x19, 0x02, 0x8e, 0x50, 0x52, 0x04, 0xb6, 0xfc, 0x23, 0x04, 0x24, 0x14, 0x1b, 0x87, 0x12, 0x06, 0x02, 0x14, 0x12, 0x10, 0x22, 0x86, 0x10, 0x06, 0x03, 0x78, 0x32, 0x0d, 0x10, 0x06, 0x04, 0x18, 0x31, 0x5b, 0x47, 0x28, 0x20, 0x14, 0x20, 0x1e, 0x1f, 0x04, 0x57, 0x00, 0x00, 0x01, 0x00, 0x18, 0xff, 0xb8, 0x02, 0xee, 0x05, 0xf0, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x21, 0x32, 0x17, 0x16, 0x14, 0x0e, 0x01, 0x07, 0x1e, 0x01, 0x12, 0x10, 0x07, 0x06, 0x23, 0x22, 0x26, 0x2f, 0x01, 0x0e, 0x01, 0x23, 0x21, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x3e, 0x01, 0x33, 0x21, 0x11, 0x21, 0x22, 0x26, 0x35, 0x34, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x01, 0x32, 0x01, 0x2e, 0x62, 0x1b, 0x11, 0x0b, 0x2b, 0x22, 0x02, 0x02, 0x37, 0x09, 0x16, 0x28, 0x14, 0x10, 0x06, 0x0c, 0x5a, 0x10, 0x28, 0xfe, 0x95, 0x3f, 0x1f, 0x78, 0x0f, 0x12, 0x20, 0x01, 0x5e, 0xfe, 0xdb, 0x62, 0x40, 0x12, 0x29, 0x0a, 0x15, 0x2a, 0x0e, 0x05, 0x8f, 0x37, 0x23, 0x2a, 0x28, 0x2f, 0x0a, 0x1a, 0x82, 0xfd, 0x24, 0xfe, 0xfb, 0x22, 0x53, 0x1e, 0x1f, 0x61, 0x65, 0x0e, 0x28, 0x10, 0x21, 0x87, 0x10, 0x06, 0x03, 0xcd, 0x71, 0x7e, 0x42, 0x19, 0x1e, 0x3b, 0x06, 0x02, 0x00, 0x00, 0x01, 0x00, 0x4d, 0xff, 0xb8, 0x04, 0x41, 0x05, 0xf0, 0x00, 0x26, 0x00, 0x00, 0x01, 0x21, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x1e, 0x02, 0x33, 0x21, 0x32, 0x1e, 0x02, 0x15, 0x14, 0x0e, 0x01, 0x07, 0x1e, 0x01, 0x17, 0x12, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x26, 0x35, 0x03, 0xa3, 0xfd, 0x4c, 0x62, 0x40, 0x04, 0x0e, 0x12, 0x17, 0x0b, 0x0b, 0x25, 0x1c, 0x19, 0x02, 0xbd, 0x2f, 0x40, 0x18, 0x05, 0x0b, 0x2b, 0x21, 0x02, 0x01, 0x04, 0x33, 0x09, 0x15, 0x29, 0x15, 0x10, 0x0b, 0x0a, 0x04, 0xa6, 0x71, 0x7e, 0x28, 0x1f, 0x14, 0x1f, 0x1e, 0x20, 0x04, 0x1f, 0x30, 0x1a, 0x0b, 0x10, 0x28, 0x2f, 0x0a, 0x1a, 0x82, 0x26, 0xfd, 0x4a, 0x93, 0x73, 0x21, 0x53, 0x27, 0x44, 0x51, 0x49, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x00, 0x00, 0x02, 0x8f, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x15, 0x00, 0x00, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x01, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x23, 0x35, 0x21, 0xa9, 0x65, 0x49, 0x47, 0x64, 0x64, 0x47, 0x49, 0x65, 0x01, 0x5d, 0x88, 0xfd, 0xb1, 0x88, 0x88, 0x01, 0xc7, 0x05, 0x54, 0x51, 0x6f, 0x6f, 0x51, 0x4f, 0x6f, 0x6e, 0xfb, 0x75, 0x79, 0x79, 0x03, 0x35, 0x79, 0x00, 0x02, 0x00, 0x51, 0xff, 0xd5, 0x06, 0x97, 0x05, 0x3b, 0x00, 0x09, 0x00, 0x1b, 0x00, 0x00, 0x12, 0x10, 0x00, 0x33, 0x32, 0x00, 0x10, 0x00, 0x23, 0x22, 0x05, 0x01, 0x15, 0x07, 0x1e, 0x01, 0x15, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x04, 0xe5, 0x01, 0x27, 0xfe, 0xfe, 0x01, 0x28, 0xfe, 0xd8, 0xfe, 0xfe, 0x03, 0x85, 0x01, 0x06, 0xd7, 0x01, 0x02, 0xfe, 0x85, 0xfe, 0xc2, 0xfe, 0xc2, 0xfe, 0x85, 0x01, 0x7b, 0x01, 0x3e, 0xea, 0x01, 0x4e, 0x03, 0x65, 0xfe, 0x48, 0xfe, 0xfd, 0x01, 0x03, 0x01, 0xb8, 0x01, 0x01, 0xc2, 0x01, 0x0a, 0xf4, 0xdd, 0x21, 0x23, 0x10, 0xfe, 0xc5, 0xfe, 0x87, 0x01, 0x79, 0x01, 0x3b, 0x01, 0x3a, 0x01, 0x78, 0xd1, 0x00, 0x00, 0x00, 0x04, 0x00, 0x87, 0x00, 0x00, 0x08, 0x5e, 0x04, 0x60, 0x00, 0x09, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x20, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x01, 0x03, 0x21, 0x03, 0x33, 0x01, 0x23, 0x27, 0x21, 0x07, 0x23, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x09, 0x01, 0x23, 0x0b, 0x01, 0x23, 0x01, 0x88, 0x02, 0x43, 0xfe, 0x45, 0x01, 0x8f, 0xfe, 0x71, 0x88, 0x03, 0x29, 0xa3, 0x01, 0x46, 0xe6, 0x87, 0x01, 0x52, 0x7c, 0x51, 0xfe, 0x70, 0x51, 0x7e, 0x03, 0x74, 0x81, 0xdc, 0xde, 0x81, 0xfe, 0xe3, 0x01, 0x30, 0x82, 0xf9, 0xfb, 0x82, 0x01, 0x3d, 0x04, 0x60, 0x80, 0xfe, 0xb6, 0x7f, 0xfd, 0xe9, 0x03, 0x08, 0xfe, 0x43, 0x02, 0x35, 0xfc, 0x80, 0xe6, 0xe6, 0x03, 0x80, 0xfe, 0xb3, 0x01, 0x4d, 0xfe, 0x52, 0xfe, 0x2e, 0x01, 0x7d, 0xfe, 0x83, 0x01, 0xde, 0x00, 0x03, 0x00, 0x20, 0xff, 0xf0, 0x04, 0xee, 0x04, 0x60, 0x00, 0x0f, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x00, 0x25, 0x35, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x11, 0x23, 0x11, 0x14, 0x16, 0x17, 0x16, 0x32, 0x03, 0x16, 0x33, 0x32, 0x37, 0x15, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x22, 0x06, 0x15, 0x23, 0x34, 0x36, 0x33, 0x21, 0x15, 0x23, 0x11, 0x14, 0x01, 0x33, 0x11, 0x23, 0x04, 0x94, 0x7c, 0x27, 0x17, 0x08, 0x0d, 0x79, 0x15, 0x12, 0x33, 0xcb, 0x50, 0x07, 0x61, 0x24, 0x41, 0x69, 0x76, 0xe4, 0x26, 0x13, 0x96, 0xfe, 0xd3, 0x37, 0x51, 0x2d, 0x5a, 0x67, 0x95, 0x03, 0xa7, 0xa4, 0xfd, 0x6a, 0x79, 0x79, 0x5a, 0x34, 0x40, 0x27, 0x21, 0x38, 0xa2, 0x02, 0x0c, 0xfd, 0xd6, 0xa6, 0x7a, 0x19, 0x45, 0x01, 0x42, 0xaf, 0x0a, 0xf1, 0x10, 0xca, 0x62, 0xfd, 0x01, 0xe3, 0xfc, 0x04, 0x03, 0xfc, 0x4c, 0x73, 0xa8, 0x7b, 0x64, 0xfe, 0x12, 0x59, 0xfe, 0xaf, 0x03, 0x98, 0x00, 0x02, 0x00, 0x00, 0xfe, 0x73, 0x04, 0xd1, 0x04, 0x7b, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x16, 0x13, 0x12, 0x11, 0x33, 0x10, 0x03, 0x02, 0x03, 0x10, 0x03, 0x02, 0x23, 0x22, 0x07, 0x23, 0x34, 0x37, 0x36, 0x33, 0x20, 0x13, 0x12, 0x13, 0x33, 0x02, 0x03, 0x02, 0x11, 0x01, 0xa8, 0x9c, 0x4d, 0x3e, 0x75, 0x3e, 0x61, 0x2f, 0x3f, 0x7e, 0xb1, 0x98, 0x16, 0x5a, 0x40, 0x49, 0xdc, 0x01, 0x89, 0x7b, 0x63, 0x90, 0x75, 0xb7, 0x3c, 0x3f, 0x04, 0x1d, 0xc1, 0xfe, 0x5c, 0xfe, 0xa7, 0xfe, 0x78, 0x01, 0x9f, 0x01, 0x42, 0x01, 0xfd, 0xfa, 0xbe, 0x02, 0x1b, 0x01, 0x2a, 0x02, 0x57, 0x9f, 0x62, 0x4f, 0x5a, 0xfd, 0x3d, 0x01, 0x9a, 0x01, 0x0e, 0xfe, 0x8f, 0xfe, 0xc9, 0xfe, 0xbe, 0xfd, 0xfd, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xac, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x25, 0x15, 0x21, 0x11, 0x21, 0x11, 0x01, 0x0e, 0xb6, 0x02, 0xe7, 0xfd, 0x73, 0xfe, 0x96, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0x64, 0xfa, 0x8f, 0x05, 0xd5, 0x00, 0x00, 0x03, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x68, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x01, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x04, 0x58, 0xb5, 0xfc, 0x02, 0xb6, 0x03, 0xa2, 0xfe, 0x97, 0xfe, 0x21, 0xfe, 0x96, 0x04, 0xb2, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0xfa, 0xf3, 0x05, 0x0d, 0xfa, 0x8f, 0x05, 0x71, 0xfa, 0x8f, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x16, 0xfe, 0x77, 0x05, 0xb2, 0x05, 0xc1, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x09, 0x02, 0x23, 0x09, 0x02, 0x15, 0x21, 0x09, 0x01, 0x21, 0x15, 0x21, 0x35, 0x09, 0x01, 0x35, 0x01, 0x7c, 0x02, 0xc1, 0xfd, 0x53, 0xea, 0x02, 0xad, 0xfd, 0x3f, 0x05, 0x08, 0xfc, 0x7d, 0x02, 0xad, 0xfd, 0x3f, 0x03, 0xae, 0xfa, 0x65, 0x02, 0xba, 0xfd, 0x62, 0xfe, 0xda, 0x03, 0x59, 0x03, 0x2a, 0xfc, 0xd6, 0xfc, 0xa7, 0x06, 0xe7, 0x64, 0xfc, 0xd6, 0xfc, 0xa7, 0x63, 0x63, 0x03, 0x53, 0x03, 0x15, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x92, 0xff, 0xe3, 0x05, 0x29, 0x05, 0xf0, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x06, 0x01, 0x47, 0x01, 0x29, 0xfe, 0x23, 0x69, 0xfe, 0x90, 0x01, 0x3b, 0x01, 0x63, 0xfe, 0x9d, 0xfe, 0xc5, 0x84, 0xec, 0x64, 0x65, 0xe2, 0x7d, 0xf7, 0xf8, 0xf8, 0xf7, 0x60, 0x97, 0x04, 0xfe, 0xfe, 0x6f, 0xa6, 0x02, 0x81, 0x53, 0x55, 0xfe, 0x67, 0xfe, 0x93, 0xfe, 0x92, 0xfe, 0x67, 0x48, 0x46, 0xd7, 0x5f, 0x60, 0x01, 0x32, 0x01, 0x2f, 0x01, 0x2e, 0x01, 0x32, 0x25, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x03, 0x4c, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x21, 0x23, 0x11, 0x21, 0x35, 0x21, 0x03, 0x4b, 0xb5, 0xfd, 0x71, 0x03, 0x44, 0x05, 0x2b, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x03, 0x4b, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x03, 0x4a, 0xfc, 0xbc, 0x02, 0x8f, 0x05, 0xd5, 0xfa, 0x2b, 0xaa, 0x05, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x00, 0x21, 0x23, 0x09, 0x01, 0x23, 0x01, 0x11, 0x33, 0x11, 0x04, 0x6a, 0xc4, 0xfe, 0x8c, 0xfe, 0x8e, 0xc4, 0x01, 0xdc, 0xb6, 0x02, 0x66, 0xfd, 0x9a, 0x03, 0x0e, 0x02, 0xc7, 0xfd, 0x39, 0x00, 0x04, 0x00, 0x4e, 0x00, 0x00, 0x05, 0xa9, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x13, 0x00, 0x17, 0x00, 0x22, 0x00, 0x00, 0x01, 0x20, 0x17, 0x16, 0x15, 0x14, 0x07, 0x02, 0x00, 0x29, 0x01, 0x01, 0x05, 0x03, 0x33, 0x32, 0x37, 0x13, 0x26, 0x23, 0x21, 0x03, 0x33, 0x13, 0x05, 0x03, 0x36, 0x37, 0x36, 0x13, 0x36, 0x35, 0x34, 0x27, 0x26, 0x03, 0x23, 0x01, 0x86, 0x98, 0x68, 0x15, 0x43, 0xfe, 0x52, 0xfe, 0x7b, 0xfe, 0x30, 0x01, 0x05, 0x01, 0x59, 0xe2, 0x59, 0xdd, 0x9b, 0xcc, 0x85, 0xdd, 0xfe, 0x97, 0xe2, 0xb6, 0xe2, 0x02, 0x6a, 0xb8, 0x18, 0x17, 0xbb, 0x3a, 0x12, 0x5c, 0x10, 0x05, 0xd5, 0xb5, 0x7c, 0xdf, 0x63, 0x76, 0xfe, 0x7e, 0xfe, 0x96, 0x05, 0xd5, 0x64, 0xfa, 0xf3, 0x41, 0x04, 0x8b, 0x41, 0xfa, 0xf3, 0x05, 0x0d, 0x78, 0xfb, 0xe3, 0x10, 0x13, 0x9d, 0x01, 0x50, 0x66, 0x55, 0xc2, 0x6d, 0x13, 0x00, 0x04, 0x00, 0x51, 0xff, 0xe3, 0x05, 0x1c, 0x06, 0x14, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x32, 0x00, 0x00, 0x13, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x13, 0x06, 0x07, 0x06, 0x01, 0x21, 0x37, 0x06, 0x07, 0x06, 0x23, 0x22, 0x02, 0x35, 0x34, 0x37, 0x36, 0x00, 0x33, 0x32, 0x17, 0x16, 0x17, 0x13, 0x21, 0x07, 0x03, 0x33, 0x13, 0x01, 0x03, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0xd0, 0x1c, 0x26, 0x1d, 0x30, 0x9e, 0x3c, 0x32, 0x6b, 0x03, 0x1f, 0xfe, 0xd3, 0x1e, 0x46, 0x58, 0x58, 0x70, 0xb7, 0x8e, 0x1f, 0x1f, 0x01, 0x1e, 0xb7, 0x70, 0x47, 0x47, 0x23, 0x6a, 0x01, 0x2d, 0xe5, 0xee, 0x78, 0xef, 0xfd, 0x7a, 0xab, 0x16, 0x17, 0x95, 0x6b, 0x6c, 0x1c, 0x1c, 0x33, 0x31, 0x95, 0x17, 0x02, 0x74, 0x9e, 0x4b, 0x73, 0x4f, 0x3d, 0x20, 0x03, 0x86, 0x20, 0x3d, 0x82, 0xfc, 0xed, 0xa8, 0x64, 0x30, 0x31, 0x01, 0x0c, 0x94, 0x50, 0xb2, 0xb2, 0x01, 0x44, 0x31, 0x30, 0x64, 0x02, 0x5e, 0x64, 0xfa, 0xac, 0x05, 0x54, 0xfe, 0x64, 0xfc, 0x36, 0x03, 0x82, 0x82, 0x9f, 0x9e, 0x4a, 0x74, 0x68, 0x69, 0x00, 0x00, 0x03, 0x00, 0x51, 0xff, 0xe3, 0x04, 0x1e, 0x04, 0x7b, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x32, 0x00, 0x00, 0x13, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x13, 0x06, 0x07, 0x06, 0x13, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x12, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x0f, 0x01, 0x21, 0x37, 0x21, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0xc4, 0x0b, 0x47, 0x13, 0x1b, 0x91, 0x22, 0x1f, 0x90, 0x97, 0x40, 0x55, 0x6d, 0x72, 0x51, 0x53, 0x15, 0x60, 0x61, 0x62, 0x60, 0xf2, 0x70, 0x51, 0x0d, 0x30, 0xa3, 0xa1, 0xe3, 0xcd, 0x5c, 0x3f, 0x0e, 0x11, 0xfd, 0xce, 0x12, 0x01, 0xcd, 0x0a, 0x34, 0x46, 0x98, 0x43, 0x3c, 0x02, 0x30, 0x3c, 0x37, 0x8d, 0x68, 0x1d, 0x16, 0x03, 0x3a, 0x15, 0x1c, 0x82, 0xfd, 0x4a, 0x15, 0x1f, 0x16, 0x28, 0x75, 0x2a, 0x16, 0x16, 0x9c, 0x6f, 0xa6, 0x44, 0x4d, 0x01, 0x13, 0xa2, 0xa1, 0x91, 0x63, 0x93, 0x46, 0x50, 0x5a, 0x64, 0x38, 0x32, 0x76, 0x52, 0x73, 0x11, 0x00, 0x00, 0x03, 0x00, 0x47, 0x00, 0x00, 0x02, 0x41, 0x06, 0x14, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x07, 0x23, 0x03, 0x33, 0x13, 0x23, 0x13, 0x21, 0x13, 0x21, 0x01, 0x9b, 0xa6, 0x29, 0xa6, 0xbf, 0x79, 0xa0, 0x79, 0x21, 0xfe, 0xd3, 0xc4, 0x01, 0x2d, 0x06, 0x14, 0xe9, 0xfb, 0x39, 0x03, 0x98, 0xfc, 0x04, 0x04, 0x60, 0x00, 0x03, 0xff, 0x2d, 0xfe, 0x56, 0x02, 0x41, 0x06, 0x14, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x33, 0x07, 0x23, 0x03, 0x13, 0x23, 0x03, 0x06, 0x07, 0x36, 0x37, 0x36, 0x05, 0x23, 0x37, 0x33, 0x32, 0x37, 0x36, 0x37, 0x13, 0x21, 0x03, 0x06, 0x07, 0x06, 0x01, 0x9b, 0xa6, 0x29, 0xa6, 0x5c, 0xb6, 0x79, 0xbb, 0x1f, 0x30, 0x41, 0x2d, 0x43, 0xfe, 0xf9, 0xc6, 0x12, 0x2d, 0x5e, 0x2b, 0x2b, 0x1a, 0xd1, 0x01, 0x2d, 0xc8, 0x25, 0x5a, 0x5b, 0x06, 0x14, 0xe9, 0xfa, 0xbf, 0x04, 0x12, 0xfb, 0xd0, 0xb5, 0x54, 0x0f, 0x30, 0x48, 0xf4, 0x64, 0x30, 0x31, 0x99, 0x04, 0xac, 0xfb, 0x8c, 0xd6, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x35, 0xff, 0xe3, 0x05, 0x26, 0x05, 0xf0, 0x00, 0x26, 0x00, 0x30, 0x00, 0x00, 0x09, 0x01, 0x0e, 0x01, 0x15, 0x23, 0x34, 0x12, 0x37, 0x03, 0x33, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x00, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x03, 0x5b, 0xfe, 0x36, 0x35, 0x40, 0xa8, 0x68, 0x54, 0xfb, 0xe3, 0x81, 0x5d, 0xcd, 0x76, 0xd9, 0x01, 0x14, 0x79, 0x79, 0x2c, 0x2d, 0xc8, 0xa6, 0x4b, 0x94, 0x4c, 0x4e, 0x8e, 0x3d, 0x5f, 0x76, 0x36, 0x2e, 0x51, 0x4d, 0xbf, 0x90, 0x55, 0x96, 0x42, 0x02, 0x40, 0x02, 0x08, 0x59, 0xcb, 0x72, 0x84, 0x01, 0x02, 0x7e, 0x01, 0x1f, 0x95, 0x59, 0x57, 0xfe, 0xed, 0xd7, 0x80, 0xe1, 0x63, 0x3f, 0x7d, 0x3c, 0xa2, 0xc5, 0x24, 0x24, 0xb6, 0x2f, 0x31, 0x6f, 0x58, 0x33, 0x67, 0xce, 0x51, 0xa1, 0x58, 0x92, 0xc2, 0x3f, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x03, 0x2e, 0x04, 0x60, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x03, 0x2e, 0xfd, 0x1b, 0x02, 0x3f, 0xfe, 0x3a, 0x01, 0xc6, 0x04, 0x60, 0xfb, 0xa0, 0x93, 0x01, 0x6f, 0x93, 0x01, 0xcb, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x06, 0xa4, 0x05, 0xf0, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa5, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x06, 0xb6, 0x05, 0xf0, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa7, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x09, 0x9d, 0x05, 0xf0, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x27, 0x00, 0x7b, 0x04, 0x17, 0xfd, 0x64, 0x10, 0x07, 0x07, 0xa0, 0x06, 0xfa, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x06, 0x9c, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x00, 0x75, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x54, 0xff, 0xe3, 0x06, 0x9c, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x74, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x00, 0x75, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x06, 0xa2, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa3, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x54, 0xff, 0xe3, 0x06, 0xa2, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x74, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa3, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x58, 0xff, 0xe3, 0x06, 0xa2, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x75, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa3, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x38, 0xff, 0xe3, 0x06, 0xa2, 0x05, 0xf0, 0x10, 0x26, 0x07, 0xa2, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa3, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x06, 0xbf, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa4, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x5b, 0xff, 0xe3, 0x06, 0xbf, 0x05, 0xf0, 0x10, 0x26, 0x07, 0xa3, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa4, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x06, 0xb8, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa6, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x58, 0xff, 0xe3, 0x06, 0xb8, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x75, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa6, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x5b, 0xff, 0xe3, 0x06, 0xb8, 0x05, 0xf0, 0x10, 0x26, 0x07, 0xa3, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa6, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x61, 0xff, 0xe3, 0x06, 0xb8, 0x05, 0xf0, 0x10, 0x26, 0x07, 0xa5, 0x00, 0x00, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa6, 0x04, 0x17, 0xfd, 0x64, 0xff, 0xff, 0x00, 0x7b, 0xff, 0xe3, 0x05, 0x69, 0x05, 0xf0, 0x10, 0x26, 0x00, 0x7b, 0x00, 0x00, 0x10, 0x07, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x6b, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x2c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x02, 0xd7, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x00, 0x2c, 0x01, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x42, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x27, 0x00, 0x2c, 0x01, 0x6c, 0x00, 0x00, 0x10, 0x07, 0x00, 0x2c, 0x02, 0xd7, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x06, 0x96, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x00, 0x39, 0x01, 0xb8, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x39, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x05, 0xf0, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x39, 0x00, 0x00, 0x10, 0x07, 0x00, 0x2c, 0x04, 0x84, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x07, 0x5b, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x39, 0x00, 0x00, 0x10, 0x27, 0x00, 0x2c, 0x04, 0x84, 0x00, 0x00, 0x10, 0x07, 0x00, 0x2c, 0x05, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x08, 0xc7, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x39, 0x00, 0x00, 0x10, 0x27, 0x00, 0x2c, 0x04, 0x84, 0x00, 0x00, 0x10, 0x27, 0x00, 0x2c, 0x05, 0xf0, 0x00, 0x00, 0x10, 0x07, 0x00, 0x2c, 0x07, 0x5c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x06, 0x62, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x2c, 0x00, 0x00, 0x10, 0x07, 0x00, 0x3b, 0x01, 0xac, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x06, 0x03, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x3b, 0x00, 0x00, 0x10, 0x07, 0x00, 0x2c, 0x04, 0x98, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x07, 0x6f, 0x05, 0xd5, 0x10, 0x26, 0x00, 0x3b, 0x00, 0x00, 0x10, 0x27, 0x00, 0x2c, 0x04, 0x98, 0x00, 0x00, 0x10, 0x07, 0x00, 0x2c, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x26, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x1f, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x30, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x01, 0x54, 0x06, 0x14, 0x10, 0x06, 0x00, 0x4c, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x02, 0x9f, 0x06, 0x14, 0x10, 0x26, 0x00, 0x4c, 0x00, 0x00, 0x10, 0x07, 0x00, 0x4c, 0x01, 0x4b, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x03, 0xea, 0x06, 0x14, 0x10, 0x26, 0x00, 0x4c, 0x00, 0x00, 0x10, 0x27, 0x00, 0x4c, 0x01, 0x4b, 0x00, 0x00, 0x10, 0x07, 0x00, 0x4c, 0x02, 0x96, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x05, 0xa1, 0x06, 0x14, 0x10, 0x26, 0x00, 0x4c, 0x00, 0x00, 0x10, 0x07, 0x00, 0x59, 0x01, 0x95, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x04, 0x60, 0x10, 0x06, 0x00, 0x59, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x05, 0x2b, 0x06, 0x14, 0x10, 0x26, 0x00, 0x59, 0x00, 0x00, 0x10, 0x07, 0x00, 0x4c, 0x03, 0xd7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x06, 0x76, 0x06, 0x14, 0x10, 0x26, 0x00, 0x59, 0x00, 0x00, 0x10, 0x27, 0x00, 0x4c, 0x03, 0xd7, 0x00, 0x00, 0x10, 0x07, 0x00, 0x4c, 0x05, 0x22, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x07, 0xc1, 0x06, 0x14, 0x10, 0x26, 0x00, 0x59, 0x00, 0x00, 0x10, 0x27, 0x00, 0x4c, 0x03, 0xd7, 0x00, 0x00, 0x10, 0x27, 0x00, 0x4c, 0x05, 0x22, 0x00, 0x00, 0x10, 0x07, 0x00, 0x4c, 0x06, 0x6d, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x05, 0xa9, 0x06, 0x14, 0x10, 0x26, 0x00, 0x4c, 0x00, 0x00, 0x10, 0x07, 0x00, 0x5b, 0x01, 0xa2, 0x00, 0x00, 0xff, 0xff, 0x00, 0x35, 0x00, 0x00, 0x04, 0x07, 0x04, 0x60, 0x10, 0x06, 0x00, 0x5b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x35, 0x00, 0x00, 0x05, 0x3f, 0x06, 0x14, 0x10, 0x26, 0x00, 0x5b, 0x00, 0x00, 0x10, 0x07, 0x00, 0x4c, 0x03, 0xec, 0x00, 0x00, 0xff, 0xff, 0x00, 0x35, 0x00, 0x00, 0x06, 0x8a, 0x06, 0x14, 0x10, 0x26, 0x00, 0x5b, 0x00, 0x00, 0x10, 0x27, 0x00, 0x4c, 0x03, 0xec, 0x00, 0x00, 0x10, 0x07, 0x00, 0x4c, 0x05, 0x37, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x01, 0x54, 0x06, 0x14, 0x10, 0x06, 0x00, 0x4f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x46, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xeb, 0x06, 0x14, 0x10, 0x06, 0x00, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x06, 0x67, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x50, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6c, 0x00, 0x00, 0x08, 0x8b, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x01, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x23, 0x03, 0x11, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x05, 0x96, 0x01, 0x87, 0x01, 0x6d, 0xfe, 0x91, 0xfe, 0x7b, 0xfd, 0xcb, 0xfe, 0x7b, 0xfe, 0x91, 0x01, 0x6d, 0x01, 0x87, 0x01, 0x75, 0xdc, 0x01, 0x16, 0x01, 0x02, 0xfe, 0xfe, 0xfe, 0xea, 0xdc, 0xb5, 0xdc, 0xfe, 0xea, 0xfe, 0xfe, 0x01, 0x02, 0x01, 0x16, 0x05, 0xd5, 0xfe, 0x97, 0xfe, 0x80, 0xfe, 0x7e, 0xfe, 0x96, 0x01, 0x6a, 0x01, 0x82, 0x01, 0x80, 0x01, 0x69, 0xfa, 0xd1, 0x01, 0x18, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x17, 0xfb, 0x77, 0x04, 0x89, 0xfe, 0xe9, 0xfe, 0xd4, 0xfe, 0xd2, 0xfe, 0xe8, 0x00, 0x03, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x1f, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x00, 0x01, 0x15, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x23, 0x15, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x03, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x03, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x01, 0x6b, 0xdb, 0x01, 0x16, 0x01, 0x03, 0xfe, 0xfd, 0xfe, 0xea, 0xdb, 0x41, 0xe6, 0xd8, 0xd9, 0xe5, 0x41, 0x46, 0x8f, 0x84, 0x84, 0x8f, 0xfc, 0x01, 0x75, 0x01, 0x87, 0x01, 0x6d, 0xfe, 0x91, 0xfe, 0x7b, 0xfe, 0x8b, 0x01, 0x59, 0xb3, 0x01, 0x18, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x17, 0xb2, 0xc2, 0xcf, 0xd0, 0xc3, 0x02, 0x9e, 0xfd, 0xe8, 0x81, 0x8c, 0x8a, 0x81, 0x01, 0xde, 0xfe, 0x97, 0xfe, 0x80, 0xfe, 0x7e, 0xfe, 0x96, 0x00, 0x05, 0x00, 0x6c, 0x00, 0x00, 0x08, 0x8b, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x28, 0x00, 0x31, 0x00, 0x43, 0x00, 0x00, 0x01, 0x15, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x15, 0x33, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x03, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x13, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x20, 0x00, 0x11, 0x10, 0x00, 0x01, 0x11, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x13, 0x35, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x33, 0x35, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x04, 0xd6, 0x41, 0xe7, 0xd8, 0xd9, 0xe6, 0x41, 0xdc, 0x01, 0x16, 0x01, 0x02, 0xfe, 0xfe, 0xfe, 0xea, 0xdc, 0x47, 0x8f, 0x84, 0x84, 0x8f, 0x47, 0xc0, 0xfd, 0xcb, 0xfe, 0x7b, 0xfe, 0x91, 0x01, 0x6d, 0x01, 0x87, 0x02, 0x35, 0x01, 0x87, 0x01, 0x6d, 0xfe, 0x91, 0xfd, 0x06, 0x47, 0x8f, 0x84, 0x84, 0x8f, 0x47, 0xdc, 0xfe, 0xea, 0xfe, 0xfe, 0x01, 0x02, 0x01, 0x16, 0xdc, 0x41, 0xe6, 0xd9, 0xd8, 0xe7, 0x05, 0x2f, 0xb2, 0xc2, 0xcf, 0xd0, 0xc3, 0xb3, 0x01, 0x18, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x17, 0xfc, 0xb0, 0x81, 0x8c, 0x8a, 0x81, 0xfc, 0x09, 0x01, 0x6a, 0x01, 0x82, 0x01, 0x80, 0x01, 0x69, 0xfe, 0x97, 0xfe, 0x80, 0xfe, 0x7e, 0xfe, 0x96, 0x01, 0xdf, 0x02, 0x18, 0x81, 0x8a, 0x8c, 0x81, 0x02, 0x9e, 0xb2, 0xfe, 0xe9, 0xfe, 0xd4, 0xfe, 0xd2, 0xfe, 0xe8, 0xb3, 0xc3, 0xd0, 0xcf, 0xc2, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x10, 0x06, 0x01, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0x72, 0xff, 0xe3, 0x03, 0x90, 0x04, 0x7b, 0x10, 0x06, 0x02, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0xfe, 0x56, 0x04, 0xa4, 0x05, 0xf0, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x36, 0x37, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x04, 0xa3, 0x5c, 0xd0, 0x75, 0xe6, 0xf5, 0xf5, 0xe6, 0x75, 0xd0, 0x5c, 0xb5, 0x0a, 0x0b, 0x6b, 0x76, 0xfe, 0xce, 0xfe, 0xa2, 0x01, 0x5e, 0x01, 0x32, 0x78, 0xd6, 0x05, 0x62, 0xd5, 0x5f, 0x5e, 0xfe, 0xc7, 0xfe, 0xd8, 0xfe, 0xd9, 0xfe, 0xc7, 0x5e, 0x5f, 0xfd, 0x10, 0x01, 0xb9, 0x04, 0x04, 0x24, 0x01, 0x9f, 0x01, 0x67, 0x01, 0x68, 0x01, 0x9f, 0x47, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4e, 0xff, 0xe3, 0x06, 0x9c, 0x05, 0xf0, 0x10, 0x27, 0x07, 0x79, 0x02, 0xe3, 0x00, 0x00, 0x10, 0x27, 0x00, 0x75, 0x04, 0x17, 0xfd, 0x64, 0x10, 0x06, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x09, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x17, 0x07, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x04, 0x49, 0xfb, 0xb7, 0xd2, 0x6c, 0x02, 0x55, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0xaa, 0xe9, 0x78, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x79, 0x00, 0x00, 0x04, 0x8e, 0x05, 0xdc, 0x00, 0x09, 0x00, 0x00, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x23, 0x11, 0x07, 0x27, 0x02, 0xdc, 0x51, 0x01, 0x61, 0x6c, 0xd1, 0x99, 0xd3, 0x6c, 0x05, 0xdc, 0xfe, 0x76, 0x78, 0xea, 0xfb, 0x3c, 0x04, 0xc4, 0xea, 0x78, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x09, 0x00, 0x00, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x05, 0xae, 0xfe, 0x9f, 0x6c, 0xd1, 0xfb, 0xb7, 0x04, 0x49, 0xd1, 0x6c, 0x02, 0xaf, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xaa, 0xe9, 0x78, 0x00, 0x00, 0x00, 0x01, 0x01, 0x79, 0xff, 0xf9, 0x04, 0x8e, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x05, 0x23, 0x01, 0x37, 0x17, 0x11, 0x33, 0x11, 0x37, 0x17, 0x03, 0x2d, 0x51, 0xfe, 0x9d, 0x6c, 0xd3, 0x99, 0xd1, 0x6c, 0x07, 0x01, 0x8a, 0x78, 0xea, 0x04, 0xc4, 0xfb, 0x3c, 0xea, 0x78, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x17, 0x07, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x03, 0x5c, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xfc, 0xa4, 0xd2, 0x6c, 0x02, 0x55, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xe9, 0x78, 0x00, 0x00, 0x01, 0x01, 0x79, 0xff, 0xef, 0x04, 0x8e, 0x05, 0xdc, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x17, 0x11, 0x07, 0x27, 0x02, 0xdc, 0x51, 0x01, 0x61, 0x6c, 0xd1, 0xd1, 0x6c, 0xfe, 0x9f, 0x51, 0xfe, 0x9d, 0x6c, 0xd3, 0xd3, 0x6c, 0x05, 0xdc, 0xfe, 0x76, 0x78, 0xea, 0xfc, 0x43, 0xea, 0x78, 0xfe, 0x76, 0x01, 0x8a, 0x78, 0xea, 0x03, 0xbd, 0xea, 0x78, 0x00, 0x01, 0x01, 0x03, 0x00, 0x34, 0x05, 0x10, 0x04, 0xb3, 0x00, 0x09, 0x00, 0x00, 0x01, 0x37, 0x21, 0x15, 0x21, 0x01, 0x07, 0x01, 0x11, 0x23, 0x01, 0x03, 0x39, 0x01, 0xf4, 0xfe, 0xd7, 0x03, 0x08, 0x6c, 0xfc, 0xf8, 0x98, 0x04, 0x74, 0x3f, 0xa9, 0xfc, 0xa2, 0x78, 0x03, 0x5e, 0xfe, 0xb6, 0x00, 0x01, 0x01, 0x03, 0x00, 0x34, 0x05, 0x10, 0x04, 0xb3, 0x00, 0x09, 0x00, 0x00, 0x01, 0x17, 0x11, 0x23, 0x11, 0x01, 0x27, 0x01, 0x21, 0x35, 0x04, 0xd6, 0x39, 0x98, 0xfc, 0xf8, 0x6c, 0x03, 0x08, 0xfe, 0xd7, 0x04, 0xb3, 0x3f, 0xfd, 0xd4, 0x01, 0x4a, 0xfc, 0xa2, 0x78, 0x03, 0x5e, 0xa9, 0x00, 0x01, 0x01, 0x03, 0x00, 0x34, 0x05, 0x10, 0x04, 0xb3, 0x00, 0x09, 0x00, 0x00, 0x25, 0x07, 0x21, 0x35, 0x21, 0x01, 0x37, 0x01, 0x11, 0x33, 0x05, 0x0f, 0x39, 0xfe, 0x0c, 0x01, 0x29, 0xfc, 0xf8, 0x6c, 0x03, 0x08, 0x98, 0x73, 0x3f, 0xa9, 0x03, 0x5e, 0x78, 0xfc, 0xa2, 0x01, 0x4a, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x34, 0x05, 0x10, 0x04, 0xb3, 0x00, 0x09, 0x00, 0x00, 0x25, 0x27, 0x11, 0x33, 0x11, 0x01, 0x17, 0x01, 0x21, 0x15, 0x01, 0x3c, 0x39, 0x98, 0x03, 0x08, 0x6c, 0xfc, 0xf8, 0x01, 0x29, 0x34, 0x3f, 0x02, 0x2c, 0xfe, 0xb6, 0x03, 0x5e, 0x78, 0xfc, 0xa2, 0xa9, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x11, 0x00, 0x00, 0x01, 0x03, 0x27, 0x13, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x13, 0x17, 0x03, 0x21, 0x15, 0x03, 0xd5, 0xb4, 0x85, 0x88, 0xfe, 0x32, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x02, 0x27, 0xb4, 0x85, 0x88, 0x01, 0x71, 0x02, 0x2d, 0xfe, 0xa5, 0x55, 0x01, 0x06, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x01, 0x5b, 0x55, 0xfe, 0xfa, 0xaa, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x11, 0x00, 0x00, 0x01, 0x13, 0x17, 0x03, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x03, 0x27, 0x13, 0x21, 0x35, 0x02, 0x33, 0xb4, 0x86, 0x88, 0x01, 0xcd, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xfd, 0xda, 0xb4, 0x86, 0x88, 0xfe, 0x8f, 0x02, 0xd7, 0x01, 0x5b, 0x55, 0xfe, 0xfa, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xfe, 0xa5, 0x55, 0x01, 0x06, 0xaa, 0x00, 0x01, 0x00, 0x27, 0x00, 0xd3, 0x05, 0xf5, 0x03, 0x50, 0x00, 0x34, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x11, 0x23, 0x11, 0x37, 0x21, 0x15, 0x05, 0x01, 0xbc, 0x1f, 0x2b, 0x24, 0x33, 0x2f, 0x28, 0x2b, 0x3f, 0x13, 0x1f, 0x36, 0x35, 0x46, 0x43, 0x4f, 0x52, 0x40, 0x49, 0x32, 0x36, 0x1f, 0x8e, 0x13, 0x1f, 0x1e, 0x2d, 0x25, 0x32, 0x30, 0x27, 0x2b, 0x20, 0x20, 0x13, 0x1b, 0x39, 0x2d, 0x4e, 0x40, 0x52, 0x4f, 0x43, 0x46, 0x35, 0x90, 0x98, 0x38, 0x01, 0xf5, 0xfe, 0xd7, 0x01, 0xf4, 0x21, 0x15, 0x13, 0x13, 0x15, 0x46, 0x30, 0x4f, 0x3c, 0x3a, 0x22, 0x20, 0x20, 0x25, 0x37, 0x3c, 0x4f, 0x41, 0x30, 0x23, 0x21, 0x17, 0x13, 0x13, 0x14, 0x24, 0x23, 0x30, 0x49, 0x42, 0x35, 0x27, 0x20, 0x20, 0x22, 0x3a, 0xa0, 0xfe, 0xb6, 0x02, 0x2c, 0x3f, 0xa9, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x13, 0x00, 0xd3, 0x05, 0xe1, 0x03, 0x50, 0x00, 0x34, 0x00, 0x00, 0x01, 0x37, 0x25, 0x35, 0x21, 0x17, 0x11, 0x23, 0x11, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x27, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x04, 0x4d, 0x90, 0xfe, 0xd7, 0x01, 0xf4, 0x39, 0x98, 0x90, 0x35, 0x47, 0x42, 0x4f, 0x52, 0x40, 0x4e, 0x2e, 0x38, 0x1c, 0x13, 0x1f, 0x21, 0x2a, 0x28, 0x2f, 0x33, 0x25, 0x2d, 0x1d, 0x20, 0x13, 0x8d, 0x1e, 0x36, 0x32, 0x4a, 0x40, 0x52, 0x4f, 0x42, 0x47, 0x35, 0x36, 0x1e, 0x13, 0x3f, 0x2b, 0x28, 0x30, 0x32, 0x25, 0x2a, 0x01, 0xf4, 0xa0, 0x01, 0xa9, 0x3f, 0xfd, 0xd4, 0x01, 0x4a, 0xa0, 0x3a, 0x22, 0x20, 0x20, 0x27, 0x35, 0x42, 0x49, 0x30, 0x23, 0x24, 0x14, 0x13, 0x13, 0x17, 0x21, 0x23, 0x30, 0x41, 0x4f, 0x3c, 0x37, 0x25, 0x20, 0x20, 0x22, 0x3a, 0x3c, 0x4f, 0x30, 0x46, 0x15, 0x13, 0x13, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x11, 0x00, 0x00, 0x13, 0x01, 0x17, 0x07, 0x33, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x17, 0x07, 0x01, 0x23, 0x17, 0x07, 0x01, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0xd8, 0x01, 0x3e, 0x6c, 0xd2, 0x02, 0x99, 0xfd, 0x67, 0xd2, 0x6c, 0xfe, 0xc2, 0xd8, 0xd2, 0x6c, 0xfe, 0x9e, 0x02, 0xaf, 0x01, 0x89, 0x78, 0xe9, 0x01, 0x61, 0x78, 0xe9, 0xaa, 0xe9, 0x78, 0x01, 0x61, 0xe9, 0x78, 0x01, 0x89, 0x00, 0x00, 0x00, 0x01, 0x01, 0x7a, 0x00, 0x00, 0x04, 0x90, 0x05, 0xdc, 0x00, 0x11, 0x00, 0x00, 0x09, 0x01, 0x07, 0x27, 0x15, 0x01, 0x07, 0x27, 0x11, 0x23, 0x11, 0x07, 0x27, 0x01, 0x35, 0x07, 0x27, 0x01, 0x03, 0x2d, 0x01, 0x62, 0x6c, 0xd2, 0x01, 0x3e, 0x6c, 0xd2, 0x99, 0xd1, 0x6c, 0x01, 0x3d, 0xd1, 0x6c, 0x01, 0x61, 0x05, 0xdc, 0xfe, 0x76, 0x78, 0xea, 0xf0, 0xfe, 0x9e, 0x78, 0xea, 0xfd, 0x1c, 0x02, 0xe4, 0xea, 0x78, 0x01, 0x62, 0xf0, 0xea, 0x78, 0x01, 0x8a, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x11, 0x00, 0x00, 0x09, 0x01, 0x27, 0x37, 0x23, 0x01, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x01, 0x33, 0x27, 0x37, 0x01, 0x05, 0xae, 0xfe, 0x9f, 0x6c, 0xd1, 0xd8, 0xfe, 0xc3, 0x6c, 0xd1, 0xfd, 0x67, 0x02, 0x99, 0xd1, 0x6c, 0x01, 0x3d, 0xd8, 0xd1, 0x6c, 0x01, 0x61, 0x02, 0x55, 0xfe, 0x77, 0x78, 0xe9, 0xfe, 0x9f, 0x78, 0xe9, 0xaa, 0xe9, 0x78, 0xfe, 0x9f, 0xe9, 0x78, 0xfe, 0x77, 0x00, 0x00, 0x01, 0x01, 0x7a, 0xff, 0xf9, 0x04, 0x90, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x05, 0x01, 0x37, 0x17, 0x35, 0x01, 0x37, 0x17, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x15, 0x37, 0x17, 0x01, 0x02, 0xde, 0xfe, 0x9d, 0x6c, 0xd3, 0xfe, 0xc1, 0x6c, 0xd3, 0x98, 0xd1, 0x6c, 0xfe, 0xc3, 0xd1, 0x6c, 0xfe, 0x9f, 0x07, 0x01, 0x8a, 0x78, 0xea, 0xf0, 0x01, 0x62, 0x78, 0xea, 0x02, 0xe4, 0xfd, 0x1c, 0xea, 0x78, 0xfe, 0x9e, 0xf0, 0xea, 0x78, 0xfe, 0x76, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x01, 0x17, 0x09, 0x01, 0x07, 0x01, 0x21, 0x17, 0x07, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x02, 0x9f, 0x01, 0x3e, 0x6c, 0xfe, 0xe2, 0x01, 0x1e, 0x6c, 0xfe, 0xc2, 0xfd, 0x61, 0xd2, 0x6c, 0x02, 0x55, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x01, 0x61, 0x78, 0xfe, 0xc2, 0xfe, 0xc2, 0x78, 0x01, 0x61, 0xe9, 0x78, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x0e, 0x00, 0x00, 0x09, 0x01, 0x27, 0x37, 0x21, 0x01, 0x27, 0x09, 0x01, 0x37, 0x01, 0x21, 0x27, 0x37, 0x01, 0x05, 0xae, 0xfe, 0x9f, 0x6c, 0xd1, 0xfd, 0x61, 0xfe, 0xc2, 0x6c, 0x01, 0x1f, 0xfe, 0xe1, 0x6c, 0x01, 0x3e, 0x02, 0x9f, 0xd1, 0x6c, 0x01, 0x61, 0x02, 0x55, 0xfe, 0x77, 0x78, 0xe9, 0xfe, 0x9f, 0x78, 0x01, 0x3e, 0x01, 0x3e, 0x78, 0xfe, 0x9f, 0xe9, 0x78, 0xfe, 0x77, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x11, 0x33, 0x11, 0x23, 0x05, 0x06, 0xfc, 0x50, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x03, 0xb0, 0x99, 0x99, 0x02, 0x2d, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x01, 0x59, 0xfc, 0xa4, 0x00, 0x00, 0x01, 0x01, 0x7a, 0x00, 0x00, 0x04, 0x8e, 0x05, 0xdc, 0x00, 0x0d, 0x00, 0x00, 0x25, 0x11, 0x07, 0x27, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x21, 0x15, 0x21, 0x35, 0x02, 0xb8, 0xd1, 0x6c, 0x01, 0x61, 0x51, 0x01, 0x61, 0x6c, 0xd1, 0x01, 0x37, 0xfc, 0xfa, 0xaa, 0x04, 0x1a, 0xea, 0x78, 0x01, 0x8a, 0xfe, 0x76, 0x78, 0xea, 0xfb, 0xe6, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x04, 0xb2, 0xfc, 0x50, 0x99, 0x99, 0x03, 0xb0, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x02, 0x2d, 0xfe, 0xa7, 0x03, 0x5c, 0xfe, 0xa7, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x00, 0x00, 0x01, 0x01, 0x7a, 0xff, 0xf9, 0x04, 0x8e, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x17, 0x02, 0xb8, 0xfe, 0xca, 0x03, 0x06, 0xfe, 0xc9, 0xd1, 0x6c, 0xfe, 0x9f, 0x51, 0xfe, 0x9f, 0x6c, 0xd1, 0x05, 0x2b, 0xaa, 0xaa, 0xfb, 0xe6, 0xea, 0x78, 0xfe, 0x76, 0x01, 0x8a, 0x78, 0xea, 0x00, 0x00, 0x01, 0x01, 0x7a, 0x00, 0x00, 0x04, 0x8e, 0x05, 0xdc, 0x00, 0x13, 0x00, 0x00, 0x01, 0x37, 0x17, 0x01, 0x21, 0x15, 0x21, 0x35, 0x21, 0x01, 0x37, 0x17, 0x11, 0x07, 0x27, 0x01, 0x33, 0x01, 0x07, 0x27, 0x03, 0x51, 0xd1, 0x6c, 0xfe, 0x9f, 0x01, 0x5b, 0xfc, 0xfa, 0x01, 0x5a, 0xfe, 0x9f, 0x6c, 0xd1, 0xd1, 0x6c, 0x01, 0x61, 0x51, 0x01, 0x61, 0x6c, 0xd1, 0x01, 0xc2, 0xea, 0x78, 0xfe, 0x76, 0xaa, 0xaa, 0x01, 0x8a, 0x78, 0xea, 0x03, 0x02, 0xea, 0x78, 0x01, 0x8a, 0xfe, 0x76, 0x78, 0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0x9f, 0x04, 0x86, 0x00, 0x25, 0x00, 0x00, 0x01, 0x35, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x20, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x04, 0x91, 0x38, 0x2f, 0x2d, 0x2a, 0x27, 0x28, 0x26, 0x29, 0x23, 0x34, 0x2c, 0x1d, 0xfc, 0xa7, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x01, 0xaa, 0x01, 0xa9, 0x14, 0x16, 0x11, 0x10, 0x12, 0x11, 0x11, 0x11, 0x16, 0x14, 0x03, 0xdc, 0xaa, 0x16, 0x15, 0x2d, 0x29, 0x6f, 0x3d, 0x3c, 0x6a, 0x2e, 0x28, 0x1a, 0x16, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x0a, 0x0a, 0x12, 0x11, 0x31, 0x1a, 0x1b, 0x2e, 0x14, 0x12, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6a, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x86, 0x00, 0x29, 0x00, 0x00, 0x01, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x01, 0x77, 0x18, 0x14, 0x15, 0x12, 0x10, 0x09, 0x09, 0x09, 0x0b, 0x0e, 0x12, 0x15, 0x14, 0x18, 0x03, 0x3b, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xfc, 0xc5, 0x3a, 0x2c, 0x35, 0x23, 0x28, 0x13, 0x14, 0x14, 0x15, 0x26, 0x2b, 0x2d, 0x2f, 0x37, 0x03, 0xdc, 0x0a, 0x0a, 0x12, 0x11, 0x1a, 0x17, 0x1b, 0x1a, 0x17, 0x1c, 0x0f, 0x12, 0x0a, 0x0a, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0x16, 0x1a, 0x28, 0x2e, 0x34, 0x36, 0x3c, 0x3d, 0x36, 0x39, 0x29, 0x2d, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0x9f, 0x04, 0x86, 0x00, 0x18, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x07, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x15, 0x23, 0x35, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x04, 0x1c, 0x75, 0x18, 0x14, 0x16, 0x11, 0x10, 0x09, 0x09, 0x09, 0x09, 0x10, 0x11, 0x16, 0x14, 0x30, 0x14, 0x16, 0x11, 0x0e, 0x0b, 0x09, 0x98, 0x14, 0x14, 0x27, 0x2b, 0x2c, 0x2f, 0x38, 0x3b, 0x2c, 0x34, 0x23, 0x29, 0x12, 0x14, 0x14, 0x14, 0x27, 0x2a, 0x2d, 0x2f, 0x38, 0x75, 0x98, 0xfd, 0xd2, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x02, 0xd7, 0x0a, 0x0a, 0x12, 0x11, 0x1a, 0x17, 0x1a, 0x1b, 0x17, 0x1a, 0x11, 0x12, 0x0a, 0x0a, 0x0a, 0x0a, 0x12, 0x0f, 0x1c, 0x17, 0x1b, 0x82, 0x82, 0x3d, 0x36, 0x39, 0x29, 0x2d, 0x15, 0x16, 0x16, 0x1a, 0x28, 0x2e, 0x34, 0x36, 0x3d, 0x3c, 0x36, 0x39, 0x29, 0x2d, 0x15, 0x16, 0xdc, 0xdc, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6a, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x86, 0x00, 0x18, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x29, 0x01, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x15, 0x23, 0x35, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x01, 0xec, 0x09, 0x0b, 0x0e, 0x11, 0x16, 0x13, 0x31, 0x14, 0x15, 0x12, 0x10, 0x09, 0x09, 0x09, 0x09, 0x10, 0x12, 0x15, 0x14, 0x18, 0x01, 0x0d, 0x02, 0x2e, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xfd, 0xd2, 0x98, 0x75, 0x37, 0x2f, 0x2d, 0x2b, 0x26, 0x15, 0x14, 0x14, 0x13, 0x28, 0x23, 0x35, 0x2c, 0x3a, 0x38, 0x2f, 0x2d, 0x2a, 0x27, 0x15, 0x13, 0x02, 0xd7, 0x82, 0x1b, 0x17, 0x1c, 0x0f, 0x12, 0x0a, 0x0a, 0x0a, 0x0a, 0x12, 0x11, 0x1a, 0x17, 0x1b, 0x1a, 0x17, 0x1a, 0x11, 0x12, 0x0a, 0x0a, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xdc, 0xdc, 0x16, 0x15, 0x2d, 0x29, 0x39, 0x36, 0x3c, 0x3d, 0x36, 0x34, 0x2e, 0x28, 0x1a, 0x16, 0x16, 0x15, 0x2d, 0x29, 0x39, 0x36, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x58, 0x00, 0x00, 0x01, 0x23, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x01, 0x5f, 0x09, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x09, 0x2b, 0x21, 0x1f, 0x20, 0x0a, 0x15, 0x18, 0x16, 0x09, 0x09, 0x05, 0x0e, 0x1d, 0x1e, 0x22, 0x23, 0x28, 0x2b, 0x21, 0x23, 0x1d, 0x1d, 0x0e, 0x04, 0x09, 0x09, 0x16, 0x18, 0x16, 0x09, 0x23, 0x1d, 0x23, 0x28, 0x09, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0x09, 0x0c, 0x0a, 0x0c, 0x09, 0x1c, 0x24, 0x23, 0x51, 0x22, 0x24, 0x1c, 0x1e, 0x0e, 0x04, 0x09, 0x09, 0x0b, 0x0a, 0x19, 0x0a, 0x0c, 0x09, 0x08, 0x05, 0x0d, 0x1f, 0x1c, 0x24, 0x22, 0x51, 0x23, 0x24, 0x1c, 0x09, 0x0b, 0x0a, 0x02, 0x2d, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x12, 0x12, 0x24, 0x0a, 0x0c, 0x0c, 0x0a, 0x0c, 0x0d, 0x2d, 0x23, 0x25, 0x11, 0x12, 0x12, 0x14, 0x22, 0x26, 0x2a, 0x0d, 0x0c, 0x0a, 0x0c, 0x0c, 0x0a, 0x27, 0x0f, 0x12, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0x06, 0x06, 0x0a, 0x22, 0x14, 0x12, 0x12, 0x14, 0x22, 0x26, 0x2a, 0x0d, 0x0c, 0x0a, 0x06, 0x06, 0x06, 0x06, 0x0a, 0x09, 0x10, 0x2a, 0x26, 0x22, 0x14, 0x12, 0x12, 0x14, 0x22, 0x0a, 0x06, 0x06, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xbe, 0x05, 0xaf, 0x04, 0x46, 0x00, 0x17, 0x00, 0x00, 0x25, 0x27, 0x13, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x13, 0x17, 0x03, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x02, 0xc2, 0x90, 0x64, 0xfe, 0xc0, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x01, 0x78, 0x79, 0x90, 0x65, 0x01, 0x40, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0x88, 0xbe, 0x3a, 0x01, 0x35, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x01, 0x6f, 0x3a, 0xfe, 0xcb, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0x00, 0x01, 0x01, 0x0c, 0xff, 0xfc, 0x05, 0x0e, 0x05, 0xd8, 0x00, 0x0d, 0x00, 0x00, 0x09, 0x01, 0x13, 0x17, 0x03, 0x01, 0x03, 0x37, 0x17, 0x01, 0x27, 0x01, 0x37, 0x13, 0x03, 0xa2, 0xfd, 0x6a, 0x8e, 0x96, 0x55, 0x02, 0x96, 0xae, 0xf2, 0x58, 0xfe, 0x67, 0x50, 0xfe, 0xe1, 0x7d, 0xab, 0x04, 0x08, 0xfe, 0x58, 0x03, 0x78, 0x1d, 0xfd, 0xee, 0x01, 0xa8, 0xfb, 0xb8, 0xbe, 0x8b, 0xfe, 0xc0, 0x10, 0x01, 0xc8, 0x62, 0xfe, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x01, 0x37, 0x00, 0x00, 0x04, 0x89, 0x05, 0xf2, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x04, 0x88, 0x99, 0xfe, 0x44, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x04, 0x91, 0xfb, 0x6f, 0x03, 0xe7, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x01, 0x81, 0x00, 0x00, 0x04, 0xd2, 0x05, 0xf2, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x11, 0x23, 0x01, 0x81, 0x02, 0x55, 0xd2, 0x6c, 0x01, 0x62, 0xfe, 0x9e, 0x6c, 0xd2, 0xfe, 0x44, 0x99, 0x04, 0x91, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xfc, 0x19, 0x00, 0x00, 0x00, 0x01, 0x01, 0x37, 0xff, 0xe3, 0x04, 0x89, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x11, 0x33, 0x04, 0x88, 0xfd, 0xab, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x01, 0xbc, 0x99, 0x01, 0x44, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x03, 0xe7, 0x00, 0x00, 0x00, 0x01, 0x01, 0x81, 0xff, 0xe3, 0x04, 0xd2, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x01, 0x81, 0x99, 0x01, 0xbc, 0xd2, 0x6c, 0x01, 0x62, 0xfe, 0x9e, 0x6c, 0xd2, 0x01, 0x44, 0x04, 0x91, 0xfc, 0x19, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0x00, 0x00, 0x00, 0x01, 0x01, 0xad, 0xff, 0xf9, 0x05, 0x79, 0x04, 0xd4, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x17, 0x11, 0x21, 0x35, 0x04, 0x3b, 0xd1, 0x6c, 0xfe, 0x9f, 0x51, 0xfe, 0x9e, 0x6c, 0xd2, 0xfe, 0x0b, 0x04, 0xd4, 0xfc, 0x3d, 0xe9, 0x78, 0xfe, 0x77, 0x01, 0x89, 0x78, 0xe9, 0x03, 0x19, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x04, 0xb9, 0x05, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x11, 0x33, 0x04, 0xb9, 0xfc, 0x9d, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x02, 0xca, 0x99, 0x02, 0x2d, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x02, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x01, 0xa0, 0x05, 0xc2, 0x05, 0x58, 0x00, 0x26, 0x00, 0x00, 0x01, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x17, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x23, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x02, 0x00, 0xd1, 0x6c, 0xfe, 0x9f, 0x51, 0xfe, 0x9d, 0x6c, 0xd3, 0x29, 0x29, 0x53, 0x51, 0x63, 0x61, 0xe6, 0x62, 0x63, 0x51, 0x52, 0x29, 0x29, 0x99, 0x3b, 0x3b, 0x36, 0x4e, 0x42, 0xac, 0x46, 0x4a, 0x39, 0x3a, 0x1f, 0x1e, 0x02, 0xb8, 0xea, 0x78, 0xfe, 0x76, 0x01, 0x8a, 0x78, 0xea, 0x32, 0x7f, 0x70, 0x6b, 0x5f, 0x56, 0x31, 0x2e, 0x2e, 0x31, 0x56, 0x5f, 0x6b, 0x70, 0x7f, 0x5d, 0xa2, 0x42, 0x3b, 0x27, 0x21, 0x21, 0x23, 0x3f, 0x40, 0x53, 0x51, 0x5d, 0x00, 0x01, 0x00, 0x47, 0x01, 0xa0, 0x05, 0xe0, 0x05, 0x58, 0x00, 0x26, 0x00, 0x00, 0x01, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x23, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x1d, 0x01, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x04, 0x08, 0x1d, 0x20, 0x39, 0x3a, 0x4a, 0x46, 0xab, 0x43, 0x4d, 0x36, 0x3b, 0x3c, 0x99, 0x29, 0x29, 0x53, 0x51, 0x63, 0x61, 0xe6, 0x62, 0x63, 0x51, 0x52, 0x29, 0x29, 0xd3, 0x6c, 0xfe, 0x9d, 0x51, 0xfe, 0xa0, 0x6c, 0x02, 0xb8, 0x32, 0x5d, 0x51, 0x53, 0x40, 0x3f, 0x23, 0x21, 0x21, 0x27, 0x3b, 0x42, 0xa2, 0x5d, 0x7f, 0x70, 0x6b, 0x5f, 0x56, 0x31, 0x2e, 0x2e, 0x31, 0x56, 0x5f, 0x6b, 0x70, 0x7f, 0x32, 0xea, 0x78, 0xfe, 0x76, 0x01, 0x8a, 0x78, 0x00, 0x00, 0x02, 0x00, 0xc7, 0x00, 0x34, 0x05, 0xac, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x35, 0x21, 0x15, 0x05, 0x37, 0x21, 0x15, 0x21, 0x01, 0x07, 0x01, 0x11, 0x23, 0xc8, 0x04, 0xe4, 0xfb, 0x57, 0x39, 0x01, 0xf4, 0xfe, 0xd7, 0x03, 0x08, 0x6c, 0xfc, 0xf8, 0x98, 0x05, 0x72, 0x63, 0x63, 0xfe, 0x3f, 0xa9, 0xfc, 0xa2, 0x78, 0x03, 0x5e, 0xfe, 0xb6, 0x00, 0x02, 0x00, 0x64, 0xff, 0xa1, 0x05, 0xa4, 0x05, 0x63, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x35, 0x21, 0x27, 0x37, 0x01, 0x11, 0x33, 0x11, 0x23, 0x11, 0x01, 0x27, 0x37, 0x01, 0x21, 0x17, 0x07, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x17, 0x07, 0x21, 0x65, 0x03, 0xaa, 0xd3, 0x6c, 0x01, 0x63, 0x99, 0x99, 0xfe, 0x9d, 0x6c, 0xd3, 0x01, 0x95, 0xfc, 0x56, 0xd2, 0x6c, 0xfe, 0x9e, 0x99, 0x99, 0x01, 0x62, 0x6c, 0xd2, 0x03, 0xaa, 0x01, 0x01, 0xaa, 0xe8, 0x78, 0xfe, 0x78, 0x01, 0x4e, 0xfd, 0x08, 0x01, 0x50, 0xfe, 0x78, 0x78, 0xe8, 0x02, 0x58, 0xe8, 0x78, 0x01, 0x88, 0xfe, 0xb0, 0x02, 0xf8, 0xfe, 0xb2, 0x01, 0x88, 0x78, 0xe8, 0x00, 0x00, 0x00, 0x01, 0x00, 0xbd, 0x00, 0x7f, 0x05, 0x7d, 0x05, 0x70, 0x00, 0x36, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x26, 0x2f, 0x01, 0x11, 0x23, 0x11, 0x37, 0x21, 0x15, 0x21, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0xcf, 0x3e, 0x1c, 0x1e, 0x3b, 0x3c, 0x36, 0x4d, 0x43, 0xab, 0x46, 0x4a, 0x39, 0x3c, 0x3b, 0x1e, 0x1e, 0x3c, 0x1f, 0x99, 0x39, 0x01, 0xf5, 0xfe, 0xd7, 0x1f, 0x51, 0x2b, 0x29, 0x29, 0x2b, 0x51, 0x4b, 0x69, 0x5c, 0x78, 0x73, 0x61, 0x65, 0x4f, 0x51, 0x2b, 0x29, 0x29, 0x29, 0x53, 0x04, 0x2b, 0x42, 0x51, 0x51, 0x5d, 0x5a, 0xa2, 0x42, 0x3b, 0x27, 0x21, 0x21, 0x23, 0x3f, 0x42, 0xa2, 0x5a, 0x5d, 0x51, 0x51, 0x42, 0x23, 0xfe, 0xb6, 0x02, 0x2c, 0x40, 0xaa, 0x23, 0x5a, 0x70, 0x70, 0x7f, 0x7c, 0x70, 0x71, 0x59, 0x53, 0x34, 0x2e, 0x2e, 0x30, 0x57, 0x59, 0x71, 0x70, 0x7c, 0x7f, 0x70, 0x6b, 0x5f, 0x00, 0x01, 0x00, 0x8d, 0x00, 0x7f, 0x05, 0x4d, 0x05, 0x70, 0x00, 0x36, 0x00, 0x00, 0x01, 0x37, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3f, 0x01, 0x21, 0x35, 0x21, 0x17, 0x11, 0x23, 0x11, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x26, 0x04, 0x3c, 0x6c, 0x52, 0x29, 0x29, 0x29, 0x2b, 0x50, 0x50, 0x64, 0x62, 0x73, 0x77, 0x5d, 0x69, 0x4b, 0x50, 0x2b, 0x2a, 0x2a, 0x2a, 0x51, 0x1f, 0xfe, 0xd7, 0x01, 0xf5, 0x39, 0x99, 0x1f, 0x3c, 0x1e, 0x1e, 0x3b, 0x3c, 0x3a, 0x49, 0x47, 0xaa, 0x43, 0x4d, 0x36, 0x3c, 0x3b, 0x1d, 0x1d, 0x04, 0x2b, 0x78, 0x5f, 0x6b, 0x70, 0x7f, 0x7c, 0x70, 0x71, 0x59, 0x57, 0x30, 0x2e, 0x2e, 0x34, 0x53, 0x59, 0x71, 0x70, 0x7c, 0x7f, 0x70, 0x70, 0x5a, 0x23, 0xaa, 0x40, 0xfd, 0xd4, 0x01, 0x4a, 0x23, 0x42, 0x51, 0x51, 0x5d, 0x5a, 0xa2, 0x42, 0x3f, 0x23, 0x21, 0x21, 0x27, 0x3b, 0x42, 0xa2, 0x5a, 0x5d, 0x51, 0x51, 0x00, 0x01, 0x00, 0x5a, 0x02, 0x2d, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x06, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x15, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x04, 0x49, 0x02, 0x2d, 0x82, 0x01, 0x89, 0x78, 0xe9, 0xaa, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x02, 0xd7, 0x00, 0x06, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x17, 0x07, 0x01, 0x5a, 0x05, 0x45, 0xfb, 0xb7, 0xd2, 0x6c, 0xfe, 0x9e, 0x02, 0xd7, 0xaa, 0xe9, 0x78, 0x01, 0x89, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb7, 0x00, 0x00, 0x04, 0x8e, 0x05, 0xdc, 0x00, 0x06, 0x00, 0x00, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x23, 0x02, 0xb8, 0x75, 0x01, 0x61, 0x6c, 0xd1, 0x99, 0x05, 0xdc, 0xfe, 0x76, 0x78, 0xea, 0xfb, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x79, 0x00, 0x00, 0x03, 0x51, 0x05, 0xdc, 0x00, 0x06, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x07, 0x27, 0x01, 0x03, 0x51, 0x99, 0xd3, 0x6c, 0x01, 0x63, 0x05, 0xdc, 0xfa, 0x24, 0x04, 0xc4, 0xea, 0x78, 0x01, 0x8a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x2d, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x06, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x27, 0x37, 0x01, 0x05, 0xae, 0xfa, 0xbb, 0x04, 0x49, 0xd1, 0x6c, 0x01, 0x61, 0x02, 0x2d, 0xaa, 0xe9, 0x78, 0xfe, 0x77, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x02, 0xd7, 0x00, 0x06, 0x00, 0x00, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x35, 0x05, 0xae, 0xfe, 0x9f, 0x6c, 0xd1, 0xfb, 0xb7, 0x02, 0xd7, 0x82, 0xfe, 0x77, 0x78, 0xe9, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb7, 0x00, 0x00, 0x04, 0x8e, 0x05, 0xdc, 0x00, 0x06, 0x00, 0x00, 0x21, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x02, 0xb8, 0x99, 0xd1, 0x6c, 0xfe, 0x9f, 0x05, 0xdc, 0xfb, 0x3c, 0xea, 0x78, 0xfe, 0x76, 0x00, 0x01, 0x01, 0x79, 0x00, 0x00, 0x03, 0x51, 0x05, 0xdc, 0x00, 0x06, 0x00, 0x00, 0x21, 0x23, 0x01, 0x37, 0x17, 0x11, 0x33, 0x03, 0x51, 0x75, 0xfe, 0x9d, 0x6c, 0xd3, 0x99, 0x01, 0x8a, 0x78, 0xea, 0x04, 0xc4, 0x00, 0xff, 0xff, 0x00, 0x5a, 0xff, 0xa0, 0x05, 0xaf, 0x05, 0x64, 0x10, 0x27, 0x08, 0x6c, 0x00, 0x00, 0xfe, 0xd4, 0x10, 0x07, 0x08, 0x6e, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6b, 0xff, 0xf9, 0x05, 0x9c, 0x05, 0xdc, 0x10, 0x27, 0x08, 0x6f, 0x01, 0x0e, 0x00, 0x00, 0x10, 0x07, 0x08, 0x6d, 0xfe, 0xf2, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5a, 0xff, 0xa0, 0x05, 0xaf, 0x05, 0x64, 0x10, 0x27, 0x08, 0x6e, 0x00, 0x00, 0xfe, 0xd4, 0x10, 0x07, 0x08, 0x6c, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0xff, 0xa0, 0x05, 0xa0, 0x05, 0x64, 0x00, 0x11, 0x00, 0x00, 0x01, 0x03, 0x35, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x17, 0x07, 0x21, 0x15, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x40, 0xe6, 0x01, 0x62, 0x6c, 0xd2, 0x04, 0x49, 0xfb, 0xb7, 0xc2, 0xc2, 0x04, 0x49, 0xfb, 0xb7, 0xd2, 0x6c, 0xfe, 0x9e, 0x02, 0x82, 0x00, 0xff, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0xaa, 0xd7, 0xd7, 0xaa, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x00, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x05, 0x9d, 0x05, 0xdc, 0x00, 0x11, 0x00, 0x00, 0x01, 0x13, 0x33, 0x01, 0x07, 0x27, 0x11, 0x23, 0x11, 0x07, 0x27, 0x11, 0x23, 0x11, 0x07, 0x27, 0x01, 0x33, 0x03, 0x04, 0xe5, 0x51, 0x01, 0x62, 0x6c, 0xd2, 0x99, 0xc1, 0xc2, 0x99, 0xd1, 0x6c, 0x01, 0x61, 0x51, 0x04, 0xdc, 0x01, 0x00, 0xfe, 0x76, 0x78, 0xea, 0xfb, 0x3c, 0x04, 0xc4, 0xd8, 0xd8, 0xfb, 0x3c, 0x04, 0xc4, 0xea, 0x78, 0x01, 0x8a, 0x00, 0x00, 0x01, 0x00, 0x6a, 0xff, 0xa0, 0x05, 0xb0, 0x05, 0x64, 0x00, 0x11, 0x00, 0x00, 0x01, 0x17, 0x15, 0x01, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x01, 0x15, 0x04, 0xca, 0xe5, 0xfe, 0x9f, 0x6c, 0xd1, 0xfb, 0xb7, 0x04, 0x49, 0xc1, 0xc1, 0xfb, 0xb7, 0x04, 0x49, 0xd1, 0x6c, 0x01, 0x61, 0x02, 0x82, 0xff, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xaa, 0xd7, 0xd7, 0xaa, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6c, 0xff, 0xf9, 0x05, 0x9d, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x25, 0x03, 0x23, 0x01, 0x37, 0x17, 0x11, 0x33, 0x11, 0x37, 0x17, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x23, 0x03, 0x04, 0xe6, 0x51, 0xfe, 0x9f, 0x6c, 0xd1, 0x99, 0xc2, 0xc1, 0x99, 0xd2, 0x6c, 0xfe, 0x9e, 0x51, 0xf9, 0xff, 0x00, 0x01, 0x8a, 0x78, 0xea, 0x04, 0xc4, 0xfb, 0x3c, 0xd8, 0xd8, 0x04, 0xc4, 0xfb, 0x3c, 0xea, 0x78, 0xfe, 0x76, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5a, 0x00, 0x0e, 0x05, 0xaf, 0x04, 0xf6, 0x10, 0x27, 0x08, 0x9d, 0x00, 0x00, 0xff, 0x42, 0x10, 0x07, 0x08, 0x98, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5a, 0x00, 0x0e, 0x05, 0xaf, 0x04, 0xf6, 0x10, 0x27, 0x08, 0x99, 0x00, 0x00, 0xff, 0x42, 0x10, 0x07, 0x08, 0x9c, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x21, 0x07, 0x17, 0x21, 0x25, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x03, 0x92, 0xfd, 0xd6, 0x5e, 0x5e, 0x01, 0xbd, 0x01, 0x08, 0x6d, 0x01, 0xdf, 0xfd, 0xe3, 0x69, 0x75, 0x42, 0xfe, 0xee, 0x54, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x54, 0x01, 0xfc, 0x69, 0x75, 0x42, 0x01, 0x33, 0x02, 0xeb, 0x69, 0x69, 0xd2, 0xd2, 0x78, 0xca, 0x4b, 0x7f, 0x5d, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x5d, 0xca, 0x4b, 0x7f, 0x78, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x5a, 0x00, 0xc1, 0x05, 0xaf, 0x04, 0x43, 0x00, 0x17, 0x00, 0x1c, 0x00, 0x21, 0x00, 0x00, 0x25, 0x27, 0x37, 0x23, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x37, 0x17, 0x07, 0x33, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x13, 0x07, 0x21, 0x37, 0x27, 0x29, 0x01, 0x07, 0x17, 0x21, 0x02, 0xba, 0x7f, 0x37, 0x9e, 0x54, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x54, 0x01, 0x32, 0x49, 0x7f, 0x38, 0x9e, 0x53, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x53, 0xfe, 0xce, 0x6c, 0x44, 0x01, 0x76, 0x5f, 0x5f, 0xfe, 0x3e, 0xfe, 0x8a, 0x5e, 0x5e, 0x01, 0x32, 0xc1, 0x34, 0xac, 0x5d, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x5d, 0xe0, 0x34, 0xac, 0x5d, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x5d, 0x01, 0x4a, 0xd2, 0x69, 0x69, 0x69, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x21, 0x37, 0x27, 0x21, 0x05, 0x37, 0x21, 0x35, 0x21, 0x37, 0x17, 0x07, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x02, 0x77, 0x02, 0x29, 0x5f, 0x5f, 0xfe, 0x44, 0xfe, 0xf7, 0x6d, 0xfe, 0x21, 0x02, 0x1d, 0x6a, 0x74, 0x41, 0x01, 0x11, 0x53, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x53, 0xfe, 0x05, 0x69, 0x76, 0x42, 0xfe, 0xcd, 0x02, 0x19, 0x69, 0x69, 0xd2, 0xd2, 0x78, 0xca, 0x4b, 0x7f, 0x5d, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x5d, 0xca, 0x4b, 0x7f, 0x78, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x01, 0x68, 0x04, 0x37, 0xfc, 0x35, 0x54, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x54, 0x03, 0xcb, 0xfb, 0xc9, 0x5e, 0x02, 0x19, 0x78, 0x5d, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x5d, 0x78, 0x69, 0x00, 0x00, 0x00, 0x01, 0x01, 0x7a, 0x00, 0x00, 0x04, 0x90, 0x05, 0xdc, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x07, 0x27, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x23, 0x11, 0x27, 0x02, 0xa6, 0x6c, 0x53, 0x6c, 0x01, 0x61, 0x51, 0x01, 0x62, 0x6c, 0x54, 0x6c, 0x5e, 0x04, 0xb0, 0xfb, 0x50, 0x04, 0x38, 0x5e, 0x78, 0x01, 0x8a, 0xfe, 0x76, 0x78, 0x5e, 0xfb, 0xc8, 0x04, 0xb0, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x37, 0x27, 0x21, 0x35, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x35, 0x04, 0xa0, 0x5f, 0x5f, 0xfb, 0xc9, 0x03, 0xcb, 0x53, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x53, 0xfc, 0x35, 0x02, 0x19, 0x69, 0x69, 0x78, 0x5d, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x5d, 0x78, 0x00, 0x00, 0x00, 0x01, 0x01, 0x7a, 0xff, 0xf9, 0x04, 0x90, 0x05, 0xd5, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x17, 0x37, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x17, 0x11, 0x33, 0x02, 0xa6, 0x5f, 0x5e, 0x6c, 0x54, 0x6c, 0xfe, 0x9e, 0x51, 0xfe, 0x9f, 0x6c, 0x53, 0x6c, 0x01, 0x25, 0x68, 0x68, 0x04, 0xb0, 0xfb, 0xc8, 0x5e, 0x78, 0xfe, 0x76, 0x01, 0x8a, 0x78, 0x5e, 0x04, 0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x01, 0x21, 0x37, 0x27, 0x21, 0x07, 0x05, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x01, 0x68, 0x03, 0x38, 0x5f, 0x5f, 0xfc, 0xc8, 0x5e, 0x03, 0x2a, 0xfd, 0xa0, 0x54, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x54, 0x02, 0x60, 0x53, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x02, 0x19, 0x69, 0x69, 0x69, 0xe1, 0x5d, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x5d, 0x5d, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x00, 0x00, 0x02, 0x01, 0x7a, 0xff, 0xf0, 0x04, 0x8f, 0x05, 0xdc, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x01, 0x11, 0x17, 0x37, 0x11, 0x27, 0x03, 0x11, 0x07, 0x27, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x02, 0xa6, 0x5e, 0x5f, 0x5f, 0xca, 0x54, 0x6c, 0x01, 0x62, 0x51, 0x01, 0x61, 0x6c, 0x53, 0x53, 0x6c, 0xfe, 0x9f, 0x51, 0xfe, 0x9e, 0x6c, 0x04, 0xb0, 0xfc, 0x6c, 0x69, 0x69, 0x03, 0x94, 0x69, 0xfc, 0x7b, 0x02, 0xa4, 0x5d, 0x78, 0x01, 0x89, 0xfe, 0x77, 0x78, 0x5d, 0xfd, 0x5c, 0x5d, 0x78, 0xfe, 0x77, 0x01, 0x89, 0x78, 0x00, 0x00, 0x01, 0x01, 0x03, 0xff, 0xd1, 0x05, 0x6a, 0x04, 0xb3, 0x00, 0x0e, 0x00, 0x00, 0x09, 0x01, 0x07, 0x01, 0x15, 0x23, 0x11, 0x37, 0x21, 0x15, 0x23, 0x01, 0x07, 0x01, 0x23, 0x01, 0x9b, 0x02, 0xfb, 0x4c, 0xfd, 0x51, 0x98, 0x39, 0x01, 0xf4, 0x76, 0x02, 0xaf, 0x4c, 0xfd, 0x04, 0x86, 0x03, 0x76, 0xfc, 0xb0, 0x55, 0x02, 0xfb, 0x84, 0x02, 0x2c, 0x3f, 0xa9, 0xfd, 0x05, 0x55, 0x03, 0x50, 0x00, 0x01, 0x00, 0xa9, 0xff, 0xd1, 0x05, 0x10, 0x04, 0xb3, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x35, 0x23, 0x01, 0x27, 0x01, 0x23, 0x35, 0x21, 0x17, 0x11, 0x23, 0x35, 0x01, 0x27, 0x04, 0x77, 0x86, 0xfd, 0x05, 0x4d, 0x02, 0xaf, 0x76, 0x01, 0xf4, 0x39, 0x98, 0xfd, 0x51, 0x4c, 0x03, 0x76, 0x94, 0xfc, 0xb0, 0x55, 0x02, 0xfb, 0xa9, 0x3f, 0xfd, 0xd4, 0x84, 0xfd, 0x05, 0x55, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa9, 0x00, 0x34, 0x05, 0x10, 0x05, 0x16, 0x00, 0x0e, 0x00, 0x00, 0x09, 0x01, 0x37, 0x01, 0x35, 0x33, 0x11, 0x07, 0x21, 0x35, 0x33, 0x01, 0x37, 0x01, 0x33, 0x04, 0x77, 0xfd, 0x05, 0x4c, 0x02, 0xaf, 0x98, 0x39, 0xfe, 0x0c, 0x76, 0xfd, 0x51, 0x4d, 0x02, 0xfb, 0x86, 0x01, 0x71, 0x03, 0x50, 0x55, 0xfd, 0x05, 0x84, 0xfd, 0xd4, 0x3f, 0xa9, 0x02, 0xfb, 0x55, 0xfc, 0xb0, 0x00, 0x01, 0x01, 0x03, 0x00, 0x34, 0x05, 0x6a, 0x05, 0x16, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x15, 0x33, 0x01, 0x17, 0x01, 0x33, 0x15, 0x21, 0x27, 0x11, 0x33, 0x15, 0x01, 0x17, 0x01, 0x9b, 0x86, 0x02, 0xfc, 0x4c, 0xfd, 0x51, 0x76, 0xfe, 0x0c, 0x39, 0x98, 0x02, 0xaf, 0x4c, 0x01, 0x71, 0x94, 0x03, 0x50, 0x55, 0xfd, 0x05, 0xa9, 0x3f, 0x02, 0x2c, 0x84, 0x02, 0xfb, 0x55, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x17, 0x21, 0x15, 0x21, 0x07, 0x01, 0x35, 0x01, 0x17, 0x21, 0x15, 0x21, 0x01, 0x40, 0x04, 0x5f, 0xfb, 0xa1, 0x7c, 0x03, 0xe3, 0xfc, 0x89, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x03, 0x77, 0xfc, 0x1d, 0x02, 0xbe, 0x78, 0x8a, 0x78, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x78, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x27, 0x21, 0x35, 0x21, 0x37, 0x01, 0x15, 0x01, 0x27, 0x21, 0x35, 0x21, 0x04, 0xc9, 0xfb, 0xa0, 0x04, 0x60, 0x7c, 0xfc, 0x1c, 0x03, 0x78, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xfc, 0x88, 0x03, 0xe4, 0x02, 0x46, 0x78, 0x8a, 0x78, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x78, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x18, 0x00, 0x00, 0x01, 0x23, 0x27, 0x07, 0x27, 0x07, 0x27, 0x07, 0x27, 0x23, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x33, 0x17, 0x37, 0x17, 0x37, 0x17, 0x37, 0x17, 0x05, 0x9f, 0x24, 0x3f, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0x63, 0x59, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x7d, 0x3f, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0x63, 0x02, 0x2d, 0x46, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x6e, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x46, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x6e, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x18, 0x00, 0x00, 0x13, 0x35, 0x37, 0x17, 0x37, 0x17, 0x37, 0x17, 0x37, 0x33, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x23, 0x07, 0x27, 0x07, 0x27, 0x07, 0x27, 0x07, 0x69, 0x63, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0x3f, 0x7d, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0x59, 0x63, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0x3f, 0x02, 0x2d, 0xaa, 0x6e, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x46, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0x6e, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x46, 0x00, 0x00, 0x00, 0x01, 0x01, 0x79, 0x00, 0x00, 0x04, 0x8e, 0x05, 0xdc, 0x00, 0x19, 0x00, 0x00, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x07, 0x27, 0x02, 0xdc, 0x51, 0x01, 0x61, 0x6c, 0xd1, 0x01, 0x0a, 0xfe, 0xf6, 0x01, 0x0a, 0xfe, 0xf6, 0x99, 0xfe, 0xf7, 0x01, 0x09, 0xfe, 0xf7, 0x01, 0x09, 0xd3, 0x6c, 0x05, 0xdc, 0xfe, 0x76, 0x78, 0xea, 0xfe, 0x8e, 0xaa, 0xaa, 0xaa, 0xfe, 0xac, 0x01, 0x54, 0xaa, 0xaa, 0xaa, 0x01, 0x72, 0xea, 0x78, 0x00, 0x01, 0x01, 0x79, 0xff, 0xf9, 0x04, 0x8e, 0x05, 0xd5, 0x00, 0x19, 0x00, 0x00, 0x05, 0x23, 0x01, 0x37, 0x17, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x37, 0x17, 0x03, 0x2b, 0x51, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0xf6, 0x01, 0x0a, 0xfe, 0xf6, 0x01, 0x0a, 0x99, 0x01, 0x09, 0xfe, 0xf7, 0x01, 0x09, 0xfe, 0xf7, 0xd3, 0x6c, 0x07, 0x01, 0x8a, 0x78, 0xea, 0x01, 0x72, 0xaa, 0xaa, 0xaa, 0x01, 0x54, 0xfe, 0xac, 0xaa, 0xaa, 0xaa, 0xfe, 0x8e, 0xea, 0x78, 0x00, 0x00, 0x03, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x17, 0x07, 0x01, 0x35, 0x33, 0x15, 0x33, 0x35, 0x33, 0x15, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x01, 0x4c, 0xfe, 0xb4, 0xd2, 0x6c, 0x01, 0x7f, 0xe6, 0x99, 0xe5, 0x02, 0x55, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0xaa, 0xe9, 0x78, 0x01, 0x61, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x03, 0x01, 0x79, 0x00, 0x00, 0x04, 0x90, 0x05, 0xdc, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x00, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x23, 0x11, 0x07, 0x27, 0x01, 0x33, 0x15, 0x23, 0x15, 0x33, 0x11, 0x23, 0x02, 0xdc, 0x51, 0x01, 0x62, 0x6c, 0xd2, 0x99, 0xd3, 0x6c, 0x01, 0x3f, 0x99, 0x99, 0x99, 0x99, 0x05, 0xdc, 0xfe, 0x76, 0x78, 0xea, 0xfe, 0x8e, 0x01, 0x72, 0xea, 0x78, 0xfe, 0x56, 0xfe, 0xaa, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x00, 0x09, 0x01, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x01, 0x25, 0x33, 0x15, 0x23, 0x27, 0x15, 0x23, 0x35, 0x05, 0xae, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0xb4, 0x01, 0x4c, 0xd1, 0x6c, 0x01, 0x61, 0xfc, 0x3a, 0xe5, 0xe5, 0x99, 0xe6, 0x02, 0x55, 0xfe, 0x77, 0x78, 0xe9, 0xaa, 0xe9, 0x78, 0xfe, 0x77, 0x28, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x03, 0x01, 0x79, 0xff, 0xf9, 0x04, 0x90, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x00, 0x05, 0x01, 0x37, 0x17, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x03, 0x35, 0x33, 0x15, 0x03, 0x11, 0x33, 0x11, 0x02, 0xdc, 0xfe, 0x9d, 0x6c, 0xd3, 0x99, 0xd2, 0x6c, 0xfe, 0x9e, 0x75, 0x99, 0x99, 0x99, 0x07, 0x01, 0x8a, 0x78, 0xea, 0x01, 0x72, 0xfe, 0x8e, 0xea, 0x78, 0xfe, 0x76, 0x03, 0x34, 0xfe, 0xfe, 0x01, 0xa8, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60, 0x00, 0xcb, 0x05, 0xa0, 0x04, 0x39, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x15, 0x21, 0x17, 0x07, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x17, 0x07, 0x05, 0x9f, 0xfc, 0x56, 0xd3, 0x6c, 0xfe, 0x9d, 0x99, 0x99, 0x01, 0x63, 0x6c, 0xd3, 0x02, 0xd7, 0xaa, 0xea, 0x78, 0x01, 0x8a, 0xfe, 0x7e, 0x03, 0x5c, 0xfe, 0x80, 0x01, 0x8a, 0x78, 0xea, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcb, 0x05, 0xa9, 0x04, 0x39, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x21, 0x27, 0x37, 0x01, 0x11, 0x33, 0x11, 0x23, 0x11, 0x01, 0x27, 0x37, 0x21, 0x69, 0x03, 0xaa, 0xd3, 0x6c, 0x01, 0x63, 0x99, 0x99, 0xfe, 0x9d, 0x6c, 0xd3, 0xfc, 0x56, 0x02, 0xd7, 0xea, 0x78, 0xfe, 0x76, 0x01, 0x80, 0xfc, 0xa4, 0x01, 0x82, 0xfe, 0x76, 0x78, 0xea, 0x00, 0x00, 0x02, 0x00, 0x31, 0x00, 0x86, 0x05, 0xa0, 0x04, 0x7e, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x03, 0x13, 0x35, 0x21, 0x11, 0x21, 0x13, 0x09, 0x01, 0x11, 0x21, 0x11, 0x21, 0x01, 0xa1, 0xf0, 0xf0, 0x03, 0xa4, 0xfc, 0x5c, 0x5a, 0xfe, 0x37, 0x01, 0xc9, 0x03, 0xa4, 0xfc, 0x5c, 0x03, 0x8c, 0xfe, 0xf6, 0xfe, 0xf6, 0x83, 0x01, 0x0e, 0xfd, 0x7d, 0x01, 0xfc, 0x01, 0xfc, 0xfe, 0xef, 0xfe, 0x2a, 0x00, 0x00, 0x00, 0x02, 0x01, 0x3b, 0x00, 0x00, 0x04, 0xce, 0x06, 0x08, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x0b, 0x01, 0x33, 0x11, 0x33, 0x11, 0x05, 0x09, 0x01, 0x23, 0x11, 0x21, 0x11, 0x03, 0xf4, 0xf0, 0xef, 0x76, 0xf3, 0xfd, 0xbd, 0x01, 0xc9, 0x01, 0xc9, 0xf5, 0xfe, 0x59, 0x04, 0x70, 0x01, 0x0a, 0xfe, 0xf6, 0xfb, 0xf4, 0x04, 0x0c, 0x64, 0x01, 0xfc, 0xfe, 0x04, 0xfb, 0xf4, 0x04, 0x0c, 0x00, 0x02, 0x00, 0x40, 0x00, 0x86, 0x05, 0xaf, 0x04, 0x7e, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x15, 0x21, 0x11, 0x21, 0x15, 0x13, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x04, 0x3f, 0xfc, 0x5c, 0x03, 0xa4, 0xf0, 0xfe, 0xb6, 0xfc, 0x5c, 0x03, 0xa4, 0x01, 0xc9, 0x03, 0x8c, 0x83, 0xfe, 0xf2, 0x83, 0x01, 0x0a, 0xfe, 0x04, 0x01, 0x11, 0x01, 0xd6, 0x01, 0x11, 0xfe, 0x04, 0x00, 0x00, 0x02, 0x01, 0x3b, 0xff, 0xcd, 0x04, 0xce, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x13, 0x01, 0x33, 0x11, 0x21, 0x11, 0x33, 0x01, 0x03, 0xf4, 0x76, 0xf3, 0x76, 0xef, 0xfe, 0x37, 0xf6, 0x01, 0xa7, 0xf5, 0xfe, 0x37, 0x01, 0x65, 0x04, 0x0c, 0xfb, 0xf4, 0xfe, 0xf6, 0x01, 0x6e, 0x04, 0x0c, 0xfb, 0xf4, 0xfe, 0x04, 0x00, 0x04, 0x01, 0x3b, 0x00, 0x00, 0x04, 0xce, 0x06, 0x08, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x01, 0x21, 0x11, 0x23, 0x09, 0x01, 0x23, 0x03, 0x11, 0x33, 0x0b, 0x01, 0x33, 0x11, 0x01, 0x11, 0x21, 0x11, 0x05, 0x23, 0x15, 0x33, 0x03, 0xd8, 0xfe, 0x59, 0xf6, 0x01, 0xc9, 0x01, 0xc9, 0xf5, 0x5a, 0x76, 0xf0, 0xef, 0x76, 0x01, 0x4d, 0xfe, 0x59, 0x01, 0x4d, 0xf3, 0xf3, 0x02, 0x24, 0x01, 0xe8, 0x01, 0xfc, 0xfe, 0x04, 0xfe, 0x7c, 0x01, 0xe8, 0x01, 0x0a, 0xfe, 0xf6, 0xfe, 0x18, 0xfe, 0xd4, 0xfe, 0xa4, 0x01, 0x5c, 0x64, 0x94, 0x00, 0x00, 0x02, 0x01, 0x3b, 0x00, 0x00, 0x04, 0xce, 0x06, 0x08, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x23, 0x09, 0x01, 0x23, 0x11, 0x33, 0x05, 0x23, 0x15, 0x21, 0x35, 0x23, 0x11, 0x33, 0x0b, 0x01, 0x33, 0x04, 0x8c, 0xfc, 0xf1, 0xb4, 0xf6, 0x01, 0xc9, 0x01, 0xc9, 0xf5, 0xb4, 0xfd, 0xff, 0xb4, 0x02, 0x5b, 0xb4, 0x76, 0xf0, 0xef, 0x76, 0x01, 0x5c, 0x02, 0xb0, 0x01, 0xfc, 0xfe, 0x04, 0xfd, 0x50, 0x64, 0x94, 0x94, 0x03, 0x78, 0x01, 0x0a, 0xfe, 0xf6, 0x00, 0x00, 0x03, 0x01, 0x20, 0x00, 0x00, 0x04, 0xe9, 0x06, 0x08, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x19, 0x00, 0x00, 0x25, 0x23, 0x15, 0x21, 0x35, 0x23, 0x11, 0x33, 0x27, 0x21, 0x07, 0x33, 0x01, 0x21, 0x11, 0x33, 0x11, 0x21, 0x09, 0x01, 0x21, 0x11, 0x33, 0x01, 0x33, 0x27, 0x02, 0x8b, 0xb4, 0x02, 0x5b, 0xb4, 0x91, 0x5a, 0xfe, 0x9f, 0x5a, 0x91, 0x02, 0x01, 0xfc, 0xf1, 0xb4, 0xfe, 0xef, 0x01, 0xe4, 0x01, 0xe4, 0xfe, 0xf0, 0xb4, 0xfe, 0x10, 0xd1, 0x69, 0xf8, 0x94, 0x94, 0x03, 0x5a, 0x64, 0x64, 0xfb, 0xae, 0x01, 0x5c, 0x02, 0x92, 0x02, 0x1a, 0xfd, 0xe6, 0xfd, 0x6e, 0x03, 0xaa, 0x74, 0x00, 0x03, 0x01, 0x3b, 0x00, 0x00, 0x04, 0xce, 0x06, 0x08, 0x00, 0x06, 0x00, 0x11, 0x00, 0x18, 0x00, 0x00, 0x25, 0x23, 0x15, 0x21, 0x11, 0x07, 0x33, 0x01, 0x21, 0x11, 0x33, 0x11, 0x23, 0x09, 0x01, 0x23, 0x11, 0x33, 0x01, 0x11, 0x21, 0x35, 0x23, 0x11, 0x33, 0x02, 0x7d, 0xa6, 0x01, 0x00, 0xc2, 0x68, 0x02, 0x0f, 0xfc, 0xf1, 0xa6, 0xe8, 0x01, 0xc9, 0x01, 0xc9, 0xe8, 0xa7, 0xfe, 0xa5, 0x01, 0x01, 0xa7, 0x69, 0xf8, 0x94, 0x04, 0xe4, 0xd8, 0xfb, 0x90, 0x01, 0x5c, 0x02, 0xb0, 0x01, 0xfc, 0xfe, 0x04, 0xfd, 0x50, 0x03, 0xec, 0xfb, 0x1c, 0x94, 0x03, 0x78, 0x00, 0x03, 0x01, 0x3b, 0x00, 0x00, 0x04, 0xce, 0x06, 0x08, 0x00, 0x06, 0x00, 0x11, 0x00, 0x17, 0x00, 0x00, 0x25, 0x11, 0x33, 0x0b, 0x01, 0x33, 0x11, 0x05, 0x21, 0x11, 0x23, 0x13, 0x23, 0x09, 0x01, 0x23, 0x13, 0x23, 0x03, 0x33, 0x0b, 0x01, 0x33, 0x37, 0x03, 0x7e, 0x76, 0xf0, 0xef, 0x76, 0x01, 0x4d, 0xfe, 0x59, 0xf6, 0xfc, 0xfc, 0x01, 0xc9, 0x01, 0xc9, 0xfc, 0xfc, 0xf5, 0x61, 0x7d, 0xf0, 0xef, 0x7c, 0x73, 0x64, 0x02, 0xf4, 0x01, 0x0a, 0xfe, 0xf6, 0xfd, 0x0c, 0x64, 0x02, 0xf4, 0x01, 0x18, 0x01, 0xfc, 0xfe, 0x04, 0xfe, 0xe8, 0x01, 0x7c, 0x01, 0x0a, 0xfe, 0xf6, 0x80, 0x00, 0x00, 0x03, 0x01, 0x3b, 0x00, 0x00, 0x04, 0xce, 0x06, 0x08, 0x00, 0x0a, 0x00, 0x19, 0x00, 0x1f, 0x00, 0x00, 0x25, 0x23, 0x15, 0x21, 0x35, 0x23, 0x11, 0x33, 0x0b, 0x01, 0x33, 0x01, 0x21, 0x11, 0x33, 0x11, 0x23, 0x13, 0x23, 0x09, 0x01, 0x23, 0x13, 0x23, 0x11, 0x33, 0x01, 0x33, 0x0b, 0x01, 0x33, 0x37, 0x02, 0x8b, 0xb4, 0x02, 0x5b, 0xb4, 0x76, 0xf0, 0xef, 0x76, 0x02, 0x01, 0xfc, 0xf1, 0xb4, 0xf6, 0xfc, 0xfc, 0x01, 0xc9, 0x01, 0xc9, 0xfc, 0xfc, 0xf5, 0xb4, 0xfe, 0xeb, 0x7d, 0xf0, 0xef, 0x7c, 0x73, 0xf8, 0x94, 0x94, 0x02, 0x60, 0x01, 0x0a, 0xfe, 0xf6, 0xfc, 0xa8, 0x01, 0x5c, 0x01, 0x98, 0x01, 0x18, 0x01, 0xfc, 0xfe, 0x04, 0xfe, 0xe8, 0xfe, 0x68, 0x03, 0x14, 0x01, 0x0a, 0xfe, 0xf6, 0x80, 0x00, 0x00, 0x02, 0x00, 0x69, 0x00, 0x86, 0x05, 0xd7, 0x04, 0x7e, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x00, 0x37, 0x11, 0x21, 0x15, 0x21, 0x11, 0x09, 0x01, 0x11, 0x21, 0x15, 0x03, 0x35, 0x23, 0x11, 0x33, 0x35, 0x21, 0x15, 0x13, 0x03, 0x15, 0x69, 0x01, 0x39, 0x02, 0x6c, 0x01, 0xc9, 0xfe, 0x37, 0xfd, 0x94, 0x5a, 0x85, 0x85, 0x03, 0x20, 0xef, 0xef, 0xcf, 0x03, 0x66, 0xc8, 0x01, 0x11, 0xfe, 0x04, 0xfe, 0x04, 0x01, 0x11, 0xc8, 0x02, 0x3a, 0xc8, 0xfd, 0x62, 0xc8, 0x83, 0x01, 0x0a, 0x01, 0x0a, 0x83, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6d, 0x00, 0x00, 0x05, 0xac, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x15, 0x21, 0x11, 0x23, 0x11, 0x01, 0x37, 0x21, 0x15, 0x21, 0x01, 0x07, 0x01, 0x11, 0x23, 0x05, 0xac, 0xfb, 0x1b, 0x59, 0x01, 0x05, 0x39, 0x01, 0xf4, 0xfe, 0xd7, 0x03, 0x08, 0x6c, 0xfc, 0xf8, 0x98, 0x05, 0xd5, 0x63, 0xfa, 0x8e, 0x05, 0xd5, 0xfe, 0x9f, 0x3f, 0xa9, 0xfc, 0xa2, 0x78, 0x03, 0x5e, 0xfe, 0xb6, 0x00, 0x02, 0x00, 0x6d, 0x00, 0x00, 0x05, 0xac, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x00, 0x33, 0x35, 0x21, 0x11, 0x33, 0x11, 0x01, 0x07, 0x21, 0x35, 0x21, 0x01, 0x37, 0x01, 0x11, 0x33, 0x6e, 0x04, 0xe5, 0x59, 0xfe, 0xfb, 0x39, 0xfe, 0x0c, 0x01, 0x29, 0xfc, 0xf8, 0x6c, 0x03, 0x08, 0x98, 0x63, 0x05, 0x72, 0xfa, 0x2b, 0x01, 0x61, 0x3f, 0xa9, 0x03, 0x5e, 0x78, 0xfc, 0xa2, 0x01, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x3b, 0xff, 0xcd, 0x04, 0xce, 0x06, 0x08, 0x00, 0x09, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x33, 0x0b, 0x01, 0x33, 0x11, 0x23, 0x1b, 0x01, 0x27, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x09, 0x01, 0x23, 0x03, 0x7e, 0x76, 0xf0, 0xef, 0x76, 0x76, 0xef, 0xf0, 0x1c, 0xf5, 0xfe, 0x37, 0xfe, 0x37, 0xf6, 0xf6, 0x01, 0xc9, 0x01, 0xc9, 0xf5, 0x01, 0x65, 0x03, 0x0b, 0x01, 0x0a, 0xfe, 0xf6, 0xfc, 0xf5, 0xfe, 0xf6, 0x01, 0x0a, 0x64, 0xfe, 0x04, 0x01, 0xfc, 0x02, 0x43, 0x01, 0xfc, 0xfe, 0x04, 0x00, 0x00, 0x03, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x29, 0x00, 0x35, 0x00, 0x41, 0x00, 0x00, 0x09, 0x01, 0x27, 0x37, 0x21, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x23, 0x35, 0x33, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x21, 0x27, 0x37, 0x01, 0x24, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x26, 0x27, 0x26, 0x27, 0x13, 0x21, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x36, 0x05, 0xae, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0xc4, 0x05, 0x09, 0x18, 0x2d, 0x2c, 0x3a, 0x37, 0x84, 0x34, 0x3d, 0x29, 0x2d, 0x18, 0x09, 0x06, 0xab, 0xab, 0x06, 0x09, 0x18, 0x2d, 0x2c, 0x3a, 0x37, 0x84, 0x34, 0x3c, 0x2a, 0x2d, 0x18, 0x09, 0x05, 0x01, 0x3c, 0xd1, 0x6c, 0x01, 0x61, 0xfc, 0xbc, 0x4a, 0x1f, 0x25, 0x16, 0x17, 0x0d, 0x01, 0x47, 0x0f, 0x16, 0x1a, 0x20, 0x5d, 0xfe, 0xbc, 0x0d, 0x16, 0x1b, 0x20, 0x1f, 0x4a, 0x20, 0x20, 0x1a, 0x17, 0x02, 0x55, 0xfe, 0x77, 0x78, 0xe9, 0x18, 0x18, 0x40, 0x32, 0x31, 0x1b, 0x1a, 0x1a, 0x1e, 0x2e, 0x32, 0x40, 0x18, 0x18, 0xaa, 0x1a, 0x19, 0x40, 0x32, 0x31, 0x1b, 0x1a, 0x1a, 0x1e, 0x2e, 0x32, 0x40, 0x19, 0x1a, 0xe9, 0x78, 0xfe, 0x77, 0x9d, 0x0f, 0x12, 0x1a, 0x1c, 0x1e, 0x23, 0x17, 0x1c, 0x10, 0xfe, 0xf0, 0x1d, 0x1a, 0x1c, 0x10, 0x0f, 0x0f, 0x10, 0x1c, 0x1a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6b, 0xff, 0xf9, 0x05, 0x9c, 0x05, 0xdc, 0x10, 0x27, 0x08, 0x6d, 0x01, 0x0e, 0x00, 0x00, 0x10, 0x07, 0x08, 0x6f, 0xfe, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x74, 0x05, 0xaf, 0x06, 0x90, 0x00, 0x19, 0x00, 0x00, 0x01, 0x07, 0x17, 0x15, 0x01, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x01, 0x15, 0x07, 0x17, 0x05, 0xae, 0xe5, 0xe5, 0xfe, 0x9f, 0x6c, 0xd1, 0xfb, 0xb7, 0x04, 0x49, 0xc1, 0xc1, 0xfb, 0xb7, 0x04, 0x49, 0xc1, 0xc1, 0xfb, 0xb7, 0x04, 0x49, 0xd1, 0x6c, 0x01, 0x61, 0xe5, 0xe5, 0x02, 0x55, 0xff, 0xff, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xaa, 0xd7, 0xd7, 0xaa, 0xd7, 0xd7, 0xaa, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xc0, 0x05, 0xa0, 0x04, 0x44, 0x00, 0x11, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x17, 0x07, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x01, 0xfb, 0x99, 0x01, 0xb5, 0xfe, 0x4b, 0x99, 0xfe, 0x05, 0xd2, 0x6c, 0x02, 0x55, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x01, 0x6d, 0xfe, 0x93, 0xaa, 0xfe, 0x93, 0x01, 0x6d, 0xe9, 0x78, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xc0, 0x05, 0xaf, 0x04, 0x44, 0x00, 0x11, 0x00, 0x00, 0x09, 0x01, 0x27, 0x37, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x27, 0x37, 0x01, 0x05, 0xae, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0x06, 0x99, 0xfe, 0x4a, 0x01, 0xb6, 0x99, 0x01, 0xfa, 0xd1, 0x6c, 0x01, 0x61, 0x02, 0x55, 0xfe, 0x77, 0x78, 0xe9, 0xfe, 0x93, 0x01, 0x6d, 0xaa, 0x01, 0x6d, 0xfe, 0x93, 0xe9, 0x78, 0xfe, 0x77, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xc0, 0x05, 0xaf, 0x04, 0x44, 0x00, 0x17, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x11, 0x23, 0x11, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x02, 0xb8, 0x99, 0x01, 0x61, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0x9f, 0x99, 0xfe, 0x9e, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x02, 0xd7, 0x01, 0x6d, 0xfe, 0x93, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xfe, 0x93, 0x01, 0x6d, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xc0, 0x05, 0xa0, 0x04, 0x44, 0x00, 0x19, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x17, 0x07, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x01, 0x7d, 0x99, 0x99, 0x99, 0x01, 0x01, 0xfe, 0xff, 0x99, 0x99, 0x99, 0xfe, 0x83, 0xd2, 0x6c, 0x02, 0x55, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x01, 0x6d, 0xfe, 0x93, 0x01, 0x6d, 0xfe, 0x93, 0xaa, 0xfe, 0x93, 0x01, 0x6d, 0xfe, 0x93, 0x01, 0x6d, 0xe9, 0x78, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xc0, 0x05, 0xaf, 0x04, 0x44, 0x00, 0x19, 0x00, 0x00, 0x09, 0x01, 0x27, 0x37, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x27, 0x37, 0x01, 0x05, 0xae, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0x84, 0x99, 0x99, 0x99, 0xfe, 0xfe, 0x01, 0x02, 0x99, 0x99, 0x99, 0x01, 0x7c, 0xd1, 0x6c, 0x01, 0x61, 0x02, 0x55, 0xfe, 0x77, 0x78, 0xe9, 0xfe, 0x93, 0x01, 0x6d, 0xfe, 0x93, 0x01, 0x6d, 0xaa, 0x01, 0x6d, 0xfe, 0x93, 0x01, 0x6d, 0xfe, 0x93, 0xe9, 0x78, 0xfe, 0x77, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xc0, 0x05, 0xaf, 0x04, 0x44, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x02, 0x59, 0x7e, 0x5a, 0x7e, 0x01, 0x03, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0xfd, 0x7e, 0x5a, 0x7e, 0xfe, 0xfd, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x02, 0xd7, 0x01, 0x6d, 0xfe, 0x93, 0x01, 0x6d, 0xfe, 0x93, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xfe, 0x93, 0x01, 0x6d, 0xfe, 0x93, 0x01, 0x6d, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x00, 0x02, 0x00, 0x31, 0x00, 0xc4, 0x05, 0xa0, 0x04, 0x40, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x07, 0x05, 0x11, 0x09, 0x01, 0x11, 0x21, 0x15, 0x01, 0x7b, 0xe1, 0x01, 0x29, 0xfe, 0x6f, 0x01, 0x91, 0x03, 0xdc, 0x01, 0x88, 0x01, 0xf4, 0xfa, 0x41, 0xfe, 0x83, 0x01, 0xbe, 0x01, 0xbe, 0xfe, 0x83, 0x82, 0x00, 0x02, 0x00, 0x69, 0x00, 0xc4, 0x05, 0xd7, 0x04, 0x40, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x01, 0x37, 0x27, 0x03, 0x21, 0x35, 0x21, 0x11, 0x09, 0x01, 0x04, 0x8e, 0xe0, 0xe0, 0x48, 0xfc, 0x23, 0x03, 0xdd, 0x01, 0x91, 0xfe, 0x6f, 0x01, 0x88, 0xfa, 0xfa, 0xfe, 0xc5, 0x82, 0x01, 0x7d, 0xfe, 0x42, 0xfe, 0x42, 0x00, 0x03, 0x00, 0x31, 0x00, 0xc4, 0x05, 0xd7, 0x04, 0x40, 0x00, 0x02, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x37, 0x27, 0x01, 0x11, 0x07, 0x05, 0x21, 0x11, 0x09, 0x01, 0x11, 0x21, 0x11, 0x09, 0x01, 0x04, 0x8e, 0xe0, 0xe0, 0xfc, 0xed, 0xe1, 0x03, 0xac, 0xfd, 0x7d, 0xfe, 0x6f, 0x01, 0x91, 0x02, 0x83, 0x01, 0x91, 0xfe, 0x6f, 0x01, 0x88, 0xfa, 0xfa, 0xfe, 0x0c, 0x01, 0xf4, 0xfa, 0x41, 0xfe, 0x83, 0x01, 0xbe, 0x01, 0xbe, 0xfe, 0x83, 0x01, 0x7d, 0xfe, 0x42, 0xfe, 0x42, 0x00, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x25, 0x13, 0x21, 0x13, 0x01, 0x33, 0x13, 0x21, 0x13, 0x33, 0x01, 0x02, 0x76, 0xf8, 0xfe, 0x11, 0x90, 0xfd, 0xff, 0xc0, 0x7a, 0x02, 0x5e, 0x7b, 0xbd, 0xfe, 0x00, 0xc7, 0x02, 0xe7, 0xfc, 0x52, 0x05, 0xd5, 0xfe, 0x81, 0x01, 0x7f, 0xfa, 0x2b, 0x00, 0x01, 0x00, 0x79, 0xff, 0xe3, 0x03, 0xfd, 0x05, 0xf0, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x10, 0x12, 0x33, 0x32, 0x17, 0x16, 0x17, 0x23, 0x26, 0x27, 0x26, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x23, 0x22, 0x02, 0x7a, 0xee, 0xe2, 0xe2, 0x78, 0x3b, 0x1e, 0xb6, 0x10, 0x19, 0x47, 0x8d, 0x8c, 0x8e, 0x8e, 0x8c, 0x8d, 0x47, 0x19, 0x10, 0xb6, 0x1e, 0x3b, 0x78, 0xe2, 0xe2, 0xee, 0x02, 0xe9, 0x01, 0x7a, 0x01, 0x8d, 0xc6, 0x63, 0x90, 0x49, 0x37, 0x99, 0xfe, 0xcd, 0xfe, 0xcc, 0xfe, 0xcc, 0xfe, 0xcd, 0x99, 0x37, 0x49, 0x90, 0x63, 0xc5, 0x01, 0x8c, 0x00, 0x00, 0x02, 0x00, 0x55, 0xff, 0xe3, 0x03, 0x64, 0x05, 0x4c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00, 0x05, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x35, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x02, 0x07, 0x06, 0x01, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x23, 0x22, 0x07, 0x06, 0x01, 0x89, 0x7f, 0x52, 0x62, 0x56, 0x59, 0xa0, 0x69, 0x53, 0x31, 0x21, 0x0c, 0x1d, 0x40, 0xa9, 0x40, 0x63, 0x68, 0x5e, 0xf1, 0x67, 0x30, 0x17, 0x39, 0x92, 0x74, 0xfe, 0xe1, 0x28, 0x2a, 0x41, 0x3a, 0x2e, 0x40, 0x30, 0x28, 0x14, 0x51, 0x8a, 0x77, 0x34, 0x21, 0x1d, 0x55, 0x65, 0xb7, 0xbe, 0x94, 0x98, 0x49, 0x2b, 0x48, 0x51, 0x5c, 0x87, 0x4e, 0xad, 0x2c, 0xa8, 0x1f, 0xf6, 0x74, 0xad, 0x71, 0x83, 0xfe, 0xb8, 0x9c, 0x7a, 0x01, 0x53, 0x64, 0x36, 0x39, 0x2d, 0x3e, 0x65, 0x53, 0x59, 0xd7, 0xae, 0x6c, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x04, 0x17, 0xfc, 0x9e, 0x02, 0xac, 0xfd, 0x54, 0x02, 0xac, 0xfd, 0x54, 0x05, 0xd5, 0xfa, 0x2b, 0xaa, 0x01, 0xec, 0xaa, 0x01, 0xeb, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0xff, 0xa2, 0x04, 0x17, 0x06, 0x35, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x07, 0x23, 0x37, 0x23, 0x35, 0x33, 0x13, 0x21, 0x35, 0x21, 0x13, 0x21, 0x35, 0x21, 0x37, 0x33, 0x0f, 0x01, 0x03, 0x33, 0x11, 0x01, 0x03, 0x21, 0x11, 0x04, 0x17, 0xfd, 0x90, 0x1a, 0x99, 0x1a, 0x59, 0x89, 0x88, 0xfe, 0xef, 0x01, 0x40, 0x89, 0xfe, 0x37, 0x01, 0xf8, 0x1b, 0x99, 0x1b, 0x2f, 0x89, 0xd3, 0xfe, 0xff, 0x89, 0x01, 0x8a, 0x05, 0xd5, 0xfa, 0x2b, 0x5e, 0x5e, 0xaa, 0x01, 0xec, 0xaa, 0x01, 0xeb, 0xaa, 0x60, 0x60, 0xaa, 0xfe, 0x15, 0x01, 0xeb, 0xfd, 0x6b, 0xfe, 0x14, 0x01, 0xec, 0x00, 0x00, 0x00, 0x03, 0x00, 0x8b, 0xff, 0xec, 0x05, 0xbb, 0x05, 0xae, 0x00, 0x1b, 0x00, 0x28, 0x00, 0x36, 0x00, 0x00, 0x01, 0x37, 0x33, 0x07, 0x16, 0x17, 0x16, 0x10, 0x02, 0x04, 0x23, 0x22, 0x27, 0x26, 0x27, 0x07, 0x23, 0x37, 0x26, 0x27, 0x26, 0x10, 0x12, 0x24, 0x33, 0x32, 0x17, 0x16, 0x09, 0x01, 0x27, 0x26, 0x23, 0x22, 0x04, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x09, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x24, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x04, 0x87, 0x50, 0x60, 0x73, 0x5e, 0x3e, 0x5a, 0xb4, 0xfe, 0xc3, 0xa6, 0xa9, 0x9e, 0x32, 0x2c, 0x71, 0x5e, 0x99, 0x39, 0x2a, 0x59, 0xb2, 0x01, 0x3c, 0xa9, 0xa6, 0x9f, 0x10, 0xfd, 0x1b, 0x02, 0xa9, 0x0d, 0x83, 0x89, 0x8b, 0xfe, 0xfa, 0x4a, 0x48, 0x01, 0x01, 0x48, 0x21, 0x03, 0x10, 0xfd, 0x51, 0x23, 0x29, 0x82, 0x8b, 0x89, 0x01, 0x06, 0x4a, 0x4a, 0x01, 0x01, 0x4a, 0x34, 0x05, 0x3b, 0x6e, 0x9d, 0x53, 0x7a, 0xb2, 0xfe, 0x80, 0xfe, 0x9d, 0xbe, 0x5f, 0x1e, 0x27, 0x9c, 0xd2, 0x42, 0x54, 0xb1, 0x01, 0x80, 0x01, 0x63, 0xbe, 0x5f, 0x0a, 0xfb, 0xe9, 0x03, 0xa5, 0x08, 0x4e, 0x9d, 0x93, 0x91, 0x9b, 0x9b, 0x91, 0x40, 0x03, 0x44, 0xfc, 0x52, 0x1f, 0x18, 0x4f, 0x9d, 0x93, 0x91, 0x9b, 0x9b, 0x91, 0x67, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xfa, 0x00, 0x00, 0x04, 0xd7, 0x05, 0xc1, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x21, 0x01, 0x33, 0x01, 0x21, 0x02, 0x68, 0xfe, 0x87, 0x02, 0xf1, 0xfe, 0x24, 0xc9, 0x02, 0x09, 0xfb, 0x25, 0x04, 0xee, 0xfb, 0xc4, 0x05, 0x0f, 0xfa, 0x3f, 0x00, 0x02, 0xff, 0xfa, 0x00, 0x00, 0x04, 0xd7, 0x05, 0xc1, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x25, 0x01, 0x21, 0x09, 0x01, 0x21, 0x01, 0x02, 0x68, 0x01, 0x78, 0xfd, 0x0f, 0x01, 0x15, 0xfd, 0xf7, 0x04, 0xdb, 0xfd, 0xf7, 0xd3, 0x04, 0x3c, 0xfa, 0xf1, 0x05, 0xc1, 0xfa, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0xff, 0xec, 0x05, 0xa9, 0x05, 0xae, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x21, 0x15, 0x21, 0x22, 0x24, 0x02, 0x35, 0x34, 0x12, 0x24, 0x33, 0x21, 0x15, 0x21, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x15, 0x01, 0x35, 0x06, 0x39, 0x43, 0x7d, 0x7c, 0x85, 0x02, 0x73, 0xfd, 0x8d, 0xad, 0xfe, 0xc0, 0xaa, 0xaa, 0x01, 0x40, 0xad, 0x02, 0x73, 0xfd, 0x8d, 0x85, 0x7c, 0x7d, 0x43, 0x3a, 0x08, 0x04, 0x76, 0x02, 0x73, 0x4a, 0x78, 0x8b, 0x4e, 0x4c, 0x01, 0x9f, 0xc6, 0x01, 0x60, 0xbb, 0xb9, 0x01, 0x60, 0xc8, 0x9f, 0x01, 0x4d, 0x4f, 0x8a, 0x78, 0x5d, 0xa0, 0x00, 0x03, 0x00, 0x9d, 0xfe, 0xe5, 0x05, 0xa9, 0x06, 0xaf, 0x00, 0x1e, 0x00, 0x26, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x03, 0x21, 0x15, 0x21, 0x03, 0x16, 0x33, 0x21, 0x15, 0x21, 0x22, 0x27, 0x03, 0x27, 0x13, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x24, 0x3b, 0x01, 0x01, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x13, 0x37, 0x13, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x04, 0x5c, 0x87, 0x42, 0x01, 0x07, 0xfe, 0xc5, 0xa6, 0x01, 0xe1, 0xfd, 0xea, 0x9e, 0x20, 0x21, 0x02, 0x73, 0xfd, 0x8d, 0x3b, 0x38, 0x5a, 0x87, 0x56, 0x28, 0x27, 0xa0, 0xaa, 0xaa, 0x01, 0x40, 0xad, 0xd2, 0xfd, 0x2e, 0x3f, 0x4c, 0x74, 0x1a, 0x1a, 0x90, 0x36, 0xa5, 0x9e, 0x85, 0x7c, 0x70, 0x50, 0x42, 0x06, 0xaf, 0x37, 0xca, 0x9f, 0xfe, 0x04, 0xa0, 0xfe, 0x1d, 0x05, 0x9f, 0x0b, 0xfe, 0xee, 0x37, 0x01, 0x08, 0x13, 0x18, 0x63, 0x01, 0x60, 0xbb, 0xb9, 0x01, 0x60, 0xc8, 0xfc, 0xc5, 0x4a, 0x78, 0x91, 0x48, 0x10, 0x0d, 0x01, 0xb8, 0xa0, 0x01, 0xfc, 0x4e, 0x47, 0x92, 0x78, 0x5d, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x9b, 0x04, 0x68, 0x04, 0x67, 0x00, 0x16, 0x00, 0x00, 0x25, 0x20, 0x24, 0x35, 0x34, 0x24, 0x29, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x07, 0x21, 0x15, 0x21, 0x16, 0x17, 0x16, 0x33, 0x21, 0x15, 0x02, 0xda, 0xfe, 0xf6, 0xfe, 0xf3, 0x01, 0x0d, 0x01, 0x0a, 0x01, 0x8e, 0xfe, 0x72, 0xd1, 0x5e, 0x46, 0x1b, 0x03, 0x1e, 0xfc, 0xe2, 0x21, 0x40, 0x67, 0xc8, 0x01, 0x8e, 0x9b, 0xf6, 0xf0, 0xf0, 0xf6, 0x8e, 0x01, 0x01, 0x4f, 0x3a, 0x85, 0x8e, 0x91, 0x30, 0x51, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0xff, 0xec, 0x05, 0xa9, 0x05, 0xae, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x21, 0x35, 0x21, 0x32, 0x04, 0x12, 0x15, 0x14, 0x02, 0x04, 0x23, 0x21, 0x35, 0x21, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x21, 0x35, 0x05, 0x11, 0x06, 0x39, 0x43, 0x7e, 0x7b, 0x85, 0xfd, 0x8d, 0x02, 0x73, 0xad, 0x01, 0x3f, 0xab, 0xab, 0xfe, 0xc1, 0xad, 0xfd, 0x8d, 0x02, 0x73, 0x85, 0x7b, 0x7d, 0x44, 0x3a, 0x08, 0xfb, 0x8a, 0x03, 0x27, 0x4a, 0x78, 0x8b, 0x4e, 0x4c, 0x01, 0x9f, 0xc6, 0xfe, 0xa0, 0xbb, 0xb9, 0xfe, 0xa0, 0xc8, 0x9f, 0x01, 0x4d, 0x4f, 0x8a, 0x78, 0x5d, 0xa0, 0x00, 0x03, 0x00, 0x9d, 0xfe, 0xe5, 0x05, 0xa9, 0x06, 0xaf, 0x00, 0x1e, 0x00, 0x26, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x27, 0x37, 0x21, 0x35, 0x21, 0x13, 0x21, 0x35, 0x21, 0x13, 0x26, 0x23, 0x21, 0x35, 0x21, 0x32, 0x17, 0x13, 0x17, 0x03, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x04, 0x2b, 0x01, 0x01, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x03, 0x07, 0x03, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x01, 0xea, 0x87, 0x41, 0xfe, 0xfa, 0x01, 0x3a, 0xa7, 0xfe, 0x1f, 0x02, 0x15, 0x9f, 0x21, 0x20, 0xfd, 0x8d, 0x02, 0x73, 0x3a, 0x39, 0x5a, 0x87, 0x56, 0x27, 0x28, 0x9f, 0xab, 0xab, 0xfe, 0xc1, 0xad, 0xd3, 0x02, 0xd3, 0x3f, 0x4c, 0x75, 0x1a, 0x1a, 0x90, 0x35, 0xa6, 0x9f, 0x84, 0x7c, 0x71, 0x50, 0x42, 0xfe, 0xe5, 0x37, 0xca, 0x9f, 0x01, 0xfc, 0xa0, 0x01, 0xe3, 0x05, 0x9f, 0x0b, 0x01, 0x12, 0x37, 0xfe, 0xf8, 0x13, 0x18, 0x63, 0xfe, 0xa0, 0xbb, 0xb9, 0xfe, 0xa0, 0xc8, 0x03, 0x3b, 0x4a, 0x78, 0x91, 0x48, 0x10, 0x0d, 0xfe, 0x48, 0xa0, 0xfe, 0x04, 0x4e, 0x47, 0x92, 0x78, 0x5d, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x9b, 0x04, 0x68, 0x04, 0x67, 0x00, 0x16, 0x00, 0x00, 0x01, 0x20, 0x04, 0x15, 0x14, 0x04, 0x29, 0x01, 0x35, 0x25, 0x32, 0x37, 0x36, 0x37, 0x21, 0x35, 0x05, 0x26, 0x27, 0x26, 0x07, 0x21, 0x35, 0x02, 0x51, 0x01, 0x0a, 0x01, 0x0d, 0xfe, 0xf3, 0xfe, 0xf6, 0xfe, 0x72, 0x01, 0x8e, 0xd1, 0x5e, 0x46, 0x1b, 0xfc, 0xe2, 0x03, 0x1e, 0x22, 0x3f, 0x68, 0xc7, 0xfe, 0x72, 0x04, 0x67, 0xf6, 0xf1, 0xef, 0xf6, 0x8e, 0x01, 0x50, 0x3a, 0x85, 0x8e, 0x01, 0x91, 0x31, 0x52, 0x01, 0x8e, 0x00, 0x00, 0x01, 0x01, 0x0e, 0x00, 0x00, 0x03, 0x87, 0x03, 0xe2, 0x00, 0x03, 0x00, 0x00, 0x21, 0x11, 0x21, 0x11, 0x01, 0x0e, 0x02, 0x79, 0x03, 0xe2, 0xfc, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8c, 0xfe, 0x77, 0x04, 0xe6, 0x05, 0xc1, 0x00, 0x07, 0x00, 0x00, 0x13, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x8c, 0x04, 0x5a, 0xd8, 0xfd, 0x56, 0xd8, 0x05, 0xc1, 0xf8, 0xb6, 0x06, 0x7d, 0xf9, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8c, 0xfe, 0x77, 0x04, 0xe6, 0x05, 0xc1, 0x00, 0x07, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x8c, 0xd8, 0x02, 0xaa, 0xd8, 0xfe, 0x77, 0x07, 0x4a, 0xf9, 0x83, 0x06, 0x7d, 0xf8, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x16, 0xfe, 0x77, 0x04, 0xb6, 0x05, 0xc1, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x09, 0x01, 0x21, 0x15, 0x21, 0x35, 0x09, 0x01, 0x32, 0x04, 0x6c, 0xfc, 0xa1, 0x02, 0x5c, 0xfd, 0x90, 0x03, 0x8a, 0xfb, 0x61, 0x02, 0x8d, 0xfd, 0x8f, 0x05, 0xc1, 0xc1, 0xfd, 0x33, 0xfd, 0x04, 0xc0, 0x95, 0x03, 0x21, 0x02, 0xe3, 0x00, 0x01, 0x00, 0xc3, 0x02, 0x2d, 0x05, 0x46, 0x02, 0xd7, 0x00, 0x03, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0xd7, 0xaa, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x05, 0x04, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x21, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x01, 0x35, 0x21, 0x15, 0x03, 0x50, 0x97, 0xfe, 0x0a, 0x01, 0xf6, 0x97, 0x01, 0xf5, 0xfe, 0x0b, 0xfd, 0x73, 0x04, 0x82, 0x01, 0x83, 0xaa, 0x01, 0x83, 0xfe, 0x7d, 0xaa, 0x02, 0xd7, 0xaa, 0xaa, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x19, 0x01, 0x33, 0x15, 0x23, 0x03, 0x50, 0x01, 0xf5, 0xfe, 0x0b, 0x97, 0xfe, 0x0a, 0x01, 0xf6, 0x97, 0x97, 0x04, 0xa0, 0xfe, 0x05, 0xaa, 0xfe, 0x05, 0x01, 0xfb, 0xaa, 0x01, 0xfb, 0x01, 0x35, 0xcc, 0xff, 0xff, 0x00, 0x00, 0xff, 0x42, 0x02, 0x6d, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x12, 0x00, 0x00, 0xff, 0xff, 0x01, 0x62, 0xff, 0x92, 0x03, 0xd0, 0x06, 0x25, 0x10, 0x07, 0x00, 0x3f, 0x01, 0x63, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0xeb, 0x00, 0x00, 0x05, 0x1e, 0x05, 0x04, 0x00, 0x11, 0x00, 0x00, 0x01, 0x25, 0x37, 0x05, 0x11, 0x33, 0x11, 0x25, 0x17, 0x0d, 0x01, 0x07, 0x25, 0x11, 0x23, 0x11, 0x05, 0x27, 0x02, 0x6c, 0xfe, 0x7f, 0x4d, 0x01, 0x81, 0x97, 0x01, 0x81, 0x4c, 0xfe, 0x7f, 0x01, 0x81, 0x4c, 0xfe, 0x7f, 0x97, 0xfe, 0x7f, 0x4d, 0x02, 0x82, 0xf7, 0x93, 0xf7, 0x01, 0xef, 0xfe, 0x11, 0xf7, 0x93, 0xf7, 0xf7, 0x93, 0xf7, 0xfe, 0x11, 0x01, 0xef, 0xf7, 0x93, 0x00, 0xff, 0xff, 0x01, 0x23, 0x01, 0x47, 0x03, 0x5f, 0x03, 0xc2, 0x10, 0x07, 0x00, 0x72, 0x00, 0x74, 0xfd, 0xd2, 0x00, 0x00, 0xff, 0xff, 0x01, 0x35, 0x01, 0x59, 0x03, 0x4d, 0x03, 0xa9, 0x10, 0x06, 0x07, 0x57, 0x21, 0x88, 0x00, 0x01, 0x00, 0x36, 0xff, 0xd7, 0x04, 0x97, 0x06, 0x7d, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x01, 0x23, 0x01, 0x07, 0x27, 0x25, 0x13, 0x03, 0xec, 0xaa, 0x67, 0xfd, 0xe9, 0x3b, 0xfe, 0xe1, 0x71, 0x16, 0x00, 0xff, 0xe6, 0x06, 0x7d, 0x60, 0xf9, 0xba, 0x03, 0x73, 0x2d, 0x50, 0x62, 0xfd, 0x3b, 0x00, 0xff, 0xff, 0x00, 0x36, 0xff, 0xd7, 0x04, 0x97, 0x07, 0x76, 0x12, 0x26, 0x08, 0xf6, 0x00, 0x00, 0x10, 0x07, 0x00, 0x75, 0x00, 0x68, 0x01, 0x86, 0xff, 0xff, 0x00, 0x36, 0xff, 0xd7, 0x04, 0x97, 0x07, 0x65, 0x12, 0x26, 0x08, 0xf6, 0x00, 0x00, 0x10, 0x07, 0x07, 0xa2, 0x00, 0x68, 0x01, 0x86, 0x00, 0x02, 0x00, 0xc6, 0x00, 0xe5, 0x04, 0x5f, 0x03, 0xe5, 0x00, 0x0b, 0x00, 0x31, 0x00, 0x00, 0x01, 0x32, 0x37, 0x02, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x05, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x12, 0x33, 0x01, 0xda, 0x95, 0x59, 0x72, 0x7c, 0x5a, 0x2e, 0x30, 0x30, 0x33, 0x02, 0xda, 0x46, 0x41, 0x31, 0x31, 0x2e, 0x1c, 0x2c, 0x3d, 0x35, 0x41, 0x69, 0x79, 0x50, 0x55, 0x55, 0x4a, 0x81, 0x42, 0x30, 0x39, 0x27, 0x24, 0x24, 0x3c, 0x35, 0x42, 0x68, 0x44, 0x3a, 0x85, 0x68, 0x72, 0x7b, 0x01, 0x6b, 0xf0, 0x01, 0x06, 0x48, 0x4d, 0x66, 0x70, 0x45, 0x46, 0x02, 0x84, 0x1e, 0x1b, 0x3f, 0x24, 0x54, 0x78, 0x35, 0x40, 0x65, 0x6a, 0xaf, 0xa8, 0x72, 0x65, 0x1e, 0x21, 0x39, 0x33, 0x45, 0x78, 0x35, 0x40, 0x83, 0xf0, 0xfe, 0xfa, 0x00, 0x00, 0x03, 0x00, 0xc6, 0x00, 0xe5, 0x05, 0x3a, 0x03, 0xe5, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x25, 0x32, 0x37, 0x02, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0x22, 0x07, 0x12, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x03, 0x48, 0x1c, 0x2c, 0x3d, 0x35, 0x42, 0x68, 0x79, 0x50, 0x55, 0x55, 0x4b, 0x80, 0x42, 0x30, 0x39, 0x27, 0x24, 0x24, 0x3c, 0x35, 0x43, 0x67, 0x7a, 0x50, 0x54, 0x54, 0x4c, 0x80, 0x41, 0x31, 0x31, 0xfe, 0x64, 0x95, 0x59, 0x72, 0x7c, 0x5a, 0x2e, 0x31, 0x31, 0x33, 0x02, 0xa0, 0x86, 0x67, 0x71, 0x7c, 0x5a, 0x2e, 0x31, 0x31, 0x32, 0x01, 0x5d, 0x24, 0x54, 0x78, 0x35, 0x40, 0x65, 0x6a, 0xaf, 0xa8, 0x72, 0x65, 0x1e, 0x21, 0x39, 0x33, 0x45, 0x78, 0x35, 0x40, 0x65, 0x6a, 0xaf, 0xa8, 0x72, 0x65, 0x1e, 0x1b, 0x4d, 0xf0, 0x01, 0x06, 0x48, 0x4d, 0x66, 0x70, 0x45, 0x46, 0x01, 0xf4, 0xf0, 0xfe, 0xfa, 0x48, 0x4d, 0x66, 0x70, 0x45, 0x46, 0x00, 0x00, 0x01, 0x00, 0xfe, 0x00, 0xcb, 0x05, 0x0a, 0x05, 0x49, 0x00, 0x05, 0x00, 0x00, 0x25, 0x21, 0x11, 0x33, 0x11, 0x21, 0x05, 0x0a, 0xfb, 0xf5, 0x99, 0x03, 0x72, 0xcb, 0x04, 0x7e, 0xfc, 0x2c, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x25, 0x15, 0x21, 0x01, 0x33, 0x01, 0x05, 0xa8, 0xfa, 0xf6, 0x03, 0x59, 0xda, 0xfd, 0x1d, 0xca, 0xca, 0x05, 0xd5, 0xfa, 0xf5, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xff, 0x94, 0x05, 0xa9, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x1b, 0x00, 0x00, 0x25, 0x26, 0x27, 0x26, 0x27, 0x01, 0x13, 0x01, 0x33, 0x01, 0x16, 0x17, 0x16, 0x17, 0x21, 0x15, 0x21, 0x16, 0x15, 0x23, 0x34, 0x27, 0x21, 0x01, 0x26, 0x27, 0x37, 0x16, 0x03, 0xf0, 0x23, 0x43, 0x3a, 0x4e, 0xfe, 0xec, 0xcc, 0x01, 0x3d, 0xda, 0xfe, 0x78, 0x65, 0x4a, 0x54, 0x26, 0x01, 0x36, 0xfe, 0xe8, 0x04, 0x7e, 0x05, 0xfc, 0x8d, 0x01, 0xd8, 0x1b, 0x1c, 0x48, 0x1a, 0xca, 0x8b, 0x86, 0x73, 0x5e, 0xfe, 0x1e, 0x02, 0xe3, 0x02, 0x28, 0xfd, 0x52, 0x73, 0x93, 0xa7, 0xb0, 0xca, 0x35, 0x37, 0x37, 0x35, 0x03, 0x36, 0x15, 0x14, 0x75, 0x13, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xd5, 0xff, 0xfa, 0x05, 0x46, 0x05, 0xd1, 0x00, 0x17, 0x00, 0x1d, 0x00, 0x00, 0x09, 0x01, 0x37, 0x01, 0x26, 0x27, 0x37, 0x16, 0x17, 0x25, 0x15, 0x05, 0x16, 0x07, 0x15, 0x06, 0x07, 0x05, 0x15, 0x25, 0x06, 0x07, 0x27, 0x36, 0x13, 0x09, 0x01, 0x36, 0x37, 0x36, 0x03, 0x1a, 0xfd, 0xbb, 0x02, 0x02, 0x4d, 0x17, 0x1a, 0x7d, 0x1a, 0x17, 0x01, 0xa5, 0xfe, 0xaf, 0x3f, 0x06, 0x06, 0x40, 0x01, 0x5e, 0xfe, 0x54, 0x19, 0x1b, 0x78, 0x1c, 0x6c, 0xfe, 0x14, 0x01, 0xe4, 0x2f, 0x04, 0x06, 0x01, 0x34, 0x01, 0x52, 0xc0, 0x01, 0x57, 0x21, 0x1e, 0x4c, 0x21, 0x24, 0xee, 0xd2, 0xbe, 0xb3, 0xc6, 0x09, 0xa1, 0x93, 0xbf, 0xd2, 0xf1, 0x26, 0x21, 0x4c, 0x20, 0x02, 0xe9, 0xfe, 0xe7, 0xfe, 0xf0, 0x7b, 0x81, 0x9e, 0x00, 0x00, 0x00, 0x01, 0x01, 0x84, 0xfe, 0x4a, 0x02, 0x15, 0x06, 0x2b, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x11, 0x23, 0x01, 0x85, 0x90, 0x90, 0x06, 0x2b, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5b, 0xfe, 0x4a, 0x03, 0x3f, 0x06, 0x2b, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x37, 0x17, 0x05, 0x11, 0x23, 0x11, 0x07, 0x27, 0x01, 0x85, 0x90, 0xe2, 0x48, 0xfe, 0xd6, 0x90, 0xe4, 0x45, 0x02, 0x56, 0x03, 0xd5, 0xfc, 0x9c, 0xb0, 0x6f, 0xe7, 0xfc, 0x29, 0x03, 0x67, 0xb1, 0x6e, 0x00, 0x00, 0x02, 0x00, 0xf4, 0xfe, 0x4a, 0x02, 0xa5, 0x06, 0x2b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0xf5, 0x90, 0x90, 0x01, 0x20, 0x90, 0x90, 0x06, 0x2b, 0xf8, 0x1f, 0x07, 0xe1, 0xf8, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x5b, 0xfe, 0x4a, 0x03, 0x3f, 0x06, 0x2b, 0x00, 0x13, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x37, 0x11, 0x33, 0x11, 0x37, 0x17, 0x07, 0x11, 0x23, 0x11, 0x07, 0x11, 0x23, 0x11, 0x07, 0x27, 0xf5, 0x90, 0x90, 0x90, 0x52, 0x48, 0x9a, 0x90, 0x90, 0x90, 0x54, 0x45, 0x01, 0xe6, 0x04, 0x45, 0xfc, 0x2b, 0x71, 0x03, 0x64, 0xfd, 0x0c, 0x40, 0x6f, 0x78, 0xfb, 0xba, 0x03, 0xd7, 0x70, 0xfc, 0x99, 0x02, 0xf7, 0x41, 0x6e, 0x00, 0x00, 0x01, 0x00, 0xed, 0x00, 0x00, 0x04, 0x58, 0x04, 0xa2, 0x00, 0x06, 0x00, 0x00, 0x33, 0x01, 0x33, 0x01, 0x23, 0x09, 0x01, 0xee, 0x01, 0x44, 0xe2, 0x01, 0x44, 0xb0, 0xfe, 0xfb, 0xfe, 0xfa, 0x04, 0xa2, 0xfb, 0x5e, 0x03, 0xac, 0xfc, 0x54, 0x00, 0x01, 0x00, 0xed, 0x00, 0x00, 0x04, 0x58, 0x04, 0xa2, 0x00, 0x06, 0x00, 0x00, 0x13, 0x33, 0x09, 0x01, 0x33, 0x01, 0x23, 0xee, 0xaf, 0x01, 0x06, 0x01, 0x05, 0xb0, 0xfe, 0xbc, 0xe2, 0x04, 0xa2, 0xfc, 0x54, 0x03, 0xac, 0xfb, 0x5e, 0x00, 0x00, 0x01, 0x00, 0xed, 0x00, 0x00, 0x04, 0x58, 0x04, 0xa2, 0x00, 0x11, 0x00, 0x00, 0x13, 0x10, 0x12, 0x33, 0x32, 0x12, 0x19, 0x01, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0xee, 0xdc, 0xd9, 0xd8, 0xdd, 0x9b, 0x85, 0x95, 0x95, 0x86, 0x9a, 0x02, 0x50, 0x01, 0x28, 0x01, 0x2a, 0xfe, 0xd6, 0xfe, 0xd8, 0xfd, 0xb0, 0x02, 0x37, 0xf4, 0xd3, 0xd3, 0xf4, 0xfd, 0xc9, 0x00, 0x00, 0x01, 0x00, 0xed, 0x00, 0x00, 0x04, 0x58, 0x04, 0xa2, 0x00, 0x11, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0xee, 0x9a, 0x86, 0x95, 0x95, 0x85, 0x9b, 0xdd, 0xd8, 0xd9, 0xdc, 0x02, 0x52, 0x02, 0x50, 0xfd, 0xc9, 0xf4, 0xd3, 0xd3, 0xf4, 0x02, 0x37, 0xfd, 0xb0, 0xfe, 0xd8, 0xfe, 0xd6, 0x01, 0x2a, 0x00, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x15, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x01, 0xb3, 0x07, 0x92, 0x88, 0x71, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x3a, 0x08, 0x91, 0x88, 0x72, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x04, 0xe2, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0xfa, 0xb0, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0xfe, 0x4d, 0x05, 0x46, 0x06, 0x0e, 0x10, 0x26, 0x09, 0x07, 0x00, 0x00, 0x10, 0x07, 0x09, 0x07, 0x01, 0xee, 0x00, 0x00, 0xff, 0xff, 0x00, 0x69, 0xfe, 0x4d, 0x07, 0x34, 0x06, 0x0e, 0x10, 0x26, 0x09, 0x07, 0x00, 0x00, 0x10, 0x27, 0x09, 0x07, 0x01, 0xee, 0x00, 0x00, 0x10, 0x07, 0x09, 0x07, 0x03, 0xdc, 0x00, 0x00, 0x00, 0x03, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x3f, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x13, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x03, 0x13, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0xb3, 0x07, 0x4b, 0x47, 0x42, 0x46, 0x40, 0x31, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0c, 0x59, 0x3b, 0x63, 0x63, 0x4d, 0x68, 0x0d, 0x08, 0x4a, 0x47, 0x43, 0x45, 0x40, 0x32, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0e, 0x54, 0x42, 0x63, 0x64, 0x4b, 0x69, 0x7c, 0x37, 0x28, 0x3e, 0x40, 0x21, 0x28, 0xaa, 0x14, 0x37, 0x28, 0x40, 0x43, 0x21, 0x04, 0xe2, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0xfe, 0xd6, 0x18, 0x4b, 0x7c, 0x92, 0x9c, 0x6f, 0x55, 0x13, 0xfe, 0xbe, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0x01, 0x31, 0x18, 0x49, 0x6f, 0x9b, 0x9c, 0x73, 0x56, 0x13, 0xfd, 0x9b, 0x10, 0x2f, 0x48, 0x67, 0x6a, 0x47, 0x24, 0x12, 0xfe, 0x34, 0x01, 0xd6, 0x11, 0x2e, 0x4a, 0x68, 0x67, 0x48, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x69, 0xfe, 0x4d, 0x05, 0x46, 0x06, 0x0e, 0x00, 0x4d, 0x00, 0x51, 0x00, 0x5a, 0x00, 0x63, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x21, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x21, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x13, 0x21, 0x13, 0x21, 0x03, 0x13, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0x03, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x01, 0xb3, 0x07, 0x4b, 0x47, 0x42, 0x46, 0x40, 0x31, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0c, 0x01, 0x57, 0x0e, 0x07, 0x4b, 0x47, 0x42, 0x46, 0x40, 0x31, 0x12, 0x85, 0x0f, 0x34, 0x40, 0x07, 0x0c, 0x59, 0x3b, 0x63, 0x63, 0x4d, 0x68, 0x0d, 0x08, 0x4a, 0x47, 0x43, 0x45, 0x40, 0x32, 0x12, 0x86, 0x0f, 0x33, 0x40, 0x07, 0x0d, 0xfe, 0xa8, 0x0d, 0x08, 0x4a, 0x47, 0x43, 0x45, 0x40, 0x32, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0e, 0x54, 0x42, 0x63, 0x64, 0x4b, 0x69, 0x7b, 0x01, 0x58, 0x16, 0xfe, 0xa8, 0xab, 0x14, 0x37, 0x28, 0x40, 0x43, 0x21, 0x02, 0xbf, 0x13, 0x36, 0x28, 0x3e, 0x40, 0x21, 0x04, 0xe2, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0xfe, 0xe2, 0x01, 0x37, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0xfe, 0xd6, 0x18, 0x4b, 0x7c, 0x92, 0x9c, 0x6f, 0x55, 0x13, 0xfe, 0xbe, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0x01, 0x24, 0xfe, 0xc3, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0x01, 0x30, 0x19, 0x49, 0x6f, 0x9b, 0x9c, 0x73, 0x56, 0x13, 0xfd, 0x92, 0x01, 0xf1, 0xfe, 0x21, 0x01, 0xd6, 0x11, 0x2e, 0x4a, 0x68, 0x67, 0x48, 0x24, 0x01, 0xba, 0xfe, 0x2b, 0x10, 0x2f, 0x48, 0x67, 0x6a, 0x47, 0x24, 0x00, 0x05, 0x00, 0x69, 0xfe, 0x4d, 0x07, 0x34, 0x06, 0x0e, 0x00, 0x6d, 0x00, 0x71, 0x00, 0x75, 0x00, 0x7e, 0x00, 0x87, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x21, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x21, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x21, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x21, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x13, 0x21, 0x03, 0x29, 0x01, 0x13, 0x21, 0x03, 0x13, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0x03, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x01, 0xb3, 0x07, 0x4b, 0x47, 0x42, 0x46, 0x40, 0x31, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0c, 0x01, 0x57, 0x0e, 0x07, 0x4b, 0x47, 0x42, 0x46, 0x40, 0x31, 0x12, 0x85, 0x0f, 0x34, 0x40, 0x07, 0x0c, 0x01, 0x57, 0x0e, 0x07, 0x4b, 0x47, 0x42, 0x46, 0x40, 0x32, 0x11, 0x85, 0x0f, 0x34, 0x3f, 0x08, 0x0c, 0x59, 0x3b, 0x63, 0x63, 0x4d, 0x68, 0x0d, 0x07, 0x4b, 0x47, 0x43, 0x45, 0x40, 0x32, 0x11, 0x85, 0x0f, 0x33, 0x40, 0x07, 0x0d, 0xfe, 0xa8, 0x0d, 0x08, 0x4a, 0x47, 0x43, 0x45, 0x40, 0x32, 0x12, 0x86, 0x0f, 0x33, 0x40, 0x07, 0x0d, 0xfe, 0xa8, 0x0d, 0x08, 0x4a, 0x47, 0x43, 0x45, 0x40, 0x32, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0e, 0x54, 0x42, 0x63, 0x64, 0x4b, 0x69, 0x03, 0xc1, 0x16, 0xfe, 0xa8, 0x15, 0xfe, 0x11, 0x01, 0x58, 0x16, 0xfe, 0xa8, 0xab, 0x14, 0x37, 0x28, 0x40, 0x43, 0x21, 0x04, 0xad, 0x13, 0x36, 0x28, 0x3e, 0x40, 0x21, 0x04, 0xe2, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0xfe, 0xe2, 0x01, 0x37, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0xfe, 0xe2, 0x01, 0x37, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0xfe, 0xd6, 0x18, 0x4b, 0x7c, 0x92, 0x9c, 0x6f, 0x55, 0x13, 0xfe, 0xbe, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0x01, 0x24, 0xfe, 0xc3, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0x01, 0x24, 0xfe, 0xc3, 0xa7, 0x44, 0x41, 0x46, 0x37, 0x8c, 0x0f, 0x82, 0xaf, 0x01, 0x30, 0x19, 0x49, 0x6f, 0x9b, 0x9c, 0x73, 0x56, 0x13, 0xfd, 0x92, 0x01, 0xf1, 0xfe, 0x0f, 0x01, 0xf1, 0xfe, 0x21, 0x01, 0xd6, 0x11, 0x2e, 0x4a, 0x68, 0x67, 0x48, 0x24, 0x01, 0xba, 0xfe, 0x2b, 0x10, 0x2f, 0x48, 0x67, 0x6a, 0x47, 0x24, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4c, 0x03, 0xc3, 0x06, 0x0f, 0x00, 0x33, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x16, 0x1d, 0x01, 0x37, 0x17, 0x07, 0x23, 0x27, 0x37, 0x17, 0x35, 0x34, 0x27, 0x26, 0x27, 0x03, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x06, 0x07, 0x06, 0x15, 0x23, 0x34, 0x37, 0x36, 0x37, 0x13, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x02, 0xd2, 0x10, 0x34, 0x3f, 0x07, 0x0e, 0x50, 0x38, 0x6c, 0x54, 0x41, 0xab, 0x31, 0xa9, 0x41, 0x53, 0x47, 0x2e, 0x28, 0x27, 0x08, 0x8f, 0x41, 0x47, 0x74, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x27, 0x3a, 0x2a, 0x4d, 0x5c, 0x62, 0x4e, 0x61, 0x10, 0x07, 0x90, 0x40, 0x48, 0x73, 0x12, 0x04, 0xf6, 0x82, 0xaf, 0xfe, 0xb3, 0x18, 0x3f, 0x75, 0x9c, 0x1e, 0x5d, 0x48, 0xbd, 0xbd, 0x48, 0x5d, 0x1e, 0x73, 0x4d, 0x33, 0x0b, 0xfc, 0x67, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x03, 0x88, 0x10, 0x2e, 0x56, 0x72, 0x9b, 0x6d, 0x56, 0x11, 0x01, 0x5f, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x03, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0xb4, 0x06, 0x0e, 0x00, 0x08, 0x00, 0x11, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x13, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x25, 0x34, 0x27, 0x03, 0x3e, 0x01, 0x37, 0x27, 0x37, 0x13, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x16, 0x15, 0x37, 0x17, 0x07, 0x06, 0x07, 0x06, 0x07, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x01, 0x8b, 0x14, 0x37, 0x28, 0x40, 0x43, 0x21, 0x01, 0x5a, 0x89, 0x14, 0x37, 0x49, 0x08, 0x79, 0x41, 0x61, 0x10, 0x35, 0x3e, 0x07, 0x0c, 0x50, 0x44, 0x62, 0x41, 0x41, 0x97, 0x17, 0x36, 0x4d, 0x68, 0x0d, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x0e, 0x54, 0x42, 0x63, 0x64, 0x4b, 0x69, 0x0e, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x01, 0x4a, 0x01, 0xd6, 0x11, 0x2e, 0x4a, 0x67, 0x68, 0x48, 0x24, 0xe6, 0x99, 0x3b, 0xfe, 0x2b, 0x10, 0x65, 0x13, 0x88, 0x48, 0x02, 0x5d, 0x82, 0xaf, 0xfe, 0xd6, 0x16, 0x4d, 0x6f, 0x7c, 0x48, 0x48, 0xa7, 0x43, 0x3f, 0x5a, 0x13, 0xfe, 0xbe, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x01, 0x31, 0x18, 0x49, 0x6f, 0x9b, 0x9c, 0x73, 0x56, 0x13, 0x01, 0x3c, 0xa4, 0x88, 0x7a, 0x8f, 0x00, 0x00, 0x03, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0xb6, 0x06, 0x0e, 0x00, 0x08, 0x00, 0x12, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x13, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0x2e, 0x01, 0x27, 0x03, 0x3e, 0x01, 0x37, 0x07, 0x27, 0x13, 0x26, 0x23, 0x22, 0x07, 0x03, 0x1e, 0x01, 0x1f, 0x01, 0x07, 0x27, 0x14, 0x06, 0x07, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x01, 0x8b, 0x14, 0x37, 0x28, 0x40, 0x43, 0x21, 0x01, 0x49, 0x20, 0x30, 0x28, 0x14, 0x37, 0x5f, 0x06, 0x4b, 0x40, 0xa0, 0x10, 0x35, 0x3e, 0x07, 0x0c, 0x59, 0x7d, 0x10, 0x94, 0x41, 0x44, 0xae, 0x68, 0x0d, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x0e, 0x54, 0x42, 0x63, 0x64, 0x4b, 0x69, 0x0e, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x01, 0x4a, 0x01, 0xd6, 0x11, 0x2e, 0x4a, 0x67, 0x68, 0x48, 0x24, 0x01, 0x36, 0x42, 0x30, 0x12, 0xfe, 0x2b, 0x10, 0x82, 0x40, 0x54, 0x48, 0x02, 0xef, 0x82, 0xaf, 0xfe, 0xd6, 0x18, 0x9d, 0x3f, 0xa4, 0x48, 0x4b, 0x7c, 0xc0, 0x13, 0xfe, 0xbe, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x01, 0x31, 0x18, 0x49, 0x6f, 0x9b, 0x9c, 0x73, 0x56, 0x13, 0x01, 0x3c, 0xa4, 0x88, 0x7a, 0x8f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6c, 0x00, 0xcd, 0x04, 0x28, 0x04, 0xd5, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xa8, 0xfe, 0x85, 0x10, 0x27, 0x09, 0xa1, 0x02, 0xa5, 0xfe, 0x85, 0x10, 0x07, 0x09, 0xa1, 0x01, 0x26, 0x01, 0x8f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6c, 0x00, 0xcd, 0x04, 0x28, 0x04, 0xd5, 0x10, 0x27, 0x09, 0xa1, 0x01, 0x26, 0xfe, 0x85, 0x10, 0x27, 0x09, 0xa1, 0x02, 0xa5, 0x01, 0x8f, 0x10, 0x07, 0x09, 0xa1, 0xff, 0xa8, 0x01, 0x8f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x90, 0x00, 0xcd, 0x01, 0x4f, 0x04, 0xd6, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xcc, 0x01, 0x90, 0x10, 0x07, 0x09, 0xa1, 0xff, 0xcc, 0xfe, 0x85, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6c, 0x00, 0xcd, 0x04, 0x28, 0x04, 0xd5, 0x10, 0x27, 0x09, 0xa1, 0x02, 0xa5, 0x01, 0x8f, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xa8, 0x01, 0x8f, 0x10, 0x27, 0x09, 0xa1, 0x02, 0xa5, 0xfe, 0x85, 0x10, 0x07, 0x09, 0xa1, 0xff, 0xa8, 0xfe, 0x85, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0x02, 0x2d, 0x05, 0x46, 0x04, 0x6a, 0x10, 0x27, 0x09, 0xa1, 0x01, 0xdf, 0x01, 0x24, 0x10, 0x06, 0x08, 0xee, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0x9f, 0x05, 0x46, 0x04, 0x6a, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x05, 0x21, 0x15, 0x21, 0x04, 0x87, 0xbe, 0xbe, 0x01, 0xbe, 0xbe, 0xfc, 0x3b, 0x03, 0x03, 0xfc, 0xfd, 0x01, 0x9d, 0xfe, 0x03, 0xcb, 0xfe, 0x95, 0xaa, 0x00, 0xff, 0xff, 0x00, 0xc2, 0x00, 0x9f, 0x05, 0x46, 0x04, 0x6a, 0x10, 0x26, 0x08, 0xee, 0x00, 0x00, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xfd, 0xfe, 0x57, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xfe, 0x01, 0x24, 0x10, 0x27, 0x09, 0xa1, 0x03, 0xc2, 0xfe, 0x57, 0x10, 0x07, 0x09, 0xa1, 0x03, 0xc3, 0x01, 0x24, 0xff, 0xff, 0x00, 0xc3, 0x00, 0x9f, 0x05, 0x46, 0x04, 0x6a, 0x10, 0x26, 0x09, 0x18, 0x00, 0x00, 0x10, 0x27, 0x09, 0xa1, 0x01, 0xde, 0xfe, 0x57, 0x10, 0x07, 0x09, 0xa1, 0x01, 0xdf, 0x01, 0x24, 0x00, 0x01, 0x00, 0xc3, 0x01, 0xd3, 0x05, 0x46, 0x03, 0x32, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x09, 0x05, 0x05, 0x0e, 0x8b, 0x55, 0x4d, 0x98, 0x03, 0x32, 0xb3, 0x4e, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x3b, 0x05, 0x02, 0x02, 0x06, 0x3d, 0x4b, 0x00, 0x01, 0x00, 0xc3, 0x01, 0xd3, 0x05, 0x46, 0x03, 0x32, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0xc3, 0x5d, 0x98, 0x4e, 0x54, 0x8c, 0x0d, 0x05, 0x05, 0x0a, 0x84, 0x63, 0x58, 0xa1, 0x5e, 0x58, 0x9b, 0x4f, 0x55, 0x8b, 0x0e, 0x05, 0x06, 0x09, 0x84, 0x63, 0x57, 0xa1, 0x5f, 0x03, 0x32, 0x55, 0x4b, 0x3d, 0x06, 0x02, 0x02, 0x05, 0x3b, 0x45, 0x4e, 0xb3, 0x54, 0x4c, 0x3d, 0x06, 0x02, 0x03, 0x04, 0x3b, 0x45, 0x4e, 0x00, 0x01, 0x00, 0x91, 0x01, 0x31, 0x05, 0x77, 0x03, 0xd4, 0x00, 0x29, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x1e, 0x01, 0x33, 0x15, 0x22, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x2e, 0x01, 0x23, 0x37, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x02, 0xe7, 0x49, 0x8f, 0x40, 0x4a, 0x5a, 0x01, 0x5e, 0x46, 0x5f, 0x8c, 0x53, 0x5a, 0x80, 0x63, 0x6c, 0xaf, 0x37, 0x3a, 0x9e, 0x41, 0x4a, 0x5a, 0x02, 0x5e, 0x46, 0x01, 0x5e, 0x8d, 0x53, 0x5a, 0x80, 0x63, 0x6c, 0xb1, 0x02, 0x2e, 0x74, 0x74, 0x6c, 0x48, 0x3d, 0x59, 0x9b, 0x4f, 0x9a, 0x48, 0x4c, 0xa2, 0x5c, 0x7d, 0x58, 0x5b, 0x8d, 0x6c, 0x48, 0x3d, 0x59, 0x9b, 0x4f, 0x9a, 0x48, 0x4c, 0xa2, 0x5c, 0x7d, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x57, 0x05, 0x46, 0x04, 0xad, 0x00, 0x11, 0x00, 0x00, 0x01, 0x02, 0x23, 0x22, 0x03, 0x02, 0x27, 0x22, 0x03, 0x23, 0x12, 0x33, 0x32, 0x13, 0x12, 0x17, 0x32, 0x13, 0x05, 0x45, 0x6f, 0xe2, 0xcf, 0x59, 0x5c, 0x5c, 0x68, 0x50, 0x99, 0x6f, 0xe2, 0xcf, 0x5a, 0x5b, 0x5c, 0x68, 0x50, 0x02, 0xd7, 0xfd, 0x80, 0x01, 0xd6, 0x01, 0xdc, 0x01, 0xfe, 0x23, 0x02, 0x80, 0xfe, 0x2a, 0xfe, 0x24, 0x01, 0x01, 0xdd, 0x00, 0x00, 0x01, 0x00, 0xbb, 0x00, 0x00, 0x01, 0xf8, 0x05, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x21, 0x23, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x16, 0x01, 0xf8, 0xa2, 0x46, 0x3d, 0x34, 0x03, 0x04, 0x02, 0x05, 0x36, 0x44, 0x4c, 0xa2, 0x46, 0x3e, 0x35, 0x05, 0x02, 0x02, 0x05, 0x36, 0x43, 0x68, 0xb4, 0x60, 0x6e, 0x92, 0x0a, 0x08, 0x06, 0x0e, 0x9c, 0x5e, 0x58, 0xac, 0x62, 0x6a, 0xb2, 0x62, 0x6e, 0x92, 0x0c, 0x04, 0x06, 0x10, 0x9a, 0x5e, 0x56, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x9d, 0x05, 0x46, 0x04, 0x6c, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x13, 0x17, 0x03, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x03, 0x27, 0x02, 0x9c, 0x5a, 0x3c, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x54, 0x6c, 0x9c, 0x8b, 0x97, 0x5b, 0x3e, 0x4d, 0x98, 0x5d, 0x5e, 0xa1, 0x58, 0x56, 0x6d, 0x9a, 0x8b, 0x02, 0x53, 0x20, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x2b, 0x01, 0x7e, 0x46, 0xfe, 0x8c, 0x20, 0x4b, 0x55, 0xb3, 0x4e, 0x45, 0x2c, 0xfe, 0x85, 0x46, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x01, 0x10, 0x05, 0x46, 0x03, 0xa2, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x01, 0x21, 0x15, 0x21, 0x05, 0x45, 0x5e, 0xa2, 0x57, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x09, 0x05, 0x05, 0x0e, 0x8b, 0x55, 0x4d, 0x98, 0xfb, 0xdb, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0x6f, 0xb3, 0x4e, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x3b, 0x05, 0x02, 0x02, 0x06, 0x3d, 0x4b, 0x01, 0x88, 0xa8, 0x00, 0x02, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x03, 0xf4, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x01, 0x21, 0x15, 0x21, 0x05, 0x45, 0x5e, 0xa2, 0x57, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0x8b, 0x55, 0x4d, 0x98, 0xfb, 0xdb, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0xf4, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x09, 0x3d, 0x4b, 0xfe, 0x6b, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x62, 0x05, 0x46, 0x04, 0xd3, 0x00, 0x25, 0x00, 0x26, 0x00, 0x00, 0x01, 0x03, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x23, 0x35, 0x21, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x01, 0x13, 0x01, 0x04, 0x83, 0xb7, 0x1c, 0x21, 0x41, 0x53, 0x9d, 0x0b, 0x5e, 0xa1, 0x58, 0x3b, 0x48, 0x82, 0x02, 0x5c, 0xfd, 0x3e, 0xa7, 0x7b, 0x61, 0xff, 0x01, 0x70, 0xa6, 0x83, 0x50, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x2d, 0xd7, 0xfd, 0xbe, 0x04, 0x6f, 0xfe, 0xe9, 0x0b, 0x2d, 0x58, 0x22, 0xb2, 0x4f, 0x45, 0x16, 0xba, 0xaa, 0xfe, 0x64, 0x9a, 0xaa, 0xf3, 0x38, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x16, 0x01, 0x49, 0xfc, 0x8d, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0xb8, 0x05, 0x46, 0x04, 0xc1, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x01, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x05, 0x45, 0x5e, 0xa2, 0x57, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0x8b, 0x55, 0x4d, 0x98, 0xfb, 0xdb, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0xc1, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x07, 0x3f, 0x4b, 0xfe, 0x6b, 0xaa, 0xcb, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x18, 0x05, 0x46, 0x04, 0xc1, 0x00, 0x1a, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x01, 0x23, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x37, 0x17, 0x07, 0x33, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0x8b, 0x55, 0x4d, 0x98, 0xfc, 0xab, 0xd0, 0x01, 0x6d, 0xbc, 0xfd, 0xd7, 0x02, 0xca, 0x7e, 0x64, 0x11, 0xe7, 0xfe, 0x77, 0xbb, 0x02, 0x44, 0xfd, 0x1b, 0x95, 0x64, 0x04, 0xc1, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x07, 0x3f, 0x4b, 0xfc, 0x4c, 0xaa, 0xcb, 0xaa, 0x8a, 0x73, 0x17, 0xaa, 0xcb, 0xaa, 0xa0, 0x73, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xf6, 0x05, 0x46, 0x05, 0x42, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x23, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x37, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x01, 0x37, 0x17, 0x03, 0xf2, 0x09, 0x08, 0x43, 0x57, 0x42, 0x66, 0x5e, 0xa1, 0x58, 0x23, 0x27, 0x52, 0x01, 0xf3, 0xfd, 0xbb, 0x62, 0x02, 0xa7, 0xfd, 0x08, 0x5e, 0x83, 0x37, 0xe0, 0x01, 0x32, 0x62, 0xfe, 0x6c, 0x01, 0xe6, 0x6a, 0x2d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x59, 0x78, 0x84, 0x04, 0x22, 0x01, 0x25, 0x1e, 0x5d, 0xb2, 0x4f, 0x45, 0x07, 0xab, 0xaa, 0xcb, 0xaa, 0xc2, 0x4e, 0x74, 0xaa, 0xcb, 0xaa, 0xda, 0x14, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x25, 0xfa, 0x4e, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x01, 0x10, 0x05, 0x46, 0x03, 0xf4, 0x00, 0x1d, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x09, 0x05, 0x05, 0x0e, 0x8b, 0x55, 0x4d, 0x98, 0x5d, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x08, 0x05, 0x06, 0x0e, 0x8b, 0x55, 0x4d, 0x98, 0x02, 0x6f, 0xb3, 0x4e, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x3b, 0x05, 0x02, 0x02, 0x06, 0x3d, 0x4b, 0x01, 0xda, 0xb2, 0x4f, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x04, 0x02, 0x03, 0x06, 0x3d, 0x4b, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x05, 0x05, 0x46, 0x04, 0xff, 0x00, 0x34, 0x00, 0x00, 0x01, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x03, 0x27, 0x13, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x32, 0x1f, 0x01, 0x13, 0x17, 0x03, 0xa9, 0x33, 0x27, 0x4d, 0x98, 0x5d, 0x5e, 0xa1, 0x58, 0x39, 0x45, 0x42, 0x84, 0x51, 0x4d, 0x98, 0x5d, 0x5e, 0xa1, 0x58, 0x76, 0x70, 0x11, 0x7f, 0x94, 0x7c, 0x33, 0x27, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x3a, 0x45, 0x41, 0x83, 0x51, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0xae, 0x91, 0x10, 0x7f, 0x93, 0x03, 0x61, 0x0d, 0x4b, 0x55, 0xb2, 0x4f, 0x45, 0x14, 0xbb, 0x38, 0x4b, 0x55, 0xb3, 0x4e, 0x45, 0x3b, 0x09, 0xfe, 0x98, 0x40, 0x01, 0x5e, 0x0d, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x14, 0xbb, 0x38, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x07, 0x01, 0x66, 0x40, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0xb8, 0x05, 0x46, 0x04, 0xc9, 0x00, 0x1a, 0x00, 0x35, 0x00, 0x39, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x01, 0x21, 0x15, 0x21, 0x05, 0x45, 0x5e, 0xa2, 0x57, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0x8b, 0x55, 0x4d, 0x98, 0x5d, 0x5e, 0xa2, 0x57, 0x65, 0x81, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0xb2, 0x2e, 0x4d, 0x98, 0xfb, 0xdb, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x4c, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x07, 0x3f, 0x4b, 0x01, 0xd2, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x07, 0x3f, 0x4b, 0xfc, 0xee, 0xaa, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0x79, 0x05, 0x46, 0x04, 0xd1, 0x00, 0x1a, 0x00, 0x35, 0x00, 0x50, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x05, 0x45, 0x5e, 0xa2, 0x57, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0x8b, 0x55, 0x4d, 0x98, 0x5d, 0x5e, 0xa2, 0x57, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0x8b, 0x55, 0x4d, 0x98, 0x5d, 0x5e, 0xa2, 0x57, 0x65, 0x81, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0xb2, 0x2e, 0x4d, 0x98, 0x01, 0xd7, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x07, 0x3f, 0x4b, 0x01, 0xd2, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x07, 0x3f, 0x4b, 0x01, 0xd2, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x07, 0x3f, 0x4b, 0x00, 0x03, 0x00, 0xc3, 0x00, 0xb8, 0x05, 0x46, 0x04, 0xc1, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x00, 0x13, 0x1e, 0x01, 0x33, 0x32, 0x3f, 0x02, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x0f, 0x01, 0x06, 0x23, 0x22, 0x26, 0x27, 0x01, 0x15, 0x21, 0x35, 0x01, 0x15, 0x21, 0x35, 0xc3, 0x5d, 0x98, 0x4e, 0x54, 0x8c, 0x13, 0x0e, 0x84, 0x63, 0x58, 0xa1, 0x5e, 0x58, 0x9b, 0x4f, 0x55, 0x8b, 0x0e, 0x05, 0x0f, 0x84, 0x63, 0x57, 0xa1, 0x5f, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0xc1, 0x55, 0x4b, 0x3f, 0x07, 0x06, 0x3b, 0x45, 0x4e, 0xb2, 0x53, 0x4c, 0x3d, 0x06, 0x02, 0x07, 0x3b, 0x45, 0x4f, 0xfe, 0xc8, 0xaa, 0xaa, 0xfe, 0x8b, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc2, 0x00, 0xd7, 0x05, 0x46, 0x04, 0x2b, 0x00, 0x09, 0x00, 0x13, 0x00, 0x00, 0x01, 0x20, 0x25, 0x35, 0x04, 0x05, 0x20, 0x25, 0x15, 0x04, 0x05, 0x20, 0x05, 0x15, 0x24, 0x25, 0x04, 0x05, 0x35, 0x24, 0x03, 0x05, 0xfe, 0xfe, 0xfe, 0xbf, 0x01, 0x43, 0x01, 0x00, 0x01, 0x09, 0x01, 0x36, 0xfe, 0xc5, 0xfe, 0xfd, 0x01, 0x07, 0x01, 0x38, 0xfe, 0xc6, 0xfe, 0xfb, 0xfe, 0xfd, 0xfe, 0xc0, 0x01, 0x44, 0x02, 0xd3, 0xa6, 0xb2, 0x95, 0x11, 0xa6, 0xb2, 0x97, 0xb3, 0xa6, 0xb2, 0x97, 0x0f, 0x02, 0xa4, 0xb2, 0x97, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x36, 0x05, 0x46, 0x04, 0xce, 0x00, 0x1c, 0x00, 0x39, 0x00, 0x00, 0x25, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x21, 0x15, 0x23, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x23, 0x35, 0x21, 0x16, 0x17, 0x16, 0x17, 0x16, 0x13, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x35, 0x33, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x33, 0x15, 0x21, 0x26, 0x27, 0x26, 0x27, 0x26, 0x03, 0x05, 0x3c, 0x29, 0x32, 0x1b, 0x18, 0x04, 0x01, 0x72, 0xef, 0x0d, 0x1a, 0x31, 0x4d, 0x50, 0xb9, 0x51, 0x4d, 0x31, 0x1b, 0x0b, 0xf0, 0x01, 0x73, 0x04, 0x18, 0x1b, 0x32, 0x29, 0x3d, 0x3d, 0x29, 0x32, 0x1b, 0x18, 0x04, 0xfe, 0x8d, 0xf0, 0x0b, 0x1b, 0x31, 0x4d, 0x51, 0xb9, 0x50, 0x4d, 0x31, 0x1a, 0x0d, 0xef, 0xfe, 0x8e, 0x04, 0x18, 0x1b, 0x32, 0x29, 0xd9, 0x04, 0x1e, 0x2c, 0x43, 0x45, 0x5b, 0xa8, 0x3c, 0x30, 0x5b, 0x32, 0x33, 0x33, 0x32, 0x5b, 0x33, 0x39, 0xa8, 0x5c, 0x44, 0x44, 0x2b, 0x1e, 0x03, 0x4e, 0x04, 0x1e, 0x2b, 0x44, 0x44, 0x5c, 0xa8, 0x39, 0x33, 0x5b, 0x32, 0x33, 0x33, 0x32, 0x5b, 0x30, 0x3c, 0xa8, 0x5b, 0x45, 0x43, 0x2c, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x04, 0xce, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x35, 0x33, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x33, 0x15, 0x21, 0x26, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x15, 0x21, 0x03, 0x05, 0x3d, 0x29, 0x32, 0x1b, 0x18, 0x04, 0xfe, 0x8d, 0xf0, 0x0b, 0x1b, 0x31, 0x4d, 0x51, 0xb9, 0x50, 0x4d, 0x31, 0x1a, 0x0d, 0xef, 0xfe, 0x8e, 0x04, 0x18, 0x1b, 0x32, 0x29, 0xfd, 0x82, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x2b, 0x04, 0x1e, 0x2b, 0x44, 0x44, 0x5c, 0xa8, 0x39, 0x33, 0x5b, 0x32, 0x33, 0x33, 0x32, 0x5b, 0x30, 0x3c, 0xa8, 0x5b, 0x45, 0x43, 0x2c, 0x1e, 0xfd, 0xe3, 0xaa, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x04, 0xff, 0x10, 0x27, 0x09, 0xa1, 0x01, 0xe0, 0x01, 0xb9, 0x10, 0x06, 0x00, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0x00, 0x02, 0x05, 0x46, 0x04, 0xff, 0x10, 0x27, 0x09, 0xa1, 0x01, 0xde, 0xfd, 0xba, 0x10, 0x26, 0x00, 0x20, 0x00, 0x00, 0x10, 0x07, 0x09, 0xa1, 0x01, 0xdf, 0x01, 0xb9, 0xff, 0xff, 0x00, 0xc3, 0x00, 0x05, 0x05, 0x48, 0x04, 0xff, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xfe, 0x01, 0xb9, 0x10, 0x26, 0x00, 0x20, 0x00, 0x00, 0x10, 0x07, 0x09, 0xa1, 0x03, 0xc5, 0xfd, 0xbd, 0xff, 0xff, 0x00, 0xc3, 0x00, 0x05, 0x05, 0x47, 0x04, 0xff, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xfe, 0xfd, 0xbd, 0x10, 0x26, 0x00, 0x20, 0x02, 0x00, 0x10, 0x07, 0x09, 0xa1, 0x03, 0xc3, 0x01, 0xb9, 0xff, 0xff, 0x00, 0xba, 0x01, 0x36, 0x06, 0x7a, 0x03, 0xcf, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xf5, 0xfe, 0xee, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xf5, 0x00, 0x89, 0x10, 0x07, 0x00, 0x20, 0x01, 0x35, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb8, 0x01, 0x36, 0x06, 0x7b, 0x03, 0xcc, 0x10, 0x26, 0x00, 0x20, 0xf5, 0x00, 0x10, 0x27, 0x09, 0xa1, 0x04, 0xf8, 0x00, 0x86, 0x10, 0x07, 0x09, 0xa1, 0x04, 0xf8, 0xfe, 0xee, 0x00, 0x02, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x03, 0xa2, 0x00, 0x09, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x06, 0x15, 0x14, 0x17, 0x33, 0x36, 0x35, 0x26, 0x27, 0x17, 0x21, 0x15, 0x21, 0x35, 0x21, 0x26, 0x35, 0x34, 0x37, 0x21, 0x35, 0x21, 0x15, 0x21, 0x16, 0x17, 0x14, 0x02, 0x9c, 0x2f, 0x2e, 0xda, 0x2f, 0x01, 0x2e, 0x7e, 0x01, 0x52, 0xfb, 0x7e, 0x01, 0x58, 0x16, 0x18, 0xfe, 0xa6, 0x04, 0x82, 0xfe, 0xaf, 0x17, 0x01, 0x02, 0xfa, 0x30, 0x49, 0x47, 0x30, 0x30, 0x47, 0x47, 0x32, 0xf0, 0xaa, 0xaa, 0x3f, 0x38, 0x3e, 0x3b, 0xa8, 0xa8, 0x1a, 0x5f, 0x38, 0x00, 0x00, 0x04, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x06, 0x15, 0x00, 0x03, 0x00, 0x07, 0x00, 0x11, 0x00, 0x20, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x32, 0x36, 0x34, 0x26, 0x27, 0x32, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0x45, 0x41, 0x5a, 0x5a, 0x83, 0x5a, 0x5b, 0x41, 0x35, 0x60, 0x24, 0x25, 0x26, 0x98, 0x6d, 0x6f, 0x93, 0x96, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x04, 0x44, 0x62, 0x46, 0x45, 0x60, 0x60, 0x8b, 0x62, 0x71, 0x2b, 0x28, 0x28, 0x64, 0x3a, 0x73, 0xa1, 0x9e, 0x76, 0x76, 0xa3, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x05, 0x4b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x15, 0x26, 0x23, 0x06, 0x07, 0x35, 0x36, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0x42, 0xe7, 0xca, 0xca, 0xe7, 0xe5, 0xce, 0xd2, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x03, 0xeb, 0x97, 0xb2, 0x97, 0x02, 0x95, 0xb2, 0x97, 0x00, 0x03, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x06, 0x7f, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x13, 0x33, 0x13, 0x23, 0x0b, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x01, 0x07, 0xea, 0xa2, 0xe9, 0x8f, 0xab, 0xa5, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x02, 0x82, 0x02, 0x9d, 0xfd, 0x63, 0x01, 0xd9, 0xfe, 0x27, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x06, 0x7f, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x23, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x01, 0x07, 0x96, 0xa5, 0xab, 0x8f, 0xe9, 0xa2, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x05, 0x1f, 0xfe, 0x27, 0x01, 0xd9, 0xfd, 0x63, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x06, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x11, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x13, 0x21, 0x1b, 0x01, 0x21, 0x07, 0x13, 0x27, 0x07, 0x13, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0xe1, 0x01, 0x0d, 0x54, 0x55, 0x01, 0x0c, 0xda, 0x55, 0xdc, 0xdb, 0x54, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x04, 0x4e, 0x01, 0x1c, 0xfe, 0xe4, 0xb0, 0xfe, 0xe4, 0xb0, 0xb0, 0x01, 0x1c, 0x00, 0x00, 0x04, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x06, 0xd4, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x03, 0x21, 0x03, 0x33, 0x01, 0x21, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0x42, 0x95, 0x01, 0x2c, 0xc8, 0x64, 0x01, 0x04, 0xfd, 0x94, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x04, 0xc0, 0xfe, 0x4e, 0x02, 0x66, 0xfd, 0x1f, 0x00, 0x07, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x06, 0x1c, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1b, 0x00, 0x30, 0x00, 0x37, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x33, 0x03, 0x15, 0x21, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x07, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x27, 0x35, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x34, 0x36, 0x33, 0x32, 0x16, 0x06, 0x14, 0x16, 0x32, 0x36, 0x34, 0x26, 0x22, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x2d, 0x38, 0x21, 0x18, 0x62, 0x62, 0x3c, 0x39, 0x39, 0x39, 0x3d, 0xd6, 0xfe, 0xee, 0x46, 0x3b, 0x23, 0x41, 0x1f, 0x20, 0x43, 0x23, 0x57, 0x65, 0x60, 0x52, 0x49, 0x55, 0x3c, 0x36, 0x2c, 0x31, 0x41, 0xb3, 0x3c, 0x3c, 0x12, 0x3a, 0x28, 0x41, 0x53, 0x53, 0x41, 0x28, 0x3a, 0xb9, 0x36, 0x5f, 0x36, 0x36, 0x5f, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x04, 0xbc, 0x37, 0x1e, 0x24, 0x24, 0x33, 0xfe, 0xa0, 0x01, 0x60, 0x33, 0x1c, 0x44, 0x3d, 0xfe, 0xaa, 0x20, 0x44, 0x48, 0x13, 0x12, 0x3e, 0x0f, 0x10, 0x70, 0x60, 0x63, 0x74, 0x69, 0x47, 0x36, 0x42, 0x3f, 0x39, 0x69, 0xda, 0xfd, 0xd0, 0x3d, 0x24, 0x23, 0x74, 0xbe, 0x75, 0x23, 0x67, 0x93, 0x53, 0x53, 0x93, 0x53, 0x00, 0x03, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x06, 0x14, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2a, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0x5c, 0x1e, 0x54, 0x38, 0x4d, 0x52, 0x50, 0x32, 0x33, 0x3e, 0x49, 0x50, 0x32, 0x34, 0x3d, 0x48, 0x51, 0x51, 0x1b, 0x4d, 0x35, 0x35, 0x4a, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x04, 0x3d, 0x3d, 0x3a, 0x78, 0x6f, 0xfe, 0xb5, 0x01, 0x48, 0x4f, 0x4d, 0x5d, 0x51, 0xfe, 0xca, 0x01, 0x48, 0x50, 0x4c, 0x5e, 0x50, 0xfe, 0xca, 0x02, 0x25, 0x55, 0x32, 0x30, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x06, 0xda, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x2c, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x33, 0x15, 0x23, 0x37, 0x23, 0x35, 0x34, 0x36, 0x3f, 0x01, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x0f, 0x01, 0x0e, 0x01, 0x07, 0x0e, 0x01, 0x15, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x01, 0xfc, 0x5b, 0x5b, 0x58, 0x56, 0x1a, 0x28, 0x29, 0x19, 0x17, 0x3b, 0x30, 0x24, 0x50, 0x2c, 0x2a, 0x57, 0x2e, 0x53, 0x65, 0x21, 0x28, 0x28, 0x15, 0x12, 0x03, 0x03, 0x03, 0x03, 0xa2, 0xa8, 0xf0, 0xaa, 0x03, 0x01, 0x7f, 0xc8, 0x4e, 0x32, 0x41, 0x2b, 0x2c, 0x1b, 0x2f, 0x18, 0x2d, 0x37, 0x23, 0x21, 0x5e, 0x1c, 0x1c, 0x61, 0x4f, 0x26, 0x45, 0x2b, 0x2b, 0x17, 0x1b, 0x0d, 0x0a, 0x1e, 0x1a, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x27, 0x05, 0x46, 0x04, 0xdd, 0x00, 0x13, 0x00, 0x00, 0x13, 0x21, 0x13, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x03, 0x27, 0x37, 0x21, 0x35, 0x21, 0x37, 0x21, 0xc3, 0x02, 0xb7, 0xe6, 0x71, 0x9d, 0x01, 0x11, 0xfe, 0x74, 0xaf, 0x02, 0x3b, 0xfd, 0x47, 0xe8, 0x70, 0x9c, 0xfe, 0xf3, 0x01, 0x8b, 0xaf, 0xfd, 0xc6, 0x03, 0xa2, 0x01, 0x3b, 0x66, 0xd5, 0xa8, 0xf0, 0xaa, 0xfe, 0xc7, 0x66, 0xd3, 0xaa, 0xf0, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0xb8, 0x05, 0x46, 0x04, 0x4c, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0xd7, 0xaa, 0x02, 0x1f, 0xaa, 0xfd, 0xc0, 0xaa, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xce, 0x05, 0x46, 0x05, 0x34, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x03, 0x39, 0xfd, 0x8a, 0x02, 0xc9, 0x73, 0x8a, 0x49, 0x01, 0x05, 0xfe, 0xa7, 0x66, 0x01, 0xbf, 0xfd, 0xf0, 0x63, 0x02, 0x73, 0xfd, 0x38, 0x74, 0x8a, 0x4a, 0xfe, 0xfa, 0x01, 0x5b, 0x64, 0xfe, 0x41, 0x02, 0x11, 0x03, 0xa2, 0xaa, 0xe8, 0x54, 0x94, 0xaa, 0xcb, 0xaa, 0xcb, 0xaa, 0xea, 0x54, 0x96, 0xaa, 0xcb, 0xaa, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x05, 0x09, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x94, 0xaa, 0x02, 0x1f, 0xaa, 0xfc, 0x4b, 0xaa, 0x02, 0x1f, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x02, 0x15, 0x01, 0x35, 0x09, 0x01, 0x21, 0x15, 0x21, 0x05, 0x45, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0xf8, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0xfc, 0x02, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x35, 0x01, 0x15, 0x01, 0x35, 0x09, 0x01, 0x15, 0x21, 0x35, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x61, 0x01, 0x21, 0xfb, 0x7e, 0x03, 0xf8, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0xfd, 0xc7, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc4, 0xff, 0x56, 0x05, 0x46, 0x05, 0x1b, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x33, 0x21, 0x15, 0x21, 0x09, 0x02, 0x15, 0x01, 0x35, 0x09, 0x01, 0x21, 0x15, 0x21, 0xc4, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0xaa, 0x05, 0x15, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0xfc, 0x02, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc4, 0xff, 0x56, 0x05, 0x46, 0x05, 0x1b, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x21, 0x15, 0x21, 0x35, 0x11, 0x35, 0x01, 0x15, 0x01, 0x35, 0x09, 0x01, 0x15, 0x21, 0x35, 0x05, 0x46, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0x01, 0x22, 0xfb, 0x7e, 0xaa, 0xaa, 0x04, 0x6b, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0xfd, 0xc7, 0xaa, 0xaa, 0x00, 0x02, 0x00, 0xc4, 0xfe, 0xb1, 0x05, 0x46, 0x05, 0x1b, 0x00, 0x13, 0x00, 0x1a, 0x00, 0x00, 0x05, 0x21, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x01, 0xf0, 0xfe, 0xd4, 0x01, 0xab, 0x56, 0xfd, 0xff, 0x02, 0x81, 0x7b, 0x7c, 0x24, 0x01, 0x2e, 0xfe, 0x52, 0x56, 0x02, 0x04, 0xfd, 0x7d, 0x7c, 0x7c, 0x03, 0x7b, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0xaa, 0xaa, 0x73, 0xaa, 0xa4, 0x73, 0x31, 0xaa, 0x73, 0xaa, 0xa5, 0x74, 0x05, 0x46, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc4, 0xfe, 0xb1, 0x05, 0x46, 0x05, 0x1b, 0x00, 0x13, 0x00, 0x1a, 0x00, 0x00, 0x05, 0x21, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x01, 0xf0, 0xfe, 0xd4, 0x01, 0xab, 0x56, 0xfd, 0xff, 0x02, 0x81, 0x7b, 0x7c, 0x24, 0x01, 0x2e, 0xfe, 0x52, 0x56, 0x02, 0x04, 0xfd, 0x7d, 0x7c, 0x7c, 0xfe, 0xf9, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0xaa, 0xaa, 0x73, 0xaa, 0xa4, 0x73, 0x31, 0xaa, 0x73, 0xaa, 0xa5, 0x74, 0x05, 0x46, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x02, 0x00, 0x85, 0x00, 0x2e, 0x07, 0x04, 0x04, 0xdf, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x05, 0x09, 0x01, 0x15, 0x01, 0x35, 0x01, 0x07, 0x04, 0xfd, 0x19, 0x02, 0xe7, 0xfc, 0x36, 0x03, 0xca, 0xfd, 0x4c, 0xfd, 0x18, 0x02, 0xe8, 0xfc, 0x36, 0x03, 0xca, 0x04, 0x11, 0xfe, 0x70, 0xfe, 0x72, 0xc5, 0x02, 0x08, 0x9f, 0x02, 0x0a, 0xce, 0xfe, 0x70, 0xfe, 0x72, 0xc5, 0x02, 0x08, 0x9f, 0x02, 0x0a, 0x00, 0x02, 0x00, 0x85, 0x00, 0x2e, 0x07, 0x04, 0x04, 0xdf, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x03, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x86, 0x03, 0xca, 0xfc, 0x36, 0x02, 0xe7, 0x33, 0x03, 0xca, 0xfc, 0x36, 0x02, 0xe7, 0x04, 0x11, 0xce, 0xfd, 0xf6, 0x9f, 0xfd, 0xf8, 0xc5, 0x01, 0x8e, 0x01, 0x90, 0xce, 0xfd, 0xf6, 0x9f, 0xfd, 0xf8, 0xc5, 0x01, 0x8e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9e, 0xfe, 0xf2, 0x02, 0xb9, 0x06, 0x12, 0x00, 0x19, 0x00, 0x27, 0x00, 0x00, 0x01, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x21, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x13, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x10, 0x17, 0x16, 0x02, 0x3c, 0x26, 0x1f, 0x50, 0x2f, 0x43, 0x43, 0x2f, 0x50, 0x1f, 0x26, 0xfe, 0xe0, 0x25, 0x1f, 0x50, 0x2f, 0x43, 0x43, 0x2f, 0x50, 0x1f, 0x25, 0x90, 0x13, 0x0f, 0x3b, 0x3a, 0x10, 0x13, 0x14, 0x10, 0x3a, 0x3b, 0x0f, 0x06, 0x12, 0x47, 0x46, 0xa3, 0x9e, 0xe2, 0xdf, 0xe0, 0xe3, 0x9e, 0xa2, 0x47, 0x47, 0x47, 0x47, 0xa2, 0x9e, 0xe3, 0xe0, 0xdf, 0xe2, 0x9e, 0xa3, 0x46, 0x47, 0xfa, 0x32, 0x3b, 0x3b, 0xe2, 0x01, 0xce, 0xe1, 0x3b, 0x3c, 0x3c, 0x3b, 0xe1, 0xfe, 0x32, 0xe2, 0x3b, 0x00, 0x00, 0x01, 0x00, 0xc2, 0x00, 0x1a, 0x05, 0x46, 0x04, 0xe8, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x06, 0x07, 0x35, 0x36, 0x3f, 0x01, 0x26, 0x25, 0x35, 0x04, 0x37, 0x13, 0x17, 0x07, 0x36, 0x37, 0x15, 0x06, 0x0f, 0x01, 0x16, 0x05, 0x15, 0x24, 0x07, 0x03, 0x27, 0x02, 0x1b, 0xa2, 0xb5, 0xee, 0xca, 0x5b, 0xf0, 0xfe, 0xdc, 0x01, 0x86, 0xe6, 0xb1, 0x85, 0x79, 0xa4, 0xb5, 0xec, 0xcd, 0x5a, 0xf5, 0x01, 0x1f, 0xfe, 0x79, 0xe6, 0xb0, 0x86, 0x01, 0x5d, 0x29, 0x5d, 0xb2, 0x6f, 0x26, 0xb6, 0x0e, 0x97, 0xb2, 0xaf, 0x0a, 0x01, 0x62, 0x52, 0xf4, 0x29, 0x60, 0xb2, 0x71, 0x25, 0xb5, 0x0d, 0x98, 0xb2, 0xaf, 0x0b, 0xfe, 0x9f, 0x52, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x05, 0x05, 0x46, 0x05, 0x64, 0x00, 0x0f, 0x00, 0x12, 0x00, 0x00, 0x01, 0x05, 0x15, 0x25, 0x03, 0x27, 0x13, 0x25, 0x35, 0x01, 0x13, 0x17, 0x07, 0x25, 0x15, 0x05, 0x07, 0x0d, 0x01, 0x03, 0x40, 0x02, 0x05, 0xfd, 0xbb, 0x8a, 0x7a, 0x85, 0xfe, 0x42, 0x02, 0xcc, 0x9b, 0x7b, 0x62, 0x01, 0x02, 0xfe, 0xa1, 0xb4, 0xfe, 0x72, 0x01, 0x1d, 0x01, 0xdf, 0xcb, 0xb6, 0xea, 0xfe, 0xbd, 0x40, 0x01, 0x36, 0xb4, 0xa6, 0x01, 0x20, 0x01, 0x6f, 0x40, 0xe6, 0x68, 0xb6, 0x8b, 0x47, 0x9d, 0x70, 0x00, 0x02, 0x00, 0xc3, 0xff, 0xa0, 0x05, 0x46, 0x04, 0xff, 0x00, 0x0f, 0x00, 0x12, 0x00, 0x00, 0x01, 0x25, 0x35, 0x05, 0x13, 0x17, 0x03, 0x05, 0x15, 0x01, 0x03, 0x27, 0x37, 0x05, 0x35, 0x25, 0x37, 0x2d, 0x01, 0x02, 0xc8, 0xfd, 0xfb, 0x02, 0x46, 0x89, 0x7a, 0x84, 0x01, 0xbd, 0xfd, 0x35, 0x9c, 0x7a, 0x62, 0xfe, 0xfd, 0x01, 0x5f, 0xb4, 0x01, 0x8e, 0xfe, 0xe4, 0x03, 0x25, 0xcb, 0xb6, 0xea, 0x01, 0x43, 0x40, 0xfe, 0xca, 0xb4, 0xa6, 0xfe, 0xe0, 0xfe, 0x91, 0x40, 0xe6, 0x68, 0xb6, 0x8b, 0x47, 0x9d, 0x70, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x2f, 0x05, 0x46, 0x05, 0x56, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x0d, 0x01, 0x03, 0x21, 0x35, 0x21, 0x13, 0x25, 0x35, 0x25, 0x13, 0x17, 0x07, 0x25, 0x15, 0x05, 0x03, 0x05, 0x15, 0x25, 0x03, 0x21, 0x15, 0x21, 0x07, 0x27, 0x03, 0x37, 0xfe, 0xae, 0x01, 0x11, 0xdc, 0xfe, 0xa9, 0x01, 0x91, 0x6c, 0xfe, 0x03, 0x02, 0xb6, 0x6a, 0x94, 0x41, 0x01, 0x0f, 0xfe, 0xaf, 0x67, 0x01, 0xb8, 0xfe, 0x12, 0x5c, 0x02, 0x4a, 0xfd, 0x7d, 0x45, 0x93, 0x03, 0x4f, 0x6c, 0x55, 0xfd, 0x72, 0xaa, 0x01, 0x43, 0xa2, 0xaa, 0xdd, 0x01, 0x40, 0x3d, 0xc7, 0x56, 0xb0, 0x6c, 0xfe, 0xd1, 0x8c, 0xb2, 0x9e, 0xfe, 0xed, 0xaa, 0xd1, 0x3d, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x2f, 0x05, 0x46, 0x05, 0x56, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x37, 0x27, 0x01, 0x23, 0x35, 0x21, 0x37, 0x05, 0x35, 0x25, 0x37, 0x25, 0x35, 0x05, 0x13, 0x17, 0x03, 0x05, 0x15, 0x05, 0x03, 0x21, 0x15, 0x21, 0x07, 0x27, 0x03, 0x36, 0xee, 0xc0, 0xfe, 0x4d, 0xee, 0x01, 0x27, 0x4e, 0xfe, 0x8b, 0x01, 0xb7, 0x52, 0xfd, 0xf7, 0x02, 0x3f, 0x77, 0x94, 0x73, 0x01, 0xab, 0xfd, 0xaf, 0x62, 0x02, 0xb3, 0xfd, 0x14, 0x46, 0x94, 0x02, 0x97, 0x4c, 0x3e, 0xfc, 0xdf, 0xaa, 0xec, 0x77, 0xb2, 0x8b, 0xf5, 0xa7, 0xb0, 0xb7, 0x01, 0x65, 0x3d, 0xfe, 0xa8, 0x88, 0xaa, 0xbd, 0xfe, 0xd8, 0xaa, 0xd1, 0x3d, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x90, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x1d, 0x00, 0x24, 0x00, 0x00, 0x25, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x13, 0x09, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x57, 0x63, 0x84, 0x09, 0x06, 0x05, 0x0e, 0x8b, 0x55, 0x4f, 0x9b, 0x58, 0x5e, 0xa1, 0x58, 0x63, 0x84, 0x0a, 0x04, 0x06, 0x0d, 0x8c, 0x54, 0x4e, 0x98, 0x5c, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0xf0, 0xb4, 0x4e, 0x44, 0x3a, 0x04, 0x04, 0x02, 0x06, 0x3c, 0x4c, 0x54, 0xb4, 0x4e, 0x44, 0x3a, 0x06, 0x02, 0x02, 0x06, 0x3c, 0x4a, 0x03, 0x5e, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc4, 0xff, 0xb0, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x1b, 0x00, 0x22, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x33, 0x32, 0x36, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x0b, 0x0e, 0x8b, 0x55, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x63, 0x85, 0x09, 0x0b, 0x0d, 0x8c, 0x55, 0x4d, 0x97, 0xfb, 0xdc, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x61, 0x01, 0x0e, 0xb2, 0x4e, 0x46, 0x3c, 0x04, 0x04, 0x06, 0x3e, 0x4c, 0x54, 0xb2, 0x4e, 0x46, 0x3c, 0x04, 0x04, 0x06, 0x3e, 0x4c, 0x03, 0x3e, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x29, 0x05, 0x46, 0x05, 0x50, 0x00, 0x31, 0x00, 0x34, 0x00, 0x00, 0x25, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x13, 0x25, 0x35, 0x25, 0x13, 0x17, 0x07, 0x25, 0x15, 0x05, 0x03, 0x05, 0x15, 0x25, 0x03, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x07, 0x27, 0x01, 0x0d, 0x01, 0x02, 0x2d, 0x1b, 0x0c, 0x4f, 0x9b, 0x58, 0x5e, 0xa1, 0x58, 0x22, 0x27, 0x60, 0xfd, 0xff, 0x02, 0xbb, 0x69, 0x95, 0x3f, 0x01, 0x08, 0xfe, 0xb4, 0x67, 0x01, 0xb3, 0xfe, 0x17, 0x60, 0x06, 0x0a, 0x04, 0x06, 0x0d, 0x8c, 0x54, 0x4e, 0x98, 0x5d, 0x5f, 0xa1, 0x57, 0x63, 0x84, 0x09, 0x06, 0x05, 0x0e, 0x1f, 0x48, 0x95, 0x01, 0x51, 0xfe, 0xaa, 0x01, 0x13, 0x2d, 0x03, 0x4c, 0x54, 0xb4, 0x4e, 0x44, 0x07, 0x01, 0x1d, 0xa3, 0xaa, 0xde, 0x01, 0x39, 0x41, 0xbb, 0x54, 0xb0, 0x6a, 0xfe, 0xcd, 0x8a, 0xb2, 0x9c, 0xfe, 0xe3, 0x02, 0x06, 0x02, 0x02, 0x06, 0x3c, 0x4a, 0x56, 0xb4, 0x4e, 0x44, 0x3a, 0x04, 0x04, 0x02, 0x06, 0x0d, 0xd8, 0x3c, 0x03, 0xec, 0x6e, 0x57, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x2f, 0x05, 0x46, 0x05, 0x56, 0x00, 0x31, 0x00, 0x34, 0x00, 0x00, 0x01, 0x05, 0x15, 0x05, 0x07, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x03, 0x27, 0x37, 0x06, 0x07, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x3f, 0x01, 0x05, 0x35, 0x25, 0x37, 0x25, 0x35, 0x05, 0x13, 0x17, 0x03, 0x37, 0x27, 0x03, 0xa1, 0x01, 0xa4, 0xfd, 0xb6, 0x54, 0x2b, 0x30, 0x0a, 0x04, 0x06, 0x0d, 0x8c, 0x54, 0x4e, 0x98, 0x5d, 0x5f, 0xa1, 0x57, 0x63, 0x84, 0x09, 0x06, 0x05, 0x0e, 0x41, 0x34, 0x5e, 0x94, 0x4e, 0x32, 0x32, 0x4d, 0x58, 0x5e, 0x51, 0x45, 0x4b, 0x36, 0xfe, 0x8a, 0x01, 0xb8, 0x55, 0xfd, 0xf3, 0x02, 0x43, 0x73, 0x94, 0xd1, 0xe8, 0xb9, 0x03, 0xbf, 0x86, 0xaa, 0xbb, 0xf7, 0x0d, 0x16, 0x04, 0x02, 0x02, 0x06, 0x3e, 0x4c, 0x54, 0xb2, 0x4e, 0x46, 0x3c, 0x04, 0x02, 0x02, 0x06, 0x1d, 0x0f, 0xfe, 0xf1, 0x3d, 0xdf, 0x09, 0x18, 0x26, 0x54, 0xb2, 0x4e, 0x23, 0x1e, 0x04, 0xa1, 0x77, 0xb2, 0x8b, 0xf4, 0xa8, 0xb0, 0xb8, 0x01, 0x66, 0x3d, 0xfd, 0x80, 0x4a, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xbb, 0xff, 0x4e, 0x05, 0x46, 0x05, 0x7d, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x35, 0x01, 0x15, 0x01, 0x35, 0x09, 0x03, 0x15, 0x01, 0x35, 0x01, 0xc4, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0x01, 0x19, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0x02, 0x27, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x03, 0xbb, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x02, 0x00, 0xbb, 0xff, 0x4e, 0x05, 0x46, 0x05, 0x7d, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x09, 0x02, 0x15, 0x01, 0x35, 0x09, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x3d, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x87, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0x02, 0x27, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x01, 0xf6, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x00, 0x03, 0x00, 0xbb, 0xfe, 0x6d, 0x05, 0x46, 0x06, 0x60, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x21, 0x00, 0x00, 0x2d, 0x02, 0x03, 0x25, 0x35, 0x25, 0x13, 0x17, 0x03, 0x25, 0x15, 0x05, 0x03, 0x05, 0x15, 0x25, 0x07, 0x05, 0x15, 0x05, 0x03, 0x27, 0x13, 0x05, 0x35, 0x25, 0x13, 0x25, 0x35, 0x05, 0x13, 0x0d, 0x01, 0x02, 0xf8, 0x01, 0x2c, 0xfe, 0xfa, 0x57, 0xfd, 0xf4, 0x02, 0x7c, 0x51, 0x95, 0x3e, 0x01, 0x5e, 0xfe, 0x7a, 0x3a, 0x01, 0xc0, 0xfe, 0x1d, 0x1a, 0x02, 0x06, 0xfd, 0x8c, 0x51, 0x96, 0x3e, 0xfe, 0x9b, 0x01, 0x8d, 0x39, 0xfe, 0x3a, 0x01, 0xe9, 0x62, 0xfe, 0xce, 0x01, 0x0d, 0xb3, 0x5f, 0x54, 0x01, 0x57, 0xa7, 0xaa, 0xca, 0x01, 0x88, 0x26, 0xfe, 0xd4, 0x6f, 0xb0, 0x7d, 0xfe, 0xe4, 0x8e, 0xb2, 0x9a, 0x81, 0xa5, 0xaa, 0xc8, 0xfe, 0x77, 0x26, 0x01, 0x2d, 0x72, 0xb2, 0x7e, 0x01, 0x18, 0x91, 0xb0, 0x9b, 0x01, 0xde, 0x62, 0x55, 0x00, 0x00, 0x00, 0x03, 0x00, 0xbb, 0xfe, 0x6d, 0x05, 0x46, 0x06, 0x60, 0x00, 0x02, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x01, 0x07, 0x17, 0x01, 0x37, 0x2f, 0x01, 0x25, 0x35, 0x05, 0x13, 0x17, 0x03, 0x05, 0x15, 0x05, 0x07, 0x25, 0x15, 0x05, 0x07, 0x05, 0x15, 0x25, 0x03, 0x27, 0x13, 0x25, 0x35, 0x25, 0x37, 0x05, 0x35, 0x25, 0x02, 0x7a, 0x9d, 0x89, 0x01, 0x29, 0x95, 0x83, 0x94, 0xfd, 0xb7, 0x02, 0x6c, 0x58, 0x95, 0x5a, 0x01, 0x83, 0xfe, 0x21, 0x1e, 0x01, 0xf4, 0xfd, 0xe5, 0x28, 0x02, 0x43, 0xfd, 0x9b, 0x57, 0x96, 0x59, 0xfe, 0x77, 0x01, 0xe6, 0x1e, 0xfe, 0x05, 0x02, 0x22, 0x01, 0x44, 0x32, 0x2c, 0x02, 0xa3, 0x2f, 0x2a, 0x2f, 0xbc, 0xb0, 0xc5, 0x01, 0xa8, 0x26, 0xfe, 0x4f, 0x7b, 0xaa, 0x98, 0x94, 0x9f, 0xb0, 0xad, 0xc2, 0xb8, 0xb2, 0xc4, 0xfe, 0x5b, 0x26, 0x01, 0xae, 0x7d, 0xaa, 0x9a, 0x94, 0xa2, 0xb2, 0xad, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xb2, 0x05, 0x46, 0x05, 0x50, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x05, 0x04, 0x01, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x05, 0x45, 0xfe, 0x9a, 0xfe, 0x27, 0x01, 0xd5, 0x01, 0x6a, 0xfe, 0x97, 0xfc, 0xe7, 0x03, 0x1b, 0x01, 0x67, 0x04, 0x61, 0xfe, 0x81, 0x61, 0x5e, 0xfe, 0x7e, 0xef, 0x02, 0x00, 0x7c, 0xa6, 0x7c, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xb2, 0x05, 0x46, 0x05, 0x50, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x00, 0x25, 0x24, 0xc3, 0x01, 0x67, 0x03, 0x1b, 0xfc, 0xe7, 0xfe, 0x97, 0x01, 0x6a, 0x01, 0xd5, 0xfe, 0x27, 0x04, 0x61, 0xef, 0xfe, 0x00, 0x7c, 0xa6, 0x7c, 0xfe, 0x00, 0xef, 0x01, 0x82, 0x5e, 0x61, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x29, 0x05, 0x46, 0x05, 0x57, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x21, 0x15, 0x00, 0x25, 0x35, 0x04, 0x01, 0x00, 0x05, 0x04, 0x01, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x05, 0x45, 0xfe, 0x90, 0xfc, 0xee, 0x03, 0x01, 0x01, 0x81, 0xfe, 0xa7, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x59, 0xfe, 0xa7, 0xfc, 0xd7, 0x03, 0x29, 0x01, 0x59, 0xd7, 0x01, 0xbe, 0x91, 0xae, 0x85, 0x02, 0xdf, 0xfe, 0xe5, 0x5d, 0x5d, 0xfe, 0xe5, 0xd7, 0x01, 0x78, 0x84, 0xa6, 0x7c, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x29, 0x05, 0x46, 0x05, 0x57, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x33, 0x00, 0x25, 0x15, 0x04, 0x01, 0x11, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x00, 0x25, 0x24, 0xc3, 0x01, 0x81, 0x03, 0x01, 0xfc, 0xee, 0xfe, 0x90, 0x01, 0x59, 0x03, 0x29, 0xfc, 0xd7, 0xfe, 0xa7, 0x01, 0x59, 0x01, 0xac, 0xfe, 0x54, 0x01, 0xa1, 0x85, 0xae, 0x91, 0xfe, 0x42, 0x05, 0x57, 0xd7, 0xfe, 0x80, 0x7c, 0xa6, 0x84, 0xfe, 0x88, 0xd7, 0x01, 0x1b, 0x5d, 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x52, 0x05, 0x46, 0x05, 0x57, 0x00, 0x1d, 0x00, 0x28, 0x00, 0x00, 0x25, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x13, 0x00, 0x05, 0x04, 0x01, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x09, 0x05, 0x05, 0x0e, 0x8b, 0x55, 0x4d, 0x98, 0x5d, 0xfe, 0xa7, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x59, 0xfe, 0xa7, 0xfc, 0xd7, 0x03, 0x29, 0x01, 0x59, 0xb1, 0xb3, 0x4e, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x3b, 0x05, 0x02, 0x02, 0x06, 0x3d, 0x4b, 0x04, 0x24, 0xfe, 0xe5, 0x5d, 0x5d, 0xfe, 0xe5, 0xd7, 0x01, 0x78, 0x84, 0xa6, 0x7c, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x52, 0x05, 0x46, 0x05, 0x57, 0x00, 0x1d, 0x00, 0x28, 0x00, 0x00, 0x25, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x01, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x00, 0x25, 0x24, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x09, 0x05, 0x05, 0x0e, 0x8b, 0x55, 0x4d, 0x98, 0xfb, 0xdb, 0x01, 0x59, 0x03, 0x29, 0xfc, 0xd7, 0xfe, 0xa7, 0x01, 0x59, 0x01, 0xac, 0xfe, 0x54, 0xb1, 0xb3, 0x4e, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x3b, 0x05, 0x02, 0x02, 0x06, 0x3d, 0x4b, 0x04, 0x24, 0xd7, 0xfe, 0x80, 0x7c, 0xa6, 0x84, 0xfe, 0x88, 0xd7, 0x01, 0x1b, 0x5d, 0x5d, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x83, 0x05, 0x46, 0x06, 0x1d, 0x00, 0x15, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x26, 0x25, 0x35, 0x24, 0x25, 0x01, 0x17, 0x03, 0x36, 0x37, 0x15, 0x06, 0x07, 0x03, 0x04, 0x17, 0x15, 0x02, 0x25, 0x03, 0x27, 0x01, 0x06, 0x07, 0x16, 0x17, 0x02, 0xa3, 0xd8, 0xfe, 0xf8, 0x01, 0x96, 0x01, 0x25, 0x01, 0x01, 0x76, 0xa7, 0x8e, 0x69, 0xa7, 0xc1, 0x7d, 0x01, 0x06, 0xdf, 0xcc, 0xfe, 0xa8, 0xd3, 0x76, 0x01, 0x47, 0x88, 0x91, 0x71, 0x6a, 0x01, 0xb0, 0x55, 0x29, 0xa6, 0x3f, 0xa5, 0x02, 0x65, 0x4b, 0xfe, 0x74, 0x75, 0x95, 0xef, 0xb3, 0x75, 0xfe, 0xd4, 0x7f, 0xed, 0xef, 0x01, 0x22, 0xa6, 0xfe, 0x09, 0x4b, 0x03, 0x0a, 0x39, 0x1e, 0x17, 0x27, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0xe5, 0x05, 0x46, 0x05, 0x7f, 0x00, 0x15, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x16, 0x05, 0x15, 0x04, 0x05, 0x01, 0x27, 0x13, 0x06, 0x07, 0x35, 0x36, 0x37, 0x13, 0x24, 0x27, 0x35, 0x12, 0x05, 0x13, 0x17, 0x01, 0x36, 0x37, 0x26, 0x27, 0x03, 0x65, 0xd8, 0x01, 0x08, 0xfe, 0x6a, 0xfe, 0xdc, 0xfe, 0xfe, 0x76, 0xa7, 0x8e, 0x69, 0xa8, 0xc0, 0x7e, 0xfe, 0xf9, 0xdf, 0xcd, 0x01, 0x57, 0xd4, 0x75, 0xfe, 0xb9, 0x88, 0x91, 0x70, 0x6a, 0x03, 0x52, 0x55, 0x29, 0xa6, 0x3f, 0xa5, 0xfd, 0x9b, 0x4b, 0x01, 0x8c, 0x75, 0x95, 0xef, 0xb3, 0x75, 0x01, 0x2c, 0x7f, 0xed, 0xef, 0xfe, 0xde, 0xa6, 0x01, 0xf7, 0x4b, 0xfc, 0xf6, 0x39, 0x1e, 0x17, 0x27, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb7, 0x00, 0xa3, 0x05, 0x51, 0x04, 0x5f, 0x00, 0x13, 0x00, 0x00, 0x25, 0x21, 0x22, 0x02, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x15, 0x21, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x21, 0x05, 0x51, 0xfd, 0x15, 0xb6, 0xf8, 0x7c, 0x7c, 0xb4, 0x02, 0xed, 0xfd, 0x13, 0x7a, 0xab, 0x54, 0x57, 0x7a, 0x02, 0xed, 0xa3, 0x01, 0x16, 0xc8, 0xc6, 0x8d, 0x8b, 0x96, 0xc0, 0x88, 0x8a, 0x5e, 0x60, 0x00, 0x00, 0x01, 0x00, 0xb7, 0x00, 0xa3, 0x05, 0x51, 0x04, 0x5f, 0x00, 0x13, 0x00, 0x00, 0x37, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x21, 0x35, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x02, 0x23, 0xb8, 0x02, 0xec, 0x7b, 0x56, 0x55, 0xab, 0x7b, 0xfd, 0x14, 0x02, 0xec, 0xb4, 0x7d, 0x7c, 0xf9, 0xb5, 0xa3, 0x96, 0x60, 0x5e, 0x8a, 0x88, 0xc0, 0x96, 0x8b, 0x8d, 0xc6, 0xc8, 0xfe, 0xea, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb7, 0xff, 0x3b, 0x05, 0x51, 0x05, 0xcf, 0x00, 0x09, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x1b, 0x01, 0x33, 0x03, 0x21, 0x15, 0x21, 0x03, 0x21, 0x15, 0x21, 0x03, 0x23, 0x13, 0x22, 0x02, 0x35, 0x34, 0x37, 0x36, 0x33, 0x03, 0x45, 0xe1, 0x7a, 0xab, 0x54, 0x57, 0x7a, 0x2b, 0xdf, 0x67, 0x99, 0x67, 0x01, 0x4a, 0xfe, 0x8d, 0xb6, 0x02, 0x29, 0xfd, 0xae, 0x65, 0x99, 0x65, 0xb4, 0xfa, 0x7c, 0x7c, 0xb4, 0x03, 0xc9, 0xc0, 0x88, 0x8a, 0x5e, 0x60, 0x03, 0x26, 0x01, 0x70, 0xfe, 0x90, 0x96, 0xfd, 0x70, 0x96, 0xfe, 0x98, 0x01, 0x68, 0x01, 0x16, 0xc8, 0xc6, 0x8d, 0x8b, 0x00, 0x02, 0x00, 0xb7, 0xff, 0x33, 0x05, 0x51, 0x05, 0xc7, 0x00, 0x09, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x0b, 0x01, 0x23, 0x13, 0x21, 0x35, 0x21, 0x13, 0x21, 0x35, 0x21, 0x13, 0x33, 0x03, 0x32, 0x12, 0x15, 0x14, 0x07, 0x06, 0x23, 0x02, 0xc3, 0xe1, 0x7b, 0xab, 0x55, 0x56, 0x7b, 0x2b, 0xdf, 0x67, 0x99, 0x67, 0xfe, 0xb7, 0x01, 0x72, 0xb6, 0xfd, 0xd8, 0x02, 0x52, 0x64, 0x99, 0x64, 0xb4, 0xfa, 0x7c, 0x7d, 0xb4, 0x01, 0x39, 0xc0, 0x88, 0x8a, 0x5e, 0x60, 0xfc, 0xda, 0xfe, 0x90, 0x01, 0x70, 0x96, 0x02, 0x90, 0x96, 0x01, 0x68, 0xfe, 0x98, 0xfe, 0xea, 0xc8, 0xc6, 0x8d, 0x8b, 0x00, 0x02, 0x00, 0xab, 0x00, 0x00, 0x05, 0x46, 0x04, 0xe8, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x37, 0x21, 0x15, 0x21, 0x01, 0x21, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x15, 0x21, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x21, 0xda, 0x04, 0x6b, 0xfb, 0x95, 0x04, 0x6b, 0xfd, 0x14, 0xb5, 0x7c, 0x7d, 0x7d, 0x7c, 0xb4, 0x02, 0xed, 0xfd, 0x13, 0x7b, 0xab, 0x56, 0x56, 0x7a, 0x02, 0xed, 0x96, 0x96, 0x01, 0x2c, 0x8b, 0x8b, 0xc8, 0xc6, 0x8d, 0x8b, 0x96, 0xc0, 0x88, 0x8a, 0x5e, 0x60, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x5e, 0x04, 0xe8, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x37, 0x21, 0x15, 0x21, 0x11, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x21, 0x35, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0xc3, 0x04, 0x6c, 0xfb, 0x94, 0x02, 0xed, 0x7a, 0x57, 0x55, 0xab, 0x7b, 0xfd, 0x13, 0x02, 0xed, 0xb4, 0x7c, 0x7d, 0x7d, 0x7c, 0xb5, 0x96, 0x96, 0x01, 0x2c, 0x96, 0x60, 0x5e, 0x8a, 0x88, 0xc0, 0x96, 0x8b, 0x8d, 0xc6, 0xc8, 0x8b, 0x8b, 0x00, 0x02, 0x00, 0xab, 0xff, 0x13, 0x05, 0x46, 0x05, 0xd7, 0x00, 0x09, 0x00, 0x27, 0x00, 0x00, 0x01, 0x21, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x02, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x23, 0x35, 0x21, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x03, 0x6f, 0xfe, 0xe9, 0x7b, 0xab, 0x56, 0x56, 0x7a, 0x23, 0x8d, 0x02, 0x3d, 0xfd, 0x8b, 0x37, 0x02, 0xac, 0xfd, 0x1c, 0x58, 0x79, 0x45, 0xfb, 0x01, 0x32, 0x38, 0xa7, 0x75, 0x7d, 0x7d, 0x7c, 0xb4, 0x01, 0x4f, 0x58, 0x79, 0x44, 0x01, 0x11, 0xfe, 0xb7, 0x04, 0x52, 0xc0, 0x88, 0x8a, 0x5e, 0x60, 0x96, 0x96, 0x96, 0xed, 0x35, 0xb8, 0x96, 0x96, 0x08, 0x83, 0x8b, 0xc8, 0xc6, 0x8d, 0x8b, 0xef, 0x37, 0xb8, 0x96, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x13, 0x05, 0x5e, 0x05, 0xd7, 0x00, 0x09, 0x00, 0x27, 0x00, 0x00, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2f, 0x01, 0x21, 0x35, 0x21, 0x37, 0x17, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x03, 0x08, 0xa8, 0x7a, 0x57, 0x55, 0x55, 0x3b, 0x4e, 0x89, 0xfd, 0x54, 0x02, 0xe4, 0x58, 0x79, 0x4c, 0x66, 0x4e, 0x7d, 0x7d, 0x7c, 0xb5, 0xde, 0x38, 0x02, 0x96, 0xfd, 0x32, 0x58, 0x79, 0x45, 0xfe, 0xee, 0x01, 0x49, 0x38, 0xfe, 0x7f, 0x01, 0xb8, 0x01, 0xc2, 0x60, 0x5e, 0x8a, 0x88, 0x60, 0x43, 0x14, 0x09, 0x96, 0xef, 0x37, 0xcb, 0x20, 0x58, 0x8d, 0xc6, 0xc8, 0x8b, 0x8b, 0x96, 0x96, 0xed, 0x35, 0xb8, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0xab, 0xff, 0x6a, 0x05, 0x46, 0x04, 0xe9, 0x00, 0x0b, 0x00, 0x20, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x01, 0x21, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x15, 0x21, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x21, 0x02, 0x7d, 0xfe, 0x5d, 0x02, 0x08, 0x66, 0x6c, 0x28, 0x01, 0xb9, 0xfd, 0xe1, 0x65, 0x6c, 0x02, 0xf0, 0xfd, 0x14, 0xb5, 0x7c, 0x7d, 0x7d, 0x7c, 0xb4, 0x02, 0xed, 0xfd, 0x13, 0x7b, 0xab, 0x56, 0x56, 0x7a, 0x02, 0xed, 0x96, 0x96, 0x5a, 0x3c, 0x96, 0x96, 0x5a, 0x01, 0x69, 0x8b, 0x8b, 0xc8, 0xc6, 0x8d, 0x8b, 0x96, 0xc0, 0x88, 0x8a, 0x5e, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0xab, 0xff, 0x6a, 0x05, 0x46, 0x04, 0xe9, 0x00, 0x0b, 0x00, 0x20, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x21, 0x35, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x02, 0x7d, 0xfe, 0x5d, 0x02, 0x08, 0x66, 0x6c, 0x28, 0x01, 0xb9, 0xfd, 0xe1, 0x65, 0x6c, 0xfe, 0x56, 0x02, 0xed, 0x7a, 0x57, 0x55, 0xab, 0x7b, 0xfd, 0x13, 0x02, 0xed, 0xb4, 0x7c, 0x7d, 0x7d, 0x7c, 0xb5, 0x96, 0x96, 0x5a, 0x3c, 0x96, 0x96, 0x5a, 0x01, 0x69, 0x96, 0x60, 0x5e, 0x8a, 0x88, 0xc0, 0x96, 0x8b, 0x8d, 0xc6, 0xc8, 0x8b, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xed, 0x00, 0x00, 0x04, 0x58, 0x04, 0xa2, 0x00, 0x11, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x37, 0x35, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x17, 0x07, 0xee, 0x9a, 0x86, 0x95, 0x95, 0x85, 0x9b, 0xdd, 0xd8, 0xd9, 0xdc, 0xd6, 0xb0, 0x36, 0x68, 0x01, 0x3f, 0xfe, 0xc1, 0x68, 0x36, 0x02, 0x52, 0x02, 0x50, 0xfd, 0xc9, 0xf4, 0xd3, 0xd3, 0xf4, 0x02, 0x37, 0xfd, 0xb0, 0xfe, 0xd8, 0xfe, 0xd6, 0x01, 0x2a, 0xca, 0x2d, 0xc5, 0x3c, 0x75, 0x55, 0x74, 0x3c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xed, 0x00, 0x00, 0x04, 0x58, 0x04, 0xa2, 0x10, 0x26, 0x09, 0x06, 0x00, 0x00, 0x10, 0x07, 0x09, 0xa1, 0x01, 0x7e, 0xff, 0x33, 0x00, 0x02, 0x00, 0xed, 0x00, 0x05, 0x04, 0x58, 0x04, 0xa7, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x01, 0x15, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0xee, 0x9a, 0x86, 0x95, 0x95, 0x85, 0x9b, 0xdd, 0xd8, 0xd9, 0xdc, 0x01, 0xe2, 0x99, 0x99, 0x5b, 0x99, 0x99, 0x02, 0x57, 0x02, 0x50, 0xfd, 0xc9, 0xf4, 0xd3, 0xd3, 0xf4, 0x02, 0x37, 0xfd, 0xb0, 0xfe, 0xd8, 0xfe, 0xd6, 0x01, 0x2a, 0x01, 0xe1, 0xab, 0x64, 0xab, 0xab, 0x64, 0xab, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x04, 0x8b, 0x00, 0x07, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0xc3, 0x04, 0x82, 0xfc, 0x17, 0x03, 0xe9, 0xfb, 0x7e, 0x04, 0x8b, 0xaa, 0xfc, 0xc9, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x04, 0x8b, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x05, 0x45, 0xfb, 0x7e, 0x03, 0xe9, 0xfc, 0x17, 0x04, 0x8b, 0xfb, 0x75, 0xaa, 0x03, 0x37, 0xaa, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x56, 0x05, 0x46, 0x05, 0x0b, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0xc3, 0x04, 0x82, 0xfc, 0x17, 0x03, 0xe9, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x05, 0x0b, 0xaa, 0xfc, 0xc9, 0xaa, 0x80, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x56, 0x05, 0x46, 0x05, 0x0b, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x01, 0x15, 0x21, 0x35, 0x05, 0x45, 0xfb, 0x7e, 0x03, 0xe9, 0xfc, 0x17, 0x04, 0x82, 0xfb, 0x7e, 0x05, 0x0b, 0xfb, 0x75, 0xaa, 0x03, 0x37, 0xaa, 0xfa, 0xf5, 0xaa, 0xaa, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x00, 0x04, 0xdb, 0x05, 0x02, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x04, 0xdb, 0x99, 0xfd, 0x1a, 0x99, 0x05, 0x02, 0xfa, 0xfe, 0x04, 0x58, 0xfb, 0xa8, 0x05, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x00, 0x04, 0xdb, 0x05, 0x02, 0x00, 0x07, 0x00, 0x00, 0x33, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0xc3, 0x99, 0x02, 0xe6, 0x99, 0x05, 0x02, 0xfb, 0xa8, 0x04, 0x58, 0xfa, 0xfe, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x19, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x05, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x03, 0x64, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x01, 0x9f, 0x01, 0x40, 0xfe, 0xc0, 0x99, 0xfe, 0xbf, 0x01, 0x41, 0x04, 0x8e, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0x84, 0xfe, 0x9b, 0xaa, 0xfe, 0x9b, 0x01, 0x65, 0xaa, 0x01, 0x65, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x37, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x77, 0x03, 0x1a, 0xfc, 0xe6, 0x01, 0xed, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x02, 0xd7, 0xaa, 0x02, 0x61, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x19, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x07, 0x17, 0x07, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x03, 0x64, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x02, 0xa2, 0xe4, 0xe3, 0x6c, 0xe3, 0xe3, 0x6d, 0xe4, 0xe3, 0x6c, 0xe3, 0xe3, 0x04, 0x8e, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0xfe, 0xbe, 0xfc, 0xfc, 0x78, 0xfc, 0xfd, 0x79, 0xfc, 0xfc, 0x78, 0xfc, 0xfd, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x37, 0x00, 0x00, 0x09, 0x01, 0x17, 0x01, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0xb5, 0x02, 0x32, 0x6c, 0xfd, 0xce, 0x01, 0x43, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x01, 0x86, 0x02, 0x70, 0x78, 0xfd, 0x90, 0x03, 0x80, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x37, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x12, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x02, 0xa5, 0xbe, 0xbe, 0xbf, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x03, 0x01, 0xfe, 0x02, 0x8b, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0x00, 0x00, 0x04, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x09, 0x00, 0x18, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x32, 0x36, 0x34, 0x26, 0x27, 0x32, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x04, 0x48, 0x63, 0x63, 0x90, 0x63, 0x64, 0x47, 0x3a, 0x6a, 0x27, 0x29, 0x2a, 0xa7, 0x79, 0x79, 0xa2, 0xa5, 0xd8, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x03, 0x41, 0x6f, 0x50, 0x4f, 0x6d, 0x6d, 0x9e, 0x70, 0x81, 0x31, 0x2e, 0x2d, 0x72, 0x42, 0x84, 0xb7, 0xb4, 0x87, 0x86, 0xba, 0xcc, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x11, 0x00, 0x2b, 0x00, 0x45, 0x00, 0x00, 0x01, 0x0d, 0x01, 0x07, 0x25, 0x11, 0x23, 0x11, 0x05, 0x27, 0x2d, 0x01, 0x37, 0x05, 0x11, 0x33, 0x11, 0x25, 0x02, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x04, 0x72, 0xfe, 0xdd, 0x01, 0x23, 0x2f, 0xfe, 0xef, 0x5c, 0xfe, 0xf0, 0x2f, 0x01, 0x23, 0xfe, 0xdd, 0x2f, 0x01, 0x10, 0x5c, 0x01, 0x11, 0xdf, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x03, 0x31, 0xaf, 0xb0, 0x58, 0xb7, 0xfe, 0xad, 0x01, 0x53, 0xb7, 0x58, 0xb0, 0xaf, 0x59, 0xb7, 0x01, 0x53, 0xfe, 0xad, 0xb7, 0x01, 0x04, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0x00, 0x00, 0x00, 0x04, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x21, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0xe4, 0x02, 0x40, 0xfd, 0xc0, 0x02, 0x40, 0xfd, 0xc0, 0x01, 0x80, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x03, 0x6a, 0x88, 0xc0, 0x88, 0x02, 0xf4, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x19, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x13, 0x21, 0x15, 0x21, 0x03, 0x64, 0xc0, 0x54, 0x53, 0x44, 0x45, 0x45, 0x45, 0x45, 0x44, 0x53, 0x54, 0xc0, 0x54, 0x53, 0x44, 0x46, 0x44, 0x44, 0x46, 0x44, 0x53, 0xfe, 0xd0, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x2c, 0x2c, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x5a, 0x2c, 0x2c, 0x2c, 0x2c, 0x5a, 0x58, 0x32, 0x02, 0x41, 0xfd, 0xbf, 0x04, 0x8e, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6d, 0x6a, 0xb8, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0xb8, 0x6a, 0x6d, 0xb8, 0x4d, 0x4c, 0x27, 0xbd, 0x64, 0x62, 0x63, 0x77, 0x76, 0x8c, 0x89, 0x77, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x77, 0x89, 0x8c, 0x76, 0x77, 0x63, 0x62, 0xfe, 0x17, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x01, 0x2f, 0x03, 0xaa, 0xfb, 0xcf, 0x04, 0xb8, 0xfb, 0x48, 0x02, 0xa9, 0x01, 0x40, 0xfe, 0xc0, 0x99, 0xfe, 0xbf, 0x01, 0x41, 0x04, 0x89, 0xfb, 0xf0, 0x04, 0x10, 0x9b, 0xfa, 0xbf, 0x04, 0x59, 0xfe, 0x9b, 0xaa, 0xfe, 0x9b, 0x01, 0x65, 0xaa, 0x01, 0x65, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x03, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x77, 0x03, 0x1a, 0xfc, 0xe6, 0x48, 0x03, 0xaa, 0xfb, 0xcf, 0x04, 0xb8, 0xfb, 0x48, 0x02, 0xd7, 0xaa, 0x02, 0x5c, 0xfb, 0xf0, 0x04, 0x10, 0x9b, 0xfa, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x09, 0x02, 0x07, 0x09, 0x01, 0x27, 0x09, 0x01, 0x37, 0x09, 0x01, 0x25, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x04, 0xb7, 0xfe, 0xb9, 0x01, 0x47, 0x6d, 0xfe, 0xba, 0xfe, 0xba, 0x6c, 0x01, 0x46, 0xfe, 0xba, 0x6c, 0x01, 0x46, 0x01, 0x46, 0xfc, 0xe5, 0x03, 0xaa, 0xfb, 0xcf, 0x04, 0xb8, 0xfb, 0x48, 0x03, 0xec, 0xfe, 0x96, 0xfe, 0x96, 0x78, 0x01, 0x6a, 0xfe, 0x95, 0x79, 0x01, 0x6a, 0x01, 0x6a, 0x79, 0xfe, 0x95, 0x01, 0x6b, 0x24, 0xfb, 0xf0, 0x04, 0x10, 0x9b, 0xfa, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x01, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x02, 0xa5, 0xbe, 0xbe, 0xfe, 0x8a, 0x03, 0xaa, 0xfb, 0xcf, 0x04, 0xb8, 0xfb, 0x48, 0x03, 0x01, 0xfe, 0x02, 0x86, 0xfb, 0xf0, 0x04, 0x10, 0x9b, 0xfa, 0xbf, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0x9a, 0x00, 0x07, 0x00, 0x00, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x9e, 0x72, 0x04, 0x99, 0xfb, 0x67, 0x05, 0x9a, 0xfd, 0x75, 0x7f, 0xfd, 0x70, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0x9a, 0x00, 0x07, 0x00, 0x00, 0x21, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x05, 0xa9, 0x72, 0xfb, 0x67, 0x04, 0x99, 0x72, 0x02, 0x90, 0x7f, 0x02, 0x8b, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0x9a, 0x00, 0x07, 0x00, 0x00, 0x01, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x05, 0xa8, 0xfd, 0xb4, 0x73, 0xfd, 0xb5, 0x05, 0x9a, 0x7f, 0xfa, 0xe5, 0x05, 0x1b, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0x9a, 0x00, 0x07, 0x00, 0x00, 0x33, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x9e, 0x02, 0x4b, 0x73, 0x02, 0x4c, 0x7f, 0x05, 0x1b, 0xfa, 0xe5, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x03, 0x23, 0x05, 0x9a, 0x00, 0x07, 0x00, 0x00, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x9e, 0x72, 0x02, 0x13, 0xfd, 0xed, 0x05, 0x9a, 0xfd, 0x75, 0x7f, 0xfd, 0x70, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x03, 0x23, 0x05, 0x9a, 0x00, 0x0b, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x10, 0x72, 0x72, 0x02, 0x13, 0xfd, 0xed, 0x02, 0x13, 0xfd, 0xed, 0x05, 0x9a, 0xfe, 0x24, 0x7f, 0xe4, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0x9a, 0x00, 0x0b, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x10, 0x72, 0x72, 0x04, 0x99, 0xfb, 0x67, 0x04, 0x99, 0xfb, 0x67, 0x05, 0x9a, 0xfe, 0x24, 0x7f, 0xe4, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0x9a, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x23, 0x11, 0x33, 0x01, 0xdd, 0x72, 0x03, 0x5a, 0xfc, 0xa6, 0xfe, 0xc1, 0x72, 0x72, 0x05, 0x9a, 0xfd, 0x75, 0x7f, 0xfd, 0x70, 0x05, 0x9a, 0x00, 0x03, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0x9a, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x01, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x23, 0x11, 0x33, 0x01, 0x10, 0x72, 0x72, 0x02, 0x0c, 0x73, 0x02, 0x1a, 0xfd, 0xe6, 0xfe, 0xc0, 0x72, 0x72, 0x05, 0x9a, 0xfa, 0x66, 0x05, 0x9a, 0xfd, 0x75, 0x7f, 0xfd, 0x70, 0x05, 0x9a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0x00, 0x00, 0x05, 0xa9, 0x05, 0x9a, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x01, 0x23, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0x10, 0x72, 0x72, 0x01, 0x3f, 0x72, 0x72, 0x03, 0x5a, 0xfc, 0xa6, 0x03, 0x5a, 0xfc, 0xa6, 0x05, 0x9a, 0xfa, 0x66, 0x05, 0x9a, 0xfe, 0x24, 0x7f, 0xe4, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x9d, 0xff, 0xaf, 0x05, 0xa9, 0x05, 0xeb, 0x00, 0x0f, 0x00, 0x00, 0x33, 0x11, 0x33, 0x11, 0x21, 0x01, 0x17, 0x01, 0x21, 0x15, 0x21, 0x01, 0x27, 0x01, 0x21, 0x11, 0x9e, 0x72, 0x01, 0xef, 0x01, 0x32, 0x67, 0xfe, 0xe5, 0x02, 0x2c, 0xfd, 0x9f, 0xfe, 0xcd, 0x68, 0x01, 0x1d, 0xfe, 0x46, 0x05, 0x9a, 0xfd, 0x75, 0x02, 0xdc, 0x35, 0xfd, 0x59, 0x7f, 0xfd, 0x1f, 0x36, 0x02, 0xab, 0xfd, 0x70, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xff, 0xaf, 0x05, 0xa9, 0x05, 0xeb, 0x00, 0x13, 0x00, 0x17, 0x00, 0x00, 0x01, 0x17, 0x03, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x03, 0x27, 0x13, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x03, 0x37, 0x21, 0x15, 0x04, 0x31, 0x67, 0xd2, 0x01, 0xe3, 0xfd, 0xe8, 0x5f, 0x02, 0x77, 0xfd, 0x54, 0xe8, 0x68, 0xd2, 0xfe, 0x91, 0x72, 0x72, 0x02, 0x38, 0x94, 0x5f, 0xfd, 0xfd, 0x05, 0xeb, 0x35, 0xfe, 0x08, 0x7f, 0xe4, 0x7f, 0xfd, 0xd3, 0x36, 0x01, 0xf7, 0xfe, 0x24, 0x05, 0x9a, 0xfe, 0x24, 0xfe, 0x9d, 0xe4, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xff, 0xaf, 0x05, 0xa9, 0x05, 0xeb, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x01, 0x17, 0x01, 0x21, 0x15, 0x21, 0x01, 0x27, 0x01, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x01, 0x23, 0x11, 0x33, 0x04, 0xf5, 0x67, 0xfe, 0xe5, 0x01, 0x68, 0xfe, 0x63, 0xfe, 0xcd, 0x67, 0x01, 0x1d, 0xfe, 0xc0, 0x72, 0x72, 0x01, 0x75, 0xfd, 0x4c, 0x72, 0x72, 0x05, 0xeb, 0x35, 0xfd, 0x59, 0x7f, 0xfd, 0x1f, 0x36, 0x02, 0xab, 0xfd, 0x70, 0x05, 0x9a, 0xfd, 0x75, 0xfc, 0xf1, 0x05, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x9d, 0xff, 0xaf, 0x05, 0xa9, 0x05, 0xeb, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x11, 0x21, 0x13, 0x17, 0x03, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x03, 0x27, 0x13, 0x23, 0x01, 0x23, 0x11, 0x33, 0x01, 0x37, 0x21, 0x15, 0x02, 0x4f, 0x72, 0x72, 0x01, 0xc2, 0xe9, 0x67, 0xd2, 0x01, 0x1a, 0xfe, 0xb1, 0x5f, 0x01, 0xae, 0xfe, 0x1d, 0xe8, 0x68, 0xd2, 0xf9, 0xfe, 0xc1, 0x72, 0x72, 0x02, 0x6d, 0x5f, 0xfe, 0x73, 0x05, 0x9a, 0xfe, 0x24, 0x02, 0x2d, 0x35, 0xfe, 0x08, 0x7f, 0xe4, 0x7f, 0xfd, 0xd3, 0x36, 0x01, 0xf7, 0xfe, 0x24, 0x05, 0x9a, 0xfc, 0xc1, 0xe4, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xa7, 0x05, 0x37, 0x05, 0x5d, 0x00, 0x2a, 0x00, 0x00, 0x13, 0x35, 0x24, 0x25, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x06, 0x05, 0x04, 0x17, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x37, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x24, 0xc3, 0x01, 0x72, 0x01, 0x20, 0xb4, 0x5b, 0x37, 0x45, 0x38, 0x48, 0x32, 0x67, 0x51, 0x90, 0x7a, 0x9f, 0x85, 0xcd, 0xfe, 0xaf, 0x01, 0x51, 0xcd, 0x85, 0x9f, 0x7a, 0x90, 0x51, 0x67, 0x32, 0x48, 0x38, 0x45, 0x37, 0x5b, 0xb4, 0xfe, 0xe0, 0x02, 0x2e, 0xa8, 0x28, 0x59, 0x37, 0x4f, 0x30, 0x3c, 0x30, 0x3a, 0x3e, 0x7e, 0x6a, 0xa0, 0x79, 0x9f, 0x5b, 0x8c, 0x3c, 0x3c, 0x8c, 0x5b, 0x9f, 0x79, 0xa0, 0x6a, 0x7e, 0x3e, 0x3a, 0x30, 0x3c, 0x30, 0x4f, 0x37, 0x59, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xa7, 0x05, 0x37, 0x05, 0x5d, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x25, 0x24, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x04, 0x05, 0x05, 0x37, 0xfe, 0x8e, 0xfe, 0xe0, 0xb4, 0x5b, 0x37, 0x45, 0x38, 0x48, 0x32, 0x67, 0x51, 0x90, 0x7a, 0x9f, 0x85, 0xcd, 0x01, 0x51, 0xfe, 0xaf, 0xcd, 0x85, 0x9f, 0x7a, 0x90, 0x51, 0x67, 0x32, 0x48, 0x38, 0x45, 0x37, 0x5b, 0xb4, 0x01, 0x20, 0x01, 0x72, 0x02, 0x2e, 0x28, 0x59, 0x37, 0x4f, 0x30, 0x3c, 0x30, 0x3a, 0x3e, 0x7e, 0x6a, 0xa0, 0x79, 0x9f, 0x5b, 0x8c, 0x3c, 0x3c, 0x8c, 0x5b, 0x9f, 0x79, 0xa0, 0x6a, 0x7e, 0x3e, 0x3a, 0x30, 0x3c, 0x30, 0x4f, 0x37, 0x59, 0x28, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x1e, 0x05, 0x46, 0x04, 0xe6, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x01, 0x11, 0x09, 0x02, 0x35, 0x01, 0x04, 0xac, 0xfc, 0xf8, 0x03, 0xa1, 0xfb, 0x7e, 0x04, 0x82, 0x01, 0x20, 0x02, 0xc4, 0xfe, 0x9e, 0xfd, 0x9c, 0x02, 0x11, 0xa6, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x1e, 0x05, 0x46, 0x04, 0xe6, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x09, 0x02, 0x03, 0x11, 0x01, 0x15, 0x01, 0x5c, 0x03, 0x08, 0xfc, 0xf8, 0x99, 0x04, 0x82, 0x01, 0x20, 0x01, 0x62, 0x01, 0x62, 0xfc, 0x3a, 0x04, 0xc8, 0xfd, 0xef, 0xa6, 0x00, 0x03, 0x00, 0xc3, 0xff, 0x9e, 0x05, 0x46, 0x05, 0x64, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x17, 0x35, 0x21, 0x15, 0x03, 0x11, 0x09, 0x02, 0x35, 0x01, 0xc3, 0x04, 0x82, 0x99, 0xfc, 0xf8, 0x03, 0xa1, 0xfb, 0x7e, 0x04, 0x82, 0x62, 0xaa, 0xaa, 0x02, 0x00, 0x02, 0xc4, 0xfe, 0x9e, 0xfd, 0x9c, 0x02, 0x11, 0xa6, 0x02, 0x11, 0x00, 0x03, 0x00, 0xc3, 0xff, 0x9e, 0x05, 0x46, 0x05, 0x64, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x17, 0x35, 0x21, 0x15, 0x09, 0x02, 0x03, 0x11, 0x01, 0x15, 0xc3, 0x04, 0x82, 0xfc, 0x17, 0x03, 0x08, 0xfc, 0xf8, 0x99, 0x04, 0x82, 0x62, 0xaa, 0xaa, 0x02, 0x00, 0x01, 0x62, 0x01, 0x62, 0xfc, 0x3a, 0x04, 0xc8, 0xfd, 0xef, 0xa6, 0x00, 0x02, 0x00, 0x6c, 0x01, 0x67, 0x06, 0xc7, 0x03, 0xa2, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x27, 0x26, 0x27, 0x21, 0x06, 0x07, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x17, 0x16, 0x17, 0x21, 0x36, 0x04, 0x22, 0x06, 0x14, 0x16, 0x32, 0x36, 0x34, 0x05, 0x0f, 0x4b, 0xd3, 0x99, 0x96, 0xda, 0x49, 0x2e, 0x11, 0xfd, 0x96, 0x12, 0x2e, 0x4c, 0xd9, 0x92, 0x95, 0xd4, 0x4e, 0x2f, 0x11, 0x02, 0x6a, 0x12, 0xfc, 0xc1, 0x67, 0x47, 0x47, 0x68, 0x47, 0x03, 0x4f, 0x53, 0xa8, 0xef, 0xa4, 0x51, 0x33, 0x43, 0x42, 0x33, 0x52, 0xa2, 0xf2, 0xa7, 0x55, 0x34, 0x43, 0x44, 0x0e, 0x50, 0x72, 0x4f, 0x4f, 0x71, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6c, 0x01, 0x67, 0x06, 0xc7, 0x03, 0xa2, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x17, 0x16, 0x17, 0x21, 0x36, 0x37, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x27, 0x26, 0x27, 0x21, 0x06, 0x24, 0x32, 0x36, 0x34, 0x26, 0x22, 0x06, 0x14, 0x02, 0x24, 0x4b, 0xd3, 0x99, 0x96, 0xda, 0x49, 0x2e, 0x11, 0x02, 0x6a, 0x12, 0x2e, 0x4c, 0xd9, 0x92, 0x95, 0xd4, 0x4e, 0x2f, 0x11, 0xfd, 0x96, 0x12, 0x03, 0x3f, 0x67, 0x47, 0x47, 0x67, 0x48, 0x01, 0xba, 0x53, 0xa8, 0xef, 0xa4, 0x51, 0x33, 0x43, 0x42, 0x33, 0x52, 0xa2, 0xf2, 0xa7, 0x55, 0x34, 0x43, 0x44, 0x0e, 0x50, 0x72, 0x4f, 0x4f, 0x71, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x58, 0x01, 0x67, 0x05, 0xb1, 0x03, 0xa2, 0x00, 0x0d, 0x00, 0x15, 0x00, 0x00, 0x13, 0x37, 0x21, 0x36, 0x37, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x26, 0x22, 0x06, 0x14, 0x16, 0x32, 0x36, 0x58, 0x01, 0x03, 0x60, 0x11, 0x2c, 0x52, 0xd4, 0x94, 0x92, 0xd9, 0x4b, 0x2f, 0x11, 0x01, 0x71, 0x47, 0x68, 0x48, 0x48, 0x68, 0x47, 0x02, 0x2e, 0xa8, 0x44, 0x2f, 0x59, 0xa7, 0xf2, 0xa2, 0x52, 0x33, 0x42, 0x8e, 0x50, 0x51, 0x71, 0x4f, 0x4f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6c, 0xff, 0xa0, 0x05, 0x9c, 0x05, 0x64, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x33, 0x11, 0x23, 0x05, 0x21, 0x15, 0x21, 0x03, 0x23, 0x11, 0x33, 0x25, 0x21, 0x35, 0x21, 0x02, 0xb9, 0x97, 0x97, 0x01, 0x0a, 0x01, 0xd9, 0xfe, 0x27, 0x73, 0x97, 0x97, 0xfe, 0xf5, 0xfe, 0x28, 0x01, 0xd8, 0x05, 0x64, 0xfd, 0xf3, 0x80, 0xaa, 0xfd, 0x73, 0x02, 0x0d, 0x80, 0xaa, 0x00, 0x00, 0x01, 0x00, 0xd6, 0x00, 0x00, 0x02, 0xea, 0x05, 0x9b, 0x00, 0x07, 0x00, 0x00, 0x21, 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x02, 0x19, 0x72, 0xd1, 0x02, 0x13, 0xd0, 0x05, 0x1c, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x92, 0x05, 0xec, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x33, 0x35, 0x21, 0x15, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x23, 0xb4, 0x03, 0xdd, 0xfc, 0x5c, 0xb0, 0x01, 0x06, 0x01, 0x05, 0xb0, 0xfe, 0xbb, 0xe1, 0xaa, 0xaa, 0x05, 0xec, 0xfc, 0x54, 0x03, 0xac, 0xfb, 0x5e, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x92, 0x05, 0xec, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x13, 0x01, 0x33, 0x01, 0x23, 0x09, 0x01, 0xb4, 0x03, 0xdd, 0xfc, 0x23, 0x39, 0x01, 0x45, 0xe1, 0x01, 0x45, 0xb0, 0xfe, 0xfb, 0xfe, 0xfa, 0x05, 0xec, 0xaa, 0xfa, 0xbe, 0x04, 0xa2, 0xfb, 0x5e, 0x03, 0xac, 0xfc, 0x54, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x92, 0x05, 0xec, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x17, 0x33, 0x09, 0x01, 0x33, 0x01, 0x23, 0xb4, 0x03, 0xdd, 0xfc, 0x23, 0x39, 0xb0, 0x01, 0x06, 0x01, 0x05, 0xb0, 0xfe, 0xbb, 0xe1, 0x05, 0xec, 0xaa, 0xa0, 0xfc, 0x54, 0x03, 0xac, 0xfb, 0x5e, 0x00, 0x02, 0x00, 0xfe, 0x00, 0x00, 0x05, 0x0a, 0x04, 0x7e, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x16, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x17, 0x33, 0x01, 0x11, 0x21, 0x26, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x05, 0x0a, 0xfb, 0xf5, 0x99, 0x51, 0x4d, 0x95, 0xd6, 0x3f, 0x21, 0x10, 0xf9, 0xfc, 0x8e, 0x02, 0x0b, 0x0e, 0x18, 0x37, 0xba, 0x80, 0x39, 0x04, 0x7e, 0xfe, 0xeb, 0x12, 0x25, 0x46, 0xee, 0xa4, 0x56, 0x5a, 0x02, 0x44, 0xfd, 0xbc, 0x41, 0x3f, 0x8f, 0xce, 0x3d, 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfe, 0x00, 0x00, 0x05, 0x0a, 0x04, 0x7e, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x09, 0x01, 0x21, 0x05, 0x35, 0x01, 0x33, 0x11, 0x04, 0x71, 0xfd, 0x27, 0x02, 0xd9, 0xfc, 0x8e, 0x03, 0x72, 0x99, 0x03, 0xd4, 0xfc, 0xd6, 0xaa, 0xaa, 0x03, 0xd4, 0xfb, 0x82, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfa, 0xfe, 0x77, 0x05, 0xee, 0x05, 0xc1, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x23, 0x09, 0x01, 0x23, 0x01, 0x03, 0x58, 0x02, 0x95, 0xb6, 0xfd, 0xbd, 0xfd, 0xbd, 0xb6, 0x02, 0x93, 0x05, 0xc1, 0xf8, 0xb6, 0x06, 0x77, 0xf9, 0x89, 0x07, 0x4a, 0x00, 0x00, 0x01, 0xff, 0xfa, 0xfe, 0x77, 0x05, 0xee, 0x05, 0xc1, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x02, 0x90, 0xfd, 0x6b, 0xb6, 0x02, 0x43, 0x02, 0x43, 0xb6, 0xfd, 0x6d, 0xfe, 0x77, 0x07, 0x4a, 0xf9, 0x89, 0x06, 0x77, 0xf8, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x7e, 0xfe, 0x77, 0x05, 0x6a, 0x05, 0xc1, 0x00, 0x10, 0x00, 0x00, 0x01, 0x22, 0x04, 0x15, 0x11, 0x23, 0x11, 0x10, 0x00, 0x20, 0x00, 0x19, 0x01, 0x23, 0x11, 0x34, 0x24, 0x02, 0xf4, 0xc5, 0xfe, 0xea, 0x9b, 0x01, 0x90, 0x01, 0xcc, 0x01, 0x90, 0x9b, 0xfe, 0xec, 0x05, 0x1d, 0xe3, 0xfc, 0xfb, 0x39, 0x04, 0xe0, 0x01, 0x42, 0x01, 0x28, 0xfe, 0xd8, 0xfe, 0xbe, 0xfb, 0x20, 0x04, 0xc7, 0xfa, 0xe5, 0x00, 0x01, 0x00, 0x7e, 0xfe, 0x77, 0x05, 0x6a, 0x05, 0xc1, 0x00, 0x10, 0x00, 0x00, 0x05, 0x32, 0x24, 0x35, 0x11, 0x33, 0x11, 0x10, 0x00, 0x20, 0x00, 0x19, 0x01, 0x33, 0x11, 0x14, 0x04, 0x02, 0xf4, 0xc5, 0x01, 0x16, 0x9b, 0xfe, 0x70, 0xfe, 0x34, 0xfe, 0x70, 0x9b, 0x01, 0x14, 0xe5, 0xe3, 0xfc, 0x04, 0xc7, 0xfb, 0x20, 0xfe, 0xbe, 0xfe, 0xd8, 0x01, 0x28, 0x01, 0x42, 0x04, 0xe0, 0xfb, 0x39, 0xfa, 0xe5, 0x00, 0xff, 0xff, 0x00, 0x05, 0xfe, 0x23, 0x03, 0x8a, 0x06, 0x75, 0x12, 0x06, 0x0a, 0xf3, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc5, 0x02, 0x48, 0x01, 0x83, 0x03, 0x46, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0xc5, 0xbe, 0xbe, 0x03, 0x46, 0xfe, 0x00, 0x01, 0x00, 0xe0, 0x01, 0x31, 0x03, 0xa2, 0x04, 0x19, 0x00, 0x09, 0x00, 0x00, 0x13, 0x21, 0x1b, 0x01, 0x21, 0x07, 0x13, 0x27, 0x07, 0x13, 0xe0, 0x01, 0x0d, 0x54, 0x55, 0x01, 0x0c, 0xda, 0x54, 0xdb, 0xdb, 0x54, 0x02, 0xfd, 0x01, 0x1c, 0xfe, 0xe4, 0xb0, 0xfe, 0xe4, 0xb0, 0xb0, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0x1e, 0x05, 0x46, 0x04, 0xe7, 0x00, 0x03, 0x00, 0x07, 0x00, 0x19, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x03, 0x21, 0x35, 0x21, 0x01, 0x37, 0x09, 0x01, 0x17, 0x01, 0x21, 0x15, 0x21, 0x01, 0x07, 0x09, 0x01, 0x27, 0x02, 0x96, 0xdd, 0xdd, 0xdd, 0xdd, 0x4a, 0xfe, 0x77, 0x01, 0x89, 0xfe, 0xb0, 0x6c, 0x01, 0x9c, 0x01, 0x9c, 0x6c, 0xfe, 0xb1, 0x01, 0x88, 0xfe, 0x78, 0x01, 0x4f, 0x6c, 0xfe, 0x64, 0xfe, 0x64, 0x6c, 0x01, 0x13, 0xf5, 0x04, 0xc9, 0xf6, 0xfe, 0x3c, 0xaa, 0x01, 0x75, 0x78, 0xfe, 0x36, 0x01, 0xca, 0x78, 0xfe, 0x8b, 0xaa, 0xfe, 0x8b, 0x78, 0x01, 0xca, 0xfe, 0x36, 0x78, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x00, 0x17, 0x11, 0x09, 0x01, 0x11, 0x01, 0x27, 0x01, 0x11, 0x09, 0x01, 0x11, 0xc3, 0x02, 0xd7, 0x02, 0xd6, 0xfd, 0x2a, 0x8c, 0xfe, 0x4e, 0x02, 0xc9, 0x01, 0xb2, 0x3e, 0x05, 0x80, 0xfd, 0xb0, 0x02, 0x50, 0xfa, 0x80, 0x02, 0x4e, 0x71, 0x01, 0x5e, 0xfd, 0x44, 0x01, 0x5e, 0xfe, 0xa2, 0x02, 0xc6, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x15, 0x09, 0x01, 0x11, 0x09, 0x01, 0x15, 0x01, 0x21, 0x01, 0x11, 0x06, 0x70, 0xfd, 0x2a, 0xfd, 0x29, 0x02, 0xd7, 0x02, 0xd6, 0xfd, 0xb5, 0xfe, 0xe9, 0xfe, 0x4e, 0xa2, 0xe0, 0x02, 0x4e, 0xfd, 0xb2, 0x05, 0x80, 0xfd, 0xb0, 0x02, 0x50, 0xdd, 0xfe, 0x1c, 0x01, 0x5e, 0xfd, 0x44, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x35, 0x09, 0x01, 0x11, 0x09, 0x01, 0x35, 0x01, 0x21, 0x01, 0x11, 0xc3, 0x02, 0xd7, 0x02, 0xd6, 0xfd, 0x2a, 0xfd, 0x29, 0x02, 0x4b, 0x01, 0x17, 0x01, 0xb2, 0x04, 0x62, 0xe0, 0xfd, 0xb2, 0x02, 0x4e, 0xfa, 0x80, 0x02, 0x50, 0xfd, 0xb0, 0xdd, 0x01, 0xe4, 0xfe, 0xa2, 0x02, 0xbc, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x07, 0x00, 0x00, 0x17, 0x35, 0x09, 0x01, 0x35, 0x01, 0x15, 0x01, 0xc3, 0x02, 0x4b, 0xfd, 0xb5, 0x05, 0xad, 0xfd, 0x2a, 0x3e, 0xe0, 0x01, 0xe1, 0x01, 0xe2, 0xdd, 0xfb, 0x5d, 0xdd, 0x02, 0x50, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x07, 0x00, 0x00, 0x05, 0x09, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x06, 0x70, 0xfd, 0x2a, 0xfd, 0x29, 0x05, 0xad, 0xfd, 0xb5, 0x02, 0x4b, 0x3e, 0x02, 0x50, 0xfd, 0xb0, 0xdd, 0x04, 0xa3, 0xdd, 0xfe, 0x1e, 0xfe, 0x1f, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x01, 0x60, 0x05, 0x46, 0x03, 0xf4, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x00, 0x13, 0x1e, 0x01, 0x33, 0x32, 0x3f, 0x02, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x0f, 0x01, 0x06, 0x23, 0x22, 0x26, 0x27, 0x01, 0x15, 0x21, 0x35, 0xc3, 0x5d, 0x98, 0x4e, 0x54, 0x8c, 0x13, 0x0e, 0x84, 0x63, 0x58, 0xa1, 0x5e, 0x58, 0x9b, 0x4f, 0x55, 0x8b, 0x0e, 0x05, 0x0f, 0x84, 0x63, 0x57, 0xa1, 0x5f, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0xf4, 0x55, 0x4b, 0x3d, 0x09, 0x06, 0x3b, 0x45, 0x4e, 0xb2, 0x53, 0x4c, 0x3d, 0x06, 0x02, 0x07, 0x3b, 0x45, 0x4f, 0xfe, 0xc8, 0xaa, 0xaa, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, 0x04, 0xed, 0x04, 0xa2, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x33, 0x00, 0x13, 0x12, 0x01, 0x33, 0x00, 0x03, 0x23, 0x02, 0x59, 0xc2, 0x01, 0x4f, 0x39, 0x42, 0x01, 0x46, 0xc2, 0xfe, 0x65, 0x5b, 0xa8, 0x5b, 0x04, 0xa2, 0xfe, 0x90, 0xfe, 0x25, 0x01, 0xda, 0x01, 0x71, 0xfe, 0x81, 0xfc, 0xdd, 0x03, 0x23, 0x00, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, 0x04, 0xed, 0x04, 0xa2, 0x00, 0x0a, 0x00, 0x00, 0x33, 0x00, 0x13, 0x33, 0x12, 0x01, 0x23, 0x00, 0x03, 0x02, 0x01, 0x59, 0x01, 0x9b, 0x5b, 0xa8, 0x5b, 0x01, 0x9b, 0xc2, 0xfe, 0xba, 0x42, 0x39, 0xfe, 0xb1, 0x01, 0x7f, 0x03, 0x23, 0xfc, 0xdd, 0xfe, 0x81, 0x01, 0x71, 0x01, 0xda, 0xfe, 0x25, 0xfe, 0x90, 0x00, 0x02, 0x00, 0xab, 0xff, 0xfa, 0x05, 0x46, 0x05, 0x0a, 0x00, 0x13, 0x00, 0x29, 0x00, 0x00, 0x01, 0x21, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x21, 0x11, 0x21, 0x22, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x33, 0x21, 0x15, 0x21, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x21, 0x05, 0x45, 0xfd, 0xad, 0x34, 0x24, 0x24, 0x48, 0x34, 0x02, 0x53, 0xfd, 0xac, 0x73, 0x51, 0x50, 0xa0, 0x74, 0x02, 0x54, 0xfd, 0xad, 0xf4, 0xa9, 0xaa, 0xaa, 0xa7, 0xf4, 0x02, 0x55, 0xfd, 0xac, 0xb4, 0x7c, 0x7d, 0x7d, 0x7c, 0xb5, 0x02, 0x53, 0x03, 0x0c, 0x28, 0x29, 0x39, 0x3a, 0x50, 0xaa, 0x5a, 0x58, 0x82, 0x80, 0xb4, 0xfc, 0x44, 0xbd, 0xbe, 0x01, 0x0d, 0x01, 0x0c, 0xbf, 0xbd, 0xaa, 0x8b, 0x8d, 0xc6, 0xc8, 0x8b, 0x8b, 0x00, 0x02, 0x00, 0xc3, 0xff, 0xfa, 0x05, 0x5e, 0x05, 0x0a, 0x00, 0x13, 0x00, 0x29, 0x00, 0x00, 0x13, 0x35, 0x21, 0x32, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x21, 0x35, 0x21, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x21, 0x35, 0x21, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0xc3, 0x02, 0x54, 0x74, 0xa0, 0x50, 0x51, 0x73, 0xfd, 0xac, 0x02, 0x53, 0x34, 0x48, 0x24, 0x24, 0x34, 0xfd, 0xad, 0x02, 0x53, 0xb5, 0x7c, 0x7d, 0x7d, 0x7c, 0xb4, 0xfd, 0xac, 0x02, 0x55, 0xf4, 0xa7, 0xaa, 0xaa, 0xa9, 0xf4, 0x03, 0x0c, 0xaa, 0xb4, 0x80, 0x82, 0x58, 0x5a, 0xaa, 0x50, 0x3a, 0x39, 0x29, 0x28, 0xfc, 0xee, 0xaa, 0x8b, 0x8b, 0xc8, 0xc6, 0x8d, 0x8b, 0xaa, 0xbd, 0xbf, 0xfe, 0xf4, 0xfe, 0xf3, 0xbe, 0xbd, 0x00, 0x00, 0x02, 0x00, 0xbd, 0x00, 0x00, 0x05, 0x4c, 0x05, 0x4e, 0x00, 0x11, 0x00, 0x24, 0x00, 0x00, 0x21, 0x11, 0x34, 0x26, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x15, 0x11, 0x21, 0x11, 0x10, 0x00, 0x20, 0x17, 0x16, 0x19, 0x01, 0x23, 0x11, 0x34, 0x27, 0x26, 0x20, 0x07, 0x06, 0x15, 0x11, 0x03, 0x80, 0x48, 0x68, 0x48, 0x99, 0x51, 0x4f, 0x75, 0x73, 0xa2, 0xfc, 0xa4, 0x01, 0x56, 0x01, 0xe2, 0xad, 0xa9, 0x99, 0x7c, 0x7e, 0xfe, 0x98, 0x7c, 0x7e, 0x02, 0xc6, 0x3a, 0x50, 0x50, 0x3a, 0xfd, 0x3a, 0x02, 0xc8, 0x80, 0x5a, 0x58, 0xb2, 0x80, 0xfd, 0x38, 0x02, 0xc6, 0x01, 0x10, 0x01, 0x78, 0xbc, 0xba, 0xfe, 0xf0, 0xfd, 0x38, 0x02, 0xc8, 0xc8, 0x8a, 0x8a, 0x8a, 0x8a, 0xca, 0xfd, 0x3a, 0x00, 0x00, 0x00, 0x02, 0x00, 0xbd, 0xff, 0xe3, 0x05, 0x4c, 0x05, 0x31, 0x00, 0x11, 0x00, 0x24, 0x00, 0x00, 0x01, 0x11, 0x14, 0x16, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x21, 0x11, 0x10, 0x00, 0x20, 0x27, 0x26, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x35, 0x11, 0x02, 0x88, 0x48, 0x68, 0x48, 0x99, 0x51, 0x4f, 0x75, 0x73, 0xa2, 0x03, 0x5c, 0xfe, 0xaa, 0xfe, 0x1e, 0xad, 0xa9, 0x99, 0x7c, 0x7e, 0x01, 0x68, 0x7c, 0x7e, 0x05, 0x31, 0xfd, 0x3a, 0x3a, 0x50, 0x50, 0x3a, 0x02, 0xc6, 0xfd, 0x38, 0x80, 0x5a, 0x58, 0xb2, 0x80, 0x02, 0xc8, 0xfd, 0x3a, 0xfe, 0xf0, 0xfe, 0x88, 0xbc, 0xba, 0x01, 0x10, 0x02, 0xc8, 0xfd, 0x38, 0xc8, 0x8a, 0x8a, 0x8a, 0x8a, 0xca, 0x02, 0xc6, 0x00, 0x01, 0x01, 0x56, 0x00, 0x00, 0x04, 0xb3, 0x05, 0xd5, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x34, 0x27, 0x26, 0x27, 0x11, 0x23, 0x11, 0x06, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x37, 0x36, 0x37, 0x11, 0x33, 0x11, 0x16, 0x17, 0x16, 0x15, 0x11, 0x23, 0x04, 0x19, 0x51, 0x34, 0x43, 0x99, 0x44, 0x34, 0x51, 0x99, 0x7e, 0x61, 0x83, 0x99, 0x84, 0x61, 0x7c, 0x99, 0x02, 0x9f, 0x80, 0x59, 0x3a, 0x14, 0xfc, 0x3a, 0x03, 0xc6, 0x13, 0x3a, 0x5a, 0x80, 0xfd, 0x61, 0x02, 0x9d, 0xc8, 0x8c, 0x6c, 0x17, 0x01, 0x61, 0xfe, 0x9f, 0x17, 0x6c, 0x8a, 0xc8, 0xfd, 0x61, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x34, 0x05, 0x46, 0x05, 0xd5, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x00, 0x05, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x27, 0x35, 0x23, 0x15, 0x03, 0xea, 0x99, 0x99, 0x99, 0xfe, 0xa4, 0x01, 0x5c, 0xfe, 0xa4, 0x01, 0x5c, 0x99, 0x99, 0x99, 0x01, 0x5b, 0xfe, 0xa5, 0x01, 0x5b, 0xfe, 0xa5, 0x99, 0x99, 0xcc, 0x02, 0x2c, 0xfd, 0xd4, 0x02, 0x2c, 0xaa, 0xf0, 0xa8, 0x02, 0x33, 0xfd, 0xcd, 0x02, 0x33, 0xfd, 0xcd, 0xa8, 0xf0, 0xaa, 0xaa, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x5e, 0x05, 0x46, 0x04, 0xa6, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x04, 0x2d, 0xbe, 0xbe, 0x01, 0x18, 0xfc, 0x5f, 0x03, 0xa1, 0xfb, 0x7e, 0x04, 0x82, 0x03, 0x00, 0xfe, 0x01, 0xee, 0xfe, 0x91, 0xfe, 0x93, 0xb6, 0x01, 0xd1, 0xa6, 0x01, 0xd1, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x5e, 0x05, 0x46, 0x04, 0xa6, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x03, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x01, 0x1d, 0xbe, 0xbe, 0x5a, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x9f, 0x03, 0x00, 0xfe, 0x01, 0xee, 0xb6, 0xfe, 0x2f, 0xa6, 0xfe, 0x2f, 0xb6, 0x01, 0x6d, 0x00, 0x03, 0x00, 0x85, 0x00, 0x2e, 0x09, 0xb8, 0x04, 0xdf, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x00, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x05, 0x09, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x09, 0x01, 0x15, 0x01, 0x35, 0x01, 0x09, 0xb8, 0xfd, 0x18, 0x02, 0xe8, 0xfc, 0x35, 0x03, 0xcb, 0xfd, 0x4c, 0xfd, 0x19, 0x02, 0xe7, 0xfc, 0x36, 0x03, 0xca, 0xfd, 0x4b, 0xfd, 0x19, 0x02, 0xe7, 0xfc, 0x36, 0x03, 0xca, 0x04, 0x11, 0xfe, 0x70, 0xfe, 0x72, 0xc5, 0x02, 0x08, 0x9f, 0x02, 0x0a, 0xce, 0xfe, 0x70, 0xfe, 0x72, 0xc5, 0x02, 0x08, 0x9f, 0x02, 0x0a, 0xce, 0xfe, 0x70, 0xfe, 0x72, 0xc5, 0x02, 0x08, 0x9f, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x85, 0x00, 0x2e, 0x09, 0xb8, 0x04, 0xdf, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x00, 0x13, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x03, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x03, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x85, 0x03, 0xca, 0xfc, 0x36, 0x02, 0xe8, 0x33, 0x03, 0xca, 0xfc, 0x36, 0x02, 0xe8, 0x35, 0x03, 0xcb, 0xfc, 0x35, 0x02, 0xe8, 0x04, 0x11, 0xce, 0xfd, 0xf6, 0x9f, 0xfd, 0xf8, 0xc5, 0x01, 0x8e, 0x01, 0x90, 0xce, 0xfd, 0xf6, 0x9f, 0xfd, 0xf8, 0xc5, 0x01, 0x8e, 0x01, 0x90, 0xce, 0xfd, 0xf6, 0x9f, 0xfd, 0xf8, 0xc5, 0x01, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0x2e, 0x05, 0x46, 0x06, 0xd4, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x00, 0x13, 0x09, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x21, 0x35, 0x21, 0x11, 0x09, 0x01, 0x15, 0x01, 0x35, 0x01, 0xc3, 0x03, 0x61, 0xfc, 0x9f, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0xfe, 0xde, 0x01, 0x15, 0x01, 0x12, 0xb2, 0xfe, 0x90, 0xaa, 0xfe, 0x91, 0x03, 0xfe, 0xaa, 0x03, 0x4e, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0x2e, 0x05, 0x46, 0x06, 0xd4, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x00, 0x01, 0x15, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0x9f, 0xfe, 0xdf, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0xfe, 0xde, 0xb0, 0x01, 0x6f, 0xaa, 0x01, 0x70, 0xb2, 0xfe, 0xee, 0x02, 0x39, 0xaa, 0xaa, 0x03, 0xf8, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x25, 0x15, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x35, 0x21, 0x15, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xa0, 0xfe, 0xde, 0x04, 0x82, 0xb0, 0xb0, 0x01, 0x6f, 0xaa, 0x01, 0x70, 0xb2, 0xfe, 0xee, 0x02, 0x39, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x37, 0x09, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x21, 0x35, 0x21, 0xc3, 0x03, 0x61, 0xfc, 0x9f, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xb0, 0x01, 0x15, 0x01, 0x12, 0xb2, 0xfe, 0x90, 0xaa, 0xfe, 0x91, 0x03, 0xfe, 0xaa, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x29, 0x05, 0x46, 0x05, 0x57, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x05, 0x35, 0x24, 0x01, 0x11, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x15, 0x00, 0x05, 0x04, 0x05, 0x45, 0xfe, 0x7f, 0xfc, 0xff, 0x03, 0x12, 0x01, 0x70, 0xfe, 0xa7, 0xfc, 0xd7, 0x03, 0x29, 0x01, 0x59, 0xfe, 0xa7, 0xfe, 0x54, 0x01, 0xac, 0x04, 0x80, 0xfe, 0x5f, 0x85, 0xae, 0x91, 0x01, 0xbe, 0xfa, 0xa9, 0xd7, 0x01, 0x80, 0x7c, 0xa6, 0x84, 0x01, 0x78, 0xd7, 0xfe, 0xe5, 0x5d, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x29, 0x05, 0x46, 0x05, 0x57, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x13, 0x35, 0x00, 0x05, 0x15, 0x24, 0x01, 0x00, 0x25, 0x24, 0x01, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0xc3, 0x01, 0x70, 0x03, 0x12, 0xfc, 0xff, 0xfe, 0x7f, 0x01, 0x59, 0x01, 0xac, 0xfe, 0x54, 0xfe, 0xa7, 0x01, 0x59, 0x03, 0x29, 0xfc, 0xd7, 0xfe, 0xa7, 0x04, 0x80, 0xd7, 0xfe, 0x42, 0x91, 0xae, 0x85, 0xfd, 0x21, 0x01, 0x1b, 0x5d, 0x5d, 0x01, 0x1b, 0xd7, 0xfe, 0x88, 0x84, 0xa6, 0x7c, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0x93, 0x05, 0x46, 0x06, 0x1d, 0x00, 0x21, 0x00, 0x26, 0x00, 0x00, 0x21, 0x15, 0x02, 0x25, 0x01, 0x27, 0x13, 0x26, 0x27, 0x35, 0x16, 0x17, 0x37, 0x26, 0x25, 0x35, 0x24, 0x25, 0x13, 0x17, 0x03, 0x36, 0x37, 0x15, 0x06, 0x0f, 0x01, 0x04, 0x17, 0x15, 0x26, 0x25, 0x07, 0x04, 0x01, 0x37, 0x06, 0x07, 0x16, 0x05, 0x45, 0xf2, 0xfe, 0x59, 0xff, 0x00, 0x76, 0xf4, 0xa7, 0xc0, 0xe6, 0xc4, 0x39, 0xd8, 0xfe, 0xf5, 0x01, 0x8a, 0x01, 0x1b, 0xde, 0x75, 0x95, 0xaa, 0x75, 0xb4, 0xcc, 0x5e, 0x01, 0x01, 0xdd, 0xc4, 0xfe, 0xa6, 0x39, 0x01, 0x70, 0xfe, 0x88, 0x2b, 0x66, 0x6b, 0x55, 0xd7, 0x01, 0x25, 0xa4, 0xfd, 0xa1, 0x4b, 0x02, 0x41, 0x36, 0x23, 0xae, 0x28, 0x41, 0x87, 0x46, 0x2b, 0xa6, 0x3c, 0x7a, 0x02, 0x0c, 0x4b, 0xfe, 0x9f, 0x64, 0x82, 0xd7, 0x94, 0x60, 0xdf, 0x67, 0xb6, 0xd7, 0xd6, 0x87, 0x88, 0x94, 0x01, 0xe2, 0x66, 0x23, 0x17, 0x12, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0x93, 0x05, 0x46, 0x06, 0x1d, 0x00, 0x21, 0x00, 0x26, 0x00, 0x00, 0x13, 0x35, 0x16, 0x05, 0x13, 0x17, 0x03, 0x16, 0x17, 0x15, 0x04, 0x0f, 0x01, 0x24, 0x25, 0x15, 0x04, 0x05, 0x03, 0x27, 0x13, 0x06, 0x07, 0x35, 0x36, 0x3f, 0x01, 0x04, 0x07, 0x35, 0x36, 0x25, 0x37, 0x24, 0x05, 0x07, 0x36, 0x37, 0x26, 0xc3, 0xe2, 0x01, 0xa8, 0xf9, 0x75, 0xea, 0xac, 0xc8, 0xfe, 0xd9, 0xea, 0x50, 0x01, 0x0b, 0x01, 0x56, 0xfe, 0x65, 0xfe, 0xd8, 0xd6, 0x76, 0x81, 0x8b, 0x69, 0x96, 0xce, 0x5a, 0xfe, 0xea, 0xa8, 0xf7, 0x01, 0x22, 0x32, 0xfe, 0xc1, 0x01, 0xc4, 0x0c, 0x21, 0x20, 0x1b, 0x04, 0x80, 0xd7, 0xfb, 0x8c, 0x02, 0x4d, 0x4b, 0xfd, 0xd6, 0x2e, 0x1f, 0xa6, 0x30, 0x51, 0xbd, 0x74, 0x3b, 0xae, 0x4c, 0x9e, 0xfe, 0x05, 0x4b, 0x01, 0x31, 0x67, 0x7f, 0xd7, 0xa2, 0x76, 0xd5, 0x7d, 0xb7, 0xd7, 0xcb, 0x69, 0x77, 0x69, 0x90, 0x1b, 0x08, 0x07, 0x06, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0xdf, 0x05, 0x46, 0x06, 0x23, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x03, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x03, 0x27, 0x37, 0x21, 0x35, 0x21, 0x37, 0x21, 0x11, 0x21, 0x03, 0x13, 0x21, 0x11, 0x03, 0xdf, 0x90, 0x4f, 0x01, 0x25, 0xfe, 0xa4, 0xc7, 0x02, 0x23, 0xfd, 0xa6, 0x2a, 0x02, 0x84, 0xfd, 0x46, 0x62, 0x90, 0x4f, 0xfe, 0xdb, 0x01, 0x5c, 0x29, 0xfe, 0x7b, 0x02, 0xba, 0xfe, 0xc7, 0xfe, 0x16, 0x06, 0x23, 0x3a, 0xf5, 0xaa, 0xfd, 0x98, 0xaa, 0x80, 0xaa, 0xfe, 0xd1, 0x3a, 0xf5, 0xaa, 0x80, 0x03, 0xbc, 0xfc, 0xee, 0x02, 0x68, 0xfd, 0x98, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0xdf, 0x05, 0x46, 0x06, 0x23, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x17, 0x07, 0x21, 0x11, 0x21, 0x07, 0x21, 0x15, 0x21, 0x03, 0x27, 0x37, 0x21, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x13, 0x21, 0x35, 0x21, 0x17, 0x03, 0x21, 0x11, 0x03, 0xdf, 0x90, 0x4f, 0x01, 0x25, 0xfd, 0xa6, 0x2a, 0x02, 0x84, 0xfd, 0x46, 0x62, 0x90, 0x4f, 0xfe, 0xdb, 0x01, 0x5c, 0x29, 0xfe, 0x7b, 0x01, 0xbc, 0xc7, 0xfd, 0x7d, 0x02, 0xba, 0x6c, 0xc7, 0x01, 0x8a, 0x06, 0x23, 0x3a, 0xf5, 0xfc, 0x44, 0x80, 0xaa, 0xfe, 0xd1, 0x3a, 0xf5, 0xaa, 0x80, 0xaa, 0x02, 0x68, 0xaa, 0xaa, 0xfd, 0x98, 0x02, 0x68, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0x3f, 0x05, 0x46, 0x04, 0xf4, 0x00, 0x14, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x37, 0x21, 0xc3, 0x04, 0x82, 0xfc, 0x17, 0x03, 0xe9, 0xfe, 0x80, 0x18, 0x45, 0x01, 0xad, 0xfd, 0xe7, 0x84, 0x7d, 0x46, 0xfe, 0x52, 0x02, 0x1a, 0x51, 0xfd, 0x95, 0x04, 0xf4, 0xaa, 0xfd, 0x98, 0xaa, 0x13, 0x6d, 0xaa, 0xcf, 0x62, 0x6d, 0xaa, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0x3f, 0x05, 0x46, 0x04, 0xf4, 0x00, 0x14, 0x00, 0x00, 0x25, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x17, 0x07, 0x05, 0x45, 0xfd, 0xe7, 0x84, 0x7d, 0x46, 0xfe, 0x52, 0x02, 0x1a, 0x51, 0xfd, 0x95, 0x03, 0xe9, 0xfc, 0x17, 0x04, 0x82, 0xfe, 0x80, 0x18, 0x45, 0xb8, 0xaa, 0xcf, 0x62, 0x6d, 0xaa, 0x80, 0xaa, 0x02, 0x68, 0xaa, 0xfc, 0x44, 0x13, 0x6d, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0xe5, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x1b, 0x00, 0x22, 0x00, 0x00, 0x25, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x17, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x27, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x02, 0x9c, 0x59, 0x3d, 0x4f, 0x9b, 0x58, 0x5e, 0xa1, 0x58, 0x54, 0x6c, 0x63, 0x8b, 0x5e, 0x5b, 0x3d, 0x4e, 0x98, 0x5d, 0x5f, 0xa1, 0x57, 0x57, 0x6d, 0x61, 0x8c, 0x03, 0x07, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0x11, 0x1f, 0x4c, 0x54, 0xb4, 0x4e, 0x44, 0x2a, 0xf3, 0x46, 0xe9, 0x20, 0x4a, 0x56, 0xb4, 0x4e, 0x44, 0x2b, 0xf0, 0x46, 0x04, 0xcd, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0xe5, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x1b, 0x00, 0x22, 0x00, 0x00, 0x25, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x17, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x27, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x02, 0x9c, 0x59, 0x3d, 0x4f, 0x9b, 0x58, 0x5e, 0xa1, 0x58, 0x54, 0x6c, 0x63, 0x8b, 0x5e, 0x5b, 0x3d, 0x4e, 0x98, 0x5d, 0x5f, 0xa1, 0x57, 0x57, 0x6d, 0x61, 0x8c, 0xfe, 0x85, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0x11, 0x1f, 0x4c, 0x54, 0xb4, 0x4e, 0x44, 0x2a, 0xf3, 0x46, 0xe9, 0x20, 0x4a, 0x56, 0xb4, 0x4e, 0x44, 0x2b, 0xf0, 0x46, 0x04, 0xcd, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0xa6, 0x05, 0x46, 0x05, 0x57, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x00, 0x05, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x17, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x27, 0x01, 0x00, 0x05, 0x04, 0x01, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x02, 0x9c, 0x5a, 0x3c, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x54, 0x6c, 0x63, 0x8c, 0x5f, 0x5b, 0x3e, 0x4d, 0x98, 0x5d, 0x5e, 0xa1, 0x58, 0x56, 0x6d, 0x62, 0x8b, 0x03, 0x07, 0xfe, 0xa7, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x59, 0xfe, 0xa7, 0xfc, 0xd7, 0x03, 0x29, 0x01, 0x59, 0x2e, 0x20, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x2b, 0xf3, 0x46, 0xe9, 0x20, 0x4b, 0x55, 0xb3, 0x4e, 0x45, 0x2c, 0xf1, 0x46, 0x05, 0x94, 0xfe, 0xe5, 0x5d, 0x5d, 0xfe, 0xe5, 0xd7, 0x01, 0x78, 0x84, 0xa6, 0x7c, 0x01, 0x80, 0x00, 0x02, 0x00, 0xca, 0xfe, 0xa2, 0x05, 0x4d, 0x05, 0x57, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x00, 0x05, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x17, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x27, 0x01, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x00, 0x25, 0x24, 0x02, 0xa3, 0x59, 0x3d, 0x4f, 0x9b, 0x59, 0x5f, 0xa1, 0x57, 0x54, 0x6d, 0x62, 0x8c, 0x5f, 0x5b, 0x3e, 0x4e, 0x98, 0x5c, 0x5e, 0xa1, 0x58, 0x56, 0x6d, 0x61, 0x8c, 0xfe, 0x85, 0x01, 0x59, 0x03, 0x29, 0xfc, 0xd7, 0xfe, 0xa7, 0x01, 0x59, 0x01, 0xad, 0xfe, 0x53, 0x33, 0x20, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x2b, 0xf4, 0x46, 0xea, 0x20, 0x4b, 0x55, 0xb3, 0x4e, 0x45, 0x2c, 0xf0, 0x46, 0x05, 0x98, 0xd7, 0xfe, 0x80, 0x7c, 0xa6, 0x84, 0xfe, 0x88, 0xd7, 0x01, 0x1b, 0x5d, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0xf6, 0x05, 0x46, 0x06, 0x0c, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x12, 0x00, 0x00, 0x01, 0x17, 0x03, 0x37, 0x11, 0x25, 0x03, 0x27, 0x13, 0x25, 0x35, 0x01, 0x13, 0x11, 0x07, 0x03, 0x27, 0x13, 0x05, 0x04, 0x6a, 0x8e, 0x76, 0xc3, 0xfd, 0xf4, 0xc6, 0x8e, 0xc6, 0xfe, 0x18, 0x02, 0xf8, 0xf1, 0x7d, 0xbb, 0x8e, 0x82, 0xfe, 0x3c, 0x06, 0x0c, 0x40, 0xfe, 0xc1, 0x59, 0xfb, 0x38, 0xf0, 0xfd, 0xe8, 0x40, 0x02, 0x19, 0xe0, 0xa6, 0x01, 0x5c, 0xfc, 0xef, 0x02, 0xc4, 0x39, 0xfe, 0x04, 0x40, 0x01, 0x61, 0xce, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0xf6, 0x05, 0x46, 0x06, 0x0c, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x12, 0x00, 0x00, 0x01, 0x27, 0x13, 0x07, 0x11, 0x05, 0x13, 0x17, 0x03, 0x05, 0x15, 0x01, 0x03, 0x11, 0x37, 0x13, 0x17, 0x03, 0x25, 0x01, 0x9f, 0x8e, 0x75, 0xc3, 0x02, 0x0d, 0xc5, 0x8e, 0xc6, 0x01, 0xe8, 0xfd, 0x09, 0xf2, 0x7d, 0xbc, 0x8e, 0x82, 0x01, 0xc3, 0xfe, 0xf6, 0x40, 0x01, 0x3f, 0x59, 0x04, 0xc8, 0xf0, 0x02, 0x18, 0x40, 0xfd, 0xe7, 0xe0, 0xa6, 0xfe, 0xa4, 0x03, 0x11, 0xfd, 0x3c, 0x39, 0x01, 0xfc, 0x40, 0xfe, 0x9f, 0xce, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0x7d, 0x05, 0x46, 0x06, 0x85, 0x00, 0x03, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x11, 0x07, 0x03, 0x01, 0x35, 0x21, 0x13, 0x25, 0x35, 0x01, 0x13, 0x17, 0x03, 0x37, 0x11, 0x25, 0x03, 0x21, 0x15, 0x21, 0x03, 0x27, 0x37, 0x01, 0x13, 0x05, 0x04, 0xac, 0x7f, 0xbb, 0xfd, 0x51, 0x01, 0x56, 0x90, 0xfe, 0x1a, 0x02, 0xf5, 0xae, 0x8e, 0x74, 0xc5, 0xfd, 0xf2, 0x78, 0x02, 0x86, 0xfd, 0x3b, 0x6a, 0x8e, 0x52, 0x01, 0x0a, 0x81, 0xfe, 0x3f, 0x01, 0x9e, 0x02, 0xc4, 0x3a, 0xfe, 0x05, 0xfd, 0x71, 0xaa, 0x01, 0x86, 0xdf, 0xa6, 0x01, 0x5b, 0x01, 0xd7, 0x40, 0xfe, 0xc5, 0x5a, 0xfb, 0x38, 0xf1, 0xfe, 0xbb, 0xaa, 0xfe, 0xdf, 0x40, 0xe1, 0x02, 0xd0, 0x01, 0x5f, 0xcd, 0x00, 0x00, 0x00, 0x03, 0x00, 0xbf, 0xfe, 0x7d, 0x05, 0x42, 0x06, 0x85, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x00, 0x37, 0x11, 0x01, 0x13, 0x17, 0x03, 0x05, 0x15, 0x01, 0x03, 0x21, 0x15, 0x21, 0x03, 0x27, 0x37, 0x23, 0x35, 0x33, 0x37, 0x13, 0x25, 0x11, 0x37, 0x01, 0x03, 0x25, 0xc0, 0x02, 0x61, 0xd2, 0x8e, 0xd2, 0x01, 0x93, 0xfd, 0x80, 0x76, 0x02, 0xf6, 0xfc, 0xcb, 0x6b, 0x8e, 0x53, 0xa7, 0xe6, 0x54, 0xec, 0xfe, 0x73, 0xf4, 0x01, 0x27, 0x60, 0x01, 0x4c, 0x9c, 0x04, 0xc8, 0xfe, 0xe9, 0x02, 0x38, 0x40, 0xfd, 0xc7, 0xb9, 0xa6, 0xfe, 0xdb, 0xfe, 0xc0, 0xaa, 0xfe, 0xdf, 0x40, 0xe1, 0xaa, 0xe4, 0x02, 0x81, 0xb5, 0xfd, 0x3c, 0x70, 0x01, 0x5e, 0xfe, 0xfc, 0x98, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x3a, 0xff, 0x42, 0x03, 0xf9, 0x05, 0xb8, 0x10, 0x27, 0x09, 0xa1, 0x02, 0x75, 0xfc, 0xfa, 0x10, 0x27, 0x09, 0xa1, 0x02, 0x75, 0x02, 0x72, 0x10, 0x07, 0x09, 0xa1, 0x02, 0x75, 0xff, 0xb6, 0x00, 0x00, 0xff, 0xff, 0x00, 0xd4, 0x01, 0xfe, 0x06, 0x5e, 0x02, 0xfc, 0x10, 0x26, 0x09, 0xa1, 0x0f, 0xb6, 0x10, 0x27, 0x09, 0xa1, 0x02, 0x75, 0xff, 0xb6, 0x10, 0x07, 0x09, 0xa1, 0x04, 0xdb, 0xff, 0xb6, 0xff, 0xff, 0x00, 0xd4, 0xff, 0x42, 0x06, 0x5e, 0x05, 0xb8, 0x10, 0x27, 0x09, 0xa1, 0x00, 0x0f, 0xfc, 0xfa, 0x10, 0x27, 0x09, 0xa1, 0x04, 0xdb, 0x02, 0x72, 0x10, 0x07, 0x09, 0xa1, 0x02, 0x75, 0xff, 0xb6, 0x00, 0x00, 0xff, 0xff, 0x00, 0xd4, 0xff, 0x42, 0x06, 0x5e, 0x05, 0xb8, 0x10, 0x27, 0x09, 0xa1, 0x04, 0xdb, 0xfc, 0xfa, 0x10, 0x27, 0x09, 0xa1, 0x00, 0x0f, 0x02, 0x72, 0x10, 0x07, 0x09, 0xa1, 0x02, 0x75, 0xff, 0xb6, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xec, 0x06, 0xe4, 0x05, 0xae, 0x00, 0x21, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x36, 0x37, 0x36, 0x24, 0x33, 0x21, 0x15, 0x21, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x15, 0x21, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x21, 0x15, 0x21, 0x22, 0x24, 0x27, 0x26, 0x01, 0xdf, 0xfe, 0x70, 0x01, 0x8e, 0x0d, 0x46, 0x54, 0x01, 0x41, 0xad, 0x02, 0x72, 0xfd, 0x8d, 0x85, 0x7c, 0x7c, 0x44, 0x3a, 0x07, 0x04, 0x75, 0xfb, 0x8d, 0x06, 0x39, 0x43, 0x7d, 0x7c, 0x85, 0x02, 0x73, 0xfd, 0x8e, 0xad, 0xfe, 0xbf, 0x54, 0x41, 0x02, 0x73, 0xa0, 0x94, 0x8f, 0xb0, 0xc8, 0x9f, 0x01, 0x4d, 0x4f, 0x8a, 0x78, 0x5d, 0xa0, 0x4a, 0x78, 0x8b, 0x4e, 0x4c, 0x01, 0x9f, 0xc6, 0xb0, 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0xff, 0xec, 0x05, 0xa9, 0x05, 0xae, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x16, 0x12, 0x16, 0x17, 0x21, 0x15, 0x21, 0x22, 0x24, 0x02, 0x10, 0x12, 0x24, 0x33, 0x21, 0x15, 0x21, 0x0e, 0x01, 0x02, 0x07, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x01, 0x35, 0x06, 0x7b, 0xfa, 0x85, 0x02, 0x73, 0xfd, 0x8d, 0xad, 0xfe, 0xc0, 0xaa, 0xaa, 0x01, 0x40, 0xad, 0x02, 0x73, 0xfd, 0x8d, 0x85, 0xf9, 0x7d, 0x08, 0x03, 0xe6, 0x90, 0x90, 0x02, 0x73, 0x4a, 0xfe, 0xfd, 0x9a, 0x01, 0x9f, 0xc6, 0x01, 0x60, 0x01, 0x74, 0x01, 0x60, 0xc8, 0x9f, 0x01, 0x9c, 0xfe, 0xfe, 0x5d, 0x01, 0x10, 0xfd, 0x40, 0x01, 0x10, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x9b, 0x04, 0x68, 0x04, 0x67, 0x00, 0x19, 0x00, 0x00, 0x25, 0x20, 0x24, 0x10, 0x24, 0x29, 0x01, 0x15, 0x21, 0x22, 0x07, 0x06, 0x07, 0x21, 0x35, 0x33, 0x11, 0x23, 0x35, 0x21, 0x16, 0x17, 0x16, 0x33, 0x21, 0x15, 0x02, 0xda, 0xfe, 0xf6, 0xfe, 0xf3, 0x01, 0x0d, 0x01, 0x0a, 0x01, 0x8e, 0xfe, 0x72, 0xcf, 0x60, 0x47, 0x1a, 0x02, 0x9e, 0x80, 0x80, 0xfd, 0x62, 0x22, 0x3f, 0x66, 0xc9, 0x01, 0x8e, 0x9b, 0xf6, 0x01, 0xe0, 0xf6, 0x8e, 0x51, 0x3b, 0x84, 0xac, 0xfe, 0x1a, 0xac, 0x91, 0x30, 0x51, 0x8e, 0x00, 0xff, 0xff, 0x00, 0x9d, 0xff, 0xec, 0x05, 0xa9, 0x07, 0x48, 0x10, 0x26, 0x08, 0xe4, 0x00, 0x00, 0x10, 0x07, 0x09, 0xa1, 0x01, 0xff, 0x04, 0x02, 0x00, 0x02, 0x00, 0x9d, 0xff, 0xec, 0x05, 0xa9, 0x06, 0xd2, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x21, 0x15, 0x21, 0x22, 0x24, 0x02, 0x35, 0x34, 0x12, 0x24, 0x33, 0x21, 0x15, 0x21, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x15, 0x11, 0x21, 0x35, 0x21, 0x01, 0x35, 0x06, 0x39, 0x43, 0x7d, 0x7c, 0x85, 0x02, 0x73, 0xfd, 0x8d, 0xad, 0xfe, 0xc0, 0xaa, 0xaa, 0x01, 0x40, 0xad, 0x02, 0x73, 0xfd, 0x8d, 0x85, 0x7c, 0x7d, 0x43, 0x3a, 0x08, 0x04, 0x76, 0xfb, 0x2e, 0x04, 0xd2, 0x02, 0x73, 0x4a, 0x78, 0x8b, 0x4e, 0x4c, 0x01, 0x9f, 0xc6, 0x01, 0x60, 0xbb, 0xb9, 0x01, 0x60, 0xc8, 0x9f, 0x01, 0x4d, 0x4f, 0x8a, 0x78, 0x5d, 0xa0, 0x03, 0xbf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x9b, 0x04, 0x68, 0x05, 0x7d, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x00, 0x25, 0x20, 0x24, 0x35, 0x34, 0x24, 0x29, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x07, 0x21, 0x15, 0x21, 0x16, 0x17, 0x16, 0x33, 0x21, 0x15, 0x11, 0x21, 0x35, 0x21, 0x02, 0xda, 0xfe, 0xf6, 0xfe, 0xf3, 0x01, 0x0d, 0x01, 0x0a, 0x01, 0x8e, 0xfe, 0x72, 0xd1, 0x5e, 0x46, 0x1b, 0x03, 0x1e, 0xfc, 0xe2, 0x21, 0x40, 0x67, 0xc8, 0x01, 0x8e, 0xfc, 0x7e, 0x03, 0x82, 0x9b, 0xf6, 0xf0, 0xf0, 0xf6, 0x8e, 0x01, 0x01, 0x4f, 0x3a, 0x85, 0x8e, 0x91, 0x30, 0x51, 0x8e, 0x04, 0x56, 0x8c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xfe, 0xda, 0x05, 0xa9, 0x05, 0xae, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x21, 0x15, 0x21, 0x22, 0x24, 0x02, 0x35, 0x34, 0x12, 0x24, 0x33, 0x21, 0x15, 0x21, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x15, 0x11, 0x21, 0x35, 0x21, 0x01, 0x35, 0x06, 0x39, 0x43, 0x7d, 0x7c, 0x85, 0x02, 0x73, 0xfd, 0x8d, 0xad, 0xfe, 0xc0, 0xaa, 0xaa, 0x01, 0x40, 0xad, 0x02, 0x73, 0xfd, 0x8d, 0x85, 0x7c, 0x7d, 0x43, 0x3a, 0x08, 0x04, 0x76, 0xfb, 0x2e, 0x04, 0xd2, 0x02, 0x73, 0x4a, 0x78, 0x8b, 0x4e, 0x4c, 0x01, 0x9f, 0xc6, 0x01, 0x60, 0xbb, 0xb9, 0x01, 0x60, 0xc8, 0x9f, 0x01, 0x4d, 0x4f, 0x8a, 0x78, 0x5d, 0xa0, 0xfc, 0x67, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0xff, 0xec, 0x05, 0xa9, 0x05, 0xae, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x17, 0x16, 0x17, 0x16, 0x17, 0x21, 0x15, 0x21, 0x22, 0x24, 0x02, 0x35, 0x34, 0x12, 0x24, 0x33, 0x21, 0x15, 0x21, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x15, 0x21, 0x01, 0x35, 0x04, 0x73, 0xfb, 0xbc, 0x10, 0x43, 0x7d, 0x7c, 0x85, 0x02, 0x73, 0xfd, 0x8d, 0xad, 0xfe, 0xc0, 0xaa, 0xaa, 0x01, 0x40, 0xad, 0x02, 0x73, 0xfd, 0x8d, 0x85, 0x7c, 0x7d, 0x43, 0x0d, 0x0b, 0x04, 0x4c, 0xfb, 0x8d, 0x02, 0x73, 0xa0, 0x22, 0x8b, 0x4e, 0x4c, 0x01, 0x9f, 0xc6, 0x01, 0x60, 0xbb, 0xb9, 0x01, 0x60, 0xc8, 0x9f, 0x01, 0x4d, 0x4f, 0x8a, 0x1b, 0x1a, 0xa0, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xec, 0x06, 0xe4, 0x05, 0xae, 0x00, 0x21, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x06, 0x07, 0x06, 0x04, 0x23, 0x21, 0x35, 0x21, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x21, 0x35, 0x21, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x21, 0x35, 0x21, 0x32, 0x04, 0x17, 0x16, 0x05, 0x54, 0x01, 0x90, 0xfe, 0x72, 0x0d, 0x46, 0x54, 0xfe, 0xbf, 0xac, 0xfd, 0x8d, 0x02, 0x73, 0x85, 0x7c, 0x7c, 0x44, 0x3a, 0x07, 0xfb, 0x8b, 0x04, 0x74, 0x07, 0x39, 0x43, 0x7d, 0x7c, 0x85, 0xfd, 0x8d, 0x02, 0x73, 0xac, 0x01, 0x41, 0x54, 0x41, 0x03, 0x27, 0xa0, 0x94, 0x8f, 0xb0, 0xc8, 0x9f, 0x01, 0x4d, 0x4f, 0x8a, 0x78, 0x5d, 0xa0, 0x4a, 0x78, 0x8b, 0x4e, 0x4c, 0x01, 0x9f, 0xc6, 0xb0, 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0xff, 0xec, 0x05, 0xa9, 0x05, 0xae, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x26, 0x02, 0x26, 0x27, 0x21, 0x35, 0x21, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x21, 0x35, 0x21, 0x3e, 0x01, 0x12, 0x37, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x05, 0x11, 0x06, 0x7c, 0xf9, 0x85, 0xfd, 0x8d, 0x02, 0x73, 0xad, 0x01, 0x3f, 0xab, 0xab, 0xfe, 0xc1, 0xad, 0xfd, 0x8d, 0x02, 0x73, 0x85, 0xf8, 0x7e, 0x08, 0xfc, 0x1a, 0x90, 0x90, 0x03, 0x27, 0x4a, 0x01, 0x03, 0x9a, 0x01, 0x9f, 0xc6, 0xfe, 0xa0, 0xfe, 0x8c, 0xfe, 0xa0, 0xc8, 0x9f, 0x01, 0x9c, 0x01, 0x02, 0x5d, 0xfe, 0xf0, 0x02, 0xc0, 0xfe, 0xf0, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x9b, 0x04, 0x68, 0x04, 0x67, 0x00, 0x19, 0x00, 0x00, 0x01, 0x20, 0x04, 0x10, 0x04, 0x29, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x37, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x26, 0x27, 0x26, 0x23, 0x25, 0x35, 0x02, 0x51, 0x01, 0x0a, 0x01, 0x0d, 0xfe, 0xf3, 0xfe, 0xf6, 0xfe, 0x72, 0x01, 0x8e, 0xcf, 0x60, 0x46, 0x1b, 0xfd, 0x62, 0x80, 0x80, 0x02, 0x9e, 0x21, 0x40, 0x67, 0xc8, 0xfe, 0x72, 0x04, 0x67, 0xf6, 0xfe, 0x20, 0xf6, 0x8e, 0x51, 0x3a, 0x85, 0xac, 0x01, 0xe6, 0xac, 0x91, 0x30, 0x50, 0x01, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xff, 0xec, 0x05, 0xa9, 0x06, 0xd2, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x21, 0x35, 0x21, 0x32, 0x04, 0x12, 0x15, 0x14, 0x02, 0x04, 0x23, 0x21, 0x35, 0x21, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x05, 0x11, 0x06, 0x39, 0x43, 0x7e, 0x7b, 0x85, 0xfd, 0x8d, 0x02, 0x73, 0xad, 0x01, 0x3f, 0xab, 0xab, 0xfe, 0xc1, 0xad, 0xfd, 0x8d, 0x02, 0x73, 0x85, 0x7b, 0x7d, 0x44, 0x3a, 0x08, 0xfb, 0x8a, 0x04, 0xd1, 0xfb, 0x2f, 0x04, 0xd1, 0x03, 0x27, 0x4a, 0x78, 0x8b, 0x4e, 0x4c, 0x01, 0x9f, 0xc6, 0xfe, 0xa0, 0xbb, 0xb9, 0xfe, 0xa0, 0xc8, 0x9f, 0x01, 0x4d, 0x4f, 0x8a, 0x78, 0x5d, 0xa0, 0x03, 0x0b, 0xa0, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x9b, 0x04, 0x68, 0x05, 0x7d, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x20, 0x04, 0x15, 0x14, 0x04, 0x29, 0x01, 0x35, 0x25, 0x32, 0x37, 0x36, 0x37, 0x21, 0x35, 0x05, 0x26, 0x27, 0x26, 0x07, 0x21, 0x35, 0x25, 0x21, 0x35, 0x21, 0x02, 0x51, 0x01, 0x0a, 0x01, 0x0d, 0xfe, 0xf3, 0xfe, 0xf6, 0xfe, 0x72, 0x01, 0x8e, 0xd1, 0x5e, 0x46, 0x1b, 0xfc, 0xe2, 0x03, 0x1e, 0x22, 0x3f, 0x68, 0xc7, 0xfe, 0x72, 0x03, 0x82, 0xfc, 0x7e, 0x03, 0x82, 0x04, 0x67, 0xf6, 0xf1, 0xef, 0xf6, 0x8e, 0x01, 0x50, 0x3a, 0x85, 0x8e, 0x01, 0x91, 0x31, 0x52, 0x01, 0x8e, 0x8a, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x83, 0x05, 0xc2, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x05, 0x82, 0xfb, 0xda, 0x04, 0x26, 0xfb, 0x41, 0x04, 0xbf, 0xfb, 0xda, 0x04, 0x26, 0x02, 0x82, 0xfe, 0x28, 0xaa, 0x05, 0xc2, 0xaa, 0xfe, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x42, 0xff, 0xdc, 0x04, 0x15, 0x04, 0x1c, 0x00, 0x13, 0x00, 0x1b, 0x00, 0x23, 0x00, 0x00, 0x01, 0x32, 0x17, 0x37, 0x17, 0x07, 0x16, 0x15, 0x14, 0x00, 0x23, 0x22, 0x27, 0x07, 0x27, 0x37, 0x26, 0x35, 0x34, 0x00, 0x05, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x1f, 0x01, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x02, 0x2a, 0xa8, 0x80, 0x6a, 0x59, 0x6a, 0x63, 0xfe, 0xe3, 0xc7, 0xa5, 0x7f, 0x6a, 0x59, 0x69, 0x64, 0x01, 0x1c, 0x01, 0x94, 0x5a, 0x74, 0x91, 0xd2, 0x40, 0x59, 0x59, 0x71, 0x93, 0xd2, 0x3e, 0x04, 0x17, 0x71, 0x76, 0x63, 0x76, 0x8d, 0xba, 0xdd, 0xfe, 0xc4, 0x6f, 0x76, 0x63, 0x76, 0x8d, 0xba, 0xdf, 0x01, 0x3c, 0xd5, 0x48, 0xe9, 0xa5, 0x80, 0x63, 0x62, 0x47, 0xe9, 0xa3, 0x80, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00, 0x66, 0x01, 0x4c, 0x03, 0xe4, 0x03, 0x8c, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x01, 0x35, 0x05, 0x11, 0x01, 0x15, 0x02, 0x5f, 0xfe, 0x08, 0x01, 0x84, 0x01, 0xf8, 0x02, 0x7a, 0xfe, 0xd2, 0x01, 0x4a, 0xc2, 0xfa, 0x01, 0x2e, 0xfe, 0xb6, 0xc2, 0x00, 0x00, 0x02, 0x00, 0x83, 0x00, 0x00, 0x04, 0x0f, 0x04, 0xc4, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x33, 0x11, 0x09, 0x01, 0x11, 0x25, 0x21, 0x11, 0x09, 0x01, 0x83, 0x01, 0xc6, 0x01, 0xc6, 0xfd, 0x0a, 0x02, 0x60, 0xfe, 0xd0, 0xfe, 0xd0, 0x02, 0xa0, 0x02, 0x24, 0xfd, 0xdc, 0xfd, 0x60, 0xaa, 0x01, 0xd5, 0x01, 0x79, 0xfe, 0x87, 0x00, 0x00, 0x00, 0x01, 0x01, 0x79, 0x03, 0xda, 0x04, 0x8e, 0x05, 0xdc, 0x00, 0x07, 0x00, 0x00, 0x01, 0x03, 0x27, 0x01, 0x33, 0x01, 0x07, 0x03, 0x02, 0xdc, 0xf7, 0x6c, 0x01, 0x63, 0x51, 0x01, 0x61, 0x6c, 0xf5, 0x04, 0xea, 0xfe, 0xf0, 0x78, 0x01, 0x8a, 0xfe, 0x76, 0x78, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x79, 0x00, 0x00, 0x04, 0x8e, 0x02, 0x02, 0x00, 0x07, 0x00, 0x00, 0x25, 0x33, 0x13, 0x17, 0x01, 0x23, 0x01, 0x37, 0x02, 0xdc, 0x51, 0xf5, 0x6c, 0xfe, 0x9f, 0x51, 0xfe, 0x9d, 0x6c, 0xf2, 0x01, 0x10, 0x78, 0xfe, 0x76, 0x01, 0x8a, 0x78, 0x00, 0x00, 0xff, 0xff, 0x01, 0x79, 0x00, 0x00, 0x04, 0x8e, 0x03, 0x3f, 0x10, 0x26, 0x11, 0x49, 0x00, 0x00, 0x10, 0x07, 0x09, 0xdf, 0x00, 0x00, 0xfc, 0x26, 0xff, 0xff, 0x01, 0x79, 0x00, 0x00, 0x04, 0x8e, 0x04, 0x1b, 0x10, 0x27, 0x11, 0x49, 0x00, 0x00, 0x00, 0xdc, 0x10, 0x26, 0x11, 0x49, 0x00, 0xd7, 0x10, 0x07, 0x09, 0xdf, 0x00, 0x00, 0xfc, 0x26, 0x00, 0x01, 0x01, 0x1b, 0xff, 0xc5, 0x02, 0x69, 0x06, 0x4e, 0x00, 0x19, 0x00, 0x00, 0x01, 0x17, 0x06, 0x14, 0x17, 0x16, 0x14, 0x07, 0x06, 0x14, 0x17, 0x16, 0x14, 0x07, 0x27, 0x36, 0x34, 0x27, 0x26, 0x34, 0x37, 0x36, 0x34, 0x27, 0x26, 0x34, 0x01, 0x8b, 0x6e, 0x45, 0x45, 0x6f, 0x6f, 0x45, 0x45, 0x6f, 0x6f, 0x6e, 0x45, 0x45, 0x6f, 0x6f, 0x45, 0x45, 0x6f, 0x06, 0x4e, 0x76, 0x4f, 0x70, 0x50, 0x81, 0xf8, 0x81, 0x50, 0x6f, 0x50, 0x81, 0xf9, 0x81, 0x76, 0x4f, 0x70, 0x50, 0x81, 0xf8, 0x81, 0x50, 0x70, 0x50, 0x81, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0xf2, 0x02, 0x1c, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x13, 0x21, 0x15, 0x23, 0x11, 0x23, 0x9e, 0x01, 0x7e, 0xd8, 0xa6, 0x06, 0x14, 0x8f, 0xf9, 0x6d, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb3, 0xfe, 0xf2, 0x02, 0x31, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x23, 0x35, 0x02, 0x31, 0xa6, 0xd8, 0x06, 0x14, 0xf8, 0xde, 0x06, 0x93, 0x8f, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0xf2, 0x02, 0x1c, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x33, 0x15, 0x9e, 0xa6, 0xd8, 0xfe, 0xf2, 0x07, 0x22, 0xf9, 0x6d, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb3, 0xfe, 0xf2, 0x02, 0x31, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x35, 0x33, 0x11, 0x33, 0x02, 0x31, 0xfe, 0x82, 0xd8, 0xa6, 0xfe, 0xf2, 0x8f, 0x06, 0x93, 0x00, 0x00, 0x02, 0x02, 0xa8, 0xff, 0x62, 0x05, 0x78, 0x02, 0x82, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x11, 0x23, 0x13, 0x35, 0x21, 0x15, 0x02, 0xa8, 0x82, 0x82, 0xb4, 0x02, 0x1c, 0x01, 0xba, 0xfd, 0xa8, 0x02, 0x90, 0x90, 0x90, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xff, 0x62, 0x03, 0x2a, 0x02, 0x82, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x15, 0x21, 0x35, 0x05, 0x33, 0x11, 0x23, 0x02, 0x76, 0xfd, 0xe4, 0x02, 0x4e, 0x82, 0x82, 0x02, 0x82, 0x90, 0x90, 0xc8, 0xfd, 0xa8, 0x00, 0x00, 0x02, 0x02, 0xa8, 0x01, 0xf2, 0x05, 0x78, 0x05, 0x12, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x25, 0x23, 0x11, 0x33, 0x03, 0x5c, 0x02, 0x1c, 0xfd, 0xb2, 0x82, 0x82, 0x01, 0xf2, 0x90, 0x90, 0xc8, 0x02, 0x58, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x01, 0xf2, 0x03, 0x2a, 0x05, 0x12, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x15, 0x21, 0x35, 0x25, 0x23, 0x11, 0x33, 0x02, 0x76, 0xfd, 0xe4, 0x02, 0xd0, 0x82, 0x82, 0x02, 0x82, 0x90, 0x90, 0x38, 0x02, 0x58, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x01, 0x1f, 0x05, 0x46, 0x03, 0x5e, 0x00, 0x05, 0x00, 0x00, 0x01, 0x15, 0x21, 0x11, 0x23, 0x11, 0x05, 0x45, 0xfc, 0x15, 0x97, 0x03, 0x5e, 0xaa, 0xfe, 0x6b, 0x02, 0x3f, 0x00, 0x02, 0x00, 0x05, 0x01, 0x02, 0x03, 0xad, 0x05, 0x12, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x24, 0x05, 0x02, 0x13, 0x04, 0x25, 0x12, 0x03, 0x12, 0x03, 0x04, 0x25, 0x02, 0x13, 0x24, 0x7e, 0x01, 0x5a, 0x01, 0x5b, 0x7c, 0x7c, 0xfe, 0xa5, 0xfe, 0xa6, 0x7c, 0xf5, 0xa6, 0xa6, 0x01, 0xd4, 0x01, 0xd3, 0xa5, 0xa5, 0xfe, 0x2c, 0x01, 0x8a, 0x89, 0x89, 0x01, 0x80, 0x01, 0x82, 0x8a, 0x8a, 0xfe, 0x7e, 0xfd, 0xf8, 0x01, 0xf4, 0x02, 0x1c, 0xb1, 0xb1, 0xfe, 0x0c, 0xfd, 0xe5, 0xb1, 0x00, 0x06, 0x00, 0xde, 0x00, 0x01, 0x06, 0x55, 0x06, 0x13, 0x00, 0x03, 0x00, 0x31, 0x00, 0x3b, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x59, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x11, 0x15, 0x14, 0x06, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x11, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x32, 0x16, 0x1d, 0x01, 0x21, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x11, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x14, 0x16, 0x33, 0x13, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x01, 0x33, 0x32, 0x36, 0x34, 0x26, 0x22, 0x06, 0x15, 0x11, 0x15, 0x14, 0x16, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x03, 0x14, 0x01, 0x0b, 0xfe, 0xf5, 0xa6, 0xea, 0xa6, 0xa6, 0x72, 0x99, 0x99, 0x72, 0xa6, 0xa6, 0xea, 0xa6, 0x01, 0x0b, 0xa6, 0x75, 0x76, 0xa5, 0xa5, 0x73, 0x99, 0x99, 0x73, 0xa5, 0xa5, 0x76, 0x75, 0xa6, 0xfe, 0x70, 0x58, 0x3e, 0x3d, 0x58, 0x58, 0x3e, 0x95, 0x95, 0x3e, 0x58, 0x58, 0x3e, 0x3d, 0x58, 0x02, 0x15, 0x96, 0x3e, 0x58, 0x58, 0x7c, 0x58, 0x58, 0x7c, 0x58, 0x58, 0x3e, 0x02, 0x76, 0x01, 0x28, 0xfe, 0x44, 0xaa, 0x80, 0xb7, 0xb8, 0x83, 0x80, 0xba, 0x01, 0x28, 0xba, 0x81, 0x82, 0xb8, 0xb7, 0x80, 0xaa, 0xaa, 0x80, 0xb7, 0xb8, 0x82, 0x81, 0xba, 0xfe, 0xd8, 0xba, 0x80, 0x83, 0xb8, 0xb7, 0x80, 0xaa, 0x02, 0x50, 0xa7, 0x45, 0x61, 0x61, 0x8a, 0x62, 0xfd, 0xb0, 0x62, 0x44, 0x45, 0x62, 0x62, 0x44, 0x02, 0xf7, 0x62, 0x8a, 0x61, 0x61, 0x45, 0xfd, 0x09, 0xa7, 0x44, 0x62, 0x62, 0x45, 0x44, 0x62, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x01, 0x1f, 0x05, 0x46, 0x03, 0x5e, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x11, 0x33, 0x11, 0x21, 0x05, 0x45, 0xfb, 0x7e, 0x97, 0x03, 0xeb, 0x01, 0x1f, 0x02, 0x3f, 0xfe, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0x03, 0x67, 0x02, 0xe8, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x11, 0x23, 0x11, 0x21, 0x02, 0xe7, 0xfe, 0x39, 0x82, 0x02, 0x49, 0x05, 0x84, 0xfd, 0xe3, 0x02, 0xad, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x78, 0x03, 0x67, 0x02, 0xc2, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x13, 0x35, 0x21, 0x11, 0x23, 0x11, 0x79, 0x02, 0x49, 0x82, 0x05, 0x84, 0x90, 0xfd, 0x53, 0x02, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xff, 0x70, 0x02, 0xe8, 0x02, 0x1d, 0x00, 0x05, 0x00, 0x00, 0x21, 0x15, 0x21, 0x11, 0x33, 0x11, 0x02, 0xe7, 0xfd, 0xb7, 0x82, 0x90, 0x02, 0xad, 0xfd, 0xe3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x78, 0xff, 0x70, 0x02, 0xc2, 0x02, 0x1d, 0x00, 0x05, 0x00, 0x00, 0x33, 0x21, 0x11, 0x33, 0x11, 0x21, 0x79, 0x01, 0xc7, 0x82, 0xfd, 0xb7, 0x02, 0x1d, 0xfd, 0x53, 0x00, 0x00, 0x00, 0x01, 0x01, 0x83, 0xfe, 0x00, 0x03, 0x95, 0x07, 0x6c, 0x00, 0x19, 0x00, 0x00, 0x01, 0x11, 0x34, 0x37, 0x1a, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x03, 0x02, 0x15, 0x30, 0x11, 0x01, 0x84, 0x03, 0x0a, 0xab, 0xb6, 0x48, 0x5a, 0x39, 0x32, 0x27, 0x19, 0x15, 0x0e, 0x05, 0x08, 0x0f, 0x5d, 0x10, 0x07, 0xfe, 0x00, 0x05, 0x08, 0x24, 0x81, 0x02, 0x03, 0x01, 0xbc, 0x54, 0x41, 0x36, 0x3f, 0x13, 0x10, 0x26, 0x0f, 0x48, 0xfd, 0x95, 0xfe, 0xd3, 0x02, 0xfa, 0x98, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0xfe, 0x1a, 0x02, 0x37, 0x07, 0x89, 0x00, 0x19, 0x00, 0x00, 0x01, 0x11, 0x14, 0x07, 0x0a, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x13, 0x12, 0x35, 0x30, 0x11, 0x02, 0x36, 0x03, 0x0a, 0xab, 0xb6, 0x48, 0x5a, 0x39, 0x32, 0x27, 0x19, 0x15, 0x0e, 0x05, 0x08, 0x0f, 0x5d, 0x10, 0x07, 0x07, 0x89, 0xfa, 0xf5, 0x24, 0x81, 0xfd, 0xfd, 0xfe, 0x44, 0x54, 0x41, 0x36, 0x3f, 0x13, 0x10, 0x26, 0x0f, 0x48, 0x02, 0x6b, 0x01, 0x2d, 0x02, 0x05, 0x6b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x8c, 0x01, 0xd0, 0x07, 0xc0, 0x04, 0x9a, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x09, 0x01, 0x27, 0x01, 0x33, 0x01, 0x07, 0x01, 0x25, 0x21, 0x35, 0x29, 0x02, 0x15, 0x21, 0x03, 0xfe, 0xfe, 0x55, 0x6c, 0x02, 0x17, 0x50, 0x02, 0x15, 0x6c, 0xfe, 0x57, 0xfe, 0xb3, 0xfd, 0x8b, 0x02, 0x75, 0x02, 0x49, 0x02, 0x76, 0xfd, 0x8a, 0x03, 0xa8, 0xfe, 0x28, 0x78, 0x02, 0x52, 0xfd, 0xae, 0x78, 0x01, 0xd8, 0x48, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8c, 0x00, 0x00, 0x07, 0xc0, 0x04, 0x9a, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x01, 0x21, 0x15, 0x21, 0x01, 0x21, 0x25, 0x21, 0x15, 0x21, 0x8c, 0x02, 0x75, 0x02, 0x9a, 0x02, 0x25, 0xfd, 0x8b, 0xfd, 0x66, 0xfd, 0xdb, 0x04, 0xbe, 0x02, 0x76, 0xfd, 0x8a, 0x04, 0x9a, 0xfc, 0x10, 0xaa, 0x03, 0xf0, 0xaa, 0xaa, 0x00, 0x05, 0x00, 0x8c, 0x00, 0x00, 0x0a, 0x2e, 0x06, 0x14, 0x00, 0x04, 0x00, 0x09, 0x00, 0x0c, 0x00, 0x0f, 0x00, 0x15, 0x00, 0x00, 0x33, 0x11, 0x21, 0x09, 0x02, 0x11, 0x33, 0x09, 0x01, 0x29, 0x01, 0x09, 0x01, 0x21, 0x09, 0x03, 0x33, 0x09, 0x01, 0x8c, 0x06, 0xe5, 0x02, 0xbd, 0xfd, 0x43, 0xf9, 0xa1, 0x7e, 0x02, 0x38, 0xfd, 0xc8, 0x04, 0x6f, 0xfc, 0x4f, 0x01, 0xd9, 0xfe, 0x27, 0x03, 0xb1, 0xfe, 0x28, 0x02, 0x94, 0xfd, 0xc9, 0x02, 0x37, 0x7f, 0x02, 0x37, 0xfd, 0xc9, 0x06, 0x14, 0xfc, 0xf6, 0xfc, 0xf6, 0x05, 0x80, 0xfb, 0x14, 0x02, 0x76, 0x02, 0x76, 0xfd, 0xf3, 0xfd, 0x21, 0x02, 0x0d, 0x02, 0xdf, 0xfd, 0x8a, 0xfd, 0x8a, 0x02, 0x74, 0x02, 0x78, 0x00, 0x05, 0x00, 0x8c, 0x00, 0x00, 0x07, 0xc0, 0x06, 0x14, 0x00, 0x03, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x13, 0x00, 0x00, 0x33, 0x11, 0x21, 0x11, 0x01, 0x11, 0x33, 0x09, 0x01, 0x29, 0x01, 0x09, 0x01, 0x21, 0x09, 0x03, 0x33, 0x11, 0x8c, 0x07, 0x34, 0xf9, 0x52, 0x7e, 0x02, 0x38, 0xfd, 0xc8, 0x04, 0x6f, 0xfc, 0x4f, 0x01, 0xd9, 0xfe, 0x27, 0x03, 0xb1, 0xfe, 0x28, 0x02, 0x94, 0xfd, 0xc9, 0x02, 0x37, 0x7f, 0x06, 0x14, 0xf9, 0xec, 0x05, 0x80, 0xfb, 0x14, 0x02, 0x76, 0x02, 0x76, 0xfd, 0xf3, 0xfd, 0x21, 0x02, 0x0d, 0x02, 0xdf, 0xfd, 0x8a, 0xfd, 0x8a, 0x04, 0xec, 0x00, 0x00, 0x2b, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xf9, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x53, 0x00, 0x5f, 0x00, 0x6b, 0x00, 0x77, 0x00, 0x83, 0x00, 0x8f, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0xb3, 0x00, 0xbf, 0x00, 0xcb, 0x00, 0xd7, 0x00, 0xe3, 0x00, 0xef, 0x00, 0xfb, 0x01, 0x07, 0x01, 0x13, 0x01, 0x1f, 0x01, 0x2b, 0x01, 0x37, 0x01, 0x43, 0x01, 0x4f, 0x01, 0x5b, 0x01, 0x67, 0x01, 0x73, 0x01, 0x7f, 0x01, 0x8b, 0x01, 0x97, 0x01, 0xa3, 0x01, 0xaf, 0x01, 0xbb, 0x01, 0xc7, 0x01, 0xd3, 0x01, 0xe4, 0x01, 0xf0, 0x01, 0xfc, 0x02, 0x08, 0x00, 0x00, 0x01, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x21, 0x22, 0x13, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x25, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x05, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x05, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x05, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x25, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x27, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x07, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x07, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x07, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x07, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x07, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x07, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x07, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x27, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x05, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x07, 0x32, 0x15, 0x11, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x23, 0x22, 0x3d, 0x01, 0x34, 0x33, 0x13, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x32, 0x05, 0x22, 0x3d, 0x01, 0x34, 0x33, 0x21, 0x32, 0x1d, 0x01, 0x14, 0x23, 0x01, 0x33, 0x07, 0xff, 0xc6, 0xc6, 0xf8, 0x01, 0xc7, 0x84, 0x43, 0x07, 0xff, 0x41, 0x41, 0xf8, 0x01, 0x43, 0xe9, 0x21, 0x42, 0x22, 0x22, 0x42, 0x21, 0xc9, 0x21, 0x44, 0x20, 0x20, 0x44, 0x21, 0x01, 0x29, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xfe, 0x72, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0x01, 0x8d, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x22, 0x42, 0x21, 0x21, 0x42, 0x22, 0xc7, 0x22, 0x42, 0x21, 0x21, 0x42, 0x22, 0x01, 0x66, 0x21, 0xe2, 0x22, 0x22, 0xe2, 0x21, 0xf9, 0x09, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x22, 0x42, 0x21, 0x21, 0x42, 0x22, 0xc6, 0x22, 0x42, 0x21, 0x21, 0x42, 0x22, 0xc7, 0x22, 0x42, 0x21, 0x21, 0x42, 0x22, 0xc7, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0xc6, 0x21, 0x42, 0x22, 0x22, 0x42, 0x21, 0xc7, 0x21, 0x42, 0x22, 0x22, 0x42, 0x21, 0x20, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc6, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x42, 0x22, 0x22, 0x42, 0x21, 0xc7, 0x21, 0x42, 0x22, 0x22, 0x42, 0x21, 0xc6, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x21, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc6, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc7, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0xc7, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0xc7, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x01, 0x01, 0x21, 0x7e, 0x21, 0x21, 0x7e, 0x21, 0x21, 0x21, 0x21, 0xde, 0x26, 0x20, 0x21, 0x21, 0x85, 0x21, 0x43, 0x21, 0x21, 0x43, 0x21, 0xc9, 0x21, 0x44, 0x20, 0x20, 0x44, 0x21, 0xfa, 0x48, 0x22, 0x22, 0x03, 0x9d, 0x21, 0x21, 0x05, 0xd5, 0xdd, 0xfb, 0xe5, 0xdd, 0xdd, 0x04, 0x1b, 0xdd, 0xdd, 0xfb, 0xe5, 0x4a, 0x4a, 0x04, 0x1b, 0x4a, 0xfc, 0x1c, 0x49, 0x25, 0x25, 0x49, 0x26, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0xb7, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0xb7, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0xb7, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0xb4, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0xdb, 0x25, 0xfe, 0xde, 0x25, 0x25, 0x95, 0x20, 0x25, 0x49, 0x25, 0xfd, 0x48, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x94, 0x25, 0x4a, 0x25, 0x25, 0x4a, 0x25, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x09, 0xa2, 0x06, 0x14, 0x00, 0x04, 0x00, 0x09, 0x00, 0x0c, 0x00, 0x0f, 0x00, 0x15, 0x00, 0x00, 0x29, 0x01, 0x09, 0x01, 0x21, 0x07, 0x23, 0x09, 0x01, 0x33, 0x09, 0x02, 0x11, 0x09, 0x01, 0x03, 0x23, 0x09, 0x01, 0x33, 0x01, 0x09, 0xa2, 0xf9, 0x1b, 0xfd, 0x44, 0x02, 0xbc, 0x06, 0xe5, 0x85, 0x7f, 0xfd, 0xc9, 0x02, 0x37, 0x7f, 0xfb, 0x12, 0x01, 0xd9, 0x01, 0xd8, 0xfe, 0x28, 0xfe, 0x27, 0xbb, 0x80, 0xfd, 0xc9, 0x02, 0x37, 0x80, 0x02, 0x37, 0x03, 0x0a, 0x03, 0x0a, 0x94, 0xfd, 0x8a, 0xfd, 0x8a, 0x04, 0xec, 0xfd, 0xf3, 0x02, 0x0d, 0xfb, 0x14, 0x02, 0x0d, 0xfd, 0xf3, 0x04, 0xec, 0xfd, 0x88, 0xfd, 0x8c, 0x02, 0x76, 0x00, 0x05, 0x00, 0x87, 0xff, 0x46, 0x05, 0xc3, 0x05, 0xfc, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x00, 0x13, 0x09, 0x01, 0x11, 0x09, 0x01, 0x03, 0x11, 0x09, 0x01, 0x11, 0x01, 0x03, 0x37, 0x01, 0x07, 0x11, 0x17, 0x01, 0x27, 0x01, 0x33, 0x11, 0x23, 0xee, 0x02, 0x37, 0x02, 0x37, 0xfd, 0xc9, 0xfd, 0xc9, 0x67, 0x02, 0x9e, 0x02, 0x9d, 0xfd, 0x63, 0x23, 0x34, 0x01, 0xae, 0x33, 0x33, 0xfe, 0x52, 0x34, 0xfe, 0x52, 0x67, 0x67, 0x01, 0x35, 0xfe, 0x95, 0x01, 0x6b, 0x02, 0xd8, 0x01, 0x6b, 0xfe, 0x95, 0xfc, 0xe6, 0x03, 0x5c, 0x01, 0xad, 0xfe, 0x53, 0xfc, 0xa4, 0xfe, 0x53, 0x05, 0x41, 0x63, 0xfe, 0xec, 0x63, 0xfe, 0x5c, 0x63, 0xfe, 0xec, 0x63, 0x02, 0xfa, 0xfd, 0xd8, 0x00, 0xff, 0xff, 0x00, 0x95, 0x00, 0x00, 0x02, 0x30, 0x04, 0x60, 0x10, 0x06, 0x03, 0x4d, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x10, 0x06, 0x03, 0x55, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x05, 0x8a, 0x04, 0x60, 0x10, 0x06, 0x03, 0x5d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe7, 0x04, 0x67, 0x04, 0x79, 0x10, 0x06, 0x03, 0x45, 0x00, 0x00, 0x00, 0x01, 0x00, 0x17, 0xfe, 0x2e, 0x05, 0x5d, 0x00, 0xd0, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x15, 0x23, 0x11, 0x21, 0x11, 0x23, 0x35, 0x21, 0x01, 0x8c, 0x02, 0x5c, 0x01, 0x74, 0xdc, 0xfc, 0x74, 0xdd, 0x01, 0x75, 0xfe, 0xd8, 0x01, 0xf8, 0xaa, 0xfe, 0x08, 0x01, 0xf8, 0xaa, 0x00, 0x02, 0x00, 0x8c, 0x00, 0x00, 0x07, 0xe5, 0x05, 0xfb, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x00, 0x01, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x01, 0x21, 0x35, 0x21, 0x05, 0x35, 0x21, 0x15, 0x05, 0x4b, 0x01, 0x9d, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xfe, 0xb3, 0xfd, 0x66, 0xfd, 0x8b, 0x02, 0x25, 0x02, 0x99, 0x02, 0x76, 0x04, 0x9a, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xfc, 0x10, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x02, 0x00, 0x1f, 0x00, 0x00, 0x06, 0x2a, 0x05, 0xd0, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x21, 0x09, 0x01, 0x21, 0x09, 0x03, 0x21, 0x09, 0x01, 0x01, 0xdd, 0x02, 0x8f, 0x01, 0x48, 0xfe, 0xb8, 0xfd, 0x71, 0xfe, 0xb8, 0x01, 0x0d, 0xfe, 0x7e, 0x01, 0x82, 0x03, 0x05, 0x01, 0x83, 0xfe, 0x7e, 0x72, 0x02, 0x76, 0x02, 0x76, 0xfd, 0x8a, 0xfd, 0x18, 0x02, 0xe8, 0x02, 0xe8, 0xfd, 0x18, 0xfd, 0x18, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfd, 0xfc, 0x02, 0xfc, 0x07, 0x92, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x23, 0x35, 0x10, 0x13, 0x12, 0x13, 0x33, 0x02, 0x03, 0x02, 0x11, 0x01, 0x4e, 0xb0, 0x90, 0xa8, 0x95, 0x90, 0xea, 0x51, 0x72, 0xfd, 0xfc, 0xea, 0x03, 0x97, 0x01, 0xe2, 0x02, 0x30, 0x01, 0x03, 0xfd, 0xf3, 0xfe, 0x86, 0xfd, 0xee, 0xfc, 0xed, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfd, 0xfc, 0x01, 0x4e, 0x07, 0x89, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x9e, 0xb0, 0xb0, 0x07, 0x89, 0xf6, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0x14, 0x02, 0xfc, 0x07, 0x89, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x15, 0x10, 0x13, 0x12, 0x13, 0x23, 0x02, 0x03, 0x02, 0x11, 0x35, 0x01, 0x4e, 0x72, 0x84, 0xb7, 0x90, 0xbb, 0x82, 0x90, 0x07, 0x89, 0xea, 0xfc, 0xa5, 0xfe, 0x57, 0xfe, 0x14, 0xfe, 0x65, 0x01, 0x45, 0x01, 0xee, 0x02, 0x26, 0x03, 0x32, 0xea, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfd, 0xfc, 0x02, 0xfc, 0x07, 0x92, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x35, 0x10, 0x03, 0x02, 0x03, 0x33, 0x12, 0x13, 0x12, 0x11, 0x15, 0x02, 0x4c, 0x73, 0x51, 0xea, 0x90, 0x96, 0xa7, 0x90, 0xfd, 0xfc, 0xea, 0x03, 0x13, 0x02, 0x12, 0x01, 0x79, 0x02, 0x0e, 0xfe, 0xfd, 0xfd, 0xd0, 0xfe, 0x1e, 0xfc, 0x69, 0xea, 0x00, 0x00, 0x01, 0x02, 0x4b, 0xfd, 0xfc, 0x02, 0xfc, 0x07, 0x89, 0x00, 0x04, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x30, 0x02, 0xfb, 0xaf, 0x07, 0x89, 0xf6, 0x73, 0x09, 0x8d, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0x14, 0x02, 0xfc, 0x07, 0x89, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x15, 0x10, 0x03, 0x02, 0x03, 0x23, 0x12, 0x13, 0x12, 0x11, 0x02, 0x4c, 0xaf, 0x90, 0x81, 0xbc, 0x90, 0xb7, 0x84, 0x73, 0x07, 0x89, 0xea, 0xfc, 0xcd, 0xfd, 0xdb, 0xfe, 0x12, 0xfe, 0xbb, 0x01, 0x9b, 0x01, 0xec, 0x01, 0xa9, 0x03, 0x5b, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfd, 0xfc, 0x02, 0xfc, 0x07, 0x6d, 0x00, 0x05, 0x00, 0x00, 0x01, 0x23, 0x11, 0x21, 0x15, 0x21, 0x01, 0x4e, 0xb0, 0x02, 0x5d, 0xfe, 0x53, 0xfd, 0xfc, 0x09, 0x71, 0xc3, 0x00, 0x01, 0x00, 0x9e, 0xfd, 0xfc, 0x01, 0x4e, 0x07, 0x89, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0x9e, 0xb0, 0xb0, 0x07, 0x89, 0xf6, 0x73, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0x14, 0x02, 0xfc, 0x07, 0x89, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x4e, 0x01, 0xad, 0xfd, 0xa3, 0x07, 0x89, 0xf7, 0x4e, 0xc3, 0x09, 0x75, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfd, 0xfc, 0x02, 0xfc, 0x07, 0x6d, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x02, 0x4c, 0xfe, 0x52, 0x02, 0x5d, 0xfd, 0xfc, 0x08, 0xae, 0xc3, 0xf6, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4b, 0xfd, 0xfc, 0x02, 0xfc, 0x07, 0x7a, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x11, 0x23, 0x02, 0x4c, 0xaf, 0xaf, 0x07, 0x7a, 0xf6, 0x82, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0x14, 0x02, 0xfc, 0x07, 0x7a, 0x00, 0x05, 0x00, 0x00, 0x01, 0x33, 0x11, 0x21, 0x35, 0x21, 0x02, 0x4c, 0xaf, 0xfd, 0xa3, 0x01, 0xae, 0x07, 0x7a, 0xf6, 0x9a, 0xc3, 0x00, 0x01, 0x02, 0x5f, 0xfd, 0xea, 0x04, 0xd0, 0x07, 0x6d, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x23, 0x11, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x03, 0x07, 0xa7, 0x63, 0x6d, 0xa8, 0xf7, 0xfd, 0x5b, 0x3d, 0x33, 0xfd, 0xea, 0x07, 0x75, 0xdf, 0x91, 0x9e, 0xb0, 0x66, 0x57, 0x99, 0x00, 0x00, 0x00, 0x01, 0x00, 0x97, 0xfd, 0xfc, 0x03, 0x07, 0x07, 0x86, 0x00, 0x18, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x19, 0x01, 0x23, 0x11, 0x10, 0x27, 0x26, 0x2f, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x10, 0x07, 0x06, 0x02, 0x52, 0x34, 0x26, 0x5b, 0xa7, 0x64, 0x43, 0xeb, 0x37, 0x37, 0xe9, 0x45, 0x64, 0xa7, 0x5b, 0x24, 0x02, 0xc1, 0x20, 0x3d, 0x93, 0xfe, 0x43, 0xfd, 0xe8, 0x02, 0x0c, 0x01, 0xb7, 0x5f, 0x41, 0x04, 0x01, 0xbb, 0x45, 0x63, 0x01, 0xb3, 0x02, 0x0c, 0xfd, 0xe8, 0xfe, 0x48, 0x98, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x02, 0x5f, 0xfe, 0x14, 0x04, 0xd0, 0x07, 0x86, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x03, 0x07, 0x33, 0x3d, 0x5b, 0xfd, 0xf7, 0xa6, 0x6f, 0x63, 0x07, 0x86, 0xf8, 0x94, 0x9a, 0x56, 0x66, 0xb0, 0x9e, 0x8f, 0xe1, 0x07, 0x64, 0x00, 0x00, 0x01, 0x02, 0x5f, 0xfd, 0xf4, 0x03, 0x07, 0x07, 0x8c, 0x00, 0x03, 0x00, 0x00, 0x01, 0x23, 0x11, 0x33, 0x03, 0x07, 0xa7, 0xa7, 0xfd, 0xf4, 0x09, 0x98, 0x00, 0x00, 0x00, 0x01, 0x00, 0x97, 0xfd, 0xea, 0x03, 0x07, 0x07, 0x6d, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x02, 0x60, 0x34, 0x3d, 0x5b, 0xfd, 0xf8, 0xa7, 0x6d, 0x64, 0xfd, 0xea, 0x07, 0x7d, 0x99, 0x57, 0x66, 0xb0, 0x9e, 0x91, 0xdf, 0xf8, 0x8b, 0x00, 0x00, 0x01, 0x02, 0x5f, 0xfd, 0xfc, 0x04, 0xd0, 0x07, 0x86, 0x00, 0x18, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x19, 0x01, 0x33, 0x11, 0x10, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x07, 0x06, 0x07, 0x06, 0x19, 0x01, 0x23, 0x11, 0x10, 0x37, 0x36, 0x03, 0x14, 0x36, 0x24, 0x5a, 0xa7, 0x63, 0x45, 0xe9, 0x37, 0x37, 0xeb, 0x43, 0x63, 0xa7, 0x5a, 0x26, 0x02, 0xc1, 0x21, 0x3c, 0x98, 0x01, 0xb8, 0x02, 0x18, 0xfd, 0xf4, 0xfe, 0x4d, 0x63, 0x45, 0xbb, 0x01, 0x04, 0x41, 0x5f, 0xfe, 0x49, 0xfd, 0xf4, 0x02, 0x18, 0x01, 0xbd, 0x93, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x97, 0xfe, 0x14, 0x03, 0x07, 0x07, 0x86, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x02, 0x60, 0xa7, 0x64, 0x6f, 0xa5, 0xf8, 0xfd, 0x5b, 0x3d, 0x34, 0x07, 0x86, 0xf8, 0x9c, 0xe1, 0x8f, 0x9e, 0xb0, 0x66, 0x56, 0x9a, 0x00, 0x00, 0x00, 0x01, 0x01, 0x83, 0xfe, 0x00, 0x02, 0x37, 0x07, 0x89, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x01, 0x84, 0xb2, 0xfe, 0x00, 0x09, 0x89, 0xf6, 0x77, 0x00, 0x00, 0x02, 0x00, 0x31, 0x00, 0x86, 0x05, 0xa0, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x11, 0x00, 0x00, 0x25, 0x09, 0x01, 0x11, 0x21, 0x11, 0x21, 0x03, 0x21, 0x03, 0x35, 0x03, 0x13, 0x35, 0x21, 0x13, 0x23, 0x03, 0x01, 0xfb, 0xfe, 0x37, 0x01, 0xc9, 0x01, 0xfe, 0x01, 0xa7, 0x01, 0xfc, 0x5c, 0x5a, 0xf0, 0xf0, 0x03, 0xa4, 0x01, 0xf3, 0x01, 0x86, 0x01, 0xfc, 0x01, 0xfc, 0xfe, 0xef, 0x02, 0x68, 0xfb, 0xc2, 0x01, 0x72, 0x83, 0xfe, 0xf6, 0xfe, 0xf6, 0x83, 0x03, 0x76, 0xfd, 0x98, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x06, 0x27, 0x04, 0xc4, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x01, 0x21, 0x09, 0x01, 0x21, 0x11, 0x21, 0x06, 0x26, 0xfa, 0x81, 0x02, 0xbf, 0x02, 0xc0, 0xfa, 0x81, 0x05, 0x7f, 0x02, 0xa0, 0x02, 0x24, 0xfb, 0x3c, 0x01, 0xf8, 0x00, 0x00, 0x04, 0x00, 0x87, 0xff, 0x46, 0x05, 0xc3, 0x05, 0xfc, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x00, 0x13, 0x09, 0x01, 0x11, 0x09, 0x01, 0x03, 0x11, 0x09, 0x01, 0x11, 0x01, 0x00, 0x14, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x36, 0x34, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x02, 0x10, 0x3e, 0x01, 0x32, 0x1e, 0x01, 0x10, 0x0e, 0x01, 0x22, 0x26, 0xee, 0x02, 0x37, 0x02, 0x37, 0xfd, 0xc9, 0xfd, 0xc9, 0x67, 0x02, 0x9e, 0x02, 0x9d, 0xfd, 0x63, 0xfe, 0x96, 0x30, 0x31, 0x53, 0x53, 0xc5, 0x53, 0x53, 0x31, 0x30, 0x30, 0x31, 0x53, 0x53, 0xc5, 0x53, 0x53, 0x31, 0x97, 0x7c, 0xd7, 0xfc, 0xd6, 0x7c, 0x7c, 0xd6, 0xfc, 0xd7, 0x01, 0x35, 0xfe, 0x95, 0x01, 0x6b, 0x02, 0xd8, 0x01, 0x6b, 0xfe, 0x95, 0xfc, 0xe6, 0x03, 0x5c, 0x01, 0xad, 0xfe, 0x53, 0xfc, 0xa4, 0xfe, 0x53, 0x03, 0xc8, 0xda, 0x5d, 0x5c, 0x36, 0x36, 0x36, 0x36, 0x5c, 0x5d, 0xda, 0x5d, 0x5c, 0x36, 0x36, 0x36, 0x36, 0x5c, 0xfe, 0xaa, 0x01, 0x18, 0xee, 0x8a, 0x8a, 0xee, 0xfe, 0xe8, 0xee, 0x8a, 0x8a, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x9a, 0x05, 0x85, 0x03, 0x8e, 0x10, 0x06, 0x0a, 0xda, 0x00, 0x00, 0x00, 0x03, 0x00, 0x50, 0xfe, 0xf7, 0x04, 0x54, 0x02, 0x5a, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x20, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x03, 0x85, 0xb6, 0x2d, 0x2e, 0x2e, 0x2d, 0xb6, 0x2d, 0x2e, 0x2e, 0x88, 0x91, 0x99, 0x99, 0x91, 0x92, 0x99, 0x99, 0xfe, 0x81, 0xc9, 0xcf, 0x7b, 0x02, 0x01, 0x56, 0x56, 0xac, 0xad, 0x56, 0x56, 0x56, 0x56, 0xad, 0xac, 0x56, 0xaf, 0xde, 0xd3, 0xd4, 0xde, 0xde, 0xd4, 0xd3, 0xde, 0xfc, 0xac, 0x02, 0xd1, 0x29, 0x74, 0x27, 0xfc, 0xbd, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8e, 0xff, 0xe3, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x15, 0x23, 0x11, 0x07, 0x27, 0x25, 0x35, 0x33, 0x15, 0x25, 0x17, 0x05, 0x00, 0x10, 0x26, 0x20, 0x06, 0x10, 0x16, 0x20, 0x01, 0x4e, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x34, 0xa7, 0xfa, 0x1e, 0x01, 0x18, 0xa7, 0x01, 0x06, 0x1e, 0xfe, 0xdc, 0x02, 0x33, 0x96, 0xfe, 0xf9, 0x96, 0x96, 0x01, 0x07, 0x03, 0xb6, 0x64, 0x61, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x61, 0x64, 0xa8, 0x04, 0xe6, 0x5d, 0x63, 0x68, 0xc0, 0x83, 0x61, 0x61, 0x6d, 0xfc, 0x40, 0x01, 0x96, 0xe7, 0xe7, 0xfe, 0x6a, 0xe7, 0x00, 0x01, 0x00, 0x83, 0xfe, 0x2e, 0x04, 0x0f, 0x00, 0xd0, 0x00, 0x07, 0x00, 0x00, 0x01, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x01, 0x1b, 0x02, 0x5c, 0x98, 0xfc, 0x74, 0x98, 0xfe, 0xd8, 0x01, 0xf8, 0xfd, 0x5e, 0x02, 0xa2, 0x00, 0x00, 0x00, 0x03, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x01, 0x33, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x33, 0x15, 0x21, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x01, 0x56, 0xc3, 0xd5, 0xe8, 0x91, 0xc4, 0xfd, 0xd5, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0xfd, 0xff, 0x02, 0x7e, 0x2b, 0x98, 0x2f, 0xfc, 0xe6, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x38, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x01, 0x21, 0x15, 0x21, 0x35, 0x3e, 0x01, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x0e, 0x01, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x02, 0x13, 0x01, 0x89, 0xfd, 0x9f, 0x4a, 0xec, 0x1e, 0x37, 0x2b, 0x56, 0x46, 0x35, 0x77, 0x67, 0x57, 0x83, 0x36, 0x93, 0xb1, 0x2b, 0x38, 0x0f, 0xa0, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0xfd, 0xff, 0x8e, 0x81, 0x4d, 0xf1, 0x22, 0x3f, 0x55, 0x28, 0x3f, 0x4e, 0x26, 0x3a, 0xab, 0x24, 0x1f, 0x97, 0x7d, 0x3a, 0x69, 0x46, 0x12, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x44, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x05, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x03, 0x59, 0x0c, 0x6a, 0xc2, 0xb0, 0x39, 0x7b, 0x4f, 0x52, 0x70, 0x3e, 0x69, 0x67, 0x60, 0x59, 0x7e, 0x83, 0x50, 0x50, 0x53, 0x52, 0x2f, 0x6d, 0x60, 0x55, 0x7b, 0x37, 0x91, 0xad, 0x5d, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0x96, 0x03, 0x81, 0x5d, 0x8d, 0x9c, 0x17, 0x1b, 0xa8, 0x30, 0x1c, 0x4f, 0x4c, 0x47, 0x4e, 0x8c, 0x3c, 0x3a, 0x3c, 0x3f, 0x15, 0x20, 0x97, 0x18, 0x14, 0x89, 0x73, 0x51, 0x72, 0x00, 0x04, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x1e, 0x00, 0x29, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x25, 0x03, 0x33, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x02, 0x78, 0xf2, 0xf2, 0x15, 0xb9, 0x7f, 0x7f, 0xa4, 0xfe, 0x70, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0x4f, 0xfe, 0x82, 0x02, 0x48, 0xfd, 0xb8, 0x8d, 0xd3, 0xd3, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x39, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x01, 0x21, 0x15, 0x21, 0x15, 0x06, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x01, 0x6f, 0x02, 0x03, 0xfe, 0x98, 0x03, 0x39, 0x1b, 0x9f, 0xba, 0xc0, 0xab, 0x39, 0x78, 0x4f, 0x55, 0x6c, 0x3d, 0x5d, 0x6a, 0x6a, 0x5d, 0x2d, 0x5b, 0x50, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0x01, 0x19, 0x8e, 0xab, 0x01, 0x0a, 0xb0, 0x95, 0x98, 0xac, 0x14, 0x18, 0xac, 0x2f, 0x1b, 0x61, 0x55, 0x56, 0x61, 0x14, 0x25, 0x00, 0x04, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x40, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x13, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x06, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x12, 0x33, 0x32, 0x16, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x02, 0x5d, 0x46, 0x53, 0x53, 0x46, 0x46, 0x53, 0x53, 0xbf, 0x4b, 0x58, 0x2a, 0x6b, 0x72, 0x05, 0x08, 0x73, 0x46, 0x90, 0xa8, 0xaf, 0x90, 0xa6, 0xad, 0xd2, 0xb4, 0x30, 0x60, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0x9f, 0x62, 0x5b, 0x5a, 0x62, 0x62, 0x5a, 0x5b, 0x62, 0x01, 0x9d, 0x9c, 0x23, 0x16, 0x94, 0x50, 0x0b, 0x3d, 0xb1, 0x94, 0x91, 0xb3, 0xfd, 0xe7, 0xda, 0x01, 0x0b, 0x13, 0x00, 0x00, 0x03, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x22, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x01, 0x21, 0x15, 0x01, 0x23, 0x01, 0x21, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x01, 0x46, 0x02, 0x67, 0xfe, 0xb8, 0xad, 0x01, 0x2f, 0xfe, 0x5f, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0x01, 0x19, 0x4b, 0xfc, 0xa3, 0x03, 0x1a, 0x00, 0x05, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x3f, 0x00, 0x4b, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x25, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x02, 0x6a, 0x4c, 0x55, 0x55, 0x4c, 0x4b, 0x56, 0x56, 0xfe, 0xe6, 0x04, 0x5f, 0xa4, 0x8e, 0x8d, 0xa4, 0x5f, 0x03, 0x0d, 0x6a, 0xaa, 0x9c, 0x9c, 0xab, 0x6a, 0x4f, 0x48, 0x46, 0x43, 0x4a, 0x4a, 0x43, 0x46, 0x48, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0xe6, 0x50, 0x49, 0x49, 0x50, 0x51, 0x48, 0x49, 0x50, 0x49, 0x01, 0x76, 0x53, 0x74, 0x88, 0x88, 0x74, 0x53, 0x76, 0x01, 0x03, 0x83, 0x5c, 0x8a, 0x97, 0x97, 0x8a, 0x5c, 0x83, 0xc1, 0x3d, 0x42, 0x42, 0x3d, 0x3e, 0x42, 0x42, 0x00, 0x00, 0x04, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x34, 0x00, 0x40, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x01, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x36, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x02, 0x23, 0x22, 0x26, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0x01, 0x68, 0x4c, 0x57, 0x2a, 0x6b, 0x72, 0x05, 0x09, 0x74, 0x47, 0x8f, 0xa7, 0xae, 0x90, 0xa7, 0xac, 0xd2, 0xb4, 0x30, 0x60, 0xc3, 0x47, 0x52, 0x52, 0x47, 0x46, 0x53, 0x53, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0xfd, 0x8b, 0x9c, 0x24, 0x15, 0x93, 0x4f, 0x0d, 0x3c, 0xaf, 0x94, 0x91, 0xb4, 0xfd, 0xe8, 0xda, 0xfe, 0xf6, 0x13, 0x01, 0xb4, 0x62, 0x5b, 0x5b, 0x62, 0x62, 0x5b, 0x5b, 0x62, 0x00, 0x05, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x32, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x13, 0x33, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x33, 0x15, 0x21, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfa, 0xe8, 0x01, 0x67, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9c, 0xfe, 0xd9, 0xa3, 0xb8, 0x8e, 0x9b, 0xaa, 0x69, 0x8f, 0xfe, 0x6b, 0x02, 0xb7, 0x3a, 0x3e, 0x3e, 0x3a, 0x39, 0x3e, 0x3e, 0x39, 0x75, 0x7a, 0x7a, 0x75, 0x76, 0x7b, 0x7b, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0xfe, 0x3e, 0x02, 0x3e, 0x27, 0x89, 0x2a, 0xfd, 0x36, 0x80, 0x02, 0xde, 0x97, 0xa3, 0xa2, 0x97, 0x97, 0xa2, 0xa3, 0x97, 0x7b, 0xe4, 0xd1, 0xd0, 0xe4, 0xe4, 0xd0, 0xd1, 0xe4, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x03, 0x00, 0x00, 0x03, 0x35, 0x21, 0x15, 0x12, 0x04, 0x7a, 0x01, 0xf0, 0xac, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x04, 0x7a, 0x01, 0x9a, 0x01, 0x58, 0xfe, 0xa8, 0x00, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x01, 0xe2, 0x90, 0xfd, 0x96, 0x0a, 0x32, 0xf5, 0xce, 0x00, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0xfd, 0x96, 0x0a, 0x32, 0xf5, 0xce, 0x00, 0x03, 0xff, 0xee, 0x01, 0xf0, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x21, 0x35, 0x21, 0x15, 0x21, 0x35, 0x21, 0x15, 0x03, 0x52, 0x01, 0x16, 0xfd, 0x3d, 0x01, 0x0b, 0xfd, 0x3e, 0x01, 0x15, 0x01, 0xf0, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x03, 0x52, 0x01, 0x16, 0xfd, 0x3d, 0x01, 0x0b, 0xfd, 0x3e, 0x01, 0x15, 0x01, 0x9a, 0x01, 0x58, 0xfe, 0xa8, 0x01, 0x58, 0xfe, 0xa8, 0x01, 0x58, 0xfe, 0xa8, 0x00, 0x03, 0x01, 0xe2, 0xfd, 0x96, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0xe2, 0x90, 0x90, 0x90, 0x90, 0x90, 0xfd, 0x96, 0x03, 0x0c, 0xfc, 0xf4, 0x03, 0xc0, 0x02, 0xb2, 0xfd, 0x4e, 0x03, 0x66, 0x03, 0x0c, 0xfc, 0xf4, 0x00, 0x00, 0x03, 0x01, 0x9a, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0xfe, 0xe0, 0x01, 0x20, 0xfe, 0xe0, 0x01, 0x20, 0xfd, 0x96, 0x03, 0x0c, 0xfc, 0xf4, 0x03, 0xc0, 0x02, 0xb2, 0xfd, 0x4e, 0x03, 0x66, 0x03, 0x0c, 0xfc, 0xf4, 0x00, 0x04, 0xff, 0xed, 0x01, 0xf0, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x35, 0x33, 0x15, 0x33, 0x35, 0x33, 0x15, 0x33, 0x35, 0x33, 0x15, 0x33, 0x35, 0x33, 0x15, 0x13, 0xa9, 0xa2, 0xa1, 0xa2, 0xa1, 0xa2, 0xaa, 0x01, 0xf0, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0x00, 0x00, 0x00, 0x04, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x69, 0x02, 0xf2, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x12, 0xa9, 0xa2, 0xa1, 0xa2, 0xa0, 0xa2, 0xab, 0x01, 0x9a, 0x01, 0x58, 0xfe, 0xa8, 0x01, 0x58, 0xfe, 0xa8, 0x01, 0x58, 0xfe, 0xa8, 0x01, 0x58, 0xfe, 0xa8, 0x00, 0x00, 0x00, 0x04, 0x01, 0xe2, 0xfd, 0x96, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0xe2, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x05, 0x96, 0x02, 0x32, 0xfd, 0xce, 0xf8, 0x00, 0x02, 0x32, 0xfd, 0xce, 0x05, 0x73, 0x01, 0xd9, 0xfe, 0x27, 0xfd, 0x73, 0x01, 0xd9, 0xfe, 0x27, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x9a, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0xfe, 0xe0, 0x01, 0x20, 0xfe, 0xe0, 0x01, 0x20, 0xfe, 0xe0, 0x01, 0x20, 0x05, 0x96, 0x02, 0x32, 0xfd, 0xce, 0xf8, 0x00, 0x02, 0x32, 0xfd, 0xce, 0x05, 0x73, 0x01, 0xd9, 0xfe, 0x27, 0xfd, 0x73, 0x01, 0xd9, 0xfe, 0x27, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0x02, 0x86, 0xfe, 0x0a, 0xfd, 0x96, 0x05, 0x06, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0x02, 0x86, 0xfe, 0x0a, 0xfd, 0x96, 0x05, 0x5c, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0x02, 0xce, 0xfe, 0x52, 0xfd, 0x96, 0x05, 0x06, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x02, 0xce, 0xfe, 0x52, 0xfd, 0x96, 0x05, 0x5c, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0x73, 0x02, 0x9c, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x02, 0x84, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0xfa, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0x73, 0x02, 0xf2, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x02, 0x84, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0xfa, 0xa4, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0xbb, 0x02, 0x9c, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x02, 0xcc, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0xfa, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0xbb, 0x02, 0xf2, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x02, 0xcc, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0xfa, 0xa4, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe2, 0x01, 0xf0, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x15, 0x01, 0xe2, 0x90, 0x01, 0xf6, 0x01, 0xf0, 0x05, 0xd8, 0xfa, 0xd4, 0xac, 0x00, 0x01, 0x01, 0xe2, 0x01, 0x9a, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x01, 0xe2, 0x90, 0x01, 0xf6, 0x01, 0x9a, 0x06, 0x2e, 0xfb, 0x2a, 0xfe, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x9a, 0x01, 0xf0, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x15, 0x01, 0x9a, 0x01, 0x20, 0x01, 0xae, 0x01, 0xf0, 0x05, 0xd8, 0xfa, 0xd4, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x9a, 0x01, 0x9a, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0x01, 0xae, 0x01, 0x9a, 0x06, 0x2e, 0xfb, 0x2a, 0xfe, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x33, 0x11, 0x12, 0x01, 0xf4, 0x90, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfa, 0x28, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x33, 0x11, 0x12, 0x01, 0xf4, 0x90, 0x01, 0x9a, 0x01, 0x58, 0x04, 0xd6, 0xf9, 0xd2, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x21, 0x11, 0x12, 0x01, 0xac, 0x01, 0x20, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfa, 0x28, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x21, 0x11, 0x12, 0x01, 0xac, 0x01, 0x20, 0x01, 0x9a, 0x01, 0x58, 0x04, 0xd6, 0xf9, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x0a, 0x32, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x0a, 0x32, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0x48, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x5a, 0x05, 0xd8, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0x48, 0x90, 0x01, 0xf6, 0xfe, 0x52, 0xfd, 0x96, 0x05, 0x06, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x52, 0xfd, 0x96, 0x0a, 0x32, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0x48, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x04, 0x06, 0x2e, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x48, 0x90, 0x01, 0xf6, 0xfe, 0x52, 0xfd, 0x96, 0x05, 0x5c, 0x04, 0xd6, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x52, 0xfd, 0x96, 0x0a, 0x32, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xf5, 0xce, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x33, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xf5, 0xce, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xac, 0x01, 0x20, 0x48, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xfa, 0x28, 0xfb, 0xa6, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xf4, 0x90, 0x48, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0xfa, 0xfa, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x20, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xf5, 0xce, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xac, 0x01, 0x20, 0x48, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xf9, 0xd2, 0xfb, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xf4, 0x90, 0x48, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfb, 0x2a, 0xfa, 0xa4, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x20, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xf5, 0xce, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x04, 0x7a, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x02, 0x84, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x56, 0xac, 0xfb, 0xa6, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0x02, 0x86, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x56, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x04, 0x7a, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x04, 0x7a, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x02, 0xcc, 0x01, 0xae, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x56, 0xac, 0xfb, 0xa6, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xac, 0x02, 0xce, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x56, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x04, 0x7a, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x12, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x12, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0x01, 0x9a, 0x01, 0x58, 0x04, 0xd6, 0xfa, 0xd4, 0xac, 0x56, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x21, 0x35, 0x12, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfd, 0x7a, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfb, 0x2a, 0xfe, 0xa8, 0x56, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x12, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0x01, 0x9a, 0x01, 0x58, 0x04, 0xd6, 0xfb, 0x2a, 0xfe, 0xa8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x21, 0x11, 0x21, 0x15, 0x12, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x12, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x52, 0x01, 0x9a, 0x01, 0x58, 0x04, 0xd6, 0xfa, 0xd4, 0xac, 0x56, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x35, 0x12, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfd, 0x32, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfb, 0x2a, 0xfe, 0xa8, 0x56, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x12, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0x01, 0x9a, 0x01, 0x58, 0x04, 0xd6, 0xfb, 0x2a, 0xfe, 0xa8, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x02, 0x72, 0x90, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0x01, 0xf0, 0xfb, 0xa6, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, 0x23, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x52, 0x48, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfa, 0xd4, 0xac, 0x56, 0xfb, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x23, 0x35, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0x48, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x04, 0x56, 0xac, 0x05, 0x2c, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x15, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xf4, 0x90, 0x48, 0x01, 0xae, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfb, 0x2a, 0x56, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xac, 0x48, 0x90, 0x01, 0xf6, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x56, 0x04, 0xd6, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x0a, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x01, 0x9a, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x20, 0x01, 0xae, 0xfe, 0x52, 0xfd, 0x96, 0x04, 0x04, 0x01, 0x58, 0x04, 0xd6, 0xfb, 0x2a, 0xfe, 0xa8, 0xfb, 0xfc, 0x00, 0x02, 0xff, 0xee, 0x01, 0xf0, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x03, 0x35, 0x21, 0x15, 0x33, 0x35, 0x21, 0x15, 0x12, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0x01, 0xf0, 0xac, 0xac, 0xac, 0xac, 0x00, 0x02, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x02, 0x72, 0x01, 0xf6, 0xfb, 0x86, 0x01, 0xf4, 0x01, 0x9a, 0x01, 0x58, 0xfe, 0xa8, 0x01, 0x58, 0xfe, 0xa8, 0x00, 0x00, 0x00, 0x02, 0x01, 0xe2, 0xfd, 0x96, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0xe2, 0x90, 0x90, 0x90, 0x02, 0xf2, 0x04, 0xd6, 0xfb, 0x2a, 0xfa, 0xa4, 0x04, 0x04, 0xfb, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x9a, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0xfe, 0xe0, 0x01, 0x20, 0x02, 0xf2, 0x04, 0xd6, 0xfb, 0x2a, 0xfa, 0xa4, 0x04, 0x04, 0xfb, 0xfc, 0x00, 0x02, 0xff, 0xee, 0x01, 0x44, 0x04, 0x68, 0x03, 0x48, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x03, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x12, 0x04, 0x7a, 0xfb, 0x86, 0x04, 0x7a, 0x02, 0x9c, 0xac, 0xac, 0xfe, 0xa8, 0xac, 0xac, 0x00, 0x00, 0x02, 0x01, 0x52, 0xfd, 0x96, 0x03, 0x03, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x01, 0x52, 0x90, 0x90, 0x90, 0xfd, 0x96, 0x0a, 0x32, 0xf5, 0xce, 0x0a, 0x32, 0xf5, 0xce, 0x00, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x04, 0x68, 0x03, 0x48, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0x02, 0x86, 0xfe, 0x0a, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x05, 0xb2, 0xac, 0xac, 0xac, 0xfc, 0x52, 0x00, 0x00, 0x01, 0x01, 0x52, 0xfd, 0x96, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x01, 0x52, 0x03, 0x16, 0xfe, 0x9a, 0x90, 0x90, 0xfd, 0x96, 0x05, 0x06, 0xac, 0xfb, 0xa6, 0x04, 0x5a, 0xfb, 0xa6, 0x00, 0x00, 0x02, 0x01, 0x52, 0xfd, 0x96, 0x04, 0x68, 0x03, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x52, 0x03, 0x16, 0xfd, 0x7a, 0x90, 0x01, 0xf6, 0xfe, 0x9a, 0xfd, 0x96, 0x05, 0xb2, 0xac, 0xfa, 0xfa, 0x04, 0x5a, 0xac, 0xfc, 0x52, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0x73, 0x03, 0x48, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0xfe, 0x0c, 0x02, 0x84, 0xfd, 0x96, 0x03, 0xae, 0xac, 0xac, 0xac, 0xfa, 0x4e, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x03, 0x03, 0x02, 0x9c, 0x00, 0x09, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x12, 0x03, 0x14, 0x90, 0x90, 0x90, 0x01, 0xf0, 0xac, 0xfa, 0xfa, 0x04, 0x5a, 0xfb, 0xa6, 0x04, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0xfd, 0x96, 0x03, 0x03, 0x03, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x02, 0x72, 0xfd, 0x7c, 0x03, 0x14, 0xfe, 0x50, 0xfe, 0x9c, 0x01, 0xf4, 0xfd, 0x96, 0x05, 0x06, 0xac, 0xfa, 0x4e, 0x03, 0xae, 0xac, 0xfb, 0xa6, 0x00, 0x01, 0x01, 0xe2, 0x01, 0x44, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x01, 0xe2, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0x01, 0xf6, 0x01, 0x44, 0x06, 0x84, 0xfb, 0x80, 0xac, 0xac, 0xac, 0x00, 0x00, 0x00, 0x01, 0x01, 0x52, 0x01, 0xf0, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x01, 0x52, 0x90, 0x90, 0x90, 0x01, 0x66, 0x01, 0xf0, 0x05, 0xd8, 0xfa, 0xd4, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0x00, 0x00, 0x00, 0x02, 0x01, 0x52, 0x01, 0x44, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x21, 0x15, 0x02, 0x72, 0x90, 0x01, 0x66, 0xfc, 0xea, 0x90, 0x02, 0x86, 0x02, 0x9c, 0x05, 0x2c, 0xfb, 0x80, 0xac, 0xfe, 0xa8, 0x06, 0x84, 0xfa, 0x28, 0xac, 0x00, 0x01, 0xff, 0xee, 0x01, 0x44, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x03, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x12, 0x01, 0xf4, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0x01, 0x44, 0xac, 0xac, 0xac, 0x04, 0x80, 0xf9, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x03, 0x03, 0x07, 0xc8, 0x00, 0x09, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x12, 0x01, 0x64, 0x90, 0x90, 0x90, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0x05, 0x2c, 0xfa, 0x28, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x01, 0x44, 0x03, 0x03, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x11, 0x33, 0x11, 0x12, 0x01, 0x64, 0x90, 0xfe, 0x0c, 0x02, 0x84, 0x90, 0x02, 0x9c, 0xac, 0x04, 0x80, 0xfa, 0xd4, 0xfe, 0xa8, 0xac, 0x05, 0xd8, 0xf9, 0x7c, 0x00, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x0a, 0x32, 0xfb, 0x80, 0xac, 0xac, 0xac, 0xfc, 0x52, 0x00, 0x02, 0x01, 0x52, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0x52, 0x90, 0x90, 0x90, 0x01, 0x66, 0xfe, 0x9a, 0xfd, 0x96, 0x0a, 0x32, 0xf5, 0xce, 0x0a, 0x32, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x00, 0x00, 0x00, 0x03, 0x01, 0x52, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x02, 0x72, 0x90, 0x01, 0x66, 0xfc, 0xea, 0x90, 0x90, 0x01, 0xf6, 0xfe, 0x9a, 0x02, 0x9c, 0x05, 0x2c, 0xfb, 0x80, 0xac, 0xfa, 0xfa, 0x0a, 0x32, 0xf5, 0xce, 0x04, 0x5a, 0xac, 0xfc, 0x52, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0xfd, 0x96, 0x03, 0xae, 0xac, 0xac, 0xac, 0x04, 0x80, 0xf5, 0xce, 0x00, 0x02, 0xff, 0xee, 0xfd, 0x96, 0x03, 0x03, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x01, 0x52, 0xfe, 0x9c, 0x01, 0x64, 0x90, 0x90, 0x90, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0x05, 0x2c, 0xf5, 0xce, 0x0a, 0x32, 0xf5, 0xce, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0xfd, 0x96, 0x03, 0x03, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x33, 0x11, 0x03, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x12, 0x01, 0x64, 0x90, 0x90, 0xfe, 0x9c, 0x01, 0xf4, 0x90, 0x90, 0x02, 0x9c, 0xac, 0x04, 0x80, 0xfa, 0xd4, 0xfa, 0xfa, 0x03, 0xae, 0xac, 0xfb, 0xa6, 0x0a, 0x32, 0xf5, 0xce, 0x00, 0x00, 0x02, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x03, 0x48, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0xe2, 0xfe, 0x0c, 0x04, 0x7a, 0xfe, 0x0a, 0xfd, 0x7c, 0x04, 0x7a, 0xfd, 0x96, 0x03, 0xae, 0xac, 0xac, 0xfc, 0x52, 0x05, 0x06, 0xac, 0xac, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x0b, 0x00, 0x00, 0x03, 0x35, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x12, 0x04, 0x7a, 0xfe, 0x9a, 0x90, 0x90, 0x90, 0x01, 0xf0, 0xac, 0xac, 0xfb, 0xa6, 0x04, 0x5a, 0xfb, 0xa6, 0x04, 0x5a, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x03, 0x48, 0x00, 0x03, 0x00, 0x09, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x35, 0x21, 0x15, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x12, 0x04, 0x7a, 0xfc, 0xea, 0xfe, 0x9c, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfe, 0x9a, 0x02, 0x9c, 0xac, 0xac, 0xfa, 0xfa, 0x03, 0xae, 0xac, 0xfb, 0xa6, 0x04, 0x5a, 0xac, 0xfc, 0x52, 0x00, 0x02, 0xff, 0xee, 0x01, 0x44, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x03, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x12, 0x04, 0x7a, 0xfb, 0x86, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0x01, 0x44, 0xac, 0xac, 0x01, 0x58, 0xac, 0x04, 0x80, 0xfb, 0x80, 0xac, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x12, 0x01, 0x64, 0x90, 0x90, 0x90, 0x01, 0x66, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0x01, 0x44, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x09, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x12, 0x04, 0x7a, 0xfb, 0x86, 0x01, 0x64, 0x90, 0x90, 0x90, 0x01, 0x66, 0x01, 0x44, 0xac, 0xac, 0x01, 0x58, 0xac, 0x04, 0x80, 0xfa, 0xd4, 0x05, 0x2c, 0xfb, 0x80, 0xac, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x01, 0xe2, 0xfe, 0x0c, 0x01, 0xf4, 0xfe, 0x0c, 0x01, 0xf4, 0x90, 0x01, 0xf6, 0xfe, 0x0a, 0x01, 0xf6, 0xfe, 0x0a, 0xfd, 0x96, 0x03, 0xae, 0xac, 0xac, 0xac, 0x04, 0x80, 0xfb, 0x80, 0xac, 0xac, 0xac, 0xfc, 0x52, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x13, 0x00, 0x00, 0x03, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x12, 0x01, 0x64, 0x90, 0x90, 0x90, 0x01, 0x66, 0xfe, 0x9a, 0x90, 0x90, 0x90, 0x01, 0xf0, 0xac, 0x05, 0x2c, 0xfa, 0xd4, 0x05, 0x2c, 0xfa, 0xd4, 0xac, 0xfb, 0xa6, 0x04, 0x5a, 0xfb, 0xa6, 0x04, 0x5a, 0x00, 0x00, 0x04, 0xff, 0xee, 0xfd, 0x96, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x11, 0x00, 0x17, 0x00, 0x00, 0x01, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x01, 0x35, 0x21, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x02, 0x72, 0x01, 0xf6, 0xfe, 0x9a, 0xfe, 0x50, 0xfe, 0x9c, 0x01, 0xf4, 0xfe, 0x0c, 0x01, 0x64, 0x90, 0x90, 0x90, 0x01, 0x66, 0xfd, 0x96, 0x04, 0x5a, 0xac, 0xfc, 0x52, 0x03, 0xae, 0xac, 0xfb, 0xa6, 0x05, 0x06, 0xac, 0x04, 0x80, 0xfa, 0xd4, 0x05, 0x2c, 0xfb, 0x80, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x11, 0x34, 0x37, 0x36, 0x33, 0x21, 0x15, 0x21, 0x22, 0x06, 0x15, 0x11, 0x01, 0xe2, 0x49, 0x52, 0x97, 0x01, 0x54, 0xfe, 0xac, 0x50, 0x52, 0xfd, 0x96, 0x03, 0x60, 0xa1, 0x7f, 0x86, 0xac, 0x7e, 0x7c, 0xfc, 0xa0, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfd, 0x96, 0x02, 0x73, 0x02, 0x9c, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x34, 0x27, 0x26, 0x23, 0x21, 0x35, 0x21, 0x32, 0x17, 0x16, 0x15, 0x11, 0x01, 0xe2, 0x29, 0x29, 0x50, 0xfe, 0xae, 0x01, 0x52, 0x98, 0x51, 0x49, 0xfd, 0x96, 0x03, 0x60, 0x7e, 0x3d, 0x3f, 0xac, 0x86, 0x78, 0xa8, 0xfc, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x0c, 0x00, 0x00, 0x03, 0x35, 0x21, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x23, 0x12, 0x01, 0x52, 0x50, 0x52, 0x90, 0x49, 0x51, 0x98, 0x01, 0xf0, 0xac, 0x7e, 0x7c, 0x04, 0x32, 0xfb, 0xce, 0xa8, 0x78, 0x86, 0x00, 0x01, 0x01, 0xe2, 0x01, 0xf0, 0x04, 0x68, 0x07, 0xc8, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x21, 0x22, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x21, 0x04, 0x68, 0xfe, 0xac, 0x97, 0x52, 0x49, 0x90, 0x52, 0x50, 0x01, 0x54, 0x01, 0xf0, 0x86, 0x78, 0xa8, 0x04, 0x32, 0xfb, 0xce, 0x7c, 0x7e, 0x00, 0x00, 0x00, 0x01, 0xff, 0x9d, 0xfd, 0x96, 0x04, 0xb8, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x03, 0x01, 0x33, 0x01, 0x62, 0x04, 0x7a, 0xa0, 0xfb, 0x86, 0xfd, 0x96, 0x0a, 0x32, 0xf5, 0xce, 0x00, 0x00, 0x00, 0x01, 0xff, 0x9d, 0xfd, 0x96, 0x04, 0xb8, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x01, 0x23, 0x01, 0x33, 0x04, 0xb8, 0xa0, 0xfb, 0x86, 0xa0, 0xfd, 0x96, 0x0a, 0x32, 0x00, 0x01, 0xff, 0x9d, 0xfd, 0x96, 0x04, 0xb8, 0x07, 0xc8, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x23, 0x09, 0x01, 0x23, 0x09, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x04, 0xb8, 0xa0, 0xfe, 0x12, 0xfe, 0x14, 0xa0, 0x02, 0x3d, 0xfd, 0xc3, 0xa0, 0x01, 0xec, 0x01, 0xee, 0xa0, 0xfd, 0xc3, 0xfd, 0x96, 0x04, 0x63, 0xfb, 0x9d, 0x05, 0x19, 0x05, 0x19, 0xfb, 0x9d, 0x04, 0x63, 0xfa, 0xe7, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0xf0, 0x02, 0x3d, 0x02, 0x9c, 0x00, 0x03, 0x00, 0x00, 0x03, 0x35, 0x21, 0x15, 0x12, 0x02, 0x4e, 0x01, 0xf0, 0xac, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe2, 0x02, 0x46, 0x02, 0x73, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x01, 0xe2, 0x90, 0x02, 0x46, 0x05, 0x82, 0xfa, 0x7e, 0x00, 0x00, 0x01, 0x02, 0x3c, 0x01, 0xf0, 0x04, 0x68, 0x02, 0x9c, 0x00, 0x03, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x02, 0x3c, 0x02, 0x2c, 0x01, 0xf0, 0xac, 0xac, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe2, 0xfd, 0x96, 0x02, 0x73, 0x02, 0x46, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x01, 0xe2, 0x90, 0xfd, 0x96, 0x04, 0xb0, 0xfb, 0x50, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x02, 0x3d, 0x02, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x02, 0x4e, 0x01, 0x9a, 0x01, 0x58, 0xfe, 0xa8, 0x00, 0x00, 0x01, 0x01, 0x9a, 0x02, 0x46, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0x02, 0x46, 0x05, 0x82, 0xfa, 0x7e, 0x00, 0x01, 0x02, 0x3c, 0x01, 0x9a, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x02, 0x3c, 0x02, 0x2c, 0x01, 0x9a, 0x01, 0x58, 0xfe, 0xa8, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x02, 0xbb, 0x02, 0x46, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x9a, 0x01, 0x20, 0xfd, 0x96, 0x04, 0xb0, 0xfb, 0x50, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x07, 0x00, 0x00, 0x03, 0x35, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x12, 0x02, 0x4e, 0x02, 0x2c, 0xfd, 0xd4, 0x01, 0xf0, 0xac, 0x56, 0xfe, 0xa8, 0x56, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x01, 0x9a, 0x48, 0x90, 0x48, 0xfd, 0x96, 0x04, 0xb0, 0x05, 0x82, 0xfa, 0x7e, 0xfb, 0x50, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x01, 0x9a, 0x04, 0x68, 0x02, 0xf2, 0x00, 0x07, 0x00, 0x00, 0x03, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x12, 0x02, 0x4e, 0x02, 0x2c, 0xfd, 0xd4, 0x01, 0x9a, 0x01, 0x58, 0x56, 0xac, 0x56, 0x00, 0x01, 0x01, 0x9a, 0xfd, 0x96, 0x02, 0xbb, 0x07, 0xc8, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x01, 0xe2, 0x48, 0x01, 0x20, 0x48, 0xfd, 0x96, 0x04, 0xb0, 0x05, 0x82, 0xfa, 0x7e, 0xfb, 0x50, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x02, 0x14, 0x05, 0x9c, 0x06, 0x28, 0x10, 0x07, 0x0a, 0xad, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0xff, 0x05, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x05, 0xae, 0xfe, 0x00, 0x01, 0x05, 0xfe, 0xfb, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0xff, 0xf6, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x05, 0xae, 0xfe, 0x00, 0x01, 0xf6, 0xfe, 0x0a, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x01, 0x0f, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x05, 0xae, 0xfe, 0x00, 0x03, 0x0f, 0xfc, 0xf1, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x02, 0x14, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x05, 0xae, 0xfe, 0x00, 0x04, 0x14, 0xfb, 0xec, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x03, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x05, 0xae, 0xfe, 0x00, 0x05, 0x19, 0xfa, 0xe7, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x04, 0x1e, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x05, 0xae, 0xfe, 0x00, 0x06, 0x1e, 0xf9, 0xe2, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x05, 0x23, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x05, 0xae, 0xfe, 0x00, 0x07, 0x23, 0xf8, 0xdd, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x05, 0xae, 0xfe, 0x00, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x04, 0xe6, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x04, 0xf8, 0xfe, 0x00, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x04, 0x30, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x04, 0x42, 0xfe, 0x00, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x03, 0x7b, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x03, 0x8c, 0xfe, 0x00, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x02, 0xc5, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x02, 0xd6, 0xfe, 0x00, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x02, 0x0f, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x02, 0x20, 0xfe, 0x00, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x01, 0x59, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x01, 0x6b, 0xfe, 0x00, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x00, 0xa3, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x33, 0x11, 0x12, 0xb5, 0xfe, 0x00, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0xff, 0xff, 0x02, 0xc4, 0xfe, 0x00, 0x05, 0x9b, 0x06, 0x28, 0x10, 0x07, 0x0a, 0xb5, 0x02, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xee, 0xfe, 0x00, 0x04, 0xe6, 0x06, 0x28, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x13, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x13, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x13, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x04, 0x30, 0xb6, 0xfc, 0x73, 0xb5, 0xb6, 0xb6, 0xfc, 0x74, 0xb5, 0x03, 0x8d, 0xb6, 0xfc, 0x73, 0xb5, 0xb6, 0xb6, 0xfc, 0x74, 0xb5, 0x03, 0x8d, 0xb6, 0xfc, 0x73, 0xb5, 0xb6, 0xb6, 0xfc, 0x74, 0xb5, 0xfe, 0x00, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x6d, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x6e, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x6d, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x6e, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x6d, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfe, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x20, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x96, 0x06, 0x28, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x27, 0x00, 0x2f, 0x00, 0x37, 0x00, 0x3f, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x57, 0x00, 0x5f, 0x00, 0x67, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x7f, 0x00, 0x87, 0x00, 0x8f, 0x00, 0x97, 0x00, 0x9f, 0x00, 0xa7, 0x00, 0xaf, 0x00, 0xb7, 0x00, 0xbf, 0x00, 0xc7, 0x00, 0xcf, 0x00, 0xd7, 0x00, 0xdf, 0x00, 0xe7, 0x00, 0xef, 0x00, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x13, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x01, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x01, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x01, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x01, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x01, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x01, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x01, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0x05, 0x07, 0x23, 0x27, 0x35, 0x37, 0x33, 0x17, 0xa3, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x6a, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x69, 0x04, 0xac, 0x04, 0x04, 0xac, 0x04, 0x01, 0x6a, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0xfc, 0x78, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x6a, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x69, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0x01, 0x6a, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0xfb, 0x0e, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x6a, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x69, 0x04, 0xac, 0x04, 0x04, 0xac, 0x04, 0x01, 0x6a, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0xfc, 0x78, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x6a, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x69, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0x01, 0x6a, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0xfb, 0x0e, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x6a, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x69, 0x04, 0xac, 0x04, 0x04, 0xac, 0x04, 0x01, 0x6a, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0xfc, 0x78, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x6a, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x69, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0x01, 0x6a, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0xfb, 0x0e, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x6a, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x69, 0x04, 0xac, 0x04, 0x04, 0xac, 0x04, 0x01, 0x6a, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0xfc, 0x78, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x6a, 0x05, 0xac, 0x04, 0x04, 0xac, 0x05, 0x01, 0x69, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0x01, 0x6a, 0x04, 0xac, 0x05, 0x05, 0xac, 0x04, 0x05, 0x28, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfe, 0x00, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfe, 0x00, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfe, 0x00, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfe, 0x00, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfe, 0x00, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfe, 0x00, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfe, 0x00, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0xfb, 0x05, 0x05, 0x00, 0x00, 0x07, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x25, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x00, 0x03, 0x11, 0x33, 0x11, 0x23, 0x11, 0x33, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x19, 0x01, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0x12, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0x02, 0x21, 0xb6, 0x02, 0x22, 0xb6, 0xb6, 0xfd, 0xde, 0xb5, 0xb5, 0xb5, 0x02, 0xd7, 0xb6, 0xb6, 0xfe, 0x94, 0xb6, 0xb6, 0xfe, 0x95, 0xb5, 0xb5, 0x02, 0xd7, 0xb6, 0xb6, 0xfe, 0x94, 0xb6, 0xb6, 0xfe, 0x00, 0x01, 0x6d, 0x01, 0x05, 0x01, 0xd6, 0x01, 0x05, 0x01, 0xd6, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xf7, 0xd8, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfe, 0xfb, 0x05, 0xb6, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfd, 0x8d, 0x01, 0x05, 0xfd, 0x8e, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0x05, 0xfd, 0x8d, 0x01, 0x05, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x05, 0x23, 0x05, 0x9c, 0x06, 0x28, 0x10, 0x07, 0x0a, 0xaa, 0x00, 0x00, 0x07, 0x23, 0x00, 0x00, 0xff, 0xff, 0x04, 0xe5, 0xfe, 0x00, 0x05, 0x9b, 0x06, 0x28, 0x10, 0x07, 0x0a, 0xb8, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x02, 0xc6, 0x02, 0x14, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x02, 0xd7, 0xfe, 0x00, 0x04, 0x14, 0xfb, 0xec, 0x00, 0x00, 0x01, 0x02, 0xc4, 0xfe, 0x00, 0x05, 0x9c, 0x02, 0x14, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x02, 0xc4, 0x02, 0xd8, 0xfe, 0x00, 0x04, 0x14, 0xfb, 0xec, 0x00, 0x01, 0xff, 0xee, 0x02, 0x14, 0x02, 0xc6, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x12, 0x02, 0xd7, 0x02, 0x14, 0x04, 0x14, 0xfb, 0xec, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x11, 0x21, 0x05, 0x9c, 0xfa, 0x52, 0x02, 0xd7, 0x02, 0xd7, 0xfe, 0x00, 0x08, 0x28, 0xfb, 0xec, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x07, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x12, 0x02, 0xd7, 0x02, 0xd7, 0xfd, 0x28, 0x02, 0x14, 0x04, 0x14, 0xfb, 0xec, 0xfb, 0xec, 0x04, 0x14, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x05, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x05, 0x9c, 0xfd, 0x29, 0xfd, 0x29, 0x06, 0x28, 0xfb, 0xec, 0xfb, 0xec, 0x08, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x05, 0x00, 0x00, 0x03, 0x21, 0x11, 0x21, 0x11, 0x21, 0x12, 0x05, 0xae, 0xfd, 0x28, 0xfd, 0x2a, 0x06, 0x28, 0xf7, 0xd8, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xc4, 0x02, 0x14, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x02, 0xc4, 0x02, 0xd8, 0x02, 0x14, 0x04, 0x14, 0xfb, 0xec, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x07, 0x00, 0x00, 0x03, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x12, 0x02, 0xd6, 0x02, 0xd8, 0xfd, 0x29, 0xfd, 0x29, 0x02, 0x14, 0x04, 0x14, 0xfb, 0xec, 0xfb, 0xec, 0x00, 0x00, 0x01, 0xff, 0xee, 0xfe, 0x00, 0x05, 0x9c, 0x06, 0x28, 0x00, 0x05, 0x00, 0x00, 0x03, 0x11, 0x21, 0x11, 0x21, 0x11, 0x12, 0x02, 0xd6, 0x02, 0xd8, 0xfe, 0x00, 0x04, 0x14, 0x04, 0x14, 0xf7, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0xa7, 0x05, 0x7f, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x05, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x01, 0x0e, 0x04, 0xb2, 0xfb, 0x4e, 0x67, 0x05, 0x7f, 0x8a, 0x05, 0x3c, 0xfa, 0x52, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x25, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x21, 0x22, 0x15, 0x03, 0x11, 0x10, 0x29, 0x01, 0x20, 0x19, 0x01, 0x10, 0x29, 0x01, 0x20, 0x01, 0x0e, 0xcd, 0x03, 0x17, 0xce, 0xce, 0xfc, 0xe9, 0xcd, 0x67, 0x01, 0x34, 0x03, 0x17, 0x01, 0x34, 0xfe, 0xcc, 0xfc, 0xe9, 0xfe, 0xcc, 0x5a, 0xe4, 0xe4, 0x03, 0x74, 0xe4, 0xe4, 0xfc, 0x8c, 0x03, 0x74, 0x01, 0x56, 0xfe, 0xaa, 0xfc, 0x8c, 0xfe, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x10, 0x27, 0x0a, 0xd3, 0x00, 0xf6, 0x00, 0x00, 0x10, 0x06, 0x0a, 0xca, 0x00, 0x00, 0x00, 0x06, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0xa7, 0x05, 0x7f, 0xfa, 0xe8, 0x04, 0xb2, 0xfb, 0x4e, 0x04, 0xb2, 0xfb, 0x4e, 0x04, 0xb2, 0xfb, 0x4e, 0x04, 0xb2, 0xfb, 0x4e, 0x04, 0xb2, 0xfb, 0x4e, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0xb0, 0x72, 0xb2, 0x72, 0xb0, 0x72, 0xb2, 0x72, 0xb0, 0x00, 0x06, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0x01, 0x33, 0x11, 0x23, 0xa7, 0x05, 0x7f, 0xfe, 0xfe, 0x9e, 0x9e, 0xfe, 0xf9, 0xa0, 0xa0, 0xfe, 0xfb, 0x9e, 0x9e, 0xfe, 0xf9, 0xa0, 0xa0, 0xfe, 0xfb, 0x9f, 0x9f, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x74, 0x05, 0x38, 0xfa, 0xc8, 0x05, 0x38, 0xfa, 0xc8, 0x05, 0x38, 0xfa, 0xc8, 0x05, 0x38, 0xfa, 0xc8, 0x05, 0x38, 0x00, 0x00, 0x1a, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x3b, 0x00, 0x3f, 0x00, 0x43, 0x00, 0x47, 0x00, 0x4b, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x67, 0x00, 0x00, 0x05, 0x33, 0x35, 0x23, 0x05, 0x33, 0x35, 0x23, 0x05, 0x33, 0x35, 0x23, 0x01, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x01, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x01, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x01, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x01, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x11, 0x33, 0x35, 0x23, 0x01, 0x11, 0x21, 0x11, 0x02, 0x11, 0xa0, 0xa0, 0x01, 0x07, 0x9e, 0x9e, 0x01, 0x05, 0xa0, 0xa0, 0xfc, 0xf1, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x01, 0x03, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x01, 0x07, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x01, 0x05, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x01, 0x07, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0xfb, 0x83, 0x05, 0x7f, 0x88, 0xae, 0xae, 0xae, 0xae, 0xae, 0x03, 0xdc, 0xae, 0xfe, 0x2e, 0xb2, 0xfe, 0x2c, 0xb0, 0xfe, 0x2c, 0xb2, 0xfe, 0x2e, 0xae, 0x03, 0xdc, 0xae, 0xfe, 0x2e, 0xb2, 0xfe, 0x2c, 0xb0, 0xfe, 0x2c, 0xb2, 0x02, 0xb8, 0xae, 0xfe, 0x2e, 0xb2, 0xfe, 0x2c, 0xb0, 0xfe, 0x2c, 0xb2, 0x02, 0xb8, 0xae, 0xfe, 0x2e, 0xb2, 0xfe, 0x2c, 0xb0, 0xfe, 0x2c, 0xb2, 0x02, 0xb8, 0xae, 0xfe, 0x2e, 0xb2, 0xfe, 0x2c, 0xb0, 0xfe, 0x2c, 0xb2, 0xfe, 0x2e, 0xae, 0xfe, 0xde, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x08, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x1f, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x01, 0x15, 0x33, 0x03, 0x15, 0x01, 0x33, 0x01, 0x15, 0x01, 0x37, 0x01, 0x15, 0x01, 0x37, 0x35, 0x01, 0x33, 0x01, 0x35, 0x01, 0x33, 0x01, 0x35, 0x01, 0x33, 0x17, 0x35, 0xa7, 0x05, 0x7f, 0xfa, 0xe8, 0xcb, 0xcb, 0x01, 0x5d, 0xe2, 0xfd, 0xc1, 0x02, 0xd1, 0xe2, 0xfc, 0x4d, 0x04, 0x45, 0x6d, 0xfb, 0xbb, 0x92, 0x03, 0xb3, 0xfd, 0x2f, 0x91, 0x02, 0x40, 0xfe, 0xa2, 0x92, 0xcc, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x01, 0x54, 0xe2, 0x02, 0x7f, 0xfc, 0xfe, 0x7d, 0x04, 0x1c, 0xfc, 0xfc, 0xdf, 0x01, 0x05, 0x3c, 0x7f, 0xfb, 0x42, 0x01, 0x7f, 0x04, 0xbd, 0xfb, 0xe4, 0xfc, 0x03, 0x20, 0xfd, 0x81, 0xfc, 0x01, 0x83, 0xe2, 0xe2, 0x00, 0x00, 0x00, 0x08, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x1f, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x33, 0x35, 0x05, 0x33, 0x01, 0x35, 0x01, 0x17, 0x01, 0x35, 0x01, 0x17, 0x01, 0x35, 0x23, 0x01, 0x35, 0x01, 0x23, 0x01, 0x35, 0x01, 0x23, 0x01, 0x35, 0x37, 0x23, 0xa7, 0x05, 0x7f, 0xfe, 0xce, 0xcc, 0xfd, 0xc0, 0xe2, 0x01, 0x5e, 0xfc, 0x4d, 0xe2, 0x02, 0xd1, 0xfb, 0x4e, 0x6d, 0x04, 0x45, 0x6d, 0xfb, 0xbb, 0x03, 0xb3, 0xe2, 0xfd, 0x2f, 0x02, 0x3f, 0xe2, 0xfe, 0xa3, 0xcb, 0xcb, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0xe2, 0xe2, 0x01, 0x83, 0xfc, 0xfd, 0x81, 0x01, 0x03, 0x21, 0xfc, 0xfb, 0xe4, 0x01, 0x04, 0xbe, 0x7f, 0xfb, 0x43, 0xa1, 0x04, 0x1c, 0xfc, 0xe0, 0xa1, 0x02, 0x7f, 0xfe, 0x7d, 0xa1, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x04, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x12, 0x00, 0x17, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x3d, 0x00, 0x41, 0x00, 0x46, 0x00, 0x4b, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x57, 0x00, 0x5c, 0x00, 0x61, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x01, 0x17, 0x37, 0x27, 0x23, 0x11, 0x17, 0x37, 0x27, 0x07, 0x01, 0x17, 0x37, 0x27, 0x23, 0x03, 0x17, 0x37, 0x27, 0x03, 0x17, 0x37, 0x27, 0x07, 0x01, 0x17, 0x37, 0x27, 0x23, 0x03, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x35, 0x23, 0x03, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x27, 0x03, 0x33, 0x37, 0x27, 0x07, 0x01, 0x17, 0x37, 0x35, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x33, 0x37, 0x27, 0x01, 0x17, 0x37, 0x35, 0x27, 0x01, 0x17, 0x37, 0x27, 0x01, 0x17, 0x33, 0x37, 0x27, 0x05, 0x17, 0x33, 0x35, 0x27, 0x01, 0x11, 0x21, 0x11, 0x01, 0x0e, 0x2d, 0x70, 0x30, 0x6d, 0x2d, 0x71, 0x71, 0x2d, 0x01, 0x2e, 0x71, 0x71, 0x2f, 0x84, 0xe8, 0x71, 0x70, 0x71, 0xe5, 0x2d, 0x71, 0x71, 0x2d, 0x02, 0xa1, 0x72, 0x71, 0x30, 0x83, 0xe9, 0x71, 0x71, 0x71, 0xfe, 0xd6, 0x71, 0x70, 0x71, 0xfe, 0xd6, 0x71, 0x72, 0x72, 0x03, 0x2f, 0x70, 0x2d, 0x6d, 0xe9, 0x6f, 0x71, 0x6f, 0xfe, 0xd4, 0x70, 0x71, 0x6f, 0xfe, 0xd6, 0x70, 0x70, 0x70, 0xfe, 0xd6, 0x70, 0x71, 0x6f, 0xfe, 0xd4, 0x71, 0x70, 0x70, 0xe6, 0x6e, 0x2f, 0x70, 0x2d, 0x04, 0x14, 0x71, 0x2d, 0x2e, 0xfe, 0xd6, 0x71, 0x71, 0x71, 0xfe, 0xd6, 0x72, 0x6f, 0x71, 0xfe, 0xd7, 0x71, 0x72, 0x72, 0xfe, 0xd5, 0x2f, 0x85, 0x2e, 0x71, 0x02, 0x75, 0x70, 0x2e, 0x2e, 0xfe, 0xd7, 0x71, 0x70, 0x71, 0xfe, 0xd6, 0x2f, 0x84, 0x30, 0x71, 0x01, 0x02, 0x2f, 0x6e, 0x2e, 0xfb, 0x15, 0x05, 0x7f, 0x04, 0x33, 0x31, 0x7c, 0x34, 0xfd, 0xe4, 0x32, 0x7e, 0x7e, 0x31, 0x01, 0x4f, 0x7e, 0x7e, 0x34, 0xfe, 0xff, 0x7e, 0x7c, 0x7e, 0xfc, 0xcc, 0x31, 0x7e, 0x7d, 0x31, 0x02, 0xec, 0x7e, 0x7e, 0x34, 0xfe, 0xfd, 0x7d, 0x7d, 0x7e, 0xfe, 0xb5, 0x7e, 0x7d, 0x7d, 0xfe, 0xb6, 0x7e, 0x7e, 0x7e, 0x01, 0xec, 0x7c, 0x31, 0x7f, 0xfe, 0xfd, 0x7c, 0x7e, 0x7c, 0xfe, 0xb4, 0x7d, 0x7e, 0x7c, 0xfe, 0xb6, 0x7c, 0x7c, 0x7c, 0xfe, 0xb5, 0x7c, 0x7e, 0x7c, 0xfe, 0xb4, 0x7c, 0x7d, 0x7d, 0xfe, 0x81, 0x34, 0x7c, 0x31, 0x02, 0xed, 0x7e, 0x32, 0x99, 0x31, 0xfe, 0xb4, 0x7e, 0x7e, 0x7e, 0xfe, 0xb5, 0x7e, 0x7c, 0x7e, 0xfe, 0xb5, 0x7e, 0x7e, 0x7e, 0xfe, 0xb4, 0x34, 0x34, 0x7e, 0x01, 0x1e, 0x7e, 0x31, 0x99, 0x31, 0xfe, 0xb5, 0x7d, 0x7c, 0x7e, 0xfe, 0xb5, 0x34, 0x34, 0x7e, 0x7e, 0x34, 0x7f, 0x31, 0xfe, 0xde, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x16, 0x04, 0x3a, 0x04, 0x12, 0x00, 0x03, 0x00, 0x00, 0x37, 0x11, 0x21, 0x11, 0xa7, 0x03, 0x93, 0x16, 0x03, 0xfc, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x16, 0x04, 0x3a, 0x04, 0x12, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x25, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x01, 0x0e, 0x02, 0xc5, 0xfd, 0x3b, 0x67, 0x03, 0x93, 0x88, 0x03, 0x18, 0xfc, 0x76, 0x03, 0xfc, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x9a, 0x06, 0x27, 0x03, 0x8e, 0x00, 0x03, 0x00, 0x00, 0x25, 0x21, 0x11, 0x21, 0x06, 0x26, 0xfa, 0x81, 0x05, 0x7f, 0x9a, 0x02, 0xf4, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x9a, 0x06, 0x27, 0x03, 0x8e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x05, 0x21, 0x11, 0x21, 0x05, 0xc0, 0xfb, 0x4e, 0x05, 0x18, 0xfa, 0x81, 0x05, 0x7f, 0x01, 0x0c, 0x02, 0x10, 0xfd, 0xf0, 0x72, 0x02, 0xf4, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xff, 0x06, 0x03, 0x4f, 0x05, 0x22, 0x00, 0x03, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0xa7, 0x02, 0xa8, 0xfa, 0x06, 0x1c, 0xf9, 0xe4, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x06, 0x03, 0x4f, 0x05, 0x22, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x05, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x01, 0x0e, 0x01, 0xda, 0xfe, 0x26, 0x67, 0x02, 0xa8, 0x88, 0x05, 0x38, 0xfa, 0x56, 0x06, 0x1c, 0xf9, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x9a, 0x05, 0x85, 0x03, 0x8e, 0x00, 0x03, 0x00, 0x00, 0x25, 0x21, 0x01, 0x21, 0x04, 0x22, 0xfb, 0xe3, 0x01, 0x63, 0x04, 0x1c, 0x9a, 0x02, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x9a, 0x05, 0x85, 0x03, 0x8e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x13, 0x21, 0x03, 0x05, 0x21, 0x01, 0x21, 0x03, 0xf2, 0xf5, 0xfc, 0xb1, 0xf6, 0x03, 0x80, 0xfb, 0xe3, 0x01, 0x63, 0x04, 0x1c, 0x01, 0x0c, 0x02, 0x10, 0xfd, 0xf0, 0x72, 0x02, 0xf4, 0x00, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x00, 0x17, 0x09, 0x01, 0x05, 0x02, 0xbf, 0x02, 0xc0, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x17, 0x21, 0x09, 0x03, 0x9f, 0x04, 0x4b, 0xfd, 0xda, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0x8a, 0x04, 0xca, 0xfa, 0xc4, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x01, 0x00, 0x05, 0x00, 0x16, 0x03, 0x98, 0x04, 0x12, 0x00, 0x02, 0x00, 0x00, 0x37, 0x09, 0x01, 0x05, 0x01, 0xca, 0x01, 0xc9, 0x16, 0x03, 0xfc, 0xfc, 0x04, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x16, 0x03, 0x98, 0x04, 0x12, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x37, 0x21, 0x09, 0x03, 0x9f, 0x02, 0x5f, 0xfe, 0xd1, 0xfe, 0x36, 0x01, 0xca, 0x01, 0xc9, 0x88, 0x02, 0xa6, 0xfc, 0xe8, 0x03, 0xfc, 0xfc, 0x04, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x00, 0x17, 0x11, 0x01, 0x05, 0x05, 0x7f, 0xfc, 0x06, 0x20, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x17, 0x09, 0x01, 0x03, 0x11, 0x01, 0x6c, 0x04, 0x4b, 0xfb, 0xb5, 0x67, 0x05, 0x7f, 0x52, 0x02, 0x66, 0x02, 0x66, 0xfa, 0x8a, 0x06, 0x20, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x16, 0x03, 0x98, 0x04, 0x12, 0x00, 0x02, 0x00, 0x00, 0x37, 0x11, 0x01, 0x05, 0x03, 0x93, 0x16, 0x03, 0xfc, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x16, 0x03, 0x98, 0x04, 0x12, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x37, 0x09, 0x01, 0x03, 0x11, 0x01, 0x6c, 0x02, 0x5f, 0xfd, 0xa1, 0x67, 0x03, 0x93, 0xc1, 0x01, 0x53, 0x01, 0x53, 0xfc, 0xaf, 0x03, 0xfc, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x16, 0x05, 0x85, 0x04, 0x12, 0x00, 0x02, 0x00, 0x00, 0x37, 0x11, 0x01, 0x05, 0x05, 0x7f, 0x16, 0x03, 0xfc, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x16, 0x05, 0x85, 0x04, 0x12, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x37, 0x09, 0x01, 0x03, 0x11, 0x01, 0x6c, 0x04, 0x18, 0xfb, 0xe8, 0x67, 0x05, 0x7f, 0xc1, 0x01, 0x53, 0x01, 0x53, 0xfc, 0xaf, 0x03, 0xfc, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x00, 0x13, 0x21, 0x01, 0x05, 0x05, 0x7f, 0xfd, 0x40, 0x05, 0x24, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x13, 0x09, 0x01, 0x25, 0x21, 0x01, 0x9f, 0x02, 0x25, 0x02, 0x26, 0xfb, 0x1b, 0x05, 0x7f, 0xfd, 0x40, 0x04, 0xb2, 0xfb, 0x36, 0x04, 0xca, 0x72, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x16, 0x03, 0x98, 0x04, 0x12, 0x00, 0x02, 0x00, 0x00, 0x13, 0x21, 0x01, 0x05, 0x03, 0x93, 0xfe, 0x37, 0x04, 0x12, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x16, 0x03, 0x98, 0x04, 0x12, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x13, 0x09, 0x01, 0x25, 0x21, 0x01, 0x9f, 0x01, 0x30, 0x01, 0x2f, 0xfd, 0x07, 0x03, 0x93, 0xfe, 0x37, 0x03, 0xa0, 0xfd, 0x5a, 0x02, 0xa6, 0x72, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x00, 0x13, 0x01, 0x11, 0x05, 0x05, 0x7f, 0x02, 0x14, 0x03, 0x10, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x13, 0x01, 0x11, 0x09, 0x01, 0x11, 0xd3, 0x04, 0x4b, 0xfa, 0xe7, 0x05, 0x7f, 0x02, 0x14, 0xfd, 0x9a, 0x04, 0xcc, 0xfd, 0x9a, 0x03, 0x10, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x16, 0x03, 0x98, 0x04, 0x12, 0x00, 0x02, 0x00, 0x00, 0x13, 0x01, 0x11, 0x05, 0x03, 0x93, 0x02, 0x14, 0x01, 0xfe, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x16, 0x03, 0x98, 0x04, 0x12, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x13, 0x01, 0x11, 0x09, 0x01, 0x11, 0xd3, 0x02, 0x5e, 0xfc, 0xd4, 0x03, 0x93, 0x02, 0x14, 0xfe, 0xad, 0x02, 0xa6, 0xfe, 0xad, 0x01, 0xfe, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x16, 0x05, 0x85, 0x04, 0x12, 0x00, 0x02, 0x00, 0x00, 0x13, 0x01, 0x11, 0x05, 0x05, 0x7f, 0x02, 0x14, 0x01, 0xfe, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x16, 0x05, 0x85, 0x04, 0x12, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x09, 0x01, 0x11, 0x09, 0x01, 0x11, 0x01, 0x06, 0x04, 0x18, 0xfa, 0xe7, 0x05, 0x7f, 0x02, 0x14, 0xfe, 0xad, 0x02, 0xa6, 0xfe, 0xad, 0x01, 0xfe, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x03, 0x00, 0x00, 0x13, 0x09, 0x02, 0x05, 0x02, 0xbf, 0x02, 0xc0, 0xfd, 0x40, 0x02, 0x14, 0x03, 0x10, 0xfc, 0xf0, 0xfc, 0xf0, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x09, 0x06, 0x8e, 0x02, 0x36, 0x02, 0x37, 0xfd, 0xc9, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0xfd, 0x40, 0x02, 0x14, 0xfd, 0x88, 0x02, 0x78, 0x02, 0x78, 0xfd, 0x88, 0x03, 0x10, 0xfc, 0xf0, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x0b, 0x01, 0x1e, 0x01, 0xa6, 0x01, 0xa6, 0xfe, 0x5a, 0xfd, 0xca, 0x02, 0x36, 0x02, 0x37, 0xfd, 0xc9, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0xfd, 0x40, 0x02, 0x14, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0x29, 0x01, 0xd7, 0xfd, 0x88, 0x02, 0x78, 0x02, 0x78, 0xfd, 0x88, 0x03, 0x10, 0xfc, 0xf0, 0xfc, 0xf0, 0x00, 0x03, 0x00, 0x64, 0xfe, 0xff, 0x05, 0xe4, 0x05, 0x29, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x29, 0x00, 0x00, 0x24, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x00, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x10, 0x25, 0x26, 0x23, 0x22, 0x07, 0x00, 0x10, 0x25, 0x36, 0x33, 0x32, 0x17, 0x04, 0x10, 0x05, 0x06, 0x23, 0x22, 0x27, 0x01, 0x5b, 0xe5, 0x71, 0x73, 0x73, 0x71, 0xe5, 0xe5, 0x71, 0x73, 0x73, 0x71, 0xfe, 0x8e, 0x01, 0x2c, 0x94, 0x96, 0x96, 0x94, 0x01, 0x2c, 0xfe, 0xd4, 0x94, 0x96, 0x96, 0x94, 0xfe, 0x6b, 0x01, 0x60, 0xaf, 0xb0, 0xb0, 0xb0, 0x01, 0x60, 0xfe, 0xa0, 0xb0, 0xb0, 0xb0, 0xaf, 0xef, 0x02, 0x4a, 0x92, 0x4a, 0x4a, 0x92, 0xfd, 0xb6, 0x92, 0x4a, 0x4a, 0x03, 0x36, 0xfd, 0x02, 0xc0, 0x60, 0x60, 0xc0, 0x02, 0xfe, 0xc0, 0x60, 0x60, 0xfb, 0xff, 0x03, 0x84, 0xe2, 0x71, 0x71, 0xe2, 0xfc, 0x7c, 0xe2, 0x71, 0x71, 0x00, 0x00, 0x02, 0x00, 0x05, 0xfe, 0x23, 0x03, 0x8a, 0x06, 0x75, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x09, 0x07, 0x01, 0xc7, 0xfe, 0xa6, 0x01, 0x5a, 0x01, 0x5b, 0xfe, 0xa5, 0x01, 0xc2, 0xfe, 0x3e, 0xfe, 0x3e, 0x05, 0x81, 0xfc, 0xcf, 0xfc, 0xc7, 0x03, 0x39, 0x04, 0x25, 0xfb, 0xdb, 0xfb, 0xd3, 0x04, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0xfe, 0xff, 0x05, 0xe4, 0x05, 0x29, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x00, 0x12, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x10, 0x25, 0x26, 0x23, 0x22, 0x07, 0x00, 0x10, 0x25, 0x36, 0x33, 0x32, 0x17, 0x04, 0x10, 0x05, 0x06, 0x23, 0x22, 0x27, 0xce, 0x01, 0x2c, 0x94, 0x96, 0x96, 0x94, 0x01, 0x2c, 0xfe, 0xd4, 0x94, 0x96, 0x96, 0x94, 0xfe, 0x6b, 0x01, 0x60, 0xaf, 0xb0, 0xb0, 0xb0, 0x01, 0x60, 0xfe, 0xa0, 0xb0, 0xb0, 0xb0, 0xaf, 0x03, 0x93, 0xfd, 0x02, 0xc0, 0x60, 0x60, 0xc0, 0x02, 0xfe, 0xc0, 0x60, 0x60, 0xfb, 0xff, 0x03, 0x84, 0xe2, 0x71, 0x71, 0xe2, 0xfc, 0x7c, 0xe2, 0x71, 0x71, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x66, 0xff, 0x01, 0x05, 0xe2, 0x05, 0x27, 0x00, 0x09, 0x00, 0x13, 0x00, 0x1d, 0x00, 0x27, 0x00, 0x2f, 0x00, 0x37, 0x00, 0x3f, 0x00, 0x47, 0x00, 0x00, 0x25, 0x16, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x27, 0x05, 0x36, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x07, 0x13, 0x26, 0x27, 0x26, 0x27, 0x37, 0x16, 0x17, 0x16, 0x17, 0x25, 0x06, 0x07, 0x06, 0x07, 0x27, 0x36, 0x37, 0x36, 0x37, 0x13, 0x16, 0x32, 0x37, 0x17, 0x06, 0x22, 0x27, 0x01, 0x36, 0x34, 0x27, 0x37, 0x16, 0x14, 0x07, 0x01, 0x26, 0x22, 0x07, 0x27, 0x36, 0x32, 0x17, 0x01, 0x06, 0x14, 0x17, 0x07, 0x26, 0x34, 0x37, 0x01, 0x39, 0x27, 0x35, 0x29, 0x33, 0x2c, 0x3f, 0x34, 0x43, 0x30, 0x03, 0x78, 0x32, 0x29, 0x2f, 0x2d, 0x5a, 0x35, 0x3e, 0x33, 0x40, 0x8c, 0x27, 0x35, 0x29, 0x32, 0x2b, 0x40, 0x33, 0x43, 0x30, 0xfc, 0x89, 0x33, 0x29, 0x35, 0x27, 0x5a, 0x2c, 0x47, 0x34, 0x3f, 0xd5, 0x44, 0x8b, 0x44, 0x23, 0x56, 0xad, 0x56, 0x02, 0xf6, 0x0e, 0x0e, 0x63, 0x12, 0x12, 0xfd, 0xdd, 0x44, 0x8b, 0x44, 0x23, 0x56, 0xad, 0x56, 0xfd, 0x0c, 0x0f, 0x0f, 0x63, 0x12, 0x12, 0x8f, 0x3c, 0x31, 0x26, 0x20, 0x6a, 0x28, 0x30, 0x3d, 0x4a, 0x75, 0x20, 0x26, 0x2c, 0x41, 0x3d, 0x4e, 0x3a, 0x30, 0x28, 0x04, 0x27, 0x3c, 0x31, 0x26, 0x20, 0x6a, 0x28, 0x30, 0x3d, 0x4a, 0x75, 0x20, 0x26, 0x31, 0x3c, 0x3e, 0x45, 0x42, 0x30, 0x28, 0xfa, 0xd4, 0x16, 0x16, 0x6e, 0x1b, 0x1b, 0x02, 0x5f, 0x49, 0xa0, 0x49, 0x27, 0x5b, 0xca, 0x5b, 0x03, 0x4a, 0x16, 0x16, 0x6e, 0x1b, 0x1b, 0xfd, 0xa1, 0x49, 0xa0, 0x49, 0x27, 0x5b, 0xca, 0x5b, 0x00, 0x00, 0x06, 0x00, 0x64, 0xfe, 0xff, 0x05, 0xe4, 0x05, 0x29, 0x00, 0x0d, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x25, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x00, 0x36, 0x10, 0x25, 0x36, 0x33, 0x32, 0x17, 0x04, 0x10, 0x05, 0x06, 0x23, 0x22, 0x27, 0x13, 0x11, 0x16, 0x17, 0x16, 0x17, 0x11, 0x06, 0x07, 0x06, 0x07, 0x06, 0x10, 0x17, 0x01, 0x11, 0x16, 0x33, 0x32, 0x37, 0x11, 0x26, 0x23, 0x22, 0x17, 0x11, 0x36, 0x37, 0x36, 0x37, 0x11, 0x26, 0x27, 0x26, 0x17, 0x11, 0x36, 0x10, 0x65, 0x01, 0x60, 0xaf, 0xb0, 0xb0, 0xb0, 0x01, 0x60, 0xfe, 0xa0, 0xb0, 0xb0, 0xb0, 0xaf, 0x0a, 0x14, 0x17, 0x3a, 0x3b, 0x3b, 0x3a, 0x17, 0x7b, 0x9a, 0x9a, 0x01, 0x6d, 0x28, 0x27, 0x28, 0x28, 0x28, 0x28, 0x27, 0xdd, 0x3b, 0x39, 0x18, 0x15, 0x15, 0x18, 0x39, 0xcc, 0x99, 0x52, 0x03, 0x84, 0xe2, 0x71, 0x71, 0xe2, 0xfc, 0x7c, 0xe2, 0x71, 0x71, 0x04, 0xc5, 0xfb, 0xbe, 0x0f, 0x0f, 0x25, 0x17, 0x04, 0xf6, 0x17, 0x25, 0x0f, 0x6d, 0xb1, 0xfd, 0xdc, 0xb1, 0x04, 0x5b, 0xfa, 0xd0, 0x07, 0x07, 0x05, 0x30, 0x07, 0x24, 0xfb, 0x0a, 0x17, 0x25, 0x0f, 0x10, 0x04, 0x40, 0x10, 0x0f, 0x25, 0xa2, 0xfc, 0x7c, 0xb1, 0x02, 0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x64, 0xfe, 0xff, 0x05, 0xe4, 0x05, 0x29, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x29, 0x00, 0x37, 0x00, 0x00, 0x00, 0x10, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x10, 0x27, 0x26, 0x23, 0x22, 0x07, 0x02, 0x10, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x10, 0x07, 0x06, 0x23, 0x22, 0x27, 0x00, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x10, 0x25, 0x26, 0x23, 0x22, 0x07, 0x00, 0x10, 0x25, 0x36, 0x33, 0x32, 0x17, 0x04, 0x10, 0x05, 0x06, 0x23, 0x22, 0x27, 0x02, 0x56, 0x67, 0x33, 0x34, 0x34, 0x33, 0x67, 0x67, 0x33, 0x34, 0x34, 0x33, 0xd5, 0x9e, 0x4f, 0x4f, 0x4f, 0x4f, 0x9e, 0x9e, 0x4f, 0x4f, 0x4f, 0x4f, 0xfe, 0x48, 0x01, 0x2c, 0x94, 0x96, 0x96, 0x94, 0x01, 0x2c, 0xfe, 0xd4, 0x94, 0x96, 0x96, 0x94, 0xfe, 0x6b, 0x01, 0x60, 0xaf, 0xb0, 0xb0, 0xb0, 0x01, 0x60, 0xfe, 0xa0, 0xb0, 0xb0, 0xb0, 0xaf, 0x02, 0x98, 0xfe, 0xf8, 0x42, 0x21, 0x21, 0x42, 0x01, 0x08, 0x42, 0x21, 0x21, 0xfe, 0x6f, 0x01, 0x96, 0x65, 0x33, 0x33, 0x65, 0xfe, 0x6a, 0x65, 0x33, 0x33, 0x02, 0xaf, 0xfd, 0x02, 0xc0, 0x60, 0x60, 0xc0, 0x02, 0xfe, 0xc0, 0x60, 0x60, 0xfb, 0xff, 0x03, 0x84, 0xe2, 0x71, 0x71, 0xe2, 0xfc, 0x7c, 0xe2, 0x71, 0x71, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x17, 0x00, 0x00, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x65, 0x5e, 0x5e, 0xa4, 0xa3, 0xbd, 0xbc, 0xa3, 0xa3, 0x5e, 0x5f, 0x5f, 0x5e, 0xa3, 0xa3, 0xbc, 0xbd, 0xa3, 0xa4, 0x5e, 0x5e, 0x02, 0x12, 0xd1, 0xb6, 0xb5, 0x69, 0x69, 0x69, 0x69, 0xb5, 0xb6, 0xd1, 0xd1, 0xb6, 0xb5, 0x69, 0x69, 0x69, 0x69, 0xb5, 0xb6, 0x00, 0x02, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0d, 0x00, 0x15, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x22, 0x24, 0x05, 0x32, 0x37, 0x24, 0x10, 0x25, 0x26, 0x23, 0x65, 0xbc, 0x01, 0x47, 0xbd, 0xbc, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xbc, 0xbd, 0xfe, 0xb9, 0x02, 0x03, 0x96, 0x94, 0x01, 0x2c, 0xfe, 0xd4, 0x94, 0x96, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x61, 0x60, 0xc0, 0x02, 0xfe, 0xc0, 0x60, 0x00, 0x00, 0x02, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0d, 0x00, 0x15, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x22, 0x24, 0x01, 0x22, 0x07, 0x04, 0x10, 0x05, 0x16, 0x33, 0x65, 0xbc, 0x01, 0x47, 0xbd, 0xbc, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xbc, 0xbd, 0xfe, 0xb9, 0x02, 0x03, 0x96, 0x94, 0xfe, 0xd4, 0x01, 0x2c, 0x94, 0x96, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x04, 0xdd, 0x60, 0xc0, 0xfd, 0x02, 0xc0, 0x60, 0x00, 0x02, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0d, 0x00, 0x16, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x22, 0x24, 0x01, 0x10, 0x25, 0x26, 0x23, 0x22, 0x07, 0x04, 0x11, 0x65, 0xbc, 0x01, 0x47, 0xbd, 0xbc, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xbc, 0xbd, 0xfe, 0xb9, 0x04, 0x59, 0xfe, 0xd4, 0x94, 0x96, 0x96, 0x94, 0xfe, 0xd4, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x02, 0x3e, 0x01, 0x7f, 0xc0, 0x60, 0x60, 0xc0, 0xfe, 0x81, 0x00, 0x00, 0x02, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0d, 0x00, 0x16, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x22, 0x24, 0x03, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x11, 0x65, 0xbc, 0x01, 0x47, 0xbd, 0xbc, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xbc, 0xbd, 0xfe, 0xb9, 0x53, 0x01, 0x2c, 0x94, 0x96, 0x96, 0x94, 0x01, 0x2c, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x02, 0x3e, 0xfe, 0x81, 0xc0, 0x60, 0x60, 0xc0, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0b, 0x00, 0x18, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x20, 0x04, 0x12, 0x10, 0x02, 0x04, 0x20, 0x24, 0x01, 0x22, 0x07, 0x04, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x11, 0x21, 0x65, 0xbc, 0x01, 0x47, 0x01, 0x79, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xfe, 0x87, 0xfe, 0xb9, 0x02, 0x03, 0x96, 0x94, 0xfe, 0xd4, 0x01, 0x2c, 0x94, 0x96, 0x96, 0x94, 0x01, 0x2c, 0xfd, 0xaa, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x04, 0xdd, 0x60, 0xc0, 0xfd, 0x02, 0xc0, 0x60, 0x60, 0xc0, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0b, 0x00, 0x11, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x20, 0x04, 0x12, 0x10, 0x02, 0x04, 0x20, 0x24, 0x01, 0x22, 0x07, 0x04, 0x11, 0x21, 0x65, 0xbc, 0x01, 0x47, 0x01, 0x79, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xfe, 0x87, 0xfe, 0xb9, 0x02, 0x03, 0x96, 0x94, 0xfe, 0xd4, 0x02, 0x56, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x04, 0xdd, 0x60, 0xc0, 0xfe, 0x81, 0x00, 0x01, 0x00, 0x64, 0xfe, 0xff, 0x03, 0x24, 0x05, 0x29, 0x00, 0x07, 0x00, 0x00, 0x36, 0x10, 0x25, 0x36, 0x33, 0x11, 0x22, 0x27, 0x65, 0x01, 0x60, 0xaf, 0xb0, 0xb0, 0xaf, 0x52, 0x03, 0x84, 0xe2, 0x71, 0xf9, 0xd6, 0x71, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xff, 0x03, 0x67, 0x05, 0x29, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x05, 0x06, 0x23, 0x11, 0x32, 0x17, 0x03, 0x66, 0xfe, 0xa0, 0xaf, 0xb0, 0xb0, 0xaf, 0x03, 0xd6, 0xfc, 0x7c, 0xe2, 0x71, 0x06, 0x2a, 0x71, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0xec, 0x05, 0x0b, 0x06, 0x28, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x14, 0x16, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x01, 0x11, 0x21, 0x11, 0x01, 0xce, 0x9a, 0xe2, 0x9a, 0x9a, 0x6f, 0x72, 0x9b, 0xfe, 0xd9, 0x04, 0x64, 0x02, 0xfa, 0x7d, 0xac, 0xac, 0x7d, 0x7c, 0xab, 0xab, 0xfc, 0x76, 0x06, 0x3c, 0xf9, 0xc4, 0x00, 0x00, 0x03, 0x00, 0xa7, 0xfe, 0x00, 0x06, 0x55, 0x06, 0x28, 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x00, 0x24, 0x10, 0x25, 0x36, 0x33, 0x32, 0x17, 0x04, 0x10, 0x05, 0x06, 0x23, 0x22, 0x27, 0x00, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x10, 0x25, 0x26, 0x23, 0x22, 0x07, 0x01, 0x11, 0x21, 0x11, 0x01, 0x28, 0x01, 0x2c, 0x94, 0x96, 0x96, 0x94, 0x01, 0x2c, 0xfe, 0xd4, 0x94, 0x96, 0x96, 0x94, 0xfe, 0x6b, 0x01, 0x60, 0xaf, 0xb0, 0xb0, 0xb0, 0x01, 0x60, 0xfe, 0xa0, 0xb0, 0xb0, 0xb0, 0xaf, 0xfe, 0x88, 0x05, 0xae, 0x95, 0x02, 0xfe, 0xc0, 0x60, 0x60, 0xc0, 0xfd, 0x02, 0xc0, 0x60, 0x60, 0x04, 0x01, 0xfc, 0x7c, 0xe2, 0x71, 0x71, 0xe2, 0x03, 0x84, 0xe2, 0x71, 0x71, 0xf9, 0x48, 0x08, 0x28, 0xf7, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x02, 0x14, 0x06, 0x55, 0x06, 0x28, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x00, 0x13, 0x11, 0x21, 0x11, 0x23, 0x10, 0x25, 0x26, 0x23, 0x22, 0x07, 0x04, 0x11, 0x29, 0x01, 0x10, 0x25, 0x36, 0x33, 0x32, 0x17, 0x04, 0xa7, 0x05, 0xae, 0x17, 0xfe, 0xa0, 0xb0, 0xb0, 0xb0, 0xaf, 0xfe, 0xa0, 0x05, 0x15, 0xfb, 0x54, 0x01, 0x2c, 0x95, 0x95, 0x95, 0x95, 0x01, 0x2c, 0x02, 0x14, 0x04, 0x14, 0xfb, 0xec, 0x01, 0xc2, 0xe2, 0x71, 0x71, 0xe2, 0xfe, 0x3e, 0x01, 0x7e, 0xc1, 0x60, 0x60, 0xc1, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xfe, 0x00, 0x06, 0x55, 0x02, 0x14, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x00, 0x13, 0x11, 0x33, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x11, 0x33, 0x11, 0x01, 0x21, 0x10, 0x05, 0x06, 0x23, 0x22, 0x27, 0x24, 0xa7, 0x18, 0x01, 0x60, 0xaf, 0xb0, 0xb0, 0xb0, 0x01, 0x60, 0x17, 0xfa, 0xd3, 0x04, 0xac, 0xfe, 0xd4, 0x95, 0x95, 0x95, 0x95, 0xfe, 0xd4, 0xfe, 0x00, 0x04, 0x14, 0xfe, 0x3e, 0xe2, 0x71, 0x71, 0xe2, 0x01, 0xc2, 0xfb, 0xec, 0x04, 0x14, 0xfe, 0x82, 0xc1, 0x60, 0x60, 0xc1, 0x00, 0x00, 0x01, 0x00, 0x05, 0x02, 0x14, 0x02, 0xc5, 0x05, 0x29, 0x00, 0x09, 0x00, 0x00, 0x13, 0x10, 0x25, 0x36, 0x33, 0x15, 0x22, 0x07, 0x04, 0x11, 0x05, 0x01, 0x60, 0xb0, 0xaf, 0x95, 0x95, 0xfe, 0xd5, 0x02, 0x14, 0x01, 0xc2, 0xe2, 0x71, 0x76, 0x60, 0xc0, 0xfe, 0x81, 0x00, 0x01, 0x00, 0x05, 0x02, 0x14, 0x02, 0xc5, 0x05, 0x29, 0x00, 0x09, 0x00, 0x00, 0x13, 0x32, 0x17, 0x04, 0x11, 0x23, 0x10, 0x25, 0x26, 0x23, 0x05, 0xb0, 0xaf, 0x01, 0x60, 0x69, 0xfe, 0xd4, 0x94, 0x96, 0x05, 0x29, 0x71, 0xe2, 0xfe, 0x3e, 0x01, 0x7f, 0xc0, 0x60, 0x00, 0x01, 0x00, 0x05, 0xfe, 0xff, 0x02, 0xc5, 0x02, 0x14, 0x00, 0x09, 0x00, 0x00, 0x13, 0x35, 0x32, 0x37, 0x24, 0x11, 0x33, 0x10, 0x05, 0x06, 0x05, 0x96, 0x94, 0x01, 0x2c, 0x69, 0xfe, 0xa0, 0xaf, 0xfe, 0xff, 0x76, 0x60, 0xc0, 0x01, 0x7f, 0xfe, 0x3e, 0xe2, 0x71, 0x00, 0x01, 0x00, 0x05, 0xfe, 0xff, 0x02, 0xc5, 0x02, 0x14, 0x00, 0x09, 0x00, 0x00, 0x01, 0x22, 0x27, 0x24, 0x11, 0x33, 0x10, 0x05, 0x16, 0x33, 0x02, 0xc4, 0xaf, 0xb0, 0xfe, 0xa0, 0x6a, 0x01, 0x2b, 0x95, 0x95, 0xfe, 0xff, 0x71, 0xe2, 0x01, 0xc2, 0xfe, 0x81, 0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x64, 0x02, 0x14, 0x05, 0xe4, 0x05, 0x29, 0x00, 0x11, 0x00, 0x00, 0x13, 0x10, 0x25, 0x36, 0x33, 0x32, 0x17, 0x04, 0x11, 0x23, 0x10, 0x25, 0x26, 0x23, 0x22, 0x07, 0x04, 0x11, 0x65, 0x01, 0x60, 0xaf, 0xb0, 0xb0, 0xb0, 0x01, 0x60, 0x6a, 0xfe, 0xd4, 0x94, 0x96, 0x96, 0x94, 0xfe, 0xd4, 0x02, 0x14, 0x01, 0xc2, 0xe2, 0x71, 0x71, 0xe2, 0xfe, 0x3e, 0x01, 0x7f, 0xc0, 0x60, 0x60, 0xc0, 0xfe, 0x81, 0x00, 0x01, 0x00, 0x64, 0xfe, 0xff, 0x05, 0xe4, 0x02, 0x14, 0x00, 0x12, 0x00, 0x00, 0x13, 0x30, 0x33, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x11, 0x33, 0x10, 0x05, 0x06, 0x23, 0x22, 0x27, 0x24, 0x65, 0x69, 0x01, 0x2c, 0x94, 0x96, 0x96, 0x94, 0x01, 0x2c, 0x6a, 0xfe, 0xa0, 0xb0, 0xb0, 0xb0, 0xaf, 0xfe, 0xa0, 0x02, 0x14, 0xfe, 0x81, 0xc0, 0x60, 0x60, 0xc0, 0x01, 0x7f, 0xfe, 0x3e, 0xe2, 0x71, 0x71, 0xe2, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x00, 0x17, 0x01, 0x11, 0x05, 0x05, 0x7f, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x00, 0x17, 0x11, 0x01, 0x05, 0x05, 0x7f, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x00, 0x17, 0x11, 0x21, 0x05, 0x05, 0x7f, 0xfc, 0x06, 0x20, 0x00, 0x00, 0x01, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x00, 0x13, 0x21, 0x11, 0x05, 0x05, 0x7f, 0x05, 0x24, 0xf9, 0xe0, 0x00, 0x02, 0x01, 0x14, 0x01, 0xd1, 0x03, 0x2b, 0x04, 0x21, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x00, 0x01, 0x14, 0x16, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x22, 0x26, 0x01, 0x49, 0x7d, 0xb4, 0x7c, 0x7c, 0x59, 0x5b, 0x7d, 0x35, 0x9c, 0x71, 0x70, 0x9a, 0x9b, 0xe1, 0x9b, 0x02, 0xfa, 0x64, 0x8a, 0x8a, 0x64, 0x63, 0x89, 0x89, 0x63, 0x7c, 0xab, 0xab, 0x7c, 0x7d, 0xac, 0xac, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0xa7, 0x05, 0x7f, 0xfd, 0x40, 0x02, 0x5a, 0xfd, 0xa6, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0x05, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0xa7, 0x05, 0x7f, 0xfa, 0xe8, 0x02, 0x58, 0xfd, 0xa8, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0x05, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0xa7, 0x05, 0x7f, 0xfa, 0xe8, 0x04, 0xb2, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0x05, 0x3c, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x01, 0x21, 0xa7, 0x05, 0x7f, 0xfa, 0xe8, 0x04, 0xb2, 0xfb, 0x4e, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0x05, 0x3c, 0x00, 0x03, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x21, 0x11, 0x21, 0xa7, 0x05, 0x7f, 0xfd, 0x74, 0x02, 0x26, 0xfd, 0xda, 0xfd, 0x74, 0x02, 0x25, 0xfd, 0xdb, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0x05, 0x3c, 0xfa, 0xc4, 0x05, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x01, 0x21, 0x09, 0x03, 0x02, 0x3f, 0x4e, 0x70, 0x4d, 0x4d, 0x71, 0xfe, 0x13, 0x04, 0x4b, 0xfd, 0xda, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0x01, 0x2c, 0x7c, 0x56, 0x56, 0x7c, 0x56, 0xfe, 0xa0, 0x04, 0xca, 0xfa, 0xc4, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x05, 0x21, 0x09, 0x03, 0x02, 0xc4, 0x02, 0x26, 0xfd, 0xda, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0x8a, 0x04, 0xca, 0xfa, 0xc4, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x17, 0x21, 0x11, 0x09, 0x02, 0x9f, 0x02, 0x25, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0x8a, 0x04, 0xca, 0xfa, 0xc4, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x02, 0x00, 0x64, 0xfe, 0x00, 0x07, 0xaa, 0x06, 0x28, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x12, 0x10, 0x01, 0x16, 0x20, 0x37, 0x00, 0x10, 0x01, 0x26, 0x20, 0x07, 0x00, 0x10, 0x01, 0x36, 0x20, 0x17, 0x00, 0x10, 0x01, 0x06, 0x20, 0x27, 0xd9, 0x01, 0x98, 0xcb, 0x01, 0x97, 0xcb, 0x01, 0x98, 0xfe, 0x68, 0xcb, 0xfe, 0x69, 0xcb, 0xfd, 0xf4, 0x01, 0xd1, 0xe9, 0x01, 0xd1, 0xe9, 0x01, 0xd1, 0xfe, 0x2f, 0xe9, 0xfe, 0x2f, 0xe9, 0x04, 0x1e, 0xfb, 0xec, 0xfe, 0xfb, 0x83, 0x83, 0x01, 0x05, 0x04, 0x14, 0x01, 0x05, 0x83, 0x83, 0xfa, 0x9d, 0x04, 0xa8, 0x01, 0x2a, 0x96, 0x96, 0xfe, 0xd6, 0xfb, 0x58, 0xfe, 0xd6, 0x96, 0x96, 0x00, 0x00, 0x03, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0x05, 0x21, 0x11, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x01, 0x21, 0x11, 0x21, 0x01, 0x0e, 0x04, 0xb2, 0xfd, 0xda, 0xfd, 0x74, 0x67, 0x05, 0x7f, 0xfa, 0xe8, 0x02, 0x25, 0xfd, 0xdb, 0x8a, 0x05, 0x3c, 0xfd, 0x29, 0xfd, 0x29, 0x06, 0x20, 0xf9, 0xe0, 0x03, 0x49, 0x02, 0x65, 0x00, 0x03, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x0e, 0x02, 0x8c, 0x02, 0x26, 0xfb, 0x4e, 0x67, 0x05, 0x7f, 0xfa, 0xe8, 0x02, 0x25, 0xfd, 0xdb, 0x02, 0x4d, 0xfd, 0x29, 0x05, 0x3c, 0xfa, 0x52, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0x02, 0x65, 0x00, 0x03, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0x05, 0x21, 0x11, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x0e, 0x02, 0x25, 0x02, 0x8d, 0xfb, 0x4e, 0x67, 0x05, 0x7f, 0xfd, 0x74, 0x02, 0x26, 0xfd, 0xda, 0x8a, 0x02, 0xd7, 0x02, 0x65, 0xfa, 0x52, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0x02, 0x65, 0x00, 0x00, 0x03, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0x05, 0x21, 0x11, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x01, 0x21, 0x11, 0x21, 0x01, 0x0e, 0x04, 0xb2, 0xfd, 0x73, 0xfd, 0xdb, 0x67, 0x05, 0x7f, 0xfd, 0x74, 0x02, 0x26, 0xfd, 0xda, 0x8a, 0x02, 0x65, 0x02, 0xd7, 0xfa, 0x52, 0x06, 0x20, 0xf9, 0xe0, 0x03, 0x49, 0x02, 0x65, 0x00, 0x03, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0d, 0x00, 0x13, 0x00, 0x20, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x22, 0x24, 0x01, 0x06, 0x07, 0x04, 0x03, 0x21, 0x05, 0x12, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x10, 0x25, 0x26, 0x27, 0x11, 0x65, 0xbc, 0x01, 0x47, 0xbd, 0xbc, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xbc, 0xbd, 0xfe, 0xb9, 0x01, 0xcf, 0x7b, 0x7b, 0xfe, 0xeb, 0x15, 0x02, 0x20, 0xfd, 0xe0, 0x15, 0x01, 0x15, 0x95, 0x95, 0x95, 0x95, 0x01, 0x2c, 0xfe, 0xd4, 0x7b, 0x7c, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x04, 0xda, 0x0e, 0x4f, 0xb2, 0xfe, 0xac, 0x72, 0xfe, 0xac, 0xb2, 0x60, 0x60, 0xc1, 0x02, 0xfc, 0xc1, 0x4f, 0x0e, 0xfd, 0x2b, 0x00, 0x03, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0d, 0x00, 0x1a, 0x00, 0x20, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x22, 0x24, 0x05, 0x36, 0x37, 0x24, 0x10, 0x25, 0x26, 0x23, 0x22, 0x07, 0x04, 0x03, 0x21, 0x05, 0x12, 0x05, 0x16, 0x17, 0x11, 0x65, 0xbc, 0x01, 0x47, 0xbd, 0xbc, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xbc, 0xbd, 0xfe, 0xb9, 0x02, 0x36, 0x7c, 0x7b, 0x01, 0x2c, 0xfe, 0xd4, 0x95, 0x95, 0x95, 0x95, 0xfe, 0xeb, 0x15, 0x02, 0x87, 0xfd, 0x79, 0x15, 0x01, 0x15, 0x7b, 0x7b, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x5e, 0x0e, 0x4f, 0xc1, 0x02, 0xfc, 0xc1, 0x60, 0x60, 0xb2, 0xfe, 0xac, 0x72, 0xfe, 0xac, 0xb2, 0x4f, 0x0e, 0x02, 0x63, 0x00, 0x00, 0x03, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0d, 0x00, 0x1a, 0x00, 0x20, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x22, 0x24, 0x02, 0x10, 0x05, 0x16, 0x17, 0x11, 0x21, 0x02, 0x25, 0x26, 0x23, 0x22, 0x07, 0x01, 0x36, 0x37, 0x24, 0x13, 0x21, 0x65, 0xbc, 0x01, 0x47, 0xbd, 0xbc, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xbc, 0xbd, 0xfe, 0xb9, 0x53, 0x01, 0x2c, 0x7b, 0x7b, 0x02, 0x88, 0x14, 0xfe, 0xea, 0x95, 0x95, 0x95, 0x95, 0x01, 0x5d, 0x7c, 0x7b, 0x01, 0x16, 0x14, 0xfd, 0xdf, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x03, 0xbc, 0xfd, 0x04, 0xc1, 0x4f, 0x0e, 0x02, 0xd5, 0x01, 0x54, 0xb2, 0x60, 0x60, 0xfb, 0x25, 0x0e, 0x4f, 0xb2, 0x01, 0x54, 0x00, 0x00, 0x03, 0x00, 0x64, 0xff, 0x04, 0x05, 0xe4, 0x05, 0x20, 0x00, 0x0d, 0x00, 0x1a, 0x00, 0x20, 0x00, 0x00, 0x12, 0x10, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x23, 0x22, 0x24, 0x02, 0x10, 0x05, 0x16, 0x33, 0x32, 0x37, 0x24, 0x13, 0x21, 0x11, 0x06, 0x07, 0x01, 0x02, 0x25, 0x26, 0x27, 0x11, 0x65, 0xbc, 0x01, 0x47, 0xbd, 0xbc, 0x01, 0x46, 0xbd, 0xbd, 0xfe, 0xba, 0xbc, 0xbd, 0xfe, 0xb9, 0x53, 0x01, 0x2c, 0x95, 0x95, 0x95, 0x95, 0x01, 0x16, 0x14, 0xfd, 0x78, 0x7b, 0x7b, 0x03, 0x7e, 0x14, 0xfe, 0xea, 0x7b, 0x7c, 0x01, 0x41, 0x01, 0xa2, 0x01, 0x6b, 0xd2, 0xd2, 0xfe, 0x95, 0xfe, 0x5e, 0xfe, 0x95, 0xd2, 0xd2, 0x03, 0xbc, 0xfd, 0x04, 0xc1, 0x60, 0x60, 0xb2, 0x01, 0x54, 0x02, 0xd5, 0x0e, 0x4f, 0xfd, 0xfa, 0x01, 0x54, 0xb2, 0x4f, 0x0e, 0xfd, 0x9d, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x37, 0x01, 0x21, 0x03, 0x11, 0x21, 0x6c, 0x04, 0x18, 0xfb, 0xe8, 0x67, 0x05, 0x7f, 0x20, 0x04, 0x92, 0xfa, 0x52, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x09, 0x01, 0x11, 0x25, 0x21, 0x11, 0x01, 0x06, 0x04, 0x18, 0xfa, 0xe7, 0x05, 0x7f, 0x04, 0xb2, 0xfb, 0x6e, 0x04, 0x92, 0x72, 0xf9, 0xe0, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x17, 0x21, 0x01, 0x03, 0x11, 0x01, 0x6c, 0x04, 0x18, 0xfb, 0xe8, 0x67, 0x05, 0x7f, 0x8a, 0x04, 0x92, 0xfa, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x79, 0x05, 0x53, 0x04, 0xaf, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x05, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x01, 0x0e, 0x03, 0xde, 0xfc, 0x22, 0x67, 0x04, 0xac, 0x15, 0x04, 0x52, 0xfb, 0x3c, 0x05, 0x36, 0xfa, 0xca, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xff, 0x79, 0x05, 0x53, 0x04, 0xaf, 0x00, 0x03, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0xa7, 0x04, 0xac, 0x87, 0x05, 0x36, 0xfa, 0xca, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0xdd, 0x04, 0x9f, 0x04, 0x4b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x25, 0x21, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x01, 0x0e, 0x03, 0x2a, 0xfc, 0xd6, 0x67, 0x03, 0xf8, 0x4f, 0x03, 0x8a, 0xfc, 0x04, 0x04, 0x6e, 0xfb, 0x92, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xff, 0xdd, 0x04, 0x9f, 0x04, 0x4b, 0x00, 0x03, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0xa7, 0x03, 0xf8, 0x23, 0x04, 0x6e, 0xfb, 0x92, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x05, 0x21, 0x11, 0x09, 0x01, 0x11, 0x01, 0x06, 0x04, 0x18, 0xfa, 0xe7, 0x05, 0x7f, 0x8a, 0x04, 0x92, 0xfa, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x05, 0xda, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x13, 0x00, 0x22, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x3a, 0x00, 0x41, 0x00, 0x49, 0x00, 0x00, 0x01, 0x33, 0x17, 0x11, 0x07, 0x23, 0x27, 0x11, 0x05, 0x17, 0x15, 0x07, 0x27, 0x25, 0x17, 0x07, 0x23, 0x26, 0x27, 0x35, 0x05, 0x32, 0x1f, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x01, 0x21, 0x17, 0x15, 0x07, 0x21, 0x27, 0x35, 0x25, 0x21, 0x17, 0x15, 0x07, 0x21, 0x27, 0x35, 0x03, 0x33, 0x16, 0x17, 0x15, 0x07, 0x27, 0x35, 0x25, 0x33, 0x17, 0x15, 0x07, 0x27, 0x35, 0x25, 0x33, 0x17, 0x11, 0x07, 0x23, 0x27, 0x11, 0x03, 0x1b, 0x45, 0x05, 0x05, 0x45, 0x06, 0x01, 0xff, 0x34, 0xdf, 0x37, 0xfd, 0x4a, 0xe3, 0x37, 0x03, 0xb4, 0x29, 0x01, 0xf8, 0xbc, 0x50, 0x0c, 0xac, 0x3f, 0x2a, 0x9d, 0x58, 0x20, 0xa5, 0x3c, 0xfd, 0x90, 0x01, 0x31, 0x06, 0x06, 0xfe, 0xcf, 0x05, 0x04, 0x03, 0x01, 0x36, 0x07, 0x07, 0xfe, 0xca, 0x06, 0x3f, 0x02, 0x79, 0x66, 0x37, 0xdf, 0xfd, 0xf0, 0x03, 0x35, 0xde, 0x37, 0x01, 0xe5, 0x45, 0x05, 0x05, 0x45, 0x06, 0x05, 0xd5, 0x06, 0xfe, 0xa2, 0x06, 0x06, 0x01, 0x5e, 0x9b, 0x3f, 0x03, 0xfe, 0x3f, 0xee, 0xfe, 0x40, 0xc7, 0x37, 0x04, 0xb5, 0xe1, 0x60, 0xbd, 0x64, 0x17, 0xa7, 0x3f, 0x5c, 0xb5, 0x67, 0x1b, 0xfe, 0xed, 0x06, 0x4f, 0x06, 0x06, 0x4f, 0x06, 0x06, 0x4f, 0x06, 0x06, 0x4f, 0xfe, 0xe8, 0x82, 0x79, 0x03, 0x3e, 0xfd, 0x04, 0x2a, 0x3c, 0x03, 0xfe, 0x3f, 0x04, 0x76, 0x06, 0xfe, 0xa2, 0x06, 0x06, 0x01, 0x5e, 0x00, 0x01, 0x00, 0x5d, 0xff, 0xfb, 0x06, 0xd5, 0x02, 0xe1, 0x00, 0x22, 0x00, 0x00, 0x01, 0x33, 0x32, 0x1f, 0x01, 0x36, 0x33, 0x16, 0x15, 0x14, 0x07, 0x16, 0x1d, 0x01, 0x06, 0x23, 0x21, 0x35, 0x32, 0x37, 0x36, 0x3b, 0x01, 0x27, 0x34, 0x3f, 0x01, 0x17, 0x27, 0x34, 0x3f, 0x01, 0x32, 0x17, 0x36, 0x04, 0x76, 0x14, 0xc3, 0x69, 0x13, 0x23, 0x31, 0x7a, 0x1f, 0x5d, 0x11, 0x48, 0xf9, 0xe2, 0x33, 0x79, 0x29, 0x2f, 0x1d, 0x0a, 0x90, 0x23, 0x26, 0x05, 0xb8, 0x3c, 0x2b, 0x2a, 0x6c, 0x02, 0xe1, 0xe8, 0x56, 0x23, 0x1b, 0x6d, 0x31, 0x34, 0x17, 0x48, 0x1a, 0x65, 0x09, 0xae, 0x27, 0x31, 0x6c, 0x31, 0x04, 0x04, 0x0c, 0x93, 0x5a, 0x08, 0x2b, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x06, 0x1b, 0x05, 0xd5, 0x00, 0x3f, 0x00, 0x00, 0x01, 0x33, 0x17, 0x15, 0x33, 0x20, 0x13, 0x16, 0x1d, 0x01, 0x23, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x22, 0x07, 0x15, 0x14, 0x07, 0x27, 0x26, 0x23, 0x11, 0x14, 0x0f, 0x01, 0x22, 0x2f, 0x01, 0x35, 0x37, 0x33, 0x17, 0x15, 0x16, 0x3b, 0x01, 0x32, 0x3f, 0x01, 0x11, 0x22, 0x07, 0x06, 0x23, 0x27, 0x35, 0x37, 0x23, 0x26, 0x27, 0x23, 0x22, 0x0f, 0x01, 0x23, 0x35, 0x36, 0x37, 0x36, 0x21, 0x35, 0x03, 0x30, 0x34, 0x06, 0x02, 0x01, 0x8c, 0xfc, 0x26, 0x01, 0x14, 0x11, 0x20, 0x33, 0x28, 0x87, 0x64, 0x08, 0x1d, 0x88, 0x7b, 0x5f, 0x1b, 0x52, 0x21, 0x02, 0x05, 0x27, 0x05, 0x09, 0x38, 0x09, 0x32, 0x12, 0x05, 0xbe, 0x4d, 0x10, 0x0c, 0x06, 0x06, 0x04, 0x3c, 0xb1, 0x3d, 0x59, 0x1e, 0x12, 0x03, 0x34, 0xad, 0xd7, 0x01, 0x19, 0x05, 0xd5, 0x06, 0x7d, 0xfe, 0x1a, 0x56, 0x0d, 0x08, 0x0f, 0x2e, 0x18, 0x65, 0x33, 0x0f, 0x02, 0x42, 0x3d, 0xfd, 0x53, 0x65, 0x18, 0x02, 0x60, 0x1c, 0x1a, 0x06, 0x06, 0x0c, 0x65, 0x39, 0x2a, 0x02, 0xa4, 0x3d, 0x39, 0x06, 0x0c, 0x33, 0x40, 0x1b, 0x3d, 0x12, 0x02, 0x90, 0xda, 0xdf, 0x7d, 0x00, 0x1a, 0x00, 0x99, 0xff, 0xff, 0x05, 0xdc, 0x07, 0x6b, 0x00, 0x0d, 0x00, 0x15, 0x00, 0x1d, 0x00, 0x25, 0x00, 0x43, 0x00, 0x60, 0x00, 0x8c, 0x00, 0xb7, 0x00, 0xe3, 0x01, 0x0e, 0x01, 0x3a, 0x01, 0x64, 0x01, 0x90, 0x01, 0xbb, 0x01, 0xe6, 0x02, 0x0f, 0x02, 0x3b, 0x02, 0x65, 0x02, 0x6d, 0x02, 0x75, 0x02, 0x7d, 0x02, 0xa9, 0x02, 0xd3, 0x02, 0xfd, 0x03, 0x27, 0x03, 0x53, 0x00, 0x00, 0x01, 0x16, 0x33, 0x32, 0x37, 0x33, 0x06, 0x07, 0x26, 0x27, 0x33, 0x16, 0x33, 0x32, 0x37, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x07, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x03, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x27, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x32, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x06, 0x13, 0x36, 0x37, 0x32, 0x1f, 0x01, 0x16, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x20, 0x24, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x34, 0x37, 0x01, 0x17, 0x27, 0x26, 0x33, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x01, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x05, 0x17, 0x27, 0x26, 0x33, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x13, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x01, 0x17, 0x27, 0x26, 0x33, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x14, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x01, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x14, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x05, 0x17, 0x27, 0x34, 0x33, 0x32, 0x15, 0x07, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x03, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x05, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x1f, 0x01, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x14, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x37, 0x17, 0x27, 0x34, 0x33, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x37, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x13, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x05, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x17, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x01, 0x17, 0x27, 0x26, 0x33, 0x32, 0x15, 0x07, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x01, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x14, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x05, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x01, 0x17, 0x27, 0x26, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x01, 0x17, 0x27, 0x26, 0x33, 0x32, 0x0f, 0x01, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x2f, 0x01, 0x17, 0x16, 0x23, 0x22, 0x35, 0x37, 0x07, 0x06, 0x23, 0x22, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x03, 0x96, 0x07, 0x07, 0x3c, 0x16, 0x17, 0x05, 0x73, 0x71, 0x08, 0x15, 0x21, 0x36, 0x07, 0x6e, 0x26, 0x01, 0x03, 0x26, 0x23, 0x03, 0x03, 0xf9, 0x25, 0x02, 0x02, 0x27, 0x24, 0x03, 0x03, 0x3a, 0x22, 0x02, 0x03, 0x23, 0x21, 0x01, 0x01, 0xb6, 0x70, 0xde, 0x9e, 0x9c, 0xe0, 0x70, 0x5b, 0x7d, 0x02, 0x03, 0x36, 0x28, 0x3b, 0x71, 0x54, 0x52, 0x7d, 0x3c, 0x28, 0x32, 0x82, 0x13, 0x17, 0x85, 0x77, 0x2c, 0x02, 0x4a, 0x44, 0x12, 0x16, 0x64, 0x4e, 0x80, 0xff, 0xfe, 0x92, 0xff, 0x00, 0x80, 0x53, 0x6a, 0x12, 0x12, 0x44, 0x44, 0xfd, 0xe5, 0x25, 0x05, 0x01, 0x0d, 0x10, 0x02, 0x05, 0x24, 0x03, 0x04, 0x0e, 0x07, 0x2b, 0x2a, 0x08, 0x0e, 0x04, 0x03, 0x24, 0x05, 0x01, 0x0f, 0x0c, 0x04, 0x24, 0x02, 0x05, 0x0c, 0x08, 0x29, 0x2c, 0x06, 0x0d, 0x05, 0x01, 0x0a, 0x21, 0x05, 0x02, 0x1b, 0x02, 0x05, 0x21, 0x04, 0x03, 0x0d, 0x06, 0x28, 0x26, 0x06, 0x0b, 0x04, 0x03, 0x1f, 0x03, 0x01, 0x0c, 0x0c, 0x04, 0x20, 0x03, 0x03, 0x0c, 0x07, 0x25, 0x26, 0x07, 0x0d, 0x03, 0x03, 0x0f, 0x21, 0x05, 0x02, 0x0d, 0x0e, 0x01, 0x06, 0x21, 0x03, 0x05, 0x0b, 0x06, 0x27, 0x25, 0x07, 0x0a, 0x06, 0x02, 0x20, 0x05, 0x01, 0x0e, 0x0b, 0x04, 0x20, 0x03, 0x03, 0x0d, 0x08, 0x25, 0x26, 0x07, 0x0d, 0x03, 0x5c, 0x21, 0x06, 0x01, 0x1b, 0x02, 0x06, 0x22, 0x03, 0x04, 0x0c, 0x06, 0x27, 0x25, 0x07, 0x0b, 0x06, 0x01, 0x21, 0x05, 0x01, 0x0d, 0x0c, 0x05, 0x20, 0x03, 0x04, 0x0b, 0x07, 0x25, 0x26, 0x07, 0x0c, 0x04, 0xfc, 0x37, 0x11, 0x02, 0x01, 0x06, 0x07, 0x01, 0x02, 0x12, 0x01, 0x01, 0x08, 0x03, 0x16, 0x15, 0x04, 0x08, 0x01, 0x01, 0x11, 0x01, 0x06, 0x05, 0x02, 0x11, 0x02, 0x03, 0x05, 0x03, 0x15, 0x16, 0x02, 0x07, 0x01, 0x02, 0xc8, 0x12, 0x02, 0x01, 0x10, 0x01, 0x03, 0x13, 0x02, 0x02, 0x08, 0x04, 0x17, 0x16, 0x04, 0x07, 0x02, 0x02, 0x13, 0x03, 0x0e, 0x02, 0x12, 0x02, 0x02, 0x07, 0x03, 0x17, 0x17, 0x04, 0x08, 0x02, 0xfd, 0x0e, 0x12, 0x04, 0x06, 0x08, 0x04, 0x11, 0x03, 0x02, 0x07, 0x05, 0x14, 0x14, 0x04, 0x06, 0x02, 0x03, 0x11, 0x03, 0x01, 0x08, 0x06, 0x04, 0x12, 0x02, 0x02, 0x06, 0x03, 0x14, 0x14, 0x04, 0x07, 0x02, 0x53, 0x12, 0x04, 0x01, 0x0f, 0x01, 0x03, 0x11, 0x03, 0x02, 0x06, 0x03, 0x15, 0x14, 0x04, 0x06, 0x02, 0x03, 0x11, 0x03, 0x01, 0x07, 0x07, 0x03, 0x11, 0x02, 0x02, 0x07, 0x05, 0x13, 0x13, 0x05, 0x07, 0x02, 0x01, 0x00, 0x11, 0x02, 0x01, 0x0f, 0x01, 0x03, 0x11, 0x01, 0x03, 0x07, 0x04, 0x14, 0x13, 0x05, 0x07, 0x03, 0x01, 0x11, 0x03, 0x01, 0x08, 0x06, 0x02, 0x11, 0x02, 0x01, 0x07, 0x04, 0x14, 0x15, 0x03, 0x07, 0x01, 0x64, 0x11, 0x02, 0x02, 0x0f, 0x01, 0x03, 0x12, 0x01, 0x02, 0x07, 0x03, 0x15, 0x15, 0x03, 0x07, 0x02, 0x01, 0x11, 0x02, 0x06, 0x06, 0x02, 0x11, 0x02, 0x03, 0x05, 0x04, 0x13, 0x14, 0x03, 0x05, 0x03, 0xde, 0x13, 0x02, 0x06, 0x08, 0x01, 0x03, 0x14, 0x01, 0x04, 0x07, 0x05, 0x17, 0x16, 0x06, 0x07, 0x04, 0x02, 0x12, 0x02, 0x01, 0x08, 0x06, 0x02, 0x13, 0x02, 0x02, 0x07, 0x04, 0x16, 0x17, 0x03, 0x07, 0x02, 0x52, 0x13, 0x02, 0x01, 0x10, 0x01, 0x04, 0x14, 0x02, 0x02, 0x07, 0x03, 0x17, 0x16, 0x04, 0x07, 0x02, 0x02, 0x14, 0x03, 0x01, 0x0e, 0x02, 0x13, 0x01, 0x03, 0x07, 0x04, 0x17, 0x18, 0x03, 0x08, 0x02, 0x9c, 0x21, 0x02, 0x02, 0x25, 0x1f, 0x03, 0x03, 0xfe, 0xd8, 0x22, 0x02, 0x03, 0x23, 0x21, 0x01, 0x01, 0xe3, 0x22, 0x02, 0x02, 0x25, 0x1f, 0x03, 0x03, 0x01, 0x3d, 0x20, 0x05, 0x01, 0x0d, 0x0d, 0x06, 0x20, 0x03, 0x05, 0x0b, 0x06, 0x26, 0x25, 0x07, 0x0b, 0x05, 0x03, 0x20, 0x04, 0x02, 0x0d, 0x0c, 0x05, 0x20, 0x03, 0x04, 0x0d, 0x08, 0x26, 0x27, 0x07, 0x0d, 0x04, 0xfc, 0xb3, 0x12, 0x02, 0x01, 0x10, 0x01, 0x04, 0x13, 0x03, 0x02, 0x08, 0x04, 0x17, 0x16, 0x04, 0x07, 0x02, 0x03, 0x13, 0x04, 0x0e, 0x02, 0x12, 0x02, 0x02, 0x07, 0x03, 0x17, 0x18, 0x03, 0x08, 0x02, 0xfe, 0x7c, 0x14, 0x03, 0x01, 0x10, 0x01, 0x02, 0x13, 0x01, 0x02, 0x07, 0x02, 0x18, 0x17, 0x03, 0x07, 0x02, 0x01, 0x13, 0x01, 0x01, 0x0e, 0x03, 0x14, 0x01, 0x02, 0x08, 0x05, 0x16, 0x17, 0x04, 0x08, 0x02, 0x03, 0xc5, 0x14, 0x03, 0x01, 0x10, 0x01, 0x03, 0x13, 0x02, 0x02, 0x07, 0x02, 0x18, 0x17, 0x03, 0x07, 0x02, 0x02, 0x13, 0x02, 0x01, 0x0e, 0x03, 0x14, 0x01, 0x03, 0x07, 0x05, 0x16, 0x17, 0x04, 0x08, 0x02, 0xfc, 0xa4, 0x22, 0x05, 0x02, 0x0d, 0x0e, 0x02, 0x05, 0x21, 0x03, 0x05, 0x0b, 0x06, 0x27, 0x25, 0x07, 0x0a, 0x06, 0x02, 0x20, 0x04, 0x01, 0x0d, 0x0b, 0x04, 0x21, 0x02, 0x03, 0x0d, 0x07, 0x26, 0x26, 0x08, 0x0e, 0x03, 0x03, 0x89, 0x01, 0x26, 0x45, 0x05, 0x07, 0x43, 0x26, 0x56, 0x02, 0x2a, 0x2c, 0x03, 0x03, 0x29, 0x2d, 0x04, 0x02, 0x29, 0x2d, 0x03, 0x03, 0x2a, 0x2c, 0xfe, 0x12, 0x02, 0x25, 0x26, 0x02, 0x02, 0x25, 0x26, 0x9e, 0x66, 0x93, 0x91, 0xd0, 0xd0, 0x91, 0x93, 0x66, 0x55, 0x20, 0x33, 0x48, 0x68, 0x66, 0x65, 0x65, 0x66, 0x68, 0x48, 0x32, 0x1e, 0x01, 0xd9, 0x70, 0x18, 0x75, 0x13, 0x5e, 0xe8, 0x51, 0x18, 0x10, 0x1c, 0x46, 0x73, 0xa5, 0xa3, 0xe6, 0xe6, 0xa3, 0xa5, 0x73, 0x4b, 0x1a, 0x0f, 0x16, 0x51, 0xe8, 0x47, 0xfd, 0x68, 0x21, 0x39, 0x0f, 0x0f, 0x39, 0x21, 0x04, 0x11, 0x0b, 0x03, 0x15, 0x16, 0x03, 0x0c, 0x0f, 0x02, 0x21, 0x37, 0x10, 0x10, 0x37, 0x21, 0x02, 0x0f, 0x0c, 0x03, 0x16, 0x15, 0x03, 0x0b, 0x11, 0x01, 0xd1, 0x1f, 0x34, 0x0d, 0x0d, 0x34, 0x1f, 0x03, 0x10, 0x07, 0x05, 0x14, 0x13, 0x03, 0x09, 0x0e, 0x02, 0x1e, 0x32, 0x0f, 0x0f, 0x32, 0x1e, 0x02, 0x0e, 0x09, 0x03, 0x13, 0x14, 0x05, 0x07, 0x10, 0x4b, 0x1f, 0x34, 0x0e, 0x0e, 0x34, 0x1f, 0x03, 0x10, 0x07, 0x03, 0x15, 0x13, 0x04, 0x09, 0x0e, 0x02, 0x1e, 0x32, 0x0e, 0x0e, 0x32, 0x1e, 0x02, 0x0e, 0x09, 0x04, 0x13, 0x15, 0x03, 0x07, 0x10, 0x01, 0x1b, 0x1e, 0x32, 0x0e, 0x0e, 0x32, 0x1e, 0x02, 0x0e, 0x09, 0x04, 0x13, 0x14, 0x03, 0x09, 0x0f, 0x03, 0x1d, 0x31, 0x0e, 0x0e, 0x31, 0x1d, 0x03, 0x0f, 0x09, 0x03, 0x14, 0x13, 0x04, 0x09, 0x0e, 0x02, 0x9a, 0x10, 0x1c, 0x06, 0x06, 0x1c, 0x10, 0x01, 0x07, 0x06, 0x02, 0x09, 0x0b, 0x02, 0x04, 0x08, 0x02, 0x0e, 0x19, 0x07, 0x07, 0x19, 0x0e, 0x02, 0x08, 0x04, 0x02, 0x0b, 0x09, 0x02, 0x06, 0x07, 0xfe, 0xe3, 0x11, 0x1d, 0x0a, 0x0a, 0x1d, 0x11, 0x03, 0x0a, 0x05, 0x01, 0x0d, 0x0a, 0x03, 0x06, 0x07, 0x01, 0x11, 0x1e, 0x07, 0x07, 0x1e, 0x11, 0x01, 0x07, 0x06, 0x03, 0x0a, 0x0d, 0x01, 0x05, 0x0a, 0xa8, 0x10, 0x1c, 0x07, 0x07, 0x1c, 0x10, 0x02, 0x07, 0x06, 0x02, 0x09, 0x0b, 0x02, 0x05, 0x08, 0x02, 0x0f, 0x1a, 0x08, 0x08, 0x1a, 0x0f, 0x02, 0x08, 0x05, 0x02, 0x0b, 0x09, 0x02, 0x06, 0x07, 0x01, 0x18, 0x10, 0x1c, 0x06, 0x06, 0x1c, 0x10, 0x02, 0x08, 0x04, 0x03, 0x0a, 0x0a, 0x02, 0x05, 0x07, 0x01, 0x0f, 0x19, 0x08, 0x08, 0x19, 0x0f, 0x01, 0x07, 0x05, 0x02, 0x0a, 0x0a, 0x03, 0x04, 0x08, 0x18, 0x0f, 0x1b, 0x07, 0x07, 0x1b, 0x0f, 0x02, 0x08, 0x05, 0x01, 0x0a, 0x0b, 0x01, 0x06, 0x07, 0x01, 0x10, 0x1b, 0x08, 0x08, 0x1b, 0x10, 0x01, 0x07, 0x06, 0x01, 0x0b, 0x0a, 0x01, 0x06, 0x07, 0xa1, 0x0f, 0x1b, 0x07, 0x07, 0x1b, 0x0f, 0x01, 0x07, 0x04, 0x01, 0x0c, 0x0a, 0x01, 0x0c, 0x01, 0x0f, 0x1b, 0x07, 0x07, 0x1b, 0x0f, 0x01, 0x0c, 0x01, 0x0a, 0x0c, 0x01, 0x04, 0x07, 0x37, 0x12, 0x1f, 0x07, 0x07, 0x1f, 0x12, 0x01, 0x08, 0x05, 0x02, 0x0c, 0x0c, 0x02, 0x05, 0x08, 0x01, 0x12, 0x1d, 0x0a, 0x0a, 0x1d, 0x12, 0x01, 0x08, 0x05, 0x02, 0x0c, 0x0c, 0x02, 0x05, 0x08, 0xd9, 0x12, 0x1f, 0x07, 0x07, 0x1f, 0x12, 0x01, 0x08, 0x05, 0x02, 0x0b, 0x0c, 0x02, 0x05, 0x0a, 0x03, 0x10, 0x1c, 0x09, 0x09, 0x1c, 0x10, 0x03, 0x0a, 0x05, 0x02, 0x0c, 0x0b, 0x02, 0x06, 0x07, 0xfa, 0xe0, 0x02, 0x25, 0x26, 0x02, 0x02, 0x25, 0x26, 0xe2, 0x02, 0x25, 0x27, 0x02, 0x03, 0x25, 0x26, 0x02, 0x02, 0x25, 0x27, 0x02, 0x03, 0x25, 0x26, 0x01, 0x81, 0x1d, 0x32, 0x0e, 0x0e, 0x32, 0x1d, 0x03, 0x0f, 0x09, 0x03, 0x13, 0x14, 0x03, 0x0a, 0x0e, 0x04, 0x1b, 0x2f, 0x0f, 0x0f, 0x2f, 0x1b, 0x04, 0x0e, 0x0a, 0x03, 0x14, 0x13, 0x03, 0x09, 0x0f, 0x02, 0x67, 0x12, 0x1e, 0x08, 0x08, 0x1e, 0x12, 0x01, 0x0a, 0x04, 0x02, 0x0b, 0x0c, 0x02, 0x06, 0x08, 0x02, 0x11, 0x1d, 0x09, 0x09, 0x1d, 0x11, 0x02, 0x08, 0x06, 0x02, 0x0c, 0x0b, 0x02, 0x04, 0x0a, 0xfb, 0x12, 0x1f, 0x07, 0x07, 0x1f, 0x12, 0x01, 0x08, 0x05, 0x03, 0x0b, 0x0c, 0x02, 0x05, 0x09, 0x01, 0x12, 0x1c, 0x0a, 0x0a, 0x1c, 0x12, 0x01, 0x09, 0x05, 0x02, 0x0c, 0x0b, 0x03, 0x05, 0x08, 0x01, 0x82, 0x11, 0x1e, 0x08, 0x08, 0x1e, 0x11, 0x02, 0x08, 0x07, 0x01, 0x0b, 0x0c, 0x02, 0x05, 0x09, 0x01, 0x11, 0x1c, 0x09, 0x09, 0x1c, 0x11, 0x01, 0x09, 0x05, 0x02, 0x0c, 0x0b, 0x01, 0x07, 0x08, 0xfd, 0x7f, 0x1f, 0x34, 0x0e, 0x0e, 0x34, 0x1f, 0x03, 0x10, 0x07, 0x04, 0x14, 0x13, 0x03, 0x0a, 0x0e, 0x03, 0x1d, 0x32, 0x0e, 0x0e, 0x32, 0x1d, 0x03, 0x0e, 0x0a, 0x03, 0x13, 0x14, 0x04, 0x07, 0x10, 0x00, 0x0f, 0x00, 0x75, 0x00, 0x00, 0x05, 0xff, 0x07, 0x0b, 0x00, 0x17, 0x00, 0x2d, 0x00, 0x3e, 0x00, 0x4f, 0x00, 0x60, 0x00, 0x71, 0x00, 0x82, 0x00, 0x93, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xc6, 0x00, 0xd7, 0x00, 0xe8, 0x00, 0xf9, 0x01, 0x0a, 0x00, 0x00, 0x01, 0x16, 0x15, 0x14, 0x07, 0x06, 0x0f, 0x01, 0x06, 0x2b, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x3f, 0x02, 0x36, 0x33, 0x32, 0x33, 0x16, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x33, 0x32, 0x3f, 0x01, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x26, 0x23, 0x22, 0x07, 0x13, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x13, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x13, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x13, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x13, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x3d, 0x01, 0x34, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x01, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x13, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x01, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x25, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x36, 0x02, 0x0a, 0x29, 0x17, 0x12, 0x2d, 0x13, 0x56, 0x6f, 0x14, 0x2f, 0x22, 0x2a, 0x36, 0x25, 0x0b, 0x5a, 0x7b, 0x03, 0x03, 0x38, 0xec, 0x47, 0x08, 0x05, 0x0c, 0x0d, 0x1b, 0x27, 0x2f, 0x41, 0x2e, 0x4a, 0x04, 0x1d, 0x1c, 0x2c, 0x31, 0x44, 0xdf, 0x1a, 0x0d, 0x07, 0x18, 0x0a, 0x0b, 0x21, 0x0b, 0x01, 0x17, 0x0c, 0x97, 0x1a, 0x0d, 0x07, 0x18, 0x09, 0x0c, 0x21, 0x0b, 0x01, 0x17, 0x0c, 0x7c, 0x19, 0x0e, 0x06, 0x17, 0x09, 0x0d, 0x1f, 0x0d, 0x01, 0x17, 0x0c, 0x8c, 0x19, 0x0d, 0x07, 0x18, 0x09, 0x0c, 0x20, 0x0c, 0x01, 0x17, 0x0c, 0x02, 0x1a, 0x0d, 0x07, 0x18, 0x09, 0x0d, 0x1f, 0x0d, 0x17, 0x0c, 0xab, 0x1b, 0x0d, 0x06, 0x17, 0x0a, 0x0c, 0x20, 0x0c, 0x01, 0x18, 0x0c, 0x01, 0x62, 0x19, 0x0e, 0x06, 0x17, 0x09, 0x0d, 0x1f, 0x0d, 0x01, 0x17, 0x0c, 0xaf, 0x1a, 0x0d, 0x07, 0x18, 0x0a, 0x0b, 0x21, 0x0b, 0x01, 0x17, 0x0c, 0xae, 0x1a, 0x0e, 0x06, 0x17, 0x0a, 0x0c, 0x20, 0x0c, 0x01, 0x18, 0x0b, 0xfd, 0x9a, 0x1a, 0x0d, 0x07, 0x18, 0x0a, 0x0b, 0x21, 0x0b, 0x01, 0x17, 0x0c, 0xf6, 0x1a, 0x0d, 0x06, 0x17, 0x09, 0x0d, 0x1f, 0x0d, 0x01, 0x18, 0x0b, 0x01, 0x05, 0x1b, 0x0d, 0x06, 0x17, 0x0a, 0x0c, 0x20, 0x0c, 0x01, 0x18, 0x0b, 0xea, 0x19, 0x0d, 0x06, 0x17, 0x09, 0x0c, 0x20, 0x0d, 0x01, 0x18, 0x0c, 0x02, 0x20, 0x37, 0x51, 0x3d, 0x4b, 0x47, 0x3c, 0x1a, 0x73, 0x07, 0x2d, 0x38, 0x50, 0x5a, 0x79, 0x39, 0x0e, 0x7a, 0x0c, 0x80, 0x5f, 0x65, 0x22, 0x22, 0x16, 0x10, 0x12, 0x23, 0x2f, 0x32, 0x64, 0x74, 0x1a, 0x1b, 0x30, 0x26, 0x32, 0x01, 0x6a, 0x1f, 0x0c, 0x0f, 0x06, 0x1f, 0x12, 0x07, 0x2c, 0x0e, 0x03, 0x1f, 0x14, 0x08, 0x01, 0x3a, 0x1e, 0x0c, 0x0f, 0x07, 0x1e, 0x13, 0x08, 0x2e, 0x0c, 0x05, 0x1e, 0x14, 0x08, 0x01, 0x34, 0x1f, 0x0c, 0x0e, 0x07, 0x1e, 0x14, 0x07, 0x2e, 0x0c, 0x05, 0x1e, 0x14, 0x08, 0x01, 0x3d, 0x1f, 0x0c, 0x0f, 0x06, 0x1f, 0x12, 0x07, 0x2c, 0x0d, 0x04, 0x1f, 0x14, 0x08, 0xfd, 0x02, 0x1f, 0x0c, 0x0f, 0x06, 0x1f, 0x12, 0x07, 0x2c, 0x0e, 0x03, 0x20, 0x13, 0x08, 0xfe, 0xfc, 0x1f, 0x0c, 0x0e, 0x06, 0x20, 0x12, 0x07, 0x2d, 0x0d, 0x04, 0x1f, 0x13, 0x08, 0x02, 0x07, 0x1e, 0x0c, 0x0f, 0x07, 0x1e, 0x13, 0x07, 0x2d, 0x0c, 0x05, 0x1e, 0x15, 0x07, 0xfa, 0x1e, 0x0c, 0x0f, 0x07, 0x1e, 0x13, 0x07, 0x2d, 0x0c, 0x05, 0x1e, 0x15, 0x07, 0x01, 0x04, 0x20, 0x0c, 0x0e, 0x06, 0x1f, 0x12, 0x08, 0x2d, 0x0d, 0x04, 0x1f, 0x13, 0x09, 0xfb, 0x0c, 0x1e, 0x0c, 0x0f, 0x07, 0x1e, 0x13, 0x08, 0x2e, 0x0c, 0x05, 0x1e, 0x14, 0x08, 0xd3, 0x1e, 0x0c, 0x0e, 0x07, 0x1e, 0x14, 0x07, 0x2e, 0x0c, 0x05, 0x1e, 0x14, 0x07, 0xe7, 0x1f, 0x0c, 0x0e, 0x06, 0x20, 0x12, 0x07, 0x2c, 0x0e, 0x03, 0x20, 0x13, 0x08, 0xca, 0x1f, 0x0c, 0x0e, 0x06, 0x20, 0x12, 0x07, 0x2d, 0x0d, 0x03, 0x20, 0x13, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x77, 0xff, 0xf7, 0x05, 0xfd, 0x05, 0xc9, 0x00, 0x09, 0x00, 0x00, 0x13, 0x21, 0x1b, 0x01, 0x21, 0x01, 0x13, 0x09, 0x01, 0x13, 0x78, 0x02, 0x1b, 0xa7, 0xa8, 0x02, 0x1b, 0xfe, 0x4c, 0xa7, 0xfe, 0x4a, 0xfe, 0x4b, 0xa6, 0x03, 0x90, 0x02, 0x39, 0xfd, 0xc7, 0xfe, 0x9f, 0xfd, 0xc8, 0x01, 0x60, 0xfe, 0xa0, 0x02, 0x38, 0x00, 0x00, 0x02, 0x00, 0x77, 0xff, 0xf7, 0x05, 0xfd, 0x05, 0xc9, 0x00, 0x09, 0x00, 0x13, 0x00, 0x00, 0x13, 0x21, 0x1b, 0x01, 0x21, 0x01, 0x13, 0x09, 0x01, 0x13, 0x37, 0x03, 0x09, 0x01, 0x03, 0x01, 0x21, 0x0b, 0x01, 0x21, 0x78, 0x02, 0x1b, 0xa7, 0xa8, 0x02, 0x1b, 0xfe, 0x4c, 0xa7, 0xfe, 0x4a, 0xfe, 0x4b, 0xa6, 0x3d, 0x7e, 0x01, 0x50, 0x01, 0x5a, 0x89, 0x01, 0x67, 0xfe, 0x4b, 0x83, 0x80, 0xfe, 0x49, 0x03, 0x90, 0x02, 0x39, 0xfd, 0xc7, 0xfe, 0x9f, 0xfd, 0xc8, 0x01, 0x60, 0xfe, 0xa0, 0x02, 0x38, 0x15, 0xfe, 0x4e, 0x01, 0x0c, 0xfe, 0xe6, 0x01, 0xc2, 0x01, 0x18, 0x01, 0xb7, 0xfe, 0x49, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x99, 0x00, 0x04, 0x03, 0x87, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x01, 0x16, 0x17, 0x14, 0x07, 0x09, 0x01, 0x37, 0x13, 0x25, 0x37, 0x01, 0x26, 0x35, 0x34, 0x37, 0x01, 0x36, 0x03, 0x52, 0x33, 0x02, 0x08, 0xfd, 0xbd, 0x01, 0xbc, 0x4e, 0x22, 0xfe, 0x65, 0xc9, 0xfe, 0x14, 0x11, 0x3b, 0x02, 0x51, 0x09, 0x05, 0xd5, 0x02, 0x36, 0x24, 0x0c, 0xfd, 0x85, 0xfd, 0xf4, 0xe6, 0xfe, 0x38, 0x27, 0x5e, 0x02, 0x34, 0x17, 0x17, 0x1b, 0x3f, 0x02, 0x86, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdb, 0x05, 0xd9, 0x00, 0x19, 0x00, 0x00, 0x13, 0x21, 0x32, 0x15, 0x14, 0x07, 0x09, 0x01, 0x37, 0x13, 0x25, 0x37, 0x01, 0x26, 0x35, 0x34, 0x37, 0x01, 0x21, 0x11, 0x06, 0x07, 0x26, 0x27, 0x11, 0x36, 0xd5, 0x04, 0xc2, 0x3a, 0x19, 0xfd, 0xfb, 0x01, 0xb6, 0x50, 0x21, 0xfe, 0x60, 0xd0, 0xfe, 0x24, 0x0e, 0x2f, 0x01, 0xb4, 0xfc, 0x18, 0x01, 0x41, 0x3f, 0x01, 0x01, 0x05, 0xd9, 0x53, 0x22, 0x1b, 0xfd, 0xc5, 0xfe, 0x1b, 0xd5, 0xfe, 0x3d, 0x22, 0x6c, 0x02, 0x16, 0x10, 0x2d, 0x1c, 0x32, 0x01, 0xdf, 0xfa, 0xfc, 0x44, 0x01, 0x01, 0x43, 0x05, 0x5b, 0x39, 0x00, 0x00, 0x00, 0x03, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd8, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x26, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x10, 0x00, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x20, 0x04, 0x02, 0x05, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x32, 0x1e, 0x01, 0x05, 0xdb, 0xfe, 0x76, 0xfe, 0xe8, 0xfe, 0xea, 0xfe, 0x76, 0xb5, 0x01, 0x44, 0xa7, 0xaa, 0x01, 0x44, 0xb4, 0xfb, 0x00, 0x01, 0x62, 0x01, 0xf8, 0x01, 0x63, 0xa2, 0xfe, 0xdc, 0xfe, 0xce, 0xfe, 0xdd, 0xa2, 0x03, 0x07, 0x62, 0x46, 0x45, 0x63, 0x2d, 0x51, 0x54, 0x52, 0x2c, 0x02, 0xec, 0xfe, 0xc9, 0xfe, 0x4b, 0x01, 0xb5, 0x01, 0x37, 0xc2, 0x01, 0x69, 0xc1, 0xc1, 0xfe, 0x99, 0xc4, 0xfe, 0xe8, 0xfe, 0x77, 0x01, 0x89, 0x01, 0x18, 0xb1, 0x01, 0x42, 0xae, 0xae, 0xfe, 0xbe, 0xb1, 0x4e, 0x6d, 0x6d, 0x4e, 0x31, 0x5a, 0x30, 0x30, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x70, 0x00, 0x00, 0x05, 0xf6, 0x05, 0xd1, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x43, 0x00, 0x00, 0x00, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x25, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x25, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x24, 0x20, 0x04, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x10, 0x06, 0x23, 0x22, 0x26, 0x10, 0x37, 0x36, 0x37, 0x26, 0x35, 0x34, 0x00, 0x21, 0x20, 0x00, 0x15, 0x14, 0x05, 0x1f, 0x85, 0x5d, 0x5d, 0x43, 0x41, 0x5e, 0xfc, 0x0c, 0x41, 0x5e, 0x5e, 0x41, 0x43, 0x5d, 0x5d, 0x03, 0xae, 0x17, 0x14, 0x52, 0xa4, 0x75, 0x74, 0xa4, 0x51, 0x49, 0x64, 0x6d, 0xfe, 0xd2, 0xfe, 0x50, 0xfe, 0xd2, 0x6d, 0x71, 0x4e, 0x51, 0xa4, 0x75, 0x73, 0xa5, 0x52, 0x11, 0x11, 0x6e, 0x01, 0x93, 0x01, 0x21, 0x01, 0x24, 0x01, 0x93, 0x01, 0xe9, 0x67, 0x4a, 0x49, 0x67, 0x67, 0x49, 0x4a, 0x67, 0x67, 0x4a, 0x49, 0x68, 0x68, 0x49, 0x4a, 0x67, 0x55, 0x11, 0x16, 0x5c, 0x82, 0x81, 0xb7, 0xb7, 0x81, 0x82, 0x5c, 0x51, 0x09, 0x73, 0x99, 0xb4, 0xfd, 0xfd, 0xb4, 0x99, 0x72, 0x04, 0x57, 0x5c, 0xfe, 0xfc, 0xb7, 0xb7, 0x01, 0x04, 0x5c, 0x11, 0x0f, 0x8e, 0xb6, 0xf8, 0x01, 0x5e, 0xfe, 0xa2, 0xf8, 0xb1, 0x00, 0x00, 0x00, 0x03, 0x00, 0x70, 0x00, 0x00, 0x05, 0xf6, 0x05, 0xc9, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x41, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x32, 0x36, 0x25, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x01, 0x14, 0x00, 0x21, 0x20, 0x00, 0x35, 0x34, 0x37, 0x26, 0x27, 0x26, 0x10, 0x36, 0x33, 0x32, 0x16, 0x10, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x04, 0x20, 0x24, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x10, 0x36, 0x33, 0x32, 0x16, 0x10, 0x07, 0x06, 0x07, 0x16, 0x05, 0x7c, 0x5e, 0x41, 0x43, 0x5d, 0x5d, 0x85, 0x5d, 0xfc, 0xac, 0x5d, 0x43, 0x41, 0x5e, 0x5e, 0x41, 0x43, 0x5d, 0x03, 0xb9, 0xfe, 0x6d, 0xfe, 0xdc, 0xfe, 0xdf, 0xfe, 0x6d, 0x6e, 0x11, 0x11, 0x52, 0xa5, 0x73, 0x75, 0xa4, 0x51, 0x4e, 0x71, 0x6d, 0x01, 0x2e, 0x01, 0xb0, 0x01, 0x2e, 0x6d, 0x64, 0x49, 0x51, 0xa4, 0x74, 0x75, 0xa4, 0x52, 0x14, 0x17, 0x68, 0x04, 0x91, 0x49, 0x68, 0x68, 0x49, 0x4a, 0x67, 0x67, 0x4a, 0x4a, 0x67, 0x67, 0x4a, 0x49, 0x67, 0x67, 0xfe, 0x0c, 0xf7, 0xfe, 0xa3, 0x01, 0x5d, 0xf7, 0xb4, 0x8d, 0x0f, 0x12, 0x5b, 0x01, 0x02, 0xb6, 0xb6, 0xfe, 0xfe, 0x5b, 0x58, 0x03, 0x72, 0x97, 0xb4, 0xfb, 0xfb, 0xb4, 0x98, 0x71, 0x09, 0x51, 0x5c, 0x01, 0x02, 0xb6, 0xb6, 0xfe, 0xfe, 0x5c, 0x16, 0x11, 0x8b, 0x00, 0x00, 0x02, 0x00, 0x70, 0xff, 0xfd, 0x04, 0x65, 0x05, 0xc6, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x37, 0x16, 0x17, 0x16, 0x10, 0x00, 0x23, 0x22, 0x00, 0x10, 0x00, 0x33, 0x32, 0x17, 0x13, 0x17, 0x02, 0x45, 0x80, 0xb5, 0xb5, 0x80, 0x80, 0xb5, 0xb3, 0xab, 0x11, 0x10, 0x89, 0xfe, 0xed, 0xc4, 0xc1, 0xfe, 0xec, 0x01, 0x11, 0xc4, 0x57, 0x4b, 0xf3, 0x8b, 0x03, 0x5f, 0xc8, 0x90, 0x8e, 0xc9, 0xc9, 0x8e, 0x90, 0xc8, 0x3b, 0x10, 0x13, 0x99, 0xfe, 0x50, 0xfe, 0xcf, 0x01, 0x31, 0x01, 0xb0, 0x01, 0x32, 0x1d, 0x01, 0xd3, 0x59, 0x00, 0x00, 0x00, 0x03, 0x00, 0x70, 0x00, 0x01, 0x06, 0xdb, 0x05, 0xc9, 0x00, 0x08, 0x00, 0x11, 0x00, 0x31, 0x00, 0x00, 0x01, 0x22, 0x06, 0x14, 0x16, 0x32, 0x36, 0x34, 0x26, 0x00, 0x22, 0x06, 0x14, 0x16, 0x33, 0x32, 0x36, 0x34, 0x01, 0x16, 0x15, 0x14, 0x02, 0x23, 0x22, 0x02, 0x35, 0x34, 0x12, 0x33, 0x32, 0x17, 0x16, 0x17, 0x37, 0x26, 0x35, 0x34, 0x12, 0x33, 0x32, 0x12, 0x15, 0x14, 0x02, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0xfb, 0x6c, 0x98, 0x98, 0xd8, 0x98, 0x97, 0x03, 0x54, 0xda, 0x97, 0x97, 0x6d, 0x6c, 0x98, 0xfd, 0x11, 0x23, 0xe8, 0xa4, 0xa3, 0xe8, 0xe6, 0xa5, 0xa6, 0x73, 0x02, 0x02, 0xc6, 0x19, 0xe5, 0xa5, 0xa6, 0xe6, 0xe7, 0xa5, 0xa3, 0x74, 0x0a, 0x0a, 0x02, 0xda, 0xa9, 0xf0, 0xa9, 0xa9, 0xf0, 0xa9, 0x02, 0x5a, 0xa9, 0xf0, 0xa9, 0xa9, 0xf0, 0xfd, 0xe4, 0x54, 0x64, 0xb5, 0xfe, 0xff, 0x01, 0x01, 0xb5, 0xb7, 0x01, 0x01, 0x80, 0x03, 0x02, 0x89, 0x49, 0x55, 0xb7, 0x01, 0x01, 0xfe, 0xff, 0xb7, 0xb5, 0xfe, 0xff, 0x81, 0x0b, 0x0c, 0x00, 0x00, 0x0e, 0x00, 0x7e, 0x00, 0x00, 0x08, 0x7a, 0x05, 0xd5, 0x00, 0x23, 0x00, 0x35, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x59, 0x00, 0x65, 0x00, 0x72, 0x00, 0x80, 0x00, 0x8d, 0x00, 0x9a, 0x00, 0xa7, 0x00, 0xb5, 0x00, 0xc5, 0x00, 0xd9, 0x00, 0x00, 0x01, 0x33, 0x04, 0x17, 0x16, 0x15, 0x06, 0x23, 0x22, 0x27, 0x25, 0x26, 0x35, 0x34, 0x37, 0x36, 0x35, 0x34, 0x27, 0x21, 0x06, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x05, 0x06, 0x23, 0x22, 0x27, 0x34, 0x37, 0x36, 0x01, 0x35, 0x33, 0x15, 0x14, 0x17, 0x16, 0x19, 0x01, 0x21, 0x11, 0x10, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x05, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x27, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x11, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x02, 0x16, 0x06, 0x07, 0x06, 0x26, 0x27, 0x26, 0x36, 0x37, 0x36, 0x33, 0x32, 0x01, 0x16, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x26, 0x36, 0x37, 0x36, 0x16, 0x01, 0x1e, 0x01, 0x0e, 0x01, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x3e, 0x01, 0x04, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x24, 0x36, 0x16, 0x17, 0x16, 0x06, 0x07, 0x06, 0x26, 0x27, 0x26, 0x35, 0x34, 0x25, 0x36, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x07, 0x06, 0x26, 0x27, 0x26, 0x36, 0x01, 0x3e, 0x01, 0x17, 0x1e, 0x01, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x04, 0x78, 0x08, 0x02, 0x1f, 0xe7, 0xf4, 0x20, 0x5d, 0x06, 0x06, 0xfe, 0x92, 0x36, 0x0b, 0x3d, 0x1f, 0xfc, 0x0d, 0x1f, 0x3d, 0x0b, 0x37, 0xfe, 0x92, 0x07, 0x05, 0x5c, 0x21, 0xf5, 0xe6, 0x02, 0xf8, 0x81, 0xd9, 0xd0, 0xfa, 0x02, 0xd1, 0xd8, 0x82, 0x9a, 0xd4, 0x95, 0x97, 0xd3, 0xd2, 0x98, 0x96, 0xd3, 0x02, 0x34, 0x76, 0x55, 0x54, 0x76, 0x76, 0x54, 0x55, 0x76, 0x90, 0x1c, 0x16, 0x15, 0x1d, 0x1d, 0x15, 0x16, 0x1c, 0x1c, 0x16, 0x15, 0x1d, 0x1d, 0x15, 0x16, 0x1c, 0xbc, 0x18, 0x06, 0x11, 0x11, 0x29, 0x0d, 0x0c, 0x07, 0x11, 0x0d, 0x10, 0x04, 0x01, 0x72, 0x0d, 0x06, 0x12, 0x0d, 0x10, 0x04, 0x18, 0x0e, 0x0c, 0x07, 0x11, 0x11, 0x29, 0xfe, 0x3e, 0x16, 0x12, 0x0d, 0x26, 0x13, 0x14, 0x10, 0x02, 0x08, 0x25, 0x02, 0x1c, 0x27, 0x0f, 0x02, 0x08, 0x24, 0x14, 0x14, 0x13, 0x06, 0x08, 0xfd, 0xea, 0x27, 0x26, 0x07, 0x06, 0x12, 0x14, 0x15, 0x25, 0x08, 0x02, 0x02, 0x3f, 0x14, 0x24, 0x08, 0x02, 0x0f, 0x14, 0x13, 0x27, 0x06, 0x06, 0x13, 0xfe, 0x46, 0x0d, 0x29, 0x11, 0x11, 0x08, 0x0e, 0x0c, 0x19, 0x04, 0x10, 0x0d, 0x11, 0x05, 0x01, 0x57, 0x0e, 0x18, 0x04, 0x10, 0x0d, 0x12, 0x04, 0x0b, 0x0c, 0x18, 0x05, 0x10, 0x0d, 0x11, 0x04, 0x05, 0xd5, 0x11, 0x9b, 0xa4, 0xaa, 0x99, 0x01, 0x8c, 0x12, 0x2b, 0x13, 0x19, 0x47, 0x20, 0x17, 0x03, 0x03, 0x17, 0x20, 0x47, 0x18, 0x14, 0x2b, 0x12, 0x8c, 0x01, 0x99, 0xaa, 0xa4, 0x99, 0xfe, 0x76, 0x4b, 0x98, 0x4b, 0x39, 0x5f, 0xfe, 0xe2, 0xfe, 0x16, 0x01, 0xea, 0x01, 0x1e, 0x5f, 0x39, 0x4b, 0x98, 0x4b, 0xfd, 0xdd, 0xa7, 0xea, 0xea, 0xa7, 0xa6, 0xec, 0xec, 0xa5, 0x5d, 0x84, 0x84, 0x5d, 0x5f, 0x83, 0x83, 0xde, 0x16, 0x22, 0x22, 0x16, 0x18, 0x22, 0x22, 0xfd, 0x73, 0x18, 0x21, 0x21, 0x18, 0x17, 0x22, 0x22, 0x02, 0x57, 0x26, 0x2e, 0x0d, 0x0f, 0x07, 0x13, 0x14, 0x2d, 0x0f, 0x0a, 0xfd, 0xec, 0x13, 0x2e, 0x0f, 0x0a, 0x04, 0x14, 0x13, 0x2d, 0x0e, 0x0d, 0x06, 0x01, 0x61, 0x08, 0x29, 0x2c, 0x15, 0x06, 0x07, 0x22, 0x0d, 0x09, 0x09, 0x16, 0x15, 0xc3, 0x0e, 0x22, 0x0d, 0x08, 0x09, 0x16, 0x15, 0x08, 0x07, 0x29, 0x17, 0x16, 0x06, 0x0e, 0x14, 0x16, 0x18, 0x29, 0x08, 0x06, 0x15, 0x16, 0x09, 0x08, 0x0d, 0xec, 0x07, 0x15, 0x16, 0x09, 0x08, 0x0d, 0x21, 0x08, 0x07, 0x15, 0x16, 0x16, 0x29, 0xfe, 0x94, 0x12, 0x07, 0x0d, 0x0e, 0x2f, 0x11, 0x14, 0x04, 0x0a, 0x0f, 0x1c, 0x05, 0x11, 0x02, 0x0c, 0x13, 0x04, 0x0a, 0x0f, 0x1b, 0x04, 0x12, 0x10, 0x13, 0x04, 0x0c, 0x0d, 0x1c, 0x05, 0x11, 0x00, 0x10, 0x00, 0x82, 0x00, 0x00, 0x08, 0x7f, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x25, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x59, 0x00, 0x64, 0x00, 0x70, 0x00, 0x7c, 0x00, 0x88, 0x00, 0x94, 0x00, 0xa6, 0x00, 0xca, 0x00, 0xf0, 0x00, 0x00, 0x01, 0x35, 0x23, 0x15, 0x06, 0x07, 0x06, 0x15, 0x11, 0x21, 0x11, 0x34, 0x27, 0x26, 0x27, 0x35, 0x23, 0x15, 0x07, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x16, 0x22, 0x06, 0x14, 0x16, 0x32, 0x36, 0x34, 0x02, 0x22, 0x06, 0x14, 0x16, 0x32, 0x36, 0x34, 0x02, 0x22, 0x06, 0x14, 0x16, 0x32, 0x36, 0x34, 0x03, 0x0e, 0x01, 0x17, 0x1e, 0x01, 0x37, 0x3e, 0x01, 0x27, 0x2e, 0x01, 0x01, 0x0e, 0x01, 0x17, 0x1e, 0x01, 0x37, 0x3e, 0x01, 0x27, 0x2e, 0x01, 0x01, 0x06, 0x16, 0x17, 0x16, 0x36, 0x37, 0x36, 0x26, 0x27, 0x26, 0x06, 0x05, 0x06, 0x16, 0x17, 0x16, 0x3e, 0x01, 0x26, 0x27, 0x26, 0x06, 0x05, 0x1e, 0x01, 0x37, 0x3e, 0x01, 0x27, 0x2e, 0x01, 0x07, 0x0e, 0x01, 0x25, 0x1e, 0x01, 0x37, 0x3e, 0x01, 0x27, 0x2e, 0x01, 0x07, 0x0e, 0x01, 0x01, 0x16, 0x36, 0x37, 0x36, 0x26, 0x27, 0x26, 0x06, 0x07, 0x06, 0x16, 0x01, 0x16, 0x36, 0x37, 0x36, 0x26, 0x27, 0x26, 0x06, 0x07, 0x06, 0x16, 0x13, 0x35, 0x33, 0x15, 0x14, 0x17, 0x16, 0x19, 0x01, 0x21, 0x11, 0x10, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x25, 0x06, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x05, 0x23, 0x22, 0x27, 0x36, 0x37, 0x36, 0x25, 0x16, 0x32, 0x37, 0x04, 0x17, 0x16, 0x17, 0x06, 0x2b, 0x01, 0x25, 0x26, 0x35, 0x34, 0x37, 0x36, 0x35, 0x34, 0x27, 0x37, 0x16, 0x15, 0x14, 0x07, 0x06, 0x15, 0x14, 0x17, 0x05, 0x16, 0x33, 0x32, 0x37, 0x26, 0x27, 0x24, 0x25, 0x27, 0x15, 0x23, 0x04, 0x05, 0x06, 0x07, 0x16, 0x33, 0x32, 0x37, 0x25, 0x36, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x03, 0x88, 0x2c, 0x0e, 0xb7, 0xaf, 0x05, 0x0d, 0xb0, 0xb6, 0x07, 0x33, 0xeb, 0x95, 0xce, 0xcf, 0x94, 0x93, 0xd0, 0xcf, 0xe6, 0xa5, 0x74, 0x74, 0xa5, 0x74, 0xa9, 0x29, 0x1d, 0x1d, 0x29, 0x1d, 0x1d, 0x29, 0x1d, 0x1d, 0x29, 0x1d, 0xf3, 0x10, 0x07, 0x0b, 0x0e, 0x28, 0x11, 0x11, 0x05, 0x0c, 0x0b, 0x29, 0x01, 0x37, 0x11, 0x07, 0x0c, 0x0d, 0x28, 0x11, 0x11, 0x06, 0x0c, 0x0c, 0x28, 0xfe, 0x2f, 0x06, 0x14, 0x13, 0x14, 0x24, 0x07, 0x06, 0x12, 0x15, 0x14, 0x24, 0x02, 0x0c, 0x06, 0x12, 0x14, 0x13, 0x25, 0x0c, 0x12, 0x14, 0x12, 0x25, 0xfd, 0xe6, 0x07, 0x24, 0x15, 0x14, 0x12, 0x06, 0x07, 0x24, 0x14, 0x13, 0x14, 0x02, 0x19, 0x06, 0x26, 0x12, 0x14, 0x12, 0x06, 0x06, 0x25, 0x13, 0x14, 0x12, 0xfe, 0x6b, 0x11, 0x29, 0x0b, 0x0e, 0x07, 0x11, 0x11, 0x28, 0x0e, 0x0b, 0x07, 0x01, 0x58, 0x11, 0x28, 0x0c, 0x0c, 0x06, 0x11, 0x11, 0x28, 0x0d, 0x0c, 0x07, 0x4d, 0x79, 0xca, 0xc2, 0xfa, 0x68, 0xc3, 0xca, 0x79, 0xfe, 0xcb, 0x17, 0x43, 0x1a, 0x35, 0xfe, 0xaf, 0x09, 0x6d, 0x3b, 0x0c, 0xdf, 0xe0, 0x02, 0x09, 0x15, 0x2b, 0x16, 0x02, 0x08, 0xe0, 0xdf, 0x0b, 0x3a, 0x6c, 0x09, 0xfe, 0xae, 0x35, 0x1a, 0x43, 0x17, 0x17, 0x23, 0x30, 0x1c, 0x1c, 0x01, 0x25, 0x0d, 0x0e, 0x42, 0x38, 0x09, 0xd4, 0xfe, 0xe6, 0xfe, 0x54, 0x2b, 0x31, 0xfe, 0x53, 0xfe, 0xe6, 0xd4, 0x08, 0x37, 0x43, 0x0d, 0x0e, 0x01, 0x25, 0x1c, 0x1c, 0x30, 0x22, 0x03, 0xc2, 0x40, 0x8e, 0x40, 0x31, 0x41, 0xf1, 0xfe, 0x65, 0x01, 0x9b, 0xf1, 0x41, 0x31, 0x40, 0x8e, 0x40, 0x48, 0xe7, 0xa3, 0xa4, 0xe6, 0xe6, 0xa4, 0xa3, 0xe7, 0xad, 0x81, 0xb8, 0x80, 0x80, 0xb8, 0x01, 0x14, 0x20, 0x2e, 0x20, 0x20, 0x2e, 0xfd, 0xb5, 0x20, 0x2e, 0x20, 0x20, 0x2e, 0x02, 0x45, 0x0d, 0x2d, 0x13, 0x12, 0x08, 0x0d, 0x0f, 0x2d, 0x13, 0x11, 0x07, 0xfd, 0xff, 0x0e, 0x2d, 0x13, 0x13, 0x07, 0x0f, 0x0d, 0x2c, 0x13, 0x13, 0x07, 0x01, 0x31, 0x16, 0x29, 0x07, 0x07, 0x14, 0x17, 0x16, 0x29, 0x07, 0x07, 0x16, 0xd5, 0x15, 0x29, 0x07, 0x07, 0x15, 0x2c, 0x28, 0x08, 0x07, 0x14, 0x39, 0x17, 0x14, 0x07, 0x07, 0x29, 0x15, 0x16, 0x16, 0x07, 0x08, 0x28, 0xa9, 0x15, 0x16, 0x07, 0x07, 0x29, 0x16, 0x15, 0x16, 0x07, 0x07, 0x29, 0xfe, 0x75, 0x0f, 0x07, 0x13, 0x13, 0x2d, 0x0d, 0x0e, 0x07, 0x13, 0x13, 0x2c, 0x01, 0xe6, 0x0d, 0x08, 0x12, 0x13, 0x2d, 0x0d, 0x0f, 0x08, 0x12, 0x13, 0x2d, 0x01, 0x20, 0x47, 0x9c, 0x37, 0x37, 0x57, 0xfe, 0xf5, 0xfe, 0x36, 0x01, 0xca, 0x01, 0x0b, 0x57, 0x37, 0x37, 0x9c, 0x47, 0xe5, 0x06, 0x12, 0x20, 0x44, 0x26, 0x1a, 0x26, 0x0b, 0xa5, 0xcb, 0xc7, 0x65, 0x8b, 0x11, 0x01, 0x01, 0x11, 0x8b, 0x65, 0xc7, 0xcb, 0xa5, 0x0b, 0x26, 0x1a, 0x26, 0x44, 0x20, 0x12, 0x06, 0x1c, 0x12, 0x22, 0x28, 0x3d, 0x16, 0x15, 0x14, 0x13, 0x88, 0x06, 0x97, 0x9d, 0x70, 0x81, 0x19, 0x01, 0x01, 0x19, 0x81, 0x70, 0x9d, 0x97, 0x06, 0x88, 0x13, 0x14, 0x15, 0x16, 0x3d, 0x28, 0x22, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa5, 0x00, 0x00, 0x05, 0xd0, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x17, 0x11, 0x07, 0x21, 0x27, 0x11, 0x17, 0x11, 0x21, 0x11, 0xab, 0x05, 0x1e, 0x07, 0x07, 0xfa, 0xe2, 0x05, 0x63, 0x04, 0x63, 0x05, 0xd5, 0x07, 0xfa, 0x38, 0x06, 0x06, 0x05, 0xc8, 0x68, 0xfb, 0x08, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa4, 0x00, 0x00, 0x05, 0xd1, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x22, 0x00, 0x00, 0x13, 0x21, 0x17, 0x11, 0x07, 0x21, 0x27, 0x11, 0x17, 0x11, 0x21, 0x11, 0x07, 0x15, 0x06, 0x07, 0x00, 0x03, 0x06, 0x23, 0x06, 0x23, 0x02, 0x2b, 0x01, 0x35, 0x37, 0x32, 0x17, 0x33, 0x36, 0x37, 0x36, 0x37, 0x36, 0xaa, 0x05, 0x21, 0x06, 0x06, 0xfa, 0xdf, 0x05, 0x64, 0x04, 0x63, 0x7a, 0x44, 0x25, 0xfe, 0xda, 0x38, 0x05, 0x0f, 0x69, 0x0c, 0x5b, 0xb8, 0x15, 0x92, 0x88, 0x41, 0x06, 0x2e, 0x38, 0x59, 0x8b, 0x57, 0x05, 0xd5, 0x06, 0xfa, 0x38, 0x07, 0x07, 0x05, 0xc8, 0x68, 0xfb, 0x08, 0x04, 0xf8, 0x9e, 0x06, 0x41, 0x3a, 0xfe, 0x46, 0xfe, 0xbd, 0x3b, 0x2f, 0x01, 0x02, 0x07, 0x49, 0x83, 0xa6, 0x74, 0xb3, 0xbb, 0x78, 0x00, 0x03, 0x00, 0xa4, 0x00, 0x00, 0x05, 0xd1, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x1a, 0x00, 0x00, 0x13, 0x21, 0x17, 0x11, 0x07, 0x21, 0x27, 0x11, 0x17, 0x11, 0x21, 0x11, 0x05, 0x09, 0x01, 0x17, 0x09, 0x01, 0x15, 0x07, 0x01, 0x23, 0x01, 0x23, 0x27, 0x09, 0x01, 0xaa, 0x05, 0x21, 0x06, 0x06, 0xfa, 0xdf, 0x05, 0x64, 0x04, 0x63, 0xfc, 0x5e, 0x01, 0x72, 0x01, 0x6e, 0x56, 0xfe, 0x91, 0x01, 0x6f, 0x52, 0xfe, 0x8e, 0x04, 0xfe, 0x92, 0x04, 0x51, 0x01, 0x6e, 0xfe, 0x92, 0x05, 0xd5, 0x06, 0xfa, 0x38, 0x07, 0x07, 0x05, 0xc8, 0x68, 0xfb, 0x08, 0x04, 0xf8, 0x86, 0xfe, 0x69, 0x01, 0x97, 0x5b, 0xfe, 0x65, 0xfe, 0x66, 0x03, 0x5b, 0x01, 0x97, 0xfe, 0x6c, 0x5b, 0x01, 0x9a, 0x01, 0x9b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x8a, 0x00, 0xa0, 0x03, 0x4a, 0x05, 0x40, 0x00, 0x14, 0x00, 0x00, 0x13, 0x33, 0x01, 0x36, 0x13, 0x32, 0x37, 0x33, 0x17, 0x09, 0x01, 0x15, 0x07, 0x01, 0x23, 0x01, 0x23, 0x27, 0x01, 0x00, 0x35, 0xd9, 0x04, 0x01, 0x0c, 0x0a, 0xfd, 0x04, 0x05, 0x04, 0x4d, 0xfe, 0xf0, 0x01, 0x10, 0x4f, 0xfe, 0xf2, 0x02, 0xfe, 0xf1, 0x03, 0x4e, 0x01, 0x12, 0xfe, 0xee, 0x05, 0x40, 0xfe, 0x0b, 0x08, 0x01, 0xde, 0x0f, 0x55, 0xfe, 0x04, 0xfe, 0x07, 0x03, 0x53, 0x01, 0xf7, 0xfe, 0x0b, 0x56, 0x01, 0xf9, 0x01, 0xf5, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x5a, 0x00, 0x00, 0x06, 0x43, 0x07, 0x76, 0x00, 0x08, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x2c, 0x00, 0x35, 0x00, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x01, 0x33, 0x06, 0x2b, 0x01, 0x26, 0x3d, 0x01, 0x34, 0x01, 0x33, 0x06, 0x2b, 0x01, 0x26, 0x3d, 0x01, 0x34, 0x25, 0x33, 0x06, 0x2b, 0x01, 0x26, 0x3d, 0x01, 0x34, 0x17, 0x33, 0x06, 0x2b, 0x01, 0x26, 0x3d, 0x01, 0x34, 0x01, 0x33, 0x06, 0x2b, 0x01, 0x26, 0x3d, 0x01, 0x34, 0x05, 0x33, 0x06, 0x2b, 0x01, 0x26, 0x3d, 0x01, 0x34, 0x17, 0x33, 0x06, 0x2b, 0x01, 0x26, 0x3d, 0x01, 0x34, 0x25, 0x33, 0x17, 0x15, 0x33, 0x20, 0x13, 0x16, 0x1d, 0x01, 0x23, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x22, 0x07, 0x15, 0x14, 0x07, 0x27, 0x26, 0x23, 0x11, 0x14, 0x0f, 0x01, 0x22, 0x2f, 0x01, 0x35, 0x37, 0x33, 0x17, 0x15, 0x16, 0x3b, 0x01, 0x32, 0x3f, 0x01, 0x11, 0x22, 0x07, 0x06, 0x23, 0x27, 0x35, 0x37, 0x23, 0x26, 0x27, 0x23, 0x22, 0x0f, 0x01, 0x23, 0x35, 0x36, 0x37, 0x36, 0x21, 0x35, 0x01, 0xa7, 0x03, 0x1b, 0x53, 0x06, 0x34, 0x02, 0x1a, 0x02, 0x1a, 0x53, 0x06, 0x33, 0x01, 0xe8, 0x02, 0x1b, 0x53, 0x05, 0x34, 0xde, 0x04, 0x1b, 0x53, 0x05, 0x35, 0x01, 0xe8, 0x03, 0x1a, 0x54, 0x05, 0x35, 0x01, 0x09, 0x02, 0x19, 0x54, 0x06, 0x34, 0x52, 0x03, 0x1b, 0x53, 0x05, 0x34, 0xfd, 0xe6, 0x34, 0x06, 0x02, 0x01, 0x8c, 0xfc, 0x26, 0x01, 0x14, 0x11, 0x20, 0x33, 0x28, 0x87, 0x64, 0x08, 0x1d, 0x88, 0x7b, 0x5f, 0x1b, 0x52, 0x21, 0x02, 0x05, 0x27, 0x05, 0x09, 0x38, 0x09, 0x32, 0x12, 0x05, 0xbe, 0x4d, 0x10, 0x0c, 0x06, 0x06, 0x04, 0x3c, 0xb1, 0x3d, 0x59, 0x1e, 0x12, 0x03, 0x34, 0xad, 0xd7, 0x01, 0x19, 0x06, 0x01, 0xcf, 0x0a, 0x23, 0x02, 0x38, 0x01, 0x64, 0xcf, 0x08, 0x23, 0x03, 0x37, 0xe3, 0xcf, 0x08, 0x24, 0x03, 0x36, 0xb9, 0xcf, 0x08, 0x24, 0x02, 0x38, 0x01, 0x3b, 0xce, 0x07, 0x24, 0x03, 0x37, 0x69, 0xcf, 0x07, 0x24, 0x03, 0x37, 0xeb, 0xcf, 0x09, 0x23, 0x02, 0x39, 0x9a, 0x05, 0x70, 0xfe, 0x50, 0x4c, 0x0c, 0x07, 0x0d, 0x29, 0x16, 0x5a, 0x2e, 0x0d, 0x02, 0x3b, 0x36, 0xfd, 0x9f, 0x5a, 0x15, 0x02, 0x56, 0x18, 0x17, 0x06, 0x06, 0x0a, 0x5a, 0x33, 0x25, 0x02, 0x59, 0x36, 0x33, 0x05, 0x0b, 0x2e, 0x38, 0x19, 0x37, 0x10, 0x02, 0x80, 0xc2, 0xc6, 0x70, 0x00, 0x09, 0x00, 0x88, 0x00, 0x00, 0x05, 0xeb, 0x05, 0xd9, 0x00, 0x0b, 0x00, 0x11, 0x00, 0x1c, 0x00, 0x33, 0x00, 0x44, 0x00, 0x4d, 0x00, 0x79, 0x00, 0x7f, 0x00, 0x8f, 0x00, 0x00, 0x01, 0x14, 0x15, 0x14, 0x17, 0x21, 0x36, 0x37, 0x34, 0x23, 0x21, 0x06, 0x13, 0x16, 0x17, 0x21, 0x36, 0x3f, 0x01, 0x06, 0x07, 0x36, 0x37, 0x36, 0x35, 0x34, 0x35, 0x26, 0x23, 0x27, 0x06, 0x07, 0x33, 0x32, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x23, 0x01, 0x33, 0x14, 0x06, 0x07, 0x14, 0x16, 0x17, 0x23, 0x26, 0x27, 0x26, 0x27, 0x34, 0x35, 0x34, 0x36, 0x01, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x21, 0x16, 0x05, 0x36, 0x37, 0x32, 0x17, 0x15, 0x14, 0x05, 0x07, 0x17, 0x14, 0x07, 0x21, 0x26, 0x3d, 0x01, 0x37, 0x35, 0x24, 0x2f, 0x01, 0x35, 0x36, 0x33, 0x16, 0x17, 0x26, 0x11, 0x34, 0x33, 0x21, 0x16, 0x15, 0x33, 0x32, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x27, 0x01, 0x16, 0x17, 0x21, 0x36, 0x37, 0x01, 0x06, 0x07, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x35, 0x33, 0x1e, 0x01, 0x15, 0x01, 0x06, 0x0d, 0x04, 0x0e, 0x0a, 0x03, 0x1b, 0xfc, 0x10, 0x19, 0x38, 0x05, 0x0e, 0x03, 0x8f, 0x0c, 0x08, 0x41, 0x08, 0x34, 0x4e, 0x2c, 0x1a, 0x01, 0x1d, 0x33, 0x02, 0x01, 0x31, 0x35, 0x3e, 0x28, 0x49, 0x1d, 0x2d, 0x07, 0x34, 0x22, 0x11, 0x61, 0x31, 0x1a, 0x16, 0x6c, 0xfd, 0x78, 0x08, 0x58, 0x01, 0x7a, 0x04, 0x08, 0x11, 0x62, 0x1e, 0x08, 0x63, 0xfe, 0xf9, 0xa5, 0xaa, 0x9d, 0x9f, 0x1f, 0x53, 0xfc, 0x9e, 0x21, 0x02, 0xf2, 0xe4, 0x5c, 0x10, 0x06, 0xfe, 0xbc, 0x71, 0x02, 0x0f, 0xfe, 0x26, 0x0f, 0x03, 0xfe, 0x8e, 0x2c, 0x03, 0x03, 0x11, 0x4c, 0xc1, 0xb5, 0x30, 0x03, 0xf7, 0x1d, 0x31, 0x81, 0x4e, 0x1f, 0x65, 0x30, 0x3c, 0x06, 0x10, 0xfc, 0x8d, 0x06, 0x09, 0x03, 0xd6, 0x0a, 0x03, 0xfe, 0xbc, 0x05, 0x11, 0x39, 0x0a, 0x05, 0x02, 0x48, 0x33, 0x05, 0x09, 0x39, 0x02, 0xb4, 0x06, 0x07, 0x37, 0x48, 0x34, 0x58, 0x16, 0x04, 0xfe, 0xcd, 0x1a, 0x12, 0x16, 0x16, 0xc7, 0x6d, 0x86, 0x01, 0x4d, 0x37, 0x52, 0x06, 0x05, 0x11, 0x56, 0x1c, 0x20, 0x2f, 0x82, 0x4d, 0x28, 0x01, 0x3d, 0x48, 0x3a, 0x0d, 0x1f, 0x2c, 0x71, 0x4c, 0x55, 0x44, 0x03, 0x29, 0x38, 0x88, 0x57, 0x71, 0x6b, 0xb1, 0x92, 0x65, 0x2d, 0x50, 0x05, 0x06, 0x65, 0x78, 0xfa, 0xf3, 0x0d, 0x0b, 0x10, 0x97, 0x4e, 0x57, 0x18, 0x0a, 0x0a, 0x0a, 0x10, 0x3d, 0x24, 0x0a, 0x0f, 0x08, 0x07, 0x10, 0x06, 0x02, 0x02, 0x55, 0x12, 0x0d, 0x04, 0x0b, 0x09, 0x14, 0xfe, 0x01, 0x2f, 0x30, 0x02, 0x18, 0x63, 0x9b, 0x99, 0x29, 0x16, 0x48, 0x04, 0x01, 0x3f, 0x1a, 0x12, 0x13, 0x19, 0x01, 0xf5, 0x32, 0x1c, 0x40, 0x5b, 0x6e, 0x44, 0x46, 0x38, 0x54, 0x24, 0x2e, 0x4a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x01, 0x05, 0xdb, 0x05, 0xd9, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x01, 0x13, 0x07, 0x21, 0x27, 0x13, 0x09, 0x01, 0x03, 0x21, 0x03, 0x01, 0x03, 0x41, 0x02, 0x4e, 0x4b, 0x02, 0xfa, 0xc8, 0x05, 0x4f, 0x02, 0x55, 0xfe, 0x05, 0x44, 0x04, 0x75, 0x40, 0xfe, 0x07, 0x05, 0xd9, 0xfe, 0x77, 0xfb, 0xb4, 0x03, 0x06, 0x04, 0x4c, 0x01, 0x86, 0xfe, 0x35, 0xfc, 0x5f, 0x03, 0xa1, 0x01, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9a, 0x00, 0x00, 0x05, 0xdb, 0x05, 0xd0, 0x00, 0x09, 0x00, 0x00, 0x09, 0x01, 0x13, 0x17, 0x07, 0x21, 0x27, 0x13, 0x00, 0x37, 0x03, 0x3f, 0x02, 0x4b, 0x4e, 0x02, 0x02, 0xfa, 0xc8, 0x05, 0x51, 0x02, 0x3e, 0x12, 0x05, 0xd0, 0xfe, 0x77, 0xfb, 0xbf, 0x03, 0x03, 0x06, 0x04, 0x44, 0x01, 0x80, 0x06, 0x00, 0x01, 0x00, 0x8f, 0x00, 0x00, 0x05, 0xe6, 0x05, 0xd4, 0x00, 0x53, 0x00, 0x00, 0x01, 0x03, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x32, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x03, 0x25, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x03, 0x16, 0x15, 0x10, 0x07, 0x23, 0x36, 0x11, 0x34, 0x27, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x35, 0x34, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x03, 0x1f, 0xc2, 0x43, 0x4f, 0x22, 0x22, 0x4f, 0x3b, 0x27, 0x3c, 0x34, 0x53, 0x32, 0x0c, 0x52, 0xb3, 0x01, 0x24, 0x46, 0x40, 0x34, 0x2f, 0x20, 0x1f, 0x3f, 0x06, 0x10, 0x61, 0x21, 0x0b, 0x0a, 0x1e, 0x33, 0x39, 0x1e, 0x20, 0x5f, 0x44, 0xbb, 0x08, 0x64, 0x56, 0x84, 0x07, 0xb9, 0x46, 0x5e, 0x20, 0x1e, 0x39, 0x32, 0x1f, 0x0b, 0x09, 0x21, 0x61, 0x11, 0x06, 0x3f, 0x20, 0x1f, 0x30, 0x32, 0x41, 0x46, 0x03, 0x08, 0x01, 0x34, 0x68, 0x6f, 0x6b, 0x40, 0x16, 0x52, 0x52, 0x72, 0x2a, 0x25, 0x7f, 0x74, 0xfe, 0xeb, 0x65, 0x1c, 0x11, 0x0c, 0x1b, 0x42, 0x42, 0x15, 0x15, 0x39, 0x27, 0x1d, 0x11, 0x37, 0x2a, 0x1f, 0x24, 0x25, 0x1b, 0x29, 0x0c, 0x22, 0x66, 0x01, 0x16, 0x58, 0x53, 0xfe, 0xdd, 0xe7, 0xf2, 0x01, 0x35, 0x45, 0x49, 0xfe, 0xea, 0x66, 0x22, 0x0c, 0x29, 0x1b, 0x25, 0x23, 0x1e, 0x2c, 0x37, 0x11, 0x1d, 0x27, 0x39, 0x15, 0x14, 0x43, 0x42, 0x1b, 0x0c, 0x11, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x99, 0x01, 0x1e, 0x05, 0xdb, 0x04, 0x98, 0x00, 0x3e, 0x00, 0x45, 0x00, 0x00, 0x01, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x16, 0x13, 0x33, 0x17, 0x07, 0x23, 0x06, 0x07, 0x22, 0x27, 0x34, 0x33, 0x16, 0x33, 0x32, 0x33, 0x32, 0x37, 0x26, 0x27, 0x23, 0x22, 0x07, 0x16, 0x15, 0x06, 0x05, 0x24, 0x03, 0x34, 0x37, 0x16, 0x17, 0x15, 0x07, 0x14, 0x17, 0x32, 0x37, 0x12, 0x25, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x36, 0x37, 0x32, 0x35, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x15, 0x14, 0x17, 0x35, 0x26, 0x05, 0x16, 0x64, 0x12, 0x42, 0x9f, 0x12, 0xe7, 0x31, 0x18, 0x11, 0x29, 0x03, 0x0f, 0x89, 0x58, 0x16, 0x12, 0x0e, 0x33, 0x02, 0x01, 0x45, 0x0c, 0xec, 0x06, 0x03, 0x76, 0x3d, 0x79, 0x08, 0xfe, 0xd3, 0xfd, 0xd7, 0x28, 0x3b, 0x2e, 0x07, 0x0b, 0x65, 0x50, 0x0c, 0x30, 0x01, 0x0c, 0xb0, 0x25, 0x53, 0x5a, 0x37, 0x41, 0x46, 0x34, 0x22, 0x79, 0x01, 0xce, 0x1d, 0x04, 0x98, 0x05, 0x73, 0x57, 0x19, 0x24, 0x2c, 0x1b, 0xfe, 0xf0, 0x4a, 0x0d, 0xae, 0x09, 0x5d, 0x54, 0x2d, 0x4d, 0x4d, 0xf1, 0x6d, 0x40, 0x65, 0xf6, 0x10, 0x03, 0x01, 0x64, 0x3a, 0x09, 0x03, 0x2c, 0x17, 0x27, 0x5a, 0x0c, 0x4d, 0x01, 0xde, 0x14, 0x06, 0xa0, 0x08, 0x27, 0x63, 0x4d, 0x14, 0x26, 0x54, 0x29, 0x24, 0x24, 0x0d, 0x3c, 0xfe, 0xa5, 0x08, 0x09, 0x84, 0x49, 0x03, 0xb5, 0x00, 0x01, 0x00, 0x9a, 0x00, 0xe7, 0x05, 0xdb, 0x04, 0x8d, 0x00, 0x32, 0x00, 0x00, 0x25, 0x21, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x33, 0x37, 0x23, 0x26, 0x27, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x3b, 0x01, 0x37, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x21, 0x37, 0x21, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x21, 0x36, 0x37, 0x36, 0x33, 0x21, 0x32, 0x16, 0x15, 0x05, 0x97, 0xfd, 0x95, 0x27, 0x37, 0x19, 0x17, 0x10, 0x11, 0x31, 0x03, 0x7a, 0x2a, 0x17, 0x1c, 0x1a, 0x2d, 0x18, 0xa2, 0x01, 0xe8, 0x3d, 0x38, 0x1b, 0x16, 0x12, 0x14, 0x01, 0x30, 0x02, 0xfd, 0x4f, 0x26, 0x38, 0x1a, 0x2d, 0x17, 0x02, 0xdb, 0x07, 0x0f, 0x1c, 0x26, 0x01, 0x51, 0x26, 0x37, 0xe7, 0x3e, 0x2b, 0x1b, 0x32, 0x0d, 0x0a, 0x03, 0x0c, 0x02, 0x1a, 0x1e, 0x2c, 0x1b, 0x32, 0x1c, 0x0a, 0x3d, 0x2c, 0x1a, 0x32, 0x0e, 0x0b, 0x02, 0x0a, 0x3d, 0x2c, 0x1b, 0x33, 0x1a, 0x16, 0x11, 0x1f, 0x3e, 0x2c, 0x00, 0x01, 0x00, 0x9a, 0x00, 0xe7, 0x05, 0xdb, 0x04, 0x8d, 0x00, 0x32, 0x00, 0x00, 0x13, 0x34, 0x36, 0x33, 0x21, 0x32, 0x17, 0x16, 0x17, 0x21, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0x17, 0x21, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x15, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x23, 0x17, 0x33, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x21, 0x9b, 0x38, 0x25, 0x01, 0x51, 0x27, 0x1b, 0x0f, 0x07, 0x02, 0xdb, 0x17, 0x2d, 0x1a, 0x37, 0x27, 0xfd, 0x50, 0x01, 0x01, 0x31, 0x13, 0x12, 0x17, 0x19, 0x37, 0x3d, 0xe7, 0xa2, 0x18, 0x2d, 0x19, 0x1b, 0x16, 0x2c, 0x79, 0x04, 0x30, 0x11, 0x10, 0x16, 0x1a, 0x37, 0x26, 0xfd, 0x94, 0x04, 0x23, 0x2c, 0x3e, 0x1f, 0x11, 0x16, 0x1a, 0x33, 0x1b, 0x2c, 0x3d, 0x0a, 0x02, 0x0b, 0x0e, 0x32, 0x1a, 0x2c, 0x3d, 0x0a, 0x1c, 0x32, 0x1b, 0x2c, 0x1e, 0x1a, 0x02, 0x0c, 0x03, 0x0a, 0x0d, 0x32, 0x1b, 0x2b, 0x3e, 0x00, 0x00, 0x02, 0x00, 0xa0, 0x00, 0xd4, 0x05, 0xd6, 0x04, 0x8d, 0x00, 0x22, 0x00, 0x44, 0x00, 0x00, 0x25, 0x13, 0x34, 0x26, 0x23, 0x21, 0x22, 0x07, 0x21, 0x30, 0x23, 0x22, 0x14, 0x33, 0x21, 0x07, 0x21, 0x22, 0x15, 0x14, 0x33, 0x21, 0x07, 0x23, 0x22, 0x15, 0x14, 0x3b, 0x01, 0x07, 0x23, 0x22, 0x15, 0x14, 0x33, 0x07, 0x26, 0x27, 0x36, 0x37, 0x33, 0x37, 0x23, 0x26, 0x27, 0x36, 0x37, 0x33, 0x37, 0x21, 0x22, 0x27, 0x36, 0x37, 0x21, 0x37, 0x21, 0x26, 0x27, 0x36, 0x33, 0x21, 0x36, 0x37, 0x21, 0x32, 0x16, 0x15, 0x03, 0x05, 0x6e, 0x41, 0x2b, 0x1e, 0xfe, 0xc3, 0x31, 0x15, 0xfd, 0x2a, 0x03, 0x48, 0x4b, 0x02, 0xb2, 0x0b, 0xfe, 0xc1, 0x4b, 0x4b, 0x01, 0x1b, 0x08, 0xc7, 0x4b, 0x4b, 0x9c, 0x11, 0x38, 0x4a, 0x4a, 0x19, 0x53, 0x01, 0x01, 0x53, 0x43, 0x03, 0x99, 0x54, 0x01, 0x01, 0x54, 0xcd, 0x01, 0xfe, 0xe6, 0x54, 0x01, 0x01, 0x54, 0x01, 0x44, 0x04, 0xfd, 0x50, 0x53, 0x01, 0x01, 0x53, 0x02, 0xdb, 0x1d, 0x3b, 0x01, 0x51, 0x25, 0x38, 0x43, 0xf1, 0x03, 0x15, 0x25, 0x33, 0x39, 0x92, 0x4c, 0x4b, 0x49, 0x4f, 0x4b, 0x48, 0x4c, 0x4b, 0x49, 0x1d, 0x01, 0x68, 0x67, 0x01, 0x0e, 0x01, 0x68, 0x67, 0x01, 0x13, 0x68, 0x67, 0x01, 0x0f, 0x01, 0x68, 0x67, 0x45, 0x02, 0x3f, 0x2d, 0xfc, 0xb3, 0x00, 0x00, 0x02, 0x00, 0x84, 0x00, 0x00, 0x03, 0xde, 0x05, 0xca, 0x00, 0x21, 0x00, 0x44, 0x00, 0x00, 0x37, 0x05, 0x32, 0x36, 0x35, 0x11, 0x34, 0x27, 0x11, 0x36, 0x23, 0x22, 0x15, 0x11, 0x27, 0x11, 0x34, 0x23, 0x22, 0x15, 0x11, 0x27, 0x35, 0x34, 0x23, 0x22, 0x1d, 0x01, 0x27, 0x35, 0x34, 0x23, 0x22, 0x15, 0x27, 0x36, 0x37, 0x16, 0x17, 0x15, 0x17, 0x35, 0x36, 0x37, 0x16, 0x17, 0x15, 0x17, 0x11, 0x34, 0x37, 0x16, 0x17, 0x11, 0x17, 0x11, 0x36, 0x37, 0x16, 0x15, 0x11, 0x16, 0x17, 0x11, 0x14, 0x06, 0x23, 0x25, 0x13, 0x9f, 0x02, 0xc6, 0x21, 0x2f, 0x35, 0x02, 0x42, 0x42, 0x44, 0x45, 0x41, 0x47, 0x43, 0x41, 0x45, 0x43, 0x42, 0x1a, 0x01, 0x5e, 0x5c, 0x01, 0x0d, 0x01, 0x5d, 0x5d, 0x01, 0x10, 0x5f, 0x5c, 0x01, 0x0e, 0x01, 0x5d, 0x5d, 0x3d, 0x02, 0x38, 0x28, 0xfd, 0x06, 0x01, 0x73, 0x4a, 0x31, 0x20, 0x01, 0x62, 0x36, 0x16, 0x03, 0x27, 0x53, 0x53, 0xfd, 0x02, 0x0d, 0x01, 0x63, 0x52, 0x52, 0xfe, 0xc4, 0x09, 0xdf, 0x53, 0x53, 0xae, 0x12, 0x3f, 0x53, 0x53, 0x1c, 0x5c, 0x01, 0x01, 0x5c, 0x4b, 0x04, 0xac, 0x5c, 0x01, 0x01, 0x5c, 0xe4, 0x03, 0x01, 0x3b, 0x5c, 0x01, 0x01, 0x5c, 0xfe, 0x96, 0x04, 0x02, 0xfd, 0x5d, 0x01, 0x01, 0x5d, 0xfc, 0xd4, 0x21, 0x41, 0xfe, 0x8a, 0x2a, 0x3e, 0x4b, 0x02, 0x9b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9f, 0x00, 0xd3, 0x05, 0xd6, 0x04, 0x8d, 0x00, 0x21, 0x00, 0x43, 0x00, 0x00, 0x25, 0x32, 0x35, 0x34, 0x2b, 0x01, 0x27, 0x33, 0x32, 0x35, 0x34, 0x2b, 0x01, 0x27, 0x21, 0x32, 0x35, 0x34, 0x23, 0x21, 0x27, 0x21, 0x32, 0x34, 0x2b, 0x01, 0x21, 0x26, 0x23, 0x21, 0x22, 0x06, 0x15, 0x13, 0x07, 0x03, 0x34, 0x36, 0x33, 0x21, 0x16, 0x17, 0x21, 0x32, 0x17, 0x06, 0x07, 0x21, 0x17, 0x21, 0x16, 0x17, 0x06, 0x23, 0x21, 0x17, 0x33, 0x16, 0x17, 0x06, 0x07, 0x23, 0x17, 0x33, 0x16, 0x17, 0x06, 0x07, 0x03, 0x61, 0x4b, 0x4b, 0x39, 0x10, 0x9d, 0x4a, 0x4a, 0xc9, 0x08, 0x01, 0x1c, 0x4a, 0x4a, 0xfe, 0xc1, 0x0c, 0x02, 0xb1, 0x4b, 0x47, 0x04, 0xfd, 0x2a, 0x14, 0x30, 0xfe, 0xc1, 0x1d, 0x2c, 0x43, 0x24, 0x44, 0x38, 0x26, 0x01, 0x51, 0x3a, 0x1e, 0x02, 0xda, 0x54, 0x01, 0x01, 0x54, 0xfd, 0x50, 0x04, 0x01, 0x45, 0x53, 0x01, 0x01, 0x53, 0xfe, 0xe5, 0x03, 0xcd, 0x53, 0x01, 0x01, 0x53, 0x9b, 0x04, 0x43, 0x53, 0x01, 0x01, 0x53, 0xf1, 0x49, 0x4b, 0x4c, 0x48, 0x4b, 0x4f, 0x49, 0x4b, 0x4c, 0x92, 0x39, 0x33, 0x25, 0xfc, 0xeb, 0x1e, 0x03, 0x4e, 0x2d, 0x3f, 0x02, 0x45, 0x67, 0x68, 0x01, 0x0f, 0x01, 0x67, 0x68, 0x13, 0x01, 0x67, 0x68, 0x01, 0x0e, 0x01, 0x67, 0x69, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x84, 0xff, 0xf9, 0x03, 0xde, 0x05, 0xc2, 0x00, 0x21, 0x00, 0x43, 0x00, 0x00, 0x13, 0x14, 0x33, 0x32, 0x3d, 0x01, 0x37, 0x15, 0x14, 0x33, 0x32, 0x3d, 0x01, 0x37, 0x11, 0x14, 0x33, 0x32, 0x35, 0x11, 0x37, 0x11, 0x14, 0x33, 0x32, 0x27, 0x11, 0x36, 0x35, 0x11, 0x34, 0x26, 0x23, 0x05, 0x27, 0x25, 0x32, 0x16, 0x15, 0x11, 0x06, 0x07, 0x11, 0x14, 0x07, 0x26, 0x27, 0x11, 0x07, 0x11, 0x06, 0x07, 0x26, 0x35, 0x11, 0x07, 0x15, 0x06, 0x07, 0x26, 0x27, 0x35, 0x07, 0x15, 0x06, 0x07, 0x26, 0x27, 0x9f, 0x42, 0x43, 0x45, 0x41, 0x43, 0x47, 0x41, 0x45, 0x44, 0x42, 0x42, 0x02, 0x35, 0x2f, 0x21, 0xfd, 0x3a, 0x1b, 0x02, 0xfa, 0x28, 0x38, 0x02, 0x3d, 0x5d, 0x5d, 0x01, 0x0e, 0x01, 0x5c, 0x5f, 0x10, 0x01, 0x5d, 0x5d, 0x01, 0x0d, 0x01, 0x5c, 0x5e, 0x01, 0x02, 0xb3, 0x53, 0x53, 0x3d, 0x14, 0xae, 0x53, 0x53, 0xdd, 0x09, 0xfe, 0xc6, 0x53, 0x53, 0x01, 0x62, 0x0d, 0xfd, 0x01, 0x53, 0x53, 0x03, 0x27, 0x17, 0x36, 0x01, 0x61, 0x21, 0x30, 0x4a, 0x29, 0x4b, 0x3e, 0x2a, 0xfe, 0x8a, 0x42, 0x20, 0xfc, 0xd4, 0x5c, 0x01, 0x01, 0x5c, 0x02, 0xfc, 0x04, 0xfe, 0x98, 0x5d, 0x01, 0x01, 0x5d, 0x01, 0x3a, 0x02, 0xe4, 0x5d, 0x01, 0x01, 0x5d, 0xab, 0x04, 0x4a, 0x5d, 0x01, 0x01, 0x5d, 0x00, 0x00, 0x1d, 0x00, 0x70, 0x00, 0x00, 0x06, 0x04, 0x05, 0xd8, 0x00, 0x4f, 0x00, 0x80, 0x00, 0x8b, 0x00, 0x95, 0x00, 0xa4, 0x00, 0xb3, 0x00, 0xba, 0x00, 0xc1, 0x00, 0xd6, 0x00, 0xdc, 0x00, 0xe3, 0x00, 0xe7, 0x00, 0xeb, 0x00, 0xef, 0x00, 0xf3, 0x00, 0xf7, 0x00, 0xfb, 0x00, 0xff, 0x01, 0x03, 0x01, 0x07, 0x01, 0x0b, 0x01, 0x1a, 0x01, 0x26, 0x01, 0x2a, 0x01, 0x2e, 0x01, 0x32, 0x01, 0x36, 0x01, 0x3a, 0x01, 0x3e, 0x00, 0x00, 0x01, 0x20, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x17, 0x15, 0x14, 0x07, 0x33, 0x36, 0x35, 0x36, 0x3b, 0x01, 0x32, 0x15, 0x16, 0x1d, 0x01, 0x06, 0x23, 0x27, 0x06, 0x07, 0x15, 0x17, 0x37, 0x16, 0x15, 0x14, 0x07, 0x14, 0x2b, 0x01, 0x22, 0x2f, 0x01, 0x06, 0x23, 0x22, 0x27, 0x06, 0x15, 0x06, 0x2b, 0x01, 0x22, 0x35, 0x26, 0x35, 0x34, 0x37, 0x17, 0x37, 0x35, 0x25, 0x07, 0x22, 0x27, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x32, 0x1f, 0x01, 0x35, 0x27, 0x37, 0x26, 0x35, 0x36, 0x37, 0x36, 0x01, 0x14, 0x17, 0x33, 0x35, 0x26, 0x35, 0x36, 0x3b, 0x01, 0x17, 0x07, 0x17, 0x15, 0x07, 0x15, 0x14, 0x17, 0x16, 0x1d, 0x01, 0x17, 0x33, 0x37, 0x34, 0x37, 0x36, 0x35, 0x27, 0x37, 0x35, 0x27, 0x37, 0x16, 0x1d, 0x01, 0x07, 0x17, 0x36, 0x3d, 0x01, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x20, 0x07, 0x06, 0x05, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x34, 0x21, 0x16, 0x17, 0x06, 0x23, 0x22, 0x27, 0x34, 0x35, 0x34, 0x13, 0x33, 0x36, 0x33, 0x17, 0x36, 0x35, 0x26, 0x35, 0x26, 0x23, 0x06, 0x07, 0x06, 0x15, 0x25, 0x06, 0x23, 0x06, 0x15, 0x17, 0x37, 0x16, 0x17, 0x35, 0x34, 0x27, 0x26, 0x35, 0x26, 0x05, 0x17, 0x15, 0x07, 0x26, 0x35, 0x34, 0x37, 0x16, 0x15, 0x14, 0x07, 0x27, 0x35, 0x03, 0x16, 0x33, 0x36, 0x37, 0x26, 0x35, 0x34, 0x37, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x26, 0x27, 0x26, 0x27, 0x16, 0x15, 0x14, 0x37, 0x16, 0x17, 0x33, 0x35, 0x26, 0x05, 0x15, 0x32, 0x3f, 0x01, 0x22, 0x07, 0x05, 0x15, 0x17, 0x35, 0x25, 0x15, 0x37, 0x35, 0x05, 0x15, 0x17, 0x35, 0x33, 0x15, 0x37, 0x27, 0x07, 0x15, 0x37, 0x27, 0x07, 0x15, 0x33, 0x35, 0x33, 0x15, 0x33, 0x35, 0x07, 0x15, 0x17, 0x35, 0x17, 0x15, 0x33, 0x35, 0x07, 0x15, 0x33, 0x35, 0x05, 0x27, 0x07, 0x15, 0x16, 0x15, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x26, 0x35, 0x06, 0x25, 0x07, 0x16, 0x15, 0x14, 0x17, 0x32, 0x3f, 0x01, 0x26, 0x23, 0x07, 0x25, 0x07, 0x17, 0x35, 0x07, 0x15, 0x17, 0x35, 0x27, 0x15, 0x17, 0x35, 0x17, 0x15, 0x37, 0x35, 0x37, 0x15, 0x37, 0x35, 0x37, 0x15, 0x37, 0x35, 0x03, 0x4a, 0x01, 0x12, 0x83, 0x35, 0x5b, 0x05, 0x16, 0x05, 0x90, 0x28, 0x20, 0x07, 0x39, 0x3f, 0x18, 0x38, 0x50, 0xe0, 0x37, 0xd2, 0x3f, 0x56, 0x45, 0x3a, 0x05, 0x2e, 0x3e, 0xac, 0x44, 0x9b, 0x9d, 0x41, 0xbc, 0x2e, 0x28, 0x0c, 0x33, 0x44, 0x50, 0x44, 0xce, 0xfe, 0xee, 0x61, 0x3e, 0x07, 0x40, 0x03, 0x23, 0x1e, 0x2b, 0x36, 0x78, 0x17, 0x0b, 0x60, 0x1f, 0xed, 0x5d, 0xfe, 0xbe, 0x3e, 0x07, 0x1c, 0x0a, 0x0b, 0x0c, 0x11, 0x0b, 0x1c, 0x11, 0x8a, 0x3e, 0x5b, 0x50, 0x72, 0xb1, 0x1d, 0x17, 0x1e, 0x0c, 0x1c, 0x17, 0x1c, 0x05, 0x40, 0xca, 0x73, 0x65, 0x22, 0xfe, 0xcf, 0x5e, 0x12, 0x01, 0x4c, 0x29, 0x02, 0x32, 0x51, 0x06, 0x46, 0x20, 0x01, 0xa0, 0xb7, 0x06, 0x22, 0x56, 0x3b, 0x3d, 0xd4, 0x05, 0xfc, 0x16, 0x5c, 0x1c, 0x3f, 0x06, 0x12, 0x19, 0x2f, 0xe0, 0xfc, 0x85, 0x0f, 0x0d, 0x2f, 0x2a, 0x55, 0x39, 0xd9, 0x5b, 0xb7, 0x16, 0x02, 0x27, 0x0d, 0x2e, 0x22, 0x6e, 0x3f, 0x24, 0x2d, 0xf0, 0x29, 0xc0, 0xc4, 0x26, 0x01, 0x1a, 0x21, 0x19, 0x44, 0x68, 0x32, 0xac, 0x0b, 0x06, 0x29, 0x14, 0x0e, 0x12, 0x17, 0x05, 0x08, 0x01, 0x60, 0x0e, 0x02, 0x17, 0x0c, 0x15, 0xfe, 0xba, 0x10, 0x01, 0x07, 0x17, 0xfe, 0xf4, 0x16, 0xb8, 0x18, 0x02, 0x3f, 0x14, 0x02, 0x68, 0x1d, 0x12, 0x16, 0x94, 0x16, 0x68, 0x16, 0x45, 0x1d, 0xfe, 0x2d, 0x67, 0x06, 0x3e, 0x05, 0x0d, 0x11, 0x3f, 0x8c, 0x1e, 0x11, 0xa7, 0x02, 0xc0, 0x10, 0xcc, 0x2e, 0x12, 0x0b, 0x38, 0x05, 0x1c, 0x56, 0xfd, 0xe0, 0x03, 0x1a, 0x16, 0x16, 0x65, 0x17, 0xb7, 0x19, 0x0d, 0x17, 0x12, 0x17, 0x05, 0xd8, 0xc1, 0x6c, 0x54, 0x45, 0x72, 0x66, 0x5e, 0x06, 0x35, 0x2e, 0x3e, 0x3d, 0x39, 0x7c, 0x35, 0x22, 0x18, 0x2d, 0x07, 0x6c, 0x29, 0x12, 0x64, 0x0d, 0x12, 0x2c, 0x26, 0x3e, 0x76, 0x76, 0x5d, 0x63, 0x63, 0x63, 0x19, 0x57, 0x70, 0x43, 0x2d, 0x2b, 0x0d, 0x0d, 0x64, 0x12, 0x95, 0x07, 0x38, 0x0d, 0x1b, 0x42, 0x70, 0x70, 0x3e, 0x06, 0x57, 0x5d, 0x6f, 0xd8, 0xe6, 0x61, 0x1d, 0xfe, 0x78, 0x76, 0x75, 0x50, 0x70, 0x38, 0x32, 0x13, 0x2c, 0x8e, 0x44, 0xa8, 0x0c, 0x5e, 0x1e, 0x38, 0x2c, 0x18, 0x0d, 0x1a, 0x5e, 0x42, 0x24, 0x4b, 0xbb, 0x9c, 0x12, 0x2b, 0x14, 0x0b, 0x22, 0x31, 0xae, 0x18, 0x52, 0x5b, 0x2b, 0xd2, 0x65, 0x2a, 0xf1, 0x3b, 0xd0, 0x0d, 0x32, 0x0b, 0x0d, 0x9b, 0x9b, 0x57, 0x0a, 0x51, 0x97, 0x9b, 0x03, 0x02, 0x50, 0xfe, 0x12, 0x82, 0x05, 0x08, 0x0a, 0x49, 0x26, 0x3f, 0x09, 0x67, 0x70, 0x13, 0xeb, 0x6f, 0x25, 0x19, 0x0b, 0x05, 0x12, 0x77, 0x0d, 0x5e, 0x19, 0x53, 0x41, 0x24, 0x0d, 0x07, 0x9f, 0x32, 0x0c, 0x39, 0x69, 0x2d, 0x35, 0x6e, 0x30, 0x08, 0x32, 0xa2, 0xfe, 0x86, 0xc7, 0x0e, 0xbf, 0x0a, 0x0c, 0x41, 0x69, 0x26, 0xae, 0x49, 0x16, 0x59, 0x5e, 0x50, 0x5d, 0x44, 0x13, 0x9b, 0x25, 0x88, 0x5c, 0x3f, 0x3f, 0x5c, 0x4f, 0x57, 0x43, 0x0d, 0x2c, 0x05, 0x2c, 0x05, 0x31, 0x0a, 0x2f, 0x0f, 0x32, 0x05, 0x31, 0x31, 0x08, 0x2f, 0x06, 0x3d, 0x02, 0x3b, 0x06, 0x37, 0x37, 0x37, 0x37, 0x3d, 0x33, 0x05, 0x32, 0x0e, 0x31, 0x38, 0x07, 0x31, 0x31, 0x7b, 0x05, 0x05, 0x13, 0x39, 0x30, 0x38, 0x68, 0x4e, 0x1d, 0x25, 0x1e, 0x62, 0x5c, 0x44, 0x68, 0x2c, 0x0f, 0x29, 0x68, 0x3f, 0x12, 0x05, 0xcc, 0x31, 0x06, 0x37, 0x49, 0x32, 0x06, 0x31, 0x21, 0x31, 0x07, 0x32, 0x18, 0x32, 0x06, 0x32, 0x04, 0x32, 0x05, 0x33, 0x0a, 0x32, 0x07, 0x31, 0x00, 0x00, 0x01, 0x00, 0x9a, 0x00, 0x00, 0x05, 0xdb, 0x05, 0xd8, 0x00, 0x26, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x01, 0x07, 0x14, 0x17, 0x25, 0x32, 0x17, 0x15, 0x14, 0x23, 0x05, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x34, 0x37, 0x00, 0x37, 0x36, 0x35, 0x34, 0x27, 0x23, 0x05, 0x22, 0x27, 0x35, 0x34, 0x37, 0x33, 0x03, 0xd5, 0x81, 0x65, 0x2f, 0x6f, 0xfd, 0xae, 0x0a, 0x57, 0x03, 0x16, 0x46, 0x08, 0x5e, 0xfc, 0xf7, 0x91, 0x61, 0x18, 0x7d, 0x02, 0x2f, 0x12, 0x0a, 0x58, 0x0a, 0xfd, 0x09, 0x33, 0x0a, 0x58, 0x0d, 0x05, 0xd8, 0x8d, 0x4d, 0x4f, 0x8a, 0x62, 0xfd, 0xa0, 0x3e, 0x59, 0x1a, 0xd1, 0x61, 0x03, 0x59, 0xc6, 0xae, 0x35, 0x38, 0x18, 0x8a, 0x6c, 0x02, 0x37, 0x1b, 0x1b, 0x16, 0x50, 0x20, 0xcc, 0x50, 0x1e, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd8, 0x00, 0x11, 0x00, 0x24, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x46, 0x00, 0x58, 0x00, 0x00, 0x01, 0x20, 0x13, 0x16, 0x15, 0x10, 0x05, 0x06, 0x2b, 0x01, 0x20, 0x03, 0x26, 0x3d, 0x01, 0x10, 0x01, 0x36, 0x05, 0x26, 0x23, 0x20, 0x03, 0x06, 0x15, 0x10, 0x17, 0x16, 0x33, 0x20, 0x13, 0x36, 0x3d, 0x01, 0x10, 0x25, 0x26, 0x01, 0x23, 0x22, 0x27, 0x13, 0x16, 0x3b, 0x01, 0x32, 0x37, 0x13, 0x06, 0x01, 0x06, 0x1d, 0x01, 0x21, 0x35, 0x10, 0x25, 0x36, 0x37, 0x13, 0x06, 0x25, 0x16, 0x17, 0x21, 0x26, 0x27, 0x26, 0x27, 0x13, 0x16, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x34, 0x37, 0x36, 0x03, 0x2e, 0x01, 0x59, 0xee, 0x66, 0xfe, 0xe3, 0xae, 0xbf, 0x1d, 0xfe, 0xaa, 0xec, 0x59, 0x01, 0x30, 0xa7, 0x01, 0xe8, 0x96, 0x96, 0xfe, 0xf2, 0xd4, 0x71, 0xfb, 0xa0, 0xc9, 0x01, 0x33, 0xd2, 0x50, 0xfe, 0xce, 0x04, 0xfe, 0xf2, 0x19, 0x97, 0x7f, 0xbc, 0x2b, 0x32, 0x08, 0x2d, 0x29, 0xbf, 0x7f, 0xfe, 0xfd, 0x56, 0xfe, 0x82, 0x01, 0x02, 0x10, 0x11, 0xbd, 0x06, 0x02, 0x45, 0x56, 0x03, 0xfe, 0x80, 0x01, 0x1c, 0x1e, 0x27, 0xbd, 0x71, 0xfe, 0x75, 0x49, 0x33, 0x16, 0x3d, 0x25, 0x29, 0x07, 0x48, 0x33, 0x12, 0x41, 0x23, 0x05, 0xd8, 0xfe, 0x8d, 0xaf, 0xd6, 0xfe, 0xb0, 0xfd, 0x93, 0x01, 0x83, 0xae, 0xb2, 0x1c, 0x01, 0x53, 0x01, 0x02, 0x84, 0xac, 0x5d, 0xfe, 0xd9, 0xb1, 0xc2, 0xfe, 0xc4, 0xe2, 0x8a, 0x01, 0x5a, 0x96, 0xa6, 0x0f, 0x01, 0x59, 0xe0, 0x04, 0xfb, 0x48, 0x59, 0x01, 0x6f, 0x1f, 0x1d, 0xfe, 0x92, 0x58, 0x03, 0x28, 0x49, 0x5f, 0x05, 0x10, 0x01, 0x20, 0xdb, 0x0d, 0x0c, 0xfe, 0x92, 0x04, 0x8f, 0x91, 0xb0, 0x3b, 0x2e, 0x32, 0x19, 0x01, 0x6c, 0x4f, 0xfe, 0xcf, 0x50, 0x25, 0x2e, 0x47, 0x36, 0x1f, 0x52, 0x25, 0x26, 0x05, 0x49, 0x38, 0x1c, 0x00, 0x00, 0x06, 0x00, 0x5a, 0x00, 0x00, 0x06, 0x1b, 0x05, 0xd8, 0x00, 0x0f, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6c, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x36, 0x37, 0x16, 0x15, 0x14, 0x06, 0x07, 0x26, 0x35, 0x34, 0x03, 0x26, 0x23, 0x22, 0x06, 0x07, 0x26, 0x27, 0x36, 0x33, 0x32, 0x16, 0x17, 0x06, 0x01, 0x14, 0x16, 0x17, 0x06, 0x07, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x16, 0x01, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x16, 0x33, 0x32, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x17, 0x06, 0x15, 0x14, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x33, 0x16, 0x17, 0x16, 0x11, 0x15, 0x2e, 0x01, 0x23, 0x06, 0x07, 0x27, 0x36, 0x35, 0x34, 0x27, 0x35, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x27, 0x26, 0x27, 0x12, 0x37, 0x0e, 0x01, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x06, 0x15, 0x14, 0x17, 0x07, 0x26, 0x2b, 0x01, 0x22, 0x23, 0x22, 0x06, 0x03, 0xcc, 0x3d, 0x41, 0x01, 0x21, 0x20, 0x02, 0x6d, 0x4d, 0x09, 0x0c, 0x39, 0x44, 0x07, 0x52, 0x37, 0x1e, 0x13, 0x4e, 0x69, 0x06, 0x78, 0x42, 0x16, 0xfe, 0x57, 0x52, 0x3f, 0x03, 0x0e, 0x5e, 0x64, 0x02, 0x26, 0x03, 0x61, 0x62, 0x96, 0x29, 0x2d, 0x94, 0x52, 0x01, 0x37, 0x6b, 0x53, 0x57, 0x6f, 0x73, 0x4c, 0x48, 0x32, 0xa5, 0x34, 0x2b, 0x19, 0x3e, 0x1f, 0x1d, 0x1c, 0x1a, 0x3a, 0x18, 0x32, 0x38, 0x90, 0x3e, 0x48, 0xfe, 0xc9, 0x92, 0x53, 0x0f, 0x3e, 0x03, 0x5f, 0x6c, 0xaf, 0x0b, 0xbd, 0x65, 0xa5, 0x75, 0x3f, 0x01, 0x39, 0xa3, 0x4c, 0x30, 0x16, 0xfb, 0xf9, 0x04, 0x6d, 0x62, 0xa2, 0x10, 0x02, 0x27, 0x02, 0x0f, 0xf9, 0xa0, 0x1e, 0x22, 0x5b, 0xac, 0x01, 0x3c, 0x02, 0x3a, 0x65, 0x96, 0x0c, 0x03, 0x04, 0x73, 0xa0, 0x01, 0x91, 0x28, 0x8b, 0x41, 0x0c, 0x0c, 0x0e, 0x05, 0x13, 0x12, 0x5f, 0xc3, 0x25, 0x18, 0x19, 0x0e, 0x02, 0x0d, 0x23, 0x04, 0x2b, 0x16, 0x1c, 0x42, 0x05, 0x37, 0x21, 0xfe, 0xea, 0x4e, 0x8f, 0x20, 0x26, 0x22, 0x2e, 0xcb, 0x4f, 0x10, 0x0f, 0x06, 0xfd, 0xb2, 0x53, 0x06, 0x24, 0xaa, 0x02, 0x58, 0x45, 0x2f, 0x4b, 0x28, 0x41, 0x61, 0x5d, 0x64, 0x4c, 0x50, 0x2a, 0x18, 0x17, 0x27, 0x46, 0x43, 0x61, 0x59, 0x72, 0x3d, 0x05, 0xa0, 0x43, 0xd9, 0x34, 0x34, 0x6d, 0x6f, 0x0a, 0x43, 0x82, 0xfe, 0xff, 0x0a, 0x9d, 0xb6, 0x0a, 0x93, 0x28, 0x07, 0x07, 0x46, 0x19, 0x4b, 0x1f, 0x9c, 0x57, 0x59, 0x1a, 0x8e, 0xfc, 0x46, 0x18, 0x19, 0x95, 0xa1, 0x76, 0x02, 0x62, 0x89, 0x01, 0x0e, 0x70, 0x68, 0xb4, 0x27, 0x55, 0x44, 0x98, 0x27, 0x52, 0x1d, 0x3c, 0x09, 0x0a, 0x24, 0x88, 0x93, 0x00, 0x17, 0x00, 0x5a, 0xff, 0xfc, 0x04, 0x77, 0x05, 0xd1, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x23, 0x00, 0x2b, 0x00, 0x3f, 0x00, 0x56, 0x00, 0x6d, 0x00, 0x83, 0x00, 0xa2, 0x00, 0xad, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc9, 0x00, 0xd0, 0x00, 0xd5, 0x00, 0xda, 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xed, 0x00, 0xf4, 0x01, 0x23, 0x00, 0x00, 0x01, 0x06, 0x15, 0x14, 0x33, 0x32, 0x37, 0x26, 0x17, 0x22, 0x07, 0x06, 0x23, 0x22, 0x27, 0x37, 0x27, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x06, 0x07, 0x26, 0x27, 0x36, 0x35, 0x34, 0x01, 0x06, 0x07, 0x23, 0x26, 0x37, 0x03, 0x16, 0x33, 0x32, 0x35, 0x34, 0x27, 0x26, 0x13, 0x15, 0x06, 0x23, 0x22, 0x27, 0x35, 0x26, 0x35, 0x36, 0x37, 0x16, 0x17, 0x06, 0x15, 0x14, 0x04, 0x07, 0x23, 0x26, 0x27, 0x15, 0x27, 0x35, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x15, 0x14, 0x04, 0x15, 0x14, 0x07, 0x27, 0x36, 0x35, 0x34, 0x27, 0x34, 0x03, 0x15, 0x27, 0x35, 0x24, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x15, 0x14, 0x17, 0x06, 0x04, 0x17, 0x06, 0x07, 0x27, 0x36, 0x35, 0x34, 0x07, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x06, 0x15, 0x14, 0x04, 0x17, 0x06, 0x07, 0x26, 0x27, 0x36, 0x35, 0x34, 0x27, 0x15, 0x27, 0x13, 0x15, 0x27, 0x35, 0x24, 0x35, 0x36, 0x37, 0x33, 0x32, 0x17, 0x07, 0x17, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x15, 0x14, 0x04, 0x17, 0x06, 0x07, 0x26, 0x27, 0x36, 0x27, 0x36, 0x01, 0x14, 0x1e, 0x01, 0x33, 0x26, 0x34, 0x37, 0x22, 0x0e, 0x01, 0x05, 0x16, 0x17, 0x37, 0x26, 0x27, 0x16, 0x17, 0x37, 0x26, 0x27, 0x16, 0x17, 0x37, 0x26, 0x27, 0x16, 0x07, 0x37, 0x26, 0x27, 0x14, 0x15, 0x14, 0x07, 0x17, 0x35, 0x34, 0x27, 0x06, 0x07, 0x17, 0x36, 0x35, 0x34, 0x05, 0x17, 0x36, 0x37, 0x06, 0x07, 0x17, 0x36, 0x37, 0x06, 0x07, 0x17, 0x36, 0x37, 0x06, 0x1f, 0x01, 0x35, 0x34, 0x37, 0x06, 0x17, 0x37, 0x26, 0x35, 0x34, 0x35, 0x06, 0x15, 0x3f, 0x01, 0x26, 0x27, 0x14, 0x15, 0x14, 0x17, 0x15, 0x27, 0x35, 0x26, 0x23, 0x22, 0x07, 0x22, 0x27, 0x36, 0x25, 0x16, 0x17, 0x16, 0x33, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x31, 0x14, 0x31, 0x15, 0x36, 0x37, 0x04, 0x17, 0x06, 0x23, 0x26, 0x23, 0x22, 0x03, 0x02, 0x04, 0x0a, 0x0b, 0x16, 0x09, 0x47, 0x06, 0x07, 0x3c, 0x31, 0x17, 0x14, 0x52, 0x61, 0x20, 0x37, 0x0a, 0x0c, 0xb8, 0x0b, 0x01, 0x7f, 0x3f, 0x8e, 0xf7, 0xfe, 0xae, 0x56, 0x1c, 0x0d, 0x01, 0x4d, 0x5d, 0x18, 0x0c, 0x09, 0x05, 0x1f, 0xd8, 0x0a, 0x18, 0x1e, 0x03, 0x9d, 0x04, 0x3a, 0x29, 0x28, 0x37, 0x01, 0x17, 0x02, 0x0e, 0x17, 0x68, 0x43, 0xfc, 0x04, 0x02, 0x73, 0x2f, 0x4e, 0x9d, 0x01, 0x8a, 0x65, 0x2c, 0x3e, 0x01, 0x48, 0x43, 0xfe, 0xb7, 0x02, 0x04, 0x66, 0x45, 0x5f, 0xba, 0x01, 0x09, 0x02, 0x37, 0x02, 0x04, 0x87, 0x5e, 0x93, 0xe4, 0xf2, 0x05, 0x01, 0x65, 0x41, 0x42, 0x93, 0x01, 0xe0, 0x02, 0x03, 0x9d, 0x1e, 0x34, 0x9e, 0xaa, 0x43, 0x43, 0x43, 0xfe, 0xa7, 0x0c, 0xb8, 0x08, 0x37, 0x2e, 0x62, 0x53, 0x15, 0x15, 0x33, 0x3b, 0x07, 0x07, 0x25, 0x02, 0x89, 0x06, 0x06, 0x9d, 0x39, 0x64, 0xed, 0x02, 0x0b, 0xfe, 0x9e, 0x10, 0x1d, 0x11, 0x0e, 0x0e, 0x10, 0x1e, 0x10, 0x01, 0x8d, 0x69, 0x27, 0x19, 0x57, 0x88, 0x68, 0x22, 0x26, 0x56, 0x71, 0x48, 0x0f, 0x2c, 0x37, 0x75, 0x30, 0x01, 0x37, 0x23, 0x5d, 0x13, 0x36, 0x37, 0x2d, 0x2f, 0x36, 0x27, 0xfd, 0x5d, 0x19, 0x28, 0x68, 0x52, 0x28, 0x26, 0x22, 0x68, 0x5a, 0x12, 0x2c, 0x0f, 0x48, 0x4b, 0x0e, 0x38, 0x2e, 0x43, 0x3a, 0x37, 0x14, 0x23, 0x5d, 0x36, 0x2f, 0x2d, 0xce, 0x43, 0x29, 0x40, 0x20, 0x26, 0xf0, 0x50, 0x4c, 0x01, 0x3c, 0x14, 0x50, 0x02, 0x01, 0x03, 0x02, 0x12, 0x14, 0x14, 0x25, 0x26, 0x25, 0x15, 0x14, 0x12, 0x03, 0x02, 0x4f, 0x15, 0x01, 0x3b, 0x4c, 0x50, 0xf0, 0x26, 0x21, 0x3d, 0x04, 0x20, 0x08, 0x04, 0x09, 0x0a, 0x14, 0x3f, 0x02, 0x18, 0x05, 0x17, 0x19, 0x3e, 0x02, 0x04, 0x7d, 0x3e, 0x20, 0x11, 0x09, 0x14, 0x2a, 0x30, 0xfc, 0x74, 0x22, 0x3c, 0x48, 0x23, 0x03, 0xa6, 0x0b, 0x08, 0x05, 0x09, 0x09, 0xfc, 0x2d, 0x38, 0x1a, 0x38, 0x29, 0x1e, 0x36, 0x31, 0x18, 0x0d, 0x06, 0x15, 0x15, 0x29, 0x36, 0x66, 0x38, 0xad, 0x5a, 0x0d, 0x5c, 0x2b, 0x48, 0x44, 0x20, 0x13, 0x09, 0x1a, 0x27, 0x2a, 0x3e, 0x4a, 0x2e, 0x0e, 0x0b, 0x11, 0x1d, 0x05, 0x05, 0x17, 0x01, 0x99, 0x8c, 0x0d, 0x89, 0x26, 0x62, 0x35, 0x16, 0x14, 0x07, 0x0f, 0x1d, 0x02, 0x02, 0x34, 0x43, 0x55, 0x45, 0x20, 0x1b, 0x27, 0x1a, 0x27, 0xa4, 0x21, 0x60, 0x39, 0x1e, 0x0c, 0x07, 0x21, 0x2c, 0x28, 0x4d, 0x54, 0x45, 0x15, 0x0f, 0x0b, 0x1e, 0x2a, 0x21, 0x1d, 0x85, 0x0c, 0x02, 0x04, 0x7f, 0x08, 0x7d, 0x15, 0x71, 0x7e, 0x04, 0x3d, 0x18, 0x17, 0x05, 0x18, 0x02, 0x2f, 0x2b, 0x29, 0x66, 0x5b, 0x14, 0x10, 0x0f, 0x1c, 0x34, 0x1f, 0x02, 0x66, 0x12, 0x20, 0x11, 0x21, 0x42, 0x22, 0x11, 0x20, 0x3c, 0x40, 0x30, 0x26, 0x39, 0x15, 0x63, 0x3f, 0x22, 0x56, 0x2b, 0x80, 0x47, 0x13, 0x6f, 0x4d, 0x93, 0x4b, 0x08, 0x7e, 0x61, 0x11, 0x0f, 0x84, 0x3f, 0x0b, 0x0c, 0x7d, 0x62, 0x89, 0x39, 0x19, 0x65, 0x5c, 0x0d, 0x50, 0x26, 0x30, 0x40, 0x11, 0x6b, 0x22, 0x3f, 0x63, 0x2a, 0x89, 0x13, 0x47, 0x80, 0x45, 0x89, 0x08, 0x06, 0x4a, 0x8e, 0x58, 0x8d, 0x0b, 0x3f, 0x84, 0x0f, 0x11, 0x65, 0x7d, 0x04, 0x19, 0x39, 0x89, 0x0d, 0x0d, 0x5c, 0xab, 0xce, 0x06, 0xc2, 0x34, 0x0c, 0xa5, 0x5c, 0x06, 0x36, 0x1e, 0x01, 0x18, 0x01, 0x02, 0x0a, 0x27, 0x16, 0x15, 0x27, 0x16, 0x16, 0x27, 0x15, 0x16, 0x27, 0x0a, 0x02, 0x01, 0x01, 0x16, 0x1e, 0x36, 0x06, 0x5c, 0xa5, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x99, 0x00, 0x00, 0x04, 0xc7, 0x05, 0xd9, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x01, 0x26, 0x27, 0x06, 0x07, 0x16, 0x17, 0x36, 0x35, 0x03, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x15, 0x14, 0x07, 0x33, 0x32, 0x37, 0x11, 0x26, 0x2b, 0x02, 0x11, 0x14, 0x17, 0x21, 0x36, 0x35, 0x11, 0x2b, 0x01, 0x22, 0x07, 0x11, 0x16, 0x33, 0x03, 0x20, 0x02, 0x6d, 0x6d, 0x01, 0x07, 0x67, 0x6f, 0xb1, 0x6b, 0x0b, 0x03, 0xb5, 0xb6, 0x03, 0x76, 0x93, 0xa3, 0x9c, 0x98, 0xa1, 0x05, 0x94, 0x59, 0xfe, 0xc9, 0x59, 0x97, 0x06, 0xa1, 0x98, 0x9d, 0xa2, 0x04, 0xde, 0xb1, 0x02, 0x02, 0xb1, 0x8e, 0x71, 0x58, 0x9f, 0xfe, 0xf1, 0x65, 0xb8, 0xf3, 0x02, 0x02, 0xf3, 0x0e, 0xb7, 0x58, 0x63, 0xfe, 0xf7, 0x36, 0xfe, 0x0c, 0xb5, 0xae, 0xae, 0xb5, 0x01, 0xf4, 0x36, 0x01, 0x09, 0x63, 0x00, 0x00, 0x03, 0x00, 0x99, 0xff, 0xfd, 0x04, 0x14, 0x05, 0xd9, 0x00, 0x03, 0x00, 0x20, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x15, 0x33, 0x35, 0x27, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x15, 0x33, 0x05, 0x15, 0x21, 0x11, 0x17, 0x15, 0x27, 0x03, 0x23, 0x11, 0x27, 0x35, 0x17, 0x11, 0x21, 0x35, 0x21, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x35, 0x23, 0x35, 0x23, 0x15, 0x23, 0x15, 0x33, 0x01, 0xf5, 0xb6, 0xa5, 0x9a, 0x71, 0x71, 0x08, 0x01, 0x6c, 0xfe, 0x8c, 0x81, 0x7a, 0x01, 0xa0, 0x79, 0x79, 0xfe, 0x93, 0x01, 0x6d, 0x6a, 0x94, 0x40, 0xf1, 0xf1, 0x40, 0xf0, 0xf0, 0x05, 0x40, 0x3c, 0x3c, 0x33, 0x66, 0x66, 0xa2, 0x58, 0x01, 0xaf, 0xfd, 0xe8, 0x8b, 0x9c, 0x85, 0xfe, 0xee, 0x01, 0xbc, 0x86, 0x9b, 0x82, 0x01, 0x71, 0xb0, 0x58, 0xa2, 0xfc, 0xcf, 0x01, 0xbb, 0x47, 0x63, 0x63, 0x47, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x99, 0x00, 0x00, 0x05, 0x0c, 0x07, 0x4a, 0x00, 0x07, 0x00, 0x20, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x10, 0x26, 0x23, 0x01, 0x11, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x11, 0x37, 0x33, 0x09, 0x01, 0x23, 0x03, 0x11, 0x23, 0x11, 0x03, 0x23, 0x09, 0x01, 0x33, 0x02, 0xd7, 0xbc, 0x69, 0x72, 0x72, 0x69, 0xfe, 0xb0, 0x01, 0x50, 0xba, 0xbf, 0xbf, 0xba, 0xbc, 0xc4, 0xc6, 0xfe, 0x90, 0x01, 0x83, 0xc5, 0xd7, 0x95, 0xe5, 0xc5, 0x01, 0x8b, 0xfe, 0x96, 0xc6, 0x06, 0xa7, 0xfd, 0xd8, 0x90, 0x01, 0x08, 0x90, 0xfc, 0x04, 0x04, 0x9f, 0xdf, 0xd8, 0xd9, 0xde, 0xfe, 0xcd, 0xed, 0xfe, 0x42, 0xfe, 0x28, 0x01, 0x06, 0xfe, 0xfa, 0x01, 0x17, 0xfe, 0xe9, 0x01, 0xe1, 0x01, 0xb5, 0x00, 0x01, 0x00, 0x99, 0x00, 0x00, 0x03, 0x54, 0x05, 0xd7, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x33, 0x17, 0x15, 0x33, 0x17, 0x15, 0x07, 0x23, 0x15, 0x21, 0x17, 0x15, 0x07, 0x21, 0x11, 0x07, 0x23, 0x27, 0x11, 0x21, 0x27, 0x35, 0x37, 0x21, 0x35, 0x23, 0x27, 0x35, 0x37, 0x33, 0x35, 0x01, 0xa8, 0x9a, 0x05, 0x95, 0x04, 0x04, 0x95, 0x01, 0x07, 0x05, 0x05, 0xfe, 0xf9, 0x05, 0x9a, 0x06, 0xfe, 0xfc, 0x05, 0x05, 0x01, 0x04, 0x92, 0x05, 0x05, 0x92, 0x05, 0xd7, 0x05, 0x9b, 0x06, 0x94, 0x06, 0x71, 0x06, 0x98, 0x05, 0xfc, 0x82, 0x05, 0x05, 0x03, 0x7e, 0x05, 0x98, 0x06, 0x71, 0x06, 0x94, 0x06, 0x9b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x99, 0xff, 0xfd, 0x05, 0xdc, 0x05, 0xd5, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x21, 0x17, 0x15, 0x07, 0x23, 0x11, 0x21, 0x35, 0x37, 0x33, 0x17, 0x11, 0x07, 0x23, 0x27, 0x35, 0x21, 0x11, 0x33, 0x17, 0x15, 0x07, 0x21, 0x27, 0x35, 0x37, 0x33, 0x11, 0x21, 0x15, 0x07, 0x23, 0x27, 0x11, 0x37, 0x33, 0x17, 0x15, 0x21, 0x11, 0x23, 0x27, 0x35, 0x02, 0x75, 0x01, 0x8a, 0x06, 0x06, 0x90, 0x02, 0x02, 0x06, 0x5f, 0x05, 0x05, 0x5f, 0x06, 0xfd, 0xfe, 0x90, 0x06, 0x06, 0xfe, 0x76, 0x05, 0x05, 0x99, 0xfd, 0xfd, 0x05, 0x68, 0x05, 0x05, 0x68, 0x05, 0x02, 0x03, 0x99, 0x05, 0x05, 0xd5, 0x06, 0x77, 0x06, 0xfd, 0xd1, 0xa1, 0x06, 0x06, 0xfe, 0x49, 0x06, 0x06, 0x9e, 0xfd, 0xc8, 0x06, 0x6a, 0x06, 0x06, 0x6a, 0x06, 0x02, 0x38, 0x9e, 0x06, 0x06, 0x01, 0xb7, 0x06, 0x06, 0xa1, 0x02, 0x2f, 0x06, 0x77, 0x00, 0x02, 0x00, 0xa0, 0x00, 0x00, 0x05, 0xd6, 0x05, 0xd8, 0x00, 0x1b, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x33, 0x32, 0x17, 0x23, 0x27, 0x20, 0x03, 0x06, 0x15, 0x10, 0x05, 0x16, 0x33, 0x37, 0x15, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x20, 0x03, 0x26, 0x35, 0x10, 0x25, 0x36, 0x01, 0x33, 0x32, 0x17, 0x33, 0x15, 0x07, 0x16, 0x15, 0x27, 0x07, 0x23, 0x35, 0x37, 0x27, 0x35, 0x33, 0x03, 0x40, 0x12, 0xc7, 0xbd, 0x05, 0xd7, 0xfe, 0xcb, 0xbc, 0x55, 0x01, 0x34, 0x7b, 0x8c, 0xe7, 0x90, 0x7c, 0x49, 0x30, 0x19, 0xfe, 0xb5, 0xd6, 0x77, 0x01, 0x5f, 0x9b, 0x02, 0x3f, 0x03, 0x05, 0x38, 0xbc, 0x97, 0x3a, 0x9f, 0x98, 0x03, 0x3c, 0x9b, 0xc0, 0x05, 0xd8, 0x92, 0x36, 0xfe, 0xca, 0x9e, 0xb9, 0xfe, 0x92, 0xd6, 0x47, 0x32, 0x06, 0x6b, 0x1a, 0x0b, 0x01, 0x3e, 0xc0, 0xe9, 0x01, 0xaa, 0xee, 0x59, 0xfe, 0x33, 0xc9, 0x03, 0x7e, 0xbb, 0x11, 0x7c, 0x7c, 0x03, 0xc9, 0x7e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdd, 0x05, 0xd9, 0x00, 0x16, 0x00, 0x4f, 0x00, 0x62, 0x00, 0x73, 0x00, 0x00, 0x01, 0x16, 0x33, 0x32, 0x37, 0x16, 0x33, 0x32, 0x37, 0x35, 0x33, 0x17, 0x15, 0x14, 0x0f, 0x01, 0x22, 0x27, 0x06, 0x23, 0x22, 0x27, 0x34, 0x17, 0x33, 0x16, 0x17, 0x32, 0x15, 0x03, 0x33, 0x24, 0x11, 0x34, 0x27, 0x35, 0x16, 0x11, 0x15, 0x10, 0x07, 0x06, 0x07, 0x15, 0x16, 0x3b, 0x01, 0x15, 0x06, 0x2b, 0x01, 0x22, 0x07, 0x27, 0x23, 0x22, 0x27, 0x35, 0x33, 0x32, 0x37, 0x35, 0x27, 0x26, 0x27, 0x26, 0x35, 0x10, 0x3f, 0x01, 0x15, 0x06, 0x15, 0x10, 0x05, 0x35, 0x03, 0x35, 0x37, 0x32, 0x27, 0x15, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x15, 0x23, 0x26, 0x27, 0x26, 0x35, 0x10, 0x37, 0x36, 0x33, 0x34, 0x25, 0x16, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x07, 0x34, 0x37, 0x36, 0x3d, 0x01, 0x10, 0x25, 0x02, 0x9f, 0x19, 0x39, 0x2a, 0x1d, 0x22, 0x27, 0x3c, 0x13, 0x04, 0x02, 0x3e, 0x1b, 0x28, 0x1f, 0x1e, 0x28, 0x49, 0x0f, 0xa0, 0x02, 0x2d, 0x1f, 0x07, 0x09, 0x02, 0x01, 0x07, 0x63, 0xc7, 0xc9, 0x45, 0x2a, 0x48, 0x95, 0x17, 0x69, 0x41, 0x74, 0x14, 0x3e, 0x3d, 0x82, 0x32, 0x7b, 0x36, 0x6d, 0x4e, 0x50, 0x70, 0x20, 0x5a, 0xb4, 0x1d, 0x69, 0x01, 0x08, 0x10, 0x03, 0x1f, 0xe6, 0x55, 0x3b, 0x78, 0x83, 0x02, 0x8e, 0x54, 0x22, 0xf1, 0x6d, 0x20, 0x02, 0x3b, 0x77, 0x75, 0x9e, 0x95, 0x50, 0x1c, 0x31, 0x52, 0xfe, 0xf4, 0x05, 0xd9, 0x4b, 0x30, 0x30, 0x44, 0x07, 0x28, 0x05, 0x3b, 0x1b, 0x04, 0x2c, 0x2c, 0x65, 0x22, 0x87, 0x40, 0x0b, 0x05, 0xfc, 0x20, 0xe4, 0x01, 0x70, 0xc2, 0xcf, 0x03, 0xd7, 0xfe, 0xeb, 0x24, 0xfe, 0xf1, 0xdd, 0x42, 0x16, 0x05, 0x28, 0x05, 0x21, 0x63, 0x63, 0x1c, 0x05, 0x2a, 0x03, 0x40, 0x72, 0x4a, 0xb1, 0xb1, 0x01, 0x01, 0xe6, 0x1f, 0x05, 0xc0, 0xe2, 0xfe, 0xa7, 0xf5, 0x02, 0x03, 0x26, 0x16, 0xa9, 0x2a, 0x06, 0x45, 0x63, 0xcc, 0xef, 0xe9, 0xd6, 0x02, 0x4a, 0xe9, 0x6b, 0x67, 0x01, 0x0c, 0xcd, 0x46, 0x04, 0x02, 0x1e, 0x70, 0xb7, 0xd8, 0x2f, 0xd4, 0xb6, 0x51, 0x06, 0x07, 0x52, 0xaf, 0xbf, 0x02, 0x01, 0x6d, 0xf4, 0x00, 0x03, 0x00, 0x99, 0x00, 0x00, 0x04, 0x85, 0x05, 0xd9, 0x00, 0x5b, 0x00, 0x66, 0x00, 0x6e, 0x00, 0x00, 0x01, 0x32, 0x17, 0x0f, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x17, 0x23, 0x15, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x37, 0x33, 0x16, 0x11, 0x10, 0x03, 0x26, 0x23, 0x22, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x15, 0x06, 0x23, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x15, 0x14, 0x15, 0x14, 0x17, 0x14, 0x23, 0x22, 0x35, 0x36, 0x3d, 0x01, 0x06, 0x15, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x34, 0x36, 0x35, 0x34, 0x23, 0x22, 0x07, 0x02, 0x11, 0x34, 0x37, 0x33, 0x17, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x35, 0x23, 0x35, 0x26, 0x35, 0x34, 0x37, 0x2f, 0x01, 0x36, 0x03, 0x14, 0x17, 0x33, 0x36, 0x35, 0x34, 0x27, 0x06, 0x07, 0x06, 0x25, 0x06, 0x15, 0x14, 0x17, 0x36, 0x35, 0x34, 0x02, 0x8f, 0x3c, 0x49, 0x11, 0x0d, 0x72, 0x2e, 0x32, 0xb8, 0x01, 0x6c, 0x6d, 0x80, 0x79, 0x71, 0x13, 0x05, 0xd2, 0x86, 0x6c, 0x47, 0x32, 0x6c, 0x1b, 0x0c, 0x26, 0x0a, 0x08, 0x28, 0x06, 0x35, 0x54, 0x48, 0x5e, 0x64, 0x48, 0x8a, 0x07, 0x33, 0x05, 0x25, 0x0d, 0x87, 0x29, 0x4a, 0x68, 0x8b, 0xcd, 0x05, 0x13, 0x71, 0xc1, 0x38, 0x6d, 0x6b, 0xb7, 0xd6, 0x16, 0x0e, 0x4e, 0xb9, 0x79, 0x04, 0x3f, 0x1a, 0x50, 0x2e, 0x24, 0x01, 0x4b, 0x1f, 0x3b, 0x81, 0x05, 0xd9, 0x4b, 0x0f, 0x7c, 0x2e, 0x50, 0x51, 0x55, 0xc7, 0x62, 0x4b, 0x78, 0x81, 0x9d, 0xc6, 0xb0, 0x72, 0x13, 0xa5, 0xfe, 0xfe, 0xfe, 0xe0, 0xfe, 0xc9, 0xae, 0x2d, 0x1c, 0x93, 0x26, 0x2a, 0x02, 0x03, 0x3b, 0x02, 0x22, 0xee, 0x31, 0x96, 0x03, 0x04, 0x46, 0x71, 0x3b, 0x3c, 0x74, 0x4d, 0x92, 0x5d, 0xbf, 0x23, 0x3b, 0x40, 0xa4, 0x22, 0x2b, 0xad, 0x01, 0x21, 0x01, 0x4d, 0xe9, 0xa6, 0x13, 0x79, 0xae, 0xfb, 0xa3, 0x2f, 0x12, 0x78, 0x4b, 0x5c, 0xcc, 0xbe, 0x67, 0x7c, 0x12, 0x48, 0xfd, 0xff, 0x92, 0x4a, 0x69, 0x8b, 0x53, 0x7e, 0x19, 0x4a, 0x3f, 0xa2, 0x73, 0x63, 0x89, 0x66, 0x3d, 0xa8, 0x98, 0x00, 0x00, 0x00, 0x01, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdb, 0x05, 0xd7, 0x00, 0x32, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x17, 0x07, 0x23, 0x27, 0x06, 0x23, 0x22, 0x27, 0x15, 0x03, 0x23, 0x26, 0x27, 0x36, 0x01, 0x36, 0x33, 0x16, 0x33, 0x32, 0x37, 0x27, 0x07, 0x23, 0x26, 0x27, 0x13, 0x04, 0x15, 0x07, 0x16, 0x17, 0x35, 0x36, 0x3d, 0x01, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x22, 0x07, 0x36, 0x03, 0x84, 0xd5, 0xbc, 0x87, 0x70, 0xae, 0x7e, 0x02, 0xa7, 0x94, 0xc3, 0x9a, 0x80, 0xea, 0x03, 0xb7, 0x04, 0x17, 0x01, 0x37, 0x15, 0x07, 0x65, 0x8f, 0xac, 0x87, 0xc3, 0x61, 0x05, 0xa9, 0x08, 0xd2, 0x00, 0xff, 0x72, 0xcf, 0x1a, 0x3c, 0xe2, 0x7c, 0x6b, 0x21, 0x58, 0x6c, 0x99, 0x05, 0xd7, 0xbd, 0x9b, 0xd7, 0xc9, 0x8a, 0x94, 0x83, 0xaa, 0x6e, 0x58, 0x03, 0xfe, 0x31, 0x8d, 0x07, 0x19, 0x01, 0x98, 0x1d, 0x55, 0x68, 0xc6, 0x73, 0x74, 0x0c, 0x01, 0x02, 0x0e, 0x05, 0x9f, 0xaf, 0x0e, 0x02, 0x5a, 0x7c, 0x24, 0xfe, 0x65, 0x45, 0x37, 0x8f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd8, 0x00, 0x0b, 0x00, 0x12, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x21, 0x00, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x14, 0x17, 0x01, 0x03, 0x06, 0x00, 0x13, 0x16, 0x17, 0x1b, 0x01, 0x36, 0x37, 0x09, 0x01, 0x36, 0x35, 0x34, 0x00, 0x27, 0x11, 0x99, 0x01, 0x8a, 0x01, 0x17, 0x01, 0x18, 0x01, 0x89, 0xfe, 0x77, 0xfe, 0xe8, 0xfe, 0xe9, 0xfe, 0x76, 0x89, 0x6d, 0x01, 0x7f, 0x02, 0xb0, 0xfe, 0xc6, 0x9c, 0x9e, 0xad, 0x01, 0x56, 0xb8, 0x9a, 0xfe, 0xae, 0x01, 0x8f, 0x65, 0xfe, 0xc4, 0xbd, 0x02, 0xea, 0x01, 0x37, 0x01, 0xb7, 0xfe, 0x49, 0xfe, 0xc9, 0xfe, 0xca, 0xfe, 0x4c, 0x01, 0xb4, 0x01, 0x36, 0xe5, 0x78, 0x01, 0xf5, 0x01, 0xc2, 0x04, 0xfe, 0xa3, 0xfd, 0x62, 0xb1, 0x06, 0x02, 0x68, 0xfd, 0x96, 0x08, 0xa4, 0x01, 0xb6, 0xfe, 0x97, 0x70, 0xf5, 0xf9, 0x01, 0x5d, 0x04, 0xfe, 0x42, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd8, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x34, 0x00, 0x00, 0x01, 0x15, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x05, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x05, 0x34, 0x26, 0x22, 0x06, 0x15, 0x14, 0x16, 0x32, 0x36, 0x25, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x3a, 0x09, 0xb1, 0x82, 0x84, 0xb4, 0xfe, 0x8c, 0xff, 0x00, 0xfe, 0xfb, 0xfe, 0xa2, 0x12, 0x16, 0x9f, 0x86, 0x81, 0xb2, 0x01, 0x9c, 0x37, 0x22, 0x26, 0x36, 0x36, 0x26, 0x24, 0x35, 0xfd, 0x8b, 0x35, 0x4a, 0x34, 0x34, 0x4a, 0x35, 0x03, 0x81, 0xfe, 0x77, 0xfe, 0xe8, 0xfe, 0xe9, 0xfe, 0x76, 0x01, 0x8a, 0x01, 0x17, 0x01, 0x18, 0x01, 0x89, 0x02, 0xf8, 0x1a, 0x8e, 0xc1, 0xcf, 0x9a, 0x01, 0x16, 0x01, 0x98, 0xfe, 0x7b, 0xfe, 0xc9, 0xac, 0xb2, 0xc0, 0x9e, 0x29, 0x3a, 0x3a, 0x29, 0x2a, 0x3c, 0x3c, 0x2a, 0x2a, 0x3c, 0x3c, 0x2a, 0x29, 0x3a, 0x3c, 0x27, 0xfe, 0xca, 0xfe, 0x4c, 0x01, 0xb4, 0x01, 0x36, 0x01, 0x37, 0x01, 0xb7, 0xfe, 0x49, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x86, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x05, 0x0d, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdd, 0x05, 0xd4, 0x12, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x01, 0x02, 0x85, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x05, 0x0c, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x85, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x05, 0x0d, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x85, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x05, 0x0d, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x85, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x05, 0x0d, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x85, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x05, 0x0d, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x85, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x05, 0x0d, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x85, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x0a, 0x00, 0x79, 0xff, 0xea, 0x05, 0xfb, 0x05, 0xe1, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x46, 0x00, 0x4c, 0x00, 0x52, 0x00, 0x58, 0x00, 0x5e, 0x00, 0x64, 0x00, 0x6a, 0x00, 0x70, 0x00, 0x00, 0x00, 0x14, 0x17, 0x16, 0x33, 0x32, 0x36, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x05, 0x26, 0x34, 0x37, 0x33, 0x36, 0x37, 0x27, 0x36, 0x37, 0x17, 0x36, 0x37, 0x35, 0x36, 0x32, 0x17, 0x15, 0x16, 0x17, 0x37, 0x16, 0x17, 0x07, 0x16, 0x17, 0x33, 0x16, 0x14, 0x07, 0x23, 0x06, 0x07, 0x17, 0x06, 0x07, 0x27, 0x06, 0x07, 0x15, 0x06, 0x23, 0x27, 0x35, 0x26, 0x27, 0x07, 0x26, 0x27, 0x37, 0x26, 0x27, 0x01, 0x36, 0x37, 0x03, 0x06, 0x07, 0x05, 0x16, 0x17, 0x37, 0x26, 0x27, 0x01, 0x36, 0x37, 0x27, 0x06, 0x07, 0x25, 0x16, 0x17, 0x37, 0x26, 0x27, 0x01, 0x26, 0x27, 0x07, 0x16, 0x17, 0x25, 0x06, 0x07, 0x17, 0x36, 0x37, 0x05, 0x06, 0x07, 0x13, 0x36, 0x37, 0x25, 0x26, 0x27, 0x07, 0x16, 0x17, 0x02, 0xa8, 0x2c, 0x2a, 0x3c, 0x3c, 0x54, 0x2b, 0x2a, 0x3b, 0x3c, 0x2a, 0xfd, 0xbf, 0x19, 0x19, 0x65, 0x18, 0x60, 0x4c, 0x0e, 0x59, 0x4a, 0x6f, 0xaf, 0x23, 0x46, 0x24, 0xa4, 0x7c, 0x47, 0x5b, 0x10, 0x4d, 0x5f, 0x19, 0x65, 0x19, 0x19, 0x65, 0x12, 0x66, 0x4d, 0x10, 0x5b, 0x47, 0x7d, 0xa3, 0x24, 0x23, 0x46, 0xa3, 0x7c, 0x49, 0x57, 0x10, 0x49, 0x5d, 0x18, 0x01, 0xc8, 0x1e, 0x20, 0x0b, 0x80, 0x58, 0x01, 0x5a, 0x25, 0x1a, 0xa4, 0x5a, 0x7e, 0xfe, 0xd1, 0x07, 0x14, 0xb7, 0x44, 0x15, 0x02, 0xab, 0x16, 0x05, 0xf7, 0x11, 0x49, 0xfd, 0xad, 0x12, 0x09, 0xf5, 0x14, 0x44, 0x02, 0x6e, 0x07, 0x14, 0xb8, 0x4a, 0x0f, 0xfe, 0x9c, 0x1e, 0x21, 0x0b, 0x7e, 0x5a, 0xfe, 0xa5, 0x1a, 0x23, 0xa6, 0x5a, 0x7f, 0x03, 0x26, 0x84, 0x2f, 0x2f, 0x5e, 0x84, 0x30, 0x30, 0x30, 0xc3, 0x27, 0x4e, 0x27, 0xb7, 0x7c, 0x50, 0x5f, 0x10, 0x50, 0x66, 0x1e, 0x70, 0x1c, 0x1c, 0x70, 0x16, 0x6f, 0x51, 0x0f, 0x60, 0x51, 0x79, 0xb9, 0x27, 0x4e, 0x27, 0xb0, 0x83, 0x50, 0x5c, 0x0b, 0x51, 0x67, 0x1d, 0x70, 0x1c, 0x1c, 0x70, 0x17, 0x6d, 0x51, 0x0b, 0x5c, 0x50, 0x79, 0xba, 0x01, 0x2c, 0x13, 0x0a, 0x01, 0x0d, 0x16, 0x4d, 0xaa, 0x0a, 0x13, 0xc6, 0x4e, 0x15, 0xfe, 0x3e, 0x26, 0x1a, 0xab, 0x60, 0x82, 0x37, 0x1e, 0x22, 0x0a, 0x7f, 0x62, 0xfe, 0x4b, 0x1e, 0x2a, 0x11, 0x8c, 0x56, 0xf4, 0x26, 0x22, 0xac, 0x67, 0x7b, 0x89, 0x12, 0x0b, 0xfe, 0xf0, 0x1e, 0x4d, 0xa5, 0x09, 0x14, 0xc2, 0x4d, 0x1e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x07, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0xd5, 0x20, 0x2e, 0xa4, 0x01, 0xd0, 0xa4, 0x2d, 0x21, 0x67, 0x1a, 0x23, 0x80, 0xfe, 0x94, 0x80, 0x23, 0x1a, 0x03, 0xfd, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xd9, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfd, 0x25, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x8d, 0x28, 0x2b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x37, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0xd5, 0x67, 0x1a, 0x23, 0x80, 0x01, 0x6c, 0x80, 0x23, 0x1a, 0x67, 0x21, 0x2d, 0xa4, 0xfe, 0x30, 0xa4, 0x2e, 0x03, 0xfd, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xd9, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfd, 0xaa, 0x47, 0x2b, 0x27, 0x8e, 0x8e, 0x27, 0x2c, 0x48, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x00, 0x00, 0x00, 0x04, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x21, 0x00, 0x31, 0x00, 0x00, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x23, 0x22, 0x06, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x22, 0x06, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x25, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x27, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x49, 0x35, 0x34, 0x4b, 0x4b, 0x68, 0x4a, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x01, 0x4e, 0x20, 0x2e, 0xa4, 0x01, 0xd0, 0xa4, 0x2d, 0x21, 0x67, 0x1a, 0x23, 0x80, 0xfe, 0x94, 0x80, 0x23, 0x1a, 0x03, 0xfd, 0x3a, 0x53, 0x52, 0x76, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0xfe, 0xb2, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x5b, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x8e, 0x27, 0x2b, 0x00, 0x0a, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0xd8, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x13, 0x00, 0x22, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x3a, 0x00, 0x41, 0x00, 0x49, 0x00, 0x58, 0x00, 0x00, 0x01, 0x33, 0x17, 0x11, 0x07, 0x23, 0x27, 0x11, 0x05, 0x17, 0x15, 0x07, 0x27, 0x25, 0x17, 0x07, 0x23, 0x26, 0x27, 0x35, 0x05, 0x32, 0x1f, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x01, 0x21, 0x17, 0x15, 0x07, 0x21, 0x27, 0x35, 0x25, 0x21, 0x17, 0x15, 0x07, 0x21, 0x27, 0x35, 0x03, 0x33, 0x16, 0x17, 0x15, 0x07, 0x27, 0x35, 0x25, 0x33, 0x17, 0x15, 0x07, 0x27, 0x35, 0x25, 0x33, 0x17, 0x11, 0x07, 0x23, 0x27, 0x11, 0x03, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x27, 0x26, 0x23, 0x22, 0x03, 0x1b, 0x46, 0x05, 0x05, 0x46, 0x06, 0x02, 0x00, 0x34, 0xdf, 0x37, 0xfd, 0x48, 0xe4, 0x38, 0x03, 0xb4, 0x28, 0x01, 0xf8, 0xc2, 0x53, 0x0b, 0xb0, 0x41, 0x2b, 0xa3, 0x5b, 0x21, 0xaa, 0x3f, 0xfd, 0x90, 0x01, 0x32, 0x05, 0x05, 0xfe, 0xce, 0x05, 0x04, 0x05, 0x01, 0x37, 0x06, 0x06, 0xfe, 0xc9, 0x06, 0x40, 0x03, 0x79, 0x66, 0x37, 0xdf, 0xfd, 0xef, 0x03, 0x35, 0xdf, 0x36, 0x01, 0xe5, 0x46, 0x05, 0x05, 0x46, 0x06, 0x20, 0x75, 0x16, 0x3e, 0x70, 0x1d, 0x2c, 0x79, 0x08, 0x39, 0x84, 0x23, 0x05, 0xd8, 0x06, 0xfe, 0xa1, 0x06, 0x06, 0x01, 0x5f, 0x9c, 0x3e, 0x03, 0xff, 0x3f, 0xee, 0xfe, 0x40, 0xc7, 0x37, 0x04, 0xb5, 0xe2, 0x60, 0xbd, 0x64, 0x18, 0xa8, 0x40, 0x5c, 0xb4, 0x68, 0x1b, 0xfe, 0xed, 0x06, 0x50, 0x06, 0x06, 0x50, 0x06, 0x06, 0x50, 0x06, 0x06, 0x50, 0xfe, 0xe7, 0x82, 0x79, 0x03, 0x3f, 0xfd, 0x04, 0x2b, 0x3c, 0x03, 0xfe, 0x3e, 0x04, 0x77, 0x06, 0xfe, 0xa1, 0x06, 0x06, 0x01, 0x5f, 0x02, 0x56, 0x47, 0x7b, 0x3f, 0x2c, 0x72, 0x11, 0x43, 0x82, 0x41, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x93, 0x00, 0x00, 0x05, 0xdd, 0x05, 0xd7, 0x00, 0x17, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x20, 0x13, 0x16, 0x15, 0x10, 0x01, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x35, 0x36, 0x37, 0x36, 0x11, 0x10, 0x25, 0x26, 0x27, 0x35, 0x34, 0x37, 0x17, 0x15, 0x04, 0x11, 0x10, 0x05, 0x07, 0x15, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x3d, 0x01, 0x10, 0x01, 0x26, 0x23, 0x03, 0x25, 0x01, 0x63, 0xf5, 0x5f, 0xfe, 0x9c, 0xa1, 0x9f, 0x2c, 0x2a, 0x49, 0xf9, 0x71, 0x8b, 0xfe, 0xd4, 0x7b, 0x53, 0x86, 0x24, 0x01, 0x9b, 0xfe, 0xd1, 0x27, 0x05, 0x4e, 0x8e, 0xd2, 0x4a, 0x1a, 0xfe, 0xc7, 0x92, 0x8f, 0x05, 0xd7, 0xfe, 0x87, 0xad, 0xc6, 0xfe, 0x78, 0xfe, 0xff, 0x62, 0x0f, 0x06, 0x4f, 0xb1, 0xca, 0x01, 0x0c, 0x01, 0x90, 0xe0, 0x50, 0x10, 0x03, 0x0b, 0x0e, 0x3e, 0x03, 0xc5, 0xfe, 0x14, 0xfe, 0x6e, 0xe8, 0x18, 0x04, 0x53, 0x98, 0xf4, 0x5d, 0x5d, 0x09, 0x01, 0x3d, 0x01, 0x05, 0x66, 0x00, 0x02, 0x00, 0x99, 0x00, 0x00, 0x03, 0xe2, 0x05, 0xd8, 0x00, 0x17, 0x00, 0x2b, 0x00, 0x00, 0x21, 0x20, 0x03, 0x26, 0x35, 0x10, 0x01, 0x36, 0x3b, 0x01, 0x32, 0x17, 0x15, 0x06, 0x07, 0x06, 0x11, 0x10, 0x05, 0x16, 0x17, 0x15, 0x14, 0x07, 0x27, 0x35, 0x24, 0x11, 0x10, 0x25, 0x37, 0x35, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x1d, 0x01, 0x10, 0x01, 0x16, 0x33, 0x03, 0x51, 0xfe, 0x9c, 0xf5, 0x5f, 0x01, 0x64, 0xa1, 0xa0, 0x2c, 0x29, 0x48, 0xf8, 0x71, 0x8b, 0x01, 0x2d, 0x7a, 0x54, 0x86, 0x24, 0xfe, 0x64, 0x01, 0x2f, 0x27, 0x05, 0x4e, 0x8f, 0xd0, 0x4b, 0x19, 0x01, 0x37, 0x94, 0x8e, 0x01, 0x79, 0xad, 0xc6, 0x01, 0x88, 0x01, 0x01, 0x63, 0x0f, 0x07, 0x4f, 0xb1, 0xcb, 0xfe, 0xf5, 0xfe, 0x70, 0xe1, 0x4f, 0x10, 0x04, 0x0a, 0x0e, 0x3e, 0x03, 0xc5, 0x01, 0xed, 0x01, 0x91, 0xe8, 0x18, 0x03, 0x53, 0x96, 0xf5, 0x5c, 0x5e, 0x09, 0xfe, 0xc2, 0xfe, 0xfc, 0x66, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xff, 0x30, 0x03, 0xce, 0x05, 0xdb, 0x00, 0x31, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x15, 0x37, 0x15, 0x07, 0x15, 0x23, 0x27, 0x23, 0x35, 0x33, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x17, 0x33, 0x36, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x07, 0x06, 0x07, 0x23, 0x06, 0x07, 0x06, 0x10, 0x16, 0x33, 0x32, 0x36, 0x10, 0x27, 0x26, 0x03, 0x12, 0x24, 0x20, 0x78, 0x77, 0x61, 0x81, 0xc3, 0xc6, 0x74, 0x01, 0xb5, 0xb5, 0x01, 0x85, 0x62, 0x77, 0x77, 0x21, 0x24, 0x24, 0x21, 0x77, 0x7f, 0x52, 0x4d, 0x69, 0x22, 0x69, 0x4c, 0x52, 0x80, 0x78, 0x20, 0xef, 0x22, 0x69, 0x4d, 0x52, 0xa5, 0x75, 0x72, 0xa5, 0x52, 0x4c, 0x04, 0x56, 0x1a, 0x24, 0x83, 0xbd, 0xbc, 0x7c, 0x64, 0x0e, 0xd1, 0x02, 0x64, 0x01, 0xca, 0xcb, 0x62, 0xd1, 0x0d, 0x65, 0x7c, 0xbc, 0xbd, 0x83, 0x24, 0x1a, 0x19, 0x25, 0x83, 0xbc, 0x08, 0x0a, 0x82, 0x5a, 0x53, 0x07, 0x07, 0x53, 0x5a, 0x82, 0x0a, 0x08, 0xbc, 0x83, 0x25, 0x5f, 0x06, 0x54, 0x59, 0xfe, 0xfc, 0xaa, 0xaa, 0x01, 0x04, 0x59, 0x54, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xfe, 0xff, 0x04, 0xa9, 0x05, 0xda, 0x00, 0x0b, 0x00, 0x23, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x26, 0x35, 0x34, 0x00, 0x33, 0x32, 0x00, 0x10, 0x07, 0x06, 0x07, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x26, 0x02, 0xa3, 0x94, 0xcf, 0xcf, 0x94, 0x91, 0xd2, 0xd2, 0xfe, 0x02, 0x98, 0x01, 0x2e, 0xd7, 0xd4, 0x01, 0x31, 0x98, 0x7a, 0xa2, 0xf5, 0xf5, 0xa2, 0xf5, 0xf5, 0xa3, 0x05, 0x27, 0xe4, 0xa4, 0xa3, 0xd8, 0xd8, 0xa3, 0xa4, 0xe4, 0xfc, 0xed, 0x9d, 0xee, 0xef, 0x01, 0x4c, 0xfe, 0xb4, 0xfe, 0x22, 0x9c, 0x7e, 0x12, 0xfe, 0xf8, 0x7c, 0xfe, 0xff, 0x01, 0x01, 0x7c, 0x01, 0x09, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xff, 0xe3, 0x04, 0xa9, 0x06, 0xbe, 0x00, 0x0b, 0x00, 0x23, 0x00, 0x00, 0x25, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0x16, 0x15, 0x14, 0x00, 0x23, 0x22, 0x00, 0x10, 0x37, 0x36, 0x37, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x16, 0x02, 0xa3, 0x94, 0xcf, 0xcf, 0x94, 0x91, 0xd2, 0xd2, 0x01, 0xfe, 0x98, 0xfe, 0xd2, 0xd7, 0xd4, 0xfe, 0xcf, 0x98, 0x7a, 0xa2, 0xf4, 0xf4, 0xa2, 0xf5, 0xf5, 0xa3, 0x96, 0xe4, 0xa4, 0xa3, 0xd8, 0xd8, 0xa3, 0xa4, 0xe4, 0x03, 0x13, 0x9d, 0xee, 0xef, 0xfe, 0xb4, 0x01, 0x4c, 0x01, 0xde, 0x9c, 0x7e, 0x12, 0x01, 0x08, 0x7c, 0x01, 0x01, 0xfe, 0xff, 0x7c, 0xfe, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x91, 0xff, 0xe3, 0x05, 0xfb, 0x05, 0xc3, 0x00, 0x09, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x36, 0x10, 0x26, 0x13, 0x06, 0x23, 0x22, 0x00, 0x10, 0x00, 0x17, 0x16, 0x17, 0x01, 0x21, 0x37, 0x21, 0x11, 0x07, 0x11, 0x01, 0x16, 0x15, 0x14, 0x02, 0x97, 0x93, 0xd0, 0xd0, 0x93, 0x91, 0xd3, 0xd3, 0xe2, 0x97, 0xdc, 0xd3, 0xfe, 0xce, 0x01, 0x36, 0xcf, 0xcd, 0x65, 0x01, 0x45, 0xfe, 0xb2, 0x7e, 0x01, 0xbd, 0x81, 0xfe, 0xbe, 0x65, 0x03, 0x96, 0xe4, 0xfe, 0xb8, 0xd8, 0xd8, 0x01, 0x48, 0xe4, 0xfc, 0xf1, 0xa4, 0x01, 0x3d, 0x01, 0xdc, 0x01, 0x55, 0x09, 0x08, 0x67, 0x01, 0x5c, 0x8e, 0xfe, 0x14, 0x8f, 0x01, 0x75, 0xfe, 0xa4, 0x92, 0xc1, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x31, 0x00, 0x00, 0x05, 0x42, 0x05, 0xd8, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x35, 0x32, 0x36, 0x34, 0x26, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x23, 0x34, 0x12, 0x33, 0x32, 0x12, 0x15, 0x14, 0x07, 0x33, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x35, 0x02, 0xbf, 0x6e, 0x99, 0x98, 0x6f, 0x6d, 0x9a, 0x87, 0xe8, 0xa6, 0xa8, 0xe8, 0x62, 0xcd, 0x88, 0x88, 0xfc, 0x77, 0x02, 0x13, 0x01, 0xab, 0xf2, 0xab, 0xab, 0x79, 0x02, 0xb9, 0x01, 0x04, 0xfe, 0xfc, 0xb9, 0xa8, 0x7b, 0x03, 0xc5, 0xfa, 0x28, 0x01, 0x7c, 0x97, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x93, 0x00, 0x00, 0x04, 0xe0, 0x05, 0xd8, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x23, 0x35, 0x33, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x36, 0x33, 0x32, 0x12, 0x15, 0x14, 0x06, 0x1d, 0x01, 0x23, 0x34, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x01, 0xf3, 0x60, 0x60, 0x88, 0xa1, 0xa1, 0x64, 0x89, 0xa0, 0xd7, 0x7e, 0x87, 0x7e, 0x8b, 0x64, 0x63, 0x8b, 0x88, 0x04, 0x8d, 0x97, 0xb4, 0xb4, 0x97, 0xfe, 0x7d, 0x6d, 0xfe, 0xfe, 0xbb, 0x5a, 0xe5, 0x79, 0x02, 0x84, 0xee, 0x48, 0x7b, 0xa9, 0xaa, 0x7a, 0xfe, 0x46, 0x00, 0x00, 0x00, 0x02, 0x00, 0xdf, 0x00, 0x00, 0x05, 0x94, 0x05, 0xd8, 0x00, 0x0a, 0x00, 0x31, 0x00, 0x00, 0x00, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x16, 0x17, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x34, 0x37, 0x36, 0x37, 0x11, 0x21, 0x11, 0x21, 0x35, 0x33, 0x11, 0x23, 0x35, 0x21, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x11, 0x21, 0x03, 0x6c, 0x65, 0x47, 0x47, 0x32, 0x32, 0x47, 0x34, 0x37, 0x2b, 0x44, 0x89, 0x62, 0x60, 0x8a, 0x45, 0x2a, 0x38, 0xfe, 0xfd, 0xfe, 0xec, 0x8c, 0x8c, 0x01, 0x14, 0x01, 0x03, 0x88, 0x01, 0x03, 0x01, 0x12, 0x89, 0x89, 0xfe, 0xee, 0xfe, 0xfd, 0x01, 0x8c, 0x4f, 0x37, 0x39, 0x4e, 0x4e, 0x39, 0x37, 0xc2, 0x12, 0x30, 0x4c, 0xd8, 0x99, 0x99, 0xd8, 0x4c, 0x31, 0x11, 0x01, 0x8c, 0xfe, 0x4b, 0x97, 0x02, 0xd3, 0x98, 0xfe, 0x4a, 0x01, 0xb6, 0xfe, 0x4a, 0x01, 0xb6, 0x98, 0xfd, 0x2d, 0x97, 0x01, 0xb5, 0x00, 0x01, 0x00, 0xea, 0x00, 0x00, 0x05, 0x8a, 0x05, 0xd8, 0x00, 0x3c, 0x00, 0x00, 0x25, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x26, 0x27, 0x26, 0x27, 0x35, 0x07, 0x27, 0x37, 0x33, 0x17, 0x15, 0x27, 0x15, 0x33, 0x15, 0x23, 0x16, 0x17, 0x16, 0x17, 0x11, 0x07, 0x27, 0x37, 0x33, 0x17, 0x15, 0x27, 0x11, 0x36, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x35, 0x07, 0x27, 0x37, 0x33, 0x17, 0x15, 0x27, 0x15, 0x33, 0x15, 0x06, 0x07, 0x06, 0x07, 0x15, 0x33, 0x15, 0x03, 0x7f, 0x88, 0x9f, 0x9f, 0x95, 0x6e, 0x87, 0x01, 0x81, 0x01, 0x82, 0x89, 0x82, 0x82, 0x02, 0x02, 0x01, 0x5e, 0x46, 0x5d, 0x83, 0x01, 0x84, 0x88, 0x82, 0x82, 0x5b, 0x45, 0x5f, 0x01, 0x81, 0x01, 0x82, 0x89, 0x82, 0x82, 0x01, 0x01, 0x87, 0x6e, 0x94, 0x9d, 0xbb, 0xbb, 0xbb, 0x97, 0x8b, 0x16, 0x7a, 0x96, 0xd7, 0x54, 0x8e, 0x8c, 0x99, 0x99, 0x8c, 0x8e, 0x54, 0x02, 0x97, 0x68, 0x4f, 0x14, 0x02, 0xca, 0x8d, 0x8b, 0x9a, 0x9a, 0x8b, 0x8d, 0xfd, 0x37, 0x14, 0x4e, 0x6a, 0x96, 0x01, 0x59, 0x8e, 0x8c, 0x99, 0x99, 0x8c, 0x8e, 0x59, 0x04, 0xd3, 0x96, 0x79, 0x17, 0x8b, 0x97, 0x00, 0x00, 0x00, 0x02, 0x01, 0xba, 0x00, 0x00, 0x04, 0xb9, 0x05, 0xd8, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x21, 0x20, 0x17, 0x16, 0x15, 0x10, 0x07, 0x06, 0x23, 0x21, 0x11, 0x21, 0x17, 0x15, 0x07, 0x21, 0x27, 0x11, 0x17, 0x11, 0x21, 0x32, 0x37, 0x36, 0x37, 0x34, 0x27, 0x26, 0x23, 0x01, 0xc2, 0x01, 0x70, 0x01, 0x10, 0x5a, 0x1d, 0xe2, 0x35, 0x31, 0xfe, 0xcc, 0x02, 0x3b, 0x07, 0x07, 0xfd, 0x4a, 0x07, 0x82, 0x01, 0x26, 0x75, 0x40, 0x0f, 0x07, 0x92, 0x21, 0x49, 0x05, 0xd8, 0xd0, 0x4d, 0x5f, 0xfe, 0xf6, 0x5c, 0x11, 0xfd, 0xad, 0x08, 0x82, 0x08, 0x08, 0x05, 0xc7, 0x83, 0xfe, 0x24, 0x82, 0x1a, 0x50, 0xa4, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x00, 0x06, 0x20, 0x05, 0xda, 0x00, 0x24, 0x00, 0x00, 0x21, 0x10, 0x00, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x23, 0x26, 0x35, 0x34, 0x36, 0x33, 0x20, 0x13, 0x16, 0x17, 0x36, 0x37, 0x12, 0x21, 0x32, 0x16, 0x15, 0x14, 0x07, 0x23, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x00, 0x11, 0x03, 0x01, 0xfe, 0xfe, 0x98, 0x74, 0x1f, 0x4c, 0x79, 0x53, 0x92, 0x84, 0x01, 0x4f, 0x75, 0x08, 0x04, 0x04, 0x07, 0x77, 0x01, 0x4e, 0x84, 0x92, 0x54, 0x78, 0x4c, 0x1f, 0x75, 0x97, 0xfe, 0xff, 0x02, 0x58, 0x03, 0x05, 0xc5, 0x22, 0x80, 0x80, 0x84, 0xa1, 0x84, 0xbb, 0xfc, 0xfb, 0x31, 0x28, 0x28, 0x31, 0x03, 0x05, 0xbb, 0x84, 0xa1, 0x84, 0x80, 0x81, 0x22, 0xc4, 0xfc, 0xfb, 0xfd, 0xa8, 0x00, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x00, 0x05, 0xd0, 0x05, 0xd8, 0x00, 0x08, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x22, 0x06, 0x10, 0x16, 0x20, 0x36, 0x10, 0x26, 0x27, 0x36, 0x37, 0x3e, 0x02, 0x33, 0x15, 0x22, 0x02, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x00, 0x23, 0x22, 0x00, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x02, 0x23, 0x35, 0x32, 0x1e, 0x01, 0x17, 0x16, 0x03, 0x39, 0x84, 0xb9, 0xb9, 0x01, 0x09, 0xba, 0xb9, 0x86, 0x76, 0x45, 0x4d, 0x57, 0x91, 0xa7, 0x6f, 0x96, 0x76, 0x13, 0x15, 0x2a, 0x26, 0x84, 0xfe, 0xf6, 0xbe, 0xbb, 0xfe, 0xf6, 0x85, 0x25, 0x2b, 0x16, 0x13, 0x74, 0x9a, 0x6d, 0xa6, 0xa8, 0x40, 0x4d, 0x45, 0x03, 0x5c, 0xcf, 0xfe, 0xda, 0xce, 0xce, 0x01, 0x26, 0xcf, 0x96, 0x05, 0x3d, 0x42, 0xb4, 0xae, 0x6c, 0xfe, 0xc8, 0x6c, 0x13, 0x0f, 0x1e, 0x29, 0x95, 0xd2, 0xd1, 0xfe, 0xd9, 0x01, 0x27, 0xd1, 0xd2, 0x95, 0x2a, 0x1e, 0x0e, 0x13, 0x6c, 0x01, 0x38, 0x6c, 0xae, 0xb4, 0x42, 0x3d, 0x00, 0x00, 0x02, 0x00, 0xac, 0x00, 0x00, 0x05, 0xc6, 0x05, 0xda, 0x00, 0x13, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x26, 0x27, 0x35, 0x04, 0x20, 0x25, 0x15, 0x06, 0x07, 0x11, 0x16, 0x17, 0x15, 0x24, 0x20, 0x05, 0x35, 0x36, 0x3f, 0x01, 0x36, 0x33, 0x17, 0x11, 0x06, 0x23, 0x27, 0x01, 0xdd, 0x97, 0x99, 0x01, 0x38, 0x02, 0xac, 0x01, 0x35, 0x9f, 0x95, 0x95, 0x9f, 0xfe, 0xcb, 0xfd, 0x54, 0xfe, 0xc8, 0x99, 0x97, 0x89, 0x68, 0x6a, 0xd1, 0x68, 0x69, 0xd2, 0x04, 0xfc, 0x16, 0x34, 0x94, 0x5a, 0x5a, 0x97, 0x2f, 0x18, 0xfb, 0xe2, 0x17, 0x2f, 0x98, 0x5b, 0x5b, 0x94, 0x35, 0x15, 0x0c, 0x0d, 0x0d, 0x04, 0x07, 0x0d, 0x0d, 0x00, 0x04, 0x00, 0xcf, 0x00, 0x40, 0x05, 0xa5, 0x05, 0x6f, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x26, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x22, 0x06, 0x14, 0x16, 0x33, 0x32, 0x36, 0x34, 0x01, 0x2c, 0x01, 0x27, 0x35, 0x16, 0x04, 0x33, 0x32, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x10, 0x07, 0x0e, 0x01, 0x01, 0x32, 0x36, 0x34, 0x26, 0x22, 0x06, 0x14, 0x16, 0x01, 0x0c, 0x01, 0x17, 0x15, 0x26, 0x24, 0x23, 0x22, 0x17, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x3e, 0x01, 0x04, 0xbb, 0xab, 0x76, 0x76, 0x56, 0x54, 0x78, 0xfe, 0x88, 0xfe, 0xe7, 0xfe, 0xb9, 0x8a, 0xe4, 0x01, 0x47, 0x35, 0x75, 0x07, 0x76, 0xb9, 0x84, 0x86, 0xb9, 0x5d, 0x42, 0xdd, 0xfd, 0xe6, 0x55, 0x78, 0x78, 0xa9, 0x79, 0x78, 0x01, 0x01, 0x01, 0x19, 0x01, 0x48, 0x89, 0xe3, 0xfe, 0xba, 0x34, 0x78, 0x07, 0x76, 0xb8, 0x85, 0x86, 0xb9, 0x5e, 0x41, 0xdd, 0x02, 0xb8, 0x84, 0xbe, 0x85, 0x85, 0xbe, 0xfe, 0x0c, 0x02, 0x28, 0x2b, 0x7c, 0x54, 0x16, 0x1a, 0x6c, 0xa7, 0x93, 0xcf, 0xcf, 0xfe, 0xda, 0x67, 0x4d, 0x4c, 0x02, 0xb6, 0x84, 0xbe, 0x84, 0x84, 0xbe, 0x84, 0x02, 0x78, 0x02, 0x29, 0x2b, 0x7b, 0x54, 0x15, 0x1a, 0x6c, 0xa6, 0x94, 0xcf, 0xcf, 0x94, 0x92, 0x67, 0x4d, 0x4d, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, 0x05, 0x73, 0x05, 0xd8, 0x00, 0x13, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x00, 0x15, 0x16, 0x17, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x00, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x32, 0x35, 0x34, 0x26, 0x02, 0x52, 0x44, 0x2c, 0x0c, 0x1a, 0x66, 0x23, 0x20, 0x20, 0x43, 0x2c, 0x0c, 0x1b, 0x64, 0x23, 0x20, 0x2b, 0xc9, 0xa2, 0x9a, 0xc4, 0xfe, 0xfc, 0x03, 0x79, 0x40, 0x5a, 0x3a, 0x72, 0x64, 0x59, 0x82, 0x01, 0x03, 0x94, 0x77, 0x72, 0x87, 0x29, 0x17, 0x21, 0x08, 0x1d, 0x2e, 0x68, 0x32, 0x33, 0x36, 0x9b, 0x2b, 0x14, 0x19, 0x2e, 0x69, 0x31, 0x32, 0x44, 0x43, 0x07, 0x45, 0x01, 0x8c, 0x1d, 0x71, 0x27, 0x23, 0x23, 0x4b, 0x32, 0x0e, 0x1e, 0x6f, 0x27, 0x23, 0x24, 0x4c, 0x31, 0x02, 0xf0, 0xa1, 0xc9, 0xdd, 0xb0, 0xbb, 0xfe, 0x0a, 0xb4, 0x7c, 0x03, 0x58, 0x48, 0x77, 0x79, 0x6f, 0xc7, 0x01, 0xe1, 0xc2, 0x86, 0xa5, 0x9b, 0x81, 0x3c, 0x91, 0x3e, 0x62, 0x80, 0x11, 0x57, 0x44, 0x73, 0x2d, 0x16, 0x4b, 0x78, 0x36, 0x38, 0x3c, 0x3c, 0x72, 0x2e, 0x15, 0x29, 0x0d, 0x1a, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x62, 0xfe, 0x8f, 0x06, 0x12, 0x05, 0xd8, 0x00, 0x3a, 0x00, 0x44, 0x00, 0x00, 0x01, 0x32, 0x16, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x1d, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x11, 0x10, 0x01, 0x16, 0x17, 0x23, 0x26, 0x27, 0x06, 0x07, 0x35, 0x36, 0x37, 0x27, 0x11, 0x34, 0x35, 0x10, 0x27, 0x0e, 0x01, 0x07, 0x11, 0x23, 0x11, 0x10, 0x26, 0x2b, 0x02, 0x22, 0x06, 0x07, 0x11, 0x23, 0x11, 0x34, 0x27, 0x33, 0x16, 0x17, 0x3e, 0x01, 0x01, 0x11, 0x36, 0x13, 0x34, 0x26, 0x2b, 0x01, 0x22, 0x06, 0x02, 0x64, 0x39, 0x6b, 0x24, 0xb2, 0x44, 0x37, 0x4a, 0x2b, 0x76, 0x3d, 0x36, 0x5a, 0xfe, 0xa9, 0x01, 0x84, 0x97, 0x2a, 0x42, 0x97, 0x9d, 0xac, 0x6f, 0x08, 0x29, 0x34, 0x78, 0x39, 0x88, 0x1c, 0x1f, 0x01, 0x01, 0x25, 0xa1, 0x11, 0x86, 0x89, 0x80, 0x6a, 0x20, 0x15, 0xa5, 0x02, 0x7d, 0xe8, 0x16, 0x29, 0x19, 0x03, 0x1b, 0x81, 0x05, 0xd8, 0xc6, 0x80, 0x77, 0xcf, 0xa7, 0xdb, 0xca, 0x7d, 0x77, 0xe8, 0xfe, 0xef, 0xfe, 0x68, 0xfe, 0xbf, 0x5e, 0xc1, 0x29, 0xa1, 0x65, 0x07, 0x74, 0x1c, 0x57, 0xd9, 0x03, 0x57, 0x12, 0x11, 0x01, 0x19, 0x01, 0x01, 0xd9, 0xc8, 0xfc, 0x61, 0x03, 0x9a, 0x01, 0x41, 0x6a, 0xe2, 0xd7, 0xfc, 0x74, 0x04, 0x41, 0xbe, 0xbf, 0x4f, 0xb0, 0x5d, 0xbc, 0xfc, 0x92, 0xfd, 0xd0, 0xfa, 0x01, 0x52, 0xc1, 0x8b, 0xce, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x99, 0x00, 0x6b, 0x05, 0xdb, 0x05, 0x39, 0x00, 0x03, 0x00, 0x23, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x01, 0x21, 0x35, 0x21, 0x26, 0x35, 0x34, 0x12, 0x33, 0x32, 0x12, 0x15, 0x14, 0x07, 0x21, 0x15, 0x21, 0x35, 0x23, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x9a, 0x05, 0x40, 0xfa, 0xc0, 0x01, 0xf5, 0xfe, 0x0b, 0x01, 0x3e, 0x3c, 0xe8, 0xa6, 0xa7, 0xe9, 0x3d, 0x01, 0x5d, 0xfd, 0xeb, 0x01, 0x10, 0x0f, 0x4e, 0x99, 0xdc, 0x99, 0x4d, 0x0e, 0x11, 0x01, 0x03, 0x98, 0x01, 0x8f, 0x98, 0x68, 0x83, 0xb9, 0x01, 0x03, 0xfe, 0xfd, 0xb9, 0x83, 0x68, 0x98, 0x98, 0x0d, 0x11, 0x55, 0x79, 0x7a, 0xaa, 0xaa, 0x7a, 0x79, 0x55, 0x11, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3e, 0xff, 0x3c, 0x06, 0x38, 0x05, 0xd8, 0x00, 0x38, 0x00, 0x00, 0x01, 0x14, 0x16, 0x17, 0x33, 0x35, 0x33, 0x17, 0x07, 0x27, 0x35, 0x23, 0x22, 0x27, 0x26, 0x27, 0x03, 0x34, 0x35, 0x10, 0x27, 0x0e, 0x01, 0x07, 0x11, 0x23, 0x11, 0x10, 0x26, 0x2b, 0x02, 0x22, 0x06, 0x07, 0x11, 0x23, 0x11, 0x34, 0x27, 0x33, 0x16, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x1d, 0x01, 0x13, 0x04, 0x80, 0x5d, 0x50, 0x50, 0x03, 0xb7, 0xb7, 0x03, 0x50, 0xb7, 0x3d, 0x28, 0x07, 0x13, 0x29, 0x34, 0x78, 0x39, 0x88, 0x1c, 0x1f, 0x01, 0x01, 0x25, 0xa1, 0x11, 0x86, 0x89, 0x80, 0x6a, 0x20, 0x15, 0xa5, 0x3e, 0x39, 0x6b, 0x24, 0xb2, 0x44, 0x37, 0x4a, 0x01, 0x01, 0x0f, 0x6f, 0x7d, 0x01, 0x76, 0xad, 0xaf, 0x04, 0x76, 0x78, 0x4a, 0x76, 0x03, 0x16, 0x12, 0x11, 0x01, 0x19, 0x01, 0x01, 0xd9, 0xc8, 0xfc, 0x61, 0x03, 0x9a, 0x01, 0x41, 0x6a, 0xe2, 0xd7, 0xfc, 0x74, 0x04, 0x41, 0xbe, 0xbf, 0x4f, 0xb0, 0x5d, 0xbc, 0xc6, 0x80, 0x77, 0xcf, 0xa7, 0xdb, 0xca, 0xfd, 0x84, 0x00, 0x01, 0x00, 0x98, 0xff, 0xff, 0x05, 0xdc, 0x05, 0xd8, 0x00, 0x14, 0x00, 0x00, 0x01, 0x11, 0x09, 0x01, 0x07, 0x09, 0x01, 0x2f, 0x02, 0x09, 0x01, 0x3f, 0x02, 0x09, 0x01, 0x21, 0x35, 0x21, 0x11, 0x05, 0x53, 0xfd, 0x85, 0x01, 0x1d, 0x61, 0xfe, 0xe3, 0xfe, 0x82, 0x01, 0x5f, 0x01, 0x01, 0x7e, 0xfe, 0xe2, 0x01, 0x60, 0x01, 0x01, 0x1d, 0x02, 0x7a, 0xfe, 0x37, 0x02, 0xb3, 0x02, 0xd8, 0x01, 0xfc, 0xfd, 0x3f, 0xfe, 0xc3, 0x6c, 0x01, 0x3d, 0xfe, 0x58, 0x01, 0x6a, 0x01, 0x01, 0xa8, 0x01, 0x3d, 0x01, 0x6a, 0x01, 0xfe, 0xc3, 0x02, 0xc1, 0x98, 0xfd, 0x00, 0x00, 0x02, 0x00, 0xac, 0x00, 0x00, 0x05, 0xc6, 0x05, 0xd8, 0x00, 0x29, 0x00, 0x31, 0x00, 0x00, 0x01, 0x32, 0x12, 0x37, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x0e, 0x01, 0x07, 0x23, 0x35, 0x37, 0x36, 0x13, 0x26, 0x02, 0x23, 0x22, 0x02, 0x15, 0x14, 0x15, 0x07, 0x34, 0x02, 0x27, 0x35, 0x32, 0x16, 0x13, 0x36, 0x37, 0x3e, 0x01, 0x01, 0x16, 0x33, 0x32, 0x37, 0x26, 0x27, 0x22, 0x02, 0xfe, 0x60, 0x49, 0x17, 0x62, 0xaf, 0x6d, 0x8a, 0x81, 0x80, 0x8b, 0x6e, 0x28, 0x71, 0x7c, 0x97, 0x8a, 0x6e, 0x5e, 0x2c, 0x3a, 0x34, 0x21, 0x8a, 0x8f, 0x7e, 0x77, 0x84, 0x91, 0x24, 0x29, 0x29, 0x25, 0x6e, 0x01, 0x34, 0x54, 0x75, 0x91, 0x08, 0x06, 0x8f, 0x89, 0x05, 0xd8, 0xfc, 0x9e, 0x04, 0xdd, 0xbe, 0x67, 0x91, 0xab, 0x85, 0xa0, 0xd7, 0x04, 0x76, 0x01, 0x04, 0x01, 0x78, 0x10, 0x03, 0x15, 0xfe, 0x2d, 0xc3, 0x0f, 0x0e, 0x02, 0xfd, 0x01, 0xf0, 0x06, 0x61, 0xde, 0xfe, 0xed, 0xc9, 0x58, 0x5b, 0x96, 0xfc, 0x26, 0x91, 0xc5, 0x9d, 0x13, 0x00, 0x02, 0x00, 0x9e, 0x01, 0x39, 0x05, 0xd6, 0x04, 0xa2, 0x00, 0x27, 0x00, 0x51, 0x00, 0x00, 0x13, 0x00, 0x33, 0x32, 0x17, 0x16, 0x32, 0x36, 0x33, 0x32, 0x17, 0x16, 0x32, 0x37, 0x36, 0x33, 0x32, 0x13, 0x07, 0x26, 0x23, 0x22, 0x07, 0x06, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x06, 0x23, 0x27, 0x11, 0x00, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x33, 0x32, 0x13, 0x07, 0x26, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x22, 0x06, 0x23, 0x27, 0x9e, 0x01, 0x25, 0x67, 0x29, 0x0c, 0x15, 0x65, 0x9b, 0x32, 0x31, 0x15, 0x18, 0x66, 0x4e, 0x26, 0x25, 0x70, 0x62, 0x55, 0x38, 0x56, 0x2e, 0x36, 0x4d, 0x65, 0x16, 0x1a, 0x35, 0x31, 0x4b, 0x4e, 0x32, 0x32, 0x17, 0x15, 0x31, 0x31, 0xe8, 0x05, 0x30, 0x01, 0x24, 0x68, 0x28, 0x0d, 0x15, 0x33, 0x31, 0x4e, 0x4e, 0x63, 0x15, 0x18, 0x32, 0x34, 0x4d, 0x27, 0x24, 0x71, 0x62, 0x55, 0x38, 0x56, 0x2e, 0x36, 0x4e, 0x31, 0x33, 0x17, 0x19, 0x35, 0x31, 0x4c, 0x4d, 0x33, 0x31, 0x17, 0x15, 0x63, 0xe7, 0x05, 0x30, 0x01, 0x9d, 0x01, 0x0f, 0x28, 0x47, 0x8e, 0x47, 0x47, 0x47, 0x24, 0xfe, 0xc4, 0x33, 0xb9, 0x35, 0x4c, 0x4b, 0x4e, 0x43, 0x47, 0x48, 0x46, 0xd5, 0x62, 0x01, 0xd9, 0x01, 0x0d, 0x27, 0x46, 0x46, 0x48, 0x48, 0x46, 0x46, 0x23, 0xfe, 0xc5, 0x32, 0xb9, 0x36, 0x4d, 0x4c, 0x4e, 0x44, 0x47, 0x48, 0x48, 0xd5, 0x61, 0x00, 0x01, 0x01, 0x20, 0x00, 0x00, 0x05, 0x53, 0x05, 0xd8, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x07, 0x02, 0x03, 0x07, 0x00, 0x13, 0x21, 0x35, 0x21, 0x02, 0x01, 0x17, 0x12, 0x13, 0x33, 0x12, 0x13, 0x37, 0x00, 0x03, 0x21, 0x07, 0x21, 0x12, 0x01, 0x27, 0x02, 0x03, 0x03, 0xa6, 0xd9, 0x1d, 0xfa, 0x94, 0x01, 0x14, 0x18, 0xfe, 0xf6, 0x01, 0x0a, 0x19, 0xfe, 0xec, 0x95, 0xfa, 0x1d, 0xda, 0x1c, 0xfb, 0x95, 0xfe, 0xeb, 0x18, 0x01, 0x0a, 0x01, 0xfe, 0xf5, 0x1a, 0x01, 0x15, 0x96, 0xfb, 0x1c, 0x02, 0x99, 0x03, 0xfe, 0xae, 0xfe, 0xbf, 0x03, 0x01, 0x5f, 0x01, 0x37, 0xac, 0x01, 0x36, 0x01, 0x60, 0x03, 0xfe, 0xc0, 0xfe, 0xad, 0x01, 0x53, 0x01, 0x40, 0x03, 0xfe, 0xa0, 0xfe, 0xca, 0xac, 0xfe, 0xc9, 0xfe, 0xa1, 0x03, 0x01, 0x41, 0x01, 0x52, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0x00, 0x00, 0x05, 0xc0, 0x05, 0xd8, 0x00, 0x0f, 0x00, 0x20, 0x00, 0x24, 0x00, 0x54, 0x00, 0x64, 0x00, 0x00, 0x01, 0x36, 0x37, 0x26, 0x27, 0x26, 0x22, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x21, 0x33, 0x21, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x07, 0x16, 0x17, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x15, 0x16, 0x17, 0x1e, 0x01, 0x1d, 0x01, 0x36, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x11, 0x01, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x02, 0xfb, 0x01, 0x02, 0x20, 0x2e, 0x42, 0x8c, 0x85, 0x4b, 0x49, 0x43, 0x14, 0x14, 0x01, 0x35, 0x7f, 0x01, 0x34, 0x16, 0x13, 0x43, 0x49, 0x4b, 0x84, 0x47, 0x46, 0x42, 0x2f, 0x1f, 0x02, 0x01, 0xfe, 0x6c, 0x02, 0xa9, 0xfd, 0x0d, 0x26, 0x22, 0x3e, 0x61, 0x63, 0xb2, 0x5e, 0x48, 0x44, 0x20, 0x1d, 0x0c, 0x0e, 0x61, 0x61, 0x5f, 0x61, 0x61, 0x0e, 0x0c, 0x1c, 0x21, 0x45, 0x47, 0x5d, 0xb2, 0x64, 0x62, 0x3d, 0x23, 0x25, 0xfe, 0x0d, 0x17, 0x29, 0x14, 0x16, 0x28, 0x16, 0x16, 0x28, 0x16, 0x14, 0x29, 0x17, 0x03, 0xc7, 0x03, 0x03, 0x2b, 0x1c, 0x29, 0x51, 0x95, 0x50, 0x51, 0x92, 0x28, 0x0e, 0x08, 0x08, 0x0e, 0x28, 0x92, 0x51, 0x50, 0x95, 0x51, 0x29, 0x1c, 0x2b, 0x03, 0x03, 0xfd, 0xb8, 0xfe, 0xd1, 0x01, 0x2f, 0xfe, 0x81, 0x01, 0x7f, 0x0d, 0x16, 0x36, 0xc4, 0x6b, 0x6c, 0xc5, 0x6a, 0x1f, 0x02, 0x24, 0x3f, 0x12, 0x07, 0x04, 0x36, 0x46, 0x57, 0x57, 0x46, 0x36, 0x04, 0x07, 0x12, 0x3f, 0x24, 0x02, 0x1f, 0x6a, 0xc5, 0x6c, 0x6b, 0xc4, 0x36, 0x16, 0x0d, 0xfe, 0x81, 0x04, 0x7d, 0x19, 0x2b, 0x19, 0x19, 0x2b, 0x19, 0x18, 0x2d, 0x17, 0x17, 0x2d, 0x00, 0x00, 0x08, 0x00, 0xcb, 0x00, 0x00, 0x05, 0xa9, 0x05, 0xd8, 0x00, 0x48, 0x00, 0x4e, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7c, 0x00, 0x90, 0x00, 0xa5, 0x00, 0xbb, 0x00, 0x00, 0x01, 0x26, 0x27, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x07, 0x13, 0x03, 0x22, 0x27, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x07, 0x1b, 0x01, 0x26, 0x27, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x07, 0x1b, 0x01, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x07, 0x03, 0x13, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x23, 0x03, 0x11, 0x21, 0x11, 0x01, 0x35, 0x07, 0x21, 0x27, 0x1d, 0x02, 0x21, 0x35, 0x01, 0x17, 0x03, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x15, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x01, 0x17, 0x03, 0x36, 0x37, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x01, 0x37, 0x13, 0x16, 0x33, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x14, 0x16, 0x17, 0x16, 0x17, 0x01, 0x33, 0x03, 0x32, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x01, 0x37, 0x13, 0x16, 0x33, 0x32, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x01, 0x2c, 0x56, 0x0b, 0x1b, 0x30, 0x1a, 0x19, 0x31, 0x19, 0x03, 0x34, 0xd7, 0x2e, 0x4b, 0x10, 0x1a, 0x30, 0x1b, 0x1a, 0x2f, 0x1a, 0x01, 0x2a, 0xaa, 0x27, 0x3c, 0x02, 0x1b, 0x30, 0x18, 0x1a, 0x30, 0x1b, 0x03, 0x3c, 0x22, 0xa6, 0x29, 0x1a, 0x31, 0x18, 0x1b, 0x31, 0x1a, 0x0a, 0x4e, 0x52, 0xe7, 0x27, 0x1a, 0x30, 0x19, 0x1b, 0x30, 0x1a, 0x0c, 0x59, 0x90, 0xfc, 0xf9, 0x02, 0xd4, 0xa3, 0xfe, 0xb9, 0xa4, 0x02, 0x8e, 0xfd, 0x4c, 0x45, 0xd0, 0x06, 0x07, 0x10, 0x12, 0x12, 0x1f, 0x12, 0x11, 0x1f, 0x13, 0x12, 0x20, 0x11, 0x06, 0x08, 0x01, 0x17, 0x7a, 0xa8, 0x05, 0x05, 0x0f, 0x11, 0x11, 0x20, 0x10, 0x12, 0x1f, 0x12, 0x11, 0x20, 0x12, 0x06, 0x07, 0x01, 0x82, 0x68, 0x56, 0x05, 0x04, 0x11, 0x21, 0x12, 0x13, 0x20, 0x11, 0x10, 0x20, 0x12, 0x12, 0x10, 0x07, 0x06, 0xfe, 0xbe, 0x5a, 0x2b, 0x11, 0x0e, 0x10, 0x13, 0x14, 0x1f, 0x11, 0x10, 0x22, 0x11, 0x11, 0x12, 0x0c, 0x0e, 0x01, 0x0b, 0x5e, 0x95, 0x0a, 0x0a, 0x11, 0x1f, 0x12, 0x12, 0x1f, 0x11, 0x12, 0x20, 0x11, 0x11, 0x10, 0x04, 0x03, 0x03, 0xfb, 0x02, 0x5f, 0x1c, 0x33, 0x1c, 0x1c, 0x33, 0x1c, 0x40, 0x16, 0xfe, 0x06, 0x02, 0xbe, 0x5d, 0x1c, 0x32, 0x1c, 0x1c, 0x32, 0x1c, 0x2d, 0x22, 0xfd, 0x14, 0x03, 0x34, 0x1e, 0x30, 0x1c, 0x34, 0x1a, 0x1a, 0x34, 0x1c, 0x36, 0x18, 0xfc, 0xca, 0x02, 0xe4, 0x2f, 0x2a, 0x1b, 0x33, 0x1c, 0x1c, 0x33, 0x1b, 0x55, 0x10, 0xfd, 0x4a, 0x02, 0x03, 0x22, 0x2b, 0x1c, 0x33, 0x1b, 0x1b, 0x33, 0x1c, 0x5e, 0xfe, 0x31, 0xfd, 0xd1, 0x02, 0x2f, 0xfe, 0xdf, 0xe1, 0x4b, 0x3d, 0xd3, 0x30, 0xa4, 0xa4, 0x01, 0x54, 0x2a, 0x02, 0x0e, 0x03, 0x04, 0x0a, 0x23, 0x13, 0x14, 0x23, 0x14, 0x14, 0x23, 0x14, 0x13, 0x23, 0x14, 0x01, 0xfd, 0xf8, 0x20, 0x02, 0xf9, 0x02, 0x03, 0x0a, 0x23, 0x26, 0x24, 0x13, 0x13, 0x24, 0x26, 0x23, 0x14, 0x01, 0xfd, 0x13, 0x1b, 0x02, 0xd1, 0x01, 0x14, 0x23, 0x26, 0x24, 0x13, 0x13, 0x24, 0x26, 0x23, 0x0a, 0x05, 0x02, 0xfd, 0x0a, 0x03, 0x42, 0x0a, 0x0a, 0x23, 0x14, 0x13, 0x23, 0x14, 0x14, 0x23, 0x13, 0x14, 0x23, 0x0a, 0x08, 0x02, 0xfc, 0xda, 0x2a, 0x01, 0xea, 0x03, 0x15, 0x22, 0x14, 0x13, 0x24, 0x13, 0x13, 0x24, 0x13, 0x14, 0x22, 0x0b, 0x02, 0x02, 0x00, 0x00, 0x00, 0x05, 0x01, 0x32, 0xff, 0xfe, 0x05, 0x41, 0x05, 0xd6, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x27, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x00, 0x01, 0x33, 0x15, 0x33, 0x35, 0x33, 0x15, 0x23, 0x15, 0x07, 0x11, 0x17, 0x15, 0x33, 0x15, 0x21, 0x35, 0x33, 0x35, 0x37, 0x33, 0x11, 0x23, 0x27, 0x35, 0x23, 0x35, 0x33, 0x15, 0x33, 0x01, 0x35, 0x21, 0x15, 0x01, 0x37, 0x35, 0x21, 0x15, 0x17, 0x11, 0x07, 0x15, 0x21, 0x35, 0x27, 0x35, 0x11, 0x37, 0x21, 0x11, 0x02, 0xba, 0xfa, 0x9a, 0xf3, 0x68, 0x53, 0x53, 0x68, 0xfb, 0xf2, 0x67, 0x54, 0x01, 0x01, 0x54, 0x67, 0xee, 0x99, 0x02, 0x55, 0xfc, 0x56, 0x02, 0xf6, 0x4a, 0xfd, 0x2b, 0x49, 0x41, 0x02, 0xc5, 0x43, 0x01, 0xfd, 0xbe, 0x05, 0xd6, 0x9b, 0x9b, 0xa2, 0x90, 0x96, 0xfd, 0xb7, 0x95, 0x8f, 0xa3, 0xa3, 0x8f, 0x98, 0x02, 0x45, 0x97, 0x90, 0xa2, 0x9b, 0xfa, 0xfb, 0x37, 0x37, 0x03, 0xea, 0x83, 0x5f, 0x5f, 0x83, 0xfd, 0x76, 0x74, 0x80, 0x80, 0x74, 0x34, 0x02, 0x21, 0x02, 0xfd, 0xdd, 0x00, 0x04, 0x01, 0x8a, 0x00, 0x00, 0x04, 0xeb, 0x05, 0xd8, 0x00, 0x37, 0x00, 0x43, 0x00, 0x51, 0x00, 0x5e, 0x00, 0x00, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x35, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x15, 0x06, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x13, 0x21, 0x1b, 0x01, 0x35, 0x33, 0x35, 0x23, 0x35, 0x23, 0x15, 0x23, 0x15, 0x33, 0x15, 0x13, 0x36, 0x35, 0x34, 0x2e, 0x01, 0x22, 0x0e, 0x01, 0x15, 0x14, 0x17, 0x03, 0x21, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x02, 0x84, 0x1c, 0x1c, 0x08, 0x0a, 0x36, 0x21, 0x25, 0x01, 0x01, 0x25, 0x27, 0x46, 0x19, 0x1b, 0x17, 0x0f, 0x14, 0x28, 0x46, 0x26, 0x25, 0x46, 0x29, 0x13, 0x0f, 0x17, 0x19, 0x1a, 0x46, 0x27, 0x26, 0x01, 0x01, 0x26, 0x21, 0x34, 0x0a, 0x07, 0x1c, 0x1d, 0x02, 0x02, 0xfe, 0xfc, 0xa0, 0xf4, 0xf1, 0x9b, 0x9b, 0x6a, 0x9b, 0x9b, 0x92, 0x36, 0x29, 0x45, 0x4b, 0x46, 0x28, 0x38, 0xc7, 0x02, 0x49, 0xfe, 0x76, 0x1a, 0x30, 0x34, 0x31, 0x1a, 0x1b, 0x31, 0x19, 0x1a, 0x2f, 0x01, 0x94, 0x35, 0x39, 0x3c, 0x35, 0x11, 0x0e, 0x26, 0x3f, 0x48, 0x50, 0x04, 0x50, 0x49, 0x4b, 0x2a, 0x0e, 0x0a, 0x12, 0x1d, 0x27, 0x29, 0x2b, 0x4b, 0x2a, 0x2a, 0x4b, 0x2b, 0x29, 0x27, 0x1d, 0x13, 0x09, 0x0e, 0x2a, 0x4b, 0x49, 0x50, 0x04, 0x50, 0x48, 0x3e, 0x26, 0x0f, 0x11, 0x35, 0x3c, 0x3a, 0x36, 0x03, 0x04, 0xfe, 0x75, 0x01, 0x94, 0x01, 0x4e, 0x7c, 0x6c, 0x7c, 0x7c, 0x6c, 0x7c, 0xfe, 0xb2, 0x2d, 0x49, 0x2b, 0x4e, 0x29, 0x29, 0x4e, 0x2b, 0x40, 0x36, 0xfe, 0xac, 0x05, 0x19, 0x3a, 0x35, 0x1c, 0x1c, 0x35, 0x3a, 0x35, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x2f, 0x00, 0x00, 0x05, 0x46, 0x05, 0xd8, 0x00, 0x29, 0x00, 0x35, 0x00, 0x3e, 0x00, 0x6f, 0x00, 0x00, 0x01, 0x36, 0x35, 0x34, 0x26, 0x35, 0x34, 0x37, 0x16, 0x15, 0x14, 0x07, 0x00, 0x13, 0x21, 0x26, 0x35, 0x34, 0x00, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x07, 0x27, 0x07, 0x26, 0x27, 0x36, 0x35, 0x34, 0x27, 0x36, 0x37, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x16, 0x17, 0x03, 0x36, 0x3b, 0x01, 0x06, 0x15, 0x14, 0x2b, 0x01, 0x22, 0x27, 0x35, 0x03, 0x17, 0x14, 0x07, 0x23, 0x22, 0x3d, 0x01, 0x36, 0x13, 0x26, 0x27, 0x06, 0x15, 0x14, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x15, 0x14, 0x07, 0x16, 0x17, 0x37, 0x07, 0x36, 0x37, 0x36, 0x37, 0x16, 0x15, 0x14, 0x00, 0x15, 0x14, 0x17, 0x25, 0x02, 0x01, 0x32, 0x35, 0x23, 0x36, 0x35, 0x34, 0x26, 0x27, 0x06, 0x15, 0x14, 0x16, 0x15, 0x14, 0x07, 0x02, 0xce, 0x04, 0x14, 0x3f, 0x6e, 0x07, 0x01, 0xb9, 0x28, 0xfc, 0x97, 0x0c, 0x01, 0x63, 0x51, 0x32, 0x2a, 0x8e, 0x08, 0x28, 0x7d, 0x1c, 0x47, 0x02, 0x2b, 0x41, 0x13, 0x07, 0x1e, 0x5e, 0x30, 0x91, 0x21, 0x56, 0x06, 0x27, 0x3e, 0x13, 0x07, 0x04, 0x05, 0x06, 0x41, 0x09, 0x19, 0x25, 0xc2, 0x1f, 0x45, 0x17, 0x1a, 0x0a, 0x35, 0x27, 0x03, 0x42, 0x16, 0x5d, 0x57, 0x1f, 0x79, 0x1a, 0x5f, 0x49, 0x0a, 0xfe, 0xa9, 0x0a, 0x03, 0x14, 0x23, 0xfe, 0x43, 0x01, 0x04, 0x1c, 0x0b, 0x46, 0x1b, 0x10, 0x08, 0x04, 0xe8, 0x08, 0x0b, 0x15, 0x2b, 0x0e, 0x31, 0x5e, 0x68, 0x67, 0x1a, 0x1b, 0xfe, 0xbd, 0xfc, 0x6f, 0x38, 0x3a, 0xa0, 0x01, 0x28, 0x40, 0x06, 0x73, 0x03, 0x8e, 0x12, 0x16, 0x1e, 0x2e, 0x50, 0xf9, 0xc0, 0x1e, 0x1c, 0x6d, 0x7a, 0x20, 0x13, 0x05, 0x1b, 0x6e, 0x1b, 0x78, 0xfe, 0xeb, 0x3f, 0x2e, 0x23, 0x31, 0x1e, 0x0f, 0xfe, 0x70, 0x23, 0x34, 0x0f, 0x1e, 0x17, 0x31, 0x02, 0xa7, 0x60, 0x26, 0x3e, 0x25, 0x1b, 0x21, 0x12, 0x10, 0x0f, 0x61, 0x63, 0x2c, 0x2c, 0xc5, 0xc0, 0x4c, 0x18, 0x48, 0x4a, 0x0a, 0x90, 0x04, 0xad, 0x1e, 0x1e, 0x78, 0xfe, 0xec, 0x7d, 0x36, 0x34, 0x01, 0x03, 0x37, 0x01, 0x7c, 0x01, 0x0a, 0x2b, 0x0c, 0x4f, 0x4a, 0x4a, 0x29, 0x13, 0x21, 0x13, 0x11, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x01, 0x11, 0xff, 0xff, 0x05, 0x62, 0x05, 0xd7, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x50, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x13, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x01, 0x15, 0x21, 0x35, 0x07, 0x26, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x07, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x06, 0x07, 0x02, 0x79, 0x34, 0x5b, 0x31, 0x34, 0x5b, 0x32, 0x33, 0x5c, 0x32, 0x30, 0x5b, 0x56, 0x0f, 0x19, 0x0d, 0x0f, 0x19, 0x0e, 0x0e, 0x1a, 0x0e, 0x0c, 0x1a, 0x0f, 0x02, 0x1f, 0xfc, 0x43, 0x4a, 0x0a, 0x94, 0x84, 0x22, 0x24, 0x1b, 0x13, 0x26, 0x4c, 0x46, 0x18, 0x1a, 0x17, 0x0e, 0x14, 0x27, 0x46, 0x25, 0x24, 0x47, 0x28, 0x13, 0x0f, 0x17, 0x19, 0x1b, 0x43, 0x4e, 0x25, 0x14, 0x1b, 0x22, 0x22, 0x84, 0x96, 0x0b, 0x53, 0x03, 0x3a, 0x3e, 0xdd, 0x73, 0x74, 0xdc, 0x3d, 0x3a, 0x04, 0x03, 0xc1, 0x70, 0x64, 0x38, 0x38, 0x64, 0x70, 0x67, 0x36, 0x36, 0x01, 0x0e, 0x10, 0x1b, 0x0f, 0x0f, 0x1b, 0x10, 0x0f, 0x1c, 0x10, 0x10, 0x1c, 0xfa, 0xbb, 0x01, 0x01, 0x01, 0x39, 0x3a, 0xa0, 0x01, 0x25, 0x4e, 0x15, 0x0f, 0x1d, 0x26, 0x4b, 0x52, 0x53, 0x97, 0x2a, 0x0e, 0x0a, 0x13, 0x1d, 0x27, 0x54, 0x4d, 0x2a, 0x2a, 0x4d, 0x54, 0x27, 0x1d, 0x14, 0x09, 0x0e, 0x2a, 0x97, 0x53, 0x52, 0x4b, 0x26, 0x1d, 0x10, 0x14, 0x4e, 0xfe, 0xdb, 0xa0, 0x3a, 0x39, 0x84, 0x7d, 0x71, 0x79, 0x83, 0x83, 0x79, 0x71, 0x7d, 0x00, 0x00, 0x00, 0x08, 0x00, 0xb4, 0x00, 0x00, 0x05, 0xc0, 0x05, 0xd8, 0x00, 0x0f, 0x00, 0x20, 0x00, 0x24, 0x00, 0x54, 0x00, 0x64, 0x00, 0x68, 0x00, 0x79, 0x00, 0x8a, 0x00, 0x00, 0x01, 0x36, 0x37, 0x26, 0x27, 0x26, 0x22, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x21, 0x33, 0x21, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x07, 0x16, 0x17, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x15, 0x16, 0x17, 0x1e, 0x01, 0x1d, 0x01, 0x36, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x11, 0x01, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x01, 0x15, 0x21, 0x35, 0x37, 0x23, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x06, 0x15, 0x33, 0x34, 0x27, 0x36, 0x37, 0x36, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x23, 0x02, 0xfb, 0x01, 0x02, 0x20, 0x2e, 0x42, 0x8c, 0x85, 0x4b, 0x49, 0x43, 0x14, 0x14, 0x01, 0x35, 0x7f, 0x01, 0x34, 0x16, 0x13, 0x43, 0x49, 0x4b, 0x84, 0x47, 0x46, 0x42, 0x2f, 0x1f, 0x02, 0x01, 0xfe, 0x6c, 0x02, 0xa9, 0xfd, 0x0d, 0x26, 0x22, 0x3e, 0x61, 0x63, 0xb2, 0x5e, 0x48, 0x44, 0x20, 0x1d, 0x0c, 0x0e, 0x61, 0x61, 0x5f, 0x61, 0x61, 0x0e, 0x0c, 0x1c, 0x21, 0x45, 0x47, 0x5d, 0xb2, 0x64, 0x62, 0x3d, 0x23, 0x25, 0xfe, 0x0d, 0x17, 0x29, 0x14, 0x16, 0x28, 0x16, 0x16, 0x28, 0x16, 0x14, 0x29, 0x17, 0x01, 0x7a, 0xfd, 0xb5, 0xb9, 0xfc, 0x10, 0x0f, 0x37, 0x3c, 0x3e, 0x6b, 0x39, 0x38, 0x37, 0x25, 0x1a, 0x02, 0xd9, 0x02, 0x1a, 0x25, 0x37, 0x37, 0x3b, 0x6b, 0x3d, 0x3b, 0x37, 0x11, 0x10, 0xfb, 0x03, 0xc7, 0x03, 0x03, 0x2b, 0x1c, 0x29, 0x51, 0x95, 0x50, 0x51, 0x92, 0x28, 0x0e, 0x08, 0x08, 0x0e, 0x28, 0x92, 0x51, 0x50, 0x95, 0x51, 0x29, 0x1c, 0x2b, 0x03, 0x03, 0xfd, 0xb8, 0xfe, 0xd1, 0x01, 0x2f, 0xfe, 0x81, 0x01, 0x7f, 0x0d, 0x16, 0x36, 0xc4, 0x6b, 0x6c, 0xc5, 0x6a, 0x1f, 0x02, 0x24, 0x3f, 0x12, 0x07, 0x04, 0x36, 0x46, 0x57, 0x57, 0x46, 0x36, 0x04, 0x07, 0x12, 0x3f, 0x24, 0x02, 0x1f, 0x6a, 0xc5, 0x6c, 0x6b, 0xc4, 0x36, 0x16, 0x0d, 0xfe, 0x81, 0x04, 0x7d, 0x19, 0x2b, 0x19, 0x19, 0x2b, 0x19, 0x18, 0x2d, 0x17, 0x17, 0x2d, 0xfc, 0xb6, 0xc8, 0xc8, 0xce, 0x07, 0x0c, 0x21, 0x79, 0x43, 0x42, 0x7b, 0x43, 0x21, 0x17, 0x24, 0x03, 0x02, 0x02, 0x03, 0x24, 0x17, 0x21, 0x43, 0x7b, 0x42, 0x43, 0x79, 0x21, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0xcb, 0x00, 0x00, 0x05, 0xa9, 0x05, 0xd8, 0x00, 0x48, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x00, 0x01, 0x26, 0x27, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x07, 0x13, 0x03, 0x22, 0x27, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x07, 0x1b, 0x01, 0x26, 0x27, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x07, 0x1b, 0x01, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x07, 0x03, 0x13, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x06, 0x23, 0x03, 0x11, 0x21, 0x11, 0x05, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x2c, 0x56, 0x0b, 0x1b, 0x30, 0x1a, 0x19, 0x31, 0x19, 0x03, 0x34, 0xd7, 0x2e, 0x4b, 0x10, 0x1a, 0x30, 0x1b, 0x1a, 0x2f, 0x1a, 0x01, 0x2a, 0xaa, 0x27, 0x3c, 0x02, 0x1b, 0x30, 0x18, 0x1a, 0x30, 0x1b, 0x03, 0x3c, 0x22, 0xa6, 0x29, 0x1a, 0x31, 0x18, 0x1b, 0x31, 0x1a, 0x0a, 0x4e, 0x52, 0xe7, 0x27, 0x1a, 0x30, 0x19, 0x1b, 0x30, 0x1a, 0x0c, 0x59, 0x90, 0xfc, 0xf9, 0x02, 0xd4, 0xfd, 0x72, 0x02, 0x8e, 0xfd, 0x72, 0x03, 0xfb, 0x02, 0x5f, 0x1c, 0x33, 0x1c, 0x1c, 0x33, 0x1c, 0x40, 0x16, 0xfe, 0x06, 0x02, 0xbe, 0x5d, 0x1c, 0x32, 0x1c, 0x1c, 0x32, 0x1c, 0x2d, 0x22, 0xfd, 0x14, 0x03, 0x34, 0x1e, 0x30, 0x1c, 0x34, 0x1a, 0x1a, 0x34, 0x1c, 0x36, 0x18, 0xfc, 0xca, 0x02, 0xe4, 0x2f, 0x2a, 0x1b, 0x33, 0x1c, 0x1c, 0x33, 0x1b, 0x55, 0x10, 0xfd, 0x4a, 0x02, 0x03, 0x22, 0x2b, 0x1c, 0x33, 0x1b, 0x1b, 0x33, 0x1c, 0x5e, 0xfe, 0x31, 0xfd, 0xd1, 0x02, 0x2f, 0xcb, 0x4e, 0x4e, 0xfe, 0xd6, 0x4f, 0x4f, 0x00, 0x00, 0x04, 0x01, 0x32, 0xff, 0xfe, 0x05, 0x41, 0x05, 0xd6, 0x00, 0x03, 0x00, 0x07, 0x00, 0x25, 0x00, 0x29, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x13, 0x33, 0x15, 0x33, 0x35, 0x33, 0x15, 0x23, 0x15, 0x07, 0x11, 0x17, 0x15, 0x33, 0x15, 0x21, 0x35, 0x33, 0x35, 0x37, 0x33, 0x11, 0x23, 0x27, 0x35, 0x23, 0x35, 0x33, 0x15, 0x33, 0x01, 0x35, 0x21, 0x15, 0x04, 0x5a, 0xfd, 0xc0, 0x02, 0x83, 0xfd, 0x3b, 0xe2, 0xfa, 0x9a, 0xf3, 0x68, 0x53, 0x53, 0x68, 0xfb, 0xf2, 0x67, 0x54, 0x01, 0x01, 0x54, 0x67, 0xee, 0x99, 0x02, 0x55, 0xfc, 0x56, 0x04, 0x84, 0x5e, 0x5e, 0xfc, 0x2f, 0x6f, 0x6f, 0x05, 0x23, 0x9b, 0x9b, 0xa2, 0x90, 0x96, 0xfd, 0xb7, 0x95, 0x8f, 0xa3, 0xa3, 0x8f, 0x98, 0x02, 0x45, 0x97, 0x90, 0xa2, 0x9b, 0xfa, 0xfb, 0x37, 0x37, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x8a, 0x00, 0x00, 0x04, 0xeb, 0x05, 0xd8, 0x00, 0x34, 0x00, 0x40, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x35, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x15, 0x06, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x13, 0x21, 0x13, 0x26, 0x01, 0x35, 0x33, 0x35, 0x23, 0x35, 0x23, 0x15, 0x23, 0x15, 0x33, 0x15, 0x02, 0x68, 0x1c, 0x08, 0x0a, 0x36, 0x21, 0x25, 0x01, 0x01, 0x25, 0x27, 0x46, 0x19, 0x1b, 0x17, 0x0f, 0x14, 0x28, 0x46, 0x26, 0x25, 0x46, 0x29, 0x13, 0x0f, 0x17, 0x19, 0x1a, 0x46, 0x27, 0x26, 0x01, 0x01, 0x26, 0x21, 0x34, 0x0a, 0x07, 0x1c, 0x1d, 0xfa, 0xfc, 0xa0, 0xf4, 0x16, 0x01, 0x07, 0x9b, 0x9b, 0x6a, 0x9b, 0x9b, 0x02, 0x02, 0x3c, 0x35, 0x11, 0x0e, 0x26, 0x3f, 0x48, 0x50, 0x04, 0x50, 0x49, 0x4b, 0x2a, 0x0e, 0x0a, 0x12, 0x1d, 0x27, 0x29, 0x2b, 0x4b, 0x2a, 0x2a, 0x4b, 0x2b, 0x29, 0x27, 0x1d, 0x13, 0x09, 0x0e, 0x2a, 0x4b, 0x49, 0x50, 0x04, 0x50, 0x48, 0x3e, 0x26, 0x0f, 0x11, 0x35, 0x3c, 0x3a, 0x36, 0xfe, 0x6e, 0x01, 0x94, 0x35, 0x01, 0x19, 0x7c, 0x6c, 0x7c, 0x7c, 0x6c, 0x7c, 0x00, 0x00, 0x04, 0x01, 0x2a, 0x00, 0x00, 0x05, 0x4a, 0x05, 0xd8, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x48, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x36, 0x35, 0x34, 0x26, 0x35, 0x34, 0x37, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x33, 0x14, 0x23, 0x00, 0x13, 0x21, 0x26, 0x35, 0x34, 0x00, 0x35, 0x34, 0x27, 0x06, 0x2b, 0x01, 0x06, 0x23, 0x22, 0x23, 0x37, 0x07, 0x26, 0x27, 0x36, 0x35, 0x34, 0x27, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x35, 0x34, 0x37, 0x16, 0x17, 0x07, 0x15, 0x16, 0x3b, 0x01, 0x32, 0x35, 0x34, 0x37, 0x23, 0x22, 0x07, 0x03, 0x15, 0x14, 0x3b, 0x01, 0x36, 0x35, 0x27, 0x22, 0x01, 0x17, 0x00, 0x13, 0x33, 0x02, 0x02, 0xc7, 0x21, 0x1b, 0x35, 0x4c, 0x0e, 0x1f, 0x03, 0x01, 0x01, 0xe2, 0x29, 0xfc, 0x97, 0x0c, 0x01, 0x6c, 0x01, 0x3b, 0x69, 0x09, 0x51, 0x5d, 0x03, 0x03, 0x2b, 0x60, 0x67, 0x18, 0x4f, 0x02, 0x2b, 0x59, 0x03, 0x28, 0x12, 0x5d, 0x33, 0x99, 0x03, 0x07, 0x13, 0x3f, 0x26, 0x05, 0x57, 0x21, 0x67, 0x19, 0x09, 0x41, 0x07, 0x38, 0x01, 0x9c, 0x2f, 0x01, 0x51, 0x06, 0x45, 0x29, 0x04, 0xe6, 0x17, 0x27, 0x19, 0x39, 0x16, 0x2e, 0x1e, 0x51, 0x59, 0x0d, 0x2f, 0x0c, 0x01, 0xfe, 0xac, 0xfc, 0x6f, 0x38, 0x3a, 0xa0, 0x01, 0x1b, 0x71, 0x08, 0x07, 0xa7, 0x92, 0x68, 0x50, 0x1c, 0x53, 0xe5, 0xbe, 0x1b, 0x1a, 0x6d, 0x68, 0x0a, 0x09, 0x1c, 0x1a, 0x23, 0x25, 0x42, 0x1b, 0x7a, 0xff, 0x10, 0x1e, 0x31, 0x22, 0x30, 0x40, 0xfe, 0x29, 0x18, 0x1d, 0x0f, 0x35, 0x22, 0x02, 0x40, 0x59, 0xfe, 0xf3, 0xfd, 0x04, 0x03, 0x52, 0x00, 0x01, 0x01, 0x11, 0xff, 0xff, 0x05, 0x62, 0x05, 0xd7, 0x00, 0x2e, 0x00, 0x00, 0x05, 0x26, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x07, 0x01, 0x1c, 0x0a, 0x94, 0x84, 0x22, 0x24, 0x1b, 0x13, 0x26, 0x4c, 0x46, 0x18, 0x1a, 0x17, 0x0e, 0x14, 0x27, 0x46, 0x25, 0x24, 0x47, 0x28, 0x13, 0x0f, 0x17, 0x19, 0x1b, 0x43, 0x4e, 0x25, 0x14, 0x1b, 0x22, 0x22, 0x84, 0x96, 0x0b, 0x01, 0x39, 0x3a, 0xa0, 0x01, 0x25, 0x4e, 0x15, 0x0f, 0x1d, 0x26, 0x4b, 0x52, 0x53, 0x97, 0x2a, 0x0e, 0x0a, 0x13, 0x1d, 0x27, 0x54, 0x4d, 0x2a, 0x2a, 0x4d, 0x54, 0x27, 0x1d, 0x14, 0x09, 0x0e, 0x2a, 0x97, 0x53, 0x52, 0x4b, 0x26, 0x1d, 0x10, 0x14, 0x4e, 0xfe, 0xdb, 0xa0, 0x3a, 0x39, 0x00, 0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x05, 0x51, 0x05, 0xd4, 0x00, 0x23, 0x00, 0x00, 0x01, 0x16, 0x13, 0x12, 0x17, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x23, 0x15, 0x10, 0x17, 0x23, 0x35, 0x36, 0x11, 0x27, 0x23, 0x07, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x00, 0x3f, 0x01, 0x03, 0x3c, 0x55, 0xc2, 0xd5, 0x06, 0x23, 0x92, 0x30, 0x39, 0x8b, 0x55, 0x26, 0x4a, 0xc1, 0x4d, 0x03, 0x22, 0x2b, 0x4c, 0x72, 0xa9, 0x44, 0x08, 0xa8, 0x01, 0x1b, 0x51, 0x02, 0x05, 0xd4, 0xa7, 0xfe, 0xec, 0xfe, 0xea, 0x39, 0x55, 0x50, 0x28, 0xa7, 0x60, 0x16, 0xdd, 0x0c, 0xfe, 0xe5, 0x96, 0x06, 0x97, 0x01, 0x1d, 0x03, 0x58, 0x85, 0xd1, 0x49, 0x2e, 0xb7, 0xcb, 0x01, 0x82, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa6, 0x00, 0x01, 0x05, 0xce, 0x05, 0xd1, 0x00, 0x18, 0x00, 0x32, 0x00, 0x00, 0x01, 0x32, 0x13, 0x16, 0x15, 0x32, 0x37, 0x12, 0x33, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x10, 0x07, 0x00, 0x07, 0x23, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x03, 0x15, 0x14, 0x17, 0x01, 0x33, 0x01, 0x36, 0x3d, 0x01, 0x34, 0x27, 0x26, 0x23, 0x22, 0x03, 0x06, 0x15, 0x23, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x01, 0xf3, 0xc4, 0x68, 0x19, 0x06, 0x0c, 0x64, 0xd4, 0xbc, 0x6e, 0x22, 0xc7, 0xfe, 0x6a, 0x36, 0x05, 0xfd, 0xdc, 0x6c, 0xb4, 0x48, 0xce, 0xbc, 0x01, 0xab, 0x03, 0x02, 0x04, 0x5e, 0xaa, 0x40, 0x34, 0xee, 0x4d, 0x09, 0x06, 0x40, 0x5b, 0xaa, 0x9d, 0x60, 0x22, 0x05, 0xd1, 0xfe, 0xed, 0x50, 0x18, 0x46, 0x01, 0x35, 0xd3, 0x4e, 0x50, 0x0d, 0xfe, 0xfe, 0xe7, 0xfd, 0xd9, 0x42, 0x02, 0xed, 0xb2, 0xb6, 0xd2, 0x7c, 0x2d, 0xfe, 0x8f, 0x10, 0xdb, 0xe4, 0xfd, 0xbc, 0x02, 0xbb, 0xa1, 0x97, 0x26, 0xac, 0x70, 0x1c, 0xfe, 0x41, 0x26, 0x1a, 0x4e, 0xd1, 0xe0, 0xb1, 0x46, 0x00, 0x02, 0x01, 0x35, 0x00, 0x00, 0x05, 0x3d, 0x05, 0xd4, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x00, 0x09, 0x01, 0x15, 0x00, 0x07, 0x26, 0x01, 0x26, 0x35, 0x09, 0x04, 0x03, 0x3a, 0x02, 0x03, 0xfe, 0x19, 0x1c, 0x0d, 0xfe, 0x48, 0x3f, 0x02, 0x01, 0xfe, 0x35, 0x01, 0xce, 0x01, 0xce, 0xfe, 0x88, 0x05, 0xd4, 0xfd, 0x1a, 0x07, 0xfd, 0x3b, 0x22, 0x0b, 0x02, 0x80, 0x56, 0x0d, 0x02, 0x96, 0xfd, 0x67, 0xfd, 0x64, 0x02, 0x9c, 0x02, 0x1e, 0x00, 0x00, 0x01, 0x00, 0xcd, 0x00, 0x00, 0x05, 0xa7, 0x05, 0xd4, 0x00, 0x37, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x14, 0x0f, 0x01, 0x33, 0x36, 0x3b, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x22, 0x03, 0x23, 0x15, 0x10, 0x17, 0x15, 0x23, 0x27, 0x36, 0x11, 0x35, 0x23, 0x02, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x32, 0x17, 0x33, 0x35, 0x26, 0x27, 0x26, 0x3d, 0x01, 0x34, 0x37, 0x36, 0x03, 0x3b, 0xc1, 0x5b, 0x0b, 0x03, 0x6c, 0x36, 0x03, 0x42, 0x4c, 0x11, 0xd6, 0x57, 0x14, 0xbc, 0x24, 0x40, 0xda, 0x5a, 0x03, 0x4a, 0xbb, 0x06, 0x4d, 0x03, 0x5a, 0xdd, 0xab, 0x5c, 0x17, 0xde, 0x3b, 0x2e, 0x08, 0x4d, 0x47, 0x02, 0x4b, 0x1a, 0x36, 0xc1, 0x40, 0x05, 0xd4, 0xe3, 0x34, 0x38, 0x75, 0xa0, 0x3c, 0x1c, 0xca, 0x42, 0x3c, 0xcd, 0x68, 0x0c, 0x06, 0x01, 0x12, 0x09, 0xfe, 0xa9, 0x6d, 0x06, 0x06, 0x80, 0x01, 0x4d, 0x03, 0xfe, 0xeb, 0xc9, 0x44, 0x3a, 0xe9, 0x53, 0x0c, 0x1c, 0x03, 0x47, 0x45, 0x6e, 0x51, 0x0e, 0xc9, 0x68, 0x13, 0x00, 0x00, 0x03, 0x01, 0x21, 0x00, 0x01, 0x05, 0x53, 0x05, 0xd5, 0x00, 0x22, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x00, 0x01, 0x16, 0x01, 0x16, 0x1d, 0x01, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x23, 0x15, 0x10, 0x17, 0x23, 0x35, 0x36, 0x11, 0x23, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x26, 0x35, 0x37, 0x35, 0x34, 0x37, 0x00, 0x37, 0x06, 0x01, 0x06, 0x15, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x32, 0x37, 0x33, 0x32, 0x17, 0x16, 0x3b, 0x01, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x34, 0x27, 0x02, 0x03, 0x33, 0x26, 0x27, 0x22, 0x07, 0x03, 0x3b, 0x71, 0x01, 0x59, 0x4e, 0xa3, 0x1f, 0x2b, 0x14, 0x82, 0x59, 0x25, 0x4a, 0xc1, 0x4d, 0x26, 0x32, 0x4c, 0x5f, 0x14, 0x90, 0x49, 0x16, 0x02, 0xba, 0x01, 0x05, 0x55, 0x6f, 0xfe, 0xd0, 0x49, 0x09, 0x85, 0x14, 0x25, 0x0e, 0x6b, 0x56, 0xa5, 0x07, 0x1b, 0x4b, 0x5d, 0x11, 0x7b, 0x3b, 0x09, 0xb7, 0xcf, 0x80, 0x39, 0x0c, 0x0d, 0x06, 0x0e, 0x05, 0xd5, 0xe1, 0xfe, 0x36, 0x8b, 0x86, 0x03, 0xd1, 0x4e, 0x10, 0xda, 0x0d, 0xfe, 0xe8, 0x9b, 0x06, 0x97, 0x01, 0x23, 0x65, 0x75, 0xae, 0x42, 0x3f, 0x0d, 0x03, 0xc8, 0xd4, 0x01, 0x67, 0x49, 0xc7, 0xfe, 0x6f, 0x82, 0x85, 0xbb, 0x35, 0x09, 0xda, 0x46, 0x94, 0xa7, 0x28, 0x1e, 0x1f, 0xb0, 0xcf, 0x01, 0x1f, 0xfb, 0x70, 0x17, 0x5a, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa3, 0x00, 0x00, 0x05, 0xd2, 0x05, 0xd4, 0x00, 0x17, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x33, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x01, 0x23, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x01, 0xf1, 0xb7, 0x68, 0x26, 0x02, 0x02, 0x20, 0x52, 0x62, 0x79, 0xbc, 0x72, 0x1d, 0xbc, 0xfe, 0x24, 0x05, 0xfe, 0x06, 0x97, 0xb3, 0x4b, 0x05, 0xd4, 0xeb, 0x5d, 0x31, 0xa2, 0x6b, 0x6c, 0xe0, 0x53, 0x49, 0xfa, 0xe3, 0xfd, 0x85, 0x02, 0xb1, 0xcd, 0xda, 0xd3, 0x7c, 0x2d, 0x00, 0x00, 0x01, 0x01, 0x35, 0x00, 0x00, 0x05, 0x3d, 0x05, 0xd4, 0x00, 0x08, 0x00, 0x00, 0x09, 0x01, 0x16, 0x15, 0x01, 0x26, 0x01, 0x34, 0x37, 0x03, 0x3a, 0x01, 0xc5, 0x3e, 0xfd, 0xfd, 0x0b, 0xfe, 0x07, 0x64, 0x05, 0xd4, 0xfd, 0x73, 0x55, 0x0d, 0xfd, 0x1b, 0x08, 0x02, 0xdd, 0x0e, 0x8a, 0x00, 0x00, 0x03, 0x00, 0xcd, 0x00, 0x00, 0x05, 0xa8, 0x05, 0xdc, 0x00, 0x32, 0x00, 0x60, 0x00, 0x67, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x0f, 0x01, 0x36, 0x3b, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x22, 0x03, 0x23, 0x15, 0x10, 0x17, 0x15, 0x23, 0x27, 0x36, 0x11, 0x35, 0x23, 0x02, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x32, 0x17, 0x26, 0x27, 0x35, 0x34, 0x37, 0x36, 0x03, 0x14, 0x1f, 0x01, 0x15, 0x26, 0x2b, 0x01, 0x22, 0x0f, 0x01, 0x14, 0x17, 0x16, 0x33, 0x32, 0x13, 0x36, 0x37, 0x33, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x34, 0x2f, 0x01, 0x23, 0x22, 0x07, 0x35, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x13, 0x14, 0x07, 0x33, 0x35, 0x26, 0x35, 0x03, 0x3f, 0xb6, 0x5e, 0x17, 0x67, 0x14, 0x1c, 0x37, 0x25, 0xdf, 0x53, 0x0e, 0xbd, 0x1e, 0x42, 0xd9, 0x5c, 0x03, 0x4a, 0xbc, 0x05, 0x4c, 0x02, 0x5a, 0xde, 0xad, 0x5c, 0x17, 0xdf, 0x3c, 0x2e, 0x22, 0x37, 0x1c, 0x59, 0x1a, 0xc3, 0x40, 0xd8, 0x98, 0x0b, 0x61, 0x6a, 0x08, 0xdb, 0x37, 0x06, 0x7b, 0x36, 0x47, 0xbd, 0x66, 0x0f, 0x13, 0x07, 0x21, 0x4b, 0x51, 0x8e, 0x97, 0x4d, 0x0a, 0xe3, 0x31, 0x05, 0x6b, 0x60, 0x74, 0x1d, 0x17, 0xa8, 0x30, 0x25, 0xa6, 0x4b, 0xed, 0x19, 0x36, 0x19, 0x05, 0xdc, 0xce, 0x46, 0x39, 0x84, 0xa6, 0x17, 0x06, 0xd7, 0x38, 0x3a, 0xd3, 0x64, 0x0c, 0x07, 0x01, 0x14, 0x09, 0xfe, 0xa7, 0x6d, 0x06, 0x06, 0x80, 0x01, 0x4f, 0x04, 0xfe, 0xe8, 0xcb, 0x45, 0x3a, 0xeb, 0x52, 0x0c, 0x06, 0x70, 0xb1, 0x26, 0xcb, 0x69, 0x13, 0xfe, 0xb3, 0x9b, 0xcc, 0x0c, 0x03, 0x09, 0xd4, 0x43, 0x94, 0x5d, 0x26, 0x01, 0x27, 0x1b, 0x41, 0x78, 0x86, 0x85, 0xbe, 0x2e, 0x2b, 0x06, 0xde, 0x30, 0x03, 0x09, 0x03, 0x89, 0x6e, 0x4d, 0x2c, 0xb6, 0x57, 0x10, 0xc8, 0xfb, 0xce, 0x1c, 0x60, 0x03, 0x63, 0x16, 0x00, 0x04, 0x00, 0xc2, 0xff, 0xfe, 0x05, 0xb2, 0x05, 0xd4, 0x00, 0x10, 0x00, 0x21, 0x00, 0x31, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x33, 0x14, 0x06, 0x07, 0x14, 0x16, 0x17, 0x23, 0x26, 0x27, 0x26, 0x27, 0x30, 0x35, 0x34, 0x36, 0x25, 0x33, 0x14, 0x06, 0x07, 0x14, 0x16, 0x13, 0x23, 0x26, 0x27, 0x26, 0x27, 0x34, 0x35, 0x34, 0x36, 0x05, 0x33, 0x14, 0x06, 0x07, 0x14, 0x16, 0x17, 0x23, 0x26, 0x27, 0x26, 0x27, 0x35, 0x34, 0x36, 0x13, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x04, 0x20, 0x24, 0x26, 0x35, 0x34, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x14, 0x16, 0x04, 0x20, 0x24, 0x36, 0x34, 0x27, 0x26, 0x27, 0x02, 0x37, 0x0c, 0x83, 0x02, 0xb8, 0x06, 0x0b, 0x1b, 0x92, 0x2b, 0x0e, 0x95, 0x01, 0x20, 0x0c, 0x83, 0x02, 0xb9, 0x05, 0x0c, 0x1a, 0x92, 0x2c, 0x0d, 0x95, 0x01, 0x37, 0x0b, 0x83, 0x02, 0xb9, 0x05, 0x0c, 0x19, 0x93, 0x2c, 0x0d, 0x95, 0x28, 0x97, 0xab, 0xa6, 0xfe, 0xd2, 0xfe, 0xb8, 0xfe, 0xd3, 0xa7, 0xaa, 0x98, 0x02, 0x76, 0x43, 0x4d, 0x96, 0x01, 0x10, 0x01, 0x29, 0x01, 0x10, 0x96, 0x4e, 0x44, 0x76, 0x05, 0x39, 0x3f, 0x9b, 0x63, 0x82, 0x79, 0xc9, 0xa6, 0x74, 0x33, 0x5a, 0x0e, 0x72, 0x88, 0xed, 0x60, 0xed, 0x97, 0xc5, 0xbb, 0xfe, 0xce, 0xfb, 0xb2, 0x4e, 0x8b, 0x08, 0x09, 0xb1, 0xd1, 0x5b, 0x4f, 0xc4, 0x7d, 0xa1, 0x9a, 0xfd, 0xd0, 0x91, 0x42, 0x72, 0x0e, 0x91, 0xad, 0xfe, 0x1e, 0x31, 0xb1, 0x61, 0x60, 0xb0, 0x62, 0x62, 0xb0, 0x60, 0x61, 0xb1, 0x31, 0x29, 0x45, 0x4d, 0xa8, 0x98, 0x55, 0x55, 0x98, 0xa8, 0x4d, 0x45, 0x29, 0x00, 0x01, 0x00, 0x9a, 0xff, 0xf6, 0x02, 0x72, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x01, 0x33, 0x17, 0x11, 0x14, 0x0f, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x34, 0x3f, 0x01, 0x32, 0x17, 0x33, 0x11, 0x02, 0x2a, 0x41, 0x07, 0xb1, 0x2b, 0x20, 0xbe, 0x1a, 0x03, 0xbe, 0x1d, 0x5a, 0x50, 0x04, 0x05, 0xd5, 0x08, 0xfa, 0xfd, 0xa3, 0x2d, 0x04, 0x85, 0x1f, 0x82, 0x18, 0x05, 0x40, 0x04, 0xd4, 0x00, 0x00, 0x01, 0x00, 0x9a, 0xff, 0xf6, 0x03, 0xfe, 0x05, 0xd5, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x33, 0x17, 0x15, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x23, 0x27, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x11, 0x14, 0x07, 0x23, 0x22, 0x35, 0x34, 0x37, 0x33, 0x32, 0x17, 0x11, 0x02, 0x1c, 0x4e, 0x08, 0x18, 0x9c, 0xd8, 0x6e, 0x04, 0x1b, 0x37, 0xcd, 0x53, 0x16, 0xca, 0x33, 0xda, 0xbf, 0x14, 0x57, 0x50, 0x05, 0xd5, 0x07, 0x27, 0x36, 0x3f, 0x46, 0x8a, 0x92, 0x60, 0x20, 0x31, 0x54, 0x46, 0x47, 0x2a, 0x1a, 0xfb, 0xd6, 0x99, 0x2d, 0xa8, 0x83, 0x17, 0x40, 0x04, 0xd6, 0x00, 0x01, 0x01, 0x52, 0xff, 0x2f, 0x05, 0x22, 0x05, 0xd5, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x05, 0x17, 0x11, 0x14, 0x07, 0x23, 0x22, 0x3d, 0x01, 0x34, 0x3f, 0x01, 0x32, 0x17, 0x11, 0x25, 0x11, 0x14, 0x0f, 0x01, 0x23, 0x22, 0x3d, 0x01, 0x34, 0x3f, 0x01, 0x32, 0x17, 0x11, 0x02, 0xb0, 0x02, 0x6e, 0x03, 0xad, 0x30, 0xc0, 0x9f, 0x23, 0x4e, 0x49, 0xfe, 0x13, 0x88, 0x3c, 0x17, 0xc3, 0x99, 0x27, 0x50, 0x48, 0x05, 0xd5, 0xca, 0x04, 0xfa, 0xed, 0x9b, 0x2a, 0xa4, 0x04, 0x7e, 0x16, 0x03, 0x3a, 0x04, 0x0b, 0xa9, 0xfb, 0xdb, 0x89, 0x38, 0x08, 0x9b, 0x07, 0x7a, 0x22, 0x04, 0x43, 0x04, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa9, 0xff, 0xf6, 0x05, 0xcb, 0x05, 0xd5, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x17, 0x11, 0x14, 0x07, 0x22, 0x27, 0x34, 0x37, 0x32, 0x17, 0x33, 0x11, 0x21, 0x11, 0x06, 0x07, 0x23, 0x22, 0x35, 0x34, 0x37, 0x32, 0x17, 0x11, 0x17, 0x15, 0x21, 0x35, 0x05, 0xc7, 0x03, 0xeb, 0xd1, 0x10, 0xd1, 0x62, 0x47, 0x03, 0xfc, 0xfb, 0x07, 0xda, 0x04, 0xe8, 0xd5, 0x5a, 0x4f, 0x4f, 0x03, 0x05, 0x05, 0xd5, 0x04, 0xfb, 0x12, 0xd5, 0x15, 0xa4, 0x8a, 0x0e, 0x3b, 0x02, 0x95, 0xfd, 0x5a, 0xcf, 0x24, 0xb1, 0x7d, 0x10, 0x40, 0x04, 0xe1, 0xcf, 0x9c, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa2, 0xff, 0xfa, 0x02, 0xd2, 0x05, 0xd9, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x00, 0x13, 0x33, 0x17, 0x11, 0x33, 0x36, 0x33, 0x16, 0x13, 0x02, 0x05, 0x27, 0x11, 0x13, 0x11, 0x24, 0x11, 0x34, 0x35, 0x34, 0x27, 0x22, 0xa8, 0x29, 0x04, 0x03, 0x99, 0x83, 0xcc, 0x12, 0x1a, 0xfd, 0xee, 0x03, 0x32, 0x01, 0x79, 0x86, 0x6b, 0x05, 0xd9, 0x06, 0xfc, 0x3f, 0xed, 0x03, 0xfe, 0xff, 0xfe, 0x57, 0x58, 0x03, 0x05, 0xd6, 0xfb, 0xd4, 0xfe, 0x9d, 0x63, 0x01, 0x31, 0x0d, 0x0c, 0x94, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x00, 0x01, 0xf8, 0x05, 0xd9, 0x00, 0x0d, 0x00, 0x13, 0x00, 0x00, 0x13, 0x33, 0x17, 0x11, 0x25, 0x17, 0x11, 0x07, 0x23, 0x27, 0x11, 0x05, 0x23, 0x11, 0x13, 0x11, 0x33, 0x25, 0x11, 0x23, 0x9f, 0x25, 0x06, 0x01, 0x2c, 0x02, 0x04, 0x24, 0x04, 0xfe, 0xd1, 0x02, 0x2f, 0x01, 0x01, 0x01, 0x02, 0x05, 0xd9, 0x05, 0xfe, 0x2f, 0xa1, 0x02, 0xfb, 0x63, 0x05, 0x05, 0x01, 0xe5, 0xa0, 0x04, 0x8a, 0xfd, 0x99, 0xfe, 0x7d, 0x90, 0x01, 0x7f, 0x00, 0x02, 0x00, 0x9b, 0x00, 0x00, 0x02, 0xe2, 0x05, 0xd9, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x33, 0x17, 0x11, 0x37, 0x17, 0x15, 0x06, 0x07, 0x11, 0x37, 0x15, 0x06, 0x07, 0x11, 0x07, 0x23, 0x27, 0x11, 0x05, 0x11, 0x07, 0x23, 0x27, 0x11, 0x07, 0x35, 0x34, 0x37, 0x11, 0x23, 0x07, 0x35, 0x37, 0x11, 0x37, 0x33, 0x17, 0x11, 0x25, 0x11, 0x01, 0x11, 0x25, 0x11, 0x02, 0x46, 0x2a, 0x04, 0x6b, 0x03, 0x03, 0x6b, 0x6e, 0x01, 0x6d, 0x04, 0x2a, 0x04, 0xfe, 0xfd, 0x05, 0x26, 0x04, 0x74, 0x74, 0x02, 0x72, 0x74, 0x04, 0x26, 0x05, 0x01, 0x03, 0xfe, 0xfd, 0x01, 0x03, 0x05, 0xd9, 0x05, 0xfe, 0xd0, 0x3c, 0x02, 0x8d, 0x07, 0x3c, 0xfe, 0x8b, 0x37, 0x87, 0x04, 0x43, 0xfe, 0xd7, 0x04, 0x04, 0x01, 0x11, 0x8c, 0xfe, 0xa6, 0x04, 0x04, 0x01, 0x41, 0x3c, 0x8e, 0x06, 0x3c, 0x01, 0x7b, 0x38, 0x8b, 0x41, 0x01, 0x1f, 0x04, 0x04, 0xfe, 0xfa, 0x86, 0x01, 0x4d, 0xfd, 0x96, 0xfe, 0x87, 0x8b, 0x01, 0x74, 0x00, 0x01, 0x00, 0x9a, 0x00, 0x00, 0x04, 0xc8, 0x05, 0xd9, 0x00, 0x48, 0x00, 0x00, 0x01, 0x23, 0x30, 0x23, 0x22, 0x07, 0x23, 0x22, 0x27, 0x35, 0x36, 0x35, 0x34, 0x27, 0x35, 0x36, 0x37, 0x33, 0x16, 0x3b, 0x01, 0x35, 0x34, 0x27, 0x35, 0x36, 0x37, 0x33, 0x16, 0x32, 0x37, 0x33, 0x16, 0x17, 0x15, 0x06, 0x1d, 0x01, 0x33, 0x32, 0x37, 0x33, 0x16, 0x17, 0x15, 0x06, 0x15, 0x14, 0x17, 0x15, 0x06, 0x2b, 0x01, 0x26, 0x2b, 0x02, 0x11, 0x14, 0x17, 0x15, 0x06, 0x07, 0x23, 0x26, 0x22, 0x07, 0x23, 0x26, 0x27, 0x35, 0x36, 0x35, 0x02, 0x71, 0x98, 0x03, 0xa1, 0x48, 0x33, 0x15, 0x0a, 0x59, 0x59, 0x02, 0x1c, 0x34, 0x4a, 0xa3, 0x97, 0x76, 0x02, 0x1b, 0x34, 0x28, 0x7e, 0x29, 0x34, 0x1a, 0x03, 0x76, 0x92, 0xa3, 0x4b, 0x32, 0x1e, 0x02, 0x59, 0x59, 0x0a, 0x16, 0x32, 0x48, 0xa1, 0x04, 0x93, 0x76, 0x03, 0x1a, 0x34, 0x29, 0x7e, 0x28, 0x34, 0x1b, 0x02, 0x76, 0x03, 0x11, 0x5a, 0x23, 0x3b, 0x31, 0x37, 0x46, 0x2d, 0x3a, 0x1d, 0x03, 0x83, 0xaf, 0xb5, 0x53, 0x38, 0x21, 0x02, 0x63, 0x63, 0x02, 0x21, 0x38, 0x53, 0xb5, 0xaf, 0x83, 0x03, 0x1d, 0x3a, 0x2d, 0x46, 0x37, 0x31, 0x3b, 0x23, 0x5a, 0xfe, 0x52, 0xb5, 0x53, 0x39, 0x20, 0x02, 0x63, 0x63, 0x02, 0x20, 0x39, 0x53, 0xb5, 0x00, 0x06, 0x00, 0x76, 0x00, 0x00, 0x05, 0x0d, 0x05, 0xd9, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x1b, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x00, 0x01, 0x06, 0x07, 0x16, 0x17, 0x37, 0x35, 0x05, 0x15, 0x17, 0x36, 0x37, 0x26, 0x27, 0x01, 0x26, 0x27, 0x06, 0x07, 0x17, 0x33, 0x03, 0x23, 0x07, 0x16, 0x17, 0x36, 0x37, 0x03, 0x33, 0x37, 0x16, 0x17, 0x06, 0x07, 0x27, 0x23, 0x11, 0x17, 0x06, 0x07, 0x26, 0x27, 0x37, 0x11, 0x23, 0x07, 0x26, 0x27, 0x36, 0x37, 0x17, 0x33, 0x35, 0x27, 0x36, 0x37, 0x16, 0x17, 0x0f, 0x01, 0x15, 0x23, 0x15, 0x33, 0x11, 0x33, 0x11, 0x33, 0x35, 0x23, 0x35, 0x01, 0x1c, 0x14, 0x2c, 0x2b, 0x15, 0x55, 0x02, 0xa2, 0x55, 0x14, 0x2b, 0x2b, 0x14, 0xfe, 0xac, 0x28, 0x2a, 0x28, 0x28, 0x3d, 0x28, 0x01, 0x28, 0x3c, 0x28, 0x28, 0x29, 0x29, 0x07, 0xcd, 0xbc, 0x09, 0x6d, 0x6d, 0x09, 0xbc, 0xcd, 0x72, 0x60, 0x5e, 0x5e, 0x5d, 0x71, 0xcd, 0xbc, 0x09, 0x6e, 0x6e, 0x09, 0xbc, 0xcd, 0x71, 0x5d, 0x5f, 0x5d, 0x60, 0x72, 0x63, 0x68, 0x68, 0x31, 0x68, 0x68, 0x03, 0xb4, 0x2d, 0x2e, 0x2c, 0x2d, 0x43, 0x2e, 0x01, 0x2e, 0x43, 0x2e, 0x2c, 0x2e, 0x2d, 0x01, 0x6e, 0x17, 0x2f, 0x2f, 0x17, 0x5f, 0xfc, 0x52, 0x5f, 0x17, 0x2f, 0x2f, 0x17, 0x02, 0xf7, 0x7e, 0x69, 0x6a, 0x68, 0x68, 0x7e, 0xfe, 0x4e, 0xd0, 0x0b, 0x79, 0x79, 0x0b, 0xd0, 0x01, 0xb2, 0x7e, 0x68, 0x69, 0x69, 0x69, 0x7e, 0xd6, 0xd1, 0x0b, 0x7a, 0x7a, 0x0b, 0xd1, 0x73, 0x9f, 0x2e, 0xfe, 0x80, 0x01, 0x80, 0x2e, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x9a, 0x00, 0x00, 0x05, 0xdb, 0x05, 0xac, 0x00, 0x14, 0x00, 0x23, 0x00, 0x2e, 0x00, 0x36, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x68, 0x00, 0x77, 0x00, 0x8c, 0x00, 0x97, 0x00, 0xa6, 0x00, 0xaf, 0x00, 0x00, 0x01, 0x21, 0x32, 0x1f, 0x01, 0x37, 0x33, 0x32, 0x15, 0x03, 0x21, 0x27, 0x35, 0x36, 0x37, 0x35, 0x02, 0x27, 0x26, 0x3d, 0x01, 0x07, 0x33, 0x32, 0x17, 0x16, 0x15, 0x02, 0x07, 0x23, 0x24, 0x27, 0x35, 0x12, 0x37, 0x36, 0x17, 0x15, 0x13, 0x07, 0x15, 0x33, 0x37, 0x07, 0x26, 0x2f, 0x01, 0x01, 0x17, 0x13, 0x26, 0x2b, 0x01, 0x22, 0x07, 0x01, 0x16, 0x13, 0x17, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x26, 0x03, 0x35, 0x17, 0x13, 0x33, 0x32, 0x3f, 0x01, 0x34, 0x2f, 0x01, 0x06, 0x25, 0x33, 0x32, 0x17, 0x16, 0x15, 0x07, 0x23, 0x27, 0x02, 0x0f, 0x01, 0x17, 0x07, 0x23, 0x26, 0x03, 0x26, 0x3d, 0x01, 0x34, 0x3f, 0x01, 0x23, 0x27, 0x35, 0x37, 0x17, 0x15, 0x17, 0x33, 0x15, 0x14, 0x07, 0x15, 0x16, 0x17, 0x13, 0x33, 0x17, 0x35, 0x27, 0x01, 0x33, 0x17, 0x15, 0x21, 0x32, 0x37, 0x33, 0x17, 0x15, 0x06, 0x03, 0x06, 0x2b, 0x01, 0x15, 0x07, 0x23, 0x02, 0x3d, 0x01, 0x27, 0x17, 0x11, 0x07, 0x21, 0x22, 0x2f, 0x01, 0x35, 0x34, 0x37, 0x05, 0x07, 0x17, 0x33, 0x35, 0x34, 0x3b, 0x01, 0x32, 0x3f, 0x01, 0x21, 0x26, 0x3d, 0x01, 0x05, 0x06, 0x07, 0x15, 0x14, 0x1f, 0x01, 0x33, 0x11, 0x02, 0xd7, 0x01, 0x64, 0x34, 0x1a, 0x45, 0x58, 0x08, 0x04, 0x9c, 0xfe, 0xc7, 0x04, 0x10, 0x4a, 0xa9, 0x0e, 0x29, 0x66, 0x15, 0x64, 0x32, 0x1b, 0x9e, 0x0f, 0x02, 0xfe, 0xf1, 0x04, 0x8e, 0x0f, 0x28, 0xf7, 0xb5, 0x13, 0xb5, 0x56, 0x19, 0x66, 0x0e, 0x12, 0xfd, 0x67, 0xd8, 0x90, 0x37, 0x46, 0x19, 0x4b, 0x28, 0x03, 0x3f, 0x10, 0x86, 0x04, 0x48, 0x14, 0x21, 0x83, 0x0b, 0xa2, 0x31, 0x8c, 0x78, 0x30, 0x21, 0x02, 0x2b, 0x56, 0xcd, 0xfd, 0x5e, 0x12, 0x08, 0x69, 0x2e, 0x04, 0x05, 0x5a, 0xa2, 0x0d, 0x03, 0x04, 0x06, 0x03, 0x14, 0x9b, 0x12, 0x4c, 0x12, 0x01, 0x5a, 0x04, 0x73, 0x10, 0x03, 0x68, 0x01, 0x8c, 0xb4, 0x02, 0x19, 0x56, 0x02, 0x3e, 0x04, 0x05, 0x01, 0x4e, 0x25, 0x21, 0x02, 0x04, 0x05, 0xb1, 0x16, 0x1f, 0xaf, 0x05, 0x07, 0x9b, 0x4a, 0x08, 0x05, 0xfe, 0xf4, 0x68, 0x2c, 0x05, 0x4f, 0x02, 0x1c, 0x55, 0x55, 0x05, 0x07, 0xd0, 0x14, 0x2a, 0x5e, 0xfe, 0x94, 0x07, 0xfd, 0xf2, 0x37, 0x05, 0x51, 0x1b, 0xf3, 0x05, 0xac, 0x47, 0x86, 0x38, 0x07, 0xfe, 0xd4, 0x05, 0x05, 0x11, 0x2a, 0x05, 0x01, 0x46, 0x14, 0x16, 0x04, 0x05, 0x0d, 0x80, 0x31, 0x0a, 0xfe, 0xc6, 0x11, 0xac, 0x08, 0x02, 0x01, 0x1a, 0x08, 0x2e, 0x17, 0x02, 0xfe, 0x9d, 0x0f, 0x03, 0xad, 0x0d, 0xc5, 0x0d, 0x05, 0xfe, 0xd1, 0x8a, 0x01, 0x17, 0x90, 0x66, 0xfe, 0xf5, 0x11, 0xfe, 0xef, 0x29, 0x14, 0x4d, 0x43, 0x12, 0x0b, 0x01, 0x3d, 0x05, 0x0f, 0xfe, 0xea, 0x67, 0x1a, 0x39, 0x45, 0xa2, 0x81, 0x6b, 0xd7, 0x4f, 0x0d, 0x05, 0x39, 0xfe, 0xcb, 0x21, 0x15, 0x28, 0x05, 0x1b, 0x01, 0x2d, 0x1a, 0x1f, 0x07, 0x1c, 0x83, 0x29, 0x3b, 0x05, 0x05, 0x26, 0x05, 0x0d, 0x02, 0x08, 0xc6, 0x0a, 0x1a, 0xfe, 0x01, 0x5d, 0x08, 0x03, 0xac, 0xfe, 0xd4, 0x05, 0x74, 0x21, 0x05, 0x02, 0x15, 0xfe, 0xb1, 0x1d, 0x79, 0x05, 0x01, 0x22, 0x0d, 0x03, 0xb3, 0x07, 0xfe, 0xa5, 0x05, 0x86, 0x26, 0x0d, 0x32, 0x7c, 0x0c, 0xac, 0xaa, 0x08, 0x1c, 0x62, 0xb3, 0x01, 0x14, 0x08, 0x1d, 0x61, 0x24, 0x0a, 0x55, 0x2b, 0x06, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x8c, 0x00, 0x20, 0x05, 0xe8, 0x05, 0xd9, 0x00, 0x0a, 0x00, 0x23, 0x00, 0x38, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x33, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x33, 0x15, 0x21, 0x05, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x37, 0x13, 0x27, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x25, 0x06, 0x07, 0x23, 0x15, 0x27, 0x37, 0x15, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x03, 0x37, 0x13, 0x16, 0x15, 0x14, 0x01, 0x16, 0x1f, 0x01, 0x37, 0x03, 0x27, 0x37, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x27, 0x13, 0x36, 0x37, 0x36, 0x02, 0x8c, 0x9a, 0xa7, 0xb6, 0x72, 0x9a, 0xfe, 0x4b, 0xfe, 0x28, 0x28, 0x23, 0x4b, 0x38, 0xd4, 0x16, 0x37, 0x59, 0x07, 0x15, 0x1f, 0x54, 0x0e, 0x0e, 0x01, 0x6d, 0xfe, 0x4d, 0x44, 0x33, 0x29, 0x04, 0xfd, 0x4d, 0x9d, 0x97, 0xbd, 0xbd, 0xb3, 0x34, 0x16, 0x07, 0x2d, 0xb5, 0x7a, 0xdb, 0x21, 0xfd, 0x35, 0x99, 0x56, 0x4c, 0x38, 0x16, 0xd3, 0x36, 0x59, 0x1f, 0x2e, 0x07, 0x06, 0x39, 0x2f, 0xb8, 0x7a, 0xd9, 0x23, 0x32, 0x2a, 0x01, 0xea, 0x01, 0x9a, 0x1a, 0x61, 0x1e, 0xfe, 0x01, 0x5c, 0xb8, 0x4d, 0x4f, 0x48, 0x4b, 0x92, 0x24, 0x6b, 0xfe, 0xff, 0x24, 0xac, 0x14, 0x13, 0x23, 0x20, 0x2c, 0x01, 0x9f, 0x21, 0x1b, 0x61, 0x93, 0x0a, 0x49, 0x97, 0x95, 0x46, 0x0b, 0x37, 0x11, 0x13, 0x34, 0x48, 0x01, 0x60, 0x4f, 0xfe, 0x5d, 0x42, 0x41, 0x36, 0x04, 0x9e, 0x01, 0x92, 0x91, 0x24, 0xfe, 0xff, 0x6b, 0x23, 0xac, 0x28, 0x01, 0x09, 0x6b, 0xfe, 0xa1, 0x4e, 0x01, 0xa4, 0x41, 0x21, 0x1b, 0x00, 0x00, 0x04, 0x00, 0x8c, 0x00, 0x20, 0x05, 0xe8, 0x05, 0xd9, 0x00, 0x1c, 0x00, 0x35, 0x00, 0x4a, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x35, 0x3e, 0x01, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x0e, 0x01, 0x01, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x37, 0x13, 0x27, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x25, 0x06, 0x07, 0x23, 0x15, 0x27, 0x37, 0x15, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x03, 0x37, 0x13, 0x16, 0x15, 0x14, 0x01, 0x16, 0x1f, 0x01, 0x37, 0x03, 0x27, 0x37, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x27, 0x13, 0x36, 0x37, 0x36, 0x03, 0x07, 0x01, 0x32, 0xfe, 0x26, 0x39, 0xb9, 0x16, 0x2c, 0x21, 0x43, 0x36, 0x2a, 0x5d, 0x50, 0x44, 0x65, 0x2b, 0x73, 0x8a, 0x22, 0x2b, 0x0d, 0x7d, 0xfd, 0x56, 0x28, 0x23, 0x4b, 0x38, 0xd4, 0x16, 0x37, 0x59, 0x07, 0x15, 0x1f, 0x54, 0x0e, 0x0e, 0x01, 0x6d, 0xfe, 0x4d, 0x44, 0x33, 0x29, 0x04, 0xfd, 0x4d, 0x9d, 0x97, 0xbd, 0xbd, 0xb3, 0x34, 0x16, 0x07, 0x2d, 0xb5, 0x7a, 0xdb, 0x21, 0xfd, 0x35, 0x99, 0x56, 0x4c, 0x38, 0x16, 0xd3, 0x36, 0x59, 0x1f, 0x2e, 0x07, 0x06, 0x39, 0x2f, 0xb8, 0x7a, 0xd9, 0x23, 0x32, 0x2a, 0x01, 0xd2, 0x5d, 0x55, 0x31, 0x9e, 0x15, 0x29, 0x38, 0x1a, 0x28, 0x33, 0x18, 0x26, 0x6e, 0x19, 0x14, 0x63, 0x51, 0x26, 0x44, 0x2d, 0x0d, 0x6d, 0xfe, 0xba, 0x4d, 0x4f, 0x48, 0x4b, 0x92, 0x24, 0x6b, 0xfe, 0xff, 0x24, 0xac, 0x14, 0x13, 0x23, 0x20, 0x2c, 0x01, 0x9f, 0x21, 0x1b, 0x61, 0x93, 0x0a, 0x49, 0x97, 0x95, 0x46, 0x0b, 0x37, 0x11, 0x13, 0x34, 0x48, 0x01, 0x60, 0x4f, 0xfe, 0x5d, 0x42, 0x41, 0x36, 0x04, 0x9e, 0x01, 0x92, 0x91, 0x24, 0xfe, 0xff, 0x6b, 0x23, 0xac, 0x28, 0x01, 0x09, 0x6b, 0xfe, 0xa1, 0x4e, 0x01, 0xa4, 0x41, 0x21, 0x1b, 0x00, 0x04, 0x00, 0x8c, 0x00, 0x20, 0x05, 0xe8, 0x05, 0xd9, 0x00, 0x28, 0x00, 0x41, 0x00, 0x56, 0x00, 0x6b, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x37, 0x13, 0x27, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x25, 0x06, 0x07, 0x23, 0x15, 0x27, 0x37, 0x15, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x03, 0x37, 0x13, 0x16, 0x15, 0x14, 0x01, 0x16, 0x1f, 0x01, 0x37, 0x03, 0x27, 0x37, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x27, 0x13, 0x36, 0x37, 0x36, 0x03, 0xeb, 0x09, 0x56, 0x9c, 0x8d, 0x2e, 0x61, 0x3f, 0x41, 0x5b, 0x2f, 0x55, 0x53, 0x4e, 0x47, 0x64, 0x68, 0x41, 0x40, 0x43, 0x42, 0x25, 0x56, 0x4e, 0x44, 0x62, 0x2c, 0x74, 0x8b, 0x4b, 0xfc, 0xc6, 0x28, 0x23, 0x4b, 0x38, 0xd4, 0x16, 0x37, 0x59, 0x07, 0x15, 0x1f, 0x54, 0x0e, 0x0e, 0x01, 0x6d, 0xfe, 0x4d, 0x44, 0x33, 0x29, 0x04, 0xfd, 0x4d, 0x9d, 0x97, 0xbd, 0xbd, 0xb3, 0x34, 0x16, 0x07, 0x2d, 0xb5, 0x7a, 0xdb, 0x21, 0xfd, 0x35, 0x99, 0x56, 0x4c, 0x38, 0x16, 0xd3, 0x36, 0x59, 0x1f, 0x2e, 0x07, 0x06, 0x39, 0x2f, 0xb8, 0x7a, 0xd9, 0x23, 0x32, 0x2a, 0x02, 0xbe, 0x02, 0x53, 0x3c, 0x5c, 0x65, 0x0e, 0x12, 0x6c, 0x1e, 0x12, 0x32, 0x33, 0x2d, 0x32, 0x5b, 0x27, 0x26, 0x27, 0x29, 0x0e, 0x14, 0x62, 0x0f, 0x0d, 0x59, 0x4b, 0x34, 0x4a, 0xfe, 0x18, 0x4d, 0x4f, 0x48, 0x4b, 0x92, 0x24, 0x6b, 0xfe, 0xff, 0x24, 0xac, 0x14, 0x13, 0x23, 0x20, 0x2c, 0x01, 0x9f, 0x21, 0x1b, 0x61, 0x93, 0x0a, 0x49, 0x97, 0x95, 0x46, 0x0b, 0x37, 0x11, 0x13, 0x34, 0x48, 0x01, 0x60, 0x4f, 0xfe, 0x5d, 0x42, 0x41, 0x36, 0x04, 0x9e, 0x01, 0x92, 0x91, 0x24, 0xfe, 0xff, 0x6b, 0x23, 0xac, 0x28, 0x01, 0x09, 0x6b, 0xfe, 0xa1, 0x4e, 0x01, 0xa4, 0x41, 0x21, 0x1b, 0x00, 0x05, 0x00, 0x8c, 0x00, 0x20, 0x05, 0xe8, 0x05, 0xd9, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x26, 0x00, 0x3b, 0x00, 0x50, 0x00, 0x00, 0x01, 0x03, 0x33, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x01, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x37, 0x13, 0x27, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x25, 0x06, 0x07, 0x23, 0x15, 0x27, 0x37, 0x15, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x03, 0x37, 0x13, 0x16, 0x15, 0x14, 0x01, 0x16, 0x1f, 0x01, 0x37, 0x03, 0x27, 0x37, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x27, 0x13, 0x36, 0x37, 0x36, 0x03, 0x57, 0xcf, 0xcf, 0x12, 0x9f, 0x6d, 0x6d, 0x8d, 0xfe, 0xa8, 0xfe, 0xb5, 0x28, 0x23, 0x4b, 0x38, 0xd4, 0x16, 0x37, 0x59, 0x07, 0x15, 0x1f, 0x54, 0x0e, 0x0e, 0x01, 0x6d, 0xfe, 0x4d, 0x44, 0x33, 0x29, 0x04, 0xfd, 0x4d, 0x9d, 0x97, 0xbd, 0xbd, 0xb3, 0x34, 0x16, 0x07, 0x2d, 0xb5, 0x7a, 0xdb, 0x21, 0xfd, 0x35, 0x99, 0x56, 0x4c, 0x38, 0x16, 0xd3, 0x36, 0x59, 0x1f, 0x2e, 0x07, 0x06, 0x39, 0x2f, 0xb8, 0x7a, 0xd9, 0x23, 0x32, 0x2a, 0x03, 0x52, 0xfe, 0xff, 0x01, 0x8a, 0xfe, 0x76, 0x5f, 0x8e, 0x8e, 0x60, 0xfe, 0x84, 0x4d, 0x4f, 0x48, 0x4b, 0x92, 0x24, 0x6b, 0xfe, 0xff, 0x24, 0xac, 0x14, 0x13, 0x23, 0x20, 0x2c, 0x01, 0x9f, 0x21, 0x1b, 0x61, 0x93, 0x0a, 0x49, 0x97, 0x95, 0x46, 0x0b, 0x37, 0x11, 0x13, 0x34, 0x48, 0x01, 0x60, 0x4f, 0xfe, 0x5d, 0x42, 0x41, 0x36, 0x04, 0x9e, 0x01, 0x92, 0x91, 0x24, 0xfe, 0xff, 0x6b, 0x23, 0xac, 0x28, 0x01, 0x09, 0x6b, 0xfe, 0xa1, 0x4e, 0x01, 0xa4, 0x41, 0x21, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x8c, 0x00, 0x20, 0x05, 0xe8, 0x05, 0xd9, 0x00, 0x1d, 0x00, 0x36, 0x00, 0x4b, 0x00, 0x60, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x15, 0x06, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x01, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x37, 0x13, 0x27, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x25, 0x06, 0x07, 0x23, 0x15, 0x27, 0x37, 0x15, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x03, 0x37, 0x13, 0x16, 0x15, 0x14, 0x01, 0x16, 0x1f, 0x01, 0x37, 0x03, 0x27, 0x37, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x27, 0x13, 0x36, 0x37, 0x36, 0x02, 0x75, 0x01, 0x96, 0xfe, 0xe5, 0x02, 0x2c, 0x15, 0x7d, 0x92, 0x96, 0x87, 0x2d, 0x5e, 0x3f, 0x45, 0x54, 0x2f, 0x4a, 0x54, 0x54, 0x4a, 0x23, 0x48, 0x3f, 0xfe, 0x3f, 0x28, 0x23, 0x4b, 0x38, 0xd4, 0x16, 0x37, 0x59, 0x07, 0x15, 0x1f, 0x54, 0x0e, 0x0e, 0x01, 0x6d, 0xfe, 0x4d, 0x44, 0x33, 0x29, 0x04, 0xfd, 0x4d, 0x9d, 0x97, 0xbd, 0xbd, 0xb3, 0x34, 0x16, 0x07, 0x2d, 0xb5, 0x7a, 0xdb, 0x21, 0xfd, 0x35, 0x99, 0x56, 0x4c, 0x38, 0x16, 0xd3, 0x36, 0x59, 0x1f, 0x2e, 0x07, 0x06, 0x39, 0x2f, 0xb8, 0x7a, 0xd9, 0x23, 0x32, 0x2a, 0x03, 0xd0, 0x5f, 0x70, 0x01, 0x07, 0x74, 0x63, 0x64, 0x72, 0x0e, 0x0f, 0x72, 0x1f, 0x12, 0x40, 0x38, 0x39, 0x40, 0x0d, 0x19, 0xfe, 0x53, 0x4d, 0x4f, 0x48, 0x4b, 0x92, 0x24, 0x6b, 0xfe, 0xff, 0x24, 0xac, 0x14, 0x13, 0x23, 0x20, 0x2c, 0x01, 0x9f, 0x21, 0x1b, 0x61, 0x93, 0x0a, 0x49, 0x97, 0x95, 0x46, 0x0b, 0x37, 0x11, 0x13, 0x34, 0x48, 0x01, 0x60, 0x4f, 0xfe, 0x5d, 0x42, 0x41, 0x36, 0x04, 0x9e, 0x01, 0x92, 0x91, 0x24, 0xfe, 0xff, 0x6b, 0x23, 0xac, 0x28, 0x01, 0x09, 0x6b, 0xfe, 0xa1, 0x4e, 0x01, 0xa4, 0x41, 0x21, 0x1b, 0x00, 0x00, 0x05, 0x00, 0x8c, 0x00, 0x20, 0x05, 0xe8, 0x05, 0xd9, 0x00, 0x09, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x50, 0x00, 0x65, 0x00, 0x00, 0x01, 0x22, 0x06, 0x14, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x13, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x06, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x01, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x37, 0x13, 0x27, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x25, 0x06, 0x07, 0x23, 0x15, 0x27, 0x37, 0x15, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x03, 0x37, 0x13, 0x16, 0x15, 0x14, 0x01, 0x16, 0x1f, 0x01, 0x37, 0x03, 0x27, 0x37, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x27, 0x13, 0x36, 0x37, 0x36, 0x03, 0x2c, 0x32, 0x3d, 0x3d, 0x32, 0x34, 0x3b, 0x3b, 0x8a, 0x37, 0x3f, 0x1f, 0x4e, 0x53, 0x03, 0x06, 0x54, 0x32, 0x69, 0x7a, 0x7f, 0x69, 0x78, 0x7e, 0x98, 0x84, 0x22, 0x45, 0xfc, 0xfb, 0x28, 0x23, 0x4b, 0x38, 0xd4, 0x16, 0x37, 0x59, 0x07, 0x15, 0x1f, 0x54, 0x0e, 0x0e, 0x01, 0x6d, 0xfe, 0x4d, 0x44, 0x33, 0x29, 0x04, 0xfd, 0x4d, 0x9d, 0x97, 0xbd, 0xbd, 0xb3, 0x34, 0x16, 0x07, 0x2d, 0xb5, 0x7a, 0xdb, 0x21, 0xfd, 0x35, 0x99, 0x56, 0x4c, 0x38, 0x16, 0xd3, 0x36, 0x59, 0x1f, 0x2e, 0x07, 0x06, 0x39, 0x2f, 0xb8, 0x7a, 0xd9, 0x23, 0x32, 0x2a, 0x02, 0xbc, 0x41, 0x76, 0x40, 0x40, 0x76, 0x41, 0x01, 0x0e, 0x66, 0x16, 0x0e, 0x60, 0x35, 0x07, 0x28, 0x73, 0x61, 0x5f, 0x74, 0xa5, 0x96, 0x8f, 0xae, 0x0c, 0xfc, 0xfd, 0x4d, 0x4f, 0x48, 0x4b, 0x92, 0x24, 0x6b, 0xfe, 0xff, 0x24, 0xac, 0x14, 0x13, 0x23, 0x20, 0x2c, 0x01, 0x9f, 0x21, 0x1b, 0x61, 0x93, 0x0a, 0x49, 0x97, 0x95, 0x46, 0x0b, 0x37, 0x11, 0x13, 0x34, 0x48, 0x01, 0x60, 0x4f, 0xfe, 0x5d, 0x42, 0x41, 0x36, 0x04, 0x9e, 0x01, 0x92, 0x91, 0x24, 0xfe, 0xff, 0x6b, 0x23, 0xac, 0x28, 0x01, 0x09, 0x6b, 0xfe, 0xa1, 0x4e, 0x01, 0xa4, 0x41, 0x21, 0x1b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x8c, 0x00, 0x20, 0x05, 0xe8, 0x05, 0xd9, 0x00, 0x06, 0x00, 0x1f, 0x00, 0x34, 0x00, 0x49, 0x00, 0x00, 0x01, 0x21, 0x15, 0x03, 0x23, 0x13, 0x21, 0x01, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x37, 0x13, 0x27, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x25, 0x06, 0x07, 0x23, 0x15, 0x27, 0x37, 0x15, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x03, 0x37, 0x13, 0x16, 0x15, 0x14, 0x01, 0x16, 0x1f, 0x01, 0x37, 0x03, 0x27, 0x37, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x27, 0x13, 0x36, 0x37, 0x36, 0x02, 0x5f, 0x01, 0xce, 0xf5, 0x84, 0xe5, 0xfe, 0xc6, 0xfe, 0x55, 0x28, 0x23, 0x4b, 0x38, 0xd4, 0x16, 0x37, 0x59, 0x07, 0x15, 0x1f, 0x54, 0x0e, 0x0e, 0x01, 0x6d, 0xfe, 0x4d, 0x44, 0x33, 0x29, 0x04, 0xfd, 0x4d, 0x9d, 0x97, 0xbd, 0xbd, 0xb3, 0x34, 0x16, 0x07, 0x2d, 0xb5, 0x7a, 0xdb, 0x21, 0xfd, 0x35, 0x99, 0x56, 0x4c, 0x38, 0x16, 0xd3, 0x36, 0x59, 0x1f, 0x2e, 0x07, 0x06, 0x39, 0x2f, 0xb8, 0x7a, 0xd9, 0x23, 0x32, 0x2a, 0x03, 0xba, 0x32, 0xfd, 0xb9, 0x02, 0x1a, 0xfd, 0x7b, 0x4d, 0x4f, 0x48, 0x4b, 0x92, 0x24, 0x6b, 0xfe, 0xff, 0x24, 0xac, 0x14, 0x13, 0x23, 0x20, 0x2c, 0x01, 0x9f, 0x21, 0x1b, 0x61, 0x93, 0x0a, 0x49, 0x97, 0x95, 0x46, 0x0b, 0x37, 0x11, 0x13, 0x34, 0x48, 0x01, 0x60, 0x4f, 0xfe, 0x5d, 0x42, 0x41, 0x36, 0x04, 0x9e, 0x01, 0x92, 0x91, 0x24, 0xfe, 0xff, 0x6b, 0x23, 0xac, 0x28, 0x01, 0x09, 0x6b, 0xfe, 0xa1, 0x4e, 0x01, 0xa4, 0x41, 0x21, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x8c, 0x00, 0x20, 0x05, 0xe8, 0x05, 0xd9, 0x00, 0x18, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x00, 0x37, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x37, 0x13, 0x27, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x21, 0x15, 0x21, 0x22, 0x27, 0x26, 0x25, 0x06, 0x07, 0x23, 0x15, 0x27, 0x37, 0x15, 0x33, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x03, 0x37, 0x13, 0x16, 0x15, 0x14, 0x01, 0x16, 0x1f, 0x01, 0x37, 0x03, 0x27, 0x37, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x03, 0x27, 0x13, 0x36, 0x37, 0x36, 0xb4, 0x28, 0x23, 0x4b, 0x38, 0xd4, 0x16, 0x37, 0x59, 0x07, 0x15, 0x1f, 0x54, 0x0e, 0x0e, 0x01, 0x6d, 0xfe, 0x4d, 0x44, 0x33, 0x29, 0x04, 0xfd, 0x4d, 0x9d, 0x97, 0xbd, 0xbd, 0xb3, 0x34, 0x16, 0x07, 0x2d, 0xb5, 0x7a, 0xdb, 0x21, 0xfd, 0x35, 0x99, 0x56, 0x4c, 0x38, 0x16, 0xd3, 0x36, 0x59, 0x1f, 0x2e, 0x07, 0x06, 0x39, 0x2f, 0xb8, 0x7a, 0xd9, 0x23, 0x32, 0x2a, 0xd6, 0x4d, 0x4f, 0x48, 0x4b, 0x92, 0x24, 0x6b, 0xfe, 0xff, 0x24, 0xac, 0x14, 0x13, 0x23, 0x20, 0x2c, 0x01, 0x9f, 0x21, 0x1b, 0x61, 0x93, 0x0a, 0x49, 0x97, 0x95, 0x46, 0x0b, 0x37, 0x11, 0x13, 0x34, 0x48, 0x01, 0x60, 0x4f, 0xfe, 0x5d, 0x42, 0x41, 0x36, 0x04, 0x9e, 0x01, 0x92, 0x91, 0x24, 0xfe, 0xff, 0x6b, 0x23, 0xac, 0x28, 0x01, 0x09, 0x6b, 0xfe, 0xa1, 0x4e, 0x01, 0xa4, 0x41, 0x21, 0x1b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x9a, 0x00, 0x00, 0x05, 0xd9, 0x05, 0xa1, 0x00, 0x10, 0x00, 0x1a, 0x00, 0x27, 0x00, 0x39, 0x00, 0x48, 0x00, 0x52, 0x00, 0x00, 0x01, 0x21, 0x32, 0x1f, 0x01, 0x37, 0x33, 0x15, 0x02, 0x07, 0x21, 0x35, 0x36, 0x37, 0x03, 0x26, 0x23, 0x07, 0x32, 0x1f, 0x01, 0x03, 0x26, 0x27, 0x12, 0x37, 0x36, 0x01, 0x12, 0x15, 0x17, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x26, 0x03, 0x36, 0x37, 0x05, 0x12, 0x17, 0x27, 0x02, 0x0f, 0x01, 0x17, 0x23, 0x03, 0x27, 0x36, 0x37, 0x36, 0x35, 0x27, 0x35, 0x33, 0x01, 0x33, 0x15, 0x21, 0x32, 0x37, 0x33, 0x14, 0x03, 0x06, 0x2b, 0x01, 0x15, 0x23, 0x03, 0x27, 0x17, 0x11, 0x07, 0x21, 0x22, 0x2f, 0x01, 0x34, 0x37, 0x02, 0xd9, 0x01, 0x5f, 0x34, 0x1e, 0x42, 0x5a, 0x05, 0x8d, 0x0f, 0xfe, 0xcc, 0x57, 0x04, 0xb2, 0x1f, 0x0c, 0x5c, 0x5f, 0x26, 0x2c, 0xae, 0xf0, 0x19, 0x86, 0x14, 0x2c, 0x03, 0x05, 0x95, 0x02, 0x58, 0x0d, 0x24, 0x71, 0x0c, 0x9e, 0x16, 0xb5, 0xfc, 0xd3, 0x9a, 0x02, 0x65, 0xad, 0x03, 0x03, 0x04, 0x04, 0xb5, 0x07, 0x03, 0x48, 0x18, 0x5a, 0xcd, 0x02, 0x8f, 0x02, 0x01, 0x63, 0x1d, 0x1b, 0x03, 0xb5, 0x15, 0x1c, 0xb8, 0x04, 0x98, 0x54, 0x04, 0x04, 0xfe, 0xfb, 0x69, 0x2a, 0x04, 0x4b, 0x05, 0xa1, 0x54, 0x7d, 0x37, 0x02, 0xfe, 0xed, 0x15, 0x05, 0x35, 0x09, 0x01, 0x62, 0x1a, 0x05, 0x5c, 0x56, 0xfe, 0xb6, 0x9a, 0x13, 0x01, 0x04, 0x1c, 0x2f, 0xfe, 0x56, 0xfe, 0xea, 0x17, 0x27, 0x66, 0x3a, 0x08, 0x0f, 0x01, 0x3a, 0x17, 0x70, 0x1b, 0xfe, 0xe0, 0x0d, 0x3f, 0xfe, 0xb6, 0x10, 0x29, 0x1d, 0x01, 0x5c, 0x20, 0x1f, 0x80, 0x29, 0x0b, 0x39, 0x03, 0xfe, 0xa5, 0x73, 0x1a, 0x09, 0xfe, 0xa4, 0x17, 0x73, 0x01, 0x25, 0xb0, 0x06, 0xfe, 0xa9, 0x05, 0x80, 0x30, 0x30, 0x82, 0x00, 0x00, 0x00, 0x07, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdd, 0x05, 0xd9, 0x00, 0x13, 0x00, 0x25, 0x00, 0x32, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x5c, 0x00, 0x65, 0x00, 0x00, 0x01, 0x33, 0x20, 0x13, 0x16, 0x1d, 0x01, 0x10, 0x05, 0x06, 0x2b, 0x01, 0x20, 0x03, 0x26, 0x3d, 0x01, 0x10, 0x25, 0x36, 0x17, 0x15, 0x32, 0x1f, 0x01, 0x15, 0x06, 0x07, 0x15, 0x33, 0x36, 0x37, 0x23, 0x07, 0x26, 0x27, 0x26, 0x23, 0x01, 0x16, 0x33, 0x36, 0x13, 0x26, 0x23, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x05, 0x15, 0x13, 0x33, 0x32, 0x37, 0x34, 0x2f, 0x01, 0x22, 0x05, 0x17, 0x06, 0x07, 0x14, 0x1f, 0x01, 0x33, 0x34, 0x3f, 0x01, 0x33, 0x17, 0x27, 0x01, 0x07, 0x16, 0x17, 0x33, 0x35, 0x37, 0x33, 0x32, 0x3f, 0x01, 0x35, 0x23, 0x06, 0x23, 0x21, 0x27, 0x35, 0x05, 0x06, 0x1d, 0x01, 0x14, 0x1f, 0x01, 0x33, 0x11, 0x03, 0x2e, 0x19, 0x01, 0x63, 0xdb, 0x57, 0xfe, 0x97, 0x92, 0xa5, 0x03, 0xfe, 0x7b, 0xd0, 0x4b, 0x01, 0x1c, 0xab, 0x7c, 0x22, 0x2e, 0x6d, 0x19, 0x34, 0xfc, 0x09, 0x77, 0x03, 0x4a, 0x47, 0x11, 0x13, 0x17, 0xfd, 0xc7, 0xda, 0x08, 0x04, 0x86, 0x3c, 0x14, 0x1a, 0x2d, 0x56, 0x30, 0x46, 0x0b, 0x02, 0x40, 0x8a, 0x6a, 0x58, 0x18, 0x5b, 0x25, 0x0c, 0xfc, 0x38, 0x48, 0x44, 0x09, 0x7d, 0x1a, 0x02, 0x19, 0x80, 0x08, 0x44, 0x7d, 0x01, 0xc6, 0x79, 0x05, 0x74, 0x03, 0x06, 0x9a, 0x21, 0x37, 0x5f, 0x03, 0x13, 0x1f, 0xfe, 0xe4, 0x06, 0xfe, 0x20, 0x3b, 0x60, 0x17, 0xe3, 0x05, 0xd9, 0xfe, 0x92, 0xae, 0xcf, 0x06, 0xfe, 0x4f, 0xeb, 0x4c, 0x01, 0x86, 0xa8, 0xa3, 0x35, 0x01, 0x5f, 0xf1, 0x83, 0x93, 0x03, 0x6b, 0xce, 0x03, 0x16, 0x1f, 0x03, 0x08, 0xf0, 0x2c, 0x89, 0x16, 0x0c, 0xfe, 0xdf, 0x8b, 0x0f, 0x01, 0x01, 0x7e, 0x12, 0x79, 0x7d, 0x1f, 0xde, 0x03, 0xfe, 0xf4, 0x8a, 0x2f, 0x9d, 0x4d, 0x3c, 0x34, 0x7b, 0x31, 0x16, 0xe8, 0x3b, 0x43, 0x19, 0xf8, 0x2c, 0xf1, 0xfe, 0xe5, 0xfb, 0x03, 0xec, 0x5b, 0x06, 0x80, 0xb1, 0x03, 0x10, 0x06, 0x5f, 0x65, 0x69, 0x27, 0x0c, 0x5b, 0x29, 0x04, 0x01, 0x24, 0x00, 0x08, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdd, 0x05, 0xd9, 0x00, 0x0f, 0x00, 0x20, 0x00, 0x2f, 0x00, 0x3a, 0x00, 0x42, 0x00, 0x52, 0x00, 0x60, 0x00, 0x6a, 0x00, 0x00, 0x01, 0x20, 0x13, 0x16, 0x15, 0x10, 0x05, 0x06, 0x23, 0x20, 0x03, 0x26, 0x35, 0x10, 0x25, 0x36, 0x01, 0x10, 0x05, 0x16, 0x3b, 0x01, 0x20, 0x13, 0x36, 0x35, 0x10, 0x25, 0x26, 0x23, 0x20, 0x03, 0x06, 0x01, 0x21, 0x32, 0x1f, 0x01, 0x37, 0x15, 0x06, 0x07, 0x23, 0x35, 0x37, 0x26, 0x2f, 0x01, 0x23, 0x32, 0x1f, 0x01, 0x03, 0x23, 0x26, 0x27, 0x36, 0x37, 0x36, 0x01, 0x16, 0x1d, 0x01, 0x06, 0x2b, 0x01, 0x03, 0x25, 0x33, 0x17, 0x07, 0x23, 0x27, 0x23, 0x02, 0x07, 0x15, 0x26, 0x03, 0x27, 0x34, 0x37, 0x27, 0x01, 0x33, 0x15, 0x21, 0x32, 0x37, 0x15, 0x03, 0x07, 0x23, 0x07, 0x15, 0x23, 0x27, 0x25, 0x21, 0x17, 0x11, 0x07, 0x23, 0x22, 0x2f, 0x01, 0x36, 0x03, 0x3c, 0x01, 0x6e, 0xd6, 0x5c, 0xfe, 0xaa, 0x93, 0xbc, 0xfe, 0x87, 0xd0, 0x55, 0x01, 0x61, 0x99, 0xfe, 0x2d, 0x01, 0x3e, 0x8e, 0x99, 0x2b, 0x01, 0x44, 0xce, 0x53, 0xfe, 0xba, 0x90, 0xa6, 0xfe, 0xa2, 0xc9, 0x52, 0x02, 0x1e, 0x01, 0x1b, 0x30, 0x15, 0x34, 0x49, 0x62, 0x18, 0xf5, 0x46, 0x84, 0x17, 0x19, 0x45, 0x52, 0x1b, 0x28, 0x8a, 0x03, 0xcc, 0x10, 0x6b, 0x19, 0x28, 0x02, 0x5f, 0x7b, 0x13, 0x61, 0x5a, 0x8c, 0xfd, 0x29, 0xf8, 0x83, 0x03, 0x03, 0x46, 0x03, 0x95, 0x05, 0x0b, 0x8d, 0x02, 0x4e, 0x46, 0x02, 0xb0, 0x06, 0x01, 0x26, 0x12, 0x16, 0x9c, 0x15, 0x98, 0x05, 0x06, 0x79, 0xfe, 0xaf, 0x01, 0x0d, 0x06, 0x06, 0xdc, 0x49, 0x23, 0x06, 0x01, 0x05, 0xd9, 0xfe, 0x97, 0xb2, 0xd4, 0xfe, 0x58, 0xe9, 0x59, 0x01, 0x74, 0xa2, 0xdb, 0x01, 0xa9, 0xeb, 0x54, 0xfd, 0x12, 0xfe, 0x70, 0xd8, 0x58, 0x01, 0x59, 0xa5, 0xc5, 0x01, 0x8c, 0xe0, 0x53, 0xfe, 0xa6, 0x9f, 0x01, 0x6d, 0x45, 0x62, 0x2c, 0x03, 0xcc, 0x23, 0x03, 0x34, 0xfe, 0x27, 0x0c, 0x46, 0x56, 0xfe, 0xfe, 0x7f, 0x10, 0xd5, 0x1a, 0x20, 0xfe, 0xa7, 0xe2, 0x21, 0x17, 0x82, 0x01, 0x09, 0x59, 0xf4, 0x03, 0x31, 0xfe, 0xea, 0x15, 0x1a, 0x0b, 0x01, 0x12, 0x11, 0x1c, 0x8d, 0x31, 0xfe, 0xec, 0x5f, 0x14, 0x06, 0xfe, 0xdc, 0x09, 0x06, 0x55, 0xee, 0x8c, 0x05, 0xfe, 0xeb, 0x05, 0x67, 0x2c, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdd, 0x05, 0xd9, 0x00, 0x07, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x41, 0x00, 0x52, 0x00, 0x00, 0x01, 0x16, 0x17, 0x32, 0x37, 0x26, 0x27, 0x06, 0x01, 0x20, 0x13, 0x16, 0x15, 0x10, 0x05, 0x06, 0x23, 0x20, 0x03, 0x26, 0x35, 0x10, 0x25, 0x36, 0x01, 0x06, 0x07, 0x16, 0x33, 0x36, 0x37, 0x26, 0x01, 0x15, 0x23, 0x06, 0x2b, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x35, 0x34, 0x35, 0x34, 0x36, 0x37, 0x32, 0x17, 0x36, 0x33, 0x1e, 0x01, 0x15, 0x14, 0x15, 0x14, 0x15, 0x14, 0x06, 0x07, 0x23, 0x22, 0x27, 0x23, 0x25, 0x10, 0x05, 0x16, 0x3b, 0x01, 0x20, 0x13, 0x36, 0x35, 0x10, 0x25, 0x26, 0x23, 0x20, 0x03, 0x06, 0x01, 0x95, 0x02, 0xa5, 0x81, 0x57, 0x4e, 0x92, 0x9d, 0x01, 0xa5, 0x01, 0x6e, 0xd6, 0x5c, 0xfe, 0xaa, 0x93, 0xbc, 0xfe, 0x87, 0xd0, 0x55, 0x01, 0x61, 0x99, 0x01, 0xb1, 0x92, 0x4e, 0x57, 0x81, 0xa5, 0x02, 0x02, 0xfe, 0x5a, 0x03, 0x6a, 0xa0, 0x0d, 0x7e, 0x6d, 0x8c, 0x7a, 0x8d, 0x72, 0x73, 0x8e, 0x7a, 0x8c, 0x6d, 0x7e, 0x0d, 0xa0, 0x6b, 0x02, 0xfd, 0x83, 0x01, 0x3e, 0x8e, 0x99, 0x2b, 0x01, 0x44, 0xce, 0x53, 0xfe, 0xba, 0x90, 0xa6, 0xfe, 0xa2, 0xc9, 0x52, 0x02, 0xf4, 0xcd, 0x02, 0xcb, 0xc2, 0x04, 0x03, 0x02, 0x26, 0xfe, 0x97, 0xb2, 0xd4, 0xfe, 0x58, 0xe9, 0x59, 0x01, 0x74, 0xa2, 0xdb, 0x01, 0xa9, 0xeb, 0x54, 0xfd, 0xdd, 0x04, 0xc2, 0xcb, 0x02, 0xcd, 0xbf, 0xfe, 0xf3, 0x1c, 0xbd, 0x0f, 0xb9, 0x50, 0x07, 0x08, 0x04, 0x05, 0x74, 0x99, 0x01, 0xaa, 0xaa, 0x01, 0x99, 0x74, 0x05, 0x04, 0x08, 0x07, 0x50, 0xb9, 0x0f, 0xbd, 0x61, 0xfe, 0x70, 0xd8, 0x58, 0x01, 0x59, 0xa5, 0xc5, 0x01, 0x8c, 0xe0, 0x53, 0xfe, 0xa6, 0x9f, 0x00, 0x00, 0x00, 0x02, 0x01, 0x12, 0x00, 0x02, 0x05, 0x61, 0x05, 0xd9, 0x00, 0x18, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x32, 0x15, 0x06, 0x07, 0x17, 0x33, 0x32, 0x17, 0x07, 0x23, 0x17, 0x21, 0x16, 0x13, 0x37, 0x17, 0x06, 0x07, 0x26, 0x03, 0x21, 0x22, 0x03, 0x34, 0x01, 0x06, 0x23, 0x22, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x14, 0x1e, 0x01, 0x32, 0x36, 0x37, 0x17, 0x06, 0x02, 0x57, 0x8a, 0x01, 0x73, 0x16, 0xf7, 0x0b, 0x0e, 0x03, 0xf8, 0x0b, 0x01, 0x91, 0x0a, 0x7f, 0x79, 0x2b, 0x05, 0xf6, 0x0e, 0x87, 0xfe, 0x53, 0x0b, 0x4c, 0x01, 0xc5, 0x65, 0x6f, 0x70, 0xcb, 0x71, 0x3a, 0x1e, 0x2a, 0x24, 0x16, 0x02, 0x4a, 0x89, 0x96, 0x88, 0x25, 0x3e, 0x29, 0x05, 0xd9, 0x8e, 0xa3, 0x02, 0xe6, 0x92, 0x04, 0x65, 0x06, 0xfe, 0x72, 0x28, 0x8d, 0x08, 0x59, 0x18, 0x01, 0xad, 0x03, 0x24, 0x85, 0xfa, 0x68, 0x3f, 0x7d, 0xe1, 0x7d, 0x7c, 0x72, 0x3c, 0x2e, 0xd9, 0x3c, 0x43, 0x53, 0x98, 0x53, 0x53, 0x4c, 0xa9, 0x32, 0x00, 0x00, 0x03, 0x00, 0x87, 0x00, 0x00, 0x05, 0xbd, 0x05, 0xcd, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x02, 0xa4, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfd, 0xe3, 0x05, 0x36, 0xfb, 0x5f, 0x04, 0x0c, 0xfb, 0xf4, 0x02, 0xe9, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfd, 0x42, 0x05, 0xcd, 0xfa, 0x33, 0xa5, 0x04, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x87, 0x00, 0x00, 0x05, 0xbd, 0x05, 0xcd, 0x00, 0x16, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x8d, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x02, 0x2e, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfc, 0xcc, 0x05, 0x36, 0xfb, 0x5f, 0x04, 0x0c, 0xfb, 0xf4, 0x01, 0xae, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x02, 0x9c, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfc, 0x0c, 0x05, 0xcd, 0xfa, 0x33, 0xa5, 0x04, 0x83, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x87, 0x00, 0x00, 0x05, 0xbd, 0x05, 0xcd, 0x00, 0x16, 0x00, 0x2d, 0x00, 0x44, 0x00, 0x48, 0x00, 0x4c, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x8d, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x01, 0x17, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x01, 0x17, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfc, 0xcc, 0x05, 0x36, 0xfb, 0x5f, 0x04, 0x0c, 0xfb, 0xf4, 0x01, 0xae, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x01, 0x66, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x01, 0x61, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfc, 0x0c, 0x05, 0xcd, 0xfa, 0x33, 0xa5, 0x04, 0x83, 0x00, 0x06, 0x00, 0x87, 0x00, 0x00, 0x05, 0xbd, 0x05, 0xcd, 0x00, 0x16, 0x00, 0x2d, 0x00, 0x44, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x8d, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x02, 0x2e, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfd, 0xd2, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x02, 0x2e, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfc, 0xcc, 0x05, 0x36, 0xfb, 0x5f, 0x04, 0x0c, 0xfb, 0xf4, 0x04, 0x1f, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfd, 0xba, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x02, 0x9c, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfc, 0x0c, 0x05, 0xcd, 0xfa, 0x33, 0xa5, 0x04, 0x83, 0x00, 0x00, 0x00, 0x07, 0x00, 0x87, 0x00, 0x00, 0x05, 0xbd, 0x05, 0xcd, 0x00, 0x16, 0x00, 0x2d, 0x00, 0x44, 0x00, 0x5b, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x01, 0x8d, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x02, 0x2e, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfd, 0xd2, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x02, 0x2e, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfe, 0xe9, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfd, 0xe3, 0x05, 0x36, 0xfb, 0x5f, 0x04, 0x0c, 0xfb, 0xf4, 0x04, 0x1f, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfd, 0xba, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x02, 0x9c, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfe, 0xf5, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfd, 0x42, 0x05, 0xcd, 0xfa, 0x33, 0xa5, 0x04, 0x83, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x87, 0x00, 0x00, 0x05, 0xbd, 0x05, 0xcd, 0x00, 0x17, 0x00, 0x2f, 0x00, 0x46, 0x00, 0x5d, 0x00, 0x74, 0x00, 0x8b, 0x00, 0x8f, 0x00, 0x93, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x11, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x03, 0xba, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0xfd, 0xd3, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x02, 0x2e, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfd, 0xd2, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x02, 0x2e, 0x11, 0x12, 0x1c, 0x18, 0x27, 0x26, 0x19, 0x1b, 0x13, 0x11, 0x11, 0x12, 0x1c, 0x19, 0x4c, 0x19, 0x1b, 0x13, 0x11, 0xfc, 0xcc, 0x05, 0x36, 0xfb, 0x5f, 0x04, 0x0c, 0xfb, 0xf4, 0x02, 0xe9, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x01, 0x93, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfd, 0x56, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x03, 0x00, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0x2b, 0x2a, 0x1c, 0x1e, 0x15, 0x13, 0x13, 0x14, 0x1f, 0x1b, 0xfb, 0xda, 0x05, 0xcd, 0xfa, 0x33, 0xa5, 0x04, 0x83, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x99, 0x00, 0x01, 0x05, 0xdc, 0x05, 0xd9, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x29, 0x00, 0x00, 0x01, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x20, 0x24, 0x02, 0x10, 0x12, 0x24, 0x01, 0x14, 0x12, 0x04, 0x20, 0x24, 0x12, 0x35, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x04, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x14, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x03, 0x3a, 0xa9, 0x01, 0x42, 0xb6, 0xb1, 0xfe, 0xbf, 0xfe, 0xa3, 0xfe, 0xbe, 0xb1, 0xb5, 0x01, 0x41, 0xfe, 0x57, 0x9d, 0x01, 0x1c, 0x01, 0x36, 0x01, 0x1c, 0x9d, 0xa1, 0xfe, 0xe3, 0x96, 0x97, 0xfe, 0xe3, 0xa0, 0x03, 0x38, 0x1e, 0x36, 0x1e, 0x1d, 0x36, 0x1f, 0x20, 0x36, 0x1c, 0x1e, 0x35, 0x05, 0xd9, 0xc1, 0xfe, 0x98, 0xfe, 0x7a, 0xfe, 0x9d, 0xc6, 0xc6, 0x01, 0x63, 0x01, 0x86, 0x01, 0x68, 0xc1, 0xfd, 0x14, 0xad, 0xfe, 0xc5, 0xae, 0xae, 0x01, 0x3b, 0xad, 0xac, 0x01, 0x3f, 0xab, 0xab, 0xfe, 0xc1, 0xcd, 0x42, 0x3c, 0x21, 0x21, 0x3c, 0x42, 0x3d, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x99, 0x00, 0x01, 0x05, 0xdc, 0x05, 0xd9, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x29, 0x00, 0x36, 0x00, 0x00, 0x01, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x20, 0x24, 0x02, 0x10, 0x12, 0x24, 0x01, 0x14, 0x12, 0x04, 0x20, 0x24, 0x12, 0x35, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x04, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x14, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x24, 0x32, 0x1e, 0x01, 0x14, 0x0e, 0x01, 0x23, 0x22, 0x2e, 0x01, 0x34, 0x36, 0x03, 0x3a, 0xa9, 0x01, 0x42, 0xb6, 0xb1, 0xfe, 0xbf, 0xfe, 0xa3, 0xfe, 0xbe, 0xb1, 0xb5, 0x01, 0x41, 0xfe, 0x57, 0x9d, 0x01, 0x1c, 0x01, 0x36, 0x01, 0x1c, 0x9d, 0xa1, 0xfe, 0xe3, 0x96, 0x97, 0xfe, 0xe3, 0xa0, 0x03, 0x38, 0x1e, 0x36, 0x1e, 0x1d, 0x36, 0x1f, 0x20, 0x36, 0x1c, 0x1e, 0x35, 0xfd, 0x85, 0x3a, 0x36, 0x1f, 0x1f, 0x36, 0x1d, 0x1d, 0x36, 0x1f, 0x20, 0x05, 0xd9, 0xc1, 0xfe, 0x98, 0xfe, 0x7a, 0xfe, 0x9d, 0xc6, 0xc6, 0x01, 0x63, 0x01, 0x86, 0x01, 0x68, 0xc1, 0xfd, 0x14, 0xad, 0xfe, 0xc5, 0xae, 0xae, 0x01, 0x3b, 0xad, 0xac, 0x01, 0x3f, 0xab, 0xab, 0xfe, 0xc1, 0xcd, 0x42, 0x3c, 0x21, 0x21, 0x3c, 0x42, 0x3d, 0x20, 0x20, 0xdc, 0x20, 0x3d, 0x42, 0x3c, 0x21, 0x21, 0x3c, 0x42, 0x3d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x99, 0x00, 0x01, 0x05, 0xdc, 0x05, 0xd9, 0x00, 0x0c, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x20, 0x24, 0x02, 0x10, 0x12, 0x24, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x14, 0x1e, 0x01, 0x03, 0x3a, 0xa9, 0x01, 0x42, 0xb6, 0xb1, 0xfe, 0xbf, 0xfe, 0xa3, 0xfe, 0xbe, 0xb1, 0xb5, 0x01, 0x41, 0x02, 0x01, 0x1c, 0x36, 0x20, 0x1f, 0x36, 0x1d, 0x1e, 0x36, 0x1e, 0x1f, 0x35, 0x05, 0xd9, 0xc1, 0xfe, 0x98, 0xfe, 0x7a, 0xfe, 0x9d, 0xc6, 0xc6, 0x01, 0x63, 0x01, 0x86, 0x01, 0x68, 0xc1, 0xfc, 0x96, 0x20, 0x3d, 0x42, 0x3c, 0x21, 0x21, 0x3c, 0x42, 0x3d, 0x20, 0x00, 0x00, 0x03, 0x00, 0x99, 0x00, 0x01, 0x05, 0xdc, 0x05, 0xd9, 0x00, 0x0c, 0x00, 0x1a, 0x00, 0x27, 0x00, 0x00, 0x01, 0x32, 0x04, 0x12, 0x10, 0x02, 0x04, 0x20, 0x24, 0x02, 0x10, 0x12, 0x24, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x14, 0x1e, 0x01, 0x24, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x03, 0x3a, 0xa9, 0x01, 0x42, 0xb6, 0xb1, 0xfe, 0xbf, 0xfe, 0xa3, 0xfe, 0xbe, 0xb1, 0xb5, 0x01, 0x41, 0x02, 0x01, 0x1c, 0x36, 0x20, 0x1f, 0x36, 0x1d, 0x1e, 0x36, 0x1e, 0x1f, 0x35, 0xfc, 0xfb, 0x1f, 0x36, 0x1d, 0x1d, 0x36, 0x1f, 0x1f, 0x36, 0x3a, 0x35, 0x05, 0xd9, 0xc1, 0xfe, 0x98, 0xfe, 0x7a, 0xfe, 0x9d, 0xc6, 0xc6, 0x01, 0x63, 0x01, 0x86, 0x01, 0x68, 0xc1, 0xfc, 0x96, 0x20, 0x3d, 0x42, 0x3c, 0x21, 0x21, 0x3c, 0x42, 0x3d, 0x20, 0x9f, 0x42, 0x3c, 0x21, 0x21, 0x3c, 0x42, 0x3d, 0x20, 0x20, 0x00, 0x01, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x37, 0x21, 0x15, 0x21, 0x99, 0x05, 0x42, 0xfa, 0xbe, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x37, 0x21, 0x15, 0x21, 0x25, 0x21, 0x15, 0x21, 0x99, 0x02, 0x23, 0xfd, 0xdd, 0x03, 0x1f, 0x02, 0x23, 0xfd, 0xdd, 0xc8, 0xc8, 0xc8, 0xc8, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x03, 0x4d, 0x12, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x85, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x03, 0x4d, 0x12, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x85, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x03, 0x4e, 0x12, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x86, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x03, 0x4e, 0x12, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x86, 0x00, 0x02, 0x01, 0x35, 0x00, 0x06, 0x05, 0x3d, 0x05, 0xd9, 0x00, 0x11, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x36, 0x33, 0x32, 0x04, 0x33, 0x32, 0x37, 0x11, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x2f, 0x01, 0x23, 0x35, 0x33, 0x15, 0x23, 0x15, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x11, 0x06, 0x23, 0x22, 0x24, 0x23, 0x22, 0x07, 0x11, 0x23, 0x01, 0xd3, 0x2f, 0x36, 0x73, 0x01, 0x2d, 0xa8, 0x3f, 0x41, 0x2f, 0x30, 0x96, 0x9f, 0x7d, 0xac, 0x2d, 0x31, 0x12, 0x59, 0x44, 0xf3, 0x45, 0x30, 0x2e, 0xae, 0x9a, 0x98, 0x91, 0x47, 0x43, 0x5f, 0x5c, 0x9a, 0xfe, 0xe3, 0x74, 0x48, 0x3f, 0x56, 0x02, 0x9f, 0x11, 0xa3, 0x0c, 0x02, 0x62, 0x0a, 0x5f, 0x7e, 0x09, 0x02, 0x5d, 0x35, 0x35, 0x1a, 0x08, 0x78, 0x5c, 0x15, 0xfd, 0x0d, 0x1c, 0x9a, 0x1e, 0xfd, 0xc6, 0x00, 0x00, 0x00, 0x01, 0x01, 0x35, 0x00, 0x06, 0x05, 0x3d, 0x05, 0xd9, 0x00, 0x18, 0x00, 0x00, 0x01, 0x23, 0x35, 0x33, 0x15, 0x23, 0x15, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x11, 0x06, 0x23, 0x22, 0x24, 0x23, 0x22, 0x07, 0x11, 0x23, 0x01, 0x7a, 0x44, 0xf3, 0x45, 0x30, 0x2e, 0xae, 0x9a, 0x98, 0x91, 0x47, 0x43, 0x5f, 0x5c, 0x9a, 0xfe, 0xe3, 0x74, 0x48, 0x3f, 0x56, 0x05, 0xa4, 0x35, 0x35, 0x1a, 0x08, 0x78, 0x5c, 0x15, 0xfd, 0x0d, 0x1c, 0x9a, 0x1e, 0xfd, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5f, 0x00, 0x01, 0x06, 0x15, 0x05, 0xda, 0x00, 0x1f, 0x00, 0x00, 0x09, 0x01, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x09, 0x01, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x16, 0x13, 0x09, 0x01, 0x17, 0x01, 0x07, 0x03, 0x27, 0x07, 0x03, 0x27, 0x01, 0x02, 0xe4, 0xfe, 0xd4, 0xa6, 0xb3, 0xa8, 0x2a, 0x7d, 0x26, 0xa7, 0xb1, 0xa6, 0x01, 0x2c, 0x01, 0x2c, 0xa6, 0xb2, 0xa6, 0x28, 0x7a, 0x28, 0x3f, 0x1f, 0xfe, 0xf1, 0xfe, 0xd5, 0xa0, 0x01, 0x1f, 0xa7, 0xf3, 0xa1, 0xa0, 0xf3, 0xa6, 0x01, 0x1e, 0x02, 0x7e, 0x01, 0x51, 0xbb, 0xc7, 0xbb, 0x2c, 0x8a, 0x2c, 0xba, 0xc8, 0xba, 0xfe, 0xb0, 0x01, 0x4f, 0xbb, 0xc8, 0xbb, 0x2d, 0x8a, 0x2c, 0x71, 0xfe, 0x74, 0x01, 0x35, 0xfe, 0xaf, 0xb3, 0xfe, 0xf0, 0xb9, 0x01, 0x40, 0xb4, 0xb4, 0xfe, 0xc0, 0xb9, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb2, 0xff, 0xec, 0x05, 0xc2, 0x05, 0xdb, 0x00, 0x0f, 0x00, 0x52, 0x00, 0x00, 0x01, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x01, 0x13, 0x15, 0x23, 0x06, 0x23, 0x22, 0x27, 0x35, 0x23, 0x15, 0x23, 0x22, 0x24, 0x27, 0x26, 0x27, 0x07, 0x03, 0x05, 0x07, 0x30, 0x17, 0x16, 0x17, 0x16, 0x17, 0x11, 0x21, 0x35, 0x21, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x15, 0x21, 0x15, 0x21, 0x11, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x27, 0x25, 0x03, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x02, 0xc2, 0x23, 0x41, 0x22, 0x24, 0x40, 0x24, 0x25, 0x40, 0x23, 0x22, 0x40, 0x24, 0xcc, 0x07, 0x22, 0x23, 0x02, 0x03, 0x06, 0x07, 0x98, 0xfe, 0xea, 0x4d, 0x0f, 0x0b, 0x4f, 0x1a, 0x01, 0x14, 0x4e, 0x06, 0x41, 0x77, 0x62, 0x6a, 0xfe, 0xae, 0x01, 0x52, 0x18, 0x16, 0x38, 0x3d, 0x3e, 0x70, 0x3b, 0x3b, 0x70, 0x40, 0x3f, 0x36, 0x19, 0x17, 0x01, 0x48, 0xfe, 0xb8, 0x5a, 0x54, 0x77, 0x43, 0x02, 0x02, 0x4e, 0x01, 0x15, 0x1b, 0x4e, 0x0b, 0x0f, 0x4e, 0x8b, 0x67, 0x04, 0xd6, 0x27, 0x48, 0x27, 0x27, 0x48, 0x27, 0x28, 0x48, 0x27, 0x27, 0x48, 0xfa, 0xf2, 0x01, 0x03, 0x01, 0x02, 0x02, 0x60, 0x58, 0x11, 0x10, 0x41, 0x01, 0x4b, 0x7c, 0x40, 0x06, 0x58, 0x31, 0x28, 0x07, 0x02, 0xd4, 0x81, 0x33, 0x08, 0x0e, 0x22, 0x7c, 0x88, 0x7d, 0x44, 0x44, 0x7d, 0x88, 0x7c, 0x22, 0x0e, 0x09, 0x32, 0x81, 0xfd, 0x2f, 0x0a, 0x22, 0x31, 0x58, 0x03, 0x03, 0x40, 0x7c, 0xfe, 0xb5, 0x41, 0x10, 0x11, 0x58, 0x31, 0x23, 0x00, 0x00, 0x01, 0x00, 0xf2, 0x00, 0x00, 0x05, 0x83, 0x05, 0xd6, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x13, 0x36, 0x37, 0x33, 0x06, 0x07, 0x17, 0x16, 0x17, 0x0e, 0x01, 0x07, 0x26, 0x2f, 0x01, 0x06, 0x07, 0x27, 0x36, 0x37, 0x0b, 0x01, 0x16, 0x17, 0x07, 0x26, 0x27, 0x07, 0x06, 0x07, 0x22, 0x26, 0x27, 0x36, 0x3f, 0x01, 0x26, 0x27, 0x33, 0x16, 0x17, 0x13, 0x01, 0x27, 0x09, 0x01, 0x07, 0x03, 0x7f, 0xfa, 0x43, 0x19, 0x51, 0x16, 0x54, 0x8d, 0x37, 0x02, 0x05, 0x36, 0x27, 0x40, 0x03, 0x8e, 0x5c, 0x52, 0x23, 0x5c, 0x3b, 0xdc, 0xd9, 0x3b, 0x5b, 0x22, 0x53, 0x5e, 0x8c, 0x01, 0x39, 0x24, 0x43, 0x04, 0x01, 0x39, 0x8c, 0x54, 0x17, 0x53, 0x18, 0x44, 0xfa, 0xfe, 0x19, 0x1d, 0x02, 0x47, 0x02, 0x49, 0x1d, 0x02, 0xbd, 0xfe, 0xd0, 0x3b, 0x3c, 0x75, 0x49, 0xb6, 0x03, 0x40, 0x2a, 0x22, 0x01, 0x04, 0x4f, 0xa8, 0x38, 0x08, 0x42, 0x11, 0x31, 0x01, 0x22, 0xfe, 0xde, 0x31, 0x11, 0x42, 0x08, 0x38, 0xa8, 0x48, 0x0b, 0x1d, 0x24, 0x4c, 0x03, 0xb6, 0x49, 0x75, 0x3c, 0x3b, 0x01, 0x30, 0x02, 0x84, 0x95, 0xfd, 0x3a, 0x02, 0xc6, 0x95, 0x00, 0x00, 0x05, 0x00, 0x70, 0xff, 0xec, 0x03, 0x73, 0x05, 0xdb, 0x00, 0x07, 0x00, 0x1a, 0x00, 0x2e, 0x00, 0x4f, 0x00, 0x60, 0x00, 0x00, 0x01, 0x16, 0x33, 0x32, 0x35, 0x34, 0x27, 0x26, 0x13, 0x15, 0x06, 0x23, 0x22, 0x27, 0x35, 0x26, 0x35, 0x34, 0x37, 0x17, 0x06, 0x15, 0x14, 0x04, 0x07, 0x23, 0x26, 0x03, 0x24, 0x35, 0x34, 0x37, 0x15, 0x06, 0x15, 0x14, 0x04, 0x17, 0x06, 0x07, 0x35, 0x36, 0x35, 0x34, 0x27, 0x11, 0x27, 0x13, 0x11, 0x27, 0x11, 0x24, 0x27, 0x36, 0x37, 0x32, 0x33, 0x32, 0x17, 0x07, 0x17, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x15, 0x14, 0x04, 0x17, 0x06, 0x05, 0x35, 0x36, 0x27, 0x34, 0x35, 0x34, 0x25, 0x27, 0x03, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x01, 0x32, 0x19, 0x0c, 0x0a, 0x05, 0x20, 0xe0, 0x0b, 0x18, 0x20, 0x02, 0xa3, 0x93, 0x01, 0x3a, 0x01, 0x22, 0x01, 0x0e, 0x19, 0xb1, 0xfe, 0xfe, 0xf3, 0x9a, 0x01, 0xf5, 0x03, 0x04, 0xf8, 0xa3, 0xb1, 0x45, 0x45, 0x45, 0xfe, 0x9d, 0x04, 0x0c, 0xc0, 0x04, 0x02, 0x3b, 0x2f, 0x64, 0x55, 0x15, 0x18, 0x33, 0x3d, 0x08, 0x06, 0x28, 0x02, 0xa4, 0x05, 0x06, 0xfe, 0xba, 0xf6, 0x01, 0xff, 0x00, 0x45, 0x05, 0x13, 0x15, 0x15, 0x26, 0x14, 0x15, 0x25, 0x16, 0x15, 0x13, 0x04, 0xa4, 0x0c, 0x09, 0x06, 0x0a, 0x0b, 0xfb, 0x94, 0x42, 0x1d, 0x40, 0x30, 0x22, 0x40, 0x52, 0x1a, 0x2f, 0x18, 0x18, 0x2f, 0x3e, 0x77, 0x41, 0x01, 0xb7, 0x26, 0x6f, 0x63, 0x2f, 0x44, 0x26, 0x33, 0x2e, 0x59, 0x61, 0x51, 0x2f, 0x35, 0x22, 0x31, 0x27, 0x22, 0xfe, 0xb4, 0x13, 0x03, 0x01, 0xfe, 0x81, 0x10, 0x01, 0x75, 0x13, 0x8a, 0x90, 0x05, 0x45, 0x1e, 0x19, 0x06, 0x1b, 0x02, 0x36, 0x32, 0x2f, 0x75, 0x8a, 0x10, 0x3d, 0x20, 0x3d, 0x01, 0x02, 0x21, 0x6d, 0x07, 0x01, 0x2d, 0x0b, 0x2e, 0x18, 0x19, 0x2e, 0x18, 0x18, 0x2e, 0x19, 0x18, 0x2e, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6c, 0xff, 0xec, 0x06, 0x07, 0x05, 0xdb, 0x00, 0x04, 0x00, 0x09, 0x00, 0x37, 0x00, 0x00, 0x25, 0x0b, 0x01, 0x16, 0x32, 0x25, 0x0b, 0x01, 0x16, 0x32, 0x01, 0x33, 0x32, 0x1d, 0x01, 0x14, 0x2b, 0x01, 0x13, 0x06, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x2e, 0x01, 0x3d, 0x01, 0x13, 0x21, 0x13, 0x15, 0x14, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x13, 0x23, 0x26, 0x3d, 0x01, 0x34, 0x3b, 0x01, 0x37, 0x17, 0x33, 0x1b, 0x01, 0x33, 0x37, 0x05, 0xbc, 0xf8, 0xf9, 0x7d, 0xf9, 0xfd, 0x6e, 0xf8, 0xf8, 0x7c, 0xf8, 0x02, 0xbc, 0xc0, 0x33, 0x25, 0xaf, 0xf9, 0x02, 0x2b, 0x2b, 0x9b, 0x56, 0x54, 0x9a, 0x55, 0xf5, 0xfd, 0x92, 0xf6, 0x54, 0x9b, 0xa9, 0x9c, 0x2c, 0x2a, 0x01, 0xf7, 0xb7, 0x1d, 0x33, 0xc2, 0x2f, 0x2e, 0xe3, 0x74, 0x74, 0xe3, 0x2f, 0xed, 0x03, 0x3c, 0xfc, 0xc4, 0x26, 0x26, 0x03, 0x3c, 0xfc, 0xc4, 0x26, 0x03, 0xd1, 0x2a, 0x19, 0x28, 0xfc, 0xc7, 0x44, 0x3e, 0x3f, 0x47, 0x47, 0x7a, 0x42, 0x08, 0x03, 0x36, 0xfc, 0xca, 0x06, 0x43, 0x7b, 0x47, 0x47, 0x3f, 0x3e, 0x44, 0x03, 0x39, 0x11, 0x1c, 0x0f, 0x2f, 0x9b, 0x9b, 0x01, 0x43, 0xfe, 0xbd, 0x9b, 0x00, 0x02, 0x00, 0x70, 0x00, 0x00, 0x06, 0x03, 0x05, 0xdb, 0x00, 0x1a, 0x00, 0x26, 0x00, 0x00, 0x01, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x03, 0x27, 0x12, 0x01, 0x13, 0x23, 0x03, 0x21, 0x11, 0x23, 0x03, 0x21, 0x03, 0x23, 0x13, 0x02, 0x8a, 0xa5, 0x8f, 0x30, 0x2d, 0xb5, 0x44, 0x1f, 0x0f, 0x27, 0x71, 0x44, 0x3f, 0x2b, 0x8d, 0x4a, 0x1e, 0x33, 0x23, 0x2b, 0x46, 0x92, 0xb4, 0x6c, 0xcf, 0x04, 0x6f, 0x55, 0x72, 0x4c, 0xfe, 0xff, 0x7c, 0x01, 0xfe, 0xff, 0x4d, 0x73, 0x56, 0x05, 0x87, 0x54, 0x09, 0x27, 0xa6, 0x4e, 0x51, 0x39, 0x3b, 0x8d, 0x3a, 0x23, 0x38, 0xb3, 0x48, 0x4c, 0x22, 0x43, 0xfe, 0xdf, 0x44, 0x01, 0x99, 0xfd, 0x7c, 0xfd, 0xa6, 0x01, 0xd7, 0xfe, 0x29, 0x01, 0xd7, 0xfe, 0x29, 0x02, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0b, 0x00, 0x00, 0x05, 0x68, 0x05, 0xdb, 0x00, 0x0d, 0x00, 0x35, 0x00, 0x00, 0x00, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x13, 0x15, 0x3b, 0x01, 0x32, 0x36, 0x37, 0x14, 0x04, 0x07, 0x06, 0x07, 0x23, 0x26, 0x3d, 0x01, 0x26, 0x24, 0x03, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x33, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x3e, 0x01, 0x32, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x02, 0x9c, 0x2d, 0x52, 0x2b, 0x2d, 0x52, 0x2d, 0x2f, 0x51, 0x2c, 0x2a, 0x52, 0xa8, 0x05, 0x03, 0x87, 0xcb, 0x9b, 0xfe, 0x58, 0x23, 0x2f, 0x02, 0x26, 0x27, 0x04, 0xfe, 0x40, 0x4f, 0xb3, 0xd4, 0x74, 0x0c, 0x0c, 0x06, 0x3b, 0x36, 0x46, 0x4e, 0x4f, 0x8d, 0x96, 0x8e, 0x51, 0x4f, 0x47, 0x33, 0x04, 0xc4, 0x64, 0x59, 0x32, 0x32, 0x59, 0x64, 0x5b, 0x30, 0x30, 0xfe, 0x2d, 0x9c, 0xbf, 0x26, 0xe7, 0x9a, 0x97, 0x88, 0xf5, 0xa8, 0x9a, 0x14, 0x84, 0x8f, 0x01, 0x31, 0x02, 0xe9, 0x01, 0x9b, 0x07, 0x23, 0x2b, 0x9c, 0xac, 0x9e, 0x55, 0x55, 0x9e, 0xac, 0x9c, 0x2b, 0x20, 0x00, 0x00, 0x03, 0x00, 0xae, 0xff, 0xdd, 0x05, 0xc6, 0x05, 0xd0, 0x00, 0x3f, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x32, 0x1f, 0x01, 0x16, 0x17, 0x37, 0x16, 0x17, 0x07, 0x16, 0x17, 0x37, 0x16, 0x17, 0x07, 0x16, 0x14, 0x07, 0x17, 0x06, 0x07, 0x27, 0x06, 0x07, 0x17, 0x06, 0x07, 0x27, 0x06, 0x0f, 0x01, 0x06, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x07, 0x26, 0x27, 0x37, 0x26, 0x27, 0x07, 0x26, 0x27, 0x37, 0x26, 0x34, 0x37, 0x27, 0x36, 0x37, 0x17, 0x36, 0x37, 0x27, 0x36, 0x37, 0x17, 0x36, 0x3f, 0x01, 0x12, 0x20, 0x02, 0x10, 0x12, 0x20, 0x12, 0x10, 0x04, 0x14, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x03, 0x13, 0x4f, 0x26, 0x18, 0x3c, 0x3a, 0x71, 0x45, 0x39, 0x4b, 0x2a, 0x1e, 0x94, 0x21, 0x0f, 0x85, 0x03, 0x03, 0x85, 0x0f, 0x21, 0x94, 0x1e, 0x2a, 0x4b, 0x39, 0x45, 0x71, 0x3a, 0x3c, 0x18, 0x26, 0x4f, 0x27, 0x18, 0x3c, 0x39, 0x72, 0x44, 0x3a, 0x4c, 0x2b, 0x1d, 0x95, 0x21, 0x0e, 0x85, 0x04, 0x04, 0x85, 0x0e, 0x21, 0x95, 0x1d, 0x2b, 0x4c, 0x3a, 0x44, 0x72, 0x39, 0x3c, 0x18, 0xf2, 0xfe, 0xb8, 0xe8, 0xe8, 0x01, 0x48, 0xe8, 0xff, 0x00, 0x52, 0x73, 0x52, 0x52, 0x73, 0x05, 0xd0, 0x05, 0xbb, 0x0d, 0x1e, 0x84, 0x2d, 0x40, 0x9c, 0x32, 0x3c, 0x1f, 0x54, 0x5c, 0x45, 0x23, 0x44, 0x23, 0x46, 0x5b, 0x54, 0x1f, 0x3c, 0x33, 0x9b, 0x40, 0x2e, 0x84, 0x1d, 0x0e, 0xba, 0x06, 0x06, 0xba, 0x0e, 0x1d, 0x84, 0x2e, 0x40, 0x9b, 0x32, 0x3d, 0x1f, 0x54, 0x5b, 0x46, 0x23, 0x44, 0x23, 0x45, 0x5c, 0x54, 0x1f, 0x3c, 0x33, 0x9b, 0x40, 0x2d, 0x83, 0x1d, 0x0d, 0xbb, 0xfe, 0xc4, 0xfe, 0xfd, 0xfe, 0x95, 0xfe, 0xfe, 0x01, 0x02, 0x01, 0x6b, 0x75, 0x80, 0x5b, 0x5b, 0x80, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xeb, 0xff, 0xed, 0x05, 0x88, 0x05, 0xdd, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x13, 0x00, 0x18, 0x00, 0x1d, 0x00, 0x25, 0x00, 0x2c, 0x00, 0x31, 0x00, 0x36, 0x00, 0x3b, 0x00, 0x40, 0x00, 0x48, 0x00, 0x4f, 0x00, 0x5b, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x14, 0x1e, 0x01, 0x33, 0x26, 0x34, 0x37, 0x22, 0x06, 0x05, 0x16, 0x17, 0x37, 0x26, 0x27, 0x16, 0x17, 0x37, 0x26, 0x27, 0x16, 0x17, 0x37, 0x26, 0x27, 0x16, 0x07, 0x37, 0x26, 0x27, 0x14, 0x15, 0x14, 0x07, 0x17, 0x35, 0x34, 0x27, 0x06, 0x07, 0x17, 0x36, 0x35, 0x34, 0x05, 0x17, 0x36, 0x37, 0x06, 0x07, 0x17, 0x36, 0x37, 0x06, 0x07, 0x17, 0x36, 0x37, 0x06, 0x1f, 0x01, 0x26, 0x37, 0x06, 0x17, 0x37, 0x26, 0x35, 0x34, 0x37, 0x06, 0x15, 0x3f, 0x01, 0x26, 0x27, 0x06, 0x15, 0x14, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x33, 0x14, 0x23, 0x15, 0x16, 0x17, 0x16, 0x17, 0x36, 0x37, 0x04, 0x17, 0x06, 0x23, 0x26, 0x22, 0x07, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x03, 0x15, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x03, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x26, 0x23, 0x22, 0x07, 0x22, 0x27, 0x36, 0x25, 0x16, 0x17, 0x36, 0x37, 0x36, 0x03, 0x01, 0x0f, 0x1c, 0x10, 0x0d, 0x0d, 0x0f, 0x1d, 0x01, 0xc1, 0x63, 0x26, 0x17, 0x52, 0x82, 0x63, 0x21, 0x23, 0x51, 0x6c, 0x45, 0x0e, 0x2b, 0x36, 0x6f, 0x2e, 0x01, 0x35, 0x22, 0x59, 0x13, 0x36, 0x36, 0x2b, 0x2d, 0x34, 0x24, 0xfc, 0xce, 0x18, 0x26, 0x62, 0x4e, 0x25, 0x23, 0x21, 0x64, 0x57, 0x12, 0x2c, 0x0e, 0x44, 0x48, 0x0e, 0x35, 0x01, 0x2d, 0x3f, 0x36, 0x35, 0x14, 0x01, 0x22, 0x59, 0x34, 0x2d, 0x2a, 0x01, 0x01, 0x00, 0x32, 0x44, 0x44, 0x32, 0x2f, 0x46, 0x45, 0x51, 0x02, 0x02, 0x11, 0x13, 0x13, 0x23, 0x13, 0x12, 0x22, 0x14, 0x13, 0x11, 0x02, 0x03, 0x01, 0x01, 0x2f, 0x25, 0x03, 0x02, 0x48, 0x14, 0x01, 0x2d, 0x48, 0x4d, 0xe4, 0x24, 0x3e, 0x19, 0x04, 0x2f, 0x24, 0x2f, 0x01, 0x0a, 0x14, 0x17, 0x07, 0x01, 0x02, 0x2e, 0x24, 0x2e, 0x02, 0x1c, 0x24, 0x1f, 0x24, 0xe5, 0x4c, 0x48, 0x01, 0x2c, 0x13, 0x4a, 0x06, 0x09, 0x24, 0x05, 0xa0, 0x22, 0x1f, 0x12, 0x20, 0x42, 0x22, 0x11, 0x76, 0x3e, 0x30, 0x26, 0x38, 0x14, 0x61, 0x3e, 0x21, 0x55, 0x2a, 0x7e, 0x45, 0x13, 0x6d, 0x4c, 0x91, 0x4b, 0x08, 0x7d, 0x60, 0x11, 0x10, 0x81, 0x3f, 0x0a, 0x0c, 0x7b, 0x61, 0x88, 0x37, 0x1a, 0x63, 0x5b, 0x0d, 0x4f, 0x26, 0x30, 0x3e, 0x10, 0x6a, 0x21, 0x3e, 0x61, 0x29, 0x86, 0x13, 0x45, 0x7e, 0x43, 0x88, 0x08, 0x4b, 0x91, 0x57, 0x8b, 0x0a, 0x3d, 0x7b, 0x14, 0x15, 0x64, 0x7b, 0x03, 0x1a, 0x37, 0x88, 0x0e, 0x0d, 0x5b, 0x2b, 0x4d, 0x35, 0x37, 0x4c, 0x4c, 0x37, 0x35, 0x4d, 0x2d, 0x5a, 0x01, 0x02, 0x0a, 0x27, 0x2a, 0x27, 0x15, 0x15, 0x27, 0x2a, 0x27, 0x0a, 0x02, 0x01, 0x01, 0x59, 0x09, 0x28, 0x03, 0x04, 0x80, 0x35, 0x06, 0x5b, 0xa3, 0x0c, 0x0c, 0x14, 0x15, 0x4a, 0x35, 0x28, 0x09, 0xfc, 0xd6, 0x5c, 0x16, 0x1c, 0x64, 0x03, 0x1c, 0x09, 0x28, 0x35, 0x4a, 0x12, 0x11, 0x11, 0x0c, 0xa3, 0x5b, 0x06, 0x34, 0x8c, 0x0a, 0x09, 0x27, 0x00, 0x00, 0x0f, 0x00, 0xea, 0x00, 0x00, 0x05, 0x8a, 0x05, 0xd3, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x2f, 0x00, 0x37, 0x00, 0x4f, 0x00, 0x5f, 0x00, 0x9f, 0x00, 0xab, 0x00, 0xb3, 0x00, 0xbb, 0x00, 0xcb, 0x00, 0xd3, 0x00, 0xdb, 0x00, 0xe3, 0x00, 0xef, 0x00, 0x00, 0x01, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x0e, 0x01, 0x23, 0x22, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x07, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x33, 0x36, 0x37, 0x26, 0x25, 0x06, 0x07, 0x16, 0x17, 0x32, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x06, 0x27, 0x16, 0x15, 0x14, 0x07, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x13, 0x16, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x05, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x15, 0x36, 0x33, 0x32, 0x33, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x23, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x23, 0x22, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x32, 0x33, 0x32, 0x05, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x16, 0x17, 0x36, 0x17, 0x06, 0x07, 0x16, 0x17, 0x16, 0x17, 0x26, 0x25, 0x06, 0x07, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x07, 0x06, 0x07, 0x16, 0x17, 0x26, 0x35, 0x34, 0x17, 0x16, 0x17, 0x36, 0x37, 0x26, 0x27, 0x26, 0x17, 0x16, 0x17, 0x36, 0x37, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x26, 0x03, 0x3a, 0x11, 0x21, 0x12, 0x12, 0x21, 0x11, 0x12, 0x20, 0x12, 0x12, 0x20, 0xca, 0x47, 0x40, 0x73, 0x2e, 0x21, 0x07, 0x15, 0x4d, 0x08, 0x08, 0x59, 0x89, 0x0d, 0x01, 0xb2, 0x05, 0x0d, 0x8a, 0x59, 0x08, 0x07, 0x4d, 0x15, 0x07, 0x21, 0x2f, 0x72, 0x40, 0x44, 0x01, 0x01, 0x33, 0x2f, 0x2f, 0x62, 0x2b, 0x2c, 0x2d, 0x2d, 0x2c, 0x2b, 0x2d, 0x2a, 0x02, 0x02, 0x29, 0x2e, 0x2b, 0x2e, 0x2c, 0x2c, 0x2d, 0x2a, 0x03, 0x16, 0x0e, 0x05, 0x47, 0x3f, 0x71, 0x30, 0x22, 0x07, 0x15, 0x4d, 0x08, 0x0a, 0x5b, 0xfd, 0xef, 0x01, 0x1e, 0x6c, 0x38, 0x38, 0x6a, 0x1f, 0x93, 0x65, 0x03, 0x04, 0x68, 0x1d, 0x0b, 0x20, 0x32, 0x7b, 0x01, 0x7c, 0x32, 0x1e, 0x0b, 0x1c, 0x6a, 0x06, 0x63, 0x93, 0x01, 0x1f, 0x34, 0x35, 0x3a, 0x3a, 0x36, 0x34, 0x1f, 0x92, 0x63, 0x05, 0x6c, 0x1c, 0x0a, 0x1e, 0x30, 0x7c, 0x7a, 0x31, 0x1f, 0x0a, 0x1d, 0x67, 0x04, 0x02, 0x65, 0x01, 0xee, 0x18, 0x29, 0x2b, 0x2c, 0x2e, 0x2a, 0x29, 0x19, 0x4d, 0x4d, 0x4c, 0x53, 0x36, 0x38, 0x1e, 0x21, 0x1e, 0x1d, 0x04, 0xfe, 0xb9, 0x08, 0x05, 0x1e, 0x1f, 0x1f, 0x1f, 0x38, 0x60, 0x86, 0x5a, 0x09, 0x09, 0x4d, 0x14, 0x08, 0x22, 0x31, 0x70, 0x3f, 0x47, 0x05, 0x08, 0x33, 0x2e, 0x2e, 0x33, 0x01, 0x33, 0x05, 0x08, 0x36, 0x38, 0x20, 0x1e, 0x20, 0xc1, 0x38, 0x36, 0x08, 0x04, 0x1d, 0x1e, 0x21, 0x51, 0x4b, 0x4d, 0x18, 0x29, 0x2a, 0x2f, 0x2e, 0x2a, 0x29, 0x17, 0x4d, 0x03, 0x35, 0x13, 0x24, 0x15, 0x14, 0x23, 0x14, 0x14, 0x23, 0x14, 0x15, 0x24, 0x13, 0xd9, 0x35, 0x39, 0x67, 0x54, 0x3b, 0x26, 0x12, 0x0e, 0x27, 0x04, 0x39, 0x5a, 0x5e, 0x5e, 0x5a, 0x39, 0x04, 0x27, 0x0e, 0x12, 0x27, 0x3a, 0x54, 0x67, 0x39, 0xa7, 0x27, 0x28, 0x27, 0x27, 0x26, 0x28, 0x29, 0x49, 0x1e, 0x1c, 0x1c, 0x1a, 0x1a, 0x1c, 0x1c, 0x1e, 0x38, 0x3a, 0x39, 0x38, 0x1e, 0x1c, 0x1d, 0x1a, 0x1a, 0x1d, 0x1c, 0x1e, 0x38, 0x39, 0x3a, 0x01, 0x0c, 0x5a, 0x5f, 0x35, 0x39, 0x65, 0x55, 0x3b, 0x27, 0x13, 0x0e, 0x28, 0x01, 0x05, 0x09, 0x02, 0xb3, 0xc0, 0xc0, 0xb3, 0x02, 0x3a, 0x02, 0x38, 0x14, 0x1b, 0x2e, 0x3e, 0x65, 0x75, 0x01, 0x76, 0x63, 0x3e, 0x2d, 0x1b, 0x14, 0x37, 0x03, 0x3a, 0xb0, 0x62, 0x63, 0x63, 0x62, 0xb0, 0x3b, 0x04, 0x37, 0x14, 0x1a, 0x2d, 0x3f, 0x63, 0x77, 0x75, 0x64, 0x3f, 0x2f, 0x1a, 0x14, 0x38, 0x02, 0x4b, 0xa2, 0x57, 0x5a, 0x5a, 0x57, 0xa2, 0x20, 0x2a, 0x2a, 0x10, 0x19, 0x1d, 0x12, 0x14, 0x15, 0x14, 0x44, 0x40, 0x40, 0x44, 0x14, 0x15, 0x14, 0x12, 0x1d, 0x2b, 0x38, 0x05, 0x01, 0x28, 0x0f, 0x13, 0x27, 0x3a, 0x54, 0x65, 0x39, 0x35, 0x5e, 0x9d, 0x26, 0x29, 0x28, 0x26, 0x27, 0x27, 0x28, 0xd6, 0x44, 0x41, 0x19, 0x1d, 0x12, 0x14, 0x14, 0x3a, 0x1d, 0x19, 0x41, 0x44, 0x15, 0x14, 0x14, 0x2e, 0x2a, 0x21, 0x9e, 0x59, 0x5b, 0x5b, 0x59, 0x9e, 0x21, 0x00, 0x07, 0x00, 0xea, 0x00, 0x00, 0x05, 0x89, 0x05, 0xd6, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x78, 0x00, 0x86, 0x00, 0x94, 0x00, 0x00, 0x01, 0x14, 0x17, 0x36, 0x37, 0x26, 0x27, 0x36, 0x37, 0x26, 0x27, 0x06, 0x05, 0x34, 0x26, 0x15, 0x06, 0x15, 0x16, 0x17, 0x36, 0x25, 0x06, 0x15, 0x14, 0x17, 0x36, 0x37, 0x2e, 0x01, 0x27, 0x06, 0x15, 0x14, 0x25, 0x34, 0x27, 0x06, 0x07, 0x16, 0x17, 0x06, 0x07, 0x16, 0x17, 0x36, 0x03, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x26, 0x27, 0x36, 0x37, 0x16, 0x17, 0x36, 0x37, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x15, 0x16, 0x15, 0x14, 0x07, 0x1e, 0x01, 0x17, 0x36, 0x37, 0x16, 0x17, 0x06, 0x07, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x06, 0x23, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x23, 0x26, 0x27, 0x35, 0x26, 0x27, 0x06, 0x07, 0x22, 0x27, 0x36, 0x37, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x06, 0x14, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x25, 0x32, 0x1e, 0x01, 0x14, 0x0e, 0x01, 0x23, 0x22, 0x2e, 0x01, 0x34, 0x3e, 0x01, 0x03, 0x6d, 0x23, 0x31, 0x28, 0x2e, 0x08, 0x03, 0x2d, 0x21, 0x2a, 0x2b, 0xfe, 0xf9, 0x25, 0x28, 0x07, 0x32, 0x13, 0x01, 0xaf, 0x01, 0x0f, 0x37, 0x03, 0x03, 0x25, 0x01, 0x20, 0xfe, 0xf5, 0x2b, 0x26, 0x27, 0x2e, 0x03, 0x0d, 0x29, 0x2d, 0x2d, 0x23, 0xef, 0x32, 0x1d, 0x0c, 0x09, 0x1c, 0x51, 0x5b, 0x02, 0x02, 0xa4, 0x99, 0x4b, 0x28, 0x2c, 0x23, 0x94, 0x01, 0x94, 0x23, 0x24, 0x2a, 0x04, 0x4d, 0x97, 0xa6, 0x01, 0x02, 0x5c, 0x50, 0x1d, 0x05, 0x0d, 0x1a, 0x38, 0x18, 0x12, 0x33, 0x33, 0x15, 0x1d, 0x1f, 0x2d, 0x01, 0x0c, 0x3b, 0x2d, 0x35, 0x3f, 0x56, 0x16, 0x1d, 0x1d, 0x4f, 0x3c, 0x38, 0x2d, 0x3d, 0x0b, 0x01, 0x2e, 0x1e, 0x1c, 0x15, 0x33, 0x34, 0x12, 0x2f, 0x5e, 0xaa, 0x5d, 0x5d, 0xa9, 0x5f, 0x61, 0xab, 0x59, 0x5b, 0xaa, 0x01, 0x05, 0x4b, 0x8f, 0x52, 0x4f, 0x8f, 0x4e, 0x4e, 0x8f, 0x4f, 0x51, 0x8f, 0x02, 0x84, 0xa3, 0xa7, 0x0f, 0x23, 0x65, 0x8d, 0xaa, 0x6a, 0x1c, 0x0f, 0x70, 0xcd, 0x4d, 0x63, 0x01, 0x4e, 0x54, 0x76, 0x4a, 0x4b, 0x72, 0x1b, 0x19, 0x5a, 0x31, 0x56, 0x6c, 0x4c, 0x57, 0x02, 0x4d, 0x49, 0x09, 0x11, 0xa9, 0x70, 0x0d, 0x1e, 0x6a, 0xaa, 0x85, 0x6b, 0x25, 0x0f, 0xa7, 0x01, 0x6e, 0x41, 0x0d, 0x56, 0x02, 0x02, 0x7b, 0x77, 0x02, 0x06, 0x77, 0x19, 0x11, 0x5b, 0x31, 0x87, 0xf4, 0x01, 0x01, 0xf4, 0x87, 0x31, 0x5b, 0x0d, 0x1a, 0x03, 0x77, 0x06, 0x02, 0x77, 0x7b, 0x02, 0x02, 0x56, 0x0d, 0x40, 0x1e, 0x23, 0x66, 0xdc, 0x64, 0x2d, 0x23, 0x4a, 0x4d, 0x0c, 0x37, 0x42, 0x2f, 0x15, 0x22, 0x89, 0x89, 0x22, 0x01, 0x14, 0x30, 0x43, 0x37, 0x0c, 0x4e, 0x4b, 0x22, 0x2c, 0x64, 0xdc, 0x66, 0x23, 0x88, 0xce, 0xbd, 0x68, 0x68, 0xbd, 0xce, 0xbf, 0x67, 0x67, 0x51, 0x55, 0xa0, 0xae, 0x9d, 0x58, 0x58, 0x9d, 0xae, 0xa0, 0x55, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x06, 0x1b, 0x05, 0xd4, 0x00, 0x07, 0x00, 0x0d, 0x00, 0x15, 0x00, 0x25, 0x00, 0x00, 0x01, 0x33, 0x01, 0x15, 0x21, 0x27, 0x23, 0x00, 0x17, 0x01, 0x15, 0x21, 0x35, 0x00, 0x07, 0x32, 0x15, 0x02, 0x23, 0x22, 0x03, 0x36, 0x13, 0x32, 0x1e, 0x01, 0x15, 0x14, 0x0e, 0x01, 0x23, 0x22, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x03, 0x42, 0x07, 0x02, 0xd1, 0xfa, 0x4f, 0x07, 0x08, 0x02, 0xcc, 0x14, 0xfd, 0xab, 0x04, 0xb3, 0xfd, 0xbc, 0x12, 0x46, 0x2f, 0x17, 0x14, 0x31, 0x17, 0x2d, 0x11, 0x22, 0x13, 0x12, 0x23, 0x11, 0x12, 0x20, 0x13, 0x13, 0x20, 0x05, 0xd4, 0xfa, 0x35, 0x09, 0x09, 0x05, 0xaa, 0x9b, 0xfb, 0x4f, 0x11, 0x09, 0x04, 0x9d, 0xc2, 0x44, 0xfd, 0x9b, 0x02, 0x6e, 0x3b, 0xfd, 0x0d, 0x14, 0x24, 0x15, 0x14, 0x24, 0x14, 0x14, 0x24, 0x14, 0x15, 0x24, 0x14, 0x00, 0x00, 0x01, 0x00, 0x99, 0x00, 0x04, 0x04, 0x76, 0x05, 0xd8, 0x00, 0x13, 0x00, 0x00, 0x01, 0x33, 0x17, 0x15, 0x01, 0x14, 0x33, 0x04, 0x15, 0x17, 0x01, 0x27, 0x35, 0x00, 0x35, 0x34, 0x23, 0x24, 0x2f, 0x01, 0x04, 0x56, 0x0c, 0x13, 0xfd, 0xcd, 0x52, 0x01, 0x5c, 0x06, 0xfc, 0xb0, 0x0d, 0x02, 0x46, 0x6b, 0xfe, 0xb8, 0x0f, 0x06, 0x05, 0xd8, 0x15, 0x07, 0xfd, 0xe2, 0x47, 0x53, 0x0e, 0x47, 0xfd, 0x55, 0x15, 0x07, 0x02, 0x57, 0x0d, 0x47, 0x4a, 0x11, 0x47, 0x00, 0x00, 0x05, 0x00, 0x9d, 0xfe, 0xff, 0x06, 0x9e, 0x05, 0xda, 0x00, 0x1e, 0x00, 0x2a, 0x00, 0x31, 0x00, 0x3d, 0x00, 0x43, 0x00, 0x00, 0x01, 0x26, 0x10, 0x00, 0x33, 0x32, 0x17, 0x36, 0x33, 0x32, 0x00, 0x10, 0x07, 0x06, 0x07, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x26, 0x13, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x37, 0x26, 0x10, 0x37, 0x26, 0x13, 0x06, 0x07, 0x11, 0x21, 0x11, 0x26, 0x37, 0x16, 0x33, 0x32, 0x36, 0x10, 0x26, 0x23, 0x22, 0x07, 0x16, 0x10, 0x05, 0x36, 0x10, 0x27, 0x06, 0x10, 0x01, 0x36, 0x98, 0x01, 0x2e, 0xd7, 0x8a, 0x70, 0x71, 0x8b, 0xd5, 0x01, 0x30, 0x97, 0x7b, 0xa2, 0xf5, 0xf5, 0xa2, 0xfe, 0xac, 0xa2, 0xf5, 0xf5, 0xa3, 0xf4, 0x94, 0xcf, 0xcf, 0x94, 0x39, 0x33, 0x7c, 0x7d, 0x33, 0xc1, 0x4f, 0x5b, 0x01, 0x54, 0x5c, 0x41, 0x33, 0x39, 0x90, 0xd3, 0xd3, 0x90, 0x3a, 0x35, 0x7e, 0xfe, 0xf5, 0x69, 0x69, 0x68, 0x02, 0x14, 0x9d, 0x01, 0xdd, 0x01, 0x4c, 0x46, 0x46, 0xfe, 0xb4, 0xfe, 0x22, 0x9c, 0x7e, 0x12, 0xfe, 0xf8, 0x7c, 0xfe, 0xff, 0x01, 0x01, 0xfe, 0xff, 0x01, 0x01, 0x7c, 0x01, 0x09, 0x11, 0x03, 0x91, 0xe4, 0xfe, 0xb9, 0xd8, 0x11, 0x95, 0x01, 0xae, 0x9d, 0x12, 0xfc, 0x94, 0x2d, 0x0a, 0xfe, 0xf8, 0x01, 0x09, 0x0a, 0xa5, 0x10, 0xd8, 0x01, 0x47, 0xe4, 0x12, 0x9d, 0xfe, 0x50, 0x38, 0x6c, 0x01, 0x47, 0x72, 0x72, 0xfe, 0xb9, 0x00, 0x05, 0x00, 0x91, 0xfe, 0x5b, 0x07, 0x5f, 0x05, 0xc3, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x2c, 0x00, 0x38, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x26, 0x20, 0x06, 0x10, 0x17, 0x16, 0x17, 0x36, 0x00, 0x37, 0x26, 0x01, 0x14, 0x00, 0x20, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x10, 0x00, 0x04, 0x17, 0x01, 0x21, 0x37, 0x21, 0x11, 0x21, 0x11, 0x07, 0x11, 0x01, 0x16, 0x03, 0x01, 0x16, 0x17, 0x16, 0x17, 0x01, 0x23, 0x03, 0x06, 0x00, 0x07, 0x16, 0x17, 0x16, 0x20, 0x36, 0x10, 0x27, 0x26, 0x01, 0x32, 0x36, 0x35, 0x22, 0x06, 0x03, 0x92, 0x6a, 0xfe, 0xdc, 0xd0, 0x68, 0x2a, 0x31, 0x0f, 0x01, 0x17, 0xb8, 0x19, 0x02, 0x44, 0xfe, 0xd6, 0xfe, 0x51, 0x99, 0x69, 0x20, 0x79, 0x61, 0x99, 0x01, 0x36, 0x01, 0x9d, 0x64, 0x01, 0x45, 0xfe, 0xb2, 0x7e, 0x01, 0xbd, 0x01, 0x63, 0x80, 0xfe, 0xbe, 0x64, 0x86, 0xfe, 0xbe, 0x3a, 0x18, 0x66, 0x3d, 0x01, 0x45, 0xf8, 0xde, 0x0d, 0xfe, 0xef, 0xc8, 0x1a, 0x2f, 0x68, 0x01, 0x25, 0xd2, 0x69, 0x29, 0xfd, 0xcb, 0x91, 0xd3, 0x94, 0xcc, 0x03, 0x24, 0x72, 0xe4, 0xfe, 0xb8, 0x6c, 0x2c, 0x1a, 0xce, 0x01, 0x33, 0x07, 0x36, 0xfd, 0x90, 0xe8, 0xfe, 0xbd, 0x9f, 0x6c, 0x92, 0x25, 0x65, 0x9e, 0x01, 0xdc, 0x01, 0x55, 0x11, 0x67, 0x01, 0x5c, 0x8e, 0xfe, 0x78, 0xfe, 0x14, 0x8f, 0x01, 0x75, 0xfe, 0xa4, 0x92, 0x03, 0x76, 0xfe, 0xa4, 0x53, 0x63, 0x1b, 0x3f, 0x01, 0x5c, 0xfe, 0x37, 0xcc, 0xfe, 0xd7, 0x0b, 0x3d, 0x31, 0x6c, 0xd8, 0x01, 0x48, 0x72, 0x2d, 0xfe, 0xc9, 0xd8, 0xa4, 0xe0, 0x00, 0x00, 0x04, 0x00, 0x9d, 0xfe, 0x83, 0x07, 0xfc, 0x06, 0xd9, 0x00, 0x05, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x45, 0x00, 0x00, 0x00, 0x02, 0x17, 0x36, 0x10, 0x27, 0x01, 0x14, 0x00, 0x23, 0x22, 0x27, 0x06, 0x07, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x26, 0x27, 0x26, 0x10, 0x00, 0x33, 0x32, 0x17, 0x36, 0x17, 0x16, 0x17, 0x01, 0x21, 0x37, 0x21, 0x11, 0x07, 0x11, 0x01, 0x16, 0x25, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x37, 0x26, 0x10, 0x37, 0x26, 0x01, 0x16, 0x33, 0x32, 0x36, 0x10, 0x26, 0x23, 0x22, 0x07, 0x16, 0x10, 0x03, 0x37, 0x01, 0x67, 0x69, 0x69, 0x03, 0x02, 0xfe, 0xd4, 0xdb, 0x8a, 0x72, 0x4e, 0x5a, 0xf5, 0xf5, 0xa2, 0xf5, 0xf5, 0xa3, 0x79, 0x98, 0x01, 0x2e, 0xd7, 0x88, 0x6f, 0x74, 0x8a, 0xce, 0x64, 0x01, 0x46, 0xfe, 0xb1, 0x7e, 0x01, 0xbd, 0x80, 0xfe, 0xbe, 0x65, 0xfc, 0x04, 0x94, 0xcf, 0xcf, 0x94, 0x39, 0x33, 0x7b, 0x7d, 0x34, 0x01, 0x50, 0x33, 0x38, 0x92, 0xd3, 0xd3, 0x92, 0x3a, 0x34, 0x7e, 0x03, 0xc8, 0xfe, 0xb8, 0x6c, 0x6c, 0x01, 0x47, 0x72, 0xfe, 0xeb, 0xe7, 0xfe, 0xbc, 0x45, 0x2c, 0x0a, 0xfe, 0xf8, 0x7c, 0xfe, 0xff, 0x01, 0x01, 0x7c, 0x01, 0x09, 0x11, 0x7e, 0x9d, 0x01, 0xdd, 0x01, 0x4c, 0x44, 0x4a, 0x06, 0x08, 0x67, 0x01, 0x5c, 0x8e, 0xfe, 0x14, 0x8f, 0x01, 0x75, 0xfe, 0xa4, 0x92, 0xc6, 0xe4, 0xfe, 0xb9, 0xd8, 0x11, 0x95, 0x01, 0xac, 0x9f, 0x12, 0xfd, 0x0d, 0x10, 0xd8, 0x01, 0x48, 0xe4, 0x12, 0x9d, 0xfe, 0x4f, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xfe, 0xff, 0x06, 0x07, 0x07, 0x55, 0x00, 0x07, 0x00, 0x28, 0x00, 0x00, 0x00, 0x26, 0x20, 0x06, 0x10, 0x16, 0x20, 0x36, 0x05, 0x26, 0x10, 0x00, 0x33, 0x32, 0x17, 0x01, 0x21, 0x37, 0x21, 0x11, 0x07, 0x11, 0x01, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x26, 0x04, 0x06, 0xd2, 0xfe, 0xdb, 0xcf, 0xcf, 0x01, 0x25, 0xd2, 0xfd, 0x30, 0x98, 0x01, 0x2e, 0xd7, 0xad, 0x86, 0x01, 0x44, 0xfe, 0xb2, 0x7e, 0x01, 0xbd, 0x81, 0xfe, 0xbe, 0x64, 0x98, 0x7a, 0xa2, 0xf5, 0xf5, 0xa2, 0xf5, 0xf5, 0xa3, 0x04, 0x43, 0xe4, 0xe4, 0xfe, 0xb9, 0xd8, 0xd8, 0xe8, 0x9d, 0x01, 0xdd, 0x01, 0x4c, 0x6e, 0x01, 0x5b, 0x8e, 0xfe, 0x14, 0x8f, 0x01, 0x75, 0xfe, 0xa4, 0x92, 0xc2, 0xef, 0x9c, 0x7e, 0x12, 0xfe, 0xf8, 0x7c, 0xfe, 0xff, 0x01, 0x01, 0x7c, 0x01, 0x09, 0x11, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf2, 0xff, 0xe3, 0x05, 0x3c, 0x06, 0xf4, 0x00, 0x2b, 0x00, 0x44, 0x00, 0x00, 0x01, 0x07, 0x16, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x33, 0x32, 0x17, 0x37, 0x27, 0x37, 0x17, 0x13, 0x07, 0x27, 0x25, 0x13, 0x07, 0x27, 0x03, 0x17, 0x07, 0x01, 0x16, 0x32, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x34, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x22, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x14, 0x17, 0x16, 0x17, 0x16, 0x03, 0xbe, 0x3f, 0x2d, 0x1f, 0x3d, 0x1f, 0x22, 0x21, 0x20, 0x70, 0x58, 0x4e, 0x56, 0x51, 0x51, 0x55, 0x35, 0x3d, 0x1f, 0x22, 0x22, 0x21, 0x76, 0x51, 0x50, 0x53, 0x35, 0x2e, 0x3f, 0xe4, 0x33, 0xe5, 0x78, 0xca, 0x34, 0x01, 0x9f, 0xad, 0x7d, 0x54, 0x78, 0xe4, 0x34, 0xfd, 0x8c, 0x37, 0x71, 0x37, 0x36, 0x51, 0x18, 0x16, 0x16, 0x15, 0x2a, 0x26, 0x72, 0x6d, 0x39, 0x36, 0x50, 0x19, 0x16, 0x16, 0x15, 0x2a, 0x24, 0x04, 0x00, 0xaa, 0x21, 0x24, 0x48, 0x53, 0x5c, 0xb4, 0x5b, 0x56, 0x83, 0x2a, 0x25, 0x25, 0x27, 0x3e, 0x48, 0x53, 0x5d, 0xb3, 0x5e, 0x58, 0x82, 0x26, 0x25, 0x0c, 0xab, 0x69, 0x8a, 0x69, 0x01, 0x44, 0x5e, 0x8b, 0xbf, 0xfe, 0x32, 0x39, 0xe1, 0xfe, 0xbd, 0x69, 0x8b, 0xfc, 0xfc, 0x1a, 0x19, 0x19, 0x5c, 0x3d, 0x3c, 0x80, 0x3c, 0x39, 0x32, 0x2d, 0x31, 0x19, 0x19, 0x58, 0x3f, 0x3a, 0x84, 0x3c, 0x39, 0x31, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xba, 0xfe, 0xa3, 0x05, 0x57, 0x07, 0x12, 0x00, 0x3d, 0x00, 0x58, 0x00, 0x00, 0x01, 0x36, 0x32, 0x17, 0x13, 0x07, 0x27, 0x25, 0x13, 0x07, 0x27, 0x03, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x15, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x26, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x27, 0x07, 0x27, 0x37, 0x27, 0x07, 0x27, 0x13, 0x05, 0x07, 0x27, 0x17, 0x37, 0x17, 0x07, 0x17, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x02, 0xa3, 0x2f, 0x65, 0x30, 0xa1, 0xcb, 0x33, 0x01, 0x9f, 0xad, 0x7e, 0x54, 0xa1, 0x2a, 0x24, 0x3e, 0x40, 0x40, 0x3e, 0x3a, 0x51, 0x28, 0x36, 0xf7, 0xf7, 0x87, 0xf8, 0xf8, 0x33, 0x2c, 0x4d, 0x3d, 0x3e, 0x40, 0x3f, 0x3f, 0x23, 0x2c, 0x1c, 0xe5, 0x33, 0xe5, 0x4c, 0x54, 0x7e, 0xad, 0x01, 0xa0, 0x33, 0xcc, 0x4c, 0xe4, 0x35, 0xe5, 0x7c, 0x40, 0x2f, 0x38, 0x27, 0x29, 0x2c, 0x2c, 0x29, 0x2a, 0x35, 0x33, 0x7c, 0x30, 0x38, 0x26, 0x2a, 0x2c, 0x2c, 0x2a, 0x2a, 0x34, 0x34, 0x04, 0x87, 0x0c, 0x0c, 0x01, 0x9e, 0x5c, 0x8a, 0xbf, 0xfe, 0x32, 0x3a, 0xe2, 0xfe, 0x61, 0x1d, 0x28, 0x45, 0xab, 0x62, 0x5f, 0xab, 0x45, 0x40, 0x28, 0x14, 0x0a, 0xb8, 0x96, 0xf0, 0xf0, 0x96, 0xb8, 0x09, 0x15, 0x25, 0x43, 0x45, 0xab, 0x5f, 0x62, 0xa9, 0x47, 0x28, 0x1e, 0x48, 0x69, 0x8a, 0x6a, 0xcb, 0xe2, 0x3a, 0x01, 0xce, 0xbf, 0x8a, 0x5c, 0xcb, 0x69, 0x8a, 0x6a, 0xd3, 0x18, 0x1c, 0x2b, 0x2e, 0x77, 0x42, 0x41, 0x77, 0x2e, 0x2f, 0x18, 0x18, 0x18, 0x1c, 0x2b, 0x2e, 0x77, 0x41, 0x42, 0x77, 0x2e, 0x2f, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x59, 0xff, 0xe3, 0x04, 0xaf, 0x06, 0xf4, 0x00, 0x2b, 0x00, 0x46, 0x00, 0x00, 0x01, 0x11, 0x33, 0x15, 0x23, 0x15, 0x16, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x35, 0x23, 0x35, 0x33, 0x11, 0x07, 0x27, 0x09, 0x01, 0x07, 0x03, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x03, 0x48, 0xf7, 0xf7, 0x36, 0x28, 0x51, 0x3a, 0x3e, 0x40, 0x40, 0x3e, 0x3d, 0x4e, 0x4a, 0x58, 0x5c, 0x46, 0x51, 0x39, 0x3e, 0x40, 0x40, 0x3e, 0x3d, 0x4d, 0x2c, 0x33, 0xf8, 0xf8, 0x9b, 0x60, 0x01, 0x3e, 0x01, 0x3f, 0x60, 0xdf, 0x3c, 0x34, 0x34, 0x2a, 0x2a, 0x2c, 0x2c, 0x2a, 0x26, 0x38, 0x30, 0x7c, 0x33, 0x35, 0x2a, 0x29, 0x2c, 0x2c, 0x29, 0x27, 0x38, 0x2f, 0x05, 0xd5, 0xfe, 0xe7, 0x96, 0x91, 0x0a, 0x14, 0x28, 0x40, 0x45, 0xab, 0x5f, 0x62, 0xab, 0x45, 0x43, 0x25, 0x23, 0x23, 0x28, 0x40, 0x45, 0xab, 0x62, 0x5f, 0xab, 0x45, 0x43, 0x25, 0x15, 0x09, 0x91, 0x96, 0x01, 0x19, 0xad, 0x6b, 0x01, 0x61, 0xfe, 0x9f, 0x6a, 0xfb, 0x50, 0x18, 0x18, 0x2f, 0x2e, 0x77, 0x42, 0x41, 0x77, 0x2e, 0x2b, 0x1c, 0x18, 0x18, 0x18, 0x2f, 0x2e, 0x77, 0x41, 0x42, 0x77, 0x2e, 0x2b, 0x1c, 0x18, 0x00, 0x02, 0x00, 0x08, 0x01, 0x10, 0x05, 0xf8, 0x04, 0xc4, 0x00, 0x2b, 0x00, 0x46, 0x00, 0x00, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x06, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x33, 0x11, 0x33, 0x11, 0x33, 0x27, 0x37, 0x09, 0x01, 0x27, 0x25, 0x14, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x34, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x06, 0x07, 0x06, 0x04, 0xf5, 0xc6, 0x87, 0x4c, 0x0a, 0x12, 0x24, 0x39, 0x3e, 0x9a, 0x56, 0x58, 0x9a, 0x3e, 0x3c, 0x21, 0x20, 0x20, 0x24, 0x39, 0x3e, 0x9a, 0x58, 0x56, 0x9a, 0x3e, 0x3c, 0x21, 0x13, 0x09, 0x4c, 0x87, 0xc6, 0x9c, 0x61, 0x01, 0x3d, 0xfe, 0xc3, 0x60, 0xfc, 0x35, 0x16, 0x15, 0x2b, 0x29, 0x6b, 0x3b, 0x3b, 0x6b, 0x2a, 0x26, 0x19, 0x16, 0x16, 0x15, 0x2a, 0x2a, 0x6b, 0x3b, 0x3b, 0x6b, 0x29, 0x27, 0x19, 0x16, 0x02, 0x9f, 0xfe, 0xed, 0x01, 0x13, 0x3c, 0x2d, 0x5a, 0x40, 0x45, 0x47, 0x47, 0x45, 0x44, 0x56, 0x52, 0x62, 0x66, 0x4e, 0x5a, 0x40, 0x45, 0x47, 0x47, 0x45, 0x44, 0x56, 0x31, 0x38, 0x01, 0x13, 0xfe, 0xed, 0xac, 0x6b, 0xfe, 0x9e, 0xfe, 0x9e, 0x6a, 0xf8, 0x43, 0x39, 0x3a, 0x2f, 0x2e, 0x31, 0x31, 0x2e, 0x2b, 0x3e, 0x35, 0x8a, 0x39, 0x3a, 0x2f, 0x2e, 0x31, 0x31, 0x2e, 0x2b, 0x3e, 0x35, 0x00, 0x00, 0x00, 0x02, 0x01, 0x58, 0x01, 0x10, 0x04, 0xb0, 0x04, 0xc5, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x34, 0x12, 0x33, 0x32, 0x12, 0x15, 0x14, 0x02, 0x23, 0x22, 0x02, 0x37, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x01, 0x59, 0xfb, 0xb0, 0xb1, 0xfb, 0xfb, 0xb1, 0xb0, 0xfb, 0x89, 0xaa, 0x78, 0x78, 0xaa, 0xaa, 0x78, 0x78, 0xaa, 0x02, 0xeb, 0xc4, 0x01, 0x16, 0xfe, 0xea, 0xc4, 0xc5, 0xfe, 0xea, 0x01, 0x16, 0xc2, 0x85, 0xbd, 0xbd, 0x85, 0x86, 0xbd, 0xbd, 0x00, 0x01, 0x01, 0x58, 0x01, 0x10, 0x04, 0xb0, 0x04, 0xc5, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x34, 0x12, 0x33, 0x32, 0x12, 0x15, 0x14, 0x02, 0x23, 0x22, 0x02, 0x01, 0x59, 0xfb, 0xb0, 0xb1, 0xfb, 0xfb, 0xb1, 0xb0, 0xfb, 0x02, 0xeb, 0xc4, 0x01, 0x16, 0xfe, 0xea, 0xc4, 0xc5, 0xfe, 0xea, 0x01, 0x16, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0xc7, 0x01, 0x8d, 0x04, 0x41, 0x04, 0x4b, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x37, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x01, 0xc7, 0xbb, 0x82, 0x83, 0xba, 0xba, 0x83, 0x82, 0xbb, 0x89, 0x6a, 0x4a, 0x4b, 0x69, 0x69, 0x4b, 0x4a, 0x6a, 0x02, 0xec, 0x92, 0xcd, 0xcd, 0x92, 0x91, 0xce, 0xce, 0x90, 0x53, 0x75, 0x75, 0x53, 0x53, 0x76, 0x76, 0x00, 0x04, 0x01, 0x40, 0x01, 0x8d, 0x04, 0xc8, 0x04, 0x4b, 0x00, 0x13, 0x00, 0x21, 0x00, 0x29, 0x00, 0x37, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x17, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x06, 0x23, 0x22, 0x26, 0x37, 0x14, 0x16, 0x33, 0x32, 0x33, 0x26, 0x35, 0x34, 0x37, 0x26, 0x23, 0x22, 0x06, 0x25, 0x06, 0x15, 0x14, 0x17, 0x36, 0x35, 0x34, 0x37, 0x16, 0x15, 0x14, 0x07, 0x32, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x01, 0x40, 0xbb, 0x82, 0x4a, 0x3d, 0x3d, 0x4a, 0x83, 0xba, 0xba, 0x83, 0x4a, 0x3d, 0x3d, 0x4a, 0x82, 0xbb, 0x89, 0x69, 0x4b, 0x06, 0x04, 0x39, 0x38, 0x04, 0x05, 0x4b, 0x69, 0x01, 0x3b, 0x2d, 0x2d, 0x2d, 0x51, 0x38, 0x39, 0x05, 0x05, 0x4b, 0x69, 0x69, 0x4b, 0x04, 0x02, 0xec, 0x92, 0xcd, 0x20, 0x20, 0xcd, 0x92, 0x91, 0xce, 0x21, 0x21, 0xce, 0x90, 0x53, 0x75, 0x58, 0x71, 0x70, 0x57, 0x01, 0x76, 0x32, 0x38, 0x4d, 0x4c, 0x38, 0x38, 0x4c, 0x4d, 0x7b, 0x57, 0x70, 0x71, 0x58, 0x75, 0x53, 0x53, 0x76, 0x00, 0x00, 0x05, 0x00, 0x4b, 0x01, 0x5a, 0x05, 0xbd, 0x04, 0x7a, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x38, 0x00, 0x52, 0x00, 0x6d, 0x00, 0x00, 0x01, 0x33, 0x11, 0x23, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x04, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x02, 0xc1, 0x87, 0x87, 0x01, 0xe7, 0x4a, 0x20, 0x25, 0x15, 0x1a, 0x1b, 0x1c, 0x19, 0x1a, 0x20, 0x20, 0x4a, 0x1f, 0x21, 0x1a, 0x1a, 0x1b, 0x1d, 0x18, 0x1a, 0x21, 0x44, 0x43, 0x34, 0x3d, 0x29, 0x2d, 0x30, 0x30, 0x2d, 0x2c, 0x3a, 0x36, 0x85, 0x34, 0x3c, 0x2a, 0x2d, 0x2f, 0x2f, 0x2d, 0x2c, 0x3a, 0x37, 0xfd, 0x69, 0x4a, 0x20, 0x25, 0x15, 0x1a, 0x1b, 0x1c, 0x19, 0x1a, 0x20, 0x20, 0x4a, 0x1f, 0x20, 0x1b, 0x1a, 0x1b, 0x1d, 0x18, 0x1b, 0x20, 0x44, 0x43, 0x34, 0x3d, 0x29, 0x2d, 0x30, 0x30, 0x2d, 0x2c, 0x3a, 0x37, 0x84, 0x34, 0x3c, 0x2a, 0x2d, 0x2f, 0x2f, 0x2d, 0x2c, 0x3a, 0x37, 0x04, 0x7a, 0xfc, 0xe0, 0x02, 0x5a, 0x0f, 0x12, 0x1a, 0x1f, 0x46, 0x29, 0x28, 0x4a, 0x1b, 0x1c, 0x10, 0x0f, 0x0f, 0x10, 0x1c, 0x1e, 0x47, 0x28, 0x29, 0x4b, 0x1a, 0x1c, 0x10, 0xa5, 0x1a, 0x1e, 0x2e, 0x32, 0x7f, 0x49, 0x46, 0x7f, 0x32, 0x31, 0x1b, 0x1a, 0x1a, 0x1e, 0x2e, 0x32, 0x7f, 0x46, 0x49, 0x7f, 0x32, 0x31, 0x1b, 0x1a, 0x96, 0x0f, 0x12, 0x1a, 0x1f, 0x46, 0x29, 0x28, 0x4a, 0x1b, 0x1c, 0x10, 0x0f, 0x0f, 0x10, 0x1c, 0x1e, 0x47, 0x28, 0x29, 0x4b, 0x1a, 0x1c, 0x10, 0xa5, 0x1a, 0x1e, 0x2e, 0x32, 0x7f, 0x49, 0x46, 0x7f, 0x32, 0x31, 0x1b, 0x1a, 0x1a, 0x1e, 0x2e, 0x32, 0x7f, 0x46, 0x49, 0x7f, 0x32, 0x31, 0x1b, 0x1a, 0x00, 0x00, 0x03, 0x00, 0x09, 0x01, 0x8d, 0x06, 0x00, 0x04, 0x4a, 0x00, 0x37, 0x00, 0x51, 0x00, 0x6b, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x27, 0x21, 0x0e, 0x01, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x17, 0x24, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x24, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x03, 0x92, 0x06, 0x1f, 0x31, 0x2c, 0x3a, 0x36, 0x41, 0x44, 0x34, 0x3c, 0x2a, 0x2d, 0x2f, 0x2f, 0x2d, 0x2c, 0x3a, 0x37, 0x84, 0x34, 0x3d, 0x29, 0x30, 0x21, 0x05, 0xfe, 0xe4, 0x05, 0x23, 0x2e, 0x2c, 0x39, 0x37, 0x84, 0x35, 0x3c, 0x29, 0x2d, 0x30, 0x30, 0x2d, 0x2c, 0x39, 0x37, 0x41, 0x44, 0x34, 0x3c, 0x29, 0x31, 0x20, 0x06, 0x02, 0x73, 0x4a, 0x1f, 0x21, 0x1a, 0x1a, 0x1b, 0x1b, 0x1a, 0x1a, 0x21, 0x1f, 0x4a, 0x20, 0x20, 0x1a, 0x1a, 0x1b, 0x1b, 0x1a, 0x1a, 0x20, 0xfc, 0x5e, 0x4a, 0x1f, 0x25, 0x16, 0x1a, 0x1b, 0x1c, 0x19, 0x1a, 0x21, 0x1f, 0x4a, 0x20, 0x20, 0x1a, 0x1a, 0x1b, 0x1d, 0x18, 0x1a, 0x20, 0x03, 0x35, 0x1f, 0x5b, 0x35, 0x31, 0x1b, 0x1a, 0x1a, 0x1e, 0x2e, 0x32, 0x7f, 0x49, 0x46, 0x7f, 0x32, 0x31, 0x1b, 0x1a, 0x1a, 0x1e, 0x2e, 0x34, 0x60, 0x18, 0x1d, 0x5d, 0x32, 0x31, 0x1b, 0x1a, 0x1a, 0x1e, 0x2e, 0x32, 0x7f, 0x46, 0x49, 0x7f, 0x32, 0x31, 0x1b, 0x1a, 0x1a, 0x1e, 0x2e, 0x35, 0x5b, 0x1f, 0x7f, 0x0f, 0x10, 0x1c, 0x1f, 0x46, 0x29, 0x28, 0x47, 0x1e, 0x1c, 0x10, 0x0f, 0x0f, 0x10, 0x1c, 0x1e, 0x47, 0x28, 0x29, 0x46, 0x1f, 0x1c, 0x10, 0x0f, 0x0f, 0x12, 0x1a, 0x1f, 0x46, 0x29, 0x28, 0x4a, 0x1b, 0x1c, 0x10, 0x0f, 0x0f, 0x10, 0x1c, 0x1e, 0x47, 0x28, 0x29, 0x4b, 0x1a, 0x1c, 0x10, 0x00, 0x02, 0x00, 0xbd, 0x01, 0xe6, 0x05, 0x73, 0x04, 0x52, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x35, 0x25, 0x07, 0x15, 0x17, 0x01, 0x25, 0x05, 0x11, 0x05, 0x25, 0x04, 0xec, 0xfd, 0x1e, 0xc6, 0xc6, 0xfe, 0xb3, 0x01, 0x4d, 0x03, 0x69, 0xfc, 0x97, 0xfe, 0xb3, 0x02, 0xd7, 0x8a, 0x65, 0x4d, 0xba, 0x4d, 0x01, 0x5e, 0x82, 0x78, 0xfe, 0x84, 0x78, 0x82, 0x00, 0x00, 0x02, 0x01, 0x85, 0x00, 0x56, 0x04, 0x83, 0x05, 0x96, 0x00, 0x15, 0x00, 0x29, 0x00, 0x00, 0x01, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x35, 0x37, 0x35, 0x23, 0x15, 0x17, 0x15, 0x06, 0x07, 0x06, 0x15, 0x14, 0x1f, 0x02, 0x23, 0x03, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x27, 0x35, 0x21, 0x15, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x03, 0x1b, 0x55, 0x6a, 0x49, 0x21, 0x46, 0x34, 0xb4, 0x34, 0x46, 0x20, 0x4a, 0x6a, 0x56, 0x92, 0xf8, 0x94, 0x6e, 0x57, 0x4c, 0x27, 0x4f, 0x02, 0x06, 0x4f, 0x28, 0x4b, 0x58, 0x6f, 0x01, 0x11, 0xb4, 0xdf, 0x34, 0x62, 0x5c, 0x29, 0x31, 0xa2, 0x25, 0x3d, 0x3d, 0x25, 0xa2, 0x31, 0x29, 0x5c, 0x62, 0x34, 0xdf, 0xb4, 0xbb, 0x01, 0x3a, 0xea, 0x60, 0xbe, 0x5c, 0x4b, 0x19, 0x44, 0xfa, 0xfa, 0x44, 0x19, 0x4b, 0x5c, 0xbe, 0x60, 0xea, 0x00, 0x02, 0x00, 0x9d, 0xfe, 0xff, 0x04, 0xa9, 0x05, 0xda, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x00, 0x26, 0x20, 0x06, 0x10, 0x16, 0x20, 0x36, 0x05, 0x26, 0x10, 0x00, 0x20, 0x00, 0x10, 0x07, 0x06, 0x07, 0x11, 0x23, 0x11, 0x26, 0x04, 0x06, 0xd2, 0xfe, 0xdb, 0xcf, 0xcf, 0x01, 0x25, 0xd2, 0xfd, 0x30, 0x98, 0x01, 0x2e, 0x01, 0xab, 0x01, 0x31, 0x98, 0x7a, 0xa2, 0xa2, 0xa3, 0x04, 0x43, 0xe4, 0xe4, 0xfe, 0xb9, 0xd8, 0xd8, 0xe8, 0x9d, 0x01, 0xdd, 0x01, 0x4c, 0xfe, 0xb4, 0xfe, 0x22, 0x9c, 0x7e, 0x12, 0xfd, 0x7b, 0x02, 0x86, 0x11, 0x00, 0x01, 0x01, 0x36, 0xfe, 0xff, 0x04, 0xa8, 0x05, 0xda, 0x00, 0x1a, 0x00, 0x00, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x16, 0x33, 0x32, 0x36, 0x10, 0x26, 0x20, 0x07, 0x27, 0x36, 0x20, 0x00, 0x10, 0x07, 0x06, 0x07, 0x11, 0x33, 0x15, 0x02, 0xf5, 0xa3, 0xf5, 0xf5, 0x24, 0x2f, 0x91, 0xd0, 0xd0, 0xfe, 0xdb, 0x71, 0x6a, 0x98, 0x01, 0xab, 0x01, 0x2f, 0x97, 0x7b, 0xa1, 0xf4, 0xfe, 0xff, 0x01, 0x01, 0x7c, 0x01, 0xb2, 0x07, 0xd8, 0x01, 0x47, 0xe4, 0x6a, 0x74, 0xa6, 0xfe, 0xb4, 0xfe, 0x20, 0x9a, 0x7e, 0x12, 0xfe, 0xf8, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9e, 0xfe, 0xff, 0x04, 0xa8, 0x05, 0xda, 0x00, 0x13, 0x00, 0x17, 0x00, 0x00, 0x13, 0x09, 0x02, 0x11, 0x32, 0x33, 0x15, 0x22, 0x23, 0x11, 0x22, 0x23, 0x11, 0x22, 0x23, 0x35, 0x32, 0x33, 0x11, 0x37, 0x09, 0x02, 0x9e, 0x02, 0x05, 0x02, 0x05, 0xfe, 0x50, 0x7a, 0x7a, 0x7a, 0x7a, 0x51, 0x51, 0x7b, 0x7a, 0x7a, 0x7b, 0x4d, 0x01, 0x2b, 0xfe, 0xd5, 0xfe, 0xd5, 0x03, 0x9f, 0x02, 0x3b, 0xfd, 0xc5, 0xfd, 0xe9, 0xfe, 0xf4, 0x7c, 0xfe, 0xff, 0x01, 0x01, 0x7c, 0x01, 0x0c, 0xa8, 0x01, 0x6f, 0x01, 0x4a, 0xfe, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x9e, 0xfe, 0xff, 0x04, 0xa8, 0x05, 0xda, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x37, 0x17, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x21, 0x15, 0x21, 0x13, 0x07, 0x27, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x07, 0x27, 0x13, 0x21, 0x35, 0x21, 0x01, 0x00, 0x6f, 0xe4, 0xa1, 0xe3, 0x6f, 0xff, 0x00, 0x01, 0x62, 0xfe, 0xa4, 0xfa, 0x6e, 0xe4, 0xf5, 0xf5, 0xa2, 0xf5, 0xf5, 0xe4, 0x6e, 0xfa, 0xfe, 0xa4, 0x01, 0x62, 0x04, 0xf9, 0x7a, 0xfd, 0x01, 0x64, 0xfe, 0x9d, 0xfc, 0x7a, 0xfe, 0xe4, 0x7c, 0xfe, 0xeb, 0x7b, 0xfd, 0xfd, 0xae, 0x7c, 0xfe, 0xff, 0x01, 0x01, 0x7c, 0x02, 0x52, 0xfd, 0x7b, 0x01, 0x15, 0x7c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6c, 0xff, 0x0f, 0x05, 0xb2, 0x05, 0x25, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x17, 0x00, 0x00, 0x01, 0x15, 0x21, 0x09, 0x01, 0x21, 0x35, 0x21, 0x09, 0x01, 0x03, 0x11, 0x23, 0x11, 0x01, 0x33, 0x17, 0x37, 0x33, 0x15, 0x23, 0x09, 0x01, 0x23, 0x05, 0xb2, 0xfe, 0xf1, 0xfe, 0x6c, 0xfe, 0x6c, 0xfe, 0xf1, 0x01, 0x78, 0x01, 0x2b, 0x01, 0x2b, 0xd9, 0x9b, 0xfe, 0x9e, 0xea, 0xc1, 0xc1, 0xea, 0x80, 0xfe, 0xd5, 0xfe, 0xd5, 0x80, 0x01, 0x4a, 0x7c, 0xfe, 0x41, 0x01, 0xbf, 0x7c, 0xfe, 0xb6, 0x01, 0x4a, 0x03, 0xdb, 0xfd, 0xa6, 0x02, 0x5a, 0xfd, 0x74, 0xd5, 0xd5, 0x7c, 0xfe, 0xb6, 0x01, 0x4a, 0x00, 0x00, 0x02, 0x01, 0x66, 0xff, 0x2c, 0x04, 0x49, 0x05, 0xaf, 0x00, 0x07, 0x00, 0x1c, 0x00, 0x00, 0x24, 0x14, 0x16, 0x32, 0x36, 0x34, 0x26, 0x22, 0x02, 0x26, 0x10, 0x37, 0x36, 0x37, 0x11, 0x33, 0x11, 0x25, 0x17, 0x0d, 0x01, 0x07, 0x25, 0x11, 0x16, 0x17, 0x16, 0x10, 0x06, 0x01, 0xef, 0x69, 0x96, 0x69, 0x69, 0x96, 0x38, 0xba, 0x5e, 0x41, 0x53, 0x9b, 0x01, 0x08, 0x4d, 0xfe, 0xbd, 0x01, 0x43, 0x4d, 0xfe, 0xf8, 0x50, 0x3f, 0x5e, 0xba, 0xdd, 0xa6, 0x75, 0x75, 0xa6, 0x76, 0xfd, 0xd9, 0xce, 0x01, 0x23, 0x67, 0x47, 0x16, 0x03, 0xce, 0xfe, 0xce, 0xad, 0x94, 0xd1, 0xd2, 0x94, 0xae, 0xfe, 0xd2, 0x16, 0x45, 0x67, 0xfe, 0xdd, 0xce, 0x00, 0x01, 0x01, 0x23, 0xfe, 0xff, 0x03, 0xe9, 0x05, 0xda, 0x00, 0x1e, 0x00, 0x00, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x26, 0x27, 0x26, 0x35, 0x10, 0x25, 0x36, 0x37, 0x36, 0x17, 0x06, 0x07, 0x06, 0x15, 0x10, 0x17, 0x16, 0x17, 0x06, 0x27, 0x15, 0x33, 0x15, 0x02, 0xf4, 0xa2, 0xf5, 0xf5, 0x8c, 0x5c, 0x46, 0x01, 0x0b, 0x54, 0x9c, 0x41, 0x35, 0xb7, 0x58, 0x68, 0xe1, 0x4e, 0x4d, 0x43, 0x63, 0xf5, 0xfe, 0xff, 0x01, 0x01, 0x7c, 0x01, 0x33, 0x4c, 0x98, 0x75, 0xa1, 0x01, 0x2e, 0xb9, 0x3a, 0x10, 0x07, 0x17, 0x3b, 0x85, 0x9d, 0xc4, 0xfe, 0xcd, 0xa2, 0x38, 0x0f, 0x25, 0x13, 0xff, 0x7c, 0x00, 0x00, 0x03, 0x00, 0x4d, 0x00, 0x08, 0x05, 0xbb, 0x04, 0x6d, 0x00, 0x0f, 0x00, 0x1d, 0x00, 0x33, 0x00, 0x00, 0x13, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x00, 0x20, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x35, 0x34, 0x27, 0x37, 0x1e, 0x01, 0x15, 0x11, 0x14, 0x06, 0x07, 0x06, 0x21, 0x20, 0x27, 0x2e, 0x01, 0x35, 0x11, 0x34, 0x36, 0x37, 0x36, 0x21, 0x20, 0xa7, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x29, 0x33, 0xd8, 0xfd, 0xae, 0xd5, 0x39, 0x03, 0x41, 0xfd, 0xed, 0xba, 0x9a, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x9a, 0x28, 0x67, 0x65, 0x65, 0x65, 0xcf, 0xfe, 0xe2, 0xfe, 0xe6, 0xd0, 0x68, 0x65, 0x65, 0x65, 0xcf, 0x01, 0x1e, 0x01, 0x1a, 0x02, 0x1d, 0x93, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x92, 0x22, 0x1c, 0x78, 0x78, 0x20, 0x02, 0x0b, 0x68, 0x56, 0x63, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x63, 0x56, 0x59, 0x39, 0x88, 0x51, 0xfe, 0xa2, 0x4e, 0x88, 0x39, 0x73, 0x73, 0x39, 0x88, 0x4e, 0x01, 0x5e, 0x51, 0x88, 0x39, 0x73, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x08, 0x05, 0xbb, 0x05, 0xcb, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x2d, 0x00, 0x45, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x03, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x01, 0x1e, 0x01, 0x15, 0x19, 0x01, 0x14, 0x06, 0x07, 0x06, 0x21, 0x20, 0x27, 0x2e, 0x01, 0x35, 0x19, 0x01, 0x34, 0x36, 0x37, 0x36, 0x21, 0x20, 0x04, 0x0e, 0xfd, 0xed, 0xba, 0x9a, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x9a, 0xfb, 0xe0, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x29, 0x33, 0xd8, 0xfd, 0xae, 0xd5, 0x39, 0x26, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x29, 0x33, 0xd8, 0xfd, 0xae, 0xd5, 0x39, 0x04, 0x22, 0x67, 0x65, 0x65, 0x65, 0xcf, 0xfe, 0xe2, 0xfe, 0xe6, 0xd0, 0x68, 0x65, 0x65, 0x65, 0xcf, 0x01, 0x1e, 0x01, 0x1a, 0x05, 0x67, 0x68, 0x56, 0x63, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x63, 0x56, 0xfe, 0x7c, 0x93, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x92, 0x22, 0x1c, 0x78, 0x78, 0x20, 0xfe, 0xc1, 0x93, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x92, 0x22, 0x1c, 0x78, 0x78, 0x20, 0x03, 0x5a, 0x39, 0x88, 0x51, 0xfe, 0xa2, 0xfe, 0xa2, 0x4e, 0x88, 0x39, 0x73, 0x73, 0x39, 0x88, 0x4e, 0x01, 0x5e, 0x01, 0x5e, 0x51, 0x88, 0x39, 0x73, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x4d, 0x00, 0x08, 0x05, 0xbb, 0x04, 0x6d, 0x00, 0x0b, 0x00, 0x21, 0x00, 0x31, 0x00, 0x3f, 0x00, 0x55, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x16, 0x21, 0x20, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x15, 0x06, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x37, 0x36, 0x37, 0x36, 0x37, 0x03, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x00, 0x20, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x35, 0x34, 0x27, 0x37, 0x1e, 0x01, 0x15, 0x11, 0x14, 0x06, 0x07, 0x06, 0x21, 0x20, 0x27, 0x2e, 0x01, 0x35, 0x11, 0x34, 0x36, 0x37, 0x36, 0x21, 0x20, 0x04, 0xec, 0x1c, 0x32, 0xa6, 0xf4, 0xf6, 0xa3, 0x35, 0x1b, 0xd4, 0x01, 0x15, 0x01, 0x13, 0xfd, 0xf9, 0x01, 0xea, 0xa4, 0x34, 0x1c, 0x19, 0x02, 0x17, 0x1c, 0x34, 0xa6, 0xfe, 0x16, 0xa3, 0x35, 0x1b, 0x1b, 0x01, 0x01, 0x19, 0x1c, 0x34, 0xc4, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x29, 0x33, 0xd8, 0xfd, 0xae, 0xd5, 0x39, 0x03, 0x41, 0xfd, 0xed, 0xba, 0x9a, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x9a, 0x28, 0x67, 0x65, 0x65, 0x65, 0xcf, 0xfe, 0xe2, 0xfe, 0xe6, 0xd0, 0x68, 0x65, 0x65, 0x65, 0xcf, 0x01, 0x1e, 0x01, 0x1a, 0x01, 0x64, 0x1b, 0x1c, 0x5d, 0x5d, 0x1e, 0x1a, 0x63, 0x02, 0xa3, 0x5d, 0x1d, 0x1c, 0x19, 0x0e, 0x0e, 0x16, 0x1c, 0x1d, 0x5d, 0x5d, 0x1e, 0x1b, 0x18, 0x0c, 0x0f, 0x18, 0x1c, 0x1d, 0xfe, 0xd5, 0x93, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x92, 0x22, 0x1c, 0x78, 0x78, 0x20, 0x02, 0x0b, 0x68, 0x56, 0x63, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x63, 0x56, 0x59, 0x39, 0x88, 0x51, 0xfe, 0xa2, 0x4e, 0x88, 0x39, 0x73, 0x73, 0x39, 0x88, 0x4e, 0x01, 0x5e, 0x51, 0x88, 0x39, 0x73, 0x00, 0x07, 0x00, 0x4d, 0x00, 0x08, 0x05, 0xbb, 0x05, 0xcb, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x3b, 0x00, 0x4b, 0x00, 0x5b, 0x00, 0x73, 0x00, 0x00, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x15, 0x06, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x37, 0x36, 0x37, 0x36, 0x37, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x16, 0x21, 0x20, 0x17, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x16, 0x21, 0x20, 0x02, 0x20, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x03, 0x15, 0x14, 0x17, 0x16, 0x20, 0x37, 0x36, 0x3d, 0x01, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x01, 0x1e, 0x01, 0x15, 0x19, 0x01, 0x14, 0x06, 0x07, 0x06, 0x21, 0x20, 0x27, 0x2e, 0x01, 0x35, 0x19, 0x01, 0x34, 0x36, 0x37, 0x36, 0x21, 0x20, 0x02, 0x10, 0x01, 0xea, 0xa4, 0x34, 0x1c, 0x19, 0x02, 0x17, 0x1c, 0x34, 0xa6, 0xfe, 0x16, 0xa3, 0x35, 0x1b, 0x1b, 0x01, 0x01, 0x19, 0x1c, 0x34, 0x03, 0x81, 0x1c, 0x32, 0xa6, 0xf4, 0xf6, 0xa3, 0x35, 0x1b, 0xd4, 0x01, 0x15, 0x01, 0x13, 0xd5, 0x1c, 0x32, 0xa6, 0xf4, 0xf6, 0xa3, 0x35, 0x1b, 0xd4, 0x01, 0x15, 0x01, 0x13, 0x09, 0xfd, 0xed, 0xba, 0x9a, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x9a, 0xfb, 0xe0, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x29, 0x33, 0xd8, 0xfd, 0xae, 0xd5, 0x39, 0x26, 0x9a, 0xba, 0x02, 0x13, 0xb9, 0x9a, 0x29, 0x33, 0xd8, 0xfd, 0xae, 0xd5, 0x39, 0x04, 0x22, 0x67, 0x65, 0x65, 0x65, 0xcf, 0xfe, 0xe2, 0xfe, 0xe6, 0xd0, 0x68, 0x65, 0x65, 0x65, 0xcf, 0x01, 0x1e, 0x01, 0x1a, 0x05, 0x03, 0x5d, 0x1d, 0x1c, 0x19, 0x0e, 0x0e, 0x16, 0x1c, 0x1d, 0x5d, 0x5d, 0x1e, 0x1b, 0x18, 0x0c, 0x0f, 0x18, 0x1c, 0x1d, 0xfe, 0x1c, 0x1b, 0x1c, 0x5d, 0x5d, 0x1e, 0x1a, 0x63, 0xfc, 0x1b, 0x1c, 0x5d, 0x5d, 0x1e, 0x1a, 0x63, 0x04, 0x65, 0x68, 0x56, 0x63, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x63, 0x56, 0xfe, 0x7c, 0x93, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x92, 0x22, 0x1c, 0x78, 0x78, 0x20, 0xfe, 0xc1, 0x93, 0x60, 0x56, 0x68, 0x68, 0x56, 0x60, 0x92, 0x22, 0x1c, 0x78, 0x78, 0x20, 0x03, 0x5a, 0x39, 0x88, 0x51, 0xfe, 0xa2, 0xfe, 0xa2, 0x4e, 0x88, 0x39, 0x73, 0x73, 0x39, 0x88, 0x4e, 0x01, 0x5e, 0x01, 0x5e, 0x51, 0x88, 0x39, 0x73, 0x00, 0x00, 0x03, 0x00, 0x9d, 0xff, 0xe3, 0x04, 0xa9, 0x06, 0xbe, 0x00, 0x0b, 0x00, 0x20, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x13, 0x16, 0x17, 0x16, 0x15, 0x14, 0x00, 0x23, 0x22, 0x00, 0x10, 0x37, 0x36, 0x37, 0x0b, 0x01, 0x35, 0x09, 0x01, 0x15, 0x0b, 0x01, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x02, 0xa3, 0x3a, 0x57, 0x55, 0x3c, 0x3f, 0x52, 0x55, 0x15, 0xa3, 0x79, 0x98, 0xfe, 0xd2, 0xd7, 0xd4, 0xfe, 0xcf, 0x98, 0x7a, 0xa2, 0x01, 0xed, 0x01, 0x3f, 0x01, 0x3f, 0xee, 0x51, 0x94, 0xcf, 0xcf, 0x94, 0x91, 0xd2, 0xd2, 0x01, 0x7d, 0x5b, 0x44, 0x3e, 0x58, 0x55, 0x41, 0x42, 0x5d, 0x02, 0xbb, 0x11, 0x7e, 0x9d, 0xee, 0xef, 0xfe, 0xb4, 0x01, 0x4c, 0x01, 0xde, 0x9c, 0x7e, 0x12, 0x01, 0x67, 0xfe, 0xfa, 0xc7, 0x01, 0x5d, 0xfe, 0xa3, 0xc7, 0x01, 0x05, 0xfa, 0xf7, 0xe4, 0xa4, 0xa3, 0xd8, 0xd8, 0xa3, 0xa4, 0xe4, 0x00, 0x03, 0x00, 0x13, 0x01, 0x85, 0x05, 0xc8, 0x05, 0x14, 0x00, 0x50, 0x00, 0x6a, 0x00, 0x85, 0x00, 0x00, 0x01, 0x27, 0x23, 0x22, 0x27, 0x26, 0x07, 0x06, 0x14, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x33, 0x32, 0x1f, 0x01, 0x16, 0x33, 0x32, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x26, 0x27, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x17, 0x16, 0x1f, 0x01, 0x21, 0x32, 0x17, 0x16, 0x17, 0x21, 0x17, 0x25, 0x16, 0x33, 0x32, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x34, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x14, 0x17, 0x1e, 0x01, 0x01, 0x26, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x14, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x34, 0x27, 0x26, 0x27, 0x26, 0x03, 0x6c, 0xc1, 0x67, 0x9d, 0x19, 0x26, 0x03, 0x01, 0x09, 0x0b, 0x2c, 0x20, 0x19, 0x27, 0x20, 0x21, 0x20, 0x17, 0x13, 0x15, 0x10, 0x0b, 0x0b, 0x2c, 0x20, 0x1a, 0x26, 0x1f, 0x09, 0x50, 0x58, 0x51, 0x21, 0x0d, 0x13, 0x22, 0x02, 0x03, 0x06, 0x0c, 0x0b, 0x14, 0x46, 0x4b, 0x2d, 0x2c, 0x17, 0x19, 0x0e, 0x11, 0x0b, 0x0c, 0x2f, 0x1c, 0x20, 0x41, 0x40, 0x18, 0x1c, 0x0c, 0x10, 0x0b, 0x08, 0x1b, 0x03, 0x04, 0x1e, 0x25, 0x62, 0x4a, 0x01, 0x64, 0xd0, 0x47, 0x5b, 0x10, 0xfd, 0xa5, 0xbf, 0xfc, 0x72, 0x13, 0x12, 0x16, 0x0e, 0x13, 0x1a, 0x05, 0x04, 0x0b, 0x08, 0x0e, 0x0f, 0x28, 0x0f, 0x12, 0x12, 0x13, 0x17, 0x07, 0x05, 0x0c, 0x08, 0x1c, 0x01, 0x11, 0x10, 0x15, 0x19, 0x0b, 0x13, 0x1b, 0x03, 0x05, 0x0b, 0x09, 0x0e, 0x0d, 0x27, 0x12, 0x14, 0x10, 0x13, 0x19, 0x04, 0x06, 0x0c, 0x09, 0x0d, 0x0a, 0x01, 0x85, 0xcd, 0x06, 0x08, 0x0d, 0x08, 0x29, 0x17, 0x20, 0x2e, 0x0d, 0x0b, 0x0f, 0x0e, 0x19, 0x15, 0x24, 0x1d, 0x4a, 0x1e, 0x20, 0x2e, 0x0d, 0x0b, 0x03, 0x25, 0x27, 0x03, 0x05, 0x1c, 0x07, 0x08, 0x2e, 0x13, 0x13, 0x13, 0x44, 0x22, 0x14, 0x14, 0x18, 0x1b, 0x1e, 0x26, 0x42, 0x1d, 0x20, 0x31, 0x0a, 0x0b, 0x1e, 0x18, 0x1e, 0x1c, 0x24, 0x43, 0x1e, 0x17, 0x1d, 0x07, 0x0d, 0x16, 0x1a, 0x6d, 0x52, 0x20, 0x29, 0x4b, 0xcf, 0x79, 0x09, 0x05, 0x07, 0x18, 0x10, 0x11, 0x1f, 0x17, 0x12, 0x0d, 0x10, 0x10, 0x06, 0x06, 0x17, 0x11, 0x11, 0x20, 0x16, 0x12, 0x1c, 0x02, 0xb5, 0x09, 0x05, 0x07, 0x19, 0x0f, 0x11, 0x21, 0x15, 0x12, 0x0e, 0x0d, 0x12, 0x05, 0x07, 0x19, 0x0e, 0x12, 0x20, 0x16, 0x12, 0x0e, 0x09, 0x00, 0x00, 0x03, 0x00, 0x4d, 0x01, 0x21, 0x05, 0xa5, 0x04, 0xb5, 0x00, 0x15, 0x00, 0x64, 0x00, 0x7a, 0x00, 0x00, 0x12, 0x32, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x01, 0x22, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x01, 0x05, 0x06, 0x23, 0x22, 0x27, 0x25, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x32, 0x37, 0x3e, 0x02, 0x34, 0x2e, 0x01, 0x27, 0x26, 0x2b, 0x01, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x25, 0x36, 0x33, 0x32, 0x17, 0x24, 0x22, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x01, 0x32, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0xe4, 0x29, 0x22, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f, 0x22, 0x29, 0x22, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x02, 0xb4, 0x02, 0x2e, 0x27, 0x62, 0x49, 0xc5, 0xfe, 0xb5, 0x5f, 0x87, 0x48, 0x0f, 0x19, 0x19, 0x14, 0x24, 0x1d, 0x47, 0x1d, 0x1f, 0x19, 0x18, 0x1b, 0x1a, 0x19, 0x14, 0x24, 0x1d, 0x09, 0x57, 0x4d, 0x5c, 0x18, 0x22, 0x16, 0x16, 0x22, 0x18, 0x58, 0x51, 0x30, 0x30, 0x1d, 0x24, 0x14, 0x19, 0x1a, 0x1b, 0x18, 0x19, 0x1f, 0x1d, 0x47, 0x1d, 0x24, 0x14, 0x19, 0x19, 0x0f, 0x48, 0x87, 0x5f, 0x01, 0x4b, 0xc5, 0x49, 0x62, 0x27, 0xfb, 0x69, 0x29, 0x22, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x22, 0x29, 0x22, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f, 0x01, 0x71, 0x0e, 0x0d, 0x0e, 0x1f, 0x13, 0x12, 0x1f, 0x0e, 0x0d, 0x0e, 0x0e, 0x0d, 0x0e, 0x1f, 0x12, 0x13, 0x1f, 0x0e, 0x0d, 0x01, 0x6c, 0xfc, 0x3f, 0x57, 0x92, 0x2c, 0x3e, 0x0e, 0x0e, 0x08, 0x26, 0x19, 0x23, 0x3c, 0x1a, 0x15, 0x10, 0x0d, 0x0d, 0x0e, 0x17, 0x15, 0x41, 0x23, 0x22, 0x3c, 0x1a, 0x15, 0x10, 0x0d, 0x22, 0x09, 0x1a, 0x28, 0x10, 0x28, 0x1a, 0x09, 0x22, 0x0d, 0x10, 0x15, 0x1a, 0x3c, 0x22, 0x23, 0x41, 0x15, 0x17, 0x0e, 0x0d, 0x0d, 0x10, 0x15, 0x1a, 0x3c, 0x23, 0x19, 0x26, 0x08, 0x0e, 0x0e, 0x3e, 0x2c, 0x92, 0x57, 0x3f, 0x7e, 0x0e, 0x0d, 0x0e, 0x1f, 0x13, 0x12, 0x1f, 0x0e, 0x0d, 0x0e, 0x0e, 0x0d, 0x0e, 0x1f, 0x12, 0x13, 0x1f, 0x0e, 0x0d, 0x00, 0x03, 0x00, 0x13, 0x00, 0xc0, 0x05, 0xc8, 0x04, 0x4f, 0x00, 0x4f, 0x00, 0x6a, 0x00, 0x85, 0x00, 0x00, 0x01, 0x33, 0x07, 0x21, 0x06, 0x07, 0x06, 0x23, 0x21, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x3f, 0x01, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x06, 0x23, 0x22, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x34, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x33, 0x32, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x14, 0x17, 0x16, 0x37, 0x36, 0x3b, 0x01, 0x25, 0x06, 0x07, 0x06, 0x07, 0x06, 0x14, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x34, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x23, 0x22, 0x13, 0x36, 0x37, 0x36, 0x37, 0x36, 0x34, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x06, 0x07, 0x06, 0x14, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x33, 0x32, 0x03, 0x6c, 0xc0, 0xbf, 0x02, 0x5b, 0x10, 0x5b, 0x47, 0xd0, 0xfe, 0x9c, 0x4a, 0x5a, 0x2d, 0x1a, 0x1e, 0x08, 0x0b, 0x10, 0x0c, 0x1c, 0x18, 0x40, 0x41, 0x20, 0x1c, 0x32, 0x09, 0x0b, 0x11, 0x0b, 0x1c, 0x17, 0x08, 0x51, 0x4b, 0x46, 0x14, 0x0b, 0x0c, 0x06, 0x03, 0x02, 0x1a, 0x1b, 0x08, 0x26, 0x51, 0x58, 0x2c, 0x2d, 0x1f, 0x27, 0x19, 0x20, 0x2c, 0x0b, 0x0b, 0x10, 0x10, 0x2f, 0x20, 0x21, 0x20, 0x27, 0x19, 0x20, 0x2c, 0x0b, 0x09, 0x01, 0x06, 0x23, 0x16, 0xa0, 0x67, 0xfd, 0xf3, 0x12, 0x0e, 0x08, 0x0e, 0x0c, 0x05, 0x07, 0x14, 0x16, 0x0f, 0x15, 0x13, 0x25, 0x0e, 0x0e, 0x08, 0x0c, 0x05, 0x07, 0x13, 0x18, 0x0f, 0x15, 0x12, 0xec, 0x13, 0x0e, 0x08, 0x0e, 0x0c, 0x06, 0x06, 0x19, 0x11, 0x10, 0x14, 0x13, 0x26, 0x0d, 0x0e, 0x09, 0x0b, 0x05, 0x06, 0x1b, 0x10, 0x12, 0x12, 0x0d, 0x04, 0x4f, 0xcf, 0x4b, 0x29, 0x20, 0x52, 0x64, 0x23, 0x14, 0x0f, 0x06, 0x1e, 0x17, 0x21, 0x3e, 0x26, 0x1c, 0x1e, 0x18, 0x1e, 0x0b, 0x0a, 0x33, 0x1e, 0x22, 0x39, 0x2a, 0x1b, 0x1e, 0x18, 0x04, 0x24, 0x22, 0x44, 0x13, 0x13, 0x13, 0x2e, 0x08, 0x07, 0x16, 0x0b, 0x03, 0x27, 0x14, 0x14, 0x0b, 0x0e, 0x2d, 0x20, 0x20, 0x44, 0x21, 0x20, 0x32, 0x0e, 0x0f, 0x0b, 0x0d, 0x2e, 0x20, 0x17, 0x2c, 0x05, 0x0e, 0x09, 0x06, 0x54, 0x08, 0x0e, 0x08, 0x18, 0x13, 0x25, 0x0f, 0x11, 0x15, 0x08, 0x06, 0x12, 0x0e, 0x0d, 0x12, 0x16, 0x23, 0x0e, 0x12, 0x15, 0x08, 0x05, 0xfd, 0x3a, 0x09, 0x0d, 0x08, 0x18, 0x13, 0x26, 0x0f, 0x10, 0x19, 0x05, 0x05, 0x12, 0x0d, 0x0e, 0x12, 0x13, 0x28, 0x0c, 0x11, 0x19, 0x05, 0x05, 0x00, 0x00, 0x09, 0x00, 0x41, 0x00, 0xf4, 0x05, 0xf0, 0x04, 0xe8, 0x00, 0x5a, 0x00, 0x78, 0x00, 0x96, 0x00, 0xb4, 0x00, 0xd2, 0x00, 0xfe, 0x01, 0x2d, 0x01, 0x34, 0x01, 0x48, 0x00, 0x00, 0x01, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x1f, 0x01, 0x25, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x0d, 0x01, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x25, 0x07, 0x06, 0x07, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x32, 0x37, 0x36, 0x02, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x12, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x12, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x02, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x05, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x37, 0x36, 0x03, 0x2d, 0x01, 0x26, 0x23, 0x22, 0x07, 0x05, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x25, 0x05, 0x16, 0x33, 0x32, 0x37, 0x25, 0x26, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x02, 0x0e, 0x0a, 0x07, 0x07, 0x0a, 0x08, 0x16, 0x49, 0x53, 0x3c, 0x29, 0x28, 0x21, 0x24, 0x1f, 0x11, 0x10, 0x10, 0x0e, 0x24, 0x19, 0x2a, 0x26, 0x2b, 0x29, 0x28, 0x27, 0x1e, 0x24, 0x0c, 0x10, 0x05, 0x2a, 0x80, 0x4f, 0x01, 0x3a, 0xcc, 0x52, 0x7b, 0x33, 0x07, 0x1b, 0xfe, 0x35, 0x01, 0xcb, 0x1b, 0x07, 0x36, 0x78, 0x52, 0xcc, 0xfe, 0xc6, 0x4f, 0x80, 0x2a, 0x05, 0x10, 0x11, 0x1f, 0x20, 0x25, 0x2b, 0x26, 0x2e, 0x23, 0x25, 0x1f, 0x25, 0x0c, 0x10, 0x10, 0x0e, 0x22, 0x19, 0x2c, 0x26, 0x2b, 0x3c, 0x4a, 0x52, 0x15, 0xfa, 0x19, 0x0a, 0x0b, 0x08, 0x09, 0x03, 0x03, 0x03, 0x03, 0x09, 0x08, 0x0b, 0x0a, 0x19, 0x0a, 0x0a, 0x09, 0x08, 0x03, 0x03, 0x03, 0x03, 0x08, 0x09, 0x0a, 0x0a, 0x19, 0x0a, 0x0b, 0x08, 0x09, 0x03, 0x03, 0x03, 0x03, 0x09, 0x08, 0x0b, 0x0a, 0x19, 0x0a, 0x0a, 0x09, 0x08, 0x03, 0x03, 0x03, 0x03, 0x08, 0x09, 0x0a, 0x2d, 0x2d, 0x13, 0x12, 0x10, 0x11, 0x08, 0x08, 0x08, 0x08, 0x11, 0x10, 0x12, 0x13, 0x2d, 0x13, 0x13, 0x10, 0x11, 0x08, 0x08, 0x08, 0x08, 0x11, 0x10, 0x13, 0x13, 0x2d, 0x13, 0x12, 0x10, 0x11, 0x08, 0x08, 0x08, 0x08, 0x11, 0x10, 0x12, 0x13, 0x2d, 0x13, 0x13, 0x10, 0x11, 0x08, 0x08, 0x08, 0x08, 0x11, 0x10, 0x13, 0x01, 0x5f, 0x21, 0x86, 0x23, 0x14, 0x0a, 0x0e, 0x0a, 0x05, 0x0c, 0x0b, 0x19, 0x12, 0x22, 0x1c, 0x42, 0x1c, 0x1d, 0x18, 0x16, 0x0e, 0x0b, 0x0b, 0x0c, 0x18, 0x12, 0x23, 0x1c, 0x21, 0x3c, 0x53, 0x5a, 0x1b, 0x10, 0x15, 0x06, 0x20, 0x19, 0xaa, 0x01, 0xbc, 0x02, 0x22, 0x26, 0x54, 0x47, 0xc3, 0xfe, 0xb6, 0x86, 0x10, 0x0f, 0x15, 0x12, 0x19, 0x5e, 0x4f, 0x3c, 0x21, 0x1c, 0x23, 0x12, 0x18, 0x0c, 0x0b, 0x0b, 0x0e, 0x16, 0x18, 0x1d, 0x1c, 0x42, 0x1c, 0x22, 0x12, 0x19, 0x0b, 0x0c, 0x05, 0x0a, 0x0e, 0x0b, 0x01, 0x6b, 0x01, 0x02, 0xc3, 0x47, 0x54, 0x26, 0xfe, 0x14, 0xc4, 0x04, 0x06, 0x08, 0x08, 0x14, 0x08, 0x08, 0x05, 0x05, 0x05, 0x05, 0x08, 0x08, 0x14, 0x08, 0x08, 0x06, 0x02, 0xd9, 0x08, 0x0d, 0x0e, 0x07, 0x06, 0x0a, 0x20, 0x10, 0x0d, 0x22, 0x1c, 0x29, 0x26, 0x60, 0x26, 0x22, 0x27, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1f, 0x24, 0x22, 0x2f, 0x27, 0x1d, 0x12, 0x09, 0x3c, 0x25, 0x8b, 0x5a, 0x53, 0x0d, 0x11, 0x1f, 0x0c, 0xcf, 0xcf, 0x0c, 0x25, 0x0d, 0x0b, 0x53, 0x5a, 0x8b, 0x25, 0x3c, 0x09, 0x18, 0x17, 0x2f, 0x27, 0x2a, 0x1d, 0x20, 0x0e, 0x10, 0x10, 0x11, 0x1c, 0x22, 0x25, 0x35, 0x22, 0x2d, 0x28, 0x24, 0x23, 0x1b, 0x13, 0x10, 0x20, 0x09, 0xfe, 0xd2, 0x04, 0x05, 0x08, 0x07, 0x07, 0x04, 0x08, 0x07, 0x05, 0x06, 0x08, 0x07, 0x05, 0x04, 0x04, 0x05, 0x08, 0x07, 0x07, 0x04, 0x07, 0x08, 0x05, 0x06, 0x08, 0x07, 0x05, 0x02, 0x3b, 0x04, 0x05, 0x08, 0x07, 0x07, 0x04, 0x07, 0x08, 0x05, 0x06, 0x08, 0x07, 0x05, 0x04, 0x04, 0x05, 0x08, 0x07, 0x07, 0x04, 0x08, 0x07, 0x05, 0x06, 0x08, 0x07, 0x05, 0xfd, 0x82, 0x07, 0x08, 0x0e, 0x10, 0x11, 0x12, 0x16, 0x15, 0x12, 0x11, 0x10, 0x0e, 0x08, 0x07, 0x07, 0x08, 0x0e, 0x10, 0x11, 0x12, 0x15, 0x16, 0x12, 0x11, 0x10, 0x0e, 0x08, 0x02, 0x38, 0x07, 0x08, 0x0e, 0x10, 0x11, 0x12, 0x15, 0x16, 0x12, 0x11, 0x10, 0x0e, 0x08, 0x07, 0x07, 0x08, 0x0e, 0x10, 0x11, 0x12, 0x16, 0x15, 0x12, 0x11, 0x10, 0x0e, 0x08, 0x5c, 0x0f, 0x3d, 0x07, 0x04, 0x06, 0x08, 0x0e, 0x0a, 0x18, 0x0e, 0x17, 0x21, 0x1c, 0x1b, 0x19, 0x13, 0x10, 0x0c, 0x0c, 0x0e, 0x16, 0x13, 0x20, 0x1c, 0x21, 0x20, 0x1c, 0x1b, 0x19, 0x13, 0x10, 0x0c, 0x22, 0x0a, 0x0e, 0x11, 0x08, 0x18, 0x11, 0xfe, 0xf2, 0xc2, 0xf7, 0x2f, 0x56, 0x92, 0x43, 0x1e, 0x1e, 0x0f, 0x0e, 0x0a, 0x22, 0x0c, 0x10, 0x13, 0x19, 0x1b, 0x1c, 0x20, 0x21, 0x1c, 0x20, 0x13, 0x16, 0x0e, 0x0c, 0x0c, 0x10, 0x13, 0x19, 0x1b, 0x1c, 0x21, 0x17, 0x0d, 0x19, 0x0a, 0x14, 0x02, 0x02, 0x5b, 0x75, 0x56, 0x2f, 0xe1, 0x2b, 0x16, 0x09, 0x09, 0x06, 0x05, 0x05, 0x06, 0x09, 0x09, 0x16, 0x09, 0x09, 0x06, 0x05, 0x05, 0x06, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4d, 0xff, 0xe3, 0x05, 0xbb, 0x05, 0xf0, 0x00, 0x61, 0x00, 0x75, 0x00, 0x87, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x15, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x37, 0x26, 0x35, 0x34, 0x37, 0x12, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x16, 0x17, 0x16, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x36, 0x37, 0x36, 0x35, 0x34, 0x01, 0xde, 0x03, 0x0b, 0x13, 0x11, 0x12, 0x16, 0x64, 0x00, 0xff, 0x6d, 0x6c, 0x58, 0x5a, 0x57, 0x55, 0x5c, 0x56, 0x6e, 0x6c, 0x7c, 0x78, 0x70, 0x6b, 0x58, 0x5a, 0x58, 0x46, 0x27, 0x60, 0x67, 0x63, 0x6a, 0x61, 0x7f, 0x7e, 0x8c, 0x8b, 0x80, 0x78, 0x68, 0x65, 0x67, 0x63, 0x69, 0x63, 0x7d, 0x7f, 0xfe, 0xe6, 0x7c, 0x26, 0x3d, 0x21, 0x1d, 0x19, 0x03, 0x61, 0xa3, 0x98, 0x49, 0x05, 0x0f, 0x21, 0x1e, 0x08, 0x31, 0x26, 0x1c, 0x3d, 0x39, 0x0f, 0x10, 0x14, 0x1e, 0x30, 0x23, 0x10, 0x0f, 0x44, 0x15, 0x24, 0x2d, 0x17, 0x14, 0x03, 0x29, 0x05, 0x10, 0x01, 0x0a, 0x11, 0x18, 0x1f, 0x1d, 0x11, 0x03, 0x03, 0x18, 0x01, 0x75, 0x37, 0x14, 0x0f, 0x13, 0x0c, 0x1b, 0x09, 0x19, 0x09, 0x34, 0x0f, 0x1a, 0x1b, 0x01, 0x37, 0x06, 0x1e, 0x1b, 0x1c, 0x32, 0x12, 0x13, 0x0b, 0x33, 0x33, 0x31, 0x63, 0x64, 0xed, 0x88, 0x8d, 0xe8, 0x69, 0x60, 0x34, 0x33, 0x33, 0x31, 0x63, 0x64, 0xed, 0x8d, 0x87, 0xbc, 0x3e, 0x98, 0x6d, 0x01, 0x10, 0x9c, 0x9d, 0x01, 0x10, 0x77, 0x6e, 0x3c, 0x3b, 0x3b, 0x38, 0x72, 0x6f, 0xfe, 0xec, 0xa1, 0x98, 0xfe, 0xf0, 0x77, 0x70, 0x3a, 0x3b, 0x3b, 0x12, 0x42, 0x56, 0x30, 0x2f, 0x4d, 0x1f, 0x10, 0x0f, 0xcd, 0xef, 0x01, 0x90, 0x08, 0x14, 0x38, 0x3a, 0x44, 0x40, 0x2a, 0x1f, 0x7c, 0x73, 0x61, 0x20, 0x16, 0x1b, 0x1e, 0x09, 0x2d, 0x46, 0x28, 0x1c, 0x37, 0x0c, 0x22, 0x2a, 0x3d, 0x38, 0x19, 0x26, 0x08, 0x15, 0x0f, 0x30, 0x21, 0x32, 0x1d, 0x1c, 0x01, 0x06, 0x04, 0x20, 0x16, 0x11, 0x0c, 0x31, 0x2d, 0x35, 0x24, 0x26, 0x0c, 0x0a, 0x12, 0x36, 0x3a, 0x42, 0x34, 0x00, 0x00, 0x06, 0x00, 0x4d, 0xff, 0xe3, 0x05, 0xbb, 0x05, 0xf0, 0x00, 0x0d, 0x00, 0x1a, 0x00, 0x28, 0x00, 0x42, 0x00, 0x5c, 0x00, 0x77, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x27, 0x25, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x13, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x13, 0x36, 0x33, 0x32, 0x17, 0x13, 0x05, 0x0e, 0x01, 0x07, 0x25, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x13, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x01, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x32, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x36, 0x01, 0x7e, 0x38, 0x23, 0x05, 0x01, 0x0c, 0x07, 0x22, 0x21, 0x1d, 0x2c, 0x12, 0x07, 0xdb, 0x21, 0x28, 0x27, 0x5e, 0x26, 0x29, 0x20, 0x3f, 0x2e, 0x31, 0x33, 0x2d, 0x7a, 0x01, 0x0c, 0x02, 0x25, 0x39, 0xfe, 0xb6, 0x0d, 0x0d, 0x2c, 0x1d, 0x20, 0x22, 0xfd, 0x38, 0x18, 0x18, 0x14, 0x13, 0x14, 0x14, 0x13, 0x14, 0x18, 0x18, 0x38, 0x17, 0x18, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x18, 0x33, 0x78, 0x70, 0x6b, 0x58, 0x5a, 0x58, 0x59, 0x59, 0x56, 0xda, 0xf6, 0x6d, 0x6c, 0x58, 0x5a, 0x57, 0x55, 0x5c, 0x56, 0x6e, 0x6c, 0x7c, 0x8b, 0x80, 0x78, 0x68, 0x65, 0x67, 0x63, 0x69, 0x63, 0x7d, 0x7f, 0xfe, 0xea, 0x80, 0x79, 0x67, 0x65, 0x68, 0x63, 0x6a, 0x61, 0x7f, 0x7e, 0x01, 0x77, 0x49, 0x5f, 0x0f, 0xfd, 0x1e, 0x22, 0x32, 0x5b, 0x24, 0x20, 0x16, 0x09, 0x01, 0x01, 0xa3, 0x22, 0x14, 0x13, 0x13, 0x14, 0x22, 0x01, 0x83, 0x09, 0x09, 0xfe, 0x0b, 0xfd, 0x07, 0x67, 0x49, 0x83, 0x04, 0x06, 0x16, 0x20, 0x24, 0x5b, 0x32, 0x21, 0x76, 0x0b, 0x0c, 0x15, 0x17, 0x35, 0x1f, 0x1e, 0x35, 0x17, 0x15, 0x0c, 0x0b, 0x0b, 0x0c, 0x15, 0x17, 0x35, 0x1e, 0x1f, 0x35, 0x17, 0x15, 0x0c, 0x02, 0x15, 0x33, 0x31, 0x63, 0x64, 0xed, 0x8d, 0x85, 0xf1, 0x63, 0x61, 0x66, 0x33, 0x31, 0x63, 0x64, 0xed, 0x88, 0x8d, 0xe8, 0x69, 0x60, 0x34, 0x33, 0x64, 0x3b, 0x38, 0x72, 0x6f, 0xfe, 0xec, 0xa1, 0x98, 0xfe, 0xf0, 0x77, 0x70, 0x3a, 0x3b, 0x3b, 0x38, 0x72, 0x6f, 0x01, 0x14, 0x9c, 0x9d, 0x01, 0x10, 0x77, 0x6e, 0x3c, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x2c, 0x05, 0xa1, 0x05, 0xaa, 0x00, 0x2d, 0x00, 0x00, 0x13, 0x35, 0x37, 0x27, 0x33, 0x17, 0x36, 0x25, 0x02, 0x03, 0x33, 0x17, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x17, 0x33, 0x32, 0x17, 0x16, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, 0x12, 0x13, 0x24, 0x27, 0x07, 0x23, 0x37, 0x85, 0x21, 0x3a, 0x5a, 0x83, 0x84, 0x01, 0x01, 0x30, 0x99, 0x6e, 0x68, 0x85, 0x4d, 0x5a, 0x8a, 0x53, 0x88, 0xee, 0x3f, 0x2b, 0x1d, 0x1d, 0x2b, 0x3f, 0xee, 0x88, 0x53, 0x8a, 0x5a, 0x4d, 0x85, 0x68, 0x6e, 0x99, 0x30, 0xfe, 0xff, 0x84, 0x83, 0x5a, 0x3a, 0x02, 0xd7, 0x28, 0x05, 0xda, 0xc9, 0x0d, 0x0a, 0x01, 0x14, 0x01, 0x6a, 0x96, 0x50, 0x82, 0x50, 0xc6, 0x1a, 0x11, 0x2c, 0x11, 0x1a, 0xc6, 0x50, 0x82, 0x50, 0x96, 0x01, 0x60, 0x01, 0x1e, 0x0b, 0x0c, 0xc9, 0xda, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x76, 0x00, 0xdc, 0x05, 0x92, 0x04, 0xf9, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x22, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x00, 0x09, 0x01, 0x21, 0x01, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x01, 0x11, 0x01, 0x16, 0x15, 0x14, 0x05, 0x01, 0x21, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x01, 0x11, 0x01, 0x26, 0x35, 0x34, 0x01, 0x11, 0x21, 0x11, 0x03, 0x91, 0x01, 0x8c, 0xfb, 0xcf, 0x01, 0x8c, 0x06, 0x07, 0x1a, 0x21, 0x1f, 0x4a, 0x20, 0x26, 0x14, 0x07, 0x2b, 0x01, 0x83, 0xfe, 0x7d, 0x02, 0xfe, 0xc3, 0xfe, 0x72, 0x04, 0x31, 0xfe, 0x72, 0x06, 0x06, 0x1a, 0x20, 0x20, 0x4a, 0x1f, 0x21, 0x1a, 0x06, 0x2c, 0xfe, 0x7e, 0x01, 0x82, 0x03, 0xfe, 0x27, 0x05, 0x1b, 0x03, 0x68, 0x01, 0x2c, 0xfe, 0xd4, 0x09, 0x08, 0x1c, 0x10, 0x0f, 0x0f, 0x13, 0x19, 0x09, 0xaa, 0xfe, 0xde, 0x02, 0x8d, 0xfe, 0xdd, 0x11, 0x12, 0x13, 0x6b, 0xfe, 0xd3, 0x01, 0x2d, 0x08, 0x07, 0x1c, 0x10, 0x0f, 0x0f, 0x10, 0x1c, 0x07, 0xaa, 0x01, 0x22, 0xfd, 0x73, 0x01, 0x21, 0x13, 0x13, 0x12, 0xfd, 0xdf, 0x04, 0x1d, 0xfb, 0xe3, 0x00, 0x00, 0x04, 0x01, 0x87, 0x00, 0x00, 0x04, 0x0a, 0x05, 0xef, 0x00, 0x50, 0x00, 0xd0, 0x00, 0xe3, 0x00, 0xf3, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x3f, 0x01, 0x36, 0x37, 0x36, 0x33, 0x17, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x03, 0x14, 0x15, 0x14, 0x1f, 0x01, 0x16, 0x15, 0x14, 0x07, 0x17, 0x16, 0x07, 0x06, 0x1d, 0x01, 0x21, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x27, 0x26, 0x01, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x14, 0x0f, 0x01, 0x06, 0x0f, 0x01, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x02, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x26, 0x27, 0x26, 0x27, 0x26, 0x3f, 0x01, 0x36, 0x27, 0x26, 0x27, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x17, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x15, 0x07, 0x21, 0x27, 0x34, 0x37, 0x36, 0x3d, 0x01, 0x27, 0x36, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x35, 0x13, 0x34, 0x35, 0x34, 0x27, 0x01, 0x07, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2f, 0x01, 0x01, 0x88, 0x21, 0x15, 0x0f, 0x2f, 0x0c, 0x29, 0x01, 0x02, 0x04, 0x18, 0x24, 0x1b, 0x12, 0x1f, 0x15, 0x18, 0x20, 0x0f, 0x10, 0x2b, 0x0f, 0x43, 0x44, 0x22, 0x0d, 0x0d, 0x10, 0x06, 0x05, 0x09, 0x04, 0x0b, 0x05, 0x01, 0x01, 0x1c, 0x18, 0x25, 0x32, 0x1a, 0x0b, 0x01, 0x09, 0x01, 0x08, 0x02, 0x02, 0x03, 0x01, 0x03, 0x01, 0x14, 0x02, 0xfe, 0x15, 0x04, 0x09, 0x21, 0x2b, 0x18, 0x10, 0x02, 0x46, 0x03, 0x23, 0x20, 0x03, 0x05, 0x0a, 0x1f, 0x05, 0x13, 0x31, 0x16, 0x08, 0x27, 0x0f, 0x29, 0x44, 0x18, 0x12, 0x0f, 0x0d, 0x0f, 0x07, 0x07, 0x1b, 0x0b, 0x11, 0x56, 0x7a, 0x56, 0x54, 0x04, 0x12, 0x05, 0x03, 0x14, 0x10, 0x05, 0x03, 0x2b, 0x67, 0x2f, 0x06, 0x26, 0x1b, 0x11, 0x0b, 0x06, 0x05, 0x02, 0x07, 0x2c, 0x24, 0x0c, 0x07, 0x29, 0x2d, 0x01, 0x13, 0x0d, 0x01, 0x30, 0x15, 0x16, 0x30, 0x09, 0x02, 0x19, 0x70, 0x2a, 0x05, 0x07, 0x0c, 0x02, 0x06, 0x02, 0x07, 0x06, 0x0d, 0x1a, 0x24, 0x0c, 0x0e, 0x15, 0x10, 0x2c, 0x08, 0x03, 0x01, 0x09, 0x07, 0x03, 0x09, 0x53, 0x01, 0x01, 0x01, 0x80, 0x01, 0x0b, 0x0c, 0x02, 0x03, 0x08, 0x05, 0x0b, 0x02, 0xfe, 0x32, 0x10, 0x20, 0x34, 0x32, 0x0f, 0x03, 0x01, 0x10, 0x09, 0x0a, 0x03, 0x02, 0x0b, 0x04, 0x06, 0x61, 0x73, 0x0e, 0x02, 0x4a, 0x23, 0x0d, 0x0a, 0x0e, 0x08, 0x03, 0x0b, 0x07, 0x0a, 0x6c, 0x02, 0xeb, 0x37, 0x31, 0x07, 0x1f, 0x5d, 0x18, 0x17, 0x01, 0x01, 0x2f, 0x7e, 0x5b, 0x23, 0x3c, 0x24, 0x1c, 0x1b, 0x20, 0x05, 0x0c, 0x1a, 0x6f, 0xbb, 0x5f, 0x25, 0x15, 0x10, 0x40, 0x2c, 0x1f, 0x10, 0x86, 0x3a, 0x06, 0x0b, 0x0a, 0x06, 0x06, 0x24, 0x22, 0x1e, 0x3b, 0x1a, 0x12, 0x76, 0x52, 0x15, 0x12, 0xfe, 0xd4, 0x07, 0x09, 0x18, 0x1d, 0x16, 0x24, 0x58, 0x24, 0x2b, 0x7c, 0x19, 0x89, 0x13, 0x8d, 0x89, 0xb6, 0x12, 0x21, 0x35, 0x44, 0x58, 0x26, 0x50, 0x59, 0x3b, 0x02, 0xb6, 0x39, 0x44, 0x6f, 0x1e, 0x36, 0xc2, 0x1d, 0x06, 0x0f, 0x0b, 0x0d, 0x62, 0x27, 0x6e, 0x95, 0x32, 0x0f, 0x0c, 0x0b, 0x06, 0x0b, 0x1f, 0x38, 0x1a, 0x33, 0xfe, 0x65, 0x46, 0x5d, 0x0c, 0x08, 0x13, 0x04, 0x01, 0x14, 0x06, 0x07, 0x34, 0x54, 0x26, 0x03, 0x1f, 0x16, 0x0a, 0x07, 0x0c, 0x16, 0x26, 0x20, 0x12, 0x0c, 0x2f, 0x35, 0x30, 0x24, 0x3f, 0x2d, 0x20, 0x02, 0x31, 0x40, 0x1b, 0x11, 0x26, 0x11, 0x06, 0x05, 0x10, 0x09, 0x33, 0x6c, 0x0f, 0x0a, 0x17, 0x17, 0x4b, 0x0f, 0x0b, 0x0a, 0x05, 0x19, 0x03, 0x05, 0x0d, 0x43, 0x04, 0x22, 0x50, 0x31, 0x16, 0xd6, 0x09, 0x0b, 0x9f, 0xb7, 0x3a, 0x30, 0x33, 0x3c, 0x08, 0x44, 0x3a, 0x35, 0x58, 0x49, 0x2e, 0x29, 0x06, 0x07, 0x01, 0x44, 0x04, 0x07, 0x13, 0x26, 0xfe, 0x5b, 0x14, 0x2b, 0x2d, 0x31, 0x3a, 0x0d, 0x0c, 0x11, 0x10, 0x09, 0x09, 0x15, 0x17, 0x09, 0x05, 0x71, 0x12, 0x14, 0x2f, 0x41, 0x38, 0x09, 0x12, 0x0a, 0x0a, 0x12, 0x11, 0x0b, 0x06, 0x67, 0x00, 0x08, 0x00, 0x26, 0x00, 0xa9, 0x05, 0xc6, 0x05, 0x6c, 0x00, 0x06, 0x00, 0x39, 0x00, 0x4c, 0x00, 0x70, 0x00, 0x7b, 0x00, 0x7f, 0x00, 0x89, 0x00, 0x8d, 0x00, 0x00, 0x13, 0x16, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x0f, 0x01, 0x13, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x07, 0x17, 0x16, 0x33, 0x32, 0x37, 0x33, 0x16, 0x15, 0x14, 0x07, 0x23, 0x35, 0x06, 0x25, 0x36, 0x37, 0x36, 0x37, 0x01, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x0f, 0x01, 0x16, 0x15, 0x14, 0x07, 0x36, 0x01, 0x22, 0x2f, 0x01, 0x07, 0x14, 0x07, 0x36, 0x37, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x07, 0x16, 0x15, 0x14, 0x07, 0x32, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x06, 0x37, 0x16, 0x15, 0x14, 0x07, 0x15, 0x33, 0x36, 0x35, 0x34, 0x27, 0x05, 0x36, 0x37, 0x0f, 0x01, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x36, 0x35, 0x34, 0x05, 0x07, 0x37, 0x26, 0xc2, 0x19, 0x12, 0x0d, 0x0e, 0x03, 0x18, 0x2a, 0x62, 0x2b, 0x1a, 0x22, 0x87, 0x43, 0x1d, 0x5a, 0x4a, 0x22, 0x50, 0xed, 0x74, 0x06, 0x0d, 0x3e, 0x19, 0x17, 0x54, 0x6e, 0x3a, 0x3c, 0x1f, 0x20, 0x2f, 0x38, 0x89, 0x29, 0x35, 0x21, 0x1b, 0x0c, 0xab, 0xb8, 0x27, 0x24, 0x31, 0x05, 0xcb, 0x50, 0x38, 0xdf, 0x62, 0xfd, 0x0f, 0x1e, 0x1b, 0x07, 0x05, 0x01, 0x2c, 0x20, 0x0f, 0x1c, 0x50, 0xd4, 0x30, 0x1f, 0x12, 0x2a, 0x27, 0x24, 0x03, 0x4d, 0x2f, 0x17, 0xd9, 0x68, 0x4b, 0x39, 0x4f, 0x0e, 0x21, 0x4c, 0x74, 0x38, 0x16, 0x1f, 0x12, 0x67, 0x43, 0x39, 0x43, 0x24, 0x57, 0x29, 0x2a, 0x2f, 0x7c, 0x26, 0x2d, 0x16, 0x43, 0x2d, 0x29, 0x8e, 0x2b, 0x38, 0xfd, 0x05, 0x4b, 0x0c, 0x92, 0x51, 0x65, 0x2b, 0x1c, 0x27, 0x15, 0xfe, 0xc3, 0x2c, 0x54, 0x06, 0x01, 0xf0, 0x03, 0x27, 0x1f, 0x1f, 0x20, 0x10, 0xfe, 0xc7, 0x0e, 0x05, 0x10, 0x08, 0x3b, 0x63, 0x73, 0x01, 0x0c, 0x12, 0x20, 0x1a, 0x2f, 0xe8, 0x5e, 0x22, 0x7c, 0x59, 0x2f, 0x1a, 0x0d, 0x34, 0xab, 0x32, 0x38, 0x19, 0x1d, 0xdb, 0x87, 0x1d, 0x1e, 0x83, 0xb4, 0xcf, 0x95, 0x6c, 0x25, 0xe9, 0x25, 0x6f, 0x1d, 0x0f, 0x01, 0x74, 0x1e, 0x0e, 0xe9, 0x35, 0x6f, 0x41, 0x3d, 0x27, 0x59, 0x24, 0x09, 0x01, 0x61, 0x10, 0x9d, 0x85, 0xa3, 0x54, 0x02, 0x2a, 0x0d, 0x16, 0x12, 0x10, 0x27, 0x01, 0x27, 0x47, 0x2b, 0x2d, 0x0d, 0x0b, 0x0c, 0x06, 0x25, 0x5f, 0x6b, 0x6a, 0x7e, 0x07, 0x1d, 0x72, 0x8d, 0x7d, 0x6a, 0x4c, 0x60, 0xd0, 0x86, 0x7c, 0xef, 0x5c, 0x67, 0xc3, 0x4b, 0x1a, 0x40, 0x2f, 0x1e, 0x14, 0x03, 0x2e, 0x38, 0x35, 0x96, 0x63, 0x28, 0x24, 0x00, 0x00, 0x00, 0x07, 0x00, 0xa3, 0x00, 0x9a, 0x05, 0x37, 0x05, 0xaf, 0x00, 0x13, 0x00, 0x19, 0x00, 0x20, 0x00, 0x28, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x35, 0x34, 0x2f, 0x01, 0x06, 0x23, 0x14, 0x07, 0x06, 0x23, 0x14, 0x07, 0x17, 0x16, 0x33, 0x32, 0x36, 0x01, 0x3f, 0x01, 0x0f, 0x02, 0x13, 0x37, 0x01, 0x13, 0x25, 0x01, 0x13, 0x05, 0x01, 0x33, 0x32, 0x35, 0x34, 0x27, 0x01, 0x00, 0x36, 0x35, 0x34, 0x27, 0x01, 0x07, 0x01, 0x16, 0x33, 0x01, 0x3e, 0x01, 0x37, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x3e, 0x01, 0x17, 0x07, 0x01, 0x16, 0x33, 0x32, 0x27, 0x04, 0xa1, 0x07, 0x0b, 0x01, 0x36, 0x14, 0x1b, 0x31, 0x30, 0x42, 0x14, 0xd5, 0x07, 0x07, 0x09, 0x17, 0xfc, 0xda, 0x89, 0x0c, 0x83, 0x8a, 0x0c, 0x76, 0xef, 0x02, 0x3d, 0xa6, 0xfd, 0xa9, 0xfd, 0xc4, 0x0f, 0x01, 0x91, 0x01, 0xd8, 0x02, 0x39, 0x02, 0xfd, 0xfb, 0x01, 0x7a, 0x31, 0x06, 0xfe, 0x2f, 0x66, 0x01, 0xd2, 0x0f, 0x0d, 0xfd, 0xb0, 0x0c, 0x1c, 0x0e, 0x0c, 0x09, 0x0d, 0x0f, 0x05, 0x05, 0x11, 0x0d, 0x0c, 0x1a, 0x10, 0x0c, 0x08, 0x0d, 0x0e, 0x03, 0x05, 0x12, 0x28, 0x72, 0x02, 0x04, 0x0a, 0x09, 0x34, 0x01, 0x01, 0x40, 0x08, 0x1c, 0x0a, 0x05, 0x08, 0xee, 0x17, 0x48, 0x36, 0x37, 0x1c, 0x18, 0x3b, 0x02, 0x0b, 0x02, 0xf9, 0x98, 0x92, 0x0d, 0x98, 0x92, 0x01, 0x7a, 0x12, 0xfd, 0x83, 0xfd, 0x68, 0xb8, 0x02, 0x7c, 0x01, 0x09, 0x14, 0xfd, 0xf3, 0x38, 0x0a, 0x0c, 0x02, 0x3e, 0xfc, 0xb6, 0x36, 0x21, 0x0f, 0x11, 0x02, 0x06, 0x71, 0xfd, 0xfa, 0x06, 0x02, 0xea, 0x0d, 0x15, 0x05, 0x04, 0x11, 0x0d, 0x0a, 0x0e, 0x10, 0x1f, 0x0d, 0x0e, 0x14, 0x05, 0x04, 0x0e, 0x10, 0x0b, 0x0d, 0x10, 0x1e, 0xf4, 0x0e, 0xfd, 0xc2, 0x02, 0x42, 0x00, 0x00, 0x07, 0x00, 0x2f, 0x01, 0x96, 0x05, 0xe7, 0x04, 0x3e, 0x00, 0x11, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x25, 0x00, 0x2b, 0x00, 0x3f, 0x00, 0x46, 0x00, 0x00, 0x00, 0x34, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x14, 0x07, 0x16, 0x14, 0x07, 0x16, 0x15, 0x37, 0x36, 0x37, 0x36, 0x05, 0x35, 0x27, 0x07, 0x15, 0x17, 0x03, 0x37, 0x21, 0x09, 0x01, 0x21, 0x27, 0x01, 0x21, 0x36, 0x35, 0x34, 0x27, 0x21, 0x00, 0x34, 0x27, 0x21, 0x15, 0x21, 0x24, 0x34, 0x36, 0x37, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x17, 0x07, 0x21, 0x36, 0x35, 0x34, 0x27, 0x05, 0x13, 0x07, 0x06, 0x04, 0x09, 0xbd, 0x13, 0x2e, 0x2e, 0x13, 0xbd, 0x09, 0x04, 0x06, 0xfc, 0x16, 0x55, 0x54, 0x54, 0x9d, 0x9d, 0x02, 0xfd, 0x02, 0x1c, 0xfd, 0xe4, 0xfd, 0x03, 0x9d, 0x01, 0x28, 0x02, 0x6f, 0x16, 0x1f, 0xfd, 0x52, 0x02, 0xf6, 0x2d, 0xfd, 0x9a, 0x02, 0x66, 0xfc, 0xc7, 0x06, 0x08, 0x06, 0x10, 0x12, 0x10, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07, 0x10, 0x12, 0x10, 0x06, 0x08, 0xb2, 0x48, 0x02, 0xae, 0x1f, 0x16, 0x02, 0xde, 0x18, 0x15, 0x09, 0x07, 0x06, 0x7e, 0x21, 0x14, 0x38, 0x90, 0x38, 0x14, 0x21, 0x7e, 0x06, 0x07, 0x09, 0x4b, 0xd8, 0x70, 0x70, 0xd8, 0x70, 0x01, 0x68, 0xc8, 0xfe, 0xac, 0xfe, 0xac, 0xc8, 0x01, 0x2c, 0x19, 0x17, 0x1b, 0x19, 0xfe, 0xc4, 0x70, 0x18, 0xa0, 0x3c, 0x28, 0x23, 0x0f, 0x0e, 0x10, 0x10, 0x0e, 0x0f, 0x23, 0x28, 0x23, 0x0f, 0x0e, 0x10, 0x10, 0x0e, 0x0f, 0x69, 0x64, 0x19, 0x1b, 0x17, 0x19, 0x00, 0x07, 0x00, 0xa3, 0x00, 0x9a, 0x05, 0x37, 0x05, 0xaf, 0x00, 0x13, 0x00, 0x19, 0x00, 0x20, 0x00, 0x28, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x0f, 0x01, 0x16, 0x15, 0x32, 0x17, 0x16, 0x15, 0x32, 0x17, 0x37, 0x36, 0x35, 0x34, 0x26, 0x01, 0x27, 0x1f, 0x02, 0x27, 0x07, 0x27, 0x03, 0x01, 0x25, 0x03, 0x01, 0x27, 0x17, 0x01, 0x36, 0x35, 0x34, 0x2b, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x01, 0x17, 0x01, 0x36, 0x35, 0x01, 0x2e, 0x01, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x17, 0x1e, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x27, 0x2e, 0x01, 0x13, 0x01, 0x36, 0x23, 0x22, 0x07, 0x01, 0x04, 0xa1, 0x08, 0x17, 0x09, 0x07, 0x07, 0xd5, 0x14, 0x42, 0x30, 0x31, 0x1b, 0x14, 0x36, 0x01, 0x0b, 0xfc, 0xcb, 0x84, 0x0c, 0x8a, 0x83, 0x0c, 0x97, 0xb2, 0x0f, 0x02, 0x3c, 0x02, 0x57, 0xa6, 0xfd, 0xc3, 0x10, 0x0c, 0x02, 0x05, 0x02, 0x39, 0x02, 0x21, 0x31, 0x1e, 0x0d, 0x0f, 0xfe, 0x2e, 0x66, 0x01, 0xd1, 0x06, 0xfd, 0x61, 0x0c, 0x12, 0x05, 0x03, 0x0e, 0x0d, 0x08, 0x0c, 0x10, 0x1a, 0x0c, 0x0d, 0x11, 0x05, 0x05, 0x0f, 0x0d, 0x09, 0x0c, 0x0e, 0x1c, 0x10, 0x01, 0xd8, 0x01, 0x34, 0x09, 0x0a, 0xfd, 0xfc, 0x05, 0x09, 0x09, 0x0b, 0x02, 0x3b, 0x18, 0x1c, 0x37, 0x36, 0x48, 0x17, 0xee, 0x08, 0x05, 0x0a, 0x1c, 0xfd, 0x18, 0x0d, 0x92, 0x98, 0x0d, 0x92, 0xd5, 0xc6, 0x01, 0x09, 0x02, 0x7c, 0xb8, 0xfd, 0x68, 0xfd, 0x83, 0xec, 0x7f, 0x02, 0x3e, 0x0c, 0x0a, 0x38, 0x88, 0x36, 0x06, 0xfd, 0xfa, 0x71, 0x02, 0x06, 0x11, 0x0f, 0xfd, 0x6d, 0x0e, 0x1e, 0x10, 0x0d, 0x0b, 0x10, 0x0e, 0x04, 0x05, 0x14, 0x0e, 0x0d, 0x1f, 0x10, 0x0e, 0x0a, 0x0d, 0x11, 0x04, 0x05, 0x15, 0x01, 0x0f, 0x02, 0x0c, 0x42, 0x02, 0xfd, 0xc2, 0x00, 0x02, 0x00, 0x4f, 0x01, 0x7b, 0x05, 0x73, 0x04, 0x5b, 0x00, 0x25, 0x00, 0x47, 0x00, 0x00, 0x12, 0x10, 0x27, 0x32, 0x33, 0x20, 0x25, 0x01, 0x15, 0x25, 0x2e, 0x01, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x3e, 0x01, 0x37, 0x25, 0x15, 0x01, 0x24, 0x21, 0x22, 0x23, 0x12, 0x14, 0x07, 0x32, 0x33, 0x32, 0x05, 0x25, 0x05, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x05, 0x25, 0x04, 0x23, 0x22, 0x23, 0x7c, 0x2d, 0x07, 0x07, 0x01, 0x07, 0x01, 0xe2, 0x02, 0x2d, 0xfd, 0xf9, 0x05, 0x0c, 0x11, 0x0b, 0x1b, 0x0c, 0x0d, 0x09, 0x0a, 0x0a, 0x0c, 0x08, 0x09, 0x0d, 0x0c, 0x1b, 0x0b, 0x11, 0x0c, 0x05, 0x02, 0x07, 0xfd, 0xd3, 0xfe, 0x1e, 0xfe, 0xf9, 0x07, 0x07, 0x8a, 0x15, 0x04, 0x04, 0xa0, 0x01, 0xda, 0x01, 0x8b, 0xfe, 0xc0, 0x14, 0x19, 0x17, 0x38, 0x17, 0x18, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x18, 0x17, 0x38, 0x17, 0x19, 0x14, 0x01, 0x40, 0xfe, 0x75, 0xfe, 0x26, 0xa0, 0x04, 0x04, 0x02, 0x49, 0x01, 0x44, 0x60, 0x6e, 0xfe, 0xed, 0x53, 0x1c, 0x08, 0x10, 0x08, 0x06, 0x06, 0x06, 0x0a, 0x09, 0x1d, 0x20, 0x1f, 0x07, 0x0a, 0x06, 0x06, 0x06, 0x08, 0x10, 0x08, 0x1c, 0x53, 0xfe, 0xed, 0x6e, 0x01, 0x47, 0x8a, 0x59, 0x6e, 0xb9, 0x18, 0x15, 0x0c, 0x0b, 0x0b, 0x0c, 0x15, 0x17, 0x35, 0x3e, 0x35, 0x17, 0x15, 0x0c, 0x0b, 0x0b, 0x0c, 0x15, 0x18, 0xb9, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7c, 0x01, 0xad, 0x05, 0x73, 0x04, 0x29, 0x00, 0x28, 0x00, 0x00, 0x01, 0x25, 0x15, 0x01, 0x24, 0x23, 0x22, 0x23, 0x36, 0x34, 0x27, 0x32, 0x33, 0x32, 0x25, 0x01, 0x15, 0x25, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x36, 0x03, 0x84, 0x01, 0xef, 0xfd, 0xd3, 0xfe, 0x21, 0xdf, 0x06, 0x06, 0x2d, 0x2d, 0x06, 0x06, 0xdf, 0x01, 0xdf, 0x02, 0x2d, 0xfe, 0x11, 0x06, 0x0e, 0x0c, 0x11, 0x0f, 0x26, 0x0f, 0x10, 0x0d, 0x0d, 0x0e, 0x0e, 0x0d, 0x0d, 0x10, 0x0f, 0x26, 0x0f, 0x11, 0x0c, 0x0e, 0x02, 0xc5, 0x1c, 0x21, 0xfe, 0xed, 0x6e, 0x60, 0xe0, 0x60, 0x6e, 0xfe, 0xed, 0x21, 0x1d, 0x11, 0x0f, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x0f, 0x23, 0x15, 0x14, 0x23, 0x0f, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x01, 0x14, 0x00, 0xc6, 0x04, 0xcf, 0x05, 0x0a, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x12, 0x13, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x00, 0x01, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x01, 0x98, 0x23, 0x12, 0x24, 0x0f, 0x0c, 0x0c, 0xfd, 0xd7, 0x38, 0x7a, 0x1c, 0x14, 0x1d, 0xfe, 0xa4, 0xfe, 0xd7, 0x14, 0x40, 0x41, 0x0c, 0x1f, 0x29, 0x2f, 0x3f, 0x27, 0x02, 0x8e, 0x40, 0x78, 0x14, 0x01, 0xc2, 0x01, 0x16, 0x48, 0x0c, 0x09, 0x0e, 0x29, 0xfe, 0x30, 0xfd, 0xfc, 0x24, 0x06, 0x0f, 0x8a, 0x99, 0x27, 0x2a, 0x27, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd5, 0x00, 0xb2, 0x05, 0x32, 0x05, 0x0c, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x33, 0x32, 0x37, 0x12, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x00, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x01, 0x98, 0x23, 0x12, 0x24, 0x0f, 0x0c, 0x0c, 0xfd, 0xd7, 0x5b, 0x57, 0x72, 0x17, 0x0a, 0x14, 0xfd, 0xbd, 0x6f, 0x26, 0x88, 0x2d, 0x32, 0x15, 0x33, 0x41, 0x3f, 0x57, 0x2b, 0x03, 0x1a, 0x40, 0x78, 0x14, 0x01, 0x9d, 0xaf, 0x4a, 0x08, 0x03, 0x16, 0x12, 0x1b, 0xfd, 0x1e, 0xde, 0x4c, 0x1a, 0x0c, 0x8d, 0xb2, 0x86, 0x31, 0x20, 0x2c, 0x00, 0x01, 0x00, 0xe9, 0x00, 0x94, 0x05, 0x20, 0x05, 0x41, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x01, 0x07, 0x09, 0x01, 0x27, 0x09, 0x01, 0x37, 0x09, 0x01, 0x17, 0x03, 0x83, 0x01, 0x9b, 0x7f, 0xfe, 0x65, 0xfe, 0x65, 0x80, 0x01, 0x9b, 0xfe, 0x65, 0x80, 0x01, 0x9b, 0x01, 0x9c, 0x7f, 0x02, 0xea, 0xfe, 0x37, 0x8d, 0x01, 0xc9, 0xfe, 0x37, 0x8d, 0x01, 0xc9, 0x01, 0xc9, 0x8d, 0xfe, 0x38, 0x01, 0xc9, 0x8d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9d, 0x00, 0x3f, 0x05, 0x6b, 0x05, 0x96, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x0b, 0x04, 0x1c, 0x01, 0x4f, 0xfe, 0xe8, 0xfe, 0xb1, 0xfe, 0xb1, 0xfe, 0xe9, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0x17, 0x01, 0x4f, 0x01, 0x4f, 0x01, 0x18, 0x02, 0xea, 0xfe, 0x8c, 0xfe, 0xc9, 0x01, 0x74, 0xfe, 0x8c, 0x01, 0x37, 0x01, 0x74, 0x01, 0x74, 0x01, 0x37, 0xfe, 0x8c, 0x01, 0x75, 0xfe, 0xc9, 0x00, 0x01, 0x00, 0xd8, 0xff, 0xee, 0x05, 0x0d, 0x05, 0xdc, 0x00, 0x42, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x03, 0x16, 0x17, 0x16, 0x15, 0x14, 0x0f, 0x01, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x03, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x12, 0x13, 0x02, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x04, 0x79, 0x09, 0x0e, 0x10, 0x10, 0x1a, 0x0f, 0x0e, 0x17, 0x0e, 0x13, 0xbc, 0xb0, 0x49, 0x81, 0x0a, 0x1b, 0x1c, 0x03, 0x14, 0x17, 0x0b, 0x17, 0x12, 0x6c, 0x73, 0x9b, 0xc8, 0x1d, 0x44, 0x21, 0x03, 0x2e, 0x0a, 0x04, 0x19, 0xb7, 0xcd, 0x6d, 0x24, 0x09, 0x11, 0x11, 0x0e, 0x0e, 0x14, 0x08, 0x0c, 0x10, 0x1a, 0x1c, 0x09, 0x31, 0x4f, 0x80, 0xb8, 0x15, 0x05, 0xdc, 0x10, 0x10, 0x1a, 0x33, 0x1b, 0x11, 0x15, 0x1b, 0x17, 0xe2, 0xfe, 0xf1, 0xc6, 0xef, 0x14, 0x0c, 0x17, 0x19, 0x16, 0x0c, 0x14, 0x1e, 0x10, 0x12, 0x1a, 0x9a, 0xd0, 0xe0, 0xfe, 0x8a, 0x36, 0x2a, 0x1c, 0x3d, 0x50, 0x1f, 0x0e, 0x2a, 0x01, 0x3e, 0x01, 0x0a, 0x01, 0x22, 0x9d, 0x23, 0x0a, 0x0e, 0x1a, 0x1a, 0x1d, 0x11, 0x0c, 0x10, 0x1e, 0xa8, 0x98, 0xb8, 0xcc, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe2, 0x00, 0x00, 0x05, 0x6e, 0x05, 0xea, 0x00, 0x52, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x36, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x03, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x02, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x27, 0x26, 0x27, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x26, 0x03, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x12, 0x37, 0x36, 0x04, 0xcc, 0x1a, 0x18, 0x12, 0x07, 0x18, 0x09, 0x1c, 0x0d, 0x0d, 0x0f, 0xd9, 0xd3, 0x85, 0x85, 0x0f, 0x1a, 0x12, 0x22, 0x02, 0x0c, 0x16, 0x1d, 0x20, 0x1b, 0x07, 0x0d, 0x20, 0x18, 0x15, 0x18, 0x50, 0x6d, 0xcf, 0x4f, 0x0f, 0x13, 0x02, 0x10, 0x0f, 0x0e, 0x02, 0x12, 0x10, 0x16, 0x1a, 0x21, 0x1b, 0x08, 0x08, 0x10, 0x15, 0x75, 0xb1, 0x6e, 0x59, 0x14, 0x15, 0x0e, 0x14, 0x17, 0x2c, 0x01, 0x09, 0x15, 0x0f, 0x27, 0x0c, 0x5f, 0x87, 0xd0, 0xe0, 0x0b, 0x05, 0xea, 0x1e, 0x16, 0x3a, 0x01, 0x05, 0x0c, 0x0e, 0x0d, 0x15, 0x28, 0x10, 0xdb, 0xfe, 0xc7, 0xcc, 0xa2, 0x12, 0x18, 0x31, 0x1a, 0x11, 0x02, 0x11, 0x23, 0x3a, 0x18, 0x12, 0x0b, 0x1b, 0x1c, 0x5f, 0xbf, 0xfe, 0xfb, 0x87, 0x1a, 0x24, 0x1f, 0x0d, 0x0c, 0x1e, 0x23, 0x11, 0x1b, 0x2d, 0x03, 0x0d, 0x18, 0x18, 0x15, 0x1f, 0xb0, 0xd4, 0xbd, 0x01, 0x0b, 0x3d, 0x1c, 0x1a, 0x31, 0x20, 0x27, 0x0e, 0x19, 0x32, 0x1a, 0xc4, 0xba, 0x01, 0x08, 0xda, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x00, 0x05, 0xa4, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x03, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x03, 0xca, 0xfe, 0x74, 0xfe, 0x81, 0x01, 0x7f, 0x01, 0x8c, 0x01, 0x80, 0xfe, 0xc8, 0x01, 0x92, 0xfe, 0x6e, 0xfd, 0xe4, 0xfe, 0x6f, 0x01, 0x91, 0x02, 0x1c, 0xb4, 0x01, 0x92, 0xfe, 0x6e, 0xb4, 0xfe, 0x6f, 0x01, 0x91, 0xb4, 0x03, 0xc6, 0x01, 0xab, 0xfe, 0x55, 0xfe, 0x48, 0xfe, 0x56, 0x01, 0xaa, 0x01, 0xb8, 0x50, 0xfd, 0xa8, 0xfe, 0x42, 0x01, 0xbe, 0x02, 0x58, 0x01, 0xbf, 0xfd, 0x79, 0xc8, 0xfe, 0x42, 0x01, 0xbe, 0xc8, 0x01, 0xbf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x00, 0x05, 0xa4, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x03, 0xb8, 0x01, 0xec, 0xfe, 0x14, 0xfe, 0x98, 0xfe, 0x15, 0x01, 0xeb, 0x01, 0x68, 0x03, 0xb2, 0xfe, 0x70, 0xfd, 0xde, 0x02, 0x22, 0x01, 0x90, 0x02, 0x23, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x05, 0xa4, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x33, 0x35, 0x23, 0x37, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x02, 0x99, 0xd6, 0xd6, 0xd7, 0x02, 0x34, 0xfd, 0xcc, 0xd8, 0xfd, 0xcd, 0x02, 0x33, 0xd8, 0x02, 0x73, 0xee, 0x01, 0xf0, 0xfd, 0x8e, 0x02, 0x72, 0xf0, 0x02, 0x73, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x05, 0xa4, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x25, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x02, 0x51, 0x01, 0x66, 0xfe, 0x9a, 0x01, 0x67, 0x01, 0xec, 0xfe, 0x14, 0xfe, 0x98, 0xfe, 0x15, 0x01, 0xeb, 0x01, 0x68, 0x02, 0x23, 0x01, 0x8e, 0x01, 0xfe, 0x70, 0xfd, 0xde, 0x02, 0x22, 0x01, 0x90, 0x02, 0x23, 0x00, 0x00, 0x01, 0x01, 0x30, 0x00, 0x00, 0x04, 0xd9, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x03, 0x70, 0x01, 0x68, 0xfe, 0x98, 0xd8, 0xfe, 0x98, 0x01, 0x68, 0xd8, 0x04, 0x45, 0xf0, 0xfc, 0xab, 0x03, 0x55, 0xf0, 0x01, 0x90, 0x00, 0x02, 0x00, 0xf1, 0x00, 0x00, 0x04, 0xe2, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x33, 0x17, 0x11, 0x21, 0x11, 0x21, 0x27, 0x11, 0x23, 0x27, 0x11, 0x21, 0x11, 0x21, 0x17, 0x07, 0x11, 0x23, 0x11, 0x21, 0x15, 0x21, 0x11, 0x33, 0x11, 0x21, 0x35, 0x03, 0xd3, 0x87, 0x87, 0xfe, 0xf2, 0xfe, 0xb3, 0x87, 0x87, 0x87, 0x01, 0x0e, 0x01, 0x4d, 0x87, 0xb4, 0xc6, 0xfe, 0xf2, 0x01, 0x0e, 0xc6, 0x01, 0x0e, 0x04, 0xa9, 0x96, 0xfe, 0x8e, 0xfd, 0x5f, 0x96, 0x02, 0x0b, 0x96, 0x01, 0x72, 0x01, 0x2c, 0x96, 0xfa, 0x01, 0x2c, 0xfe, 0xd4, 0xdc, 0xfd, 0x5f, 0x02, 0xa1, 0xdc, 0x00, 0x03, 0x01, 0x1e, 0x00, 0x00, 0x04, 0xeb, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x27, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x03, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x03, 0xa6, 0xfe, 0xbc, 0xfc, 0xfc, 0x01, 0x44, 0xfc, 0xb4, 0xfc, 0xfc, 0xfe, 0x2c, 0xfc, 0xfc, 0x01, 0xd4, 0x90, 0xfc, 0xfc, 0xb4, 0xfc, 0xfc, 0xb4, 0x04, 0x6d, 0x01, 0x18, 0xfe, 0xe8, 0xfe, 0x84, 0xfd, 0x5f, 0x02, 0xa1, 0x01, 0x7c, 0x50, 0xfd, 0xe4, 0xfd, 0x5f, 0x02, 0xa1, 0x02, 0x1c, 0x01, 0x18, 0xfe, 0x48, 0xdc, 0xfd, 0x5f, 0x02, 0xa1, 0xdc, 0x01, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x00, 0x05, 0xa4, 0x05, 0xd5, 0x00, 0x4b, 0x00, 0x00, 0x01, 0x23, 0x22, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x07, 0x11, 0x17, 0x16, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x27, 0x21, 0x07, 0x06, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x1d, 0x01, 0x33, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x37, 0x11, 0x27, 0x26, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x2b, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x17, 0x21, 0x37, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x02, 0xc1, 0x6f, 0x5a, 0xa1, 0x42, 0x3b, 0x28, 0x20, 0x2d, 0x16, 0x17, 0x20, 0x26, 0x3d, 0x3e, 0xa1, 0x5e, 0x6f, 0x45, 0x40, 0x3c, 0x55, 0x4a, 0x19, 0x48, 0x04, 0x09, 0x31, 0x30, 0x4a, 0x56, 0x3c, 0x42, 0x42, 0x6e, 0x5e, 0xa1, 0x3e, 0x3d, 0x26, 0x21, 0x2d, 0x17, 0x16, 0x21, 0x27, 0x3c, 0x3f, 0xa4, 0x5a, 0x6e, 0x44, 0x40, 0x3c, 0x56, 0x4a, 0x18, 0x49, 0xfb, 0xf7, 0x30, 0x31, 0x4a, 0x55, 0x3c, 0x42, 0x43, 0x02, 0xa0, 0x4b, 0x49, 0x42, 0x60, 0x4f, 0x1b, 0x54, 0x04, 0x7c, 0x38, 0x37, 0x4f, 0x5c, 0x46, 0x47, 0x4b, 0x7a, 0x64, 0xb6, 0x47, 0x42, 0x2b, 0x25, 0x32, 0x19, 0x19, 0x25, 0x2b, 0x42, 0x49, 0xb4, 0x64, 0x7a, 0x4b, 0x47, 0x46, 0x5c, 0x4f, 0x1b, 0x54, 0xfb, 0x84, 0x38, 0x37, 0x4f, 0x60, 0x42, 0x48, 0x4c, 0x7b, 0x64, 0xb6, 0x47, 0x42, 0x2b, 0x25, 0x32, 0x19, 0x19, 0x25, 0x2b, 0x42, 0x49, 0xb4, 0x64, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xa8, 0xff, 0xe5, 0x05, 0x61, 0x05, 0xf3, 0x00, 0x0b, 0x00, 0x11, 0x00, 0x14, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x1d, 0x00, 0x20, 0x00, 0x23, 0x00, 0x00, 0x01, 0x13, 0x21, 0x03, 0x13, 0x21, 0x0b, 0x01, 0x21, 0x13, 0x03, 0x21, 0x17, 0x03, 0x13, 0x21, 0x13, 0x0b, 0x01, 0x07, 0x33, 0x1f, 0x01, 0x37, 0x03, 0x07, 0x33, 0x05, 0x23, 0x17, 0x03, 0x27, 0x07, 0x13, 0x37, 0x23, 0x03, 0x04, 0xca, 0x01, 0x92, 0xca, 0xca, 0xfe, 0x6e, 0xca, 0xc9, 0xfe, 0x6d, 0xca, 0xca, 0x01, 0x93, 0x34, 0x96, 0x96, 0x01, 0x2b, 0x95, 0x95, 0x96, 0x61, 0xc2, 0x9c, 0x62, 0x61, 0x61, 0x62, 0xc3, 0xfe, 0xa1, 0xc2, 0x61, 0xfd, 0x62, 0x61, 0x61, 0x62, 0xc3, 0x05, 0xf3, 0xfe, 0x7c, 0xfe, 0x7d, 0xfe, 0x7d, 0xfe, 0x7c, 0x01, 0x84, 0x01, 0x83, 0x01, 0x83, 0x64, 0xfe, 0xe1, 0xfe, 0xe0, 0x01, 0x20, 0x01, 0x1f, 0x01, 0x1f, 0xbb, 0x64, 0xbb, 0xbb, 0xfe, 0x7d, 0xbc, 0x63, 0xbc, 0x01, 0x1f, 0xbc, 0xbc, 0x01, 0x84, 0xbb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4b, 0xff, 0xe3, 0x05, 0xbd, 0x05, 0xf0, 0x00, 0x43, 0x00, 0x00, 0x01, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x1d, 0x01, 0x33, 0x32, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x2b, 0x01, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3d, 0x01, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x02, 0xd7, 0x44, 0x28, 0x31, 0x32, 0x6c, 0x33, 0x30, 0x27, 0x45, 0x1d, 0xa7, 0x6e, 0x3f, 0x6a, 0x5a, 0x2c, 0x2b, 0x2b, 0x2c, 0x5a, 0x6a, 0x3f, 0x6e, 0xa7, 0x1d, 0x45, 0x27, 0x30, 0x33, 0x6c, 0x32, 0x31, 0x28, 0x44, 0x1d, 0xa7, 0x6e, 0x3f, 0x6a, 0x5a, 0x2b, 0x2b, 0x2b, 0x2b, 0x5a, 0x6a, 0x3f, 0x6e, 0xa7, 0x03, 0x1c, 0x20, 0xba, 0x7a, 0x46, 0x76, 0x64, 0x30, 0x30, 0x30, 0x30, 0x64, 0x76, 0x46, 0x7a, 0xba, 0x20, 0x4c, 0x2c, 0x36, 0x38, 0x78, 0x38, 0x36, 0x2c, 0x4c, 0x20, 0xbb, 0x79, 0x46, 0x76, 0x64, 0x30, 0x31, 0x31, 0x30, 0x64, 0x76, 0x46, 0x79, 0xbb, 0x20, 0x4c, 0x2c, 0x36, 0x38, 0x78, 0x38, 0x36, 0x2c, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4d, 0xff, 0xe7, 0x05, 0xbb, 0x05, 0xf0, 0x00, 0x83, 0x00, 0x00, 0x01, 0x26, 0x27, 0x23, 0x06, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x33, 0x36, 0x37, 0x36, 0x37, 0x35, 0x26, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x15, 0x16, 0x17, 0x16, 0x17, 0x33, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x23, 0x06, 0x07, 0x06, 0x07, 0x15, 0x16, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x35, 0x26, 0x02, 0xb5, 0x0e, 0x09, 0xbf, 0x02, 0x09, 0x12, 0x1a, 0x1d, 0x4a, 0x29, 0x29, 0x49, 0x1d, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x1d, 0x49, 0x29, 0x29, 0x4a, 0x1d, 0x1e, 0x0e, 0x08, 0x03, 0xbf, 0x09, 0x0e, 0x0f, 0x13, 0x0e, 0x12, 0x26, 0x1b, 0x1e, 0x1e, 0x1e, 0x1e, 0x1d, 0x24, 0x24, 0x53, 0x24, 0x24, 0x1c, 0x1e, 0x1f, 0x1f, 0x1e, 0x1f, 0x21, 0x15, 0x0c, 0x13, 0x0f, 0x0f, 0x09, 0xbf, 0x02, 0x08, 0x0e, 0x1e, 0x1d, 0x4a, 0x29, 0x29, 0x4a, 0x1d, 0x1c, 0x10, 0x0f, 0x0f, 0x10, 0x1c, 0x1d, 0x4a, 0x29, 0x29, 0x4a, 0x1d, 0x1a, 0x12, 0x09, 0x01, 0xbf, 0x09, 0x0f, 0x0f, 0x13, 0x0c, 0x15, 0x21, 0x1f, 0x1e, 0x1f, 0x1f, 0x1e, 0x1c, 0x24, 0x24, 0x53, 0x24, 0x24, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1b, 0x26, 0x12, 0x0e, 0x13, 0x02, 0x93, 0x11, 0x15, 0x10, 0x14, 0x2a, 0x1e, 0x21, 0x22, 0x22, 0x21, 0x20, 0x28, 0x28, 0x5c, 0x28, 0x28, 0x20, 0x21, 0x22, 0x22, 0x21, 0x23, 0x25, 0x17, 0x0d, 0x15, 0x11, 0x10, 0x0a, 0xd5, 0x02, 0x0a, 0x14, 0x1d, 0x20, 0x52, 0x2e, 0x2d, 0x52, 0x20, 0x1f, 0x12, 0x11, 0x11, 0x12, 0x1f, 0x20, 0x52, 0x2d, 0x2e, 0x52, 0x20, 0x22, 0x0f, 0x09, 0x03, 0xd5, 0x0a, 0x10, 0x11, 0x15, 0x0d, 0x17, 0x25, 0x23, 0x21, 0x22, 0x22, 0x21, 0x20, 0x28, 0x28, 0x5c, 0x28, 0x28, 0x20, 0x21, 0x22, 0x22, 0x21, 0x1e, 0x2a, 0x14, 0x10, 0x15, 0x11, 0x10, 0x0a, 0xd4, 0x03, 0x09, 0x0f, 0x22, 0x20, 0x52, 0x2e, 0x2d, 0x52, 0x20, 0x1f, 0x12, 0x11, 0x11, 0x12, 0x1f, 0x20, 0x52, 0x2d, 0x2e, 0x52, 0x20, 0x1d, 0x14, 0x0a, 0x02, 0xd4, 0x0a, 0x00, 0x01, 0x00, 0x4a, 0xff, 0xe3, 0x05, 0xbe, 0x05, 0xf0, 0x00, 0x83, 0x00, 0x00, 0x01, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x22, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x02, 0xd7, 0x27, 0x21, 0x0c, 0x0f, 0x15, 0x09, 0x24, 0x24, 0x25, 0x23, 0x1c, 0x35, 0x29, 0x67, 0x2b, 0x30, 0x21, 0x22, 0x26, 0x26, 0x22, 0x09, 0x18, 0x07, 0x12, 0x25, 0x23, 0x3d, 0x5b, 0x1e, 0x0c, 0x0b, 0x10, 0x09, 0x23, 0x5a, 0x32, 0x34, 0x59, 0x22, 0x20, 0x16, 0x13, 0x13, 0x16, 0x20, 0x22, 0x59, 0x34, 0x32, 0x5a, 0x23, 0x09, 0x10, 0x0b, 0x0c, 0x25, 0x57, 0x3a, 0x2b, 0x1d, 0x0c, 0x0e, 0x17, 0x09, 0x23, 0x25, 0x26, 0x22, 0x21, 0x30, 0x2a, 0x67, 0x2a, 0x31, 0x20, 0x23, 0x25, 0x24, 0x24, 0x09, 0x16, 0x0f, 0x0b, 0x23, 0x25, 0x39, 0x59, 0x23, 0x0c, 0x0b, 0x10, 0x09, 0x22, 0x5a, 0x33, 0x34, 0x58, 0x23, 0x1d, 0x19, 0x13, 0x13, 0x16, 0x20, 0x23, 0x58, 0x34, 0x37, 0x56, 0x22, 0x09, 0x10, 0x05, 0x12, 0x24, 0x58, 0x03, 0x1c, 0x43, 0x63, 0x22, 0x0e, 0x0c, 0x12, 0x0a, 0x26, 0x64, 0x38, 0x3a, 0x62, 0x26, 0x20, 0x1c, 0x16, 0x16, 0x18, 0x24, 0x26, 0x62, 0x3a, 0x3d, 0x5f, 0x26, 0x0a, 0x12, 0x06, 0x14, 0x28, 0x61, 0x3f, 0x2f, 0x21, 0x0d, 0x10, 0x19, 0x0a, 0x27, 0x29, 0x2a, 0x26, 0x24, 0x36, 0x2f, 0x72, 0x2f, 0x36, 0x24, 0x26, 0x2a, 0x29, 0x27, 0x0a, 0x19, 0x10, 0x0d, 0x27, 0x29, 0x44, 0x65, 0x21, 0x0d, 0x0c, 0x12, 0x0a, 0x27, 0x64, 0x38, 0x3a, 0x62, 0x26, 0x24, 0x18, 0x15, 0x15, 0x18, 0x24, 0x26, 0x62, 0x3a, 0x38, 0x64, 0x27, 0x0a, 0x12, 0x0c, 0x0d, 0x29, 0x61, 0x40, 0x29, 0x27, 0x0e, 0x10, 0x18, 0x0a, 0x28, 0x28, 0x2a, 0x26, 0x20, 0x3a, 0x2e, 0x72, 0x30, 0x36, 0x24, 0x26, 0x2a, 0x2a, 0x26, 0x0a, 0x1a, 0x08, 0x14, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4b, 0xff, 0xe5, 0x05, 0xbd, 0x05, 0xf2, 0x01, 0x30, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x11, 0x21, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x21, 0x11, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x17, 0x11, 0x21, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x11, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x03, 0x04, 0x1b, 0x15, 0x18, 0x10, 0x12, 0x0a, 0x09, 0x09, 0x0a, 0x12, 0x0a, 0x12, 0x17, 0x19, 0x1b, 0x16, 0x17, 0x11, 0x12, 0x0a, 0x09, 0x09, 0x0a, 0x24, 0x16, 0x17, 0x1a, 0x1b, 0x15, 0x16, 0x12, 0x0d, 0x09, 0x01, 0x09, 0x0f, 0x0d, 0x11, 0x0a, 0x0a, 0x14, 0x11, 0x12, 0x17, 0x17, 0x19, 0x1a, 0x17, 0x17, 0x12, 0x11, 0x0a, 0x0a, 0x0a, 0x07, 0x08, 0x12, 0x16, 0x17, 0x19, 0x1d, 0x14, 0x17, 0x12, 0x11, 0x0b, 0x09, 0x09, 0x0b, 0x11, 0x14, 0x15, 0x17, 0x1a, 0x19, 0x17, 0x16, 0x12, 0x08, 0x07, 0x0a, 0x14, 0x11, 0x0f, 0x1a, 0x17, 0x1a, 0x16, 0x1a, 0x17, 0x12, 0x11, 0x0a, 0x0a, 0x0a, 0x0a, 0x11, 0x0d, 0x0f, 0xfe, 0xf8, 0x08, 0x0d, 0x0f, 0x1a, 0x15, 0x1b, 0x1a, 0x16, 0x17, 0x11, 0x12, 0x0a, 0x09, 0x09, 0x0a, 0x12, 0x10, 0x18, 0x15, 0x1b, 0x17, 0x19, 0x12, 0x0a, 0x11, 0x0a, 0x0a, 0x0a, 0x0a, 0x12, 0x10, 0x18, 0x15, 0x36, 0x15, 0x18, 0x10, 0x12, 0x0a, 0x0a, 0x0a, 0x0a, 0x11, 0x0a, 0x12, 0x15, 0x1a, 0x1c, 0x14, 0x18, 0x11, 0x12, 0x0a, 0x09, 0x09, 0x0a, 0x12, 0x11, 0x18, 0x15, 0x1b, 0x18, 0x2f, 0x12, 0x0c, 0x08, 0xfe, 0xf9, 0x0f, 0x0c, 0x13, 0x08, 0x0a, 0x0a, 0x09, 0x12, 0x14, 0x15, 0x17, 0x19, 0x1b, 0x16, 0x17, 0x12, 0x11, 0x0b, 0x08, 0x08, 0x08, 0x09, 0x14, 0x15, 0x17, 0x19, 0x1a, 0x17, 0x17, 0x12, 0x11, 0x0a, 0x09, 0x09, 0x0a, 0x11, 0x0f, 0x1a, 0x17, 0x1a, 0x19, 0x17, 0x17, 0x12, 0x09, 0x08, 0x08, 0x08, 0x0b, 0x11, 0x12, 0x17, 0x16, 0x1b, 0x19, 0x17, 0x17, 0x12, 0x12, 0x09, 0x0a, 0x0a, 0x0a, 0x11, 0x0c, 0x0f, 0x01, 0x07, 0x09, 0x0c, 0x12, 0x17, 0x15, 0x1a, 0x1b, 0x15, 0x18, 0x24, 0x09, 0x09, 0x09, 0x09, 0x12, 0x12, 0x18, 0x14, 0x1c, 0x1a, 0x15, 0x12, 0x0a, 0x12, 0x0a, 0x09, 0x09, 0x0a, 0x12, 0x11, 0x18, 0x14, 0x05, 0xf2, 0x0b, 0x0c, 0x12, 0x14, 0x1a, 0x19, 0x1d, 0x1c, 0x19, 0x1a, 0x14, 0x0a, 0x08, 0x0a, 0x0a, 0x0c, 0x12, 0x14, 0x1a, 0x19, 0x1d, 0x1f, 0x17, 0x19, 0x28, 0x0b, 0x0a, 0x0a, 0x0c, 0x13, 0x0d, 0x11, 0xfe, 0xdb, 0x0a, 0x0e, 0x14, 0x19, 0x17, 0x1e, 0x1d, 0x32, 0x14, 0x14, 0x0b, 0x0a, 0x0a, 0x0b, 0x14, 0x13, 0x1a, 0x18, 0x1e, 0x1c, 0x19, 0x14, 0x0b, 0x14, 0x0b, 0x0a, 0x0a, 0x0b, 0x14, 0x12, 0x1b, 0x18, 0x1d, 0x1e, 0x18, 0x1b, 0x12, 0x16, 0x09, 0x0a, 0x0a, 0x0b, 0x14, 0x0b, 0x14, 0x19, 0x1c, 0x1a, 0x36, 0x13, 0x11, 0x0d, 0x0b, 0x0b, 0x0a, 0x14, 0x14, 0x1a, 0x18, 0x1d, 0x1e, 0x17, 0x19, 0x14, 0x0e, 0x0a, 0xfe, 0xda, 0x12, 0x0d, 0x10, 0x0e, 0x0b, 0x0b, 0x0b, 0x13, 0x14, 0x1a, 0x19, 0x1c, 0x1d, 0x19, 0x1a, 0x14, 0x12, 0x0c, 0x0b, 0x0b, 0x08, 0x09, 0x13, 0x1a, 0x19, 0x1c, 0x1d, 0x1a, 0x19, 0x14, 0x13, 0x0c, 0x0a, 0x0a, 0x0c, 0x13, 0x14, 0x19, 0x1a, 0x1d, 0x1c, 0x19, 0x1a, 0x13, 0x09, 0x08, 0x0b, 0x0b, 0x0c, 0x12, 0x14, 0x1a, 0x19, 0x1d, 0x1c, 0x19, 0x1a, 0x14, 0x13, 0x0b, 0x0b, 0x16, 0x13, 0x0d, 0x12, 0x01, 0x25, 0x09, 0x0e, 0x17, 0x16, 0x18, 0x1e, 0x1c, 0x19, 0x1a, 0x13, 0x16, 0x09, 0x0a, 0x0a, 0x0b, 0x14, 0x12, 0x1b, 0x17, 0x1e, 0x1d, 0x19, 0x13, 0x0c, 0x16, 0x09, 0x0a, 0x0a, 0x0b, 0x14, 0x12, 0x1b, 0x17, 0x3c, 0x17, 0x1b, 0x13, 0x11, 0x0d, 0x0b, 0x0b, 0x0a, 0x14, 0x0b, 0x14, 0x18, 0x1d, 0x1e, 0x17, 0x1b, 0x12, 0x14, 0x0b, 0x0b, 0x0b, 0x0b, 0x14, 0x13, 0x1a, 0x18, 0x1d, 0x1e, 0x17, 0x1a, 0x13, 0x0e, 0x0a, 0x01, 0x25, 0x11, 0x0d, 0x13, 0x0c, 0x0a, 0x0a, 0x0b, 0x28, 0x19, 0x1a, 0x1c, 0x19, 0x1d, 0x1a, 0x14, 0x12, 0x0c, 0x0a, 0x0a, 0x08, 0x0a, 0x14, 0x1a, 0x19, 0x1c, 0x1d, 0x19, 0x1a, 0x14, 0x12, 0x0c, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4e, 0xff, 0xe3, 0x05, 0xbc, 0x05, 0xf5, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x32, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x33, 0x22, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x34, 0x02, 0x27, 0x26, 0x27, 0x26, 0x4e, 0x8c, 0x7f, 0x78, 0x68, 0x65, 0x67, 0x63, 0x69, 0x62, 0x7f, 0x7e, 0x8c, 0x8c, 0x7e, 0x7f, 0x62, 0x69, 0x63, 0x67, 0x65, 0x68, 0x78, 0x7f, 0x02, 0xec, 0x3b, 0x38, 0x72, 0x6f, 0x01, 0x14, 0xa1, 0x9d, 0xfe, 0xf0, 0x77, 0x6e, 0x3c, 0x3b, 0x3b, 0x3c, 0x6e, 0x77, 0xfe, 0xf0, 0x9d, 0xa1, 0x01, 0x14, 0x6f, 0x72, 0x38, 0x3b, 0x00, 0x02, 0x00, 0x4e, 0xff, 0xe3, 0x05, 0xbc, 0x05, 0xf5, 0x00, 0x1b, 0x00, 0x37, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x21, 0x32, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x33, 0x22, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x34, 0x02, 0x27, 0x26, 0x27, 0x26, 0x01, 0x41, 0x5b, 0x53, 0x4e, 0x43, 0x42, 0x43, 0x40, 0x45, 0x3f, 0x52, 0x52, 0x5c, 0x5c, 0x52, 0x52, 0x3f, 0x45, 0x40, 0x43, 0x42, 0x43, 0x4e, 0x53, 0xfe, 0xb2, 0x8c, 0x7f, 0x78, 0x68, 0x65, 0x67, 0x63, 0x69, 0x62, 0x7f, 0x7e, 0x8c, 0x8c, 0x7e, 0x7f, 0x62, 0x69, 0x63, 0x67, 0x65, 0x68, 0x78, 0x7f, 0x02, 0xec, 0x26, 0x25, 0x4a, 0x48, 0xb3, 0x69, 0x66, 0xb1, 0x4d, 0x48, 0x27, 0x26, 0x26, 0x27, 0x48, 0x4d, 0xb1, 0x66, 0x69, 0xb3, 0x48, 0x4a, 0x25, 0x26, 0x3b, 0x38, 0x72, 0x6f, 0x01, 0x14, 0xa1, 0x9d, 0xfe, 0xf0, 0x77, 0x6e, 0x3c, 0x3b, 0x3b, 0x3c, 0x6e, 0x77, 0xfe, 0xf0, 0x9d, 0xa1, 0x01, 0x14, 0x6f, 0x72, 0x38, 0x3b, 0x00, 0x02, 0x00, 0x2a, 0xff, 0xec, 0x05, 0xdf, 0x05, 0xf3, 0x00, 0x09, 0x00, 0x13, 0x00, 0x00, 0x13, 0x25, 0x09, 0x01, 0x05, 0x01, 0x13, 0x25, 0x05, 0x13, 0x01, 0x03, 0x21, 0x01, 0x03, 0x09, 0x01, 0x03, 0x01, 0x21, 0x2a, 0x01, 0xd9, 0x01, 0x01, 0x01, 0x02, 0x01, 0xd8, 0xfe, 0xc9, 0x21, 0xfe, 0x3c, 0xfe, 0x3c, 0x22, 0x01, 0xa2, 0xac, 0xfd, 0xd3, 0x01, 0xc2, 0xac, 0x01, 0xc3, 0x01, 0xc3, 0xac, 0x01, 0xc2, 0xfd, 0xd3, 0x03, 0xa5, 0x83, 0x01, 0xcb, 0xfe, 0x35, 0x83, 0xfe, 0x61, 0xfd, 0xe6, 0xca, 0xca, 0x02, 0x1a, 0x03, 0xec, 0xfd, 0xb3, 0xfe, 0x94, 0xfd, 0xb4, 0x01, 0x6c, 0xfe, 0x94, 0x02, 0x4c, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4d, 0xff, 0xe3, 0x05, 0xbb, 0x05, 0xf0, 0x00, 0x09, 0x00, 0x24, 0x00, 0x00, 0x01, 0x03, 0x21, 0x01, 0x03, 0x09, 0x01, 0x03, 0x01, 0x21, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x36, 0x03, 0x04, 0x9b, 0xfe, 0x0b, 0x01, 0x95, 0x9b, 0x01, 0x96, 0x01, 0x96, 0x9b, 0x01, 0x95, 0xfe, 0x0b, 0x9b, 0x8b, 0x80, 0x78, 0x68, 0x65, 0x67, 0x63, 0x69, 0x63, 0x7d, 0x7f, 0xfe, 0xea, 0x80, 0x79, 0x67, 0x65, 0x68, 0x63, 0x6a, 0x61, 0x7f, 0x7e, 0x05, 0xea, 0xfd, 0xee, 0xfe, 0xb8, 0xfd, 0xef, 0x01, 0x48, 0xfe, 0xb8, 0x02, 0x11, 0x01, 0x48, 0x02, 0x18, 0x3b, 0x38, 0x72, 0x6f, 0xfe, 0xec, 0xa1, 0x98, 0xfe, 0xf0, 0x77, 0x70, 0x3a, 0x3b, 0x3b, 0x38, 0x72, 0x6f, 0x01, 0x14, 0x9c, 0x9d, 0x01, 0x10, 0x77, 0x6e, 0x3c, 0x3b, 0x00, 0x02, 0x00, 0x2b, 0xff, 0xed, 0x05, 0xde, 0x05, 0xf2, 0x00, 0x1d, 0x00, 0x27, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x03, 0x13, 0x21, 0x01, 0x13, 0x09, 0x01, 0x13, 0x01, 0x21, 0x03, 0x40, 0x78, 0x33, 0x34, 0x2b, 0x2b, 0x15, 0x15, 0x15, 0x15, 0x2b, 0x2b, 0x34, 0x33, 0x78, 0x34, 0x33, 0x2b, 0x2c, 0x14, 0x16, 0x16, 0x14, 0x2c, 0x2b, 0x33, 0x70, 0xac, 0x02, 0x2d, 0xfe, 0x3e, 0xac, 0xfe, 0x3d, 0xfe, 0x3d, 0xac, 0xfe, 0x3e, 0x02, 0x2d, 0x03, 0xe4, 0x18, 0x1a, 0x2d, 0x32, 0x38, 0x3b, 0x42, 0x41, 0x3b, 0x38, 0x32, 0x2d, 0x1a, 0x18, 0x18, 0x1a, 0x2d, 0x32, 0x38, 0x3b, 0x41, 0x42, 0x3b, 0x38, 0x32, 0x2d, 0x1a, 0x02, 0x26, 0xfd, 0xb3, 0xfe, 0x94, 0xfd, 0xb4, 0x01, 0x6b, 0xfe, 0x95, 0x02, 0x4c, 0x01, 0x6c, 0x00, 0x03, 0x00, 0x2a, 0xff, 0xec, 0x05, 0xdf, 0x05, 0xf3, 0x00, 0x09, 0x00, 0x27, 0x00, 0x31, 0x00, 0x00, 0x13, 0x25, 0x09, 0x01, 0x05, 0x01, 0x13, 0x25, 0x05, 0x13, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x13, 0x03, 0x21, 0x01, 0x03, 0x09, 0x01, 0x03, 0x01, 0x21, 0x2a, 0x01, 0xd9, 0x01, 0x01, 0x01, 0x02, 0x01, 0xd8, 0xfe, 0xc9, 0x21, 0xfe, 0x3c, 0xfe, 0x3c, 0x22, 0x01, 0x66, 0x78, 0x34, 0x33, 0x2b, 0x2c, 0x14, 0x16, 0x16, 0x14, 0x2c, 0x2b, 0x33, 0x34, 0x78, 0x33, 0x34, 0x2b, 0x2b, 0x15, 0x15, 0x15, 0x15, 0x2b, 0x2b, 0x34, 0x6f, 0xac, 0xfd, 0xd3, 0x01, 0xc2, 0xac, 0x01, 0xc3, 0x01, 0xc3, 0xac, 0x01, 0xc2, 0xfd, 0xd3, 0x03, 0xa5, 0x83, 0x01, 0xcb, 0xfe, 0x35, 0x83, 0xfe, 0x61, 0xfd, 0xe6, 0xca, 0xca, 0x02, 0x1a, 0x01, 0xde, 0x18, 0x1a, 0x2d, 0x32, 0x38, 0x3b, 0x42, 0x41, 0x3b, 0x38, 0x32, 0x2d, 0x1a, 0x18, 0x18, 0x1a, 0x2d, 0x32, 0x38, 0x3b, 0x41, 0x42, 0x3b, 0x38, 0x32, 0x2d, 0x1a, 0x02, 0x26, 0xfd, 0xb3, 0xfe, 0x94, 0xfd, 0xb4, 0x01, 0x6b, 0xfe, 0x95, 0x02, 0x4c, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x2b, 0xff, 0xed, 0x05, 0xde, 0x05, 0xf2, 0x00, 0x09, 0x00, 0x13, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x13, 0x21, 0x07, 0x13, 0x27, 0x07, 0x13, 0x27, 0x21, 0x13, 0x03, 0x21, 0x01, 0x03, 0x09, 0x01, 0x03, 0x01, 0x21, 0x03, 0x13, 0x21, 0x01, 0x13, 0x09, 0x01, 0x13, 0x01, 0x21, 0x03, 0x04, 0x57, 0x01, 0x16, 0xe1, 0x55, 0xe1, 0xe1, 0x56, 0xe1, 0x01, 0x16, 0x56, 0x80, 0xfe, 0x5d, 0x01, 0x52, 0x81, 0x01, 0x52, 0x01, 0x53, 0x82, 0x01, 0x52, 0xfe, 0x5e, 0x81, 0xac, 0x02, 0x2d, 0xfe, 0x3e, 0xac, 0xfe, 0x3d, 0xfe, 0x3d, 0xac, 0xfe, 0x3e, 0x02, 0x2d, 0x04, 0x49, 0xfe, 0xd9, 0xb6, 0xfe, 0xda, 0xb6, 0xb6, 0x01, 0x26, 0xb6, 0x01, 0xfb, 0xfe, 0x47, 0xfe, 0xef, 0xfe, 0x47, 0x01, 0x11, 0xfe, 0xef, 0x01, 0xb9, 0x01, 0x11, 0x02, 0x8e, 0xfd, 0xb3, 0xfe, 0x94, 0xfd, 0xb4, 0x01, 0x6c, 0xfe, 0x94, 0x02, 0x4c, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x2b, 0xff, 0xed, 0x05, 0xde, 0x05, 0xf2, 0x00, 0x09, 0x00, 0x13, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x17, 0x33, 0x07, 0x17, 0x27, 0x07, 0x37, 0x27, 0x33, 0x1b, 0x01, 0x21, 0x01, 0x13, 0x09, 0x01, 0x13, 0x01, 0x21, 0x37, 0x03, 0x21, 0x05, 0x03, 0x25, 0x05, 0x03, 0x25, 0x21, 0x03, 0x04, 0x22, 0x70, 0x5a, 0x22, 0x5a, 0x5a, 0x22, 0x5a, 0x70, 0x22, 0xac, 0x02, 0x2d, 0xfe, 0x3e, 0xac, 0xfe, 0x3d, 0xfe, 0x3d, 0xac, 0xfe, 0x3e, 0x02, 0x2d, 0xac, 0x67, 0xfe, 0xaf, 0x01, 0x11, 0x69, 0x01, 0x10, 0x01, 0x11, 0x69, 0x01, 0x10, 0xfe, 0xb0, 0x03, 0x49, 0x76, 0x49, 0x76, 0x49, 0x49, 0x76, 0x49, 0x03, 0x1f, 0xfd, 0xb3, 0xfe, 0x94, 0xfd, 0xb4, 0x01, 0x6c, 0xfe, 0x94, 0x02, 0x4c, 0x01, 0x6c, 0xfb, 0xfe, 0x9d, 0xdb, 0xfe, 0x9d, 0xdb, 0xdb, 0x01, 0x63, 0xdb, 0x00, 0x00, 0x06, 0x00, 0x2b, 0xff, 0xed, 0x05, 0xde, 0x05, 0xf2, 0x00, 0x02, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x00, 0x25, 0x01, 0x35, 0x25, 0x01, 0x37, 0x01, 0x03, 0x27, 0x25, 0x21, 0x07, 0x0b, 0x01, 0x17, 0x11, 0x13, 0x21, 0x01, 0x13, 0x09, 0x01, 0x13, 0x01, 0x21, 0x01, 0xb1, 0x01, 0x52, 0xfd, 0xdd, 0x01, 0x52, 0xd1, 0x01, 0x55, 0x82, 0xd1, 0x02, 0x23, 0xfe, 0x5e, 0x81, 0x01, 0x80, 0x80, 0xac, 0x02, 0x2d, 0xfe, 0x3e, 0xac, 0xfe, 0x3d, 0xfe, 0x3d, 0xac, 0xfe, 0x3e, 0x02, 0x2d, 0x99, 0x01, 0x11, 0xf3, 0xc7, 0xfe, 0xef, 0x4b, 0xfd, 0xfb, 0x01, 0xb9, 0x4b, 0xc7, 0xc6, 0x02, 0x80, 0xfe, 0x47, 0xc6, 0x03, 0x53, 0xfd, 0xb3, 0xfe, 0x94, 0xfd, 0xb4, 0x01, 0x6c, 0xfe, 0x94, 0x02, 0x4c, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x2d, 0x00, 0x18, 0x05, 0xdf, 0x05, 0xb7, 0x00, 0x0d, 0x00, 0x17, 0x00, 0x00, 0x09, 0x01, 0x13, 0x27, 0x25, 0x01, 0x27, 0x13, 0x01, 0x21, 0x13, 0x17, 0x13, 0x21, 0x01, 0x03, 0x21, 0x05, 0x03, 0x01, 0x05, 0x03, 0x01, 0x21, 0x05, 0xdf, 0xfe, 0x6b, 0x9b, 0x92, 0xfe, 0xd3, 0xfe, 0x93, 0x92, 0x9b, 0xfe, 0x6b, 0x01, 0xf5, 0x9b, 0x92, 0x8b, 0x01, 0x73, 0xfd, 0x70, 0x79, 0xfe, 0x7b, 0x01, 0x3b, 0x79, 0x01, 0x3c, 0x01, 0x3c, 0x79, 0x01, 0x3b, 0xfe, 0x7b, 0x03, 0x71, 0xfe, 0xb8, 0xfd, 0xef, 0x34, 0xf3, 0xfe, 0xd9, 0x34, 0x02, 0x11, 0x01, 0x48, 0x02, 0x12, 0x34, 0xfe, 0x22, 0x01, 0x68, 0xfe, 0x64, 0xff, 0xfe, 0x64, 0x00, 0xff, 0xff, 0x01, 0x9c, 0x00, 0xff, 0x00, 0x01, 0x00, 0x76, 0x00, 0x00, 0x05, 0x92, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x25, 0x13, 0x0d, 0x01, 0x03, 0x25, 0x11, 0x21, 0x11, 0x05, 0x03, 0x2d, 0x01, 0x13, 0x02, 0x74, 0x01, 0x20, 0x01, 0x6e, 0x90, 0xfe, 0x92, 0x01, 0x6e, 0x90, 0xfe, 0x92, 0xfe, 0xe0, 0xfe, 0x93, 0x90, 0x01, 0x6c, 0xfe, 0x94, 0x90, 0x04, 0x00, 0x01, 0xd5, 0xfe, 0x2a, 0xeb, 0xfe, 0xeb, 0xea, 0xeb, 0xfe, 0xeb, 0xeb, 0xfe, 0x2a, 0x01, 0xd6, 0xeb, 0x01, 0x15, 0xeb, 0xea, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x88, 0x00, 0x00, 0x05, 0x80, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x17, 0x00, 0x00, 0x01, 0x07, 0x17, 0x33, 0x37, 0x27, 0x05, 0x01, 0x37, 0x01, 0x11, 0x33, 0x11, 0x01, 0x17, 0x09, 0x01, 0x07, 0x01, 0x11, 0x23, 0x11, 0x01, 0x27, 0x02, 0x99, 0x6c, 0x6c, 0xd6, 0x6c, 0x6c, 0xfe, 0xbd, 0xfe, 0x5d, 0x6c, 0x01, 0xa3, 0xd8, 0x01, 0xa4, 0x6c, 0xfe, 0x5c, 0x01, 0xa4, 0x6c, 0xfe, 0x5c, 0xd8, 0xfe, 0x5d, 0x6c, 0x03, 0xb9, 0xce, 0xd0, 0xd0, 0xce, 0xce, 0x01, 0x0d, 0xd0, 0xfe, 0xf2, 0x02, 0x1b, 0xfd, 0xe5, 0x01, 0x0e, 0xd0, 0xfe, 0xf3, 0xfe, 0xf2, 0xd0, 0x01, 0x0d, 0xfd, 0xe6, 0x02, 0x1a, 0xfe, 0xf3, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x00, 0x05, 0xa4, 0x05, 0xd5, 0x00, 0x17, 0x00, 0x00, 0x09, 0x01, 0x07, 0x01, 0x11, 0x23, 0x11, 0x01, 0x27, 0x01, 0x21, 0x35, 0x21, 0x01, 0x37, 0x01, 0x11, 0x33, 0x11, 0x01, 0x17, 0x01, 0x21, 0x15, 0x03, 0x72, 0x01, 0x8d, 0x40, 0xfe, 0x72, 0x5a, 0xfe, 0x72, 0x3f, 0x01, 0x8d, 0xfd, 0xce, 0x02, 0x33, 0xfe, 0x72, 0x3f, 0x01, 0x8e, 0x5a, 0x01, 0x8e, 0x40, 0xfe, 0x71, 0x02, 0x34, 0x02, 0xb8, 0xfe, 0x46, 0x47, 0x01, 0xbb, 0xfd, 0x8e, 0x02, 0x71, 0xfe, 0x46, 0x47, 0x01, 0xba, 0x64, 0x01, 0xbb, 0x47, 0xfe, 0x46, 0x02, 0x71, 0xfd, 0x8f, 0x01, 0xba, 0x47, 0xfe, 0x45, 0x64, 0x00, 0x01, 0x00, 0x39, 0xff, 0xe3, 0x05, 0xab, 0x05, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x13, 0x09, 0x01, 0x0d, 0x01, 0x09, 0x01, 0x0b, 0x01, 0x09, 0x01, 0x2d, 0x01, 0x09, 0x01, 0x02, 0xf2, 0x47, 0x01, 0xa5, 0xfe, 0xc1, 0x02, 0x0c, 0xfd, 0xf4, 0x01, 0x3f, 0xfe, 0x5b, 0x47, 0x47, 0xfe, 0x5b, 0x01, 0x3f, 0xfd, 0xf5, 0x02, 0x0b, 0xfe, 0xc1, 0x01, 0xa5, 0x05, 0xf0, 0xfd, 0xb9, 0x01, 0x64, 0xfe, 0x2c, 0x50, 0x4f, 0xfe, 0x2c, 0x01, 0x64, 0xfd, 0xb9, 0x02, 0x47, 0xfe, 0x9c, 0x01, 0xd4, 0x4f, 0x50, 0x01, 0xd4, 0xfe, 0x9c, 0x00, 0x00, 0x09, 0x00, 0x4b, 0xff, 0xe3, 0x05, 0xbd, 0x05, 0xf0, 0x00, 0x02, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x11, 0x00, 0x14, 0x00, 0x17, 0x00, 0x27, 0x00, 0x00, 0x01, 0x05, 0x03, 0x05, 0x25, 0x05, 0x01, 0x03, 0x25, 0x03, 0x13, 0x03, 0x01, 0x25, 0x13, 0x25, 0x05, 0x25, 0x01, 0x13, 0x05, 0x13, 0x03, 0x13, 0x11, 0x13, 0x25, 0x03, 0x0d, 0x01, 0x13, 0x25, 0x0b, 0x01, 0x05, 0x13, 0x2d, 0x01, 0x03, 0x05, 0x04, 0x76, 0xfe, 0xfa, 0x6b, 0x02, 0x0a, 0xfe, 0xf8, 0xfe, 0xfe, 0x01, 0x71, 0x6f, 0xfe, 0xfe, 0x01, 0x6b, 0x6b, 0xfe, 0x8e, 0x01, 0x06, 0x6b, 0xfd, 0xf6, 0x01, 0x08, 0x01, 0x02, 0xfe, 0x8f, 0x6f, 0x01, 0x02, 0x01, 0x6b, 0x6b, 0x8f, 0x01, 0x5d, 0x93, 0x01, 0x60, 0xfe, 0xa0, 0x93, 0xfe, 0xa3, 0x8f, 0x8f, 0xfe, 0xa3, 0x94, 0xfe, 0xa0, 0x01, 0x60, 0x94, 0x01, 0x5d, 0x04, 0x85, 0x7b, 0xfe, 0xe0, 0x01, 0x78, 0x78, 0xfe, 0x65, 0x01, 0x23, 0x77, 0xfd, 0xbc, 0x01, 0x25, 0x01, 0x1f, 0xfe, 0x66, 0x7b, 0x01, 0x1f, 0x01, 0x77, 0x77, 0x01, 0x9c, 0xfe, 0xdd, 0x78, 0x02, 0x45, 0xfe, 0xdb, 0xfe, 0xe0, 0x03, 0x06, 0xfe, 0x79, 0xa4, 0xfe, 0x7c, 0xa0, 0x9f, 0xfe, 0x7c, 0xa4, 0xfe, 0x79, 0x01, 0x87, 0xa4, 0x01, 0x84, 0x9f, 0xa0, 0x01, 0x84, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa8, 0xff, 0xe3, 0x05, 0x61, 0x05, 0xf0, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x13, 0x25, 0x09, 0x01, 0x25, 0x0b, 0x01, 0x05, 0x09, 0x01, 0x05, 0x03, 0x04, 0x65, 0x01, 0xf7, 0xfe, 0x6e, 0x01, 0x92, 0xfe, 0x09, 0x65, 0x65, 0xfe, 0x09, 0x01, 0x93, 0xfe, 0x6d, 0x01, 0xf7, 0x05, 0xf0, 0xfd, 0xbc, 0xc1, 0xfe, 0x7d, 0xfe, 0x7d, 0xc1, 0xfd, 0xbb, 0x02, 0x45, 0xc1, 0x01, 0x83, 0x01, 0x83, 0xc1, 0x00, 0x00, 0x01, 0x00, 0x4b, 0xff, 0xe3, 0x05, 0xbd, 0x05, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x13, 0x01, 0x03, 0x0d, 0x01, 0x13, 0x01, 0x0b, 0x01, 0x01, 0x13, 0x2d, 0x01, 0x03, 0x01, 0x03, 0x04, 0x66, 0x01, 0x86, 0xf5, 0x01, 0xc2, 0xfe, 0x3e, 0xf5, 0xfe, 0x7a, 0x66, 0x66, 0xfe, 0x7a, 0xf6, 0xfe, 0x3e, 0x01, 0xc2, 0xf6, 0x01, 0x86, 0x05, 0xf0, 0xfe, 0x0b, 0x01, 0x12, 0xfe, 0x4e, 0x72, 0x71, 0xfe, 0x4e, 0x01, 0x12, 0xfe, 0x0b, 0x01, 0xf5, 0xfe, 0xee, 0x01, 0xb2, 0x71, 0x72, 0x01, 0xb2, 0xfe, 0xee, 0x00, 0x00, 0x01, 0x00, 0x4b, 0xff, 0xe3, 0x05, 0xbd, 0x05, 0xf0, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x13, 0x25, 0x03, 0x0d, 0x01, 0x13, 0x25, 0x0b, 0x01, 0x05, 0x13, 0x2d, 0x01, 0x03, 0x05, 0x03, 0x04, 0x99, 0x01, 0x53, 0x7b, 0x01, 0x48, 0xfe, 0xb8, 0x7b, 0xfe, 0xad, 0x99, 0x99, 0xfe, 0xad, 0x7b, 0xfe, 0xb9, 0x01, 0x47, 0x7b, 0x01, 0x53, 0x05, 0xf0, 0xfe, 0x94, 0x89, 0xfe, 0x87, 0xab, 0xaa, 0xfe, 0x87, 0x89, 0xfe, 0x94, 0x01, 0x6c, 0x89, 0x01, 0x79, 0xaa, 0xab, 0x01, 0x79, 0x89, 0x00, 0x00, 0x01, 0x00, 0x4b, 0xff, 0xe3, 0x05, 0xbd, 0x05, 0xf0, 0x00, 0x17, 0x00, 0x00, 0x01, 0x13, 0x37, 0x03, 0x25, 0x03, 0x0d, 0x01, 0x13, 0x25, 0x13, 0x27, 0x0b, 0x01, 0x07, 0x13, 0x05, 0x13, 0x2d, 0x01, 0x03, 0x05, 0x03, 0x17, 0x03, 0x04, 0x69, 0xf3, 0x3f, 0x01, 0x3f, 0xd7, 0x01, 0x34, 0xfe, 0xcc, 0xd7, 0xfe, 0xc1, 0x3f, 0xf3, 0x69, 0x68, 0xf4, 0x40, 0xfe, 0xc0, 0xd7, 0xfe, 0xcd, 0x01, 0x33, 0xd7, 0x01, 0x40, 0x40, 0xf4, 0x05, 0xf0, 0xfe, 0xa9, 0xef, 0xfe, 0x9d, 0x47, 0xfe, 0xf1, 0x73, 0x74, 0xfe, 0xf1, 0x47, 0xfe, 0x9d, 0xef, 0xfe, 0xa9, 0x01, 0x57, 0xef, 0x01, 0x63, 0x47, 0x01, 0x0f, 0x74, 0x73, 0x01, 0x0f, 0x47, 0x01, 0x63, 0xef, 0x00, 0x00, 0x01, 0x00, 0x64, 0x00, 0x00, 0x05, 0xa4, 0x05, 0xd5, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x13, 0x17, 0x03, 0x01, 0x17, 0x01, 0x25, 0x17, 0x05, 0x21, 0x15, 0x21, 0x05, 0x07, 0x25, 0x01, 0x07, 0x01, 0x13, 0x07, 0x03, 0x11, 0x23, 0x11, 0x03, 0x27, 0x13, 0x01, 0x27, 0x01, 0x05, 0x27, 0x25, 0x21, 0x35, 0x21, 0x25, 0x37, 0x05, 0x01, 0x37, 0x01, 0x03, 0x37, 0x02, 0xce, 0x6c, 0x99, 0x64, 0x99, 0x01, 0x1b, 0x4c, 0xfe, 0xe5, 0x01, 0x72, 0x2a, 0xfe, 0x8c, 0x01, 0x92, 0xfe, 0x72, 0x01, 0x70, 0x2a, 0xfe, 0x8e, 0x01, 0x1b, 0x4c, 0xfe, 0xe6, 0x98, 0x64, 0x99, 0x6c, 0x99, 0x64, 0x99, 0xfe, 0xe6, 0x4d, 0x01, 0x1b, 0xfe, 0x8e, 0x2a, 0x01, 0x72, 0xfe, 0x71, 0x01, 0x91, 0xfe, 0x8c, 0x2a, 0x01, 0x70, 0xfe, 0xe7, 0x4d, 0x01, 0x19, 0x98, 0x64, 0x04, 0x17, 0x01, 0xbe, 0xfe, 0x45, 0x01, 0x99, 0x2e, 0xfe, 0x66, 0x01, 0x3a, 0x55, 0xfe, 0xc5, 0xab, 0x6f, 0xab, 0x78, 0xaa, 0x6f, 0xac, 0xfe, 0xc4, 0x55, 0x01, 0x39, 0xfe, 0x67, 0x2e, 0x01, 0x98, 0xfe, 0x46, 0x01, 0xbc, 0xfe, 0x66, 0x2e, 0x01, 0x9b, 0xfe, 0xc5, 0x55, 0x01, 0x3a, 0xaa, 0x6f, 0xaa, 0x78, 0xab, 0x6f, 0xa9, 0x01, 0x39, 0x55, 0xfe, 0xc7, 0x01, 0x99, 0x2e, 0x00, 0x00, 0x01, 0x00, 0x96, 0xff, 0xe3, 0x05, 0x73, 0x05, 0xf0, 0x00, 0x9b, 0x00, 0x00, 0x01, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x1d, 0x01, 0x17, 0x16, 0x17, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x23, 0x22, 0x0f, 0x01, 0x16, 0x15, 0x14, 0x07, 0x17, 0x16, 0x33, 0x32, 0x3b, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x06, 0x0f, 0x01, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3d, 0x01, 0x26, 0x27, 0x26, 0x27, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x32, 0x33, 0x32, 0x3f, 0x01, 0x26, 0x35, 0x34, 0x37, 0x27, 0x26, 0x23, 0x22, 0x2b, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x36, 0x37, 0x36, 0x02, 0xd6, 0x43, 0x28, 0x31, 0x32, 0x6c, 0x33, 0x30, 0x27, 0x45, 0x0f, 0x1c, 0x15, 0x09, 0x66, 0x3a, 0x23, 0x3d, 0x36, 0x2e, 0x14, 0x13, 0x40, 0x1b, 0x12, 0x04, 0x0d, 0x4e, 0x38, 0x45, 0x0a, 0x0a, 0x09, 0x76, 0x5a, 0x0b, 0x04, 0x05, 0x0b, 0x5c, 0x75, 0x0a, 0x09, 0x0a, 0x45, 0x38, 0x4e, 0x0d, 0x04, 0x12, 0x1b, 0x40, 0x13, 0x14, 0x2e, 0x36, 0x3d, 0x23, 0x3c, 0x63, 0x0d, 0x18, 0x16, 0x0f, 0x45, 0x27, 0x30, 0x33, 0x6c, 0x32, 0x31, 0x28, 0x45, 0x08, 0x07, 0x1a, 0x15, 0x0d, 0x63, 0x3c, 0x23, 0x3c, 0x36, 0x2f, 0x14, 0x13, 0x40, 0x1b, 0x12, 0x05, 0x0c, 0x4f, 0x38, 0x44, 0x0b, 0x0a, 0x09, 0x76, 0x5a, 0x0b, 0x04, 0x03, 0x0a, 0x5a, 0x76, 0x09, 0x0a, 0x0b, 0x44, 0x38, 0x4f, 0x0c, 0x05, 0x12, 0x1b, 0x40, 0x13, 0x14, 0x2f, 0x36, 0x3c, 0x23, 0x3e, 0x61, 0x0a, 0x18, 0x1a, 0x07, 0x03, 0x94, 0x0c, 0x80, 0x77, 0x46, 0x4e, 0x64, 0x30, 0x31, 0x31, 0x30, 0x64, 0x4e, 0x46, 0x79, 0x7e, 0x0c, 0x06, 0x0e, 0x17, 0x06, 0x44, 0x7a, 0x49, 0x27, 0x23, 0x07, 0x18, 0x34, 0x23, 0x2c, 0x16, 0x18, 0x47, 0x32, 0x24, 0x3a, 0x07, 0x13, 0x14, 0x15, 0x14, 0x07, 0x3b, 0x24, 0x32, 0x47, 0x18, 0x16, 0x2c, 0x23, 0x34, 0x18, 0x07, 0x23, 0x27, 0x49, 0x7e, 0x3f, 0x08, 0x19, 0x09, 0x06, 0x0f, 0x7f, 0x79, 0x46, 0x4e, 0x64, 0x30, 0x31, 0x31, 0x30, 0x64, 0x4e, 0x46, 0x79, 0x7f, 0x0f, 0x03, 0x03, 0x0d, 0x15, 0x08, 0x3f, 0x7e, 0x49, 0x27, 0x23, 0x07, 0x18, 0x34, 0x23, 0x2c, 0x16, 0x18, 0x47, 0x32, 0x24, 0x3a, 0x07, 0x14, 0x16, 0x14, 0x13, 0x07, 0x3a, 0x24, 0x32, 0x47, 0x18, 0x16, 0x2c, 0x23, 0x34, 0x18, 0x07, 0x23, 0x27, 0x49, 0x82, 0x3b, 0x06, 0x19, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x96, 0xff, 0xe3, 0x05, 0x73, 0x05, 0xf0, 0x00, 0x19, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x1d, 0x01, 0x17, 0x16, 0x17, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x22, 0x23, 0x22, 0x0f, 0x01, 0x16, 0x15, 0x14, 0x07, 0x17, 0x16, 0x33, 0x32, 0x3b, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x06, 0x0f, 0x01, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3d, 0x01, 0x26, 0x27, 0x26, 0x27, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x32, 0x33, 0x32, 0x3f, 0x01, 0x26, 0x35, 0x34, 0x37, 0x27, 0x26, 0x23, 0x22, 0x2b, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x36, 0x37, 0x36, 0x03, 0x17, 0x26, 0x0f, 0x10, 0x0d, 0x0d, 0x0e, 0x0e, 0x0d, 0x0d, 0x10, 0x0f, 0x26, 0x0f, 0x11, 0x0c, 0x0e, 0x0d, 0x0d, 0x0e, 0x0c, 0x11, 0x50, 0x43, 0x28, 0x31, 0x32, 0x6c, 0x33, 0x30, 0x27, 0x45, 0x0f, 0x1c, 0x15, 0x09, 0x66, 0x3a, 0x23, 0x3d, 0x36, 0x2e, 0x14, 0x13, 0x40, 0x1b, 0x12, 0x04, 0x0d, 0x4e, 0x38, 0x45, 0x0a, 0x0a, 0x09, 0x76, 0x5a, 0x0b, 0x04, 0x05, 0x0b, 0x5c, 0x75, 0x0a, 0x09, 0x0a, 0x45, 0x38, 0x4e, 0x0d, 0x04, 0x12, 0x1b, 0x40, 0x13, 0x14, 0x2e, 0x36, 0x3d, 0x23, 0x3c, 0x63, 0x0d, 0x18, 0x16, 0x0f, 0x45, 0x27, 0x30, 0x33, 0x6c, 0x32, 0x31, 0x28, 0x45, 0x08, 0x07, 0x1a, 0x15, 0x0d, 0x63, 0x3c, 0x23, 0x3c, 0x36, 0x2f, 0x14, 0x13, 0x40, 0x1b, 0x12, 0x05, 0x0c, 0x4f, 0x38, 0x44, 0x0b, 0x0a, 0x09, 0x76, 0x5a, 0x0b, 0x04, 0x03, 0x0a, 0x5a, 0x76, 0x09, 0x0a, 0x0b, 0x44, 0x38, 0x4f, 0x0c, 0x05, 0x12, 0x1b, 0x40, 0x13, 0x14, 0x2f, 0x36, 0x3c, 0x23, 0x3e, 0x61, 0x0a, 0x18, 0x1a, 0x07, 0x03, 0x50, 0x08, 0x08, 0x0e, 0x0f, 0x23, 0x15, 0x14, 0x23, 0x0f, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x0f, 0x23, 0x14, 0x15, 0x23, 0x0f, 0x0e, 0x08, 0x4c, 0x0c, 0x80, 0x77, 0x46, 0x4e, 0x64, 0x30, 0x31, 0x31, 0x30, 0x64, 0x4e, 0x46, 0x79, 0x7e, 0x0c, 0x06, 0x0e, 0x17, 0x06, 0x44, 0x7a, 0x49, 0x27, 0x23, 0x07, 0x18, 0x34, 0x23, 0x2c, 0x16, 0x18, 0x47, 0x32, 0x24, 0x3a, 0x07, 0x13, 0x14, 0x15, 0x14, 0x07, 0x3b, 0x24, 0x32, 0x47, 0x18, 0x16, 0x2c, 0x23, 0x34, 0x18, 0x07, 0x23, 0x27, 0x49, 0x7e, 0x3f, 0x08, 0x19, 0x09, 0x06, 0x0f, 0x7f, 0x79, 0x46, 0x4e, 0x64, 0x30, 0x31, 0x31, 0x30, 0x64, 0x4e, 0x46, 0x79, 0x7f, 0x0f, 0x03, 0x03, 0x0d, 0x15, 0x08, 0x3f, 0x7e, 0x49, 0x27, 0x23, 0x07, 0x18, 0x34, 0x23, 0x2c, 0x16, 0x18, 0x47, 0x32, 0x24, 0x3a, 0x07, 0x14, 0x16, 0x14, 0x13, 0x07, 0x3a, 0x24, 0x32, 0x47, 0x18, 0x16, 0x2c, 0x23, 0x34, 0x18, 0x07, 0x23, 0x27, 0x49, 0x82, 0x3b, 0x06, 0x19, 0x0b, 0x03, 0x00, 0x01, 0x00, 0x90, 0xff, 0xe3, 0x05, 0x77, 0x05, 0xf0, 0x00, 0x68, 0x00, 0x00, 0x01, 0x17, 0x32, 0x3f, 0x01, 0x27, 0x26, 0x23, 0x07, 0x22, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x35, 0x34, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x16, 0x14, 0x07, 0x06, 0x1d, 0x01, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x23, 0x27, 0x22, 0x0f, 0x01, 0x17, 0x16, 0x33, 0x37, 0x32, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x15, 0x14, 0x17, 0x16, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x3d, 0x01, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x3e, 0x01, 0x01, 0x89, 0x8f, 0x49, 0x1e, 0x2a, 0x2a, 0x1c, 0x4d, 0x87, 0x51, 0x92, 0x10, 0x0a, 0x16, 0x26, 0x63, 0x12, 0x46, 0x8a, 0x27, 0x40, 0x32, 0x2b, 0x5f, 0x3a, 0x31, 0x4a, 0x97, 0x4a, 0x30, 0x39, 0x60, 0x2b, 0x2b, 0x48, 0x2c, 0x84, 0x46, 0x12, 0xa0, 0x0a, 0x11, 0x91, 0x4c, 0x8e, 0x48, 0x20, 0x2b, 0x2b, 0x1c, 0x4e, 0x87, 0x51, 0x91, 0x11, 0x0a, 0x17, 0x28, 0x61, 0x13, 0x47, 0x39, 0x4f, 0x26, 0x40, 0x33, 0x2b, 0x60, 0x39, 0x30, 0x4a, 0x9b, 0x46, 0x31, 0x3a, 0x5f, 0x2b, 0x2e, 0x44, 0x2b, 0x86, 0x46, 0x12, 0xa0, 0x0b, 0x11, 0x91, 0x02, 0xc4, 0x0a, 0x14, 0x1c, 0x1b, 0x12, 0x07, 0x5d, 0x48, 0x2c, 0x60, 0x2c, 0x48, 0x20, 0x06, 0x59, 0x63, 0xa2, 0x21, 0x1c, 0x37, 0x37, 0x99, 0x5c, 0xca, 0x34, 0x4f, 0x4f, 0x34, 0xd0, 0x56, 0x8f, 0x41, 0x37, 0x1c, 0x1c, 0xa7, 0x67, 0x55, 0x06, 0x33, 0x9a, 0x27, 0x2c, 0x48, 0x5e, 0x0a, 0x14, 0x1b, 0x1c, 0x12, 0x07, 0x5d, 0x48, 0x2c, 0x60, 0x2c, 0x4c, 0x1c, 0x06, 0x26, 0x33, 0x63, 0xa2, 0x21, 0x1c, 0x37, 0x37, 0x99, 0x5c, 0xca, 0x34, 0x4f, 0x4f, 0x37, 0xcd, 0x56, 0x8f, 0x41, 0x37, 0x1c, 0x1e, 0xa5, 0x66, 0x56, 0x06, 0x34, 0x9a, 0x26, 0x2c, 0x48, 0x5e, 0x00, 0x04, 0x00, 0x90, 0xff, 0xe3, 0x05, 0x77, 0x05, 0xf0, 0x00, 0x0e, 0x00, 0x99, 0x00, 0xb1, 0x00, 0xc9, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x13, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3d, 0x01, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x3f, 0x01, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x1d, 0x01, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x05, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x25, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x03, 0x04, 0x19, 0x33, 0x21, 0x1b, 0x2c, 0x4c, 0x2c, 0x1b, 0x22, 0x32, 0x97, 0x10, 0x30, 0x5b, 0x1d, 0x21, 0x10, 0x0f, 0x51, 0x3f, 0x52, 0x11, 0x0a, 0x17, 0x27, 0x62, 0x12, 0x13, 0x33, 0x3b, 0x4b, 0x2a, 0x39, 0x43, 0x10, 0x4e, 0x39, 0x30, 0x4a, 0x4c, 0x4f, 0x46, 0x31, 0x3a, 0x4d, 0x10, 0x40, 0x3b, 0x2c, 0x49, 0x3c, 0x32, 0x14, 0x12, 0x63, 0x26, 0x16, 0x0a, 0x10, 0x53, 0x3f, 0x51, 0x0e, 0x10, 0x22, 0x1c, 0x5b, 0x30, 0x10, 0x10, 0x2e, 0x5b, 0x1d, 0x23, 0x10, 0x0e, 0x51, 0x3f, 0x51, 0x12, 0x0b, 0x17, 0x26, 0x63, 0x12, 0x14, 0x32, 0x3c, 0x4a, 0x2b, 0x38, 0x43, 0x10, 0x4d, 0x3a, 0x31, 0x4a, 0x97, 0x4a, 0x30, 0x39, 0x4e, 0x10, 0x40, 0x3c, 0x2c, 0x49, 0x3b, 0x33, 0x13, 0x12, 0x62, 0x27, 0x17, 0x0a, 0x11, 0x52, 0x3f, 0x51, 0x0f, 0x10, 0x22, 0x1e, 0x5b, 0x2e, 0xfe, 0xbc, 0x3d, 0x3a, 0x1b, 0x1a, 0x08, 0x0a, 0x2f, 0x36, 0x35, 0x07, 0x04, 0x0c, 0x13, 0x37, 0x09, 0x0b, 0x1c, 0x27, 0x3f, 0x16, 0x21, 0x01, 0xac, 0x41, 0x20, 0x17, 0x3f, 0x26, 0x1c, 0x0b, 0x09, 0x38, 0x13, 0x0c, 0x05, 0x06, 0x35, 0x36, 0x30, 0x09, 0x08, 0x1a, 0x1b, 0x3b, 0x03, 0xd3, 0x63, 0x4a, 0x32, 0x51, 0x44, 0x1a, 0x2b, 0x2b, 0x1a, 0x44, 0x51, 0x32, 0x4a, 0xfe, 0xb4, 0x0b, 0x20, 0x03, 0x01, 0x28, 0x35, 0x48, 0x2c, 0x27, 0x39, 0x2c, 0x4a, 0x1e, 0x06, 0x26, 0x30, 0x66, 0x89, 0x29, 0x0a, 0x14, 0x54, 0x7c, 0x5c, 0x60, 0x6a, 0x34, 0x4f, 0x4f, 0x37, 0x67, 0x60, 0x5c, 0x7c, 0x54, 0x14, 0x0a, 0x27, 0x8b, 0x67, 0x2f, 0x26, 0x06, 0x20, 0x48, 0x2c, 0x39, 0x27, 0x2c, 0x49, 0x34, 0x28, 0x01, 0x03, 0x20, 0x0b, 0x0b, 0x1f, 0x03, 0x01, 0x28, 0x33, 0x4a, 0x2c, 0x26, 0x39, 0x2d, 0x48, 0x20, 0x06, 0x26, 0x30, 0x66, 0x89, 0x29, 0x0a, 0x14, 0x54, 0x7c, 0x5c, 0x60, 0x6a, 0x34, 0x4f, 0x4f, 0x34, 0x6a, 0x60, 0x5c, 0x7c, 0x54, 0x14, 0x0a, 0x27, 0x8b, 0x67, 0x2f, 0x26, 0x06, 0x1e, 0x4a, 0x2c, 0x39, 0x27, 0x2c, 0x48, 0x35, 0x28, 0x01, 0x03, 0x1f, 0x80, 0x12, 0x04, 0x01, 0x22, 0x22, 0x27, 0x18, 0x15, 0x21, 0x17, 0x24, 0x15, 0x04, 0x19, 0x28, 0x3a, 0x55, 0x4a, 0x4a, 0x55, 0x3a, 0x28, 0x19, 0x04, 0x15, 0x24, 0x17, 0x21, 0x15, 0x18, 0x27, 0x22, 0x22, 0x01, 0x04, 0x00, 0x00, 0x02, 0x00, 0x63, 0x00, 0x00, 0x05, 0xa6, 0x05, 0xad, 0x00, 0x19, 0x00, 0x77, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x27, 0x0e, 0x01, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x03, 0x45, 0x82, 0x37, 0x37, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x2e, 0x37, 0x37, 0x82, 0x37, 0x38, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x38, 0x6c, 0x38, 0x21, 0x32, 0x30, 0x31, 0x31, 0x2b, 0x29, 0x25, 0x27, 0x24, 0x28, 0x21, 0x33, 0x2a, 0x52, 0x18, 0x2b, 0x1e, 0x28, 0x24, 0x28, 0x24, 0x29, 0x2b, 0x2d, 0x6d, 0x2a, 0x33, 0x21, 0x2b, 0x1a, 0x05, 0x04, 0x22, 0x24, 0x29, 0x2b, 0x2d, 0x6d, 0x2a, 0x33, 0x21, 0x29, 0x24, 0x2a, 0x23, 0x22, 0x20, 0x14, 0x4e, 0x2b, 0x34, 0x1f, 0x29, 0x24, 0x28, 0x25, 0x28, 0x2b, 0x2d, 0x35, 0x38, 0x2a, 0x35, 0x25, 0x07, 0x18, 0x28, 0x24, 0x29, 0x2b, 0x2d, 0x35, 0x38, 0x2a, 0x33, 0x21, 0x28, 0x24, 0x18, 0x04, 0x0b, 0x1a, 0x1c, 0x30, 0x36, 0x7b, 0x49, 0x46, 0x7b, 0x36, 0x30, 0x1c, 0x1a, 0x1a, 0x1c, 0x30, 0x36, 0x7b, 0x46, 0x49, 0x7b, 0x36, 0x30, 0x1c, 0x13, 0x35, 0x10, 0x17, 0x17, 0x14, 0x2b, 0x27, 0x67, 0x3e, 0x3a, 0x63, 0x2e, 0x26, 0x19, 0x15, 0x05, 0x17, 0x22, 0x2e, 0x63, 0x3b, 0x3d, 0x67, 0x27, 0x2b, 0x14, 0x15, 0x15, 0x19, 0x26, 0x31, 0x4e, 0x25, 0x26, 0x57, 0x27, 0x2b, 0x14, 0x15, 0x15, 0x19, 0x26, 0x2e, 0x63, 0x3a, 0x3e, 0x6b, 0x23, 0x22, 0x15, 0x04, 0x15, 0x1b, 0x24, 0x2e, 0x63, 0x3a, 0x3e, 0x67, 0x27, 0x2b, 0x14, 0x15, 0x15, 0x19, 0x2c, 0x0e, 0x42, 0x3a, 0x3e, 0x67, 0x27, 0x2b, 0x14, 0x15, 0x15, 0x19, 0x26, 0x2e, 0x63, 0x3b, 0x3d, 0x3f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x63, 0x00, 0x00, 0x05, 0xa6, 0x05, 0xad, 0x00, 0x5c, 0x00, 0x76, 0x00, 0x8d, 0x00, 0xa6, 0x00, 0xbd, 0x00, 0xd6, 0x00, 0x00, 0x25, 0x0e, 0x01, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x02, 0x32, 0x17, 0x16, 0x17, 0x37, 0x36, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x1f, 0x01, 0x36, 0x37, 0x13, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x03, 0x26, 0x35, 0x34, 0x36, 0x37, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x01, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x13, 0x37, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x0f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x03, 0x04, 0x04, 0x1a, 0x2c, 0x21, 0x32, 0x2b, 0x6c, 0x2e, 0x2b, 0x28, 0x25, 0x28, 0x24, 0x29, 0x1d, 0x2c, 0x19, 0x51, 0x2b, 0x32, 0x21, 0x29, 0x24, 0x28, 0x25, 0x2b, 0x28, 0x36, 0x2c, 0x35, 0x2d, 0x22, 0x37, 0x06, 0x18, 0x24, 0x28, 0x22, 0x32, 0x2a, 0x70, 0x2a, 0x33, 0x21, 0x28, 0x24, 0x18, 0x06, 0x38, 0x21, 0x32, 0x30, 0x31, 0x31, 0x2b, 0x29, 0x25, 0x27, 0x24, 0x28, 0x21, 0x33, 0x2a, 0x52, 0x18, 0x2b, 0x1e, 0x28, 0x24, 0x28, 0x24, 0x29, 0x2b, 0x2d, 0x6d, 0x2a, 0x33, 0x21, 0x2b, 0x1a, 0x46, 0x82, 0x37, 0x07, 0x06, 0x0d, 0x0c, 0x17, 0x18, 0x17, 0x1c, 0x1b, 0x41, 0x1b, 0x1d, 0x16, 0x19, 0x16, 0x02, 0x16, 0x06, 0x07, 0x3d, 0x20, 0x1d, 0x3b, 0x2a, 0x1b, 0x18, 0x5d, 0x16, 0x19, 0x16, 0x19, 0x16, 0x1d, 0x1b, 0x41, 0x1b, 0x1d, 0x16, 0x16, 0x03, 0xc0, 0x03, 0x2a, 0x26, 0x6c, 0x07, 0x06, 0x20, 0x1c, 0x20, 0x1b, 0x1d, 0x16, 0x16, 0x19, 0x16, 0x19, 0x16, 0x1d, 0x13, 0x03, 0x02, 0x00, 0x1f, 0x20, 0x15, 0x17, 0x1d, 0x1a, 0x41, 0x1b, 0x1d, 0x17, 0x18, 0x16, 0x19, 0x15, 0x5d, 0x18, 0x1b, 0x2b, 0x3b, 0x1d, 0xdd, 0x48, 0x48, 0x12, 0x1d, 0x17, 0x18, 0x17, 0x1a, 0x15, 0x17, 0x1d, 0x1a, 0x21, 0x1c, 0x1f, 0x07, 0x07, 0x6c, 0x26, 0x2a, 0xf8, 0x25, 0x4e, 0x31, 0x26, 0x19, 0x15, 0x15, 0x14, 0x2b, 0x27, 0x67, 0x3d, 0x3b, 0x63, 0x2e, 0x22, 0x17, 0x05, 0x15, 0x19, 0x26, 0x2e, 0x63, 0x3a, 0x3e, 0x67, 0x27, 0x2e, 0x11, 0x17, 0x17, 0x10, 0x35, 0x0d, 0x3f, 0x3d, 0x3b, 0x63, 0x2e, 0x26, 0x19, 0x15, 0x15, 0x19, 0x26, 0x2e, 0x63, 0x3b, 0x3d, 0x3f, 0x0d, 0x35, 0x10, 0x17, 0x17, 0x14, 0x2b, 0x27, 0x67, 0x3e, 0x3a, 0x63, 0x2e, 0x26, 0x19, 0x15, 0x05, 0x17, 0x22, 0x2e, 0x63, 0x3b, 0x3d, 0x67, 0x27, 0x2b, 0x14, 0x15, 0x15, 0x19, 0x26, 0x31, 0x4e, 0x03, 0x38, 0x1a, 0x03, 0x04, 0x47, 0x47, 0x14, 0x24, 0x3e, 0x1b, 0x18, 0x0e, 0x0d, 0x0d, 0x0e, 0x18, 0x1b, 0x3e, 0x24, 0x14, 0x0c, 0x82, 0x04, 0x03, 0xfd, 0x63, 0x06, 0x0e, 0x1e, 0x2e, 0x1e, 0x2c, 0x62, 0x17, 0x42, 0x24, 0x23, 0x3e, 0x1b, 0x18, 0x0e, 0x0d, 0x0d, 0x0e, 0x18, 0x18, 0x09, 0x01, 0xba, 0x16, 0x17, 0x49, 0x72, 0x30, 0x43, 0x04, 0x03, 0x0d, 0x0d, 0x0e, 0x18, 0x18, 0x3e, 0x27, 0x23, 0x3e, 0x1b, 0x18, 0x0e, 0x09, 0xfe, 0xc2, 0x4c, 0x4d, 0x18, 0x18, 0x0e, 0x0d, 0x0d, 0x0e, 0x18, 0x1b, 0x3e, 0x23, 0x24, 0x42, 0x17, 0x62, 0x2c, 0x1e, 0x2e, 0x1e, 0x0e, 0x01, 0x24, 0x0a, 0x0a, 0x09, 0x0e, 0x18, 0x1b, 0x3e, 0x23, 0x27, 0x3e, 0x18, 0x18, 0x0e, 0x0d, 0x0d, 0x03, 0x04, 0x43, 0x30, 0x72, 0x49, 0x17, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x4b, 0xff, 0xe3, 0x05, 0xbd, 0x05, 0xf0, 0x00, 0x29, 0x00, 0x54, 0x00, 0xbd, 0x00, 0xe6, 0x01, 0x11, 0x01, 0x3a, 0x01, 0x65, 0x01, 0x7f, 0x01, 0xa9, 0x01, 0xd3, 0x00, 0x00, 0x01, 0x26, 0x27, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x01, 0x36, 0x37, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x06, 0x07, 0x06, 0x14, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x25, 0x06, 0x07, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x34, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x0f, 0x01, 0x16, 0x17, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x23, 0x01, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x07, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x23, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x34, 0x36, 0x37, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x01, 0x26, 0x27, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x07, 0x26, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x3f, 0x01, 0x26, 0x27, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x16, 0x17, 0x1e, 0x02, 0x33, 0x32, 0x36, 0x37, 0x36, 0x37, 0x01, 0x16, 0x17, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x26, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x06, 0x0f, 0x01, 0x16, 0x17, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x37, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x0e, 0x01, 0x07, 0x06, 0x07, 0x03, 0x06, 0x07, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x17, 0x06, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x07, 0x2e, 0x01, 0x27, 0x26, 0x2f, 0x01, 0x06, 0x07, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x01, 0x37, 0x36, 0x37, 0x34, 0x26, 0x27, 0x26, 0x27, 0x01, 0x36, 0x37, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x14, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x36, 0x37, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x1e, 0x01, 0x17, 0x16, 0x17, 0x04, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x13, 0x06, 0x07, 0x17, 0x16, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x3f, 0x01, 0x26, 0x27, 0x07, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x03, 0x16, 0x17, 0x37, 0x36, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x1f, 0x01, 0x36, 0x37, 0x27, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x02, 0x01, 0x05, 0x02, 0xcd, 0x10, 0x08, 0x09, 0x17, 0x09, 0x07, 0x06, 0x03, 0x03, 0x06, 0x07, 0x09, 0x15, 0x0b, 0x08, 0x10, 0xcd, 0x02, 0x05, 0xb9, 0x21, 0x12, 0x19, 0x2f, 0x14, 0x12, 0x0a, 0x09, 0x09, 0x0a, 0x12, 0x14, 0x2f, 0x19, 0x12, 0x21, 0x02, 0xca, 0x02, 0x05, 0x6b, 0x6b, 0x10, 0x1b, 0x2f, 0x14, 0x12, 0x0b, 0x09, 0x09, 0x0b, 0x12, 0x14, 0x2f, 0x1b, 0x10, 0x08, 0xce, 0x05, 0x02, 0x6d, 0x6c, 0x06, 0x0f, 0x14, 0x09, 0x07, 0x05, 0x04, 0x04, 0x05, 0x07, 0x0b, 0x16, 0x0b, 0x06, 0x04, 0xfc, 0x35, 0x21, 0x1f, 0x10, 0x0e, 0x1d, 0x1e, 0x24, 0x25, 0x28, 0x27, 0x4c, 0x21, 0x1e, 0x1e, 0x1d, 0x24, 0x24, 0x53, 0x24, 0x24, 0x1c, 0x1e, 0x1f, 0x22, 0x4b, 0x26, 0x29, 0x25, 0x24, 0x1d, 0x1a, 0x12, 0x0f, 0x1d, 0x23, 0x32, 0x45, 0x1e, 0x20, 0x0d, 0x0f, 0x0f, 0x10, 0x1d, 0x19, 0x4d, 0x2d, 0x21, 0x1d, 0x0f, 0x0f, 0x3a, 0x24, 0x25, 0x29, 0x29, 0x4a, 0x20, 0x1f, 0x1e, 0x1c, 0x24, 0x24, 0x53, 0x24, 0x24, 0x1d, 0x1e, 0x1e, 0x24, 0x47, 0x29, 0x28, 0x25, 0x24, 0x3b, 0x0e, 0x10, 0x1f, 0x20, 0x2d, 0x48, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x10, 0x1d, 0x1f, 0x45, 0x01, 0x94, 0x12, 0x0e, 0x80, 0x0a, 0x05, 0x07, 0x16, 0x0d, 0x0c, 0x0a, 0x0a, 0x11, 0x05, 0x04, 0x09, 0x08, 0x05, 0x0d, 0xa2, 0x0d, 0x0a, 0xa5, 0x1e, 0x0d, 0x13, 0x13, 0x01, 0x09, 0x09, 0x26, 0x2f, 0x1a, 0x1d, 0x2d, 0x13, 0x0c, 0x11, 0x01, 0xba, 0x0e, 0x09, 0x60, 0x61, 0x0b, 0x14, 0x13, 0x01, 0x09, 0x09, 0x13, 0x13, 0x2f, 0x1a, 0x1c, 0x2e, 0x13, 0x0c, 0x05, 0x69, 0x12, 0x0f, 0x44, 0x44, 0x04, 0x09, 0x15, 0x0c, 0x0c, 0x0a, 0x0b, 0x09, 0x08, 0x04, 0x04, 0x01, 0x01, 0x0a, 0x07, 0x05, 0x03, 0x95, 0x0a, 0x0c, 0xa2, 0x0c, 0x06, 0x06, 0x0a, 0x01, 0x01, 0x04, 0x04, 0x11, 0x0b, 0x0a, 0x0c, 0x0c, 0x15, 0x08, 0x05, 0x0a, 0x80, 0x10, 0x11, 0x5f, 0x11, 0x0d, 0x12, 0x2e, 0x1c, 0x1a, 0x2f, 0x26, 0x09, 0x09, 0x01, 0x13, 0x13, 0x0c, 0x1e, 0xfd, 0xc8, 0x10, 0x11, 0x37, 0x37, 0x0b, 0x14, 0x2d, 0x1d, 0x1a, 0x2f, 0x13, 0x13, 0x09, 0x09, 0x01, 0x13, 0x14, 0x0c, 0x08, 0xb9, 0x09, 0x0d, 0x56, 0x56, 0x04, 0x09, 0x09, 0x04, 0x05, 0x08, 0x09, 0x0a, 0x0a, 0x0c, 0x0f, 0x14, 0x07, 0x05, 0x02, 0x01, 0x52, 0x4a, 0x1f, 0x21, 0x1a, 0x1a, 0x1b, 0x1b, 0x1a, 0x1a, 0x21, 0x1f, 0x4a, 0x20, 0x20, 0x1a, 0x1a, 0x1b, 0x1b, 0x1a, 0x1a, 0x20, 0x02, 0x13, 0x13, 0x18, 0x02, 0x09, 0x08, 0x09, 0x0a, 0x0b, 0x18, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x02, 0x18, 0x14, 0x13, 0x32, 0x09, 0x13, 0x13, 0x13, 0x18, 0x16, 0x36, 0x17, 0x17, 0x13, 0x14, 0x13, 0x09, 0x59, 0x14, 0x13, 0x1d, 0x1e, 0x13, 0x14, 0x13, 0x17, 0x17, 0x36, 0x16, 0x18, 0x13, 0x13, 0x13, 0x02, 0x38, 0x14, 0x14, 0x0d, 0x0d, 0x09, 0x08, 0x09, 0x0a, 0x0a, 0x18, 0x0b, 0x0a, 0x09, 0x0a, 0x07, 0x01, 0x02, 0x9a, 0x16, 0x16, 0x1c, 0x02, 0x0a, 0x0a, 0x0a, 0x0a, 0x0c, 0x1a, 0x0c, 0x0c, 0x0a, 0x08, 0x0a, 0x02, 0x1a, 0x16, 0x14, 0x38, 0x0a, 0x14, 0x16, 0x16, 0x1a, 0x18, 0x3c, 0x1a, 0x1a, 0x14, 0x16, 0x16, 0x0a, 0x64, 0x18, 0x14, 0x21, 0x21, 0x16, 0x16, 0x14, 0x1a, 0x1a, 0x3c, 0x18, 0x1a, 0x16, 0x16, 0x14, 0x02, 0x3e, 0x17, 0x15, 0x0e, 0x0e, 0x0a, 0x08, 0x0a, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x0a, 0x0a, 0x0c, 0x08, 0x01, 0x22, 0x25, 0x55, 0x56, 0x2a, 0x29, 0x20, 0x21, 0x10, 0x10, 0x21, 0x24, 0x33, 0x52, 0x20, 0x1f, 0x12, 0x11, 0x11, 0x12, 0x1f, 0x20, 0x52, 0x33, 0x26, 0x1f, 0x10, 0x10, 0x21, 0x1c, 0x2d, 0x28, 0x2d, 0x25, 0x5a, 0x26, 0x20, 0x22, 0x23, 0x25, 0x28, 0x2e, 0x32, 0x24, 0x28, 0x20, 0x1e, 0x26, 0x26, 0x53, 0x2b, 0x2c, 0x29, 0x29, 0x41, 0x10, 0x10, 0x21, 0x24, 0x33, 0x52, 0x20, 0x1f, 0x12, 0x11, 0x11, 0x12, 0x1f, 0x20, 0x52, 0x33, 0x27, 0x1e, 0x10, 0x10, 0x41, 0x29, 0x29, 0x58, 0x54, 0x24, 0x22, 0x22, 0x23, 0x25, 0x28, 0x60, 0x24, 0x28, 0x20, 0x22, 0x20, 0xfe, 0x1c, 0x0b, 0x0d, 0xb4, 0x0d, 0x06, 0x08, 0x0a, 0x01, 0x01, 0x04, 0x05, 0x12, 0x0c, 0x0c, 0x0d, 0x0d, 0x18, 0x09, 0x06, 0x0a, 0x8e, 0x11, 0x13, 0x69, 0x13, 0x0e, 0x14, 0x33, 0x1f, 0x1d, 0x1b, 0x19, 0x2b, 0x14, 0x15, 0x14, 0x0e, 0x21, 0x02, 0x78, 0x12, 0x13, 0x3d, 0x3d, 0x0d, 0x15, 0x33, 0x1f, 0x1d, 0x1b, 0x19, 0x16, 0x15, 0x14, 0x15, 0x15, 0x0d, 0x09, 0xcd, 0x0c, 0x0e, 0x5f, 0x60, 0x05, 0x0b, 0x08, 0x01, 0x01, 0x04, 0x05, 0x09, 0x09, 0x0c, 0x0c, 0x0d, 0x10, 0x16, 0x09, 0x05, 0x02, 0xfe, 0x1d, 0x13, 0x11, 0x8e, 0x0a, 0x06, 0x08, 0x19, 0x0d, 0x0d, 0x0c, 0x0c, 0x12, 0x05, 0x04, 0x01, 0x01, 0x09, 0x09, 0x06, 0x0d, 0xb4, 0x0e, 0x0a, 0xb9, 0x21, 0x0e, 0x14, 0x15, 0x14, 0x2b, 0x19, 0x1b, 0x1d, 0x1f, 0x33, 0x14, 0x0e, 0x13, 0x01, 0xeb, 0x0f, 0x0b, 0x6b, 0x6b, 0x0d, 0x15, 0x15, 0x14, 0x15, 0x16, 0x19, 0x1b, 0x1d, 0x1f, 0x33, 0x15, 0x0d, 0x05, 0x75, 0x13, 0x12, 0x4b, 0x4a, 0x05, 0x0b, 0x17, 0x0d, 0x0d, 0x0c, 0x0c, 0x09, 0x09, 0x05, 0x04, 0x01, 0x01, 0x0a, 0x09, 0x05, 0x03, 0xdf, 0x0f, 0x10, 0x1c, 0x1f, 0x46, 0x29, 0x28, 0x47, 0x1e, 0x1c, 0x10, 0x0f, 0x0f, 0x10, 0x1c, 0x1e, 0x47, 0x28, 0x29, 0x46, 0x1f, 0x1c, 0x10, 0xfe, 0x24, 0x06, 0x02, 0xe4, 0x11, 0x08, 0x0b, 0x19, 0x0a, 0x09, 0x05, 0x05, 0x05, 0x05, 0x09, 0x0a, 0x17, 0x0d, 0x08, 0x11, 0xe4, 0x02, 0x06, 0xcd, 0x25, 0x13, 0x1d, 0x33, 0x16, 0x14, 0x0c, 0x0b, 0x0b, 0x0c, 0x14, 0x16, 0x33, 0x1d, 0x13, 0x25, 0x03, 0x1a, 0x02, 0x06, 0x77, 0x77, 0x12, 0x1e, 0x33, 0x16, 0x14, 0x0c, 0x0b, 0x0b, 0x0c, 0x14, 0x16, 0x33, 0x1e, 0x12, 0x09, 0xe5, 0x06, 0x02, 0x78, 0x79, 0x07, 0x0f, 0x16, 0x0a, 0x09, 0x05, 0x05, 0x05, 0x05, 0x09, 0x0c, 0x17, 0x0c, 0x07, 0x05, 0x00, 0x04, 0x00, 0x4d, 0xff, 0xe3, 0x05, 0xbb, 0x05, 0xf0, 0x00, 0x19, 0x00, 0x33, 0x00, 0x4e, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x13, 0x32, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x36, 0x17, 0x03, 0x25, 0x13, 0x0d, 0x01, 0x03, 0x25, 0x1b, 0x01, 0x05, 0x03, 0x2d, 0x01, 0x13, 0x05, 0x03, 0x3b, 0x6e, 0x2e, 0x2f, 0x27, 0x27, 0x26, 0x26, 0x27, 0x27, 0x2f, 0x2e, 0x6e, 0x2e, 0x30, 0x26, 0x27, 0x27, 0x27, 0x27, 0x26, 0x30, 0x65, 0x4e, 0x3e, 0x45, 0x31, 0x33, 0x39, 0x37, 0x35, 0x34, 0x42, 0x41, 0x99, 0x3d, 0x46, 0x30, 0x33, 0x39, 0x37, 0x35, 0x33, 0x43, 0x41, 0x4a, 0x8b, 0x80, 0x78, 0x68, 0x65, 0x67, 0x63, 0x69, 0x63, 0x7d, 0x7f, 0xfe, 0xea, 0x80, 0x79, 0x67, 0x65, 0x68, 0x63, 0x6a, 0x61, 0x7f, 0x7e, 0x8c, 0x8d, 0xfe, 0xa5, 0x93, 0xfe, 0xa4, 0x01, 0x5c, 0x93, 0x01, 0x5b, 0x8d, 0x8e, 0x01, 0x5a, 0x93, 0x01, 0x5d, 0xfe, 0xa3, 0x93, 0xfe, 0xa6, 0x04, 0x13, 0x16, 0x18, 0x28, 0x2e, 0x68, 0x3c, 0x3b, 0x68, 0x2e, 0x28, 0x18, 0x16, 0x16, 0x18, 0x28, 0x2e, 0x68, 0x3b, 0x3c, 0x68, 0x2e, 0x28, 0x18, 0x86, 0x1f, 0x22, 0x36, 0x38, 0x96, 0x54, 0x4e, 0x96, 0x3b, 0x39, 0x1f, 0x1f, 0x1f, 0x22, 0x36, 0x38, 0x96, 0xa2, 0x96, 0x3b, 0x39, 0x1f, 0x1f, 0x01, 0x6d, 0x3b, 0x38, 0x72, 0x6f, 0xfe, 0xec, 0xa1, 0x98, 0xfe, 0xf0, 0x77, 0x70, 0x3a, 0x3b, 0x3b, 0x38, 0x72, 0x6f, 0x01, 0x14, 0x9c, 0x9d, 0x01, 0x10, 0x77, 0x6e, 0x3c, 0x3b, 0x08, 0xfe, 0x7d, 0xa3, 0xfe, 0x7f, 0x9e, 0x9d, 0xfe, 0x7f, 0xa3, 0xfe, 0x7d, 0x01, 0x83, 0xa3, 0x01, 0x81, 0x9d, 0x9e, 0x01, 0x81, 0xa3, 0x00, 0x00, 0x07, 0x00, 0x90, 0xff, 0xe3, 0x05, 0x77, 0x05, 0xf0, 0x00, 0x08, 0x00, 0x93, 0x00, 0x9c, 0x00, 0xa7, 0x00, 0xb2, 0x00, 0xc1, 0x00, 0xd0, 0x00, 0x00, 0x01, 0x11, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x13, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x15, 0x14, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3d, 0x01, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x33, 0x32, 0x3f, 0x01, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x1d, 0x01, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x11, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x13, 0x25, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x01, 0x05, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x13, 0x25, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x33, 0x32, 0x0d, 0x01, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x23, 0x22, 0x03, 0x04, 0x26, 0x2c, 0x1b, 0x22, 0x32, 0x97, 0x10, 0x30, 0x5b, 0x1d, 0x21, 0x10, 0x0f, 0x51, 0x3f, 0x52, 0x11, 0x0a, 0x17, 0x27, 0x62, 0x12, 0x13, 0x33, 0x3b, 0x4b, 0x2a, 0x39, 0x43, 0x10, 0x4e, 0x39, 0x30, 0x4a, 0x4c, 0x4f, 0x46, 0x31, 0x3a, 0x4d, 0x10, 0x40, 0x3b, 0x2c, 0x49, 0x3c, 0x32, 0x14, 0x12, 0x63, 0x26, 0x16, 0x0a, 0x10, 0x53, 0x3f, 0x51, 0x0e, 0x10, 0x22, 0x1c, 0x5b, 0x30, 0x10, 0x10, 0x2e, 0x5b, 0x1d, 0x23, 0x10, 0x0e, 0x51, 0x3f, 0x51, 0x12, 0x0b, 0x17, 0x26, 0x63, 0x12, 0x14, 0x32, 0x3c, 0x4a, 0x2b, 0x38, 0x43, 0x10, 0x4d, 0x3a, 0x31, 0x4a, 0x97, 0x4a, 0x30, 0x39, 0x4e, 0x10, 0x40, 0x3c, 0x2c, 0x49, 0x3b, 0x33, 0x13, 0x12, 0x62, 0x27, 0x17, 0x0a, 0x11, 0x52, 0x3f, 0x51, 0x0f, 0x10, 0x22, 0x1e, 0x5b, 0x2e, 0x8e, 0x26, 0x2c, 0x1b, 0x21, 0x33, 0x9d, 0x01, 0x58, 0x13, 0x38, 0x09, 0x0b, 0x1c, 0x26, 0x3f, 0x17, 0x20, 0xfe, 0x53, 0xfe, 0xa9, 0x13, 0x37, 0x09, 0x0b, 0x1c, 0x27, 0x3f, 0x16, 0x21, 0x40, 0xfe, 0xa9, 0x0c, 0x04, 0x07, 0x35, 0x36, 0x2f, 0x0a, 0x08, 0x1a, 0x1b, 0x3a, 0x01, 0xa9, 0x01, 0x58, 0x0c, 0x05, 0x06, 0x35, 0x36, 0x30, 0x09, 0x08, 0x1a, 0x1b, 0x3b, 0x03, 0xd3, 0x01, 0xb9, 0x2b, 0x1a, 0x44, 0x51, 0x32, 0x4a, 0xfe, 0xb4, 0x0b, 0x20, 0x03, 0x01, 0x28, 0x35, 0x48, 0x2c, 0x27, 0x39, 0x2c, 0x4a, 0x1e, 0x06, 0x26, 0x30, 0x66, 0x89, 0x29, 0x0a, 0x14, 0x54, 0x7c, 0x5c, 0x60, 0x6a, 0x34, 0x4f, 0x4f, 0x37, 0x67, 0x60, 0x5c, 0x7c, 0x54, 0x14, 0x0a, 0x27, 0x8b, 0x67, 0x2f, 0x26, 0x06, 0x20, 0x48, 0x2c, 0x39, 0x27, 0x2c, 0x49, 0x34, 0x28, 0x01, 0x03, 0x20, 0x0b, 0x0b, 0x1f, 0x03, 0x01, 0x28, 0x33, 0x4a, 0x2c, 0x26, 0x39, 0x2d, 0x48, 0x20, 0x06, 0x26, 0x30, 0x66, 0x89, 0x29, 0x0a, 0x14, 0x54, 0x7c, 0x5c, 0x60, 0x6a, 0x34, 0x4f, 0x4f, 0x34, 0x6a, 0x60, 0x5c, 0x7c, 0x54, 0x14, 0x0a, 0x27, 0x8b, 0x67, 0x2f, 0x26, 0x06, 0x1e, 0x4a, 0x2c, 0x39, 0x27, 0x2c, 0x48, 0x35, 0x28, 0x01, 0x03, 0x1f, 0xf5, 0xfe, 0x47, 0x2b, 0x1a, 0x44, 0x51, 0x32, 0x4a, 0x01, 0xc1, 0xdd, 0x24, 0x15, 0x04, 0x19, 0x28, 0x3a, 0x55, 0xfe, 0xcd, 0xdd, 0x24, 0x15, 0x04, 0x19, 0x28, 0x3a, 0x55, 0x01, 0x33, 0xdd, 0x17, 0x21, 0x15, 0x18, 0x27, 0x22, 0x22, 0x01, 0x04, 0xfb, 0xdd, 0x17, 0x21, 0x15, 0x18, 0x27, 0x22, 0x22, 0x01, 0x04, 0x00, 0x01, 0x00, 0xa3, 0x00, 0x00, 0x05, 0x65, 0x05, 0xd5, 0x00, 0x41, 0x00, 0x00, 0x01, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x35, 0x33, 0x15, 0x17, 0x11, 0x27, 0x37, 0x17, 0x35, 0x33, 0x15, 0x37, 0x17, 0x07, 0x11, 0x37, 0x35, 0x33, 0x15, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x07, 0x17, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x15, 0x23, 0x35, 0x27, 0x11, 0x17, 0x07, 0x27, 0x15, 0x23, 0x35, 0x07, 0x27, 0x37, 0x11, 0x07, 0x15, 0x23, 0x35, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x02, 0x98, 0xd8, 0xae, 0x36, 0x78, 0xb0, 0x36, 0xb0, 0x6c, 0xd8, 0xae, 0x36, 0x78, 0x6c, 0x79, 0x36, 0xaf, 0xd8, 0x6c, 0xb1, 0x36, 0xb1, 0x79, 0x36, 0xaf, 0xd8, 0xd8, 0xaf, 0x36, 0x79, 0xb1, 0x36, 0xb1, 0x6c, 0xd8, 0xaf, 0x36, 0x79, 0x6c, 0x78, 0x36, 0xae, 0xd8, 0x6c, 0xb0, 0x36, 0xb0, 0x78, 0x36, 0xae, 0x02, 0xeb, 0x8a, 0x70, 0x68, 0x4d, 0x72, 0x68, 0x72, 0x9b, 0xe0, 0x8b, 0x01, 0x16, 0x6f, 0x68, 0x4d, 0xe3, 0xe3, 0x4d, 0x68, 0x6f, 0xfe, 0xeb, 0x8a, 0xe0, 0x9b, 0x72, 0x68, 0x72, 0x4d, 0x68, 0x70, 0x8a, 0x8b, 0x70, 0x68, 0x4d, 0x72, 0x68, 0x72, 0x9b, 0xe0, 0x8b, 0xfe, 0xea, 0x6f, 0x68, 0x4d, 0xe3, 0xe3, 0x4d, 0x68, 0x6f, 0x01, 0x16, 0x8b, 0xe0, 0x9b, 0x72, 0x68, 0x72, 0x4d, 0x68, 0x70, 0x00, 0x07, 0x00, 0x8c, 0x00, 0x00, 0x05, 0x7c, 0x05, 0xd5, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x25, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x00, 0x01, 0x33, 0x11, 0x25, 0x11, 0x37, 0x17, 0x07, 0x0d, 0x01, 0x17, 0x07, 0x27, 0x11, 0x25, 0x11, 0x23, 0x11, 0x05, 0x11, 0x07, 0x27, 0x37, 0x2d, 0x01, 0x27, 0x37, 0x17, 0x11, 0x05, 0x07, 0x15, 0x17, 0x35, 0x25, 0x07, 0x15, 0x37, 0x05, 0x07, 0x17, 0x37, 0x25, 0x07, 0x17, 0x37, 0x05, 0x07, 0x15, 0x3f, 0x01, 0x15, 0x17, 0x35, 0x02, 0xce, 0x6c, 0x01, 0x06, 0xef, 0x36, 0xf0, 0x01, 0x07, 0xfe, 0xfa, 0xef, 0x36, 0xef, 0xfe, 0xfa, 0x6c, 0xfe, 0xfa, 0xee, 0x36, 0xee, 0xfe, 0xfa, 0x01, 0x07, 0xef, 0x36, 0xee, 0x01, 0x06, 0x9a, 0x9a, 0x01, 0x06, 0x9a, 0x9a, 0xfe, 0x2b, 0x9b, 0x9a, 0x9a, 0x01, 0x71, 0x99, 0x9a, 0x9a, 0xfe, 0x2a, 0x9a, 0x9a, 0x6c, 0x9a, 0x05, 0xd5, 0xfe, 0xcc, 0xa9, 0xfe, 0xb0, 0x9a, 0x68, 0x9a, 0xa8, 0xa8, 0x99, 0x68, 0x9a, 0xfe, 0xaf, 0xa9, 0xfe, 0xcd, 0x01, 0x33, 0xa9, 0x01, 0x51, 0x9a, 0x68, 0x99, 0xa8, 0xa8, 0x9a, 0x68, 0x9a, 0x01, 0x50, 0xa9, 0x27, 0xc5, 0x63, 0xc5, 0x63, 0x63, 0xc5, 0x63, 0x68, 0x63, 0x62, 0x62, 0x63, 0x63, 0x62, 0x62, 0x67, 0x63, 0xc6, 0x63, 0xc6, 0xc6, 0x63, 0xc6, 0x00, 0x00, 0x00, 0x01, 0x00, 0x75, 0x00, 0x04, 0x05, 0x92, 0x05, 0xd5, 0x00, 0x41, 0x00, 0x00, 0x01, 0x33, 0x15, 0x37, 0x17, 0x07, 0x11, 0x37, 0x11, 0x33, 0x15, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x07, 0x17, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x15, 0x23, 0x11, 0x27, 0x11, 0x17, 0x07, 0x27, 0x15, 0x23, 0x35, 0x07, 0x27, 0x37, 0x11, 0x07, 0x11, 0x23, 0x35, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x35, 0x33, 0x11, 0x17, 0x11, 0x27, 0x37, 0x17, 0x02, 0xce, 0x6c, 0x7e, 0x5a, 0xd8, 0xf1, 0xb4, 0x50, 0x36, 0x52, 0x7e, 0x5a, 0xd8, 0xf0, 0xf1, 0xd8, 0x5a, 0x7e, 0x50, 0x36, 0x53, 0xb4, 0xed, 0xd8, 0x5a, 0x7e, 0x6c, 0x7e, 0x5a, 0xd8, 0xee, 0xb4, 0x52, 0x36, 0x4f, 0x7e, 0x5a, 0xd8, 0xf0, 0xee, 0xd8, 0x5a, 0x7e, 0x53, 0x36, 0x50, 0xb4, 0xf2, 0xd8, 0x5a, 0x7e, 0x05, 0xd5, 0x68, 0x51, 0xad, 0x8b, 0xfe, 0xce, 0x9b, 0x01, 0x15, 0xa2, 0x34, 0x68, 0x35, 0x51, 0xad, 0x8a, 0x99, 0x9b, 0x8b, 0xad, 0x51, 0x34, 0x68, 0x35, 0xa1, 0x01, 0x15, 0x98, 0xfe, 0xd0, 0x8b, 0xad, 0x51, 0x68, 0x65, 0x51, 0xad, 0x8b, 0x01, 0x35, 0x99, 0xfe, 0xeb, 0xa1, 0x35, 0x68, 0x33, 0x51, 0xae, 0x8b, 0x9a, 0x99, 0x8b, 0xad, 0x51, 0x35, 0x68, 0x33, 0xa1, 0xfe, 0xeb, 0x9b, 0x01, 0x36, 0x8b, 0xad, 0x51, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x90, 0xff, 0xe5, 0x05, 0x78, 0x05, 0xf0, 0x00, 0x87, 0x00, 0x00, 0x01, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x07, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x27, 0x11, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x0e, 0x01, 0x22, 0x2e, 0x01, 0x34, 0x36, 0x37, 0x36, 0x37, 0x11, 0x07, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x37, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x17, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x36, 0x37, 0x36, 0x33, 0x32, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x11, 0x37, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x05, 0x5f, 0x19, 0x19, 0x18, 0x29, 0x2b, 0x2f, 0x31, 0x29, 0x12, 0x0f, 0xd9, 0xd9, 0x0f, 0x12, 0x29, 0x31, 0x2f, 0x2b, 0x29, 0x18, 0x19, 0x19, 0x19, 0x28, 0x2b, 0x2f, 0x2e, 0x2c, 0x2b, 0x18, 0x17, 0x03, 0xd9, 0x13, 0x11, 0x2a, 0x30, 0x30, 0x53, 0x61, 0x53, 0x31, 0x31, 0x29, 0x11, 0x13, 0xd9, 0x04, 0x17, 0x19, 0x2a, 0x2a, 0x30, 0x31, 0x29, 0x29, 0x19, 0x18, 0x18, 0x19, 0x29, 0x2a, 0x60, 0x2a, 0x11, 0x0f, 0xd9, 0xd9, 0x0e, 0x12, 0x2c, 0x2e, 0x31, 0x52, 0x31, 0x18, 0x19, 0x29, 0x2a, 0x30, 0x2e, 0x2c, 0x2a, 0x19, 0x17, 0x04, 0xd9, 0x13, 0x11, 0x29, 0x31, 0x31, 0x29, 0x2a, 0x30, 0x31, 0x53, 0x30, 0x30, 0x2a, 0x11, 0x13, 0xd9, 0x03, 0x17, 0x17, 0x2c, 0x29, 0x31, 0x2f, 0x2b, 0x2d, 0x04, 0x6d, 0x36, 0x2e, 0x35, 0x2f, 0x2e, 0x1b, 0x1b, 0x1b, 0x0b, 0x0f, 0x8b, 0x8c, 0x0f, 0x0b, 0x1b, 0x1b, 0x1b, 0x2e, 0x2f, 0x35, 0x34, 0x2f, 0x2f, 0x1b, 0x1b, 0x1b, 0x1a, 0x2f, 0x2e, 0x36, 0x16, 0x15, 0x8c, 0xfe, 0xe9, 0x07, 0x0b, 0x1b, 0x5c, 0x6c, 0x5c, 0x36, 0x36, 0x5c, 0x6c, 0x5c, 0x1b, 0x0b, 0x07, 0x01, 0x17, 0x8c, 0x15, 0x16, 0x36, 0x2e, 0x2f, 0x1a, 0x1b, 0x1b, 0x1a, 0x2f, 0x2e, 0x36, 0x35, 0x2f, 0x2e, 0x1b, 0x1b, 0x1b, 0x0b, 0x0f, 0x8c, 0x8b, 0x0f, 0x0b, 0x1b, 0x36, 0x5c, 0x6c, 0x2e, 0x2f, 0x1a, 0x1b, 0x1b, 0x1a, 0x2f, 0x2e, 0x36, 0x16, 0x15, 0x8c, 0x01, 0x17, 0x07, 0x0b, 0x1b, 0x5c, 0x6c, 0x5c, 0x1b, 0x1b, 0x36, 0x5c, 0x6c, 0x5c, 0x1b, 0x0b, 0x07, 0xfe, 0xe9, 0x8c, 0x15, 0x16, 0x36, 0x2e, 0x2d, 0x1c, 0x1b, 0x1b, 0x1e, 0x00, 0x00, 0x09, 0x00, 0x57, 0xff, 0xe5, 0x05, 0xb2, 0x05, 0xd7, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x2e, 0x00, 0x45, 0x00, 0x5c, 0x00, 0x73, 0x00, 0x00, 0x00, 0x14, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x09, 0x01, 0x37, 0x09, 0x02, 0x37, 0x09, 0x02, 0x27, 0x09, 0x02, 0x27, 0x01, 0x13, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x05, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x03, 0x8b, 0x4f, 0x70, 0x4f, 0x4f, 0x70, 0x01, 0x7d, 0xfe, 0xa3, 0x4d, 0x01, 0x5c, 0xfd, 0x59, 0xfe, 0xa5, 0x4d, 0x01, 0x5a, 0x02, 0x5b, 0xfe, 0xa4, 0x4d, 0x01, 0x5d, 0xfd, 0xf1, 0xfe, 0xa6, 0x4d, 0x01, 0x5b, 0xa6, 0x33, 0x0e, 0x14, 0x04, 0x01, 0x02, 0x03, 0x0d, 0x15, 0x67, 0x14, 0x0e, 0x02, 0x02, 0x01, 0x03, 0x15, 0x0d, 0x34, 0x34, 0x0d, 0x15, 0x03, 0x01, 0x02, 0x02, 0x0e, 0x14, 0x67, 0x15, 0x0d, 0x03, 0x02, 0x01, 0x04, 0x14, 0x0e, 0x8f, 0x36, 0x16, 0x21, 0x3d, 0x1a, 0x4a, 0x3e, 0x1b, 0x3b, 0x1d, 0x2c, 0x2c, 0x1d, 0x3b, 0x1b, 0x3e, 0x4a, 0x1a, 0x3d, 0x21, 0x16, 0x01, 0xbb, 0x36, 0x15, 0x22, 0x3d, 0x1a, 0x4a, 0x3e, 0x1b, 0x3a, 0x1d, 0x2c, 0x2c, 0x1d, 0x3a, 0x1b, 0x3e, 0x4a, 0x1a, 0x3d, 0x22, 0x15, 0x03, 0x2c, 0x7c, 0x58, 0x58, 0x7c, 0x58, 0xfd, 0x2e, 0x01, 0x84, 0x55, 0xfe, 0x7c, 0x02, 0x4a, 0x01, 0x81, 0x55, 0xfe, 0x7e, 0x01, 0x2d, 0xfe, 0x7c, 0x55, 0x01, 0x84, 0xfd, 0x0d, 0xfe, 0x7e, 0x55, 0x01, 0x81, 0x01, 0x2e, 0x3c, 0x18, 0x25, 0x44, 0x1d, 0x52, 0x45, 0x1e, 0x41, 0x20, 0x31, 0x31, 0x20, 0x41, 0x1e, 0x45, 0x52, 0x1d, 0x44, 0x25, 0x18, 0xfe, 0x14, 0x3c, 0x18, 0x25, 0x44, 0x1d, 0x52, 0x45, 0x1e, 0x41, 0x20, 0x31, 0x31, 0x20, 0x41, 0x1e, 0x45, 0x52, 0x1d, 0x44, 0x25, 0x18, 0x01, 0x14, 0x39, 0x0f, 0x17, 0x04, 0x01, 0x02, 0x03, 0x0f, 0x17, 0x72, 0x17, 0x0f, 0x03, 0x02, 0x01, 0x04, 0x17, 0x0f, 0x39, 0x39, 0x0f, 0x17, 0x04, 0x01, 0x02, 0x03, 0x0f, 0x17, 0x72, 0x17, 0x0f, 0x03, 0x02, 0x01, 0x04, 0x17, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x57, 0xff, 0xe5, 0x05, 0xb2, 0x05, 0xd7, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x2b, 0x00, 0x3f, 0x00, 0x53, 0x00, 0x67, 0x00, 0x00, 0x00, 0x14, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x09, 0x01, 0x17, 0x09, 0x02, 0x17, 0x09, 0x02, 0x07, 0x09, 0x02, 0x07, 0x01, 0x02, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x12, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x24, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x03, 0xcf, 0x77, 0xa8, 0x76, 0x76, 0xa8, 0xfd, 0xab, 0x01, 0x0b, 0x4d, 0xfe, 0xf5, 0x02, 0x5d, 0x01, 0x0c, 0x4c, 0xfe, 0xf5, 0xfd, 0x56, 0x01, 0x0b, 0x4d, 0xfe, 0xf5, 0x02, 0xf7, 0x01, 0x0b, 0x4c, 0xfe, 0xf4, 0x07, 0x11, 0x13, 0x23, 0x29, 0x63, 0x2a, 0x23, 0x13, 0x11, 0x11, 0x13, 0x23, 0x2a, 0x63, 0x29, 0x23, 0x13, 0x11, 0x11, 0x13, 0x23, 0x29, 0x63, 0x2a, 0x23, 0x13, 0x11, 0x11, 0x13, 0x23, 0x2a, 0x63, 0x29, 0x23, 0x13, 0xfd, 0x63, 0x65, 0x2c, 0x32, 0x1f, 0x24, 0x24, 0x1f, 0x32, 0x2c, 0x65, 0x2c, 0x31, 0x20, 0x24, 0x24, 0x20, 0x31, 0x03, 0xdf, 0x65, 0x2c, 0x32, 0x1f, 0x24, 0x24, 0x1f, 0x32, 0x2c, 0x65, 0x2c, 0x31, 0x20, 0x24, 0x24, 0x20, 0x31, 0x03, 0x4b, 0xba, 0x84, 0x84, 0xba, 0x84, 0xfd, 0x38, 0x01, 0x29, 0x55, 0xfe, 0xd7, 0x03, 0x4c, 0x01, 0x29, 0x55, 0xfe, 0xd7, 0x01, 0x7e, 0xfe, 0xd7, 0x55, 0x01, 0x29, 0xfd, 0x5e, 0xfe, 0xd7, 0x55, 0x01, 0x29, 0x03, 0x49, 0x70, 0x31, 0x37, 0x23, 0x28, 0x28, 0x23, 0x37, 0x31, 0x70, 0x31, 0x37, 0x23, 0x28, 0x28, 0x23, 0x37, 0xfb, 0xb3, 0x70, 0x31, 0x37, 0x23, 0x28, 0x28, 0x23, 0x37, 0x31, 0x70, 0x31, 0x37, 0x23, 0x28, 0x28, 0x23, 0x37, 0x02, 0x59, 0x13, 0x15, 0x27, 0x2e, 0x6e, 0x2e, 0x27, 0x15, 0x13, 0x13, 0x15, 0x27, 0x2e, 0x6e, 0x2e, 0x27, 0x15, 0x13, 0x13, 0x15, 0x27, 0x2e, 0x6e, 0x2e, 0x27, 0x15, 0x13, 0x13, 0x15, 0x27, 0x2e, 0x6e, 0x2e, 0x27, 0x15, 0x00, 0x00, 0x00, 0x09, 0x00, 0x4b, 0xff, 0xe5, 0x05, 0xbd, 0x05, 0xf2, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x25, 0x00, 0x32, 0x00, 0x3f, 0x00, 0x4b, 0x00, 0x57, 0x00, 0x5f, 0x00, 0x6b, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x25, 0x35, 0x25, 0x33, 0x32, 0x17, 0x16, 0x05, 0x34, 0x36, 0x3b, 0x01, 0x05, 0x15, 0x05, 0x23, 0x22, 0x27, 0x26, 0x01, 0x16, 0x15, 0x14, 0x0f, 0x01, 0x01, 0x27, 0x13, 0x37, 0x36, 0x33, 0x32, 0x01, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x01, 0x17, 0x03, 0x07, 0x06, 0x23, 0x22, 0x03, 0x36, 0x33, 0x32, 0x1f, 0x01, 0x13, 0x07, 0x01, 0x27, 0x26, 0x35, 0x34, 0x01, 0x06, 0x22, 0x2f, 0x01, 0x03, 0x37, 0x01, 0x17, 0x16, 0x15, 0x14, 0x00, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x03, 0x23, 0x03, 0x35, 0x34, 0x37, 0x12, 0x14, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x02, 0x22, 0x27, 0x26, 0x3d, 0x01, 0x13, 0x33, 0x13, 0x15, 0x14, 0x07, 0x05, 0xbd, 0x19, 0x1a, 0x24, 0x09, 0xfe, 0x8a, 0x01, 0x76, 0x09, 0x23, 0x1b, 0x19, 0xfa, 0x8f, 0x32, 0x24, 0x09, 0x01, 0x76, 0xfe, 0x8a, 0x09, 0x22, 0x1b, 0x19, 0x04, 0xa5, 0x1b, 0x19, 0x06, 0xfe, 0xd8, 0x40, 0xe8, 0x06, 0x1a, 0x25, 0x25, 0xfc, 0x40, 0x1a, 0x18, 0x07, 0x01, 0x28, 0x40, 0xe9, 0x06, 0x19, 0x25, 0x24, 0x1c, 0x1a, 0x26, 0x24, 0x1a, 0x06, 0xe9, 0x40, 0xfe, 0xd8, 0x07, 0x18, 0x03, 0xf4, 0x1b, 0x49, 0x1a, 0x06, 0xe8, 0x40, 0x01, 0x28, 0x06, 0x19, 0xfd, 0xd3, 0x4a, 0x1b, 0x1a, 0x2d, 0x5a, 0x2d, 0x1a, 0xc7, 0x4f, 0x70, 0x4f, 0x4f, 0x70, 0x13, 0x4a, 0x1b, 0x1a, 0x2d, 0x5a, 0x2d, 0x1a, 0x02, 0xec, 0x2a, 0x1e, 0x1c, 0x32, 0x64, 0x32, 0x1e, 0x1e, 0x28, 0x28, 0x3c, 0x32, 0x64, 0x32, 0x1c, 0x1e, 0x02, 0x4d, 0x1d, 0x2a, 0x27, 0x1d, 0x07, 0xfe, 0xfe, 0x46, 0x01, 0x49, 0x07, 0x1c, 0xfb, 0x9b, 0x1d, 0x2a, 0x27, 0x1d, 0x07, 0x01, 0x02, 0x46, 0xfe, 0xb7, 0x07, 0x1c, 0x04, 0x65, 0x1e, 0x1c, 0x07, 0xfe, 0xb7, 0x46, 0x01, 0x02, 0x07, 0x1b, 0x29, 0x2a, 0xfb, 0xd6, 0x1e, 0x1c, 0x07, 0x01, 0x49, 0x46, 0xfe, 0xfe, 0x07, 0x1b, 0x29, 0x2a, 0x05, 0x0d, 0x1d, 0x1c, 0x28, 0x0a, 0xfe, 0x61, 0x01, 0x9f, 0x0a, 0x27, 0x1d, 0xfd, 0x55, 0x7c, 0x58, 0x58, 0x7c, 0x58, 0xfc, 0x63, 0x1d, 0x1c, 0x28, 0x0a, 0x01, 0x9f, 0xfe, 0x61, 0x0a, 0x27, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4b, 0xff, 0xe5, 0x05, 0xbd, 0x05, 0xf2, 0x00, 0x6c, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x03, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x01, 0x25, 0x36, 0x33, 0x32, 0x17, 0x16, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x25, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x03, 0x13, 0x16, 0x15, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x13, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x05, 0x06, 0x23, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x05, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x16, 0x17, 0x16, 0x17, 0x01, 0x03, 0x26, 0x35, 0x34, 0x37, 0x36, 0x03, 0x04, 0x27, 0x2a, 0x20, 0x05, 0x46, 0x01, 0x00, 0x12, 0x02, 0x2f, 0x2d, 0x3c, 0x1b, 0x1b, 0x2e, 0x09, 0x17, 0xfe, 0xa2, 0x01, 0xaf, 0x17, 0x0a, 0x45, 0x1e, 0x2a, 0x2a, 0x20, 0x43, 0x06, 0x21, 0xfe, 0x57, 0x01, 0x63, 0x19, 0x02, 0x2e, 0x1b, 0x1b, 0x3c, 0x27, 0x35, 0x09, 0x10, 0xfb, 0x46, 0x05, 0x20, 0x2a, 0x4d, 0x2b, 0x1f, 0x04, 0x46, 0xfb, 0x10, 0x09, 0x2f, 0x2d, 0x3b, 0x1c, 0x1b, 0x2f, 0x02, 0x19, 0x01, 0x62, 0xfe, 0x58, 0x22, 0x06, 0x43, 0x20, 0x29, 0x29, 0x1f, 0x44, 0x0b, 0x16, 0x01, 0xaf, 0xfe, 0xa2, 0x16, 0x09, 0x2f, 0x1b, 0x1c, 0x3b, 0x21, 0x3b, 0x02, 0x13, 0x00, 0xff, 0x46, 0x04, 0x1f, 0x2a, 0x05, 0xf2, 0x2f, 0x23, 0x4a, 0x07, 0x1f, 0xfe, 0x22, 0x01, 0x89, 0x1d, 0x01, 0x35, 0x1f, 0x1e, 0x43, 0x37, 0x2f, 0x09, 0x12, 0xfe, 0xe9, 0x4e, 0x04, 0x22, 0x2e, 0x58, 0x2e, 0x24, 0x06, 0x4d, 0xfe, 0xe5, 0x16, 0x01, 0x35, 0x31, 0x43, 0x1e, 0x1f, 0x35, 0x09, 0x19, 0x01, 0x85, 0xfe, 0x22, 0x1f, 0x07, 0x4a, 0x23, 0x2f, 0x2f, 0x23, 0x4a, 0x0e, 0x1e, 0x01, 0xd8, 0xfe, 0x7b, 0x19, 0x09, 0x35, 0x1f, 0x1e, 0x43, 0x4c, 0x1a, 0x01, 0x16, 0x01, 0x1b, 0x4d, 0x06, 0x24, 0x2e, 0x58, 0x2e, 0x22, 0x04, 0x4e, 0x01, 0x17, 0x12, 0x09, 0x35, 0x31, 0x43, 0x1e, 0x1f, 0x14, 0x21, 0x01, 0x1d, 0xfe, 0x77, 0x01, 0xd8, 0x1e, 0x0e, 0x4a, 0x23, 0x2f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5b, 0xff, 0xec, 0x06, 0x19, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x23, 0x00, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x02, 0x24, 0x23, 0x22, 0x04, 0x02, 0x01, 0x06, 0x23, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x17, 0x36, 0x33, 0x32, 0x04, 0x12, 0x15, 0x10, 0x00, 0x21, 0x22, 0xa6, 0x01, 0x68, 0x00, 0xff, 0x01, 0x00, 0x01, 0x67, 0xa4, 0xfe, 0xd9, 0x9c, 0x9b, 0xfe, 0xd8, 0xa4, 0x02, 0x93, 0x16, 0x17, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0x17, 0x16, 0x17, 0x16, 0xae, 0x01, 0x4c, 0xb9, 0xfe, 0x6b, 0xfe, 0xe2, 0x16, 0x02, 0xea, 0xfe, 0xe4, 0xfe, 0x70, 0x01, 0x90, 0x01, 0x1c, 0xb3, 0x01, 0x47, 0xb1, 0xb1, 0xfe, 0xb9, 0xfc, 0x51, 0x02, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0x02, 0x02, 0xc6, 0xfe, 0x90, 0xc8, 0xfe, 0xc1, 0xfe, 0x41, 0x00, 0x02, 0x00, 0x6d, 0xff, 0x9c, 0x06, 0x07, 0x05, 0xd4, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x17, 0x23, 0x11, 0x21, 0x15, 0x33, 0x11, 0x21, 0x05, 0x62, 0xfb, 0x56, 0x10, 0x5a, 0x05, 0x3f, 0x5a, 0xfa, 0xc1, 0x53, 0x05, 0x2e, 0xfa, 0xd2, 0x53, 0x05, 0xd4, 0x64, 0xfa, 0x2c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6d, 0x00, 0x00, 0x06, 0x07, 0x06, 0x38, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x25, 0x15, 0x21, 0x11, 0x33, 0x35, 0x21, 0x11, 0x05, 0x62, 0xfb, 0x56, 0x04, 0xf5, 0xfa, 0xc1, 0x5a, 0x05, 0x3f, 0x53, 0x05, 0x2e, 0xfa, 0xd2, 0x11, 0x64, 0x05, 0xd4, 0x64, 0xfa, 0x2c, 0x00, 0x00, 0x02, 0x00, 0x6d, 0xff, 0x9c, 0x06, 0x07, 0x05, 0xd4, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x07, 0x11, 0x21, 0x17, 0x11, 0x21, 0x05, 0x62, 0xfb, 0x56, 0x4a, 0x05, 0x3f, 0x5a, 0xfa, 0xdc, 0x53, 0x05, 0x2e, 0xfa, 0xd2, 0x53, 0x05, 0xd4, 0x82, 0xfa, 0x4a, 0x00, 0x00, 0x02, 0x00, 0x6d, 0x00, 0x00, 0x06, 0x07, 0x06, 0x38, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x05, 0x21, 0x11, 0x37, 0x21, 0x11, 0x05, 0x62, 0xfb, 0x56, 0x04, 0xf5, 0xfa, 0xc1, 0x75, 0x05, 0x24, 0x53, 0x05, 0x2e, 0xfa, 0xd2, 0x53, 0x05, 0xd4, 0x64, 0xfa, 0x4a, 0x00, 0x04, 0x00, 0x99, 0xff, 0xfb, 0x05, 0xdc, 0x05, 0xd3, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x09, 0x0e, 0x99, 0x01, 0x31, 0x01, 0x31, 0xfe, 0xcf, 0x01, 0xaf, 0x01, 0x32, 0x01, 0x30, 0xfe, 0xd0, 0xfd, 0x60, 0x01, 0x31, 0x01, 0x31, 0xfe, 0xcf, 0xfe, 0xcf, 0x01, 0x31, 0x01, 0x31, 0xfe, 0xcf, 0x02, 0xe9, 0x01, 0x53, 0xfe, 0xad, 0xfe, 0xad, 0x01, 0x53, 0x01, 0x52, 0xfe, 0xae, 0xfe, 0xab, 0x02, 0xea, 0x01, 0x55, 0xfe, 0xab, 0xfe, 0xae, 0xfe, 0x22, 0x01, 0x53, 0xfe, 0xad, 0xfe, 0xad, 0x00, 0x00, 0x00, 0x01, 0x02, 0xb7, 0xfe, 0x14, 0x03, 0x51, 0x06, 0x14, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x03, 0x51, 0x99, 0x06, 0x14, 0xf8, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x02, 0x6b, 0xfe, 0x14, 0x03, 0x9e, 0x06, 0x14, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x03, 0x9d, 0xfe, 0xce, 0x06, 0x14, 0xf8, 0x00, 0x08, 0x00, 0x00, 0x01, 0x01, 0xd2, 0xfe, 0x14, 0x04, 0x37, 0x06, 0x14, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x04, 0x36, 0xfd, 0x9c, 0x06, 0x14, 0xf8, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x9c, 0x03, 0x28, 0x01, 0xe6, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x01, 0x21, 0x11, 0x13, 0x33, 0x03, 0x33, 0x01, 0xe6, 0xfe, 0xb7, 0x93, 0x74, 0x4a, 0x8c, 0x03, 0x28, 0x01, 0x6e, 0x01, 0x3f, 0xfe, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6c, 0x03, 0x28, 0x01, 0xb6, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x13, 0x21, 0x11, 0x03, 0x23, 0x13, 0x23, 0x6c, 0x01, 0x49, 0x93, 0x74, 0x4a, 0x8c, 0x05, 0xd5, 0xfe, 0x92, 0xfe, 0xc1, 0x01, 0x3f, 0xff, 0xff, 0x00, 0x9c, 0x03, 0x28, 0x03, 0x74, 0x05, 0xd5, 0x10, 0x26, 0x0c, 0x34, 0x00, 0x00, 0x10, 0x07, 0x0c, 0x34, 0x01, 0x8e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6c, 0x03, 0x28, 0x03, 0x44, 0x05, 0xd5, 0x10, 0x26, 0x0c, 0x35, 0x00, 0x00, 0x10, 0x07, 0x0c, 0x35, 0x01, 0x8e, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1e, 0xff, 0x42, 0x05, 0x8f, 0x06, 0xcf, 0x00, 0x44, 0x00, 0x48, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x11, 0x21, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x21, 0x35, 0x37, 0x15, 0x21, 0x07, 0x23, 0x11, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x01, 0x11, 0x23, 0x11, 0x02, 0x94, 0x1c, 0x17, 0x18, 0x14, 0x13, 0x15, 0x15, 0x13, 0x14, 0x18, 0x17, 0x18, 0x19, 0x11, 0x11, 0x0f, 0x0f, 0x0e, 0x11, 0x0e, 0x12, 0x0f, 0x15, 0x56, 0x38, 0x41, 0x29, 0x31, 0x2f, 0xfe, 0xec, 0xc8, 0xe4, 0xea, 0xc2, 0x01, 0x14, 0x7f, 0x01, 0x32, 0x7e, 0xb4, 0x48, 0x38, 0x3c, 0x48, 0x46, 0xa0, 0x3d, 0x40, 0x28, 0x2d, 0x2a, 0x2c, 0x2b, 0x22, 0x3d, 0x33, 0x01, 0x7e, 0xab, 0x01, 0xd0, 0x0b, 0x0c, 0x15, 0x14, 0x38, 0x1f, 0x1e, 0x38, 0x14, 0x15, 0x0c, 0x0b, 0x09, 0x08, 0x10, 0x10, 0x27, 0x2e, 0x2a, 0x0e, 0x12, 0x06, 0x09, 0x1b, 0x21, 0x2d, 0x38, 0x81, 0x44, 0x01, 0x5f, 0xee, 0xb8, 0xbe, 0xe8, 0xc8, 0x32, 0xfa, 0x7b, 0xfb, 0xdb, 0x6a, 0xb7, 0x40, 0x46, 0x27, 0x25, 0x19, 0x1a, 0x2e, 0x33, 0x72, 0x40, 0x4d, 0x64, 0x37, 0x2b, 0x1d, 0x18, 0x01, 0x34, 0x02, 0x56, 0xfd, 0xaa, 0x00, 0x00, 0x02, 0x01, 0x74, 0xff, 0xdd, 0x04, 0x94, 0x05, 0xf0, 0x00, 0x15, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x07, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x12, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x03, 0x04, 0x90, 0x6d, 0x26, 0x27, 0x23, 0x23, 0x7b, 0xa0, 0x75, 0x78, 0x9d, 0x7a, 0x23, 0x22, 0x21, 0x2c, 0x54, 0x71, 0x70, 0x2f, 0x2f, 0x28, 0x29, 0x26, 0x26, 0x29, 0x28, 0x2f, 0x2f, 0x70, 0x2e, 0x30, 0x28, 0x28, 0x27, 0x27, 0x28, 0x28, 0x30, 0x05, 0xf0, 0x28, 0x0e, 0x2b, 0x26, 0x61, 0x34, 0x7c, 0x64, 0x83, 0xce, 0xce, 0x83, 0x66, 0x7a, 0x34, 0x61, 0x26, 0x24, 0x15, 0x28, 0xfc, 0x46, 0x16, 0x18, 0x2a, 0x2e, 0x6a, 0x3d, 0x3c, 0x6a, 0x2e, 0x2a, 0x18, 0x16, 0x16, 0x18, 0x2a, 0x2e, 0x6a, 0x3c, 0x3d, 0x6a, 0x2e, 0x2a, 0x18, 0x00, 0x02, 0x01, 0x2c, 0xff, 0xdd, 0x04, 0xdc, 0x05, 0xf0, 0x00, 0x21, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x02, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x03, 0x04, 0x6e, 0xef, 0x7a, 0x23, 0x22, 0x21, 0x2c, 0x29, 0x61, 0x29, 0x2b, 0x22, 0x21, 0x24, 0x24, 0x22, 0x22, 0x2a, 0x29, 0x62, 0x28, 0x2c, 0x21, 0x23, 0x23, 0x7b, 0xef, 0xa6, 0x70, 0x2f, 0x2f, 0x28, 0x29, 0x26, 0x26, 0x29, 0x28, 0x2f, 0x2f, 0x70, 0x2e, 0x30, 0x28, 0x28, 0x27, 0x27, 0x28, 0x28, 0x30, 0x02, 0xad, 0xc4, 0xa1, 0x53, 0x83, 0x34, 0x61, 0x26, 0x24, 0x15, 0x14, 0x14, 0x14, 0x25, 0x25, 0x60, 0x36, 0x36, 0x60, 0x25, 0x25, 0x14, 0x14, 0x14, 0x15, 0x24, 0x26, 0x61, 0x34, 0x84, 0x52, 0xa1, 0xfe, 0xc5, 0x16, 0x18, 0x2a, 0x2e, 0x6a, 0x3d, 0x3c, 0x6a, 0x2e, 0x2a, 0x18, 0x16, 0x16, 0x18, 0x2a, 0x2e, 0x6a, 0x3c, 0x3d, 0x6a, 0x2e, 0x2a, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0xab, 0x05, 0xa6, 0x05, 0x28, 0x00, 0x21, 0x00, 0x00, 0x25, 0x26, 0x25, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x04, 0x03, 0x04, 0x7b, 0xfe, 0x89, 0xaf, 0x31, 0x32, 0x30, 0x3e, 0x3a, 0x8b, 0x3a, 0x3e, 0x30, 0x30, 0x33, 0x34, 0x2f, 0x31, 0x3d, 0x3b, 0x8a, 0x3b, 0x3e, 0x2f, 0x32, 0x31, 0xae, 0xfe, 0x89, 0xab, 0xef, 0xf2, 0x71, 0xb2, 0x4b, 0x8a, 0x36, 0x34, 0x1e, 0x1c, 0x1c, 0x1d, 0x35, 0x34, 0x89, 0x4e, 0x4e, 0x89, 0x34, 0x35, 0x1d, 0x1c, 0x1c, 0x1e, 0x34, 0x36, 0x8a, 0x4b, 0xb4, 0x6f, 0xf2, 0x00, 0x00, 0x01, 0x01, 0x35, 0xff, 0xfe, 0x05, 0x3f, 0x05, 0xd6, 0x00, 0x23, 0x00, 0x00, 0x01, 0x06, 0x03, 0x06, 0x23, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x12, 0x05, 0x3f, 0xd6, 0xda, 0x67, 0xa0, 0x43, 0x7c, 0x30, 0x2f, 0x1b, 0x19, 0x19, 0x19, 0x31, 0x2e, 0x7b, 0x46, 0x46, 0x7b, 0x2e, 0x31, 0x19, 0x19, 0x19, 0x1b, 0x2f, 0x30, 0x7c, 0x43, 0xa2, 0x65, 0xda, 0x02, 0xea, 0x8a, 0xfe, 0x60, 0xc2, 0x36, 0x38, 0x34, 0x46, 0x40, 0x4e, 0x4c, 0x42, 0x44, 0x36, 0x34, 0x3a, 0x38, 0x36, 0x36, 0x44, 0x40, 0x4e, 0x4c, 0x42, 0x44, 0x36, 0x36, 0x38, 0xc2, 0xfe, 0x5e, 0x00, 0x02, 0x00, 0x71, 0x00, 0x2a, 0x05, 0x37, 0x05, 0x9e, 0x00, 0x0d, 0x00, 0x69, 0x00, 0x00, 0x01, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x06, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x05, 0x06, 0x15, 0x14, 0x33, 0x32, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x21, 0x22, 0x27, 0x26, 0x35, 0x10, 0x33, 0x32, 0x17, 0x36, 0x37, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x1f, 0x01, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x03, 0x3b, 0x09, 0x1a, 0x16, 0x30, 0x1b, 0x14, 0x11, 0x27, 0x42, 0x64, 0x13, 0x29, 0x54, 0x4e, 0x6f, 0x36, 0x28, 0xfe, 0xea, 0x8a, 0x5f, 0x68, 0x0f, 0x2d, 0x31, 0x39, 0xfe, 0xe4, 0xb7, 0xa8, 0xb2, 0xeb, 0x5c, 0x49, 0x45, 0x0e, 0x5b, 0xcf, 0x3e, 0x42, 0x4b, 0x39, 0x24, 0x26, 0x17, 0x21, 0x12, 0x1d, 0x16, 0x0d, 0x68, 0x54, 0x6a, 0x5d, 0x2d, 0x44, 0x25, 0x26, 0x46, 0x44, 0x2c, 0x2e, 0x0e, 0x36, 0x4d, 0x45, 0x25, 0x29, 0x13, 0x26, 0x13, 0x1c, 0x32, 0x3b, 0x26, 0x12, 0x81, 0x56, 0x6c, 0x3a, 0x04, 0x67, 0x30, 0x2c, 0x3f, 0x29, 0x21, 0x12, 0x0f, 0x1b, 0x3a, 0x22, 0x39, 0x8c, 0x4a, 0x4f, 0x43, 0x51, 0x3e, 0x5e, 0xda, 0x76, 0x3a, 0x4d, 0x63, 0x2a, 0x84, 0x5a, 0x9c, 0x99, 0xa3, 0xfe, 0x01, 0x65, 0x8d, 0x97, 0x43, 0x30, 0xaa, 0x33, 0x4e, 0x33, 0x35, 0x25, 0x26, 0x1d, 0x17, 0x14, 0x1c, 0x2d, 0x19, 0x4b, 0x74, 0x5c, 0x4b, 0x25, 0x39, 0x53, 0x1f, 0x20, 0x3e, 0x42, 0x57, 0x4e, 0x3d, 0x11, 0x21, 0x24, 0x1f, 0x3f, 0x12, 0x24, 0x15, 0x38, 0x1c, 0x28, 0x46, 0x21, 0x35, 0x7b, 0x5e, 0x3f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x90, 0x01, 0x5a, 0x05, 0x78, 0x04, 0x84, 0x00, 0x09, 0x00, 0x51, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x35, 0x34, 0x01, 0x20, 0x35, 0x34, 0x37, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x16, 0x07, 0x06, 0x07, 0x16, 0x33, 0x32, 0x37, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x35, 0x33, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x32, 0x17, 0x16, 0x17, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x13, 0x16, 0x33, 0x32, 0x35, 0x34, 0x27, 0x26, 0x35, 0x34, 0x33, 0x32, 0x15, 0x14, 0x07, 0x06, 0x01, 0xaf, 0x39, 0x28, 0x3c, 0x18, 0x47, 0x38, 0x37, 0x01, 0xcb, 0xfe, 0xb0, 0x6b, 0x2c, 0x30, 0x22, 0x22, 0x03, 0x01, 0x43, 0x57, 0x5a, 0x17, 0x3c, 0x27, 0x24, 0x07, 0x82, 0x61, 0x12, 0x20, 0x23, 0x1b, 0x5b, 0x45, 0x39, 0x0d, 0x21, 0x1f, 0x37, 0x41, 0x58, 0x0b, 0x81, 0x3b, 0x04, 0x37, 0x25, 0x27, 0x32, 0x1c, 0x37, 0x29, 0x62, 0xc3, 0x33, 0x16, 0x5b, 0x58, 0x0b, 0x0a, 0x48, 0x3c, 0xdf, 0x9e, 0x03, 0x3e, 0x0e, 0x24, 0x33, 0x67, 0x1d, 0x3a, 0x38, 0x34, 0x04, 0xfe, 0x21, 0xfe, 0x45, 0x42, 0x37, 0x1c, 0x14, 0x57, 0x50, 0x66, 0x0f, 0x47, 0x2b, 0x1e, 0x31, 0x4b, 0xab, 0x48, 0x8e, 0x50, 0x3c, 0x02, 0x12, 0x12, 0x12, 0x0e, 0x11, 0x46, 0x66, 0x1d, 0x23, 0x26, 0x54, 0x27, 0x19, 0x13, 0x14, 0x30, 0x50, 0x2b, 0x41, 0x27, 0x1d, 0xfe, 0x93, 0x9a, 0x3c, 0x1e, 0x12, 0x11, 0x1b, 0x3c, 0x51, 0xad, 0x62, 0x46, 0x00, 0x01, 0x01, 0x68, 0xfe, 0xe4, 0x04, 0xab, 0x06, 0x27, 0x00, 0x20, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x15, 0x22, 0x07, 0x06, 0x02, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x04, 0xaa, 0xa7, 0x98, 0x91, 0x7c, 0x79, 0x3f, 0x3d, 0x3d, 0x3a, 0x7e, 0x76, 0x97, 0x98, 0xa7, 0x62, 0x5d, 0x57, 0x95, 0x24, 0x24, 0x24, 0x24, 0x4b, 0x46, 0x5b, 0x59, 0x66, 0xfe, 0xe4, 0x47, 0x43, 0x89, 0x85, 0xa7, 0xa4, 0xbb, 0xbd, 0xa9, 0x9d, 0x8f, 0x86, 0x46, 0x47, 0x2f, 0x43, 0x3e, 0xfe, 0xfa, 0x9b, 0x9c, 0xb8, 0xb1, 0x9c, 0x9b, 0x83, 0x7d, 0x44, 0x43, 0x00, 0x00, 0x01, 0x01, 0x68, 0xfe, 0xe4, 0x04, 0xab, 0x06, 0x27, 0x00, 0x22, 0x00, 0x00, 0x01, 0x30, 0x35, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x02, 0x27, 0x26, 0x23, 0x30, 0x35, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x01, 0x69, 0x67, 0x59, 0x5b, 0x46, 0x4a, 0x24, 0x24, 0x24, 0x24, 0x95, 0x56, 0x5e, 0x62, 0xa7, 0x98, 0x97, 0x77, 0x7e, 0x39, 0x3d, 0x3d, 0x3f, 0x78, 0x7d, 0x91, 0x98, 0xfe, 0xe4, 0x2f, 0x43, 0x44, 0x7d, 0x83, 0x9b, 0x9c, 0xb1, 0xb8, 0x9c, 0x9b, 0x01, 0x06, 0x3e, 0x43, 0x2f, 0x47, 0x46, 0x86, 0x8f, 0x9d, 0xa9, 0xbd, 0xbb, 0xa4, 0xa7, 0x85, 0x89, 0x43, 0x47, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe6, 0xfe, 0xf1, 0x04, 0x23, 0x06, 0x11, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x06, 0x02, 0x10, 0x12, 0x17, 0x21, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x04, 0x22, 0x78, 0x75, 0x76, 0x77, 0xfe, 0xd2, 0x87, 0x86, 0x85, 0x88, 0x06, 0x11, 0xe6, 0xfe, 0x3e, 0xfe, 0x32, 0xfe, 0x3b, 0xe5, 0xeb, 0x01, 0xc6, 0xe0, 0xdf, 0x01, 0xc4, 0xec, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xe6, 0xfe, 0xf1, 0x04, 0x23, 0x06, 0x11, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x30, 0x21, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x21, 0x36, 0x12, 0x10, 0x02, 0x01, 0xe7, 0x01, 0x2e, 0x88, 0x85, 0x86, 0x87, 0xfe, 0xd2, 0x78, 0x75, 0x74, 0x06, 0x11, 0xec, 0xfe, 0x3c, 0xdf, 0xe0, 0xfe, 0x3a, 0xeb, 0xe5, 0x01, 0xc5, 0x01, 0xce, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8c, 0xfe, 0x14, 0x04, 0x5f, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x09, 0x01, 0x21, 0x01, 0x04, 0x5f, 0xfe, 0xf9, 0xfe, 0x35, 0x01, 0xcb, 0x01, 0x07, 0xfe, 0x33, 0xfe, 0x14, 0x04, 0x00, 0x04, 0x00, 0xfc, 0x00, 0x00, 0x01, 0x01, 0xab, 0xfe, 0x14, 0x04, 0x7d, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x09, 0x02, 0x21, 0x09, 0x01, 0x01, 0xac, 0x01, 0xcb, 0xfe, 0x35, 0x01, 0x05, 0x01, 0xcb, 0xfe, 0x35, 0xfe, 0x14, 0x04, 0x00, 0x04, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0xfe, 0x14, 0x04, 0xef, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x09, 0x01, 0x21, 0x01, 0x04, 0xef, 0xfe, 0x69, 0xfd, 0xae, 0x02, 0x52, 0x01, 0x97, 0xfd, 0xa3, 0xfe, 0x14, 0x04, 0x00, 0x04, 0x00, 0xfc, 0x00, 0x00, 0x01, 0x01, 0x19, 0xfe, 0x14, 0x05, 0x03, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x09, 0x02, 0x21, 0x09, 0x01, 0x01, 0x1a, 0x02, 0x5c, 0xfd, 0xa4, 0x01, 0x96, 0x02, 0x52, 0xfd, 0xae, 0xfe, 0x14, 0x04, 0x00, 0x04, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x32, 0xfe, 0x14, 0x04, 0xb9, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x01, 0x21, 0x09, 0x01, 0x21, 0x01, 0x04, 0xb9, 0xfe, 0x45, 0xfe, 0x35, 0x01, 0xcb, 0x01, 0xbb, 0xfe, 0x33, 0xfe, 0x14, 0x04, 0x00, 0x04, 0x00, 0xfc, 0x00, 0x00, 0x01, 0x01, 0x51, 0xfe, 0x14, 0x04, 0xd7, 0x06, 0x14, 0x00, 0x05, 0x00, 0x00, 0x09, 0x02, 0x21, 0x09, 0x01, 0x01, 0x52, 0x01, 0xcb, 0xfe, 0x35, 0x01, 0xb9, 0x01, 0xcb, 0xfe, 0x35, 0xfe, 0x14, 0x04, 0x00, 0x04, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x7d, 0xfe, 0x13, 0x03, 0xdb, 0x06, 0x14, 0x00, 0x07, 0x00, 0x00, 0x05, 0x17, 0x07, 0x03, 0x11, 0x13, 0x17, 0x07, 0x03, 0x04, 0xd6, 0x5f, 0xfe, 0xfe, 0x5f, 0xd6, 0x95, 0xee, 0x6a, 0x01, 0x1a, 0x05, 0xcd, 0x01, 0x1a, 0x6a, 0xee, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x2e, 0xfe, 0x13, 0x03, 0x8c, 0x06, 0x14, 0x00, 0x07, 0x00, 0x00, 0x01, 0x27, 0x37, 0x13, 0x11, 0x03, 0x27, 0x37, 0x03, 0x04, 0xd6, 0x5f, 0xfe, 0xfe, 0x5f, 0xd6, 0x04, 0xbc, 0xee, 0x6a, 0xfe, 0xe6, 0xfa, 0x33, 0xfe, 0xe6, 0x6a, 0xee, 0x00, 0x00, 0x00, 0x01, 0x01, 0x42, 0xfe, 0xb2, 0x04, 0x92, 0x06, 0x14, 0x00, 0x24, 0x00, 0x00, 0x05, 0x15, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x1d, 0x01, 0x14, 0x16, 0x33, 0x04, 0x91, 0xbf, 0xe0, 0x98, 0x61, 0x80, 0x37, 0x37, 0x81, 0x60, 0x98, 0xe0, 0xbf, 0x3d, 0x7f, 0x4d, 0x52, 0x63, 0x64, 0x51, 0x4d, 0x7f, 0xbe, 0x90, 0x94, 0xdd, 0xef, 0x97, 0x74, 0x8f, 0x73, 0x95, 0xf0, 0xdd, 0x93, 0x8f, 0x58, 0x8d, 0xf8, 0x9d, 0x8e, 0x19, 0x1b, 0x8e, 0x9c, 0xf8, 0x8d, 0x58, 0x00, 0x01, 0x01, 0x77, 0xfe, 0xb2, 0x04, 0xc7, 0x06, 0x14, 0x00, 0x24, 0x00, 0x00, 0x05, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x34, 0x36, 0x37, 0x2e, 0x01, 0x3d, 0x01, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x16, 0x1d, 0x01, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x14, 0x06, 0x2b, 0x01, 0x01, 0x77, 0x3d, 0x7f, 0x4e, 0x51, 0x64, 0x63, 0x52, 0x4e, 0x7f, 0x3d, 0xbf, 0xe0, 0x98, 0x61, 0x80, 0x37, 0x37, 0x7f, 0x62, 0x98, 0xe0, 0xbf, 0xbe, 0x58, 0x8d, 0xf8, 0x9c, 0x8e, 0x1b, 0x19, 0x8e, 0x9d, 0xf8, 0x8d, 0x58, 0x8f, 0x93, 0xdd, 0xf0, 0x95, 0x73, 0x8f, 0x74, 0x97, 0xef, 0xdd, 0x94, 0x00, 0x02, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x18, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x01, 0x21, 0x35, 0x23, 0x11, 0x23, 0x07, 0x15, 0x37, 0x11, 0x23, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfc, 0x3e, 0x02, 0x2b, 0xc4, 0x91, 0xe8, 0xd5, 0xc3, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xfd, 0x5c, 0x8e, 0x03, 0x1a, 0x2f, 0x98, 0x2b, 0xfd, 0x82, 0x00, 0x00, 0x02, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x0e, 0x01, 0x07, 0x15, 0x21, 0x35, 0x21, 0x3e, 0x01, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfe, 0x1b, 0x38, 0x2b, 0xb1, 0x93, 0x36, 0x83, 0x57, 0x67, 0x77, 0x35, 0x46, 0x56, 0x2b, 0x37, 0x1e, 0xec, 0x4a, 0x02, 0x61, 0xfe, 0x77, 0x71, 0xa0, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xe9, 0x46, 0x69, 0x3a, 0x7d, 0x97, 0x1f, 0x24, 0xab, 0x3a, 0x26, 0x4e, 0x3f, 0x28, 0x55, 0x3f, 0x22, 0xf1, 0x4d, 0x81, 0x8e, 0x74, 0xa7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x36, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x25, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x15, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x15, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x36, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfe, 0xa2, 0xad, 0x91, 0x37, 0x7b, 0x55, 0x60, 0x6d, 0x2f, 0x52, 0x53, 0x50, 0x50, 0x83, 0x7e, 0x59, 0x60, 0x67, 0x69, 0x3e, 0x70, 0x52, 0x4f, 0x7b, 0x39, 0xb0, 0xc2, 0x6a, 0x0c, 0x04, 0x5d, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0x18, 0x73, 0x89, 0x14, 0x18, 0x97, 0x20, 0x15, 0x3f, 0x3c, 0x3a, 0x3c, 0x8c, 0x4e, 0x47, 0x4c, 0x4f, 0x1c, 0x30, 0xa8, 0x1b, 0x17, 0x9c, 0x8d, 0x5d, 0x81, 0x03, 0x72, 0x00, 0x00, 0x00, 0x03, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x10, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x01, 0x23, 0x13, 0x01, 0x15, 0x21, 0x15, 0x33, 0x35, 0x33, 0x35, 0x23, 0x11, 0x23, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfd, 0x60, 0xf2, 0xf2, 0xfe, 0x70, 0x01, 0x90, 0xa4, 0x7f, 0x7f, 0xb9, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xfe, 0xbc, 0x01, 0x7e, 0xfe, 0x83, 0x8e, 0xd3, 0xd3, 0x8d, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x05, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x15, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x37, 0x35, 0x21, 0x35, 0x21, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfc, 0x57, 0x50, 0x5b, 0x2d, 0x5d, 0x6a, 0x6a, 0x5d, 0x3d, 0x6c, 0x55, 0x4f, 0x78, 0x39, 0xab, 0xc0, 0xba, 0x9f, 0x1b, 0x39, 0x03, 0x01, 0x68, 0xfd, 0xfd, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xf3, 0x25, 0x14, 0x61, 0x56, 0x55, 0x61, 0x1b, 0x2f, 0xac, 0x18, 0x14, 0xac, 0x98, 0x95, 0xb0, 0x0a, 0x01, 0xab, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x32, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x03, 0x22, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x35, 0x2e, 0x01, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfd, 0xde, 0x53, 0x46, 0x46, 0x53, 0x53, 0x46, 0x46, 0x53, 0x66, 0xb4, 0xd2, 0xad, 0xa6, 0x90, 0xaf, 0xa8, 0x90, 0x46, 0x73, 0x08, 0x05, 0x72, 0x6b, 0x2a, 0x58, 0x4b, 0x42, 0x60, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xfe, 0x8f, 0x5a, 0x62, 0x62, 0x5a, 0x5b, 0x62, 0x62, 0x02, 0x2a, 0xfe, 0xf5, 0xda, 0xe7, 0xfd, 0xb3, 0x91, 0x94, 0xb1, 0x3d, 0x0b, 0x50, 0x94, 0x16, 0x23, 0x9c, 0x18, 0x13, 0x00, 0x00, 0x02, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x25, 0x21, 0x01, 0x33, 0x01, 0x35, 0x21, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfc, 0x2e, 0x01, 0xa1, 0xfe, 0xd1, 0xad, 0x01, 0x48, 0xfd, 0x99, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0x76, 0xfc, 0xe6, 0x03, 0x5d, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x31, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x0e, 0x01, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfd, 0xf3, 0x56, 0x4b, 0x4c, 0x55, 0x55, 0x4c, 0x4b, 0x56, 0xfe, 0x18, 0xab, 0x9c, 0x9c, 0xaa, 0x6a, 0x0d, 0x03, 0x5f, 0xa4, 0x8d, 0x8e, 0xa4, 0x5f, 0x04, 0x0e, 0x6a, 0x01, 0x47, 0x43, 0x4a, 0x4a, 0x43, 0x46, 0x48, 0x48, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xfe, 0x6c, 0x48, 0x51, 0x50, 0x49, 0x49, 0x50, 0x50, 0x49, 0x8a, 0x97, 0x97, 0x8a, 0x5c, 0x83, 0x03, 0x01, 0x76, 0x53, 0x74, 0x88, 0x88, 0x74, 0x53, 0x76, 0x01, 0x03, 0x83, 0x01, 0xc4, 0x42, 0x3e, 0x3d, 0x42, 0x42, 0x3d, 0x3e, 0x42, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x26, 0x00, 0x32, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x01, 0x32, 0x12, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x15, 0x1e, 0x01, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfd, 0x22, 0xb4, 0xd2, 0xac, 0xa7, 0x90, 0xae, 0xa7, 0x8f, 0x47, 0x74, 0x09, 0x05, 0x72, 0x6b, 0x2a, 0x57, 0x4c, 0x42, 0x60, 0x36, 0x53, 0x46, 0x47, 0x52, 0x52, 0x47, 0x46, 0x53, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xfd, 0x4b, 0x01, 0x0a, 0xda, 0xe8, 0xfd, 0xb4, 0x91, 0x94, 0xaf, 0x3c, 0x0d, 0x4f, 0x93, 0x15, 0x24, 0x9c, 0x18, 0x13, 0x02, 0x84, 0x5b, 0x62, 0x62, 0x5b, 0x5b, 0x62, 0x62, 0x00, 0x00, 0x04, 0x00, 0x88, 0xff, 0xec, 0x05, 0xec, 0x05, 0xe8, 0x00, 0x0d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x12, 0x24, 0x33, 0x32, 0x04, 0x12, 0x01, 0x21, 0x35, 0x23, 0x11, 0x23, 0x07, 0x15, 0x37, 0x11, 0x23, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x05, 0xec, 0xfe, 0x6c, 0xfe, 0xe1, 0xfe, 0xe4, 0xfe, 0x6c, 0xb9, 0x01, 0x4c, 0xab, 0xae, 0x01, 0x4c, 0xb9, 0xfb, 0xa0, 0x01, 0x95, 0x8f, 0x69, 0xaa, 0x9b, 0x8e, 0x03, 0x2e, 0x3e, 0x39, 0x3a, 0x3e, 0x3e, 0x3a, 0x39, 0x3e, 0xfe, 0x98, 0x7b, 0x76, 0x75, 0x7a, 0x7a, 0x75, 0x76, 0x7b, 0x02, 0xea, 0xfe, 0xc1, 0xfe, 0x41, 0x01, 0xbf, 0x01, 0x3f, 0xc6, 0x01, 0x72, 0xc6, 0xc6, 0xfe, 0x90, 0xfd, 0xa9, 0x80, 0x02, 0xca, 0x2a, 0x89, 0x27, 0xfd, 0xc2, 0x01, 0x24, 0xa2, 0x97, 0x97, 0xa2, 0xa3, 0x97, 0x97, 0xa3, 0xd0, 0xe4, 0xe4, 0xd0, 0xd1, 0xe4, 0xe4, 0x00, 0x03, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x24, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x01, 0x33, 0x11, 0x05, 0x35, 0x25, 0x33, 0x11, 0x33, 0x15, 0x21, 0x12, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0xfd, 0xe2, 0xed, 0xfe, 0xfe, 0x01, 0x01, 0x91, 0xee, 0xfd, 0x95, 0x7f, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0xfb, 0x7d, 0x03, 0x8f, 0x39, 0x93, 0x3a, 0xfb, 0xdd, 0x88, 0x05, 0xa8, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x36, 0x00, 0x50, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x01, 0x21, 0x15, 0x21, 0x35, 0x36, 0x00, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x0e, 0x01, 0x02, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0xfe, 0x59, 0x01, 0xfb, 0xfd, 0x56, 0x53, 0x01, 0x1d, 0x25, 0x46, 0x37, 0x78, 0x60, 0x48, 0x95, 0x56, 0x57, 0x99, 0x3f, 0xa8, 0xc7, 0x32, 0x42, 0x12, 0xc1, 0xa7, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0xfb, 0x80, 0x88, 0x88, 0x5f, 0x01, 0x41, 0x2e, 0x58, 0x78, 0x3b, 0x5f, 0x78, 0x35, 0x35, 0xa3, 0x27, 0x28, 0xba, 0x9b, 0x49, 0x84, 0x5a, 0x17, 0xde, 0x04, 0x56, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x42, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x03, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x68, 0x68, 0x76, 0xda, 0xca, 0x44, 0x8f, 0x4d, 0x3d, 0x90, 0x4e, 0x89, 0x8f, 0x85, 0x77, 0x7d, 0x83, 0x6c, 0x71, 0x75, 0x6e, 0x3b, 0x89, 0x53, 0x4a, 0x9a, 0x40, 0xa7, 0xc0, 0x66, 0xfe, 0x6a, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0xfd, 0x79, 0x19, 0x9c, 0x74, 0xb0, 0xc2, 0x1e, 0x1d, 0x9c, 0x27, 0x28, 0x78, 0x72, 0x6a, 0x77, 0x85, 0x5f, 0x5a, 0x5c, 0x62, 0x1d, 0x1e, 0x90, 0x17, 0x1c, 0xa7, 0x8e, 0x64, 0x88, 0x03, 0x09, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x04, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x1c, 0x00, 0x27, 0x00, 0x41, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x07, 0x01, 0x21, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x21, 0x35, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0xc7, 0xfe, 0x90, 0x01, 0x70, 0x26, 0xb6, 0x9a, 0x9a, 0x90, 0xfe, 0x1a, 0x01, 0x0e, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0xed, 0xfd, 0x82, 0x03, 0x0b, 0xfc, 0xf5, 0x86, 0xfe, 0xe6, 0x01, 0x1a, 0x9c, 0x03, 0xf2, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x03, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x37, 0x00, 0x51, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x05, 0x21, 0x15, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x12, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0xfd, 0xe0, 0x02, 0x3b, 0xfe, 0x4a, 0x20, 0x40, 0x1f, 0xb4, 0xd2, 0xd8, 0xc5, 0x43, 0x8c, 0x4b, 0x44, 0x86, 0x4e, 0x7c, 0x92, 0x92, 0x7c, 0x3b, 0x74, 0x3c, 0x81, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0x63, 0x88, 0xfe, 0xdb, 0x0c, 0x0c, 0xdb, 0xbb, 0xc1, 0xd6, 0x1a, 0x19, 0xa3, 0x29, 0x25, 0x92, 0x7d, 0x7c, 0x92, 0x1d, 0x1e, 0x03, 0x58, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x25, 0x00, 0x3e, 0x00, 0x58, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x13, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x16, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0xfe, 0xf4, 0x61, 0x73, 0x73, 0x61, 0x62, 0x73, 0x73, 0xbf, 0x37, 0x6f, 0x36, 0x90, 0x98, 0x0b, 0x2a, 0x80, 0x4d, 0xa2, 0xbc, 0xc4, 0xa3, 0xba, 0xc5, 0xf2, 0xcb, 0x37, 0x70, 0xfe, 0x88, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0xfd, 0x8b, 0x95, 0x82, 0x80, 0x96, 0x96, 0x80, 0x82, 0x95, 0x01, 0xfa, 0x93, 0x1d, 0x1e, 0xd8, 0xda, 0x45, 0x4b, 0xdb, 0xbc, 0xb8, 0xde, 0x01, 0x3e, 0x01, 0x2d, 0x01, 0x1d, 0x01, 0x4f, 0x18, 0x01, 0x00, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x20, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x05, 0x21, 0x15, 0x01, 0x23, 0x01, 0x21, 0x12, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0xfd, 0xa0, 0x02, 0xb3, 0xfe, 0x7a, 0x98, 0x01, 0x70, 0xfd, 0xfb, 0xc1, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0x60, 0x45, 0xfb, 0x9a, 0x04, 0x23, 0x01, 0x85, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x23, 0x00, 0x39, 0x00, 0x45, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x01, 0x22, 0x06, 0x14, 0x16, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x20, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x20, 0x26, 0x35, 0x34, 0x36, 0x13, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x12, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0xfe, 0xfc, 0x67, 0x77, 0x77, 0xcf, 0x77, 0x76, 0xfa, 0x5e, 0x68, 0xb7, 0x01, 0x41, 0xb7, 0x68, 0x5e, 0x69, 0x76, 0xbe, 0xfe, 0x9b, 0xbf, 0x77, 0x33, 0x69, 0x5e, 0x5e, 0x6a, 0x6a, 0x5e, 0x5e, 0x69, 0x2c, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0xfd, 0x2c, 0x7b, 0xd8, 0x7b, 0x7c, 0x6b, 0x6c, 0x7b, 0x45, 0x1a, 0x8e, 0x67, 0x8f, 0xa6, 0xa6, 0x8f, 0x67, 0x8e, 0x1a, 0x1b, 0x9e, 0x73, 0xad, 0xba, 0xba, 0xad, 0x73, 0x9e, 0x01, 0x1a, 0x5c, 0x68, 0x68, 0x5c, 0x5d, 0x68, 0x68, 0x01, 0xd0, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x04, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x19, 0x00, 0x32, 0x00, 0x3e, 0x00, 0x58, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x01, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x02, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x62, 0x62, 0x64, 0x62, 0x77, 0xfd, 0xe3, 0x37, 0x70, 0x36, 0x90, 0x98, 0x0b, 0x2a, 0x80, 0x4e, 0xa2, 0xbb, 0xc4, 0xa2, 0xbc, 0xc4, 0xf1, 0xcc, 0x37, 0x70, 0xe4, 0x63, 0x72, 0x72, 0x63, 0x61, 0x73, 0x73, 0x42, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0xfe, 0xf7, 0x9c, 0x97, 0xfe, 0xf7, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x01, 0x09, 0x97, 0x9c, 0x01, 0x09, 0x6f, 0x6f, 0x36, 0xfb, 0x0e, 0x93, 0x1d, 0x1e, 0xd7, 0xdb, 0x44, 0x4a, 0xd9, 0xbc, 0xb8, 0xde, 0xfe, 0xc3, 0xfe, 0xd1, 0xfe, 0xe6, 0xfe, 0xaf, 0x18, 0x02, 0x12, 0x95, 0x82, 0x81, 0x95, 0x95, 0x81, 0x82, 0x95, 0x03, 0x95, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x1d, 0x00, 0x2b, 0x00, 0x38, 0x00, 0x43, 0x00, 0x61, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x07, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x2e, 0x01, 0x20, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x20, 0x02, 0x11, 0x10, 0x37, 0x01, 0x33, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x33, 0x15, 0x21, 0x12, 0x20, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x03, 0x8f, 0xfe, 0xeb, 0x79, 0x77, 0x62, 0x64, 0x30, 0x32, 0x32, 0x30, 0x64, 0x62, 0x77, 0x79, 0x01, 0x15, 0x78, 0x77, 0x62, 0x64, 0x30, 0x32, 0x32, 0x30, 0x64, 0x62, 0x77, 0x1a, 0x4b, 0x28, 0x27, 0x4e, 0x4c, 0x4e, 0x4d, 0x27, 0x26, 0xd7, 0x01, 0x13, 0x49, 0x48, 0x48, 0x49, 0xfe, 0xed, 0x90, 0x48, 0xfe, 0x61, 0x7f, 0x87, 0x86, 0x74, 0x76, 0xfe, 0x98, 0xeb, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x36, 0x38, 0x38, 0x36, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x36, 0x39, 0x39, 0x36, 0x71, 0x70, 0x87, 0x05, 0xd9, 0x39, 0x36, 0x6f, 0x6f, 0x83, 0x86, 0x9c, 0x97, 0x86, 0x83, 0x6f, 0x6f, 0x36, 0x39, 0x39, 0x36, 0x6f, 0x6f, 0x83, 0x86, 0x97, 0x9c, 0x86, 0x83, 0x6f, 0x6f, 0x36, 0xcb, 0x7b, 0x7a, 0xf7, 0xf5, 0xf6, 0xf6, 0xf5, 0xf3, 0x7e, 0x7b, 0x80, 0x9f, 0x9e, 0xfe, 0xd1, 0xfe, 0xd3, 0x9f, 0x9f, 0x01, 0x3e, 0x01, 0x2d, 0x01, 0x2c, 0xa1, 0xfc, 0x67, 0x03, 0x8f, 0x25, 0x93, 0x26, 0xfb, 0xdd, 0x88, 0x05, 0xa8, 0x40, 0x3e, 0x7d, 0x7e, 0x95, 0x97, 0xb1, 0xac, 0x97, 0x95, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x95, 0x97, 0xac, 0xb1, 0x97, 0x95, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x0a, 0x00, 0x24, 0x00, 0x00, 0x01, 0x15, 0x21, 0x35, 0x23, 0x11, 0x23, 0x05, 0x15, 0x25, 0x11, 0x02, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x01, 0xe9, 0x02, 0x6b, 0xee, 0x91, 0xfe, 0xff, 0x01, 0x02, 0x6e, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x01, 0x1d, 0x88, 0x88, 0x04, 0x23, 0x3a, 0x93, 0x39, 0xfc, 0x71, 0x05, 0x20, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x02, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x1c, 0x00, 0x36, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x06, 0x00, 0x07, 0x15, 0x21, 0x35, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x02, 0x60, 0xaf, 0xc1, 0x12, 0x42, 0x32, 0xc7, 0xa8, 0x3f, 0x99, 0x57, 0x56, 0x99, 0x44, 0x60, 0x78, 0x37, 0x46, 0x25, 0xfe, 0xe3, 0x53, 0x02, 0xaa, 0xfe, 0x0d, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x01, 0x20, 0xc7, 0xde, 0x17, 0x5a, 0x84, 0x49, 0x9b, 0xba, 0x28, 0x27, 0xa3, 0x35, 0x35, 0x78, 0x5f, 0x3b, 0x78, 0x58, 0x2e, 0xfe, 0xbf, 0x5f, 0x88, 0x88, 0x05, 0x1d, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x02, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x28, 0x00, 0x42, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x15, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x15, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x9f, 0x5f, 0x66, 0xc1, 0xa6, 0x40, 0x91, 0x53, 0x53, 0x89, 0x3b, 0x6e, 0x75, 0x71, 0x6c, 0x83, 0x7d, 0x77, 0x85, 0x8f, 0x89, 0x4e, 0x90, 0x3d, 0x4d, 0x8f, 0x44, 0xca, 0xda, 0x76, 0xfe, 0x61, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x03, 0x19, 0x1b, 0x88, 0x64, 0x8e, 0xa7, 0x19, 0x1a, 0x90, 0x1e, 0x1d, 0x62, 0x5c, 0x5a, 0x5f, 0x85, 0x77, 0x6a, 0x72, 0x78, 0x28, 0x27, 0x9c, 0x1d, 0x1e, 0xc2, 0xb0, 0x74, 0x9c, 0x03, 0x3d, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x27, 0x00, 0x00, 0x01, 0x11, 0x21, 0x09, 0x01, 0x15, 0x21, 0x11, 0x33, 0x11, 0x33, 0x35, 0x23, 0x11, 0x24, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x40, 0xfe, 0x90, 0x01, 0x4a, 0xfe, 0x40, 0x01, 0xe6, 0x90, 0x9a, 0x9a, 0xfe, 0x98, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x04, 0xb3, 0xfd, 0x82, 0x03, 0x0b, 0xfd, 0x0b, 0x9c, 0xfe, 0xe6, 0x01, 0x1a, 0x86, 0x03, 0x0b, 0xfd, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x02, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x1d, 0x00, 0x37, 0x00, 0x00, 0x01, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x15, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x11, 0x21, 0x35, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x01, 0xe7, 0x3c, 0x74, 0x3b, 0x7c, 0x92, 0x92, 0x7c, 0x4e, 0x89, 0x41, 0x4b, 0x8c, 0x43, 0xc5, 0xd8, 0xd2, 0xb4, 0x1f, 0x40, 0x20, 0x01, 0xb6, 0xfe, 0x46, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0x3d, 0xfd, 0xa8, 0x1e, 0x1d, 0x92, 0x7c, 0x7d, 0x92, 0x27, 0x27, 0xa3, 0x19, 0x1a, 0xd6, 0xc1, 0xbb, 0xdb, 0x0c, 0x0c, 0x01, 0x25, 0x88, 0x01, 0x00, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x0b, 0x00, 0x24, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x02, 0xfb, 0x62, 0x73, 0x73, 0x62, 0x61, 0x73, 0x73, 0x01, 0x82, 0x3c, 0x70, 0x37, 0xcb, 0xf2, 0xc5, 0xba, 0xa3, 0xc4, 0xbc, 0xa2, 0x4d, 0x80, 0x2a, 0x0b, 0x98, 0x90, 0x36, 0x6f, 0x37, 0xfe, 0x4c, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x03, 0x2b, 0x95, 0x82, 0x80, 0x96, 0x96, 0x80, 0x82, 0x95, 0x01, 0xfa, 0x18, 0x18, 0xfe, 0xaf, 0xfe, 0xe5, 0xfe, 0xd3, 0xfe, 0xc2, 0xde, 0xb8, 0xbc, 0xdb, 0x4b, 0x45, 0xda, 0xd8, 0x1e, 0x1d, 0x01, 0xab, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x06, 0x00, 0x20, 0x00, 0x00, 0x01, 0x15, 0x21, 0x01, 0x33, 0x01, 0x35, 0x24, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x01, 0xa7, 0x02, 0x05, 0xfe, 0x90, 0x98, 0x01, 0x86, 0xfe, 0x0e, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x05, 0x40, 0x88, 0xfb, 0xdd, 0x04, 0x66, 0x45, 0xfd, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x04, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x09, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x45, 0x00, 0x00, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x22, 0x26, 0x34, 0x36, 0x27, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x20, 0x36, 0x35, 0x34, 0x26, 0x27, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x20, 0x06, 0x15, 0x14, 0x16, 0x37, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x12, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x03, 0x03, 0x69, 0x76, 0x77, 0xcf, 0x77, 0x77, 0x2a, 0x69, 0x77, 0xbf, 0x01, 0x65, 0xbe, 0x76, 0x69, 0x5e, 0x68, 0xb7, 0xfe, 0xbf, 0xb7, 0x68, 0x28, 0x69, 0x5e, 0x5e, 0x6a, 0x6a, 0x5e, 0x5e, 0x69, 0x2c, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x02, 0xcc, 0x7b, 0x6c, 0x6b, 0x7c, 0x7b, 0xd8, 0x7b, 0x45, 0x1b, 0x9e, 0x73, 0xad, 0xba, 0xba, 0xad, 0x73, 0x9e, 0x1b, 0x1a, 0x8e, 0x67, 0x8f, 0xa6, 0xa6, 0x8f, 0x67, 0x8e, 0xe5, 0x5d, 0x68, 0x68, 0x5d, 0x5c, 0x68, 0x68, 0x02, 0x89, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x3e, 0x00, 0x00, 0x25, 0x1e, 0x01, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x00, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x01, 0xea, 0x3d, 0x70, 0x37, 0xcc, 0xf1, 0xc4, 0xbc, 0xa2, 0xc4, 0xbc, 0xa1, 0x4e, 0x80, 0x2a, 0x0b, 0x98, 0x90, 0x36, 0x70, 0x37, 0x01, 0x21, 0x61, 0x73, 0x73, 0x61, 0x63, 0x72, 0x72, 0xfe, 0xfa, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0xae, 0x18, 0x18, 0x01, 0x51, 0x01, 0x1a, 0x01, 0x2f, 0x01, 0x3d, 0xde, 0xb8, 0xbc, 0xd9, 0x4a, 0x44, 0xdb, 0xd7, 0x1e, 0x1d, 0x01, 0x67, 0x95, 0x82, 0x81, 0x95, 0x95, 0x81, 0x82, 0x95, 0x03, 0x95, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0xff, 0x96, 0x06, 0x01, 0x06, 0x3d, 0x00, 0x0b, 0x00, 0x15, 0x00, 0x20, 0x00, 0x3a, 0x00, 0x00, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x01, 0x20, 0x02, 0x11, 0x10, 0x12, 0x20, 0x12, 0x11, 0x10, 0x01, 0x15, 0x21, 0x35, 0x23, 0x11, 0x23, 0x07, 0x15, 0x37, 0x11, 0x12, 0x20, 0x17, 0x16, 0x17, 0x16, 0x12, 0x15, 0x14, 0x02, 0x07, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x27, 0x26, 0x02, 0x35, 0x34, 0x12, 0x37, 0x36, 0x37, 0x04, 0x23, 0x5b, 0x5a, 0x5a, 0x5b, 0x5a, 0x5a, 0x5a, 0xeb, 0xfe, 0xde, 0x98, 0x98, 0x01, 0x22, 0x99, 0xfc, 0x03, 0x01, 0x95, 0x91, 0x74, 0xa1, 0xa2, 0x87, 0x01, 0x39, 0x89, 0x87, 0x6f, 0x72, 0x6e, 0x6e, 0x72, 0x6f, 0x87, 0x89, 0xfe, 0xc7, 0x89, 0x87, 0x70, 0x71, 0x6f, 0x6f, 0x71, 0x70, 0x87, 0x04, 0xd5, 0xf5, 0xf7, 0xf5, 0xf6, 0xf6, 0xf5, 0xf7, 0xf5, 0x80, 0xfe, 0xc3, 0xfe, 0xd1, 0xfe, 0xd3, 0xfe, 0xc2, 0x01, 0x3e, 0x01, 0x2d, 0x01, 0x2f, 0xfd, 0x05, 0x88, 0x88, 0x04, 0x23, 0x26, 0x93, 0x25, 0xfc, 0x71, 0x05, 0x20, 0x40, 0x3e, 0x7d, 0x7e, 0xfe, 0xd4, 0xb1, 0xac, 0xfe, 0xd4, 0x7e, 0x7d, 0x3e, 0x40, 0x40, 0x3e, 0x7d, 0x7e, 0x01, 0x2c, 0xac, 0xb1, 0x01, 0x2c, 0x7e, 0x7d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0x9a, 0x05, 0xaf, 0x04, 0x6a, 0x00, 0x08, 0x00, 0x00, 0x09, 0x01, 0x21, 0x01, 0x21, 0x35, 0x21, 0x01, 0x21, 0x05, 0xae, 0xfe, 0x49, 0xfe, 0xe0, 0x01, 0x4b, 0xfc, 0x47, 0x03, 0xb9, 0xfe, 0xb5, 0x01, 0x20, 0x02, 0x82, 0xfe, 0x18, 0x01, 0x70, 0xf0, 0x01, 0x70, 0x00, 0x01, 0x00, 0xe2, 0x00, 0x70, 0x04, 0xe9, 0x04, 0xe9, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x37, 0x01, 0x1b, 0x01, 0x25, 0x03, 0x92, 0xfd, 0x51, 0x98, 0x02, 0x70, 0xbe, 0x3f, 0xfd, 0x93, 0x01, 0x8b, 0x02, 0xb4, 0xaa, 0xfd, 0x05, 0x01, 0x34, 0xfd, 0x4e, 0x47, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x06, 0x00, 0x00, 0x01, 0x05, 0x35, 0x05, 0x03, 0x09, 0x01, 0x04, 0x07, 0xfc, 0x62, 0x03, 0x9e, 0x3d, 0x01, 0xe4, 0xfe, 0x1c, 0x02, 0x3c, 0x32, 0xf0, 0x32, 0x01, 0x70, 0xfe, 0x4a, 0xfe, 0x4a, 0x00, 0x00, 0x01, 0x00, 0xe2, 0x00, 0x1b, 0x04, 0xe9, 0x04, 0x94, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x27, 0x01, 0x2d, 0x01, 0x03, 0x03, 0xeb, 0xfd, 0x90, 0x98, 0x02, 0xaf, 0xfe, 0xe9, 0x02, 0x6d, 0x3f, 0x03, 0x16, 0xfd, 0x05, 0xaa, 0x02, 0xb4, 0xd4, 0x47, 0xfd, 0x4e, 0x00, 0x01, 0x00, 0x69, 0x01, 0x08, 0x05, 0xaf, 0x03, 0xfc, 0x00, 0x08, 0x00, 0x00, 0x13, 0x21, 0x03, 0x04, 0x05, 0x04, 0x05, 0x13, 0x21, 0x69, 0x02, 0x75, 0x97, 0x01, 0x39, 0x02, 0x2e, 0xfd, 0xd2, 0xfe, 0xc7, 0x97, 0xfd, 0x8b, 0x02, 0xbe, 0x01, 0x3e, 0xfc, 0x7e, 0x7e, 0xfc, 0x01, 0x3e, 0x00, 0x01, 0x00, 0x69, 0x00, 0x75, 0x05, 0x81, 0x04, 0x8f, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x14, 0x06, 0x07, 0x01, 0x06, 0x07, 0x06, 0x22, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x3f, 0x01, 0x21, 0x22, 0x2e, 0x02, 0x34, 0x3e, 0x02, 0x33, 0x21, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x3e, 0x01, 0x32, 0x17, 0x16, 0x17, 0x01, 0x16, 0x05, 0x80, 0x12, 0x0f, 0xfe, 0x98, 0x0e, 0x16, 0x14, 0x2e, 0x28, 0x10, 0x10, 0x11, 0x12, 0x0f, 0xa7, 0xfc, 0xda, 0x18, 0x27, 0x21, 0x11, 0x11, 0x21, 0x27, 0x18, 0x03, 0x26, 0xa7, 0x0f, 0x12, 0x11, 0x10, 0x10, 0x28, 0x2e, 0x14, 0x16, 0x0e, 0x01, 0x68, 0x11, 0x02, 0x9b, 0x32, 0x2e, 0x11, 0xfe, 0x70, 0x10, 0x0b, 0x0a, 0x14, 0x11, 0x13, 0x2c, 0x19, 0x1a, 0x2e, 0x11, 0xba, 0x14, 0x22, 0x2e, 0x32, 0x2e, 0x22, 0x14, 0xba, 0x11, 0x2e, 0x1a, 0x19, 0x2c, 0x13, 0x11, 0x14, 0x0a, 0x0b, 0x10, 0xfe, 0x70, 0x13, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x06, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x11, 0x09, 0x01, 0x04, 0x24, 0xfc, 0x45, 0x03, 0xbb, 0x01, 0x8a, 0xfe, 0x76, 0x02, 0x5a, 0x50, 0x01, 0x8e, 0xfe, 0x4a, 0xfe, 0x4a, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x06, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x11, 0x09, 0x01, 0x04, 0x24, 0xfc, 0x45, 0x03, 0xbb, 0x01, 0x8a, 0xfe, 0x76, 0x02, 0x14, 0xdc, 0x01, 0x48, 0xfe, 0x4a, 0xfe, 0x4a, 0x00, 0x04, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x12, 0x00, 0x00, 0x01, 0x23, 0x11, 0x33, 0x01, 0x23, 0x11, 0x33, 0x03, 0x23, 0x11, 0x33, 0x01, 0x21, 0x11, 0x21, 0x35, 0x09, 0x01, 0x02, 0x73, 0xd8, 0xd8, 0xfe, 0xe0, 0x6c, 0x6c, 0xb4, 0x36, 0x36, 0x03, 0x85, 0xfe, 0x97, 0x01, 0x69, 0x01, 0x8a, 0xfe, 0x76, 0x01, 0xba, 0x01, 0x90, 0xfe, 0x70, 0x01, 0x90, 0xfe, 0x70, 0x01, 0x90, 0xfe, 0x70, 0x01, 0x90, 0xee, 0xfe, 0x4a, 0xfe, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x00, 0x01, 0x35, 0x12, 0x17, 0x06, 0x03, 0x35, 0x21, 0x11, 0x03, 0x23, 0x11, 0x33, 0x01, 0x23, 0x11, 0x33, 0x03, 0x23, 0x11, 0x33, 0x04, 0x24, 0xa6, 0xe4, 0xe4, 0xa6, 0xfe, 0x97, 0x48, 0xd8, 0xd8, 0xfe, 0xe0, 0x6c, 0x6c, 0xb4, 0x36, 0x36, 0x03, 0xae, 0x8a, 0xfe, 0xce, 0x84, 0x84, 0xfe, 0xce, 0x8a, 0x02, 0x58, 0xfd, 0xa8, 0x02, 0x58, 0xfd, 0xa8, 0x02, 0x58, 0xfd, 0xa8, 0x02, 0x58, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0x86, 0x05, 0xd7, 0x04, 0x7e, 0x00, 0x06, 0x00, 0x00, 0x09, 0x02, 0x11, 0x21, 0x11, 0x21, 0x04, 0x0e, 0x01, 0xc9, 0xfe, 0x37, 0xfc, 0x5b, 0x03, 0xa5, 0x04, 0x7e, 0xfe, 0x04, 0xfe, 0x04, 0x01, 0x11, 0x01, 0xd6, 0x00, 0x02, 0x00, 0xcd, 0x00, 0xc0, 0x05, 0xaf, 0x04, 0x44, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x01, 0x21, 0x01, 0x13, 0x09, 0x02, 0x02, 0xce, 0x01, 0xfe, 0xfd, 0x0f, 0x87, 0xfe, 0x6b, 0x04, 0xe1, 0xfb, 0x1f, 0x02, 0x82, 0x01, 0x0f, 0xfe, 0xf1, 0x01, 0xc2, 0xfe, 0x3e, 0xfe, 0x3e, 0x00, 0x00, 0x02, 0x00, 0xcd, 0x00, 0xc0, 0x05, 0xaf, 0x04, 0x44, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x01, 0x03, 0x01, 0x21, 0x09, 0x02, 0x02, 0xce, 0xf3, 0x02, 0xf1, 0xfd, 0x96, 0xfe, 0x6b, 0x04, 0xe1, 0xfb, 0x1f, 0x02, 0x82, 0xfe, 0xf1, 0x01, 0x0f, 0x01, 0xc2, 0xfe, 0x3e, 0xfe, 0x3e, 0x00, 0x00, 0x01, 0x00, 0xcd, 0xff, 0xf8, 0x05, 0xaf, 0x05, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x09, 0x03, 0x02, 0x08, 0xfe, 0xc5, 0x04, 0xe1, 0xfb, 0x1f, 0x02, 0x82, 0x02, 0x8a, 0xfd, 0x76, 0xfd, 0x76, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x62, 0x00, 0x14, 0x00, 0x00, 0x13, 0x11, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x21, 0x35, 0x09, 0x01, 0x35, 0x21, 0x20, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x69, 0x21, 0x1f, 0x20, 0x26, 0x26, 0x0b, 0x03, 0x04, 0x01, 0x8a, 0xfe, 0x76, 0xfe, 0x79, 0xfe, 0x78, 0x26, 0x26, 0x20, 0x1f, 0x21, 0x02, 0x82, 0x01, 0xe0, 0x30, 0x55, 0x25, 0x21, 0x13, 0x12, 0xc6, 0xfe, 0x4a, 0xfe, 0x4a, 0xc6, 0x12, 0x13, 0x21, 0x25, 0x55, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xa2, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x14, 0x00, 0x00, 0x13, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x21, 0x35, 0x09, 0x01, 0x35, 0x21, 0x20, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x69, 0x21, 0x1f, 0x20, 0x26, 0x26, 0x0b, 0x03, 0x04, 0x01, 0x8a, 0xfe, 0x76, 0xfe, 0x79, 0xfe, 0x78, 0x26, 0x26, 0x20, 0x1f, 0x21, 0x02, 0x82, 0x30, 0x55, 0x25, 0x21, 0x13, 0x12, 0xc6, 0xfe, 0x4a, 0xfe, 0x4a, 0xc6, 0x12, 0x13, 0x21, 0x25, 0x55, 0x30, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xba, 0xff, 0xf1, 0x04, 0x5d, 0x05, 0x13, 0x00, 0x06, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x11, 0x09, 0x01, 0x03, 0x08, 0xfe, 0xb3, 0x01, 0x4d, 0x01, 0x55, 0xfe, 0xab, 0x01, 0x56, 0x02, 0x58, 0x01, 0x65, 0xfd, 0x6f, 0xfd, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x08, 0x00, 0x00, 0x01, 0x35, 0x12, 0x05, 0x04, 0x03, 0x35, 0x21, 0x11, 0x03, 0x9d, 0x82, 0x01, 0x8f, 0xfe, 0x71, 0x82, 0xfc, 0xcc, 0x03, 0x9a, 0x9e, 0xfe, 0xce, 0x84, 0x84, 0xfe, 0xce, 0x9e, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0x00, 0x9a, 0x05, 0x82, 0x04, 0x6a, 0x00, 0x08, 0x00, 0x0f, 0x00, 0x00, 0x25, 0x35, 0x21, 0x11, 0x21, 0x35, 0x33, 0x09, 0x01, 0x03, 0x15, 0x09, 0x01, 0x15, 0x21, 0x11, 0x02, 0xe9, 0xfd, 0x80, 0x02, 0x80, 0xe1, 0x01, 0xb7, 0xfe, 0x49, 0x99, 0x01, 0x6f, 0xfe, 0x91, 0xfd, 0x80, 0x9a, 0xee, 0x01, 0xf4, 0xee, 0xfe, 0x18, 0xfe, 0x18, 0x01, 0x3e, 0xee, 0x01, 0x98, 0x01, 0x98, 0xee, 0xfe, 0xac, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0x00, 0x9a, 0x05, 0x82, 0x04, 0x6a, 0x00, 0x08, 0x00, 0x0f, 0x00, 0x00, 0x25, 0x35, 0x21, 0x11, 0x21, 0x35, 0x33, 0x09, 0x01, 0x03, 0x15, 0x09, 0x01, 0x15, 0x21, 0x11, 0x02, 0xe9, 0xfd, 0x80, 0x02, 0x80, 0xe1, 0x01, 0xb7, 0xfe, 0x49, 0x12, 0x01, 0x6f, 0xfe, 0x91, 0xfd, 0x80, 0x9a, 0xee, 0x01, 0xf4, 0xee, 0xfe, 0x18, 0xfe, 0x18, 0x01, 0x3e, 0xee, 0x01, 0x98, 0x01, 0x98, 0xee, 0xfe, 0xac, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x26, 0x00, 0x18, 0x05, 0xb8, 0x04, 0xb0, 0x00, 0x0b, 0x00, 0x12, 0x00, 0x00, 0x13, 0x01, 0x21, 0x37, 0x33, 0x13, 0x15, 0x01, 0x23, 0x35, 0x37, 0x21, 0x01, 0x07, 0x01, 0x03, 0x07, 0x21, 0x03, 0x27, 0x01, 0x03, 0x02, 0xf5, 0x7c, 0x5a, 0xc2, 0xfd, 0x6f, 0x87, 0x14, 0xfd, 0x74, 0x03, 0x6f, 0x7c, 0x02, 0x43, 0x9a, 0x7d, 0xfd, 0x0c, 0xb1, 0x01, 0xce, 0x01, 0xf4, 0xee, 0xfd, 0xfe, 0xc8, 0xfe, 0x32, 0xc8, 0x26, 0x01, 0x18, 0xee, 0x01, 0x98, 0x01, 0x98, 0xee, 0xfe, 0xac, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x26, 0x00, 0x18, 0x05, 0xb8, 0x04, 0xb0, 0x00, 0x0b, 0x00, 0x12, 0x00, 0x00, 0x13, 0x35, 0x21, 0x27, 0x35, 0x33, 0x01, 0x15, 0x03, 0x23, 0x27, 0x21, 0x01, 0x21, 0x13, 0x21, 0x17, 0x13, 0x01, 0x27, 0x02, 0x8c, 0x14, 0x87, 0x02, 0x91, 0xc2, 0x5a, 0x7c, 0xfd, 0x0b, 0x02, 0x6c, 0xfd, 0x0b, 0xb1, 0x02, 0xf4, 0x7d, 0x9a, 0xfd, 0xbd, 0x02, 0xfa, 0xc8, 0x26, 0xc8, 0xfe, 0x32, 0xc8, 0xfd, 0xfe, 0xee, 0x01, 0xa4, 0xfe, 0xac, 0xee, 0x01, 0x98, 0x01, 0x98, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf9, 0x00, 0x00, 0x05, 0x94, 0x04, 0x98, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x00, 0x21, 0x27, 0x21, 0x27, 0x11, 0x21, 0x35, 0x33, 0x01, 0x17, 0x01, 0x03, 0x15, 0x09, 0x01, 0x15, 0x21, 0x11, 0x03, 0x79, 0x47, 0xfe, 0x21, 0x5a, 0x02, 0x26, 0x63, 0x01, 0xb7, 0x5a, 0xfe, 0x49, 0x75, 0x01, 0x6f, 0xfe, 0x91, 0xfd, 0xda, 0x9e, 0xc8, 0x02, 0x94, 0x9e, 0xfe, 0x18, 0xc8, 0xfe, 0x18, 0x01, 0xb6, 0x9e, 0x01, 0x98, 0x01, 0x98, 0x9e, 0xfe, 0x0c, 0x00, 0x00, 0x02, 0x00, 0xf9, 0x00, 0x00, 0x05, 0x94, 0x04, 0x98, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x00, 0x01, 0x33, 0x01, 0x07, 0x01, 0x23, 0x35, 0x21, 0x11, 0x37, 0x21, 0x13, 0x21, 0x11, 0x21, 0x15, 0x09, 0x01, 0x03, 0x79, 0x63, 0x01, 0xb7, 0x5a, 0xfe, 0x49, 0x63, 0xfd, 0xda, 0x5a, 0x01, 0xdf, 0x35, 0xfd, 0xda, 0x02, 0x26, 0x01, 0x6f, 0xfe, 0x91, 0x04, 0x98, 0xfe, 0x18, 0xc8, 0xfe, 0x18, 0x9e, 0x02, 0x94, 0xc8, 0xfe, 0xe8, 0xfe, 0x0c, 0x9e, 0x01, 0x98, 0x01, 0x98, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x72, 0x00, 0x64, 0x05, 0xc1, 0x04, 0x98, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x00, 0x13, 0x03, 0x21, 0x35, 0x33, 0x01, 0x17, 0x01, 0x23, 0x27, 0x35, 0x21, 0x27, 0x13, 0x07, 0x21, 0x15, 0x09, 0x01, 0x15, 0x21, 0xf9, 0x87, 0x03, 0x07, 0x63, 0x01, 0xb7, 0x2d, 0xfe, 0x49, 0x63, 0x2d, 0xfd, 0x26, 0x2d, 0xda, 0x66, 0x02, 0xdb, 0x01, 0x6f, 0xfe, 0x91, 0xfd, 0x25, 0x02, 0xb0, 0x01, 0x4a, 0x9e, 0xfe, 0x18, 0x64, 0xfe, 0x18, 0x63, 0x3b, 0x64, 0x01, 0x4a, 0xfa, 0x9e, 0x01, 0x98, 0x01, 0x98, 0x9e, 0x00, 0x02, 0x00, 0x72, 0x00, 0x64, 0x05, 0xc1, 0x04, 0x98, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x00, 0x13, 0x03, 0x37, 0x21, 0x35, 0x37, 0x33, 0x01, 0x07, 0x01, 0x23, 0x35, 0x21, 0x13, 0x07, 0x21, 0x15, 0x09, 0x01, 0x15, 0x21, 0xf9, 0x87, 0x2d, 0x02, 0xda, 0x2d, 0x63, 0x01, 0xb7, 0x2d, 0xfe, 0x49, 0x63, 0xfc, 0xf9, 0xda, 0x66, 0x02, 0xdb, 0x01, 0x6f, 0xfe, 0x91, 0xfd, 0x25, 0x02, 0x4c, 0x01, 0x4a, 0x64, 0x3b, 0x63, 0xfe, 0x18, 0x64, 0xfe, 0x18, 0x9e, 0x01, 0x4a, 0xfa, 0x9e, 0x01, 0x98, 0x01, 0x98, 0x9e, 0x00, 0x01, 0x01, 0x1c, 0xff, 0xd8, 0x05, 0x31, 0x04, 0xaf, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x21, 0x15, 0x09, 0x01, 0x15, 0x01, 0x1c, 0x24, 0x3c, 0x51, 0x62, 0x64, 0x71, 0x6d, 0x69, 0x5e, 0x55, 0x51, 0x52, 0x4f, 0x54, 0x4e, 0x65, 0x64, 0xdf, 0x68, 0x5f, 0x54, 0x39, 0x25, 0x02, 0x1c, 0x01, 0x9c, 0xfe, 0x64, 0x03, 0x6e, 0x47, 0x43, 0x5a, 0x2e, 0x2f, 0x2f, 0x2b, 0x5d, 0x59, 0xdd, 0x80, 0x7a, 0xda, 0x5f, 0x58, 0x30, 0x2f, 0x2f, 0x2b, 0x5d, 0x3e, 0x49, 0x9e, 0x01, 0xca, 0x01, 0xca, 0x9e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x75, 0x01, 0x42, 0x05, 0xaf, 0x03, 0xc2, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x07, 0x33, 0x37, 0x23, 0x07, 0x33, 0x37, 0x23, 0x07, 0x33, 0x37, 0x23, 0x07, 0x33, 0x37, 0x23, 0x35, 0x03, 0x21, 0x13, 0x21, 0x11, 0x16, 0x17, 0x06, 0x07, 0x11, 0x21, 0x03, 0x21, 0x01, 0x33, 0x27, 0x23, 0x17, 0x33, 0x27, 0x23, 0x17, 0x33, 0x27, 0x23, 0x17, 0x33, 0x27, 0x23, 0x02, 0x97, 0x90, 0x36, 0x90, 0xa2, 0x90, 0x36, 0x90, 0xa2, 0x90, 0x36, 0x90, 0xa2, 0x90, 0x36, 0x90, 0x6c, 0xa8, 0x01, 0xe6, 0xa8, 0x01, 0x60, 0x9c, 0xaf, 0xaf, 0x9c, 0xfe, 0xa0, 0xa8, 0xfe, 0x1a, 0x02, 0x22, 0x36, 0x90, 0x36, 0x24, 0x36, 0x90, 0x36, 0x24, 0x36, 0x90, 0x36, 0x24, 0x36, 0x90, 0x36, 0x02, 0x5a, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x50, 0x01, 0x18, 0xfe, 0xe8, 0x01, 0x16, 0xbc, 0x82, 0x82, 0xbc, 0x01, 0x16, 0xfe, 0xe8, 0x01, 0x68, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x94, 0x00, 0x70, 0x04, 0xe9, 0x05, 0x3e, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x00, 0x01, 0x37, 0x06, 0x15, 0x14, 0x17, 0x26, 0x23, 0x22, 0x07, 0x37, 0x27, 0x37, 0x09, 0x01, 0x23, 0x01, 0x25, 0x11, 0x01, 0x11, 0x04, 0x2b, 0x9e, 0x06, 0x25, 0x7f, 0x94, 0x3b, 0x3f, 0x9d, 0xe4, 0x32, 0xfe, 0x4d, 0x01, 0x7f, 0xff, 0xfe, 0x81, 0x01, 0x33, 0x01, 0x7e, 0x01, 0x7b, 0xb0, 0x46, 0x43, 0xa3, 0x8f, 0x2a, 0x07, 0xb0, 0xfe, 0x39, 0x01, 0x6f, 0xfe, 0x58, 0x01, 0xa8, 0x3a, 0x01, 0x1b, 0xfe, 0x57, 0xfe, 0xe6, 0x00, 0x00, 0x03, 0x00, 0x69, 0x01, 0x62, 0x05, 0xaf, 0x03, 0xa2, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x01, 0x35, 0x16, 0x17, 0x06, 0x07, 0x35, 0x21, 0x35, 0x05, 0x21, 0x07, 0x21, 0x13, 0x27, 0x21, 0x17, 0x04, 0x7e, 0x8b, 0xa5, 0xa5, 0x8b, 0xfe, 0xbc, 0xfd, 0xe3, 0x02, 0x1c, 0xb4, 0xfd, 0xe4, 0xb4, 0xb4, 0x02, 0x1c, 0xb4, 0x02, 0xaa, 0xf8, 0xbc, 0x64, 0x64, 0xbc, 0xf8, 0x50, 0x52, 0xc8, 0x01, 0x1a, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x03, 0x00, 0x96, 0xff, 0xc5, 0x04, 0xe9, 0x04, 0x94, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x00, 0x01, 0x27, 0x16, 0x33, 0x32, 0x37, 0x06, 0x15, 0x14, 0x17, 0x27, 0x07, 0x27, 0x09, 0x01, 0x11, 0x01, 0x03, 0x23, 0x01, 0x21, 0x03, 0xf8, 0x9d, 0x3f, 0x3b, 0x94, 0x7f, 0x25, 0x06, 0x9e, 0xe5, 0x32, 0xfe, 0xb5, 0x01, 0x7e, 0xfe, 0x82, 0x34, 0xff, 0x01, 0x7e, 0x00, 0xff, 0x03, 0xc1, 0xb0, 0x07, 0x2a, 0x90, 0xa2, 0x43, 0x46, 0xb0, 0xff, 0x39, 0xfe, 0x1d, 0x01, 0xa8, 0xfe, 0xe5, 0xfe, 0x58, 0x01, 0x55, 0x01, 0xa8, 0x00, 0x00, 0x01, 0x00, 0x96, 0x00, 0x70, 0x04, 0xe9, 0x05, 0x3e, 0x00, 0x2a, 0x00, 0x00, 0x25, 0x26, 0x23, 0x22, 0x07, 0x3e, 0x01, 0x37, 0x27, 0x26, 0x27, 0x26, 0x22, 0x06, 0x07, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x01, 0x37, 0x26, 0x35, 0x34, 0x36, 0x37, 0x01, 0x0e, 0x01, 0x15, 0x14, 0x17, 0x16, 0x17, 0x01, 0x3e, 0x01, 0x37, 0x06, 0x15, 0x14, 0x04, 0xe8, 0x80, 0x95, 0x3b, 0x3e, 0x40, 0x74, 0x15, 0x95, 0x96, 0x1f, 0x22, 0x46, 0x44, 0x19, 0xfe, 0x82, 0x21, 0x4e, 0x2a, 0x28, 0x2b, 0x13, 0x05, 0x12, 0x21, 0x1e, 0x01, 0x7e, 0x1d, 0x16, 0x0c, 0x0e, 0x06, 0x01, 0x24, 0x03, 0x30, 0x41, 0x06, 0x70, 0x2a, 0x07, 0x47, 0x36, 0x03, 0xa6, 0xa6, 0x0e, 0x0f, 0x1e, 0x1c, 0x01, 0xa8, 0x24, 0x22, 0x12, 0x08, 0x21, 0x30, 0x2c, 0x30, 0x59, 0x22, 0xfe, 0x57, 0x21, 0x46, 0x26, 0x27, 0x26, 0x23, 0x07, 0xfe, 0xbb, 0x17, 0x81, 0x47, 0x47, 0x43, 0xa3, 0x00, 0x00, 0x01, 0x00, 0x69, 0x01, 0x61, 0x05, 0xaf, 0x03, 0xa3, 0x00, 0x27, 0x00, 0x00, 0x01, 0x06, 0x07, 0x34, 0x36, 0x37, 0x23, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x21, 0x34, 0x36, 0x37, 0x36, 0x3f, 0x01, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x21, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x21, 0x2e, 0x01, 0x35, 0x16, 0x05, 0xae, 0xa4, 0x8c, 0x30, 0x0c, 0xd3, 0xd3, 0x1f, 0x21, 0x1a, 0x19, 0x1c, 0xfd, 0xe4, 0x22, 0x1e, 0x1c, 0x2a, 0x13, 0x13, 0x2a, 0x1c, 0x1e, 0x22, 0x02, 0x1c, 0x1c, 0x19, 0x1a, 0x21, 0x1f, 0x09, 0x01, 0x9d, 0x0c, 0x30, 0x8c, 0x02, 0x82, 0x65, 0xbc, 0x65, 0x81, 0x13, 0x0f, 0x10, 0x1c, 0x1b, 0x4a, 0x28, 0x30, 0x59, 0x21, 0x1f, 0x15, 0x09, 0x1b, 0x15, 0x1f, 0x22, 0x58, 0x30, 0x28, 0x4a, 0x1b, 0x1c, 0x10, 0x0f, 0x13, 0x81, 0x65, 0xbc, 0x00, 0x00, 0x01, 0x00, 0x96, 0xff, 0xc6, 0x04, 0xe9, 0x04, 0x94, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x06, 0x15, 0x14, 0x17, 0x2e, 0x01, 0x27, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x16, 0x17, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x3f, 0x01, 0x27, 0x06, 0x23, 0x22, 0x26, 0x27, 0x01, 0x1e, 0x01, 0x32, 0x37, 0x36, 0x37, 0x01, 0x2e, 0x01, 0x27, 0x16, 0x33, 0x32, 0x04, 0xe8, 0x24, 0x06, 0x41, 0x30, 0x03, 0x97, 0x96, 0x0b, 0x0c, 0x1a, 0x19, 0xfe, 0x82, 0x1e, 0x21, 0x12, 0x07, 0x1f, 0x2b, 0x28, 0x2b, 0x4f, 0x1f, 0x01, 0x7e, 0x19, 0x44, 0x46, 0x22, 0x1f, 0x07, 0x01, 0x24, 0x15, 0x74, 0x40, 0x3e, 0x3b, 0x95, 0x04, 0x94, 0x8e, 0xa3, 0x43, 0x47, 0x47, 0x81, 0x17, 0xa8, 0xa8, 0x1f, 0x26, 0x27, 0x26, 0x4b, 0x1c, 0xfe, 0x57, 0x22, 0x59, 0x30, 0x2c, 0x30, 0x15, 0x04, 0x12, 0x24, 0x22, 0x01, 0xa8, 0x1c, 0x1e, 0x0f, 0x0e, 0x07, 0x01, 0x45, 0x03, 0x36, 0x47, 0x07, 0x00, 0x03, 0x00, 0x67, 0x00, 0xac, 0x05, 0xaf, 0x04, 0x58, 0x00, 0x14, 0x00, 0x27, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x36, 0x25, 0x06, 0x03, 0x06, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x24, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x04, 0x05, 0x04, 0x05, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x12, 0x17, 0x24, 0x03, 0xc4, 0xdd, 0x01, 0x0d, 0xcc, 0x6e, 0x0a, 0x13, 0x14, 0x19, 0x17, 0x38, 0x17, 0x18, 0x14, 0x13, 0x15, 0x15, 0x13, 0x14, 0xfc, 0xbc, 0x1c, 0x19, 0x1a, 0x20, 0x20, 0x49, 0x20, 0x01, 0x3e, 0x03, 0x0f, 0xfc, 0xdb, 0xfe, 0xd8, 0x20, 0x49, 0x20, 0x25, 0x15, 0x1b, 0x03, 0x42, 0x18, 0x14, 0x13, 0x15, 0x15, 0x13, 0x14, 0x18, 0x17, 0x38, 0x17, 0x19, 0x14, 0x10, 0x0d, 0x6c, 0xce, 0xfe, 0xb9, 0x01, 0xce, 0x62, 0x51, 0x75, 0xfe, 0xfd, 0x1d, 0x14, 0x15, 0x0c, 0x0b, 0x0b, 0x0c, 0x15, 0x14, 0x38, 0x1f, 0x1e, 0x38, 0x14, 0x15, 0x97, 0x52, 0x4b, 0x1a, 0x1c, 0x10, 0x0f, 0x0e, 0x85, 0x36, 0x38, 0x83, 0x0e, 0x0f, 0x12, 0x1a, 0x1f, 0x01, 0x23, 0x0c, 0x15, 0x14, 0x38, 0x1e, 0x1f, 0x38, 0x14, 0x15, 0x0c, 0x0b, 0x0b, 0x0c, 0x15, 0x11, 0x20, 0xfe, 0xfe, 0x76, 0x63, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x87, 0x01, 0x1f, 0x05, 0x9d, 0x03, 0xe5, 0x00, 0x1a, 0x00, 0x2a, 0x00, 0x00, 0x13, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x05, 0x04, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x25, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x37, 0x16, 0x17, 0x06, 0x07, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x87, 0x3b, 0x1a, 0x1d, 0x12, 0x23, 0x24, 0x26, 0x2a, 0x30, 0x2f, 0x36, 0x2e, 0x92, 0x01, 0x69, 0xfe, 0x97, 0x92, 0x33, 0x62, 0x2e, 0x2d, 0x23, 0x34, 0x13, 0x1a, 0x15, 0x1a, 0x03, 0x9f, 0x21, 0x21, 0x21, 0x21, 0x59, 0xe2, 0xe2, 0x59, 0x21, 0x21, 0x21, 0x02, 0x82, 0x26, 0x3a, 0x3f, 0x13, 0x24, 0x12, 0x13, 0x13, 0x16, 0x20, 0x66, 0x4c, 0x4c, 0x66, 0x23, 0x26, 0x13, 0x1d, 0x19, 0x23, 0x2f, 0x3a, 0x26, 0x27, 0x58, 0x32, 0x33, 0x58, 0x27, 0xf1, 0x72, 0x72, 0xf1, 0x27, 0x58, 0x33, 0x32, 0x58, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x91, 0x01, 0x56, 0x05, 0x94, 0x03, 0xae, 0x00, 0x63, 0x00, 0x00, 0x00, 0x14, 0x06, 0x0f, 0x01, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x3f, 0x01, 0x36, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x22, 0x07, 0x06, 0x07, 0x06, 0x0f, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x21, 0x22, 0x2e, 0x02, 0x34, 0x3f, 0x01, 0x36, 0x34, 0x2f, 0x01, 0x26, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x21, 0x32, 0x17, 0x16, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x2f, 0x01, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x05, 0x93, 0x05, 0x05, 0xd8, 0x04, 0x08, 0x06, 0x0f, 0x06, 0x06, 0x06, 0x05, 0x06, 0x03, 0x18, 0x03, 0x05, 0x06, 0x04, 0x07, 0x08, 0x06, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x04, 0x04, 0x51, 0x05, 0x02, 0x06, 0x07, 0x05, 0x07, 0xfd, 0xd9, 0x07, 0x0d, 0x0b, 0x05, 0x02, 0x35, 0x35, 0x01, 0x69, 0x02, 0x05, 0x06, 0x05, 0x06, 0x07, 0x07, 0x02, 0x27, 0x07, 0x05, 0x08, 0x05, 0x02, 0x05, 0x51, 0x04, 0x04, 0x06, 0x06, 0x06, 0x07, 0xfe, 0x06, 0x08, 0x07, 0x04, 0x06, 0x05, 0x03, 0x18, 0x03, 0x06, 0x05, 0x06, 0x06, 0x06, 0x0f, 0x06, 0x08, 0x04, 0xd8, 0x05, 0x02, 0x8b, 0x12, 0x0e, 0x06, 0xf0, 0x04, 0x05, 0x03, 0x03, 0x04, 0x05, 0x06, 0x0e, 0x09, 0x04, 0x0b, 0x63, 0x0b, 0x05, 0x07, 0x0f, 0x06, 0x05, 0x03, 0x04, 0x03, 0x04, 0x05, 0x05, 0x08, 0xb4, 0x0a, 0x03, 0x05, 0x04, 0x03, 0x06, 0x0c, 0x0e, 0x12, 0x06, 0x75, 0x75, 0x14, 0x02, 0xe8, 0x06, 0x12, 0x0e, 0x06, 0x05, 0x04, 0x03, 0x03, 0x03, 0x06, 0x03, 0x0a, 0xb4, 0x08, 0x05, 0x05, 0x04, 0x03, 0x04, 0x03, 0x05, 0x06, 0x0f, 0x07, 0x05, 0x0b, 0x63, 0x0b, 0x04, 0x09, 0x0e, 0x06, 0x05, 0x04, 0x03, 0x03, 0x05, 0x04, 0xf0, 0x06, 0x00, 0x00, 0x01, 0x00, 0x91, 0x00, 0xf1, 0x05, 0x94, 0x04, 0x13, 0x00, 0x63, 0x00, 0x00, 0x00, 0x14, 0x06, 0x07, 0x01, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x3f, 0x01, 0x36, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x26, 0x2b, 0x01, 0x22, 0x07, 0x06, 0x07, 0x06, 0x0f, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x21, 0x22, 0x2e, 0x02, 0x34, 0x3f, 0x01, 0x36, 0x34, 0x27, 0x03, 0x26, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x21, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x13, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x2f, 0x01, 0x26, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x01, 0x16, 0x05, 0x93, 0x05, 0x05, 0xfe, 0x98, 0x05, 0x07, 0x06, 0x0f, 0x06, 0x06, 0x06, 0x05, 0x06, 0x03, 0x4e, 0x03, 0x05, 0x06, 0x04, 0x07, 0x08, 0x06, 0x53, 0x07, 0x06, 0x07, 0x05, 0x04, 0x04, 0x6c, 0x05, 0x02, 0x06, 0x07, 0x05, 0x07, 0xfd, 0xac, 0x07, 0x0d, 0x0b, 0x05, 0x03, 0x42, 0x42, 0x01, 0x8d, 0x02, 0x05, 0x06, 0x05, 0x06, 0x07, 0x07, 0x02, 0x54, 0x07, 0x05, 0x08, 0x05, 0x03, 0x04, 0x75, 0x04, 0x04, 0x05, 0x07, 0x06, 0x07, 0x53, 0x06, 0x08, 0x07, 0x04, 0x06, 0x05, 0x03, 0x4e, 0x03, 0x06, 0x05, 0x06, 0x06, 0x06, 0x0f, 0x06, 0x07, 0x05, 0x01, 0x68, 0x05, 0x02, 0x8b, 0x12, 0x0f, 0x05, 0xfe, 0x98, 0x05, 0x04, 0x03, 0x03, 0x04, 0x05, 0x06, 0x0e, 0x09, 0x07, 0x08, 0xdb, 0x08, 0x08, 0x07, 0x0f, 0x06, 0x05, 0x03, 0x04, 0x03, 0x04, 0x05, 0x05, 0x08, 0xf0, 0x0a, 0x03, 0x05, 0x04, 0x03, 0x06, 0x0c, 0x0e, 0x12, 0x06, 0x93, 0x93, 0x14, 0x02, 0x01, 0x38, 0x06, 0x12, 0x0e, 0x06, 0x05, 0x04, 0x03, 0x03, 0x03, 0x06, 0x03, 0x0a, 0xfe, 0xfc, 0x08, 0x05, 0x05, 0x04, 0x03, 0x04, 0x03, 0x05, 0x06, 0x0f, 0x07, 0x08, 0x08, 0xdb, 0x08, 0x07, 0x09, 0x0e, 0x06, 0x05, 0x04, 0x03, 0x03, 0x04, 0x05, 0xfe, 0x98, 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x69, 0x00, 0xa6, 0x05, 0xaf, 0x04, 0x5e, 0x00, 0x13, 0x00, 0x1d, 0x00, 0x27, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x07, 0x23, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x2f, 0x01, 0x33, 0x16, 0x17, 0x16, 0x01, 0x23, 0x3e, 0x01, 0x37, 0x21, 0x35, 0x21, 0x0e, 0x01, 0x03, 0x1e, 0x01, 0x17, 0x21, 0x35, 0x21, 0x2e, 0x01, 0x27, 0x05, 0xae, 0x7a, 0x4b, 0x7e, 0x42, 0x61, 0x29, 0x29, 0x90, 0x22, 0x40, 0x40, 0x22, 0x90, 0x12, 0x40, 0x61, 0x41, 0x7f, 0x4b, 0xfe, 0x04, 0x5e, 0x11, 0x31, 0x26, 0xfd, 0x27, 0x03, 0x82, 0x63, 0x44, 0x0c, 0x0c, 0x44, 0x63, 0xfc, 0x7e, 0x02, 0xd9, 0x26, 0x31, 0x11, 0x02, 0x82, 0x4f, 0x55, 0x8f, 0xa9, 0x6e, 0x6d, 0xa4, 0x27, 0x36, 0x36, 0x27, 0xa4, 0x31, 0xaa, 0xa4, 0x94, 0x55, 0xfd, 0xd5, 0x3d, 0x85, 0x48, 0x64, 0x8e, 0xb7, 0x03, 0x8f, 0x29, 0xb7, 0x8e, 0x64, 0x48, 0x85, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xfe, 0xb2, 0x02, 0x88, 0x06, 0x26, 0x00, 0x19, 0x00, 0x00, 0x01, 0x2a, 0x01, 0x27, 0x24, 0x03, 0x26, 0x00, 0x27, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x37, 0x36, 0x15, 0x14, 0x00, 0x07, 0x06, 0x05, 0x16, 0x36, 0x37, 0x02, 0x88, 0x08, 0x5e, 0x31, 0xfe, 0x74, 0x02, 0x01, 0x01, 0x49, 0x04, 0x03, 0x54, 0x34, 0x29, 0x7a, 0x2d, 0xc0, 0xc8, 0xfe, 0xd2, 0x07, 0x0b, 0x01, 0x00, 0x4a, 0x3e, 0x12, 0xfe, 0xb2, 0x0b, 0x53, 0x01, 0x52, 0xae, 0x03, 0xf5, 0x51, 0x4f, 0x89, 0x31, 0xd8, 0x01, 0x01, 0xcc, 0xa1, 0xfc, 0x4c, 0x8f, 0xdc, 0x48, 0x15, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x47, 0xfe, 0xb2, 0x02, 0x6d, 0x06, 0x26, 0x00, 0x19, 0x00, 0x00, 0x13, 0x35, 0x1e, 0x01, 0x37, 0x24, 0x27, 0x26, 0x00, 0x35, 0x34, 0x17, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x06, 0x00, 0x07, 0x02, 0x05, 0x06, 0x22, 0x47, 0x12, 0x3e, 0x4a, 0x01, 0x00, 0x0b, 0x06, 0xfe, 0xd1, 0xc8, 0xc0, 0x2d, 0x7a, 0x28, 0x35, 0x54, 0x03, 0x04, 0x01, 0x49, 0x01, 0x02, 0xfe, 0x74, 0x31, 0x5e, 0xfe, 0xb2, 0x8f, 0x02, 0x01, 0x15, 0x48, 0xdc, 0x8f, 0x03, 0xb4, 0xa1, 0xcc, 0x01, 0x01, 0xd8, 0x31, 0x89, 0x4f, 0x51, 0xfc, 0x0b, 0xae, 0xfe, 0xae, 0x53, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0xfe, 0x23, 0x03, 0x8a, 0x06, 0x75, 0x00, 0x03, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x09, 0x05, 0x21, 0x09, 0x01, 0x21, 0x01, 0xc6, 0x01, 0xc3, 0xfe, 0x3d, 0xfe, 0x3f, 0x01, 0xc1, 0xfe, 0xbc, 0x02, 0x8a, 0xfe, 0xba, 0x01, 0x46, 0xfd, 0x76, 0x06, 0x75, 0xfb, 0xdb, 0xfb, 0xd3, 0x04, 0x2d, 0x03, 0x31, 0xfd, 0x08, 0xfc, 0x8e, 0x03, 0x00, 0x00, 0x02, 0x00, 0x9e, 0xfe, 0xf2, 0x02, 0xdf, 0x06, 0x14, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x25, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0xf8, 0xb4, 0xfe, 0xf2, 0x02, 0x40, 0xd8, 0xd8, 0xfd, 0xc0, 0x05, 0xb0, 0xf9, 0xa6, 0x06, 0x5a, 0x64, 0x64, 0xf9, 0xa6, 0x64, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9d, 0xfe, 0xf2, 0x02, 0xde, 0x06, 0x14, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x23, 0x11, 0x33, 0x13, 0x11, 0x21, 0x35, 0x33, 0x11, 0x23, 0x35, 0x02, 0x84, 0xb4, 0xb4, 0x5a, 0xfd, 0xc0, 0xd8, 0xd8, 0x05, 0xb0, 0xf9, 0xa6, 0x06, 0xbe, 0xf8, 0xde, 0x64, 0x06, 0x5a, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa4, 0xfe, 0xf2, 0x02, 0x3c, 0x06, 0x12, 0x00, 0x05, 0x00, 0x00, 0x1b, 0x01, 0x33, 0x03, 0x13, 0x23, 0xa5, 0xfd, 0x9a, 0xfe, 0xfe, 0x9a, 0x02, 0x82, 0x03, 0x90, 0xfc, 0x70, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x01, 0x00, 0x93, 0xfe, 0xf2, 0x02, 0x2b, 0x06, 0x12, 0x00, 0x05, 0x00, 0x00, 0x01, 0x03, 0x23, 0x13, 0x03, 0x33, 0x02, 0x2a, 0xfd, 0x99, 0xfd, 0xfd, 0x99, 0x02, 0x82, 0xfc, 0x70, 0x03, 0x90, 0x03, 0x90, 0x00, 0xff, 0xff, 0x00, 0xa4, 0xfe, 0xf2, 0x03, 0x6e, 0x06, 0x12, 0x10, 0x26, 0x0c, 0x97, 0x00, 0x00, 0x10, 0x07, 0x0c, 0x97, 0x01, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x93, 0xfe, 0xf2, 0x03, 0x5d, 0x06, 0x12, 0x10, 0x26, 0x0c, 0x98, 0x00, 0x00, 0x10, 0x07, 0x0c, 0x98, 0x01, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x05, 0xb9, 0x05, 0xdc, 0x00, 0x16, 0x00, 0x00, 0x09, 0x01, 0x07, 0x27, 0x11, 0x23, 0x11, 0x27, 0x11, 0x23, 0x11, 0x27, 0x07, 0x11, 0x23, 0x11, 0x07, 0x11, 0x23, 0x11, 0x07, 0x27, 0x01, 0x03, 0x2e, 0x02, 0x8a, 0x6c, 0x52, 0x6c, 0xbe, 0x6c, 0x5f, 0x5f, 0x6c, 0xbd, 0x6c, 0x53, 0x6c, 0x02, 0x8a, 0x05, 0xdc, 0xfd, 0x2c, 0x78, 0x5c, 0xfd, 0x14, 0x03, 0x65, 0xd3, 0xfb, 0xc8, 0x04, 0xb0, 0x68, 0x68, 0xfb, 0x50, 0x04, 0x38, 0xd3, 0xfc, 0x9b, 0x02, 0xec, 0x5c, 0x78, 0x02, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x50, 0xff, 0xf9, 0x05, 0xb7, 0x05, 0xd5, 0x00, 0x16, 0x00, 0x00, 0x05, 0x01, 0x37, 0x17, 0x11, 0x33, 0x11, 0x17, 0x11, 0x33, 0x11, 0x17, 0x37, 0x11, 0x33, 0x11, 0x37, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x02, 0xda, 0xfd, 0x76, 0x6c, 0x53, 0x6c, 0xbd, 0x6c, 0x5f, 0x60, 0x6c, 0xbd, 0x6c, 0x52, 0x6c, 0xfd, 0x77, 0x07, 0x02, 0xd4, 0x78, 0x5c, 0x02, 0xec, 0xfc, 0x9b, 0xd3, 0x04, 0x38, 0xfb, 0x50, 0x68, 0x68, 0x04, 0xb0, 0xfb, 0xc8, 0xd3, 0x03, 0x65, 0xfd, 0x14, 0x5c, 0x78, 0xfd, 0x2c, 0x00, 0x01, 0x00, 0x47, 0x00, 0x6c, 0x05, 0xde, 0x05, 0x44, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x30, 0x37, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x02, 0x28, 0x6b, 0x39, 0x4a, 0x46, 0xab, 0x43, 0x4d, 0x36, 0x3c, 0x3b, 0x1e, 0x1f, 0x3a, 0x39, 0x4a, 0x46, 0xab, 0x43, 0x4d, 0x36, 0x3c, 0x1d, 0x15, 0x06, 0xd1, 0x6c, 0xfe, 0x9f, 0x51, 0xfe, 0x9d, 0x6c, 0xd2, 0x07, 0x20, 0x2c, 0x50, 0x4b, 0x69, 0x5c, 0x78, 0x73, 0x61, 0x66, 0x4e, 0x52, 0x2a, 0x29, 0x29, 0x2a, 0x52, 0x4a, 0x6a, 0x5c, 0x78, 0x73, 0x61, 0x60, 0x01, 0x21, 0x78, 0x3f, 0x23, 0x21, 0x21, 0x27, 0x3b, 0x42, 0xa2, 0x5d, 0x59, 0x51, 0x53, 0x40, 0x3f, 0x23, 0x21, 0x21, 0x27, 0x3b, 0x42, 0x51, 0x39, 0x3f, 0xea, 0x78, 0xfe, 0x76, 0x01, 0x8a, 0x78, 0xe9, 0x60, 0x58, 0x71, 0x59, 0x53, 0x34, 0x2e, 0x2e, 0x30, 0x57, 0x59, 0x71, 0x70, 0x7b, 0x7f, 0x70, 0x71, 0x59, 0x53, 0x34, 0x2e, 0x2e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x47, 0x00, 0x7c, 0x05, 0xde, 0x05, 0x54, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x37, 0x17, 0x01, 0x23, 0x01, 0x37, 0x17, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x03, 0xfd, 0x55, 0x5f, 0x62, 0x73, 0x78, 0x5c, 0x69, 0x4b, 0x50, 0x2c, 0x29, 0x29, 0x2c, 0x50, 0x4f, 0x65, 0x61, 0x73, 0x78, 0x5d, 0x68, 0x4c, 0x50, 0x2b, 0x20, 0x08, 0xd1, 0x6c, 0xfe, 0x9e, 0x51, 0xfe, 0x9f, 0x6c, 0xd1, 0x07, 0x14, 0x1e, 0x3b, 0x36, 0x4e, 0x42, 0xac, 0x46, 0x4a, 0x39, 0x3a, 0x1f, 0x1e, 0x3c, 0x3b, 0x36, 0x4d, 0x43, 0xab, 0x46, 0x4a, 0x3a, 0x01, 0x31, 0x5a, 0x2d, 0x2e, 0x2e, 0x34, 0x53, 0x59, 0x71, 0x70, 0x7f, 0x7b, 0x70, 0x71, 0x59, 0x57, 0x30, 0x2e, 0x2e, 0x34, 0x53, 0x59, 0x71, 0x58, 0x60, 0xe9, 0x78, 0xfe, 0x76, 0x01, 0x8a, 0x78, 0xea, 0x3f, 0x39, 0x51, 0x42, 0x3b, 0x27, 0x21, 0x21, 0x23, 0x3f, 0x40, 0x53, 0x51, 0x59, 0x5d, 0xa2, 0x42, 0x3b, 0x27, 0x21, 0x21, 0x23, 0x3f, 0x00, 0x03, 0x00, 0x69, 0xff, 0xe3, 0x07, 0xfb, 0x05, 0x24, 0x00, 0x25, 0x00, 0x39, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x06, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x23, 0x35, 0x33, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x21, 0x27, 0x37, 0x24, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x11, 0x33, 0x11, 0x21, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x01, 0x21, 0x11, 0x23, 0x11, 0x21, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x07, 0xfb, 0xfe, 0x9e, 0x6c, 0xd2, 0xfe, 0xc3, 0x0a, 0x1d, 0x2d, 0x59, 0x58, 0xd6, 0xf8, 0xd7, 0x58, 0x59, 0x2c, 0x1e, 0x0a, 0xaa, 0xaa, 0x09, 0x1f, 0x2c, 0x59, 0x58, 0xd7, 0xf8, 0xd6, 0x58, 0x59, 0x2d, 0x1e, 0x09, 0x01, 0x3d, 0xd2, 0x6c, 0xfd, 0x32, 0xc1, 0x53, 0x53, 0x44, 0x46, 0x22, 0x15, 0x08, 0x01, 0x83, 0x99, 0x01, 0x83, 0x08, 0x14, 0x23, 0x45, 0x44, 0x53, 0x01, 0x1b, 0xfe, 0x7d, 0x99, 0xfe, 0x7d, 0x09, 0x14, 0x22, 0x46, 0x44, 0x53, 0x53, 0xc1, 0x54, 0x53, 0x44, 0x45, 0x23, 0x13, 0x02, 0xaf, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0x5a, 0x51, 0x76, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x76, 0x51, 0x5a, 0xaa, 0x5b, 0x52, 0x77, 0x63, 0x62, 0x64, 0x64, 0x62, 0x63, 0x77, 0x52, 0x5b, 0xe9, 0x78, 0x56, 0x27, 0x27, 0x4c, 0x4d, 0x5c, 0x37, 0x3d, 0x01, 0x65, 0xfe, 0x9b, 0x3d, 0x37, 0x5c, 0x4d, 0x4c, 0x27, 0xfd, 0xc6, 0xfe, 0x9b, 0x01, 0x65, 0x3b, 0x36, 0x5c, 0x4d, 0x4c, 0x27, 0x27, 0x27, 0x27, 0x4c, 0x4d, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x09, 0xea, 0x04, 0x38, 0x00, 0x09, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x17, 0x07, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x08, 0x93, 0xf7, 0x6d, 0xd2, 0x6c, 0x02, 0x55, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0xaa, 0xe9, 0x78, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x09, 0xf9, 0x04, 0x38, 0x00, 0x09, 0x00, 0x00, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x35, 0x21, 0x27, 0x37, 0x09, 0xf8, 0xfe, 0x9f, 0x6c, 0xd1, 0xf7, 0x6d, 0x08, 0x93, 0xd1, 0x6c, 0x02, 0xaf, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xaa, 0xe9, 0x78, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x09, 0xf9, 0x04, 0x38, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x35, 0x01, 0x17, 0x07, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x17, 0x07, 0x5a, 0x01, 0x62, 0x6c, 0xd2, 0x07, 0xa6, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0xf8, 0x5a, 0xd2, 0x6c, 0x02, 0x55, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0xe9, 0x78, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x09, 0xea, 0x04, 0x38, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x21, 0x15, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x01, 0x68, 0x08, 0x81, 0xf7, 0xeb, 0x54, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x54, 0x08, 0x15, 0xf7, 0x7f, 0x5e, 0x02, 0x19, 0x78, 0x5d, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x5d, 0x78, 0x69, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x09, 0xf9, 0x04, 0x38, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x37, 0x27, 0x21, 0x35, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x35, 0x08, 0xea, 0x5f, 0x5f, 0xf7, 0x7f, 0x08, 0x15, 0x53, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x53, 0xf7, 0xeb, 0x02, 0x19, 0x69, 0x69, 0x78, 0x5d, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x5d, 0x78, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0xcc, 0x09, 0xf9, 0x04, 0x38, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x01, 0x21, 0x37, 0x27, 0x21, 0x07, 0x05, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x01, 0x68, 0x07, 0x82, 0x5f, 0x5f, 0xf8, 0x7e, 0x5e, 0x07, 0x74, 0xf9, 0x56, 0x54, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x54, 0x06, 0xaa, 0x53, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x02, 0x19, 0x69, 0x69, 0x69, 0xe1, 0x5d, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x5d, 0x5d, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0xcc, 0x09, 0xea, 0x04, 0x38, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x11, 0x33, 0x11, 0x23, 0x09, 0x50, 0xf8, 0x06, 0xd2, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0xd2, 0x07, 0xfa, 0x99, 0x99, 0x02, 0x2d, 0xe9, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0xe9, 0x01, 0x59, 0xfc, 0xa4, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x09, 0xf9, 0x04, 0x38, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x01, 0x02, 0x99, 0x99, 0x07, 0xfa, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0x02, 0x2d, 0xfe, 0xa7, 0x03, 0x5c, 0xfe, 0xa7, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0xcc, 0x09, 0xea, 0x04, 0x38, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x00, 0x01, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x35, 0x33, 0x11, 0x23, 0x11, 0x35, 0x21, 0x07, 0x17, 0x09, 0x50, 0xf8, 0x84, 0x54, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x54, 0x07, 0x7c, 0x99, 0x99, 0xf8, 0x18, 0x5e, 0x5e, 0x01, 0xa1, 0x5d, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x5d, 0xcd, 0xfc, 0xa4, 0x01, 0x45, 0xd2, 0x69, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0x00, 0xcc, 0x09, 0xf9, 0x04, 0x38, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x00, 0x01, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x15, 0x23, 0x11, 0x33, 0x11, 0x15, 0x21, 0x37, 0x27, 0x01, 0x02, 0x07, 0x7c, 0x53, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x53, 0xf8, 0x84, 0x99, 0x99, 0x07, 0xe8, 0x5f, 0x5f, 0x03, 0x63, 0x5d, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x5d, 0xcd, 0x03, 0x5c, 0xfe, 0xbb, 0xd2, 0x69, 0x69, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0x00, 0xcc, 0x09, 0xf9, 0x04, 0x38, 0x00, 0x25, 0x00, 0x00, 0x13, 0x17, 0x37, 0x17, 0x37, 0x17, 0x37, 0x17, 0x37, 0x17, 0x37, 0x17, 0x37, 0x17, 0x37, 0x33, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x23, 0x07, 0x27, 0x07, 0x27, 0x07, 0x27, 0x07, 0x27, 0x07, 0x27, 0x07, 0x27, 0x07, 0x27, 0x69, 0x3f, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0x3f, 0x7d, 0xd1, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0xd1, 0x59, 0x63, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0x3f, 0x02, 0xd7, 0x46, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x46, 0xe9, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0xe9, 0x6e, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x46, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x05, 0x14, 0x02, 0x1c, 0x06, 0x40, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x02, 0x1c, 0x04, 0x09, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x02, 0x1c, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x02, 0x1c, 0x01, 0xd3, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x02, 0x1c, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x02, 0x1c, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x02, 0x1c, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0x05, 0x14, 0x04, 0x38, 0x06, 0x40, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x05, 0x14, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0x02, 0xdd, 0x04, 0x38, 0x04, 0x09, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0x02, 0xdd, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x02, 0xdd, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0x00, 0xa7, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0x00, 0xa7, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0x00, 0xa7, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x02, 0x1c, 0xff, 0x9c, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x02, 0x1c, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x02, 0x1c, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x02, 0x1c, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x02, 0x1c, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x02, 0x1c, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x02, 0x1c, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x02, 0x1c, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0xfe, 0x70, 0x04, 0x38, 0xff, 0x9c, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0xfe, 0x70, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x03, 0x2a, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0xff, 0x9c, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x01, 0xd3, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x04, 0x09, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x0e, 0xfe, 0x70, 0x04, 0x38, 0x06, 0x40, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x05, 0x14, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x02, 0xdd, 0x10, 0x27, 0x11, 0x33, 0x03, 0x2a, 0x00, 0xa7, 0x10, 0x27, 0x11, 0x33, 0x01, 0x0e, 0xfe, 0x70, 0x10, 0x07, 0x11, 0x33, 0x03, 0x2a, 0xfe, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0xcc, 0x05, 0xa0, 0x04, 0x38, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x00, 0x01, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x35, 0x33, 0x11, 0x23, 0x11, 0x35, 0x21, 0x07, 0x17, 0x05, 0x06, 0xfc, 0xce, 0x54, 0x6c, 0xfe, 0x9e, 0x01, 0x62, 0x6c, 0x54, 0x03, 0x32, 0x99, 0x99, 0xfc, 0x62, 0x5e, 0x5e, 0x01, 0xa1, 0x5d, 0x78, 0x01, 0x89, 0x5a, 0x01, 0x89, 0x78, 0x5d, 0xcd, 0xfc, 0xa4, 0x01, 0x45, 0xd2, 0x69, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0x00, 0xcc, 0x05, 0xaf, 0x04, 0x38, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x00, 0x01, 0x21, 0x27, 0x37, 0x01, 0x15, 0x01, 0x27, 0x37, 0x21, 0x15, 0x23, 0x11, 0x33, 0x11, 0x15, 0x21, 0x37, 0x27, 0x01, 0x02, 0x03, 0x32, 0x53, 0x6c, 0x01, 0x61, 0xfe, 0x9f, 0x6c, 0x53, 0xfc, 0xce, 0x99, 0x99, 0x03, 0x9e, 0x5f, 0x5f, 0x03, 0x63, 0x5d, 0x78, 0xfe, 0x77, 0x5a, 0xfe, 0x77, 0x78, 0x5d, 0xcd, 0x03, 0x5c, 0xfe, 0xbb, 0xd2, 0x69, 0x69, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe6, 0x00, 0x00, 0x05, 0x22, 0x05, 0xdc, 0x00, 0x11, 0x00, 0x00, 0x13, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x23, 0x11, 0x27, 0x11, 0x23, 0x11, 0x07, 0x11, 0x23, 0x11, 0x07, 0xe6, 0x01, 0xf6, 0x51, 0x01, 0xf5, 0x6c, 0x53, 0x6c, 0xbd, 0x6c, 0xbd, 0x6c, 0x53, 0x03, 0xae, 0x02, 0x2e, 0xfd, 0xd2, 0x78, 0x5c, 0xfc, 0x6e, 0x04, 0x0a, 0xd3, 0xfb, 0x23, 0x04, 0xdd, 0xd3, 0xfb, 0xf6, 0x03, 0x92, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe6, 0xff, 0xf9, 0x05, 0x22, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x00, 0x13, 0x37, 0x17, 0x11, 0x33, 0x11, 0x17, 0x11, 0x33, 0x11, 0x37, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x23, 0xe6, 0x6c, 0x53, 0x6c, 0xbd, 0x6c, 0xbd, 0x6c, 0x53, 0x6c, 0xfe, 0x0b, 0x51, 0x02, 0x27, 0x78, 0x5c, 0x03, 0x92, 0xfb, 0xf6, 0xd3, 0x04, 0xdd, 0xfb, 0x23, 0xd3, 0x04, 0x0a, 0xfc, 0x6e, 0x5c, 0x78, 0xfd, 0xd2, 0x00, 0x00, 0x02, 0x00, 0x47, 0x00, 0x80, 0x04, 0xa4, 0x06, 0xb5, 0x00, 0x1e, 0x00, 0x3d, 0x00, 0x00, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x10, 0x37, 0x36, 0x37, 0x36, 0x37, 0x01, 0x17, 0x07, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x10, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x03, 0x30, 0x17, 0x07, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x14, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x02, 0x77, 0x72, 0x65, 0x60, 0x56, 0x4d, 0x2d, 0x29, 0x29, 0x2d, 0x4d, 0x58, 0x67, 0x01, 0x61, 0x6c, 0xd1, 0x56, 0x4f, 0x61, 0x55, 0x4e, 0x2c, 0x29, 0x29, 0x2c, 0x4e, 0x55, 0x61, 0x64, 0x42, 0xd2, 0x6c, 0xfe, 0xda, 0x50, 0x3e, 0x39, 0x1f, 0x1e, 0x1e, 0x23, 0x35, 0x3b, 0x92, 0x54, 0x50, 0x49, 0x4b, 0x39, 0x39, 0x1f, 0x1e, 0x1e, 0x23, 0x35, 0x3b, 0x49, 0x34, 0x80, 0x2e, 0x2d, 0x5c, 0x5a, 0x6e, 0x6c, 0x01, 0x00, 0x6c, 0x6e, 0x5a, 0x5f, 0x2e, 0x01, 0x89, 0x78, 0xe9, 0x08, 0x24, 0x2d, 0x5c, 0x5a, 0x6e, 0x6c, 0xff, 0x00, 0x6c, 0x6e, 0x5a, 0x5c, 0x2d, 0x2e, 0x04, 0x29, 0xe8, 0x78, 0x01, 0x46, 0x21, 0x46, 0x40, 0x52, 0x4e, 0xbe, 0x4a, 0x56, 0x3c, 0x42, 0x42, 0x21, 0x23, 0x40, 0x40, 0x52, 0x4e, 0xbe, 0x4a, 0x56, 0x3c, 0x42, 0x21, 0x17, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x47, 0x00, 0x80, 0x04, 0xa4, 0x06, 0xb5, 0x00, 0x1e, 0x00, 0x3c, 0x00, 0x00, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x10, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x27, 0x37, 0x01, 0x16, 0x17, 0x16, 0x17, 0x16, 0x10, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x03, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x37, 0x36, 0x37, 0x36, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x01, 0x27, 0x02, 0x73, 0x6e, 0x65, 0x60, 0x56, 0x4d, 0x2d, 0x29, 0x29, 0x2d, 0x4d, 0x56, 0x60, 0x4f, 0x57, 0xd2, 0x6c, 0x01, 0x61, 0x67, 0x58, 0x4e, 0x2c, 0x29, 0x29, 0x2c, 0x4e, 0x55, 0x61, 0x64, 0xa0, 0x38, 0x34, 0x49, 0x3b, 0x35, 0x23, 0x1e, 0x1e, 0x1f, 0x39, 0x3a, 0x4a, 0x49, 0x50, 0x54, 0x92, 0x3b, 0x35, 0x23, 0x1e, 0x1e, 0x1f, 0x39, 0x3e, 0x4f, 0xfe, 0xd9, 0x6c, 0x80, 0x2e, 0x2d, 0x5c, 0x5a, 0x6e, 0x6c, 0x01, 0x00, 0x6c, 0x6e, 0x5a, 0x5c, 0x2d, 0x24, 0x08, 0xe9, 0x78, 0xfe, 0x77, 0x2e, 0x5f, 0x5a, 0x6e, 0x6c, 0xff, 0x00, 0x6c, 0x6e, 0x5a, 0x5c, 0x2d, 0x2e, 0x04, 0x29, 0x07, 0x17, 0x21, 0x42, 0x3c, 0x56, 0x4a, 0xbe, 0x4e, 0x52, 0x40, 0x40, 0x23, 0x21, 0x42, 0x42, 0x3c, 0x56, 0x4a, 0xbe, 0x4e, 0x52, 0x40, 0x46, 0x21, 0xfe, 0xba, 0x78, 0x00, 0x02, 0x00, 0xe6, 0xfe, 0xb2, 0x04, 0x63, 0x06, 0x14, 0x00, 0x10, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x15, 0x14, 0x16, 0x17, 0x26, 0x35, 0x11, 0x34, 0x37, 0x0e, 0x01, 0x1d, 0x01, 0x10, 0x07, 0x16, 0x01, 0x15, 0x23, 0x22, 0x06, 0x15, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x3d, 0x01, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x34, 0x36, 0x33, 0x02, 0x59, 0x44, 0x9e, 0x2d, 0x2b, 0x9e, 0x42, 0x9b, 0x9b, 0x02, 0x09, 0x2f, 0x7e, 0x4d, 0x4d, 0x7e, 0x2f, 0xec, 0xe0, 0x97, 0x61, 0x80, 0x38, 0x38, 0x80, 0x61, 0x97, 0xe0, 0x01, 0x12, 0xef, 0x98, 0x6d, 0x07, 0x47, 0x9d, 0x04, 0xd0, 0xa1, 0x42, 0x07, 0x6b, 0x98, 0xf0, 0xfe, 0xee, 0x3e, 0x44, 0x03, 0xf4, 0x64, 0x57, 0x8e, 0xfb, 0x30, 0x8d, 0x58, 0x64, 0x94, 0xdd, 0xef, 0x97, 0x74, 0x8f, 0x73, 0x95, 0xf0, 0xdd, 0x93, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe6, 0xfe, 0xb2, 0x04, 0x63, 0x06, 0x14, 0x00, 0x10, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x10, 0x37, 0x26, 0x11, 0x35, 0x34, 0x26, 0x27, 0x16, 0x15, 0x11, 0x14, 0x07, 0x3e, 0x01, 0x35, 0x01, 0x33, 0x32, 0x16, 0x1d, 0x01, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x34, 0x26, 0x2b, 0x01, 0x02, 0xf0, 0x9b, 0x9b, 0x42, 0x9f, 0x2c, 0x2d, 0x9e, 0x44, 0xfd, 0xf6, 0xed, 0xe0, 0x97, 0x61, 0x7f, 0x38, 0x38, 0x7f, 0x61, 0x97, 0xe0, 0xed, 0x30, 0x7e, 0x4d, 0x4d, 0x7e, 0x30, 0x01, 0x12, 0x01, 0x0e, 0x44, 0x3e, 0x01, 0x12, 0xf0, 0x98, 0x6b, 0x07, 0x42, 0xa1, 0xfb, 0x30, 0x9d, 0x47, 0x07, 0x6d, 0x98, 0x05, 0xf1, 0x93, 0xdd, 0xf0, 0x95, 0x73, 0x8f, 0x74, 0x97, 0xef, 0xdd, 0x94, 0x64, 0x58, 0x8d, 0x04, 0xd0, 0x8e, 0x57, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfe, 0x32, 0x05, 0x46, 0x05, 0xf9, 0x00, 0x02, 0x00, 0x06, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0x05, 0x11, 0x09, 0x02, 0x35, 0x01, 0x05, 0x09, 0x01, 0x03, 0x11, 0x01, 0x15, 0x04, 0xac, 0xfd, 0x00, 0x03, 0x99, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0x17, 0x03, 0x01, 0xfc, 0xff, 0x99, 0x04, 0x82, 0xcc, 0x02, 0x64, 0xfe, 0xce, 0xfd, 0xcc, 0x01, 0xe1, 0xa6, 0x01, 0xe1, 0x07, 0x01, 0x32, 0x01, 0x32, 0xfc, 0x9a, 0x04, 0x68, 0xfe, 0x1f, 0xa6, 0x00, 0x03, 0x00, 0xc3, 0x00, 0x1e, 0x06, 0x70, 0x04, 0xe6, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x25, 0x23, 0x11, 0x33, 0x01, 0x11, 0x09, 0x02, 0x35, 0x01, 0x06, 0x70, 0x99, 0x99, 0xfe, 0x3c, 0xfc, 0xf8, 0x03, 0xa1, 0xfb, 0x7e, 0x04, 0x82, 0x1e, 0x04, 0xc8, 0xfc, 0x3a, 0x02, 0xc4, 0xfe, 0x9e, 0xfd, 0x9c, 0x02, 0x11, 0xa6, 0x02, 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0x1e, 0x06, 0x70, 0x04, 0xe6, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x37, 0x11, 0x33, 0x11, 0x09, 0x02, 0x03, 0x11, 0x01, 0x15, 0xc3, 0x99, 0x01, 0x2b, 0x03, 0x08, 0xfc, 0xf8, 0x99, 0x04, 0x82, 0x1e, 0x04, 0xc8, 0xfb, 0x38, 0x01, 0x02, 0x01, 0x62, 0x01, 0x62, 0xfc, 0x3a, 0x04, 0xc8, 0xfd, 0xef, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x17, 0x11, 0x09, 0x01, 0x11, 0x01, 0x37, 0x01, 0x11, 0xc3, 0x02, 0xd7, 0x02, 0xd6, 0xfd, 0x2a, 0x8b, 0x01, 0xb2, 0x3e, 0x05, 0x80, 0xfd, 0xb0, 0x02, 0x50, 0xfa, 0x80, 0x02, 0x4e, 0x71, 0xfe, 0xa2, 0x02, 0xc6, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x17, 0x11, 0x09, 0x01, 0x11, 0x01, 0x27, 0x01, 0x11, 0xc3, 0x02, 0xd7, 0x02, 0xd6, 0xfd, 0x2a, 0x8c, 0xfe, 0x4e, 0x3e, 0x05, 0x80, 0xfd, 0xb0, 0x02, 0x50, 0xfa, 0x80, 0x02, 0x4e, 0x71, 0x01, 0x5e, 0xfd, 0x44, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x05, 0x00, 0x00, 0x17, 0x11, 0x09, 0x01, 0x11, 0x01, 0xc3, 0x02, 0xd7, 0x02, 0xd6, 0xfd, 0x2a, 0x3e, 0x05, 0x80, 0xfd, 0xb0, 0x02, 0x50, 0xfa, 0x80, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x08, 0x00, 0x00, 0x25, 0x15, 0x09, 0x01, 0x11, 0x09, 0x01, 0x15, 0x01, 0x06, 0x70, 0xfd, 0x2a, 0xfd, 0x29, 0x02, 0xd7, 0x02, 0xd6, 0xfd, 0xb5, 0xa2, 0xe0, 0x02, 0x4e, 0xfd, 0xb2, 0x05, 0x80, 0xfd, 0xb0, 0x02, 0x50, 0xdd, 0xfe, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0xff, 0xc2, 0x06, 0x70, 0x05, 0x42, 0x00, 0x08, 0x00, 0x00, 0x13, 0x35, 0x09, 0x01, 0x11, 0x09, 0x01, 0x35, 0x01, 0xc3, 0x02, 0xd7, 0x02, 0xd6, 0xfd, 0x2a, 0xfd, 0x29, 0x02, 0x4b, 0x04, 0x62, 0xe0, 0xfd, 0xb2, 0x02, 0x4e, 0xfa, 0x80, 0x02, 0x50, 0xfd, 0xb0, 0xdd, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xfe, 0x23, 0x03, 0x8a, 0x06, 0x75, 0x00, 0x03, 0x00, 0x00, 0x09, 0x03, 0x01, 0xc7, 0x01, 0xc2, 0xfe, 0x3e, 0xfe, 0x3e, 0x06, 0x75, 0xfb, 0xdb, 0xfb, 0xd3, 0x04, 0x2d, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x05, 0x04, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x01, 0xd8, 0x97, 0x01, 0x2b, 0x97, 0x01, 0x14, 0xfe, 0xec, 0x97, 0xfe, 0xd5, 0x97, 0xfe, 0xeb, 0x02, 0xd7, 0x02, 0x2d, 0xfd, 0xd3, 0x02, 0x2d, 0xfd, 0xd3, 0xaa, 0xfd, 0xd3, 0x02, 0x2d, 0xfd, 0xd3, 0x02, 0x2d, 0xaa, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc3, 0x00, 0x00, 0x05, 0x46, 0x05, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x01, 0x7e, 0x97, 0xa4, 0x97, 0xa4, 0x97, 0xba, 0xba, 0x97, 0xa4, 0x97, 0xa4, 0x97, 0xbb, 0x02, 0xd7, 0x02, 0x2d, 0xfd, 0xd3, 0x02, 0x2d, 0xfd, 0xd3, 0x02, 0x2d, 0xfd, 0xd3, 0xaa, 0xfd, 0xd3, 0x02, 0x2d, 0xfd, 0xd3, 0x02, 0x2d, 0xfd, 0xd3, 0x02, 0x2d, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x34, 0xfe, 0x6b, 0x06, 0xff, 0x05, 0xfb, 0x00, 0x03, 0x00, 0x1d, 0x00, 0x37, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x24, 0x20, 0x04, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x04, 0x20, 0x24, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x11, 0x01, 0x11, 0xfe, 0xef, 0x01, 0x19, 0xfe, 0xe0, 0x7e, 0x7c, 0x66, 0x69, 0x66, 0x66, 0x69, 0x66, 0x7c, 0x7e, 0x01, 0x20, 0x7e, 0x7b, 0x67, 0x68, 0x66, 0x66, 0x68, 0x67, 0x7b, 0xfe, 0x3e, 0x01, 0x67, 0x01, 0x33, 0x80, 0x80, 0x40, 0x3f, 0x3f, 0x40, 0x80, 0x80, 0xfe, 0xcd, 0xfe, 0x99, 0xfe, 0xcd, 0x80, 0x80, 0x40, 0x3f, 0x3f, 0x40, 0x80, 0x80, 0x02, 0xe8, 0xfe, 0x92, 0x03, 0xc8, 0x3b, 0x3a, 0x72, 0x73, 0xfe, 0xec, 0xa3, 0x9f, 0xfe, 0xec, 0x73, 0x72, 0x3a, 0x3b, 0x3b, 0x3a, 0x72, 0x73, 0x01, 0x14, 0x9f, 0xa3, 0x01, 0x14, 0x73, 0x72, 0x3a, 0xf4, 0x90, 0x8d, 0x8e, 0xac, 0xaa, 0xc9, 0xc5, 0xac, 0xaa, 0x8e, 0x8d, 0x90, 0x90, 0x8d, 0x8e, 0xaa, 0xac, 0xc5, 0xc9, 0xaa, 0xac, 0x8e, 0x8d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x34, 0xfe, 0x6b, 0x06, 0xff, 0x05, 0xfb, 0x00, 0x19, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x24, 0x20, 0x04, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x04, 0x20, 0x24, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x05, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x04, 0x2a, 0xfe, 0xe0, 0x7e, 0x7c, 0x66, 0x69, 0x66, 0x66, 0x69, 0x66, 0x7c, 0x7e, 0x01, 0x20, 0x7e, 0x7b, 0x67, 0x68, 0x66, 0x66, 0x68, 0x67, 0x7b, 0xfe, 0x3e, 0x01, 0x67, 0x01, 0x33, 0x80, 0x80, 0x40, 0x3f, 0x3f, 0x40, 0x80, 0x80, 0xfe, 0xcd, 0xfe, 0x99, 0xfe, 0xcd, 0x80, 0x80, 0x40, 0x3f, 0x3f, 0x40, 0x80, 0x73, 0x02, 0x3f, 0x02, 0x4c, 0xfd, 0xb4, 0x97, 0xfd, 0xb4, 0x02, 0x4c, 0x05, 0x42, 0x3b, 0x3a, 0x72, 0x73, 0xfe, 0xec, 0xa3, 0x9f, 0xfe, 0xec, 0x73, 0x72, 0x3a, 0x3b, 0x3b, 0x3a, 0x72, 0x73, 0x01, 0x14, 0x9f, 0xa3, 0x01, 0x14, 0x73, 0x72, 0x3a, 0xf4, 0x90, 0x8d, 0x8e, 0xac, 0xaa, 0xc9, 0xc5, 0xac, 0xaa, 0x8e, 0x8d, 0x90, 0x90, 0x8d, 0x8e, 0xaa, 0xac, 0xc5, 0xc9, 0xaa, 0xac, 0x8e, 0x80, 0x4b, 0xfd, 0x73, 0xaa, 0xfd, 0x73, 0x02, 0x8d, 0xaa, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x34, 0xfe, 0x6b, 0x06, 0xff, 0x05, 0xfb, 0x00, 0x19, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x07, 0x06, 0x07, 0x06, 0x02, 0x15, 0x14, 0x12, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x12, 0x35, 0x34, 0x02, 0x27, 0x26, 0x27, 0x24, 0x20, 0x04, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x04, 0x20, 0x24, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x17, 0x09, 0x01, 0x17, 0x09, 0x01, 0x07, 0x09, 0x01, 0x27, 0x09, 0x01, 0x04, 0x2a, 0xfe, 0xe0, 0x7e, 0x7c, 0x66, 0x69, 0x66, 0x66, 0x69, 0x66, 0x7c, 0x7e, 0x01, 0x20, 0x7e, 0x7b, 0x67, 0x68, 0x66, 0x66, 0x68, 0x67, 0x7b, 0xfe, 0x3e, 0x01, 0x67, 0x01, 0x33, 0x80, 0x80, 0x40, 0x3f, 0x3f, 0x40, 0x80, 0x80, 0xfe, 0xcd, 0xfe, 0x99, 0xfe, 0xcd, 0x80, 0x80, 0x40, 0x3f, 0x3f, 0x40, 0x80, 0x73, 0x53, 0x01, 0xa0, 0x01, 0xa0, 0x6c, 0xfe, 0x60, 0x01, 0xa0, 0x6b, 0xfe, 0x60, 0xfe, 0x61, 0x6d, 0x01, 0xa0, 0xfe, 0x60, 0x05, 0x42, 0x3b, 0x3a, 0x72, 0x73, 0xfe, 0xec, 0xa3, 0x9f, 0xfe, 0xec, 0x73, 0x72, 0x3a, 0x3b, 0x3b, 0x3a, 0x72, 0x73, 0x01, 0x14, 0x9f, 0xa3, 0x01, 0x14, 0x73, 0x72, 0x3a, 0xf4, 0x90, 0x8d, 0x8e, 0xac, 0xaa, 0xc9, 0xc5, 0xac, 0xaa, 0x8e, 0x8d, 0x90, 0x90, 0x8d, 0x8e, 0xaa, 0xac, 0xc5, 0xc9, 0xaa, 0xac, 0x8e, 0x80, 0xe8, 0xfe, 0x33, 0x01, 0xcd, 0x78, 0xfe, 0x32, 0xfe, 0x33, 0x77, 0x01, 0xcd, 0xfe, 0x33, 0x78, 0x01, 0xce, 0x01, 0xcd, 0xff, 0xff, 0x00, 0x69, 0xfe, 0x4d, 0x09, 0x22, 0x06, 0x0e, 0x10, 0x27, 0x09, 0x07, 0x05, 0xca, 0x00, 0x00, 0x10, 0x26, 0x09, 0x07, 0x00, 0x00, 0x10, 0x27, 0x09, 0x07, 0x01, 0xee, 0x00, 0x00, 0x10, 0x07, 0x09, 0x07, 0x03, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x1d, 0x00, 0x00, 0x17, 0x16, 0x33, 0x32, 0x37, 0x13, 0x23, 0x35, 0x33, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x33, 0x15, 0x23, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0xee, 0x10, 0x35, 0x3e, 0x07, 0x1d, 0xf7, 0xfe, 0x17, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x0f, 0x36, 0x3e, 0x07, 0x16, 0xf7, 0xfe, 0x1d, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x9b, 0x82, 0xaf, 0x02, 0x9a, 0xaa, 0x02, 0x0c, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0xfe, 0x0d, 0xaa, 0xfd, 0x4d, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x25, 0x00, 0x00, 0x17, 0x16, 0x33, 0x32, 0x37, 0x13, 0x23, 0x35, 0x33, 0x37, 0x21, 0x35, 0x21, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x33, 0x15, 0x23, 0x07, 0x21, 0x15, 0x21, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0xee, 0x10, 0x35, 0x3e, 0x07, 0x14, 0xee, 0xf5, 0x0b, 0xff, 0x00, 0x01, 0x07, 0x0e, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x0c, 0xed, 0xf5, 0x0a, 0x00, 0xff, 0xfe, 0xf9, 0x14, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x9b, 0x82, 0xaf, 0x01, 0xce, 0xaa, 0xf0, 0xa8, 0x01, 0x40, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0xfe, 0xd9, 0xa8, 0xf0, 0xaa, 0xfe, 0x19, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x03, 0x25, 0x15, 0x05, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x05, 0x35, 0x25, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x02, 0xd2, 0x10, 0x35, 0x3e, 0x07, 0x17, 0x01, 0x22, 0xfe, 0xd7, 0x1c, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x18, 0xfe, 0xde, 0x01, 0x29, 0x1c, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x04, 0xf6, 0x82, 0xaf, 0xfd, 0xe7, 0xb6, 0xa0, 0xba, 0xfd, 0x6d, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x02, 0x19, 0xb6, 0xa0, 0xba, 0x02, 0x93, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x2a, 0x00, 0x33, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x07, 0x26, 0x27, 0x03, 0x36, 0x37, 0x17, 0x06, 0x07, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x01, 0x13, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x02, 0xd2, 0x10, 0x35, 0x3e, 0x07, 0x0c, 0x89, 0x42, 0x66, 0x24, 0x48, 0x14, 0x1d, 0x13, 0x38, 0x31, 0x3d, 0x0d, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x0e, 0x54, 0x42, 0x63, 0x64, 0x4b, 0x69, 0x0e, 0x07, 0x8f, 0x89, 0x73, 0x12, 0xfe, 0x34, 0x14, 0x37, 0x28, 0x40, 0x43, 0x21, 0x04, 0xf6, 0x82, 0xaf, 0xfe, 0xd6, 0x29, 0x88, 0x41, 0x48, 0x21, 0xfe, 0x2b, 0x06, 0x11, 0x70, 0x24, 0x09, 0xfe, 0xbe, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x01, 0x31, 0x18, 0x49, 0x6f, 0x9b, 0x9c, 0x73, 0x56, 0x13, 0x01, 0x3c, 0xa4, 0x88, 0x7a, 0x8f, 0xfc, 0x45, 0x01, 0xd6, 0x11, 0x2e, 0x4a, 0x67, 0x68, 0x48, 0x24, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0xc3, 0x06, 0x0e, 0x00, 0x32, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x03, 0x36, 0x37, 0x36, 0x3d, 0x01, 0x07, 0x27, 0x37, 0x33, 0x17, 0x07, 0x27, 0x15, 0x14, 0x07, 0x06, 0x07, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x35, 0x33, 0x14, 0x17, 0x16, 0x17, 0x13, 0x3e, 0x01, 0x32, 0x17, 0x16, 0x17, 0x02, 0xd2, 0x10, 0x35, 0x3e, 0x07, 0x27, 0x3a, 0x2a, 0x4e, 0x54, 0x41, 0xaa, 0x31, 0xa9, 0x41, 0x53, 0x62, 0x4d, 0x62, 0x0f, 0x08, 0x90, 0x88, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3d, 0x08, 0x0f, 0x52, 0x38, 0x6b, 0x5c, 0x48, 0x2e, 0x27, 0x28, 0x07, 0x90, 0x88, 0x42, 0x30, 0x13, 0x04, 0xf6, 0x82, 0xaf, 0xfc, 0x78, 0x10, 0x2f, 0x55, 0x72, 0x1e, 0x5d, 0x48, 0xbd, 0xbd, 0x48, 0x5d, 0x1e, 0x9c, 0x6c, 0x56, 0x11, 0xfe, 0xa1, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x01, 0x4d, 0x19, 0x3e, 0x77, 0x9a, 0x72, 0x4e, 0x33, 0x0b, 0x03, 0x99, 0xa5, 0x87, 0x46, 0x34, 0x8f, 0x00, 0x00, 0x02, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x03, 0x00, 0x21, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x03, 0x13, 0x21, 0x11, 0x21, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x21, 0x11, 0x21, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x01, 0x87, 0xbd, 0xbd, 0x0f, 0x10, 0x01, 0x51, 0xfe, 0xc8, 0x12, 0x07, 0x92, 0x88, 0x71, 0x12, 0x85, 0x10, 0x33, 0x3f, 0x08, 0x0c, 0x01, 0x19, 0xfe, 0xc4, 0x0b, 0x08, 0x98, 0x82, 0x71, 0x12, 0x85, 0x10, 0x33, 0x40, 0x02, 0xa6, 0xfe, 0xfd, 0xea, 0x01, 0x72, 0x02, 0x30, 0x01, 0xae, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0xfe, 0xf5, 0xfc, 0xbc, 0xfe, 0xff, 0xad, 0x7f, 0x7d, 0x8c, 0x0f, 0x82, 0x00, 0x02, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x03, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x13, 0x06, 0x07, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x16, 0x10, 0x07, 0x06, 0x07, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x01, 0x87, 0xbd, 0xbd, 0x59, 0x25, 0x1c, 0x14, 0x07, 0x92, 0x88, 0x71, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0c, 0x59, 0x3b, 0x63, 0x63, 0x4d, 0x68, 0x0d, 0x08, 0x91, 0x88, 0x72, 0x12, 0x85, 0x10, 0x33, 0x3f, 0x08, 0x14, 0x24, 0x31, 0x63, 0x7a, 0x85, 0x02, 0xa6, 0xfe, 0x01, 0x7e, 0x02, 0x05, 0x01, 0xc3, 0xa7, 0x85, 0x7c, 0x8d, 0x0f, 0x82, 0xaf, 0xfe, 0xd6, 0x18, 0x4b, 0x7c, 0xfe, 0xd2, 0x6f, 0x55, 0x13, 0xfe, 0xbe, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0x01, 0xb6, 0x10, 0x93, 0xd8, 0x7f, 0x00, 0x00, 0x02, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0xff, 0x06, 0x0e, 0x00, 0x03, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x01, 0x16, 0x33, 0x32, 0x37, 0x13, 0x16, 0x17, 0x16, 0x32, 0x36, 0x34, 0x26, 0x23, 0x22, 0x07, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x36, 0x33, 0x32, 0x16, 0x10, 0x06, 0x23, 0x22, 0x27, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x02, 0x4e, 0xbd, 0xbd, 0xfe, 0xa0, 0x10, 0x35, 0x3e, 0x07, 0x18, 0x29, 0x32, 0x65, 0xb2, 0x87, 0x7c, 0x65, 0xc0, 0x4b, 0x16, 0x05, 0x92, 0x88, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x0d, 0x35, 0x3d, 0x98, 0xb9, 0xc6, 0x8b, 0x4e, 0x42, 0x0f, 0x08, 0x90, 0x88, 0x73, 0x12, 0x02, 0xae, 0xfe, 0xfd, 0xb5, 0x82, 0xaf, 0x02, 0x33, 0x3e, 0x1c, 0x36, 0x91, 0xd1, 0x8f, 0xa1, 0x02, 0x5d, 0xa4, 0x88, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0xfe, 0xcb, 0x13, 0xe9, 0xfe, 0xd2, 0xdb, 0x21, 0xfe, 0xa3, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x03, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x31, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x16, 0x36, 0x34, 0x26, 0x22, 0x06, 0x14, 0x16, 0x03, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x10, 0x37, 0x36, 0x37, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x16, 0x10, 0x07, 0x06, 0x07, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x01, 0x82, 0xbe, 0xbe, 0xb7, 0x85, 0x7c, 0xc1, 0x81, 0x80, 0x92, 0x10, 0x35, 0x3e, 0x07, 0x0e, 0x54, 0x42, 0x63, 0x64, 0x4b, 0x69, 0x0e, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x0c, 0x59, 0x3b, 0x63, 0x63, 0x4d, 0x68, 0x0d, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x02, 0xb0, 0xfe, 0x7a, 0x90, 0xd1, 0x8f, 0x91, 0xcf, 0x90, 0xfe, 0x2d, 0x82, 0xaf, 0x01, 0x31, 0x18, 0x49, 0x6f, 0x01, 0x37, 0x73, 0x56, 0x13, 0x01, 0x3c, 0xa4, 0x88, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0xfe, 0xd6, 0x18, 0x4b, 0x7c, 0xfe, 0xd2, 0x6f, 0x55, 0x13, 0xfe, 0xbe, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x00, 0x03, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x25, 0x00, 0x00, 0x37, 0x11, 0x21, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x33, 0x11, 0x21, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x1b, 0x01, 0x03, 0x33, 0x11, 0x21, 0x23, 0x11, 0x33, 0x89, 0x01, 0x1b, 0x0f, 0x07, 0x92, 0x88, 0x71, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0d, 0xfc, 0xfe, 0xe3, 0x0c, 0x08, 0x98, 0x80, 0x73, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x0c, 0xb1, 0x15, 0x9a, 0xfe, 0xe5, 0x9a, 0x84, 0x9b, 0x02, 0xfe, 0x01, 0x49, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0xfe, 0xd0, 0xfd, 0x02, 0xfe, 0xde, 0xad, 0x7f, 0x7b, 0x8e, 0x0f, 0x82, 0xaf, 0x01, 0x09, 0x02, 0x74, 0xfe, 0x16, 0x01, 0xea, 0xfe, 0x16, 0x00, 0x01, 0xff, 0xc4, 0xfe, 0x4d, 0x03, 0xfc, 0x06, 0x0e, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x03, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x35, 0x36, 0x37, 0x26, 0x27, 0x23, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x21, 0x17, 0x07, 0x01, 0x35, 0x01, 0x17, 0x07, 0x21, 0x13, 0x3e, 0x01, 0x32, 0x17, 0x16, 0x17, 0x02, 0xd2, 0x10, 0x35, 0x3e, 0x07, 0x16, 0xf3, 0x5a, 0x7d, 0x82, 0x55, 0x56, 0x07, 0x07, 0x56, 0xfa, 0x1d, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3d, 0x08, 0x1d, 0xfe, 0xf9, 0xa8, 0x56, 0xfe, 0xe5, 0x01, 0x1b, 0x56, 0xa8, 0x01, 0x0c, 0x19, 0x07, 0x8f, 0x89, 0x42, 0x30, 0x13, 0x04, 0xf6, 0x82, 0xaf, 0xfd, 0xef, 0x8f, 0xc6, 0x8c, 0x88, 0x04, 0x65, 0x62, 0x06, 0xfd, 0x49, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x02, 0x9e, 0xba, 0x60, 0x01, 0x3a, 0x48, 0x01, 0x3a, 0x60, 0xba, 0x02, 0x2a, 0xa5, 0x87, 0x46, 0x34, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x23, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x03, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x02, 0xd2, 0x10, 0x35, 0x3e, 0x07, 0x12, 0x8d, 0x6c, 0xe2, 0xe2, 0x6c, 0x9f, 0x16, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x15, 0x8f, 0x6e, 0xe5, 0xe3, 0x6c, 0xa0, 0x15, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x04, 0xf6, 0x82, 0xaf, 0xfe, 0x58, 0x9d, 0x79, 0xfc, 0xfc, 0x78, 0xb0, 0xfd, 0xf4, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x01, 0xe2, 0xa0, 0x79, 0xfc, 0xfc, 0x78, 0xb3, 0x01, 0xd8, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x2a, 0x00, 0x00, 0x17, 0x16, 0x33, 0x32, 0x37, 0x13, 0x06, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x36, 0x37, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x16, 0x17, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x27, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0xee, 0x10, 0x35, 0x3e, 0x07, 0x29, 0x3b, 0x1d, 0x2e, 0x6d, 0x8b, 0x6d, 0x0d, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x0c, 0x51, 0x38, 0x4e, 0x6d, 0x70, 0x28, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x9b, 0x82, 0xaf, 0x03, 0xa6, 0x10, 0x32, 0x50, 0x9c, 0xfe, 0xc8, 0x01, 0x49, 0xcf, 0xbc, 0x11, 0x01, 0x2b, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0xfe, 0xe6, 0x18, 0x45, 0x61, 0xd6, 0xfe, 0xb7, 0x01, 0x38, 0xf3, 0x32, 0xfc, 0x4a, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x00, 0x01, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x27, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x03, 0x36, 0x19, 0x01, 0x33, 0x11, 0x10, 0x07, 0x03, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x13, 0x26, 0x27, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x13, 0x3e, 0x01, 0x32, 0x16, 0x17, 0x02, 0xd2, 0x10, 0x35, 0x3e, 0x07, 0x26, 0x84, 0x6d, 0xf6, 0x0f, 0x08, 0x8f, 0x89, 0x73, 0x12, 0x85, 0x10, 0x35, 0x3e, 0x07, 0x0f, 0x53, 0x39, 0x4d, 0x6d, 0x71, 0x27, 0x07, 0x8f, 0x89, 0x73, 0x12, 0x04, 0xf6, 0x82, 0xaf, 0xfc, 0x8d, 0x26, 0x01, 0x07, 0x01, 0x38, 0xfe, 0xb7, 0xfe, 0x8c, 0x27, 0xfe, 0xa2, 0xa5, 0x87, 0x7a, 0x8f, 0x0f, 0x82, 0xaf, 0x01, 0x4c, 0x17, 0x46, 0x61, 0xd6, 0x01, 0x49, 0xfe, 0xc8, 0xf5, 0x31, 0x03, 0x85, 0xa5, 0x87, 0x7a, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x69, 0xfe, 0x4d, 0x03, 0x60, 0x06, 0xf9, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x01, 0x15, 0x21, 0x35, 0x01, 0xb3, 0x07, 0x92, 0x43, 0x45, 0x71, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x3a, 0x08, 0x91, 0x45, 0x43, 0x72, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x01, 0xe8, 0xfd, 0x3e, 0x04, 0xe2, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0xfa, 0xb0, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0x07, 0x67, 0xa0, 0xa0, 0x00, 0x00, 0x02, 0x00, 0x60, 0xfd, 0x62, 0x03, 0x57, 0x06, 0x0e, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x03, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x27, 0x37, 0x16, 0x33, 0x32, 0x37, 0x01, 0x35, 0x21, 0x15, 0x01, 0xb3, 0x07, 0x92, 0x43, 0x45, 0x71, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0x3a, 0x08, 0x91, 0x45, 0x43, 0x72, 0x12, 0x85, 0x10, 0x33, 0x40, 0x07, 0xfe, 0xe8, 0x02, 0xc3, 0x04, 0xe2, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0xfa, 0xb0, 0xa7, 0x85, 0x7d, 0x8c, 0x0f, 0x82, 0xaf, 0xfd, 0xd0, 0xa0, 0xa0, 0x00, 0xff, 0xff, 0x00, 0xfc, 0x00, 0x3f, 0x05, 0x0d, 0x04, 0xc5, 0x10, 0x06, 0x00, 0x99, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0x01, 0xd3, 0x05, 0x46, 0x04, 0x6a, 0x10, 0x26, 0x09, 0x18, 0x00, 0x00, 0x10, 0x07, 0x09, 0xa1, 0x01, 0xdf, 0x01, 0x24, 0xff, 0xff, 0x00, 0xc3, 0x00, 0x9f, 0x05, 0x46, 0x04, 0x6a, 0x10, 0x26, 0x09, 0x18, 0x00, 0x00, 0x10, 0x27, 0x09, 0xa1, 0x00, 0xd0, 0xfe, 0x57, 0x10, 0x07, 0x09, 0xa1, 0x02, 0xed, 0x01, 0x24, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x04, 0x05, 0x46, 0x04, 0xa6, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x05, 0x15, 0x01, 0x35, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0x5f, 0x03, 0xa1, 0xfb, 0x7e, 0x04, 0x82, 0x46, 0xb6, 0x01, 0xd1, 0xb6, 0x02, 0x65, 0xfe, 0x91, 0xfe, 0x93, 0xb6, 0x01, 0xd1, 0xa6, 0x01, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x04, 0x05, 0x46, 0x04, 0xa6, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x17, 0x01, 0x15, 0x01, 0x11, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0xa1, 0x46, 0x01, 0xd1, 0xb6, 0xfe, 0x2f, 0x04, 0xec, 0xb6, 0xfe, 0x2f, 0xa6, 0xfe, 0x2f, 0xb6, 0x01, 0x6d, 0x00, 0xff, 0xff, 0x00, 0xc3, 0xff, 0x04, 0x05, 0x47, 0x04, 0xa6, 0x10, 0x27, 0x09, 0xa1, 0x03, 0xc4, 0xff, 0xbb, 0x10, 0x06, 0x0d, 0xd5, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0xff, 0x04, 0x05, 0x46, 0x04, 0xa6, 0x10, 0x26, 0x09, 0xa1, 0xfe, 0xbb, 0x10, 0x06, 0x0d, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0xff, 0x04, 0x05, 0x46, 0x05, 0x27, 0x10, 0x27, 0x09, 0xa1, 0x00, 0xf4, 0x01, 0xe1, 0x10, 0x06, 0x0d, 0xd5, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0xff, 0x04, 0x05, 0x46, 0x05, 0x27, 0x10, 0x27, 0x09, 0xa1, 0x02, 0xcd, 0x01, 0xe1, 0x10, 0x06, 0x0d, 0xd6, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0xff, 0x04, 0x05, 0x47, 0x06, 0x12, 0x10, 0x27, 0x09, 0xa1, 0x03, 0xc4, 0x02, 0xcc, 0x10, 0x06, 0x0d, 0xd5, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0xff, 0x04, 0x05, 0x46, 0x06, 0x0d, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xfe, 0x02, 0xc7, 0x10, 0x06, 0x0d, 0xd6, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0xf1, 0x05, 0x46, 0x05, 0x4e, 0x00, 0x1c, 0x00, 0x3a, 0x00, 0x41, 0x00, 0x00, 0x25, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x13, 0x09, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x06, 0x05, 0x0e, 0x8b, 0x55, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x63, 0x85, 0x09, 0x0b, 0x0d, 0x8c, 0x55, 0x4d, 0x97, 0x5e, 0x5f, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x06, 0x05, 0x0e, 0x8b, 0x55, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x63, 0x85, 0x09, 0x04, 0x07, 0x0d, 0x8c, 0x55, 0x4d, 0x97, 0x5d, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0x50, 0xb3, 0x4e, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x3b, 0x05, 0x04, 0x06, 0x3d, 0x4b, 0x01, 0x9b, 0xb2, 0x50, 0x44, 0x3a, 0x04, 0x04, 0x02, 0x06, 0x3c, 0x4c, 0x52, 0xb2, 0x4e, 0x44, 0x3a, 0x04, 0x02, 0x04, 0x06, 0x3c, 0x4a, 0x03, 0x5e, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0xf1, 0x05, 0x46, 0x05, 0x4e, 0x00, 0x1c, 0x00, 0x3a, 0x00, 0x41, 0x00, 0x00, 0x25, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x1e, 0x01, 0x17, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x06, 0x05, 0x0e, 0x8b, 0x55, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x63, 0x85, 0x09, 0x0b, 0x0d, 0x8c, 0x55, 0x4d, 0x97, 0x5e, 0x5f, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x06, 0x05, 0x0e, 0x8b, 0x55, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x63, 0x85, 0x09, 0x04, 0x07, 0x0d, 0x8c, 0x55, 0x4d, 0x97, 0xfb, 0xdb, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0x50, 0xb3, 0x4e, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x3b, 0x05, 0x04, 0x06, 0x3d, 0x4b, 0x01, 0x9b, 0xb2, 0x50, 0x44, 0x3a, 0x04, 0x04, 0x02, 0x06, 0x3c, 0x4c, 0x52, 0xb2, 0x4e, 0x44, 0x3a, 0x04, 0x02, 0x04, 0x06, 0x3c, 0x4a, 0x03, 0x5e, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x08, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x0b, 0x00, 0x12, 0x00, 0x00, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x03, 0x4e, 0x87, 0x51, 0x01, 0xc1, 0xfd, 0xed, 0x78, 0x87, 0x51, 0xfe, 0x3f, 0x02, 0x13, 0x02, 0x6f, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0x01, 0xa2, 0x50, 0xa8, 0xaa, 0xf8, 0x50, 0xa8, 0xaa, 0x03, 0x4e, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x08, 0x05, 0x46, 0x04, 0xa8, 0x00, 0x0b, 0x00, 0x12, 0x00, 0x00, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x03, 0x4e, 0x87, 0x51, 0x01, 0xc1, 0xfd, 0xed, 0x78, 0x87, 0x51, 0xfe, 0x3f, 0x02, 0x13, 0xfd, 0xed, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0x01, 0xa2, 0x50, 0xa8, 0xaa, 0xf8, 0x50, 0xa8, 0xaa, 0x03, 0x4e, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0x5f, 0x05, 0x46, 0x05, 0x4e, 0x00, 0x36, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x07, 0x27, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x17, 0x16, 0x1f, 0x01, 0x37, 0x17, 0x07, 0x16, 0x33, 0x32, 0x36, 0x13, 0x09, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x3d, 0x4b, 0x2e, 0x7e, 0x4e, 0x4d, 0x97, 0x5e, 0x5f, 0xa1, 0x58, 0x62, 0x84, 0x07, 0x53, 0x94, 0x50, 0x39, 0x2b, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x3e, 0x4b, 0x2e, 0x7d, 0x4e, 0x4f, 0x9b, 0x58, 0x5e, 0x51, 0x62, 0x45, 0x84, 0x64, 0x07, 0x52, 0x93, 0x50, 0x3a, 0x2c, 0x4d, 0x97, 0x5d, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0x01, 0x96, 0xb2, 0x50, 0x44, 0x17, 0x83, 0x34, 0x4b, 0x55, 0xb3, 0x4e, 0x45, 0x3b, 0x03, 0xe9, 0x40, 0xe2, 0x10, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x17, 0x82, 0x34, 0x4c, 0x52, 0xb2, 0x4e, 0x22, 0x2a, 0x08, 0x0e, 0x2c, 0x03, 0xe9, 0x40, 0xe3, 0x0f, 0x4a, 0x03, 0x5e, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0x5f, 0x05, 0x46, 0x05, 0x4e, 0x00, 0x35, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x07, 0x27, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x01, 0x37, 0x17, 0x07, 0x16, 0x33, 0x32, 0x36, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x3d, 0x4b, 0x2e, 0x7e, 0x4e, 0x4d, 0x97, 0x5e, 0x5f, 0xa1, 0x58, 0x62, 0x84, 0x07, 0x53, 0x94, 0x50, 0x39, 0x2b, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x3e, 0x4b, 0x2e, 0x7d, 0x4e, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x63, 0x85, 0x07, 0x52, 0x93, 0x50, 0x3a, 0x2c, 0x4d, 0x97, 0xfb, 0xdb, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0x01, 0x96, 0xb2, 0x50, 0x44, 0x17, 0x83, 0x34, 0x4b, 0x55, 0xb3, 0x4e, 0x45, 0x3b, 0x03, 0xe9, 0x40, 0xe2, 0x10, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x17, 0x82, 0x34, 0x4c, 0x52, 0xb2, 0x4e, 0x44, 0x3a, 0x03, 0xe9, 0x40, 0xe3, 0x0f, 0x4a, 0x03, 0x5e, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfd, 0x84, 0x05, 0x46, 0x06, 0x54, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x01, 0x15, 0x01, 0x35, 0x01, 0x15, 0x05, 0x01, 0x21, 0x35, 0x21, 0x01, 0x2d, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x21, 0x35, 0x21, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xe4, 0x03, 0x1c, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x1d, 0xfc, 0xe3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0x03, 0xfb, 0xb0, 0x01, 0x2f, 0xaa, 0x01, 0x30, 0xb2, 0xd2, 0xfd, 0x5c, 0xaa, 0xfb, 0x5e, 0xd5, 0xd2, 0xb2, 0xfe, 0xd0, 0xaa, 0xfe, 0xd1, 0x03, 0x7e, 0xaa, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfd, 0x84, 0x05, 0x46, 0x06, 0x54, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x13, 0x2d, 0x01, 0x35, 0x01, 0x15, 0x01, 0x11, 0x35, 0x21, 0x15, 0x11, 0x15, 0x01, 0x35, 0x01, 0x15, 0x05, 0x01, 0x35, 0x21, 0x15, 0xc3, 0x03, 0x1d, 0xfc, 0xe3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xe4, 0xfe, 0x9a, 0x04, 0x82, 0x03, 0xfb, 0xd5, 0xd2, 0xb2, 0xfe, 0xd0, 0xaa, 0xfe, 0xd1, 0xfe, 0xe1, 0xaa, 0xaa, 0xfc, 0x08, 0xb0, 0x01, 0x2f, 0xaa, 0x01, 0x30, 0xb2, 0xd2, 0x01, 0xf9, 0xaa, 0xaa, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xff, 0x02, 0x05, 0x46, 0x05, 0x4e, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x25, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x01, 0x21, 0x15, 0x21, 0x09, 0x02, 0x15, 0x01, 0x35, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x63, 0x83, 0x0f, 0x05, 0x0e, 0x8b, 0x55, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x63, 0x85, 0x0d, 0x14, 0x8c, 0x55, 0x4d, 0x97, 0xfb, 0xdc, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x81, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0x01, 0x96, 0xb2, 0x50, 0x44, 0x3a, 0x08, 0x02, 0x06, 0x3c, 0x4b, 0x53, 0xb2, 0x4e, 0x44, 0x3a, 0x06, 0x0a, 0x3c, 0x4a, 0xfe, 0x6c, 0xaa, 0x05, 0x9c, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xff, 0x02, 0x05, 0x46, 0x05, 0x4e, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x25, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x01, 0x21, 0x15, 0x21, 0x03, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x63, 0x83, 0x0f, 0x05, 0x0e, 0x8b, 0x55, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x63, 0x85, 0x0d, 0x14, 0x8c, 0x55, 0x4d, 0x97, 0xfb, 0xdc, 0x04, 0x82, 0xfb, 0x7e, 0x01, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0x01, 0x96, 0xb2, 0x50, 0x44, 0x3a, 0x08, 0x02, 0x06, 0x3c, 0x4b, 0x53, 0xb2, 0x4e, 0x44, 0x3a, 0x06, 0x0a, 0x3c, 0x4a, 0xfe, 0x6c, 0xaa, 0x05, 0x9c, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0x12, 0x05, 0x46, 0x06, 0x0c, 0x00, 0x1a, 0x00, 0x21, 0x00, 0x28, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x01, 0x35, 0x01, 0x15, 0x05, 0x01, 0x2d, 0x01, 0x35, 0x01, 0x15, 0x01, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0x8b, 0x55, 0x4d, 0x98, 0x5d, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xe4, 0xfe, 0x9a, 0x03, 0x1d, 0xfc, 0xe3, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0xbe, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x09, 0x3d, 0x4b, 0x01, 0x4a, 0xb0, 0x01, 0x2f, 0xaa, 0x01, 0x30, 0xb2, 0xd2, 0xfa, 0x3a, 0xd5, 0xd2, 0xb2, 0xfe, 0xd0, 0xaa, 0xfe, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0x12, 0x05, 0x46, 0x06, 0x0c, 0x00, 0x1a, 0x00, 0x21, 0x00, 0x28, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x02, 0x16, 0x33, 0x32, 0x36, 0x01, 0x2d, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x15, 0x01, 0x35, 0x01, 0x15, 0x05, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x10, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x0d, 0x14, 0x8b, 0x55, 0x4d, 0x98, 0xfb, 0xdb, 0x03, 0x1d, 0xfc, 0xe3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xe4, 0x02, 0xbe, 0xb2, 0x4f, 0x45, 0x3b, 0x07, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x06, 0x09, 0x3d, 0x4b, 0x01, 0x4a, 0xd5, 0xd2, 0xb2, 0xfe, 0xd0, 0xaa, 0xfe, 0xd1, 0xfb, 0xbf, 0xb0, 0x01, 0x2f, 0xaa, 0x01, 0x30, 0xb2, 0xd2, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfe, 0x2c, 0x05, 0x46, 0x05, 0xd7, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x13, 0x2d, 0x01, 0x35, 0x01, 0x15, 0x01, 0x11, 0x35, 0x21, 0x15, 0x11, 0x15, 0x01, 0x35, 0x01, 0x15, 0x05, 0x01, 0x35, 0x21, 0x15, 0xc3, 0x03, 0x1d, 0xfc, 0xe3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xe4, 0xfe, 0x9a, 0x04, 0x82, 0x01, 0x25, 0xd5, 0xd2, 0xb2, 0xfe, 0xd0, 0xaa, 0xfe, 0xd1, 0xfe, 0xe1, 0xaa, 0xaa, 0x04, 0x28, 0xb0, 0x01, 0x2f, 0xaa, 0x01, 0x30, 0xb2, 0xd2, 0xf9, 0xd9, 0xaa, 0xaa, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfe, 0x2c, 0x05, 0x46, 0x05, 0xd7, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x01, 0x15, 0x01, 0x35, 0x01, 0x15, 0x05, 0x01, 0x21, 0x35, 0x21, 0x01, 0x2d, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x21, 0x35, 0x21, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xe4, 0x03, 0x1c, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x1d, 0xfc, 0xe3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0x01, 0x25, 0xb0, 0x01, 0x2f, 0xaa, 0x01, 0x30, 0xb2, 0xd2, 0xfd, 0x5c, 0xaa, 0x03, 0x7e, 0xd5, 0xd2, 0xb2, 0xfe, 0xd0, 0xaa, 0xfe, 0xd1, 0xfb, 0x5e, 0xaa, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfe, 0x36, 0x05, 0x46, 0x05, 0xee, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x01, 0x15, 0x01, 0x35, 0x01, 0x15, 0x05, 0x09, 0x01, 0x35, 0x09, 0x01, 0x2d, 0x01, 0x35, 0x01, 0x15, 0x01, 0x11, 0x35, 0x01, 0x15, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xe4, 0x03, 0x1c, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x1d, 0xfc, 0xe3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0x03, 0x95, 0xb0, 0x01, 0x2f, 0xaa, 0x01, 0x30, 0xb2, 0xd2, 0xfd, 0x56, 0x01, 0x2f, 0xb0, 0xfe, 0xd1, 0xfd, 0xa6, 0xd5, 0xd2, 0xb2, 0xfe, 0xd0, 0xaa, 0xfe, 0xd1, 0xfe, 0xd0, 0xb0, 0x01, 0x2f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfe, 0x36, 0x05, 0x46, 0x05, 0xee, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x13, 0x2d, 0x01, 0x35, 0x01, 0x15, 0x01, 0x11, 0x35, 0x01, 0x15, 0x11, 0x15, 0x01, 0x35, 0x01, 0x15, 0x05, 0x09, 0x01, 0x35, 0x01, 0xc3, 0x03, 0x1d, 0xfc, 0xe3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xe4, 0x03, 0x1c, 0xfb, 0x7e, 0x04, 0x82, 0x03, 0x95, 0xd5, 0xd2, 0xb2, 0xfe, 0xd0, 0xaa, 0xfe, 0xd1, 0xfe, 0xdb, 0xb0, 0x01, 0x2f, 0xb0, 0xfd, 0x27, 0xb0, 0x01, 0x2f, 0xaa, 0x01, 0x30, 0xb2, 0xd2, 0xfd, 0x4b, 0x01, 0x2f, 0xb0, 0xfe, 0xd1, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x84, 0x05, 0x46, 0x05, 0x26, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x01, 0x35, 0x01, 0x11, 0x15, 0x01, 0x35, 0x01, 0x15, 0x01, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0x5f, 0x04, 0x70, 0xfe, 0x2f, 0xb6, 0x01, 0xd1, 0xfb, 0x14, 0xb6, 0x01, 0xd1, 0xa6, 0x01, 0xd1, 0xb6, 0xfe, 0x93, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0x84, 0x05, 0x46, 0x05, 0x26, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x35, 0x01, 0x15, 0x09, 0x02, 0x35, 0x01, 0x15, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0xa1, 0xfc, 0x5f, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x70, 0xb6, 0xfe, 0x2f, 0xb6, 0xfd, 0x9b, 0x01, 0x6f, 0x01, 0x6d, 0xb6, 0xfe, 0x2f, 0xa6, 0xfe, 0x2f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0xff, 0x84, 0x05, 0x47, 0x05, 0x26, 0x10, 0x27, 0x09, 0xa1, 0x03, 0xc4, 0xfe, 0xee, 0x10, 0x06, 0x0d, 0xed, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc3, 0xff, 0x84, 0x05, 0x46, 0x05, 0x26, 0x10, 0x27, 0x09, 0xa1, 0xff, 0xfe, 0xfe, 0xe4, 0x10, 0x06, 0x0d, 0xee, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc4, 0xff, 0xb6, 0x05, 0x46, 0x05, 0x7b, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x35, 0x21, 0x15, 0x11, 0x15, 0x01, 0x35, 0x01, 0x15, 0x09, 0x01, 0x35, 0x21, 0x15, 0xc4, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xa0, 0xfe, 0xde, 0x04, 0x82, 0x04, 0xd1, 0xaa, 0xaa, 0xfb, 0x95, 0xb0, 0x01, 0x6f, 0xaa, 0x01, 0x70, 0xb2, 0xfe, 0xee, 0x02, 0x39, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc4, 0xff, 0xb6, 0x05, 0x46, 0x05, 0x7b, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x09, 0x02, 0x35, 0x01, 0x15, 0x09, 0x01, 0x21, 0x35, 0x21, 0x05, 0x46, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0xfc, 0xa0, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0x04, 0xd1, 0xaa, 0xfa, 0xeb, 0x01, 0x15, 0x01, 0x12, 0xb2, 0xfe, 0x90, 0xaa, 0xfe, 0x91, 0x03, 0xfe, 0xaa, 0x00, 0x03, 0x00, 0xc3, 0xff, 0xc0, 0x05, 0x46, 0x05, 0xcd, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x15, 0x11, 0x15, 0x01, 0x35, 0x01, 0x15, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xa0, 0x03, 0xab, 0xb2, 0x01, 0x70, 0xb2, 0xfd, 0x4e, 0xb2, 0x01, 0x70, 0xb2, 0xfc, 0x97, 0xb0, 0x01, 0x6f, 0xaa, 0x01, 0x70, 0xb2, 0xfe, 0xee, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xff, 0xc0, 0x05, 0x46, 0x05, 0xcd, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x09, 0x01, 0x35, 0x01, 0x11, 0x01, 0x35, 0x09, 0x03, 0x35, 0x01, 0x15, 0x01, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0xfc, 0xa0, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0xab, 0x01, 0x70, 0xb2, 0xfe, 0x90, 0xfe, 0x0c, 0x01, 0x70, 0xb2, 0xfe, 0x90, 0xfd, 0x55, 0x01, 0x15, 0x01, 0x12, 0xb2, 0xfe, 0x90, 0xaa, 0xfe, 0x91, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x11, 0x05, 0x46, 0x05, 0x28, 0x00, 0x1b, 0x00, 0x22, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x03, 0x15, 0x01, 0x35, 0x01, 0x15, 0x01, 0x05, 0x46, 0x5e, 0x97, 0x4d, 0x55, 0x8c, 0x0d, 0x0b, 0x09, 0x85, 0x63, 0x56, 0xa2, 0x5e, 0x58, 0x9b, 0x4f, 0x55, 0x8b, 0x0e, 0x0b, 0x09, 0x83, 0x63, 0x58, 0xa1, 0x5f, 0x01, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xa0, 0x03, 0xca, 0x54, 0x4c, 0x3e, 0x06, 0x04, 0x04, 0x3c, 0x46, 0x4e, 0xb2, 0x54, 0x4c, 0x3e, 0x06, 0x04, 0x04, 0x3c, 0x46, 0x4e, 0xfc, 0x45, 0xb0, 0x01, 0x6f, 0xaa, 0x01, 0x70, 0xb2, 0xfe, 0xee, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0x00, 0x30, 0x05, 0x46, 0x05, 0x28, 0x00, 0x1b, 0x00, 0x22, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x09, 0x02, 0x35, 0x01, 0x15, 0x01, 0x05, 0x46, 0x5e, 0x97, 0x4d, 0x55, 0x8c, 0x0d, 0x0b, 0x09, 0x85, 0x63, 0x56, 0xa2, 0x5e, 0x58, 0x9b, 0x4f, 0x55, 0x8b, 0x0e, 0x0b, 0x09, 0x83, 0x63, 0x58, 0xa1, 0x5f, 0xfb, 0x7d, 0x03, 0x61, 0xfc, 0x9f, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0xca, 0x54, 0x4c, 0x3e, 0x06, 0x04, 0x04, 0x3c, 0x46, 0x4e, 0xb2, 0x54, 0x4c, 0x3e, 0x06, 0x04, 0x04, 0x3c, 0x46, 0x4e, 0xfc, 0x64, 0x01, 0x15, 0x01, 0x12, 0xb2, 0xfe, 0x90, 0xaa, 0xfe, 0x91, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfe, 0x98, 0x05, 0x46, 0x05, 0xd4, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x00, 0x2b, 0x00, 0x00, 0x17, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x13, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x03, 0x15, 0x01, 0x35, 0x01, 0x15, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0x01, 0x5e, 0x97, 0x4d, 0x55, 0x8c, 0x0d, 0x0b, 0x09, 0x85, 0x63, 0x56, 0xa2, 0x5e, 0x58, 0x9b, 0x4f, 0x55, 0x8b, 0x0e, 0x05, 0x06, 0x09, 0x83, 0x63, 0x58, 0xa1, 0x5f, 0x01, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xa0, 0x3e, 0xaa, 0xaa, 0xfe, 0xd6, 0xaa, 0xaa, 0x05, 0xdc, 0x56, 0x4a, 0x3c, 0x06, 0x04, 0x06, 0x3a, 0x44, 0x4e, 0xb4, 0x54, 0x4c, 0x3c, 0x06, 0x02, 0x04, 0x04, 0x3a, 0x44, 0x4e, 0xfc, 0x44, 0xb0, 0x01, 0x6f, 0xaa, 0x01, 0x70, 0xb2, 0xfe, 0xee, 0x00, 0x00, 0x00, 0x04, 0x00, 0xc3, 0xfe, 0x98, 0x05, 0x46, 0x05, 0xd4, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x00, 0x2b, 0x00, 0x00, 0x17, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x13, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x09, 0x02, 0x35, 0x01, 0x15, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0x01, 0x5e, 0x97, 0x4d, 0x55, 0x8c, 0x0d, 0x0b, 0x09, 0x85, 0x63, 0x56, 0xa2, 0x5e, 0x58, 0x9b, 0x4f, 0x55, 0x8b, 0x0e, 0x05, 0x06, 0x09, 0x83, 0x63, 0x58, 0xa1, 0x5f, 0xfb, 0x7d, 0x03, 0x60, 0xfc, 0xa0, 0x04, 0x82, 0xfb, 0x7e, 0x3e, 0xaa, 0xaa, 0xfe, 0xd6, 0xaa, 0xaa, 0x05, 0xdc, 0x56, 0x4a, 0x3c, 0x06, 0x04, 0x06, 0x3a, 0x44, 0x4e, 0xb4, 0x54, 0x4c, 0x3c, 0x06, 0x02, 0x04, 0x04, 0x3a, 0x44, 0x4e, 0xfc, 0x44, 0x01, 0x15, 0x01, 0x12, 0xb2, 0xfe, 0x90, 0xaa, 0xfe, 0x91, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0x00, 0x66, 0x05, 0x46, 0x04, 0xce, 0x00, 0x03, 0x00, 0x20, 0x00, 0x24, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x21, 0x35, 0x33, 0x36, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x33, 0x15, 0x21, 0x26, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x15, 0x21, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0x42, 0x3c, 0x2a, 0x32, 0x1b, 0x18, 0x04, 0xfe, 0x8d, 0xf0, 0x0b, 0x1a, 0x31, 0x4e, 0x51, 0xb9, 0x50, 0x4d, 0x32, 0x19, 0x0d, 0xef, 0xfe, 0x8e, 0x03, 0x19, 0x1b, 0x32, 0x29, 0xfd, 0x82, 0x04, 0x82, 0xfb, 0x7e, 0x02, 0x5a, 0xaa, 0x02, 0x7b, 0x04, 0x1e, 0x2b, 0x44, 0x44, 0x5c, 0xa8, 0x39, 0x33, 0x5b, 0x32, 0x33, 0x33, 0x32, 0x5b, 0x30, 0x3c, 0xa8, 0x5b, 0x45, 0x43, 0x2c, 0x1e, 0xfc, 0xe9, 0xaa, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xff, 0xcf, 0x05, 0x46, 0x05, 0x57, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x37, 0x21, 0x15, 0x21, 0x01, 0x00, 0x05, 0x04, 0x01, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfe, 0xa7, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x59, 0xfe, 0xa7, 0xfc, 0xd7, 0x03, 0x29, 0x01, 0x59, 0x79, 0xaa, 0x04, 0xb1, 0xfe, 0xe5, 0x5d, 0x5d, 0xfe, 0xe5, 0xd7, 0x01, 0x78, 0x84, 0xa6, 0x7c, 0x01, 0x80, 0x00, 0x02, 0x00, 0xc3, 0xff, 0xcf, 0x05, 0x46, 0x05, 0x57, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x25, 0x15, 0x21, 0x35, 0x11, 0x35, 0x00, 0x05, 0x30, 0x15, 0x04, 0x01, 0x35, 0x00, 0x25, 0x24, 0x05, 0x45, 0xfb, 0x7e, 0x01, 0x59, 0x03, 0x29, 0xfc, 0xd7, 0xfe, 0xa7, 0x01, 0x59, 0x01, 0xac, 0xfe, 0x54, 0x79, 0xaa, 0xaa, 0x04, 0x07, 0xd7, 0xfe, 0x80, 0x7c, 0xa6, 0x84, 0xfe, 0x88, 0xd7, 0x01, 0x1b, 0x5d, 0x5d, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0xd7, 0x05, 0x46, 0x05, 0x57, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x00, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x01, 0x00, 0x05, 0x04, 0x01, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x03, 0x4e, 0x87, 0x51, 0x01, 0xc1, 0xfd, 0xed, 0x78, 0x87, 0x51, 0xfe, 0x3f, 0x02, 0x13, 0x02, 0x6f, 0xfe, 0xa7, 0xfe, 0x54, 0x01, 0xac, 0x01, 0x59, 0xfe, 0xa7, 0xfc, 0xd7, 0x03, 0x29, 0x01, 0x59, 0x01, 0x71, 0x50, 0xa8, 0xaa, 0xf8, 0x50, 0xa8, 0xaa, 0x04, 0x07, 0xfe, 0xe5, 0x5d, 0x5d, 0xfe, 0xe5, 0xd7, 0x01, 0x78, 0x84, 0xa6, 0x7c, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0xd7, 0x05, 0x46, 0x05, 0x57, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x00, 0x01, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x37, 0x21, 0x35, 0x21, 0x01, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x00, 0x25, 0x24, 0x03, 0x4e, 0x87, 0x51, 0x01, 0xc1, 0xfd, 0xed, 0x78, 0x87, 0x51, 0xfe, 0x3f, 0x02, 0x13, 0xfd, 0xed, 0x01, 0x59, 0x03, 0x29, 0xfc, 0xd7, 0xfe, 0xa7, 0x01, 0x59, 0x01, 0xac, 0xfe, 0x54, 0x01, 0x71, 0x50, 0xa8, 0xaa, 0xf8, 0x50, 0xa8, 0xaa, 0x04, 0x07, 0xd7, 0xfe, 0x80, 0x7c, 0xa6, 0x84, 0xfe, 0x88, 0xd7, 0x01, 0x1b, 0x5d, 0x5d, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xff, 0x09, 0x05, 0x46, 0x05, 0x4b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x12, 0x00, 0x00, 0x37, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x11, 0x00, 0x05, 0x04, 0x05, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfe, 0xec, 0xfe, 0x0f, 0x01, 0xea, 0x01, 0x1b, 0xfe, 0xc6, 0xfc, 0xb8, 0x03, 0x48, 0x01, 0x3a, 0x33, 0xaa, 0xaa, 0xfe, 0xd6, 0xaa, 0xaa, 0x05, 0x6b, 0xfe, 0xe5, 0x2d, 0x51, 0xf7, 0xd7, 0x01, 0x74, 0x58, 0xa6, 0x56, 0x01, 0x76, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xff, 0x09, 0x05, 0x46, 0x05, 0x4b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x12, 0x00, 0x00, 0x37, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x24, 0x25, 0x24, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x01, 0x3a, 0x03, 0x48, 0xfc, 0xb8, 0xfe, 0xc6, 0x01, 0x1b, 0x01, 0xea, 0xfe, 0x10, 0x33, 0xaa, 0xaa, 0xfe, 0xd6, 0xaa, 0xaa, 0x05, 0x6b, 0xd7, 0xfe, 0x8a, 0x56, 0xa6, 0x58, 0xfe, 0x8c, 0xd7, 0xf7, 0x51, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0x71, 0x05, 0x46, 0x05, 0x4b, 0x00, 0x13, 0x00, 0x1e, 0x00, 0x00, 0x05, 0x21, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x01, 0x00, 0x05, 0x04, 0x05, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x01, 0xef, 0xfe, 0xd4, 0x01, 0xab, 0x56, 0xfd, 0xff, 0x02, 0x81, 0x7b, 0x7d, 0x25, 0x01, 0x2e, 0xfe, 0x52, 0x56, 0x02, 0x04, 0xfd, 0x7d, 0x7c, 0x7c, 0x03, 0x7b, 0xfe, 0xec, 0xfe, 0x0f, 0x01, 0xea, 0x01, 0x1b, 0xfe, 0xc6, 0xfc, 0xb8, 0x03, 0x48, 0x01, 0x3a, 0xea, 0xaa, 0x73, 0xaa, 0xa4, 0x73, 0x31, 0xaa, 0x73, 0xaa, 0xa5, 0x74, 0x05, 0x8f, 0xfe, 0xe5, 0x2d, 0x51, 0xf7, 0xd7, 0x01, 0x74, 0x58, 0xa6, 0x56, 0x01, 0x76, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfe, 0x71, 0x05, 0x46, 0x05, 0x4b, 0x00, 0x13, 0x00, 0x1e, 0x00, 0x00, 0x05, 0x21, 0x35, 0x21, 0x37, 0x21, 0x35, 0x21, 0x37, 0x17, 0x07, 0x21, 0x15, 0x21, 0x07, 0x21, 0x15, 0x21, 0x07, 0x27, 0x01, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x24, 0x25, 0x24, 0x01, 0xef, 0xfe, 0xd4, 0x01, 0xab, 0x56, 0xfd, 0xff, 0x02, 0x81, 0x7b, 0x7d, 0x25, 0x01, 0x2e, 0xfe, 0x52, 0x56, 0x02, 0x04, 0xfd, 0x7d, 0x7c, 0x7c, 0xfe, 0xf9, 0x01, 0x3a, 0x03, 0x48, 0xfc, 0xb8, 0xfe, 0xc6, 0x01, 0x1b, 0x01, 0xea, 0xfe, 0x10, 0xea, 0xaa, 0x73, 0xaa, 0xa4, 0x73, 0x31, 0xaa, 0x73, 0xaa, 0xa5, 0x74, 0x05, 0x8f, 0xd7, 0xfe, 0x8a, 0x56, 0xa6, 0x58, 0xfe, 0x8c, 0xd7, 0xf7, 0x51, 0x2d, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0x79, 0x05, 0x46, 0x05, 0x8b, 0x00, 0x1d, 0x00, 0x3a, 0x00, 0x45, 0x00, 0x00, 0x05, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x37, 0x36, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3e, 0x01, 0x13, 0x00, 0x05, 0x04, 0x05, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa0, 0x58, 0x57, 0x91, 0x09, 0x05, 0x05, 0x0e, 0x8b, 0x55, 0x4d, 0x98, 0x5d, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x08, 0x05, 0x06, 0x0e, 0x99, 0x8e, 0x9e, 0x5d, 0xfe, 0xec, 0xfe, 0x0f, 0x01, 0xea, 0x01, 0x1b, 0xfe, 0xc6, 0xfc, 0xb8, 0x03, 0x48, 0x01, 0x3a, 0x28, 0xb3, 0x4e, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x39, 0x0c, 0x06, 0x41, 0x05, 0x02, 0x02, 0x06, 0x3d, 0x4b, 0x01, 0x9a, 0xb2, 0x4f, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x04, 0x02, 0x03, 0x06, 0x43, 0x0c, 0x45, 0x03, 0xec, 0xfe, 0xe5, 0x2d, 0x51, 0xf7, 0xd7, 0x01, 0x74, 0x58, 0xa6, 0x56, 0x01, 0x76, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0x79, 0x05, 0x46, 0x05, 0x8b, 0x00, 0x1d, 0x00, 0x3a, 0x00, 0x45, 0x00, 0x00, 0x05, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x37, 0x36, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x13, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3e, 0x01, 0x01, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x24, 0x25, 0x24, 0x05, 0x45, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa0, 0x58, 0x57, 0x91, 0x09, 0x05, 0x05, 0x0e, 0x8b, 0x55, 0x4d, 0x98, 0x5d, 0x5e, 0xa1, 0x58, 0x63, 0x83, 0x09, 0x07, 0x05, 0x0d, 0x8c, 0x54, 0x50, 0x9a, 0x59, 0x5f, 0xa1, 0x57, 0x63, 0x85, 0x08, 0x05, 0x06, 0x0e, 0x99, 0x8e, 0x9e, 0xfb, 0xdb, 0x01, 0x3a, 0x03, 0x48, 0xfc, 0xb8, 0xfe, 0xc6, 0x01, 0x1b, 0x01, 0xea, 0xfe, 0x10, 0x28, 0xb3, 0x4e, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x54, 0xb3, 0x4e, 0x39, 0x0c, 0x06, 0x41, 0x05, 0x02, 0x02, 0x06, 0x3d, 0x4b, 0x01, 0x9a, 0xb2, 0x4f, 0x45, 0x3b, 0x04, 0x03, 0x02, 0x06, 0x3d, 0x4c, 0x53, 0xb2, 0x4e, 0x45, 0x3b, 0x04, 0x02, 0x03, 0x06, 0x43, 0x0c, 0x45, 0x03, 0xec, 0xd7, 0xfe, 0x8a, 0x56, 0xa6, 0x58, 0xfe, 0x8c, 0xd7, 0xf7, 0x51, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc3, 0xfd, 0xed, 0x05, 0x46, 0x05, 0x8b, 0x00, 0x36, 0x00, 0x41, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x07, 0x27, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x17, 0x16, 0x1f, 0x01, 0x37, 0x17, 0x07, 0x16, 0x33, 0x32, 0x36, 0x13, 0x00, 0x05, 0x04, 0x05, 0x15, 0x00, 0x25, 0x35, 0x24, 0x01, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x3d, 0x4b, 0x2e, 0x7e, 0x4e, 0x4d, 0x97, 0x5e, 0x5f, 0xa1, 0x58, 0x62, 0x84, 0x07, 0x53, 0x94, 0x50, 0x39, 0x2b, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x3e, 0x4b, 0x2e, 0x7d, 0x4e, 0x4f, 0x9b, 0x58, 0x5e, 0x51, 0x62, 0x45, 0x84, 0x64, 0x07, 0x52, 0x93, 0x50, 0x3a, 0x2c, 0x4d, 0x97, 0x5d, 0xfe, 0xec, 0xfe, 0x0f, 0x01, 0xea, 0x01, 0x1b, 0xfe, 0xc6, 0xfc, 0xb8, 0x03, 0x48, 0x01, 0x3a, 0x01, 0x24, 0xb2, 0x50, 0x44, 0x17, 0x83, 0x34, 0x4b, 0x55, 0xb3, 0x4e, 0x45, 0x3b, 0x03, 0xe9, 0x40, 0xe2, 0x10, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x17, 0x82, 0x34, 0x4c, 0x52, 0xb2, 0x4e, 0x22, 0x2a, 0x08, 0x0e, 0x2c, 0x03, 0xe9, 0x40, 0xe3, 0x0f, 0x4a, 0x03, 0xe6, 0xfe, 0xe5, 0x2d, 0x51, 0xf7, 0xd7, 0x01, 0x74, 0x58, 0xa6, 0x56, 0x01, 0x76, 0x00, 0x02, 0x00, 0xc3, 0xfd, 0xed, 0x05, 0x46, 0x05, 0x8b, 0x00, 0x36, 0x00, 0x41, 0x00, 0x00, 0x01, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x2f, 0x01, 0x07, 0x27, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x37, 0x36, 0x17, 0x16, 0x1f, 0x01, 0x37, 0x17, 0x07, 0x16, 0x33, 0x32, 0x36, 0x01, 0x35, 0x00, 0x05, 0x15, 0x04, 0x01, 0x35, 0x24, 0x25, 0x24, 0x05, 0x46, 0x5f, 0xa1, 0x58, 0x3d, 0x4b, 0x2e, 0x7e, 0x4e, 0x4d, 0x97, 0x5e, 0x5f, 0xa1, 0x58, 0x62, 0x84, 0x07, 0x53, 0x94, 0x50, 0x39, 0x2b, 0x4f, 0x9b, 0x58, 0x5e, 0xa2, 0x56, 0x3e, 0x4b, 0x2e, 0x7d, 0x4e, 0x4f, 0x9b, 0x58, 0x5e, 0x51, 0x62, 0x45, 0x84, 0x64, 0x07, 0x52, 0x93, 0x50, 0x3a, 0x2c, 0x4d, 0x97, 0xfb, 0xdb, 0x01, 0x3a, 0x03, 0x48, 0xfc, 0xb8, 0xfe, 0xc6, 0x01, 0x1b, 0x01, 0xea, 0xfe, 0x10, 0x01, 0x24, 0xb2, 0x50, 0x44, 0x17, 0x83, 0x34, 0x4b, 0x55, 0xb3, 0x4e, 0x45, 0x3b, 0x03, 0xe9, 0x40, 0xe2, 0x10, 0x4c, 0x54, 0xb3, 0x4e, 0x45, 0x17, 0x82, 0x34, 0x4c, 0x52, 0xb2, 0x4e, 0x22, 0x2a, 0x08, 0x0e, 0x2c, 0x03, 0xe9, 0x40, 0xe3, 0x0f, 0x4a, 0x03, 0xe6, 0xd7, 0xfe, 0x8a, 0x56, 0xa6, 0x58, 0xfe, 0x8c, 0xd7, 0xf7, 0x51, 0x2d, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0xa1, 0x05, 0x46, 0x04, 0xae, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x37, 0x01, 0x15, 0x01, 0x11, 0x01, 0x15, 0x09, 0x03, 0x15, 0x01, 0x35, 0x01, 0xc3, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfc, 0xa0, 0x03, 0x60, 0xfb, 0x7e, 0x04, 0x82, 0xc3, 0xfe, 0x90, 0xb2, 0x01, 0x70, 0x01, 0xf4, 0xfe, 0x90, 0xb2, 0x01, 0x70, 0x02, 0xab, 0xfe, 0xeb, 0xfe, 0xee, 0xb2, 0x01, 0x70, 0xaa, 0x01, 0x6f, 0x00, 0x00, 0x03, 0x00, 0xc3, 0xfe, 0xa1, 0x05, 0x46, 0x04, 0xae, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x25, 0x15, 0x01, 0x35, 0x01, 0x15, 0x01, 0x35, 0x11, 0x35, 0x01, 0x15, 0x01, 0x35, 0x01, 0x05, 0x45, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x04, 0x82, 0xfb, 0x7e, 0x03, 0x60, 0xc3, 0xb2, 0xfe, 0x90, 0xb2, 0x02, 0xb2, 0xb2, 0xfe, 0x90, 0xb2, 0x03, 0x69, 0xb0, 0xfe, 0x91, 0xaa, 0xfe, 0x90, 0xb2, 0x01, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa2, 0xff, 0xc9, 0x05, 0x10, 0x04, 0xb3, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x17, 0x01, 0x17, 0x01, 0x17, 0x11, 0x13, 0x27, 0x09, 0x02, 0x27, 0x21, 0x03, 0x62, 0x54, 0xfd, 0x6c, 0xac, 0x02, 0x93, 0x53, 0x5b, 0xae, 0xfd, 0x6d, 0xfe, 0xd5, 0x02, 0x94, 0xaf, 0x02, 0x87, 0x04, 0x4e, 0x5c, 0xfd, 0x23, 0xbf, 0x02, 0xdd, 0x5d, 0x01, 0x78, 0xfd, 0x96, 0xc2, 0xfd, 0x23, 0x01, 0x4c, 0x02, 0xdd, 0xc1, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0xff, 0xc9, 0x05, 0x70, 0x04, 0xb3, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x21, 0x11, 0x37, 0x01, 0x37, 0x09, 0x01, 0x11, 0x21, 0x07, 0x09, 0x02, 0x02, 0xb0, 0xfe, 0xae, 0x53, 0x02, 0x94, 0xab, 0xfd, 0x6d, 0xfe, 0xa6, 0x02, 0x87, 0xae, 0x02, 0x93, 0xfe, 0xd6, 0xfd, 0x6c, 0x04, 0x4e, 0xfe, 0x88, 0x5d, 0xfd, 0x23, 0xbf, 0x02, 0xdd, 0xfd, 0xf2, 0x02, 0xcf, 0xc1, 0xfd, 0x23, 0xfe, 0xb4, 0x02, 0xdd, 0x00, 0x00, 0x02, 0x00, 0xa2, 0x00, 0x34, 0x05, 0x10, 0x05, 0x1e, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x07, 0x01, 0x07, 0x01, 0x07, 0x21, 0x05, 0x37, 0x09, 0x02, 0x37, 0x11, 0x04, 0xb4, 0x53, 0xfd, 0x6d, 0xac, 0x02, 0x94, 0x54, 0x01, 0x52, 0xfd, 0xd4, 0xaf, 0xfd, 0x6c, 0x01, 0x2b, 0x02, 0x93, 0xae, 0x02, 0x11, 0x5d, 0x02, 0xdd, 0xbf, 0xfd, 0x23, 0x5c, 0x65, 0xc1, 0x02, 0xdd, 0x01, 0x4c, 0xfd, 0x23, 0xc2, 0xfd, 0x31, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x34, 0x05, 0x70, 0x05, 0x1e, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x00, 0x25, 0x27, 0x01, 0x27, 0x01, 0x27, 0x11, 0x03, 0x17, 0x09, 0x02, 0x17, 0x21, 0x02, 0xb0, 0x53, 0x02, 0x93, 0xab, 0xfd, 0x6c, 0x53, 0x5b, 0xae, 0x02, 0x94, 0x01, 0x2a, 0xfd, 0x6d, 0xae, 0xfd, 0x79, 0x99, 0x5c, 0x02, 0xdd, 0xbf, 0xfd, 0x23, 0x5d, 0xfe, 0x88, 0x02, 0x6a, 0xc2, 0x02, 0xdd, 0xfe, 0xb4, 0xfd, 0x23, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x31, 0x00, 0x86, 0x05, 0xaf, 0x04, 0x7e, 0x00, 0x09, 0x00, 0x13, 0x00, 0x00, 0x25, 0x09, 0x01, 0x11, 0x21, 0x11, 0x09, 0x01, 0x11, 0x21, 0x01, 0x15, 0x21, 0x35, 0x03, 0x13, 0x35, 0x21, 0x15, 0x13, 0x01, 0xfb, 0xfe, 0x37, 0x01, 0xc9, 0x01, 0xea, 0x01, 0xc9, 0xfe, 0x37, 0xfe, 0x16, 0x02, 0x44, 0xfd, 0x62, 0xf0, 0xf0, 0x02, 0x9e, 0xf0, 0x86, 0x01, 0xfc, 0x01, 0xfc, 0xfe, 0xef, 0x01, 0x11, 0xfe, 0x04, 0xfe, 0x04, 0x01, 0x11, 0x01, 0xf5, 0x83, 0x83, 0xfe, 0xf6, 0xfe, 0xf6, 0x83, 0x83, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0x00, 0x86, 0x05, 0xa0, 0x04, 0x7e, 0x00, 0x06, 0x00, 0x00, 0x25, 0x09, 0x01, 0x11, 0x21, 0x11, 0x21, 0x01, 0xfb, 0xfe, 0x37, 0x01, 0xc9, 0x03, 0xa4, 0xfc, 0x5c, 0x86, 0x01, 0xfc, 0x01, 0xfc, 0xfe, 0xef, 0xfe, 0x2a, 0x00, 0x01, 0x01, 0x3b, 0x00, 0x00, 0x04, 0xce, 0x06, 0x08, 0x00, 0x06, 0x00, 0x00, 0x09, 0x02, 0x23, 0x11, 0x21, 0x11, 0x01, 0x3b, 0x01, 0xc9, 0x01, 0xc9, 0xf5, 0xfe, 0x59, 0x04, 0x0c, 0x01, 0xfc, 0xfe, 0x04, 0xfb, 0xf4, 0x04, 0x0c, 0x00, 0x00, 0x01, 0x01, 0x3b, 0xff, 0xcd, 0x04, 0xce, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x01, 0x33, 0x11, 0x21, 0x11, 0x33, 0x01, 0x01, 0x3b, 0xf6, 0x01, 0xa7, 0xf5, 0xfe, 0x37, 0x01, 0xc9, 0x04, 0x0c, 0xfb, 0xf4, 0xfe, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa2, 0xff, 0xc9, 0x05, 0x10, 0x04, 0xb3, 0x00, 0x06, 0x00, 0x00, 0x01, 0x27, 0x09, 0x02, 0x27, 0x21, 0x05, 0x0f, 0xae, 0xfd, 0x6d, 0xfe, 0xd5, 0x02, 0x94, 0xaf, 0x02, 0x87, 0x01, 0xe4, 0xc2, 0xfd, 0x23, 0x01, 0x4c, 0x02, 0xdd, 0xc1, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0xff, 0xc9, 0x05, 0x70, 0x04, 0xb3, 0x00, 0x06, 0x00, 0x00, 0x01, 0x11, 0x21, 0x07, 0x09, 0x02, 0x01, 0x03, 0x02, 0x87, 0xae, 0x02, 0x93, 0xfe, 0xd6, 0xfd, 0x6c, 0x01, 0xe4, 0x02, 0xcf, 0xc1, 0xfd, 0x23, 0xfe, 0xb4, 0x02, 0xdd, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa2, 0x00, 0x34, 0x05, 0x10, 0x05, 0x1e, 0x00, 0x06, 0x00, 0x00, 0x25, 0x37, 0x09, 0x02, 0x37, 0x11, 0x02, 0x88, 0xaf, 0xfd, 0x6c, 0x01, 0x2b, 0x02, 0x93, 0xae, 0x34, 0xc1, 0x02, 0xdd, 0x01, 0x4c, 0xfd, 0x23, 0xc2, 0xfd, 0x31, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x34, 0x05, 0x70, 0x05, 0x1e, 0x00, 0x06, 0x00, 0x00, 0x01, 0x17, 0x09, 0x02, 0x17, 0x21, 0x01, 0x03, 0xae, 0x02, 0x94, 0x01, 0x2a, 0xfd, 0x6d, 0xae, 0xfd, 0x79, 0x03, 0x03, 0xc2, 0x02, 0xdd, 0xfe, 0xb4, 0xfd, 0x23, 0xc1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x31, 0x00, 0x86, 0x05, 0xaf, 0x04, 0x7e, 0x00, 0x09, 0x00, 0x00, 0x25, 0x09, 0x01, 0x11, 0x21, 0x11, 0x09, 0x01, 0x11, 0x21, 0x01, 0xfb, 0xfe, 0x37, 0x01, 0xc9, 0x01, 0xea, 0x01, 0xc9, 0xfe, 0x37, 0xfe, 0x16, 0x86, 0x01, 0xfc, 0x01, 0xfc, 0xfe, 0xef, 0x01, 0x11, 0xfe, 0x04, 0xfe, 0x04, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x3b, 0xff, 0xcd, 0x04, 0xce, 0x06, 0x08, 0x00, 0x09, 0x00, 0x00, 0x01, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x09, 0x01, 0x23, 0x03, 0xd8, 0xf5, 0xfe, 0x37, 0xfe, 0x37, 0xf6, 0xf6, 0x01, 0xc9, 0x01, 0xc9, 0xf5, 0x01, 0xc9, 0xfe, 0x04, 0x01, 0xfc, 0x02, 0x43, 0x01, 0xfc, 0xfe, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x69, 0xff, 0xf9, 0x05, 0xb1, 0x02, 0xd7, 0x00, 0x0b, 0x00, 0x00, 0x05, 0x23, 0x01, 0x37, 0x17, 0x11, 0x21, 0x35, 0x21, 0x11, 0x37, 0x17, 0x04, 0x4e, 0x51, 0xfe, 0x9f, 0x6c, 0xd1, 0xfc, 0x90, 0x04, 0x09, 0xd2, 0x6c, 0x07, 0x01, 0x8a, 0x78, 0xea, 0x01, 0x1c, 0xaa, 0xfe, 0x3a, 0xea, 0x78, 0x00, 0x00, 0x01, 0x00, 0x69, 0x02, 0x2d, 0x05, 0xb1, 0x05, 0x0b, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x01, 0x07, 0x27, 0x11, 0x21, 0x35, 0x21, 0x11, 0x07, 0x27, 0x01, 0x04, 0x4e, 0x01, 0x62, 0x6c, 0xd2, 0xfb, 0xf7, 0x03, 0x70, 0xd1, 0x6c, 0x01, 0x61, 0x05, 0x0b, 0xfe, 0x76, 0x78, 0xea, 0xfe, 0x3a, 0xaa, 0x01, 0x1c, 0xea, 0x78, 0x01, 0x8a, 0x00, 0x00, 0x01, 0x00, 0x40, 0xff, 0xf9, 0x05, 0x88, 0x02, 0xd7, 0x00, 0x0b, 0x00, 0x00, 0x05, 0x01, 0x37, 0x17, 0x11, 0x21, 0x15, 0x21, 0x11, 0x37, 0x17, 0x01, 0x01, 0xa3, 0xfe, 0x9e, 0x6c, 0xd2, 0x04, 0x09, 0xfc, 0x90, 0xd1, 0x6c, 0xfe, 0x9f, 0x07, 0x01, 0x8a, 0x78, 0xea, 0x01, 0xc6, 0xaa, 0xfe, 0xe4, 0xea, 0x78, 0xfe, 0x76, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x02, 0x2d, 0x05, 0x88, 0x05, 0x0b, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x01, 0x07, 0x27, 0x11, 0x21, 0x15, 0x21, 0x11, 0x07, 0x27, 0x01, 0xa3, 0x51, 0x01, 0x61, 0x6c, 0xd1, 0x03, 0x70, 0xfb, 0xf7, 0xd2, 0x6c, 0x05, 0x0b, 0xfe, 0x76, 0x78, 0xea, 0xfe, 0xe4, 0xaa, 0x01, 0xc6, 0xea, 0x78, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0xa7, 0x05, 0x7f, 0xfa, 0xe8, 0x04, 0xb2, 0xfb, 0x4e, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x72, 0x02, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x17, 0x11, 0x21, 0x11, 0x01, 0x21, 0x11, 0x21, 0xa7, 0x05, 0x7f, 0xfa, 0xe8, 0x04, 0xb2, 0xfb, 0x4e, 0xfc, 0x06, 0x20, 0xf9, 0xe0, 0x03, 0x10, 0x02, 0x9e, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x05, 0x21, 0x01, 0x03, 0x11, 0x21, 0x11, 0x01, 0x0e, 0x04, 0xb2, 0xfb, 0x4e, 0x67, 0x05, 0x7f, 0x8a, 0x05, 0x3c, 0xfa, 0x52, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x05, 0x11, 0x21, 0x03, 0x11, 0x21, 0x11, 0x05, 0xc0, 0xfb, 0x4e, 0x67, 0x05, 0x7f, 0x8a, 0x05, 0x3c, 0xfa, 0x52, 0x06, 0x20, 0xf9, 0xe0, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x05, 0x09, 0x05, 0x02, 0xc4, 0x02, 0x37, 0xfd, 0xc9, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0xfd, 0x40, 0x64, 0x02, 0x78, 0x02, 0x78, 0xfd, 0x88, 0x03, 0x10, 0xfc, 0xf0, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x13, 0x01, 0x11, 0x09, 0x03, 0x8e, 0x02, 0x36, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0xfd, 0x40, 0x02, 0x14, 0xfd, 0x88, 0x04, 0xf0, 0xfd, 0x88, 0x03, 0x10, 0xfc, 0xf0, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x13, 0x09, 0x01, 0x21, 0x09, 0x02, 0x8e, 0x02, 0x36, 0x02, 0x37, 0xfb, 0x0a, 0x02, 0xbf, 0x02, 0xc0, 0xfd, 0x40, 0x02, 0x14, 0xfd, 0x88, 0x02, 0x78, 0x03, 0x10, 0xfc, 0xf0, 0xfc, 0xf0, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0x04, 0x05, 0x85, 0x05, 0x24, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x13, 0x21, 0x09, 0x04, 0x8e, 0x04, 0x6d, 0xfd, 0xc9, 0xfd, 0x41, 0x02, 0xbf, 0x02, 0xc0, 0xfd, 0x40, 0x02, 0x14, 0x02, 0x78, 0xfd, 0x88, 0x03, 0x10, 0xfc, 0xf0, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xa7, 0xff, 0x04, 0x06, 0x27, 0x05, 0x24, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x15, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x37, 0x00, 0x00, 0x05, 0x15, 0x23, 0x35, 0x33, 0x35, 0x13, 0x15, 0x23, 0x35, 0x13, 0x15, 0x23, 0x35, 0x01, 0x15, 0x23, 0x35, 0x23, 0x15, 0x23, 0x35, 0x01, 0x15, 0x23, 0x35, 0x23, 0x35, 0x23, 0x15, 0x23, 0x35, 0x23, 0x15, 0x23, 0x35, 0x01, 0x15, 0x33, 0x15, 0x23, 0x35, 0x13, 0x15, 0x23, 0x35, 0x13, 0x15, 0x23, 0x35, 0x13, 0x15, 0x23, 0x15, 0x23, 0x35, 0x06, 0x26, 0xcc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfe, 0xc7, 0xb7, 0xd3, 0xb6, 0x03, 0xdf, 0x66, 0x66, 0xd3, 0xb7, 0xd3, 0xb6, 0xfe, 0xc7, 0x67, 0xce, 0x67, 0x67, 0x67, 0x67, 0xce, 0x67, 0x67, 0x16, 0xe6, 0x74, 0x72, 0x01, 0xb6, 0xcc, 0xcc, 0x01, 0xb4, 0xca, 0xca, 0xfc, 0x24, 0x74, 0x74, 0x74, 0x74, 0x05, 0xac, 0xe6, 0x72, 0x74, 0x74, 0x74, 0x74, 0x74, 0xfa, 0xc6, 0x72, 0x74, 0xe6, 0x01, 0xb6, 0xcc, 0xcc, 0x01, 0xb4, 0xca, 0xca, 0x01, 0xd0, 0x74, 0x72, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0xff, 0xca, 0x06, 0x22, 0x06, 0x23, 0x00, 0x04, 0x00, 0x00, 0x13, 0x09, 0x02, 0x21, 0x20, 0x03, 0x01, 0x03, 0x01, 0xfe, 0xda, 0xfc, 0x4a, 0x03, 0xb6, 0x02, 0x6d, 0xfd, 0x93, 0xfc, 0x14, 0x00, 0x00, 0x02, 0x00, 0x20, 0xff, 0xca, 0x06, 0x22, 0x06, 0x23, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x1b, 0x01, 0x21, 0x13, 0x09, 0x04, 0x21, 0x99, 0xf7, 0x03, 0x22, 0xf7, 0xfd, 0x78, 0xfc, 0xff, 0x03, 0x01, 0x03, 0x01, 0xfe, 0xda, 0xfc, 0x4a, 0x03, 0x8b, 0xfc, 0xb1, 0x03, 0x4f, 0x02, 0x0c, 0xfe, 0x1f, 0x02, 0x6d, 0xfd, 0x93, 0xfc, 0x14, 0x00, 0x02, 0x00, 0x87, 0xff, 0x46, 0x05, 0xc3, 0x05, 0xfc, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x09, 0x01, 0x11, 0x09, 0x01, 0x03, 0x11, 0x09, 0x01, 0x11, 0x01, 0xee, 0x02, 0x37, 0x02, 0x37, 0xfd, 0xc9, 0xfd, 0xc9, 0x67, 0x02, 0x9e, 0x02, 0x9d, 0xfd, 0x63, 0x01, 0x35, 0xfe, 0x95, 0x01, 0x6b, 0x02, 0xd8, 0x01, 0x6b, 0xfe, 0x95, 0xfc, 0xe6, 0x03, 0x5c, 0x01, 0xad, 0xfe, 0x53, 0xfc, 0xa4, 0xfe, 0x53, 0x00, 0x01, 0x00, 0x87, 0xff, 0x46, 0x05, 0xc3, 0x05, 0xfc, 0x00, 0x05, 0x00, 0x00, 0x37, 0x11, 0x09, 0x01, 0x11, 0x01, 0x87, 0x02, 0x9e, 0x02, 0x9d, 0xfd, 0x63, 0xf3, 0x03, 0x5c, 0x01, 0xad, 0xfe, 0x53, 0xfc, 0xa4, 0xfe, 0x53, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1e, 0xff, 0xb9, 0x06, 0x2a, 0x05, 0x89, 0x00, 0x05, 0x00, 0x00, 0x05, 0x09, 0x01, 0x21, 0x09, 0x01, 0x01, 0xa2, 0xfe, 0x7d, 0x01, 0x83, 0x03, 0x05, 0x01, 0x83, 0xfe, 0x7d, 0x47, 0x02, 0xe8, 0x02, 0xe8, 0xfd, 0x18, 0xfd, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x64, 0xfe, 0x00, 0x07, 0xaa, 0x06, 0x28, 0x00, 0x0b, 0x00, 0x00, 0x16, 0x10, 0x01, 0x36, 0x20, 0x17, 0x00, 0x10, 0x01, 0x06, 0x20, 0x27, 0x65, 0x01, 0xd1, 0xe9, 0x01, 0xd1, 0xe9, 0x01, 0xd1, 0xfe, 0x2f, 0xe9, 0xfe, 0x2f, 0xe9, 0x40, 0x04, 0xa8, 0x01, 0x2a, 0x96, 0x96, 0xfe, 0xd6, 0xfb, 0x58, 0xfe, 0xd6, 0x96, 0x96, 0x00, 0x01, 0x00, 0x45, 0xff, 0xa0, 0x05, 0xfd, 0x06, 0x4d, 0x00, 0x04, 0x00, 0x00, 0x09, 0x03, 0x11, 0x03, 0xcd, 0x02, 0x2f, 0xfd, 0xd1, 0xfc, 0x79, 0x06, 0x4c, 0xfc, 0xaa, 0xfc, 0xaa, 0x01, 0x46, 0x04, 0x20, 0x00, 0x00, 0x02, 0x00, 0x45, 0xff, 0xa0, 0x05, 0xfd, 0x06, 0x4d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x09, 0x01, 0x11, 0x09, 0x05, 0x11, 0x03, 0xa7, 0xfd, 0x05, 0x02, 0xfb, 0x01, 0xd7, 0xfe, 0x4f, 0x02, 0x2f, 0xfd, 0xd1, 0xfc, 0x79, 0x05, 0xc6, 0xfe, 0xee, 0xfc, 0x86, 0xfe, 0xec, 0x02, 0xd0, 0x03, 0x56, 0xfc, 0xaa, 0xfc, 0xaa, 0x01, 0x46, 0x04, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x00, 0x15, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x35, 0x33, 0x35, 0x23, 0x35, 0x33, 0xb5, 0xb6, 0x01, 0x38, 0xfe, 0xc8, 0x01, 0x38, 0xfe, 0xc8, 0x02, 0x8e, 0xfc, 0xbc, 0xac, 0xac, 0xac, 0xac, 0x05, 0xd5, 0xfe, 0x07, 0x90, 0x90, 0x90, 0xfe, 0x7e, 0xaa, 0x02, 0x2c, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0xf3, 0x06, 0x14, 0x00, 0x13, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x01, 0x53, 0xa0, 0xa0, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa0, 0xa0, 0x02, 0xbc, 0x90, 0xfd, 0xd4, 0x02, 0x2c, 0x90, 0x90, 0x90, 0x02, 0x38, 0xfd, 0xc8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xdb, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x00, 0x23, 0x00, 0x00, 0x13, 0x33, 0x11, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x33, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x11, 0x21, 0x15, 0x21, 0x11, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x33, 0x32, 0x17, 0xb5, 0xb6, 0x01, 0x01, 0x10, 0x0b, 0x23, 0x10, 0x10, 0x02, 0x70, 0x01, 0x5c, 0x52, 0x12, 0x11, 0x02, 0x8e, 0xfc, 0xbc, 0x05, 0x05, 0x0f, 0x0c, 0x22, 0x10, 0x11, 0x01, 0x71, 0x02, 0x5c, 0x52, 0x16, 0x14, 0x05, 0xd5, 0xfd, 0x2c, 0x01, 0x01, 0x09, 0x25, 0x24, 0x52, 0x86, 0x94, 0x04, 0xfe, 0x2f, 0xaa, 0x03, 0x02, 0x04, 0x03, 0x09, 0x25, 0x24, 0x52, 0x86, 0x94, 0x06, 0x00, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x00, 0x10, 0x00, 0x1d, 0x00, 0x00, 0x13, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x17, 0x15, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x15, 0x21, 0x15, 0xb5, 0x01, 0x9a, 0xe2, 0x73, 0x74, 0x74, 0x73, 0xe2, 0xe4, 0xb6, 0xac, 0xac, 0xb6, 0xe4, 0x7f, 0x8b, 0x8b, 0x7f, 0xe4, 0x01, 0x38, 0x05, 0xd5, 0x71, 0x72, 0xdb, 0xdd, 0x71, 0x71, 0xfd, 0xa8, 0x03, 0xcf, 0x90, 0x90, 0xd1, 0x92, 0x87, 0x86, 0x92, 0xd0, 0x90, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0xfe, 0x66, 0x04, 0xcc, 0x05, 0xd5, 0x00, 0x1b, 0x00, 0x24, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x17, 0x13, 0x23, 0x03, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x19, 0x01, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x03, 0x32, 0x3b, 0x6e, 0x38, 0xb9, 0xc4, 0xac, 0x42, 0x7d, 0x6c, 0xc6, 0x63, 0x78, 0x39, 0x45, 0xcd, 0xb8, 0x01, 0x9a, 0xe7, 0xe2, 0x75, 0xfd, 0xc8, 0xe4, 0x84, 0x86, 0x86, 0x84, 0x02, 0xbc, 0x16, 0x90, 0x7e, 0xfe, 0x68, 0x01, 0x7f, 0x96, 0x62, 0xfd, 0xf1, 0xc2, 0x96, 0xaa, 0xf4, 0x01, 0x0e, 0x05, 0x6d, 0xd6, 0xd8, 0x8d, 0xba, 0x02, 0x4f, 0xfd, 0xee, 0x87, 0x83, 0x83, 0x85, 0x00, 0x04, 0x00, 0x40, 0xff, 0xa2, 0x04, 0x26, 0x04, 0xbc, 0x00, 0x23, 0x00, 0x28, 0x00, 0x30, 0x00, 0x37, 0x00, 0x00, 0x01, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x07, 0x27, 0x37, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x37, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x37, 0x17, 0x07, 0x16, 0x0f, 0x01, 0x33, 0x35, 0x34, 0x07, 0x01, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x01, 0x13, 0x06, 0x07, 0x06, 0x15, 0x14, 0x03, 0xc2, 0xa6, 0x38, 0xa9, 0x7b, 0x7a, 0x52, 0x5d, 0x56, 0x63, 0x35, 0xe3, 0xe2, 0x26, 0x8d, 0x0a, 0x0c, 0x4b, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0xd1, 0x6b, 0x85, 0x56, 0x97, 0x33, 0xa8, 0x30, 0x32, 0x9d, 0xfe, 0xdd, 0x37, 0x59, 0x8a, 0xa6, 0xfd, 0xff, 0xcd, 0x59, 0x2d, 0x4e, 0x02, 0x7f, 0xfd, 0x81, 0xaa, 0x66, 0x61, 0x3c, 0x7d, 0x4e, 0x85, 0x56, 0x7b, 0xbd, 0xc0, 0xbf, 0x0c, 0x0c, 0x45, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0x72, 0xb3, 0x4f, 0xcb, 0x73, 0x2b, 0x41, 0x12, 0x18, 0xba, 0xfe, 0x78, 0x2e, 0xd9, 0xb4, 0x29, 0xfe, 0xe2, 0x01, 0x15, 0x0c, 0x1e, 0x33, 0x7b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xea, 0xff, 0x42, 0x02, 0xc4, 0x06, 0x93, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x11, 0x33, 0x13, 0x33, 0x03, 0x33, 0x15, 0x23, 0x03, 0x15, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x03, 0x23, 0x13, 0x11, 0x23, 0x35, 0x33, 0x11, 0x01, 0x52, 0x2b, 0xad, 0x99, 0xad, 0x91, 0xbd, 0x98, 0x43, 0x67, 0xab, 0xab, 0xbf, 0x49, 0x0b, 0x0a, 0x5c, 0x99, 0xc1, 0x79, 0x79, 0x05, 0x9e, 0xfe, 0xc2, 0x02, 0x33, 0xfd, 0xcd, 0x8f, 0xfe, 0x0f, 0x6f, 0x89, 0x4e, 0x9a, 0x50, 0x0c, 0x10, 0xfe, 0xd6, 0x02, 0x72, 0x02, 0x1d, 0x8f, 0x01, 0x3e, 0xff, 0xff, 0x00, 0xb4, 0xfe, 0xbf, 0x05, 0x6a, 0x05, 0xd5, 0x10, 0x06, 0x04, 0x36, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x04, 0x9a, 0x06, 0x14, 0x00, 0x19, 0x00, 0x00, 0x21, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x11, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x33, 0x11, 0x23, 0x03, 0xf4, 0xa6, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0x50, 0x51, 0x6a, 0xad, 0x59, 0x5a, 0xa5, 0xa5, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x06, 0x14, 0xfd, 0x9e, 0x65, 0x32, 0x32, 0x77, 0x78, 0xe8, 0xfd, 0xf5, 0xfe, 0x4c, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x04, 0xe0, 0x05, 0xd5, 0x00, 0x0e, 0x00, 0x00, 0x25, 0x33, 0x11, 0x23, 0x11, 0x23, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x01, 0x33, 0x01, 0x04, 0x47, 0x98, 0xb1, 0x3e, 0xfd, 0x7b, 0xb6, 0xb6, 0x02, 0x5b, 0xea, 0xfd, 0x65, 0xaa, 0xfe, 0x15, 0x01, 0x41, 0x02, 0xcf, 0xfd, 0x31, 0x05, 0xd5, 0xfd, 0x89, 0x02, 0x77, 0xfd, 0x48, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x04, 0x26, 0x06, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x11, 0x23, 0x01, 0x11, 0x23, 0xa7, 0xa7, 0x01, 0xee, 0xd4, 0xfd, 0xe9, 0x01, 0x9e, 0x8f, 0xa6, 0x32, 0xfe, 0x00, 0xa7, 0x06, 0x14, 0xfc, 0x69, 0x01, 0xe3, 0xfd, 0xf4, 0xfe, 0x45, 0xfe, 0x4c, 0x01, 0x1b, 0x02, 0x23, 0xfd, 0xdd, 0x00, 0x00, 0x00, 0x01, 0x00, 0x52, 0xfe, 0xbf, 0x05, 0x51, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x01, 0x21, 0x68, 0x04, 0x1f, 0xfc, 0xaf, 0x04, 0x1b, 0xb5, 0xfb, 0xb7, 0x03, 0x51, 0xfc, 0xc4, 0x05, 0xd5, 0x9a, 0xfb, 0x6f, 0xfe, 0x15, 0x01, 0x41, 0x9a, 0x04, 0x91, 0x00, 0x01, 0x00, 0x4f, 0xfe, 0xe5, 0x04, 0x1e, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x01, 0x21, 0x11, 0x23, 0x11, 0x21, 0x35, 0x01, 0x21, 0x66, 0x03, 0x12, 0xfd, 0x92, 0x03, 0x14, 0xa6, 0xfc, 0xd7, 0x02, 0x6f, 0xfd, 0xa8, 0x04, 0x60, 0xa8, 0xfc, 0xdb, 0xfe, 0x52, 0x01, 0x1b, 0xa8, 0x03, 0x25, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xec, 0x05, 0xf1, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x35, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x16, 0x01, 0x10, 0x12, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x04, 0x3b, 0xb0, 0xb0, 0x46, 0xd4, 0x95, 0xf3, 0xfe, 0xcf, 0x01, 0x31, 0xf3, 0x95, 0xd4, 0xfd, 0x2f, 0xd3, 0xb8, 0xb8, 0xd4, 0xd4, 0xb8, 0xb8, 0xd3, 0x04, 0xed, 0xe8, 0xfa, 0x2b, 0xe7, 0x84, 0x80, 0x01, 0xab, 0x01, 0x5c, 0x01, 0x5c, 0x01, 0xab, 0x80, 0xfd, 0x78, 0xfe, 0xe3, 0xfe, 0xbb, 0x01, 0x45, 0x01, 0x1d, 0x01, 0x1d, 0x01, 0x45, 0xfe, 0xbb, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x66, 0x05, 0x83, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x00, 0x13, 0x21, 0x09, 0x01, 0x21, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x01, 0x23, 0x01, 0x11, 0x23, 0xb5, 0x01, 0x0f, 0x01, 0x57, 0x01, 0x58, 0x01, 0x0f, 0xb8, 0xcc, 0x46, 0x3d, 0x79, 0x63, 0xfe, 0xa5, 0xb6, 0xfe, 0xa5, 0xb0, 0x05, 0xd5, 0xfc, 0x08, 0x03, 0xf8, 0xfa, 0x93, 0xfe, 0xf2, 0xf4, 0xaa, 0x96, 0xc2, 0x04, 0xb7, 0xfc, 0x00, 0x04, 0x00, 0xfa, 0xe1, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x25, 0x13, 0x21, 0x01, 0x23, 0x01, 0x33, 0x13, 0x21, 0x13, 0x33, 0x02, 0x76, 0xf7, 0xfe, 0x11, 0x01, 0x5f, 0xcf, 0xfe, 0x00, 0xbd, 0x7b, 0x02, 0x5e, 0x7a, 0xc0, 0xc7, 0x02, 0xe7, 0xfc, 0x52, 0x05, 0xd5, 0xfe, 0x81, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xec, 0x05, 0xf1, 0x00, 0x0f, 0x00, 0x18, 0x00, 0x00, 0x25, 0x15, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x00, 0x10, 0x00, 0x23, 0x22, 0x26, 0x00, 0x10, 0x02, 0x23, 0x22, 0x02, 0x10, 0x12, 0x20, 0x01, 0x18, 0xb0, 0xb0, 0x45, 0xd5, 0x94, 0xf3, 0x01, 0x32, 0xfe, 0xce, 0xf3, 0x94, 0xd5, 0x02, 0xd1, 0xd2, 0xb8, 0xb9, 0xd3, 0xd3, 0x01, 0x71, 0xe7, 0xe8, 0x05, 0xd5, 0xe7, 0x84, 0x80, 0xfe, 0x55, 0xfd, 0x48, 0xfe, 0x55, 0x80, 0x01, 0x6b, 0x02, 0x3a, 0x01, 0x45, 0xfe, 0xbb, 0xfd, 0xc6, 0xfe, 0xbb, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x05, 0x4a, 0x04, 0x7b, 0x00, 0x14, 0x00, 0x00, 0x01, 0x30, 0x01, 0x23, 0x01, 0x33, 0x01, 0x13, 0x36, 0x33, 0x32, 0x16, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x26, 0x22, 0x07, 0x06, 0x03, 0xba, 0xfe, 0xd8, 0xe1, 0xfe, 0x86, 0xaf, 0x01, 0x3b, 0xf9, 0x4b, 0xc8, 0x76, 0xa7, 0xa1, 0x49, 0x66, 0x25, 0x13, 0x03, 0x6d, 0xfc, 0x93, 0x04, 0x60, 0xfc, 0x54, 0x02, 0xe6, 0xe1, 0xbf, 0x86, 0x72, 0x72, 0x3a, 0x54, 0x2a, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x08, 0x1f, 0x05, 0xf0, 0x00, 0x1d, 0x00, 0x00, 0x09, 0x01, 0x23, 0x09, 0x01, 0x23, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x13, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x06, 0xa9, 0xfe, 0xe8, 0xe5, 0xfe, 0xe5, 0xfe, 0xe1, 0xe4, 0xfe, 0xaf, 0xb8, 0x01, 0x1a, 0x01, 0x1a, 0xcc, 0x01, 0x1b, 0xed, 0x10, 0x36, 0x4d, 0x7c, 0x7a, 0x4c, 0x4d, 0x99, 0x49, 0x29, 0x26, 0x24, 0x1a, 0x04, 0xe1, 0xfb, 0x1f, 0x05, 0x10, 0xfa, 0xf0, 0x05, 0xd5, 0xfb, 0x12, 0x04, 0xee, 0xfb, 0x12, 0x04, 0x26, 0x47, 0x40, 0x5c, 0x5c, 0x5b, 0x6e, 0x83, 0x79, 0x36, 0x50, 0x28, 0x1c, 0x00, 0x01, 0x00, 0x4d, 0x00, 0x00, 0x06, 0xed, 0x04, 0x7b, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x26, 0x22, 0x07, 0x06, 0x07, 0x03, 0x23, 0x0b, 0x01, 0x23, 0x01, 0x33, 0x1b, 0x01, 0x33, 0x13, 0x04, 0xbf, 0x15, 0x33, 0x52, 0x77, 0x76, 0xa6, 0xa0, 0x49, 0x67, 0x24, 0x16, 0x06, 0xce, 0xc3, 0xd9, 0xda, 0xc3, 0xfe, 0xf8, 0xa6, 0xcf, 0xce, 0xc3, 0xcf, 0x03, 0x88, 0x56, 0x3d, 0x60, 0xbf, 0x86, 0x72, 0x72, 0x3a, 0x54, 0x2a, 0x19, 0x14, 0xfc, 0x93, 0x03, 0x96, 0xfc, 0x6a, 0x04, 0x60, 0xfc, 0x96, 0x03, 0x6a, 0xfc, 0x96, 0x00, 0x02, 0x00, 0x5d, 0x00, 0x00, 0x04, 0x0c, 0x04, 0xb3, 0x00, 0x13, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x10, 0x25, 0x36, 0x33, 0x32, 0x15, 0x14, 0x0f, 0x01, 0x13, 0x01, 0x33, 0x01, 0x23, 0x03, 0x07, 0x35, 0x36, 0x3f, 0x01, 0x36, 0x35, 0x26, 0x23, 0x22, 0x15, 0x14, 0xb4, 0x01, 0x32, 0x12, 0x10, 0x97, 0xa5, 0x72, 0x99, 0x01, 0x3b, 0xb0, 0xfe, 0x86, 0xe1, 0xbc, 0x97, 0x2c, 0x36, 0x94, 0xc3, 0x01, 0x29, 0x9d, 0x03, 0x4d, 0x01, 0x32, 0x31, 0x03, 0xf8, 0x99, 0x5d, 0x40, 0xfe, 0x2f, 0x03, 0xac, 0xfb, 0xa0, 0x02, 0x32, 0x55, 0xc4, 0x14, 0x1c, 0x50, 0x6e, 0x34, 0x34, 0xa0, 0x25, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x00, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x00, 0x01, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x03, 0xff, 0xfd, 0x6c, 0xb6, 0xb6, 0x02, 0x94, 0x02, 0xc7, 0xfd, 0x39, 0x05, 0xd5, 0xfd, 0x9c, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x03, 0x6f, 0x04, 0x60, 0x00, 0x07, 0x00, 0x00, 0x01, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x03, 0x6e, 0xfd, 0xe5, 0xa5, 0xa5, 0x02, 0x1b, 0x02, 0x04, 0xfd, 0xfc, 0x04, 0x60, 0xfe, 0x33, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0xff, 0xe7, 0x04, 0x56, 0x04, 0x68, 0x00, 0x0a, 0x00, 0x27, 0x00, 0x00, 0x01, 0x22, 0x15, 0x11, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x32, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x23, 0x07, 0x22, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x11, 0x10, 0x02, 0xea, 0x3a, 0x55, 0x56, 0x4c, 0x4d, 0x3f, 0x31, 0x7d, 0x73, 0x7c, 0x7c, 0x74, 0xb6, 0xa5, 0xb4, 0x78, 0x7a, 0x7a, 0x5b, 0x96, 0x3b, 0x34, 0x4e, 0x4e, 0x45, 0x65, 0x03, 0xcb, 0x91, 0xfd, 0x52, 0x68, 0x5d, 0xdf, 0xd0, 0x70, 0x5b, 0x9d, 0x84, 0x8d, 0xfe, 0xd9, 0xfe, 0xf1, 0xa1, 0x98, 0x01, 0x99, 0x9c, 0x01, 0x13, 0x01, 0x1e, 0x92, 0x6d, 0x1c, 0xa3, 0x17, 0x4e, 0x73, 0xbe, 0xca, 0x73, 0x67, 0x02, 0xaf, 0x01, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0xe5, 0x02, 0x4f, 0x06, 0x14, 0x00, 0x17, 0x00, 0x00, 0x21, 0x35, 0x06, 0x23, 0x22, 0x2f, 0x01, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x01, 0xa8, 0x67, 0xec, 0x22, 0x32, 0x01, 0x36, 0x4f, 0x8d, 0x96, 0x45, 0x5f, 0xd0, 0xe5, 0xa4, 0x48, 0x49, 0xae, 0xc9, 0x0a, 0xbd, 0x23, 0xcb, 0xbe, 0x02, 0x6c, 0x99, 0x61, 0x9c, 0x60, 0x62, 0xd4, 0xfb, 0x82, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x20, 0x00, 0x00, 0x00, 0x26, 0x22, 0x06, 0x14, 0x16, 0x32, 0x36, 0x00, 0x12, 0x20, 0x12, 0x10, 0x02, 0x20, 0x02, 0x00, 0x26, 0x20, 0x06, 0x15, 0x14, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x36, 0x35, 0x02, 0xc7, 0x55, 0x79, 0x54, 0x54, 0x7a, 0x54, 0xfd, 0x9f, 0xf5, 0x01, 0xb1, 0xf7, 0xf7, 0xfe, 0x4f, 0xf5, 0x02, 0xed, 0x9a, 0xfe, 0xf6, 0x9b, 0x12, 0x14, 0x32, 0x52, 0x78, 0x7a, 0x51, 0x2d, 0x15, 0x10, 0x01, 0x61, 0x5f, 0x5e, 0x87, 0x5c, 0x5c, 0x02, 0x68, 0x01, 0x38, 0xfe, 0xc8, 0xfd, 0xd9, 0xfe, 0xc7, 0x01, 0x39, 0x01, 0xda, 0xe9, 0xe7, 0xc9, 0x60, 0x4d, 0x47, 0x38, 0x5d, 0x5f, 0x32, 0x42, 0x49, 0x5b, 0x00, 0x00, 0x01, 0x00, 0x58, 0x00, 0x00, 0x02, 0xe2, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x02, 0xe1, 0xfd, 0x77, 0x01, 0xe2, 0xfe, 0x3f, 0x01, 0xc1, 0xfe, 0x2a, 0x04, 0x60, 0xfb, 0xa0, 0x93, 0x01, 0x78, 0x94, 0x01, 0x2d, 0x94, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xeb, 0xff, 0x11, 0x00, 0xd7, 0x03, 0x67, 0x12, 0x07, 0x02, 0x74, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x02, 0x9c, 0x03, 0x11, 0x05, 0xe0, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x01, 0x4c, 0xfe, 0xbd, 0x78, 0x01, 0x0c, 0x01, 0x0d, 0x77, 0xfe, 0xbd, 0x02, 0x9c, 0x03, 0x44, 0xfd, 0x40, 0x02, 0xc0, 0xfc, 0xbc, 0x00, 0x00, 0x01, 0x00, 0x79, 0xfe, 0x10, 0x04, 0x4e, 0x05, 0xf0, 0x00, 0x3a, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x17, 0x1e, 0x01, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x2e, 0x02, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x03, 0xda, 0x67, 0xb8, 0x55, 0x95, 0xa1, 0x36, 0x31, 0x9a, 0x6d, 0xd0, 0x5d, 0x60, 0x83, 0x67, 0xb5, 0x79, 0x70, 0x84, 0x3f, 0x16, 0x39, 0x1e, 0x47, 0x5d, 0x6e, 0x36, 0xc9, 0x2c, 0x0d, 0x2d, 0x22, 0x6c, 0x73, 0x6f, 0xd4, 0x67, 0x9b, 0xaa, 0x7a, 0x8b, 0x6e, 0xcc, 0xb5, 0xfb, 0xdc, 0x5f, 0xc4, 0x05, 0xa4, 0xc5, 0x37, 0x36, 0x80, 0x76, 0x63, 0x33, 0x2e, 0x23, 0x19, 0x2f, 0x69, 0x6c, 0xb6, 0xd9, 0x70, 0x59, 0x12, 0x77, 0x6e, 0x49, 0xaa, 0x10, 0x27, 0x4f, 0x38, 0xce, 0x2d, 0x0a, 0x21, 0x07, 0x18, 0x2f, 0xd0, 0x45, 0x46, 0x88, 0x7e, 0x6e, 0x7c, 0x1f, 0x18, 0x2d, 0xc0, 0xab, 0xc6, 0xe4, 0x26, 0x00, 0x00, 0x01, 0x00, 0x52, 0xfe, 0x10, 0x04, 0x9c, 0x05, 0xd5, 0x00, 0x18, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x22, 0x2e, 0x02, 0x27, 0x25, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x04, 0x3b, 0x61, 0x84, 0x23, 0x51, 0x6a, 0x7e, 0x3e, 0xfe, 0xf2, 0x47, 0x66, 0x70, 0x03, 0x51, 0xfc, 0xc4, 0x04, 0x1f, 0xfc, 0xb3, 0x67, 0x69, 0xe3, 0x7a, 0x90, 0xfe, 0xba, 0xaa, 0x10, 0x27, 0x4f, 0x38, 0xf3, 0x3f, 0x9a, 0x04, 0x91, 0xaa, 0x9a, 0xfb, 0x6f, 0x0d, 0x5f, 0xcd, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x01, 0x11, 0x33, 0x11, 0xc1, 0x99, 0x99, 0x01, 0x92, 0x7a, 0x05, 0x58, 0x88, 0xfb, 0x30, 0x05, 0x58, 0xfa, 0xa8, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x01, 0x11, 0x33, 0x11, 0xc1, 0x99, 0x99, 0x01, 0x92, 0x7a, 0x04, 0x24, 0x88, 0xfc, 0x64, 0x05, 0x58, 0xfa, 0xa8, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x01, 0x11, 0x33, 0x11, 0xc1, 0x99, 0x99, 0x01, 0x92, 0x7a, 0x02, 0xf0, 0x88, 0xfd, 0x98, 0x05, 0x58, 0xfa, 0xa8, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x01, 0x11, 0x33, 0x11, 0xc1, 0x99, 0x99, 0x01, 0x92, 0x7a, 0x01, 0xbc, 0x88, 0xfe, 0xcc, 0x05, 0x58, 0xfa, 0xa8, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x37, 0x33, 0x15, 0x23, 0x01, 0x33, 0x11, 0x23, 0xc1, 0x99, 0x99, 0x01, 0x92, 0x7a, 0x7a, 0x88, 0x88, 0x05, 0x58, 0xfa, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x03, 0x23, 0x11, 0x33, 0x02, 0x34, 0x99, 0x99, 0xf9, 0x7a, 0x7a, 0x05, 0x58, 0x88, 0xfb, 0x30, 0x05, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x03, 0x23, 0x11, 0x33, 0x02, 0x34, 0x99, 0x99, 0xf9, 0x7a, 0x7a, 0x04, 0x24, 0x88, 0xfc, 0x64, 0x05, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x03, 0x23, 0x11, 0x33, 0x02, 0x34, 0x99, 0x99, 0xf9, 0x7a, 0x7a, 0x02, 0xf0, 0x88, 0xfd, 0x98, 0x05, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x03, 0x23, 0x11, 0x33, 0x02, 0x34, 0x99, 0x99, 0xf9, 0x7a, 0x7a, 0x01, 0xbc, 0x88, 0xfe, 0xcc, 0x05, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x25, 0x33, 0x15, 0x2b, 0x02, 0x11, 0x33, 0x02, 0x34, 0x99, 0x99, 0xf9, 0x7a, 0x7a, 0x88, 0x88, 0x05, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x21, 0x23, 0x11, 0x21, 0x15, 0x21, 0x01, 0x3b, 0x7a, 0x02, 0x0c, 0xfe, 0x6e, 0x05, 0x58, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x07, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x01, 0x3b, 0x7a, 0x7a, 0x01, 0x92, 0xfe, 0x6e, 0x05, 0x58, 0xfe, 0xcc, 0x88, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x07, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x01, 0x3b, 0x7a, 0x7a, 0x01, 0x92, 0xfe, 0x6e, 0x05, 0x58, 0xfd, 0x98, 0x88, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x07, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x01, 0x3b, 0x7a, 0x7a, 0x01, 0x92, 0xfe, 0x6e, 0x05, 0x58, 0xfc, 0x64, 0x88, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x02, 0xce, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x25, 0x21, 0x15, 0x21, 0x11, 0x33, 0x01, 0x3b, 0x01, 0x92, 0xfd, 0xf4, 0x7a, 0x88, 0x88, 0x05, 0x58, 0x00, 0x00, 0x01, 0x00, 0x5b, 0x02, 0x9c, 0x02, 0x4d, 0x05, 0xe4, 0x00, 0x09, 0x00, 0x00, 0x01, 0x33, 0x17, 0x07, 0x27, 0x11, 0x23, 0x11, 0x07, 0x27, 0x01, 0x3b, 0x33, 0xdf, 0x45, 0x83, 0x61, 0x84, 0x44, 0x05, 0xe4, 0xdd, 0x43, 0x83, 0xfd, 0x55, 0x02, 0xab, 0x83, 0x43, 0x00, 0x01, 0x00, 0x5b, 0x02, 0x98, 0x02, 0x4d, 0x05, 0xe0, 0x00, 0x09, 0x00, 0x00, 0x01, 0x23, 0x27, 0x37, 0x17, 0x11, 0x33, 0x11, 0x37, 0x17, 0x01, 0x6e, 0x33, 0xdf, 0x44, 0x84, 0x61, 0x83, 0x45, 0x02, 0x98, 0xdd, 0x43, 0x83, 0x02, 0xab, 0xfd, 0x55, 0x83, 0x43, 0x00, 0x02, 0x00, 0xaf, 0x02, 0x9c, 0x01, 0x23, 0x05, 0xe0, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x11, 0x33, 0x11, 0x07, 0x23, 0x27, 0xb0, 0x73, 0x73, 0x73, 0x0c, 0x5c, 0x0b, 0x03, 0x2a, 0x8e, 0x03, 0x44, 0xfe, 0x91, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x02, 0x00, 0xaf, 0x02, 0x9c, 0x01, 0x23, 0x05, 0xe0, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x01, 0x23, 0x35, 0x33, 0x11, 0x23, 0x11, 0x37, 0x33, 0x17, 0x01, 0x23, 0x73, 0x73, 0x73, 0x0a, 0x5c, 0x0d, 0x05, 0x52, 0x8e, 0xfc, 0xbc, 0x01, 0x6f, 0xc8, 0xc8, 0x00, 0xff, 0xff, 0x00, 0xaf, 0x00, 0x00, 0x01, 0x23, 0x03, 0x44, 0x10, 0x07, 0x0e, 0x5c, 0x00, 0x00, 0xfd, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7b, 0x00, 0x00, 0x02, 0x86, 0x05, 0xd4, 0x00, 0x10, 0x00, 0x00, 0x33, 0x35, 0x20, 0x02, 0x21, 0x35, 0x20, 0x02, 0x21, 0x35, 0x20, 0x13, 0x16, 0x07, 0x16, 0x13, 0x12, 0xba, 0x01, 0x29, 0x12, 0xfe, 0xd7, 0x01, 0x29, 0x1b, 0xfe, 0xc5, 0x01, 0xe7, 0x0d, 0x08, 0x9d, 0xa6, 0x05, 0x09, 0xa3, 0x02, 0x27, 0xa3, 0x01, 0xc5, 0xa2, 0xfe, 0x8c, 0xe5, 0x63, 0x6d, 0xfe, 0xfb, 0xfe, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7b, 0x00, 0x00, 0x02, 0x50, 0x04, 0x60, 0x00, 0x10, 0x00, 0x00, 0x33, 0x35, 0x20, 0x02, 0x21, 0x35, 0x20, 0x02, 0x21, 0x35, 0x20, 0x13, 0x16, 0x07, 0x16, 0x17, 0x12, 0xa8, 0x01, 0x0e, 0x12, 0xfe, 0xf2, 0x01, 0x0e, 0x1b, 0xfe, 0xf2, 0x01, 0xb1, 0x0d, 0x07, 0x77, 0x81, 0x05, 0x09, 0x99, 0x01, 0x7c, 0x99, 0x01, 0x1a, 0x98, 0xfe, 0xe8, 0x9e, 0x4d, 0x59, 0xbc, 0xfe, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0x01, 0xcb, 0x02, 0xf6, 0x05, 0xf0, 0x00, 0x09, 0x00, 0x00, 0x01, 0x10, 0x17, 0x07, 0x02, 0x35, 0x10, 0x21, 0x15, 0x20, 0x01, 0x0f, 0x69, 0x93, 0x7d, 0x02, 0x8e, 0xfe, 0x19, 0x03, 0xcd, 0xfe, 0xfe, 0xd2, 0x2e, 0x01, 0x31, 0xd4, 0x02, 0x20, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x67, 0x00, 0x56, 0x02, 0xf6, 0x04, 0x7b, 0x00, 0x09, 0x00, 0x00, 0x01, 0x10, 0x17, 0x07, 0x02, 0x35, 0x10, 0x21, 0x15, 0x20, 0x01, 0x0f, 0x69, 0x93, 0x7d, 0x02, 0x8e, 0xfe, 0x19, 0x02, 0x58, 0xfe, 0xfe, 0xd2, 0x2e, 0x01, 0x31, 0xd4, 0x02, 0x20, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x66, 0x04, 0xb6, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x13, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x11, 0x21, 0x11, 0x23, 0xb5, 0xb6, 0x02, 0x94, 0xb6, 0xb8, 0xcd, 0x45, 0x39, 0x78, 0x63, 0xfd, 0x6c, 0xb6, 0x05, 0xd5, 0xfd, 0x9c, 0x02, 0x64, 0xfa, 0x93, 0xfe, 0xf2, 0xf4, 0xaa, 0x96, 0xc2, 0x02, 0x5f, 0xfd, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x06, 0x14, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x14, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x03, 0x4e, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0xa1, 0x6a, 0xad, 0xb3, 0x93, 0xa3, 0x3f, 0x2c, 0x63, 0x1e, 0x22, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x06, 0x14, 0xfd, 0x9e, 0x65, 0x64, 0xef, 0xe8, 0xfd, 0x48, 0xd6, 0xc0, 0x9c, 0x30, 0x38, 0x92, 0x00, 0x00, 0x01, 0xff, 0xfa, 0xfe, 0x4c, 0x05, 0xe6, 0x05, 0xd5, 0x00, 0x2a, 0x00, 0x00, 0x03, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x21, 0x11, 0x23, 0x11, 0x21, 0x05, 0x04, 0x70, 0xfe, 0x23, 0x03, 0x08, 0xfe, 0x8e, 0x5f, 0x74, 0x59, 0x4c, 0x49, 0x89, 0x88, 0xfc, 0x68, 0x74, 0x75, 0x75, 0x60, 0x72, 0x71, 0x7b, 0xad, 0x59, 0x5a, 0x52, 0x54, 0x95, 0x9c, 0x01, 0x5a, 0xfd, 0xdb, 0xb6, 0xfe, 0x23, 0x05, 0xd5, 0xaa, 0xcb, 0x9a, 0xfe, 0x16, 0x38, 0x2b, 0x6c, 0x68, 0x8a, 0xdc, 0x7a, 0x79, 0x13, 0x13, 0x24, 0xc3, 0x31, 0x19, 0x19, 0x4b, 0x4b, 0x8f, 0x86, 0x49, 0x4a, 0x98, 0x01, 0xea, 0xfc, 0x4a, 0x05, 0x2b, 0x00, 0x00, 0x01, 0x00, 0x31, 0xfe, 0x4c, 0x04, 0xaf, 0x05, 0x9e, 0x00, 0x30, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x04, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x35, 0x01, 0x21, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x02, 0xee, 0x5e, 0x74, 0x59, 0x4d, 0x49, 0xfe, 0xee, 0xfc, 0x54, 0x59, 0x5a, 0x60, 0x4c, 0xb4, 0x62, 0xab, 0x59, 0x5a, 0x53, 0x52, 0x96, 0x9d, 0x01, 0x83, 0xfd, 0xad, 0x43, 0x67, 0xab, 0xab, 0xbf, 0x92, 0x79, 0x79, 0xa7, 0x03, 0x0e, 0x01, 0xdc, 0x38, 0x2b, 0x6c, 0x68, 0x8a, 0xdd, 0xf2, 0x12, 0x13, 0x25, 0xc3, 0x31, 0x32, 0x4b, 0x4b, 0x8f, 0x84, 0x4b, 0x4a, 0xa6, 0x01, 0xf3, 0xfd, 0xa4, 0x89, 0x4e, 0x9a, 0x9f, 0xd2, 0x02, 0x60, 0x8f, 0x01, 0x3e, 0xfe, 0xc2, 0xa8, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x93, 0xff, 0xe3, 0x04, 0x09, 0x05, 0xf0, 0x10, 0x06, 0x01, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x77, 0xfe, 0x67, 0x03, 0x68, 0x04, 0x7c, 0x00, 0x31, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x15, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x64, 0x65, 0x36, 0x36, 0x66, 0x66, 0xb0, 0x45, 0x99, 0x58, 0x57, 0x48, 0x49, 0x40, 0x74, 0x35, 0x3f, 0x3d, 0x3c, 0x69, 0x8b, 0x85, 0x7b, 0x41, 0x46, 0x4b, 0x4d, 0x88, 0x57, 0x49, 0x4c, 0x40, 0x51, 0x4b, 0x4d, 0x48, 0xd6, 0xe8, 0x7c, 0x01, 0xac, 0x20, 0x56, 0x55, 0x7b, 0xba, 0x68, 0x68, 0x1a, 0x26, 0xb6, 0x2d, 0x14, 0x15, 0x3e, 0x48, 0x6d, 0x6d, 0x46, 0x45, 0x98, 0x4d, 0x55, 0x85, 0x88, 0x55, 0x55, 0x1c, 0x1c, 0x38, 0xbe, 0x25, 0x13, 0x12, 0xf0, 0xe5, 0x8f, 0xc1, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x25, 0x04, 0x60, 0x00, 0x09, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0xa7, 0x02, 0x7e, 0xfe, 0x2a, 0x01, 0xa6, 0xfe, 0x5a, 0xa8, 0x04, 0x60, 0x94, 0xfe, 0xd3, 0x94, 0xfd, 0xf5, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x56, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x08, 0xf0, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x12, 0x00, 0x15, 0x00, 0x00, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x23, 0x03, 0x21, 0x03, 0x2b, 0x01, 0x03, 0x21, 0x03, 0x23, 0x01, 0x03, 0x21, 0x01, 0x03, 0x21, 0x02, 0x0f, 0xcf, 0x01, 0xa1, 0x01, 0xa3, 0xce, 0x02, 0x00, 0xbd, 0x7b, 0xfd, 0xa3, 0x7b, 0x02, 0xbd, 0x7b, 0xfd, 0xa2, 0x7a, 0xc0, 0x02, 0x68, 0xf7, 0x01, 0xef, 0x03, 0x1a, 0xf6, 0x01, 0xee, 0x05, 0xd5, 0xfb, 0x3e, 0x04, 0xc2, 0xfa, 0x2b, 0x01, 0x7f, 0xfe, 0x81, 0x01, 0x7f, 0xfe, 0x81, 0x05, 0x0e, 0xfd, 0x19, 0x02, 0xe7, 0xfd, 0x19, 0x00, 0x04, 0x00, 0x6e, 0xff, 0xe3, 0x06, 0x70, 0x04, 0x7b, 0x00, 0x0a, 0x00, 0x35, 0x00, 0x40, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x25, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x15, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x30, 0x17, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x01, 0x16, 0x17, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x02, 0x78, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0x03, 0x54, 0xa6, 0x38, 0xaa, 0x7a, 0x63, 0x49, 0xa6, 0x38, 0xa9, 0x7b, 0x9b, 0xb6, 0xe3, 0xe2, 0xe8, 0x96, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0xdb, 0x6c, 0x10, 0x5b, 0xab, 0x51, 0xdb, 0xd8, 0xfe, 0xb6, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0xfd, 0xc8, 0x2f, 0x01, 0x6d, 0xb3, 0xe8, 0x96, 0x88, 0x56, 0x52, 0x3b, 0x02, 0x33, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0x4c, 0xfd, 0x81, 0xaa, 0x66, 0x61, 0x27, 0x0a, 0xaa, 0x66, 0x61, 0xc1, 0xa2, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0x7e, 0x14, 0x44, 0x27, 0x27, 0xfc, 0xfe, 0xb4, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0x01, 0x68, 0x6e, 0xa6, 0x3c, 0x12, 0x7f, 0x8b, 0x17, 0x10, 0x00, 0x03, 0x00, 0x0e, 0xff, 0xe3, 0x08, 0x43, 0x05, 0xf0, 0x00, 0x13, 0x00, 0x16, 0x00, 0x20, 0x00, 0x00, 0x01, 0x33, 0x13, 0x36, 0x37, 0x36, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x27, 0x26, 0x27, 0x21, 0x03, 0x23, 0x01, 0x03, 0x21, 0x00, 0x20, 0x02, 0x11, 0x10, 0x12, 0x20, 0x12, 0x11, 0x10, 0x02, 0x0f, 0xcf, 0xa5, 0x29, 0x64, 0xaa, 0x01, 0x1b, 0x01, 0x1b, 0x01, 0x52, 0xfe, 0xae, 0xfe, 0xe5, 0xfe, 0xe5, 0xaa, 0x47, 0x2a, 0xfd, 0xa9, 0x7a, 0xc0, 0x02, 0x68, 0xf7, 0x01, 0xef, 0x03, 0x2d, 0xfe, 0x74, 0xe9, 0xe9, 0x01, 0x8c, 0xe7, 0x05, 0xd5, 0xfe, 0x1e, 0xae, 0x7d, 0xd2, 0xfe, 0x5b, 0xfe, 0x9e, 0xfe, 0x9f, 0xfe, 0x5b, 0xd2, 0x58, 0x72, 0xfe, 0x81, 0x05, 0x0e, 0xfd, 0x19, 0x03, 0x25, 0xfe, 0xb8, 0xfe, 0xe5, 0xfe, 0xe6, 0xfe, 0xb8, 0x01, 0x48, 0x01, 0x1a, 0x01, 0x1b, 0x00, 0x00, 0x03, 0x00, 0x6e, 0xff, 0xe3, 0x06, 0xbc, 0x04, 0x7b, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x00, 0x01, 0x32, 0x12, 0x11, 0x10, 0x02, 0x20, 0x27, 0x26, 0x27, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x20, 0x17, 0x36, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x01, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x04, 0xed, 0xd8, 0xf7, 0xf7, 0xfe, 0x4f, 0x7b, 0x31, 0x1e, 0x10, 0x56, 0x7e, 0xa0, 0xa0, 0xb7, 0xe3, 0xe2, 0xe8, 0x96, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0x01, 0x0c, 0x66, 0x7c, 0xfe, 0x7b, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0x01, 0xd1, 0x85, 0x9b, 0x9a, 0x86, 0x84, 0x9b, 0x9b, 0x04, 0x7b, 0xfe, 0xc8, 0xfe, 0xec, 0xfe, 0xed, 0xfe, 0xc7, 0x9d, 0x3e, 0x52, 0x45, 0x87, 0x61, 0xc1, 0xa2, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0xbd, 0xbd, 0xfd, 0xb8, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0x01, 0xac, 0xe7, 0xfe, 0x6e, 0xe7, 0xe8, 0xc8, 0xc7, 0xe9, 0x00, 0x00, 0x02, 0x00, 0x0e, 0xff, 0xe3, 0x07, 0x99, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x16, 0x00, 0x00, 0x01, 0x03, 0x21, 0x01, 0x33, 0x01, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x00, 0x23, 0x20, 0x03, 0x27, 0x21, 0x03, 0x23, 0x02, 0x76, 0xf7, 0x01, 0xef, 0xfe, 0xa1, 0xcf, 0x01, 0x8f, 0x42, 0xe8, 0xaf, 0x9c, 0xb7, 0xfe, 0xfc, 0xfe, 0xfe, 0x9a, 0x69, 0x22, 0xfd, 0xa2, 0x7a, 0xc0, 0x05, 0x0e, 0xfd, 0x19, 0x03, 0xae, 0xfb, 0x72, 0xc0, 0xd3, 0xf0, 0x03, 0x8b, 0xfc, 0x5c, 0xfe, 0xdc, 0xfe, 0xd6, 0x01, 0x34, 0x68, 0xfe, 0x81, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6e, 0xff, 0xe3, 0x06, 0x69, 0x04, 0x7b, 0x00, 0x28, 0x00, 0x33, 0x00, 0x00, 0x25, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x11, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x03, 0x37, 0x41, 0x91, 0xa0, 0x9f, 0xb7, 0xe3, 0xe2, 0xe8, 0x96, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0xdb, 0xd8, 0x70, 0x6f, 0x86, 0x9c, 0xa6, 0xa6, 0x3c, 0x9f, 0x6a, 0xfe, 0xfe, 0xf8, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0xdf, 0x8d, 0x6f, 0xc1, 0xa2, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0xfc, 0xff, 0x00, 0xbe, 0x9f, 0x9f, 0xbe, 0xa4, 0x02, 0x7b, 0xfb, 0xa0, 0xac, 0x66, 0x63, 0x02, 0x50, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x06, 0xef, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x03, 0x21, 0x13, 0x03, 0x21, 0x03, 0x23, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x02, 0x76, 0xf7, 0x01, 0xef, 0xb3, 0x7b, 0xfd, 0xa2, 0x7a, 0xc0, 0x02, 0x01, 0xcf, 0x01, 0xac, 0x01, 0xa8, 0xbd, 0xfe, 0x00, 0x05, 0x0e, 0xfd, 0x19, 0xfd, 0xd9, 0x01, 0x7f, 0xfe, 0x81, 0x05, 0xd5, 0xfb, 0x1f, 0x04, 0xe1, 0xfa, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x6e, 0xff, 0xe3, 0x05, 0xad, 0x04, 0x7b, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x00, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x11, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x19, 0x01, 0x01, 0x33, 0x01, 0x02, 0x78, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0x38, 0xa9, 0x7b, 0x9b, 0xb6, 0xe3, 0xe2, 0xe8, 0x96, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0xdb, 0xd8, 0x01, 0x3b, 0xb0, 0xfe, 0x86, 0x02, 0x33, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0xfd, 0xcd, 0xaa, 0x66, 0x61, 0xc1, 0xa2, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0xfc, 0xff, 0x00, 0xfe, 0x35, 0x03, 0xac, 0xfb, 0xa0, 0x00, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x06, 0xef, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x12, 0x00, 0x15, 0x00, 0x00, 0x01, 0x03, 0x29, 0x02, 0x15, 0x21, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x01, 0x33, 0x01, 0x33, 0x01, 0x33, 0x01, 0x23, 0x17, 0x02, 0x76, 0xf7, 0x01, 0xef, 0x02, 0x3e, 0x01, 0x43, 0xfe, 0x83, 0x83, 0xce, 0x7b, 0xfd, 0xa2, 0x7a, 0xc0, 0x02, 0x01, 0xcf, 0x01, 0x43, 0xd1, 0x01, 0x40, 0xbd, 0xfd, 0xca, 0x5f, 0x30, 0x05, 0x0e, 0xfd, 0x19, 0xa8, 0xfe, 0x81, 0x01, 0x7f, 0xfe, 0x81, 0x05, 0xd5, 0xfc, 0x52, 0x03, 0xae, 0xfb, 0xaa, 0x8b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x6e, 0xff, 0xe3, 0x05, 0xad, 0x04, 0x7b, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x00, 0x21, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x17, 0x33, 0x13, 0x33, 0x03, 0x33, 0x15, 0x23, 0x03, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x21, 0x23, 0x11, 0x03, 0x1c, 0x38, 0xa9, 0x7b, 0x9b, 0xb6, 0xe3, 0xe2, 0xe8, 0x96, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0xdb, 0x6c, 0x5d, 0x0d, 0xb2, 0x8b, 0xb0, 0x8c, 0x8c, 0xbd, 0xbd, 0xfe, 0x45, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0x01, 0x27, 0x81, 0xaa, 0x66, 0x61, 0xc1, 0xa2, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0x7e, 0x6d, 0xcd, 0x01, 0x9d, 0xfe, 0x63, 0x90, 0xfd, 0xcd, 0x02, 0x33, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0xfe, 0x81, 0x00, 0x00, 0x02, 0x00, 0x0e, 0xfe, 0x56, 0x06, 0xd9, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00, 0x01, 0x03, 0x21, 0x01, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3f, 0x01, 0x03, 0x21, 0x03, 0x23, 0x01, 0x33, 0x09, 0x01, 0x33, 0x02, 0x76, 0xf7, 0x01, 0xef, 0x01, 0x47, 0x43, 0x46, 0x42, 0x70, 0xc2, 0x9a, 0x44, 0x26, 0x26, 0x2e, 0x11, 0x7b, 0xfd, 0xa2, 0x7a, 0xc0, 0x02, 0x01, 0xcf, 0x01, 0xa0, 0x01, 0x9d, 0xbd, 0x05, 0x0e, 0xfd, 0x19, 0xfd, 0x71, 0xc6, 0x3f, 0x3d, 0xaa, 0x24, 0x25, 0x85, 0x32, 0x01, 0x7f, 0xfe, 0x81, 0x05, 0xd5, 0xfb, 0x40, 0x04, 0xc0, 0x00, 0x02, 0x00, 0x6e, 0xfe, 0x56, 0x05, 0xad, 0x04, 0x7b, 0x00, 0x27, 0x00, 0x32, 0x00, 0x00, 0x21, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x19, 0x01, 0x01, 0x33, 0x01, 0x0e, 0x01, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x3f, 0x01, 0x03, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x03, 0x1c, 0x38, 0xa9, 0x7b, 0x9b, 0xb6, 0xe3, 0xe2, 0xe8, 0x96, 0x88, 0x56, 0xa4, 0x4c, 0x5b, 0xab, 0x51, 0xdb, 0xd8, 0x01, 0x3b, 0xb0, 0xfe, 0x45, 0x46, 0x86, 0x6f, 0x85, 0x62, 0x44, 0x4c, 0x2e, 0x17, 0xf1, 0xc9, 0x9b, 0x74, 0x64, 0x8a, 0xa6, 0xaa, 0x66, 0x61, 0xc1, 0xa2, 0xbd, 0xc0, 0x12, 0x7f, 0x8b, 0x2e, 0x2e, 0xaa, 0x27, 0x27, 0xfc, 0xff, 0x00, 0xfe, 0x77, 0x03, 0x6a, 0xfb, 0x38, 0xc8, 0x7a, 0x9a, 0x48, 0x86, 0x42, 0x02, 0x33, 0x66, 0x7b, 0x62, 0x73, 0xd9, 0xb4, 0x29, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x10, 0x06, 0x03, 0x93, 0x00, 0x00, 0xff, 0xff, 0x00, 0x72, 0xff, 0xe3, 0x03, 0x90, 0x04, 0x7b, 0x10, 0x06, 0x03, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x04, 0xe0, 0x05, 0xd5, 0x00, 0x12, 0x00, 0x00, 0x13, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0xb5, 0xb6, 0xac, 0xac, 0x02, 0x5b, 0xea, 0xfd, 0x65, 0x02, 0xca, 0xef, 0xfd, 0x7b, 0xb6, 0xac, 0xac, 0x05, 0xd5, 0xb9, 0xaa, 0xfe, 0xec, 0x02, 0x77, 0xfd, 0x48, 0xfc, 0xe3, 0x02, 0xcf, 0xfd, 0x31, 0x04, 0x72, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x12, 0x00, 0x00, 0x13, 0x33, 0x15, 0x21, 0x15, 0x21, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0xaf, 0xa6, 0x01, 0x05, 0xfe, 0xfb, 0x01, 0xee, 0xd4, 0xfd, 0xe9, 0x02, 0x2d, 0xd8, 0xfe, 0x00, 0xa6, 0xa2, 0xa2, 0x06, 0x14, 0xac, 0xa4, 0xfd, 0xb9, 0x01, 0xe3, 0xfd, 0xf4, 0xfd, 0xac, 0x02, 0x23, 0xfd, 0xdd, 0x04, 0xc4, 0xa4, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xdc, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x37, 0x11, 0x21, 0x15, 0x21, 0x11, 0xb5, 0xb6, 0xe3, 0x02, 0x8e, 0xfc, 0xbc, 0x02, 0xad, 0x03, 0x28, 0xfd, 0x5e, 0x4d, 0xfd, 0x2a, 0xaa, 0x02, 0xfa, 0x00, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x02, 0x26, 0x06, 0x14, 0x00, 0x07, 0x00, 0x00, 0x13, 0x11, 0x33, 0x11, 0x37, 0x11, 0x23, 0x11, 0xae, 0xa5, 0xd3, 0xa6, 0x02, 0x9c, 0x03, 0x78, 0xfd, 0x05, 0x49, 0xfc, 0x9e, 0x02, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4a, 0x00, 0x00, 0x04, 0x26, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x21, 0x15, 0x21, 0x11, 0x23, 0x35, 0x33, 0xe2, 0xb6, 0x97, 0x97, 0x02, 0x8e, 0xfc, 0xbc, 0x97, 0x97, 0x05, 0xd5, 0xe0, 0xa4, 0xfc, 0x59, 0xaa, 0x04, 0x51, 0xa4, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x02, 0xa7, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x01, 0x36, 0xa6, 0xcb, 0xcb, 0xa6, 0xca, 0xca, 0x06, 0x14, 0xfe, 0xe2, 0xa4, 0xfb, 0xae, 0x04, 0x52, 0xa4, 0x00, 0x03, 0x00, 0x09, 0xff, 0xe3, 0x05, 0xc6, 0x05, 0xf0, 0x00, 0x15, 0x00, 0x1d, 0x00, 0x25, 0x00, 0x00, 0x01, 0x20, 0x17, 0x16, 0x13, 0x33, 0x15, 0x23, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x23, 0x35, 0x33, 0x12, 0x37, 0x36, 0x04, 0x20, 0x07, 0x06, 0x07, 0x21, 0x26, 0x27, 0x13, 0x21, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x02, 0xe8, 0x01, 0x1b, 0xa9, 0x91, 0x15, 0x74, 0x72, 0x0a, 0x9e, 0xa9, 0xfe, 0xe5, 0xfe, 0xe5, 0xa9, 0xa0, 0x0a, 0x71, 0x74, 0x15, 0x92, 0xa9, 0x01, 0xe1, 0xfe, 0x74, 0x74, 0x5f, 0x12, 0x03, 0x55, 0x11, 0x5f, 0x73, 0xfc, 0xa5, 0x09, 0x6b, 0x74, 0x01, 0x8c, 0x74, 0x6b, 0x05, 0xf0, 0xd2, 0xb5, 0xfe, 0xe3, 0x90, 0xfe, 0xbe, 0xc4, 0xd3, 0xd2, 0xc4, 0x01, 0x43, 0x90, 0x01, 0x1d, 0xb5, 0xd2, 0xa4, 0xa4, 0x86, 0xd6, 0xd6, 0x86, 0xfe, 0x14, 0xfa, 0x97, 0xa4, 0xa4, 0x97, 0x00, 0x00, 0x00, 0x03, 0x00, 0x09, 0xff, 0xe3, 0x05, 0x00, 0x04, 0x7b, 0x00, 0x15, 0x00, 0x1e, 0x00, 0x27, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x33, 0x15, 0x23, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x23, 0x35, 0x33, 0x36, 0x37, 0x36, 0x17, 0x22, 0x07, 0x06, 0x07, 0x21, 0x26, 0x27, 0x26, 0x13, 0x21, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x02, 0x85, 0xd8, 0x7c, 0x63, 0x13, 0xb1, 0xad, 0x09, 0x71, 0x7c, 0xd8, 0xd9, 0x7a, 0x71, 0x09, 0xaf, 0xb2, 0x13, 0x64, 0x7a, 0xd9, 0x85, 0x4d, 0x39, 0x0f, 0x02, 0x34, 0x0f, 0x39, 0x4d, 0x9a, 0xfd, 0xc2, 0x07, 0x45, 0x4d, 0x86, 0x85, 0x4d, 0x45, 0x04, 0x7b, 0x9c, 0x7e, 0xcd, 0x90, 0xf4, 0x90, 0x9d, 0x9d, 0x90, 0xf4, 0x90, 0xcd, 0x7e, 0x9c, 0x9c, 0x73, 0x55, 0x83, 0x81, 0x55, 0x75, 0xfe, 0x25, 0xab, 0x67, 0x73, 0x74, 0x67, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x67, 0xff, 0xe3, 0x09, 0x60, 0x05, 0xf0, 0x00, 0x1a, 0x00, 0x24, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x20, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x21, 0x20, 0x00, 0x10, 0x00, 0x04, 0x20, 0x02, 0x11, 0x10, 0x12, 0x20, 0x12, 0x11, 0x10, 0x00, 0x20, 0x02, 0x11, 0x10, 0x12, 0x20, 0x12, 0x11, 0x10, 0x02, 0xd6, 0x01, 0x1b, 0xa9, 0x2a, 0x20, 0x1f, 0x2a, 0xaa, 0x01, 0x1b, 0x01, 0x1b, 0x01, 0x52, 0xfe, 0xae, 0xfe, 0xe5, 0xfe, 0xe5, 0xaa, 0x2a, 0x20, 0x1f, 0x2a, 0xa9, 0xfe, 0xe5, 0xfe, 0xe5, 0xfe, 0xad, 0x01, 0x53, 0x01, 0xe1, 0xfe, 0x74, 0xe9, 0xe9, 0x01, 0x8c, 0xe8, 0x03, 0x34, 0xfe, 0x74, 0xe9, 0xe9, 0x01, 0x8c, 0xe8, 0x05, 0xf0, 0xd2, 0x35, 0x3d, 0x3d, 0x35, 0xd2, 0xfe, 0x5b, 0xfe, 0x9e, 0xfe, 0x9f, 0xfe, 0x5b, 0xd2, 0x34, 0x3d, 0x3c, 0x34, 0xd3, 0x01, 0xa4, 0x02, 0xc4, 0x01, 0xa5, 0xa4, 0xfe, 0xb8, 0xfe, 0xe5, 0xfe, 0xe6, 0xfe, 0xb8, 0x01, 0x48, 0x01, 0x1a, 0x01, 0x1b, 0x01, 0x48, 0xfe, 0xb8, 0xfe, 0xe5, 0xfe, 0xe6, 0xfe, 0xb8, 0x01, 0x48, 0x01, 0x1a, 0x01, 0x1b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x65, 0xff, 0xe3, 0x06, 0xf1, 0x04, 0x7b, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x31, 0x00, 0x00, 0x01, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x21, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x32, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x33, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x05, 0x22, 0x85, 0x9b, 0x9a, 0x86, 0x84, 0x9b, 0x9b, 0xfc, 0x8e, 0x85, 0x9b, 0x9a, 0x86, 0x85, 0x9a, 0x9a, 0x85, 0xd8, 0x7c, 0x12, 0x11, 0x10, 0x13, 0x7b, 0xd9, 0xd8, 0xf7, 0xf7, 0xd8, 0xd9, 0x7b, 0x13, 0x10, 0x11, 0x12, 0x7c, 0xd8, 0xd9, 0xf5, 0xf5, 0x03, 0xdf, 0xe7, 0xfe, 0x6e, 0xe7, 0xe8, 0xc8, 0xc7, 0xe9, 0xe7, 0xfe, 0x6e, 0xe7, 0xe8, 0xc8, 0xc7, 0xe9, 0x9c, 0x9c, 0x18, 0x1b, 0x1b, 0x18, 0x9c, 0xfe, 0xc8, 0xfe, 0xec, 0xfe, 0xed, 0xfe, 0xc7, 0x9d, 0x18, 0x1b, 0x1b, 0x18, 0x9d, 0x01, 0x39, 0x01, 0x13, 0x01, 0x14, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x25, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x15, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x01, 0x6b, 0xe4, 0x7f, 0x8b, 0x8b, 0x7f, 0xfe, 0x66, 0x01, 0x9a, 0xe2, 0x73, 0x74, 0x74, 0x73, 0xe2, 0xe4, 0xd5, 0xd5, 0xb6, 0xac, 0xac, 0x05, 0x2f, 0xfd, 0xcf, 0x92, 0x87, 0x86, 0x92, 0xa6, 0x71, 0x72, 0xdb, 0xdd, 0x71, 0x71, 0xc4, 0x90, 0xfe, 0xfc, 0x01, 0x04, 0x90, 0x00, 0x00, 0x02, 0xff, 0xfb, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x00, 0x07, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10, 0x26, 0x20, 0x06, 0x10, 0x16, 0x20, 0x01, 0x35, 0x33, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x03, 0x81, 0x96, 0xfe, 0xf9, 0x96, 0x96, 0x01, 0x07, 0xfd, 0x11, 0xab, 0xa7, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x34, 0xe4, 0xe4, 0xa7, 0x01, 0x64, 0x01, 0x96, 0xe7, 0xe7, 0xfe, 0x6a, 0xe7, 0xfe, 0x67, 0x90, 0x04, 0xec, 0xaa, 0x64, 0x61, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x61, 0x64, 0xfe, 0xcc, 0x90, 0x8e, 0x8e, 0x00, 0x02, 0x00, 0x2d, 0x00, 0x00, 0x05, 0x0a, 0x05, 0xd5, 0x00, 0x1e, 0x00, 0x27, 0x00, 0x00, 0x01, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x23, 0x22, 0x07, 0x06, 0x15, 0x16, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x03, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x01, 0xa6, 0x01, 0x9a, 0xe2, 0xe8, 0xe8, 0xe2, 0xe4, 0xb6, 0x28, 0x53, 0x2b, 0x35, 0x01, 0x18, 0x15, 0x35, 0x3d, 0x47, 0x3e, 0x3f, 0x72, 0x58, 0x91, 0x1e, 0xb6, 0xe4, 0x7f, 0x8b, 0x8b, 0x7f, 0xe4, 0x05, 0xd5, 0xe3, 0xdb, 0xdd, 0xe2, 0xfd, 0xa8, 0x02, 0x58, 0x18, 0x1f, 0x3d, 0x35, 0x27, 0x20, 0x18, 0x94, 0x17, 0x49, 0x4b, 0x7d, 0x93, 0x4c, 0x3b, 0x92, 0x87, 0x86, 0x92, 0x00, 0x02, 0x00, 0x2d, 0xfe, 0x56, 0x05, 0x2f, 0x04, 0x7b, 0x00, 0x0c, 0x00, 0x31, 0x00, 0x00, 0x01, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x20, 0x06, 0x15, 0x03, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x27, 0x11, 0x23, 0x02, 0x4f, 0x09, 0x8e, 0x83, 0x80, 0x4f, 0x4b, 0x97, 0xfe, 0xfa, 0x97, 0xa6, 0x2e, 0x25, 0x28, 0x2e, 0x35, 0x19, 0x15, 0x35, 0x3d, 0x47, 0x3e, 0x3f, 0x72, 0x4b, 0x5e, 0x30, 0x31, 0xa6, 0x35, 0x9f, 0x6f, 0xb7, 0xe6, 0xe6, 0xb6, 0xac, 0x98, 0xa6, 0x01, 0x32, 0x0b, 0xaa, 0x73, 0x70, 0xcf, 0xcb, 0xe7, 0xe7, 0xcb, 0xfe, 0xe3, 0x19, 0x18, 0x1b, 0x41, 0x34, 0x28, 0x20, 0x18, 0x94, 0x17, 0x49, 0x4b, 0x7d, 0x86, 0x59, 0x3b, 0x17, 0x02, 0xa6, 0xaa, 0x64, 0x61, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0xa2, 0xfd, 0xd1, 0x00, 0x00, 0x02, 0x00, 0x67, 0xfe, 0x94, 0x05, 0x44, 0x05, 0xf0, 0x00, 0x09, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x02, 0x11, 0x10, 0x12, 0x20, 0x12, 0x11, 0x10, 0x01, 0x27, 0x37, 0x27, 0x07, 0x06, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x02, 0x07, 0x17, 0x37, 0x17, 0x07, 0x17, 0x23, 0x27, 0x03, 0x9c, 0xfe, 0x74, 0xe9, 0xe9, 0x01, 0x8c, 0xe8, 0xfe, 0xa6, 0x41, 0x99, 0x60, 0x2e, 0x10, 0x0e, 0xfe, 0xe5, 0xfe, 0xad, 0x01, 0x53, 0x01, 0x1b, 0x01, 0x1b, 0x01, 0x52, 0xbc, 0xb2, 0x3e, 0xc2, 0x40, 0xa9, 0x58, 0xdb, 0x0d, 0x05, 0x4c, 0xfe, 0xb8, 0xfe, 0xe5, 0xfe, 0xe6, 0xfe, 0xb8, 0x01, 0x48, 0x01, 0x1a, 0x01, 0x1b, 0xfa, 0x90, 0x7d, 0x62, 0x74, 0x03, 0x01, 0x01, 0xa5, 0x01, 0x61, 0x01, 0x62, 0x01, 0xa5, 0xfe, 0x5b, 0xfe, 0x9e, 0xfe, 0xfc, 0xfe, 0x8e, 0x58, 0x4b, 0x7c, 0x7d, 0x6c, 0x6b, 0x0f, 0x00, 0x02, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x97, 0x04, 0x7b, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x00, 0x25, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x00, 0x10, 0x16, 0x20, 0x36, 0x10, 0x26, 0x20, 0x03, 0x45, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0xa6, 0xab, 0xab, 0xa6, 0xe5, 0xe5, 0xfd, 0xcc, 0x96, 0x01, 0x07, 0x97, 0x97, 0xfe, 0xf9, 0xa8, 0x64, 0x61, 0x01, 0x44, 0x02, 0x10, 0x01, 0x44, 0x61, 0x64, 0xaa, 0xfb, 0x14, 0x90, 0x8e, 0x8e, 0x90, 0x03, 0x86, 0xfe, 0x6a, 0xe7, 0xe7, 0x01, 0x96, 0xe7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x10, 0x26, 0x23, 0x01, 0x33, 0x15, 0x33, 0x15, 0x23, 0x15, 0x33, 0x32, 0x16, 0x10, 0x06, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x01, 0x6b, 0xe4, 0x7f, 0x8b, 0x8a, 0x80, 0xfe, 0x66, 0xb6, 0xd5, 0xd5, 0xe4, 0xe2, 0xe7, 0xe7, 0xe2, 0xe4, 0xb6, 0xac, 0xac, 0x04, 0x27, 0xfd, 0xd1, 0x92, 0x01, 0x0c, 0x91, 0x01, 0xae, 0x2d, 0x90, 0x4b, 0xe1, 0xfe, 0x48, 0xe2, 0xfe, 0xae, 0x05, 0x18, 0x90, 0x00, 0x00, 0x02, 0xff, 0xfb, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x07, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10, 0x26, 0x20, 0x06, 0x10, 0x16, 0x20, 0x25, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x26, 0x03, 0x81, 0x96, 0xfe, 0xf9, 0x96, 0x96, 0x01, 0x07, 0xfe, 0x63, 0xa7, 0xab, 0xab, 0xa7, 0xe4, 0xe4, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x01, 0x64, 0x01, 0x96, 0xe7, 0xe7, 0xfe, 0x6a, 0xe7, 0x2b, 0xfd, 0xae, 0x06, 0x9b, 0x90, 0x93, 0x93, 0x90, 0xfe, 0xc5, 0x64, 0x61, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x61, 0x00, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x36, 0x10, 0x26, 0x23, 0x01, 0x33, 0x11, 0x33, 0x32, 0x16, 0x10, 0x06, 0x2b, 0x01, 0x15, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x01, 0x6b, 0xe4, 0x7f, 0x8b, 0x8a, 0x80, 0xfe, 0x66, 0xb6, 0xe4, 0xe2, 0xe7, 0xe7, 0xe2, 0xe4, 0xd5, 0xd5, 0xb6, 0xac, 0xac, 0x04, 0x27, 0xfd, 0xd1, 0x92, 0x01, 0x0c, 0x91, 0x01, 0xae, 0xfe, 0xf8, 0xe1, 0xfe, 0x48, 0xe2, 0x5e, 0x90, 0x64, 0x64, 0x90, 0x00, 0x00, 0x00, 0x02, 0xff, 0xfb, 0xfe, 0x56, 0x04, 0x2e, 0x06, 0x14, 0x00, 0x07, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10, 0x26, 0x20, 0x06, 0x10, 0x16, 0x20, 0x01, 0x35, 0x33, 0x11, 0x33, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x03, 0x81, 0x96, 0xfe, 0xf9, 0x96, 0x96, 0x01, 0x07, 0xfd, 0x11, 0xab, 0xa7, 0x34, 0x9f, 0x6f, 0xb8, 0xe5, 0xe5, 0xb8, 0x6f, 0x9f, 0x34, 0xe4, 0xe4, 0xa7, 0x01, 0x64, 0x01, 0x96, 0xe7, 0xe7, 0xfe, 0x6a, 0xe7, 0xfe, 0x67, 0x90, 0x06, 0xa0, 0xfd, 0xa2, 0x64, 0x61, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x61, 0x64, 0xfe, 0xcc, 0x90, 0x8e, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x4e, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x21, 0x23, 0x11, 0x21, 0x35, 0x21, 0x03, 0x4e, 0xb6, 0xfd, 0x72, 0x03, 0x44, 0x05, 0x2b, 0xaa, 0x00, 0x00, 0x00, 0x02, 0x00, 0xad, 0xfe, 0x56, 0x01, 0x54, 0x04, 0x7b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x07, 0x33, 0x11, 0x23, 0x01, 0x00, 0x52, 0xa5, 0xa5, 0x04, 0x7b, 0x1b, 0xf9, 0xf6, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x04, 0x97, 0x05, 0xf0, 0x00, 0x14, 0x00, 0x00, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x12, 0x19, 0x01, 0x23, 0x03, 0xe2, 0x8b, 0x8a, 0xa1, 0xc1, 0xb6, 0xb6, 0x48, 0x5c, 0x5b, 0x8e, 0xcd, 0xd1, 0xb4, 0x03, 0x7f, 0xd7, 0xd5, 0xff, 0xde, 0xfb, 0x08, 0x07, 0x7f, 0xf1, 0x87, 0x43, 0x42, 0xfe, 0xc1, 0xfe, 0xcc, 0xfc, 0x83, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0x56, 0x03, 0xf4, 0x04, 0x7b, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x03, 0xf4, 0xa6, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0xa1, 0x6a, 0xad, 0xb3, 0x02, 0xa4, 0xfd, 0x5c, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfb, 0xdd, 0x06, 0x0a, 0xae, 0x65, 0x64, 0xef, 0x00, 0x00, 0xff, 0xff, 0x00, 0xd8, 0x00, 0x00, 0x01, 0x96, 0x04, 0x23, 0x12, 0x06, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x90, 0x01, 0x49, 0x02, 0x25, 0x03, 0x0b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x35, 0x21, 0x35, 0x21, 0x02, 0x25, 0xfe, 0x6b, 0x01, 0x95, 0xfe, 0x6b, 0x01, 0x95, 0x01, 0x49, 0x96, 0x96, 0x96, 0x00, 0x00, 0x01, 0x01, 0x16, 0x01, 0xe1, 0x01, 0xcd, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x01, 0x33, 0x11, 0x03, 0x23, 0x03, 0x01, 0x16, 0xb7, 0x12, 0x92, 0x13, 0x05, 0xd5, 0xfd, 0x71, 0xfe, 0x9b, 0x01, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb1, 0x03, 0xaa, 0x01, 0x4b, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x01, 0x4a, 0x99, 0x05, 0xd5, 0xfd, 0xd5, 0x02, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x9d, 0x00, 0x00, 0x04, 0x3b, 0x05, 0xd5, 0x12, 0x06, 0x03, 0xbb, 0x00, 0x00, 0x00, 0x02, 0x00, 0x45, 0xfe, 0x56, 0x02, 0xff, 0x06, 0x14, 0x00, 0x06, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x26, 0x23, 0x22, 0x07, 0x14, 0x33, 0x37, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0x30, 0x03, 0x23, 0x22, 0x37, 0x36, 0x33, 0x32, 0x01, 0x6a, 0x15, 0x31, 0x46, 0x01, 0x53, 0x48, 0xa6, 0xe1, 0xe1, 0x37, 0x6c, 0x2c, 0x3f, 0xac, 0x8a, 0x02, 0x36, 0xfc, 0x01, 0x01, 0xdd, 0x30, 0x03, 0x12, 0x84, 0x4b, 0x39, 0xfa, 0x02, 0x08, 0xfc, 0xfe, 0xa0, 0xfd, 0x70, 0x7c, 0x74, 0x9c, 0xcc, 0xca, 0x02, 0x86, 0xbd, 0xf6, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0xbf, 0x05, 0x47, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x33, 0x01, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x01, 0x11, 0x23, 0xb5, 0xf5, 0x02, 0x54, 0xb0, 0x99, 0x99, 0xf5, 0xfd, 0xac, 0xb0, 0x05, 0xd5, 0xfb, 0x1f, 0x04, 0xe1, 0xfa, 0xd5, 0xfe, 0x15, 0x01, 0x41, 0x04, 0xe1, 0xfb, 0x1f, 0x00, 0x00, 0x01, 0x00, 0xa7, 0xfe, 0xe5, 0x04, 0x78, 0x04, 0x7b, 0x00, 0x17, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x23, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x03, 0xf4, 0x84, 0x84, 0xa6, 0x70, 0x6f, 0x86, 0x9b, 0xa7, 0xa7, 0x3b, 0xa1, 0x6a, 0xad, 0xb3, 0x02, 0xa4, 0xfd, 0xef, 0xfe, 0x52, 0x01, 0x1b, 0x02, 0x9e, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x87, 0x04, 0x60, 0xae, 0x65, 0x64, 0xef, 0x00, 0x01, 0x00, 0x03, 0xff, 0xe3, 0x05, 0x9a, 0x05, 0xf0, 0x00, 0x28, 0x00, 0x00, 0x25, 0x11, 0x21, 0x35, 0x21, 0x11, 0x0e, 0x01, 0x23, 0x24, 0x27, 0x26, 0x27, 0x07, 0x27, 0x37, 0x34, 0x35, 0x10, 0x00, 0x21, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x03, 0x01, 0x17, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x04, 0x49, 0xfe, 0xd7, 0x01, 0xdd, 0x69, 0xfe, 0x90, 0xfe, 0xc5, 0xb2, 0x7f, 0x24, 0x4c, 0x26, 0x64, 0x01, 0x63, 0x01, 0x3b, 0x83, 0xed, 0x64, 0x65, 0xe3, 0x7d, 0xf5, 0x7d, 0x79, 0x03, 0x04, 0x4c, 0x27, 0xfb, 0x94, 0x16, 0x5f, 0x7d, 0xf5, 0x61, 0x97, 0xd5, 0x01, 0x91, 0xa6, 0xfd, 0x7f, 0x53, 0x55, 0x01, 0xcc, 0x92, 0xe2, 0x1c, 0x7f, 0x25, 0x1e, 0x1f, 0x01, 0x6e, 0x01, 0x99, 0x48, 0x46, 0xd7, 0x5f, 0x60, 0x99, 0x97, 0xfe, 0xd9, 0x01, 0x95, 0x7f, 0xfe, 0x5f, 0xcf, 0x77, 0x99, 0x25, 0x00, 0x03, 0x00, 0x03, 0xfe, 0x56, 0x04, 0x8f, 0x04, 0x7b, 0x00, 0x26, 0x00, 0x30, 0x00, 0x3a, 0x00, 0x00, 0x25, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x26, 0x27, 0x07, 0x27, 0x37, 0x26, 0x35, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x33, 0x11, 0x37, 0x17, 0x0f, 0x01, 0x05, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x17, 0x03, 0xeb, 0xe5, 0xec, 0x57, 0x9b, 0x49, 0x49, 0x8e, 0x4a, 0xa3, 0xa2, 0x33, 0xa0, 0x70, 0xba, 0x71, 0x3c, 0x1c, 0x5e, 0x1d, 0x68, 0x06, 0xe2, 0xba, 0x70, 0xa0, 0x33, 0xa6, 0x86, 0x1d, 0xa3, 0xa7, 0xfd, 0xdc, 0x12, 0x29, 0x4a, 0x85, 0x86, 0x95, 0x0c, 0x11, 0x2d, 0x4a, 0x87, 0x85, 0x94, 0x01, 0x8b, 0xfe, 0xe2, 0xfe, 0xe9, 0x1d, 0x1e, 0xb3, 0x2c, 0x2a, 0xbd, 0xbf, 0x5b, 0x63, 0x62, 0x9d, 0x53, 0x70, 0x23, 0x63, 0x27, 0x38, 0x3e, 0x01, 0x04, 0x01, 0x3a, 0x62, 0x63, 0xaa, 0xfe, 0xb1, 0x32, 0x63, 0x3d, 0x3d, 0xcb, 0x57, 0x3c, 0x6e, 0xdc, 0xc7, 0x15, 0x7e, 0x62, 0x41, 0x6e, 0xdc, 0xc8, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x04, 0xe0, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x16, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x01, 0x17, 0x25, 0x17, 0x05, 0x01, 0x23, 0x01, 0x07, 0x11, 0x23, 0x11, 0x07, 0x27, 0x37, 0x25, 0x27, 0x15, 0xb5, 0xb6, 0x02, 0x5b, 0xea, 0xfd, 0x65, 0x6d, 0x02, 0x16, 0x27, 0xfe, 0x22, 0x01, 0xfe, 0xef, 0xfe, 0x3d, 0xc2, 0xb6, 0x8b, 0x26, 0xb1, 0x01, 0x19, 0x63, 0x05, 0xd5, 0xfd, 0x89, 0x02, 0x77, 0xfd, 0x48, 0x7a, 0xc5, 0x7f, 0xb0, 0xfd, 0xc7, 0x01, 0xf7, 0x48, 0xfe, 0x51, 0x01, 0x6c, 0x33, 0x7f, 0x41, 0x68, 0x6e, 0x93, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x04, 0x28, 0x06, 0x14, 0x00, 0x13, 0x00, 0x16, 0x00, 0x00, 0x13, 0x33, 0x11, 0x01, 0x33, 0x01, 0x17, 0x25, 0x17, 0x05, 0x01, 0x23, 0x01, 0x07, 0x11, 0x23, 0x35, 0x07, 0x27, 0x37, 0x25, 0x27, 0x15, 0xa7, 0xa7, 0x01, 0xee, 0xd4, 0xfd, 0xe9, 0x55, 0x01, 0xbc, 0x1e, 0xfe, 0x72, 0x01, 0x8c, 0xd8, 0xfe, 0xab, 0xab, 0xa7, 0x86, 0x1d, 0xa3, 0x01, 0x05, 0x5e, 0x06, 0x14, 0xfc, 0x69, 0x01, 0xe3, 0xfd, 0xf4, 0x5b, 0xa4, 0x62, 0x93, 0xfe, 0x58, 0x01, 0x6c, 0x3f, 0xfe, 0xd3, 0xf0, 0x32, 0x63, 0x3c, 0x61, 0x65, 0x88, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x05, 0x60, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x16, 0x00, 0x19, 0x00, 0x00, 0x13, 0x33, 0x01, 0x25, 0x11, 0x33, 0x11, 0x37, 0x17, 0x07, 0x11, 0x23, 0x01, 0x05, 0x11, 0x23, 0x11, 0x07, 0x27, 0x37, 0x25, 0x03, 0x11, 0x25, 0x13, 0x11, 0xb5, 0xf5, 0x01, 0x3b, 0x01, 0x19, 0xb0, 0x8a, 0x27, 0xb1, 0xf5, 0xfe, 0xc9, 0xfe, 0xe3, 0xb0, 0x8b, 0x26, 0xb1, 0x01, 0x93, 0xe3, 0x01, 0xb9, 0xe0, 0x05, 0xd5, 0xfd, 0x6b, 0x67, 0x02, 0x2e, 0xfe, 0x13, 0x33, 0x7f, 0x41, 0xfc, 0xa5, 0x02, 0x8e, 0x69, 0xfd, 0xdb, 0x01, 0xe4, 0x33, 0x7f, 0x41, 0x95, 0x01, 0xdb, 0xfd, 0xd1, 0x16, 0xfe, 0x2c, 0x02, 0x26, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x04, 0x8f, 0x04, 0x7b, 0x00, 0x17, 0x00, 0x20, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x05, 0x11, 0x23, 0x11, 0x07, 0x27, 0x37, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x36, 0x17, 0x16, 0x17, 0x37, 0x17, 0x07, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x03, 0xf4, 0xa6, 0xfe, 0x00, 0xa7, 0x86, 0x1d, 0xa3, 0xa7, 0x3b, 0xa1, 0x6a, 0xad, 0x59, 0x43, 0x11, 0x83, 0x1d, 0x9a, 0xa8, 0x08, 0x2e, 0x38, 0x6f, 0x86, 0x9b, 0x02, 0xa4, 0xfd, 0x5c, 0x02, 0x6a, 0xbe, 0xfe, 0x54, 0x01, 0x6f, 0x32, 0x63, 0x3d, 0x02, 0x83, 0xae, 0x65, 0x64, 0x01, 0x78, 0x59, 0x99, 0x31, 0x63, 0x39, 0x30, 0x75, 0x40, 0x4f, 0xbe, 0xa4, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x04, 0xfe, 0x05, 0xd5, 0x00, 0x1d, 0x00, 0x24, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x1e, 0x01, 0x17, 0x13, 0x23, 0x03, 0x2e, 0x01, 0x2b, 0x01, 0x11, 0x23, 0x11, 0x07, 0x27, 0x37, 0x11, 0x21, 0x32, 0x17, 0x16, 0x17, 0x37, 0x17, 0x07, 0x14, 0x15, 0x14, 0x06, 0x2d, 0x01, 0x26, 0x27, 0x26, 0x27, 0x23, 0x11, 0x15, 0x33, 0x16, 0x37, 0x36, 0x37, 0x03, 0x32, 0x3b, 0x6e, 0x38, 0xb9, 0xc4, 0xac, 0x42, 0x7d, 0x6c, 0xc6, 0xb6, 0x8b, 0x26, 0xb1, 0x01, 0x9a, 0xe7, 0x71, 0x42, 0x1c, 0xd1, 0x27, 0xe5, 0x75, 0xfd, 0xc8, 0x01, 0xe3, 0x10, 0x28, 0x42, 0x85, 0xe4, 0xe4, 0x85, 0x42, 0x37, 0x0a, 0x02, 0xbc, 0x16, 0x90, 0x7e, 0xfe, 0x68, 0x01, 0x7f, 0x96, 0x62, 0xfd, 0x89, 0x03, 0x01, 0x33, 0x7f, 0x42, 0x02, 0x46, 0x6b, 0x3e, 0x64, 0x4e, 0x7f, 0x55, 0x0d, 0x0e, 0x8d, 0xba, 0xf2, 0xb3, 0x3f, 0x28, 0x42, 0x01, 0xfe, 0x16, 0x28, 0x01, 0x44, 0x38, 0x63, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0xf6, 0x04, 0x7b, 0x00, 0x19, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x25, 0x17, 0x05, 0x11, 0x23, 0x11, 0x07, 0x27, 0x37, 0x11, 0x33, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x02, 0xf6, 0x1c, 0x42, 0x27, 0x8d, 0x96, 0x01, 0x86, 0x1e, 0xfe, 0x5c, 0xa7, 0x86, 0x1d, 0xa3, 0xa7, 0x34, 0xa8, 0x77, 0x11, 0x2a, 0x19, 0x03, 0xb4, 0x12, 0x11, 0xcb, 0xbe, 0x34, 0x90, 0x62, 0x9c, 0xfe, 0x54, 0x01, 0x6f, 0x32, 0x63, 0x3c, 0x02, 0x84, 0xae, 0x66, 0x63, 0x05, 0x05, 0x00, 0x00, 0x01, 0x00, 0x03, 0xff, 0xe3, 0x04, 0x8f, 0x05, 0xf0, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x15, 0x14, 0x04, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x05, 0x27, 0x25, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x03, 0xda, 0x67, 0xb8, 0x55, 0x95, 0xa1, 0x6b, 0x96, 0x4b, 0x01, 0xec, 0x26, 0xfe, 0xbd, 0x4f, 0x30, 0x61, 0xfe, 0xfb, 0xfd, 0x60, 0xd7, 0x73, 0x6f, 0xd4, 0x67, 0x9b, 0xaa, 0x7a, 0x8b, 0x57, 0xfe, 0x18, 0x26, 0x01, 0x41, 0x45, 0x2c, 0x5a, 0xfb, 0xdc, 0x5f, 0xc4, 0x05, 0xa4, 0xc5, 0x37, 0x36, 0x80, 0x76, 0x63, 0x65, 0x1f, 0x11, 0xb5, 0x7f, 0x77, 0x27, 0x38, 0x6c, 0xb6, 0xd9, 0xe0, 0x30, 0x2f, 0xd0, 0x45, 0x46, 0x88, 0x7e, 0x6e, 0x7c, 0x1f, 0x13, 0xb4, 0x7f, 0x77, 0x22, 0x2e, 0x60, 0xab, 0xc6, 0xe4, 0x26, 0x00, 0x00, 0x01, 0x00, 0x03, 0xff, 0xe3, 0x03, 0xbd, 0x04, 0x7b, 0x00, 0x2f, 0x00, 0x00, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x17, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x05, 0x27, 0x25, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x03, 0x30, 0x46, 0x97, 0x51, 0x7b, 0x7c, 0x59, 0x85, 0x28, 0x01, 0x8e, 0x1e, 0xfe, 0xf3, 0x44, 0x28, 0x49, 0x01, 0xde, 0xc2, 0x51, 0xb0, 0x61, 0x5c, 0xb2, 0x57, 0x75, 0x7e, 0x5b, 0x9a, 0x20, 0xfe, 0x7a, 0x1d, 0x01, 0x06, 0x38, 0x22, 0x45, 0xca, 0xb9, 0x5c, 0xa2, 0x04, 0x3f, 0xae, 0x28, 0x28, 0x54, 0x54, 0x40, 0x49, 0x21, 0x0a, 0x93, 0x63, 0x63, 0x20, 0x28, 0x4c, 0x89, 0x9c, 0xb6, 0x23, 0x23, 0xbe, 0x35, 0x35, 0x59, 0x51, 0x4b, 0x50, 0x25, 0x08, 0x90, 0x63, 0x61, 0x1b, 0x26, 0x4a, 0x83, 0x9e, 0xac, 0x1e, 0x00, 0x00, 0x01, 0xff, 0xa1, 0x00, 0x00, 0x05, 0x10, 0x05, 0xd5, 0x00, 0x14, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x11, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x01, 0x0f, 0x77, 0x6a, 0x8c, 0xac, 0xc1, 0xb6, 0x02, 0x94, 0xb6, 0xb6, 0xfd, 0x6c, 0xb6, 0x05, 0x30, 0x01, 0x5e, 0x69, 0x31, 0x46, 0xb5, 0xa3, 0xfd, 0x9c, 0x02, 0x64, 0xfa, 0x2b, 0x02, 0xc7, 0xfd, 0x39, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x05, 0xf0, 0x04, 0x60, 0x12, 0x06, 0x03, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x00, 0x03, 0x70, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x03, 0x6f, 0xb5, 0xfd, 0xeb, 0x02, 0x15, 0xfd, 0xb1, 0x05, 0xd5, 0xfa, 0x2b, 0x02, 0xc9, 0xaa, 0x01, 0xb8, 0xaa, 0x00, 0x00, 0x02, 0x00, 0x3f, 0x00, 0x00, 0x03, 0xa3, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x13, 0x00, 0x00, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x3b, 0x01, 0x13, 0x11, 0x23, 0x11, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x02, 0xed, 0xe5, 0x7f, 0x8a, 0x8a, 0x7f, 0xe5, 0xb6, 0xb6, 0xe5, 0xe2, 0xe7, 0xe7, 0xe2, 0x05, 0x2f, 0x92, 0x86, 0x87, 0x92, 0x02, 0xd7, 0xfa, 0x2b, 0x02, 0x58, 0xe2, 0xdd, 0xdb, 0xe3, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x00, 0x33, 0x11, 0x33, 0x11, 0x01, 0x33, 0x01, 0x11, 0x33, 0x11, 0x21, 0x09, 0x01, 0xb5, 0xb0, 0x01, 0x5b, 0xb6, 0x01, 0x5b, 0xb1, 0xfe, 0xf1, 0xfe, 0xa8, 0xfe, 0xa9, 0x05, 0xd5, 0xfa, 0xe1, 0x04, 0x00, 0xfc, 0x00, 0x05, 0x1f, 0xfa, 0x2b, 0x03, 0xf8, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x6b, 0x07, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0xb5, 0xb6, 0xb6, 0x07, 0x6d, 0xf8, 0x93, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x08, 0x67, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x25, 0x01, 0x33, 0x09, 0x01, 0x33, 0x01, 0x23, 0x09, 0x01, 0x23, 0x09, 0x01, 0x23, 0x01, 0x33, 0x03, 0x8f, 0x01, 0x1e, 0xcc, 0x01, 0x1b, 0x01, 0x1a, 0xb8, 0xfe, 0xaf, 0xe5, 0xfe, 0xe4, 0xfe, 0xe2, 0xcc, 0xfe, 0xe5, 0xfe, 0xe7, 0xb9, 0x01, 0x52, 0xe4, 0xc5, 0x05, 0x10, 0xfb, 0x12, 0x04, 0xee, 0xfa, 0x2b, 0x05, 0x10, 0xfa, 0xf0, 0x04, 0xee, 0xfb, 0x12, 0x05, 0xd5, 0x00, 0x00, 0x01, 0x00, 0xae, 0x04, 0xd0, 0x02, 0x53, 0x05, 0x58, 0x00, 0x03, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x02, 0x53, 0xfe, 0x5c, 0x01, 0xa4, 0x04, 0xd0, 0x88, 0x00, 0x00, 0x01, 0x00, 0x7e, 0x03, 0x9c, 0x02, 0x77, 0x05, 0x58, 0x00, 0x04, 0x00, 0x00, 0x13, 0x27, 0x01, 0x33, 0x15, 0xc1, 0x42, 0x01, 0xd4, 0x24, 0x03, 0x9c, 0x73, 0x01, 0x49, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x02, 0x68, 0x02, 0x9a, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x01, 0x23, 0x01, 0x27, 0x01, 0x33, 0x02, 0x9a, 0x0e, 0xfe, 0x35, 0x5e, 0x01, 0xf0, 0x47, 0x04, 0xd0, 0xfd, 0x98, 0x57, 0x02, 0x99, 0x00, 0x01, 0x00, 0x56, 0x01, 0x34, 0x02, 0xa7, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x01, 0x23, 0x01, 0x27, 0x01, 0x33, 0x02, 0xa7, 0x0d, 0xfe, 0x27, 0x6b, 0x01, 0xfd, 0x54, 0x04, 0xd0, 0xfc, 0x64, 0x44, 0x03, 0xe0, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x02, 0xad, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x01, 0x23, 0x01, 0x27, 0x01, 0x33, 0x02, 0xad, 0x0a, 0xfe, 0x1e, 0x70, 0x02, 0x02, 0x5a, 0x04, 0xd0, 0xfb, 0x30, 0x37, 0x05, 0x21, 0x00, 0x01, 0x00, 0x7e, 0x03, 0x9c, 0x02, 0x77, 0x05, 0x58, 0x00, 0x04, 0x00, 0x00, 0x13, 0x01, 0x15, 0x23, 0x01, 0xc1, 0x01, 0xb6, 0x24, 0xfe, 0x2c, 0x05, 0x58, 0xfe, 0xcc, 0x88, 0x01, 0x49, 0xff, 0xff, 0x00, 0xae, 0x03, 0x9c, 0x02, 0x53, 0x04, 0x24, 0x10, 0x07, 0x0e, 0xa9, 0x00, 0x00, 0xfe, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7e, 0x02, 0x68, 0x02, 0x77, 0x04, 0x24, 0x10, 0x07, 0x0e, 0xaa, 0x00, 0x00, 0xfe, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0x01, 0x34, 0x02, 0x9a, 0x04, 0x24, 0x10, 0x07, 0x0e, 0xab, 0x00, 0x00, 0xfe, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, 0x02, 0xa7, 0x04, 0x24, 0x10, 0x07, 0x0e, 0xac, 0x00, 0x00, 0xfe, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x02, 0x68, 0x02, 0x9a, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x01, 0x15, 0x23, 0x01, 0x37, 0x01, 0x02, 0x9a, 0x47, 0xfe, 0x10, 0x5e, 0x01, 0xcb, 0x02, 0xf0, 0x88, 0x02, 0x99, 0x57, 0xfd, 0x98, 0xff, 0xff, 0x00, 0x7e, 0x02, 0x68, 0x02, 0x77, 0x04, 0x24, 0x10, 0x07, 0x0e, 0xae, 0x00, 0x00, 0xfe, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0xae, 0x02, 0x68, 0x02, 0x53, 0x02, 0xf0, 0x10, 0x07, 0x0e, 0xa9, 0x00, 0x00, 0xfd, 0x98, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7e, 0x01, 0x34, 0x02, 0x77, 0x02, 0xf0, 0x10, 0x07, 0x0e, 0xaa, 0x00, 0x00, 0xfd, 0x98, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0x00, 0x00, 0x02, 0x9a, 0x02, 0xf0, 0x10, 0x07, 0x0e, 0xab, 0x00, 0x00, 0xfd, 0x98, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x01, 0x34, 0x02, 0xa7, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x01, 0x15, 0x23, 0x01, 0x37, 0x01, 0x02, 0xa7, 0x54, 0xfe, 0x03, 0x6b, 0x01, 0xd9, 0x01, 0xbc, 0x88, 0x03, 0xe0, 0x44, 0xfc, 0x64, 0xff, 0xff, 0x00, 0x63, 0x01, 0x34, 0x02, 0x9a, 0x04, 0x24, 0x10, 0x07, 0x0e, 0xb3, 0x00, 0x00, 0xfe, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7e, 0x01, 0x34, 0x02, 0x77, 0x02, 0xf0, 0x10, 0x07, 0x0e, 0xae, 0x00, 0x00, 0xfd, 0x98, 0x00, 0x00, 0xff, 0xff, 0x00, 0xae, 0x01, 0x34, 0x02, 0x53, 0x01, 0xbc, 0x10, 0x07, 0x0e, 0xa9, 0x00, 0x00, 0xfc, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x02, 0x77, 0x01, 0xbc, 0x10, 0x07, 0x0e, 0xaa, 0x00, 0x00, 0xfc, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x02, 0xad, 0x05, 0x58, 0x00, 0x05, 0x00, 0x00, 0x25, 0x15, 0x23, 0x01, 0x37, 0x01, 0x02, 0xad, 0x5a, 0xfd, 0xfe, 0x70, 0x01, 0xe2, 0x88, 0x88, 0x05, 0x21, 0x37, 0xfb, 0x30, 0x00, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, 0x02, 0xa7, 0x04, 0x24, 0x10, 0x07, 0x0e, 0xb8, 0x00, 0x00, 0xfe, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0x00, 0x00, 0x02, 0x9a, 0x02, 0xf0, 0x10, 0x07, 0x0e, 0xb3, 0x00, 0x00, 0xfd, 0x98, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x02, 0x77, 0x01, 0xbc, 0x10, 0x07, 0x0e, 0xae, 0x00, 0x00, 0xfc, 0x64, 0x00, 0x00, 0xff, 0xff, 0x00, 0xae, 0x00, 0x00, 0x02, 0x53, 0x00, 0x88, 0x11, 0x07, 0x0e, 0xa9, 0x00, 0x00, 0xfb, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x3b, 0x05, 0x58, 0x00, 0x03, 0x00, 0x00, 0x33, 0x11, 0x33, 0x11, 0xc1, 0x7a, 0x05, 0x58, 0xfa, 0xa8, 0x00, 0x0e, 0x00, 0x87, 0x00, 0x00, 0x06, 0x81, 0x05, 0xdc, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x15, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x15, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x06, 0x27, 0x5a, 0x5a, 0x5a, 0xfd, 0xb7, 0x01, 0xef, 0xfe, 0x11, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0xfe, 0x98, 0x5a, 0x5a, 0x5a, 0xfd, 0xb7, 0x01, 0xef, 0xfe, 0x11, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x03, 0x25, 0x02, 0x4e, 0xfd, 0xb2, 0xfd, 0x44, 0x02, 0x4e, 0xfd, 0xb2, 0x05, 0x0f, 0x64, 0x64, 0xfa, 0x88, 0x64, 0x64, 0x03, 0x25, 0x02, 0x4e, 0xfd, 0xb2, 0x69, 0x64, 0x64, 0xfd, 0xad, 0x02, 0x4e, 0xfd, 0xb2, 0x02, 0xbc, 0x02, 0x4e, 0xfd, 0xb2, 0xfd, 0x44, 0x02, 0x4e, 0xfd, 0xb2, 0x05, 0x0f, 0x64, 0x64, 0xfa, 0x88, 0x64, 0x64, 0x03, 0x25, 0x02, 0x4e, 0xfd, 0xb2, 0x69, 0x64, 0x64, 0xfd, 0xad, 0x02, 0x4e, 0xfd, 0xb2, 0x00, 0x0e, 0x00, 0x87, 0x00, 0x00, 0x06, 0x81, 0x05, 0xdc, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x15, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x15, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x06, 0x27, 0x5a, 0x5a, 0x5a, 0xfd, 0xb7, 0x01, 0xef, 0xfe, 0x11, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0xfe, 0x98, 0x5a, 0x5a, 0x5a, 0xfd, 0xb7, 0x01, 0xef, 0xfe, 0x11, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x03, 0x1b, 0x02, 0x58, 0xfd, 0xa8, 0xfd, 0x44, 0x02, 0x58, 0xfd, 0xa8, 0x05, 0x19, 0x64, 0x64, 0xfa, 0x88, 0x64, 0x64, 0x03, 0x1b, 0x02, 0x58, 0xfd, 0xa8, 0x5f, 0x64, 0x64, 0xfd, 0xa3, 0x02, 0x58, 0xfd, 0xa8, 0x02, 0xbc, 0x02, 0x58, 0xfd, 0xa8, 0xfd, 0x44, 0x02, 0x58, 0xfd, 0xa8, 0x05, 0x19, 0x64, 0x64, 0xfa, 0x88, 0x64, 0x64, 0x03, 0x1b, 0x02, 0x58, 0xfd, 0xa8, 0x5f, 0x64, 0x64, 0xfd, 0xa3, 0x02, 0x58, 0xfd, 0xa8, 0x00, 0x0e, 0x00, 0x87, 0x00, 0x00, 0x06, 0x81, 0x05, 0xdc, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x15, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x15, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x06, 0x27, 0x5a, 0x5a, 0x5a, 0xfd, 0xb7, 0x01, 0xef, 0xfe, 0x11, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0xfe, 0x98, 0x5a, 0x5a, 0x5a, 0xfd, 0xb7, 0x01, 0xef, 0xfe, 0x11, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x03, 0x25, 0x02, 0x4e, 0xfd, 0xb2, 0xfd, 0x44, 0x02, 0x4e, 0xfd, 0xb2, 0x05, 0x0f, 0x64, 0x64, 0xfa, 0x88, 0x64, 0x64, 0x03, 0x25, 0x02, 0x4e, 0xfd, 0xb2, 0x69, 0x64, 0x64, 0xfd, 0xad, 0x02, 0x4e, 0xfd, 0xb2, 0x02, 0xbc, 0x02, 0x4e, 0xfd, 0xb2, 0xfd, 0x44, 0x02, 0x4e, 0xfd, 0xb2, 0x05, 0x0f, 0x64, 0x64, 0xfa, 0x88, 0x64, 0x64, 0x03, 0x25, 0x02, 0x4e, 0xfd, 0xb2, 0x69, 0x64, 0x64, 0xfd, 0xad, 0x02, 0x4e, 0xfd, 0xb2, 0x00, 0x0e, 0x00, 0x87, 0x00, 0x00, 0x06, 0x81, 0x05, 0xdc, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x15, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x01, 0x11, 0x33, 0x11, 0x03, 0x11, 0x33, 0x11, 0x01, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x15, 0x35, 0x21, 0x15, 0x01, 0x11, 0x33, 0x11, 0x06, 0x27, 0x5a, 0x5a, 0x5a, 0xfd, 0xb7, 0x01, 0xef, 0xfe, 0x11, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0xfe, 0x98, 0x5a, 0x5a, 0x5a, 0xfd, 0xb7, 0x01, 0xef, 0xfe, 0x11, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x01, 0xef, 0xfd, 0xb7, 0x5a, 0x03, 0x1b, 0x02, 0x58, 0xfd, 0xa8, 0xfd, 0x44, 0x02, 0x58, 0xfd, 0xa8, 0x05, 0x19, 0x64, 0x64, 0xfa, 0x88, 0x64, 0x64, 0x03, 0x1b, 0x02, 0x58, 0xfd, 0xa8, 0x5f, 0x64, 0x64, 0xfd, 0xa3, 0x02, 0x58, 0xfd, 0xa8, 0x02, 0xbc, 0x02, 0x58, 0xfd, 0xa8, 0xfd, 0x44, 0x02, 0x58, 0xfd, 0xa8, 0x05, 0x19, 0x64, 0x64, 0xfa, 0x88, 0x64, 0x64, 0x03, 0x1b, 0x02, 0x58, 0xfd, 0xa8, 0x5f, 0x64, 0x64, 0xfd, 0xa3, 0x02, 0x58, 0xfd, 0xa8, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xcb, 0x06, 0x9f, 0x00, 0x15, 0x00, 0x00, 0x01, 0x15, 0x10, 0x21, 0x20, 0x11, 0x35, 0x13, 0x33, 0x03, 0x15, 0x10, 0x21, 0x20, 0x11, 0x35, 0x34, 0x00, 0x11, 0x33, 0x16, 0x00, 0x03, 0xca, 0xfe, 0x56, 0xfe, 0x43, 0x35, 0xb4, 0x3e, 0x01, 0x12, 0x01, 0x08, 0xfe, 0x41, 0xa3, 0x01, 0x01, 0xbd, 0x02, 0xa1, 0x9f, 0xfd, 0xe0, 0x02, 0x25, 0x8b, 0x01, 0x09, 0xfe, 0xda, 0x73, 0xfe, 0x80, 0x01, 0x8a, 0xb8, 0xf9, 0x01, 0xcb, 0x01, 0x17, 0xc5, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xcb, 0x06, 0x9f, 0x00, 0x09, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x12, 0x25, 0x04, 0x03, 0x15, 0x10, 0x21, 0x20, 0x11, 0x37, 0x15, 0x10, 0x20, 0x11, 0x35, 0x10, 0x25, 0x33, 0x36, 0x27, 0x26, 0x27, 0x33, 0x14, 0x16, 0x07, 0x33, 0x04, 0x03, 0x28, 0x01, 0xfe, 0xe8, 0xfe, 0xfe, 0x01, 0x01, 0x09, 0x01, 0x11, 0xa2, 0xfc, 0x99, 0x01, 0x6b, 0x12, 0x2e, 0x78, 0x78, 0x02, 0xbb, 0xc4, 0x21, 0x12, 0x01, 0x3c, 0x02, 0x9d, 0x01, 0x67, 0x0b, 0x08, 0xfe, 0x82, 0x55, 0xfe, 0x4e, 0x01, 0xad, 0x4b, 0x37, 0xfd, 0x9f, 0x02, 0x61, 0x3c, 0x01, 0xeb, 0x3d, 0xa3, 0x51, 0x52, 0xb2, 0x6c, 0x9e, 0xf3, 0x45, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x04, 0x1b, 0x06, 0xb3, 0x00, 0x09, 0x00, 0x21, 0x00, 0x00, 0x01, 0x10, 0x21, 0x20, 0x11, 0x15, 0x10, 0x21, 0x20, 0x11, 0x37, 0x15, 0x10, 0x21, 0x20, 0x11, 0x35, 0x10, 0x25, 0x33, 0x36, 0x27, 0x36, 0x23, 0x22, 0x15, 0x23, 0x10, 0x21, 0x20, 0x03, 0x06, 0x07, 0x04, 0x03, 0x70, 0xfe, 0xd8, 0xfe, 0xc6, 0x01, 0x36, 0x01, 0x2c, 0xaa, 0xfe, 0x26, 0xfe, 0x23, 0x01, 0xd3, 0x55, 0x45, 0x02, 0x01, 0xab, 0xa4, 0x93, 0x01, 0x34, 0x01, 0x3a, 0x01, 0x0b, 0x3d, 0x01, 0x08, 0x02, 0x7e, 0x01, 0xa4, 0xfe, 0x62, 0x5f, 0xfe, 0x5d, 0x01, 0xa3, 0x61, 0x57, 0xfd, 0xb3, 0x02, 0x3e, 0x78, 0x01, 0xd6, 0x4e, 0x5c, 0x61, 0x9a, 0xc4, 0x01, 0x64, 0xfe, 0xc1, 0x8b, 0x55, 0x72, 0x00, 0x00, 0x02, 0x00, 0x63, 0x00, 0x00, 0x06, 0x04, 0x06, 0xb3, 0x00, 0x24, 0x00, 0x2e, 0x00, 0x00, 0x37, 0x36, 0x37, 0x00, 0x11, 0x35, 0x10, 0x21, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0x15, 0x10, 0x05, 0x24, 0x11, 0x35, 0x34, 0x37, 0x26, 0x23, 0x22, 0x11, 0x15, 0x10, 0x01, 0x17, 0x04, 0x17, 0x23, 0x26, 0x27, 0x26, 0x07, 0x01, 0x10, 0x23, 0x22, 0x11, 0x15, 0x02, 0x17, 0x36, 0x13, 0xf2, 0x59, 0x73, 0xfe, 0xa5, 0x01, 0x8d, 0x98, 0x8f, 0x5b, 0xe8, 0x01, 0xaa, 0xfe, 0x56, 0xfe, 0x62, 0x23, 0x4b, 0x9c, 0xeb, 0x01, 0x7e, 0xbf, 0x01, 0x5f, 0x33, 0xee, 0x0c, 0xd6, 0xe8, 0xdc, 0x04, 0x11, 0xff, 0xf6, 0x01, 0xf7, 0xfe, 0x01, 0xc3, 0x4e, 0x21, 0x01, 0x56, 0x01, 0xc6, 0x6d, 0x01, 0xf8, 0xb3, 0xa9, 0xfd, 0xff, 0x95, 0xfd, 0xd2, 0x1e, 0x1c, 0x02, 0x30, 0x77, 0x5f, 0x8c, 0x9a, 0xfe, 0xb7, 0x63, 0xfe, 0x2d, 0xfe, 0xb1, 0x18, 0x53, 0xd6, 0x52, 0x40, 0x40, 0xb4, 0x04, 0x5d, 0x01, 0x8f, 0xfe, 0x9e, 0x9a, 0xfe, 0x77, 0x1d, 0x1c, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xcb, 0x06, 0xb3, 0x00, 0x17, 0x00, 0x00, 0x01, 0x10, 0x21, 0x20, 0x1b, 0x01, 0x33, 0x03, 0x10, 0x21, 0x04, 0x19, 0x01, 0x34, 0x23, 0x22, 0x11, 0x17, 0x23, 0x03, 0x10, 0x21, 0x20, 0x11, 0x03, 0xca, 0xfe, 0x47, 0xfe, 0x52, 0x01, 0x51, 0xbb, 0x63, 0x01, 0x0a, 0x01, 0x1a, 0xff, 0xdb, 0x4b, 0xab, 0x3f, 0x01, 0x87, 0x01, 0x8b, 0x01, 0xc8, 0xfe, 0x1a, 0x01, 0xe9, 0x01, 0x2f, 0xfe, 0xd1, 0xfe, 0xb7, 0x01, 0x01, 0x4f, 0x03, 0x73, 0xd1, 0xfe, 0xff, 0xf6, 0x01, 0x0d, 0x01, 0x89, 0xfe, 0x8b, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xcb, 0x06, 0xb3, 0x00, 0x21, 0x00, 0x00, 0x01, 0x06, 0x07, 0x16, 0x1d, 0x01, 0x10, 0x20, 0x11, 0x13, 0x33, 0x03, 0x10, 0x21, 0x20, 0x11, 0x35, 0x34, 0x27, 0x23, 0x35, 0x33, 0x36, 0x03, 0x34, 0x23, 0x06, 0x07, 0x17, 0x23, 0x27, 0x10, 0x21, 0x20, 0x03, 0xa6, 0x04, 0xb9, 0xe1, 0xfc, 0x99, 0x30, 0xb0, 0x36, 0x01, 0x0a, 0x01, 0x11, 0xab, 0x99, 0x52, 0xc6, 0x02, 0xe2, 0xe9, 0x02, 0x21, 0xa8, 0x16, 0x01, 0x88, 0x01, 0x8e, 0x05, 0x1b, 0xe6, 0x7c, 0x73, 0xfe, 0x7d, 0xfe, 0x17, 0x02, 0x01, 0x01, 0x17, 0xfe, 0xe0, 0xfe, 0xa8, 0x01, 0x4e, 0x73, 0xcd, 0x28, 0xa9, 0x50, 0x01, 0x0a, 0xda, 0x01, 0xf5, 0x9a, 0x9e, 0x01, 0x90, 0x00, 0x00, 0x00, 0x03, 0x00, 0x63, 0xff, 0xe2, 0x04, 0x51, 0x06, 0xb3, 0x00, 0x09, 0x00, 0x13, 0x00, 0x26, 0x00, 0x00, 0x01, 0x12, 0x07, 0x22, 0x15, 0x14, 0x17, 0x36, 0x37, 0x33, 0x01, 0x10, 0x21, 0x20, 0x11, 0x15, 0x10, 0x21, 0x20, 0x11, 0x37, 0x15, 0x10, 0x21, 0x20, 0x11, 0x35, 0x34, 0x37, 0x26, 0x35, 0x10, 0x21, 0x20, 0x11, 0x14, 0x07, 0x33, 0x04, 0x02, 0x89, 0x02, 0xc1, 0xbc, 0x5e, 0x5b, 0xad, 0x10, 0x01, 0x1e, 0xfe, 0xe7, 0xfe, 0xd5, 0x01, 0x26, 0x01, 0x1e, 0xae, 0xfe, 0x33, 0xfe, 0x30, 0x5b, 0xab, 0x01, 0x5e, 0x01, 0x69, 0x0b, 0x0a, 0x01, 0x27, 0x04, 0xde, 0x01, 0x36, 0x01, 0xdf, 0xb4, 0x5f, 0x63, 0x09, 0xfd, 0xe5, 0x01, 0x88, 0xfe, 0x76, 0x4b, 0xfe, 0x5d, 0x01, 0x9b, 0x58, 0x4b, 0xfd, 0xb8, 0x02, 0x52, 0x46, 0x8d, 0xbc, 0x94, 0xce, 0x01, 0x8e, 0xfe, 0x2e, 0x25, 0x40, 0x7f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x05, 0xf7, 0x06, 0xb3, 0x00, 0x09, 0x00, 0x22, 0x00, 0x00, 0x01, 0x10, 0x23, 0x22, 0x19, 0x01, 0x10, 0x33, 0x32, 0x11, 0x25, 0x02, 0x03, 0x23, 0x36, 0x13, 0x11, 0x10, 0x23, 0x22, 0x03, 0x11, 0x10, 0x21, 0x20, 0x19, 0x01, 0x10, 0x21, 0x36, 0x17, 0x36, 0x33, 0x20, 0x13, 0x02, 0xf5, 0xf2, 0xf8, 0xf8, 0xf2, 0x03, 0x01, 0x09, 0xb7, 0xef, 0xee, 0x15, 0xda, 0xc2, 0x11, 0xfe, 0x5d, 0xfe, 0x69, 0x01, 0xa0, 0xc9, 0x86, 0x68, 0xde, 0x01, 0x5d, 0x01, 0x04, 0x92, 0x01, 0x82, 0xfe, 0x7e, 0xfd, 0x93, 0xfe, 0x5c, 0x01, 0xa4, 0x9b, 0xfe, 0x46, 0xfe, 0xfa, 0xe5, 0x01, 0xdb, 0x01, 0xd2, 0x01, 0x79, 0xfe, 0xed, 0xfd, 0x2d, 0xfd, 0xbd, 0x02, 0x43, 0x02, 0x6d, 0x02, 0x21, 0x02, 0xe6, 0xda, 0xfd, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x03, 0x9d, 0x06, 0xb3, 0x00, 0x15, 0x00, 0x00, 0x01, 0x10, 0x03, 0x23, 0x12, 0x19, 0x01, 0x10, 0x23, 0x20, 0x19, 0x01, 0x10, 0x13, 0x23, 0x02, 0x19, 0x01, 0x10, 0x21, 0x20, 0x11, 0x03, 0x9c, 0x8b, 0xb2, 0x93, 0xdc, 0xfe, 0xf8, 0x9d, 0xb4, 0x94, 0x01, 0xb3, 0x01, 0x86, 0x02, 0xfb, 0xfe, 0x8a, 0xfe, 0x7b, 0x01, 0x43, 0x01, 0xb8, 0x01, 0x9a, 0x01, 0x7e, 0xfe, 0x82, 0xfe, 0x66, 0xfe, 0x53, 0xfe, 0xb2, 0x01, 0x79, 0x01, 0x82, 0x01, 0x9a, 0x02, 0x1e, 0xfd, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xcb, 0x06, 0xa0, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x02, 0x21, 0x20, 0x11, 0x13, 0x33, 0x03, 0x10, 0x05, 0x20, 0x11, 0x35, 0x10, 0x2b, 0x01, 0x35, 0x33, 0x36, 0x35, 0x34, 0x27, 0x33, 0x16, 0x15, 0x10, 0x07, 0x16, 0x11, 0x03, 0xca, 0x01, 0xfe, 0x4e, 0xfe, 0x4c, 0x27, 0xb9, 0x36, 0x01, 0x0a, 0x01, 0x11, 0xbd, 0xc6, 0x9e, 0xe5, 0xb4, 0xfc, 0x5a, 0xe1, 0xe1, 0x01, 0xc6, 0xfe, 0x1c, 0x01, 0xf3, 0x01, 0x24, 0xfe, 0xdc, 0xfe, 0xae, 0x01, 0x01, 0x44, 0x78, 0x01, 0x3c, 0xa8, 0x81, 0xaf, 0x95, 0xb9, 0xbe, 0x6d, 0xfe, 0xf7, 0x64, 0x63, 0xfe, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x08, 0x07, 0x06, 0xb3, 0x00, 0x35, 0x00, 0x00, 0x25, 0x36, 0x37, 0x24, 0x03, 0x35, 0x10, 0x21, 0x32, 0x17, 0x36, 0x20, 0x17, 0x36, 0x33, 0x20, 0x11, 0x15, 0x14, 0x03, 0x23, 0x12, 0x3d, 0x01, 0x12, 0x23, 0x22, 0x15, 0x11, 0x23, 0x11, 0x10, 0x23, 0x06, 0x15, 0x11, 0x23, 0x11, 0x26, 0x23, 0x22, 0x11, 0x15, 0x12, 0x05, 0x36, 0x17, 0x04, 0x13, 0x21, 0x26, 0x25, 0x24, 0x01, 0x01, 0x3a, 0x68, 0x82, 0xfe, 0x6a, 0x2b, 0x01, 0x8b, 0xd1, 0x65, 0x5a, 0x01, 0x74, 0x62, 0x55, 0xdb, 0x01, 0x83, 0xc9, 0xb8, 0xe2, 0x01, 0xe3, 0xe7, 0x9b, 0xcc, 0xc5, 0x9c, 0x02, 0xe8, 0xdf, 0x28, 0x01, 0x87, 0x6e, 0x81, 0x01, 0xda, 0xf6, 0xfe, 0xef, 0x24, 0xfe, 0xbd, 0xfe, 0xbe, 0xfe, 0xe9, 0xa6, 0x78, 0x43, 0xf3, 0x01, 0xf0, 0x7b, 0x01, 0xeb, 0xb2, 0xbb, 0xbb, 0xb2, 0xfe, 0x1f, 0x67, 0xba, 0xfe, 0x64, 0x01, 0xb1, 0xc8, 0x3f, 0x01, 0x47, 0xe7, 0xfe, 0x5a, 0x01, 0xa6, 0x01, 0x00, 0x02, 0xfe, 0xfe, 0x5a, 0x01, 0xa6, 0xe7, 0xfe, 0xb7, 0x79, 0xfe, 0x41, 0xe9, 0x17, 0x0b, 0x23, 0xfe, 0x76, 0xa5, 0x5c, 0x5b, 0xfe, 0xc3, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xc9, 0x06, 0xb3, 0x00, 0x09, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x11, 0x26, 0x27, 0x20, 0x11, 0x15, 0x10, 0x05, 0x20, 0x13, 0x10, 0x21, 0x20, 0x11, 0x35, 0x10, 0x25, 0x32, 0x17, 0x35, 0x34, 0x21, 0x22, 0x06, 0x15, 0x23, 0x10, 0x21, 0x20, 0x11, 0x03, 0x30, 0x5f, 0xa6, 0xfe, 0xe3, 0x01, 0x1b, 0x01, 0x07, 0x98, 0xfe, 0x61, 0xfe, 0x3a, 0x01, 0xb3, 0x8e, 0x8d, 0xfe, 0xfe, 0x8a, 0x6f, 0xa1, 0x01, 0x8e, 0x01, 0xa5, 0x01, 0xda, 0x01, 0xcb, 0x3f, 0x01, 0xfe, 0xc1, 0xb8, 0xfe, 0x95, 0x01, 0x01, 0x62, 0xfd, 0xfe, 0x02, 0x02, 0xae, 0x01, 0xee, 0x14, 0x4a, 0xd1, 0xf9, 0x71, 0x6c, 0x01, 0x7c, 0xfe, 0x63, 0x00, 0x00, 0x00, 0x02, 0x00, 0x75, 0xff, 0xe2, 0x03, 0xdd, 0x06, 0xa0, 0x00, 0x09, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x10, 0x21, 0x22, 0x07, 0x11, 0x10, 0x21, 0x20, 0x11, 0x37, 0x15, 0x10, 0x21, 0x20, 0x19, 0x01, 0x10, 0x29, 0x01, 0x15, 0x21, 0x22, 0x1d, 0x01, 0x36, 0x33, 0x20, 0x03, 0x3a, 0xfe, 0xe8, 0x97, 0x74, 0x01, 0x16, 0x01, 0x0d, 0xa2, 0xfe, 0x46, 0xfe, 0x53, 0x01, 0x2f, 0x01, 0xd0, 0xfe, 0x35, 0x9b, 0x98, 0x7e, 0x01, 0xb8, 0x02, 0xab, 0x01, 0x4f, 0x4b, 0xfe, 0x26, 0xfe, 0xad, 0x01, 0x44, 0xfe, 0xfa, 0xfe, 0x18, 0x01, 0xe8, 0x03, 0x54, 0x01, 0x82, 0xa0, 0xe6, 0xc7, 0x55, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x05, 0xdf, 0x06, 0xb3, 0x00, 0x20, 0x00, 0x00, 0x01, 0x10, 0x01, 0x23, 0x00, 0x19, 0x01, 0x10, 0x23, 0x22, 0x19, 0x01, 0x23, 0x11, 0x10, 0x23, 0x22, 0x19, 0x01, 0x10, 0x01, 0x23, 0x00, 0x19, 0x01, 0x10, 0x21, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0x05, 0xdf, 0xfe, 0xe6, 0xc9, 0x01, 0x3b, 0xf3, 0xce, 0xa5, 0xef, 0xd3, 0x01, 0x1e, 0xc1, 0xfe, 0xf7, 0x01, 0x91, 0xc8, 0x6c, 0x75, 0xa7, 0x01, 0x9b, 0x02, 0xc2, 0xfe, 0x66, 0xfe, 0xd8, 0x01, 0x6e, 0x01, 0x55, 0x01, 0xcf, 0x01, 0x83, 0xfe, 0xcf, 0xfd, 0x82, 0x02, 0x87, 0x01, 0x28, 0xfe, 0x7d, 0xfe, 0x31, 0xfe, 0xa7, 0xfe, 0x96, 0x01, 0x28, 0x01, 0x9b, 0x01, 0xcf, 0x02, 0x21, 0xf0, 0xf0, 0xfd, 0xdf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xcb, 0x06, 0x9f, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x15, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x21, 0x20, 0x11, 0x35, 0x34, 0x27, 0x23, 0x35, 0x33, 0x36, 0x35, 0x34, 0x24, 0x35, 0x33, 0x14, 0x04, 0x15, 0x14, 0x07, 0x16, 0x03, 0xca, 0xfe, 0x5f, 0xfe, 0x3a, 0x12, 0xb3, 0x1a, 0x01, 0x16, 0x01, 0x04, 0x9e, 0xc4, 0x67, 0xe9, 0xfe, 0x87, 0xc6, 0x01, 0x55, 0xd3, 0xe5, 0x01, 0xd7, 0x25, 0xfe, 0x30, 0x01, 0xdf, 0xb3, 0xb3, 0xfe, 0xc1, 0x01, 0x3f, 0x43, 0xc0, 0x2d, 0xb6, 0x3f, 0xb0, 0xa3, 0x72, 0xf4, 0x96, 0x8e, 0xdd, 0xb2, 0x79, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xca, 0x06, 0xc1, 0x00, 0x16, 0x00, 0x00, 0x01, 0x10, 0x25, 0x20, 0x11, 0x33, 0x10, 0x21, 0x20, 0x19, 0x01, 0x05, 0x04, 0x15, 0x10, 0x25, 0x35, 0x04, 0x27, 0x36, 0x25, 0x35, 0x25, 0x03, 0xc9, 0xfe, 0x49, 0xfe, 0x51, 0xab, 0x01, 0x04, 0x01, 0x14, 0xfe, 0x0f, 0x01, 0x3d, 0xfd, 0xf2, 0x01, 0x78, 0x01, 0x02, 0xfe, 0x87, 0x03, 0x65, 0x01, 0xd1, 0xfe, 0x0f, 0x02, 0x02, 0x4a, 0xfe, 0x56, 0x01, 0x4f, 0x04, 0x3b, 0x32, 0x78, 0xd6, 0xfe, 0x7d, 0x02, 0xb2, 0x02, 0xce, 0xb0, 0x5f, 0xa7, 0x82, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x06, 0x31, 0x06, 0xb3, 0x00, 0x26, 0x00, 0x00, 0x01, 0x15, 0x10, 0x01, 0x23, 0x00, 0x11, 0x35, 0x10, 0x27, 0x22, 0x03, 0x11, 0x23, 0x11, 0x10, 0x23, 0x22, 0x11, 0x15, 0x10, 0x01, 0x23, 0x00, 0x11, 0x35, 0x10, 0x37, 0x36, 0x21, 0x15, 0x24, 0x03, 0x37, 0x32, 0x17, 0x36, 0x33, 0x20, 0x06, 0x31, 0xfe, 0xc5, 0xd7, 0x01, 0x60, 0xeb, 0xf0, 0x01, 0xad, 0xfe, 0xea, 0x01, 0x6c, 0xd4, 0xfe, 0xbd, 0xf8, 0xfa, 0x02, 0x82, 0xfd, 0x41, 0x9f, 0x71, 0xef, 0x7c, 0x69, 0xc6, 0x01, 0xac, 0x03, 0x1e, 0x7c, 0xfe, 0x62, 0xfe, 0xfc, 0x01, 0x62, 0x01, 0x49, 0x8c, 0x01, 0x4b, 0x02, 0xfe, 0xd7, 0xfe, 0xa2, 0x01, 0x5e, 0x01, 0x28, 0xfe, 0xb4, 0x95, 0xfe, 0xc1, 0xfe, 0x9d, 0x01, 0x04, 0x01, 0x9e, 0x77, 0x01, 0xa3, 0xfc, 0xfb, 0xa0, 0x01, 0xfe, 0xd8, 0x34, 0xf4, 0xf4, 0x00, 0x00, 0x01, 0x00, 0x75, 0xff, 0xe2, 0x03, 0xdd, 0x06, 0x9f, 0x00, 0x15, 0x00, 0x00, 0x01, 0x15, 0x10, 0x21, 0x20, 0x19, 0x01, 0x33, 0x11, 0x10, 0x21, 0x20, 0x11, 0x35, 0x34, 0x02, 0x27, 0x37, 0x33, 0x07, 0x14, 0x12, 0x03, 0xdc, 0xfe, 0x46, 0xfe, 0x53, 0xa2, 0x01, 0x0d, 0x01, 0x16, 0xe3, 0x02, 0x28, 0xb4, 0x42, 0xed, 0x02, 0x07, 0x2d, 0xfe, 0x08, 0x02, 0x52, 0x04, 0x6b, 0xfb, 0x6d, 0xfe, 0x76, 0x01, 0x49, 0x4b, 0xb3, 0x01, 0x26, 0x99, 0xd9, 0xe6, 0x7c, 0xfe, 0xfb, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x04, 0xe0, 0x06, 0xb3, 0x00, 0x24, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x07, 0x11, 0x16, 0x12, 0x33, 0x32, 0x12, 0x35, 0x11, 0x34, 0x02, 0x27, 0x23, 0x13, 0x23, 0x13, 0x35, 0x33, 0x15, 0x33, 0x04, 0x12, 0x07, 0x11, 0x16, 0x00, 0x21, 0x20, 0x00, 0x35, 0x11, 0x34, 0x12, 0x37, 0x01, 0xd6, 0x77, 0x4f, 0x02, 0x01, 0xbc, 0xd9, 0xd7, 0xb9, 0xc1, 0x83, 0x11, 0x12, 0xa8, 0x12, 0x84, 0x11, 0x01, 0x0f, 0xe1, 0x01, 0x01, 0xfe, 0xf5, 0xfe, 0xcb, 0xfe, 0xdd, 0xfe, 0xe6, 0xad, 0xc6, 0x05, 0xa7, 0x2f, 0xf0, 0xb3, 0xfe, 0xbd, 0x98, 0xfe, 0x88, 0x01, 0x77, 0x99, 0x01, 0x40, 0xb6, 0x01, 0x44, 0x02, 0xfc, 0xed, 0x03, 0x11, 0xe7, 0x44, 0x5c, 0xfe, 0x75, 0xb1, 0xfe, 0xb6, 0xd1, 0xfe, 0x26, 0x01, 0xd6, 0xd5, 0x01, 0x49, 0xb0, 0x01, 0x8d, 0x52, 0x00, 0x00, 0x01, 0x00, 0x2d, 0xff, 0xe1, 0x03, 0xbd, 0x06, 0xb3, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x12, 0x21, 0x20, 0x03, 0x13, 0x33, 0x03, 0x10, 0x21, 0x20, 0x19, 0x01, 0x26, 0x23, 0x22, 0x17, 0x11, 0x23, 0x11, 0x26, 0x27, 0x23, 0x35, 0x33, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0x03, 0xbd, 0x01, 0xfe, 0x62, 0xfe, 0x3a, 0x04, 0x33, 0xb7, 0x3e, 0x01, 0x22, 0x01, 0x01, 0x01, 0xaf, 0x96, 0x02, 0x8f, 0x12, 0x8f, 0x84, 0x7e, 0x8b, 0x44, 0x5e, 0x99, 0x01, 0x4c, 0x01, 0xee, 0xfd, 0xf3, 0x01, 0xea, 0x01, 0x2e, 0xfe, 0xd7, 0xfe, 0xb2, 0x01, 0x35, 0x03, 0xb4, 0xa9, 0x54, 0xfe, 0x68, 0x01, 0x4d, 0x8c, 0x13, 0x9f, 0x9f, 0x9f, 0xfe, 0x86, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x05, 0xe5, 0x06, 0xb3, 0x00, 0x09, 0x00, 0x37, 0x00, 0x00, 0x01, 0x10, 0x23, 0x22, 0x11, 0x15, 0x10, 0x33, 0x32, 0x11, 0x01, 0x14, 0x00, 0x2b, 0x01, 0x22, 0x24, 0x35, 0x33, 0x14, 0x16, 0x3b, 0x01, 0x32, 0x36, 0x35, 0x10, 0x2b, 0x01, 0x35, 0x37, 0x36, 0x35, 0x10, 0x23, 0x22, 0x07, 0x16, 0x07, 0x15, 0x10, 0x25, 0x04, 0x11, 0x35, 0x10, 0x21, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0x10, 0x07, 0x16, 0x02, 0xf2, 0xf6, 0xee, 0xfa, 0xea, 0x02, 0xe0, 0xfe, 0xdf, 0xfb, 0x5a, 0xbb, 0xfe, 0xd6, 0xb7, 0xc4, 0x75, 0x43, 0xb2, 0xd1, 0x73, 0x6f, 0x35, 0xbf, 0xef, 0x77, 0x64, 0x22, 0x03, 0xfe, 0x75, 0xfe, 0x5a, 0x01, 0x96, 0xe4, 0x62, 0x7e, 0xa8, 0x01, 0x7f, 0xd4, 0xc2, 0x04, 0x9e, 0x01, 0x76, 0xfe, 0x8f, 0x8b, 0xfe, 0x79, 0x01, 0x87, 0xfd, 0xc0, 0xd4, 0xfe, 0xde, 0xd9, 0x81, 0x3b, 0x80, 0xcd, 0x89, 0x01, 0x01, 0x97, 0x02, 0x89, 0xdf, 0x01, 0x35, 0x80, 0x70, 0x94, 0x72, 0xfd, 0xd7, 0x01, 0x01, 0x02, 0x29, 0x8b, 0x02, 0x10, 0xc7, 0xc1, 0xfe, 0x5a, 0xfe, 0xe5, 0x92, 0x7b, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xca, 0x06, 0x9f, 0x00, 0x19, 0x00, 0x00, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x21, 0x20, 0x19, 0x01, 0x02, 0x27, 0x06, 0x07, 0x13, 0x23, 0x27, 0x10, 0x05, 0x32, 0x13, 0x11, 0x33, 0x03, 0xc9, 0xfe, 0x47, 0xfe, 0x53, 0x31, 0xb8, 0x3e, 0x01, 0x04, 0x01, 0x1f, 0xbb, 0xa2, 0xb0, 0x01, 0x3b, 0xa1, 0x36, 0x01, 0x49, 0x9a, 0xc7, 0x98, 0x01, 0xca, 0xfe, 0x18, 0x01, 0xe8, 0xdd, 0xdc, 0xfe, 0xb7, 0x01, 0x4e, 0x02, 0x24, 0x01, 0xb2, 0x02, 0x01, 0xa8, 0xfe, 0xff, 0xf9, 0x01, 0x5e, 0x02, 0xfe, 0xaa, 0x01, 0xa2, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x06, 0x0f, 0x06, 0xb3, 0x00, 0x2a, 0x00, 0x00, 0x37, 0x36, 0x37, 0x00, 0x11, 0x35, 0x10, 0x21, 0x32, 0x13, 0x12, 0x33, 0x20, 0x13, 0x15, 0x06, 0x03, 0x23, 0x12, 0x3d, 0x01, 0x10, 0x23, 0x22, 0x19, 0x01, 0x23, 0x11, 0x10, 0x20, 0x13, 0x15, 0x02, 0x01, 0x16, 0x17, 0x04, 0x17, 0x23, 0x26, 0x27, 0x26, 0x05, 0xe3, 0x6c, 0x8a, 0xfe, 0x8a, 0x01, 0x99, 0xc3, 0x7b, 0x6c, 0xcf, 0x01, 0x99, 0x01, 0x02, 0x9e, 0xce, 0xc1, 0xe9, 0xf4, 0x9a, 0xfe, 0x21, 0x02, 0x01, 0x01, 0x88, 0x6a, 0x4b, 0x01, 0x7a, 0x33, 0xee, 0x03, 0xe3, 0xf6, 0xfe, 0xfc, 0xb1, 0x62, 0x22, 0x01, 0x1c, 0x02, 0x20, 0x4b, 0x01, 0xf7, 0xfe, 0xf9, 0x01, 0x07, 0xfe, 0x20, 0x61, 0xeb, 0xfe, 0x94, 0x01, 0x60, 0xf2, 0x54, 0x01, 0x54, 0xfe, 0x72, 0xfe, 0xc0, 0x01, 0x40, 0x01, 0x8d, 0xfe, 0xa8, 0x6d, 0xfe, 0x4d, 0xfe, 0xad, 0x04, 0x12, 0x70, 0xe1, 0x52, 0x63, 0x45, 0xbe, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xc9, 0x06, 0xa1, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x10, 0x21, 0x20, 0x11, 0x13, 0x33, 0x03, 0x10, 0x21, 0x20, 0x19, 0x01, 0x06, 0x07, 0x04, 0x11, 0x35, 0x34, 0x37, 0x33, 0x06, 0x1d, 0x01, 0x10, 0x17, 0x36, 0x37, 0x11, 0x33, 0x03, 0xc8, 0xfe, 0x4a, 0xfe, 0x51, 0x1b, 0xaf, 0x1f, 0x01, 0x04, 0x01, 0x1f, 0x94, 0x82, 0xfe, 0x63, 0x82, 0xca, 0xa1, 0xe9, 0x94, 0x8b, 0x97, 0x01, 0xc5, 0xfe, 0x1d, 0x01, 0xbb, 0x01, 0x09, 0xfe, 0xf3, 0xfe, 0xe9, 0x01, 0x44, 0x01, 0xf8, 0x63, 0x0b, 0x02, 0x01, 0xb9, 0x28, 0xa9, 0xc9, 0xd4, 0x94, 0x28, 0xfe, 0xda, 0x01, 0x0a, 0x74, 0x02, 0x39, 0x00, 0x00, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xc9, 0x06, 0xb3, 0x00, 0x08, 0x00, 0x23, 0x00, 0x00, 0x01, 0x11, 0x26, 0x23, 0x20, 0x11, 0x15, 0x02, 0x20, 0x13, 0x10, 0x21, 0x20, 0x11, 0x35, 0x12, 0x21, 0x16, 0x17, 0x11, 0x34, 0x23, 0x22, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x23, 0x35, 0x20, 0x17, 0x36, 0x33, 0x20, 0x11, 0x03, 0x31, 0x67, 0xb3, 0xfe, 0xf8, 0x01, 0x02, 0x23, 0x97, 0xfe, 0x60, 0xfe, 0x3b, 0x01, 0x01, 0xb3, 0x7a, 0xa0, 0x9c, 0xa1, 0x94, 0xfd, 0x01, 0x00, 0x30, 0x4d, 0xbe, 0x01, 0x2a, 0x01, 0xcb, 0x01, 0xc6, 0x49, 0xfe, 0x90, 0x72, 0xfe, 0x8a, 0x01, 0x5d, 0xfe, 0x03, 0x02, 0x0c, 0x90, 0x01, 0xf9, 0x02, 0x3d, 0x01, 0x60, 0x7c, 0xb4, 0x3a, 0x3a, 0xb4, 0x9f, 0xc0, 0xc0, 0xfe, 0xb3, 0x00, 0x00, 0x01, 0x00, 0x75, 0x00, 0x00, 0x03, 0xdd, 0x06, 0xb3, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x37, 0x34, 0x23, 0x22, 0x11, 0x15, 0x36, 0x17, 0x04, 0x03, 0x15, 0x10, 0x03, 0x23, 0x12, 0x3d, 0x01, 0x10, 0x05, 0x26, 0x07, 0x11, 0x23, 0x11, 0x02, 0x21, 0x20, 0x13, 0x07, 0x02, 0x4e, 0x0e, 0x95, 0xb0, 0x9d, 0x8b, 0x01, 0x9e, 0x01, 0xad, 0xc6, 0xd1, 0xfe, 0xf8, 0x74, 0xa7, 0xa1, 0x01, 0x01, 0x33, 0x01, 0x59, 0x01, 0x12, 0x05, 0x0e, 0x92, 0x75, 0xfe, 0xe6, 0xe1, 0x68, 0x04, 0x01, 0xfe, 0x3d, 0x5e, 0xfe, 0xfd, 0xfe, 0xa7, 0x01, 0x75, 0xb0, 0xae, 0x01, 0x13, 0x01, 0x01, 0x62, 0xfc, 0x7c, 0x04, 0xf0, 0x01, 0xc3, 0xfe, 0xed, 0x92, 0x00, 0x01, 0x00, 0x64, 0xff, 0xe2, 0x04, 0x4a, 0x06, 0xa0, 0x00, 0x23, 0x00, 0x00, 0x01, 0x16, 0x07, 0x04, 0x11, 0x10, 0x02, 0x20, 0x00, 0x19, 0x01, 0x02, 0x13, 0x33, 0x02, 0x15, 0x11, 0x1a, 0x01, 0x17, 0x32, 0x12, 0x35, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x36, 0x35, 0x34, 0x24, 0x37, 0x33, 0x14, 0x04, 0x04, 0x1c, 0x02, 0xdf, 0x01, 0x0a, 0xff, 0xfe, 0x35, 0xfe, 0xe6, 0x02, 0x67, 0xc1, 0x79, 0x01, 0xb8, 0x9a, 0x9d, 0x9b, 0x03, 0xac, 0xbd, 0x51, 0xee, 0xff, 0x00, 0x01, 0xa5, 0x01, 0x07, 0x05, 0x07, 0xae, 0x8c, 0x7b, 0xfe, 0xf6, 0xfe, 0xe2, 0xfe, 0xb8, 0x01, 0x48, 0x01, 0x70, 0x01, 0x9d, 0x01, 0x2c, 0x01, 0x3d, 0xfe, 0x8b, 0xf4, 0xfe, 0x63, 0xfe, 0xf6, 0xfe, 0xf2, 0x01, 0x01, 0x0f, 0xad, 0xfb, 0xa3, 0x65, 0xc2, 0x81, 0x91, 0x8c, 0x54, 0x88, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xc9, 0x06, 0x9f, 0x00, 0x09, 0x00, 0x15, 0x00, 0x00, 0x01, 0x11, 0x26, 0x23, 0x20, 0x11, 0x15, 0x10, 0x21, 0x20, 0x13, 0x10, 0x21, 0x20, 0x11, 0x35, 0x10, 0x21, 0x36, 0x17, 0x11, 0x33, 0x03, 0x31, 0x6e, 0xb5, 0xff, 0x00, 0x01, 0x00, 0x01, 0x23, 0x97, 0xfe, 0x4f, 0xfe, 0x4c, 0x01, 0xb4, 0x95, 0x85, 0x97, 0x02, 0x07, 0x01, 0xa3, 0x50, 0xfe, 0x70, 0x59, 0xfe, 0x71, 0x01, 0x6c, 0xfd, 0xf4, 0x02, 0x3e, 0x4a, 0x02, 0x3d, 0x01, 0x52, 0x02, 0x49, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x75, 0xff, 0xe2, 0x03, 0xdc, 0x06, 0xb3, 0x00, 0x1a, 0x00, 0x24, 0x00, 0x00, 0x13, 0x10, 0x21, 0x32, 0x17, 0x36, 0x21, 0x15, 0x22, 0x1d, 0x01, 0x23, 0x35, 0x34, 0x23, 0x22, 0x15, 0x11, 0x36, 0x37, 0x20, 0x13, 0x15, 0x10, 0x21, 0x20, 0x13, 0x33, 0x10, 0x33, 0x20, 0x11, 0x35, 0x10, 0x21, 0x22, 0x07, 0x76, 0x01, 0x38, 0xb4, 0x57, 0x21, 0x01, 0x01, 0xfd, 0x93, 0x97, 0x9d, 0x95, 0x7d, 0x01, 0xb1, 0x01, 0xfe, 0x3c, 0xfe, 0x5e, 0x02, 0xa1, 0xfb, 0x01, 0x28, 0xfe, 0xee, 0x7c, 0x95, 0x05, 0x79, 0x01, 0x3a, 0xbd, 0xbd, 0x9f, 0xa0, 0x44, 0x44, 0xa0, 0x9b, 0xfe, 0x9e, 0x55, 0x01, 0xfe, 0x11, 0x77, 0xfd, 0xdb, 0x02, 0x1b, 0xfe, 0x85, 0x01, 0x71, 0x8b, 0x01, 0x52, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xed, 0x06, 0xa0, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x00, 0x01, 0x23, 0x13, 0x33, 0x15, 0x23, 0x13, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x21, 0x20, 0x11, 0x03, 0x23, 0x20, 0x11, 0x10, 0x21, 0x33, 0x27, 0x33, 0x17, 0x33, 0x01, 0x14, 0x3b, 0x01, 0x03, 0x23, 0x22, 0x03, 0xec, 0xc6, 0x38, 0x8e, 0x71, 0x4e, 0xfe, 0x47, 0xfe, 0x53, 0x35, 0xb8, 0x41, 0x01, 0x03, 0x01, 0x16, 0x54, 0xcb, 0xfe, 0x90, 0x01, 0x73, 0x54, 0x21, 0xb4, 0x1f, 0xda, 0xfd, 0x3c, 0xda, 0xc0, 0x3e, 0x7f, 0xdd, 0x05, 0x69, 0xfe, 0xb9, 0x8d, 0xfe, 0x35, 0xfe, 0x18, 0x01, 0xe8, 0xdd, 0xdc, 0xfe, 0xb7, 0x01, 0x4e, 0x01, 0xc5, 0x01, 0x2d, 0x01, 0x36, 0xa8, 0xa8, 0xfe, 0xcf, 0xa5, 0x01, 0x47, 0x00, 0x00, 0x00, 0x02, 0x00, 0x75, 0xff, 0xe2, 0x03, 0xdd, 0x06, 0x9f, 0x00, 0x09, 0x00, 0x15, 0x00, 0x00, 0x01, 0x10, 0x21, 0x06, 0x07, 0x11, 0x10, 0x21, 0x20, 0x11, 0x37, 0x15, 0x10, 0x21, 0x20, 0x19, 0x01, 0x33, 0x11, 0x36, 0x33, 0x04, 0x03, 0x3a, 0xfe, 0xea, 0x92, 0x7a, 0x01, 0x1a, 0x01, 0x08, 0xa2, 0xfe, 0x56, 0xfe, 0x43, 0xa3, 0x91, 0x7b, 0x01, 0xb8, 0x02, 0x8d, 0x01, 0x7f, 0x03, 0x55, 0xfe, 0x58, 0xfe, 0x76, 0x01, 0x80, 0x6e, 0x5f, 0xfd, 0xd1, 0x02, 0x25, 0x04, 0x98, 0xfd, 0xbc, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2d, 0xff, 0xe2, 0x03, 0x8b, 0x06, 0xb3, 0x00, 0x21, 0x00, 0x00, 0x01, 0x07, 0x25, 0x03, 0x04, 0x17, 0x06, 0x04, 0x21, 0x35, 0x32, 0x36, 0x35, 0x26, 0x2f, 0x01, 0x13, 0x25, 0x37, 0x05, 0x37, 0x36, 0x34, 0x26, 0x23, 0x07, 0x35, 0x33, 0x32, 0x17, 0x16, 0x14, 0x0f, 0x01, 0x03, 0x8a, 0x45, 0xfe, 0xc9, 0x82, 0x01, 0x2e, 0x01, 0x01, 0xfe, 0xe8, 0xfe, 0xbd, 0xfb, 0xb5, 0x01, 0xeb, 0x68, 0xd2, 0xfe, 0xa0, 0x48, 0x01, 0x5b, 0x5f, 0x11, 0x43, 0x39, 0x75, 0x8c, 0x77, 0x43, 0x43, 0x1b, 0x65, 0x03, 0xcc, 0x8a, 0xab, 0xfe, 0xeb, 0x6e, 0xdc, 0xc6, 0xe6, 0xa0, 0x7f, 0x7a, 0xc0, 0x28, 0x45, 0x01, 0x95, 0xbe, 0x8c, 0xc5, 0xc2, 0x1c, 0x53, 0x38, 0x13, 0x9b, 0x4b, 0x4a, 0xb2, 0x37, 0xc4, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xca, 0x06, 0xb3, 0x00, 0x26, 0x00, 0x00, 0x01, 0x10, 0x21, 0x20, 0x11, 0x33, 0x10, 0x21, 0x20, 0x11, 0x34, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x35, 0x34, 0x27, 0x23, 0x35, 0x33, 0x32, 0x35, 0x34, 0x21, 0x23, 0x35, 0x33, 0x20, 0x11, 0x14, 0x07, 0x33, 0x16, 0x15, 0x16, 0x07, 0x16, 0x03, 0xc9, 0xfe, 0x49, 0xfe, 0x51, 0xab, 0x01, 0x04, 0x01, 0x0f, 0x8b, 0xd0, 0xbe, 0x8b, 0x8b, 0xd0, 0xd0, 0x76, 0xfe, 0x96, 0x6b, 0x6b, 0x02, 0x15, 0x88, 0x02, 0x98, 0x01, 0x76, 0x87, 0x01, 0x99, 0xfe, 0x49, 0x02, 0x04, 0xfe, 0x9c, 0x01, 0x17, 0xc5, 0xb3, 0x84, 0x79, 0x01, 0xb5, 0x99, 0xb8, 0x9e, 0xfe, 0xaa, 0x9b, 0x61, 0x4e, 0x87, 0x94, 0x47, 0x6e, 0x00, 0x01, 0x00, 0x6c, 0xff, 0xe2, 0x03, 0xd2, 0x06, 0xb2, 0x00, 0x26, 0x00, 0x00, 0x05, 0x20, 0x19, 0x01, 0x33, 0x11, 0x10, 0x21, 0x20, 0x11, 0x34, 0x27, 0x23, 0x35, 0x33, 0x32, 0x37, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x36, 0x35, 0x34, 0x21, 0x35, 0x20, 0x11, 0x06, 0x07, 0x23, 0x16, 0x17, 0x06, 0x07, 0x16, 0x15, 0x10, 0x02, 0x20, 0xfe, 0x4c, 0xa3, 0x01, 0x11, 0x01, 0x0a, 0x76, 0x98, 0x98, 0x61, 0x05, 0x05, 0x76, 0x95, 0x95, 0x64, 0xfe, 0xf5, 0x01, 0xb6, 0x01, 0x8f, 0x02, 0xa4, 0x01, 0x01, 0x9b, 0xac, 0x1e, 0x01, 0xe6, 0x04, 0x4d, 0xfb, 0xb3, 0xfe, 0xba, 0x01, 0x12, 0xe0, 0x02, 0xb1, 0x83, 0x7d, 0xb7, 0x01, 0xb4, 0x81, 0x9e, 0xfe, 0xd2, 0xa5, 0x53, 0x67, 0x7e, 0x80, 0x5c, 0x56, 0xe1, 0xfe, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x63, 0xff, 0x5f, 0x03, 0xcb, 0x06, 0xb3, 0x00, 0x09, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x10, 0x05, 0x24, 0x19, 0x01, 0x10, 0x21, 0x20, 0x11, 0x03, 0x32, 0x37, 0x23, 0x02, 0x19, 0x01, 0x10, 0x21, 0x20, 0x19, 0x01, 0x10, 0x03, 0x16, 0x33, 0x15, 0x22, 0x27, 0x23, 0x06, 0x27, 0x01, 0x0e, 0x01, 0x07, 0x01, 0x0c, 0xfe, 0xf5, 0xfe, 0xf8, 0xab, 0xc3, 0x39, 0x02, 0xfa, 0x01, 0xb2, 0x01, 0xb3, 0xfe, 0x29, 0xd7, 0xaf, 0xfd, 0x13, 0xf7, 0xb1, 0x02, 0xd2, 0xfe, 0x68, 0x78, 0x78, 0x01, 0x98, 0x01, 0xa2, 0x01, 0xa0, 0xfe, 0x60, 0xfb, 0xa9, 0x53, 0x01, 0x04, 0x01, 0x5e, 0x01, 0xa6, 0x02, 0x3b, 0xfd, 0xc1, 0xfe, 0x5e, 0xfe, 0xa2, 0xfe, 0xf8, 0x4f, 0xbe, 0xe6, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xc9, 0x06, 0xb5, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x10, 0x21, 0x20, 0x11, 0x35, 0x33, 0x15, 0x10, 0x21, 0x20, 0x11, 0x35, 0x10, 0x2b, 0x01, 0x35, 0x33, 0x24, 0x11, 0x05, 0x15, 0x23, 0x11, 0x25, 0x10, 0x05, 0x04, 0x11, 0x03, 0xc8, 0xfe, 0x48, 0xfe, 0x55, 0xaa, 0x01, 0x08, 0x01, 0x0a, 0xda, 0xcd, 0x6f, 0x01, 0x38, 0xfd, 0xf0, 0xae, 0x03, 0x65, 0xfe, 0xdb, 0x01, 0x25, 0x01, 0x96, 0xfe, 0x4c, 0x01, 0xd4, 0xd3, 0xdd, 0xfe, 0xd6, 0x01, 0x14, 0x9b, 0x01, 0x1a, 0xa4, 0xad, 0x01, 0x78, 0x17, 0xec, 0x01, 0x8f, 0x15, 0xfd, 0xbf, 0x9e, 0x71, 0xfe, 0xd2, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe2, 0x03, 0xd5, 0x06, 0xb4, 0x00, 0x20, 0x00, 0x00, 0x01, 0x10, 0x21, 0x20, 0x11, 0x35, 0x33, 0x15, 0x10, 0x21, 0x20, 0x11, 0x10, 0x2b, 0x01, 0x35, 0x33, 0x24, 0x03, 0x06, 0x23, 0x04, 0x11, 0x33, 0x14, 0x21, 0x32, 0x37, 0x33, 0x15, 0x02, 0x05, 0x04, 0x03, 0xc9, 0xfe, 0x49, 0xfe, 0x51, 0xac, 0x01, 0x03, 0x01, 0x0f, 0xfa, 0xad, 0x63, 0x01, 0x43, 0x02, 0x96, 0x76, 0xfe, 0x51, 0xab, 0x01, 0x04, 0xc8, 0x70, 0x8b, 0x0a, 0xfe, 0xf3, 0x01, 0x0b, 0x01, 0xc8, 0xfe, 0x1a, 0x01, 0xe6, 0x8e, 0x8e, 0xfe, 0xba, 0x01, 0x46, 0x01, 0x60, 0xad, 0x1e, 0x01, 0xbb, 0x6f, 0x02, 0x01, 0x77, 0xc6, 0xc5, 0xe1, 0xfe, 0x80, 0xa6, 0x9c, 0x00, 0x03, 0x00, 0x63, 0xff, 0xe2, 0x04, 0x48, 0x06, 0xb3, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x25, 0x00, 0x00, 0x01, 0x21, 0x24, 0x11, 0x10, 0x21, 0x20, 0x35, 0x01, 0x10, 0x29, 0x01, 0x11, 0x34, 0x21, 0x20, 0x01, 0x15, 0x10, 0x21, 0x20, 0x11, 0x10, 0x37, 0x23, 0x26, 0x11, 0x10, 0x21, 0x20, 0x11, 0x15, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x03, 0x2a, 0xfe, 0xe6, 0xfe, 0xfe, 0x01, 0x09, 0x01, 0x13, 0xfd, 0xe4, 0x01, 0x02, 0x01, 0x1a, 0xfe, 0xed, 0xfe, 0xf7, 0x02, 0xbb, 0xfe, 0x47, 0xfe, 0x53, 0xf1, 0x01, 0xf0, 0x01, 0xb4, 0x01, 0xb2, 0x7e, 0x7e, 0x7e, 0x02, 0xde, 0x02, 0xfe, 0xce, 0xfe, 0xd4, 0xf4, 0x03, 0x62, 0xfe, 0xba, 0x01, 0x9f, 0xe3, 0xfb, 0xda, 0x78, 0xfe, 0x6c, 0x01, 0xcc, 0x01, 0x21, 0x6a, 0x60, 0x01, 0x3f, 0x01, 0xdb, 0xfe, 0x7e, 0x97, 0xbe, 0xfe, 0xca, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe2, 0x06, 0x7e, 0x06, 0xb4, 0x00, 0x0a, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x11, 0x34, 0x26, 0x23, 0x20, 0x13, 0x11, 0x10, 0x05, 0x20, 0x13, 0x10, 0x21, 0x22, 0x27, 0x15, 0x10, 0x21, 0x35, 0x32, 0x35, 0x11, 0x10, 0x21, 0x22, 0x06, 0x1d, 0x01, 0x10, 0x21, 0x15, 0x20, 0x03, 0x35, 0x10, 0x36, 0x37, 0x32, 0x17, 0x36, 0x33, 0x04, 0x12, 0x15, 0x05, 0xd6, 0x74, 0x96, 0xfe, 0xfc, 0x01, 0x01, 0x03, 0x01, 0x0a, 0xa7, 0xfe, 0x49, 0x73, 0x8b, 0xfe, 0x5e, 0xf8, 0xfe, 0xf8, 0x7d, 0x8a, 0x01, 0x08, 0xfe, 0x4d, 0x01, 0xfc, 0xb7, 0xea, 0x7b, 0x6a, 0xe7, 0x01, 0x0a, 0xa7, 0x03, 0xb5, 0x01, 0x03, 0xc3, 0x9a, 0xfe, 0xd9, 0xfe, 0x6b, 0xfe, 0xd4, 0x01, 0x01, 0x84, 0xfd, 0xdd, 0x87, 0x9e, 0xfe, 0x6c, 0xa0, 0xf4, 0x03, 0x78, 0x01, 0x27, 0x9b, 0xc2, 0xfd, 0xfe, 0xaf, 0xa5, 0x01, 0xf6, 0xfd, 0x01, 0x01, 0xfa, 0x01, 0xd8, 0xd8, 0x01, 0xfe, 0xc4, 0xbf, 0x00, 0x03, 0x00, 0x6d, 0xfe, 0x1e, 0x06, 0x47, 0x06, 0x87, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x23, 0x00, 0x00, 0x01, 0x04, 0x07, 0x03, 0x06, 0x33, 0x32, 0x25, 0x17, 0x24, 0x37, 0x13, 0x36, 0x23, 0x22, 0x05, 0x01, 0x06, 0x05, 0x13, 0x23, 0x03, 0x04, 0x23, 0x22, 0x1b, 0x01, 0x36, 0x25, 0x03, 0x33, 0x13, 0x24, 0x33, 0x32, 0x03, 0x03, 0x3e, 0xfe, 0x2f, 0x18, 0x3b, 0x15, 0x65, 0x66, 0x01, 0x10, 0x9a, 0x01, 0xd0, 0x0d, 0x41, 0x18, 0x80, 0x52, 0xff, 0x00, 0x02, 0x27, 0x1d, 0xfd, 0x8a, 0x54, 0xbb, 0x53, 0xfe, 0xe6, 0x98, 0xbe, 0x26, 0x41, 0x20, 0x02, 0x76, 0x47, 0xab, 0x41, 0x01, 0x16, 0xae, 0xbe, 0x26, 0x03, 0xfc, 0x4e, 0xa8, 0xfe, 0x2c, 0xae, 0xae, 0xae, 0x46, 0x68, 0x01, 0xfa, 0xae, 0x49, 0xfd, 0xa1, 0xe0, 0x28, 0xfd, 0xf4, 0x02, 0x91, 0xaf, 0x01, 0x32, 0x01, 0xf9, 0xfa, 0x3a, 0x02, 0x28, 0xfd, 0x6a, 0x6e, 0xfe, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xfe, 0x28, 0x05, 0x78, 0x06, 0xd3, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x14, 0x00, 0x15, 0x14, 0x07, 0x04, 0x11, 0x02, 0x05, 0x24, 0x03, 0x34, 0x37, 0x27, 0x26, 0x27, 0x06, 0x11, 0x10, 0x05, 0x04, 0x17, 0x23, 0x26, 0x25, 0x06, 0x07, 0x27, 0x36, 0x37, 0x24, 0x11, 0x10, 0x25, 0x26, 0x35, 0x37, 0x17, 0x07, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x26, 0x00, 0x35, 0x01, 0x10, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x12, 0x17, 0x36, 0x03, 0x14, 0x01, 0x34, 0x1b, 0x01, 0x4b, 0x13, 0xfe, 0x99, 0xfe, 0x8c, 0x12, 0x36, 0x3f, 0x60, 0x4c, 0xc7, 0x01, 0x41, 0x01, 0xf4, 0x04, 0xc5, 0x0a, 0xfe, 0xa3, 0x87, 0x68, 0x6e, 0x60, 0x8d, 0xfe, 0xc1, 0x01, 0x1b, 0x21, 0x22, 0x90, 0x15, 0x88, 0x57, 0x64, 0x73, 0x01, 0xfe, 0xce, 0x02, 0x62, 0xd8, 0x1c, 0x18, 0x30, 0x50, 0x3c, 0x09, 0xe7, 0xce, 0x06, 0xd3, 0xa4, 0xfe, 0xe6, 0xab, 0x66, 0x45, 0x14, 0xfe, 0x2c, 0xfe, 0x20, 0x14, 0x14, 0x01, 0xeb, 0x66, 0x8e, 0x0a, 0x09, 0x5c, 0x37, 0xfe, 0xb9, 0xfe, 0xac, 0xad, 0xc0, 0xde, 0xa8, 0x59, 0x03, 0x98, 0x6c, 0x67, 0x2f, 0xe9, 0x01, 0x42, 0x01, 0xbf, 0x38, 0x4d, 0x75, 0xb1, 0x38, 0x79, 0x8e, 0x90, 0x89, 0x8b, 0x7a, 0x01, 0x1b, 0xd4, 0xfb, 0x0e, 0x01, 0x52, 0x05, 0x34, 0x1a, 0x5d, 0xa1, 0xfe, 0x95, 0x0a, 0x0a, 0x00, 0x02, 0x00, 0x5a, 0xff, 0xe2, 0x03, 0x4e, 0x06, 0x1e, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x11, 0x26, 0x24, 0x35, 0x33, 0x16, 0x17, 0x16, 0xc3, 0x02, 0x1b, 0xfd, 0xe5, 0x02, 0x8b, 0xfe, 0x85, 0xfe, 0x87, 0x23, 0x9f, 0x20, 0xda, 0xd7, 0x01, 0xfe, 0xa1, 0xa8, 0x02, 0xab, 0xac, 0x06, 0x1e, 0x94, 0xfc, 0x20, 0xfe, 0x38, 0x01, 0xbe, 0xd0, 0xd0, 0xfe, 0xce, 0x01, 0x3c, 0xdd, 0xfe, 0xdd, 0xad, 0x7e, 0x7e, 0x00, 0x00, 0x03, 0x00, 0x5a, 0xff, 0xe2, 0x03, 0x4e, 0x06, 0x38, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x11, 0x26, 0x24, 0x35, 0x33, 0x16, 0x17, 0x16, 0x02, 0x11, 0xb7, 0xb7, 0xfe, 0xa0, 0xb7, 0xb7, 0x02, 0x9d, 0xfe, 0x85, 0xfe, 0x87, 0x23, 0x9f, 0x20, 0xda, 0xd7, 0x01, 0xfe, 0xa1, 0xa8, 0x02, 0xab, 0xac, 0x06, 0x38, 0xca, 0xca, 0xca, 0xfc, 0x3c, 0xfe, 0x38, 0x01, 0xbe, 0xd0, 0xd0, 0xfe, 0xce, 0x01, 0x3c, 0xdd, 0xfe, 0xdd, 0xad, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x5a, 0xff, 0xe2, 0x03, 0x4e, 0x07, 0x00, 0x00, 0x12, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x11, 0x26, 0x24, 0x35, 0x33, 0x16, 0x17, 0x16, 0x01, 0x21, 0x15, 0x21, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x03, 0x4e, 0xfe, 0x85, 0xfe, 0x87, 0x23, 0x9f, 0x20, 0xda, 0xd7, 0x01, 0xfe, 0xa1, 0xa8, 0x02, 0xab, 0xac, 0xfd, 0x58, 0x02, 0x1b, 0xfd, 0xe5, 0x01, 0x62, 0xb7, 0xb7, 0xfe, 0xa0, 0xb7, 0xb7, 0x01, 0xaa, 0xfe, 0x38, 0x01, 0xbe, 0xd0, 0xd0, 0xfe, 0xce, 0x01, 0x3c, 0xdd, 0xfe, 0xdd, 0xad, 0x7e, 0x7e, 0x02, 0xb6, 0x94, 0x02, 0x25, 0xca, 0xca, 0xca, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xff, 0xe2, 0x03, 0x4e, 0x06, 0x8c, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x01, 0x33, 0x03, 0x23, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x11, 0x26, 0x24, 0x35, 0x33, 0x16, 0x17, 0x16, 0x01, 0xf0, 0xd3, 0xe8, 0x9b, 0x02, 0x0e, 0xfe, 0x85, 0xfe, 0x87, 0x23, 0x9f, 0x20, 0xda, 0xd7, 0x01, 0xfe, 0xa1, 0xa8, 0x02, 0xab, 0xac, 0x06, 0x8c, 0xfe, 0xf8, 0xfc, 0x26, 0xfe, 0x38, 0x01, 0xbe, 0xd0, 0xd0, 0xfe, 0xce, 0x01, 0x3c, 0xdd, 0xfe, 0xdd, 0xad, 0x7e, 0x7e, 0x00, 0x03, 0x00, 0x5a, 0xff, 0xe2, 0x03, 0x4e, 0x07, 0x18, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x33, 0x03, 0x23, 0x07, 0x21, 0x15, 0x21, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x11, 0x26, 0x24, 0x35, 0x33, 0x16, 0x17, 0x16, 0x01, 0xf0, 0xa6, 0xcd, 0x89, 0x88, 0x02, 0x1b, 0xfd, 0xe5, 0x02, 0x96, 0xfe, 0x85, 0xfe, 0x87, 0x23, 0x9f, 0x20, 0xda, 0xd7, 0x01, 0xfe, 0xa1, 0xa8, 0x02, 0xab, 0xac, 0x07, 0x18, 0xfe, 0xf8, 0x79, 0x94, 0xfc, 0xa7, 0xfe, 0x38, 0x01, 0xbe, 0xd0, 0xd0, 0xfe, 0xce, 0x01, 0x3c, 0xdd, 0xfe, 0xdd, 0xad, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xff, 0xe2, 0x03, 0x4e, 0x06, 0x79, 0x00, 0x08, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x02, 0x20, 0x03, 0x33, 0x16, 0x33, 0x32, 0x37, 0x13, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x11, 0x26, 0x24, 0x35, 0x33, 0x16, 0x17, 0x16, 0x02, 0xd7, 0x11, 0xfd, 0xef, 0x11, 0x6a, 0x16, 0x9a, 0x9a, 0x15, 0xe1, 0xfe, 0x85, 0xfe, 0x87, 0x23, 0x9f, 0x20, 0xda, 0xd7, 0x01, 0xfe, 0xa1, 0xa8, 0x02, 0xab, 0xac, 0x06, 0x79, 0xfe, 0xe1, 0x01, 0x1f, 0x96, 0x96, 0xfb, 0x31, 0xfe, 0x38, 0x01, 0xbe, 0xd0, 0xd0, 0xfe, 0xce, 0x01, 0x3c, 0xdd, 0xfe, 0xdd, 0xad, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xfe, 0x1d, 0x03, 0x3c, 0x06, 0x1e, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x10, 0x23, 0x22, 0x15, 0x17, 0x23, 0x27, 0x10, 0x21, 0x20, 0x11, 0xf0, 0x02, 0x1a, 0xfd, 0xe6, 0x02, 0x4c, 0xfe, 0x9c, 0xfe, 0x82, 0x1e, 0x9a, 0x16, 0xdc, 0xcb, 0xcb, 0xb4, 0x32, 0x9b, 0x2c, 0x01, 0x49, 0x01, 0x64, 0x06, 0x1e, 0x94, 0xfa, 0x37, 0xfe, 0x5c, 0x01, 0xa6, 0xe1, 0xe3, 0xfe, 0xe8, 0x01, 0x16, 0x03, 0x13, 0x01, 0x02, 0xf4, 0xe2, 0xdc, 0x01, 0x86, 0xfe, 0x6f, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xfe, 0x1d, 0x03, 0x3c, 0x06, 0x64, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x33, 0x03, 0x23, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x10, 0x23, 0x22, 0x15, 0x17, 0x23, 0x27, 0x10, 0x21, 0x20, 0x11, 0x02, 0x2f, 0xd3, 0xe8, 0x9c, 0x01, 0xbe, 0xfe, 0x9c, 0xfe, 0x82, 0x1e, 0x9a, 0x16, 0xdc, 0xcb, 0xcb, 0xb4, 0x32, 0x9b, 0x2c, 0x01, 0x49, 0x01, 0x64, 0x06, 0x64, 0xfe, 0xf8, 0xfa, 0x65, 0xfe, 0x5c, 0x01, 0xa6, 0xe1, 0xe3, 0xfe, 0xe8, 0x01, 0x16, 0x03, 0x13, 0x01, 0x02, 0xf4, 0xe2, 0xdc, 0x01, 0x86, 0xfe, 0x6f, 0x00, 0x03, 0x00, 0x5a, 0xfe, 0x1d, 0x03, 0x3c, 0x07, 0x36, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x33, 0x03, 0x23, 0x07, 0x21, 0x15, 0x21, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x10, 0x23, 0x22, 0x15, 0x17, 0x23, 0x27, 0x10, 0x21, 0x20, 0x11, 0x02, 0x1d, 0xc1, 0xcd, 0xa5, 0x86, 0x02, 0x1a, 0xfd, 0xe6, 0x02, 0x56, 0xfe, 0x9c, 0xfe, 0x82, 0x1e, 0x9a, 0x16, 0xdc, 0xcb, 0xcb, 0xb4, 0x32, 0x9b, 0x2c, 0x01, 0x49, 0x01, 0x64, 0x07, 0x36, 0xfe, 0xf8, 0x79, 0x94, 0xfa, 0xa0, 0xfe, 0x5c, 0x01, 0xa6, 0xe1, 0xe3, 0xfe, 0xe8, 0x01, 0x16, 0x03, 0x13, 0x01, 0x02, 0xf4, 0xe2, 0xdc, 0x01, 0x86, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xfe, 0x1d, 0x03, 0x3c, 0x06, 0x79, 0x00, 0x08, 0x00, 0x20, 0x00, 0x00, 0x01, 0x02, 0x20, 0x03, 0x33, 0x16, 0x33, 0x32, 0x37, 0x13, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x10, 0x23, 0x22, 0x15, 0x17, 0x23, 0x27, 0x10, 0x21, 0x20, 0x11, 0x02, 0xfb, 0x11, 0xfd, 0xef, 0x11, 0x6a, 0x16, 0x9a, 0x9a, 0x15, 0xab, 0xfe, 0x9c, 0xfe, 0x82, 0x1e, 0x9a, 0x16, 0xdc, 0xcb, 0xcb, 0xb4, 0x32, 0x9b, 0x2c, 0x01, 0x49, 0x01, 0x64, 0x06, 0x79, 0xfe, 0xe1, 0x01, 0x1f, 0x96, 0x96, 0xf9, 0x48, 0xfe, 0x5c, 0x01, 0xa6, 0xe1, 0xe3, 0xfe, 0xe8, 0x01, 0x16, 0x03, 0x13, 0x01, 0x02, 0xf4, 0xe2, 0xdc, 0x01, 0x86, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x60, 0x06, 0x1e, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x01, 0x10, 0x03, 0x23, 0x12, 0x11, 0x10, 0x23, 0x22, 0x11, 0x10, 0x13, 0x23, 0x02, 0x11, 0x10, 0x21, 0x20, 0x01, 0x21, 0x15, 0x21, 0x03, 0x60, 0x8a, 0x9b, 0x83, 0xdd, 0xe5, 0x82, 0x9c, 0x88, 0x01, 0x87, 0x01, 0x7f, 0xfd, 0x7e, 0x02, 0x1a, 0xfd, 0xe6, 0x02, 0x44, 0xfe, 0xf4, 0xfe, 0xc8, 0x01, 0x21, 0x01, 0x23, 0x01, 0x90, 0xfe, 0x6d, 0xfe, 0xe0, 0xfe, 0xdf, 0x01, 0x3a, 0x01, 0x0d, 0x02, 0x19, 0x01, 0xbe, 0x94, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x60, 0x06, 0x64, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x01, 0x10, 0x03, 0x23, 0x12, 0x11, 0x10, 0x23, 0x22, 0x11, 0x10, 0x13, 0x23, 0x02, 0x11, 0x10, 0x21, 0x20, 0x01, 0x33, 0x03, 0x23, 0x03, 0x60, 0x8a, 0x9b, 0x83, 0xdd, 0xe5, 0x82, 0x9c, 0x88, 0x01, 0x87, 0x01, 0x7f, 0xfe, 0xd8, 0xca, 0xe8, 0x92, 0x02, 0x44, 0xfe, 0xf4, 0xfe, 0xc9, 0x01, 0x20, 0x01, 0x23, 0x01, 0x90, 0xfe, 0x6d, 0xfe, 0xe0, 0xfe, 0xdf, 0x01, 0x3a, 0x01, 0x0d, 0x02, 0x19, 0x02, 0x04, 0xfe, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x60, 0x06, 0x79, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x10, 0x03, 0x23, 0x12, 0x11, 0x10, 0x23, 0x22, 0x11, 0x10, 0x13, 0x23, 0x02, 0x11, 0x10, 0x21, 0x20, 0x03, 0x02, 0x20, 0x03, 0x33, 0x16, 0x33, 0x32, 0x37, 0x03, 0x60, 0x8a, 0x9b, 0x83, 0xdd, 0xe5, 0x82, 0x9c, 0x88, 0x01, 0x87, 0x01, 0x7f, 0x65, 0x11, 0xfd, 0xef, 0x11, 0x6a, 0x16, 0x9a, 0x9a, 0x15, 0x02, 0x44, 0xfe, 0xf4, 0xfe, 0xc9, 0x01, 0x20, 0x01, 0x23, 0x01, 0x90, 0xfe, 0x6d, 0xfe, 0xe0, 0xfe, 0xdf, 0x01, 0x3a, 0x01, 0x0d, 0x02, 0x19, 0x02, 0x19, 0xfe, 0xe1, 0x01, 0x1f, 0x96, 0x96, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xff, 0xff, 0x05, 0x4f, 0x06, 0x1e, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x12, 0x03, 0x23, 0x00, 0x11, 0x02, 0x23, 0x22, 0x11, 0x15, 0x23, 0x35, 0x10, 0x23, 0x22, 0x11, 0x02, 0x01, 0x23, 0x02, 0x11, 0x10, 0x21, 0x32, 0x17, 0x36, 0x33, 0x20, 0x01, 0x21, 0x15, 0x21, 0x05, 0x4f, 0x01, 0xf8, 0xbc, 0x01, 0x11, 0x01, 0xbd, 0xd0, 0x95, 0xd0, 0xbe, 0x01, 0x01, 0x19, 0xbc, 0xfe, 0x01, 0x61, 0xca, 0x4f, 0x58, 0xc6, 0x01, 0x5e, 0xfc, 0x78, 0x02, 0x1a, 0xfd, 0xe6, 0x02, 0x56, 0xfe, 0xd1, 0xfe, 0xd9, 0x01, 0x16, 0x01, 0x40, 0x01, 0x7e, 0xfe, 0xa7, 0xd2, 0xd2, 0x01, 0x59, 0xfe, 0x82, 0xfe, 0xcd, 0xfe, 0xdc, 0x01, 0x24, 0x01, 0x33, 0x02, 0x0a, 0xe3, 0xe3, 0x01, 0xbe, 0x94, 0x00, 0x03, 0x00, 0x5a, 0xff, 0xff, 0x05, 0x4f, 0x06, 0x38, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x00, 0x01, 0x12, 0x03, 0x23, 0x00, 0x11, 0x02, 0x23, 0x22, 0x11, 0x15, 0x23, 0x35, 0x10, 0x23, 0x22, 0x11, 0x02, 0x01, 0x23, 0x02, 0x11, 0x10, 0x21, 0x32, 0x17, 0x36, 0x33, 0x20, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x05, 0x4f, 0x01, 0xf8, 0xbc, 0x01, 0x11, 0x01, 0xbd, 0xd0, 0x95, 0xd0, 0xbe, 0x01, 0x01, 0x19, 0xbc, 0xfe, 0x01, 0x61, 0xca, 0x4f, 0x58, 0xc6, 0x01, 0x5e, 0xfd, 0xd8, 0xb7, 0xb7, 0xfe, 0xa0, 0xb7, 0xb7, 0x02, 0x56, 0xfe, 0xd1, 0xfe, 0xd9, 0x01, 0x16, 0x01, 0x40, 0x01, 0x7e, 0xfe, 0xa7, 0xd2, 0xd2, 0x01, 0x59, 0xfe, 0x82, 0xfe, 0xcd, 0xfe, 0xdc, 0x01, 0x24, 0x01, 0x33, 0x02, 0x0a, 0xe3, 0xe3, 0x01, 0xd8, 0xca, 0xca, 0xca, 0x00, 0x00, 0x00, 0x04, 0x00, 0x5a, 0xff, 0xff, 0x05, 0x4f, 0x07, 0x28, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x00, 0x01, 0x12, 0x03, 0x23, 0x00, 0x11, 0x02, 0x23, 0x22, 0x11, 0x15, 0x23, 0x35, 0x10, 0x23, 0x22, 0x11, 0x02, 0x01, 0x23, 0x02, 0x11, 0x10, 0x21, 0x32, 0x17, 0x36, 0x33, 0x20, 0x01, 0x21, 0x15, 0x21, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x05, 0x4f, 0x01, 0xf8, 0xbc, 0x01, 0x11, 0x01, 0xbd, 0xd0, 0x95, 0xd0, 0xbe, 0x01, 0x01, 0x19, 0xbc, 0xfe, 0x01, 0x61, 0xca, 0x4f, 0x58, 0xc6, 0x01, 0x5e, 0xfc, 0x76, 0x02, 0x1b, 0xfd, 0xe5, 0x01, 0x62, 0xb7, 0xb7, 0xfe, 0xa0, 0xb7, 0xb7, 0x02, 0x56, 0xfe, 0xd1, 0xfe, 0xd9, 0x01, 0x16, 0x01, 0x40, 0x01, 0x7e, 0xfe, 0xa7, 0xd2, 0xd2, 0x01, 0x59, 0xfe, 0x82, 0xfe, 0xcd, 0xfe, 0xdc, 0x01, 0x24, 0x01, 0x33, 0x02, 0x0a, 0xe3, 0xe3, 0x01, 0x37, 0x94, 0x02, 0x25, 0xca, 0xca, 0xca, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xff, 0xff, 0x05, 0x4f, 0x06, 0x64, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x12, 0x03, 0x23, 0x00, 0x11, 0x02, 0x23, 0x22, 0x11, 0x15, 0x23, 0x35, 0x10, 0x23, 0x22, 0x11, 0x02, 0x01, 0x23, 0x02, 0x11, 0x10, 0x21, 0x32, 0x17, 0x36, 0x33, 0x20, 0x01, 0x33, 0x03, 0x23, 0x05, 0x4f, 0x01, 0xf8, 0xbc, 0x01, 0x11, 0x01, 0xbd, 0xd0, 0x95, 0xd0, 0xbe, 0x01, 0x01, 0x19, 0xbc, 0xfe, 0x01, 0x61, 0xca, 0x4f, 0x58, 0xc6, 0x01, 0x5e, 0xfd, 0xb7, 0xca, 0xe8, 0x93, 0x02, 0x56, 0xfe, 0xd1, 0xfe, 0xd9, 0x01, 0x16, 0x01, 0x40, 0x01, 0x7e, 0xfe, 0xa7, 0xd2, 0xd2, 0x01, 0x59, 0xfe, 0x82, 0xfe, 0xcd, 0xfe, 0xdc, 0x01, 0x24, 0x01, 0x33, 0x02, 0x0a, 0xe3, 0xe3, 0x02, 0x04, 0xfe, 0xf8, 0x00, 0x02, 0x00, 0x5a, 0xff, 0xff, 0x05, 0x4f, 0x06, 0x79, 0x00, 0x1c, 0x00, 0x25, 0x00, 0x00, 0x01, 0x12, 0x03, 0x23, 0x00, 0x11, 0x02, 0x23, 0x22, 0x11, 0x15, 0x23, 0x35, 0x10, 0x23, 0x22, 0x11, 0x02, 0x01, 0x23, 0x02, 0x11, 0x10, 0x21, 0x32, 0x17, 0x36, 0x33, 0x20, 0x01, 0x02, 0x20, 0x03, 0x33, 0x16, 0x33, 0x32, 0x37, 0x05, 0x4f, 0x01, 0xf8, 0xbc, 0x01, 0x11, 0x01, 0xbd, 0xd0, 0x95, 0xd0, 0xbe, 0x01, 0x01, 0x19, 0xbc, 0xfe, 0x01, 0x61, 0xca, 0x4f, 0x58, 0xc6, 0x01, 0x5e, 0xfe, 0xb0, 0x11, 0xfd, 0xef, 0x11, 0x6a, 0x17, 0x98, 0x9b, 0x15, 0x02, 0x56, 0xfe, 0xd1, 0xfe, 0xd9, 0x01, 0x16, 0x01, 0x40, 0x01, 0x7e, 0xfe, 0xa7, 0xd2, 0xd2, 0x01, 0x59, 0xfe, 0x82, 0xfe, 0xcd, 0xfe, 0xdc, 0x01, 0x24, 0x01, 0x33, 0x02, 0x0a, 0xe3, 0xe3, 0x02, 0x19, 0xfe, 0xe1, 0x01, 0x1f, 0x96, 0x96, 0x00, 0x00, 0x02, 0x00, 0x36, 0xfe, 0x1d, 0x03, 0x84, 0x06, 0x1e, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x26, 0x23, 0x22, 0x15, 0x03, 0x23, 0x03, 0x34, 0x2b, 0x01, 0x27, 0x37, 0x17, 0x33, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0xd5, 0x02, 0x1b, 0xfd, 0xe5, 0x02, 0xaf, 0xfe, 0x96, 0xfe, 0x73, 0x17, 0xa0, 0x15, 0xeb, 0xd1, 0x02, 0x79, 0x6f, 0x09, 0x81, 0x09, 0x8c, 0x4a, 0x62, 0x12, 0x4e, 0x48, 0x81, 0x47, 0x3c, 0x90, 0x01, 0x12, 0x06, 0x1e, 0x94, 0xfa, 0x36, 0xfe, 0x5d, 0x01, 0xa3, 0xe3, 0xe3, 0xfe, 0xe9, 0x01, 0x17, 0x03, 0x67, 0xb6, 0x8c, 0xfe, 0xa5, 0x01, 0x5b, 0x78, 0x28, 0xa1, 0x32, 0xbb, 0xbb, 0xfe, 0xc7, 0x00, 0x00, 0x00, 0x03, 0x00, 0x36, 0xfe, 0x1d, 0x03, 0x84, 0x06, 0x38, 0x00, 0x03, 0x00, 0x07, 0x00, 0x28, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x26, 0x23, 0x22, 0x15, 0x03, 0x23, 0x03, 0x34, 0x2b, 0x01, 0x27, 0x37, 0x17, 0x33, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0x02, 0x35, 0xb7, 0xb7, 0xfe, 0xa0, 0xb7, 0xb7, 0x02, 0xaf, 0xfe, 0x96, 0xfe, 0x73, 0x17, 0xa0, 0x15, 0xeb, 0xd1, 0x02, 0x79, 0x6f, 0x09, 0x81, 0x09, 0x8c, 0x4a, 0x62, 0x12, 0x4e, 0x48, 0x81, 0x47, 0x3c, 0x90, 0x01, 0x12, 0x06, 0x38, 0xca, 0xca, 0xca, 0xfa, 0x52, 0xfe, 0x5d, 0x01, 0xa3, 0xe3, 0xe3, 0xfe, 0xe9, 0x01, 0x17, 0x03, 0x67, 0xb6, 0x8c, 0xfe, 0xa5, 0x01, 0x5b, 0x78, 0x28, 0xa1, 0x32, 0xbb, 0xbb, 0xfe, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x36, 0xfe, 0x1d, 0x03, 0x84, 0x07, 0x3c, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x2c, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x26, 0x23, 0x22, 0x15, 0x03, 0x23, 0x03, 0x34, 0x2b, 0x01, 0x27, 0x37, 0x17, 0x33, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0xd4, 0x02, 0x1a, 0xfd, 0xe6, 0x01, 0x61, 0xb7, 0xb7, 0xfe, 0xa0, 0xb7, 0xb7, 0x02, 0xaf, 0xfe, 0x96, 0xfe, 0x73, 0x17, 0xa0, 0x15, 0xeb, 0xd1, 0x02, 0x79, 0x6f, 0x09, 0x81, 0x09, 0x8c, 0x4a, 0x62, 0x12, 0x4e, 0x48, 0x81, 0x47, 0x3c, 0x90, 0x01, 0x12, 0x05, 0xab, 0x94, 0x02, 0x25, 0xca, 0xca, 0xca, 0xf9, 0x4e, 0xfe, 0x5d, 0x01, 0xa3, 0xe3, 0xe3, 0xfe, 0xe9, 0x01, 0x17, 0x03, 0x67, 0xb6, 0x8c, 0xfe, 0xa5, 0x01, 0x5b, 0x78, 0x28, 0xa1, 0x32, 0xbb, 0xbb, 0xfe, 0xc7, 0x00, 0x00, 0x02, 0x00, 0x36, 0xfe, 0x1d, 0x03, 0x84, 0x06, 0x64, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x01, 0x33, 0x03, 0x23, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x26, 0x23, 0x22, 0x15, 0x03, 0x23, 0x03, 0x34, 0x2b, 0x01, 0x27, 0x37, 0x17, 0x33, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0x02, 0x1d, 0xc1, 0xdf, 0x93, 0x02, 0x18, 0xfe, 0x96, 0xfe, 0x73, 0x17, 0xa0, 0x15, 0xeb, 0xd1, 0x02, 0x79, 0x6f, 0x09, 0x81, 0x09, 0x8c, 0x4a, 0x62, 0x12, 0x4e, 0x48, 0x81, 0x47, 0x3c, 0x90, 0x01, 0x12, 0x06, 0x64, 0xfe, 0xf8, 0xfa, 0x64, 0xfe, 0x5d, 0x01, 0xa3, 0xe3, 0xe3, 0xfe, 0xe9, 0x01, 0x17, 0x03, 0x67, 0xb6, 0x8c, 0xfe, 0xa5, 0x01, 0x5b, 0x78, 0x28, 0xa1, 0x32, 0xbb, 0xbb, 0xfe, 0xc7, 0x00, 0x00, 0x02, 0x00, 0x36, 0xfe, 0x1d, 0x03, 0x84, 0x06, 0x79, 0x00, 0x08, 0x00, 0x29, 0x00, 0x00, 0x01, 0x02, 0x20, 0x03, 0x33, 0x16, 0x33, 0x32, 0x37, 0x13, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x26, 0x23, 0x22, 0x15, 0x03, 0x23, 0x03, 0x34, 0x2b, 0x01, 0x27, 0x37, 0x17, 0x33, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0x02, 0xf2, 0x11, 0xfd, 0xef, 0x11, 0x6a, 0x17, 0x98, 0x9b, 0x15, 0xfc, 0xfe, 0x96, 0xfe, 0x73, 0x17, 0xa0, 0x15, 0xeb, 0xd1, 0x02, 0x79, 0x6f, 0x09, 0x81, 0x09, 0x8c, 0x4a, 0x62, 0x12, 0x4e, 0x48, 0x81, 0x47, 0x3c, 0x90, 0x01, 0x12, 0x06, 0x79, 0xfe, 0xe1, 0x01, 0x1f, 0x96, 0x96, 0xf9, 0x47, 0xfe, 0x5d, 0x01, 0xa3, 0xe3, 0xe3, 0xfe, 0xe9, 0x01, 0x17, 0x03, 0x67, 0xb6, 0x8c, 0xfe, 0xa5, 0x01, 0x5b, 0x78, 0x28, 0xa1, 0x32, 0xbb, 0xbb, 0xfe, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x36, 0xfe, 0x1d, 0x03, 0x84, 0x06, 0xd1, 0x00, 0x06, 0x00, 0x27, 0x00, 0x00, 0x01, 0x13, 0x23, 0x27, 0x07, 0x23, 0x13, 0x01, 0x10, 0x21, 0x20, 0x11, 0x37, 0x33, 0x07, 0x10, 0x33, 0x32, 0x19, 0x01, 0x26, 0x23, 0x22, 0x15, 0x03, 0x23, 0x03, 0x34, 0x2b, 0x01, 0x27, 0x37, 0x17, 0x33, 0x32, 0x17, 0x36, 0x33, 0x20, 0x11, 0x02, 0x1c, 0xdc, 0x7d, 0xa2, 0xa2, 0x7d, 0xdd, 0x01, 0xed, 0xfe, 0x96, 0xfe, 0x73, 0x17, 0xa0, 0x15, 0xeb, 0xd1, 0x02, 0x79, 0x6f, 0x09, 0x81, 0x09, 0x8c, 0x4a, 0x62, 0x12, 0x4e, 0x48, 0x81, 0x47, 0x3c, 0x90, 0x01, 0x12, 0x06, 0xd1, 0xfe, 0x88, 0xf5, 0xf5, 0x01, 0x78, 0xf8, 0xef, 0xfe, 0x5d, 0x01, 0xa3, 0xe3, 0xe3, 0xfe, 0xe9, 0x01, 0x17, 0x03, 0x67, 0xb6, 0x8c, 0xfe, 0xa5, 0x01, 0x5b, 0x78, 0x28, 0xa1, 0x32, 0xbb, 0xbb, 0xfe, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x06, 0x14, 0x00, 0x09, 0x00, 0x20, 0x00, 0x00, 0x01, 0x22, 0x06, 0x10, 0x16, 0x20, 0x36, 0x35, 0x34, 0x26, 0x01, 0x10, 0x37, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x21, 0x15, 0x21, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x12, 0x10, 0x02, 0x20, 0x02, 0x02, 0x33, 0x84, 0x9b, 0x9a, 0x01, 0x0b, 0x9a, 0x9a, 0xfd, 0xad, 0xaf, 0x47, 0x3a, 0xae, 0x8e, 0x01, 0xca, 0xfe, 0x57, 0xa9, 0x69, 0x83, 0xd6, 0xf9, 0xf8, 0xfe, 0x50, 0xf5, 0x03, 0xdf, 0xe7, 0xfe, 0x6e, 0xe7, 0xe8, 0xc7, 0xc8, 0xe9, 0xfe, 0x50, 0x01, 0x4d, 0x9b, 0x2f, 0x8d, 0x31, 0x7c, 0x94, 0x93, 0x89, 0x49, 0x34, 0xfe, 0xc8, 0xfd, 0xda, 0xfe, 0xc6, 0x01, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x05, 0x19, 0x06, 0x14, 0x00, 0x24, 0x00, 0x00, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x21, 0x35, 0x34, 0x36, 0x33, 0x05, 0x19, 0x9e, 0x59, 0x46, 0x01, 0x11, 0xfe, 0xef, 0xa6, 0xfe, 0x39, 0xa6, 0x9f, 0x9f, 0x9c, 0xaa, 0x9d, 0x9e, 0x5a, 0x22, 0x23, 0x01, 0xc7, 0x9c, 0xaa, 0x06, 0x14, 0x99, 0x50, 0x68, 0x63, 0x8f, 0xfc, 0x2f, 0x03, 0xd1, 0xfc, 0x2f, 0x03, 0xd1, 0x8f, 0x4e, 0xbb, 0xab, 0x99, 0x28, 0x28, 0x68, 0x63, 0x4e, 0xbb, 0xab, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x00, 0x03, 0xdd, 0x06, 0x14, 0x00, 0x15, 0x00, 0x19, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x01, 0x33, 0x15, 0x23, 0x03, 0xdc, 0xa6, 0xfe, 0x39, 0xa6, 0x9f, 0x9f, 0x9b, 0xa2, 0xa6, 0x9e, 0x5a, 0x45, 0x01, 0xc7, 0xa6, 0xa6, 0x04, 0x60, 0xfb, 0xa0, 0x03, 0xd1, 0xfc, 0x2f, 0x03, 0xd1, 0x8f, 0x4e, 0xb7, 0xaf, 0x99, 0x50, 0x68, 0x63, 0x01, 0xb2, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x03, 0xdd, 0x06, 0x14, 0x00, 0x15, 0x00, 0x00, 0x01, 0x21, 0x11, 0x23, 0x11, 0x21, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x02, 0x0f, 0x01, 0xcd, 0xa6, 0xfe, 0xd8, 0x5a, 0x45, 0x01, 0x11, 0xfe, 0xef, 0xa6, 0x9f, 0x9f, 0x9c, 0x06, 0x14, 0xf9, 0xec, 0x05, 0x7b, 0x50, 0x68, 0x63, 0x8f, 0xfc, 0x2f, 0x03, 0xd1, 0x8f, 0x4e, 0xbb, 0xab, 0x00, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x00, 0x06, 0x4a, 0x06, 0x14, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x21, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x33, 0x05, 0x33, 0x15, 0x23, 0x02, 0xac, 0x9e, 0x5a, 0x22, 0x23, 0x01, 0xc7, 0x4e, 0x19, 0x23, 0x47, 0x75, 0x9d, 0x9e, 0x59, 0x46, 0x02, 0x6d, 0xa6, 0xfe, 0x39, 0xa6, 0xfe, 0x39, 0xa6, 0x9f, 0x9f, 0x9c, 0xaa, 0x03, 0x94, 0xa6, 0xa6, 0x06, 0x14, 0x99, 0x28, 0x28, 0x68, 0x63, 0x4e, 0xbb, 0x55, 0x1c, 0x13, 0x27, 0x99, 0x50, 0x68, 0x63, 0xfb, 0xa0, 0x03, 0xd1, 0xfc, 0x2f, 0x03, 0xd1, 0xfc, 0x2f, 0x03, 0xd1, 0x8f, 0x4e, 0xbb, 0xab, 0x02, 0xe9, 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x06, 0x4a, 0x06, 0x14, 0x00, 0x26, 0x00, 0x00, 0x01, 0x15, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x21, 0x35, 0x34, 0x36, 0x33, 0x21, 0x11, 0x23, 0x11, 0x21, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x36, 0x33, 0x02, 0xac, 0x9e, 0x5a, 0x22, 0x23, 0x01, 0xc7, 0x9c, 0xaa, 0x01, 0xcd, 0xa6, 0xfe, 0xd8, 0x59, 0x46, 0x01, 0x11, 0xfe, 0xef, 0xa6, 0xfe, 0x39, 0xa6, 0x9f, 0x9f, 0x9c, 0xaa, 0x06, 0x14, 0x99, 0x28, 0x28, 0x68, 0x63, 0x4e, 0xbb, 0xab, 0xf9, 0xec, 0x05, 0x7b, 0x50, 0x68, 0x63, 0x8f, 0xfc, 0x2f, 0x03, 0xd1, 0xfc, 0x2f, 0x03, 0xd1, 0x8f, 0x4e, 0xbb, 0xab, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x04, 0xc5, 0x06, 0x14, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x22, 0x07, 0x06, 0x15, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x37, 0x36, 0x3b, 0x01, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x23, 0x35, 0x02, 0xc9, 0x21, 0x21, 0x5b, 0x1e, 0x5a, 0x23, 0x22, 0xa6, 0x9f, 0x9f, 0x4e, 0x4e, 0xaa, 0x1b, 0xaa, 0x4f, 0x4c, 0x01, 0x55, 0xfe, 0xab, 0x22, 0x22, 0x67, 0xaa, 0xaa, 0xbf, 0x49, 0x49, 0x7a, 0x04, 0x60, 0x63, 0x68, 0x28, 0x28, 0x28, 0x28, 0x68, 0xfb, 0x3d, 0x03, 0xd1, 0x8f, 0x4e, 0xbb, 0x55, 0x56, 0x56, 0x53, 0xbd, 0x4e, 0x8f, 0xfd, 0xa0, 0x89, 0x27, 0x27, 0x9a, 0x50, 0x4f, 0xd2, 0x02, 0x60, 0x8f, 0x00, 0x00, 0x01, 0x00, 0x63, 0xff, 0xe3, 0x06, 0x07, 0x05, 0xf0, 0x00, 0x59, 0x00, 0x00, 0x01, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x27, 0x26, 0x07, 0x22, 0x07, 0x06, 0x15, 0x14, 0x02, 0xfc, 0x4d, 0x42, 0x4c, 0x3f, 0x69, 0x39, 0x35, 0x2c, 0x2d, 0x85, 0x38, 0xb0, 0x95, 0x6e, 0x70, 0xc2, 0x57, 0x53, 0x57, 0x61, 0x5c, 0x59, 0x59, 0x57, 0x75, 0x3f, 0x3f, 0x2d, 0x28, 0xa0, 0x39, 0x9a, 0x44, 0x45, 0x5c, 0x65, 0xa3, 0x40, 0x46, 0x05, 0x53, 0x52, 0x92, 0x7e, 0x58, 0x55, 0x01, 0x55, 0xfe, 0xab, 0x21, 0x22, 0x67, 0xab, 0xab, 0xbf, 0x49, 0x49, 0x79, 0x79, 0x2b, 0x31, 0x3d, 0x3e, 0x31, 0x2f, 0x04, 0x3f, 0xae, 0x2b, 0x11, 0x14, 0x2a, 0x27, 0x57, 0x40, 0x25, 0x24, 0x21, 0x0e, 0x2b, 0x98, 0x89, 0x9c, 0x5b, 0x5b, 0x11, 0x12, 0x23, 0xbe, 0x35, 0x1a, 0x1b, 0x2d, 0x2c, 0x51, 0x4b, 0x28, 0x23, 0x2a, 0x0f, 0x24, 0x4a, 0x4b, 0x82, 0xa6, 0x4e, 0x56, 0x0b, 0x1d, 0x1f, 0x87, 0x5f, 0x5d, 0x01, 0x60, 0x5c, 0x88, 0x4c, 0x8f, 0xfd, 0xa0, 0x89, 0x27, 0x27, 0x9a, 0x50, 0x4f, 0xd2, 0x02, 0x60, 0x8f, 0x4e, 0x41, 0x2b, 0x32, 0x01, 0x31, 0x30, 0x40, 0x3d, 0x00, 0x00, 0x01, 0xfc, 0xcb, 0x06, 0x04, 0x00, 0x00, 0x07, 0x6e, 0x00, 0x07, 0x00, 0x00, 0x11, 0x22, 0x04, 0x07, 0x35, 0x36, 0x24, 0x33, 0xd0, 0xfe, 0x6a, 0xcf, 0xd5, 0x01, 0x97, 0xc9, 0x06, 0xd4, 0x67, 0x69, 0x7e, 0x77, 0x75, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x04, 0x03, 0x35, 0x07, 0x6e, 0x00, 0x07, 0x00, 0x00, 0x11, 0x35, 0x32, 0x04, 0x17, 0x15, 0x26, 0x24, 0xc9, 0x01, 0x97, 0xd5, 0xcf, 0xfe, 0x6a, 0x06, 0xd4, 0x9a, 0x75, 0x77, 0x7e, 0x69, 0x67, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x72, 0x06, 0x0d, 0x00, 0x00, 0x07, 0x27, 0x00, 0x13, 0x00, 0x00, 0x11, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x23, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x04, 0x81, 0x19, 0x48, 0x27, 0x21, 0x5a, 0x30, 0x3f, 0x05, 0x91, 0x03, 0x66, 0x65, 0xb4, 0x52, 0x38, 0x32, 0x4f, 0x06, 0x48, 0x02, 0x37, 0x0b, 0x12, 0x0a, 0x24, 0x30, 0x47, 0x87, 0x4a, 0x49, 0x0e, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x0d, 0x02, 0x8e, 0x07, 0x27, 0x00, 0x13, 0x00, 0x00, 0x11, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x33, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x04, 0x81, 0x19, 0x48, 0x27, 0x21, 0x57, 0x33, 0x40, 0x04, 0x91, 0x03, 0x66, 0x65, 0xb4, 0x52, 0x38, 0x32, 0x4f, 0x06, 0xec, 0x02, 0x37, 0x0b, 0x12, 0x0a, 0x24, 0x2c, 0x4b, 0x87, 0x4a, 0x49, 0x0e, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1b, 0xff, 0x54, 0x07, 0x47, 0x07, 0x4c, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2a, 0x00, 0x00, 0x09, 0x04, 0x15, 0x33, 0x35, 0x27, 0x35, 0x34, 0x36, 0x37, 0x36, 0x37, 0x36, 0x3f, 0x01, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x0f, 0x01, 0x0e, 0x01, 0x1d, 0x01, 0x03, 0xb1, 0x03, 0x96, 0xfc, 0x6a, 0xfc, 0x6a, 0x03, 0x3a, 0xb7, 0x06, 0x06, 0x05, 0x07, 0x12, 0x14, 0x28, 0x4f, 0x53, 0x1e, 0x21, 0xc9, 0xa5, 0x5d, 0xae, 0x54, 0x57, 0xa1, 0x47, 0x61, 0x76, 0x2e, 0x33, 0x51, 0x51, 0x32, 0x07, 0x4c, 0xfc, 0x04, 0xfc, 0x04, 0x03, 0xfc, 0xfd, 0xae, 0xfe, 0xfe, 0x93, 0x7b, 0x34, 0x3c, 0x15, 0x19, 0x1a, 0x1f, 0x2b, 0x56, 0x5a, 0x40, 0x45, 0x4c, 0x9f, 0xc2, 0x38, 0x39, 0xbc, 0x43, 0x46, 0x6e, 0x59, 0x31, 0x5e, 0x35, 0x59, 0x56, 0x82, 0x65, 0x9a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5a, 0xff, 0xe3, 0x05, 0x19, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x0a, 0x00, 0x00, 0x37, 0x01, 0x33, 0x01, 0x07, 0x03, 0x21, 0x03, 0x13, 0x21, 0x03, 0x5a, 0x01, 0xf8, 0xcf, 0x01, 0xf8, 0x97, 0xae, 0xfd, 0xcb, 0xae, 0xec, 0x01, 0xb9, 0xdc, 0x23, 0x05, 0xb2, 0xfa, 0x4e, 0x40, 0x01, 0xf6, 0xfe, 0x0a, 0x02, 0xaa, 0x02, 0x7c, 0x00, 0x03, 0x00, 0xb4, 0xff, 0xed, 0x03, 0xac, 0x05, 0xe8, 0x00, 0x09, 0x00, 0x1a, 0x00, 0x24, 0x00, 0x00, 0x01, 0x11, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x15, 0x14, 0x07, 0x06, 0x21, 0x22, 0x27, 0x13, 0x11, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x56, 0x2f, 0xe2, 0x6b, 0x37, 0xb3, 0x9d, 0xfe, 0xfb, 0x7a, 0x5a, 0xd8, 0x92, 0xba, 0xc2, 0xc1, 0x6a, 0x99, 0xfe, 0xdd, 0x5a, 0x77, 0xa2, 0x64, 0xd2, 0x55, 0x28, 0xd5, 0xac, 0x02, 0x7e, 0xfe, 0x23, 0x72, 0x3b, 0x42, 0x59, 0x95, 0x03, 0x57, 0x13, 0x61, 0x7b, 0xd0, 0xd5, 0x7a, 0x7a, 0xe4, 0x8e, 0x70, 0xa4, 0x13, 0x05, 0x34, 0xfe, 0x15, 0x80, 0x3d, 0x38, 0x68, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0xff, 0xe3, 0x03, 0x86, 0x05, 0xf3, 0x00, 0x05, 0x00, 0x00, 0x05, 0x09, 0x01, 0x17, 0x09, 0x01, 0x03, 0x14, 0xfd, 0x46, 0x02, 0xba, 0x72, 0xfd, 0xb9, 0x02, 0x47, 0x1d, 0x03, 0x08, 0x03, 0x08, 0x7f, 0xfd, 0x77, 0xfd, 0x77, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x03, 0x9f, 0x05, 0xd2, 0x00, 0x0c, 0x00, 0x15, 0x00, 0x00, 0x33, 0x11, 0x33, 0x20, 0x17, 0x16, 0x17, 0x16, 0x10, 0x07, 0x06, 0x04, 0x21, 0x37, 0x3e, 0x02, 0x10, 0x27, 0x2e, 0x01, 0x27, 0xb4, 0x51, 0x01, 0x5d, 0x8e, 0x90, 0x16, 0x09, 0x23, 0x32, 0xfe, 0xd9, 0xfe, 0xe2, 0x51, 0xb9, 0xb3, 0x3b, 0x09, 0x10, 0xa9, 0xe5, 0x05, 0xd2, 0x78, 0x7a, 0xf9, 0x65, 0xfe, 0x62, 0x7f, 0xb8, 0xad, 0xc0, 0x08, 0x63, 0xd4, 0x01, 0x7a, 0x5c, 0xac, 0x91, 0x0a, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0x40, 0x05, 0xf2, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x05, 0x07, 0x25, 0x11, 0x05, 0x07, 0x25, 0x11, 0x05, 0x07, 0x01, 0x56, 0xa2, 0x02, 0x8c, 0x1a, 0xfe, 0x30, 0x01, 0xea, 0x1a, 0xfe, 0x30, 0x01, 0xea, 0x1a, 0x01, 0x36, 0xfe, 0xca, 0x05, 0xf2, 0x75, 0xb2, 0x53, 0xfe, 0xc3, 0x58, 0xb2, 0x53, 0xfe, 0xc3, 0x58, 0xb2, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0x40, 0x05, 0xf2, 0x00, 0x09, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x05, 0x07, 0x25, 0x11, 0x05, 0x07, 0x01, 0x56, 0xa2, 0x02, 0x8c, 0x1a, 0xfe, 0x30, 0x01, 0xea, 0x1a, 0x03, 0x2a, 0xfc, 0xd6, 0x05, 0xf2, 0x75, 0xb2, 0x53, 0xfe, 0xc3, 0x58, 0xb2, 0x00, 0x01, 0x00, 0x87, 0x00, 0x00, 0x02, 0xa3, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x23, 0x87, 0x02, 0x1c, 0xbd, 0xbd, 0xfd, 0xe4, 0xbd, 0xbd, 0x05, 0xd5, 0xb4, 0xfb, 0x93, 0xb4, 0xb4, 0x04, 0x6d, 0x00, 0x03, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xcc, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x11, 0x21, 0x01, 0x11, 0x21, 0x11, 0x05, 0x21, 0x11, 0x21, 0xb4, 0x03, 0x18, 0xfc, 0xe8, 0x02, 0x76, 0xfe, 0x2c, 0x01, 0xd4, 0xfe, 0x2c, 0x01, 0xd4, 0x05, 0xd5, 0xfa, 0x2b, 0x03, 0x45, 0x01, 0xdc, 0xfe, 0x24, 0xb4, 0xfe, 0x23, 0x00, 0x00, 0x00, 0x05, 0x00, 0x87, 0xff, 0xe3, 0x05, 0xfa, 0x05, 0xf3, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00, 0x23, 0x00, 0x00, 0x00, 0x02, 0x06, 0x04, 0x20, 0x24, 0x26, 0x02, 0x10, 0x12, 0x36, 0x24, 0x20, 0x04, 0x16, 0x12, 0x01, 0x36, 0x12, 0x37, 0x21, 0x03, 0x11, 0x21, 0x16, 0x12, 0x01, 0x21, 0x11, 0x06, 0x02, 0x01, 0x11, 0x21, 0x26, 0x02, 0x05, 0xfa, 0x6e, 0xbb, 0xfe, 0xfd, 0xfe, 0xe5, 0xfe, 0xfd, 0xbb, 0x6e, 0x6e, 0xbb, 0x01, 0x03, 0x01, 0x1b, 0x01, 0x03, 0xbb, 0x6e, 0xfd, 0x98, 0xae, 0xf7, 0x1b, 0xfe, 0x40, 0xa2, 0xfe, 0x3f, 0x1b, 0xf7, 0xfe, 0xee, 0x01, 0xc1, 0xaf, 0xf7, 0x02, 0x48, 0x01, 0xc0, 0x1b, 0xf7, 0x02, 0x4e, 0xfe, 0xe0, 0xd0, 0x7b, 0x7b, 0xd0, 0x01, 0x20, 0x01, 0x3a, 0x01, 0x20, 0xd0, 0x7b, 0x7b, 0xd0, 0xfe, 0xe0, 0xfd, 0x16, 0x1e, 0x01, 0x12, 0xc3, 0xfe, 0x0d, 0x01, 0xf3, 0xc3, 0xfe, 0xee, 0x02, 0x89, 0x01, 0xf3, 0x1e, 0xfe, 0xee, 0x01, 0x30, 0xfe, 0x0d, 0xc3, 0x01, 0x12, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x56, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x00, 0x13, 0x33, 0x11, 0x23, 0xb4, 0xa2, 0xa2, 0x05, 0xd5, 0xfa, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xff, 0xe3, 0x04, 0x10, 0x05, 0xf3, 0x00, 0x0a, 0x00, 0x00, 0x21, 0x23, 0x11, 0x33, 0x11, 0x01, 0x17, 0x09, 0x01, 0x07, 0x01, 0x01, 0x56, 0xa2, 0xa2, 0x02, 0x47, 0x6c, 0xfd, 0x76, 0x02, 0x91, 0x6c, 0xfd, 0xb2, 0x05, 0xd5, 0xfd, 0xe1, 0x02, 0x3d, 0x86, 0xfd, 0x81, 0xfd, 0x7b, 0x86, 0x02, 0x43, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x03, 0x96, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x09, 0x01, 0x17, 0x01, 0x23, 0x11, 0x33, 0x01, 0x56, 0x01, 0xcc, 0x73, 0xfd, 0x92, 0x73, 0xa2, 0x01, 0x33, 0x02, 0x00, 0x80, 0xfd, 0x4d, 0x05, 0xd5, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x09, 0xbf, 0x05, 0xf3, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x33, 0x09, 0x03, 0x17, 0x09, 0x03, 0x11, 0x23, 0xb4, 0x68, 0x02, 0x43, 0x01, 0xff, 0x01, 0xf7, 0x01, 0xf7, 0x73, 0xfd, 0x96, 0xfe, 0x0a, 0xfe, 0x09, 0xfd, 0xee, 0xa2, 0x05, 0xd5, 0xfd, 0xe5, 0x02, 0x39, 0xfd, 0xd1, 0x02, 0x2f, 0x80, 0xfd, 0x53, 0x02, 0x2e, 0xfd, 0xd2, 0x01, 0xee, 0xfb, 0x4c, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x05, 0xd2, 0x05, 0xf3, 0x00, 0x08, 0x00, 0x00, 0x13, 0x33, 0x09, 0x01, 0x17, 0x09, 0x01, 0x11, 0x23, 0xb4, 0x68, 0x02, 0x43, 0x01, 0xff, 0x74, 0xfd, 0x96, 0xfd, 0xee, 0xa2, 0x05, 0xd5, 0xfd, 0xe5, 0x02, 0x39, 0x80, 0xfd, 0x53, 0x01, 0xee, 0xfb, 0x4c, 0x00, 0x05, 0x00, 0xb4, 0x00, 0x00, 0x05, 0xf3, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x21, 0x11, 0x21, 0x01, 0x11, 0x21, 0x11, 0x21, 0x11, 0x21, 0x11, 0x13, 0x11, 0x21, 0x11, 0x01, 0x56, 0x01, 0xac, 0xfd, 0xb2, 0x05, 0x3f, 0xfa, 0xc1, 0x02, 0xf0, 0x01, 0xad, 0xfc, 0x05, 0x01, 0xac, 0xa2, 0x01, 0xad, 0x02, 0x90, 0xfe, 0x24, 0x01, 0xdc, 0x03, 0x45, 0xfa, 0x2b, 0x05, 0x21, 0xfe, 0x24, 0x01, 0xdc, 0xfe, 0x24, 0x01, 0xdc, 0xfd, 0x6f, 0xfe, 0x24, 0x01, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x87, 0xff, 0xe3, 0x05, 0xfa, 0x05, 0xf3, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x27, 0x00, 0x00, 0x00, 0x36, 0x34, 0x2e, 0x02, 0x22, 0x0e, 0x02, 0x14, 0x1e, 0x02, 0x32, 0x36, 0x00, 0x02, 0x06, 0x04, 0x20, 0x24, 0x26, 0x02, 0x10, 0x12, 0x36, 0x24, 0x20, 0x04, 0x16, 0x12, 0x04, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x16, 0x05, 0x03, 0x55, 0x55, 0x8f, 0xc8, 0xd8, 0xc7, 0x8f, 0x55, 0x55, 0x8f, 0xc7, 0xd8, 0xc8, 0x01, 0x86, 0x6e, 0xbb, 0xfe, 0xfd, 0xfe, 0xe5, 0xfe, 0xfd, 0xbb, 0x6e, 0x6e, 0xbb, 0x01, 0x03, 0x01, 0x1b, 0x01, 0x03, 0xbb, 0x6e, 0xfd, 0xc4, 0x49, 0x69, 0x4a, 0x4a, 0x69, 0x49, 0x01, 0x94, 0xdf, 0xf0, 0xdf, 0x9e, 0x5f, 0x5f, 0x9e, 0xdf, 0xf0, 0xdf, 0x9e, 0x5f, 0x5f, 0x01, 0x58, 0xfe, 0xe0, 0xd0, 0x7b, 0x7b, 0xd0, 0x01, 0x20, 0x01, 0x3a, 0x01, 0x20, 0xd0, 0x7b, 0x7b, 0xd0, 0xfe, 0xe0, 0xd7, 0x52, 0x52, 0x74, 0x52, 0x52, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6a, 0x05, 0xe8, 0x00, 0x11, 0x00, 0x00, 0x01, 0x36, 0x35, 0x34, 0x24, 0x21, 0x22, 0x07, 0x11, 0x23, 0x11, 0x36, 0x33, 0x20, 0x00, 0x11, 0x10, 0x05, 0x02, 0xd7, 0xf1, 0xfe, 0xf1, 0xfe, 0xfe, 0x2f, 0x32, 0xa2, 0x92, 0x71, 0x01, 0x3f, 0x01, 0x74, 0xfe, 0xa7, 0x02, 0x59, 0x66, 0xd4, 0xb6, 0xf9, 0x06, 0xfa, 0xc4, 0x05, 0xd4, 0x14, 0xfe, 0xbf, 0xfe, 0xec, 0xfe, 0xb0, 0x92, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x8d, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x33, 0x11, 0x33, 0x09, 0x01, 0x33, 0x11, 0x23, 0x11, 0x09, 0x01, 0x11, 0xb4, 0xa2, 0x01, 0xca, 0x01, 0xca, 0xa2, 0xa2, 0xfe, 0x36, 0xfe, 0x36, 0x05, 0xd5, 0xfd, 0xa2, 0x02, 0x5e, 0xfa, 0x2b, 0x04, 0xbd, 0xfd, 0xa1, 0x02, 0x5f, 0xfb, 0x43, 0x00, 0x00, 0x00, 0x02, 0x00, 0x87, 0x00, 0x00, 0x03, 0xb1, 0x05, 0xf2, 0x00, 0x0b, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x34, 0x2e, 0x01, 0x22, 0x0e, 0x01, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x06, 0x07, 0x06, 0x07, 0x11, 0x23, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x3e, 0x01, 0x32, 0x1e, 0x01, 0x03, 0x0f, 0x41, 0x70, 0x84, 0x70, 0x41, 0x41, 0x70, 0x84, 0x70, 0xe3, 0x6e, 0x5c, 0x39, 0x41, 0xa2, 0x40, 0x3a, 0x5e, 0x6c, 0x6d, 0xba, 0xdc, 0xba, 0x6d, 0x03, 0xe7, 0x93, 0x7c, 0x48, 0x48, 0x7c, 0x93, 0x7d, 0x48, 0x48, 0x4c, 0xd1, 0x3b, 0x25, 0x0e, 0xfd, 0x89, 0x02, 0x77, 0x0e, 0x25, 0x3c, 0xd0, 0xf4, 0xcf, 0x79, 0x79, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xd7, 0x05, 0xe9, 0x00, 0x0c, 0x00, 0x17, 0x00, 0x00, 0x08, 0x01, 0x15, 0x14, 0x02, 0x07, 0x06, 0x23, 0x11, 0x23, 0x11, 0x36, 0x33, 0x03, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x02, 0x8f, 0x01, 0x48, 0xb4, 0xe6, 0x6a, 0x7d, 0xa2, 0x92, 0x71, 0x61, 0xee, 0x78, 0x79, 0x7d, 0x67, 0xab, 0x26, 0x2a, 0x05, 0xe9, 0xfe, 0xe5, 0xfc, 0x8d, 0xfe, 0xd1, 0x4e, 0x24, 0xfe, 0x5c, 0x05, 0xd5, 0x14, 0xfc, 0x6f, 0x73, 0x72, 0x96, 0x9e, 0x6c, 0x58, 0x04, 0x00, 0x01, 0x00, 0x87, 0xff, 0xf2, 0x02, 0xa7, 0x05, 0xea, 0x00, 0x09, 0x00, 0x00, 0x09, 0x03, 0x07, 0x09, 0x03, 0x17, 0x01, 0x6c, 0x01, 0x3b, 0xfe, 0xc5, 0x01, 0x02, 0x73, 0xfe, 0x8c, 0x01, 0x3b, 0xfe, 0xc5, 0x01, 0x74, 0x73, 0x04, 0x4c, 0xfe, 0xa2, 0xfe, 0xa2, 0xfe, 0xe2, 0x80, 0x01, 0x9e, 0x01, 0x5e, 0x01, 0x5e, 0x01, 0x9e, 0x80, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x04, 0x7d, 0x05, 0xf2, 0x00, 0x07, 0x00, 0x00, 0x01, 0x07, 0x25, 0x11, 0x23, 0x11, 0x25, 0x37, 0x04, 0x7c, 0x32, 0xfe, 0x60, 0xa2, 0xfe, 0x52, 0x32, 0x04, 0x8a, 0xac, 0x95, 0xfb, 0x8d, 0x04, 0xad, 0x99, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x3c, 0x05, 0xea, 0x00, 0x07, 0x00, 0x00, 0x01, 0x17, 0x01, 0x11, 0x23, 0x11, 0x33, 0x11, 0x03, 0xc8, 0x74, 0xfd, 0x1a, 0xa2, 0xa2, 0x05, 0xea, 0x80, 0xfc, 0xc9, 0xfd, 0xcd, 0x05, 0xd5, 0xfd, 0x5c, 0x00, 0x01, 0x00, 0x87, 0xff, 0xe3, 0x04, 0x6a, 0x05, 0xf2, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x01, 0x37, 0x09, 0x01, 0x17, 0x09, 0x01, 0x07, 0x09, 0x01, 0x27, 0x02, 0x16, 0xfe, 0x71, 0x87, 0x01, 0x6a, 0x01, 0x6a, 0x88, 0xfe, 0x71, 0x01, 0x8f, 0x88, 0xfe, 0x96, 0xfe, 0x96, 0x87, 0x02, 0xed, 0x02, 0xa3, 0x62, 0xfd, 0xa1, 0x02, 0x5f, 0x62, 0xfd, 0x5d, 0xfd, 0x58, 0x62, 0x02, 0x64, 0xfd, 0x9c, 0x62, 0x00, 0x00, 0x00, 0x03, 0x00, 0x87, 0x00, 0x00, 0x04, 0x65, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x1b, 0x00, 0x24, 0x00, 0x00, 0x21, 0x23, 0x35, 0x26, 0x27, 0x26, 0x10, 0x37, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x17, 0x16, 0x10, 0x07, 0x06, 0x07, 0x19, 0x01, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x03, 0x11, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x02, 0xc7, 0xa2, 0x99, 0x74, 0x91, 0x91, 0x73, 0x9a, 0xa2, 0x99, 0x74, 0x91, 0x91, 0x73, 0x9a, 0x56, 0x44, 0x62, 0x62, 0x44, 0xf8, 0x56, 0x44, 0x62, 0x62, 0x44, 0xcc, 0x1a, 0x80, 0xa1, 0x01, 0xc7, 0xa2, 0x80, 0x1a, 0xcb, 0xcb, 0x1a, 0x80, 0xa1, 0xfe, 0x39, 0xa2, 0x80, 0x1a, 0x03, 0x87, 0xfd, 0x30, 0x17, 0x4c, 0x6c, 0x01, 0x32, 0x6c, 0x4b, 0xfd, 0x48, 0x02, 0xd0, 0x17, 0x4c, 0x6e, 0x98, 0x96, 0x6e, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x05, 0x7b, 0x05, 0xf2, 0x00, 0x0b, 0x00, 0x00, 0x21, 0x23, 0x11, 0x01, 0x37, 0x01, 0x11, 0x33, 0x11, 0x01, 0x17, 0x01, 0x03, 0x3b, 0xa2, 0xfd, 0xc1, 0x73, 0x01, 0xcc, 0xa2, 0x01, 0xcc, 0x73, 0xfd, 0xc1, 0x02, 0xf4, 0x02, 0x7e, 0x80, 0xfe, 0x00, 0x01, 0xe3, 0xfe, 0x1d, 0x02, 0x00, 0x80, 0xfd, 0x82, 0x00, 0x03, 0x00, 0x87, 0xff, 0xf1, 0x03, 0x45, 0x05, 0xb9, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x25, 0x00, 0x00, 0x00, 0x34, 0x26, 0x22, 0x06, 0x14, 0x16, 0x32, 0x24, 0x06, 0x20, 0x26, 0x10, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x10, 0x36, 0x20, 0x16, 0x10, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x02, 0x34, 0x26, 0x22, 0x06, 0x14, 0x16, 0x32, 0x02, 0xa3, 0x6f, 0x9c, 0x6f, 0x6f, 0x9c, 0x01, 0x11, 0xce, 0xfe, 0xde, 0xce, 0x67, 0x2a, 0x31, 0x31, 0x2a, 0x67, 0xce, 0x01, 0x22, 0xce, 0x67, 0x2a, 0x31, 0x31, 0x2a, 0x67, 0xa2, 0x6f, 0x9c, 0x6f, 0x6f, 0x9c, 0x01, 0x20, 0xae, 0x7b, 0x7b, 0xae, 0x7b, 0x31, 0xe5, 0xe5, 0x01, 0x42, 0x73, 0x2f, 0x1b, 0x1c, 0x2e, 0x72, 0x01, 0x43, 0xe5, 0xe5, 0xfe, 0xbe, 0x73, 0x2f, 0x1b, 0x1c, 0x2e, 0x72, 0x01, 0xc3, 0xae, 0x7b, 0x7b, 0xae, 0x7b, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x03, 0x7d, 0x05, 0xe8, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x00, 0x33, 0x11, 0x36, 0x33, 0x32, 0x04, 0x15, 0x14, 0x04, 0x23, 0x19, 0x01, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0xb4, 0x77, 0x74, 0xdb, 0x01, 0x03, 0xfe, 0xcb, 0xf2, 0xb6, 0xcf, 0xa2, 0x92, 0x26, 0x2b, 0x05, 0xd5, 0x13, 0xe6, 0xbd, 0xd0, 0xdc, 0xfd, 0x67, 0x03, 0x4e, 0x7f, 0x76, 0x63, 0x9c, 0x06, 0x00, 0x00, 0x02, 0x00, 0xb4, 0xff, 0xed, 0x03, 0x7d, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x13, 0x33, 0x11, 0x32, 0x04, 0x15, 0x14, 0x04, 0x23, 0x22, 0x27, 0x13, 0x30, 0x11, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xb4, 0xa2, 0xf2, 0x01, 0x35, 0xfe, 0xfd, 0xdb, 0x74, 0x77, 0xa2, 0x2b, 0x26, 0x92, 0xa2, 0xcf, 0x05, 0xd5, 0xfd, 0x67, 0xdc, 0xd0, 0xbd, 0xe6, 0x13, 0x02, 0x87, 0xfe, 0x12, 0x06, 0x9c, 0x63, 0x76, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0x76, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x00, 0x13, 0x35, 0x21, 0x11, 0x33, 0x11, 0x23, 0x11, 0x5a, 0x01, 0x7a, 0xa2, 0xa2, 0x02, 0x91, 0xb4, 0x02, 0x90, 0xfa, 0x2b, 0x02, 0x91, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x00, 0x05, 0x19, 0x05, 0xf2, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x00, 0x09, 0x01, 0x23, 0x01, 0x37, 0x09, 0x01, 0x00, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x16, 0x05, 0x19, 0xfe, 0x08, 0xcf, 0xfe, 0x08, 0x97, 0x01, 0xc9, 0x01, 0xc8, 0xfe, 0xb6, 0x4a, 0x69, 0x49, 0x49, 0x69, 0x4a, 0x05, 0xb2, 0xfa, 0x4e, 0x05, 0xb2, 0x40, 0xfa, 0xda, 0x05, 0x26, 0xfd, 0xd8, 0x52, 0x52, 0x74, 0x52, 0x52, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x01, 0x56, 0x05, 0xd5, 0x12, 0x06, 0x0f, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0xff, 0xe3, 0x05, 0x19, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x00, 0x37, 0x01, 0x33, 0x01, 0x07, 0x09, 0x01, 0x5a, 0x01, 0xf8, 0xcf, 0x01, 0xf8, 0x97, 0xfe, 0x38, 0xfe, 0x37, 0x23, 0x05, 0xb2, 0xfa, 0x4e, 0x40, 0x05, 0x26, 0xfa, 0xda, 0x00, 0x00, 0xff, 0xff, 0x00, 0x87, 0xff, 0xe3, 0x04, 0x6a, 0x05, 0xf2, 0x12, 0x06, 0x0f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x05, 0x8a, 0x05, 0xf3, 0x00, 0x08, 0x00, 0x00, 0x13, 0x09, 0x01, 0x07, 0x01, 0x11, 0x23, 0x11, 0x01, 0x5a, 0x02, 0x81, 0x02, 0xaf, 0x6e, 0xfe, 0x12, 0xa2, 0xfe, 0x41, 0x03, 0x2c, 0x02, 0xc7, 0xfd, 0x3b, 0x84, 0x01, 0xfe, 0xfb, 0x58, 0x04, 0x9d, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x99, 0x01, 0xe0, 0x05, 0xdc, 0x02, 0xa8, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x21, 0x35, 0x21, 0x05, 0x35, 0x21, 0x15, 0x29, 0x01, 0x35, 0x21, 0x01, 0xca, 0xfe, 0xcf, 0x01, 0x31, 0x02, 0xe0, 0x01, 0x31, 0xfd, 0xf7, 0xfe, 0xd0, 0x01, 0x30, 0x01, 0xe0, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x01, 0x37, 0x05, 0xdc, 0x04, 0x0e, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xff, 0x58, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x46, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x01, 0x3a, 0x05, 0xdc, 0x04, 0x0a, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x62, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x01, 0x3d, 0x05, 0xdc, 0x04, 0x0b, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xff, 0x5d, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x43, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x01, 0x3b, 0x05, 0xdc, 0x04, 0x0a, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x3c, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x01, 0x3d, 0x05, 0xdc, 0x04, 0x0a, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xff, 0x5d, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x06, 0x0f, 0x3c, 0x00, 0xa0, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x04, 0x80, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0f, 0x3c, 0x00, 0xa0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x06, 0x0f, 0x3c, 0x00, 0xa0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0f, 0x3c, 0x00, 0xa0, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x04, 0x80, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0f, 0x3c, 0x00, 0xa0, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0x00, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x10, 0x26, 0x0b, 0xb3, 0x00, 0x00, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x26, 0x0b, 0xb4, 0x00, 0x00, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x06, 0x0b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x06, 0x0b, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x00, 0x00, 0x05, 0xdc, 0x05, 0x48, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x02, 0xa0, 0x10, 0x27, 0x0f, 0x3c, 0x00, 0x00, 0x01, 0x20, 0x10, 0x26, 0x0f, 0x3c, 0x00, 0xa0, 0x10, 0x07, 0x0f, 0x3c, 0x00, 0x00, 0xfe, 0x20, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x05, 0x46, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x23, 0x01, 0x33, 0x09, 0x01, 0x21, 0x03, 0x21, 0x03, 0x23, 0x01, 0x17, 0x01, 0x21, 0x03, 0x07, 0xb9, 0x01, 0xbd, 0xb9, 0xfe, 0x81, 0x02, 0x01, 0xfe, 0x86, 0x89, 0xfd, 0xc0, 0x89, 0x6c, 0x02, 0x00, 0x16, 0xff, 0x00, 0x01, 0xff, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x71, 0xfa, 0x2b, 0x01, 0xa1, 0xfe, 0x5f, 0x05, 0xd5, 0xc7, 0xfc, 0xf7, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xc7, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x25, 0x00, 0x2a, 0x00, 0x00, 0x13, 0x21, 0x32, 0x16, 0x15, 0x14, 0x07, 0x16, 0x11, 0x14, 0x06, 0x23, 0x21, 0x01, 0x11, 0x33, 0x32, 0x37, 0x11, 0x26, 0x23, 0x03, 0x11, 0x33, 0x36, 0x33, 0x11, 0x26, 0x23, 0x21, 0x11, 0x33, 0x11, 0x01, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x36, 0x35, 0x34, 0x27, 0xb5, 0x02, 0x29, 0xcf, 0xe1, 0xac, 0xe4, 0xf5, 0xe1, 0xfd, 0xc5, 0x01, 0x68, 0xd3, 0x35, 0x2d, 0x2d, 0x35, 0xd3, 0xc1, 0x20, 0x1d, 0x1d, 0x20, 0xfe, 0x31, 0xb6, 0x01, 0xec, 0xbb, 0xbb, 0x38, 0xbb, 0xbb, 0x05, 0xd5, 0xc0, 0xb1, 0xe5, 0x5d, 0x61, 0xfe, 0xe1, 0xc8, 0xda, 0x02, 0xe9, 0xfd, 0x7b, 0x07, 0x02, 0x77, 0x07, 0x02, 0x88, 0xfd, 0xdc, 0x03, 0x02, 0x1f, 0x02, 0xfa, 0xf3, 0x05, 0x0d, 0xfb, 0x11, 0x44, 0xdc, 0xe5, 0x44, 0x96, 0x36, 0xcd, 0xc4, 0x36, 0x00, 0x00, 0x04, 0x00, 0xd0, 0x00, 0x00, 0x05, 0x95, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x10, 0x00, 0x14, 0x00, 0x19, 0x00, 0x00, 0x13, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x29, 0x01, 0x01, 0x13, 0x33, 0x32, 0x37, 0x11, 0x26, 0x23, 0x21, 0x11, 0x33, 0x03, 0x01, 0x36, 0x11, 0x10, 0x27, 0xd1, 0x01, 0xcf, 0x01, 0x87, 0x01, 0x6d, 0xfe, 0x91, 0xfe, 0x7b, 0xfe, 0x31, 0x01, 0x6a, 0x01, 0x59, 0xdc, 0x90, 0x90, 0xdd, 0xfe, 0x98, 0xb6, 0x01, 0x02, 0x7f, 0xc8, 0xc8, 0x05, 0xd5, 0xfe, 0x97, 0xfe, 0x80, 0xfe, 0x7e, 0xfe, 0x96, 0x05, 0x71, 0xfa, 0xf3, 0x41, 0x04, 0x8b, 0x41, 0xfa, 0xf3, 0x05, 0x0d, 0xfb, 0x6b, 0x95, 0x01, 0x7b, 0x01, 0x71, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xcb, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x25, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x01, 0x0f, 0xb6, 0xfe, 0xf0, 0x04, 0x05, 0xfd, 0x65, 0x02, 0x80, 0xfd, 0x80, 0x02, 0xac, 0xfb, 0xea, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0x64, 0xfd, 0xe4, 0x64, 0xfd, 0x73, 0x64, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x00, 0x13, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x01, 0x23, 0x11, 0x33, 0xb5, 0x03, 0xb9, 0xfd, 0xb1, 0x02, 0x15, 0xfd, 0xeb, 0xfe, 0x96, 0x01, 0x10, 0xb6, 0xb6, 0x05, 0xd5, 0x64, 0xfd, 0xe4, 0x64, 0xfd, 0x0f, 0x05, 0x71, 0xfa, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x05, 0xf0, 0x00, 0x1d, 0x00, 0x26, 0x00, 0x00, 0x01, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x11, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x11, 0x21, 0x35, 0x21, 0x11, 0x0e, 0x01, 0x23, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x32, 0x16, 0x17, 0x01, 0x11, 0x06, 0x07, 0x06, 0x11, 0x10, 0x17, 0x16, 0x04, 0xda, 0x72, 0xea, 0x78, 0xa8, 0x7a, 0x7a, 0xa8, 0x82, 0x73, 0x5b, 0x4d, 0xfe, 0x7d, 0x01, 0xdd, 0x69, 0xfe, 0x90, 0xfe, 0xc5, 0xfe, 0x9d, 0x01, 0x63, 0x01, 0x3b, 0x83, 0xed, 0x64, 0xfc, 0xb0, 0x19, 0x17, 0x98, 0x98, 0x17, 0x04, 0xe4, 0x61, 0x47, 0x40, 0xfb, 0x3b, 0x40, 0x26, 0x1f, 0x35, 0x01, 0xe7, 0x64, 0xfd, 0x7f, 0x53, 0x55, 0x01, 0x99, 0x01, 0x6d, 0x01, 0x6e, 0x01, 0x99, 0x48, 0x46, 0xfb, 0x63, 0x04, 0x49, 0x16, 0x1a, 0xaf, 0xfe, 0xba, 0xfe, 0xbb, 0xaf, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5b, 0x00, 0x00, 0x02, 0x78, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x25, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x23, 0x01, 0x10, 0xb6, 0xfe, 0x96, 0x02, 0x1c, 0x5a, 0x5a, 0xfd, 0xe4, 0x5a, 0x5a, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0x64, 0xfa, 0xf3, 0x64, 0x64, 0x05, 0x0d, 0x00, 0x00, 0x02, 0xff, 0xa0, 0xfe, 0x66, 0x02, 0x1d, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x01, 0x11, 0x14, 0x07, 0x36, 0x37, 0x36, 0x35, 0x11, 0x25, 0x21, 0x11, 0x10, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x01, 0x0f, 0x4d, 0x81, 0x39, 0x47, 0xfe, 0xf2, 0x01, 0x68, 0xb9, 0xcc, 0xf7, 0x38, 0x79, 0x63, 0x05, 0x71, 0xfa, 0xb1, 0xf2, 0x64, 0x0a, 0x4a, 0x5e, 0xea, 0x05, 0x09, 0x64, 0xfa, 0x93, 0xfe, 0xf2, 0xf4, 0x64, 0x96, 0xc2, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x92, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x21, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x21, 0x13, 0x11, 0x33, 0x11, 0xb5, 0x01, 0x68, 0x02, 0xb6, 0x8f, 0xfc, 0xf9, 0x03, 0x37, 0x8a, 0xfd, 0x15, 0xfe, 0x98, 0x5a, 0xb6, 0x05, 0xd5, 0xfd, 0x89, 0x02, 0x77, 0xfd, 0x40, 0xfc, 0xeb, 0x02, 0xcf, 0xfd, 0x31, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xad, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x13, 0x21, 0x11, 0x21, 0x15, 0x21, 0x13, 0x11, 0x33, 0x11, 0xb5, 0x01, 0x6a, 0x02, 0x8e, 0xfc, 0x08, 0x5a, 0xb6, 0x05, 0xd5, 0xfa, 0x8f, 0x64, 0x05, 0x6f, 0xfa, 0xf3, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb0, 0x00, 0x00, 0x06, 0xb1, 0x05, 0xd5, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x00, 0x21, 0x11, 0x01, 0x23, 0x01, 0x03, 0x21, 0x11, 0x21, 0x09, 0x01, 0x21, 0x11, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x05, 0x47, 0xfe, 0x89, 0x40, 0xfe, 0x8b, 0x01, 0xfe, 0x96, 0x01, 0xa9, 0x01, 0x57, 0x01, 0x59, 0x01, 0xa8, 0xfe, 0xf0, 0xb6, 0xfa, 0xb3, 0xb6, 0x05, 0x71, 0xfb, 0xae, 0x04, 0x52, 0xfa, 0x8f, 0x05, 0xd5, 0xfc, 0x08, 0x03, 0xf8, 0xfa, 0x2b, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0xfa, 0xf3, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x66, 0xff, 0xe3, 0x05, 0x45, 0x05, 0xf0, 0x00, 0x0f, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x27, 0x00, 0x28, 0x00, 0x00, 0x01, 0x20, 0x17, 0x16, 0x11, 0x10, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x11, 0x10, 0x37, 0x36, 0x13, 0x16, 0x32, 0x37, 0x11, 0x26, 0x22, 0x07, 0x03, 0x11, 0x06, 0x07, 0x06, 0x10, 0x17, 0x16, 0x01, 0x11, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x01, 0x02, 0xd5, 0x01, 0x1b, 0xa9, 0xab, 0xaa, 0xaa, 0xfe, 0xe5, 0xfe, 0xe5, 0xa9, 0xaa, 0xaa, 0xa9, 0x40, 0x61, 0xf5, 0x61, 0x61, 0xf5, 0x61, 0x5f, 0x20, 0x1d, 0x8b, 0x8b, 0x1d, 0x02, 0x95, 0x1f, 0x1c, 0x8b, 0x8b, 0x1c, 0xfc, 0x38, 0x05, 0xf0, 0xd2, 0xd5, 0xfe, 0xa0, 0xfe, 0xa1, 0xd4, 0xd3, 0xd3, 0xd2, 0x01, 0x61, 0x01, 0x62, 0xd3, 0xd2, 0xfa, 0x8e, 0x32, 0x32, 0x04, 0xd7, 0x32, 0x32, 0xfb, 0x6a, 0x04, 0x54, 0x1d, 0x25, 0xb6, 0xfd, 0x9c, 0xb5, 0x25, 0x04, 0x35, 0xfb, 0xaf, 0x1d, 0x24, 0xb6, 0x02, 0x63, 0xb6, 0x24, 0xfd, 0xf4, 0x00, 0x00, 0x02, 0x00, 0x7a, 0xff, 0xdc, 0x04, 0x29, 0x05, 0xf6, 0x00, 0x11, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x06, 0x10, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x10, 0x07, 0x36, 0x10, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x34, 0x25, 0x15, 0x26, 0x20, 0x06, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x10, 0x04, 0x20, 0x27, 0x35, 0x16, 0x20, 0x36, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x10, 0x36, 0x20, 0x01, 0x2e, 0x5a, 0x7b, 0x9b, 0x64, 0x98, 0x97, 0x22, 0x74, 0x8d, 0x99, 0x63, 0x9e, 0x8e, 0x02, 0xc0, 0xb9, 0xfe, 0xe5, 0x92, 0x62, 0x85, 0x63, 0xb6, 0xb5, 0xfe, 0xfd, 0xfe, 0x44, 0xeb, 0xc9, 0x01, 0x43, 0x98, 0x6e, 0x7c, 0x64, 0xb6, 0xa5, 0xfb, 0x01, 0x98, 0x05, 0x2d, 0x5b, 0xfe, 0xca, 0x9a, 0x29, 0x1a, 0x27, 0xb9, 0xfe, 0xff, 0x4e, 0x58, 0x01, 0x64, 0xbb, 0x27, 0x1b, 0x27, 0x9d, 0xe3, 0xb4, 0x70, 0x75, 0x89, 0xe9, 0x69, 0x24, 0x1b, 0x32, 0xeb, 0xfe, 0x58, 0xee, 0x66, 0x7c, 0x95, 0x92, 0xfd, 0x86, 0x20, 0x1a, 0x2f, 0xcf, 0x01, 0x8c, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xfa, 0x00, 0x00, 0x05, 0x1f, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x25, 0x21, 0x15, 0x21, 0x11, 0x21, 0x11, 0x21, 0x02, 0x33, 0xb4, 0xfd, 0x14, 0x05, 0x23, 0xfe, 0x23, 0xfe, 0x98, 0xfe, 0x22, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0x64, 0xfa, 0x8f, 0x05, 0x71, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x9f, 0xff, 0xe3, 0x05, 0x5b, 0x05, 0xd5, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x11, 0x10, 0x07, 0x24, 0x19, 0x01, 0x21, 0x11, 0x10, 0x05, 0x26, 0x13, 0x11, 0x25, 0x21, 0x11, 0x14, 0x16, 0x20, 0x36, 0x35, 0x11, 0x21, 0x11, 0x10, 0x00, 0x20, 0x00, 0x11, 0x04, 0x4c, 0x4f, 0x01, 0x04, 0xfb, 0xf8, 0x01, 0x04, 0x50, 0x01, 0xfe, 0xf1, 0x01, 0x69, 0x73, 0x01, 0x04, 0x73, 0x01, 0x69, 0xfe, 0xce, 0xfd, 0xa8, 0xfe, 0xce, 0x05, 0x71, 0xfc, 0x99, 0xfe, 0xe6, 0x82, 0x62, 0x01, 0x61, 0x03, 0x40, 0xfc, 0xc0, 0xfe, 0x9e, 0x60, 0x7c, 0x01, 0x1f, 0x03, 0x67, 0x64, 0xfc, 0x35, 0xf0, 0xd3, 0xd3, 0xf0, 0x03, 0xcb, 0xfc, 0x5c, 0xfe, 0xdc, 0xfe, 0xd6, 0x01, 0x2a, 0x01, 0x24, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x05, 0x25, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x01, 0x33, 0x01, 0x25, 0x21, 0x09, 0x01, 0x33, 0x01, 0x21, 0x8b, 0x01, 0xbc, 0xb4, 0xfe, 0x44, 0xfe, 0xcf, 0x01, 0x68, 0x01, 0xaa, 0x01, 0xab, 0x5a, 0xfe, 0x00, 0xfe, 0xea, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0xfb, 0x17, 0x04, 0xe9, 0xfa, 0x2b, 0x00, 0x00, 0x03, 0x00, 0x3d, 0x00, 0x00, 0x07, 0xd0, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x09, 0x01, 0x33, 0x01, 0x21, 0x01, 0x33, 0x01, 0x25, 0x21, 0x09, 0x01, 0x21, 0x09, 0x01, 0x33, 0x01, 0x21, 0x09, 0x01, 0x21, 0x04, 0x4a, 0x01, 0x24, 0xb4, 0xfe, 0xdc, 0xfb, 0xb0, 0x01, 0x23, 0xb4, 0xfe, 0xdd, 0xfe, 0xdb, 0x01, 0x68, 0x01, 0x1b, 0x01, 0x1a, 0x01, 0x68, 0x01, 0x1a, 0x01, 0x1a, 0x5a, 0xfe, 0xae, 0xfe, 0xa3, 0xfe, 0xe5, 0xfe, 0xe1, 0xfe, 0xa7, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0xfb, 0x12, 0x04, 0xee, 0xfb, 0x12, 0x04, 0xee, 0xfa, 0x2b, 0x05, 0x10, 0xfa, 0xf0, 0x00, 0x00, 0x02, 0x00, 0x61, 0x00, 0x00, 0x05, 0x6c, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x09, 0x01, 0x33, 0x01, 0x25, 0x21, 0x09, 0x01, 0x33, 0x09, 0x01, 0x21, 0x09, 0x01, 0x23, 0x01, 0x01, 0x0a, 0x03, 0x06, 0xb3, 0xfc, 0xfa, 0xfe, 0xa4, 0x01, 0x8c, 0x01, 0x51, 0x01, 0x5d, 0x58, 0xfe, 0x78, 0x02, 0x01, 0xfe, 0x74, 0xfe, 0xaf, 0xfe, 0xa3, 0x5a, 0x01, 0x8a, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0xfd, 0xce, 0x02, 0x32, 0xfd, 0x84, 0xfc, 0xa7, 0x02, 0x32, 0xfd, 0xce, 0x02, 0x7b, 0x00, 0x00, 0x00, 0x02, 0xff, 0xfc, 0x00, 0x00, 0x05, 0x1b, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x09, 0x01, 0x33, 0x01, 0x11, 0x21, 0x11, 0x01, 0x21, 0x09, 0x01, 0x23, 0x01, 0x11, 0x33, 0x03, 0x16, 0x01, 0xab, 0x5a, 0xfe, 0x25, 0xfe, 0x98, 0xfe, 0x24, 0x01, 0x6c, 0x01, 0x7f, 0xfe, 0x61, 0xb4, 0x01, 0x9e, 0xb5, 0x03, 0x13, 0x02, 0xc2, 0xfc, 0xf2, 0xfd, 0x39, 0x02, 0xc7, 0x03, 0x0e, 0xfc, 0xf2, 0x02, 0xaa, 0xfd, 0x56, 0xfd, 0x9d, 0x00, 0x04, 0x00, 0x6e, 0xff, 0xe3, 0x04, 0x1e, 0x04, 0x7b, 0x00, 0x07, 0x00, 0x22, 0x00, 0x2c, 0x00, 0x33, 0x00, 0x00, 0x01, 0x34, 0x26, 0x27, 0x16, 0x15, 0x11, 0x33, 0x13, 0x11, 0x21, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3b, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x20, 0x16, 0x01, 0x35, 0x23, 0x22, 0x07, 0x11, 0x3e, 0x01, 0x37, 0x36, 0x05, 0x11, 0x0e, 0x01, 0x15, 0x14, 0x16, 0x03, 0xc4, 0x87, 0x37, 0x44, 0x7a, 0x5a, 0xfe, 0xd2, 0x39, 0xa9, 0x4e, 0x9b, 0xb6, 0xe3, 0xe2, 0xbc, 0x6a, 0x88, 0x56, 0xa4, 0x4c, 0x6c, 0xc8, 0x33, 0x01, 0x01, 0xfe, 0xfe, 0xd2, 0xbc, 0x30, 0x2b, 0x55, 0x58, 0x35, 0x35, 0xfe, 0x8f, 0x3c, 0x7a, 0x6d, 0x02, 0x7f, 0xd3, 0x86, 0x18, 0x5d, 0x88, 0xfd, 0x59, 0x02, 0x1b, 0xfd, 0x81, 0xaa, 0x66, 0x61, 0xc1, 0xa2, 0xbd, 0xc0, 0x48, 0x7f, 0x8b, 0x2e, 0x2e, 0x74, 0x27, 0x27, 0xfc, 0xfe, 0x8b, 0x55, 0x04, 0xfd, 0xed, 0x04, 0x4e, 0x48, 0x47, 0xdc, 0x01, 0xfd, 0x12, 0x67, 0x8b, 0x77, 0x74, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x85, 0xff, 0xe3, 0x04, 0x92, 0x06, 0x14, 0x00, 0x0f, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x2d, 0x00, 0x00, 0x13, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x15, 0x21, 0x01, 0x34, 0x27, 0x26, 0x27, 0x11, 0x36, 0x37, 0x36, 0x37, 0x36, 0x01, 0x11, 0x33, 0x11, 0x01, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x85, 0x01, 0x2d, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0xfe, 0xd3, 0x03, 0xaa, 0x55, 0x27, 0x36, 0x36, 0x27, 0x34, 0x14, 0x0d, 0xfc, 0xb0, 0x79, 0x01, 0xc6, 0x16, 0x18, 0x94, 0x44, 0x45, 0x14, 0x0c, 0x55, 0x54, 0x94, 0x18, 0x16, 0x06, 0x14, 0xfd, 0xa2, 0x64, 0x61, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x61, 0x64, 0xa8, 0x02, 0x74, 0x9f, 0x82, 0x3d, 0x20, 0xfc, 0x7a, 0x20, 0x3d, 0x4f, 0x73, 0x4b, 0x03, 0xda, 0xfa, 0xac, 0x05, 0x54, 0xfe, 0x64, 0x03, 0x69, 0x68, 0x74, 0x4a, 0x9e, 0x9f, 0x82, 0x82, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x00, 0x25, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x16, 0x17, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x11, 0x16, 0x33, 0x32, 0x37, 0x36, 0x25, 0x11, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x03, 0x83, 0x45, 0x95, 0x53, 0xe4, 0xfe, 0xf4, 0x01, 0x0f, 0xeb, 0x4d, 0x92, 0x44, 0x3e, 0x62, 0x40, 0x43, 0x4f, 0x41, 0x3d, 0x49, 0x49, 0x41, 0x4e, 0xfe, 0x48, 0x27, 0x21, 0x6e, 0x6e, 0x20, 0x8f, 0x64, 0x24, 0x24, 0x01, 0x3e, 0x01, 0x0e, 0x01, 0x12, 0x01, 0x3a, 0x23, 0x23, 0x64, 0x1f, 0x18, 0x0f, 0x14, 0xfc, 0x57, 0x13, 0x10, 0x13, 0x1b, 0x03, 0x53, 0x1a, 0x25, 0x80, 0xea, 0xe6, 0x83, 0x26, 0x00, 0x00, 0x00, 0x04, 0x00, 0x85, 0xff, 0xe3, 0x04, 0x92, 0x06, 0x14, 0x00, 0x0f, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x21, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x10, 0x12, 0x33, 0x32, 0x16, 0x01, 0x14, 0x17, 0x16, 0x17, 0x16, 0x17, 0x11, 0x06, 0x07, 0x06, 0x01, 0x11, 0x33, 0x11, 0x01, 0x11, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x03, 0x64, 0x01, 0x2d, 0xfe, 0xd3, 0x34, 0x9f, 0x70, 0xb6, 0xe6, 0xe6, 0xb6, 0x70, 0x9f, 0xfd, 0xb7, 0x0e, 0x14, 0x33, 0x28, 0x36, 0x36, 0x28, 0x55, 0x02, 0xd7, 0x79, 0xfd, 0xc1, 0x16, 0x18, 0x94, 0x54, 0x56, 0x0d, 0x14, 0x45, 0x44, 0x94, 0x18, 0x03, 0xb6, 0x02, 0x5e, 0xf9, 0xec, 0xa8, 0x64, 0x61, 0x01, 0x44, 0x02, 0x10, 0x01, 0x44, 0x61, 0xfe, 0x5a, 0x9e, 0x4b, 0x73, 0x4f, 0x3d, 0x20, 0x03, 0x86, 0x20, 0x3d, 0x82, 0x02, 0x9d, 0xfa, 0xac, 0x05, 0x54, 0xfe, 0x64, 0xfc, 0x36, 0x03, 0x82, 0x82, 0x9f, 0x9e, 0x4a, 0x74, 0x68, 0x69, 0x00, 0x00, 0x03, 0x00, 0x63, 0xff, 0xe3, 0x04, 0x0b, 0x04, 0x7b, 0x00, 0x13, 0x00, 0x18, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x21, 0x13, 0x16, 0x33, 0x32, 0x37, 0x15, 0x0e, 0x01, 0x23, 0x22, 0x00, 0x11, 0x10, 0x00, 0x33, 0x32, 0x12, 0x15, 0x01, 0x06, 0x11, 0x12, 0x17, 0x13, 0x21, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x04, 0x0a, 0xfd, 0xca, 0x01, 0x43, 0x56, 0xc3, 0xb0, 0x62, 0xb0, 0x60, 0xf1, 0xfe, 0xe6, 0x01, 0x0b, 0xe3, 0xce, 0xea, 0xfd, 0x6c, 0xb2, 0x01, 0xb1, 0x5f, 0x01, 0xce, 0x03, 0xb8, 0x98, 0x42, 0x3a, 0x02, 0x04, 0xfe, 0x62, 0x15, 0x5d, 0x75, 0x2d, 0x29, 0x01, 0x38, 0x01, 0x0a, 0x01, 0x13, 0x01, 0x43, 0xfe, 0xda, 0xf7, 0x01, 0x71, 0x7a, 0xfe, 0xdb, 0xfe, 0xf3, 0x8e, 0x01, 0xd3, 0xbe, 0xe7, 0x11, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x00, 0x03, 0x80, 0x06, 0x14, 0x00, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x15, 0x11, 0x33, 0x11, 0x34, 0x37, 0x36, 0x25, 0x15, 0x23, 0x22, 0x07, 0x06, 0x1d, 0x01, 0x21, 0x15, 0x21, 0x11, 0x21, 0x11, 0x23, 0x35, 0x33, 0x35, 0x34, 0x37, 0x36, 0x33, 0x01, 0xdc, 0x5d, 0x29, 0x33, 0x79, 0x14, 0x10, 0x01, 0xc0, 0x9d, 0x85, 0x34, 0x34, 0x01, 0x5d, 0xfe, 0xa3, 0xfe, 0xd3, 0x9f, 0x9f, 0x4e, 0x4f, 0xa9, 0x05, 0xae, 0x0a, 0x2d, 0x38, 0x91, 0xfb, 0xb6, 0x04, 0x4a, 0x5f, 0x44, 0x38, 0x8b, 0x64, 0x39, 0x37, 0x92, 0x64, 0x64, 0xfc, 0x1a, 0x03, 0xe6, 0x64, 0x64, 0xbc, 0x54, 0x56, 0x00, 0x00, 0x04, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x72, 0x04, 0x7b, 0x00, 0x07, 0x00, 0x23, 0x00, 0x2e, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x11, 0x14, 0x07, 0x16, 0x36, 0x19, 0x01, 0x01, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x21, 0x11, 0x10, 0x00, 0x21, 0x22, 0x26, 0x03, 0x14, 0x17, 0x16, 0x17, 0x11, 0x06, 0x07, 0x06, 0x07, 0x06, 0x01, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x03, 0x9f, 0x5f, 0x04, 0xd4, 0xfc, 0xc7, 0x49, 0x8e, 0x4a, 0xa3, 0xa2, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0x01, 0x2d, 0xfe, 0xf3, 0xfe, 0xec, 0x67, 0xb5, 0x6d, 0x54, 0x28, 0x36, 0x36, 0x28, 0x33, 0x14, 0x0d, 0x01, 0x10, 0x17, 0x17, 0x95, 0x43, 0x46, 0x14, 0x0c, 0x55, 0x54, 0x95, 0x17, 0x17, 0x03, 0xfa, 0xfc, 0x3d, 0xca, 0x8c, 0x05, 0x9d, 0x01, 0x12, 0x03, 0x6f, 0xfa, 0x97, 0x80, 0x2c, 0x2a, 0xbd, 0xbf, 0x71, 0x64, 0x61, 0x01, 0x44, 0x02, 0x10, 0x01, 0x44, 0x61, 0x64, 0xa8, 0xfc, 0x2d, 0xfe, 0xe2, 0xfe, 0xe9, 0x1d, 0x03, 0x77, 0x9f, 0x82, 0x3d, 0x20, 0x03, 0x86, 0x20, 0x3d, 0x4f, 0x73, 0x4b, 0xfd, 0xc2, 0x03, 0x69, 0x68, 0x74, 0x4a, 0x9e, 0x9f, 0x82, 0x82, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xc1, 0x06, 0x14, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x22, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x15, 0x11, 0x33, 0x11, 0x34, 0x27, 0x26, 0x01, 0x11, 0x33, 0x11, 0x27, 0x21, 0x11, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x21, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x21, 0x03, 0x9a, 0x08, 0x07, 0x40, 0x7e, 0x4b, 0x30, 0xfd, 0x15, 0x7a, 0xd4, 0x01, 0x2e, 0x42, 0xb2, 0x74, 0xbf, 0xc5, 0xfe, 0xce, 0x61, 0x60, 0x73, 0x86, 0xfe, 0xd2, 0x04, 0x0d, 0x0b, 0x0c, 0x68, 0xbe, 0xfd, 0x94, 0x02, 0x40, 0xc1, 0x5b, 0x3a, 0x01, 0xb6, 0xfa, 0xb4, 0x05, 0x4c, 0x64, 0xfd, 0x9e, 0x65, 0x64, 0xef, 0xe8, 0xfd, 0x5c, 0x02, 0xd0, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x55, 0x00, 0x03, 0x00, 0xcf, 0x00, 0x00, 0x01, 0xfd, 0x06, 0x14, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x03, 0x33, 0x15, 0x23, 0x07, 0x21, 0x11, 0x21, 0x01, 0x29, 0x79, 0x90, 0xa7, 0xa7, 0x43, 0x01, 0x2d, 0xfe, 0xd3, 0x03, 0xfc, 0xfc, 0x68, 0x03, 0x98, 0x02, 0x18, 0xe9, 0xcb, 0xfb, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xdb, 0xfe, 0x56, 0x01, 0xd8, 0x06, 0x14, 0x00, 0x08, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x00, 0x05, 0x11, 0x23, 0x11, 0x14, 0x07, 0x36, 0x37, 0x36, 0x07, 0x23, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x21, 0x11, 0x14, 0x07, 0x06, 0x03, 0x33, 0x15, 0x23, 0x01, 0x7e, 0x7a, 0x21, 0x40, 0x24, 0x37, 0xdc, 0xc7, 0x2c, 0x61, 0x21, 0x21, 0x01, 0x2e, 0x49, 0x4a, 0x57, 0xa5, 0xa5, 0x16, 0x04, 0x12, 0xfb, 0xd0, 0xb5, 0x54, 0x0f, 0x30, 0x48, 0xf4, 0x64, 0x30, 0x31, 0x99, 0x04, 0xac, 0xfb, 0x8c, 0xd6, 0x60, 0x60, 0x07, 0xbe, 0xe9, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xad, 0x06, 0x14, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x00, 0x13, 0x21, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x21, 0x13, 0x11, 0x33, 0x11, 0xa7, 0x01, 0x2e, 0x02, 0x43, 0x7e, 0xfd, 0x8e, 0x02, 0x89, 0x87, 0xfd, 0xaf, 0xfe, 0xd2, 0x5a, 0x7a, 0x06, 0x14, 0xfc, 0x69, 0x01, 0xe3, 0xfd, 0xf6, 0xfd, 0xaa, 0x02, 0x23, 0xfd, 0xdd, 0x05, 0xb0, 0xfa, 0xb4, 0x05, 0x4c, 0x00, 0x02, 0x00, 0xcf, 0x00, 0x00, 0x02, 0xa0, 0x06, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x01, 0x14, 0x17, 0x16, 0x17, 0x26, 0x35, 0x11, 0x23, 0x13, 0x22, 0x27, 0x26, 0x35, 0x11, 0x21, 0x11, 0x14, 0x16, 0x33, 0x15, 0x01, 0x29, 0x37, 0x24, 0x40, 0x22, 0x79, 0xdd, 0xa4, 0x4a, 0x49, 0x01, 0x2d, 0x45, 0x5e, 0x01, 0x94, 0xa0, 0x48, 0x30, 0x0f, 0x54, 0xb5, 0x04, 0x30, 0xfa, 0x5a, 0x60, 0x60, 0xd6, 0x04, 0x7e, 0xfb, 0x4a, 0x9c, 0x5e, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0xa7, 0x00, 0x00, 0x07, 0xad, 0x04, 0x7b, 0x00, 0x22, 0x00, 0x26, 0x00, 0x31, 0x00, 0x3c, 0x00, 0x00, 0x13, 0x21, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x21, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x21, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x21, 0x13, 0x11, 0x33, 0x11, 0x25, 0x16, 0x17, 0x16, 0x15, 0x11, 0x33, 0x11, 0x34, 0x27, 0x26, 0x25, 0x16, 0x17, 0x16, 0x15, 0x11, 0x33, 0x11, 0x34, 0x27, 0x26, 0xa7, 0x01, 0x2e, 0x42, 0xb2, 0x74, 0xbf, 0x8d, 0x18, 0x4c, 0xc8, 0x74, 0xbf, 0xc5, 0xfe, 0xce, 0x61, 0x60, 0x73, 0x86, 0xfe, 0xce, 0x61, 0x60, 0x73, 0x86, 0xfe, 0xd2, 0x5a, 0x7a, 0x02, 0x1f, 0x08, 0x07, 0x40, 0x7e, 0x4b, 0x30, 0x02, 0x9a, 0x08, 0x07, 0x40, 0x7e, 0x4b, 0x30, 0x04, 0x60, 0xae, 0x65, 0x64, 0xac, 0x4a, 0x80, 0x76, 0xef, 0xe8, 0xfd, 0x5c, 0x02, 0xd0, 0x9f, 0x9e, 0xbe, 0xab, 0xfd, 0x5c, 0x02, 0xd0, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x55, 0x03, 0xfc, 0xfc, 0x68, 0x03, 0x98, 0x11, 0x0b, 0x0c, 0x68, 0xbe, 0xfd, 0x94, 0x02, 0x40, 0xc1, 0x5b, 0x3a, 0x13, 0x0b, 0x0c, 0x68, 0xbe, 0xfd, 0x94, 0x02, 0x40, 0xc1, 0x5b, 0x3a, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xc1, 0x04, 0x7b, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x22, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x15, 0x11, 0x33, 0x11, 0x34, 0x27, 0x26, 0x25, 0x11, 0x33, 0x11, 0x27, 0x21, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x11, 0x21, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x21, 0x03, 0x9a, 0x08, 0x07, 0x40, 0x7e, 0x4b, 0x30, 0xfd, 0x15, 0x7a, 0xd4, 0x01, 0x2e, 0x42, 0xb2, 0x74, 0xbf, 0xc5, 0xfe, 0xce, 0x61, 0x60, 0x73, 0x86, 0xfe, 0xd2, 0x04, 0x0d, 0x0b, 0x0c, 0x68, 0xbe, 0xfd, 0x94, 0x02, 0x40, 0xc1, 0x5b, 0x3a, 0x02, 0xfc, 0x68, 0x03, 0x98, 0x64, 0xae, 0x65, 0x64, 0xef, 0xe8, 0xfd, 0x5c, 0x02, 0xd0, 0x9f, 0x9e, 0xbe, 0xa4, 0xfd, 0x55, 0x00, 0x00, 0x00, 0x04, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x00, 0x0b, 0x00, 0x13, 0x00, 0x1b, 0x00, 0x23, 0x00, 0x00, 0x01, 0x32, 0x12, 0x11, 0x10, 0x02, 0x23, 0x22, 0x02, 0x11, 0x10, 0x12, 0x13, 0x16, 0x32, 0x37, 0x11, 0x26, 0x22, 0x07, 0x03, 0x11, 0x06, 0x07, 0x06, 0x10, 0x17, 0x16, 0x01, 0x11, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x02, 0x34, 0xd8, 0xf7, 0xf7, 0xd8, 0xd9, 0xf5, 0xf5, 0x75, 0x2e, 0x6c, 0x2e, 0x2e, 0x6c, 0x2e, 0x5a, 0x2e, 0x24, 0x64, 0x64, 0x24, 0x01, 0xaa, 0x2e, 0x24, 0x65, 0x65, 0x24, 0x04, 0x7b, 0xfe, 0xc8, 0xfe, 0xec, 0xfe, 0xed, 0xfe, 0xc7, 0x01, 0x39, 0x01, 0x13, 0x01, 0x14, 0x01, 0x38, 0xfb, 0xd7, 0x0b, 0x0b, 0x03, 0xba, 0x0b, 0x0b, 0xfc, 0x6b, 0x03, 0x70, 0x1d, 0x2d, 0x80, 0xfe, 0x24, 0x80, 0x2d, 0x03, 0x52, 0xfc, 0x92, 0x1c, 0x2d, 0x81, 0x01, 0xdb, 0x80, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x72, 0x04, 0x7b, 0x00, 0x0f, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x2d, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x21, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x22, 0x26, 0x01, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x11, 0x36, 0x37, 0x36, 0x01, 0x11, 0x23, 0x11, 0x01, 0x11, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x01, 0x92, 0xfe, 0xd4, 0x01, 0x2c, 0x34, 0xa0, 0x6f, 0xb7, 0xe6, 0xe6, 0xb7, 0x6f, 0xa0, 0x02, 0x4a, 0x0e, 0x14, 0x33, 0x28, 0x36, 0x36, 0x28, 0x55, 0xfd, 0x28, 0x78, 0x02, 0x3f, 0x17, 0x17, 0x95, 0x53, 0x56, 0x0d, 0x14, 0x45, 0x43, 0x95, 0x17, 0xa8, 0xfd, 0xae, 0x06, 0x08, 0xa8, 0x64, 0x61, 0xfe, 0xbc, 0xfd, 0xf0, 0xfe, 0xbc, 0x61, 0x01, 0xa6, 0x9e, 0x4b, 0x73, 0x4f, 0x3d, 0x20, 0xfc, 0x7a, 0x20, 0x3d, 0x82, 0xfd, 0x6f, 0x05, 0x48, 0xfa, 0xb8, 0x01, 0x90, 0x03, 0xca, 0x03, 0x82, 0x82, 0x9f, 0x9e, 0x4a, 0x74, 0x68, 0x69, 0x00, 0x00, 0x00, 0x04, 0x00, 0x65, 0xfe, 0x56, 0x04, 0x72, 0x04, 0x7b, 0x00, 0x0f, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x2d, 0x00, 0x00, 0x25, 0x0e, 0x01, 0x23, 0x22, 0x02, 0x10, 0x12, 0x33, 0x32, 0x16, 0x17, 0x35, 0x21, 0x11, 0x21, 0x01, 0x14, 0x17, 0x16, 0x17, 0x11, 0x06, 0x07, 0x06, 0x07, 0x06, 0x01, 0x33, 0x11, 0x23, 0x01, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x03, 0x45, 0x34, 0x9f, 0x70, 0xb7, 0xe5, 0xe5, 0xb7, 0x70, 0x9f, 0x34, 0x01, 0x2d, 0xfe, 0xd3, 0xfd, 0x83, 0x54, 0x28, 0x36, 0x36, 0x28, 0x33, 0x14, 0x0d, 0x02, 0xd7, 0x79, 0x79, 0xfe, 0x39, 0x17, 0x17, 0x95, 0x43, 0x46, 0x14, 0x0c, 0x55, 0x54, 0x95, 0x17, 0x17, 0xa8, 0x64, 0x61, 0x01, 0x44, 0x02, 0x10, 0x01, 0x44, 0x61, 0x64, 0xa8, 0xf9, 0xf8, 0x03, 0x94, 0x9f, 0x82, 0x3d, 0x20, 0x03, 0x86, 0x20, 0x3d, 0x4f, 0x73, 0x4b, 0xfc, 0x32, 0x05, 0x48, 0xfc, 0x48, 0x03, 0x69, 0x68, 0x74, 0x4a, 0x9e, 0x9f, 0x82, 0x82, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x03, 0x7c, 0x04, 0x7b, 0x00, 0x03, 0x00, 0x15, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x27, 0x21, 0x15, 0x3e, 0x01, 0x33, 0x32, 0x1f, 0x01, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x11, 0x21, 0x01, 0x01, 0x79, 0xd3, 0x01, 0x2d, 0x34, 0xa8, 0x77, 0x19, 0x0d, 0x2f, 0x1c, 0x42, 0x27, 0x8d, 0x96, 0xfe, 0xd3, 0x03, 0xfc, 0xfc, 0x68, 0x03, 0x98, 0x64, 0xae, 0x66, 0x63, 0x03, 0x07, 0x85, 0x12, 0x11, 0xcb, 0xbe, 0xfd, 0x7a, 0x00, 0x02, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x04, 0x7b, 0x00, 0x1d, 0x00, 0x45, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x1f, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x03, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x01, 0x45, 0x23, 0x19, 0x44, 0x22, 0x23, 0x66, 0x2f, 0x94, 0x37, 0x3c, 0x22, 0x22, 0x1a, 0x4c, 0x26, 0x2a, 0x77, 0x2d, 0x82, 0x33, 0x40, 0xbe, 0x4b, 0x90, 0x47, 0x5f, 0x66, 0x45, 0x82, 0x2f, 0x81, 0x6a, 0xca, 0xb9, 0x5c, 0xa2, 0x44, 0x42, 0x53, 0x56, 0x63, 0x65, 0x48, 0x6c, 0x2e, 0x91, 0x76, 0xde, 0xc2, 0x51, 0xb0, 0x61, 0x03, 0xf9, 0x0f, 0x17, 0x3d, 0x76, 0x66, 0x30, 0x33, 0x22, 0x10, 0x33, 0x3b, 0x40, 0x7b, 0x52, 0x3f, 0x10, 0x17, 0x42, 0x73, 0x6c, 0x33, 0x37, 0x27, 0x0f, 0x2a, 0x37, 0x43, 0x6f, 0x54, 0xfc, 0xfe, 0x37, 0x38, 0x5e, 0x55, 0x4e, 0x4f, 0x2c, 0x10, 0x2c, 0x97, 0x88, 0xa6, 0xb5, 0x20, 0x1f, 0x7a, 0x31, 0x24, 0x59, 0x58, 0x44, 0x4c, 0x23, 0x0f, 0x2f, 0x9e, 0x90, 0xa4, 0xc0, 0x25, 0x25, 0x00, 0x02, 0x00, 0x31, 0x00, 0x00, 0x03, 0x2e, 0x05, 0x9e, 0x00, 0x07, 0x00, 0x1b, 0x00, 0x00, 0x25, 0x26, 0x37, 0x11, 0x23, 0x11, 0x06, 0x16, 0x13, 0x11, 0x21, 0x15, 0x21, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x21, 0x22, 0x26, 0x35, 0x11, 0x23, 0x35, 0x33, 0x11, 0x01, 0xa2, 0x26, 0x02, 0x79, 0x01, 0x53, 0x81, 0x01, 0x56, 0xfe, 0xaa, 0x44, 0x68, 0xaa, 0xfe, 0xce, 0xbf, 0x92, 0x79, 0x79, 0x6a, 0x55, 0x7c, 0x03, 0xff, 0xfc, 0x37, 0xad, 0x4e, 0x05, 0x28, 0xfe, 0xac, 0x64, 0xfd, 0x55, 0x89, 0x4e, 0x64, 0x9f, 0xd2, 0x02, 0x75, 0x64, 0x01, 0x54, 0x00, 0x00, 0x03, 0x00, 0x9f, 0xff, 0xe5, 0x04, 0xbe, 0x04, 0x60, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27, 0x26, 0x35, 0x11, 0x23, 0x11, 0x14, 0x17, 0x16, 0x05, 0x11, 0x23, 0x11, 0x17, 0x21, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x11, 0x21, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x21, 0x01, 0xc6, 0x08, 0x07, 0x40, 0x7e, 0x4b, 0x30, 0x02, 0xef, 0x79, 0xd3, 0xfe, 0xce, 0x41, 0xb3, 0x74, 0xbf, 0xc5, 0x01, 0x32, 0x61, 0x60, 0x73, 0x86, 0x01, 0x32, 0x53, 0x0b, 0x0c, 0x68, 0xbe, 0x02, 0x6c, 0xfd, 0xc0, 0xc1, 0x5b, 0x3a, 0x02, 0x03, 0x98, 0xfc, 0x68, 0x64, 0xae, 0x65, 0x64, 0xef, 0xe8, 0x02, 0xa4, 0xfd, 0x30, 0x9f, 0x9e, 0xbe, 0xa4, 0x02, 0xab, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x04, 0x39, 0x04, 0x60, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x13, 0x01, 0x33, 0x01, 0x27, 0x21, 0x09, 0x01, 0x33, 0x01, 0x21, 0xb8, 0x01, 0x37, 0x76, 0xfe, 0xc6, 0xf4, 0x01, 0x32, 0x01, 0x3b, 0x01, 0x3b, 0x5a, 0xfe, 0x86, 0xfe, 0xf2, 0x03, 0xfc, 0xfc, 0x68, 0x03, 0x98, 0x64, 0xfc, 0x54, 0x03, 0xac, 0xfb, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4d, 0x00, 0x00, 0x06, 0x41, 0x04, 0x60, 0x00, 0x03, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x01, 0x13, 0x33, 0x03, 0x21, 0x13, 0x33, 0x03, 0x27, 0x21, 0x1b, 0x01, 0x21, 0x1b, 0x01, 0x33, 0x01, 0x21, 0x0b, 0x01, 0x21, 0x03, 0x8c, 0xd8, 0x7a, 0xda, 0xfc, 0xbe, 0xd8, 0x7a, 0xda, 0xed, 0x01, 0x32, 0xcf, 0xce, 0x01, 0x2d, 0xcf, 0xce, 0x5a, 0xfe, 0xf8, 0xfe, 0xea, 0xd9, 0xda, 0xfe, 0xe6, 0x03, 0xfc, 0xfc, 0x68, 0x03, 0x98, 0xfc, 0x68, 0x03, 0x98, 0x64, 0xfc, 0x96, 0x03, 0x6a, 0xfc, 0x96, 0x03, 0x6a, 0xfb, 0xa0, 0x03, 0x96, 0xfc, 0x6a, 0x00, 0x02, 0x00, 0x44, 0x00, 0x00, 0x04, 0x9a, 0x04, 0x60, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x13, 0x01, 0x33, 0x01, 0x25, 0x21, 0x09, 0x01, 0x33, 0x09, 0x01, 0x21, 0x09, 0x01, 0x23, 0x01, 0xf8, 0x02, 0x66, 0x88, 0xfd, 0x99, 0xfe, 0xc5, 0x01, 0x68, 0x01, 0x01, 0x01, 0x00, 0x70, 0xfe, 0xc8, 0x01, 0xb4, 0xfe, 0x98, 0xff, 0x00, 0xfe, 0xff, 0x6f, 0x01, 0x38, 0x03, 0xfc, 0xfc, 0x68, 0x03, 0x98, 0x64, 0xfe, 0x81, 0x01, 0x7f, 0xfe, 0x2d, 0xfd, 0x73, 0x01, 0x7f, 0xfe, 0x81, 0x01, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x4a, 0x04, 0x60, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x13, 0x01, 0x37, 0x01, 0x27, 0x21, 0x09, 0x01, 0x33, 0x01, 0x0e, 0x01, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x37, 0xbd, 0x01, 0x87, 0x37, 0xfe, 0xba, 0xfe, 0x01, 0x3b, 0x01, 0x3a, 0x01, 0x3c, 0x61, 0xfe, 0x45, 0x48, 0x83, 0x70, 0x84, 0x84, 0x4f, 0x49, 0x27, 0x03, 0xfc, 0xfb, 0xdb, 0x99, 0x03, 0x8c, 0x64, 0xfc, 0x97, 0x03, 0x69, 0xfb, 0x38, 0xc7, 0x7b, 0x64, 0x43, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4f, 0x00, 0x00, 0x03, 0xf2, 0x04, 0x60, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x09, 0x01, 0x33, 0x01, 0x25, 0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x21, 0x03, 0x06, 0xfd, 0xb7, 0x7e, 0x02, 0x49, 0xfc, 0xe2, 0x03, 0x8c, 0xfd, 0xb8, 0x02, 0x48, 0xfc, 0x5d, 0x02, 0x48, 0xfd, 0xcf, 0x03, 0xfc, 0xfc, 0x68, 0x03, 0x98, 0x64, 0x64, 0xfc, 0x68, 0x64, 0x64, 0x03, 0x98, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x24, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x6e, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x25, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xa4, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x26, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x1f, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x27, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x17, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x28, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xba, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x29, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x04, 0xfe, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x2a, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x87, 0x00, 0x00, 0x02, 0xab, 0x05, 0xd5, 0x10, 0x06, 0x11, 0x48, 0x00, 0x00, 0xff, 0xff, 0xff, 0xa0, 0xfe, 0x66, 0x01, 0x6b, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x2d, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xe0, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x2e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x03, 0xf9, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x05, 0x83, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x30, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xae, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xff, 0xe3, 0x05, 0x44, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0x19, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x33, 0x00, 0x00, 0xff, 0xff, 0x00, 0x67, 0xfe, 0xf8, 0x05, 0x44, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x34, 0x00, 0x00, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x00, 0x04, 0xcc, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x35, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x2c, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x36, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfa, 0x00, 0x00, 0x04, 0x6c, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x37, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa0, 0xff, 0xe3, 0x04, 0xa5, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x38, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0x04, 0xde, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x39, 0x00, 0x00, 0xff, 0xff, 0x00, 0x3d, 0x00, 0x00, 0x06, 0xe3, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x3a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0xb6, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x04, 0x6a, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x3c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x52, 0x00, 0x00, 0x04, 0x9c, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x6e, 0xff, 0xe3, 0x03, 0xc3, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x44, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xff, 0xe3, 0x04, 0x2e, 0x06, 0x14, 0x10, 0x06, 0x00, 0x45, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0x84, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x46, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x03, 0xeb, 0x06, 0x14, 0x10, 0x06, 0x00, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x0c, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x48, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, 0x06, 0x14, 0x10, 0x06, 0x00, 0x49, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x4a, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x06, 0x14, 0x10, 0x06, 0x00, 0x4b, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x01, 0x54, 0x06, 0x14, 0x10, 0x06, 0x00, 0x4c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xde, 0xfe, 0x56, 0x01, 0x54, 0x06, 0x14, 0x10, 0x06, 0x00, 0x4d, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x26, 0x06, 0x14, 0x10, 0x06, 0x00, 0x4e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xad, 0x00, 0x00, 0x02, 0x01, 0x06, 0x14, 0x10, 0x06, 0x11, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x06, 0x67, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x03, 0xf4, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x51, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x03, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x52, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0xfe, 0x56, 0x04, 0x2e, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x53, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xfe, 0x56, 0x03, 0xeb, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x54, 0x00, 0x00, 0xff, 0xff, 0x00, 0xa7, 0x00, 0x00, 0x02, 0xf6, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x55, 0x00, 0x00, 0xff, 0xff, 0x00, 0x63, 0xff, 0xe3, 0x03, 0x67, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x56, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0x00, 0x00, 0x02, 0xa7, 0x05, 0x9e, 0x10, 0x06, 0x00, 0x57, 0x00, 0x00, 0xff, 0xff, 0x00, 0x9c, 0xff, 0xe3, 0x03, 0xe9, 0x04, 0x7b, 0x10, 0x06, 0x00, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0x00, 0x00, 0x04, 0x0c, 0x04, 0x60, 0x10, 0x06, 0x00, 0x59, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x97, 0x04, 0x60, 0x10, 0x06, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x35, 0x00, 0x00, 0x04, 0x07, 0x04, 0x60, 0x10, 0x06, 0x00, 0x5b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x36, 0xfe, 0x56, 0x04, 0x0c, 0x04, 0x60, 0x10, 0x06, 0x00, 0x5c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4f, 0x00, 0x00, 0x03, 0x79, 0x04, 0x60, 0x10, 0x06, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x7a, 0xff, 0xe3, 0x04, 0x1c, 0x05, 0xf0, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x19, 0x00, 0x00, 0x00, 0x20, 0x12, 0x10, 0x02, 0x20, 0x02, 0x10, 0x01, 0x36, 0x11, 0x10, 0x2f, 0x01, 0x26, 0x22, 0x07, 0x11, 0x16, 0x32, 0x37, 0x01, 0x06, 0x11, 0x10, 0x17, 0x01, 0x68, 0x01, 0xc4, 0xef, 0xef, 0xfe, 0x3c, 0xee, 0x02, 0x90, 0xb7, 0xb7, 0x5a, 0x2e, 0x6f, 0x2f, 0x2f, 0x6f, 0x2e, 0xfe, 0xda, 0xb6, 0xb6, 0x05, 0xf0, 0xfe, 0x73, 0xfd, 0x0d, 0xfe, 0x73, 0x01, 0x8d, 0x02, 0xf3, 0xfc, 0x23, 0x8f, 0x01, 0xd4, 0x01, 0xd5, 0x8f, 0x30, 0x0f, 0x0f, 0xfa, 0xd9, 0x0f, 0x0f, 0x04, 0xf7, 0x90, 0xfe, 0x2c, 0xfe, 0x2d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x60, 0x00, 0x00, 0x04, 0x35, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x11, 0x33, 0x11, 0x37, 0x11, 0x21, 0x15, 0x21, 0x35, 0x21, 0x11, 0x05, 0x35, 0x25, 0x01, 0xfd, 0xb6, 0x58, 0x01, 0x29, 0xfc, 0x46, 0x01, 0x29, 0xfe, 0xbd, 0x01, 0x43, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0xfa, 0x8f, 0x64, 0x64, 0x05, 0x0d, 0x48, 0x64, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x75, 0x00, 0x00, 0x04, 0x25, 0x05, 0xf0, 0x00, 0x10, 0x00, 0x28, 0x00, 0x00, 0x37, 0x33, 0x01, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x27, 0x17, 0x16, 0x15, 0x14, 0x0e, 0x01, 0x0b, 0x01, 0x36, 0x33, 0x32, 0x04, 0x15, 0x14, 0x0e, 0x01, 0x07, 0x03, 0x21, 0x15, 0x21, 0x37, 0x36, 0x00, 0x37, 0x36, 0x10, 0x26, 0x23, 0x22, 0x07, 0xe2, 0xe6, 0x01, 0x0c, 0x56, 0x1f, 0x44, 0x61, 0x3d, 0x59, 0x03, 0x51, 0x3e, 0x75, 0xbc, 0xfd, 0xe9, 0xa3, 0xdb, 0x01, 0x02, 0x2b, 0x49, 0x54, 0xec, 0x01, 0xf1, 0xfc, 0x51, 0x01, 0x02, 0x01, 0x74, 0x37, 0x6d, 0x79, 0x63, 0x88, 0xae, 0x64, 0x01, 0xcd, 0x95, 0x40, 0x8f, 0x01, 0x39, 0x5c, 0x39, 0x18, 0x04, 0x70, 0xa8, 0x64, 0xba, 0xcf, 0xfe, 0xdd, 0x04, 0x39, 0x68, 0xf4, 0xcc, 0x62, 0xac, 0x96, 0x91, 0xfe, 0x69, 0x64, 0x64, 0x05, 0x02, 0x41, 0x62, 0xbf, 0x01, 0x19, 0xa8, 0x95, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x8c, 0xff, 0xe3, 0x04, 0x02, 0x05, 0xf0, 0x00, 0x24, 0x00, 0x2a, 0x00, 0x30, 0x00, 0x00, 0x05, 0x22, 0x27, 0x35, 0x17, 0x16, 0x33, 0x32, 0x37, 0x11, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x11, 0x26, 0x23, 0x22, 0x0f, 0x01, 0x35, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x04, 0x35, 0x36, 0x35, 0x34, 0x26, 0x27, 0x19, 0x01, 0x3e, 0x01, 0x35, 0x34, 0x01, 0xf4, 0xa9, 0xbf, 0x1e, 0xb0, 0x9a, 0x5a, 0x48, 0x31, 0x39, 0xb7, 0xbe, 0x35, 0x2e, 0x35, 0x44, 0x8d, 0xc3, 0x18, 0xcf, 0x9d, 0xcf, 0xf2, 0x7f, 0x73, 0x7f, 0x92, 0xfe, 0xef, 0xb7, 0x69, 0x4e, 0x3e, 0x5a, 0x1d, 0x4a, 0x6a, 0x0c, 0x44, 0x10, 0x02, 0x95, 0x0a, 0x64, 0x08, 0x02, 0x20, 0x0a, 0x3c, 0x08, 0x68, 0x40, 0xd1, 0xb2, 0x7c, 0xaa, 0x21, 0x1f, 0xc5, 0x90, 0xdd, 0xf2, 0x92, 0x55, 0xe8, 0x6c, 0x8d, 0x24, 0x02, 0x96, 0xfe, 0x1a, 0x1d, 0x79, 0x58, 0xac, 0x00, 0x03, 0x00, 0x51, 0x00, 0x00, 0x04, 0x40, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x06, 0x00, 0x11, 0x00, 0x00, 0x01, 0x23, 0x13, 0x33, 0x09, 0x01, 0x21, 0x03, 0x21, 0x11, 0x33, 0x15, 0x23, 0x11, 0x21, 0x11, 0x21, 0x35, 0x03, 0x4a, 0xb7, 0x03, 0xb4, 0xfe, 0xf2, 0xfe, 0x7c, 0x01, 0x84, 0x03, 0x01, 0x6b, 0x9b, 0x9b, 0xfe, 0x98, 0xfe, 0x15, 0x05, 0x71, 0xfa, 0xf3, 0x04, 0xc1, 0xfc, 0xe3, 0x03, 0xcd, 0xfc, 0x33, 0x64, 0xfe, 0x5c, 0x01, 0xa4, 0x7f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x85, 0xff, 0xe3, 0x04, 0x18, 0x05, 0xd5, 0x00, 0x04, 0x00, 0x08, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x11, 0x23, 0x11, 0x36, 0x01, 0x36, 0x10, 0x27, 0x03, 0x11, 0x26, 0x23, 0x22, 0x07, 0x11, 0x21, 0x15, 0x21, 0x11, 0x1e, 0x01, 0x10, 0x04, 0x21, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x01, 0xcc, 0xb4, 0x5d, 0x01, 0x8a, 0xb7, 0xb7, 0x5a, 0x2c, 0x60, 0xa2, 0xb9, 0x02, 0xf7, 0xfe, 0x71, 0xf6, 0xfc, 0xfe, 0xf2, 0xfe, 0xdd, 0xa7, 0xbb, 0xaa, 0xc6, 0x74, 0x03, 0x91, 0x01, 0xe0, 0xfd, 0xfd, 0x1b, 0xfc, 0xe6, 0x5c, 0x01, 0xdc, 0x60, 0xfd, 0x49, 0x02, 0xd7, 0x0a, 0x4b, 0x02, 0xef, 0x64, 0xfe, 0x23, 0x09, 0xf5, 0xfe, 0x46, 0xf9, 0x3c, 0x88, 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x33, 0x05, 0xf0, 0x00, 0x04, 0x00, 0x09, 0x00, 0x11, 0x00, 0x25, 0x00, 0x00, 0x25, 0x36, 0x11, 0x10, 0x27, 0x01, 0x06, 0x11, 0x10, 0x1f, 0x01, 0x16, 0x32, 0x37, 0x11, 0x26, 0x22, 0x07, 0x13, 0x32, 0x17, 0x15, 0x27, 0x26, 0x20, 0x07, 0x11, 0x36, 0x33, 0x32, 0x12, 0x10, 0x02, 0x23, 0x20, 0x02, 0x10, 0x00, 0x03, 0x23, 0xb6, 0xb6, 0xfe, 0x55, 0xb8, 0xb8, 0x5a, 0x34, 0x9a, 0x29, 0x24, 0x9a, 0x39, 0xdc, 0x96, 0x97, 0x1e, 0x8a, 0xfe, 0xf4, 0x55, 0x3c, 0x5d, 0xdd, 0xeb, 0xf5, 0xde, 0xfe, 0xfc, 0xf6, 0x01, 0x2e, 0x70, 0x63, 0x01, 0x0c, 0x01, 0x18, 0x5c, 0x01, 0xca, 0xb3, 0xfe, 0x91, 0xfe, 0x23, 0x95, 0x32, 0x10, 0x08, 0x03, 0x22, 0x06, 0x13, 0x02, 0x8c, 0x3c, 0x6a, 0x0c, 0x36, 0x2d, 0xfe, 0x66, 0x16, 0xfe, 0xef, 0xfe, 0x2f, 0xfe, 0xea, 0x01, 0x8d, 0x02, 0xdb, 0x01, 0xa5, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x00, 0x04, 0x5b, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x01, 0x33, 0x01, 0x25, 0x21, 0x15, 0x01, 0x21, 0x01, 0x21, 0x03, 0x39, 0xfe, 0x3f, 0xc1, 0x01, 0xc1, 0xfc, 0x40, 0x04, 0x20, 0xfe, 0x1d, 0xfe, 0x7e, 0x01, 0xe4, 0xfd, 0x61, 0x05, 0x71, 0xfa, 0xf3, 0x05, 0x0d, 0x64, 0x64, 0xfa, 0x8f, 0x05, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x7d, 0xff, 0xe3, 0x04, 0x17, 0x05, 0xf0, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x24, 0x00, 0x29, 0x00, 0x31, 0x00, 0x39, 0x00, 0x41, 0x00, 0x00, 0x25, 0x36, 0x27, 0x26, 0x27, 0x00, 0x10, 0x17, 0x16, 0x17, 0x11, 0x06, 0x07, 0x13, 0x35, 0x2e, 0x01, 0x35, 0x34, 0x36, 0x20, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x20, 0x26, 0x35, 0x34, 0x36, 0x13, 0x11, 0x06, 0x07, 0x06, 0x05, 0x16, 0x32, 0x37, 0x11, 0x26, 0x22, 0x07, 0x19, 0x01, 0x16, 0x32, 0x37, 0x11, 0x26, 0x22, 0x17, 0x11, 0x36, 0x37, 0x36, 0x10, 0x27, 0x26, 0x03, 0x02, 0xbc, 0x06, 0x06, 0xb0, 0xfd, 0xf5, 0x55, 0x1e, 0x27, 0x27, 0x1d, 0x44, 0x73, 0x81, 0xe5, 0x01, 0x91, 0xe4, 0x81, 0x74, 0x83, 0x92, 0xef, 0xfe, 0x44, 0xef, 0x93, 0x81, 0xaf, 0x06, 0x07, 0x01, 0x16, 0x2d, 0x64, 0x2c, 0x2c, 0x64, 0x2d, 0x2c, 0x66, 0x2b, 0x2b, 0x66, 0xeb, 0x28, 0x1d, 0x56, 0x55, 0x1e, 0x64, 0x4a, 0xea, 0xe4, 0x4e, 0x02, 0x27, 0xfe, 0xf8, 0x4d, 0x1b, 0x12, 0x01, 0xfc, 0x12, 0x1b, 0xfd, 0xdc, 0x02, 0x20, 0xb1, 0x80, 0xb3, 0xd0, 0xd0, 0xb3, 0x80, 0xb1, 0x20, 0x01, 0x23, 0xc5, 0x8f, 0xd9, 0xe8, 0xe8, 0xd9, 0x8f, 0xc5, 0xfd, 0x6c, 0x02, 0x66, 0x4e, 0xe4, 0xea, 0x61, 0x06, 0x06, 0x02, 0x96, 0x07, 0x07, 0x02, 0xa2, 0xfd, 0xd0, 0x07, 0x07, 0x02, 0x30, 0x07, 0x21, 0xfe, 0x04, 0x12, 0x1b, 0x4d, 0x01, 0x08, 0x4d, 0x1b, 0x00, 0x04, 0x00, 0x5f, 0xff, 0xe3, 0x04, 0x2d, 0x05, 0xf0, 0x00, 0x04, 0x00, 0x09, 0x00, 0x11, 0x00, 0x25, 0x00, 0x00, 0x01, 0x06, 0x11, 0x10, 0x17, 0x01, 0x36, 0x11, 0x10, 0x2f, 0x01, 0x26, 0x22, 0x07, 0x11, 0x16, 0x32, 0x37, 0x03, 0x22, 0x27, 0x35, 0x17, 0x16, 0x20, 0x37, 0x11, 0x06, 0x23, 0x22, 0x02, 0x10, 0x12, 0x33, 0x20, 0x12, 0x10, 0x00, 0x01, 0x6f, 0xb6, 0xb6, 0x01, 0xab, 0xb8, 0xb8, 0x5a, 0x34, 0x9a, 0x29, 0x24, 0x9a, 0x39, 0xdc, 0x96, 0x97, 0x1e, 0x8a, 0x01, 0x0c, 0x55, 0x3c, 0x5d, 0xdd, 0xeb, 0xf5, 0xde, 0x01, 0x04, 0xf6, 0xfe, 0xd2, 0x05, 0x63, 0x63, 0xfe, 0xf4, 0xfe, 0xe8, 0x5c, 0xfe, 0x36, 0xb3, 0x01, 0x6f, 0x01, 0xdd, 0x95, 0x32, 0x10, 0x08, 0xfc, 0xde, 0x06, 0x13, 0xfd, 0x74, 0x3c, 0x6a, 0x0c, 0x36, 0x2d, 0x01, 0x9a, 0x16, 0x01, 0x11, 0x01, 0xd1, 0x01, 0x16, 0xfe, 0x73, 0xfd, 0x25, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x79, 0xff, 0xe3, 0x04, 0x1b, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x13, 0x00, 0x00, 0xff, 0xff, 0x00, 0xca, 0x00, 0x00, 0x03, 0xeb, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x14, 0x00, 0x00, 0xff, 0xff, 0x00, 0x87, 0x00, 0x00, 0x03, 0xdd, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x15, 0x00, 0x00, 0xff, 0xff, 0x00, 0x8c, 0xff, 0xe3, 0x04, 0x02, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x16, 0x00, 0x00, 0xff, 0xff, 0x00, 0x5a, 0x00, 0x00, 0x04, 0x2e, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x17, 0x00, 0x00, 0xff, 0xff, 0x00, 0x8e, 0xff, 0xe3, 0x03, 0xf4, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0x80, 0xff, 0xe3, 0x04, 0x21, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x19, 0x00, 0x00, 0xff, 0xff, 0x00, 0x97, 0x00, 0x00, 0x03, 0xf8, 0x05, 0xd5, 0x10, 0x06, 0x00, 0x1a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x7d, 0xff, 0xe3, 0x04, 0x17, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x00, 0x74, 0xff, 0xe3, 0x04, 0x14, 0x05, 0xf0, 0x10, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x11, 0x23, 0x01, 0x11, 0x21, 0x11, 0x04, 0xa9, 0x7f, 0x7f, 0xfc, 0x0b, 0x08, 0x6a, 0x01, 0x5f, 0x02, 0xc3, 0xfc, 0x24, 0x04, 0xf5, 0xfb, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x37, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0xb4, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x46, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x06, 0x78, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x05, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfd, 0xfe, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x02, 0x11, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x06, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfe, 0xec, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xf0, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x01, 0x09, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x48, 0x19, 0x1a, 0x12, 0x0f, 0x01, 0x08, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x07, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xf9, 0x4e, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x9f, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x02, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x06, 0xe0, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xeb, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0x02, 0x19, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0x15, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0xfd, 0xbe, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0xfa, 0xb3, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x03, 0x52, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x24, 0x24, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfd, 0xde, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfc, 0xe3, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x02, 0x83, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0xfe, 0x31, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x02, 0x84, 0x0f, 0x0e, 0x19, 0x14, 0x43, 0x15, 0x16, 0x11, 0x0f, 0x0f, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x18, 0x0f, 0x0f, 0x03, 0xf4, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x06, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2c, 0x00, 0x42, 0x00, 0x46, 0x00, 0x4a, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x02, 0x83, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x05, 0x4f, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfd, 0xfe, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfe, 0xa1, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x02, 0x11, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2c, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x02, 0x83, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x05, 0x4f, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfe, 0xec, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xf0, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfe, 0xa1, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x01, 0x09, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x48, 0x19, 0x1a, 0x12, 0x0f, 0x01, 0x08, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x08, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x71, 0x00, 0x75, 0x00, 0x79, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x02, 0x83, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x03, 0x07, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xf9, 0x4e, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x9f, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x84, 0x00, 0x88, 0x00, 0x8c, 0x00, 0x90, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x02, 0x83, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x03, 0x07, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x0a, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x56, 0x00, 0x6b, 0x00, 0x7f, 0x00, 0x95, 0x00, 0x99, 0x00, 0x9d, 0x00, 0xa1, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x02, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x02, 0x83, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x04, 0x5d, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xeb, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0x02, 0x19, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0x15, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0xfd, 0xbe, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0xfa, 0xb3, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xb4, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x24, 0x24, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfd, 0xde, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfc, 0xe3, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x00, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfd, 0xe8, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0x95, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x40, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfc, 0xf4, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x06, 0x78, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfe, 0xd8, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfd, 0xe8, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x1f, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x64, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfd, 0xfe, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfe, 0xd8, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfd, 0xe8, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x02, 0x11, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x1f, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x08, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfe, 0xec, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xf0, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfe, 0xd8, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfd, 0xe8, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x01, 0x09, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x48, 0x19, 0x1a, 0x12, 0x0f, 0x01, 0x08, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x1f, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x09, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x14, 0x00, 0x29, 0x00, 0x3e, 0x00, 0x53, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x74, 0x00, 0x89, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x42, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x42, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x42, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x42, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xf9, 0x4e, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfe, 0xd8, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfd, 0xe8, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x9f, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x1f, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x90, 0x00, 0xa6, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfe, 0xd8, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfd, 0xe8, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x1f, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x00, 0x0b, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x02, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x06, 0xe0, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xeb, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0x02, 0x19, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0x15, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0xfd, 0xbe, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0xfa, 0xb3, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfe, 0xd8, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfd, 0xe8, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x03, 0x52, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x24, 0x24, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfd, 0xde, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfc, 0xe3, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x1f, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x00, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfe, 0xd7, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xf0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0x95, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x40, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xf9, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfc, 0xf4, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x58, 0x00, 0x5c, 0x00, 0x60, 0x00, 0x64, 0x00, 0x00, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x00, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfe, 0xd7, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xf0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x04, 0x59, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x40, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xf9, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x8f, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x08, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x58, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x00, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfe, 0xd7, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xf0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x05, 0xb3, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfd, 0xfe, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x40, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xf9, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xed, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x02, 0x11, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x58, 0x00, 0x6d, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x00, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfe, 0xd7, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xf0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x05, 0xb3, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfe, 0xec, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xf0, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x40, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xf9, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xed, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x01, 0x09, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x48, 0x19, 0x1a, 0x12, 0x0f, 0x01, 0x08, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x0a, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x83, 0x00, 0x99, 0x00, 0x9d, 0x00, 0xa1, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x00, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfe, 0xd7, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xf0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x03, 0x6b, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xf9, 0x4e, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x40, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xf9, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x7a, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x9f, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x83, 0x00, 0x99, 0x00, 0xb0, 0x00, 0xb4, 0x00, 0xb8, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x00, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfe, 0xd7, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xf0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x03, 0x6b, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x40, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xf9, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x7a, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x56, 0x00, 0x6c, 0x00, 0x82, 0x00, 0x97, 0x00, 0xab, 0x00, 0xc1, 0x00, 0xc5, 0x00, 0xc9, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x25, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x21, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x02, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x04, 0x00, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0xfe, 0xd7, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xf0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x04, 0xc1, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xeb, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0x02, 0x19, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0x15, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0xfd, 0xbe, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0xfa, 0xb3, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x01, 0x40, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xf9, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x24, 0x24, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfd, 0xde, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfc, 0xe3, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x14, 0x00, 0x29, 0x00, 0x3e, 0x00, 0x53, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x94, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x42, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x41, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x42, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xfd, 0x43, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x9f, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x36, 0x00, 0x4b, 0x00, 0x60, 0x00, 0x75, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x06, 0x78, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x42, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x41, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x42, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x64, 0x00, 0x7a, 0x00, 0x90, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfd, 0xfe, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x02, 0x11, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0xa5, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfe, 0xec, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xf0, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x01, 0x09, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x48, 0x19, 0x1a, 0x12, 0x0f, 0x01, 0x08, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x0b, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0xa5, 0x00, 0xbb, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xf9, 0x4e, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x9f, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x90, 0x00, 0xa6, 0x00, 0xbc, 0x00, 0xd2, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x0d, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0xcd, 0x00, 0xe3, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x02, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x06, 0xe0, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xeb, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0x02, 0x19, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0x15, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0xfd, 0xbe, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0xfa, 0xb3, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x03, 0x52, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x24, 0x24, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfd, 0xde, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfc, 0xe3, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x08, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x21, 0x00, 0x37, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x00, 0x37, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0xb4, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x46, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x64, 0x00, 0x7a, 0x00, 0x90, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x06, 0x78, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x00, 0x00, 0x0a, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x64, 0x00, 0x7a, 0x00, 0x90, 0x00, 0xa6, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfd, 0xfe, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x02, 0x11, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x00, 0x0b, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0xa5, 0x00, 0xbb, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfe, 0xec, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xf0, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x01, 0x09, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x48, 0x19, 0x1a, 0x12, 0x0f, 0x01, 0x08, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x00, 0x00, 0x0c, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0xa5, 0x00, 0xbb, 0x00, 0xd1, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xf9, 0x4e, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x9f, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x90, 0x00, 0xa6, 0x00, 0xbc, 0x00, 0xd2, 0x00, 0xe8, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0xcd, 0x00, 0xe3, 0x00, 0xf9, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x02, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x06, 0xe0, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xeb, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0x02, 0x19, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0x15, 0x42, 0x14, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0xfd, 0xbe, 0x42, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0xfa, 0xb3, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfc, 0x6c, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x14, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x41, 0x16, 0x18, 0x0f, 0x0e, 0x03, 0x52, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x24, 0x24, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfd, 0xde, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfc, 0xe3, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x02, 0x6d, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x22, 0x00, 0x3a, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7c, 0x00, 0x92, 0x00, 0x00, 0x37, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0xb4, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfd, 0xc4, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x21, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xec, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0xf8, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0xfd, 0xd3, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x46, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x01, 0xf2, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x02, 0x12, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x00, 0x0a, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x39, 0x00, 0x51, 0x00, 0x67, 0x00, 0x7d, 0x00, 0x93, 0x00, 0xa9, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x06, 0x78, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfd, 0xc4, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x21, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xec, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0xf8, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0xfd, 0xd3, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x02, 0xc3, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x01, 0xf2, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x02, 0x12, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x4f, 0x00, 0x67, 0x00, 0x7d, 0x00, 0x93, 0x00, 0xa9, 0x00, 0xbf, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfd, 0xfe, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfd, 0xc4, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x21, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xec, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0xf8, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0xfd, 0xd3, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x02, 0x11, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x01, 0xf2, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x02, 0x12, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x64, 0x00, 0x7c, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbe, 0x00, 0xd4, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x07, 0xd2, 0x20, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x15, 0xfe, 0xec, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xf0, 0x20, 0x16, 0x18, 0x10, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0xfa, 0xa1, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfd, 0xc4, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x21, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xec, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0xf8, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0xfd, 0xd3, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0x3f, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x01, 0x09, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x48, 0x19, 0x1a, 0x12, 0x0f, 0x01, 0x08, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0xfc, 0xf6, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x01, 0xf2, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x02, 0x12, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x7a, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbe, 0x00, 0xd4, 0x00, 0xea, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xf9, 0x4e, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfd, 0xc4, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x21, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xec, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0xf8, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0xfd, 0xd3, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x9f, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x01, 0xf2, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x02, 0x12, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x00, 0x00, 0x0e, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x91, 0x00, 0xa9, 0x00, 0xbf, 0x00, 0xd5, 0x00, 0xeb, 0x01, 0x01, 0x00, 0x00, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x05, 0x8a, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0xfe, 0x15, 0x0e, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0e, 0x19, 0x15, 0x20, 0x22, 0x15, 0x17, 0x10, 0x01, 0xce, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x17, 0x10, 0x0f, 0xee, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x41, 0x16, 0x16, 0x11, 0x0e, 0xfa, 0x3c, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfd, 0xc4, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x21, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xec, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0xf8, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0xfd, 0xd3, 0x43, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x03, 0xcc, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfd, 0xe9, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xe4, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0xfd, 0xa8, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x01, 0xf2, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x02, 0x12, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x00, 0x0f, 0x00, 0xb4, 0x00, 0x46, 0x09, 0x1e, 0x05, 0x3b, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0xcc, 0x00, 0xe1, 0x00, 0xf6, 0x01, 0x0b, 0x00, 0x00, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x02, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x01, 0x11, 0x21, 0x11, 0x27, 0x11, 0x21, 0x11, 0x25, 0x11, 0x33, 0x11, 0x01, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x20, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x01, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x03, 0x22, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x00, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x1e, 0x01, 0x07, 0x06, 0x07, 0x06, 0xe0, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x11, 0x0f, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0xfe, 0xea, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0x02, 0x19, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x01, 0x0f, 0x10, 0x18, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0d, 0x0d, 0x0f, 0x19, 0xfd, 0xbd, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x0f, 0x0e, 0x01, 0x0f, 0x0f, 0x18, 0xfa, 0xb3, 0x08, 0x6a, 0x7f, 0xf8, 0x94, 0x03, 0x76, 0x7f, 0xfd, 0xc4, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x21, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0xfe, 0xeb, 0x42, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x01, 0xf8, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x01, 0x0f, 0x0f, 0x19, 0x14, 0x41, 0x16, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0xfd, 0xd2, 0x42, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x15, 0x17, 0x0f, 0x0f, 0x01, 0x10, 0x0e, 0x18, 0x03, 0x52, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x49, 0x17, 0x1a, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x24, 0x24, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfd, 0xde, 0x10, 0x11, 0x1b, 0x18, 0x47, 0x18, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x18, 0x48, 0x18, 0x19, 0x13, 0xfc, 0xe3, 0x04, 0xf5, 0xfb, 0x0b, 0x8d, 0x03, 0xdb, 0xfc, 0x25, 0x8c, 0x02, 0xc3, 0xfd, 0x3d, 0x01, 0xf2, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x49, 0x18, 0x19, 0x13, 0x10, 0xfd, 0xef, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x02, 0x02, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x02, 0x12, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x15, 0x21, 0x35, 0x01, 0x21, 0x11, 0x21, 0x01, 0xb1, 0x02, 0x7c, 0xfc, 0x87, 0x04, 0x76, 0xfb, 0x8a, 0x03, 0x07, 0x8d, 0x8d, 0x04, 0x66, 0xf6, 0xa7, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0xb4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x07, 0x6d, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x01, 0x05, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x02, 0x3b, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0xef, 0x0d, 0x0f, 0x19, 0x14, 0x43, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x18, 0x10, 0x0d, 0xed, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x32, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x07, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfc, 0xf6, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x07, 0x71, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x09, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0x00, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x03, 0x72, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x42, 0x14, 0x17, 0x12, 0x0e, 0xfe, 0x24, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x15, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x20, 0x20, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfe, 0x15, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfd, 0x33, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x91, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x33, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0xfd, 0xab, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x02, 0x82, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0x05, 0xe4, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x05, 0x6b, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0x02, 0x02, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x13, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x21, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x05, 0x69, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x18, 0x48, 0x18, 0x1a, 0x11, 0x10, 0xfb, 0x9c, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2c, 0x00, 0x42, 0x00, 0x46, 0x00, 0x4a, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfe, 0xc4, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x05, 0x6b, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0xfa, 0x19, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x02, 0x3b, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2c, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfe, 0xc4, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0xef, 0x0d, 0x0f, 0x19, 0x14, 0x43, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x18, 0x10, 0x0d, 0xed, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x05, 0x6b, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0xfa, 0x19, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x32, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x08, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x71, 0x00, 0x75, 0x00, 0x79, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x01, 0x10, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfc, 0xf6, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x05, 0x6b, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0xfc, 0xa3, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x07, 0x71, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x84, 0x00, 0x88, 0x00, 0x8c, 0x00, 0x90, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x01, 0x10, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x05, 0x6b, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0xfc, 0xa3, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x0a, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x56, 0x00, 0x6b, 0x00, 0x7f, 0x00, 0x95, 0x00, 0x99, 0x00, 0x9d, 0x00, 0xa1, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xa2, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x42, 0x14, 0x17, 0x12, 0x0e, 0xfe, 0x24, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x15, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x20, 0x20, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfe, 0x15, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfd, 0x33, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x05, 0x6b, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0xfb, 0x26, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x33, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0xfd, 0xab, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x02, 0x82, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0x05, 0xe4, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x95, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfd, 0x42, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x03, 0xc3, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x93, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x1c, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x01, 0x05, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x01, 0x49, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x07, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x64, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x1c, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x02, 0x3b, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x01, 0x49, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x08, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0xef, 0x0d, 0x0f, 0x19, 0x14, 0x43, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x18, 0x10, 0x0d, 0xed, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x1c, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x32, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x01, 0x49, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x09, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfc, 0xf6, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x1c, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x07, 0x71, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x01, 0x49, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x90, 0x00, 0xa6, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x1c, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x01, 0x49, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x0b, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0x00, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x02, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x03, 0x72, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x42, 0x14, 0x17, 0x12, 0x0e, 0xfe, 0x24, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x15, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x20, 0x20, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfe, 0x15, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfd, 0x33, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x1c, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x91, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x33, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0xfd, 0xab, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x02, 0x82, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0x05, 0xe4, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x01, 0x49, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x02, 0x53, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x95, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0xe1, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x42, 0x15, 0x17, 0x10, 0x0e, 0xee, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfd, 0x42, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x03, 0xc3, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x01, 0x4a, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x93, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x07, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x58, 0x00, 0x5c, 0x00, 0x60, 0x00, 0x64, 0x00, 0x00, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x95, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0xe1, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x42, 0x15, 0x17, 0x10, 0x0e, 0xee, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x81, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x03, 0xc3, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x01, 0x4a, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfb, 0x2b, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x08, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x58, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x95, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0xe1, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x42, 0x15, 0x17, 0x10, 0x0e, 0xee, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x22, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x03, 0xc3, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x01, 0x4a, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xf9, 0xaa, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x02, 0x3b, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x09, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x58, 0x00, 0x6d, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x95, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0xe1, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x42, 0x15, 0x17, 0x10, 0x0e, 0xee, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x22, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0xef, 0x0d, 0x0f, 0x19, 0x14, 0x43, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x18, 0x10, 0x0d, 0xed, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x03, 0xc3, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x01, 0x4a, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xf9, 0xaa, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x32, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x83, 0x00, 0x99, 0x00, 0x9d, 0x00, 0xa1, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x95, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0xe1, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x42, 0x15, 0x17, 0x10, 0x0e, 0xee, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x6e, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfc, 0xf6, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x03, 0xc3, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x01, 0x4a, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x34, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x07, 0x71, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x0b, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x83, 0x00, 0x99, 0x00, 0xb0, 0x00, 0xb4, 0x00, 0xb8, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x95, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0xe1, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x42, 0x15, 0x17, 0x10, 0x0e, 0xee, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x6e, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x03, 0xc3, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x01, 0x4a, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfc, 0x34, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x56, 0x00, 0x6c, 0x00, 0x82, 0x00, 0x97, 0x00, 0xab, 0x00, 0xc1, 0x00, 0xc5, 0x00, 0xc9, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x11, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x95, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0xe1, 0x0e, 0x0f, 0x18, 0x14, 0x43, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x42, 0x15, 0x17, 0x10, 0x0e, 0xee, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x42, 0x14, 0x17, 0x12, 0x0e, 0xfe, 0x24, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x15, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x20, 0x20, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfe, 0x15, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfd, 0x33, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x03, 0xc3, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x01, 0x4a, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x10, 0x1b, 0x17, 0x4a, 0x17, 0x19, 0x13, 0x10, 0x10, 0x11, 0x1b, 0x17, 0xfa, 0xb7, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x33, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0xfd, 0xab, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x02, 0x82, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0x05, 0xe4, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x07, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x14, 0x00, 0x29, 0x00, 0x3e, 0x00, 0x53, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfc, 0xf6, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x06, 0x74, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x03, 0x0b, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x36, 0x00, 0x4b, 0x00, 0x60, 0x00, 0x75, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x42, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0x01, 0x05, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x64, 0x00, 0x7a, 0x00, 0x90, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x02, 0x3b, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x0a, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0xa5, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0xef, 0x0d, 0x0f, 0x19, 0x14, 0x43, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x18, 0x10, 0x0d, 0xed, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x32, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0xa5, 0x00, 0xbb, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfc, 0xf6, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x07, 0x71, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x14, 0x00, 0x29, 0x00, 0x3e, 0x00, 0x53, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x71, 0x00, 0x75, 0x00, 0x8a, 0x00, 0x9f, 0x00, 0xb4, 0x00, 0xc9, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x42, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x00, 0x0d, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0xcd, 0x00, 0xe3, 0x00, 0x00, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x72, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x42, 0x14, 0x17, 0x12, 0x0e, 0xfe, 0x24, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x15, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x20, 0x20, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfe, 0x15, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfd, 0x33, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0x91, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x33, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0xfd, 0xab, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x02, 0x82, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0x05, 0xe4, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x21, 0x00, 0x37, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x00, 0x13, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0xb4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x07, 0x6d, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0x00, 0x09, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4e, 0x00, 0x64, 0x00, 0x7a, 0x00, 0x90, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x01, 0x05, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0x00, 0x0a, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x4c, 0x00, 0x61, 0x00, 0x76, 0x00, 0x8b, 0x00, 0xa0, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x42, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x02, 0x3b, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0x00, 0x0b, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0xa5, 0x00, 0xbb, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0xef, 0x0d, 0x0f, 0x19, 0x14, 0x43, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x18, 0x10, 0x0d, 0xed, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x32, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x79, 0x00, 0x8f, 0x00, 0xa5, 0x00, 0xbb, 0x00, 0xd1, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfc, 0xf6, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x07, 0x71, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0x00, 0x00, 0x00, 0x0d, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x6e, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7a, 0x00, 0x90, 0x00, 0xa6, 0x00, 0xbc, 0x00, 0xd2, 0x00, 0xe8, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0x00, 0x0e, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0xcd, 0x00, 0xe3, 0x00, 0xf9, 0x00, 0x00, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x72, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x42, 0x14, 0x17, 0x12, 0x0e, 0xfe, 0x24, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x15, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x20, 0x20, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfe, 0x15, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfd, 0x33, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x02, 0x2f, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0x91, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x33, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0xfd, 0xab, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x4a, 0x16, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x02, 0x82, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0x05, 0xe4, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x03, 0xfa, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x4a, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x19, 0x1a, 0x11, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x22, 0x00, 0x3a, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7c, 0x00, 0x92, 0x00, 0x00, 0x13, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0xb4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x01, 0xc0, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x42, 0x15, 0x16, 0x11, 0x0f, 0xfe, 0x24, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x23, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x07, 0x6d, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x02, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x33, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0xfd, 0xd0, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x02, 0x6b, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x39, 0x00, 0x51, 0x00, 0x67, 0x00, 0x7d, 0x00, 0x93, 0x00, 0xa9, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x02, 0xf1, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x21, 0x21, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x01, 0xc0, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x42, 0x15, 0x16, 0x11, 0x0f, 0xfe, 0x24, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x23, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x01, 0x05, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x02, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x33, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0xfd, 0xd0, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x02, 0x6b, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x4f, 0x00, 0x67, 0x00, 0x7d, 0x00, 0x93, 0x00, 0xa9, 0x00, 0xbf, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x01, 0xdc, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x01, 0xc0, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x42, 0x15, 0x16, 0x11, 0x0f, 0xfe, 0x24, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x23, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x02, 0x3b, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x02, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x33, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0xfd, 0xd0, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x02, 0x6b, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x16, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x64, 0x00, 0x7c, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbe, 0x00, 0xd4, 0x00, 0x00, 0x05, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x13, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x94, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0xef, 0x0d, 0x0f, 0x19, 0x14, 0x43, 0x15, 0x17, 0x10, 0x0f, 0x0f, 0x0f, 0x18, 0x15, 0x41, 0x16, 0x18, 0x10, 0x0d, 0xed, 0x0f, 0x0f, 0x19, 0x15, 0x41, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0f, 0xfd, 0x44, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x01, 0xc0, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x42, 0x15, 0x16, 0x11, 0x0f, 0xfe, 0x24, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x23, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x32, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x2e, 0x24, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x05, 0xf8, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x02, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x33, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0xfd, 0xd0, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x02, 0x6b, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x2b, 0x00, 0x41, 0x00, 0x57, 0x00, 0x5b, 0x00, 0x5f, 0x00, 0x63, 0x00, 0x7a, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbe, 0x00, 0xd4, 0x00, 0xea, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x43, 0x14, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfc, 0xf6, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x01, 0xc0, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x42, 0x15, 0x16, 0x11, 0x0f, 0xfe, 0x24, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x23, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0e, 0x10, 0x18, 0x15, 0x20, 0x21, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x07, 0x71, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x02, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x24, 0x25, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x33, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0xfd, 0xd0, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x02, 0x6b, 0x4a, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0x00, 0x00, 0x0e, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x14, 0x00, 0x29, 0x00, 0x3e, 0x00, 0x53, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x71, 0x00, 0x75, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb6, 0x00, 0xcb, 0x00, 0xe0, 0x00, 0xf5, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x00, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x12, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x01, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x03, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x34, 0x37, 0x36, 0x37, 0x36, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x03, 0xe0, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xfe, 0x1f, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x0f, 0x19, 0x14, 0x22, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x02, 0x18, 0x20, 0x16, 0x17, 0x0f, 0x0f, 0x0f, 0x0e, 0x18, 0x15, 0x42, 0x15, 0x17, 0x11, 0x0e, 0x0e, 0x10, 0x18, 0x14, 0xcd, 0x21, 0x14, 0x18, 0x10, 0x0e, 0x0e, 0x0e, 0x1a, 0x14, 0x42, 0x16, 0x16, 0x10, 0x0f, 0x0f, 0x0f, 0x17, 0x16, 0xfd, 0xe4, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x01, 0xc0, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0f, 0xfe, 0x24, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x23, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x02, 0x0e, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0xfd, 0xee, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x02, 0x22, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0xfd, 0xfe, 0x10, 0x11, 0x1b, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x01, 0x09, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x18, 0x1a, 0x11, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x49, 0x18, 0x19, 0x12, 0x10, 0x06, 0x68, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x02, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x34, 0x49, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0xfd, 0xd0, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x02, 0x6c, 0x49, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xb4, 0xfe, 0x14, 0x05, 0x2b, 0x07, 0x6d, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x40, 0x00, 0x55, 0x00, 0x69, 0x00, 0x7f, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0xb7, 0x00, 0xcc, 0x00, 0xe1, 0x00, 0xf6, 0x01, 0x0b, 0x00, 0x00, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x24, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x21, 0x11, 0x21, 0x37, 0x21, 0x11, 0x21, 0x13, 0x21, 0x15, 0x21, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x10, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x01, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x25, 0x34, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x17, 0x16, 0x17, 0x16, 0x14, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x26, 0x27, 0x26, 0x00, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x03, 0x72, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x17, 0x11, 0x0d, 0x0d, 0x10, 0x18, 0x15, 0x41, 0x15, 0x17, 0x12, 0x0e, 0xfe, 0x24, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x15, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x20, 0x20, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfe, 0x15, 0x0e, 0x10, 0x18, 0x16, 0x3f, 0x16, 0x17, 0x12, 0x0e, 0x0e, 0x10, 0x19, 0x15, 0x40, 0x16, 0x18, 0x10, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x21, 0x20, 0x16, 0x17, 0x10, 0x0e, 0x0e, 0x0f, 0x18, 0x16, 0x41, 0x15, 0x17, 0x11, 0xfd, 0x33, 0x04, 0x76, 0xfb, 0x8a, 0x7f, 0x03, 0x78, 0xfc, 0x88, 0x7e, 0x02, 0x7c, 0xfd, 0x84, 0x01, 0xc0, 0x0f, 0x0f, 0x18, 0x15, 0x21, 0x21, 0x15, 0x17, 0x10, 0x0e, 0x0e, 0x10, 0x17, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0f, 0xfe, 0x24, 0x0e, 0x10, 0x17, 0x15, 0x22, 0x20, 0x15, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x01, 0xcf, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x0e, 0xfe, 0x23, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x18, 0x10, 0x0e, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x01, 0xdd, 0x0e, 0x10, 0x18, 0x15, 0x41, 0x16, 0x16, 0x11, 0x0e, 0x0e, 0x10, 0x17, 0x16, 0x40, 0x16, 0x17, 0x11, 0x91, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x13, 0x10, 0x10, 0x11, 0x1c, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x01, 0x34, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0xfd, 0xab, 0x49, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x17, 0x49, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x0f, 0x0f, 0x11, 0x1b, 0x02, 0x83, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x17, 0x26, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x11, 0x1a, 0x05, 0xe4, 0xf6, 0xa7, 0x8d, 0x08, 0x3f, 0xfc, 0x27, 0x8d, 0x02, 0x7c, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x10, 0x1c, 0x17, 0x49, 0x18, 0x19, 0x12, 0x10, 0x10, 0x11, 0x1a, 0x18, 0x01, 0x34, 0x49, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0xfd, 0xd0, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x12, 0x10, 0x01, 0x11, 0x11, 0x1b, 0x17, 0x48, 0x18, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x02, 0x6c, 0x49, 0x17, 0x1a, 0x12, 0x10, 0x10, 0x11, 0x1b, 0x17, 0x25, 0x24, 0x17, 0x1a, 0x11, 0x10, 0x01, 0x11, 0x10, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x11, 0x21, 0x11, 0x01, 0x8c, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x0e, 0x03, 0xda, 0x06, 0xf5, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf7, 0xd3, 0x07, 0x01, 0xf8, 0xff, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x33, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x03, 0x33, 0x03, 0x33, 0x01, 0x23, 0x27, 0x21, 0x07, 0x23, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x10, 0x78, 0xf1, 0xbd, 0x8a, 0x01, 0x04, 0x77, 0x3d, 0xfe, 0xd7, 0x3d, 0x77, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0xac, 0xfe, 0x55, 0x02, 0x0f, 0xfc, 0xbc, 0xda, 0xda, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x49, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x21, 0x15, 0x21, 0x35, 0x36, 0x37, 0x00, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x01, 0x06, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x75, 0x01, 0x7d, 0xfd, 0xe6, 0x1f, 0x38, 0x01, 0x36, 0x5e, 0x4c, 0x2f, 0x6e, 0x41, 0x46, 0x77, 0x34, 0x82, 0x9d, 0xfe, 0xd6, 0x33, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfc, 0x3f, 0x72, 0x6e, 0x1f, 0x38, 0x01, 0x31, 0x5e, 0x42, 0x51, 0x23, 0x23, 0x7b, 0x1c, 0x1c, 0x84, 0x6c, 0x8b, 0xfe, 0xe4, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x59, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x57, 0x53, 0x5b, 0xab, 0x9f, 0x33, 0x71, 0x3f, 0x2f, 0x6b, 0x3c, 0x62, 0x6c, 0x64, 0x61, 0x4d, 0x54, 0x55, 0x57, 0x5a, 0x55, 0x24, 0x5c, 0x49, 0x42, 0x73, 0x31, 0x82, 0x98, 0x51, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x91, 0x12, 0x6d, 0x52, 0x7c, 0x86, 0x15, 0x14, 0x79, 0x1b, 0x1a, 0x4f, 0x46, 0x4a, 0x4c, 0x6c, 0x3f, 0x3c, 0x3a, 0x3d, 0x12, 0x17, 0x73, 0x11, 0x12, 0x76, 0x63, 0x45, 0x60, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x33, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x09, 0x01, 0x21, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x4d, 0xfe, 0xe9, 0x01, 0x17, 0x14, 0x95, 0x7a, 0x7a, 0x81, 0xfe, 0x8b, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0x97, 0xfe, 0x5d, 0x02, 0x1c, 0xfd, 0xe4, 0x6d, 0xba, 0xba, 0x79, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x51, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x21, 0x15, 0x21, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xfc, 0x01, 0xcb, 0xfe, 0xa0, 0x19, 0x1a, 0x1a, 0x19, 0x91, 0x54, 0x55, 0x57, 0x57, 0x9e, 0x36, 0x72, 0x3b, 0x33, 0x38, 0x38, 0x3e, 0x64, 0x75, 0x75, 0x64, 0x2f, 0x5d, 0x31, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0x5f, 0xcc, 0x09, 0x04, 0x04, 0x4d, 0x4c, 0x83, 0x87, 0x4b, 0x4a, 0x12, 0x12, 0x71, 0x1b, 0x0e, 0x0d, 0x66, 0xae, 0x66, 0x14, 0x15, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x40, 0x00, 0x60, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x13, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x0d, 0x4f, 0x2e, 0x2e, 0x2e, 0x2e, 0x4f, 0x4e, 0x2e, 0x2e, 0x2e, 0x2e, 0x9a, 0x2c, 0x2d, 0x2d, 0x2c, 0x73, 0x3e, 0x3d, 0x09, 0x22, 0x34, 0x34, 0x3d, 0x83, 0x4b, 0x4c, 0x4f, 0x4f, 0x82, 0x97, 0x9e, 0x61, 0x61, 0xa4, 0x2c, 0x2d, 0x2d, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x9e, 0x34, 0x35, 0x5b, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5b, 0x35, 0x34, 0x01, 0x62, 0x67, 0x14, 0x0a, 0x0b, 0x4b, 0x4c, 0x99, 0x31, 0x1a, 0x1a, 0x4c, 0x4d, 0x84, 0x7f, 0x4f, 0x4e, 0xde, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x37, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x21, 0x15, 0x01, 0x23, 0x01, 0x21, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xd8, 0x02, 0x2b, 0xfe, 0xc7, 0x7a, 0x01, 0x27, 0xfe, 0x61, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0x30, 0xfc, 0xed, 0x02, 0xe4, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x3d, 0x00, 0x5b, 0x00, 0x6a, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x34, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x20, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x55, 0xa8, 0x2f, 0x30, 0x5f, 0x54, 0x53, 0x30, 0x30, 0x30, 0xf8, 0x4c, 0x29, 0x2a, 0x93, 0x01, 0x02, 0x4a, 0x48, 0x29, 0x2a, 0x4b, 0x51, 0x32, 0x30, 0x4c, 0x4e, 0x8e, 0x8f, 0x4d, 0x4d, 0x30, 0x30, 0x29, 0x2a, 0x29, 0x4d, 0x49, 0x2c, 0x2b, 0x2b, 0x2a, 0x96, 0x2b, 0x2a, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x5b, 0x2c, 0x2b, 0x4b, 0x4c, 0x56, 0x2c, 0x2b, 0x96, 0x2b, 0x5d, 0x12, 0x31, 0x32, 0x48, 0x64, 0x74, 0x3a, 0x3a, 0x64, 0x4a, 0x30, 0x31, 0x12, 0x12, 0x3a, 0x37, 0x50, 0x79, 0x41, 0x41, 0x41, 0x41, 0x79, 0x4e, 0x39, 0x38, 0xc6, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x41, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x50, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x13, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x10, 0x2c, 0x2d, 0x2d, 0x2b, 0x74, 0x3d, 0x3d, 0x09, 0x20, 0x36, 0x33, 0x3e, 0x82, 0x97, 0x4e, 0x50, 0x82, 0x96, 0x4f, 0x4f, 0x60, 0x62, 0xa4, 0x2c, 0x2d, 0x2d, 0xb8, 0x4f, 0x5c, 0x2e, 0x2e, 0x4f, 0x4c, 0x30, 0x2f, 0x2f, 0x2e, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xdf, 0x67, 0x14, 0x0b, 0x0a, 0x4b, 0x4b, 0x9a, 0x2f, 0x1b, 0x1a, 0x98, 0x84, 0x81, 0x4d, 0x4e, 0x6f, 0x6f, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x01, 0x72, 0x68, 0x5c, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5c, 0x34, 0x34, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x3e, 0x00, 0x4a, 0x00, 0x51, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x03, 0x86, 0x80, 0x2d, 0x2e, 0x2e, 0x2d, 0x80, 0x2d, 0x2e, 0x2e, 0x6d, 0x76, 0x99, 0x99, 0x76, 0x92, 0x7e, 0x7e, 0xfe, 0x9c, 0x78, 0x7e, 0x7b, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0xc8, 0x56, 0x56, 0xac, 0xad, 0x56, 0x56, 0x56, 0x56, 0xad, 0xac, 0x56, 0xaf, 0xde, 0xd3, 0xd4, 0xde, 0xde, 0xd4, 0xd3, 0xde, 0xfc, 0xac, 0x02, 0xd1, 0x29, 0x74, 0x27, 0xfc, 0xbd, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x05, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x87, 0x72, 0x3b, 0x39, 0x81, 0x2c, 0x24, 0x4c, 0x3f, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0xfd, 0xdc, 0x95, 0x46, 0x45, 0x60, 0x54, 0x6c, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x4a, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0xe9, 0x2c, 0x5b, 0x33, 0xa3, 0xb4, 0xb5, 0xa2, 0x33, 0x5c, 0x2b, 0x2a, 0x5f, 0x31, 0x70, 0x6f, 0x6e, 0x71, 0x31, 0x60, 0x29, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xeb, 0x17, 0x16, 0xe3, 0xce, 0xcd, 0xe5, 0x17, 0x17, 0x74, 0x22, 0x24, 0xaa, 0xac, 0xab, 0xab, 0x24, 0x22, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x11, 0x00, 0x1b, 0x00, 0x34, 0x00, 0x40, 0x00, 0x4c, 0x00, 0x00, 0x01, 0x22, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x07, 0x12, 0x10, 0x26, 0x23, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x05, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x02, 0xaf, 0x04, 0x0f, 0x05, 0x8e, 0x8b, 0x8c, 0x8e, 0x8f, 0x8d, 0x4e, 0x4f, 0x71, 0x55, 0x09, 0x4c, 0x58, 0x56, 0x4d, 0x4d, 0x56, 0x58, 0x01, 0x6b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x03, 0x2c, 0x01, 0xd7, 0xda, 0xdb, 0xd7, 0xd7, 0xdb, 0xa5, 0xc9, 0x28, 0x6a, 0x38, 0x01, 0x80, 0x01, 0x70, 0x9e, 0x9e, 0xfe, 0x90, 0x9e, 0x6e, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x16, 0x00, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x23, 0x14, 0x17, 0x23, 0x36, 0x35, 0x23, 0x06, 0x23, 0x22, 0x35, 0x34, 0x37, 0x36, 0x00, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x04, 0x5b, 0x3b, 0x01, 0x1b, 0x08, 0x19, 0xb0, 0x61, 0x3c, 0x1b, 0x36, 0x89, 0x35, 0x1b, 0x3c, 0x61, 0xaf, 0x18, 0x08, 0x01, 0x1c, 0xfd, 0x6b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xd8, 0x72, 0x01, 0x46, 0x94, 0xfe, 0x91, 0x01, 0x8c, 0x96, 0xfe, 0x9f, 0x72, 0x03, 0x18, 0x79, 0xfe, 0x7e, 0x26, 0x25, 0x4e, 0xe4, 0x9b, 0xcc, 0x6b, 0x6b, 0xcc, 0x9b, 0xe4, 0x4e, 0x25, 0x26, 0x01, 0x82, 0x04, 0x56, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0xfe, 0x9f, 0x01, 0x61, 0xfe, 0x7a, 0xfe, 0x42, 0x01, 0x93, 0xfe, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x38, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x03, 0x33, 0x03, 0x33, 0x01, 0x23, 0x27, 0x21, 0x07, 0x23, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x10, 0x78, 0xf1, 0xbd, 0x8a, 0x01, 0x04, 0x77, 0x3d, 0xfe, 0xd7, 0x3d, 0x77, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0xac, 0xfe, 0x55, 0x02, 0x0f, 0xfc, 0xbc, 0xda, 0xda, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x46, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x21, 0x15, 0x21, 0x35, 0x36, 0x37, 0x00, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x01, 0x06, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x75, 0x01, 0x7d, 0xfd, 0xe6, 0x1f, 0x38, 0x01, 0x36, 0x5e, 0x4c, 0x2f, 0x6e, 0x41, 0x46, 0x77, 0x34, 0x82, 0x9d, 0xfe, 0xd6, 0x33, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfc, 0x3f, 0x72, 0x6e, 0x1f, 0x38, 0x01, 0x31, 0x5e, 0x42, 0x51, 0x23, 0x23, 0x7b, 0x1c, 0x1c, 0x84, 0x6c, 0x8b, 0xfe, 0xe4, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x57, 0x53, 0x5b, 0xab, 0x9f, 0x33, 0x71, 0x3f, 0x2f, 0x6b, 0x3c, 0x62, 0x6c, 0x64, 0x61, 0x4d, 0x54, 0x55, 0x57, 0x5a, 0x55, 0x24, 0x5c, 0x49, 0x42, 0x73, 0x31, 0x82, 0x98, 0x51, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x91, 0x12, 0x6d, 0x52, 0x7c, 0x86, 0x15, 0x14, 0x79, 0x1b, 0x1a, 0x4f, 0x46, 0x4a, 0x4c, 0x6c, 0x3f, 0x3c, 0x3a, 0x3d, 0x12, 0x17, 0x73, 0x11, 0x12, 0x76, 0x63, 0x45, 0x60, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x09, 0x01, 0x21, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x4d, 0xfe, 0xe9, 0x01, 0x17, 0x14, 0x95, 0x7a, 0x7a, 0x81, 0xfe, 0x8b, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0x97, 0xfe, 0x5d, 0x02, 0x1c, 0xfd, 0xe4, 0x6d, 0xba, 0xba, 0x79, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x21, 0x15, 0x21, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xfc, 0x01, 0xcb, 0xfe, 0xa0, 0x19, 0x1a, 0x1a, 0x19, 0x91, 0x54, 0x55, 0x57, 0x57, 0x9e, 0x36, 0x72, 0x3b, 0x33, 0x38, 0x38, 0x3e, 0x64, 0x75, 0x75, 0x64, 0x2f, 0x5d, 0x31, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0x5f, 0xcc, 0x09, 0x04, 0x04, 0x4d, 0x4c, 0x83, 0x87, 0x4b, 0x4a, 0x12, 0x12, 0x71, 0x1b, 0x0e, 0x0d, 0x66, 0xae, 0x66, 0x14, 0x15, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x3d, 0x00, 0x5d, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x13, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x0d, 0x4f, 0x2e, 0x2e, 0x2e, 0x2e, 0x4f, 0x4e, 0x2e, 0x2e, 0x2e, 0x2e, 0x9a, 0x2c, 0x2d, 0x2d, 0x2c, 0x73, 0x3e, 0x3d, 0x09, 0x22, 0x34, 0x34, 0x3d, 0x83, 0x4b, 0x4c, 0x4f, 0x4f, 0x82, 0x97, 0x9e, 0x61, 0x61, 0xa4, 0x2c, 0x2d, 0x2d, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x9e, 0x34, 0x35, 0x5b, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5b, 0x35, 0x34, 0x01, 0x62, 0x67, 0x14, 0x0a, 0x0b, 0x4b, 0x4c, 0x99, 0x31, 0x1a, 0x1a, 0x4c, 0x4d, 0x84, 0x7f, 0x4f, 0x4e, 0xde, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x21, 0x15, 0x01, 0x23, 0x01, 0x21, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xd8, 0x02, 0x2b, 0xfe, 0xc7, 0x7a, 0x01, 0x27, 0xfe, 0x61, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0x30, 0xfc, 0xed, 0x02, 0xe4, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x3a, 0x00, 0x58, 0x00, 0x67, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x34, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x20, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x55, 0xa8, 0x2f, 0x30, 0x5f, 0x54, 0x53, 0x30, 0x30, 0x30, 0xf8, 0x4c, 0x29, 0x2a, 0x93, 0x01, 0x02, 0x4a, 0x48, 0x29, 0x2a, 0x4b, 0x51, 0x32, 0x30, 0x4c, 0x4e, 0x8e, 0x8f, 0x4d, 0x4d, 0x30, 0x30, 0x29, 0x2a, 0x29, 0x4d, 0x49, 0x2c, 0x2b, 0x2b, 0x2a, 0x96, 0x2b, 0x2a, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x5b, 0x2c, 0x2b, 0x4b, 0x4c, 0x56, 0x2c, 0x2b, 0x96, 0x2b, 0x5d, 0x12, 0x31, 0x32, 0x48, 0x64, 0x74, 0x3a, 0x3a, 0x64, 0x4a, 0x30, 0x31, 0x12, 0x12, 0x3a, 0x37, 0x50, 0x79, 0x41, 0x41, 0x41, 0x41, 0x79, 0x4e, 0x39, 0x38, 0xc6, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x41, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x4d, 0x00, 0x5c, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x13, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x10, 0x2c, 0x2d, 0x2d, 0x2b, 0x74, 0x3d, 0x3d, 0x09, 0x20, 0x36, 0x33, 0x3e, 0x82, 0x97, 0x4e, 0x50, 0x82, 0x96, 0x4f, 0x4f, 0x60, 0x62, 0xa4, 0x2c, 0x2d, 0x2d, 0xb8, 0x4f, 0x5c, 0x2e, 0x2e, 0x4f, 0x4c, 0x30, 0x2f, 0x2f, 0x2e, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xdf, 0x67, 0x14, 0x0b, 0x0a, 0x4b, 0x4b, 0x9a, 0x2f, 0x1b, 0x1a, 0x98, 0x84, 0x81, 0x4d, 0x4e, 0x6f, 0x6f, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x01, 0x72, 0x68, 0x5c, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5c, 0x34, 0x34, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x03, 0x86, 0x80, 0x2d, 0x2e, 0x2e, 0x2d, 0x80, 0x2d, 0x2e, 0x2e, 0x6d, 0x76, 0x99, 0x99, 0x76, 0x92, 0x7e, 0x7e, 0xfe, 0x9c, 0x78, 0x7e, 0x7b, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0xc8, 0x56, 0x56, 0xac, 0xad, 0x56, 0x56, 0x56, 0x56, 0xad, 0xac, 0x56, 0xaf, 0xde, 0xd3, 0xd4, 0xde, 0xde, 0xd4, 0xd3, 0xde, 0xfc, 0xac, 0x02, 0xd1, 0x29, 0x74, 0x27, 0xfc, 0xbd, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x3a, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x05, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x87, 0x72, 0x3b, 0x39, 0x81, 0x2c, 0x24, 0x4c, 0x3f, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0xfd, 0xdc, 0x95, 0x46, 0x45, 0x60, 0x54, 0x6c, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0xe9, 0x2c, 0x5b, 0x33, 0xa3, 0xb4, 0xb5, 0xa2, 0x33, 0x5c, 0x2b, 0x2a, 0x5f, 0x31, 0x70, 0x6f, 0x6e, 0x71, 0x31, 0x60, 0x29, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xeb, 0x17, 0x16, 0xe3, 0xce, 0xcd, 0xe5, 0x17, 0x17, 0x74, 0x22, 0x24, 0xaa, 0xac, 0xab, 0xab, 0x24, 0x22, 0x00, 0x00, 0x05, 0x00, 0xc3, 0xfe, 0x14, 0x06, 0xb9, 0x07, 0x6d, 0x00, 0x11, 0x00, 0x1b, 0x00, 0x31, 0x00, 0x3d, 0x00, 0x49, 0x00, 0x00, 0x01, 0x22, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x07, 0x12, 0x10, 0x26, 0x23, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x02, 0xaf, 0x04, 0x0f, 0x05, 0x8e, 0x8b, 0x8c, 0x8e, 0x8f, 0x8d, 0x4e, 0x4f, 0x71, 0x55, 0x09, 0x4c, 0x58, 0x56, 0x4d, 0x4d, 0x56, 0x58, 0x01, 0x61, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x5e, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x03, 0x2c, 0x01, 0xd7, 0xda, 0xdb, 0xd7, 0xd7, 0xdb, 0xa5, 0xc9, 0x28, 0x6a, 0x38, 0x01, 0x80, 0x01, 0x70, 0x9e, 0x9e, 0xfe, 0x90, 0x9e, 0xfe, 0x30, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x09, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x04, 0x51, 0x14, 0x31, 0x38, 0x4c, 0x7d, 0x38, 0x11, 0x71, 0xfe, 0xe4, 0xfe, 0xe0, 0x71, 0x12, 0x38, 0x7c, 0x4e, 0x36, 0x31, 0xfd, 0x4f, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xd8, 0x72, 0x01, 0x46, 0x94, 0xfe, 0x91, 0x01, 0x8c, 0x96, 0xfe, 0x9f, 0x72, 0x01, 0xb6, 0x76, 0x3e, 0x47, 0x95, 0x2d, 0x3b, 0x9e, 0x9f, 0xfe, 0x6e, 0x01, 0x92, 0x9d, 0xa0, 0x3b, 0x2d, 0x95, 0x47, 0x41, 0x04, 0xcc, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0xfe, 0x9f, 0x01, 0x61, 0xfe, 0x7a, 0xfe, 0x42, 0x01, 0x93, 0xfe, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x21, 0x00, 0x29, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x03, 0x33, 0x03, 0x33, 0x01, 0x23, 0x27, 0x21, 0x07, 0x23, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x10, 0x78, 0xf1, 0xbd, 0x8a, 0x01, 0x04, 0x77, 0x3d, 0xfe, 0xd7, 0x3d, 0x77, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0xac, 0xfe, 0x55, 0x02, 0x0f, 0xfc, 0xbc, 0xda, 0xda, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x37, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x21, 0x15, 0x21, 0x35, 0x36, 0x37, 0x00, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x01, 0x06, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x75, 0x01, 0x7d, 0xfd, 0xe6, 0x1f, 0x38, 0x01, 0x36, 0x5e, 0x4c, 0x2f, 0x6e, 0x41, 0x46, 0x77, 0x34, 0x82, 0x9d, 0xfe, 0xd6, 0x33, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfc, 0x3f, 0x72, 0x6e, 0x1f, 0x38, 0x01, 0x31, 0x5e, 0x42, 0x51, 0x23, 0x23, 0x7b, 0x1c, 0x1c, 0x84, 0x6c, 0x8b, 0xfe, 0xe4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x47, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x57, 0x53, 0x5b, 0xab, 0x9f, 0x33, 0x71, 0x3f, 0x2f, 0x6b, 0x3c, 0x62, 0x6c, 0x64, 0x61, 0x4d, 0x54, 0x55, 0x57, 0x5a, 0x55, 0x24, 0x5c, 0x49, 0x42, 0x73, 0x31, 0x82, 0x98, 0x51, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x91, 0x12, 0x6d, 0x52, 0x7c, 0x86, 0x15, 0x14, 0x79, 0x1b, 0x1a, 0x4f, 0x46, 0x4a, 0x4c, 0x6c, 0x3f, 0x3c, 0x3a, 0x3d, 0x12, 0x17, 0x73, 0x11, 0x12, 0x76, 0x63, 0x45, 0x60, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x21, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x09, 0x01, 0x21, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x4d, 0xfe, 0xe9, 0x01, 0x17, 0x14, 0x95, 0x7a, 0x7a, 0x81, 0xfe, 0x8b, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0x97, 0xfe, 0x5d, 0x02, 0x1c, 0xfd, 0xe4, 0x6d, 0xba, 0xba, 0x79, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x3f, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x21, 0x15, 0x21, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xfc, 0x01, 0xcb, 0xfe, 0xa0, 0x19, 0x1a, 0x1a, 0x19, 0x91, 0x54, 0x55, 0x57, 0x57, 0x9e, 0x36, 0x72, 0x3b, 0x33, 0x38, 0x38, 0x3e, 0x64, 0x75, 0x75, 0x64, 0x2f, 0x5d, 0x31, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0x5f, 0xcc, 0x09, 0x04, 0x04, 0x4d, 0x4c, 0x83, 0x87, 0x4b, 0x4a, 0x12, 0x12, 0x71, 0x1b, 0x0e, 0x0d, 0x66, 0xae, 0x66, 0x14, 0x15, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x2e, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x13, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x0d, 0x4f, 0x2e, 0x2e, 0x2e, 0x2e, 0x4f, 0x4e, 0x2e, 0x2e, 0x2e, 0x2e, 0x9a, 0x2c, 0x2d, 0x2d, 0x2c, 0x73, 0x3e, 0x3d, 0x09, 0x22, 0x34, 0x34, 0x3d, 0x83, 0x4b, 0x4c, 0x4f, 0x4f, 0x82, 0x97, 0x9e, 0x61, 0x61, 0xa4, 0x2c, 0x2d, 0x2d, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x9e, 0x34, 0x35, 0x5b, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5b, 0x35, 0x34, 0x01, 0x62, 0x67, 0x14, 0x0a, 0x0b, 0x4b, 0x4c, 0x99, 0x31, 0x1a, 0x1a, 0x4c, 0x4d, 0x84, 0x7f, 0x4f, 0x4e, 0xde, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x25, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x21, 0x15, 0x01, 0x23, 0x01, 0x21, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xd8, 0x02, 0x2b, 0xfe, 0xc7, 0x7a, 0x01, 0x27, 0xfe, 0x61, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0x30, 0xfc, 0xed, 0x02, 0xe4, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x2b, 0x00, 0x49, 0x00, 0x58, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x34, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x20, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x55, 0xa8, 0x2f, 0x30, 0x5f, 0x54, 0x53, 0x30, 0x30, 0x30, 0xf8, 0x4c, 0x29, 0x2a, 0x93, 0x01, 0x02, 0x4a, 0x48, 0x29, 0x2a, 0x4b, 0x51, 0x32, 0x30, 0x4c, 0x4e, 0x8e, 0x8f, 0x4d, 0x4d, 0x30, 0x30, 0x29, 0x2a, 0x29, 0x4d, 0x49, 0x2c, 0x2b, 0x2b, 0x2a, 0x96, 0x2b, 0x2a, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x5b, 0x2c, 0x2b, 0x4b, 0x4c, 0x56, 0x2c, 0x2b, 0x96, 0x2b, 0x5d, 0x12, 0x31, 0x32, 0x48, 0x64, 0x74, 0x3a, 0x3a, 0x64, 0x4a, 0x30, 0x31, 0x12, 0x12, 0x3a, 0x37, 0x50, 0x79, 0x41, 0x41, 0x41, 0x41, 0x79, 0x4e, 0x39, 0x38, 0xc6, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x41, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x3e, 0x00, 0x4d, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x13, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x10, 0x2c, 0x2d, 0x2d, 0x2b, 0x74, 0x3d, 0x3d, 0x09, 0x20, 0x36, 0x33, 0x3e, 0x82, 0x97, 0x4e, 0x50, 0x82, 0x96, 0x4f, 0x4f, 0x60, 0x62, 0xa4, 0x2c, 0x2d, 0x2d, 0xb8, 0x4f, 0x5c, 0x2e, 0x2e, 0x4f, 0x4c, 0x30, 0x2f, 0x2f, 0x2e, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xdf, 0x67, 0x14, 0x0b, 0x0a, 0x4b, 0x4b, 0x9a, 0x2f, 0x1b, 0x1a, 0x98, 0x84, 0x81, 0x4d, 0x4e, 0x6f, 0x6f, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x01, 0x72, 0x68, 0x5c, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5c, 0x34, 0x34, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x38, 0x00, 0x3f, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x03, 0x86, 0x80, 0x2d, 0x2e, 0x2e, 0x2d, 0x80, 0x2d, 0x2e, 0x2e, 0x6d, 0x76, 0x99, 0x99, 0x76, 0x92, 0x7e, 0x7e, 0xfe, 0x9c, 0x78, 0x7e, 0x7b, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0xc8, 0x56, 0x56, 0xac, 0xad, 0x56, 0x56, 0x56, 0x56, 0xad, 0xac, 0x56, 0xaf, 0xde, 0xd3, 0xd4, 0xde, 0xde, 0xd4, 0xd3, 0xde, 0xfc, 0xac, 0x02, 0xd1, 0x29, 0x74, 0x27, 0xfc, 0xbd, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x05, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x87, 0x72, 0x3b, 0x39, 0x81, 0x2c, 0x24, 0x4c, 0x3f, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0xfd, 0xdc, 0x95, 0x46, 0x45, 0x60, 0x54, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x38, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0xe9, 0x2c, 0x5b, 0x33, 0xa3, 0xb4, 0xb5, 0xa2, 0x33, 0x5c, 0x2b, 0x2a, 0x5f, 0x31, 0x70, 0x6f, 0x6e, 0x71, 0x31, 0x60, 0x29, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xeb, 0x17, 0x16, 0xe3, 0xce, 0xcd, 0xe5, 0x17, 0x17, 0x74, 0x22, 0x24, 0xaa, 0xac, 0xab, 0xab, 0x24, 0x22, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x18, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x3a, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x03, 0x22, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x07, 0x12, 0x10, 0x26, 0x23, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0x2f, 0x04, 0x0f, 0x05, 0x8e, 0x8b, 0x8c, 0x8e, 0x8f, 0x8d, 0x4e, 0x4f, 0x71, 0x55, 0x09, 0x4c, 0x58, 0x56, 0x4d, 0x4d, 0x56, 0x58, 0xfe, 0x9c, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x02, 0x41, 0x01, 0xd7, 0xda, 0xdb, 0xd7, 0xd7, 0xdb, 0xa5, 0xc9, 0x28, 0x6a, 0x38, 0x01, 0x80, 0x01, 0x70, 0x9e, 0x9e, 0xfe, 0x90, 0x9e, 0x03, 0x6f, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x06, 0x00, 0x12, 0x00, 0x1e, 0x00, 0x29, 0x00, 0x00, 0x01, 0x30, 0x09, 0x01, 0x30, 0x01, 0x30, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x04, 0x4f, 0x01, 0x70, 0xfe, 0x90, 0xfe, 0x8f, 0xfe, 0xae, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xd8, 0x72, 0x01, 0x46, 0x94, 0xfe, 0x91, 0x01, 0x8c, 0x96, 0xfe, 0x9f, 0x72, 0x02, 0xf9, 0xfd, 0xf2, 0xfd, 0xfa, 0x02, 0x06, 0x06, 0x0a, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0xfe, 0x9f, 0x01, 0x61, 0xfe, 0x7a, 0xfe, 0x42, 0x01, 0x93, 0xfe, 0x6d, 0x00, 0x03, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x09, 0x00, 0x15, 0x00, 0x21, 0x00, 0x00, 0x01, 0x13, 0x21, 0x01, 0x13, 0x09, 0x01, 0x13, 0x01, 0x21, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x03, 0xaf, 0x80, 0x01, 0xa3, 0xfe, 0xae, 0x81, 0xfe, 0xae, 0xfe, 0xad, 0x82, 0xfe, 0xae, 0x01, 0xa2, 0xfe, 0x5e, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x05, 0x31, 0xfe, 0x47, 0xfe, 0xef, 0xfe, 0x47, 0x01, 0x11, 0xfe, 0xef, 0x01, 0xb9, 0x01, 0x11, 0x03, 0x7d, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x3e, 0x00, 0x46, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x03, 0x33, 0x03, 0x33, 0x01, 0x23, 0x27, 0x21, 0x07, 0x23, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x10, 0x78, 0xf1, 0xbd, 0x8a, 0x01, 0x04, 0x77, 0x3d, 0xfe, 0xd7, 0x3d, 0x77, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0xac, 0xfe, 0x55, 0x02, 0x0f, 0xfc, 0xbc, 0xda, 0xda, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x54, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x21, 0x15, 0x21, 0x35, 0x36, 0x37, 0x00, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x01, 0x06, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x75, 0x01, 0x7d, 0xfd, 0xe6, 0x1f, 0x38, 0x01, 0x36, 0x5e, 0x4c, 0x2f, 0x6e, 0x41, 0x46, 0x77, 0x34, 0x82, 0x9d, 0xfe, 0xd6, 0x33, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfc, 0x3f, 0x72, 0x6e, 0x1f, 0x38, 0x01, 0x31, 0x5e, 0x42, 0x51, 0x23, 0x23, 0x7b, 0x1c, 0x1c, 0x84, 0x6c, 0x8b, 0xfe, 0xe4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x64, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x57, 0x53, 0x5b, 0xab, 0x9f, 0x33, 0x71, 0x3f, 0x2f, 0x6b, 0x3c, 0x62, 0x6c, 0x64, 0x61, 0x4d, 0x54, 0x55, 0x57, 0x5a, 0x55, 0x24, 0x5c, 0x49, 0x42, 0x73, 0x31, 0x82, 0x98, 0x51, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x91, 0x12, 0x6d, 0x52, 0x7c, 0x86, 0x15, 0x14, 0x79, 0x1b, 0x1a, 0x4f, 0x46, 0x4a, 0x4c, 0x6c, 0x3f, 0x3c, 0x3a, 0x3d, 0x12, 0x17, 0x73, 0x11, 0x12, 0x76, 0x63, 0x45, 0x60, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x3e, 0x00, 0x49, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x09, 0x01, 0x21, 0x03, 0x33, 0x11, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x4d, 0xfe, 0xe9, 0x01, 0x17, 0x14, 0x95, 0x7a, 0x7a, 0x81, 0xfe, 0x8b, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0x97, 0xfe, 0x5d, 0x02, 0x1c, 0xfd, 0xe4, 0x6d, 0xba, 0xba, 0x79, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x5c, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x21, 0x15, 0x21, 0x15, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xfc, 0x01, 0xcb, 0xfe, 0xa0, 0x19, 0x1a, 0x1a, 0x19, 0x91, 0x54, 0x55, 0x57, 0x57, 0x9e, 0x36, 0x72, 0x3b, 0x33, 0x38, 0x38, 0x3e, 0x64, 0x75, 0x75, 0x64, 0x2f, 0x5d, 0x31, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0x5f, 0xcc, 0x09, 0x04, 0x04, 0x4d, 0x4c, 0x83, 0x87, 0x4b, 0x4a, 0x12, 0x12, 0x71, 0x1b, 0x0e, 0x0d, 0x66, 0xae, 0x66, 0x14, 0x15, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x4b, 0x00, 0x6b, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x13, 0x15, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x0d, 0x4f, 0x2e, 0x2e, 0x2e, 0x2e, 0x4f, 0x4e, 0x2e, 0x2e, 0x2e, 0x2e, 0x9a, 0x2c, 0x2d, 0x2d, 0x2c, 0x73, 0x3e, 0x3d, 0x09, 0x22, 0x34, 0x34, 0x3d, 0x83, 0x4b, 0x4c, 0x4f, 0x4f, 0x82, 0x97, 0x9e, 0x61, 0x61, 0xa4, 0x2c, 0x2d, 0x2d, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x9e, 0x34, 0x35, 0x5b, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5b, 0x35, 0x34, 0x01, 0x62, 0x67, 0x14, 0x0a, 0x0b, 0x4b, 0x4c, 0x99, 0x31, 0x1a, 0x1a, 0x4c, 0x4d, 0x84, 0x7f, 0x4f, 0x4e, 0xde, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x42, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x21, 0x15, 0x01, 0x23, 0x01, 0x21, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xd8, 0x02, 0x2b, 0xfe, 0xc7, 0x7a, 0x01, 0x27, 0xfe, 0x61, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0x30, 0xfc, 0xed, 0x02, 0xe4, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x48, 0x00, 0x66, 0x00, 0x75, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x37, 0x36, 0x34, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x20, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x22, 0x07, 0x06, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0x55, 0xa8, 0x2f, 0x30, 0x5f, 0x54, 0x53, 0x30, 0x30, 0x30, 0xf8, 0x4c, 0x29, 0x2a, 0x93, 0x01, 0x02, 0x4a, 0x48, 0x29, 0x2a, 0x4b, 0x51, 0x32, 0x30, 0x4c, 0x4e, 0x8e, 0x8f, 0x4d, 0x4d, 0x30, 0x30, 0x29, 0x2a, 0x29, 0x4d, 0x49, 0x2c, 0x2b, 0x2b, 0x2a, 0x96, 0x2b, 0x2a, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfd, 0x5b, 0x2c, 0x2b, 0x4b, 0x4c, 0x56, 0x2c, 0x2b, 0x96, 0x2b, 0x5d, 0x12, 0x31, 0x32, 0x48, 0x64, 0x74, 0x3a, 0x3a, 0x64, 0x4a, 0x30, 0x31, 0x12, 0x12, 0x3a, 0x37, 0x50, 0x79, 0x41, 0x41, 0x41, 0x41, 0x79, 0x4e, 0x39, 0x38, 0xc6, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x41, 0x3f, 0x26, 0x25, 0x25, 0x24, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x5b, 0x00, 0x6a, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x35, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x06, 0x07, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x13, 0x32, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x10, 0x2c, 0x2d, 0x2d, 0x2b, 0x74, 0x3d, 0x3d, 0x09, 0x20, 0x36, 0x33, 0x3e, 0x82, 0x97, 0x4e, 0x50, 0x82, 0x96, 0x4f, 0x4f, 0x60, 0x62, 0xa4, 0x2c, 0x2d, 0x2d, 0xb8, 0x4f, 0x5c, 0x2e, 0x2e, 0x4f, 0x4c, 0x30, 0x2f, 0x2f, 0x2e, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xdf, 0x67, 0x14, 0x0b, 0x0a, 0x4b, 0x4b, 0x9a, 0x2f, 0x1b, 0x1a, 0x98, 0x84, 0x81, 0x4d, 0x4e, 0x6f, 0x6f, 0xd4, 0xc6, 0x75, 0x76, 0x08, 0x09, 0x01, 0x72, 0x68, 0x5c, 0x5a, 0x34, 0x35, 0x35, 0x34, 0x5a, 0x5c, 0x34, 0x34, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x49, 0x00, 0x55, 0x00, 0x5c, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x00, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x37, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x01, 0x11, 0x07, 0x35, 0x37, 0x33, 0x11, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x03, 0x86, 0x80, 0x2d, 0x2e, 0x2e, 0x2d, 0x80, 0x2d, 0x2e, 0x2e, 0x6d, 0x76, 0x99, 0x99, 0x76, 0x92, 0x7e, 0x7e, 0xfe, 0x9c, 0x78, 0x7e, 0x7b, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfe, 0xc8, 0x56, 0x56, 0xac, 0xad, 0x56, 0x56, 0x56, 0x56, 0xad, 0xac, 0x56, 0xaf, 0xde, 0xd3, 0xd4, 0xde, 0xde, 0xd4, 0xd3, 0xde, 0xfc, 0xac, 0x02, 0xd1, 0x29, 0x74, 0x27, 0xfc, 0xbd, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x48, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x05, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x36, 0x35, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0x87, 0x72, 0x3b, 0x39, 0x81, 0x2c, 0x24, 0x4c, 0x3f, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0xfd, 0xdc, 0x95, 0x46, 0x45, 0x60, 0x54, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x55, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x15, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x02, 0xe9, 0x2c, 0x5b, 0x33, 0xa3, 0xb4, 0xb5, 0xa2, 0x33, 0x5c, 0x2b, 0x2a, 0x5f, 0x31, 0x70, 0x6f, 0x6e, 0x71, 0x31, 0x60, 0x29, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xeb, 0x17, 0x16, 0xe3, 0xce, 0xcd, 0xe5, 0x17, 0x17, 0x74, 0x22, 0x24, 0xaa, 0xac, 0xab, 0xab, 0x24, 0x22, 0x00, 0x00, 0x00, 0x05, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x4d, 0x00, 0x57, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x01, 0x22, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x07, 0x12, 0x10, 0x26, 0x23, 0x22, 0x06, 0x10, 0x16, 0x33, 0x32, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x01, 0xfb, 0x04, 0x0f, 0x05, 0x8e, 0x8b, 0x8c, 0x8e, 0x8f, 0x8d, 0x4e, 0x4f, 0x71, 0x55, 0x09, 0x4c, 0x58, 0x56, 0x4d, 0x4d, 0x56, 0x58, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xfb, 0xbf, 0x01, 0xd7, 0xda, 0xdb, 0xd7, 0xd7, 0xdb, 0xa5, 0xc9, 0x28, 0x6a, 0x38, 0x01, 0x80, 0x01, 0x70, 0x9e, 0x9e, 0xfe, 0x90, 0x9e, 0x00, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x46, 0x00, 0x00, 0x05, 0x36, 0x35, 0x06, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x26, 0x35, 0x34, 0x20, 0x15, 0x14, 0x07, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x14, 0x17, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x17, 0x33, 0x11, 0x01, 0x33, 0x09, 0x01, 0x23, 0x01, 0x11, 0x23, 0x03, 0xe6, 0x33, 0x40, 0x99, 0x30, 0x17, 0x83, 0x0e, 0x39, 0x9a, 0x43, 0x2d, 0x70, 0x01, 0xa9, 0x70, 0x2c, 0x44, 0x9a, 0x38, 0x0f, 0x84, 0x16, 0x30, 0x98, 0x42, 0x34, 0xfd, 0x1b, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0xd8, 0x72, 0x01, 0x46, 0x94, 0xfe, 0x91, 0x01, 0x8c, 0x96, 0xfe, 0x9f, 0x72, 0xfc, 0x4c, 0xfb, 0xc3, 0x03, 0x01, 0x0c, 0x43, 0x95, 0x34, 0x24, 0x8d, 0x13, 0x82, 0x6a, 0xea, 0xea, 0x6a, 0x82, 0x13, 0x8d, 0x24, 0x34, 0x92, 0x46, 0x0c, 0x01, 0x05, 0xc5, 0xfb, 0x4c, 0x07, 0xf1, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0xf0, 0xfe, 0x9f, 0x01, 0x61, 0xfe, 0x7a, 0xfe, 0x42, 0x01, 0x93, 0xfe, 0x6d, 0x00, 0x04, 0x00, 0xb4, 0xfe, 0x14, 0x06, 0xaa, 0x07, 0x6d, 0x00, 0x09, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x00, 0x01, 0x03, 0x21, 0x17, 0x03, 0x37, 0x17, 0x03, 0x37, 0x21, 0x03, 0x13, 0x05, 0x01, 0x13, 0x25, 0x05, 0x13, 0x01, 0x25, 0x01, 0x22, 0x15, 0x11, 0x14, 0x33, 0x21, 0x32, 0x35, 0x11, 0x34, 0x23, 0x25, 0x21, 0x32, 0x15, 0x11, 0x14, 0x23, 0x21, 0x22, 0x35, 0x11, 0x34, 0x03, 0xaf, 0x5a, 0xfe, 0xdd, 0xeb, 0x5b, 0xed, 0xeb, 0x59, 0xeb, 0xfe, 0xdb, 0x58, 0x9c, 0x01, 0x87, 0xfe, 0xd8, 0x57, 0xfe, 0xae, 0xfe, 0xad, 0x58, 0xfe, 0xd8, 0x01, 0x88, 0xfe, 0x78, 0x6c, 0x6c, 0x04, 0x46, 0x6c, 0x6c, 0xfb, 0xba, 0x04, 0x46, 0xd8, 0xd8, 0xfb, 0xba, 0xd8, 0x04, 0x6e, 0xfe, 0xce, 0xbe, 0xfe, 0xcd, 0xbe, 0xbe, 0x01, 0x33, 0xbe, 0x01, 0xf5, 0xfe, 0x6f, 0x28, 0xfe, 0xe2, 0xfe, 0x54, 0xdf, 0xdf, 0x01, 0xa8, 0x01, 0x22, 0x28, 0x03, 0x55, 0x78, 0xf8, 0x87, 0x78, 0x78, 0x07, 0x79, 0x78, 0x78, 0xf0, 0xf8, 0x87, 0xf0, 0xf0, 0x07, 0x79, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x89, 0xff, 0x6a, 0x06, 0xf9, 0x07, 0x56, 0x00, 0x07, 0x00, 0x11, 0x00, 0x19, 0x00, 0x23, 0x00, 0x2b, 0x00, 0x33, 0x00, 0x7f, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x37, 0x22, 0x06, 0x15, 0x14, 0x33, 0x32, 0x36, 0x35, 0x34, 0x24, 0x14, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x17, 0x22, 0x06, 0x15, 0x14, 0x33, 0x32, 0x36, 0x35, 0x34, 0x00, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x36, 0x14, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x06, 0x32, 0x3e, 0x03, 0x37, 0x13, 0x17, 0x07, 0x3e, 0x04, 0x35, 0x34, 0x26, 0x27, 0x26, 0x27, 0x3e, 0x01, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x01, 0x15, 0x14, 0x17, 0x07, 0x26, 0x35, 0x34, 0x37, 0x26, 0x22, 0x07, 0x16, 0x15, 0x14, 0x07, 0x27, 0x36, 0x35, 0x34, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x06, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x1e, 0x03, 0x17, 0x27, 0x37, 0x13, 0x1e, 0x03, 0x12, 0x32, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x07, 0x05, 0x07, 0x25, 0x07, 0x06, 0x07, 0x05, 0x07, 0x25, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x05, 0x27, 0x25, 0x26, 0x2f, 0x01, 0x05, 0x27, 0x25, 0x2e, 0x03, 0x35, 0x34, 0x37, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x02, 0x9c, 0x3b, 0x53, 0x3b, 0x3b, 0x53, 0x69, 0x10, 0x28, 0x0c, 0x0f, 0x29, 0x01, 0x84, 0x3b, 0x53, 0x3c, 0x3c, 0x53, 0x14, 0x0f, 0x28, 0x0c, 0x10, 0x28, 0xfe, 0x97, 0x14, 0x1d, 0x14, 0x14, 0x1d, 0xd4, 0x13, 0x1d, 0x14, 0x14, 0x1d, 0x91, 0x61, 0x46, 0x29, 0x19, 0x08, 0x02, 0x0e, 0x79, 0x0b, 0x35, 0x66, 0x67, 0x4e, 0x30, 0x3c, 0x32, 0x2b, 0x3a, 0x41, 0x58, 0x58, 0x47, 0x4b, 0x74, 0x3d, 0x10, 0x75, 0x14, 0x01, 0x26, 0x97, 0x26, 0x01, 0x15, 0x75, 0x10, 0x3c, 0x75, 0x4b, 0x47, 0x58, 0x58, 0x42, 0x3b, 0x2b, 0x31, 0x3d, 0x31, 0x4d, 0x68, 0x66, 0x35, 0x0b, 0x78, 0x0f, 0x02, 0x08, 0x18, 0x29, 0x33, 0x89, 0x44, 0x27, 0xb5, 0x81, 0x7d, 0x9c, 0x54, 0x8d, 0x44, 0x76, 0x89, 0x50, 0x01, 0x76, 0x04, 0xfe, 0x22, 0x01, 0x02, 0x04, 0x01, 0xc9, 0x14, 0xfe, 0x3f, 0x1d, 0x98, 0xe1, 0x98, 0x1d, 0xfe, 0x3f, 0x14, 0x01, 0xc8, 0x03, 0x02, 0x01, 0xfe, 0x21, 0x04, 0x01, 0x76, 0x50, 0x89, 0x76, 0x43, 0x8c, 0x54, 0x9c, 0x7d, 0x81, 0xb6, 0x26, 0x03, 0x38, 0x90, 0x67, 0x67, 0x90, 0x67, 0x82, 0x3d, 0x18, 0x12, 0x3e, 0x18, 0x11, 0x75, 0x90, 0x67, 0x67, 0x90, 0x67, 0xdc, 0x3d, 0x18, 0x12, 0x3e, 0x18, 0x11, 0xfd, 0x22, 0x36, 0x27, 0x27, 0x36, 0x27, 0x5d, 0x36, 0x27, 0x27, 0x36, 0x27, 0xe0, 0x24, 0x39, 0x5d, 0x57, 0x3e, 0x01, 0x3a, 0x06, 0xfb, 0x1f, 0x4c, 0x6b, 0x74, 0x93, 0x4c, 0x4a, 0x98, 0x37, 0x33, 0x28, 0x23, 0x83, 0x58, 0x51, 0x69, 0x6b, 0xa4, 0x5c, 0x42, 0x3f, 0x26, 0x53, 0x54, 0x1b, 0x0e, 0x03, 0x03, 0x0e, 0x1b, 0x54, 0x53, 0x26, 0x3f, 0x42, 0x5c, 0xa4, 0x6b, 0x69, 0x51, 0x58, 0x83, 0x23, 0x28, 0x33, 0x37, 0x98, 0x4a, 0x4c, 0x93, 0x74, 0x6b, 0x4c, 0x1f, 0xfb, 0x06, 0xfe, 0xc6, 0x3e, 0x57, 0x5d, 0x39, 0x06, 0x02, 0x06, 0x86, 0xbe, 0xb7, 0x8c, 0x8a, 0x72, 0xac, 0xc8, 0x6c, 0xc8, 0xa1, 0x7e, 0x33, 0x1a, 0x44, 0x23, 0x01, 0x1f, 0x1f, 0xae, 0x40, 0xac, 0x6d, 0x8a, 0x8a, 0x6d, 0xac, 0x40, 0xae, 0x1f, 0x1f, 0x01, 0x23, 0x44, 0x1a, 0x33, 0x7e, 0xa1, 0xc8, 0x6c, 0xc8, 0xac, 0x72, 0x8a, 0x8c, 0xb7, 0xbe, 0x86, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x43, 0xff, 0x6a, 0x08, 0x43, 0x06, 0x8a, 0x00, 0x09, 0x00, 0x14, 0x00, 0x18, 0x00, 0x22, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x8e, 0x00, 0x99, 0x00, 0x9f, 0x00, 0xfd, 0x01, 0x07, 0x00, 0x00, 0x01, 0x22, 0x26, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x27, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x33, 0x15, 0x23, 0x01, 0x22, 0x26, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x01, 0x37, 0x17, 0x07, 0x27, 0x37, 0x01, 0x15, 0x23, 0x35, 0x25, 0x17, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x1e, 0x01, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x37, 0x16, 0x17, 0x3e, 0x04, 0x37, 0x16, 0x33, 0x32, 0x3e, 0x04, 0x37, 0x3e, 0x01, 0x35, 0x34, 0x27, 0x2e, 0x04, 0x23, 0x22, 0x0e, 0x02, 0x0f, 0x01, 0x06, 0x07, 0x2e, 0x01, 0x20, 0x06, 0x07, 0x26, 0x2f, 0x01, 0x2e, 0x03, 0x23, 0x22, 0x0e, 0x03, 0x07, 0x06, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x05, 0x33, 0x32, 0x37, 0x1e, 0x04, 0x17, 0x36, 0x25, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x01, 0x07, 0x17, 0x07, 0x27, 0x37, 0x01, 0x34, 0x37, 0x27, 0x26, 0x27, 0x23, 0x22, 0x2e, 0x06, 0x27, 0x2e, 0x01, 0x35, 0x34, 0x3e, 0x01, 0x37, 0x3e, 0x01, 0x33, 0x32, 0x1e, 0x02, 0x17, 0x16, 0x1f, 0x01, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x37, 0x36, 0x37, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x17, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x0e, 0x07, 0x2b, 0x01, 0x06, 0x0f, 0x01, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26, 0x01, 0x06, 0x20, 0x27, 0x16, 0x17, 0x16, 0x33, 0x32, 0x36, 0x03, 0x20, 0x2d, 0x38, 0x37, 0x2e, 0x2d, 0x38, 0x37, 0x1b, 0x10, 0x29, 0x0d, 0x0f, 0x15, 0x14, 0x30, 0x63, 0x63, 0x02, 0x0f, 0x2e, 0x37, 0x37, 0x2e, 0x2d, 0x37, 0x38, 0xfb, 0xcb, 0x2e, 0xb1, 0x33, 0x39, 0x26, 0x03, 0x39, 0x63, 0xfe, 0x09, 0x3c, 0x39, 0x0f, 0x05, 0x34, 0x2e, 0xa0, 0x7d, 0x5e, 0x3e, 0x74, 0x3b, 0x33, 0x04, 0x0f, 0x39, 0x3b, 0x16, 0x10, 0x04, 0x1c, 0x0b, 0x12, 0x09, 0x01, 0x4a, 0x23, 0x1d, 0x32, 0x21, 0x2b, 0x14, 0x30, 0x0b, 0x2c, 0x2a, 0x2f, 0x02, 0x22, 0x1b, 0x27, 0x27, 0x10, 0x0f, 0x1d, 0x20, 0x0e, 0x11, 0x11, 0x39, 0x50, 0x37, 0xee, 0xfe, 0xde, 0xef, 0x37, 0x50, 0x38, 0x11, 0x11, 0x0f, 0x1f, 0x1d, 0x0f, 0x11, 0x26, 0x27, 0x1b, 0x22, 0x02, 0x2f, 0x2a, 0x2c, 0x0a, 0x31, 0x14, 0x2a, 0x21, 0x33, 0x1d, 0x23, 0x49, 0x01, 0x09, 0x12, 0x0c, 0x1b, 0x05, 0x10, 0x02, 0xb8, 0x11, 0x28, 0x0d, 0x0f, 0x15, 0x13, 0x01, 0xbb, 0x99, 0x26, 0x39, 0x33, 0xb1, 0xfb, 0x51, 0x0b, 0x12, 0x34, 0x0e, 0x09, 0x1e, 0x35, 0x27, 0x2f, 0x19, 0x31, 0x11, 0x39, 0x09, 0x3b, 0x34, 0x24, 0x28, 0x20, 0x2d, 0x7a, 0x3a, 0x1b, 0x2d, 0x2d, 0x17, 0x15, 0x21, 0x0f, 0x3b, 0x24, 0x31, 0x94, 0x01, 0x7a, 0x93, 0x32, 0x24, 0x3a, 0x10, 0x21, 0x15, 0x16, 0x2d, 0x2e, 0x1a, 0x3b, 0x79, 0x2e, 0x20, 0x27, 0x25, 0x34, 0x3c, 0x08, 0x39, 0x11, 0x32, 0x18, 0x30, 0x26, 0x36, 0x1d, 0x09, 0x0f, 0x33, 0x13, 0x0c, 0x0c, 0x1f, 0x56, 0x08, 0x14, 0x1d, 0x3b, 0x31, 0x7a, 0xb0, 0x7b, 0x30, 0x3c, 0x1d, 0x13, 0x08, 0x56, 0x20, 0x0b, 0x02, 0xe2, 0x57, 0xfe, 0xda, 0x57, 0x0f, 0x1c, 0x32, 0x8d, 0x60, 0x71, 0x02, 0xd1, 0x6e, 0x82, 0x6e, 0x6e, 0x82, 0x6e, 0x1b, 0x41, 0x15, 0x11, 0x1f, 0x1d, 0x19, 0x12, 0xd4, 0xd2, 0x01, 0x8b, 0x6e, 0x82, 0x6e, 0x6e, 0x82, 0x6e, 0x02, 0xb5, 0x2d, 0xda, 0xba, 0x18, 0x94, 0xfd, 0x4d, 0xd2, 0xd2, 0x93, 0x76, 0x24, 0x44, 0x11, 0x19, 0x4b, 0x3b, 0x37, 0x22, 0x08, 0x0d, 0x44, 0x3b, 0x4b, 0x19, 0x11, 0x44, 0x24, 0x76, 0x0d, 0x0f, 0x13, 0x68, 0x35, 0x57, 0x4d, 0x27, 0x14, 0x0b, 0x0c, 0x20, 0x11, 0x31, 0x0a, 0x2a, 0x4c, 0x37, 0x2e, 0x34, 0x02, 0x28, 0x1a, 0x23, 0x13, 0x0e, 0x22, 0x11, 0x19, 0x19, 0x4e, 0x83, 0x65, 0x6d, 0x6d, 0x65, 0x83, 0x4e, 0x19, 0x19, 0x11, 0x22, 0x0e, 0x13, 0x23, 0x1a, 0x28, 0x02, 0x34, 0x2e, 0x37, 0x4c, 0x2a, 0x0a, 0x31, 0x11, 0x20, 0x0c, 0x0b, 0x14, 0x27, 0x4d, 0x57, 0x35, 0x68, 0x13, 0x0f, 0x4e, 0x41, 0x15, 0x11, 0x1f, 0x1d, 0x19, 0x12, 0x02, 0x9a, 0xbb, 0x94, 0x18, 0xba, 0xda, 0xfb, 0xef, 0x2a, 0x2c, 0x50, 0xdd, 0x49, 0x09, 0x08, 0x1b, 0x0d, 0x2c, 0x0f, 0x39, 0x09, 0x3a, 0x6b, 0x52, 0x34, 0x5f, 0x35, 0x22, 0x32, 0x53, 0x12, 0x27, 0x18, 0x19, 0x27, 0x15, 0x52, 0x1d, 0x1b, 0x4e, 0x4e, 0x1b, 0x1d, 0x52, 0x15, 0x27, 0x19, 0x18, 0x27, 0x12, 0x53, 0x32, 0x22, 0x35, 0x5f, 0x34, 0x52, 0x6b, 0x3a, 0x09, 0x39, 0x0f, 0x2c, 0x0d, 0x1b, 0x08, 0x09, 0x49, 0xdd, 0x50, 0x2c, 0x2a, 0x30, 0x28, 0x73, 0x42, 0x44, 0x30, 0x48, 0x2e, 0x26, 0x1b, 0x1b, 0x26, 0x2e, 0x48, 0x30, 0x44, 0x42, 0x73, 0x28, 0xfe, 0xe0, 0x16, 0x16, 0x24, 0x15, 0x27, 0x26, 0x00, 0x08, 0x00, 0x36, 0xff, 0x6a, 0x07, 0x4e, 0x07, 0x14, 0x00, 0x11, 0x00, 0x19, 0x00, 0x28, 0x00, 0x32, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x7f, 0x00, 0xb8, 0x00, 0x00, 0x01, 0x37, 0x16, 0x33, 0x32, 0x37, 0x16, 0x33, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x27, 0x06, 0x23, 0x22, 0x01, 0x17, 0x06, 0x22, 0x27, 0x37, 0x16, 0x32, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x07, 0x22, 0x06, 0x15, 0x14, 0x17, 0x3e, 0x01, 0x37, 0x26, 0x05, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x05, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x23, 0x22, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x15, 0x14, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x05, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x36, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x02, 0x62, 0x53, 0x3e, 0x52, 0x34, 0x4c, 0x4b, 0x35, 0x51, 0x3f, 0x52, 0x61, 0x81, 0x43, 0x3d, 0x3e, 0x42, 0x82, 0x01, 0x8c, 0x38, 0x6e, 0xae, 0x6e, 0x38, 0x51, 0x78, 0xea, 0x26, 0x49, 0x1d, 0x24, 0x3f, 0x31, 0x12, 0x2f, 0x2b, 0x3a, 0x3f, 0x5b, 0x46, 0x21, 0x2b, 0x05, 0x26, 0x3e, 0x11, 0x14, 0x01, 0x8c, 0x04, 0x5a, 0x3f, 0x3c, 0x2a, 0x30, 0x13, 0x31, 0x3f, 0x24, 0x1d, 0x49, 0x6d, 0x0b, 0x18, 0x2b, 0x24, 0x0e, 0x03, 0x0b, 0x0c, 0x27, 0x3a, 0x01, 0x6b, 0x10, 0x09, 0x09, 0x14, 0x04, 0x18, 0x26, 0xda, 0x8a, 0x69, 0x8b, 0x8d, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x05, 0x13, 0x09, 0x0a, 0x11, 0x01, 0x21, 0x0a, 0xfe, 0xdf, 0x0c, 0x15, 0x01, 0x01, 0x18, 0xfe, 0xfd, 0x5d, 0x94, 0xa3, 0x01, 0xb9, 0xa3, 0x93, 0x5d, 0xfe, 0xfe, 0x17, 0x01, 0x01, 0x13, 0x0e, 0xfe, 0xe0, 0x09, 0xfb, 0x46, 0x0f, 0x06, 0x11, 0x0b, 0x1c, 0x04, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x5e, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x04, 0x1c, 0x0b, 0x11, 0x06, 0x0f, 0x61, 0x09, 0x62, 0x0d, 0x1d, 0x63, 0x17, 0x63, 0x69, 0xaf, 0xc4, 0xfe, 0xfd, 0xfe, 0xfc, 0xc3, 0xae, 0x6a, 0x62, 0x18, 0x62, 0x1b, 0x0e, 0x62, 0x09, 0x01, 0x8c, 0x62, 0x40, 0x2c, 0x2c, 0x40, 0x62, 0x64, 0x1c, 0x1c, 0x01, 0xa8, 0x78, 0x3d, 0x3d, 0x78, 0x2e, 0x01, 0x06, 0x4c, 0x1c, 0x0b, 0x23, 0x24, 0x2d, 0x47, 0x30, 0x2c, 0x61, 0x26, 0x30, 0x24, 0x0e, 0x0f, 0x07, 0x34, 0x25, 0x11, 0x1d, 0x43, 0x61, 0x2c, 0x30, 0x47, 0x2d, 0x24, 0x23, 0x0b, 0x1c, 0x04, 0x03, 0x16, 0x18, 0x1c, 0x0e, 0x0c, 0x03, 0x3b, 0xa7, 0x82, 0x74, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0x2e, 0x74, 0x82, 0x2b, 0x42, 0x2c, 0x45, 0x40, 0x79, 0x3e, 0x7a, 0xe7, 0x77, 0x84, 0x84, 0x77, 0xe7, 0x7a, 0x3e, 0x79, 0x39, 0x4c, 0x2c, 0x42, 0x3d, 0x7c, 0x8f, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0x0d, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x8f, 0x7c, 0x0f, 0x42, 0x0e, 0x51, 0x57, 0x2e, 0x3e, 0x2e, 0xfe, 0xf7, 0x8e, 0x9e, 0x9e, 0x8c, 0x01, 0x0b, 0x2e, 0x3e, 0x2e, 0x51, 0x57, 0x0e, 0x42, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x99, 0xff, 0x6a, 0x07, 0xbb, 0x07, 0x0b, 0x00, 0x07, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x25, 0x00, 0x31, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x68, 0x00, 0x98, 0x00, 0xaa, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x37, 0x22, 0x06, 0x15, 0x14, 0x33, 0x32, 0x36, 0x35, 0x34, 0x03, 0x22, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x15, 0x14, 0x07, 0x06, 0x00, 0x14, 0x06, 0x22, 0x26, 0x34, 0x36, 0x32, 0x03, 0x34, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x23, 0x22, 0x27, 0x26, 0x01, 0x22, 0x06, 0x15, 0x14, 0x33, 0x32, 0x36, 0x35, 0x34, 0x01, 0x37, 0x16, 0x33, 0x32, 0x36, 0x37, 0x17, 0x06, 0x23, 0x22, 0x26, 0x12, 0x20, 0x37, 0x36, 0x35, 0x34, 0x27, 0x3e, 0x02, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x07, 0x2e, 0x01, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x1e, 0x01, 0x17, 0x06, 0x15, 0x14, 0x17, 0x12, 0x20, 0x04, 0x17, 0x16, 0x17, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x2b, 0x01, 0x06, 0x07, 0x0e, 0x01, 0x07, 0x06, 0x20, 0x27, 0x2e, 0x01, 0x27, 0x26, 0x27, 0x23, 0x22, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x17, 0x36, 0x37, 0x36, 0x03, 0x26, 0x23, 0x22, 0x07, 0x0e, 0x01, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x36, 0x37, 0x26, 0x25, 0x06, 0x07, 0x16, 0x17, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x27, 0x26, 0x23, 0x22, 0x02, 0xca, 0x4a, 0x68, 0x4a, 0x4a, 0x68, 0x82, 0x14, 0x31, 0x0e, 0x14, 0x32, 0x0e, 0x16, 0x28, 0x21, 0x1b, 0x16, 0x28, 0x21, 0x01, 0xd8, 0x49, 0x69, 0x4a, 0x4a, 0x69, 0xe8, 0x16, 0x1c, 0x21, 0x28, 0x16, 0x1c, 0x21, 0x28, 0x01, 0x02, 0x14, 0x32, 0x0f, 0x14, 0x32, 0xfd, 0x33, 0x5f, 0x75, 0xb9, 0x57, 0xa2, 0x35, 0x5f, 0x97, 0xf6, 0x74, 0xd2, 0x7c, 0x01, 0x93, 0x95, 0x6f, 0x4b, 0x1b, 0x1a, 0x1c, 0x4e, 0x51, 0x75, 0x40, 0x65, 0x1c, 0x19, 0x65, 0x40, 0x75, 0x51, 0x4e, 0x1c, 0x1a, 0x1c, 0x4c, 0x70, 0xbb, 0x01, 0x45, 0x01, 0x18, 0x58, 0x5e, 0x0f, 0x16, 0x1a, 0x60, 0x81, 0x07, 0x0c, 0x19, 0x1e, 0x79, 0x50, 0x07, 0x0d, 0x34, 0x33, 0x9a, 0x62, 0x85, 0xfe, 0xfd, 0x85, 0x62, 0x9a, 0x33, 0x34, 0x0d, 0x07, 0x50, 0x78, 0x1f, 0x19, 0x0c, 0x07, 0x82, 0x5f, 0x1a, 0x17, 0x0e, 0x5f, 0x57, 0xc1, 0x15, 0x1d, 0x0c, 0x13, 0x24, 0x27, 0x07, 0x15, 0x3f, 0x1c, 0x23, 0x03, 0x07, 0x36, 0x2f, 0x04, 0xe8, 0x0e, 0x30, 0x36, 0x07, 0x04, 0x22, 0x1c, 0x40, 0x14, 0x07, 0x27, 0x24, 0x13, 0x0c, 0x1c, 0x04, 0x08, 0x74, 0x52, 0x52, 0x74, 0x52, 0x68, 0x31, 0x13, 0x0e, 0x31, 0x13, 0x0e, 0xfe, 0x52, 0x15, 0x20, 0x24, 0x1f, 0x15, 0x20, 0x24, 0x1f, 0x02, 0x0c, 0x74, 0x52, 0x52, 0x74, 0x52, 0xfe, 0x05, 0x15, 0x1f, 0x24, 0x20, 0x15, 0x1f, 0x24, 0x01, 0x6b, 0x31, 0x13, 0x0e, 0x31, 0x13, 0x0e, 0xfd, 0xa8, 0x54, 0xa4, 0x58, 0x4c, 0x54, 0xd6, 0x72, 0xfe, 0xde, 0xcb, 0x9a, 0xb8, 0x86, 0x95, 0x2c, 0x30, 0x5e, 0x31, 0x8a, 0x69, 0x6f, 0x45, 0x35, 0x35, 0x45, 0x6f, 0x69, 0x8a, 0x31, 0x5e, 0x30, 0x2c, 0x95, 0x86, 0xb8, 0x9a, 0x06, 0x00, 0xa4, 0x7c, 0x88, 0x9b, 0x06, 0xa4, 0x87, 0x2c, 0x36, 0x5b, 0x3f, 0x4b, 0x69, 0x7b, 0x70, 0x6e, 0xad, 0x37, 0x4c, 0x4c, 0x37, 0xad, 0x6e, 0x70, 0x7b, 0x69, 0x4b, 0x3f, 0x5b, 0x36, 0x2c, 0x87, 0xa4, 0x06, 0x9b, 0x88, 0x7c, 0xfd, 0xcc, 0x15, 0x07, 0x0f, 0x52, 0x3a, 0x1e, 0x33, 0x97, 0x2f, 0x15, 0x87, 0x7b, 0x57, 0x60, 0x60, 0x57, 0x7b, 0x87, 0x15, 0x2f, 0x97, 0x33, 0x1e, 0x3a, 0x52, 0x0f, 0x07, 0x00, 0x00, 0x09, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x39, 0x00, 0x3e, 0x00, 0x42, 0x00, 0x46, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x21, 0x10, 0x00, 0x20, 0x00, 0x05, 0x36, 0x37, 0x11, 0x23, 0x03, 0x11, 0x23, 0x11, 0x16, 0x25, 0x36, 0x37, 0x23, 0x05, 0x35, 0x23, 0x16, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0xc8, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0xf8, 0x04, 0x5f, 0xfe, 0xb9, 0xfe, 0x30, 0xfe, 0xb8, 0x02, 0x6d, 0x50, 0x44, 0x94, 0x7a, 0x94, 0x45, 0x01, 0xd7, 0x41, 0x19, 0x5a, 0xfd, 0x6a, 0x5b, 0x19, 0x03, 0xff, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xdb, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x6a, 0xfe, 0xfe, 0xfe, 0x96, 0x01, 0x6a, 0xdf, 0x0b, 0x2a, 0x01, 0x25, 0xfe, 0xa6, 0x01, 0x5a, 0xfe, 0xdb, 0x2a, 0x99, 0x52, 0x64, 0xb8, 0xb8, 0x66, 0x00, 0x00, 0x09, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x3a, 0x00, 0x3f, 0x00, 0x43, 0x00, 0x47, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x21, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x07, 0x21, 0x10, 0x00, 0x20, 0x00, 0x05, 0x36, 0x37, 0x11, 0x23, 0x03, 0x11, 0x23, 0x11, 0x16, 0x25, 0x36, 0x37, 0x23, 0x05, 0x35, 0x23, 0x16, 0x01, 0x12, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x03, 0x5c, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfd, 0x72, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xc9, 0x04, 0x5f, 0xfe, 0xb9, 0xfe, 0x30, 0xfe, 0xb8, 0x02, 0x6d, 0x50, 0x44, 0x94, 0x7a, 0x94, 0x45, 0x01, 0xd7, 0x41, 0x19, 0x5a, 0xfd, 0x6a, 0x5b, 0x19, 0x02, 0xea, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x02, 0x16, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xac, 0xfe, 0xfe, 0xfe, 0x96, 0x01, 0x6a, 0xdf, 0x0b, 0x2a, 0x01, 0x25, 0xfe, 0xa6, 0x01, 0x5a, 0xfe, 0xdb, 0x2a, 0x99, 0x52, 0x64, 0xb8, 0xb8, 0x66, 0x00, 0x09, 0x00, 0x55, 0xff, 0x6a, 0x08, 0x14, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x11, 0x00, 0x17, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x59, 0x00, 0x7e, 0x00, 0x00, 0x01, 0x35, 0x23, 0x16, 0x05, 0x36, 0x37, 0x23, 0x01, 0x11, 0x23, 0x11, 0x16, 0x17, 0x36, 0x37, 0x11, 0x23, 0x25, 0x21, 0x10, 0x00, 0x20, 0x00, 0x13, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x21, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x14, 0x07, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x02, 0x07, 0x02, 0x21, 0x20, 0x03, 0x26, 0x03, 0x07, 0x06, 0x07, 0x06, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3f, 0x01, 0x26, 0x37, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x27, 0x06, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x17, 0x16, 0x17, 0x26, 0x27, 0x26, 0x21, 0x20, 0x07, 0x06, 0x07, 0x36, 0x3f, 0x01, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x06, 0x02, 0xe9, 0x5b, 0x1a, 0x02, 0xd8, 0x40, 0x1a, 0x5a, 0xfe, 0x77, 0x93, 0x44, 0xca, 0x4f, 0x44, 0x93, 0xfd, 0x93, 0x04, 0x5e, 0xfe, 0xba, 0xfe, 0x2f, 0xfe, 0xb9, 0x4f, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0x01, 0x9c, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xfc, 0x2a, 0x01, 0xda, 0x01, 0x4e, 0x01, 0x50, 0x01, 0xd8, 0x02, 0x54, 0x35, 0x15, 0x1b, 0x30, 0x45, 0x1c, 0x16, 0x10, 0x0a, 0x26, 0xbc, 0xec, 0xfe, 0xb0, 0xfe, 0xb2, 0xed, 0xbc, 0x27, 0x09, 0x10, 0x17, 0x1c, 0x44, 0x30, 0x1a, 0x15, 0x36, 0x53, 0x02, 0x7a, 0x01, 0x92, 0x01, 0x1c, 0x01, 0x1e, 0x01, 0x90, 0x01, 0x18, 0x21, 0x22, 0x1c, 0x17, 0x10, 0x29, 0x7b, 0x25, 0x15, 0x2a, 0x8b, 0xc7, 0xfe, 0xe1, 0xfe, 0xe4, 0xca, 0x8a, 0x2a, 0x15, 0x25, 0x7a, 0x28, 0x10, 0x17, 0x1c, 0x44, 0x18, 0x01, 0x01, 0xa1, 0xb8, 0x66, 0x50, 0x52, 0x64, 0xfe, 0xa6, 0x01, 0x5a, 0xfe, 0xdb, 0x2a, 0x0b, 0x0b, 0x2a, 0x01, 0x25, 0x87, 0xfe, 0xfe, 0xfe, 0x96, 0x01, 0x6a, 0x01, 0xae, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xa2, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0x1d, 0x1b, 0x1f, 0x14, 0x18, 0x1f, 0x25, 0x26, 0x36, 0x1f, 0x19, 0x39, 0x20, 0xfe, 0xe9, 0xd1, 0xfe, 0xfa, 0x01, 0x06, 0xd0, 0x01, 0x16, 0x1e, 0x39, 0x19, 0x1f, 0x36, 0x26, 0x25, 0x1f, 0x19, 0x13, 0x1e, 0x1c, 0x1d, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x14, 0x13, 0x1a, 0x1f, 0x19, 0x39, 0x88, 0x2d, 0x0e, 0x0f, 0xc7, 0x9a, 0xe0, 0xe0, 0x9b, 0xc6, 0x10, 0x0d, 0x2d, 0x88, 0x39, 0x19, 0x1f, 0x1b, 0x14, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x21, 0x10, 0x00, 0x20, 0x00, 0x25, 0x21, 0x16, 0x17, 0x16, 0x24, 0x37, 0x36, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x7f, 0x04, 0x5f, 0xfe, 0xb9, 0xfe, 0x30, 0xfe, 0xb8, 0x03, 0xd5, 0xfc, 0xb5, 0x1e, 0x53, 0x7f, 0x01, 0x6c, 0x80, 0x53, 0x03, 0xff, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xdb, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xb9, 0xfe, 0xfe, 0xfe, 0x96, 0x01, 0x6a, 0x7b, 0x75, 0x5c, 0x8e, 0x01, 0x8e, 0x5c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x21, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x21, 0x10, 0x00, 0x20, 0x00, 0x25, 0x21, 0x16, 0x17, 0x16, 0x37, 0x32, 0x37, 0x36, 0x01, 0xe1, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0x01, 0x9b, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfc, 0x2a, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x7f, 0x04, 0x5f, 0xfe, 0xb9, 0xfe, 0x30, 0xfe, 0xb8, 0x03, 0xd5, 0xfc, 0xb5, 0x1e, 0x53, 0x7f, 0xb6, 0xb6, 0x80, 0x53, 0x03, 0x8c, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xa2, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xb9, 0xfe, 0xfe, 0xfe, 0x96, 0x01, 0x6a, 0x7b, 0x75, 0x5c, 0x8e, 0x01, 0x8e, 0x5c, 0x00, 0x07, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x41, 0x00, 0x4a, 0x00, 0x00, 0x01, 0x17, 0x16, 0x07, 0x14, 0x07, 0x06, 0x22, 0x26, 0x35, 0x34, 0x37, 0x05, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x21, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x21, 0x10, 0x00, 0x20, 0x00, 0x25, 0x21, 0x16, 0x17, 0x16, 0x37, 0x32, 0x37, 0x36, 0x05, 0xfe, 0x3a, 0x19, 0x01, 0x18, 0x18, 0x45, 0x30, 0x18, 0xfc, 0x1e, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0x01, 0x9b, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfc, 0x2a, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x7f, 0x04, 0x5f, 0xfe, 0xb9, 0xfe, 0x30, 0xfe, 0xb8, 0x03, 0xd5, 0xfc, 0xb5, 0x1e, 0x53, 0x7f, 0xb6, 0xb6, 0x80, 0x53, 0x04, 0x2c, 0x80, 0x38, 0x22, 0x2b, 0x1a, 0x1b, 0x36, 0x2c, 0x23, 0x35, 0x20, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xa2, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xb9, 0xfe, 0xfe, 0xfe, 0x96, 0x01, 0x6a, 0x7b, 0x75, 0x5c, 0x8e, 0x01, 0x8e, 0x5c, 0x00, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x25, 0x00, 0x2b, 0x00, 0x33, 0x00, 0x00, 0x01, 0x25, 0x17, 0x07, 0x17, 0x07, 0x25, 0x27, 0x15, 0x05, 0x27, 0x37, 0x27, 0x37, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x21, 0x10, 0x00, 0x20, 0x00, 0x25, 0x21, 0x16, 0x17, 0x16, 0x24, 0x37, 0x36, 0x04, 0x09, 0x01, 0x0a, 0x45, 0xb2, 0xb2, 0x45, 0xfe, 0xf6, 0x90, 0xfe, 0xf7, 0x46, 0xb3, 0xb3, 0x46, 0xfe, 0x29, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x7f, 0x04, 0x5f, 0xfe, 0xb9, 0xfe, 0x30, 0xfe, 0xb8, 0x03, 0xd5, 0xfc, 0xb5, 0x1e, 0x53, 0x7f, 0x01, 0x6c, 0x80, 0x53, 0x04, 0x27, 0xce, 0x6e, 0x8b, 0x8a, 0x6e, 0xce, 0x55, 0x55, 0xce, 0x6e, 0x8a, 0x8b, 0x6e, 0xfd, 0xf5, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xb9, 0xfe, 0xfe, 0xfe, 0x96, 0x01, 0x6a, 0x7b, 0x75, 0x5c, 0x8e, 0x01, 0x8e, 0x5c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x80, 0xff, 0x6a, 0x07, 0x01, 0x07, 0x63, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x49, 0x00, 0x57, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x37, 0x16, 0x17, 0x16, 0x04, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x2f, 0x01, 0x06, 0x21, 0x20, 0x27, 0x07, 0x06, 0x05, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x01, 0x34, 0x24, 0x21, 0x20, 0x04, 0x15, 0x14, 0x07, 0x16, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x37, 0x26, 0x25, 0x36, 0x35, 0x34, 0x24, 0x21, 0x20, 0x04, 0x15, 0x14, 0x17, 0x36, 0x21, 0x20, 0x17, 0x26, 0x23, 0x22, 0x07, 0x16, 0x33, 0x32, 0x01, 0xe7, 0x67, 0x1a, 0x24, 0x80, 0x01, 0x6b, 0x80, 0x23, 0x1a, 0x68, 0x22, 0x2d, 0xa4, 0xfe, 0x30, 0xa4, 0x2d, 0xf6, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xc8, 0x0c, 0xcf, 0xfe, 0xf5, 0xfe, 0xf6, 0xcf, 0x0d, 0xc9, 0x03, 0x38, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfd, 0xf8, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0xfe, 0x3f, 0x01, 0xe7, 0x01, 0x59, 0x01, 0x5a, 0x01, 0xe6, 0xe4, 0xcb, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0xcc, 0xe4, 0x05, 0x45, 0xa9, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0xab, 0xdb, 0x01, 0x29, 0x01, 0x2a, 0x3c, 0x9e, 0xc8, 0xc7, 0x9e, 0x9e, 0xc7, 0xc8, 0x01, 0xd1, 0x47, 0x2c, 0x26, 0x8d, 0x01, 0x8e, 0x27, 0x2c, 0x48, 0x39, 0x32, 0xb5, 0xb5, 0x33, 0x01, 0x51, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0xe0, 0x0e, 0x39, 0x39, 0x0e, 0xe0, 0x2a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x02, 0x5c, 0x86, 0xbe, 0xbe, 0x86, 0x82, 0x5c, 0xfc, 0xfe, 0xa5, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0x01, 0x5b, 0xfc, 0x5c, 0x02, 0x36, 0x4a, 0x51, 0x72, 0x72, 0x51, 0x4a, 0x36, 0xcf, 0xf5, 0x6e, 0x6e, 0x1c, 0x00, 0x07, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x07, 0x30, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x4a, 0x00, 0x00, 0x01, 0x05, 0x07, 0x25, 0x01, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x01, 0x17, 0x05, 0x27, 0x01, 0x37, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x36, 0x20, 0x17, 0x25, 0x11, 0x16, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x37, 0x11, 0x02, 0x8a, 0x01, 0x10, 0x45, 0xfe, 0xef, 0x02, 0x06, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfd, 0xf8, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0xb7, 0x45, 0xfe, 0xef, 0x45, 0xfd, 0xff, 0x67, 0x1a, 0x24, 0x7f, 0x01, 0x6c, 0x80, 0x23, 0x1a, 0x68, 0x22, 0x2d, 0xa4, 0xfe, 0x30, 0xa4, 0x2d, 0xf6, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x01, 0xb2, 0x77, 0x01, 0x0c, 0x77, 0x01, 0x8f, 0x9b, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x9d, 0x05, 0x67, 0xd4, 0x6f, 0xd5, 0xfe, 0xbc, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x01, 0xec, 0x6e, 0xd5, 0x6f, 0xfd, 0x3e, 0x47, 0x2c, 0x26, 0x8e, 0x8e, 0x27, 0x2c, 0x48, 0x39, 0x32, 0xb5, 0xb5, 0x33, 0x01, 0x51, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x02, 0x1d, 0x2a, 0x2a, 0xec, 0xfd, 0xd0, 0xe7, 0xfe, 0xd1, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0x01, 0x2f, 0xe7, 0x02, 0x30, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x32, 0x00, 0x39, 0x00, 0x00, 0x01, 0x37, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x2d, 0x01, 0x17, 0x07, 0x17, 0x07, 0x25, 0x01, 0xe7, 0x67, 0x1a, 0x24, 0x7f, 0x01, 0x6c, 0x80, 0x23, 0x1a, 0x68, 0x22, 0x2d, 0xa4, 0xfe, 0x30, 0xa4, 0x2d, 0xf6, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x01, 0xa9, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x01, 0xc7, 0x01, 0x0a, 0x45, 0xb2, 0xb2, 0x45, 0xfe, 0xf6, 0x01, 0xd1, 0x47, 0x2c, 0x26, 0x8e, 0x8e, 0x27, 0x2c, 0x48, 0x39, 0x32, 0xb5, 0xb5, 0x33, 0x01, 0x51, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x02, 0x87, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x64, 0xce, 0x6e, 0x8b, 0x8a, 0x6e, 0xce, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x01, 0x37, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x03, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x21, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0xe7, 0x67, 0x1a, 0x24, 0x7f, 0x01, 0x6c, 0x80, 0x23, 0x1a, 0x68, 0x22, 0x2d, 0xa4, 0xfe, 0x30, 0xa4, 0x2d, 0x27, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0x01, 0x9b, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfc, 0x2a, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x01, 0xd1, 0x47, 0x2c, 0x26, 0x8e, 0x8e, 0x27, 0x2c, 0x48, 0x39, 0x32, 0xb5, 0xb5, 0x33, 0x01, 0xf3, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xa2, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x37, 0x00, 0x43, 0x00, 0x51, 0x00, 0x00, 0x01, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x21, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x05, 0x10, 0x00, 0x21, 0x32, 0x37, 0x26, 0x27, 0x06, 0x23, 0x22, 0x00, 0x11, 0x33, 0x14, 0x00, 0x20, 0x00, 0x35, 0x33, 0x14, 0x07, 0x16, 0x1d, 0x01, 0x36, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x05, 0x06, 0x07, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x34, 0x27, 0x26, 0x03, 0xf5, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfd, 0x72, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xfe, 0xb8, 0x01, 0x93, 0x01, 0x1c, 0x7b, 0x6a, 0x5b, 0x3b, 0x26, 0x29, 0xe8, 0xfe, 0xb8, 0x7a, 0x01, 0x00, 0x01, 0x6c, 0x01, 0x00, 0x79, 0x6f, 0x32, 0xbc, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x04, 0x8e, 0x47, 0x52, 0x1b, 0x23, 0x20, 0x18, 0x0f, 0x0b, 0x1e, 0x01, 0x01, 0x02, 0x03, 0x8c, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xa2, 0xfe, 0xc4, 0xfe, 0x43, 0x29, 0x30, 0x6c, 0x05, 0x01, 0x6a, 0x01, 0x02, 0xca, 0xfe, 0xe5, 0x01, 0x1c, 0xc9, 0xd5, 0xa0, 0x64, 0x63, 0x04, 0xda, 0x01, 0x33, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x36, 0x43, 0x24, 0x28, 0x18, 0x17, 0x08, 0x13, 0x39, 0x05, 0x06, 0x2e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x01, 0x37, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x01, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x21, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0xe7, 0x67, 0x1a, 0x24, 0x7f, 0x01, 0x6c, 0x80, 0x23, 0x1a, 0x68, 0x22, 0x2d, 0xa4, 0xfe, 0x30, 0xa4, 0x2d, 0x03, 0x9a, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfe, 0x65, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xfd, 0x85, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x01, 0xd1, 0x47, 0x2c, 0x26, 0x8e, 0x8e, 0x27, 0x2c, 0x48, 0x39, 0x32, 0xb5, 0xb5, 0x33, 0x02, 0xef, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xfe, 0x62, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x17, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x57, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x15, 0x06, 0x0f, 0x01, 0x23, 0x27, 0x26, 0x35, 0x26, 0x37, 0x36, 0x33, 0x16, 0x17, 0x16, 0x17, 0x33, 0x34, 0x37, 0x36, 0x21, 0x32, 0x17, 0x16, 0x15, 0x33, 0x36, 0x37, 0x36, 0x37, 0x32, 0x17, 0x16, 0x07, 0x14, 0x0f, 0x01, 0x23, 0x27, 0x26, 0x27, 0x34, 0x37, 0x36, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x37, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x05, 0x15, 0x18, 0x16, 0x36, 0x01, 0x2d, 0x97, 0x02, 0x8f, 0x37, 0x01, 0x09, 0x22, 0x38, 0x25, 0x1d, 0x19, 0x09, 0x01, 0x0c, 0x1f, 0xfd, 0x8f, 0x37, 0x1f, 0x0c, 0x01, 0x09, 0x19, 0x1d, 0x25, 0x39, 0x22, 0x09, 0x01, 0x38, 0x8f, 0x02, 0x97, 0x2d, 0x01, 0x36, 0x17, 0xfe, 0x43, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0xd5, 0x67, 0x1a, 0x24, 0x7f, 0x01, 0x6c, 0x80, 0x23, 0x1a, 0x68, 0x22, 0x2d, 0xa4, 0xfe, 0x30, 0xa4, 0x2d, 0x04, 0xc0, 0x0e, 0x25, 0x3f, 0x41, 0x3e, 0xcf, 0xbe, 0x44, 0x4c, 0x15, 0x19, 0x44, 0x01, 0x20, 0x20, 0x31, 0x0e, 0x1d, 0x47, 0x47, 0x1d, 0x0e, 0x31, 0x20, 0x20, 0x01, 0x44, 0x19, 0x15, 0x4c, 0x44, 0xbe, 0xcf, 0x3e, 0x41, 0x3f, 0x25, 0x0e, 0xfe, 0x2a, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfd, 0xaa, 0x47, 0x2c, 0x26, 0x8e, 0x8e, 0x27, 0x2c, 0x48, 0x39, 0x32, 0xb5, 0xb5, 0x33, 0x00, 0x00, 0x00, 0x04, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x17, 0x00, 0x23, 0x00, 0x33, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x27, 0x23, 0x15, 0x14, 0x06, 0x22, 0x26, 0x35, 0x14, 0x06, 0x22, 0x26, 0x3d, 0x01, 0x23, 0x06, 0x07, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x25, 0x37, 0x16, 0x17, 0x16, 0x04, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x20, 0x27, 0x26, 0x03, 0x21, 0x26, 0x27, 0x26, 0x21, 0x20, 0x07, 0x06, 0x01, 0x12, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0x4c, 0x63, 0x95, 0xd4, 0x96, 0x95, 0xd5, 0x95, 0x63, 0x4d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x01, 0x4e, 0x67, 0x1a, 0x24, 0x80, 0x01, 0x6b, 0x80, 0x23, 0x1a, 0x68, 0x22, 0x2d, 0xa4, 0xfe, 0x30, 0xa4, 0x2d, 0x56, 0x04, 0x1f, 0x14, 0x16, 0xc8, 0xfe, 0xe2, 0xfe, 0xe4, 0xca, 0x15, 0x02, 0xea, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0xc3, 0xa0, 0x4f, 0x64, 0x8e, 0x8e, 0x64, 0x64, 0x8e, 0x8e, 0x64, 0x4f, 0xa0, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x5b, 0x47, 0x2c, 0x26, 0x8d, 0x01, 0x8e, 0x27, 0x2c, 0x48, 0x39, 0x32, 0xb5, 0xb5, 0x33, 0x03, 0x3b, 0x1a, 0x19, 0xe0, 0xe0, 0x19, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x21, 0x35, 0x21, 0x15, 0x13, 0x32, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x23, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x04, 0x22, 0x01, 0x80, 0xfc, 0x3f, 0x01, 0x7f, 0x61, 0xb6, 0x80, 0x23, 0x1a, 0x68, 0x22, 0x2d, 0xa4, 0xe8, 0xfc, 0xd8, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x03, 0x8c, 0x87, 0x87, 0x87, 0x87, 0xfd, 0xac, 0x8e, 0x27, 0x2c, 0x48, 0x39, 0x32, 0xb5, 0x02, 0x39, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x19, 0x00, 0x25, 0x00, 0x31, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x02, 0x11, 0x03, 0x60, 0xfc, 0xd1, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x01, 0x71, 0x87, 0x87, 0x02, 0x8c, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xd9, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x21, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x15, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x04, 0x22, 0x01, 0x80, 0xfc, 0x3f, 0x01, 0x7f, 0xfe, 0xb1, 0x03, 0x60, 0xfb, 0x28, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x03, 0x8c, 0x87, 0x87, 0x87, 0x87, 0xfd, 0xe5, 0x87, 0x87, 0x01, 0x79, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x29, 0x00, 0x37, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x05, 0x35, 0x21, 0x15, 0x01, 0x35, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x35, 0x21, 0x35, 0x21, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x35, 0x01, 0x12, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x01, 0x78, 0x03, 0x60, 0xfc, 0x68, 0x01, 0x53, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x01, 0x34, 0x01, 0x52, 0x34, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0x02, 0xea, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x05, 0x87, 0x87, 0x02, 0x2d, 0x87, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x03, 0x02, 0x87, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x03, 0x02, 0x00, 0x08, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x1f, 0x00, 0x2a, 0x00, 0x36, 0x00, 0x42, 0x00, 0x00, 0x01, 0x17, 0x16, 0x14, 0x06, 0x22, 0x26, 0x34, 0x37, 0x01, 0x35, 0x21, 0x15, 0x13, 0x25, 0x37, 0x0d, 0x01, 0x27, 0x25, 0x17, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x05, 0xae, 0x3b, 0x18, 0x30, 0x45, 0x30, 0x18, 0xfc, 0x9d, 0x03, 0x60, 0x0a, 0xfe, 0xcb, 0x45, 0x01, 0x35, 0xfc, 0x47, 0x45, 0x01, 0x36, 0x45, 0xfb, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x03, 0xac, 0x80, 0x35, 0x4f, 0x36, 0x36, 0x4f, 0x35, 0xfe, 0x45, 0x87, 0x87, 0x02, 0xa5, 0xf0, 0x6f, 0xf1, 0x6e, 0x6e, 0xf1, 0x6f, 0xfe, 0xaf, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x91, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x33, 0x00, 0x00, 0x01, 0x35, 0x21, 0x15, 0x13, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x21, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x02, 0x11, 0x03, 0x60, 0x31, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfe, 0x65, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xfd, 0x85, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x01, 0x71, 0x87, 0x87, 0x03, 0x17, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xfe, 0x62, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x19, 0x00, 0x25, 0x00, 0x31, 0x00, 0x00, 0x25, 0x27, 0x01, 0x17, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x02, 0x53, 0x33, 0x03, 0x10, 0x33, 0xfc, 0xdf, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0xac, 0x7b, 0x01, 0x96, 0x7b, 0x01, 0xbb, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xd9, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x42, 0x00, 0x00, 0x01, 0x27, 0x13, 0x17, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x03, 0x37, 0x13, 0x03, 0x22, 0x07, 0x06, 0x07, 0x0e, 0x01, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x02, 0x82, 0x56, 0xf3, 0x56, 0xfd, 0x9d, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x04, 0x68, 0xf3, 0x55, 0xf3, 0x8a, 0x2f, 0x25, 0x0a, 0x16, 0x3f, 0xb0, 0x3f, 0x19, 0x0b, 0x1f, 0x2f, 0x33, 0x1d, 0x6c, 0x0e, 0x16, 0x40, 0xb0, 0x3f, 0x19, 0x0b, 0x1f, 0x2f, 0x2f, 0x24, 0x0b, 0x15, 0x3f, 0xb1, 0x3f, 0x15, 0x0f, 0x6d, 0x1c, 0x03, 0x5c, 0x5f, 0x01, 0x0e, 0x5f, 0xfe, 0x80, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0xe6, 0x01, 0x0e, 0x5f, 0xfe, 0xf2, 0xfe, 0x57, 0x69, 0x1d, 0x22, 0x62, 0x01, 0x63, 0x28, 0x21, 0x5f, 0x5f, 0x39, 0x28, 0x22, 0x62, 0x62, 0x28, 0x22, 0x5f, 0x69, 0x1e, 0x22, 0x62, 0x62, 0x22, 0x28, 0x39, 0x5f, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x03, 0x37, 0x27, 0x37, 0x17, 0x15, 0x07, 0x17, 0x15, 0x07, 0x27, 0x37, 0x27, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xb9, 0x48, 0x82, 0x3b, 0xe9, 0x36, 0x36, 0xe9, 0x3b, 0x82, 0x48, 0xfd, 0x08, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x03, 0xff, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xfe, 0x24, 0x3e, 0x4e, 0x76, 0x8d, 0x58, 0x2e, 0x2e, 0x58, 0x8d, 0x76, 0x4e, 0x3e, 0x01, 0x23, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x17, 0x00, 0x22, 0x00, 0x29, 0x00, 0x36, 0x00, 0x42, 0x00, 0x4e, 0x00, 0x00, 0x01, 0x32, 0x17, 0x16, 0x15, 0x06, 0x0f, 0x01, 0x23, 0x27, 0x26, 0x35, 0x26, 0x37, 0x36, 0x33, 0x16, 0x17, 0x16, 0x17, 0x33, 0x34, 0x37, 0x36, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x2d, 0x01, 0x17, 0x07, 0x17, 0x07, 0x25, 0x03, 0x37, 0x27, 0x37, 0x17, 0x15, 0x07, 0x17, 0x15, 0x07, 0x27, 0x37, 0x27, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x05, 0xc6, 0x17, 0x18, 0x36, 0x02, 0x2d, 0x97, 0x02, 0x8e, 0x38, 0x02, 0x09, 0x22, 0x3a, 0x24, 0x1d, 0x19, 0x09, 0x02, 0x0a, 0x1f, 0xfc, 0xb4, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x01, 0xc7, 0x01, 0x0a, 0x45, 0xb2, 0xb2, 0x45, 0xfe, 0xf6, 0x78, 0x48, 0x82, 0x3b, 0xe9, 0x36, 0x36, 0xe9, 0x3b, 0x82, 0x48, 0xfd, 0x08, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x02, 0xaf, 0x0e, 0x25, 0x3f, 0x41, 0x3e, 0xcf, 0xbe, 0x44, 0x4c, 0x15, 0x19, 0x44, 0x01, 0x20, 0x20, 0x31, 0x0e, 0x1d, 0x47, 0x01, 0x4e, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x64, 0xce, 0x6e, 0x8b, 0x8a, 0x6e, 0xce, 0xfe, 0x17, 0x3e, 0x4e, 0x76, 0x8d, 0x58, 0x2e, 0x2e, 0x58, 0x8d, 0x76, 0x4e, 0x3e, 0x01, 0x23, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x24, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x21, 0x34, 0x36, 0x32, 0x16, 0x15, 0x23, 0x34, 0x26, 0x22, 0x06, 0x15, 0x03, 0x37, 0x27, 0x37, 0x17, 0x15, 0x07, 0x17, 0x15, 0x07, 0x27, 0x37, 0x27, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0xe1, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0x01, 0x9b, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xde, 0x48, 0x82, 0x3b, 0xe9, 0x36, 0x36, 0xe9, 0x3b, 0x82, 0x48, 0xfd, 0x08, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x03, 0x8c, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xfe, 0x5d, 0x3e, 0x4e, 0x76, 0x8d, 0x58, 0x2e, 0x2e, 0x58, 0x8d, 0x76, 0x4e, 0x3e, 0x01, 0x23, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x37, 0x27, 0x37, 0x17, 0x15, 0x07, 0x17, 0x15, 0x07, 0x27, 0x37, 0x27, 0x01, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x21, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x91, 0x48, 0x82, 0x3b, 0xe9, 0x36, 0x36, 0xe9, 0x3b, 0x82, 0x48, 0x02, 0x11, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfe, 0x65, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xfd, 0x85, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x01, 0xe9, 0x3e, 0x4e, 0x76, 0x8d, 0x58, 0x2e, 0x2e, 0x58, 0x8d, 0x76, 0x4e, 0x3e, 0x02, 0xc1, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xfe, 0x62, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x25, 0x35, 0x21, 0x15, 0x23, 0x14, 0x06, 0x22, 0x26, 0x35, 0x21, 0x23, 0x14, 0x16, 0x32, 0x36, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0xc8, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x01, 0x78, 0x03, 0x60, 0xda, 0x7e, 0xb0, 0x7e, 0x01, 0x33, 0xba, 0x37, 0x4c, 0x37, 0x03, 0xff, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xdb, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x63, 0x87, 0x87, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0a, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x33, 0x00, 0x39, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x2d, 0x01, 0x17, 0x07, 0x17, 0x07, 0x25, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x25, 0x35, 0x21, 0x15, 0x23, 0x14, 0x06, 0x22, 0x26, 0x35, 0x21, 0x23, 0x14, 0x16, 0x32, 0x36, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x01, 0xc7, 0x01, 0x0a, 0x45, 0xb2, 0xb2, 0x45, 0xfe, 0xf6, 0xfd, 0x09, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x01, 0x78, 0x03, 0x60, 0xda, 0x7e, 0xb0, 0x7e, 0x01, 0x33, 0xba, 0x37, 0x4c, 0x37, 0x03, 0xfd, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x64, 0xce, 0x6e, 0x8b, 0x8a, 0x6e, 0xce, 0xe8, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x63, 0x87, 0x87, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x00, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x25, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x15, 0x05, 0x27, 0x37, 0x27, 0x37, 0x05, 0x25, 0x17, 0x07, 0x17, 0x07, 0x25, 0x01, 0x35, 0x21, 0x15, 0x23, 0x14, 0x06, 0x22, 0x26, 0x35, 0x21, 0x23, 0x14, 0x16, 0x32, 0x36, 0x01, 0x12, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x02, 0xe0, 0xfe, 0xf7, 0x46, 0xb3, 0xb3, 0x46, 0x01, 0x99, 0x01, 0x0a, 0x45, 0xb2, 0xb2, 0x45, 0xfe, 0xf6, 0xfe, 0x08, 0x03, 0x60, 0xda, 0x7e, 0xb0, 0x7e, 0x01, 0x33, 0xba, 0x37, 0x4c, 0x37, 0x02, 0xea, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x02, 0xb1, 0x55, 0xce, 0x6e, 0x8a, 0x8b, 0x6e, 0xce, 0xce, 0x6e, 0x8b, 0x8a, 0x6e, 0xce, 0xfe, 0x07, 0x87, 0x87, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x00, 0x00, 0x07, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x35, 0x00, 0x46, 0x00, 0x00, 0x01, 0x25, 0x37, 0x0d, 0x01, 0x27, 0x25, 0x17, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x23, 0x26, 0x07, 0x06, 0x07, 0x05, 0x7b, 0xfe, 0xcb, 0x45, 0x01, 0x35, 0xfc, 0x47, 0x45, 0x01, 0x36, 0x45, 0xfb, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0xd5, 0x21, 0x2d, 0xa4, 0x01, 0xd0, 0xa4, 0x2e, 0x21, 0x68, 0x19, 0x24, 0x80, 0xb6, 0xb6, 0x7f, 0x24, 0x1a, 0x04, 0x16, 0xf0, 0x6f, 0xf1, 0x6e, 0x6e, 0xf1, 0x6f, 0xfe, 0xaf, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x91, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfd, 0x25, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x01, 0x8e, 0x27, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x45, 0x00, 0x56, 0x00, 0x00, 0x25, 0x27, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x01, 0x25, 0x37, 0x0d, 0x01, 0x27, 0x25, 0x17, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x23, 0x26, 0x07, 0x06, 0x07, 0x03, 0x73, 0x6d, 0x0e, 0x16, 0x3f, 0xb0, 0x3f, 0x16, 0x0e, 0x6c, 0x07, 0x07, 0x1b, 0x4c, 0x1b, 0x07, 0x02, 0x02, 0xfe, 0xcb, 0x45, 0x01, 0x35, 0xfc, 0x47, 0x45, 0x01, 0x36, 0x45, 0xfb, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0xd5, 0x21, 0x2d, 0xa4, 0x01, 0xd0, 0xa4, 0x2e, 0x21, 0x68, 0x19, 0x24, 0x80, 0xb6, 0xb6, 0x7f, 0x24, 0x1a, 0x9f, 0x39, 0x28, 0x22, 0x62, 0x62, 0x22, 0x28, 0x39, 0x13, 0x10, 0x3c, 0x3c, 0x10, 0x03, 0x64, 0xf0, 0x6f, 0xf1, 0x6e, 0x6e, 0xf1, 0x6f, 0xfe, 0xaf, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x91, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfd, 0x25, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x01, 0x8e, 0x27, 0x2c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x35, 0x00, 0x46, 0x00, 0x00, 0x01, 0x17, 0x05, 0x27, 0x05, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x01, 0x05, 0x07, 0x25, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x23, 0x26, 0x07, 0x06, 0x07, 0x04, 0xf9, 0x45, 0xfe, 0xef, 0x45, 0xfe, 0x5a, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfe, 0x40, 0x01, 0x10, 0x45, 0xfe, 0xef, 0xfe, 0x55, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0xd5, 0x21, 0x2d, 0xa4, 0x01, 0xd0, 0xa4, 0x2e, 0x21, 0x68, 0x19, 0x24, 0x80, 0xb6, 0xb6, 0x7f, 0x24, 0x1a, 0x05, 0x67, 0x6e, 0xd5, 0x6f, 0xde, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x01, 0xec, 0xd4, 0x6f, 0xd5, 0xfd, 0xf1, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfd, 0x25, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x01, 0x8e, 0x27, 0x2c, 0x00, 0x00, 0x08, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x37, 0x00, 0x42, 0x00, 0x46, 0x00, 0x56, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x23, 0x26, 0x07, 0x06, 0x07, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x05, 0x07, 0x25, 0x01, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x01, 0x17, 0x05, 0x27, 0x03, 0x27, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x22, 0x07, 0x06, 0x01, 0xe7, 0x21, 0x2d, 0xa4, 0x01, 0xd0, 0xa4, 0x2e, 0x21, 0x68, 0x19, 0x24, 0x80, 0xb6, 0xb6, 0x7f, 0x24, 0x1a, 0xfe, 0xc4, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x10, 0x45, 0xfe, 0xef, 0x02, 0x06, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfd, 0xf8, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0xb7, 0x45, 0xfe, 0xef, 0x45, 0x75, 0x6d, 0x0e, 0x16, 0x3f, 0xb0, 0x3f, 0x16, 0x0e, 0x6c, 0x07, 0x07, 0x1b, 0x4c, 0x1b, 0x07, 0x01, 0x4c, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x01, 0x8e, 0x27, 0x2c, 0x01, 0xe5, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x03, 0xf1, 0xd4, 0x6f, 0xd5, 0xfe, 0xbc, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x01, 0xec, 0x6e, 0xd5, 0x6f, 0xfc, 0x0c, 0x39, 0x28, 0x22, 0x62, 0x62, 0x22, 0x28, 0x39, 0x13, 0x10, 0x3c, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x34, 0x00, 0x4f, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x01, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x23, 0x26, 0x07, 0x06, 0x07, 0x01, 0x14, 0x07, 0x06, 0x07, 0x17, 0x16, 0x07, 0x14, 0x07, 0x06, 0x22, 0x26, 0x35, 0x34, 0x3f, 0x01, 0x26, 0x27, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x01, 0x12, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x02, 0xf4, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xfe, 0xd3, 0x21, 0x2d, 0xa4, 0x01, 0xd0, 0xa4, 0x2e, 0x21, 0x68, 0x19, 0x24, 0x80, 0xb6, 0xb6, 0x7f, 0x24, 0x1a, 0x03, 0x54, 0x3f, 0x34, 0x46, 0x1d, 0x19, 0x01, 0x18, 0x18, 0x45, 0x30, 0x18, 0x1d, 0x45, 0x35, 0x3f, 0x7a, 0x37, 0x4b, 0x37, 0x02, 0xea, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x03, 0x12, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xfc, 0xc4, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x01, 0x8e, 0x27, 0x2c, 0x03, 0x83, 0x8c, 0x62, 0x51, 0x0e, 0x3f, 0x37, 0x23, 0x2b, 0x1a, 0x1b, 0x36, 0x2c, 0x23, 0x35, 0x3f, 0x0d, 0x52, 0x62, 0x8c, 0x53, 0x77, 0x77, 0x53, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x10, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x2a, 0x00, 0x36, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x23, 0x26, 0x07, 0x06, 0x07, 0x01, 0x25, 0x17, 0x07, 0x17, 0x07, 0x25, 0x27, 0x15, 0x05, 0x27, 0x37, 0x27, 0x37, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0xe7, 0x21, 0x2d, 0xa4, 0x01, 0xd0, 0xa4, 0x2e, 0x21, 0x68, 0x19, 0x24, 0x80, 0xb6, 0xb6, 0x7f, 0x24, 0x1a, 0x01, 0xbb, 0x01, 0x0a, 0x45, 0xb2, 0xb2, 0x45, 0xfe, 0xf6, 0x90, 0xfe, 0xf7, 0x46, 0xb3, 0xb3, 0x46, 0xfe, 0x29, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x01, 0x4c, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x01, 0x8e, 0x27, 0x2c, 0x03, 0x22, 0xce, 0x6e, 0x8b, 0x8a, 0x6e, 0xce, 0x55, 0x55, 0xce, 0x6e, 0x8a, 0x8b, 0x6e, 0xfd, 0xf5, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x39, 0x00, 0x00, 0x01, 0x27, 0x13, 0x17, 0x01, 0x03, 0x37, 0x13, 0x01, 0x36, 0x37, 0x36, 0x20, 0x17, 0x16, 0x17, 0x07, 0x26, 0x27, 0x26, 0x23, 0x26, 0x07, 0x06, 0x07, 0x01, 0x17, 0x16, 0x0e, 0x01, 0x22, 0x26, 0x34, 0x37, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x02, 0x82, 0x56, 0xf3, 0x56, 0x01, 0x8c, 0xf3, 0x55, 0xf3, 0xfc, 0x91, 0x21, 0x2d, 0xa4, 0x01, 0xd0, 0xa4, 0x2e, 0x21, 0x68, 0x19, 0x24, 0x80, 0xb6, 0xb6, 0x7f, 0x24, 0x1a, 0x03, 0x78, 0x3b, 0x19, 0x01, 0x31, 0x44, 0x31, 0x19, 0xfb, 0x86, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x03, 0x5c, 0x5f, 0x01, 0x0e, 0x5f, 0xfe, 0xf2, 0x01, 0x0e, 0x5f, 0xfe, 0xf2, 0xfd, 0x91, 0x38, 0x33, 0xb5, 0xb5, 0x33, 0x38, 0x48, 0x2c, 0x27, 0x8e, 0x01, 0x8e, 0x27, 0x2c, 0x03, 0x23, 0x80, 0x35, 0x4f, 0x36, 0x36, 0x4f, 0x35, 0xbe, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x3c, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x21, 0x34, 0x00, 0x20, 0x00, 0x05, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x04, 0x75, 0xfc, 0x74, 0x01, 0x09, 0x01, 0x79, 0x01, 0x0a, 0xfc, 0xfe, 0x02, 0x77, 0x15, 0x3f, 0x60, 0xfe, 0xf0, 0x5f, 0x3e, 0x03, 0xff, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xdb, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfc, 0xa4, 0xe8, 0x01, 0x46, 0xfe, 0xba, 0x61, 0x60, 0x4c, 0x74, 0x75, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x43, 0x00, 0x00, 0x01, 0x25, 0x37, 0x0d, 0x01, 0x27, 0x25, 0x17, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x21, 0x34, 0x00, 0x20, 0x00, 0x05, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x05, 0x7b, 0xfe, 0xcb, 0x45, 0x01, 0x35, 0xfc, 0x47, 0x45, 0x01, 0x36, 0x45, 0xfb, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x04, 0x75, 0xfc, 0x74, 0x01, 0x09, 0x01, 0x79, 0x01, 0x0a, 0xfc, 0xfe, 0x02, 0x77, 0x15, 0x3f, 0x60, 0xfe, 0xf0, 0x5f, 0x3e, 0x04, 0x16, 0xf0, 0x6f, 0xf1, 0x6e, 0x6e, 0xf1, 0x6f, 0xfe, 0xaf, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x91, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfc, 0xa4, 0xe8, 0x01, 0x46, 0xfe, 0xba, 0x61, 0x60, 0x4c, 0x74, 0x75, 0x4c, 0x00, 0x0e, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x13, 0x00, 0x19, 0x00, 0x4e, 0x00, 0x5a, 0x00, 0x66, 0x00, 0x6c, 0x00, 0x78, 0x00, 0x84, 0x00, 0x8a, 0x00, 0x90, 0x00, 0x96, 0x00, 0x9c, 0x00, 0xa2, 0x00, 0x00, 0x01, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x01, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x05, 0x21, 0x34, 0x00, 0x20, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x27, 0x15, 0x23, 0x11, 0x26, 0x27, 0x11, 0x23, 0x35, 0x0e, 0x01, 0x22, 0x27, 0x23, 0x35, 0x26, 0x34, 0x37, 0x11, 0x26, 0x27, 0x11, 0x23, 0x11, 0x06, 0x07, 0x11, 0x16, 0x14, 0x07, 0x15, 0x23, 0x06, 0x22, 0x26, 0x27, 0x15, 0x23, 0x11, 0x06, 0x07, 0x11, 0x23, 0x35, 0x06, 0x07, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x36, 0x37, 0x35, 0x06, 0x07, 0x13, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x27, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x01, 0x15, 0x16, 0x17, 0x35, 0x26, 0x27, 0x26, 0x27, 0x15, 0x36, 0x3f, 0x01, 0x26, 0x27, 0x15, 0x16, 0x17, 0x25, 0x06, 0x07, 0x15, 0x36, 0x3f, 0x01, 0x06, 0x07, 0x15, 0x16, 0x17, 0x04, 0x21, 0x68, 0x43, 0x4c, 0x5f, 0x64, 0x47, 0x45, 0x66, 0xfe, 0x64, 0x02, 0x77, 0x15, 0x3f, 0x60, 0xfe, 0xf0, 0x5f, 0x3e, 0x02, 0xec, 0xfc, 0x74, 0x01, 0x09, 0x01, 0x79, 0x01, 0x0a, 0xfb, 0x8b, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0x30, 0x3d, 0x1b, 0x21, 0x3d, 0x1b, 0x62, 0x80, 0x33, 0x3d, 0x27, 0x27, 0x1e, 0x1e, 0x3d, 0x1f, 0x1e, 0x27, 0x27, 0x3d, 0x32, 0x80, 0x63, 0x1a, 0x3d, 0x22, 0x1b, 0x3d, 0x31, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x03, 0xff, 0x1f, 0x15, 0x15, 0x1e, 0x1c, 0x17, 0x14, 0x20, 0xfd, 0xdb, 0x1d, 0x20, 0x20, 0x1d, 0xef, 0x67, 0x44, 0x47, 0x64, 0x5e, 0x4d, 0x42, 0x69, 0x78, 0x1f, 0x14, 0x18, 0x1b, 0x1d, 0x16, 0x15, 0x1e, 0x01, 0xe9, 0x20, 0x1c, 0x1d, 0x5c, 0x1e, 0x1f, 0x1c, 0x21, 0xf3, 0x1e, 0x1f, 0x27, 0x16, 0xfc, 0xad, 0x1f, 0x1d, 0x16, 0x26, 0xf3, 0x1f, 0x1d, 0x20, 0x1c, 0x04, 0x1a, 0x52, 0x6c, 0x75, 0x49, 0x4f, 0x6f, 0x6f, 0xfc, 0xe9, 0x60, 0x4c, 0x74, 0x75, 0x4c, 0xe6, 0xe8, 0x01, 0x46, 0xfe, 0xba, 0x01, 0x37, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x9b, 0x85, 0xba, 0x01, 0x3b, 0x2e, 0x29, 0xfe, 0x6e, 0x59, 0x36, 0x47, 0x24, 0x40, 0x3c, 0x9c, 0x3c, 0x01, 0x3d, 0x04, 0x01, 0xfd, 0x6a, 0x02, 0x96, 0x01, 0x04, 0xfe, 0xc3, 0x3c, 0x9c, 0x3c, 0x40, 0x24, 0x46, 0x37, 0x59, 0x01, 0x93, 0x2a, 0x2e, 0xfe, 0xc5, 0xbc, 0x86, 0x9c, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x02, 0xa4, 0x18, 0x21, 0x21, 0x18, 0x16, 0x23, 0x20, 0xfc, 0x0a, 0x01, 0xa2, 0x0f, 0x12, 0xfe, 0x91, 0x4f, 0x6f, 0x6f, 0x4f, 0x49, 0x75, 0x6c, 0x52, 0x19, 0x20, 0x23, 0x16, 0x18, 0x21, 0x21, 0x01, 0x79, 0xa3, 0x01, 0x0a, 0x8c, 0x13, 0x28, 0x0a, 0x08, 0xf2, 0x14, 0x09, 0x26, 0x1e, 0x18, 0x84, 0x21, 0x2d, 0xd2, 0x19, 0x1d, 0x9c, 0x2d, 0x21, 0xfd, 0x07, 0x0b, 0xc3, 0x09, 0x14, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x00, 0x01, 0x27, 0x13, 0x17, 0x01, 0x03, 0x37, 0x13, 0x01, 0x27, 0x13, 0x17, 0x01, 0x03, 0x37, 0x13, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x21, 0x34, 0x00, 0x20, 0x00, 0x05, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x02, 0x82, 0x56, 0xf3, 0x56, 0x01, 0x8c, 0xf3, 0x55, 0xf3, 0xfd, 0x2c, 0x56, 0xf3, 0x56, 0x01, 0x8c, 0xf3, 0x55, 0xf3, 0xfb, 0x43, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x04, 0x75, 0xfc, 0x74, 0x01, 0x09, 0x01, 0x79, 0x01, 0x0a, 0xfc, 0xfe, 0x02, 0x77, 0x15, 0x3f, 0x60, 0xfe, 0xf0, 0x5f, 0x3e, 0x04, 0x13, 0x5f, 0x01, 0x0e, 0x5f, 0xfe, 0xf2, 0x01, 0x0e, 0x5f, 0xfe, 0xf2, 0xfe, 0x58, 0x5f, 0x01, 0x0e, 0x5f, 0xfe, 0xf2, 0x01, 0x0e, 0x5f, 0xfe, 0xf2, 0x3f, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfc, 0xa4, 0xe8, 0x01, 0x46, 0xfe, 0xba, 0x61, 0x60, 0x4c, 0x74, 0x75, 0x4c, 0x00, 0x07, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x29, 0x00, 0x35, 0x00, 0x41, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x00, 0x01, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x03, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x21, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x21, 0x34, 0x00, 0x20, 0x00, 0x05, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x05, 0x30, 0x4d, 0x21, 0x1c, 0x17, 0x13, 0x0c, 0x0c, 0x20, 0x10, 0x09, 0x04, 0x0b, 0x23, 0x1c, 0x35, 0x10, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfe, 0x65, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xfd, 0x85, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x04, 0x75, 0xfc, 0x74, 0x01, 0x09, 0x01, 0x79, 0x01, 0x0a, 0xfc, 0xfe, 0x02, 0x77, 0x15, 0x3f, 0x60, 0xfe, 0xf0, 0x5f, 0x3e, 0x02, 0xc8, 0x74, 0x32, 0x0f, 0x0b, 0x04, 0x0c, 0x22, 0x14, 0x15, 0x0e, 0x0f, 0x24, 0x14, 0x10, 0x01, 0xc0, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xfe, 0x62, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfc, 0xa4, 0xe8, 0x01, 0x46, 0xfe, 0xba, 0x61, 0x60, 0x4c, 0x74, 0x75, 0x4c, 0x00, 0x00, 0x06, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x06, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x25, 0x00, 0x2b, 0x00, 0x33, 0x00, 0x00, 0x01, 0x25, 0x17, 0x07, 0x17, 0x07, 0x25, 0x27, 0x15, 0x05, 0x27, 0x37, 0x27, 0x37, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x21, 0x34, 0x00, 0x20, 0x00, 0x05, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x04, 0x09, 0x01, 0x0a, 0x45, 0xb2, 0xb2, 0x45, 0xfe, 0xf6, 0x90, 0xfe, 0xf7, 0x46, 0xb3, 0xb3, 0x46, 0xfe, 0x29, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x04, 0x75, 0xfc, 0x74, 0x01, 0x09, 0x01, 0x79, 0x01, 0x0a, 0xfc, 0xfe, 0x02, 0x77, 0x15, 0x3f, 0x60, 0xfe, 0xf0, 0x5f, 0x3e, 0x04, 0x27, 0xce, 0x6e, 0x8b, 0x8a, 0x6e, 0xce, 0x55, 0x55, 0xce, 0x6e, 0x8a, 0x8b, 0x6e, 0xfd, 0xf5, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfc, 0xa4, 0xe8, 0x01, 0x46, 0xfe, 0xba, 0x61, 0x60, 0x4c, 0x74, 0x75, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x55, 0xff, 0x6a, 0x08, 0x14, 0x06, 0x6e, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x13, 0x00, 0x3d, 0x00, 0x62, 0x00, 0x00, 0x25, 0x21, 0x34, 0x00, 0x20, 0x00, 0x01, 0x15, 0x05, 0x27, 0x37, 0x27, 0x37, 0x05, 0x25, 0x17, 0x07, 0x17, 0x07, 0x25, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x14, 0x07, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x06, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x02, 0x07, 0x02, 0x21, 0x20, 0x03, 0x26, 0x03, 0x07, 0x06, 0x07, 0x06, 0x22, 0x26, 0x35, 0x34, 0x37, 0x36, 0x3f, 0x01, 0x26, 0x37, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x27, 0x06, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x17, 0x16, 0x17, 0x26, 0x27, 0x26, 0x21, 0x20, 0x07, 0x06, 0x07, 0x36, 0x3f, 0x01, 0x07, 0x06, 0x07, 0x06, 0x22, 0x27, 0x06, 0x05, 0xfa, 0xfc, 0x74, 0x01, 0x09, 0x01, 0x79, 0x01, 0x0a, 0xfd, 0xf2, 0xfe, 0xf7, 0x45, 0xb2, 0xb2, 0x45, 0x01, 0x99, 0x01, 0x0a, 0x45, 0xb2, 0xb2, 0x45, 0xfe, 0xf6, 0xfc, 0x90, 0x01, 0xda, 0x01, 0x4e, 0x01, 0x50, 0x01, 0xd8, 0x02, 0x54, 0x35, 0x15, 0x1b, 0x30, 0x45, 0x1c, 0x16, 0x10, 0x0a, 0x26, 0xbc, 0xec, 0xfe, 0xb0, 0xfe, 0xb2, 0xed, 0xbc, 0x27, 0x09, 0x10, 0x17, 0x1c, 0x44, 0x30, 0x1a, 0x15, 0x36, 0x53, 0x02, 0x7a, 0x01, 0x92, 0x01, 0x1c, 0x01, 0x1e, 0x01, 0x90, 0x01, 0x18, 0x21, 0x22, 0x1c, 0x17, 0x10, 0x29, 0x7b, 0x25, 0x15, 0x2a, 0x8b, 0xc7, 0xfe, 0xe1, 0xfe, 0xe4, 0xca, 0x8a, 0x2a, 0x15, 0x25, 0x7a, 0x28, 0x10, 0x17, 0x1c, 0x44, 0x18, 0x01, 0xcb, 0xe8, 0x01, 0x46, 0xfe, 0xba, 0x02, 0x74, 0x55, 0xce, 0x6e, 0x8a, 0x8b, 0x6e, 0xce, 0xce, 0x6e, 0x8b, 0x8a, 0x6e, 0xce, 0xe8, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0x1d, 0x1b, 0x1f, 0x14, 0x18, 0x1f, 0x25, 0x26, 0x36, 0x1f, 0x19, 0x39, 0x20, 0xfe, 0xe9, 0xd1, 0xfe, 0xfa, 0x01, 0x06, 0xd0, 0x01, 0x16, 0x1e, 0x39, 0x19, 0x1f, 0x36, 0x26, 0x25, 0x1f, 0x19, 0x13, 0x1e, 0x1c, 0x1d, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x14, 0x13, 0x1a, 0x1f, 0x19, 0x39, 0x88, 0x2d, 0x0e, 0x0f, 0xc7, 0x9a, 0xe0, 0xe0, 0x9b, 0xc6, 0x10, 0x0d, 0x2d, 0x88, 0x39, 0x19, 0x1f, 0x1b, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x07, 0x00, 0x13, 0x00, 0x1e, 0x00, 0x2a, 0x00, 0x36, 0x00, 0x00, 0x00, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x02, 0xdb, 0x87, 0xbf, 0x87, 0x87, 0xbf, 0xfe, 0xe0, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x01, 0x5a, 0xd4, 0x96, 0x96, 0xd4, 0x96, 0x03, 0x3b, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xdb, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x03, 0x00, 0x07, 0x00, 0x12, 0x00, 0x1d, 0x00, 0x25, 0x00, 0x31, 0x00, 0x3d, 0x00, 0x00, 0x01, 0x25, 0x37, 0x0d, 0x01, 0x27, 0x25, 0x17, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x02, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x05, 0x7b, 0xfe, 0xcb, 0x45, 0x01, 0x35, 0xfc, 0x47, 0x45, 0x01, 0x36, 0x45, 0xfb, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x44, 0x5f, 0x43, 0x43, 0x5f, 0xfd, 0x07, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x04, 0x16, 0xf0, 0x6f, 0xf1, 0x6e, 0x6e, 0xf1, 0x6f, 0xfe, 0xaf, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xfe, 0x14, 0x6a, 0x4b, 0x4b, 0x6a, 0x4b, 0x01, 0xa6, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x08, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x08, 0x00, 0x10, 0x00, 0x14, 0x00, 0x18, 0x00, 0x23, 0x00, 0x2e, 0x00, 0x3a, 0x00, 0x46, 0x00, 0x00, 0x01, 0x17, 0x16, 0x14, 0x06, 0x22, 0x26, 0x34, 0x37, 0x00, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x01, 0x25, 0x37, 0x0d, 0x01, 0x27, 0x25, 0x17, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x05, 0xae, 0x3b, 0x18, 0x30, 0x45, 0x30, 0x18, 0xfd, 0x67, 0x87, 0xbf, 0x87, 0x87, 0xbf, 0x02, 0x19, 0xfe, 0xcb, 0x45, 0x01, 0x35, 0xfc, 0x47, 0x45, 0x01, 0x36, 0x45, 0xfb, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x03, 0xac, 0x80, 0x35, 0x4f, 0x36, 0x36, 0x4f, 0x35, 0xfe, 0x2e, 0xd4, 0x96, 0x96, 0xd4, 0x96, 0x03, 0x52, 0xf0, 0x6f, 0xf1, 0x6e, 0x6e, 0xf1, 0x6f, 0xfe, 0xaf, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0x91, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x07, 0x00, 0x1f, 0xff, 0x3c, 0x07, 0x63, 0x06, 0x6e, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x6b, 0x00, 0x94, 0x00, 0x00, 0x00, 0x26, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x20, 0x26, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x2f, 0x01, 0x25, 0x17, 0x05, 0x25, 0x37, 0x05, 0x00, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x01, 0x35, 0x2e, 0x01, 0x27, 0x02, 0x11, 0x34, 0x36, 0x37, 0x36, 0x37, 0x12, 0x20, 0x13, 0x16, 0x17, 0x1e, 0x01, 0x15, 0x10, 0x03, 0x0e, 0x01, 0x07, 0x15, 0x23, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x13, 0x34, 0x26, 0x22, 0x06, 0x07, 0x06, 0x07, 0x06, 0x0f, 0x01, 0x0e, 0x01, 0x1d, 0x01, 0x23, 0x35, 0x06, 0x22, 0x27, 0x15, 0x23, 0x35, 0x34, 0x26, 0x2f, 0x01, 0x26, 0x27, 0x26, 0x27, 0x2e, 0x01, 0x22, 0x06, 0x15, 0x12, 0x17, 0x16, 0x17, 0x16, 0x1d, 0x01, 0x25, 0x16, 0x32, 0x37, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x3e, 0x01, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x07, 0x16, 0x17, 0x1e, 0x02, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x04, 0x93, 0x49, 0x4a, 0x68, 0x4b, 0x4b, 0xfd, 0x8f, 0x49, 0x49, 0x69, 0x4a, 0x4a, 0xed, 0x45, 0x01, 0x36, 0x45, 0x02, 0x3e, 0xfe, 0xcb, 0x45, 0x01, 0x35, 0xfd, 0x1b, 0x87, 0xbf, 0x87, 0x87, 0xbf, 0xfd, 0xde, 0x41, 0x4e, 0x15, 0x7c, 0x5d, 0x37, 0x35, 0x9d, 0xec, 0x02, 0x9f, 0xec, 0x9c, 0x35, 0x37, 0x5e, 0x7c, 0x16, 0x4d, 0x41, 0x7a, 0x23, 0x74, 0x1a, 0x6e, 0x01, 0x23, 0x34, 0x21, 0x06, 0x0c, 0x5f, 0x25, 0x32, 0x55, 0x23, 0x18, 0x7a, 0x63, 0xeb, 0x6d, 0x7b, 0x18, 0x23, 0x55, 0x32, 0x25, 0x5e, 0x0d, 0x05, 0x22, 0x34, 0x23, 0x02, 0x6e, 0x1a, 0x74, 0x22, 0x01, 0x2b, 0x6b, 0xee, 0x62, 0x18, 0x2b, 0x83, 0x32, 0x0f, 0x36, 0x10, 0x01, 0x08, 0x0a, 0x0b, 0x2e, 0x0e, 0x0f, 0x2d, 0x81, 0xc8, 0xfd, 0xc6, 0xca, 0x81, 0x2d, 0x10, 0x0d, 0x2e, 0x16, 0x07, 0x02, 0x0f, 0x36, 0x0f, 0x33, 0x82, 0x2c, 0x18, 0x03, 0x28, 0x53, 0x75, 0x51, 0x51, 0x75, 0x53, 0x53, 0x75, 0x51, 0x51, 0x76, 0x52, 0xee, 0x6e, 0xf1, 0x6f, 0xf0, 0xf0, 0x6f, 0xf1, 0xfc, 0xd6, 0xd4, 0x96, 0x96, 0xd4, 0x96, 0xfe, 0x78, 0xcb, 0x3e, 0x5b, 0x31, 0x01, 0x17, 0x01, 0x27, 0x53, 0x6b, 0x0a, 0xdf, 0xb0, 0x01, 0x08, 0xfe, 0xf8, 0xaf, 0xe0, 0x0a, 0x6b, 0x53, 0xfe, 0xd9, 0xfe, 0xe9, 0x31, 0x5b, 0x3e, 0xcb, 0xe7, 0x24, 0x1f, 0x6e, 0x39, 0xf0, 0x01, 0x12, 0x1c, 0x28, 0x23, 0x6d, 0xf3, 0x71, 0x2c, 0x25, 0x40, 0x1c, 0x3c, 0x3f, 0xfb, 0x4c, 0x1e, 0x20, 0x4e, 0xfb, 0x3f, 0x3c, 0x1c, 0x40, 0x25, 0x2c, 0x71, 0xf3, 0x6d, 0x23, 0x28, 0x1c, 0xfe, 0xee, 0xf0, 0x39, 0x6e, 0x1f, 0x24, 0xe7, 0xdb, 0x26, 0x25, 0x21, 0x59, 0x3b, 0x65, 0x56, 0x22, 0x13, 0x44, 0x78, 0x0f, 0x86, 0x38, 0x36, 0x30, 0x0e, 0x0a, 0xb5, 0x90, 0xe0, 0xe0, 0x8f, 0xb5, 0x0b, 0x0e, 0x30, 0x6e, 0x86, 0x0f, 0x78, 0x44, 0x13, 0x22, 0x56, 0x65, 0x3b, 0x59, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x2f, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x5b, 0x00, 0x67, 0x00, 0x00, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x37, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x17, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x27, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x02, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x8d, 0x83, 0x53, 0x60, 0x76, 0x7d, 0x59, 0x55, 0x81, 0x68, 0x81, 0x56, 0x59, 0x7d, 0x77, 0x5f, 0x53, 0x84, 0x2c, 0x68, 0x43, 0x4c, 0x5f, 0x64, 0x47, 0x45, 0x66, 0x77, 0x1f, 0x15, 0x15, 0x1e, 0x1c, 0x17, 0x14, 0x20, 0xfe, 0xca, 0x67, 0x44, 0x47, 0x64, 0x5e, 0x4d, 0x42, 0x69, 0x78, 0x1f, 0x14, 0x18, 0x1b, 0x1d, 0x16, 0x15, 0x1e, 0x0f, 0x87, 0xbf, 0x87, 0x87, 0xbf, 0xfd, 0x37, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x04, 0x1a, 0x66, 0x88, 0x93, 0x5b, 0x63, 0x8b, 0x8b, 0x63, 0x63, 0x8b, 0x8b, 0x63, 0x5b, 0x93, 0x88, 0x66, 0x52, 0x6c, 0x75, 0x49, 0x4f, 0x6f, 0x6f, 0x4f, 0x18, 0x21, 0x21, 0x18, 0x16, 0x23, 0x20, 0x19, 0x4f, 0x6f, 0x6f, 0x4f, 0x49, 0x75, 0x6c, 0x52, 0x19, 0x20, 0x23, 0x16, 0x18, 0x21, 0x21, 0xfd, 0x28, 0xd4, 0x96, 0x96, 0xd4, 0x96, 0x02, 0x26, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x4a, 0x00, 0x56, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x66, 0x00, 0x6b, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x7e, 0x00, 0x00, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x34, 0x27, 0x11, 0x23, 0x11, 0x26, 0x27, 0x15, 0x17, 0x07, 0x11, 0x23, 0x35, 0x23, 0x15, 0x23, 0x35, 0x23, 0x15, 0x23, 0x35, 0x23, 0x15, 0x23, 0x11, 0x33, 0x11, 0x33, 0x11, 0x27, 0x37, 0x17, 0x35, 0x26, 0x20, 0x07, 0x15, 0x37, 0x17, 0x07, 0x11, 0x33, 0x11, 0x33, 0x11, 0x23, 0x35, 0x23, 0x15, 0x23, 0x35, 0x23, 0x15, 0x23, 0x35, 0x23, 0x15, 0x23, 0x11, 0x27, 0x37, 0x35, 0x06, 0x07, 0x11, 0x23, 0x11, 0x06, 0x07, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x24, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x13, 0x11, 0x33, 0x11, 0x13, 0x33, 0x35, 0x27, 0x17, 0x33, 0x35, 0x07, 0x27, 0x11, 0x15, 0x17, 0x35, 0x26, 0x01, 0x35, 0x07, 0x15, 0x03, 0x06, 0x07, 0x15, 0x37, 0x11, 0x35, 0x07, 0x27, 0x15, 0x01, 0x12, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0x3a, 0x3d, 0x1b, 0x22, 0x05, 0x05, 0x3d, 0x2f, 0x3d, 0x3d, 0x3e, 0x3d, 0x3d, 0x3d, 0x3d, 0x51, 0x45, 0x87, 0x96, 0xfe, 0x8b, 0x96, 0x87, 0x45, 0x52, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3e, 0x2e, 0x3e, 0x05, 0x05, 0x21, 0x1c, 0x3d, 0x3b, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x02, 0xb5, 0x44, 0x5f, 0x43, 0x43, 0x5f, 0x11, 0x3d, 0xf5, 0x3d, 0x3d, 0x7a, 0x2f, 0x03, 0x2c, 0x2f, 0x17, 0xfd, 0x47, 0x3d, 0x3e, 0x18, 0x16, 0x2e, 0x2c, 0x02, 0x02, 0xea, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0xaa, 0x8f, 0xfe, 0x85, 0x01, 0xf3, 0x2c, 0x28, 0x67, 0x04, 0x09, 0xfe, 0x2d, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x02, 0x38, 0xfe, 0xd7, 0x01, 0x10, 0x3f, 0x6f, 0x69, 0x7b, 0x60, 0x60, 0x7b, 0x69, 0x6f, 0x3f, 0xfe, 0xf0, 0x01, 0x29, 0xfd, 0xc8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x01, 0xd3, 0x09, 0x04, 0x68, 0x28, 0x2c, 0xfe, 0x0c, 0x01, 0x7d, 0x90, 0xab, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x19, 0x6a, 0x4b, 0x4b, 0x6a, 0x4b, 0x01, 0x64, 0x02, 0x38, 0xfd, 0xc8, 0x01, 0x0f, 0xb1, 0x2f, 0xe0, 0x63, 0x04, 0x22, 0x01, 0x23, 0x7f, 0x24, 0x7a, 0x16, 0xfe, 0x6f, 0xe0, 0x2f, 0xb1, 0x01, 0xa4, 0x13, 0x17, 0x79, 0x24, 0xfe, 0xdb, 0x81, 0x22, 0x04, 0x63, 0x00, 0x08, 0x00, 0x99, 0xff, 0x6a, 0x0b, 0x33, 0x07, 0x6c, 0x00, 0x09, 0x00, 0x13, 0x00, 0x1d, 0x00, 0x25, 0x00, 0x31, 0x00, 0x3d, 0x00, 0x49, 0x00, 0x55, 0x00, 0x00, 0x01, 0x21, 0x15, 0x03, 0x33, 0x15, 0x21, 0x35, 0x13, 0x23, 0x25, 0x21, 0x15, 0x03, 0x33, 0x15, 0x21, 0x35, 0x13, 0x23, 0x25, 0x21, 0x15, 0x03, 0x33, 0x15, 0x21, 0x35, 0x13, 0x23, 0x00, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x01, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x21, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x01, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x09, 0xdd, 0x01, 0x55, 0xdf, 0xdf, 0xfe, 0xa2, 0xe0, 0xd7, 0xfe, 0x48, 0x01, 0x55, 0xdf, 0xdf, 0xfe, 0xa2, 0xe0, 0xd7, 0xfe, 0x48, 0x01, 0x55, 0xdf, 0xdf, 0xfe, 0xa2, 0xdf, 0xd6, 0xfc, 0xe1, 0x44, 0x5f, 0x43, 0x43, 0x5f, 0x02, 0x10, 0x7e, 0xb1, 0x7e, 0x7a, 0x37, 0x4b, 0x37, 0xfe, 0x65, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xfd, 0x85, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x07, 0x6c, 0x68, 0xfe, 0xf4, 0x5c, 0x68, 0x01, 0x0c, 0x5c, 0x68, 0xfe, 0xf4, 0x5c, 0x68, 0x01, 0x0c, 0x5c, 0x68, 0xfe, 0xf4, 0x5c, 0x68, 0x01, 0x0c, 0xfa, 0x7f, 0x6a, 0x4b, 0x4b, 0x6a, 0x4b, 0x03, 0x44, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xfe, 0x62, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x05, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x23, 0x00, 0x2b, 0x00, 0x37, 0x00, 0x00, 0x01, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x03, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x04, 0x34, 0x36, 0x32, 0x16, 0x14, 0x06, 0x22, 0x01, 0x27, 0x37, 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x02, 0x53, 0x56, 0x66, 0x66, 0x56, 0x66, 0x66, 0x56, 0x66, 0x66, 0x56, 0x66, 0xfe, 0x59, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x79, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x02, 0x42, 0x87, 0xbf, 0x87, 0x87, 0xbf, 0x01, 0x01, 0x55, 0x65, 0x65, 0x55, 0x66, 0x67, 0x55, 0x66, 0x66, 0x55, 0x67, 0x03, 0x28, 0x5f, 0x71, 0x72, 0x5f, 0x71, 0x71, 0x5f, 0x72, 0x71, 0x5f, 0x71, 0xaf, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0xfe, 0xc3, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x1c, 0xd4, 0x96, 0x96, 0xd4, 0x96, 0x02, 0x64, 0x5f, 0x71, 0x72, 0x5f, 0x71, 0x71, 0x5f, 0x72, 0x71, 0x5f, 0x71, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x00, 0x01, 0x34, 0x36, 0x33, 0x32, 0x16, 0x14, 0x06, 0x23, 0x22, 0x26, 0x25, 0x34, 0x36, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x05, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x02, 0x42, 0x49, 0x35, 0x34, 0x4a, 0x4a, 0x34, 0x35, 0x49, 0x02, 0x08, 0x4a, 0x68, 0x4b, 0x4b, 0x34, 0x35, 0x49, 0xfc, 0x4f, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x79, 0x01, 0x93, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x91, 0xfe, 0x6f, 0xfe, 0xe3, 0xfe, 0xe4, 0xfe, 0x6d, 0x03, 0xfd, 0x3b, 0x51, 0x51, 0x76, 0x52, 0x53, 0x3a, 0x3b, 0x51, 0x51, 0x3b, 0x3a, 0x53, 0x53, 0xd9, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0x74, 0xfe, 0xc4, 0xfe, 0x43, 0x01, 0xbd, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0xc0, 0xfe, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x99, 0xff, 0x6a, 0x06, 0xe9, 0x06, 0x6e, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x17, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x37, 0x00, 0x00, 0x13, 0x10, 0x00, 0x21, 0x20, 0x00, 0x11, 0x10, 0x00, 0x21, 0x20, 0x00, 0x01, 0x35, 0x21, 0x15, 0x33, 0x35, 0x21, 0x15, 0x25, 0x27, 0x25, 0x17, 0x05, 0x25, 0x37, 0x05, 0x01, 0x21, 0x11, 0x21, 0x01, 0x21, 0x16, 0x33, 0x32, 0x37, 0x36, 0x13, 0x07, 0x01, 0x11, 0x27, 0x12, 0x01, 0x02, 0x27, 0x26, 0x21, 0x20, 0x07, 0x06, 0x03, 0x17, 0x21, 0x99, 0x01, 0xd9, 0x01, 0x4f, 0x01, 0x50, 0x01, 0xd7, 0xfe, 0x29, 0xfe, 0xb0, 0xfe, 0xb1, 0xfe, 0x27, 0x01, 0x48, 0x01, 0x7f, 0xc2, 0x01, 0x80, 0xfc, 0x65, 0x45, 0x01, 0x36, 0x45, 0x02, 0x3e, 0xfe, 0xcb, 0x45, 0x01, 0x35, 0xfc, 0x9a, 0x02, 0xce, 0xfd, 0x32, 0x02, 0xff, 0xfc, 0xd1, 0xb0, 0xe7, 0xe8, 0xf9, 0xb6, 0x14, 0xca, 0xfc, 0x3f, 0xcc, 0x14, 0x05, 0x41, 0x18, 0xab, 0xc8, 0xfe, 0xe2, 0xfe, 0xe4, 0xca, 0xab, 0x19, 0xca, 0x03, 0xc1, 0x02, 0xea, 0x01, 0x75, 0x02, 0x0f, 0xfd, 0xf1, 0xfe, 0x8b, 0xfe, 0x8c, 0xfd, 0xf4, 0x02, 0x0c, 0x01, 0xba, 0x87, 0x87, 0x87, 0x87, 0xe6, 0x6e, 0xf1, 0x6f, 0xf0, 0xf0, 0x6f, 0xf1, 0xfc, 0x87, 0x01, 0x18, 0xfe, 0x61, 0x93, 0xd9, 0xc9, 0x01, 0x11, 0x9e, 0xfe, 0xc4, 0x01, 0x3c, 0x9e, 0xfe, 0xef, 0x01, 0xb3, 0x01, 0x02, 0xbf, 0xe0, 0xe0, 0xbf, 0xfe, 0xff, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x34, 0xff, 0x6a, 0x07, 0x56, 0x07, 0x14, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x52, 0x00, 0x8f, 0x00, 0x9d, 0x00, 0xab, 0x00, 0xb5, 0x00, 0xbb, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x27, 0x37, 0x17, 0x16, 0x33, 0x32, 0x37, 0x16, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x20, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x16, 0x33, 0x32, 0x01, 0x14, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x23, 0x22, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x07, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x36, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x26, 0x27, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x25, 0x34, 0x2e, 0x01, 0x22, 0x0e, 0x01, 0x15, 0x23, 0x34, 0x36, 0x32, 0x16, 0x15, 0x21, 0x34, 0x2e, 0x01, 0x22, 0x0e, 0x01, 0x15, 0x23, 0x34, 0x36, 0x32, 0x16, 0x15, 0x01, 0x26, 0x27, 0x06, 0x07, 0x15, 0x16, 0x33, 0x32, 0x3f, 0x01, 0x15, 0x36, 0x37, 0x06, 0x23, 0x05, 0x35, 0x23, 0x22, 0x27, 0x16, 0x03, 0x88, 0x75, 0x52, 0x38, 0x6c, 0x59, 0x5b, 0x6a, 0x38, 0x90, 0x66, 0x69, 0x8e, 0x83, 0x05, 0x1a, 0x31, 0xf7, 0xfe, 0xbf, 0xf8, 0x35, 0x20, 0x03, 0x86, 0x90, 0x6d, 0xfd, 0xa0, 0x07, 0x01, 0x2b, 0x05, 0xfe, 0xd5, 0x07, 0x0d, 0x01, 0x15, 0x14, 0xfe, 0xe7, 0x10, 0x14, 0x5c, 0x93, 0xa3, 0x01, 0xb9, 0xa3, 0x90, 0x5d, 0x17, 0x0f, 0xfe, 0xec, 0x13, 0x01, 0x10, 0x0d, 0x07, 0xfe, 0xdb, 0x04, 0x01, 0x26, 0x06, 0x09, 0x09, 0x14, 0x04, 0x18, 0x26, 0xda, 0x8a, 0x69, 0x8b, 0x8d, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x05, 0x13, 0x09, 0x0a, 0x73, 0x04, 0x06, 0x11, 0x0b, 0x1c, 0x04, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x5e, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x04, 0x1c, 0x0b, 0x11, 0x06, 0x04, 0x5e, 0x03, 0x60, 0x08, 0x13, 0x5e, 0x14, 0x5a, 0x11, 0x18, 0x69, 0xac, 0xc4, 0xfe, 0xfd, 0xfe, 0xfc, 0xc3, 0xad, 0x68, 0x1b, 0x0e, 0x55, 0x13, 0x58, 0x12, 0x08, 0x5b, 0x04, 0x02, 0xe0, 0x13, 0x2d, 0x3b, 0x2c, 0x13, 0x79, 0x7e, 0xb0, 0x7e, 0x01, 0x9b, 0x13, 0x2c, 0x3b, 0x2c, 0x13, 0x7a, 0x7e, 0xb1, 0x7e, 0xfe, 0x67, 0x20, 0x24, 0x18, 0x2d, 0x27, 0x21, 0x24, 0x1d, 0x7b, 0x56, 0x2e, 0x41, 0x34, 0xfe, 0x73, 0x13, 0x39, 0x38, 0x2e, 0x02, 0xfc, 0x2e, 0x78, 0x3d, 0x3d, 0x78, 0xfc, 0x25, 0x42, 0x20, 0x19, 0x44, 0x47, 0x81, 0x93, 0x8f, 0x7d, 0x4b, 0x53, 0x17, 0x17, 0x42, 0x01, 0xc7, 0x24, 0x62, 0x15, 0x43, 0x16, 0x4a, 0x41, 0x69, 0x3f, 0x6c, 0x3a, 0x31, 0xe2, 0x77, 0x84, 0x84, 0x76, 0xe3, 0x38, 0x35, 0x6a, 0x3f, 0x67, 0x3e, 0x4c, 0x15, 0x43, 0x15, 0x52, 0x34, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0xbd, 0x4d, 0x45, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0x0d, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x44, 0x4d, 0x07, 0x44, 0x07, 0x56, 0x57, 0x24, 0x40, 0x22, 0x3c, 0x3c, 0xfe, 0xfd, 0x8c, 0x9e, 0x9e, 0x8c, 0x01, 0x03, 0x40, 0x36, 0x20, 0x40, 0x22, 0x4f, 0x60, 0x07, 0x44, 0x51, 0x2b, 0x5a, 0x45, 0x45, 0x59, 0x2c, 0x8c, 0xc4, 0xc4, 0x8c, 0x2b, 0x5a, 0x45, 0x45, 0x59, 0x2c, 0x8c, 0xc4, 0xc4, 0x8c, 0xfe, 0x03, 0x07, 0x0b, 0x07, 0x0a, 0x91, 0x05, 0x04, 0x84, 0x63, 0x27, 0x46, 0x0a, 0x61, 0x61, 0x09, 0x43, 0x00, 0x00, 0x09, 0x00, 0x56, 0xff, 0x6a, 0x08, 0x13, 0x07, 0x14, 0x00, 0x3f, 0x00, 0x48, 0x00, 0x5d, 0x00, 0xa8, 0x00, 0xb6, 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd4, 0x00, 0xda, 0x00, 0x00, 0x01, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x20, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x15, 0x14, 0x17, 0x36, 0x3f, 0x01, 0x07, 0x0e, 0x01, 0x23, 0x22, 0x27, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x37, 0x06, 0x23, 0x22, 0x26, 0x2f, 0x01, 0x17, 0x16, 0x04, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x27, 0x37, 0x17, 0x16, 0x33, 0x32, 0x37, 0x16, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x20, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x16, 0x33, 0x32, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x3f, 0x01, 0x34, 0x27, 0x07, 0x27, 0x37, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x36, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x1e, 0x01, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x2f, 0x01, 0x06, 0x07, 0x02, 0x07, 0x06, 0x20, 0x27, 0x26, 0x03, 0x26, 0x27, 0x07, 0x06, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x0e, 0x01, 0x15, 0x23, 0x34, 0x36, 0x32, 0x16, 0x15, 0x21, 0x34, 0x2e, 0x01, 0x22, 0x0e, 0x01, 0x15, 0x23, 0x34, 0x36, 0x32, 0x16, 0x15, 0x01, 0x26, 0x27, 0x06, 0x07, 0x15, 0x16, 0x33, 0x32, 0x3f, 0x01, 0x15, 0x36, 0x37, 0x06, 0x23, 0x05, 0x35, 0x23, 0x22, 0x27, 0x16, 0x06, 0xf4, 0x02, 0x09, 0x09, 0x14, 0x03, 0x18, 0x26, 0xd9, 0x8b, 0x68, 0xfe, 0xe7, 0x69, 0x88, 0xdc, 0x26, 0x19, 0x04, 0x13, 0x09, 0x09, 0x01, 0x16, 0x48, 0x7a, 0x27, 0x0f, 0x2e, 0x28, 0x2b, 0x19, 0x07, 0x0e, 0x01, 0x15, 0x14, 0xfe, 0xe7, 0x11, 0x13, 0x5c, 0x94, 0xa3, 0x01, 0xb8, 0xa4, 0x91, 0x5c, 0x18, 0x0e, 0xfe, 0xeb, 0x14, 0x01, 0x0f, 0x0f, 0x07, 0x19, 0x2b, 0x28, 0x2f, 0x0e, 0x2a, 0x7d, 0x49, 0xfd, 0x1b, 0x75, 0x53, 0x37, 0x6c, 0x58, 0x5c, 0x6a, 0x38, 0x90, 0x67, 0x68, 0x8e, 0x84, 0x05, 0x1b, 0x31, 0xf6, 0xfe, 0xbf, 0xf8, 0x36, 0x1f, 0x02, 0x87, 0x90, 0x6c, 0xfc, 0xd6, 0x21, 0x32, 0x38, 0x2f, 0x51, 0x07, 0x5c, 0x04, 0x5a, 0x05, 0x07, 0x10, 0x0b, 0x1d, 0x04, 0x15, 0x22, 0x0d, 0x36, 0x81, 0xe3, 0x55, 0x5e, 0xcb, 0x5f, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x14, 0x04, 0x1c, 0x0b, 0x12, 0x06, 0x04, 0x5e, 0x04, 0x5f, 0x06, 0x03, 0x51, 0x2e, 0x36, 0x30, 0x21, 0x27, 0x2f, 0x10, 0x0d, 0x15, 0x28, 0x68, 0xad, 0xc3, 0xfd, 0xfa, 0xc4, 0xad, 0x68, 0x26, 0x18, 0x0e, 0x20, 0x02, 0x9a, 0x14, 0x2b, 0x3c, 0x2d, 0x12, 0x7a, 0x7e, 0xb0, 0x7e, 0x01, 0x9c, 0x13, 0x2c, 0x3b, 0x2d, 0x12, 0x7a, 0x7e, 0xb0, 0x7e, 0xfe, 0x67, 0x20, 0x24, 0x17, 0x2d, 0x27, 0x21, 0x24, 0x1c, 0x7b, 0x56, 0x2f, 0x41, 0x34, 0xfe, 0x72, 0x12, 0x38, 0x39, 0x2f, 0x03, 0x7c, 0x28, 0x2c, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0x2e, 0x2a, 0x27, 0x2c, 0x19, 0x2c, 0x88, 0x33, 0x3c, 0x25, 0x57, 0x4c, 0x69, 0x3f, 0x6c, 0x3a, 0x31, 0xe2, 0x77, 0x84, 0x84, 0x76, 0xe3, 0x38, 0x35, 0x6a, 0x3f, 0x67, 0x44, 0x60, 0x28, 0x3c, 0x33, 0x88, 0x2c, 0x19, 0xaf, 0x2e, 0x78, 0x3d, 0x3d, 0x78, 0xfc, 0x25, 0x42, 0x20, 0x19, 0x44, 0x47, 0x81, 0x93, 0x8f, 0x7d, 0x4b, 0x53, 0x17, 0x17, 0x42, 0x41, 0x36, 0x25, 0x2c, 0x34, 0x11, 0x1d, 0x03, 0x4a, 0x07, 0x44, 0x06, 0x4d, 0x45, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0x0d, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x44, 0x4d, 0x07, 0x44, 0x07, 0x34, 0x19, 0x1d, 0x11, 0x34, 0x2c, 0x25, 0x36, 0x3c, 0x33, 0x2a, 0x68, 0x62, 0xfe, 0xfd, 0x8c, 0x9e, 0x9e, 0x8c, 0x01, 0x03, 0x5d, 0x70, 0x2d, 0x6f, 0x01, 0xc4, 0x2b, 0x5a, 0x45, 0x45, 0x59, 0x2c, 0x8c, 0xc4, 0xc4, 0x8c, 0x2b, 0x5a, 0x45, 0x45, 0x59, 0x2c, 0x8c, 0xc4, 0xc4, 0x8c, 0xfe, 0x03, 0x07, 0x0b, 0x07, 0x0a, 0x91, 0x05, 0x04, 0x84, 0x63, 0x27, 0x46, 0x0a, 0x61, 0x61, 0x09, 0x43, 0x00, 0x09, 0x00, 0x34, 0xff, 0x6a, 0x07, 0x56, 0x07, 0x14, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x2a, 0x00, 0x5f, 0x00, 0x9c, 0x00, 0xaa, 0x00, 0xb4, 0x00, 0xc3, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x27, 0x37, 0x17, 0x16, 0x33, 0x32, 0x37, 0x16, 0x15, 0x14, 0x07, 0x0e, 0x01, 0x20, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x16, 0x33, 0x32, 0x17, 0x06, 0x23, 0x22, 0x27, 0x1e, 0x01, 0x32, 0x36, 0x37, 0x06, 0x23, 0x22, 0x01, 0x14, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x23, 0x22, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x07, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x36, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x26, 0x27, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x25, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x37, 0x22, 0x06, 0x15, 0x14, 0x17, 0x3e, 0x01, 0x37, 0x26, 0x05, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x36, 0x37, 0x36, 0x33, 0x32, 0x16, 0x07, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x03, 0x88, 0x75, 0x52, 0x38, 0x6c, 0x59, 0x5b, 0x6a, 0x38, 0x90, 0x66, 0x69, 0x8e, 0x83, 0x05, 0x1a, 0x31, 0xf7, 0xfe, 0xbf, 0xf8, 0x35, 0x20, 0x03, 0x86, 0x90, 0x6d, 0x65, 0x67, 0x6b, 0x39, 0x38, 0x2f, 0xad, 0xd3, 0xaa, 0x2d, 0x41, 0x34, 0x69, 0xfc, 0xd6, 0x07, 0x01, 0x2b, 0x05, 0xfe, 0xd5, 0x07, 0x0d, 0x01, 0x15, 0x14, 0xfe, 0xe7, 0x10, 0x14, 0x5c, 0x93, 0xa3, 0x01, 0xb9, 0xa3, 0x90, 0x5d, 0x17, 0x0f, 0xfe, 0xec, 0x13, 0x01, 0x10, 0x0d, 0x07, 0xfe, 0xdb, 0x04, 0x01, 0x26, 0x06, 0x09, 0x09, 0x14, 0x04, 0x18, 0x26, 0xda, 0x8a, 0x69, 0x8b, 0x8d, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x05, 0x13, 0x09, 0x0a, 0x73, 0x04, 0x06, 0x11, 0x0b, 0x1c, 0x04, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x5e, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x04, 0x1c, 0x0b, 0x11, 0x06, 0x04, 0x5e, 0x03, 0x60, 0x08, 0x13, 0x5e, 0x14, 0x5a, 0x11, 0x18, 0x69, 0xac, 0xc4, 0xfe, 0xfd, 0xfe, 0xfc, 0xc3, 0xad, 0x68, 0x1b, 0x0e, 0x55, 0x13, 0x58, 0x12, 0x08, 0x5b, 0x04, 0x01, 0xb2, 0x59, 0x3c, 0x38, 0x54, 0x06, 0x2b, 0x44, 0x1e, 0x24, 0x3c, 0x33, 0x07, 0xe4, 0x21, 0x2b, 0x05, 0x26, 0x3e, 0x11, 0x13, 0x02, 0xb2, 0x07, 0x33, 0x3c, 0x21, 0x21, 0x45, 0x2a, 0x07, 0x2d, 0x28, 0x36, 0x3c, 0x59, 0x94, 0x0b, 0x18, 0x29, 0x26, 0x0e, 0x03, 0x0b, 0x0c, 0x27, 0x3a, 0x02, 0xfc, 0x2e, 0x78, 0x3d, 0x3d, 0x78, 0xfc, 0x25, 0x42, 0x20, 0x19, 0x44, 0x47, 0x81, 0x93, 0x8f, 0x7d, 0x4b, 0x53, 0x17, 0x17, 0x42, 0x68, 0x1f, 0x09, 0x45, 0x4c, 0x4d, 0x45, 0x0a, 0x02, 0x4e, 0x24, 0x62, 0x15, 0x43, 0x16, 0x4a, 0x41, 0x69, 0x3f, 0x6c, 0x3a, 0x31, 0xe2, 0x77, 0x84, 0x84, 0x76, 0xe3, 0x38, 0x35, 0x6a, 0x3f, 0x67, 0x3e, 0x4c, 0x15, 0x43, 0x15, 0x52, 0x34, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0xbd, 0x4d, 0x45, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0x0d, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x44, 0x4d, 0x07, 0x44, 0x07, 0x56, 0x57, 0x24, 0x40, 0x22, 0x3c, 0x3c, 0xfe, 0xfd, 0x8c, 0x9e, 0x9e, 0x8c, 0x01, 0x03, 0x40, 0x36, 0x20, 0x40, 0x22, 0x4f, 0x60, 0x07, 0x44, 0x9f, 0x46, 0x5f, 0x57, 0x3b, 0x45, 0x18, 0x0b, 0x21, 0x17, 0x49, 0x2b, 0x20, 0x0d, 0x0d, 0x06, 0x2f, 0x21, 0x0f, 0x2d, 0x1d, 0x17, 0x21, 0x0c, 0x19, 0x43, 0x42, 0x2a, 0x26, 0x5f, 0x7a, 0x03, 0x14, 0x15, 0x19, 0x0c, 0x0b, 0x03, 0x35, 0x00, 0x06, 0x00, 0x36, 0xff, 0x6a, 0x07, 0x4e, 0x07, 0x14, 0x00, 0x11, 0x00, 0x19, 0x00, 0x4a, 0x00, 0x83, 0x00, 0x98, 0x00, 0xad, 0x00, 0x00, 0x01, 0x37, 0x16, 0x33, 0x32, 0x37, 0x16, 0x33, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x27, 0x06, 0x23, 0x22, 0x01, 0x17, 0x06, 0x22, 0x27, 0x37, 0x16, 0x32, 0x25, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x23, 0x22, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x15, 0x14, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x05, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x36, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x01, 0x3e, 0x01, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0f, 0x01, 0x23, 0x27, 0x26, 0x27, 0x34, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x25, 0x32, 0x16, 0x17, 0x33, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x15, 0x06, 0x0f, 0x01, 0x23, 0x27, 0x26, 0x35, 0x34, 0x36, 0x02, 0x62, 0x53, 0x3e, 0x52, 0x34, 0x4c, 0x4b, 0x35, 0x51, 0x3f, 0x52, 0x61, 0x81, 0x43, 0x3d, 0x3e, 0x42, 0x82, 0x01, 0x8c, 0x38, 0x6e, 0xae, 0x6e, 0x38, 0x51, 0x78, 0x02, 0x75, 0x10, 0x09, 0x09, 0x14, 0x04, 0x18, 0x26, 0xda, 0x8a, 0x69, 0x8b, 0x8d, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x05, 0x13, 0x09, 0x0a, 0x11, 0x01, 0x21, 0x0a, 0xfe, 0xdf, 0x0c, 0x15, 0x01, 0x01, 0x18, 0xfe, 0xfd, 0x5d, 0x94, 0xa3, 0x01, 0xb9, 0xa3, 0x93, 0x5d, 0xfe, 0xfe, 0x17, 0x01, 0x01, 0x13, 0x0e, 0xfe, 0xe0, 0x09, 0xfb, 0x46, 0x0f, 0x06, 0x11, 0x0b, 0x1c, 0x04, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x5e, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x04, 0x1c, 0x0b, 0x11, 0x06, 0x0f, 0x61, 0x09, 0x62, 0x0d, 0x1d, 0x63, 0x17, 0x63, 0x69, 0xaf, 0xc4, 0xfe, 0xfd, 0xfe, 0xfc, 0xc3, 0xae, 0x6a, 0x62, 0x18, 0x62, 0x1b, 0x0e, 0x62, 0x09, 0x02, 0x99, 0x09, 0x34, 0x29, 0x29, 0x38, 0x38, 0x8f, 0x02, 0x97, 0x2c, 0x02, 0x3a, 0x2a, 0x37, 0x1f, 0x0c, 0x01, 0x7e, 0x28, 0x34, 0x09, 0x01, 0x0c, 0x1f, 0x37, 0x2b, 0x39, 0x01, 0x2d, 0x97, 0x02, 0x8f, 0x37, 0x37, 0x01, 0x8c, 0x62, 0x40, 0x2c, 0x2c, 0x40, 0x62, 0x64, 0x1c, 0x1c, 0x01, 0xa8, 0x78, 0x3d, 0x3d, 0x78, 0x2e, 0x38, 0x82, 0x74, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0x2e, 0x74, 0x82, 0x2b, 0x42, 0x2c, 0x45, 0x40, 0x79, 0x3e, 0x7a, 0xe7, 0x77, 0x84, 0x84, 0x77, 0xe7, 0x7a, 0x3e, 0x79, 0x39, 0x4c, 0x2c, 0x42, 0x3d, 0x7c, 0x8f, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0x0d, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x8f, 0x7c, 0x0f, 0x42, 0x0e, 0x51, 0x57, 0x2e, 0x3e, 0x2e, 0xfe, 0xf7, 0x8e, 0x9e, 0x9e, 0x8c, 0x01, 0x0b, 0x2e, 0x3e, 0x2e, 0x51, 0x57, 0x0e, 0x42, 0x01, 0x95, 0x30, 0x42, 0x3d, 0x31, 0x4a, 0x4a, 0xbe, 0xcf, 0x3d, 0x42, 0x2a, 0x48, 0x47, 0x1b, 0x10, 0x72, 0x42, 0x30, 0x10, 0x1b, 0x47, 0x48, 0x2a, 0x42, 0x3d, 0xcf, 0xbe, 0x4a, 0x4a, 0x31, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0xff, 0x6a, 0x07, 0x4e, 0x07, 0x14, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x37, 0x00, 0x44, 0x00, 0x75, 0x00, 0xae, 0x00, 0xb8, 0x00, 0x00, 0x01, 0x05, 0x07, 0x2d, 0x01, 0x17, 0x05, 0x27, 0x13, 0x17, 0x06, 0x22, 0x27, 0x37, 0x16, 0x32, 0x03, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x07, 0x22, 0x06, 0x15, 0x14, 0x17, 0x3e, 0x01, 0x37, 0x26, 0x05, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x05, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x23, 0x22, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x15, 0x14, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x05, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x36, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x01, 0x32, 0x37, 0x36, 0x37, 0x17, 0x06, 0x07, 0x06, 0x23, 0x02, 0x8a, 0x01, 0x10, 0x45, 0xfe, 0xef, 0x02, 0xb5, 0x45, 0xfe, 0xef, 0x45, 0x67, 0x38, 0x6e, 0xae, 0x6e, 0x38, 0x51, 0x78, 0xea, 0x26, 0x49, 0x1d, 0x24, 0x3f, 0x31, 0x12, 0x2f, 0x2b, 0x3a, 0x3f, 0x5b, 0x46, 0x21, 0x2b, 0x05, 0x26, 0x3e, 0x11, 0x14, 0x01, 0x8c, 0x04, 0x5a, 0x3f, 0x3c, 0x2a, 0x30, 0x13, 0x31, 0x3f, 0x24, 0x1d, 0x49, 0x6d, 0x0b, 0x18, 0x2b, 0x24, 0x0e, 0x03, 0x0b, 0x0c, 0x27, 0x3a, 0x01, 0x6b, 0x10, 0x09, 0x09, 0x14, 0x04, 0x18, 0x26, 0xda, 0x8a, 0x69, 0x8b, 0x8d, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x05, 0x13, 0x09, 0x0a, 0x11, 0x01, 0x21, 0x0a, 0xfe, 0xdf, 0x0c, 0x15, 0x01, 0x01, 0x18, 0xfe, 0xfd, 0x5d, 0x94, 0xa3, 0x01, 0xb9, 0xa3, 0x93, 0x5d, 0xfe, 0xfe, 0x17, 0x01, 0x01, 0x13, 0x0e, 0xfe, 0xe0, 0x09, 0xfb, 0x46, 0x0f, 0x06, 0x11, 0x0b, 0x1c, 0x04, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x5e, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x04, 0x1c, 0x0b, 0x11, 0x06, 0x0f, 0x61, 0x09, 0x62, 0x0d, 0x1d, 0x63, 0x17, 0x63, 0x69, 0xaf, 0xc4, 0xfe, 0xfd, 0xfe, 0xfc, 0xc3, 0xae, 0x6a, 0x62, 0x18, 0x62, 0x1b, 0x0e, 0x62, 0x09, 0x03, 0x8a, 0xb6, 0x80, 0x24, 0x19, 0x68, 0x1f, 0x30, 0xa3, 0xe9, 0x05, 0x67, 0xd4, 0x6f, 0xd5, 0x6e, 0x6e, 0xd5, 0x6f, 0xfe, 0x3d, 0x78, 0x3d, 0x3d, 0x78, 0x2e, 0x01, 0x06, 0x4c, 0x1c, 0x0b, 0x23, 0x24, 0x2d, 0x47, 0x30, 0x2c, 0x61, 0x26, 0x30, 0x24, 0x0e, 0x0f, 0x07, 0x34, 0x25, 0x11, 0x1d, 0x43, 0x61, 0x2c, 0x30, 0x47, 0x2d, 0x24, 0x23, 0x0b, 0x1c, 0x04, 0x03, 0x16, 0x18, 0x1c, 0x0e, 0x0c, 0x03, 0x3b, 0xa7, 0x82, 0x74, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0x2e, 0x74, 0x82, 0x2b, 0x42, 0x2c, 0x45, 0x40, 0x79, 0x3e, 0x7a, 0xe7, 0x77, 0x84, 0x84, 0x77, 0xe7, 0x7a, 0x3e, 0x79, 0x39, 0x4c, 0x2c, 0x42, 0x3d, 0x7c, 0x8f, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0x0d, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x8f, 0x7c, 0x0f, 0x42, 0x0e, 0x51, 0x57, 0x2e, 0x3e, 0x2e, 0xfe, 0xf7, 0x8e, 0x9e, 0x9e, 0x8c, 0x01, 0x0b, 0x2e, 0x3e, 0x2e, 0x51, 0x57, 0x0e, 0x42, 0xfe, 0x7f, 0x8e, 0x28, 0x2b, 0x48, 0x36, 0x35, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x36, 0xff, 0x6a, 0x07, 0x4e, 0x07, 0x14, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x27, 0x00, 0x34, 0x00, 0x69, 0x00, 0xa8, 0x00, 0xb5, 0x00, 0xbe, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x07, 0x22, 0x06, 0x15, 0x14, 0x17, 0x3e, 0x01, 0x37, 0x26, 0x05, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x05, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x23, 0x22, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x15, 0x14, 0x17, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x3f, 0x01, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x00, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x06, 0x15, 0x06, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x07, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x27, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x37, 0x26, 0x27, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x13, 0x37, 0x27, 0x37, 0x17, 0x15, 0x07, 0x17, 0x15, 0x07, 0x27, 0x37, 0x27, 0x02, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x27, 0x37, 0x03, 0x14, 0x26, 0x49, 0x1d, 0x24, 0x3f, 0x31, 0x12, 0x2f, 0x2b, 0x3a, 0x3f, 0x5b, 0x46, 0x21, 0x2b, 0x05, 0x26, 0x3e, 0x11, 0x14, 0x01, 0x8c, 0x04, 0x5a, 0x3f, 0x3c, 0x2a, 0x30, 0x13, 0x31, 0x3f, 0x24, 0x1d, 0x49, 0x6d, 0x0b, 0x18, 0x2b, 0x24, 0x0e, 0x03, 0x0b, 0x0c, 0x27, 0x3a, 0x01, 0x6b, 0x10, 0x09, 0x09, 0x14, 0x04, 0x18, 0x26, 0xda, 0x8a, 0x69, 0x8b, 0x8d, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x05, 0x13, 0x09, 0x0a, 0x02, 0x07, 0x08, 0x01, 0x21, 0x0a, 0xfe, 0xdf, 0x0c, 0x15, 0x01, 0x01, 0x18, 0xfe, 0xfd, 0x02, 0x5c, 0x93, 0xa3, 0x01, 0xb9, 0xa3, 0x90, 0x5d, 0x03, 0xfe, 0xfe, 0x17, 0x01, 0x01, 0x13, 0x0e, 0xfe, 0xe0, 0x09, 0xfe, 0x0a, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x04, 0x1c, 0x0b, 0x11, 0x06, 0x01, 0x02, 0x0c, 0x61, 0x09, 0x62, 0x0d, 0x1d, 0x63, 0x17, 0x63, 0x03, 0x69, 0xac, 0xc4, 0xfe, 0xfd, 0xfe, 0xfc, 0xc3, 0xad, 0x68, 0x03, 0x62, 0x18, 0x62, 0x1b, 0x0e, 0x62, 0x09, 0x61, 0x0c, 0x03, 0x06, 0x11, 0x0b, 0x1c, 0x04, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x93, 0x48, 0x82, 0x3b, 0xe9, 0x36, 0x36, 0xe9, 0x3b, 0x82, 0x48, 0x0a, 0x77, 0x51, 0x38, 0x6b, 0x5a, 0x5b, 0x6a, 0x38, 0x03, 0xa8, 0x4c, 0x1c, 0x0b, 0x23, 0x24, 0x2d, 0x47, 0x30, 0x2c, 0x61, 0x26, 0x30, 0x24, 0x0e, 0x0f, 0x07, 0x34, 0x25, 0x11, 0x1d, 0x43, 0x61, 0x2c, 0x30, 0x47, 0x2d, 0x24, 0x23, 0x0b, 0x1c, 0x04, 0x03, 0x16, 0x18, 0x1c, 0x0e, 0x0c, 0x03, 0x3b, 0xa7, 0x83, 0x73, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0x2e, 0x0f, 0x24, 0x82, 0x41, 0x2b, 0x42, 0x2c, 0x45, 0x40, 0x79, 0x3e, 0x7a, 0x05, 0xe2, 0x77, 0x84, 0x84, 0x76, 0xe3, 0x05, 0x7a, 0x3e, 0x79, 0x39, 0x4c, 0x2c, 0x42, 0x03, 0x13, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x07, 0x1c, 0x07, 0x8a, 0x57, 0x0f, 0x42, 0x0e, 0x51, 0x57, 0x2e, 0x3e, 0x2e, 0x08, 0xfe, 0xfd, 0x8c, 0x9e, 0x9e, 0x8c, 0x01, 0x03, 0x08, 0x2e, 0x3e, 0x2e, 0x51, 0x57, 0x0e, 0x42, 0x0f, 0x60, 0x81, 0x2a, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0xfb, 0x3a, 0x3d, 0x4e, 0x77, 0x8d, 0x59, 0x2e, 0x2d, 0x59, 0x8d, 0x77, 0x4e, 0x3d, 0x01, 0xda, 0x2e, 0x78, 0x3d, 0x3d, 0x78, 0x00, 0x0b, 0x00, 0x36, 0xff, 0x6a, 0x07, 0x4e, 0x07, 0x14, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x27, 0x00, 0x34, 0x00, 0x65, 0x00, 0x9e, 0x00, 0xa6, 0x00, 0xaf, 0x00, 0xb8, 0x00, 0xbc, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x16, 0x07, 0x22, 0x06, 0x15, 0x14, 0x17, 0x3e, 0x01, 0x37, 0x26, 0x05, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x06, 0x05, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x23, 0x22, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x15, 0x14, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x05, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x36, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x01, 0x36, 0x32, 0x17, 0x07, 0x26, 0x22, 0x07, 0x25, 0x36, 0x20, 0x17, 0x07, 0x26, 0x23, 0x22, 0x07, 0x12, 0x32, 0x37, 0x17, 0x06, 0x23, 0x22, 0x27, 0x37, 0x01, 0x17, 0x05, 0x27, 0x25, 0x05, 0x07, 0x25, 0x03, 0x14, 0x26, 0x49, 0x1d, 0x24, 0x3f, 0x31, 0x12, 0x2f, 0x2b, 0x3a, 0x3f, 0x5b, 0x46, 0x21, 0x2b, 0x05, 0x26, 0x3e, 0x11, 0x14, 0x01, 0x8c, 0x04, 0x5a, 0x3f, 0x3c, 0x2a, 0x30, 0x13, 0x31, 0x3f, 0x24, 0x1d, 0x49, 0x6d, 0x0b, 0x18, 0x2b, 0x24, 0x0e, 0x03, 0x0b, 0x0c, 0x27, 0x3a, 0x01, 0x6b, 0x10, 0x09, 0x09, 0x14, 0x04, 0x18, 0x26, 0xda, 0x8a, 0x69, 0x8b, 0x8d, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x05, 0x13, 0x09, 0x0a, 0x11, 0x01, 0x21, 0x0a, 0xfe, 0xdf, 0x0c, 0x15, 0x01, 0x01, 0x18, 0xfe, 0xfd, 0x5d, 0x94, 0xa3, 0x01, 0xb9, 0xa3, 0x93, 0x5d, 0xfe, 0xfe, 0x17, 0x01, 0x01, 0x13, 0x0e, 0xfe, 0xe0, 0x09, 0xfb, 0x46, 0x0f, 0x06, 0x11, 0x0b, 0x1c, 0x04, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x5e, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x04, 0x1c, 0x0b, 0x11, 0x06, 0x0f, 0x61, 0x09, 0x62, 0x0d, 0x1d, 0x63, 0x17, 0x63, 0x69, 0xaf, 0xc4, 0xfe, 0xfd, 0xfe, 0xfc, 0xc3, 0xae, 0x6a, 0x62, 0x18, 0x62, 0x1b, 0x0e, 0x62, 0x09, 0x02, 0xf3, 0x3f, 0xb0, 0x3f, 0x56, 0x1b, 0x4c, 0x1b, 0xfe, 0xb5, 0xa3, 0x01, 0xd2, 0xa3, 0x56, 0x80, 0xb6, 0xb4, 0x81, 0xfb, 0x77, 0x51, 0x38, 0x6b, 0x5a, 0x5b, 0x6a, 0x38, 0x01, 0xc4, 0x45, 0xfe, 0xef, 0x45, 0xfe, 0xa2, 0x01, 0x10, 0x45, 0xfe, 0xef, 0x03, 0xa8, 0x4c, 0x1c, 0x0b, 0x23, 0x24, 0x2d, 0x47, 0x30, 0x2c, 0x61, 0x26, 0x30, 0x24, 0x0e, 0x0f, 0x07, 0x34, 0x25, 0x11, 0x1d, 0x43, 0x61, 0x2c, 0x30, 0x47, 0x2d, 0x24, 0x23, 0x0b, 0x1c, 0x04, 0x03, 0x16, 0x18, 0x1c, 0x0e, 0x0c, 0x03, 0x3b, 0xa7, 0x82, 0x74, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0x2e, 0x74, 0x82, 0x2b, 0x42, 0x2c, 0x45, 0x40, 0x79, 0x3e, 0x7a, 0xe7, 0x77, 0x84, 0x84, 0x77, 0xe7, 0x7a, 0x3e, 0x79, 0x39, 0x4c, 0x2c, 0x42, 0x3d, 0x7c, 0x8f, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0x0d, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x8f, 0x7c, 0x0f, 0x42, 0x0e, 0x51, 0x57, 0x2e, 0x3e, 0x2e, 0xfe, 0xf7, 0x8e, 0x9e, 0x9e, 0x8c, 0x01, 0x0b, 0x2e, 0x3e, 0x2e, 0x51, 0x57, 0x0e, 0x42, 0xfe, 0x13, 0x63, 0x63, 0x5f, 0x3c, 0x3c, 0xf5, 0xb5, 0xb5, 0x60, 0x8e, 0x8e, 0x01, 0xfa, 0x2e, 0x78, 0x3d, 0x3d, 0x78, 0x02, 0x3d, 0x6e, 0xd5, 0x6f, 0xd4, 0xd4, 0x6f, 0xd5, 0x00, 0x00, 0x00, 0x05, 0x00, 0x36, 0xff, 0x6a, 0x07, 0x4e, 0x07, 0x14, 0x00, 0x20, 0x00, 0x2c, 0x00, 0x34, 0x00, 0x64, 0x00, 0x8e, 0x00, 0x00, 0x01, 0x14, 0x06, 0x07, 0x17, 0x16, 0x14, 0x06, 0x22, 0x26, 0x35, 0x34, 0x35, 0x06, 0x22, 0x27, 0x37, 0x16, 0x32, 0x37, 0x17, 0x36, 0x3f, 0x01, 0x2e, 0x01, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x21, 0x14, 0x06, 0x22, 0x26, 0x35, 0x33, 0x14, 0x16, 0x32, 0x36, 0x35, 0x03, 0x36, 0x20, 0x17, 0x07, 0x26, 0x20, 0x07, 0x01, 0x26, 0x10, 0x36, 0x3f, 0x01, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x36, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x14, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x02, 0x00, 0x20, 0x00, 0x03, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x05, 0x12, 0x21, 0x32, 0x24, 0x37, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x05, 0x36, 0x35, 0x34, 0x2f, 0x01, 0x26, 0x27, 0x06, 0x07, 0x26, 0x20, 0x07, 0x26, 0x27, 0x06, 0x0f, 0x01, 0x06, 0x15, 0x14, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0xa2, 0x73, 0x46, 0x1d, 0x18, 0x30, 0x45, 0x30, 0x63, 0xaf, 0x6a, 0x38, 0x52, 0x77, 0x51, 0x2e, 0x07, 0x0d, 0x1d, 0x45, 0x74, 0x7a, 0x37, 0x4b, 0x37, 0xfe, 0x65, 0x7e, 0xb0, 0x7e, 0x79, 0x37, 0x4c, 0x37, 0xdf, 0xa3, 0x01, 0xd2, 0xa3, 0x56, 0x80, 0xfe, 0x96, 0x81, 0xfe, 0x0c, 0x0f, 0x1d, 0x13, 0x12, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x5e, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x12, 0x27, 0x09, 0x0f, 0x61, 0x09, 0x62, 0x0d, 0x1d, 0x63, 0x17, 0x63, 0x69, 0xfe, 0x8d, 0xfd, 0xf9, 0xfe, 0x8f, 0x6a, 0x62, 0x18, 0x62, 0x1b, 0x0e, 0x62, 0x09, 0x01, 0x1b, 0xc2, 0x01, 0xae, 0xdd, 0x01, 0x36, 0x5d, 0xfe, 0xfe, 0x17, 0x01, 0x01, 0x13, 0x0e, 0xfe, 0xe0, 0x09, 0x01, 0x21, 0x10, 0x18, 0x1b, 0x0e, 0x27, 0xda, 0x8a, 0x69, 0xfe, 0xe8, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x0f, 0x1c, 0x11, 0x01, 0x21, 0x0a, 0xfe, 0xdf, 0x0c, 0x15, 0x01, 0x01, 0x18, 0x04, 0x88, 0x8b, 0xb4, 0x0e, 0x3f, 0x35, 0x4f, 0x36, 0x36, 0x2c, 0x03, 0x03, 0x35, 0x3d, 0x78, 0x2e, 0x2e, 0x63, 0x18, 0x1d, 0x3f, 0x0e, 0xb4, 0x8b, 0x53, 0x77, 0x77, 0x53, 0x8b, 0xc5, 0xc5, 0x8b, 0x53, 0x77, 0x77, 0x53, 0xfc, 0xda, 0xb5, 0xb5, 0x60, 0x8e, 0x8e, 0x01, 0xc6, 0x7c, 0x01, 0x06, 0xc4, 0x6a, 0x61, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0x0d, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x61, 0xcc, 0xa0, 0xc8, 0x7c, 0x0f, 0x42, 0x0e, 0x51, 0x57, 0x2e, 0x3e, 0x2e, 0xfe, 0xf7, 0xfe, 0xd4, 0x01, 0x2a, 0x01, 0x0b, 0x2e, 0x3e, 0x2e, 0x51, 0x57, 0x0e, 0x42, 0xe6, 0xfe, 0x1e, 0xfb, 0xe7, 0x7a, 0x3e, 0x79, 0x39, 0x4c, 0x2c, 0x42, 0x2b, 0x82, 0x51, 0x88, 0x8d, 0xae, 0x62, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x54, 0xa8, 0x6e, 0x6b, 0x82, 0x2b, 0x42, 0x2c, 0x45, 0x40, 0x79, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x36, 0xff, 0x6a, 0x07, 0x4e, 0x07, 0x14, 0x00, 0x34, 0x00, 0x73, 0x00, 0x7b, 0x00, 0x83, 0x00, 0x87, 0x00, 0x8b, 0x00, 0x00, 0x01, 0x36, 0x35, 0x34, 0x2e, 0x02, 0x27, 0x26, 0x27, 0x06, 0x07, 0x26, 0x23, 0x22, 0x07, 0x26, 0x27, 0x06, 0x07, 0x0e, 0x03, 0x15, 0x14, 0x17, 0x16, 0x17, 0x25, 0x17, 0x05, 0x16, 0x17, 0x25, 0x17, 0x05, 0x17, 0x16, 0x17, 0x16, 0x20, 0x37, 0x36, 0x3f, 0x01, 0x25, 0x37, 0x05, 0x36, 0x37, 0x25, 0x37, 0x00, 0x32, 0x17, 0x3e, 0x01, 0x3f, 0x01, 0x17, 0x16, 0x17, 0x1e, 0x04, 0x15, 0x14, 0x06, 0x15, 0x06, 0x07, 0x17, 0x07, 0x27, 0x06, 0x07, 0x17, 0x07, 0x27, 0x07, 0x02, 0x07, 0x06, 0x21, 0x20, 0x27, 0x26, 0x03, 0x27, 0x07, 0x27, 0x37, 0x26, 0x27, 0x07, 0x27, 0x37, 0x26, 0x27, 0x35, 0x34, 0x3e, 0x03, 0x37, 0x36, 0x3f, 0x01, 0x17, 0x1e, 0x01, 0x17, 0x03, 0x21, 0x26, 0x27, 0x26, 0x20, 0x07, 0x06, 0x05, 0x21, 0x34, 0x37, 0x36, 0x33, 0x32, 0x00, 0x0b, 0x01, 0x37, 0x13, 0x05, 0x27, 0x13, 0x17, 0x06, 0x73, 0x10, 0x09, 0x09, 0x14, 0x04, 0x18, 0x26, 0xda, 0x8a, 0x69, 0x8b, 0x8d, 0x69, 0x89, 0xdb, 0x26, 0x18, 0x05, 0x13, 0x09, 0x0a, 0x02, 0x07, 0x08, 0x01, 0x21, 0x0a, 0xfe, 0xdf, 0x0c, 0x15, 0x01, 0x01, 0x18, 0xfe, 0xfd, 0x02, 0x5c, 0x93, 0xa3, 0x01, 0xb9, 0xa3, 0x90, 0x5d, 0x03, 0xfe, 0xfe, 0x17, 0x01, 0x01, 0x13, 0x0e, 0xfe, 0xe0, 0x09, 0xfe, 0x0a, 0xcc, 0x5e, 0x54, 0xe4, 0x80, 0x36, 0x0e, 0x22, 0x15, 0x04, 0x1c, 0x0b, 0x11, 0x06, 0x01, 0x02, 0x0c, 0x61, 0x09, 0x62, 0x0d, 0x1d, 0x63, 0x17, 0x63, 0x03, 0x69, 0xac, 0xc4, 0xfe, 0xfd, 0xfe, 0xfc, 0xc3, 0xad, 0x68, 0x03, 0x62, 0x18, 0x62, 0x1b, 0x0e, 0x62, 0x09, 0x61, 0x0c, 0x03, 0x06, 0x11, 0x0b, 0x1c, 0x04, 0x15, 0x22, 0x0e, 0x36, 0x80, 0xe4, 0x54, 0x79, 0x02, 0x77, 0x15, 0x3f, 0x60, 0xfe, 0xf0, 0x5f, 0x3e, 0x02, 0xec, 0xfc, 0x74, 0x84, 0x84, 0xbd, 0xbc, 0x01, 0x0b, 0x86, 0xf3, 0x55, 0xf3, 0xfd, 0x2c, 0x56, 0xf3, 0x56, 0x02, 0xda, 0x83, 0x73, 0x2e, 0x66, 0x3e, 0x76, 0x19, 0xa1, 0xa7, 0x3a, 0xc4, 0x15, 0x15, 0xc4, 0x3a, 0xa7, 0xa1, 0x1b, 0x72, 0x41, 0x65, 0x2e, 0x0f, 0x24, 0x82, 0x41, 0x2b, 0x42, 0x2c, 0x45, 0x40, 0x79, 0x3e, 0x7a, 0x05, 0xe2, 0x77, 0x84, 0x84, 0x76, 0xe3, 0x05, 0x7a, 0x3e, 0x79, 0x39, 0x4c, 0x2c, 0x42, 0x03, 0x13, 0x0d, 0x61, 0x89, 0x16, 0x09, 0x3a, 0x8c, 0x75, 0x18, 0x93, 0x41, 0x77, 0x6a, 0x39, 0x07, 0x1c, 0x07, 0x8a, 0x57, 0x0f, 0x42, 0x0e, 0x51, 0x57, 0x2e, 0x3e, 0x2e, 0x08, 0xfe, 0xfd, 0x8c, 0x9e, 0x9e, 0x8c, 0x01, 0x03, 0x08, 0x2e, 0x3e, 0x2e, 0x51, 0x57, 0x0e, 0x42, 0x0f, 0x60, 0x81, 0x2a, 0x39, 0x6a, 0x77, 0x41, 0x93, 0x18, 0x75, 0x8c, 0x3a, 0x09, 0x16, 0x89, 0x61, 0xfb, 0x47, 0x61, 0x4b, 0x74, 0x75, 0x4b, 0xe7, 0xe7, 0xa4, 0xa3, 0xfe, 0xba, 0x01, 0x7e, 0x01, 0x0e, 0x5f, 0xfe, 0xf2, 0x5f, 0x5f, 0x01, 0x0e, 0x5f, 0x00, 0x00, 0x01, 0xff, 0xc0, 0x04, 0x9a, 0x00, 0xb4, 0x06, 0x12, 0x00, 0x03, 0x00, 0x00, 0x11, 0x33, 0x03, 0x23, 0xb3, 0x69, 0x8a, 0x06, 0x12, 0xfe, 0x88, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x27, 0x05, 0x0e, 0xff, 0x3f, 0x05, 0xd9, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0x25, 0x33, 0x15, 0x23, 0xfe, 0x88, 0xb6, 0xb6, 0xfe, 0xa0, 0xb7, 0xb7, 0x05, 0xd9, 0xcb, 0xcb, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0xb4, 0x04, 0xee, 0xff, 0x0c, 0x05, 0xf6, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x03, 0x23, 0xfe, 0x65, 0xa6, 0xcd, 0x8a, 0x05, 0xf6, 0xfe, 0xf8, 0x00, 0x00, 0x01, 0xfd, 0x0a, 0x05, 0x0e, 0xff, 0x5d, 0x05, 0xe9, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x23, 0x34, 0x36, 0x33, 0x32, 0x16, 0x1f, 0x01, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x3d, 0x01, 0x33, 0x0e, 0x01, 0x23, 0x22, 0x26, 0xfe, 0x30, 0x34, 0x16, 0x1c, 0x0b, 0x20, 0x24, 0x71, 0x5d, 0x4d, 0x21, 0x37, 0x2b, 0x33, 0x15, 0x1e, 0x0e, 0x1d, 0x24, 0x70, 0x02, 0x5c, 0x4c, 0x1e, 0x36, 0x05, 0x39, 0x21, 0x0e, 0x0b, 0x32, 0x2d, 0x06, 0x65, 0x76, 0x10, 0x1b, 0x1e, 0x0d, 0x0c, 0x33, 0x29, 0x06, 0x64, 0x77, 0x10, 0x00, 0x00, 0x01, 0xfd, 0x57, 0x04, 0xee, 0xfe, 0xb1, 0x05, 0xf6, 0x00, 0x03, 0x00, 0x00, 0x01, 0x13, 0x23, 0x03, 0xfe, 0x00, 0xb0, 0x89, 0xcf, 0x05, 0xf6, 0xfe, 0xf8, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x20, 0x04, 0xee, 0xff, 0x46, 0x05, 0xf8, 0x00, 0x06, 0x00, 0x00, 0x01, 0x33, 0x13, 0x23, 0x27, 0x07, 0x23, 0xfd, 0xdf, 0xa9, 0xbe, 0x7d, 0x96, 0x95, 0x7d, 0x05, 0xf8, 0xfe, 0xf6, 0xb2, 0xb2, 0x00, 0x00, 0x01, 0xfd, 0x20, 0x04, 0xee, 0xff, 0x46, 0x05, 0xf8, 0x00, 0x06, 0x00, 0x00, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0xfd, 0xdf, 0xbe, 0x7d, 0x95, 0x96, 0x7d, 0xbe, 0x04, 0xee, 0x01, 0x0a, 0xb2, 0xb2, 0xfe, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x19, 0x05, 0x06, 0xff, 0x4d, 0x05, 0xf8, 0x00, 0x0d, 0x00, 0x00, 0x03, 0x23, 0x2e, 0x01, 0x23, 0x22, 0x06, 0x07, 0x23, 0x3e, 0x01, 0x33, 0x32, 0x16, 0xb3, 0x6a, 0x0c, 0x59, 0x4b, 0x4a, 0x57, 0x0e, 0x6a, 0x08, 0x90, 0x81, 0x82, 0x8f, 0x05, 0x06, 0x36, 0x39, 0x37, 0x38, 0x77, 0x7b, 0x7a, 0x00, 0x00, 0x01, 0xfd, 0x19, 0x05, 0x06, 0xff, 0x4d, 0x05, 0xf8, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x33, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x37, 0x33, 0x0e, 0x01, 0x23, 0x22, 0x26, 0xfd, 0x1a, 0x6a, 0x0b, 0x59, 0x4b, 0x4a, 0x57, 0x0f, 0x6a, 0x09, 0x90, 0x81, 0x81, 0x90, 0x05, 0xf8, 0x36, 0x39, 0x37, 0x38, 0x77, 0x7b, 0x7a, 0x00, 0x01, 0xfd, 0xd7, 0x05, 0x0e, 0xfe, 0x8f, 0x05, 0xdb, 0x00, 0x03, 0x00, 0x00, 0x01, 0x33, 0x15, 0x23, 0xfd, 0xd7, 0xb8, 0xb8, 0x05, 0xdb, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x35, 0x04, 0xee, 0xff, 0xba, 0x05, 0xf6, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x03, 0x33, 0x03, 0x23, 0x03, 0x33, 0x03, 0x23, 0xed, 0xa7, 0xcd, 0x8a, 0x7d, 0xa6, 0xcd, 0x8a, 0x05, 0xf6, 0xfe, 0xf8, 0x01, 0x08, 0xfe, 0xf8, 0x00, 0x02, 0xfc, 0xac, 0x04, 0xee, 0xff, 0x31, 0x05, 0xf6, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x01, 0x13, 0x23, 0x03, 0x21, 0x13, 0x23, 0x03, 0xfd, 0x53, 0xb1, 0x8a, 0xcd, 0x01, 0xd4, 0xb0, 0x8a, 0xcd, 0x05, 0xf6, 0xfe, 0xf8, 0x01, 0x08, 0xfe, 0xf8, 0x01, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x96, 0x00, 0x03, 0x00, 0x00, 0x35, 0x33, 0x15, 0x23, 0x87, 0x87, 0x96, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x00, 0x96, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x37, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0xe1, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x96, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x01, 0x90, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x70, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x01, 0x90, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xff, 0x06, 0x01, 0x68, 0x00, 0x96, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x17, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x70, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x64, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff, 0x06, 0x00, 0x87, 0x00, 0x96, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x15, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x87, 0x87, 0x87, 0x87, 0x64, 0x96, 0x01, 0x90, 0x96, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xff, 0x06, 0x01, 0x68, 0x00, 0x96, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x17, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x07, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0xe1, 0x87, 0x87, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x87, 0x87, 0x64, 0x96, 0x01, 0x90, 0x96, 0x64, 0x96, 0x01, 0x90, 0x96, 0x00, 0x01, 0x00, 0x75, 0xff, 0xec, 0x07, 0x24, 0x02, 0x9d, 0x00, 0x26, 0x00, 0x00, 0x01, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x03, 0x26, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x33, 0x16, 0x06, 0x3e, 0x3e, 0x39, 0x39, 0x36, 0x5c, 0x68, 0x40, 0x48, 0x16, 0x8b, 0xd2, 0xe9, 0xbe, 0xb0, 0x70, 0xfe, 0xd8, 0x01, 0x01, 0x3a, 0xa5, 0x3a, 0xb7, 0x5d, 0x88, 0xea, 0xab, 0xb3, 0x6f, 0x35, 0x1a, 0xa5, 0x12, 0x01, 0xf8, 0xd0, 0x3b, 0x35, 0xb8, 0x49, 0x53, 0x42, 0x83, 0x35, 0x3a, 0x26, 0x65, 0x01, 0x08, 0x8a, 0x5c, 0x5e, 0x88, 0x7d, 0x43, 0x22, 0x02, 0x37, 0x3a, 0x6d, 0x34, 0x77, 0x3e, 0x37, 0x4b, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x01, 0x60, 0x02, 0x58, 0x00, 0x0d, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x01, 0x0d, 0x41, 0x8d, 0x51, 0x20, 0x59, 0x27, 0x2c, 0xa6, 0x56, 0x56, 0xb8, 0x2c, 0x31, 0x6a, 0xd9, 0xd9, 0xbb, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x02, 0x3f, 0x02, 0x58, 0x00, 0x14, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x01, 0x0d, 0x45, 0x89, 0x51, 0x20, 0x59, 0x27, 0x2c, 0xa6, 0x2c, 0x28, 0x59, 0x31, 0x63, 0x87, 0x56, 0x56, 0xb8, 0x2c, 0x31, 0x6a, 0xd9, 0xd9, 0x6a, 0x31, 0x2c, 0xb8, 0x00, 0x00, 0x02, 0x00, 0x75, 0xff, 0xa5, 0x07, 0x86, 0x03, 0x11, 0x00, 0x2c, 0x00, 0x3e, 0x00, 0x00, 0x25, 0x06, 0x07, 0x06, 0x23, 0x24, 0x27, 0x24, 0x03, 0x26, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x21, 0x32, 0x25, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x05, 0xd2, 0x5d, 0x63, 0xfc, 0xf5, 0xfe, 0xed, 0x70, 0xfe, 0xd8, 0x01, 0x01, 0x3a, 0xa5, 0x3a, 0xb7, 0x48, 0x01, 0x0e, 0xd0, 0x01, 0x01, 0x19, 0x1f, 0x1a, 0x49, 0x03, 0x14, 0xa9, 0x34, 0x2f, 0x4a, 0x49, 0x7b, 0x10, 0x04, 0x48, 0x08, 0x06, 0xed, 0xf1, 0x5f, 0x64, 0x5e, 0x04, 0x0d, 0x2f, 0x1e, 0x24, 0x16, 0x14, 0x37, 0x11, 0x05, 0x25, 0x2c, 0x24, 0x2b, 0x18, 0x3c, 0x01, 0x27, 0x67, 0x01, 0x06, 0x8a, 0x5c, 0x5e, 0x88, 0x73, 0x4d, 0x1f, 0x36, 0x04, 0x1b, 0x2c, 0x7c, 0x79, 0x1f, 0x24, 0x9b, 0x4b, 0x17, 0x32, 0x53, 0x96, 0x25, 0x1e, 0x90, 0x6a, 0x01, 0xb8, 0xdf, 0x41, 0x7a, 0x14, 0x1b, 0x47, 0x27, 0x19, 0x0a, 0x19, 0x3c, 0x13, 0x12, 0x38, 0x42, 0x4e, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x02, 0xec, 0x03, 0xd9, 0x00, 0x0f, 0x00, 0x30, 0x00, 0x00, 0x01, 0x36, 0x35, 0x34, 0x27, 0x26, 0x07, 0x06, 0x07, 0x06, 0x07, 0x14, 0x17, 0x16, 0x33, 0x32, 0x01, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x06, 0x07, 0x06, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x21, 0x02, 0x1a, 0x25, 0x3b, 0x1c, 0x28, 0x2f, 0x24, 0x24, 0x01, 0x32, 0x24, 0x26, 0x41, 0xfd, 0xe9, 0xd9, 0x4b, 0x88, 0x48, 0x36, 0x1b, 0x0e, 0x39, 0x57, 0x75, 0x46, 0x58, 0x07, 0x14, 0x87, 0x47, 0x44, 0x51, 0x3b, 0x57, 0x29, 0x15, 0x46, 0x43, 0x6f, 0x63, 0x82, 0xfe, 0xdf, 0x02, 0x19, 0x2b, 0x4d, 0x3b, 0x33, 0x19, 0x01, 0x01, 0x2a, 0x29, 0x33, 0x50, 0x26, 0x19, 0xfe, 0xb7, 0x17, 0x0c, 0x5d, 0x30, 0x32, 0x37, 0x02, 0x02, 0x45, 0x57, 0x81, 0x34, 0x2c, 0x94, 0x45, 0x24, 0x32, 0x48, 0x66, 0x33, 0x8c, 0xd0, 0x8f, 0x88, 0x2c, 0x27, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0xb7, 0x03, 0x08, 0x00, 0x21, 0x00, 0x35, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x07, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x02, 0x29, 0xa4, 0x16, 0x07, 0x13, 0x1a, 0x20, 0x23, 0x84, 0x72, 0xc3, 0x7a, 0xa7, 0xa6, 0x7b, 0xc3, 0x72, 0x85, 0x23, 0x1a, 0x21, 0x13, 0x08, 0x14, 0xa7, 0x1b, 0x3a, 0x39, 0x39, 0x0d, 0x11, 0x32, 0x16, 0x08, 0x15, 0x1c, 0x3d, 0x39, 0x20, 0x17, 0x0a, 0x15, 0x33, 0x11, 0x02, 0xfa, 0x50, 0x96, 0x32, 0x2a, 0x49, 0x31, 0x43, 0x32, 0x11, 0xb8, 0x39, 0x39, 0xb8, 0x11, 0x28, 0x4d, 0x2e, 0x4c, 0x2c, 0x30, 0x8f, 0x57, 0x0e, 0xb8, 0x0a, 0x20, 0x35, 0x15, 0x1d, 0x2b, 0x35, 0x44, 0x16, 0x15, 0x45, 0x32, 0x2e, 0x18, 0x1a, 0x34, 0x21, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x60, 0xfe, 0x0c, 0x06, 0x14, 0x02, 0xe4, 0x00, 0x2e, 0x00, 0x40, 0x00, 0x00, 0x25, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x2b, 0x01, 0x06, 0x07, 0x06, 0x07, 0x06, 0x27, 0x24, 0x27, 0x26, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x13, 0x36, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x04, 0x3f, 0x3b, 0x2a, 0x6c, 0x34, 0x84, 0x05, 0x24, 0x85, 0x24, 0x4f, 0x65, 0x32, 0x59, 0x2d, 0x12, 0x06, 0x17, 0x03, 0xed, 0xf1, 0x2b, 0x28, 0x38, 0x72, 0x8f, 0x9e, 0xb8, 0xfe, 0xb3, 0x55, 0x3e, 0x38, 0xa6, 0x38, 0x18, 0x36, 0xec, 0x7e, 0x87, 0xc0, 0x61, 0x04, 0x14, 0x11, 0x2b, 0x1e, 0x23, 0x1f, 0x13, 0x2e, 0x13, 0x09, 0x34, 0x44, 0x5a, 0x2a, 0x0a, 0x05, 0x0d, 0x23, 0x2b, 0x6d, 0xb9, 0x3d, 0x1a, 0xa5, 0x45, 0x13, 0x32, 0x58, 0x91, 0x3a, 0xd6, 0x01, 0xb8, 0x7a, 0x46, 0x91, 0x4e, 0x56, 0x01, 0x02, 0xbe, 0x8a, 0x7d, 0xa6, 0x60, 0x6b, 0x9b, 0x4c, 0x3a, 0x82, 0x44, 0x62, 0x01, 0x5a, 0x7a, 0x57, 0x4b, 0x23, 0x19, 0x0a, 0x1b, 0x3a, 0x1e, 0x19, 0x3c, 0x2c, 0x3b, 0x14, 0x09, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x02, 0xec, 0x03, 0xd9, 0x10, 0x06, 0x11, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x03, 0xb7, 0x03, 0x08, 0x10, 0x06, 0x11, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x01, 0x60, 0x03, 0xe8, 0x10, 0x26, 0x10, 0xfd, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x00, 0xca, 0x03, 0x52, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x02, 0x3f, 0x03, 0xe8, 0x10, 0x26, 0x10, 0xfe, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x00, 0xca, 0x03, 0x52, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8b, 0x01, 0xb7, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x25, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x01, 0x1c, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x38, 0x3a, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x3a, 0xdc, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0xff, 0xff, 0x00, 0x75, 0xfe, 0x90, 0x07, 0x24, 0x03, 0x20, 0x10, 0x27, 0x10, 0xf7, 0x02, 0x76, 0x02, 0x8a, 0x10, 0x27, 0x11, 0x07, 0x02, 0x65, 0xfe, 0x90, 0x10, 0x06, 0x10, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xf4, 0x01, 0xd3, 0x03, 0xe8, 0x10, 0x26, 0x10, 0xfd, 0x00, 0x00, 0x10, 0x27, 0x10, 0xf7, 0x00, 0x59, 0x03, 0x52, 0x10, 0x07, 0x11, 0x07, 0x00, 0x48, 0xfe, 0xf4, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xf4, 0x02, 0x3f, 0x03, 0xe8, 0x10, 0x26, 0x10, 0xfe, 0x00, 0x00, 0x10, 0x27, 0x10, 0xf7, 0x00, 0x59, 0x03, 0x52, 0x10, 0x07, 0x11, 0x07, 0x00, 0x48, 0xfe, 0xf4, 0xff, 0xff, 0x00, 0x75, 0xff, 0xec, 0x07, 0x24, 0x03, 0xb6, 0x10, 0x27, 0x10, 0xf9, 0x02, 0x76, 0x03, 0x20, 0x10, 0x06, 0x10, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x01, 0xc2, 0x04, 0xe2, 0x10, 0x26, 0x10, 0xfd, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf9, 0x00, 0x59, 0x04, 0x4c, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x02, 0x3f, 0x04, 0xe2, 0x10, 0x26, 0x10, 0xfe, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf9, 0x00, 0x59, 0x04, 0x4c, 0x00, 0x02, 0x00, 0x8d, 0xfe, 0x0c, 0x04, 0xb8, 0x05, 0xaf, 0x00, 0x30, 0x00, 0x49, 0x00, 0x00, 0x25, 0x33, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x21, 0x32, 0x37, 0x15, 0x06, 0x23, 0x20, 0x27, 0x26, 0x35, 0x10, 0x37, 0x36, 0x37, 0x22, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x33, 0x20, 0x17, 0x15, 0x22, 0x07, 0x17, 0x16, 0x17, 0x16, 0x01, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x15, 0x05, 0x04, 0x94, 0x24, 0x2c, 0x74, 0x6f, 0x4a, 0x37, 0x05, 0x42, 0x67, 0x58, 0xc9, 0x42, 0x74, 0x01, 0x29, 0xad, 0xbf, 0x87, 0xe1, 0xfe, 0x88, 0x98, 0x76, 0xbf, 0x56, 0x7b, 0x0a, 0x0c, 0x56, 0x7e, 0x79, 0x56, 0xf5, 0xae, 0x01, 0x08, 0xb4, 0x62, 0x1c, 0x1a, 0x2e, 0x41, 0x51, 0xfd, 0x62, 0x46, 0x28, 0x0e, 0x0e, 0x32, 0x34, 0x53, 0x38, 0x2f, 0x2e, 0x39, 0x3b, 0x10, 0x1a, 0x55, 0x1d, 0x6c, 0xfe, 0xcc, 0xb8, 0xb8, 0x96, 0x64, 0x9c, 0x0f, 0xb2, 0x18, 0x50, 0xb7, 0xfc, 0x89, 0x5e, 0xa4, 0x76, 0xb8, 0x63, 0xc2, 0x96, 0xe0, 0x01, 0x02, 0xdf, 0x65, 0x34, 0x13, 0x13, 0x29, 0xb8, 0x3f, 0x36, 0x9a, 0x0d, 0x5b, 0xa0, 0x5f, 0x77, 0x03, 0xa3, 0x12, 0x14, 0x24, 0x25, 0x2d, 0x60, 0x2b, 0x2d, 0x21, 0x64, 0x21, 0x12, 0x20, 0x1a, 0x4d, 0x1b, 0x0a, 0x1d, 0x66, 0x4d, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0xed, 0x05, 0x4b, 0x00, 0x1e, 0x00, 0x37, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x07, 0x35, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x15, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x01, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x15, 0x05, 0x02, 0xfe, 0x4b, 0x5d, 0x4c, 0xa2, 0x4a, 0x91, 0x41, 0x44, 0x91, 0x9b, 0xe8, 0xc6, 0x44, 0x4f, 0x96, 0x42, 0x83, 0x43, 0xc7, 0x93, 0x73, 0x5a, 0xcc, 0x74, 0x5e, 0x68, 0x55, 0xfe, 0xda, 0x46, 0x28, 0x0e, 0x0f, 0x33, 0x34, 0x53, 0x38, 0x2e, 0x2c, 0x3a, 0x3c, 0x0f, 0x1a, 0x55, 0x1d, 0x6c, 0xfe, 0xcc, 0x02, 0x1d, 0x17, 0x17, 0x13, 0x10, 0x07, 0x06, 0xb8, 0x07, 0x01, 0x23, 0x34, 0x62, 0x9a, 0x18, 0x34, 0x62, 0x42, 0x81, 0x1b, 0x50, 0xb8, 0x48, 0x3a, 0x6a, 0x56, 0x01, 0xfd, 0x12, 0x14, 0x24, 0x25, 0x2d, 0x60, 0x2b, 0x2d, 0x21, 0x64, 0x21, 0x12, 0x20, 0x1a, 0x4d, 0x1b, 0x0a, 0x1d, 0x66, 0x4d, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0xb8, 0x05, 0x4b, 0x00, 0x29, 0x00, 0x42, 0x00, 0x00, 0x01, 0x16, 0x17, 0x15, 0x06, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x26, 0x07, 0x35, 0x36, 0x37, 0x32, 0x27, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x15, 0x05, 0x02, 0x3e, 0xe8, 0xc6, 0x3a, 0x42, 0x2d, 0x1b, 0x5e, 0x66, 0x3c, 0x4e, 0xbc, 0x71, 0x24, 0x35, 0x3e, 0x25, 0x83, 0x43, 0xc7, 0x93, 0x73, 0x5a, 0xcc, 0x74, 0x5e, 0x68, 0x55, 0x5b, 0x4b, 0x5d, 0x4c, 0xa2, 0x4a, 0x91, 0x41, 0x44, 0x91, 0x26, 0x46, 0x28, 0x0e, 0x0f, 0x33, 0x34, 0x53, 0x38, 0x2e, 0x2c, 0x3a, 0x3c, 0x0f, 0x1a, 0x55, 0x1d, 0x6c, 0xfe, 0xcc, 0x03, 0x0c, 0x34, 0x62, 0x9a, 0x14, 0x29, 0x4e, 0x22, 0x77, 0xb8, 0xa8, 0x36, 0x61, 0x2e, 0x25, 0x81, 0x1b, 0x50, 0xb8, 0x48, 0x3a, 0x6a, 0x56, 0x23, 0x17, 0x17, 0x13, 0x10, 0x07, 0x06, 0xb8, 0x07, 0x01, 0xc8, 0x12, 0x14, 0x24, 0x25, 0x2d, 0x60, 0x2b, 0x2d, 0x21, 0x64, 0x21, 0x12, 0x20, 0x1a, 0x4d, 0x1b, 0x0a, 0x1d, 0x66, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x8d, 0xfe, 0x0c, 0x04, 0xb8, 0x05, 0xaa, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x00, 0x25, 0x33, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x21, 0x32, 0x37, 0x15, 0x06, 0x23, 0x20, 0x27, 0x26, 0x35, 0x10, 0x37, 0x36, 0x37, 0x22, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x33, 0x20, 0x17, 0x15, 0x22, 0x07, 0x17, 0x16, 0x17, 0x16, 0x01, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x04, 0x94, 0x24, 0x2c, 0x74, 0x6f, 0x4a, 0x37, 0x05, 0x42, 0x67, 0x58, 0xc9, 0x42, 0x74, 0x01, 0x29, 0xad, 0xbf, 0x87, 0xe1, 0xfe, 0x88, 0x98, 0x76, 0xbf, 0x56, 0x7b, 0x0a, 0x0c, 0x56, 0x7e, 0x79, 0x56, 0xf5, 0xae, 0x01, 0x08, 0xb4, 0x62, 0x1c, 0x1a, 0x2e, 0x41, 0x51, 0xfd, 0xbe, 0x86, 0x86, 0x86, 0x86, 0xb8, 0xb8, 0x96, 0x64, 0x9c, 0x0f, 0xb2, 0x18, 0x50, 0xb7, 0xfc, 0x89, 0x5e, 0xa4, 0x76, 0xb8, 0x63, 0xc2, 0x96, 0xe0, 0x01, 0x02, 0xdf, 0x65, 0x34, 0x13, 0x13, 0x29, 0xb8, 0x3f, 0x36, 0x9a, 0x0d, 0x5b, 0xa0, 0x5f, 0x77, 0x03, 0xf8, 0x96, 0x01, 0x90, 0x96, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0x00, 0x00, 0x03, 0xed, 0x05, 0x46, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x07, 0x35, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x15, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x03, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x02, 0xfe, 0x4b, 0x5d, 0x4c, 0xa2, 0x4a, 0x91, 0x41, 0x44, 0x91, 0x9b, 0xe8, 0xc6, 0x44, 0x4f, 0x96, 0x42, 0x83, 0x43, 0xc7, 0x93, 0x73, 0x5a, 0xcc, 0x74, 0x5e, 0x68, 0x55, 0xcb, 0x88, 0x88, 0x88, 0x88, 0x02, 0x1d, 0x17, 0x17, 0x13, 0x10, 0x07, 0x06, 0xb8, 0x07, 0x01, 0x23, 0x34, 0x62, 0x9a, 0x18, 0x34, 0x62, 0x42, 0x81, 0x1b, 0x50, 0xb8, 0x48, 0x3a, 0x6a, 0x56, 0x02, 0x52, 0x96, 0x01, 0x90, 0x96, 0x00, 0x03, 0xff, 0xee, 0x00, 0x00, 0x04, 0xb8, 0x05, 0x46, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x00, 0x01, 0x16, 0x17, 0x15, 0x06, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x26, 0x07, 0x35, 0x36, 0x37, 0x32, 0x13, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x02, 0x3e, 0xe8, 0xc6, 0x3a, 0x42, 0x2d, 0x1b, 0x5e, 0x66, 0x3c, 0x4e, 0xbc, 0x71, 0x24, 0x35, 0x3e, 0x25, 0x83, 0x43, 0xc7, 0x93, 0x73, 0x5a, 0xcc, 0x74, 0x5e, 0x68, 0x55, 0x5b, 0x4b, 0x5d, 0x4c, 0xa2, 0x4a, 0x91, 0x41, 0x44, 0x91, 0x35, 0x88, 0x88, 0x88, 0x88, 0x03, 0x0c, 0x34, 0x62, 0x9a, 0x14, 0x29, 0x4e, 0x22, 0x77, 0xb8, 0xa8, 0x36, 0x61, 0x2e, 0x25, 0x81, 0x1b, 0x50, 0xb8, 0x48, 0x3a, 0x6a, 0x56, 0x23, 0x17, 0x17, 0x13, 0x10, 0x07, 0x06, 0xb8, 0x07, 0x01, 0x01, 0x1d, 0x96, 0x01, 0x90, 0x96, 0x00, 0x04, 0x00, 0x8d, 0xfe, 0x0c, 0x04, 0xb8, 0x05, 0xaa, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x00, 0x25, 0x33, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x21, 0x32, 0x37, 0x15, 0x06, 0x23, 0x20, 0x27, 0x26, 0x35, 0x10, 0x37, 0x36, 0x37, 0x22, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x33, 0x20, 0x17, 0x15, 0x22, 0x07, 0x17, 0x16, 0x17, 0x16, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x04, 0x94, 0x24, 0x2c, 0x74, 0x6f, 0x4a, 0x37, 0x05, 0x42, 0x67, 0x58, 0xc9, 0x42, 0x74, 0x01, 0x29, 0xad, 0xbf, 0x87, 0xe1, 0xfe, 0x88, 0x98, 0x76, 0xbf, 0x56, 0x7b, 0x0a, 0x0c, 0x56, 0x7e, 0x79, 0x56, 0xf5, 0xae, 0x01, 0x08, 0xb4, 0x62, 0x1c, 0x1a, 0x2e, 0x41, 0x51, 0xfd, 0xbe, 0x86, 0x86, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb8, 0xb8, 0x96, 0x64, 0x9c, 0x0f, 0xb2, 0x18, 0x50, 0xb7, 0xfc, 0x89, 0x5e, 0xa4, 0x76, 0xb8, 0x63, 0xc2, 0x96, 0xe0, 0x01, 0x02, 0xdf, 0x65, 0x34, 0x13, 0x13, 0x29, 0xb8, 0x3f, 0x36, 0x9a, 0x0d, 0x5b, 0xa0, 0x5f, 0x77, 0x04, 0xf2, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x04, 0xff, 0xee, 0x00, 0x00, 0x03, 0xed, 0x05, 0x46, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x07, 0x35, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x15, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x03, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x02, 0xfe, 0x4b, 0x5d, 0x4c, 0xa2, 0x4a, 0x91, 0x41, 0x44, 0x91, 0x9b, 0xe8, 0xc6, 0x44, 0x4f, 0x96, 0x42, 0x83, 0x43, 0xc7, 0x93, 0x73, 0x5a, 0xcc, 0x74, 0x5e, 0x68, 0x55, 0xcb, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x02, 0x1d, 0x17, 0x17, 0x13, 0x10, 0x07, 0x06, 0xb8, 0x07, 0x01, 0x23, 0x34, 0x62, 0x9a, 0x18, 0x34, 0x62, 0x42, 0x81, 0x1b, 0x50, 0xb8, 0x48, 0x3a, 0x6a, 0x56, 0x03, 0x4c, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x04, 0xff, 0xee, 0x00, 0x00, 0x04, 0xb8, 0x05, 0x46, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x00, 0x01, 0x16, 0x17, 0x15, 0x06, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x26, 0x07, 0x35, 0x36, 0x37, 0x32, 0x13, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x02, 0x3e, 0xe8, 0xc6, 0x3a, 0x42, 0x2d, 0x1b, 0x5e, 0x66, 0x3c, 0x4e, 0xbc, 0x71, 0x24, 0x35, 0x3e, 0x25, 0x83, 0x43, 0xc7, 0x93, 0x73, 0x5a, 0xcc, 0x74, 0x5e, 0x68, 0x55, 0x5b, 0x4b, 0x5d, 0x4c, 0xa2, 0x4a, 0x91, 0x41, 0x44, 0x91, 0x35, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x03, 0x0c, 0x34, 0x62, 0x9a, 0x14, 0x29, 0x4e, 0x22, 0x77, 0xb8, 0xa8, 0x36, 0x61, 0x2e, 0x25, 0x81, 0x1b, 0x50, 0xb8, 0x48, 0x3a, 0x6a, 0x56, 0x23, 0x17, 0x17, 0x13, 0x10, 0x07, 0x06, 0xb8, 0x07, 0x01, 0x02, 0x17, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x05, 0x00, 0x8d, 0xfe, 0x0c, 0x04, 0xb8, 0x04, 0xb0, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x00, 0x25, 0x33, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x21, 0x32, 0x37, 0x15, 0x06, 0x23, 0x20, 0x27, 0x26, 0x35, 0x10, 0x37, 0x36, 0x37, 0x22, 0x23, 0x22, 0x07, 0x06, 0x07, 0x35, 0x36, 0x33, 0x20, 0x17, 0x15, 0x22, 0x07, 0x17, 0x16, 0x17, 0x16, 0x01, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x04, 0x94, 0x24, 0x2c, 0x74, 0x6f, 0x4a, 0x37, 0x05, 0x42, 0x67, 0x58, 0xc9, 0x42, 0x74, 0x01, 0x29, 0xad, 0xbf, 0x87, 0xe1, 0xfe, 0x88, 0x98, 0x76, 0xbf, 0x56, 0x7b, 0x0a, 0x0c, 0x56, 0x7e, 0x79, 0x56, 0xf5, 0xae, 0x01, 0x08, 0xb4, 0x62, 0x1c, 0x1a, 0x2e, 0x41, 0x51, 0xfd, 0xbe, 0x86, 0x86, 0x21, 0x87, 0x87, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb8, 0xb8, 0x96, 0x64, 0x9c, 0x0f, 0xb2, 0x18, 0x50, 0xb7, 0xfc, 0x89, 0x5e, 0xa4, 0x76, 0xb8, 0x63, 0xc2, 0x96, 0xe0, 0x01, 0x02, 0xdf, 0x65, 0x34, 0x13, 0x13, 0x29, 0xb8, 0x3f, 0x36, 0x9a, 0x0d, 0x5b, 0xa0, 0x5f, 0x77, 0x03, 0xf8, 0x96, 0xfb, 0x9b, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0xee, 0xfe, 0x3e, 0x03, 0xed, 0x04, 0x4c, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x26, 0x07, 0x35, 0x36, 0x37, 0x32, 0x17, 0x16, 0x17, 0x15, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x03, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x02, 0xfe, 0x4b, 0x5d, 0x4c, 0xa2, 0x4a, 0x91, 0x41, 0x44, 0x91, 0x9b, 0xe8, 0xc6, 0x44, 0x4f, 0x96, 0x42, 0x83, 0x43, 0xc7, 0x93, 0x73, 0x5a, 0xcc, 0x74, 0x5e, 0x68, 0x55, 0xcb, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x70, 0x88, 0x88, 0x02, 0x1d, 0x17, 0x17, 0x13, 0x10, 0x07, 0x06, 0xb8, 0x07, 0x01, 0x23, 0x34, 0x62, 0x9a, 0x18, 0x34, 0x62, 0x42, 0x81, 0x1b, 0x50, 0xb8, 0x48, 0x3a, 0x6a, 0x56, 0xfc, 0xda, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x05, 0x14, 0x96, 0x00, 0x05, 0xff, 0xee, 0xfe, 0x3e, 0x04, 0xb8, 0x04, 0x4c, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x00, 0x01, 0x16, 0x17, 0x15, 0x06, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x27, 0x26, 0x07, 0x35, 0x36, 0x37, 0x32, 0x13, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x02, 0x3e, 0xe8, 0xc6, 0x3a, 0x42, 0x2d, 0x1b, 0x5e, 0x66, 0x3c, 0x4e, 0xbc, 0x71, 0x24, 0x35, 0x3e, 0x25, 0x83, 0x43, 0xc7, 0x93, 0x73, 0x5a, 0xcc, 0x74, 0x5e, 0x68, 0x55, 0x5b, 0x4b, 0x5d, 0x4c, 0xa2, 0x4a, 0x91, 0x41, 0x44, 0x91, 0x40, 0x87, 0x87, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x65, 0x88, 0x88, 0x03, 0x0c, 0x34, 0x62, 0x9a, 0x14, 0x29, 0x4e, 0x22, 0x77, 0xb8, 0xa8, 0x36, 0x61, 0x2e, 0x25, 0x81, 0x1b, 0x50, 0xb8, 0x48, 0x3a, 0x6a, 0x56, 0x23, 0x17, 0x17, 0x13, 0x10, 0x07, 0x06, 0xb8, 0x07, 0x01, 0xfb, 0xa5, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x05, 0x14, 0x96, 0x00, 0x01, 0x00, 0x00, 0x05, 0x33, 0x03, 0x09, 0x07, 0x2b, 0x00, 0x03, 0x00, 0x00, 0x09, 0x01, 0x35, 0x01, 0x03, 0x09, 0xfc, 0xf7, 0x03, 0x09, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0x00, 0x00, 0x01, 0x00, 0xbf, 0xfe, 0x56, 0x04, 0xa4, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x13, 0x33, 0x01, 0x11, 0x33, 0x11, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x01, 0x11, 0x23, 0xc0, 0xa5, 0x02, 0x99, 0xa5, 0x4a, 0x49, 0xa2, 0xe5, 0xd2, 0x5e, 0x22, 0x23, 0xfd, 0x67, 0xa5, 0x05, 0xd5, 0xfb, 0x83, 0x04, 0x7d, 0xfa, 0x17, 0xd6, 0x60, 0x60, 0x9c, 0x30, 0x31, 0xad, 0x04, 0x7d, 0xfb, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x01, 0xe9, 0x04, 0x60, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x33, 0x15, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x33, 0xb0, 0xa5, 0x94, 0x94, 0xa5, 0xa2, 0xa2, 0x04, 0x60, 0xfe, 0x08, 0xa4, 0xfe, 0x3c, 0x01, 0xc4, 0xa4, 0x00, 0x00, 0x02, 0xff, 0x0d, 0xfe, 0x56, 0x01, 0xf7, 0x04, 0x60, 0x00, 0x0e, 0x00, 0x17, 0x00, 0x00, 0x13, 0x20, 0x35, 0x34, 0x3b, 0x01, 0x11, 0x33, 0x11, 0x33, 0x15, 0x23, 0x06, 0x07, 0x06, 0x03, 0x23, 0x22, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x1e, 0xfe, 0xef, 0xf3, 0xae, 0xa5, 0xa3, 0xac, 0x10, 0x30, 0x49, 0x1d, 0xa3, 0x6b, 0x02, 0x04, 0x6f, 0x5e, 0x23, 0x0f, 0xfe, 0x56, 0xdd, 0xcd, 0x04, 0x60, 0xfb, 0xa0, 0x9b, 0x70, 0x3f, 0x60, 0x01, 0x10, 0x33, 0x41, 0x30, 0x17, 0x00, 0x00, 0xff, 0xff, 0x01, 0x69, 0x06, 0x63, 0x03, 0x84, 0x08, 0x33, 0x10, 0x27, 0x00, 0x71, 0x00, 0xaa, 0x02, 0x3d, 0x10, 0x07, 0x10, 0xeb, 0x04, 0x43, 0x01, 0x55, 0x00, 0x00, 0xff, 0xff, 0x01, 0x69, 0x06, 0x61, 0x03, 0x84, 0x08, 0x34, 0x10, 0x27, 0x00, 0x71, 0x00, 0xaa, 0x00, 0xff, 0x10, 0x07, 0x10, 0xeb, 0x04, 0x43, 0x02, 0x5b, 0x00, 0x00, 0xff, 0xff, 0x01, 0x69, 0x06, 0x5e, 0x03, 0x84, 0x08, 0x33, 0x10, 0x27, 0x10, 0xf3, 0x04, 0x43, 0x01, 0x50, 0x10, 0x07, 0x00, 0x71, 0x00, 0xaa, 0x02, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x01, 0x6a, 0x06, 0x63, 0x03, 0x82, 0x08, 0x5a, 0x10, 0x27, 0x10, 0xec, 0x04, 0x72, 0x02, 0x64, 0x10, 0x07, 0x10, 0xeb, 0x04, 0x43, 0x01, 0x55, 0x00, 0x00, 0xff, 0xff, 0x01, 0x6a, 0x06, 0x63, 0x03, 0x82, 0x08, 0x5a, 0x10, 0x27, 0x10, 0xee, 0x04, 0x18, 0x02, 0x64, 0x10, 0x07, 0x10, 0xeb, 0x04, 0x43, 0x01, 0x55, 0x00, 0x00, 0xff, 0xff, 0x01, 0x69, 0x06, 0x61, 0x03, 0x84, 0x08, 0x5a, 0x10, 0x27, 0x10, 0xec, 0x04, 0x72, 0x02, 0x64, 0x10, 0x07, 0x00, 0x71, 0x00, 0xaa, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x01, 0x69, 0x06, 0x61, 0x03, 0x84, 0x08, 0x5a, 0x10, 0x27, 0x10, 0xee, 0x04, 0x18, 0x02, 0x64, 0x10, 0x07, 0x00, 0x71, 0x00, 0xaa, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x01, 0x50, 0x06, 0x6a, 0x03, 0xa3, 0x08, 0x33, 0x10, 0x27, 0x10, 0xed, 0x04, 0x46, 0x01, 0x5c, 0x10, 0x07, 0x00, 0x71, 0x00, 0xaa, 0x02, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x01, 0x63, 0x06, 0x63, 0x03, 0x89, 0x08, 0x5a, 0x10, 0x27, 0x10, 0xf0, 0x04, 0x43, 0x02, 0x62, 0x10, 0x07, 0x10, 0xeb, 0x04, 0x43, 0x01, 0x55, 0x00, 0x00, 0xff, 0xff, 0x01, 0x50, 0x06, 0x6a, 0x03, 0xa3, 0x08, 0x56, 0x10, 0x27, 0x10, 0xeb, 0x04, 0x43, 0x02, 0x7d, 0x10, 0x07, 0x10, 0xed, 0x04, 0x46, 0x01, 0x5c, 0x00, 0x00, 0xff, 0xff, 0x01, 0x63, 0x06, 0x63, 0x03, 0x89, 0x08, 0x57, 0x10, 0x27, 0x10, 0xf0, 0x04, 0x43, 0x01, 0x75, 0x10, 0x07, 0x10, 0xf3, 0x04, 0x43, 0x02, 0x7c, 0x00, 0x00, 0xff, 0xff, 0x01, 0x50, 0x06, 0x6a, 0x03, 0xc5, 0x08, 0x5a, 0x10, 0x27, 0x10, 0xec, 0x04, 0xba, 0x02, 0x64, 0x10, 0x07, 0x10, 0xed, 0x04, 0x46, 0x01, 0x5c, 0x00, 0x00, 0xff, 0xff, 0x01, 0x63, 0x06, 0x63, 0x04, 0x96, 0x08, 0x3a, 0x10, 0x27, 0x10, 0xef, 0x04, 0x43, 0x01, 0x75, 0x10, 0x07, 0x10, 0xec, 0x05, 0x8a, 0x02, 0x44, 0x00, 0x00, 0xff, 0xff, 0x01, 0x63, 0x06, 0x63, 0x03, 0xfc, 0x08, 0x3a, 0x10, 0x27, 0x10, 0xee, 0x05, 0x4b, 0x02, 0x44, 0x10, 0x07, 0x10, 0xef, 0x04, 0x43, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0x01, 0x50, 0x06, 0x63, 0x03, 0xa3, 0x08, 0x75, 0x10, 0x27, 0x10, 0xef, 0x04, 0x43, 0x01, 0x75, 0x10, 0x07, 0x10, 0xed, 0x04, 0x46, 0x02, 0x8c, 0x00, 0x00, 0xff, 0xff, 0x01, 0x50, 0x06, 0x56, 0x03, 0xa3, 0x08, 0x59, 0x10, 0x27, 0x10, 0xf2, 0x04, 0x43, 0x01, 0x50, 0x10, 0x07, 0x10, 0xed, 0x04, 0x46, 0x02, 0x70, 0x00, 0x00, 0xff, 0xff, 0x01, 0x5c, 0x06, 0x56, 0x03, 0x90, 0x08, 0x5a, 0x10, 0x27, 0x10, 0xf2, 0x04, 0x43, 0x01, 0x50, 0x10, 0x07, 0x10, 0xec, 0x04, 0x72, 0x02, 0x64, 0x00, 0x00, 0xff, 0xff, 0x01, 0x5c, 0x06, 0x56, 0x03, 0x90, 0x08, 0x5a, 0x10, 0x27, 0x10, 0xf2, 0x04, 0x43, 0x01, 0x50, 0x10, 0x07, 0x10, 0xee, 0x04, 0x18, 0x02, 0x64, 0x00, 0x00, 0xff, 0xff, 0x01, 0x5c, 0x06, 0x56, 0x03, 0x90, 0x08, 0x8b, 0x10, 0x27, 0x02, 0xba, 0x04, 0x34, 0x02, 0x10, 0x10, 0x07, 0x10, 0xf2, 0x04, 0x43, 0x01, 0x50, 0x00, 0x00, 0xff, 0xff, 0x01, 0x63, 0x06, 0x63, 0x04, 0x87, 0x08, 0x5b, 0x10, 0x27, 0x02, 0xba, 0x05, 0x75, 0x01, 0xe0, 0x10, 0x07, 0x10, 0xef, 0x04, 0x43, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xf1, 0x04, 0x7b, 0xff, 0x62, 0x06, 0x6e, 0x10, 0x26, 0x02, 0xb2, 0x00, 0x00, 0x10, 0x07, 0x02, 0xb8, 0xff, 0x12, 0x00, 0x5a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x2c, 0x00, 0x03, 0x00, 0x00, 0x11, 0x21, 0x11, 0x21, 0x01, 0x0e, 0xfe, 0xf2, 0x01, 0x2c, 0xfe, 0xd4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0xe3, 0x02, 0xfb, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x3d, 0x01, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x06, 0x23, 0x22, 0x26, 0x52, 0xae, 0x5e, 0x81, 0x65, 0xb6, 0xbe, 0xde, 0x56, 0xab, 0x3d, 0xec, 0x51, 0x51, 0x95, 0xcb, 0x03, 0xee, 0xfc, 0x12, 0xfe, 0xe6, 0xea, 0x2c, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb3, 0xfe, 0x0c, 0x04, 0x92, 0x02, 0x26, 0x00, 0x06, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x01, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x02, 0x07, 0x04, 0x21, 0x35, 0x20, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x03, 0x5c, 0xaf, 0x7d, 0x75, 0x75, 0x7d, 0xaf, 0xfe, 0x57, 0xa5, 0x1b, 0x03, 0x09, 0x42, 0x26, 0x5b, 0xaf, 0xe1, 0x75, 0x2d, 0x3d, 0xe2, 0xff, 0x00, 0xfe, 0xdf, 0x01, 0x11, 0xb7, 0xc4, 0x20, 0x08, 0xfe, 0x0c, 0x01, 0x46, 0xc3, 0xc3, 0xfe, 0xba, 0x04, 0x1a, 0x70, 0x1e, 0x67, 0x4d, 0x2c, 0xb8, 0x3e, 0xfe, 0xea, 0x85, 0x97, 0xb8, 0x80, 0x8a, 0xd0, 0x3a, 0x48, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xb3, 0xfe, 0x0c, 0x04, 0x77, 0x02, 0x26, 0x00, 0x18, 0x00, 0x00, 0x01, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x02, 0x07, 0x04, 0x21, 0x35, 0x20, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x02, 0x39, 0xa5, 0x1b, 0x03, 0x09, 0x42, 0x26, 0x5b, 0xaf, 0xe1, 0x75, 0x2d, 0x3d, 0xe2, 0xff, 0x00, 0xfe, 0xdf, 0x01, 0x11, 0xb7, 0xc4, 0x20, 0x08, 0x02, 0x26, 0x70, 0x1e, 0x67, 0x4d, 0x2c, 0xb8, 0x3e, 0xfe, 0xea, 0x85, 0x97, 0xb8, 0x80, 0x8a, 0xd0, 0x3a, 0x48, 0x7e, 0x00, 0x02, 0x00, 0x81, 0xfe, 0xc8, 0x05, 0x86, 0x07, 0xc4, 0x00, 0x24, 0x00, 0x2b, 0x00, 0x00, 0x25, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x26, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x03, 0xaa, 0x46, 0xa6, 0x2c, 0x27, 0x59, 0x44, 0x75, 0x65, 0x46, 0x10, 0x19, 0x6d, 0xea, 0x79, 0x4d, 0x59, 0x3e, 0xfe, 0xf9, 0x01, 0x39, 0xa6, 0x3b, 0x96, 0x24, 0x41, 0x48, 0x63, 0x9c, 0x99, 0xaf, 0x7d, 0x75, 0x75, 0x7d, 0xb0, 0x49, 0x7e, 0xe3, 0x04, 0x6a, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x33, 0x2e, 0x28, 0xb1, 0x42, 0x22, 0x16, 0x5b, 0x01, 0x12, 0x8a, 0x5c, 0x73, 0x73, 0x7e, 0x42, 0x10, 0x22, 0x35, 0x06, 0xac, 0x01, 0x46, 0xc3, 0xc3, 0xfe, 0xba, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x02, 0x24, 0x07, 0xc4, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x27, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x01, 0x84, 0x4e, 0x48, 0x8b, 0x75, 0x44, 0x59, 0x27, 0x2c, 0xa6, 0x96, 0xaf, 0x7d, 0x75, 0x75, 0x7d, 0xaf, 0x01, 0x73, 0xb2, 0x65, 0x5c, 0xb8, 0x2c, 0x31, 0x6a, 0x04, 0x95, 0x6a, 0x01, 0x46, 0xc3, 0xc3, 0xfe, 0xba, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x02, 0x75, 0x07, 0xc4, 0x00, 0x14, 0x00, 0x1b, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x0b, 0x01, 0x33, 0x17, 0x37, 0x33, 0x03, 0x01, 0x31, 0x45, 0x89, 0x75, 0x44, 0x59, 0x27, 0x2c, 0xa6, 0x2c, 0x28, 0x59, 0x43, 0x75, 0x87, 0x8a, 0xaf, 0x7d, 0x75, 0x75, 0x7d, 0xaf, 0x56, 0x56, 0xb8, 0x2c, 0x31, 0x6a, 0x04, 0x95, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x06, 0x7e, 0x01, 0x46, 0xc3, 0xc3, 0xfe, 0xba, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x75, 0xfe, 0xf0, 0x06, 0x13, 0x03, 0x46, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x00, 0x05, 0x36, 0x35, 0x26, 0x27, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x03, 0xde, 0x52, 0x01, 0x2a, 0x1a, 0x1b, 0x28, 0x2f, 0x48, 0x4b, 0x1b, 0x26, 0x69, 0x4f, 0x73, 0x1d, 0x1f, 0x1f, 0x67, 0x65, 0x61, 0x17, 0x21, 0x0d, 0x29, 0x3b, 0x42, 0x02, 0x03, 0x66, 0x73, 0xc4, 0x50, 0x5e, 0xa9, 0x69, 0xfe, 0xf8, 0x39, 0xa5, 0x3a, 0x95, 0x3c, 0xa1, 0x52, 0x45, 0x86, 0xfe, 0x8b, 0xaf, 0x7d, 0x75, 0x75, 0x7d, 0xaf, 0x21, 0x33, 0x21, 0x2b, 0x0d, 0x08, 0x28, 0x3b, 0x3d, 0x41, 0x3c, 0x5e, 0x0e, 0x06, 0x86, 0xc4, 0xb8, 0xac, 0xa5, 0x06, 0x11, 0x23, 0x30, 0x1b, 0x1e, 0x7b, 0x62, 0x56, 0x60, 0x1f, 0x0c, 0x29, 0x67, 0x01, 0x06, 0x99, 0x5a, 0x5a, 0x99, 0x72, 0x4e, 0x1f, 0x08, 0x0f, 0x02, 0x42, 0x01, 0x46, 0xc3, 0xc3, 0xfe, 0xba, 0x00, 0x00, 0x04, 0xff, 0xee, 0xfe, 0xd4, 0x02, 0x00, 0x04, 0x40, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x0b, 0x01, 0x33, 0x17, 0x37, 0x33, 0x0b, 0x01, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x0d, 0x41, 0x8d, 0x51, 0x20, 0x59, 0x27, 0x2c, 0xa6, 0x96, 0xaf, 0x7d, 0x75, 0x75, 0x7d, 0xaf, 0x16, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x56, 0x56, 0xb8, 0x2c, 0x31, 0x6a, 0xd9, 0xd9, 0xbb, 0x02, 0x36, 0x01, 0x46, 0xc3, 0xc3, 0xfe, 0xba, 0xfc, 0x70, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x04, 0xff, 0xee, 0xfe, 0xd4, 0x02, 0x3f, 0x04, 0x40, 0x00, 0x14, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x0b, 0x01, 0x33, 0x17, 0x37, 0x33, 0x0b, 0x01, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x0d, 0x45, 0x89, 0x51, 0x20, 0x59, 0x27, 0x2c, 0xa6, 0x2c, 0x28, 0x59, 0x31, 0x63, 0x87, 0x8a, 0xaf, 0x7d, 0x75, 0x75, 0x7d, 0xaf, 0x16, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x56, 0x56, 0xb8, 0x2c, 0x31, 0x6a, 0xd9, 0xd9, 0x6a, 0x31, 0x2c, 0xb8, 0x02, 0xfa, 0x01, 0x46, 0xc3, 0xc3, 0xfe, 0xba, 0xfc, 0x70, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb3, 0xfe, 0x0c, 0x04, 0x0b, 0x04, 0x72, 0x00, 0x18, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x02, 0x07, 0x04, 0x21, 0x35, 0x20, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x0b, 0x01, 0x33, 0x17, 0x37, 0x33, 0x03, 0x02, 0x39, 0xa5, 0x1b, 0x03, 0x09, 0x42, 0x26, 0x5b, 0x43, 0x75, 0x75, 0x2d, 0x3d, 0xe2, 0xff, 0x00, 0xfe, 0xdf, 0x01, 0x11, 0xb7, 0xc4, 0x20, 0x08, 0x35, 0xaf, 0x7d, 0x75, 0x75, 0x7d, 0xaf, 0x02, 0x26, 0x70, 0x1e, 0x67, 0x4d, 0x2c, 0xb8, 0x3e, 0xfe, 0xea, 0x85, 0x97, 0xb8, 0x80, 0x8a, 0xd0, 0x3a, 0x48, 0x7e, 0x01, 0x8e, 0x01, 0x46, 0xc3, 0xc3, 0xfe, 0xba, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x02, 0x01, 0x06, 0x14, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x33, 0x11, 0x14, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x35, 0xae, 0xa5, 0x45, 0x5e, 0x0a, 0x1d, 0xa3, 0x92, 0x06, 0x14, 0xfb, 0x82, 0x99, 0x61, 0x9c, 0xc0, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x82, 0x00, 0x00, 0x03, 0xef, 0x02, 0xee, 0x00, 0x0a, 0x00, 0x24, 0x00, 0x00, 0x01, 0x26, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x17, 0x1e, 0x01, 0x13, 0x26, 0x27, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x02, 0x60, 0x0d, 0x0c, 0x0b, 0x0b, 0x6c, 0x4a, 0x64, 0x02, 0x01, 0xa2, 0x68, 0x04, 0x02, 0xa5, 0x01, 0x21, 0x13, 0x32, 0x1c, 0x65, 0x43, 0x75, 0x51, 0x42, 0x28, 0x22, 0x7c, 0x8d, 0x32, 0x34, 0xab, 0xb8, 0x62, 0x01, 0x1a, 0x2a, 0x31, 0x32, 0x65, 0x0c, 0x43, 0x59, 0x3e, 0x29, 0x32, 0x01, 0xd1, 0x27, 0x2b, 0xa8, 0xae, 0x65, 0x4f, 0x2c, 0xb8, 0x33, 0x1f, 0x3b, 0x49, 0x0f, 0x30, 0x9a, 0xad, 0x7f, 0x44, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0xa2, 0x05, 0xf0, 0x10, 0x06, 0x01, 0xe4, 0x00, 0x00, 0xff, 0xff, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x00, 0x05, 0x0f, 0x10, 0x06, 0x01, 0xe5, 0x00, 0x00, 0xff, 0xff, 0x00, 0x87, 0xfe, 0x75, 0x01, 0xd7, 0x04, 0x7b, 0x10, 0x26, 0x00, 0xf3, 0x00, 0x00, 0x10, 0x07, 0x02, 0x9d, 0xff, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x47, 0x00, 0x00, 0x02, 0x38, 0x04, 0x60, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x37, 0x33, 0x13, 0x23, 0x13, 0x21, 0x13, 0x21, 0xb3, 0x79, 0xa0, 0x79, 0x21, 0xfe, 0xd3, 0xc4, 0x01, 0x2d, 0x64, 0x03, 0x98, 0xfc, 0x04, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x2d, 0xfe, 0x56, 0x02, 0x38, 0x04, 0x60, 0x00, 0x08, 0x00, 0x16, 0x00, 0x00, 0x05, 0x13, 0x23, 0x03, 0x06, 0x07, 0x36, 0x37, 0x36, 0x05, 0x23, 0x37, 0x33, 0x32, 0x37, 0x36, 0x37, 0x13, 0x21, 0x03, 0x06, 0x07, 0x06, 0x01, 0x16, 0xb6, 0x79, 0xbb, 0x1f, 0x30, 0x41, 0x2d, 0x43, 0xfe, 0xf9, 0xc6, 0x12, 0x2d, 0x5e, 0x2b, 0x2b, 0x1a, 0xd1, 0x01, 0x2d, 0xc8, 0x25, 0x5a, 0x5b, 0x16, 0x04, 0x12, 0xfb, 0xd0, 0xb5, 0x54, 0x0f, 0x30, 0x48, 0xf4, 0x64, 0x30, 0x31, 0x99, 0x04, 0xac, 0xfb, 0x8c, 0xd6, 0x60, 0x60, 0x00, 0xff, 0xff, 0xff, 0xd7, 0xfe, 0x76, 0x02, 0x2a, 0x04, 0x7b, 0x10, 0x27, 0x02, 0xb0, 0xff, 0x34, 0x00, 0x00, 0x10, 0x06, 0x00, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x00, 0xab, 0xfe, 0x89, 0x01, 0x54, 0x04, 0x7b, 0x10, 0x26, 0x00, 0xf3, 0x00, 0x00, 0x10, 0x07, 0x02, 0xd4, 0x02, 0xcd, 0x00, 0x00, 0x00, 0x02, 0x00, 0xd8, 0x00, 0xd8, 0x01, 0x96, 0x04, 0xfb, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x13, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0xd8, 0xbe, 0xbe, 0xbe, 0xbe, 0x01, 0xd6, 0xfe, 0x04, 0x23, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x87, 0x00, 0x00, 0x02, 0xab, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x13, 0x21, 0x15, 0x23, 0x11, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x23, 0x88, 0x02, 0x21, 0xb5, 0xb6, 0xfd, 0xdf, 0xb5, 0xb6, 0x05, 0xd5, 0xaa, 0xfb, 0x7f, 0xaa, 0xaa, 0x04, 0x81, 0x00, 0x01, 0x01, 0x82, 0x02, 0x95, 0x04, 0x89, 0x03, 0x3f, 0x00, 0x03, 0x00, 0x00, 0x01, 0x15, 0x21, 0x35, 0x04, 0x88, 0xfc, 0xfa, 0x03, 0x3f, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0x04, 0xcb, 0x02, 0xe6, 0x08, 0xf2, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x36, 0x37, 0x36, 0x35, 0x33, 0x16, 0x15, 0x14, 0x33, 0x32, 0x35, 0x34, 0x27, 0x33, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x01, 0x35, 0x25, 0x15, 0x01, 0x35, 0x25, 0x15, 0x01, 0xdb, 0x0d, 0x1e, 0x34, 0x3d, 0x48, 0x25, 0x1e, 0x0e, 0x58, 0x0a, 0x16, 0x11, 0x2d, 0x37, 0x04, 0x02, 0x56, 0x03, 0x50, 0x40, 0x0c, 0x5d, 0x0b, 0x19, 0x28, 0x4b, 0x40, 0x1c, 0x18, 0xfe, 0xe0, 0x02, 0x0e, 0xfd, 0xf2, 0x02, 0x0e, 0x05, 0x84, 0x4c, 0x28, 0x45, 0x3f, 0x34, 0x6d, 0x6d, 0x62, 0x7d, 0x38, 0x54, 0x22, 0x19, 0x14, 0x18, 0xaa, 0x52, 0x59, 0x24, 0x36, 0xc3, 0xae, 0x73, 0x39, 0x49, 0x74, 0x85, 0x36, 0x59, 0x0a, 0x09, 0x21, 0x1e, 0x02, 0xb3, 0x6e, 0x82, 0x6e, 0xfe, 0x8e, 0x6e, 0x82, 0x6e, 0x00, 0x00, 0x03, 0x00, 0xb4, 0x04, 0xcb, 0x02, 0xe6, 0x09, 0x55, 0x00, 0x28, 0x00, 0x4f, 0x00, 0x5e, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x36, 0x37, 0x36, 0x35, 0x33, 0x16, 0x15, 0x14, 0x33, 0x32, 0x35, 0x34, 0x27, 0x33, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x03, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x33, 0x16, 0x33, 0x15, 0x22, 0x2f, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x33, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0xdb, 0x0d, 0x1e, 0x34, 0x3d, 0x48, 0x25, 0x1e, 0x0e, 0x58, 0x0a, 0x16, 0x11, 0x2d, 0x37, 0x04, 0x02, 0x56, 0x03, 0x50, 0x40, 0x0c, 0x5d, 0x0b, 0x19, 0x28, 0x4b, 0x40, 0x1c, 0x18, 0x0f, 0x21, 0x13, 0x1e, 0x15, 0x61, 0x3e, 0x1a, 0x38, 0x42, 0x24, 0x31, 0x0b, 0x12, 0x0c, 0x11, 0x12, 0x2b, 0x12, 0x2e, 0x18, 0x43, 0x4d, 0x55, 0x66, 0x32, 0x0e, 0x51, 0x0b, 0x1f, 0x2b, 0x33, 0x8f, 0x03, 0x02, 0x09, 0x1f, 0x12, 0x15, 0x0a, 0x10, 0x29, 0x11, 0x05, 0x84, 0x4c, 0x28, 0x45, 0x3f, 0x34, 0x6d, 0x6d, 0x62, 0x7d, 0x38, 0x54, 0x22, 0x19, 0x14, 0x18, 0xaa, 0x52, 0x59, 0x24, 0x36, 0xc3, 0xae, 0x73, 0x39, 0x49, 0x74, 0x85, 0x36, 0x59, 0x0a, 0x09, 0x21, 0x1e, 0x02, 0x6d, 0x24, 0x2a, 0x07, 0x0d, 0x39, 0x5e, 0x57, 0x34, 0x15, 0x27, 0x36, 0x4f, 0x27, 0x26, 0x01, 0x01, 0x6e, 0x02, 0x05, 0x3d, 0x4e, 0x56, 0x9a, 0x29, 0x71, 0x61, 0x1a, 0x4b, 0xee, 0x07, 0x07, 0x15, 0x18, 0x22, 0x1c, 0x09, 0x0d, 0x1c, 0x25, 0x12, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb4, 0x04, 0xba, 0x02, 0xe6, 0x08, 0xe8, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x36, 0x37, 0x36, 0x35, 0x33, 0x16, 0x15, 0x14, 0x33, 0x32, 0x35, 0x34, 0x27, 0x33, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x01, 0x35, 0x25, 0x15, 0x01, 0x35, 0x25, 0x15, 0x01, 0xdb, 0x0d, 0x1e, 0x34, 0x3d, 0x48, 0x25, 0x1e, 0x0e, 0x58, 0x0a, 0x16, 0x11, 0x2d, 0x37, 0x04, 0x02, 0x56, 0x03, 0x50, 0x40, 0x0c, 0x5d, 0x0b, 0x19, 0x28, 0x4b, 0x40, 0x1c, 0x18, 0xfe, 0xe0, 0x02, 0x0e, 0xfd, 0xf2, 0x02, 0x0e, 0x07, 0x78, 0x4c, 0x28, 0x45, 0x3f, 0x34, 0x6d, 0x6d, 0x62, 0x7d, 0x38, 0x54, 0x22, 0x19, 0x14, 0x18, 0xaa, 0x52, 0x59, 0x24, 0x36, 0xc3, 0xae, 0x73, 0x39, 0x49, 0x74, 0x85, 0x36, 0x59, 0x0a, 0x09, 0x21, 0x1e, 0xfe, 0x67, 0x6e, 0x82, 0x6e, 0xfe, 0x8e, 0x6e, 0x82, 0x6e, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x04, 0xcb, 0x02, 0xe6, 0x08, 0x02, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x36, 0x37, 0x36, 0x35, 0x33, 0x16, 0x15, 0x14, 0x33, 0x32, 0x35, 0x34, 0x27, 0x33, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x01, 0x35, 0x25, 0x15, 0x01, 0xdb, 0x0d, 0x1e, 0x34, 0x3d, 0x48, 0x25, 0x1e, 0x0e, 0x58, 0x0a, 0x16, 0x11, 0x2d, 0x37, 0x04, 0x02, 0x56, 0x03, 0x50, 0x40, 0x0c, 0x5d, 0x0b, 0x19, 0x28, 0x4b, 0x40, 0x1c, 0x18, 0xfe, 0xe0, 0x02, 0x0e, 0x05, 0x84, 0x4c, 0x28, 0x45, 0x3f, 0x34, 0x6d, 0x6d, 0x62, 0x7d, 0x38, 0x54, 0x22, 0x19, 0x14, 0x18, 0xaa, 0x52, 0x59, 0x24, 0x36, 0xc3, 0xae, 0x73, 0x39, 0x49, 0x74, 0x85, 0x36, 0x59, 0x0a, 0x09, 0x21, 0x1e, 0x01, 0xc3, 0x6e, 0x82, 0x6e, 0x00, 0x03, 0x00, 0xb4, 0x04, 0xcb, 0x02, 0xe6, 0x09, 0x55, 0x00, 0x28, 0x00, 0x47, 0x00, 0x56, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x36, 0x37, 0x36, 0x35, 0x33, 0x16, 0x15, 0x14, 0x33, 0x32, 0x35, 0x34, 0x27, 0x33, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x1e, 0x01, 0x33, 0x15, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x35, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0xdb, 0x0d, 0x1e, 0x34, 0x3d, 0x48, 0x25, 0x1e, 0x0e, 0x58, 0x0a, 0x16, 0x11, 0x2d, 0x37, 0x04, 0x02, 0x56, 0x03, 0x50, 0x40, 0x0c, 0x5d, 0x0b, 0x19, 0x28, 0x4b, 0x40, 0x1c, 0x18, 0x0c, 0x08, 0x12, 0x61, 0x3e, 0x1a, 0x38, 0x42, 0x24, 0x31, 0x0c, 0x0f, 0x21, 0x12, 0x20, 0x1d, 0x1b, 0x19, 0x26, 0x3f, 0xb4, 0x84, 0x89, 0x7d, 0x15, 0x4d, 0x03, 0x02, 0x09, 0x1f, 0x12, 0x15, 0x0a, 0x10, 0x29, 0x11, 0x05, 0x84, 0x4c, 0x28, 0x45, 0x3f, 0x34, 0x6d, 0x6d, 0x62, 0x7d, 0x38, 0x54, 0x22, 0x19, 0x14, 0x18, 0xaa, 0x52, 0x59, 0x24, 0x36, 0xc3, 0xae, 0x73, 0x39, 0x49, 0x74, 0x85, 0x36, 0x59, 0x0a, 0x09, 0x21, 0x1e, 0x02, 0xc3, 0x02, 0x0a, 0x38, 0x5f, 0x57, 0x34, 0x15, 0x27, 0x36, 0x4f, 0x20, 0x2d, 0x01, 0x01, 0x6e, 0x02, 0x02, 0x03, 0x3d, 0x2a, 0x7b, 0x6e, 0x6d, 0x12, 0x70, 0x07, 0x07, 0x15, 0x18, 0x22, 0x1c, 0x09, 0x0d, 0x1c, 0x25, 0x12, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0xb4, 0x04, 0xba, 0x02, 0xe6, 0x08, 0x20, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x36, 0x37, 0x36, 0x35, 0x33, 0x16, 0x15, 0x14, 0x33, 0x32, 0x35, 0x34, 0x27, 0x33, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x01, 0x35, 0x25, 0x15, 0x01, 0xdb, 0x0d, 0x1e, 0x34, 0x3d, 0x48, 0x25, 0x1e, 0x0e, 0x58, 0x0a, 0x16, 0x11, 0x2d, 0x37, 0x04, 0x02, 0x56, 0x03, 0x50, 0x40, 0x0c, 0x5d, 0x0b, 0x19, 0x28, 0x4b, 0x40, 0x1c, 0x18, 0xfe, 0xe0, 0x02, 0x0e, 0x06, 0xb0, 0x4c, 0x28, 0x45, 0x3f, 0x34, 0x6d, 0x6d, 0x62, 0x7d, 0x38, 0x54, 0x22, 0x19, 0x14, 0x18, 0xaa, 0x52, 0x59, 0x24, 0x36, 0xc3, 0xae, 0x73, 0x39, 0x49, 0x74, 0x85, 0x36, 0x59, 0x0a, 0x09, 0x21, 0x1e, 0xfe, 0x3f, 0x6e, 0x82, 0x6e, 0x00, 0x02, 0x00, 0xc6, 0x04, 0xbf, 0x02, 0xd4, 0x07, 0x9e, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x15, 0x05, 0x03, 0x35, 0x25, 0x15, 0x01, 0x2e, 0x46, 0x28, 0x0e, 0x0f, 0x33, 0x34, 0x53, 0x37, 0x2f, 0x2d, 0x39, 0x3c, 0x0f, 0x1a, 0x54, 0x1e, 0x6c, 0xfe, 0xcc, 0x68, 0x02, 0x0e, 0x05, 0x23, 0x12, 0x14, 0x24, 0x25, 0x2d, 0x60, 0x2b, 0x2d, 0x21, 0x64, 0x21, 0x12, 0x20, 0x1a, 0x4d, 0x1b, 0x0a, 0x1d, 0x66, 0x4d, 0x01, 0xef, 0x6e, 0x82, 0x6e, 0x00, 0x03, 0x00, 0xc6, 0x04, 0xbf, 0x02, 0xd4, 0x08, 0xf1, 0x00, 0x18, 0x00, 0x37, 0x00, 0x46, 0x00, 0x00, 0x01, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x15, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x37, 0x15, 0x05, 0x13, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x1e, 0x01, 0x33, 0x15, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x35, 0x32, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0x2e, 0x46, 0x28, 0x0e, 0x0f, 0x33, 0x34, 0x53, 0x37, 0x2f, 0x2d, 0x39, 0x3c, 0x0f, 0x1a, 0x54, 0x1e, 0x6c, 0xfe, 0xcc, 0xc4, 0x08, 0x12, 0x61, 0x3e, 0x1a, 0x38, 0x42, 0x24, 0x31, 0x0c, 0x0f, 0x21, 0x12, 0x20, 0x1d, 0x1b, 0x19, 0x26, 0x3f, 0xb4, 0x84, 0x89, 0x7d, 0x15, 0x4d, 0x03, 0x02, 0x09, 0x1f, 0x12, 0x15, 0x0a, 0x10, 0x29, 0x11, 0x05, 0x23, 0x12, 0x14, 0x24, 0x25, 0x2d, 0x60, 0x2b, 0x2d, 0x21, 0x64, 0x21, 0x12, 0x20, 0x1a, 0x4d, 0x1b, 0x0a, 0x1d, 0x66, 0x4d, 0x02, 0xef, 0x02, 0x0a, 0x38, 0x5f, 0x57, 0x34, 0x15, 0x27, 0x36, 0x4f, 0x20, 0x2d, 0x01, 0x01, 0x6e, 0x02, 0x02, 0x03, 0x3d, 0x2a, 0x7b, 0x6e, 0x6d, 0x12, 0x70, 0x07, 0x07, 0x15, 0x18, 0x22, 0x1c, 0x09, 0x0d, 0x1c, 0x25, 0x12, 0x08, 0x00, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x02, 0x13, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x33, 0x11, 0x33, 0x11, 0x33, 0x15, 0xae, 0xa5, 0xc0, 0x05, 0xd5, 0xfa, 0xbe, 0x93, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x02, 0x13, 0x05, 0xd5, 0x00, 0x07, 0x00, 0x00, 0x25, 0x33, 0x15, 0x21, 0x35, 0x33, 0x11, 0x33, 0x01, 0x53, 0xc0, 0xfd, 0xdb, 0xc0, 0xa5, 0x93, 0x93, 0x93, 0x05, 0x42, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x01, 0x54, 0x05, 0xd5, 0x00, 0x05, 0x00, 0x00, 0x29, 0x01, 0x35, 0x33, 0x11, 0x33, 0x01, 0x53, 0xfe, 0x9b, 0xc0, 0xa5, 0x93, 0x05, 0x42, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0xff, 0xe3, 0x04, 0x2f, 0x03, 0x93, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x12, 0x10, 0x16, 0x32, 0x36, 0x10, 0x26, 0x22, 0x01, 0x06, 0x23, 0x22, 0x02, 0x10, 0x12, 0x20, 0x12, 0x15, 0x14, 0x07, 0x33, 0x15, 0xf2, 0xa7, 0xeb, 0xa7, 0xa7, 0xeb, 0x01, 0x0c, 0x46, 0x51, 0xaf, 0xf9, 0xf9, 0x01, 0x5f, 0xf9, 0x5d, 0xd5, 0x02, 0x3e, 0xfe, 0xfa, 0xb9, 0xb9, 0x01, 0x06, 0xb9, 0xfd, 0x09, 0x1d, 0x01, 0x15, 0x01, 0x86, 0x01, 0x15, 0xfe, 0xeb, 0xc3, 0xa9, 0x7f, 0x93, 0x00, 0x02, 0xff, 0xee, 0xff, 0xe3, 0x04, 0x2f, 0x03, 0x93, 0x00, 0x07, 0x00, 0x19, 0x00, 0x00, 0x12, 0x10, 0x16, 0x32, 0x36, 0x10, 0x26, 0x22, 0x01, 0x06, 0x22, 0x27, 0x21, 0x35, 0x33, 0x26, 0x35, 0x34, 0x12, 0x20, 0x12, 0x15, 0x14, 0x07, 0x33, 0x15, 0xf2, 0xa7, 0xeb, 0xa7, 0xa7, 0xeb, 0x01, 0x0c, 0x46, 0xa1, 0x46, 0xfe, 0x76, 0xd5, 0x5d, 0xf9, 0x01, 0x5f, 0xf9, 0x5d, 0xd5, 0x02, 0x3e, 0xfe, 0xfa, 0xb9, 0xb9, 0x01, 0x06, 0xb9, 0xfd, 0x09, 0x1d, 0x1d, 0x93, 0x7f, 0xa9, 0xc3, 0x01, 0x15, 0xfe, 0xeb, 0xc3, 0xa9, 0x7f, 0x93, 0x00, 0x02, 0xff, 0xee, 0xff, 0xe3, 0x03, 0xb8, 0x03, 0x93, 0x00, 0x07, 0x00, 0x15, 0x00, 0x00, 0x12, 0x10, 0x16, 0x32, 0x36, 0x10, 0x26, 0x22, 0x03, 0x26, 0x35, 0x34, 0x12, 0x20, 0x12, 0x10, 0x02, 0x23, 0x22, 0x27, 0x21, 0x35, 0xf2, 0xa7, 0xeb, 0xa7, 0xa7, 0xeb, 0xd6, 0x5d, 0xf9, 0x01, 0x5f, 0xf9, 0xf9, 0xb0, 0x50, 0x46, 0xfe, 0x76, 0x02, 0x3e, 0xfe, 0xfa, 0xb9, 0xb9, 0x01, 0x06, 0xb9, 0xfd, 0x9c, 0x7f, 0xa9, 0xc3, 0x01, 0x15, 0xfe, 0xeb, 0xfe, 0x7a, 0xfe, 0xeb, 0x1d, 0x93, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x03, 0x20, 0x05, 0xd9, 0x00, 0x0a, 0x00, 0x00, 0x29, 0x01, 0x11, 0x03, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x11, 0x21, 0x03, 0x1f, 0xfe, 0x15, 0xfd, 0xaf, 0xa1, 0xa1, 0xae, 0xfd, 0x01, 0x46, 0x03, 0x2a, 0x02, 0xaf, 0xfe, 0x5d, 0x01, 0xa3, 0xfd, 0x51, 0xfd, 0x69, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x20, 0x05, 0xd9, 0x00, 0x0c, 0x00, 0x00, 0x25, 0x15, 0x21, 0x35, 0x21, 0x11, 0x03, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x11, 0x03, 0x1f, 0xfc, 0xcf, 0x01, 0x46, 0xfd, 0xaf, 0xa1, 0xa1, 0xae, 0xfd, 0x93, 0x93, 0x93, 0x02, 0x97, 0x02, 0xaf, 0xfe, 0x5d, 0x01, 0xa3, 0xfd, 0x51, 0xfd, 0x69, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x02, 0xd7, 0x05, 0xd9, 0x00, 0x0a, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x03, 0x33, 0x1b, 0x01, 0x33, 0x03, 0x11, 0x12, 0x01, 0x46, 0xfd, 0xaf, 0xa1, 0xa1, 0xae, 0xfd, 0x93, 0x02, 0x97, 0x02, 0xaf, 0xfe, 0x5d, 0x01, 0xa3, 0xfd, 0x51, 0xfc, 0xd6, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x04, 0x55, 0x03, 0x71, 0x00, 0x08, 0x00, 0x00, 0x21, 0x23, 0x09, 0x01, 0x23, 0x01, 0x33, 0x01, 0x33, 0x04, 0x55, 0xf9, 0xfe, 0xc5, 0xfe, 0xc5, 0xaf, 0x01, 0x7a, 0xe1, 0x01, 0x48, 0x7b, 0x02, 0xbd, 0xfd, 0x43, 0x03, 0x71, 0xfd, 0x22, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x04, 0x55, 0x03, 0x71, 0x00, 0x0a, 0x00, 0x00, 0x33, 0x23, 0x35, 0x33, 0x01, 0x33, 0x01, 0x33, 0x15, 0x23, 0x01, 0xe6, 0xf8, 0x7a, 0x01, 0x49, 0xe1, 0x01, 0x48, 0x7b, 0xf9, 0xfe, 0xc5, 0x93, 0x02, 0xde, 0xfd, 0x22, 0x93, 0x02, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x04, 0x0c, 0x03, 0x71, 0x00, 0x08, 0x00, 0x00, 0x33, 0x23, 0x35, 0x33, 0x01, 0x33, 0x01, 0x23, 0x01, 0xe6, 0xf8, 0x7a, 0x01, 0x49, 0xe1, 0x01, 0x7a, 0xb0, 0xfe, 0xc5, 0x93, 0x02, 0xde, 0xfc, 0x8f, 0x02, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xc8, 0x03, 0x71, 0x00, 0x09, 0x00, 0x00, 0x29, 0x01, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x04, 0xc7, 0xfb, 0xe0, 0xa7, 0x02, 0x19, 0xa7, 0xb9, 0x03, 0x71, 0xfd, 0x22, 0x02, 0xde, 0xfd, 0x22, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x04, 0xc8, 0x03, 0x71, 0x00, 0x0b, 0x00, 0x00, 0x29, 0x01, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x04, 0xc7, 0xfb, 0x27, 0xb9, 0xa7, 0x02, 0x19, 0xa7, 0xb9, 0x93, 0x02, 0xde, 0xfd, 0x22, 0x02, 0xde, 0xfd, 0x22, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x04, 0x0e, 0x03, 0x71, 0x00, 0x09, 0x00, 0x00, 0x29, 0x01, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x04, 0x0e, 0xfb, 0xe0, 0xb9, 0xa7, 0x02, 0x19, 0xa7, 0x93, 0x02, 0xde, 0xfd, 0x22, 0x02, 0xde, 0x00, 0x01, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xc8, 0x03, 0x71, 0x00, 0x09, 0x00, 0x00, 0x33, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x15, 0xa7, 0x02, 0xc0, 0xfd, 0x40, 0x03, 0x67, 0xb9, 0x93, 0x02, 0x4b, 0x93, 0xfd, 0x22, 0x93, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x04, 0xc8, 0x03, 0x71, 0x00, 0x09, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x15, 0x12, 0x03, 0x79, 0xfd, 0x40, 0x03, 0x67, 0xb9, 0x93, 0x02, 0x4b, 0x93, 0xfd, 0x22, 0x93, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x04, 0x0e, 0x03, 0x71, 0x00, 0x07, 0x00, 0x00, 0x01, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x04, 0x0e, 0xfb, 0xe0, 0x03, 0x79, 0xfd, 0x40, 0x03, 0x71, 0xfc, 0x8f, 0x93, 0x02, 0x4b, 0x93, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x04, 0x59, 0x05, 0xe2, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x00, 0x21, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x3e, 0x01, 0x32, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x11, 0x21, 0x15, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x01, 0xd0, 0x49, 0x43, 0x67, 0x77, 0x77, 0xce, 0xf1, 0xcf, 0x76, 0x76, 0x68, 0x43, 0x4a, 0x01, 0xe2, 0xfc, 0x9a, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x03, 0x0e, 0x0b, 0x20, 0x31, 0xa8, 0xc5, 0xa9, 0x62, 0x62, 0xa9, 0xc5, 0xa8, 0x31, 0x20, 0x0b, 0xfd, 0x85, 0x93, 0x04, 0xad, 0x70, 0x60, 0x38, 0x38, 0x60, 0x70, 0x60, 0x38, 0x38, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x59, 0x05, 0xe2, 0x00, 0x15, 0x00, 0x21, 0x00, 0x00, 0x25, 0x21, 0x15, 0x21, 0x35, 0x21, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x3e, 0x01, 0x32, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x02, 0x76, 0x01, 0xe2, 0xfb, 0x96, 0x01, 0xe2, 0x49, 0x43, 0x67, 0x77, 0x77, 0xce, 0xf1, 0xcf, 0x76, 0x76, 0x68, 0x43, 0x4a, 0xfe, 0x7c, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x93, 0x93, 0x93, 0x02, 0x7b, 0x0b, 0x20, 0x31, 0xa8, 0xc5, 0xa9, 0x62, 0x62, 0xa9, 0xc5, 0xa8, 0x31, 0x20, 0x0b, 0x01, 0x9f, 0x70, 0x60, 0x38, 0x38, 0x60, 0x70, 0x60, 0x38, 0x38, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0xe1, 0x05, 0xe2, 0x00, 0x13, 0x00, 0x1f, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x3e, 0x01, 0x32, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x11, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x12, 0x01, 0xe2, 0x49, 0x43, 0x67, 0x77, 0x77, 0xce, 0xf1, 0xcf, 0x76, 0x76, 0x68, 0x43, 0x4a, 0xfe, 0x7c, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x93, 0x02, 0x7b, 0x0b, 0x20, 0x31, 0xa8, 0xc5, 0xa9, 0x62, 0x62, 0xa9, 0xc5, 0xa8, 0x31, 0x20, 0x0b, 0xfc, 0xf2, 0x04, 0xad, 0x70, 0x60, 0x38, 0x38, 0x60, 0x70, 0x60, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xc8, 0x04, 0xa6, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x10, 0x33, 0x15, 0x22, 0x07, 0x33, 0x15, 0x23, 0x01, 0x21, 0x35, 0x21, 0x01, 0xdc, 0xda, 0x77, 0x02, 0x78, 0xd9, 0x02, 0xeb, 0xfb, 0xe0, 0x04, 0x20, 0x03, 0x9c, 0x01, 0x0a, 0x66, 0x9a, 0x9e, 0xfc, 0xf8, 0x93, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0xc8, 0x04, 0xa6, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x10, 0x33, 0x15, 0x22, 0x07, 0x33, 0x15, 0x23, 0x01, 0x21, 0x35, 0x21, 0x01, 0xdc, 0xda, 0x77, 0x02, 0x78, 0xd9, 0x02, 0xeb, 0xfb, 0x27, 0x04, 0xd9, 0x03, 0x9c, 0x01, 0x0a, 0x66, 0x9a, 0x9e, 0xfc, 0xf8, 0x93, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x0e, 0x04, 0xa6, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x10, 0x33, 0x15, 0x22, 0x07, 0x33, 0x15, 0x23, 0x01, 0x21, 0x35, 0x21, 0x01, 0xdc, 0xda, 0x77, 0x02, 0x78, 0xd9, 0x02, 0x32, 0xfb, 0xe0, 0x04, 0x20, 0x03, 0x9c, 0x01, 0x0a, 0x66, 0x9a, 0x9e, 0xfc, 0xf8, 0x93, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x06, 0x0a, 0x05, 0xee, 0x00, 0x13, 0x00, 0x1d, 0x00, 0x00, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x22, 0x26, 0x10, 0x36, 0x20, 0x17, 0x16, 0x1d, 0x01, 0x21, 0x11, 0x33, 0x15, 0x01, 0x35, 0x34, 0x27, 0x26, 0x22, 0x06, 0x14, 0x16, 0x33, 0x04, 0xa9, 0xfe, 0x70, 0x8d, 0xdf, 0xa9, 0x9e, 0x9f, 0x01, 0x42, 0x55, 0x7d, 0x02, 0x37, 0xb9, 0xfc, 0x83, 0x53, 0x33, 0xb2, 0x62, 0x67, 0x54, 0x02, 0xde, 0xfe, 0xc4, 0x01, 0x3c, 0xd6, 0x01, 0x55, 0xe5, 0x66, 0x98, 0xb6, 0xc9, 0xfd, 0x22, 0x93, 0x03, 0x71, 0xc9, 0x83, 0x5d, 0x38, 0x98, 0xc6, 0x83, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x06, 0x0a, 0x05, 0xee, 0x00, 0x15, 0x00, 0x1f, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x22, 0x26, 0x10, 0x36, 0x20, 0x17, 0x16, 0x1d, 0x01, 0x21, 0x11, 0x33, 0x15, 0x21, 0x35, 0x01, 0x35, 0x34, 0x27, 0x26, 0x22, 0x06, 0x14, 0x16, 0x33, 0x04, 0xa9, 0xfe, 0x70, 0x8d, 0xdf, 0xa9, 0x9e, 0x9f, 0x01, 0x42, 0x55, 0x7d, 0x02, 0x37, 0xb9, 0xf9, 0xe5, 0x02, 0x9e, 0x53, 0x33, 0xb2, 0x62, 0x67, 0x54, 0x93, 0x02, 0x4b, 0xfe, 0xc4, 0x01, 0x3c, 0xd6, 0x01, 0x55, 0xe5, 0x66, 0x98, 0xb6, 0xc9, 0xfd, 0x22, 0x93, 0x93, 0x02, 0xde, 0xc9, 0x83, 0x5d, 0x38, 0x98, 0xc6, 0x83, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x05, 0x50, 0x05, 0xee, 0x00, 0x13, 0x00, 0x1d, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x23, 0x11, 0x23, 0x22, 0x26, 0x10, 0x36, 0x20, 0x17, 0x16, 0x1d, 0x01, 0x21, 0x11, 0x21, 0x35, 0x01, 0x35, 0x34, 0x27, 0x26, 0x22, 0x06, 0x14, 0x16, 0x33, 0x04, 0xa9, 0xfe, 0x70, 0x8d, 0xdf, 0xa9, 0x9e, 0x9f, 0x01, 0x42, 0x55, 0x7d, 0x02, 0x37, 0xfa, 0x9e, 0x02, 0x9e, 0x53, 0x33, 0xb2, 0x62, 0x67, 0x54, 0x93, 0x02, 0x4b, 0xfe, 0xc4, 0x01, 0x3c, 0xd6, 0x01, 0x55, 0xe5, 0x66, 0x98, 0xb6, 0xc9, 0xfc, 0x8f, 0x93, 0x02, 0xde, 0xc9, 0x83, 0x5d, 0x38, 0x98, 0xc6, 0x83, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x03, 0x3a, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0xae, 0x02, 0x42, 0xfe, 0x63, 0x01, 0x9d, 0xfe, 0x63, 0x01, 0xe6, 0x05, 0xd5, 0x93, 0xfe, 0x2f, 0x92, 0xfd, 0xb4, 0x93, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x3a, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x23, 0x35, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x12, 0xc0, 0x02, 0x42, 0xfe, 0x63, 0x01, 0x9d, 0xfe, 0x63, 0x01, 0xe6, 0x93, 0x05, 0x42, 0x93, 0xfe, 0x2f, 0x92, 0xfd, 0xb4, 0x93, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x02, 0xf1, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x29, 0x01, 0x35, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x21, 0x01, 0x53, 0xfe, 0x9b, 0xc0, 0x02, 0x42, 0xfe, 0x63, 0x01, 0x9d, 0xfe, 0x63, 0x93, 0x05, 0x42, 0x93, 0xfe, 0x2f, 0x92, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x03, 0x3a, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x15, 0x01, 0xd4, 0xfe, 0x63, 0x01, 0x9d, 0xfe, 0x63, 0x02, 0x43, 0xbf, 0x02, 0xdf, 0x92, 0x01, 0xd1, 0x93, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x3a, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x15, 0x12, 0x01, 0xe6, 0xfe, 0x63, 0x01, 0x9d, 0xfe, 0x63, 0x02, 0x43, 0xbf, 0x93, 0x02, 0x4c, 0x92, 0x01, 0xd1, 0x93, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x02, 0x7a, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x02, 0x7a, 0xfd, 0x74, 0x01, 0xe6, 0xfe, 0x63, 0x01, 0x9d, 0xfe, 0x63, 0x02, 0x43, 0x93, 0x02, 0x4c, 0x92, 0x01, 0xd1, 0x93, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x04, 0x18, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x17, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x01, 0x11, 0x33, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x33, 0x15, 0x02, 0x59, 0xfe, 0xef, 0x01, 0x0e, 0x49, 0x2f, 0x28, 0x28, 0x37, 0xfe, 0x10, 0xa7, 0x01, 0x33, 0x5e, 0x73, 0x4f, 0x47, 0xbe, 0x02, 0xde, 0xfd, 0xb5, 0x5d, 0x4f, 0x7a, 0x7d, 0x49, 0x5f, 0xfd, 0x22, 0x05, 0xd5, 0xfd, 0x9c, 0x87, 0x5f, 0xd2, 0xa4, 0x82, 0x93, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x18, 0x05, 0xd5, 0x00, 0x0e, 0x00, 0x19, 0x00, 0x00, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x33, 0x15, 0x01, 0x21, 0x11, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x12, 0xb9, 0xa7, 0x01, 0x33, 0x5e, 0x73, 0x4f, 0x47, 0xbe, 0xfe, 0x41, 0xfe, 0xef, 0x01, 0x0e, 0x49, 0x2f, 0x28, 0x28, 0x37, 0x93, 0x05, 0x42, 0xfd, 0x9c, 0x87, 0x5f, 0xd2, 0xa4, 0x82, 0x93, 0x02, 0xde, 0xfd, 0xb5, 0x5d, 0x4f, 0x7a, 0x7d, 0x49, 0x5f, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0xa1, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x19, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x01, 0x35, 0x33, 0x11, 0x33, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x02, 0x59, 0xfe, 0xef, 0x01, 0x0e, 0x49, 0x2f, 0x28, 0x28, 0x37, 0xfd, 0x57, 0xb9, 0xa7, 0x01, 0x33, 0x5e, 0x73, 0x4f, 0x4f, 0x50, 0x61, 0x02, 0xde, 0xfd, 0xb5, 0x5d, 0x4f, 0x7a, 0x7d, 0x49, 0x5f, 0xfd, 0x22, 0x93, 0x05, 0x42, 0xfd, 0x9c, 0x87, 0x5f, 0xd2, 0xad, 0x87, 0x85, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x04, 0x7a, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x21, 0x34, 0x02, 0x27, 0x26, 0x27, 0x03, 0x35, 0x21, 0x15, 0x05, 0x13, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x21, 0x15, 0x02, 0x66, 0x18, 0x30, 0x46, 0x7b, 0xaf, 0x03, 0x0c, 0xfd, 0xd6, 0x8e, 0x7a, 0x2f, 0x3b, 0x06, 0x02, 0x01, 0x70, 0x99, 0x01, 0x5f, 0x96, 0xdc, 0xdc, 0x01, 0x39, 0x56, 0x93, 0x01, 0xfe, 0xef, 0xea, 0xb8, 0xe6, 0x9c, 0x40, 0x39, 0x93, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x04, 0x7a, 0x05, 0xd5, 0x00, 0x16, 0x00, 0x00, 0x23, 0x35, 0x21, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x03, 0x35, 0x21, 0x15, 0x05, 0x13, 0x16, 0x17, 0x16, 0x17, 0x16, 0x15, 0x21, 0x15, 0x12, 0x02, 0x75, 0x03, 0x07, 0x0b, 0x30, 0x46, 0x7b, 0xaf, 0x03, 0x0c, 0xfd, 0xd6, 0x8e, 0x7a, 0x2f, 0x3b, 0x06, 0x02, 0x01, 0x70, 0x93, 0x58, 0x5d, 0xb0, 0x96, 0xdc, 0xdc, 0x01, 0x39, 0x56, 0x93, 0x01, 0xfe, 0xef, 0xea, 0xb8, 0xe6, 0x9c, 0x40, 0x39, 0x93, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0xba, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x00, 0x23, 0x35, 0x21, 0x26, 0x27, 0x26, 0x27, 0x26, 0x27, 0x03, 0x35, 0x21, 0x15, 0x05, 0x13, 0x16, 0x17, 0x16, 0x12, 0x07, 0x12, 0x02, 0x75, 0x03, 0x07, 0x0b, 0x30, 0x46, 0x7b, 0xaf, 0x03, 0x0c, 0xfd, 0xd6, 0x8e, 0x7a, 0x2f, 0x3b, 0x0a, 0x01, 0x93, 0x58, 0x5d, 0xb0, 0x96, 0xdc, 0xdc, 0x01, 0x39, 0x56, 0x93, 0x01, 0xfe, 0xef, 0xea, 0xb8, 0xe6, 0xfe, 0xc9, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x02, 0x98, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x00, 0x21, 0x11, 0x03, 0x35, 0x13, 0x33, 0x11, 0x33, 0x15, 0x01, 0x32, 0xfb, 0xf9, 0xa8, 0xbf, 0x04, 0xdf, 0xfe, 0xc7, 0xf6, 0x01, 0x39, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x02, 0x98, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x03, 0x35, 0x13, 0x33, 0x11, 0x33, 0x15, 0x12, 0x01, 0x44, 0xfb, 0xf9, 0xa8, 0xbf, 0x93, 0x04, 0x4c, 0xfe, 0xc7, 0xf6, 0x01, 0x39, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x01, 0xd8, 0x05, 0xd5, 0x00, 0x08, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x03, 0x35, 0x13, 0x33, 0x11, 0x12, 0x01, 0x44, 0xfb, 0xf9, 0xa8, 0x93, 0x04, 0x4c, 0xfe, 0xc7, 0xf6, 0x01, 0x39, 0xfa, 0x2b, 0x00, 0x00, 0x03, 0x00, 0xad, 0x00, 0x00, 0x06, 0xfa, 0x04, 0x1a, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x00, 0x33, 0x11, 0x34, 0x12, 0x33, 0x32, 0x16, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x33, 0x15, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x21, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0xae, 0xdb, 0xb3, 0x70, 0x6c, 0x30, 0x21, 0x87, 0xbe, 0xbd, 0x55, 0x7a, 0xc0, 0xfe, 0x98, 0x93, 0x51, 0x74, 0x72, 0x01, 0xca, 0xfd, 0x8e, 0x94, 0x50, 0x62, 0x85, 0x01, 0xcb, 0x01, 0xee, 0xa6, 0x00, 0xff, 0x4b, 0x2d, 0x2d, 0xd2, 0x58, 0x80, 0x68, 0xfd, 0xb9, 0x93, 0x02, 0x7c, 0x82, 0x80, 0xc5, 0x95, 0xfe, 0x6e, 0x01, 0x63, 0x83, 0x7f, 0xa7, 0xd2, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0x00, 0x00, 0x06, 0xfa, 0x04, 0x1a, 0x00, 0x13, 0x00, 0x1c, 0x00, 0x25, 0x00, 0x00, 0x23, 0x35, 0x33, 0x11, 0x34, 0x12, 0x33, 0x32, 0x16, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x33, 0x15, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x21, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x12, 0xc0, 0xdb, 0xb3, 0x70, 0x6c, 0x30, 0x21, 0x87, 0xbe, 0xbd, 0x55, 0x7a, 0xc0, 0xfe, 0x98, 0x93, 0x51, 0x74, 0x72, 0x01, 0xca, 0xfd, 0x8e, 0x94, 0x50, 0x62, 0x85, 0x01, 0xcb, 0x93, 0x01, 0x5b, 0xa6, 0x00, 0xff, 0x4b, 0x2d, 0x2d, 0xd2, 0x58, 0x80, 0x68, 0xfd, 0xb9, 0x93, 0x02, 0x7c, 0x82, 0x80, 0xc5, 0x95, 0xfe, 0x6e, 0x01, 0x63, 0x83, 0x7f, 0xa7, 0xd2, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0x00, 0x00, 0x06, 0x3a, 0x04, 0x1a, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x23, 0x00, 0x00, 0x23, 0x35, 0x33, 0x11, 0x34, 0x12, 0x33, 0x32, 0x16, 0x17, 0x3e, 0x01, 0x33, 0x32, 0x17, 0x16, 0x15, 0x11, 0x03, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x21, 0x01, 0x34, 0x26, 0x23, 0x22, 0x06, 0x1d, 0x01, 0x21, 0x12, 0xc0, 0xdb, 0xb3, 0x70, 0x6c, 0x30, 0x21, 0x87, 0xbe, 0xbd, 0x55, 0x7a, 0xa8, 0x93, 0x51, 0x74, 0x72, 0x01, 0xca, 0xfd, 0x8e, 0x94, 0x50, 0x62, 0x85, 0x01, 0xcb, 0x93, 0x01, 0x5b, 0xa6, 0x00, 0xff, 0x4b, 0x2d, 0x2d, 0xd2, 0x58, 0x80, 0x68, 0xfd, 0x26, 0x02, 0x7c, 0x82, 0x80, 0xc5, 0x95, 0xfe, 0x6e, 0x01, 0x63, 0x83, 0x7f, 0xa7, 0xd2, 0xf2, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x03, 0x7a, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x01, 0x61, 0xfe, 0xd6, 0x01, 0x2a, 0xa5, 0x01, 0x2a, 0xfe, 0xd6, 0x01, 0x73, 0x03, 0x81, 0x93, 0x01, 0xc1, 0xfe, 0x3f, 0x93, 0xfd, 0x12, 0x93, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x7a, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x12, 0x01, 0x73, 0xfe, 0xd6, 0x01, 0x2a, 0xa5, 0x01, 0x2a, 0xfe, 0xd6, 0x01, 0x73, 0x93, 0x02, 0xee, 0x93, 0x01, 0xc1, 0xfe, 0x3f, 0x93, 0xfd, 0x12, 0x93, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x31, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x02, 0x06, 0xfd, 0xe8, 0x01, 0x73, 0xfe, 0xd6, 0x01, 0x2a, 0xa5, 0x01, 0x2a, 0xfe, 0xd6, 0x93, 0x02, 0xee, 0x93, 0x01, 0xc1, 0xfe, 0x3f, 0x93, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x05, 0xb6, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x15, 0x00, 0x00, 0x25, 0x11, 0x21, 0x11, 0x07, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x03, 0x9d, 0xfe, 0x6a, 0xa6, 0xfe, 0xd6, 0x01, 0x2a, 0xa6, 0x01, 0x96, 0xa6, 0x01, 0x2b, 0xfe, 0xd5, 0x01, 0x73, 0x93, 0x02, 0xee, 0xfd, 0x12, 0x93, 0x03, 0x81, 0x93, 0x01, 0xc1, 0xfe, 0x3f, 0x01, 0xc1, 0xfe, 0x3f, 0x93, 0xfd, 0x12, 0x93, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x05, 0xb6, 0x05, 0xd5, 0x00, 0x13, 0x00, 0x17, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x25, 0x11, 0x21, 0x11, 0x12, 0x01, 0x73, 0xfe, 0xd6, 0x01, 0x2a, 0xa6, 0x01, 0x96, 0xa6, 0x01, 0x2b, 0xfe, 0xd5, 0x01, 0x73, 0xfd, 0xe7, 0xfe, 0x6a, 0x93, 0x02, 0xee, 0x93, 0x01, 0xc1, 0xfe, 0x3f, 0x01, 0xc1, 0xfe, 0x3f, 0x93, 0xfd, 0x12, 0x93, 0x93, 0x02, 0xee, 0xfd, 0x12, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x05, 0x6e, 0x05, 0xd5, 0x00, 0x11, 0x00, 0x15, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x21, 0x15, 0x21, 0x03, 0x11, 0x21, 0x11, 0x04, 0x43, 0xfb, 0xab, 0x01, 0x73, 0xfe, 0xd6, 0x01, 0x2a, 0xa6, 0x01, 0x96, 0xa6, 0x01, 0x2b, 0xfe, 0xd5, 0xa6, 0xfe, 0x6a, 0x93, 0x02, 0xee, 0x93, 0x01, 0xc1, 0xfe, 0x3f, 0x01, 0xc1, 0xfe, 0x3f, 0x93, 0xfd, 0x12, 0x02, 0xee, 0xfd, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0xa7, 0x00, 0x00, 0x04, 0xc8, 0x03, 0x71, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x33, 0x11, 0x21, 0x11, 0x33, 0x15, 0x01, 0x11, 0x21, 0x11, 0xa7, 0x03, 0x67, 0xb9, 0xfc, 0x87, 0x02, 0x19, 0x03, 0x71, 0xfd, 0x22, 0x93, 0x02, 0xde, 0xfd, 0xb5, 0x02, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0xc8, 0x03, 0x71, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x23, 0x35, 0x33, 0x11, 0x21, 0x11, 0x33, 0x15, 0x01, 0x11, 0x21, 0x11, 0x12, 0xb9, 0x03, 0x67, 0xb9, 0xfc, 0x87, 0x02, 0x19, 0x93, 0x02, 0xde, 0xfd, 0x22, 0x93, 0x02, 0xde, 0xfd, 0xb5, 0x02, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x0e, 0x03, 0x71, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x29, 0x01, 0x35, 0x33, 0x11, 0x21, 0x05, 0x11, 0x21, 0x11, 0x04, 0x0e, 0xfb, 0xe0, 0xb9, 0x03, 0x67, 0xfd, 0x40, 0x02, 0x19, 0x93, 0x02, 0xde, 0x93, 0xfd, 0xb5, 0x02, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x04, 0x92, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x01, 0x21, 0x01, 0x07, 0x01, 0x21, 0x01, 0x21, 0x15, 0x03, 0x65, 0xfd, 0xb6, 0x01, 0x25, 0x68, 0xfe, 0x5f, 0x04, 0x12, 0xfe, 0x91, 0x01, 0xb8, 0x05, 0x42, 0xfb, 0x7e, 0xc0, 0x05, 0xd5, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x92, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x21, 0x01, 0x05, 0x35, 0x21, 0x01, 0x21, 0x01, 0x21, 0x15, 0x03, 0x65, 0xfd, 0xb6, 0x01, 0x25, 0xfd, 0xae, 0x01, 0xb8, 0xfe, 0x91, 0x04, 0x12, 0xfe, 0x91, 0x01, 0xb8, 0x05, 0x42, 0xfb, 0x7e, 0xc0, 0x93, 0x05, 0x42, 0xfa, 0xbe, 0x93, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x4a, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x01, 0x21, 0x01, 0x05, 0x35, 0x21, 0x01, 0x21, 0x01, 0x03, 0x65, 0xfd, 0xb6, 0x01, 0x25, 0xfd, 0xae, 0x01, 0xb8, 0xfe, 0x91, 0x04, 0x12, 0xfe, 0x5f, 0x05, 0x42, 0xfb, 0x7e, 0xc0, 0x93, 0x05, 0x42, 0xfa, 0x2b, 0x00, 0x00, 0x03, 0x00, 0xad, 0x00, 0x00, 0x05, 0x5b, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x21, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x06, 0x07, 0x06, 0x2f, 0x01, 0x11, 0x21, 0x15, 0x03, 0x15, 0x97, 0x55, 0x21, 0x1b, 0x1b, 0x1b, 0x5e, 0x94, 0xfe, 0x3f, 0x01, 0x1c, 0xfe, 0x3e, 0x01, 0xc2, 0x01, 0x84, 0x77, 0x3a, 0x3e, 0x01, 0x3d, 0x53, 0x7e, 0xbf, 0x02, 0x46, 0x03, 0x71, 0x51, 0x45, 0x3d, 0x3c, 0x64, 0x5e, 0xfd, 0x9c, 0xfd, 0xb5, 0x02, 0x4b, 0xfd, 0x22, 0x03, 0x71, 0x02, 0x64, 0x85, 0x90, 0x7c, 0x91, 0x5b, 0x7c, 0x01, 0x01, 0xfd, 0xb5, 0x93, 0x00, 0x00, 0x03, 0xff, 0xee, 0x00, 0x00, 0x05, 0x5b, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x21, 0x00, 0x00, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x01, 0x11, 0x21, 0x11, 0x01, 0x35, 0x33, 0x11, 0x21, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x06, 0x07, 0x06, 0x2f, 0x01, 0x11, 0x21, 0x15, 0x03, 0x15, 0x97, 0x55, 0x21, 0x1b, 0x1b, 0x1b, 0x5e, 0x94, 0xfe, 0x3f, 0x01, 0x1c, 0xfd, 0x7e, 0xc0, 0x01, 0xc2, 0x01, 0x84, 0x77, 0x3a, 0x3e, 0x01, 0x3d, 0x53, 0x7e, 0xbf, 0x02, 0x46, 0x03, 0x71, 0x51, 0x45, 0x3d, 0x3c, 0x64, 0x5e, 0xfd, 0x9c, 0xfd, 0xb5, 0x02, 0x4b, 0xfd, 0x22, 0x93, 0x02, 0xde, 0x02, 0x64, 0x85, 0x90, 0x7c, 0x91, 0x5b, 0x7c, 0x01, 0x01, 0xfd, 0xb5, 0x93, 0x00, 0x00, 0x03, 0xff, 0xee, 0x00, 0x00, 0x04, 0xe3, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x2b, 0x01, 0x01, 0x11, 0x21, 0x11, 0x13, 0x21, 0x35, 0x33, 0x11, 0x21, 0x11, 0x21, 0x32, 0x17, 0x16, 0x15, 0x06, 0x07, 0x06, 0x2f, 0x01, 0x03, 0x15, 0x97, 0x55, 0x21, 0x1b, 0x1b, 0x1b, 0x5e, 0x94, 0xfe, 0x3f, 0x01, 0x1c, 0xa5, 0xfc, 0xd9, 0xc0, 0x01, 0xc2, 0x01, 0x84, 0x77, 0x3a, 0x3e, 0x01, 0x3d, 0x53, 0x7e, 0xbf, 0x03, 0x71, 0x51, 0x45, 0x3d, 0x3c, 0x64, 0x5e, 0xfd, 0x9c, 0xfd, 0xb5, 0x02, 0x4b, 0xfd, 0x22, 0x93, 0x02, 0xde, 0x02, 0x64, 0x85, 0x90, 0x7c, 0x91, 0x5b, 0x7c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x03, 0xe3, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x15, 0x02, 0x7e, 0xfe, 0xd6, 0xa6, 0xa6, 0x01, 0x2a, 0xa6, 0xbe, 0x03, 0x81, 0xfe, 0xfc, 0x02, 0x9b, 0xfe, 0xfc, 0x01, 0xc1, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0xe3, 0x05, 0xd5, 0x00, 0x0f, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x33, 0x15, 0x12, 0x02, 0x90, 0xfe, 0xd6, 0xa6, 0xa6, 0x01, 0x2a, 0xa6, 0xbe, 0x93, 0x02, 0xee, 0xfe, 0xfc, 0x02, 0x9b, 0xfe, 0xfc, 0x01, 0xc1, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x24, 0x05, 0xd5, 0x00, 0x0d, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x11, 0x12, 0x02, 0x90, 0xfe, 0xd6, 0xa6, 0xa6, 0x01, 0x2a, 0xa6, 0x93, 0x02, 0xee, 0xfe, 0xfc, 0x02, 0x9b, 0xfe, 0xfc, 0x01, 0xc1, 0xfa, 0x2b, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x00, 0x05, 0x49, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0x11, 0x21, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x01, 0xac, 0x01, 0x12, 0xfe, 0xf2, 0x4a, 0x2f, 0x27, 0x27, 0x37, 0x01, 0x4a, 0xfe, 0xcd, 0x61, 0x70, 0x4f, 0x4f, 0x4f, 0x61, 0x01, 0xfa, 0x01, 0x2b, 0xfe, 0xd5, 0x01, 0xeb, 0x02, 0xf7, 0x02, 0x4b, 0x5d, 0x4f, 0x7a, 0x7d, 0x49, 0x5f, 0xfd, 0x09, 0x02, 0x64, 0x87, 0x5f, 0xd2, 0xad, 0x87, 0x85, 0xfd, 0x22, 0x93, 0xfe, 0x2f, 0x93, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x05, 0x49, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0x35, 0x21, 0x11, 0x21, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x01, 0xac, 0x01, 0x12, 0xfe, 0xf2, 0x4a, 0x2f, 0x27, 0x27, 0x37, 0xfe, 0x80, 0x02, 0xca, 0xfe, 0xcd, 0x61, 0x70, 0x4f, 0x4f, 0x4f, 0x61, 0x01, 0xfa, 0x01, 0x2b, 0xfe, 0xd5, 0x01, 0xeb, 0x02, 0xf7, 0x02, 0x4b, 0x5d, 0x4f, 0x7a, 0x7d, 0x49, 0x5f, 0xfd, 0x09, 0x93, 0x01, 0xd1, 0x87, 0x5f, 0xd2, 0xad, 0x87, 0x85, 0xfd, 0x22, 0x93, 0xfe, 0x2f, 0x93, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x89, 0x05, 0xd5, 0x00, 0x0a, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x21, 0x11, 0x21, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x01, 0x35, 0x21, 0x11, 0x21, 0x22, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x33, 0x21, 0x11, 0x21, 0x15, 0x21, 0x11, 0x01, 0xac, 0x01, 0x12, 0xfe, 0xf2, 0x4a, 0x2f, 0x27, 0x27, 0x37, 0xfe, 0x80, 0x02, 0xca, 0xfe, 0xcd, 0x61, 0x70, 0x4f, 0x4f, 0x4f, 0x61, 0x01, 0xfa, 0x01, 0x2b, 0xfe, 0xd5, 0x02, 0xf7, 0x02, 0x4b, 0x5d, 0x4f, 0x7a, 0x7d, 0x49, 0x5f, 0xfd, 0x09, 0x93, 0x01, 0xd1, 0x87, 0x5f, 0xd2, 0xad, 0x87, 0x85, 0xfd, 0x22, 0x93, 0xfd, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x03, 0x7a, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x21, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x01, 0x61, 0xfe, 0xd6, 0x02, 0xf9, 0xfe, 0xd6, 0x01, 0x73, 0x05, 0x42, 0x93, 0x93, 0xfb, 0x51, 0x93, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x7a, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x11, 0x21, 0x15, 0x12, 0x01, 0x73, 0xfe, 0xd6, 0x02, 0xf9, 0xfe, 0xd6, 0x01, 0x73, 0x93, 0x04, 0xaf, 0x93, 0x93, 0xfb, 0x51, 0x93, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x31, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x11, 0x21, 0x35, 0x21, 0x15, 0x21, 0x02, 0x06, 0xfd, 0xe8, 0x01, 0x73, 0xfe, 0xd6, 0x02, 0xf9, 0xfe, 0xd6, 0x93, 0x04, 0xaf, 0x93, 0x93, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x04, 0x92, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x25, 0x09, 0x01, 0x07, 0x01, 0x33, 0x01, 0x33, 0x15, 0x03, 0x65, 0xfe, 0xdb, 0xfe, 0xdb, 0xe4, 0x01, 0xa1, 0xd0, 0x01, 0x6f, 0x7b, 0x93, 0x04, 0x82, 0xfb, 0x7e, 0x93, 0x05, 0xd5, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x92, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x25, 0x09, 0x01, 0x05, 0x35, 0x33, 0x01, 0x33, 0x01, 0x33, 0x15, 0x03, 0x65, 0xfe, 0xdb, 0xfe, 0xdb, 0xfe, 0xd3, 0x7b, 0x01, 0x6f, 0xd0, 0x01, 0x6f, 0x7b, 0x93, 0x04, 0x82, 0xfb, 0x7e, 0x93, 0x93, 0x05, 0x42, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x4a, 0x05, 0xd5, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x25, 0x09, 0x01, 0x05, 0x35, 0x33, 0x01, 0x33, 0x01, 0x03, 0x65, 0xfe, 0xdb, 0xfe, 0xdb, 0xfe, 0xd3, 0x7b, 0x01, 0x6f, 0xd0, 0x01, 0xa1, 0x93, 0x04, 0x82, 0xfb, 0x7e, 0x93, 0x93, 0x05, 0x42, 0xfa, 0x2b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x04, 0x59, 0x05, 0xd5, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x00, 0x21, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x35, 0x21, 0x35, 0x21, 0x11, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x15, 0x21, 0x15, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x01, 0xd0, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xfe, 0xd6, 0x01, 0xd0, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0x01, 0xe2, 0xfc, 0x9a, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x01, 0x86, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0xf3, 0x93, 0xfe, 0x7b, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0xf2, 0x93, 0x03, 0x22, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x59, 0x05, 0xd5, 0x00, 0x1e, 0x00, 0x2a, 0x00, 0x00, 0x23, 0x35, 0x21, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x35, 0x21, 0x35, 0x21, 0x11, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x15, 0x21, 0x15, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x12, 0x01, 0xe2, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xfe, 0xd6, 0x01, 0xd0, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0x01, 0xe2, 0xfc, 0x9a, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x93, 0xf3, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0xf3, 0x93, 0xfe, 0x7b, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0xf2, 0x93, 0x03, 0x22, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0xe1, 0x05, 0xd5, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x00, 0x23, 0x35, 0x21, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x35, 0x21, 0x35, 0x21, 0x11, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x11, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x12, 0x01, 0xe2, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xfe, 0xd6, 0x01, 0xd0, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0xfe, 0x7c, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x93, 0xf3, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0xf3, 0x93, 0xfe, 0x7b, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0xfe, 0x7b, 0x03, 0x22, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x03, 0xe3, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x33, 0x15, 0x02, 0x7e, 0xfe, 0xd6, 0xa6, 0x02, 0x76, 0xbe, 0x05, 0x42, 0xfe, 0xc5, 0x01, 0xce, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0xe3, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x33, 0x15, 0x12, 0x02, 0x90, 0xfe, 0xd6, 0xa6, 0x02, 0x76, 0xbe, 0x93, 0x04, 0xaf, 0xfe, 0xc5, 0x01, 0xce, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x24, 0x05, 0xd5, 0x00, 0x09, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x21, 0x11, 0x12, 0x02, 0x90, 0xfe, 0xd6, 0xa6, 0x02, 0x76, 0x93, 0x04, 0xaf, 0xfe, 0xc5, 0x01, 0xce, 0xfa, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0x00, 0x00, 0x03, 0xe3, 0x04, 0xe6, 0x00, 0x0b, 0x00, 0x00, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x15, 0x02, 0x7e, 0xfe, 0xd6, 0xa6, 0xa6, 0x01, 0xd0, 0xbe, 0x03, 0x4f, 0xfe, 0xfc, 0x02, 0x9b, 0xfe, 0xfc, 0xfc, 0xb1, 0x93, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0xe3, 0x04, 0xe6, 0x00, 0x0d, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x15, 0x12, 0x02, 0x90, 0xfe, 0xd6, 0xa6, 0xa6, 0x01, 0xd0, 0xbe, 0x93, 0x02, 0xbc, 0xfe, 0xfc, 0x02, 0x9b, 0xfe, 0xfc, 0xfc, 0xb1, 0x93, 0x00, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x03, 0x24, 0x04, 0xe6, 0x00, 0x0b, 0x00, 0x00, 0x23, 0x35, 0x21, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x12, 0x02, 0x90, 0xfe, 0xd6, 0xa6, 0xa6, 0x01, 0xd0, 0x93, 0x02, 0xbc, 0xfe, 0xfc, 0x02, 0x9b, 0xfe, 0xfc, 0xfc, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0xad, 0x00, 0x00, 0x03, 0xd5, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x11, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x15, 0x01, 0x54, 0x01, 0x1c, 0xfe, 0x3e, 0x01, 0xc2, 0xfe, 0x3e, 0x02, 0x67, 0xc0, 0x02, 0xde, 0xfd, 0xb5, 0x02, 0x4b, 0xfd, 0x22, 0x03, 0x71, 0x01, 0xd1, 0x93, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0xd5, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x35, 0x33, 0x11, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x33, 0x15, 0x01, 0x54, 0x01, 0x1c, 0xfd, 0x7e, 0xc0, 0x01, 0xc2, 0xfe, 0x3e, 0x02, 0x67, 0xc0, 0x02, 0xde, 0xfd, 0xb5, 0x02, 0x4b, 0xfd, 0x22, 0x93, 0x02, 0xde, 0x01, 0xd1, 0x93, 0xfa, 0xbe, 0x93, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0x16, 0x05, 0xd5, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x11, 0x21, 0x11, 0x01, 0x35, 0x33, 0x11, 0x21, 0x11, 0x21, 0x35, 0x21, 0x11, 0x01, 0x54, 0x01, 0x1c, 0xfd, 0x7e, 0xc0, 0x01, 0xc2, 0xfe, 0x3e, 0x02, 0x67, 0x02, 0xde, 0xfd, 0xb5, 0x02, 0x4b, 0xfd, 0x22, 0x93, 0x02, 0xde, 0x01, 0xd1, 0x93, 0xfa, 0x2b, 0x00, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x04, 0x59, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x26, 0x00, 0x00, 0x12, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x13, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x11, 0x33, 0x11, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x15, 0x21, 0x15, 0xf2, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x8c, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xa6, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0x01, 0xe2, 0x03, 0x22, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0xfc, 0x7e, 0x01, 0x86, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0x01, 0x86, 0xfe, 0x7b, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0xf2, 0x93, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x59, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x28, 0x00, 0x00, 0x12, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x01, 0x15, 0x21, 0x35, 0x21, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x11, 0x33, 0x11, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x15, 0xf2, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x03, 0x14, 0xfb, 0x96, 0x01, 0xe2, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xa6, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0x03, 0x22, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0xfd, 0x11, 0x93, 0x93, 0xf3, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0x01, 0x86, 0xfe, 0x7b, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0xf2, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0xe1, 0x05, 0xd5, 0x00, 0x0b, 0x00, 0x26, 0x00, 0x00, 0x12, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x13, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x11, 0x33, 0x11, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x11, 0x21, 0x35, 0xf2, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x8c, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xa6, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0xfd, 0x78, 0x03, 0x22, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0xfd, 0x11, 0xf3, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0x01, 0x86, 0xfe, 0x7b, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0xfe, 0x7b, 0x93, 0x00, 0x00, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x04, 0x59, 0x05, 0xd5, 0x00, 0x1e, 0x00, 0x2a, 0x00, 0x00, 0x21, 0x11, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x35, 0x21, 0x35, 0x21, 0x15, 0x21, 0x15, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x15, 0x21, 0x15, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x01, 0xd0, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xfe, 0xd6, 0x02, 0xfa, 0xfe, 0xd6, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0x01, 0xe2, 0xfc, 0x9a, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x01, 0x86, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0xf3, 0x93, 0x93, 0xf2, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0xf2, 0x93, 0x03, 0x22, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x59, 0x05, 0xd5, 0x00, 0x20, 0x00, 0x2c, 0x00, 0x00, 0x25, 0x15, 0x21, 0x35, 0x21, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x35, 0x21, 0x35, 0x21, 0x15, 0x21, 0x15, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x15, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x04, 0x58, 0xfb, 0x96, 0x01, 0xe2, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xfe, 0xd6, 0x02, 0xfa, 0xfe, 0xd6, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0xfe, 0x7c, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x93, 0x93, 0x93, 0xf3, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0xf3, 0x93, 0x93, 0xf2, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0xf2, 0x02, 0x8f, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0xe1, 0x05, 0xd5, 0x00, 0x1e, 0x00, 0x2a, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x35, 0x26, 0x27, 0x2e, 0x01, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x35, 0x21, 0x35, 0x21, 0x15, 0x21, 0x15, 0x16, 0x17, 0x1e, 0x01, 0x14, 0x06, 0x07, 0x06, 0x07, 0x00, 0x14, 0x1e, 0x01, 0x32, 0x3e, 0x01, 0x34, 0x2e, 0x01, 0x22, 0x06, 0x02, 0x76, 0xfd, 0x78, 0x01, 0xe2, 0x49, 0x43, 0x67, 0x77, 0x3c, 0x3e, 0x64, 0x43, 0x49, 0xfe, 0xd6, 0x02, 0xfa, 0xfe, 0xd6, 0x4f, 0x3e, 0x67, 0x77, 0x77, 0x67, 0x42, 0x4b, 0xfe, 0x7c, 0x52, 0x8c, 0xa6, 0x8d, 0x51, 0x51, 0x8d, 0xa6, 0x8c, 0x93, 0xf3, 0x0b, 0x1f, 0x31, 0xa6, 0xc6, 0x53, 0x56, 0x2f, 0x1f, 0x0b, 0xf3, 0x93, 0x93, 0xf2, 0x0d, 0x1e, 0x32, 0xa6, 0xc6, 0xa6, 0x31, 0x20, 0x0b, 0x01, 0x9d, 0x70, 0x5f, 0x38, 0x38, 0x5f, 0x70, 0x60, 0x38, 0x38, 0x00, 0xff, 0xff, 0xfd, 0x3a, 0x03, 0xfb, 0xff, 0x28, 0x06, 0x20, 0x10, 0x07, 0x02, 0x9c, 0xfc, 0x65, 0xff, 0x1a, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x02, 0x86, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x86, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0xca, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x02, 0x86, 0x05, 0xdd, 0x05, 0xd5, 0x12, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x86, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x01, 0x03, 0xc9, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x02, 0x86, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x86, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0xc9, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x02, 0x86, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x02, 0x86, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0xc9, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x02, 0x86, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x86, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0xc9, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x02, 0x86, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x86, 0x10, 0x27, 0x0b, 0xb3, 0x00, 0x00, 0x03, 0xc9, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x02, 0x86, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x86, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0xc9, 0x10, 0x07, 0x0b, 0xb3, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x00, 0x99, 0x02, 0x86, 0x05, 0xdc, 0x05, 0xd5, 0x12, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x02, 0x86, 0x10, 0x27, 0x0b, 0xb4, 0x00, 0x00, 0x03, 0xc9, 0x10, 0x07, 0x0b, 0xb4, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x01, 0x6e, 0x05, 0x18, 0x04, 0x99, 0x05, 0xe0, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x07, 0x23, 0x27, 0x23, 0x07, 0x23, 0x27, 0x23, 0x07, 0x23, 0x27, 0x04, 0x98, 0x5a, 0x2d, 0x2d, 0x9d, 0x2d, 0x2d, 0x2d, 0x9e, 0x2d, 0x2d, 0x5a, 0x05, 0xe0, 0xc8, 0x64, 0x64, 0x64, 0x64, 0xc8, 0x00, 0x00, 0x01, 0x00, 0xb4, 0xfe, 0x56, 0x05, 0x63, 0x05, 0xd5, 0x00, 0x0e, 0x00, 0x00, 0x21, 0x23, 0x11, 0x01, 0x23, 0x11, 0x33, 0x11, 0x01, 0x33, 0x11, 0x33, 0x15, 0x01, 0x23, 0x04, 0xae, 0xb0, 0xfd, 0xac, 0xf5, 0xb0, 0x02, 0x54, 0xf5, 0xb5, 0xfe, 0xb6, 0x78, 0x04, 0xe1, 0xfb, 0x1f, 0x05, 0xd5, 0xfb, 0x1f, 0x04, 0xe1, 0xfa, 0xd5, 0xaa, 0xfe, 0x56, 0x00, 0x00, 0x00, 0x01, 0x00, 0xad, 0xfe, 0x56, 0x04, 0xb3, 0x04, 0x60, 0x00, 0x0e, 0x00, 0x00, 0x21, 0x23, 0x11, 0x01, 0x23, 0x11, 0x33, 0x11, 0x01, 0x33, 0x11, 0x33, 0x15, 0x01, 0x23, 0x04, 0x0d, 0xa5, 0xfe, 0x1a, 0xd4, 0xa4, 0x01, 0xe6, 0xd5, 0xa5, 0xfe, 0xfb, 0x6e, 0x03, 0x83, 0xfc, 0x7d, 0x04, 0x60, 0xfc, 0x7f, 0x03, 0x81, 0xfc, 0x39, 0x99, 0xfe, 0x56, 0x00, 0x00, 0x00, 0x02, 0x00, 0x9c, 0xfe, 0x56, 0x03, 0xe9, 0x04, 0x7b, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x25, 0x35, 0x0e, 0x01, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x10, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x1e, 0x01, 0x33, 0x32, 0x36, 0x01, 0x03, 0x43, 0x3c, 0x9f, 0x6a, 0xad, 0xb4, 0xa5, 0x70, 0x6f, 0x87, 0x9b, 0xa6, 0xe5, 0xec, 0x57, 0x9b, 0x49, 0x49, 0x8e, 0x4a, 0xa3, 0xa2, 0xfe, 0xfa, 0x6a, 0x42, 0x66, 0x63, 0xf0, 0xe7, 0x02, 0xa6, 0xfd, 0x61, 0x9f, 0x9f, 0xbe, 0xa4, 0x02, 0x7b, 0xfc, 0x2b, 0xfe, 0xe2, 0xfe, 0xe9, 0x1d, 0x1e, 0xb3, 0x2c, 0x2a, 0xbd, 0x04, 0xd0, 0x00, 0x03, 0x00, 0x70, 0xfe, 0x90, 0x03, 0xda, 0x03, 0x52, 0x00, 0x20, 0x00, 0x2c, 0x00, 0x38, 0x00, 0x00, 0x01, 0x26, 0x27, 0x33, 0x16, 0x17, 0x16, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x03, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x01, 0xeb, 0x33, 0xa4, 0xcd, 0x57, 0x4a, 0x49, 0x4a, 0x28, 0x59, 0x44, 0x76, 0x84, 0x57, 0x54, 0xba, 0x29, 0x29, 0x5c, 0x5d, 0x68, 0x4c, 0x1d, 0x1f, 0x9b, 0x1f, 0x07, 0x08, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x39, 0x39, 0xa6, 0x39, 0x39, 0x39, 0x39, 0xa6, 0x39, 0x02, 0x3f, 0x7a, 0x99, 0x4e, 0x89, 0x86, 0x75, 0x49, 0x53, 0x2c, 0xb8, 0x82, 0x80, 0x21, 0x07, 0x26, 0xb8, 0x2a, 0x09, 0x31, 0x70, 0x1b, 0x2a, 0x44, 0xfd, 0xab, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0x00, 0x02, 0x00, 0x70, 0xfe, 0xa2, 0x03, 0xda, 0x03, 0x52, 0x00, 0x20, 0x00, 0x24, 0x00, 0x00, 0x01, 0x26, 0x27, 0x33, 0x16, 0x17, 0x16, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x03, 0x33, 0x15, 0x23, 0x01, 0xeb, 0x33, 0xa4, 0xcd, 0x57, 0x4a, 0x49, 0x4a, 0x28, 0x59, 0x44, 0x76, 0x84, 0x57, 0x54, 0xba, 0x29, 0x29, 0x5c, 0x5d, 0x68, 0x4c, 0x1d, 0x1f, 0x9b, 0x1f, 0x07, 0xa3, 0x88, 0x88, 0x02, 0x3f, 0x7a, 0x99, 0x4e, 0x89, 0x86, 0x75, 0x49, 0x53, 0x2c, 0xb8, 0x82, 0x80, 0x21, 0x07, 0x26, 0xb8, 0x2a, 0x09, 0x31, 0x70, 0x1b, 0x2a, 0x44, 0xfd, 0x77, 0x96, 0x00, 0x04, 0x00, 0x70, 0xfe, 0xa2, 0x03, 0xda, 0x05, 0xf7, 0x00, 0x20, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x00, 0x01, 0x26, 0x27, 0x33, 0x16, 0x17, 0x16, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x03, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x07, 0x06, 0x17, 0x2b, 0x01, 0x35, 0x33, 0x11, 0x33, 0x11, 0x36, 0x37, 0x36, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x03, 0x33, 0x15, 0x23, 0x01, 0xeb, 0x33, 0xa4, 0xcd, 0x57, 0x4a, 0x49, 0x4a, 0x28, 0x59, 0x44, 0x76, 0x84, 0x57, 0x54, 0xba, 0x29, 0x29, 0x5c, 0x5d, 0x68, 0x4c, 0x1d, 0x1f, 0x9b, 0x1f, 0x07, 0xba, 0x32, 0x46, 0x14, 0x2f, 0x1b, 0x01, 0x40, 0x2e, 0x15, 0x9d, 0x65, 0x49, 0x5c, 0x20, 0x5e, 0x38, 0x3f, 0x3b, 0x3a, 0x30, 0x98, 0x88, 0x88, 0x02, 0x3f, 0x7a, 0x99, 0x4e, 0x89, 0x86, 0x75, 0x49, 0x53, 0x2c, 0xb8, 0x82, 0x80, 0x21, 0x07, 0x26, 0xb8, 0x2a, 0x09, 0x31, 0x70, 0x1b, 0x2a, 0x44, 0x02, 0xa7, 0x0d, 0x21, 0x15, 0x20, 0x10, 0x01, 0x1c, 0x15, 0xa8, 0x65, 0x01, 0x8f, 0xfe, 0xbf, 0x49, 0x28, 0x18, 0x1a, 0x19, 0x52, 0x5b, 0x32, 0x2a, 0xfb, 0x35, 0x96, 0x00, 0x00, 0x00, 0x04, 0x00, 0x70, 0xff, 0xda, 0x03, 0xda, 0x05, 0x78, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x26, 0x27, 0x33, 0x16, 0x17, 0x16, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x03, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0xeb, 0x33, 0xa4, 0xcd, 0x57, 0x4a, 0x49, 0x4a, 0x28, 0x59, 0x44, 0x76, 0x84, 0x57, 0x54, 0xba, 0x29, 0x29, 0x5c, 0x5d, 0x68, 0x4c, 0x1d, 0x1f, 0x9b, 0x1f, 0x07, 0xcf, 0x86, 0x86, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x02, 0x3f, 0x7a, 0x99, 0x4e, 0x89, 0x86, 0x75, 0x49, 0x53, 0x2c, 0xb8, 0x82, 0x80, 0x21, 0x07, 0x26, 0xb8, 0x2a, 0x09, 0x31, 0x70, 0x1b, 0x2a, 0x44, 0x02, 0xbd, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x05, 0x00, 0x70, 0xff, 0xda, 0x03, 0xda, 0x05, 0xaa, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x00, 0x01, 0x26, 0x27, 0x33, 0x16, 0x17, 0x16, 0x15, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x03, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x07, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x01, 0xeb, 0x33, 0xa4, 0xcd, 0x57, 0x4a, 0x49, 0x4a, 0x28, 0x59, 0x44, 0x76, 0x84, 0x57, 0x54, 0xba, 0x29, 0x29, 0x5c, 0x5d, 0x68, 0x4c, 0x1d, 0x1f, 0x9b, 0x1f, 0x07, 0x5f, 0x87, 0x87, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x87, 0x87, 0x02, 0x3f, 0x7a, 0x99, 0x4e, 0x89, 0x86, 0x75, 0x49, 0x53, 0x2c, 0xb8, 0x82, 0x80, 0x21, 0x07, 0x26, 0xb8, 0x2a, 0x09, 0x31, 0x70, 0x1b, 0x2a, 0x44, 0x02, 0xef, 0x96, 0x01, 0x90, 0x96, 0x64, 0x96, 0x01, 0x90, 0x96, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xb3, 0xfe, 0x0c, 0x04, 0x0b, 0x02, 0x26, 0x00, 0x18, 0x00, 0x24, 0x00, 0x30, 0x00, 0x00, 0x01, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x02, 0x07, 0x04, 0x21, 0x35, 0x20, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x13, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x02, 0x39, 0xa5, 0x1b, 0x03, 0x09, 0x42, 0x26, 0x5b, 0x43, 0x75, 0x75, 0x2d, 0x3d, 0xe2, 0xff, 0x00, 0xfe, 0xdf, 0x01, 0x11, 0xb7, 0xc4, 0x20, 0x08, 0xd0, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x38, 0x3a, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x3a, 0x02, 0x26, 0x70, 0x1e, 0x67, 0x4d, 0x2c, 0xb8, 0x3e, 0xfe, 0xea, 0x85, 0x97, 0xb8, 0x80, 0x8a, 0xd0, 0x3a, 0x48, 0x7e, 0xfd, 0x4a, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0x00, 0x02, 0xff, 0xb3, 0xfe, 0x0c, 0x04, 0x0b, 0x02, 0x26, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x02, 0x07, 0x04, 0x21, 0x35, 0x20, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x13, 0x33, 0x15, 0x23, 0x02, 0x39, 0xa5, 0x1b, 0x03, 0x09, 0x42, 0x26, 0x5b, 0x43, 0x75, 0x75, 0x2d, 0x3d, 0xe2, 0xff, 0x00, 0xfe, 0xdf, 0x01, 0x11, 0xb7, 0xc4, 0x20, 0x08, 0x7a, 0x87, 0x87, 0x02, 0x26, 0x70, 0x1e, 0x67, 0x4d, 0x2c, 0xb8, 0x3e, 0xfe, 0xea, 0x85, 0x97, 0xb8, 0x80, 0x8a, 0xd0, 0x3a, 0x48, 0x7e, 0xfd, 0x40, 0x96, 0x00, 0x03, 0xff, 0xb3, 0xfe, 0x0c, 0x04, 0x0b, 0x02, 0x26, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x02, 0x07, 0x04, 0x21, 0x35, 0x20, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x05, 0x33, 0x15, 0x23, 0x01, 0x33, 0x15, 0x23, 0x02, 0x39, 0xa5, 0x1b, 0x03, 0x09, 0x42, 0x26, 0x5b, 0x43, 0x75, 0x75, 0x2d, 0x3d, 0xe2, 0xff, 0x00, 0xfe, 0xdf, 0x01, 0x11, 0xb7, 0xc4, 0x20, 0x08, 0xfe, 0x3a, 0x87, 0x87, 0x02, 0x40, 0x87, 0x87, 0x02, 0x26, 0x70, 0x1e, 0x67, 0x4d, 0x2c, 0xb8, 0x3e, 0xfe, 0xea, 0x85, 0x97, 0xb8, 0x80, 0x8a, 0xd0, 0x3a, 0x48, 0x7e, 0xe0, 0x96, 0xfe, 0xb6, 0x96, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xb3, 0xfe, 0x0c, 0x04, 0x0b, 0x03, 0xb6, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x01, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x02, 0x07, 0x04, 0x21, 0x35, 0x20, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x02, 0x39, 0xa5, 0x1b, 0x03, 0x09, 0x42, 0x26, 0x5b, 0x43, 0x75, 0x75, 0x2d, 0x3d, 0xe2, 0xff, 0x00, 0xfe, 0xdf, 0x01, 0x11, 0xb7, 0xc4, 0x20, 0x08, 0x3b, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x02, 0x26, 0x70, 0x1e, 0x67, 0x4d, 0x2c, 0xb8, 0x3e, 0xfe, 0xea, 0x85, 0x97, 0xb8, 0x80, 0x8a, 0xd0, 0x3a, 0x48, 0x7e, 0x02, 0x18, 0x96, 0x96, 0x96, 0x00, 0x00, 0x05, 0xff, 0xb3, 0xfe, 0x0c, 0x04, 0x0b, 0x04, 0xb0, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x00, 0x01, 0x33, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x02, 0x07, 0x04, 0x21, 0x35, 0x20, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x13, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x07, 0x33, 0x15, 0x23, 0x11, 0x33, 0x15, 0x23, 0x02, 0x39, 0xa5, 0x1b, 0x03, 0x09, 0x42, 0x26, 0x5b, 0x43, 0x75, 0x75, 0x2d, 0x3d, 0xe2, 0xff, 0x00, 0xfe, 0xdf, 0x01, 0x11, 0xb7, 0xc4, 0x20, 0x08, 0x3b, 0x87, 0x87, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x87, 0x87, 0x02, 0x26, 0x70, 0x1e, 0x67, 0x4d, 0x2c, 0xb8, 0x3e, 0xfe, 0xea, 0x85, 0x97, 0xb8, 0x80, 0x8a, 0xd0, 0x3a, 0x48, 0x7e, 0x02, 0x18, 0x96, 0x01, 0x90, 0x96, 0x64, 0x96, 0x01, 0x90, 0x96, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x75, 0xfe, 0x0c, 0x09, 0x40, 0x03, 0xb6, 0x00, 0x46, 0x00, 0x4a, 0x00, 0x4e, 0x00, 0x00, 0x25, 0x16, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x33, 0x32, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x26, 0x27, 0x26, 0x11, 0x34, 0x37, 0x33, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x2f, 0x01, 0x33, 0x17, 0x16, 0x17, 0x16, 0x13, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x05, 0x26, 0x46, 0x2b, 0x21, 0xa6, 0x11, 0x3a, 0x63, 0x7f, 0xa6, 0x4b, 0x27, 0x59, 0x44, 0x75, 0x83, 0x6a, 0x3d, 0x62, 0x21, 0x1d, 0x42, 0x2b, 0x7c, 0x10, 0x2c, 0x55, 0x3a, 0x32, 0x7b, 0x24, 0x15, 0x4c, 0x77, 0xae, 0x48, 0x6c, 0x73, 0x63, 0xf7, 0x5f, 0xa5, 0x61, 0x01, 0x01, 0x84, 0x56, 0x48, 0x59, 0x55, 0x6d, 0x55, 0x39, 0x01, 0x01, 0x0e, 0x3a, 0xa6, 0x20, 0x0f, 0x19, 0x34, 0x19, 0x86, 0x86, 0x86, 0x88, 0x88, 0xb5, 0x02, 0x7c, 0x5f, 0xca, 0xcd, 0x32, 0xa9, 0x01, 0x18, 0x01, 0x26, 0xfe, 0xaa, 0x61, 0x53, 0x2c, 0xb8, 0x60, 0x5b, 0x19, 0x09, 0x19, 0x46, 0x7b, 0x9f, 0x1e, 0x14, 0x02, 0x02, 0x3c, 0xb3, 0x6b, 0xaa, 0x3e, 0x1a, 0x01, 0x1c, 0x47, 0x01, 0x48, 0xf6, 0xb4, 0xce, 0xdc, 0xb3, 0x26, 0x18, 0x25, 0x30, 0x9e, 0x6c, 0x8e, 0x7d, 0x3d, 0xea, 0x9c, 0x4a, 0x3c, 0x7e, 0x02, 0xfe, 0x96, 0xfc, 0x18, 0x96, 0x00, 0x03, 0xff, 0xee, 0xfe, 0xa2, 0x05, 0x70, 0x03, 0xe8, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x00, 0x25, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x01, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x01, 0x5a, 0x27, 0x33, 0x44, 0x59, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x27, 0x27, 0x5e, 0x62, 0x27, 0x22, 0xa5, 0x11, 0x3a, 0x63, 0x80, 0xa5, 0x52, 0x44, 0x5c, 0x21, 0x20, 0x38, 0x32, 0x7b, 0x10, 0x2b, 0x57, 0x3d, 0x3a, 0x59, 0x41, 0x36, 0x01, 0x3c, 0x86, 0x86, 0x86, 0x88, 0x88, 0x8a, 0x3b, 0x21, 0x2e, 0xb8, 0x2c, 0x50, 0x64, 0xc0, 0x9c, 0x40, 0x64, 0x63, 0x7a, 0x67, 0xc2, 0xcd, 0x32, 0xaa, 0x01, 0x02, 0x01, 0x16, 0x01, 0x26, 0xfe, 0xaa, 0xc7, 0x71, 0x5c, 0x18, 0x09, 0x19, 0x3d, 0x84, 0x9c, 0x21, 0x18, 0x31, 0x28, 0x03, 0xa7, 0x96, 0xfb, 0xe6, 0x96, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0xfe, 0xa2, 0x06, 0x7f, 0x03, 0xe8, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x00, 0x05, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x01, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x04, 0x7d, 0x21, 0x20, 0x38, 0x32, 0x7b, 0x10, 0x2b, 0x57, 0x3d, 0x3a, 0x59, 0x41, 0x36, 0x24, 0x27, 0x33, 0x44, 0x59, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x27, 0x27, 0x5e, 0x62, 0x27, 0x22, 0xa5, 0x11, 0x3a, 0x63, 0x80, 0xa5, 0x4b, 0x28, 0x59, 0x43, 0x75, 0x82, 0x6a, 0x3e, 0xfd, 0xdb, 0x86, 0x86, 0x86, 0x88, 0x88, 0x14, 0x09, 0x19, 0x3d, 0x84, 0x9c, 0x21, 0x18, 0x31, 0x28, 0x49, 0x3b, 0x21, 0x2e, 0xb8, 0x2c, 0x50, 0x64, 0xc0, 0x9c, 0x40, 0x64, 0x63, 0x7a, 0x67, 0xc2, 0xcd, 0x32, 0xaa, 0x01, 0x02, 0x01, 0x16, 0x01, 0x26, 0xfe, 0xaa, 0x61, 0x53, 0x2c, 0xb8, 0x60, 0x5a, 0x03, 0xe2, 0x96, 0xfb, 0xe6, 0x96, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x75, 0xfe, 0x0c, 0x09, 0x40, 0x02, 0xee, 0x00, 0x46, 0x00, 0x4a, 0x00, 0x4e, 0x00, 0x52, 0x00, 0x00, 0x25, 0x16, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x33, 0x32, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x26, 0x27, 0x26, 0x11, 0x34, 0x37, 0x33, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x2f, 0x01, 0x33, 0x17, 0x16, 0x17, 0x16, 0x13, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x05, 0x26, 0x46, 0x2b, 0x21, 0xa6, 0x11, 0x3a, 0x63, 0x7f, 0xa6, 0x4b, 0x27, 0x59, 0x44, 0x75, 0x83, 0x6a, 0x3d, 0x62, 0x21, 0x1d, 0x42, 0x2b, 0x7c, 0x10, 0x2c, 0x55, 0x3a, 0x32, 0x7b, 0x24, 0x15, 0x4c, 0x77, 0xae, 0x48, 0x6c, 0x73, 0x63, 0xf7, 0x5f, 0xa5, 0x61, 0x01, 0x01, 0x84, 0x56, 0x48, 0x59, 0x55, 0x6d, 0x55, 0x39, 0x01, 0x01, 0x0e, 0x3a, 0xa6, 0x20, 0x0f, 0x19, 0x34, 0x9f, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb5, 0x02, 0x7c, 0x5f, 0xca, 0xcd, 0x32, 0xa9, 0x01, 0x18, 0x01, 0x26, 0xfe, 0xaa, 0x61, 0x53, 0x2c, 0xb8, 0x60, 0x5b, 0x19, 0x09, 0x19, 0x46, 0x7b, 0x9f, 0x1e, 0x14, 0x02, 0x02, 0x3c, 0xb3, 0x6b, 0xaa, 0x3e, 0x1a, 0x01, 0x1c, 0x47, 0x01, 0x48, 0xf6, 0xb4, 0xce, 0xdc, 0xb3, 0x26, 0x18, 0x25, 0x30, 0x9e, 0x6c, 0x8e, 0x7d, 0x3d, 0xea, 0x9c, 0x4a, 0x3c, 0x7e, 0xfd, 0xea, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x04, 0xff, 0xee, 0xfe, 0x0c, 0x05, 0x70, 0x02, 0xee, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x3d, 0x00, 0x00, 0x25, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x01, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x5a, 0x27, 0x33, 0x44, 0x59, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x27, 0x27, 0x5e, 0x62, 0x27, 0x22, 0xa5, 0x11, 0x3a, 0x63, 0x80, 0xa5, 0x52, 0x44, 0x5c, 0x21, 0x20, 0x38, 0x32, 0x7b, 0x10, 0x2b, 0x57, 0x3d, 0x3a, 0x59, 0x41, 0x36, 0x01, 0xc2, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x8a, 0x3b, 0x21, 0x2e, 0xb8, 0x2c, 0x50, 0x64, 0xc0, 0x9c, 0x40, 0x64, 0x63, 0x7a, 0x67, 0xc2, 0xcd, 0x32, 0xaa, 0x01, 0x02, 0x01, 0x16, 0x01, 0x26, 0xfe, 0xaa, 0xc7, 0x71, 0x5c, 0x18, 0x09, 0x19, 0x3d, 0x84, 0x9c, 0x21, 0x18, 0x31, 0x28, 0xfe, 0x61, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x04, 0xff, 0xee, 0xfe, 0x0c, 0x06, 0x7f, 0x02, 0xee, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x00, 0x05, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x01, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x04, 0x7d, 0x21, 0x20, 0x38, 0x32, 0x7b, 0x10, 0x2b, 0x57, 0x3d, 0x3a, 0x59, 0x41, 0x36, 0x24, 0x27, 0x33, 0x44, 0x59, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x27, 0x27, 0x5e, 0x62, 0x27, 0x22, 0xa5, 0x11, 0x3a, 0x63, 0x80, 0xa5, 0x4b, 0x28, 0x59, 0x43, 0x75, 0x82, 0x6a, 0x3e, 0xfe, 0x61, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x14, 0x09, 0x19, 0x3d, 0x84, 0x9c, 0x21, 0x18, 0x31, 0x28, 0x49, 0x3b, 0x21, 0x2e, 0xb8, 0x2c, 0x50, 0x64, 0xc0, 0x9c, 0x40, 0x64, 0x63, 0x7a, 0x67, 0xc2, 0xcd, 0x32, 0xaa, 0x01, 0x02, 0x01, 0x16, 0x01, 0x26, 0xfe, 0xaa, 0x61, 0x53, 0x2c, 0xb8, 0x60, 0x5a, 0xfe, 0x9c, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x07, 0x00, 0x75, 0xfe, 0x0c, 0x09, 0x40, 0x04, 0xb0, 0x00, 0x46, 0x00, 0x4a, 0x00, 0x4e, 0x00, 0x52, 0x00, 0x56, 0x00, 0x5a, 0x00, 0x5e, 0x00, 0x00, 0x25, 0x16, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x33, 0x32, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x26, 0x27, 0x26, 0x11, 0x34, 0x37, 0x33, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x2f, 0x01, 0x33, 0x17, 0x16, 0x17, 0x16, 0x13, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x05, 0x26, 0x46, 0x2b, 0x21, 0xa6, 0x11, 0x3a, 0x63, 0x7f, 0xa6, 0x4b, 0x27, 0x59, 0x44, 0x75, 0x83, 0x6a, 0x3d, 0x62, 0x21, 0x1d, 0x42, 0x2b, 0x7c, 0x10, 0x2c, 0x55, 0x3a, 0x32, 0x7b, 0x24, 0x15, 0x4c, 0x77, 0xae, 0x48, 0x6c, 0x73, 0x63, 0xf7, 0x5f, 0xa5, 0x61, 0x01, 0x01, 0x84, 0x56, 0x48, 0x59, 0x55, 0x6d, 0x55, 0x39, 0x01, 0x01, 0x0e, 0x3a, 0xa6, 0x20, 0x0f, 0x19, 0x34, 0x19, 0x86, 0x86, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xf7, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb5, 0x02, 0x7c, 0x5f, 0xca, 0xcd, 0x32, 0xa9, 0x01, 0x18, 0x01, 0x26, 0xfe, 0xaa, 0x61, 0x53, 0x2c, 0xb8, 0x60, 0x5b, 0x19, 0x09, 0x19, 0x46, 0x7b, 0x9f, 0x1e, 0x14, 0x02, 0x02, 0x3c, 0xb3, 0x6b, 0xaa, 0x3e, 0x1a, 0x01, 0x1c, 0x47, 0x01, 0x48, 0xf6, 0xb4, 0xce, 0xdc, 0xb3, 0x26, 0x18, 0x25, 0x30, 0x9e, 0x6c, 0x8e, 0x7d, 0x3d, 0xea, 0x9c, 0x4a, 0x3c, 0x7e, 0x03, 0xf8, 0x96, 0x64, 0x96, 0x96, 0x96, 0xfb, 0x82, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xee, 0xfe, 0x0c, 0x05, 0x70, 0x04, 0xb0, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x3d, 0x00, 0x41, 0x00, 0x45, 0x00, 0x49, 0x00, 0x00, 0x25, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x5a, 0x27, 0x33, 0x44, 0x59, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x27, 0x27, 0x5e, 0x62, 0x27, 0x22, 0xa5, 0x11, 0x3a, 0x63, 0x80, 0xa5, 0x52, 0x44, 0x5c, 0x21, 0x20, 0x38, 0x32, 0x7b, 0x10, 0x2b, 0x57, 0x3d, 0x3a, 0x59, 0x41, 0x36, 0x01, 0x3c, 0x86, 0x86, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xf7, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x8a, 0x3b, 0x21, 0x2e, 0xb8, 0x2c, 0x50, 0x64, 0xc0, 0x9c, 0x40, 0x64, 0x63, 0x7a, 0x67, 0xc2, 0xcd, 0x32, 0xaa, 0x01, 0x02, 0x01, 0x16, 0x01, 0x26, 0xfe, 0xaa, 0xc7, 0x71, 0x5c, 0x18, 0x09, 0x19, 0x3d, 0x84, 0x9c, 0x21, 0x18, 0x31, 0x28, 0x04, 0x6f, 0x96, 0x64, 0x96, 0x96, 0x96, 0xfb, 0x82, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x07, 0xff, 0xee, 0xfe, 0x0c, 0x06, 0x7f, 0x04, 0xb0, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x48, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x00, 0x05, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x33, 0x14, 0x17, 0x16, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x04, 0x7d, 0x21, 0x20, 0x38, 0x32, 0x7b, 0x10, 0x2b, 0x57, 0x3d, 0x3a, 0x59, 0x41, 0x36, 0x24, 0x27, 0x33, 0x44, 0x59, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x27, 0x27, 0x5e, 0x62, 0x27, 0x22, 0xa5, 0x11, 0x3a, 0x63, 0x80, 0xa5, 0x4b, 0x28, 0x59, 0x43, 0x75, 0x82, 0x6a, 0x3e, 0xfd, 0xdb, 0x86, 0x86, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xf7, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x14, 0x09, 0x19, 0x3d, 0x84, 0x9c, 0x21, 0x18, 0x31, 0x28, 0x49, 0x3b, 0x21, 0x2e, 0xb8, 0x2c, 0x50, 0x64, 0xc0, 0x9c, 0x40, 0x64, 0x63, 0x7a, 0x67, 0xc2, 0xcd, 0x32, 0xaa, 0x01, 0x02, 0x01, 0x16, 0x01, 0x26, 0xfe, 0xaa, 0x61, 0x53, 0x2c, 0xb8, 0x60, 0x5a, 0x04, 0xaa, 0x96, 0x64, 0x96, 0x96, 0x96, 0xfb, 0x82, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x04, 0x00, 0x75, 0xfe, 0x0c, 0x08, 0xe5, 0x02, 0xe5, 0x00, 0x3c, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x51, 0x00, 0x00, 0x21, 0x23, 0x22, 0x27, 0x26, 0x35, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x26, 0x27, 0x26, 0x11, 0x34, 0x37, 0x33, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x33, 0x06, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x2f, 0x01, 0x06, 0x03, 0x22, 0x07, 0x06, 0x07, 0x33, 0x32, 0x37, 0x36, 0x27, 0x26, 0x27, 0x26, 0x01, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x05, 0xd0, 0xf9, 0x22, 0x2f, 0x28, 0x43, 0x4f, 0xd6, 0x48, 0x6c, 0x73, 0x63, 0xf7, 0x5f, 0xa5, 0x61, 0x01, 0x01, 0x84, 0x56, 0x48, 0x5c, 0x52, 0x92, 0x27, 0x1d, 0x23, 0x9a, 0x01, 0x0d, 0x09, 0x24, 0x67, 0x6f, 0x61, 0x85, 0x40, 0x50, 0x70, 0x57, 0xa8, 0x26, 0x0d, 0x0e, 0x37, 0x4a, 0x43, 0x75, 0x76, 0x5d, 0x19, 0xb7, 0x10, 0x45, 0x71, 0x98, 0x82, 0xa8, 0xd6, 0x74, 0xa8, 0x01, 0x02, 0x7b, 0x21, 0xfe, 0xe6, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x1e, 0x1a, 0x10, 0xba, 0x80, 0x9b, 0x4d, 0x1a, 0x01, 0x1c, 0x47, 0x01, 0x48, 0xf6, 0xb4, 0xce, 0xdc, 0xb3, 0x26, 0x18, 0x25, 0x44, 0x8a, 0x6c, 0x7f, 0x93, 0x8a, 0x0f, 0x37, 0x28, 0x32, 0x92, 0x6c, 0x5e, 0x46, 0x22, 0x01, 0x02, 0x25, 0x47, 0xe9, 0x4d, 0x46, 0x0c, 0x0b, 0x2c, 0xb8, 0x5c, 0x1a, 0x76, 0x02, 0x37, 0x51, 0x6c, 0xc2, 0x3f, 0x5b, 0x46, 0x87, 0x13, 0x05, 0xfd, 0x01, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0xee, 0xfe, 0xa2, 0x05, 0x94, 0x02, 0xe5, 0x00, 0x0c, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x36, 0x00, 0x00, 0x01, 0x06, 0x07, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x03, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x16, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x05, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x6e, 0x97, 0x82, 0xa8, 0xd6, 0x73, 0xa8, 0x7d, 0x21, 0x2c, 0x44, 0xa8, 0xf8, 0x43, 0x46, 0x3a, 0x23, 0x5c, 0x9b, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x10, 0x28, 0x5b, 0x56, 0x89, 0x82, 0x44, 0x4c, 0x68, 0x60, 0xa7, 0xa5, 0xb6, 0xfe, 0xc5, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x01, 0xe6, 0x6c, 0xc2, 0x3f, 0x5b, 0x46, 0x87, 0x13, 0x05, 0xfd, 0xc9, 0x2a, 0x23, 0x3d, 0x8a, 0xb8, 0x2c, 0x50, 0x64, 0x72, 0x4e, 0x18, 0x50, 0x32, 0x86, 0x54, 0x89, 0x3f, 0x21, 0x27, 0x44, 0xec, 0xa9, 0x6d, 0x78, 0xc8, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0xee, 0xfe, 0xa2, 0x06, 0x51, 0x02, 0xe5, 0x00, 0x2b, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x00, 0x21, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x16, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x2f, 0x01, 0x06, 0x03, 0x06, 0x07, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x03, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x3c, 0xfc, 0x43, 0x46, 0x3a, 0x23, 0x5c, 0x9b, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x10, 0x28, 0x5b, 0x56, 0x89, 0x82, 0x44, 0x4c, 0x66, 0x62, 0xab, 0x26, 0x0d, 0x0e, 0x37, 0x4a, 0x43, 0x75, 0x75, 0x5d, 0x19, 0xb8, 0xca, 0x97, 0x82, 0xa8, 0xd6, 0x73, 0xa8, 0x7d, 0x21, 0x2c, 0x44, 0xe3, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x2a, 0x23, 0x3d, 0x8a, 0xb8, 0x2c, 0x50, 0x64, 0x72, 0x4e, 0x18, 0x50, 0x32, 0x86, 0x54, 0x89, 0x3f, 0x21, 0x27, 0x44, 0xec, 0x4b, 0x48, 0x0c, 0x0b, 0x2c, 0xb8, 0x5c, 0x1a, 0x76, 0x01, 0xe6, 0x6c, 0xc2, 0x3f, 0x5b, 0x46, 0x87, 0x13, 0x05, 0xfd, 0x01, 0x96, 0x96, 0x96, 0x00, 0x05, 0x00, 0x75, 0xfe, 0x0c, 0x08, 0xe5, 0x04, 0xb0, 0x00, 0x3c, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x51, 0x00, 0x55, 0x00, 0x00, 0x21, 0x23, 0x22, 0x27, 0x26, 0x35, 0x14, 0x07, 0x06, 0x07, 0x06, 0x23, 0x26, 0x27, 0x26, 0x11, 0x34, 0x37, 0x33, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x33, 0x06, 0x17, 0x16, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x2f, 0x01, 0x06, 0x03, 0x22, 0x07, 0x06, 0x07, 0x33, 0x32, 0x37, 0x36, 0x27, 0x26, 0x27, 0x26, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x05, 0xd0, 0xf9, 0x22, 0x2f, 0x28, 0x43, 0x4f, 0xd6, 0x48, 0x6c, 0x73, 0x63, 0xf7, 0x5f, 0xa5, 0x61, 0x01, 0x01, 0x84, 0x56, 0x48, 0x5c, 0x52, 0x92, 0x27, 0x1d, 0x23, 0x9a, 0x01, 0x0d, 0x09, 0x24, 0x67, 0x6f, 0x61, 0x85, 0x40, 0x50, 0x70, 0x57, 0xa8, 0x26, 0x0d, 0x0e, 0x37, 0x4a, 0x43, 0x75, 0x76, 0x5d, 0x19, 0xb7, 0x10, 0x45, 0x71, 0x98, 0x82, 0xa8, 0xd6, 0x74, 0xa8, 0x01, 0x02, 0x7b, 0x21, 0xfd, 0x95, 0x86, 0x86, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x1e, 0x1a, 0x10, 0xba, 0x80, 0x9b, 0x4d, 0x1a, 0x01, 0x1c, 0x47, 0x01, 0x48, 0xf6, 0xb4, 0xce, 0xdc, 0xb3, 0x26, 0x18, 0x25, 0x44, 0x8a, 0x6c, 0x7f, 0x93, 0x8a, 0x0f, 0x37, 0x28, 0x32, 0x92, 0x6c, 0x5e, 0x46, 0x22, 0x01, 0x02, 0x25, 0x47, 0xe9, 0x4d, 0x46, 0x0c, 0x0b, 0x2c, 0xb8, 0x5c, 0x1a, 0x76, 0x02, 0x37, 0x51, 0x6c, 0xc2, 0x3f, 0x5b, 0x46, 0x87, 0x13, 0x05, 0x02, 0x79, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x05, 0xff, 0xee, 0x00, 0x00, 0x05, 0x94, 0x04, 0xb0, 0x00, 0x0c, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3a, 0x00, 0x00, 0x01, 0x06, 0x07, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x03, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x16, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x6e, 0x97, 0x82, 0xa8, 0xd6, 0x73, 0xa8, 0x7d, 0x21, 0x2c, 0x44, 0xa8, 0xf8, 0x43, 0x46, 0x3a, 0x23, 0x5c, 0x9b, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x10, 0x28, 0x5b, 0x56, 0x89, 0x82, 0x44, 0x4c, 0x68, 0x60, 0xa7, 0xa5, 0xb6, 0xfd, 0xa0, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x01, 0xe6, 0x6c, 0xc2, 0x3f, 0x5b, 0x46, 0x87, 0x13, 0x05, 0xfd, 0xc9, 0x2a, 0x23, 0x3d, 0x8a, 0xb8, 0x2c, 0x50, 0x64, 0x72, 0x4e, 0x18, 0x50, 0x32, 0x86, 0x54, 0x89, 0x3f, 0x21, 0x27, 0x44, 0xec, 0xa9, 0x6d, 0x78, 0x04, 0xb0, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0xee, 0x00, 0x00, 0x06, 0x51, 0x04, 0xb0, 0x00, 0x2b, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x00, 0x21, 0x23, 0x22, 0x27, 0x26, 0x27, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x3d, 0x01, 0x33, 0x15, 0x14, 0x16, 0x17, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x2f, 0x01, 0x06, 0x03, 0x06, 0x07, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x23, 0x22, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x3c, 0xfc, 0x43, 0x46, 0x3a, 0x23, 0x5c, 0x9b, 0x75, 0x44, 0x59, 0x27, 0x48, 0xa6, 0x10, 0x28, 0x5b, 0x56, 0x89, 0x82, 0x44, 0x4c, 0x66, 0x62, 0xab, 0x26, 0x0d, 0x0e, 0x37, 0x4a, 0x43, 0x75, 0x75, 0x5d, 0x19, 0xb8, 0xca, 0x97, 0x82, 0xa8, 0xd6, 0x73, 0xa8, 0x7d, 0x21, 0x2c, 0x44, 0xfd, 0xf8, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x2a, 0x23, 0x3d, 0x8a, 0xb8, 0x2c, 0x50, 0x64, 0x72, 0x4e, 0x18, 0x50, 0x32, 0x86, 0x54, 0x89, 0x3f, 0x21, 0x27, 0x44, 0xec, 0x4b, 0x48, 0x0c, 0x0b, 0x2c, 0xb8, 0x5c, 0x1a, 0x76, 0x01, 0xe6, 0x6c, 0xc2, 0x3f, 0x5b, 0x46, 0x87, 0x13, 0x05, 0x02, 0x79, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x05, 0x00, 0x81, 0x00, 0x00, 0x06, 0xe8, 0x06, 0x14, 0x00, 0x1c, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x00, 0x29, 0x02, 0x35, 0x21, 0x11, 0x33, 0x11, 0x12, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x2f, 0x01, 0x06, 0x25, 0x33, 0x32, 0x37, 0x36, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x13, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0xd3, 0xfd, 0xf9, 0xfe, 0xb6, 0x01, 0x4a, 0xa6, 0xc3, 0xf8, 0x53, 0x3d, 0x69, 0x5f, 0xa9, 0x26, 0x0d, 0x0e, 0x37, 0x4a, 0x44, 0x75, 0x76, 0x5d, 0x19, 0xb8, 0xfe, 0x1f, 0xa8, 0xd5, 0x74, 0xa9, 0x01, 0x02, 0x7b, 0x22, 0x2b, 0x48, 0x6e, 0x9f, 0x32, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb8, 0x05, 0x5c, 0xfb, 0x0e, 0x01, 0x3f, 0x63, 0x21, 0x27, 0x45, 0xeb, 0x4d, 0x46, 0x0c, 0x0b, 0x2c, 0xb8, 0x5c, 0x1a, 0x76, 0xb8, 0x3f, 0x5d, 0x44, 0x87, 0x13, 0x05, 0x51, 0x78, 0x03, 0x74, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x05, 0xff, 0xee, 0x00, 0x00, 0x05, 0x3f, 0x06, 0x14, 0x00, 0x0c, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x00, 0x25, 0x33, 0x32, 0x37, 0x36, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x13, 0x21, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x12, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x02, 0x00, 0xa8, 0xd6, 0x74, 0xa8, 0x01, 0x02, 0x7b, 0x21, 0x2b, 0x48, 0x6e, 0xa0, 0x6a, 0xfd, 0xfa, 0xf0, 0xf0, 0xa6, 0xc3, 0xf9, 0x52, 0x3e, 0x69, 0x5e, 0xa8, 0xa6, 0xb6, 0xfe, 0xca, 0x87, 0x87, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb8, 0x3f, 0x5d, 0x44, 0x87, 0x13, 0x05, 0x51, 0x78, 0xfe, 0x92, 0xb8, 0x05, 0x5c, 0xfb, 0x0e, 0x01, 0x3f, 0x63, 0x21, 0x27, 0x45, 0xeb, 0xa9, 0x6d, 0x78, 0x04, 0xe2, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x05, 0xff, 0xee, 0x00, 0x00, 0x05, 0xfa, 0x06, 0x14, 0x00, 0x1c, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x00, 0x29, 0x01, 0x23, 0x35, 0x33, 0x11, 0x33, 0x11, 0x12, 0x37, 0x36, 0x33, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x2f, 0x01, 0x06, 0x25, 0x33, 0x32, 0x37, 0x36, 0x27, 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x06, 0x13, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x02, 0xe6, 0xfd, 0xf8, 0xf0, 0xf0, 0xa6, 0xc3, 0xf9, 0x52, 0x3e, 0x69, 0x5e, 0xaa, 0x26, 0x0c, 0x0f, 0x37, 0x49, 0x44, 0x75, 0x76, 0x5d, 0x19, 0xb7, 0xfe, 0x1e, 0xa8, 0xd6, 0x74, 0xa8, 0x01, 0x02, 0x7b, 0x21, 0x2b, 0x48, 0x6e, 0xa0, 0x33, 0x87, 0x87, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb8, 0x05, 0x5c, 0xfb, 0x0e, 0x01, 0x3f, 0x63, 0x21, 0x27, 0x45, 0xeb, 0x4d, 0x46, 0x0c, 0x0b, 0x2c, 0xb8, 0x5c, 0x1a, 0x76, 0xb8, 0x3f, 0x5d, 0x44, 0x87, 0x13, 0x05, 0x51, 0x78, 0x03, 0x74, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x69, 0xfe, 0x0c, 0x04, 0x3a, 0x05, 0x46, 0x00, 0x25, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x00, 0x01, 0x06, 0x23, 0x20, 0x27, 0x26, 0x10, 0x37, 0x2e, 0x01, 0x35, 0x34, 0x37, 0x36, 0x32, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x1e, 0x01, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x15, 0x14, 0x17, 0x16, 0x21, 0x32, 0x37, 0x01, 0x36, 0x34, 0x22, 0x15, 0x14, 0x13, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x04, 0x3a, 0x89, 0xe7, 0xfe, 0x85, 0x8d, 0x59, 0xa9, 0x37, 0x3d, 0x70, 0x57, 0xd7, 0x55, 0x72, 0x52, 0x33, 0x54, 0x3d, 0xa3, 0x4d, 0x90, 0x82, 0xef, 0xdf, 0x8b, 0x25, 0x60, 0x01, 0x3c, 0xae, 0xbf, 0xfd, 0x79, 0x7a, 0xb9, 0x0a, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xfe, 0x6f, 0x63, 0xbc, 0x7a, 0x01, 0x92, 0x8c, 0x32, 0x74, 0x2a, 0x6e, 0x40, 0x30, 0x30, 0x40, 0x70, 0x5b, 0x43, 0x2b, 0x20, 0x40, 0x4d, 0xb8, 0xe4, 0x81, 0x6b, 0x6c, 0x3d, 0x9e, 0x76, 0x02, 0x96, 0x38, 0x60, 0x33, 0x24, 0x03, 0x48, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x04, 0xff, 0xee, 0x00, 0x00, 0x03, 0x93, 0x06, 0x40, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x00, 0x37, 0x32, 0x37, 0x26, 0x27, 0x26, 0x35, 0x10, 0x37, 0x36, 0x33, 0x15, 0x22, 0x06, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x25, 0x15, 0x05, 0x04, 0x2b, 0x01, 0x35, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x36, 0x91, 0xb6, 0x44, 0x2f, 0x4f, 0xb8, 0x70, 0xe2, 0xc4, 0xa7, 0x37, 0x4b, 0x3f, 0x32, 0x42, 0x01, 0x03, 0xfe, 0x86, 0xfe, 0xc5, 0xa0, 0x4f, 0x01, 0x90, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb8, 0x5d, 0x18, 0x3b, 0x64, 0x8c, 0x01, 0x08, 0x7d, 0x4d, 0xa9, 0x89, 0xff, 0x34, 0x46, 0x21, 0x81, 0xb8, 0xc5, 0xa4, 0xb8, 0x05, 0x88, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0xee, 0x00, 0x00, 0x03, 0x8c, 0x05, 0x46, 0x00, 0x24, 0x00, 0x2f, 0x00, 0x33, 0x00, 0x37, 0x00, 0x3b, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x37, 0x26, 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x32, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x02, 0x22, 0x07, 0x06, 0x15, 0x14, 0x17, 0x36, 0x35, 0x34, 0x27, 0x03, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0xbd, 0xaf, 0xb6, 0x6a, 0x56, 0x61, 0x3b, 0x35, 0x24, 0x57, 0x3d, 0x1b, 0x0b, 0x0f, 0x5d, 0x51, 0xd6, 0x50, 0x5d, 0x0f, 0x0c, 0x1c, 0x45, 0x4f, 0x1c, 0x3d, 0x37, 0x65, 0x56, 0x6a, 0xb6, 0x97, 0x2f, 0x1b, 0x2a, 0x5d, 0x5c, 0x2a, 0x71, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb9, 0xb9, 0xb8, 0x28, 0x24, 0x27, 0x55, 0x5a, 0x27, 0x2d, 0x1f, 0x29, 0x37, 0x34, 0x2d, 0x2d, 0x34, 0x37, 0x29, 0x1f, 0x2d, 0x27, 0x62, 0x4d, 0x1f, 0x2c, 0x28, 0xb8, 0x02, 0x55, 0x07, 0x0c, 0x20, 0x1d, 0x5f, 0x5f, 0x1d, 0x20, 0x0c, 0x02, 0xf8, 0x96, 0x64, 0x96, 0x96, 0x96, 0xff, 0xff, 0x00, 0x75, 0xfe, 0xa2, 0x07, 0x86, 0x03, 0x11, 0x10, 0x26, 0x10, 0xff, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x03, 0x14, 0xfe, 0xa2, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xd4, 0x02, 0xec, 0x03, 0xd9, 0x10, 0x26, 0x11, 0x00, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x01, 0x7e, 0xfe, 0xd4, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xd4, 0x03, 0xb7, 0x03, 0x08, 0x10, 0x26, 0x11, 0x01, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x01, 0x7e, 0xfe, 0xd4, 0xff, 0xff, 0x00, 0x75, 0xfe, 0xa2, 0x07, 0x86, 0x04, 0x4c, 0x10, 0x26, 0x10, 0xff, 0x00, 0x00, 0x10, 0x27, 0x10, 0xf6, 0x05, 0x5c, 0x03, 0xb6, 0x10, 0x07, 0x10, 0xf6, 0x03, 0x14, 0xfe, 0xa2, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xd4, 0x02, 0xec, 0x05, 0x14, 0x10, 0x26, 0x11, 0x00, 0x00, 0x00, 0x10, 0x27, 0x10, 0xf6, 0x01, 0x7e, 0x04, 0x7e, 0x10, 0x07, 0x10, 0xf6, 0x01, 0x7e, 0xfe, 0xd4, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xd4, 0x03, 0xb7, 0x04, 0x7e, 0x10, 0x26, 0x11, 0x01, 0x00, 0x00, 0x10, 0x27, 0x10, 0xf6, 0x01, 0x8f, 0x03, 0xe8, 0x10, 0x07, 0x10, 0xf6, 0x01, 0x7e, 0xfe, 0xd4, 0xff, 0xff, 0x00, 0x75, 0xfd, 0xa8, 0x07, 0x86, 0x03, 0x11, 0x10, 0x26, 0x10, 0xff, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf9, 0x02, 0xa3, 0xfe, 0xa2, 0xff, 0xff, 0xff, 0xee, 0xfd, 0xda, 0x02, 0xec, 0x03, 0xd9, 0x10, 0x26, 0x11, 0x00, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf9, 0x01, 0x0e, 0xfe, 0xd4, 0xff, 0xff, 0xff, 0xee, 0xfd, 0xda, 0x03, 0xb7, 0x03, 0x08, 0x10, 0x26, 0x11, 0x01, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf9, 0x01, 0x0e, 0xfe, 0xd4, 0xff, 0xff, 0x00, 0x60, 0xfe, 0x0c, 0x06, 0x14, 0x04, 0x01, 0x10, 0x26, 0x11, 0x02, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x03, 0x9a, 0x03, 0x6b, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x02, 0xec, 0x05, 0x14, 0x10, 0x26, 0x11, 0x03, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x01, 0x7e, 0x04, 0x7e, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x03, 0xb7, 0x04, 0x7e, 0x10, 0x26, 0x11, 0x04, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x01, 0x8f, 0x03, 0xe8, 0xff, 0xff, 0x00, 0x60, 0xfe, 0x0c, 0x06, 0x14, 0x04, 0xfb, 0x10, 0x26, 0x11, 0x02, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf8, 0x03, 0x2a, 0x03, 0x6b, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x02, 0xec, 0x06, 0x0e, 0x10, 0x26, 0x11, 0x03, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf8, 0x01, 0x0e, 0x04, 0x7e, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x03, 0xb7, 0x05, 0x78, 0x10, 0x26, 0x11, 0x04, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf8, 0x01, 0x1e, 0x03, 0xe8, 0x00, 0x01, 0x00, 0x75, 0xff, 0xa7, 0x07, 0xa9, 0x06, 0x14, 0x00, 0x37, 0x00, 0x00, 0x25, 0x32, 0x24, 0x36, 0x3d, 0x01, 0x34, 0x27, 0x25, 0x24, 0x3d, 0x01, 0x34, 0x37, 0x36, 0x37, 0x01, 0x21, 0x01, 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x05, 0x16, 0x1d, 0x01, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x27, 0x06, 0x04, 0x23, 0x21, 0x22, 0x27, 0x24, 0x11, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x04, 0x77, 0xa6, 0x01, 0x46, 0x2c, 0x6d, 0xfc, 0xb7, 0xfe, 0xc1, 0x09, 0x11, 0x90, 0x02, 0x6c, 0x01, 0x3c, 0xfc, 0xc4, 0x55, 0x0d, 0x09, 0x04, 0x05, 0x9d, 0x03, 0x69, 0xdf, 0x2b, 0x0d, 0x14, 0x29, 0x51, 0x53, 0x33, 0x0a, 0x4b, 0xfe, 0x95, 0x91, 0xfe, 0x3e, 0xad, 0x73, 0xfe, 0xd7, 0x39, 0xa5, 0x3a, 0xb7, 0x5d, 0x88, 0x58, 0x96, 0x6c, 0x05, 0x09, 0x6b, 0x12, 0x91, 0x37, 0xbe, 0x07, 0x06, 0x3e, 0x63, 0x60, 0x01, 0x9b, 0xfd, 0xe8, 0x37, 0x23, 0x0a, 0x23, 0x35, 0x1b, 0x96, 0x26, 0xf8, 0x45, 0x5e, 0x11, 0x05, 0xb8, 0x32, 0x30, 0x39, 0x82, 0x26, 0x62, 0x01, 0x0b, 0x8a, 0x5c, 0x5e, 0x88, 0x7e, 0x42, 0x22, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x05, 0xde, 0x06, 0x14, 0x00, 0x20, 0x00, 0x00, 0x23, 0x35, 0x21, 0x32, 0x37, 0x36, 0x27, 0x26, 0x27, 0x25, 0x24, 0x3d, 0x01, 0x34, 0x37, 0x36, 0x37, 0x01, 0x21, 0x01, 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x05, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x12, 0x04, 0x87, 0x85, 0x29, 0x11, 0x03, 0x0b, 0x5a, 0xfc, 0xb7, 0xfe, 0xc1, 0x09, 0x10, 0x91, 0x02, 0x6c, 0x01, 0x3c, 0xfc, 0xc4, 0x55, 0x0d, 0x09, 0x04, 0x05, 0x9d, 0x03, 0x69, 0xdf, 0x38, 0x55, 0xc9, 0xb8, 0x68, 0x2c, 0x1c, 0x6e, 0x0f, 0x91, 0x37, 0xbe, 0x08, 0x05, 0x3e, 0x62, 0x61, 0x01, 0x9b, 0xfd, 0xe8, 0x37, 0x23, 0x0a, 0x23, 0x35, 0x1b, 0x96, 0x26, 0xf8, 0x71, 0x65, 0x9b, 0x00, 0x00, 0x01, 0xff, 0xee, 0x00, 0x00, 0x06, 0x53, 0x06, 0x14, 0x00, 0x29, 0x00, 0x00, 0x23, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x25, 0x24, 0x3d, 0x01, 0x34, 0x37, 0x36, 0x37, 0x01, 0x21, 0x01, 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x05, 0x16, 0x1d, 0x01, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x26, 0x27, 0x06, 0x23, 0x12, 0x04, 0x87, 0x7b, 0x33, 0x0e, 0x65, 0xfc, 0xb7, 0xfe, 0xc1, 0x09, 0x10, 0x91, 0x02, 0x6c, 0x01, 0x3c, 0xfc, 0xc4, 0x55, 0x0d, 0x09, 0x04, 0x05, 0x9d, 0x03, 0x69, 0xdf, 0x2b, 0x0d, 0x14, 0x29, 0x51, 0x51, 0x32, 0x0a, 0x56, 0x97, 0xb8, 0x68, 0x1d, 0x18, 0x7f, 0x11, 0x91, 0x37, 0xbe, 0x08, 0x04, 0x3f, 0x62, 0x61, 0x01, 0x9b, 0xfd, 0xe8, 0x37, 0x23, 0x0a, 0x23, 0x35, 0x1b, 0x96, 0x26, 0xf8, 0x45, 0x5f, 0x10, 0x05, 0xb8, 0x2f, 0x28, 0x57, 0x00, 0x00, 0x00, 0x03, 0x00, 0x75, 0xff, 0xa7, 0x07, 0x11, 0x06, 0x14, 0x00, 0x37, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x00, 0x25, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x01, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x06, 0x13, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x05, 0x0c, 0x59, 0x98, 0xb8, 0xa5, 0xad, 0x73, 0xfe, 0xd7, 0x39, 0xa5, 0x3a, 0xb7, 0x5d, 0x88, 0xa6, 0xae, 0x8e, 0x20, 0x0e, 0x30, 0xfe, 0xe9, 0x2d, 0x09, 0x1f, 0x5a, 0x02, 0x9f, 0xfd, 0xe8, 0x40, 0x13, 0x05, 0x1c, 0x02, 0x0d, 0x13, 0x23, 0x26, 0x3a, 0x4f, 0x77, 0x3a, 0x34, 0x5d, 0x1e, 0x57, 0x17, 0x99, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x39, 0x39, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x39, 0x78, 0x4c, 0x3c, 0x49, 0x26, 0x62, 0x01, 0x0b, 0x8a, 0x5c, 0x5e, 0x88, 0x7e, 0x42, 0x22, 0x50, 0x41, 0x37, 0x1a, 0x2e, 0x45, 0x42, 0x01, 0x7c, 0x3d, 0x51, 0x23, 0x21, 0x77, 0x2a, 0x01, 0x36, 0xba, 0xfa, 0x1e, 0x28, 0x0b, 0x19, 0x20, 0x25, 0xfd, 0x3f, 0x1a, 0x0e, 0x10, 0xb8, 0x18, 0x2b, 0x29, 0x78, 0x40, 0x03, 0xbc, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0xff, 0xee, 0x00, 0x00, 0x03, 0x6e, 0x06, 0x14, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x37, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x13, 0x16, 0x15, 0x14, 0x07, 0x06, 0x13, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x01, 0x17, 0xfe, 0xd7, 0x01, 0x17, 0x85, 0x29, 0x0e, 0x31, 0xfe, 0xea, 0x2e, 0x0a, 0x1b, 0x5e, 0x02, 0x9f, 0xfd, 0xe8, 0x40, 0x13, 0x05, 0x1c, 0xf7, 0x5c, 0x38, 0x55, 0xfe, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x38, 0x3a, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x3a, 0xb8, 0x68, 0x24, 0x24, 0x45, 0x42, 0x01, 0x7c, 0x3d, 0x51, 0x23, 0x21, 0x76, 0x2b, 0x01, 0x36, 0xba, 0xfa, 0x1e, 0x28, 0x0b, 0x19, 0x20, 0x25, 0xfe, 0xb6, 0x7b, 0x7b, 0x71, 0x65, 0x9b, 0x04, 0x60, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xee, 0x00, 0x00, 0x04, 0x0c, 0x06, 0x14, 0x00, 0x29, 0x00, 0x35, 0x00, 0x41, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x01, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x06, 0x07, 0x06, 0x01, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x01, 0x17, 0xfe, 0xd7, 0x01, 0x17, 0x85, 0x29, 0x0e, 0x31, 0xfe, 0xea, 0x2e, 0x0a, 0x1b, 0x5e, 0x02, 0x9f, 0xfd, 0xe8, 0x40, 0x13, 0x05, 0x1c, 0x02, 0x0c, 0x14, 0x22, 0x27, 0x3a, 0x4f, 0x77, 0x3a, 0x35, 0x5c, 0x1e, 0x57, 0x13, 0x10, 0x55, 0x01, 0x01, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x38, 0x3a, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x3a, 0xb8, 0x68, 0x24, 0x24, 0x45, 0x42, 0x01, 0x7c, 0x3d, 0x51, 0x23, 0x21, 0x76, 0x2b, 0x01, 0x36, 0xba, 0xfa, 0x1e, 0x28, 0x0b, 0x19, 0x20, 0x25, 0xfd, 0x3f, 0x1a, 0x0e, 0x10, 0xb8, 0x18, 0x2b, 0x29, 0x78, 0x2e, 0x1b, 0x9b, 0x04, 0x60, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x81, 0xff, 0xc9, 0x06, 0x24, 0x06, 0x14, 0x00, 0x21, 0x00, 0x44, 0x00, 0x48, 0x00, 0x00, 0x01, 0x15, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x37, 0x36, 0x37, 0x36, 0x13, 0x06, 0x27, 0x26, 0x27, 0x24, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x01, 0x33, 0x15, 0x23, 0x03, 0x6e, 0x42, 0x22, 0x48, 0x0c, 0x0b, 0x3d, 0x5c, 0x4f, 0x4a, 0x46, 0x3c, 0x32, 0x3d, 0x29, 0x36, 0x33, 0x36, 0x46, 0x43, 0x10, 0x1d, 0x01, 0x02, 0x43, 0x4d, 0x7c, 0x62, 0x83, 0xba, 0x5b, 0xfe, 0xf9, 0x0e, 0xa6, 0x0d, 0x02, 0x90, 0x6d, 0x72, 0x7e, 0x50, 0x89, 0x58, 0x45, 0xa5, 0x2c, 0x28, 0x59, 0x43, 0x75, 0x89, 0x66, 0x8e, 0xfe, 0x72, 0x87, 0x87, 0x04, 0x6f, 0x52, 0x04, 0x0e, 0x1e, 0x21, 0x1c, 0x12, 0x10, 0x0a, 0x0f, 0x58, 0x6e, 0x2a, 0x27, 0x0b, 0x58, 0x0a, 0x1a, 0x1a, 0x1e, 0x26, 0x11, 0x10, 0x1c, 0x2f, 0x2e, 0x51, 0x26, 0x2b, 0xfb, 0x70, 0x14, 0x02, 0x02, 0x1e, 0x58, 0xc3, 0x4b, 0x35, 0x3a, 0x2c, 0x5c, 0x2e, 0x23, 0x1b, 0x2f, 0x5e, 0x49, 0x01, 0x01, 0x03, 0xb1, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x7b, 0x7e, 0x05, 0xdf, 0x96, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x03, 0x6e, 0x06, 0x72, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x13, 0x16, 0x15, 0x14, 0x07, 0x06, 0x01, 0x33, 0x15, 0x23, 0x01, 0x17, 0xfe, 0xd7, 0x01, 0x17, 0x85, 0x29, 0x0e, 0x31, 0xfe, 0xea, 0x2e, 0x0a, 0x1b, 0x5e, 0x02, 0x9f, 0xfd, 0xe8, 0x40, 0x13, 0x05, 0x1c, 0xf7, 0x5c, 0x38, 0x55, 0xfe, 0xd4, 0x87, 0x87, 0xb8, 0x68, 0x24, 0x24, 0x45, 0x42, 0x01, 0x7c, 0x3d, 0x51, 0x23, 0x21, 0x76, 0x2b, 0x01, 0x36, 0xba, 0xfa, 0x1e, 0x28, 0x0b, 0x19, 0x20, 0x25, 0xfe, 0xb6, 0x7b, 0x7b, 0x71, 0x65, 0x9b, 0x06, 0x72, 0x96, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x04, 0x0c, 0x06, 0x72, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x01, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x06, 0x07, 0x06, 0x01, 0x33, 0x15, 0x23, 0x01, 0x17, 0xfe, 0xd7, 0x01, 0x17, 0x85, 0x29, 0x0e, 0x31, 0xfe, 0xea, 0x2e, 0x0a, 0x1b, 0x5e, 0x02, 0x9f, 0xfd, 0xe8, 0x40, 0x13, 0x05, 0x1c, 0x02, 0x0c, 0x14, 0x22, 0x27, 0x3a, 0x4f, 0x77, 0x3a, 0x35, 0x5c, 0x1e, 0x57, 0x13, 0x10, 0x55, 0xfe, 0xd7, 0x87, 0x87, 0xb8, 0x68, 0x24, 0x24, 0x45, 0x42, 0x01, 0x7c, 0x3d, 0x51, 0x23, 0x21, 0x76, 0x2b, 0x01, 0x36, 0xba, 0xfa, 0x1e, 0x28, 0x0b, 0x19, 0x20, 0x25, 0xfd, 0x3f, 0x1a, 0x0e, 0x10, 0xb8, 0x18, 0x2b, 0x29, 0x78, 0x2e, 0x1b, 0x9b, 0x06, 0x72, 0x96, 0x00, 0x00, 0x00, 0x05, 0x00, 0x81, 0xfd, 0xa8, 0x06, 0x24, 0x06, 0x14, 0x00, 0x21, 0x00, 0x44, 0x00, 0x48, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x00, 0x01, 0x15, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x37, 0x36, 0x37, 0x36, 0x13, 0x06, 0x27, 0x26, 0x27, 0x24, 0x35, 0x34, 0x37, 0x33, 0x06, 0x15, 0x16, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x19, 0x01, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x01, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x6e, 0x42, 0x22, 0x48, 0x0c, 0x0b, 0x3d, 0x5c, 0x4f, 0x4a, 0x46, 0x3c, 0x32, 0x3d, 0x29, 0x36, 0x33, 0x36, 0x46, 0x43, 0x10, 0x1d, 0x01, 0x02, 0x43, 0x4d, 0x7c, 0x62, 0x83, 0xba, 0x5b, 0xfe, 0xf9, 0x0e, 0xa6, 0x0d, 0x02, 0x90, 0x6d, 0x72, 0x7e, 0x50, 0x89, 0x58, 0x45, 0xa5, 0x2c, 0x28, 0x59, 0x43, 0x75, 0x89, 0x66, 0x8e, 0xfe, 0x5b, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x04, 0x6f, 0x52, 0x04, 0x0e, 0x1e, 0x21, 0x1c, 0x12, 0x10, 0x0a, 0x0f, 0x58, 0x6e, 0x2a, 0x27, 0x0b, 0x58, 0x0a, 0x1a, 0x1a, 0x1e, 0x26, 0x11, 0x10, 0x1c, 0x2f, 0x2e, 0x51, 0x26, 0x2b, 0xfb, 0x70, 0x14, 0x02, 0x02, 0x1e, 0x58, 0xc3, 0x4b, 0x35, 0x3a, 0x2c, 0x5c, 0x2e, 0x23, 0x1b, 0x2f, 0x5e, 0x49, 0x01, 0x01, 0x03, 0xb1, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x7b, 0x7e, 0xfe, 0x41, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x04, 0xff, 0xee, 0xfd, 0xda, 0x03, 0x6e, 0x06, 0x14, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x13, 0x16, 0x15, 0x14, 0x07, 0x06, 0x03, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x17, 0xfe, 0xd7, 0x01, 0x17, 0x85, 0x29, 0x0e, 0x31, 0xfe, 0xea, 0x2e, 0x0a, 0x1b, 0x5e, 0x02, 0x9f, 0xfd, 0xe8, 0x40, 0x13, 0x05, 0x1c, 0xf7, 0x5c, 0x38, 0x55, 0xbc, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb8, 0x68, 0x24, 0x24, 0x45, 0x42, 0x01, 0x7c, 0x3d, 0x51, 0x23, 0x21, 0x76, 0x2b, 0x01, 0x36, 0xba, 0xfa, 0x1e, 0x28, 0x0b, 0x19, 0x20, 0x25, 0xfe, 0xb6, 0x7b, 0x7b, 0x71, 0x65, 0x9b, 0xfe, 0x70, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x04, 0xff, 0xee, 0xfd, 0xda, 0x04, 0x0c, 0x06, 0x14, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x00, 0x29, 0x01, 0x35, 0x21, 0x32, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x01, 0x15, 0x05, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17, 0x01, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x26, 0x2f, 0x01, 0x06, 0x07, 0x06, 0x03, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x17, 0xfe, 0xd7, 0x01, 0x17, 0x85, 0x29, 0x0e, 0x31, 0xfe, 0xea, 0x2e, 0x0a, 0x1b, 0x5e, 0x02, 0x9f, 0xfd, 0xe8, 0x40, 0x13, 0x05, 0x1c, 0x02, 0x0c, 0x14, 0x22, 0x27, 0x3a, 0x4f, 0x77, 0x3a, 0x35, 0x5c, 0x1e, 0x57, 0x13, 0x10, 0x55, 0xb9, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0xb8, 0x68, 0x24, 0x24, 0x45, 0x42, 0x01, 0x7c, 0x3d, 0x51, 0x23, 0x21, 0x76, 0x2b, 0x01, 0x36, 0xba, 0xfa, 0x1e, 0x28, 0x0b, 0x19, 0x20, 0x25, 0xfd, 0x3f, 0x1a, 0x0e, 0x10, 0xb8, 0x18, 0x2b, 0x29, 0x78, 0x2e, 0x1b, 0x9b, 0xfe, 0x70, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x03, 0x03, 0x69, 0x03, 0x84, 0x06, 0x72, 0x07, 0x2b, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x00, 0x09, 0x01, 0x35, 0x01, 0x03, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x06, 0x72, 0xfc, 0xf7, 0x03, 0x09, 0x97, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x39, 0x39, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x39, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0xfd, 0x35, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x00, 0x64, 0x03, 0x84, 0x03, 0x6e, 0x07, 0x2b, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x00, 0x09, 0x01, 0x35, 0x01, 0x03, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x03, 0x6e, 0xfc, 0xf7, 0x03, 0x09, 0x90, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x38, 0x3a, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x3a, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0xfd, 0x35, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x00, 0x64, 0x03, 0x84, 0x03, 0x6e, 0x07, 0x2b, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x00, 0x09, 0x01, 0x35, 0x01, 0x03, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x03, 0x6e, 0xfc, 0xf7, 0x03, 0x09, 0x90, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x38, 0x3a, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x3a, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0xfd, 0x35, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x02, 0x1c, 0xfe, 0xa2, 0x06, 0x72, 0x07, 0x2b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x01, 0x35, 0x09, 0x01, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x06, 0x72, 0xfc, 0xf7, 0x03, 0x09, 0xfc, 0x8b, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0xf8, 0x0d, 0x96, 0x96, 0x96, 0x00, 0x00, 0x03, 0x00, 0x64, 0xfe, 0xd4, 0x03, 0x6e, 0x07, 0x2b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x01, 0x35, 0x09, 0x01, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x6e, 0xfc, 0xf7, 0x03, 0x09, 0xfe, 0x27, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0xf8, 0x3f, 0x96, 0x96, 0x96, 0x00, 0x00, 0x03, 0x00, 0x64, 0xfe, 0xd4, 0x03, 0x6e, 0x07, 0x2b, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x01, 0x35, 0x09, 0x01, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x6e, 0xfc, 0xf7, 0x03, 0x09, 0xfe, 0x27, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0xf8, 0x3f, 0x96, 0x96, 0x96, 0x00, 0x00, 0x04, 0x03, 0x2a, 0x05, 0x33, 0x06, 0x72, 0x08, 0x34, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x09, 0x01, 0x35, 0x09, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x06, 0x72, 0xfc, 0xf7, 0x03, 0x09, 0xfd, 0x28, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0x01, 0x09, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x04, 0x00, 0x43, 0x05, 0x33, 0x03, 0x6e, 0x08, 0x34, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x09, 0x01, 0x35, 0x09, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x6e, 0xfc, 0xf7, 0x03, 0x09, 0xfd, 0x46, 0x87, 0x87, 0x70, 0x88, 0x88, 0xe0, 0x86, 0x86, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0x01, 0x09, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x04, 0x00, 0x43, 0x05, 0x33, 0x03, 0x6e, 0x08, 0x34, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x00, 0x09, 0x01, 0x35, 0x09, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0x6e, 0xfc, 0xf7, 0x03, 0x09, 0xfd, 0x46, 0x87, 0x87, 0x70, 0x88, 0x88, 0xe0, 0x86, 0x86, 0x06, 0x95, 0xfe, 0x9e, 0x96, 0x01, 0x62, 0x01, 0x09, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x81, 0xfe, 0xc8, 0x05, 0x86, 0x07, 0x9e, 0x00, 0x24, 0x00, 0x28, 0x00, 0x00, 0x25, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x26, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x13, 0x33, 0x15, 0x23, 0x03, 0xaa, 0x46, 0xa6, 0x2c, 0x27, 0x59, 0x44, 0x75, 0x65, 0x46, 0x10, 0x19, 0x6d, 0xea, 0x79, 0x4d, 0x59, 0x3e, 0xfe, 0xf9, 0x01, 0x39, 0xa6, 0x3b, 0x96, 0x24, 0x41, 0x48, 0x63, 0x9c, 0x92, 0x87, 0x87, 0x49, 0x7e, 0xe3, 0x04, 0x6a, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x33, 0x2e, 0x28, 0xb1, 0x42, 0x22, 0x16, 0x5b, 0x01, 0x12, 0x8a, 0x5c, 0x73, 0x73, 0x7e, 0x42, 0x10, 0x22, 0x35, 0x07, 0xcc, 0x96, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x01, 0x84, 0x07, 0x9e, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x03, 0x33, 0x15, 0x23, 0x01, 0x84, 0x4e, 0x48, 0x8b, 0x75, 0x44, 0x59, 0x27, 0x2c, 0xa6, 0x9d, 0x87, 0x87, 0x01, 0x73, 0xb2, 0x65, 0x5c, 0xb8, 0x2c, 0x31, 0x6a, 0x04, 0x95, 0x01, 0x8a, 0x96, 0x00, 0x00, 0x00, 0x02, 0xff, 0xee, 0x00, 0x00, 0x02, 0x75, 0x07, 0x9e, 0x00, 0x14, 0x00, 0x18, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x03, 0x33, 0x15, 0x23, 0x01, 0x31, 0x45, 0x89, 0x75, 0x44, 0x59, 0x27, 0x2c, 0xa6, 0x2c, 0x28, 0x59, 0x43, 0x75, 0x87, 0x91, 0x87, 0x87, 0x56, 0x56, 0xb8, 0x2c, 0x31, 0x6a, 0x04, 0x95, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x07, 0x9e, 0x96, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x81, 0xfe, 0xc8, 0x05, 0x86, 0x08, 0x34, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x00, 0x25, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x26, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x13, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0xaa, 0x46, 0xa6, 0x2c, 0x27, 0x59, 0x44, 0x75, 0x65, 0x46, 0x10, 0x19, 0x6d, 0xea, 0x79, 0x4d, 0x59, 0x3e, 0xfe, 0xf9, 0x01, 0x39, 0xa6, 0x3b, 0x96, 0x24, 0x41, 0x48, 0x63, 0x9c, 0x8d, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x49, 0x7e, 0xe3, 0x04, 0x6a, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x33, 0x2e, 0x28, 0xb1, 0x42, 0x22, 0x16, 0x5b, 0x01, 0x12, 0x8a, 0x5c, 0x73, 0x73, 0x7e, 0x42, 0x10, 0x22, 0x35, 0x08, 0x62, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x04, 0xff, 0xee, 0x00, 0x00, 0x01, 0xdb, 0x08, 0x34, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x15, 0x00, 0x19, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x03, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x84, 0x4e, 0x48, 0x8b, 0x75, 0x44, 0x59, 0x27, 0x2c, 0xa6, 0xa1, 0x87, 0x87, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x01, 0x73, 0xb2, 0x65, 0x5c, 0xb8, 0x2c, 0x31, 0x6a, 0x04, 0x95, 0x02, 0x20, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x04, 0xff, 0xee, 0x00, 0x00, 0x02, 0x75, 0x08, 0x34, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x03, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x31, 0x45, 0x89, 0x75, 0x44, 0x59, 0x27, 0x2c, 0xa6, 0x2c, 0x28, 0x59, 0x43, 0x75, 0x87, 0x95, 0x87, 0x87, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x56, 0x56, 0xb8, 0x2c, 0x31, 0x6a, 0x04, 0x95, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x08, 0x34, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0x04, 0x00, 0x81, 0xfc, 0xe0, 0x05, 0x86, 0x06, 0x14, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x00, 0x25, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x26, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x01, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x03, 0xaa, 0x46, 0xa6, 0x2c, 0x27, 0x59, 0x44, 0x75, 0x65, 0x46, 0x10, 0x19, 0x6d, 0xea, 0x79, 0x4d, 0x59, 0x3e, 0xfe, 0xf9, 0x01, 0x39, 0xa6, 0x3b, 0x96, 0x24, 0x41, 0x48, 0x63, 0x9c, 0xfe, 0xf9, 0x86, 0x86, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x49, 0x7e, 0xe3, 0x04, 0x6a, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0x33, 0x2e, 0x28, 0xb1, 0x42, 0x22, 0x16, 0x5b, 0x01, 0x12, 0x8a, 0x5c, 0x73, 0x73, 0x7e, 0x42, 0x10, 0x22, 0x35, 0xfd, 0xa4, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x04, 0xff, 0xee, 0xfe, 0x0c, 0x01, 0xc2, 0x06, 0x14, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x15, 0x00, 0x19, 0x00, 0x00, 0x01, 0x14, 0x07, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x03, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x84, 0x4e, 0x48, 0x8b, 0x75, 0x44, 0x59, 0x27, 0x2c, 0xa6, 0xba, 0x87, 0x87, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x01, 0x73, 0xb2, 0x65, 0x5c, 0xb8, 0x2c, 0x31, 0x6a, 0x04, 0x95, 0xf8, 0x8e, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0xee, 0xfe, 0x0c, 0x02, 0x75, 0x06, 0x14, 0x00, 0x14, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x00, 0x25, 0x06, 0x2b, 0x01, 0x35, 0x33, 0x32, 0x37, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x03, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x01, 0x31, 0x45, 0x89, 0x75, 0x44, 0x59, 0x27, 0x2c, 0xa6, 0x2c, 0x28, 0x59, 0x43, 0x75, 0x87, 0x93, 0x87, 0x87, 0x70, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x56, 0x56, 0xb8, 0x2c, 0x31, 0x6a, 0x04, 0x95, 0xfb, 0x6b, 0x6a, 0x31, 0x2c, 0xb8, 0xfe, 0xa2, 0x96, 0x01, 0x90, 0x96, 0x96, 0x96, 0x00, 0x03, 0x00, 0x84, 0xfc, 0xc7, 0x05, 0x8e, 0x02, 0xbc, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x25, 0x33, 0x15, 0x23, 0x13, 0x33, 0x15, 0x23, 0x04, 0x63, 0x28, 0x18, 0x14, 0x2d, 0x30, 0x36, 0x43, 0x75, 0x40, 0x1e, 0x03, 0x50, 0x6c, 0xd7, 0x58, 0x52, 0x69, 0x65, 0xfe, 0xd8, 0x2b, 0xa5, 0x2c, 0xb5, 0x51, 0x44, 0x50, 0x47, 0xae, 0x44, 0x1d, 0x5a, 0xfe, 0x48, 0x86, 0x86, 0x70, 0x87, 0x87, 0x02, 0x45, 0x61, 0x60, 0x50, 0x3c, 0x40, 0xb8, 0x30, 0x6d, 0x93, 0xc7, 0x42, 0x1b, 0x25, 0x6b, 0x01, 0x63, 0xaf, 0x8d, 0x89, 0xb3, 0xec, 0x35, 0x18, 0x14, 0x30, 0xe3, 0x65, 0x70, 0xb8, 0xcb, 0x77, 0x96, 0xfb, 0x37, 0x96, 0x00, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xd4, 0x01, 0x60, 0x03, 0xe8, 0x10, 0x27, 0x10, 0xf6, 0x00, 0xca, 0x03, 0x52, 0x10, 0x26, 0x10, 0xfd, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x00, 0xca, 0xfe, 0xd4, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xd4, 0x02, 0x3f, 0x03, 0xe8, 0x10, 0x27, 0x10, 0xf6, 0x00, 0xca, 0x03, 0x52, 0x10, 0x26, 0x10, 0xfe, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf6, 0x00, 0xca, 0xfe, 0xd4, 0x00, 0x04, 0x00, 0x84, 0xfc, 0xae, 0x05, 0x8e, 0x02, 0xbc, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x36, 0x00, 0x42, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x25, 0x33, 0x15, 0x23, 0x01, 0x34, 0x27, 0x26, 0x22, 0x06, 0x15, 0x14, 0x17, 0x16, 0x32, 0x3e, 0x01, 0x14, 0x07, 0x06, 0x22, 0x27, 0x26, 0x34, 0x37, 0x36, 0x32, 0x17, 0x04, 0x63, 0x28, 0x18, 0x14, 0x2d, 0x30, 0x36, 0x43, 0x75, 0x40, 0x1e, 0x03, 0x50, 0x6c, 0xd7, 0x58, 0x52, 0x69, 0x65, 0xfe, 0xd8, 0x2b, 0xa5, 0x2c, 0xb5, 0x51, 0x44, 0x50, 0x47, 0xae, 0x44, 0x1d, 0x5a, 0xfe, 0x48, 0x86, 0x86, 0x01, 0x05, 0x19, 0x19, 0x4a, 0x32, 0x19, 0x19, 0x4a, 0x32, 0x6e, 0x39, 0x39, 0xa6, 0x38, 0x3a, 0x3a, 0x38, 0xa6, 0x39, 0x02, 0x45, 0x61, 0x60, 0x50, 0x3c, 0x40, 0xb8, 0x30, 0x6d, 0x93, 0xc7, 0x42, 0x1b, 0x25, 0x6b, 0x01, 0x63, 0xaf, 0x8d, 0x89, 0xb3, 0xec, 0x35, 0x18, 0x14, 0x30, 0xe3, 0x65, 0x70, 0xb8, 0xcb, 0x77, 0x96, 0xfb, 0x64, 0x28, 0x1c, 0x1d, 0x38, 0x29, 0x2a, 0x1c, 0x1b, 0x38, 0x85, 0xb8, 0x40, 0x40, 0x40, 0x40, 0xb8, 0x40, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xf4, 0x01, 0xd3, 0x03, 0xe8, 0x10, 0x27, 0x10, 0xf6, 0x00, 0xca, 0x03, 0x52, 0x10, 0x26, 0x10, 0xfd, 0x00, 0x00, 0x10, 0x07, 0x11, 0x07, 0x00, 0x48, 0xfe, 0xf4, 0xff, 0xff, 0xff, 0xee, 0xfe, 0xf4, 0x02, 0x3f, 0x03, 0xe8, 0x10, 0x27, 0x10, 0xf6, 0x00, 0xca, 0x03, 0x52, 0x10, 0x26, 0x10, 0xfe, 0x00, 0x00, 0x10, 0x07, 0x11, 0x07, 0x00, 0x48, 0xfe, 0xf4, 0x00, 0x04, 0x00, 0x84, 0xfe, 0x0c, 0x05, 0x8e, 0x03, 0xb6, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x00, 0x01, 0x16, 0x17, 0x16, 0x17, 0x16, 0x3b, 0x01, 0x15, 0x23, 0x22, 0x27, 0x06, 0x07, 0x06, 0x07, 0x06, 0x23, 0x22, 0x27, 0x24, 0x11, 0x34, 0x37, 0x33, 0x06, 0x15, 0x14, 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x01, 0x33, 0x15, 0x23, 0x17, 0x33, 0x15, 0x23, 0x27, 0x33, 0x15, 0x23, 0x04, 0x63, 0x28, 0x18, 0x14, 0x2d, 0x30, 0x36, 0x43, 0x75, 0x40, 0x1e, 0x03, 0x50, 0x6c, 0xd7, 0x58, 0x52, 0x69, 0x65, 0xfe, 0xd8, 0x2b, 0xa5, 0x2c, 0xb5, 0x51, 0x44, 0x50, 0x47, 0xae, 0x44, 0x1d, 0x5a, 0xfe, 0x74, 0x88, 0x88, 0x71, 0x87, 0x87, 0xe1, 0x87, 0x87, 0x02, 0x45, 0x61, 0x60, 0x50, 0x3c, 0x40, 0xb8, 0x30, 0x6d, 0x93, 0xc7, 0x42, 0x1b, 0x25, 0x6b, 0x01, 0x63, 0xaf, 0x8d, 0x89, 0xb3, 0xec, 0x35, 0x18, 0x14, 0x30, 0xe3, 0x65, 0x70, 0xb8, 0xcb, 0x01, 0x71, 0x96, 0x64, 0x96, 0x96, 0x96, 0x00, 0x00, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x01, 0xc2, 0x04, 0xe2, 0x10, 0x26, 0x10, 0xfd, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf8, 0x00, 0x59, 0x03, 0x52, 0xff, 0xff, 0xff, 0xee, 0x00, 0x00, 0x02, 0x3f, 0x04, 0xe2, 0x10, 0x26, 0x10, 0xfe, 0x00, 0x00, 0x10, 0x07, 0x10, 0xf8, 0x00, 0x59, 0x03, 0x52, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x57, 0x0a, 0xdd, 0x83, 0xf3, 0x6b, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x1f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0x3f, 0xd8, 0x65, 0x00, 0x00, 0x00, 0x00, 0xce, 0x3f, 0xd8, 0x65, 0xf8, 0xa7, 0xfc, 0xae, 0x0c, 0x1a, 0x09, 0x55, 0x00, 0x20, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x6d, 0xfe, 0x1d, 0x00, 0x00, 0x0c, 0x7e, 0xf8, 0xa7, 0xfc, 0xc9, 0x0c, 0x1a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0e, 0x04, 0x52, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x02, 0xaa, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x02, 0xe2, 0x01, 0x16, 0x03, 0x4f, 0x00, 0xb1, 0x06, 0x08, 0x00, 0x8e, 0x04, 0x94, 0x00, 0x99, 0x06, 0xd7, 0x00, 0x65, 0x05, 0x9d, 0x00, 0x74, 0x01, 0xfa, 0x00, 0xb1, 0x02, 0xcf, 0x00, 0x9e, 0x02, 0xcf, 0x00, 0x93, 0x03, 0x99, 0x00, 0x36, 0x06, 0x08, 0x00, 0xc3, 0x02, 0x49, 0x00, 0x8e, 0x02, 0x99, 0x00, 0x5a, 0x02, 0x49, 0x00, 0xc5, 0x02, 0x6d, 0x00, 0x00, 0x04, 0x94, 0x00, 0x79, 0x04, 0x94, 0x00, 0xca, 0x04, 0x94, 0x00, 0x87, 0x04, 0x94, 0x00, 0x8c, 0x04, 0x94, 0x00, 0x5a, 0x04, 0x94, 0x00, 0x8e, 0x04, 0x94, 0x00, 0x80, 0x04, 0x94, 0x00, 0x97, 0x04, 0x94, 0x00, 0x7d, 0x04, 0x94, 0x00, 0x74, 0x02, 0x6d, 0x00, 0xd8, 0x02, 0x6d, 0x00, 0x8e, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x03, 0xd2, 0x00, 0x84, 0x07, 0x33, 0x00, 0x79, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xf0, 0x00, 0xb4, 0x05, 0x07, 0x00, 0x67, 0x05, 0x8b, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x24, 0x00, 0xb4, 0x05, 0x94, 0x00, 0x67, 0x05, 0x6a, 0x00, 0xb4, 0x02, 0x1f, 0x00, 0xb4, 0x02, 0x1f, 0xff, 0xa1, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x02, 0x00, 0xb4, 0x06, 0x36, 0x00, 0xb4, 0x05, 0x62, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x57, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x05, 0x00, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x79, 0x04, 0x65, 0xff, 0xfb, 0x05, 0x45, 0x00, 0xa0, 0x04, 0xec, 0x00, 0x0e, 0x07, 0x1e, 0x00, 0x3d, 0x04, 0xee, 0x00, 0x36, 0x04, 0x65, 0xff, 0xfd, 0x04, 0xee, 0x00, 0x52, 0x02, 0xcf, 0x00, 0x9e, 0x02, 0x6d, 0x00, 0x00, 0x02, 0xcf, 0x00, 0xb3, 0x06, 0x08, 0x00, 0xc3, 0x03, 0x99, 0xff, 0xee, 0x03, 0x99, 0x00, 0x99, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x92, 0x00, 0xa7, 0x03, 0xf5, 0x00, 0x65, 0x04, 0x92, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x02, 0x88, 0x00, 0x2a, 0x04, 0x92, 0x00, 0x65, 0x04, 0x90, 0x00, 0xa7, 0x02, 0x00, 0x00, 0xad, 0x02, 0x00, 0xff, 0xdf, 0x04, 0x2b, 0x00, 0xa7, 0x02, 0x00, 0x00, 0xad, 0x07, 0x03, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x67, 0x00, 0x65, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x92, 0x00, 0x65, 0x02, 0xf5, 0x00, 0xa7, 0x03, 0xc0, 0x00, 0x63, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x42, 0x00, 0x36, 0x05, 0xe3, 0x00, 0x4d, 0x04, 0x42, 0x00, 0x35, 0x04, 0x42, 0x00, 0x36, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0x94, 0x00, 0xe6, 0x02, 0x6d, 0x00, 0xea, 0x04, 0x94, 0x00, 0xe6, 0x06, 0x08, 0x00, 0xc3, 0x02, 0x49, 0x00, 0x00, 0x02, 0xe2, 0x01, 0x16, 0x04, 0x94, 0x00, 0x9a, 0x04, 0x94, 0x00, 0x74, 0x04, 0x94, 0x00, 0x54, 0x04, 0x94, 0x00, 0x49, 0x02, 0x6d, 0x00, 0xea, 0x03, 0x99, 0x00, 0x52, 0x03, 0x99, 0x00, 0xc1, 0x07, 0x33, 0x00, 0xfe, 0x03, 0x64, 0x00, 0x67, 0x04, 0x67, 0x00, 0x8e, 0x06, 0x08, 0x00, 0xc3, 0x02, 0x99, 0x00, 0x5a, 0x07, 0x33, 0x00, 0xfe, 0x03, 0x99, 0x00, 0xbf, 0x03, 0x99, 0x00, 0xaf, 0x06, 0x08, 0x00, 0xc3, 0x02, 0xe2, 0x00, 0x54, 0x02, 0xe2, 0x00, 0x58, 0x03, 0x99, 0x01, 0x4d, 0x04, 0x94, 0x00, 0x9c, 0x04, 0x94, 0x00, 0x8e, 0x02, 0x49, 0x00, 0xc5, 0x03, 0x99, 0x01, 0x05, 0x02, 0xe2, 0x00, 0x7b, 0x03, 0x64, 0x00, 0x56, 0x04, 0x67, 0x00, 0xad, 0x06, 0xfa, 0x00, 0x7b, 0x06, 0xfa, 0x00, 0x7b, 0x06, 0xfa, 0x00, 0x58, 0x03, 0xd2, 0x00, 0x80, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x07, 0x03, 0x00, 0x07, 0x05, 0x07, 0x00, 0x67, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x02, 0x1f, 0x00, 0x35, 0x02, 0x1f, 0x00, 0x91, 0x02, 0x1f, 0xff, 0xff, 0x02, 0x1f, 0x00, 0x05, 0x05, 0x94, 0x00, 0x09, 0x05, 0x62, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x05, 0xaa, 0x00, 0x67, 0x05, 0xaa, 0x00, 0x67, 0x05, 0xaa, 0x00, 0x67, 0x05, 0xaa, 0x00, 0x67, 0x06, 0x08, 0x00, 0xfc, 0x05, 0xaa, 0x00, 0x5b, 0x05, 0x45, 0x00, 0xa0, 0x05, 0x45, 0x00, 0xa0, 0x05, 0x45, 0x00, 0xa0, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x5b, 0x00, 0xb4, 0x04, 0x89, 0x00, 0xa7, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x69, 0x00, 0x6e, 0x07, 0x11, 0x00, 0x6e, 0x03, 0xf5, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x02, 0x00, 0xff, 0xcd, 0x02, 0x00, 0x00, 0x81, 0x02, 0x00, 0xff, 0xe2, 0x02, 0x00, 0xff, 0xf6, 0x04, 0x67, 0x00, 0x65, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x06, 0x08, 0x00, 0xc3, 0x04, 0x67, 0x00, 0x40, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x42, 0x00, 0x36, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x42, 0x00, 0x36, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x05, 0x07, 0x00, 0x67, 0x03, 0xf5, 0x00, 0x65, 0x05, 0x07, 0x00, 0x67, 0x03, 0xf5, 0x00, 0x65, 0x05, 0x07, 0x00, 0x67, 0x03, 0xf5, 0x00, 0x65, 0x05, 0x07, 0x00, 0x67, 0x03, 0xf5, 0x00, 0x65, 0x05, 0x8b, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x65, 0x05, 0x94, 0x00, 0x09, 0x04, 0x92, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x05, 0x94, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x05, 0x94, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x05, 0x94, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x05, 0x94, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x90, 0xff, 0xe8, 0x06, 0x98, 0x00, 0xb4, 0x05, 0x00, 0x00, 0x6c, 0x02, 0x1f, 0xff, 0xe7, 0x02, 0x00, 0xff, 0xd8, 0x02, 0x1f, 0x00, 0x02, 0x02, 0x00, 0xff, 0xf4, 0x02, 0x1f, 0xff, 0xf7, 0x02, 0x00, 0xff, 0xe7, 0x02, 0x1f, 0x00, 0x9e, 0x02, 0x00, 0x00, 0x87, 0x02, 0x1f, 0x00, 0xb4, 0x02, 0x00, 0x00, 0xad, 0x04, 0x3f, 0x00, 0xb4, 0x04, 0x00, 0x00, 0xad, 0x02, 0x1f, 0xff, 0xa1, 0x02, 0x00, 0xff, 0xdf, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x2b, 0x00, 0xa7, 0x04, 0x2b, 0x00, 0xa7, 0x04, 0x02, 0x00, 0xb4, 0x02, 0x00, 0x00, 0xad, 0x04, 0x02, 0x00, 0xb4, 0x02, 0x00, 0x00, 0x7a, 0x04, 0x02, 0x00, 0xb4, 0x02, 0xb3, 0x00, 0xad, 0x04, 0x02, 0x00, 0xb4, 0x02, 0x76, 0x00, 0xad, 0x04, 0x0b, 0xff, 0xf4, 0x02, 0x0b, 0x00, 0x01, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0xdb, 0x00, 0xb8, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x07, 0xb3, 0x00, 0x67, 0x07, 0x5d, 0x00, 0x65, 0x05, 0x00, 0x00, 0xb4, 0x02, 0xf5, 0x00, 0xa7, 0x05, 0x00, 0x00, 0xb4, 0x02, 0xf5, 0x00, 0x75, 0x05, 0x00, 0x00, 0xb4, 0x02, 0xf5, 0x00, 0xa7, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x65, 0xff, 0xfb, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x65, 0xff, 0xfb, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x65, 0xff, 0xfb, 0x02, 0xd2, 0x00, 0x31, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x07, 0x1e, 0x00, 0x3d, 0x05, 0xe3, 0x00, 0x4d, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x04, 0x65, 0xff, 0xfd, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x02, 0x88, 0x00, 0x2a, 0x04, 0x92, 0x00, 0x1c, 0x05, 0x4a, 0xff, 0xa2, 0x04, 0xf0, 0x00, 0xb4, 0x04, 0x92, 0x00, 0xa7, 0x04, 0xf0, 0x00, 0x00, 0x04, 0x92, 0x00, 0x00, 0x05, 0x10, 0x00, 0x67, 0x05, 0x07, 0x00, 0x67, 0x03, 0xf5, 0x00, 0x65, 0x05, 0x94, 0x00, 0x09, 0x05, 0xe5, 0xff, 0xa2, 0x04, 0xf0, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x8c, 0x00, 0x75, 0x05, 0xaa, 0x00, 0x69, 0x04, 0x6c, 0x00, 0x93, 0x04, 0x24, 0xff, 0xa1, 0x02, 0x88, 0xff, 0x8c, 0x05, 0x94, 0x00, 0x67, 0x04, 0xf1, 0x00, 0x07, 0x07, 0x15, 0x00, 0xa7, 0x02, 0x8b, 0x00, 0xb4, 0x02, 0x1f, 0x00, 0x09, 0x05, 0x5e, 0x00, 0xb4, 0x04, 0x2b, 0x00, 0xa6, 0x02, 0x00, 0x00, 0x09, 0x04, 0x42, 0x00, 0x36, 0x07, 0x03, 0x00, 0xa0, 0x05, 0x62, 0xff, 0xa1, 0x04, 0x90, 0x00, 0xa7, 0x05, 0xaa, 0x00, 0x67, 0x06, 0x93, 0x00, 0x5c, 0x04, 0x67, 0x00, 0x6a, 0x06, 0xd4, 0x00, 0x67, 0x05, 0x77, 0x00, 0x65, 0x04, 0xb1, 0xff, 0xa2, 0x04, 0x92, 0x00, 0xa6, 0x05, 0x00, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x66, 0x03, 0xc0, 0x00, 0x5a, 0x04, 0x8c, 0x00, 0xb4, 0x02, 0x6b, 0xff, 0x0d, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x65, 0x00, 0x15, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x65, 0xff, 0xfb, 0x06, 0x2d, 0x00, 0x9b, 0x04, 0x90, 0x00, 0x9e, 0x05, 0x80, 0x00, 0x46, 0x05, 0x30, 0x00, 0xb4, 0x05, 0x5a, 0xff, 0xfd, 0x05, 0x42, 0x00, 0x36, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0xcb, 0x00, 0x90, 0x04, 0xcb, 0x00, 0x52, 0x04, 0x28, 0x00, 0x5d, 0x03, 0xc7, 0x00, 0x65, 0x04, 0x94, 0x00, 0x87, 0x04, 0xcb, 0x00, 0x53, 0x04, 0x28, 0x00, 0x5d, 0x03, 0xac, 0x00, 0x4f, 0x04, 0x92, 0x00, 0xa7, 0x02, 0x1f, 0x00, 0xb4, 0x03, 0x8b, 0x00, 0xb4, 0x03, 0x4e, 0x00, 0x12, 0x02, 0x20, 0x00, 0xb4, 0x0a, 0x3c, 0x00, 0xb4, 0x09, 0x5a, 0x00, 0xb4, 0x08, 0x4f, 0x00, 0x65, 0x06, 0x03, 0x00, 0xb4, 0x05, 0xa9, 0x00, 0xb4, 0x03, 0x49, 0x00, 0xad, 0x06, 0xb4, 0x00, 0xb4, 0x06, 0xa6, 0x00, 0xb4, 0x05, 0xbd, 0x00, 0xa7, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x02, 0x1f, 0xff, 0xff, 0x02, 0x00, 0xff, 0xe4, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x6e, 0x00, 0x65, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x07, 0x03, 0x00, 0x07, 0x07, 0x11, 0x00, 0x6e, 0x05, 0x94, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x05, 0x94, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x2b, 0xff, 0xec, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x04, 0xcb, 0x00, 0x90, 0x04, 0x28, 0x00, 0x4f, 0x02, 0x00, 0xff, 0xdf, 0x0a, 0x3c, 0x00, 0xb4, 0x09, 0x5a, 0x00, 0xb4, 0x08, 0x4f, 0x00, 0x65, 0x05, 0x94, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x08, 0x03, 0x00, 0xb4, 0x04, 0xe9, 0x00, 0xb4, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x07, 0x03, 0x00, 0x07, 0x07, 0x11, 0x00, 0x6e, 0x05, 0xaa, 0x00, 0x5b, 0x04, 0x67, 0x00, 0x40, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x02, 0x1f, 0xff, 0xb0, 0x02, 0x00, 0xff, 0xca, 0x02, 0x1f, 0x00, 0x04, 0x02, 0x00, 0xff, 0xe6, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0x00, 0x00, 0xb3, 0x02, 0xf5, 0x00, 0x75, 0x05, 0x00, 0x00, 0xb4, 0x02, 0xf5, 0x00, 0xa7, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x65, 0xff, 0xfb, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x83, 0x00, 0x8c, 0x03, 0xc1, 0x00, 0x3f, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x90, 0xff, 0xf2, 0x05, 0x4b, 0x00, 0xb4, 0x06, 0x08, 0x00, 0x65, 0x05, 0x07, 0x00, 0x65, 0x04, 0x65, 0x00, 0x65, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x03, 0x6a, 0x00, 0x7c, 0x06, 0x11, 0x00, 0xa7, 0x03, 0x6f, 0x00, 0x31, 0x02, 0x00, 0xff, 0xdf, 0x07, 0x2f, 0x00, 0x65, 0x07, 0x2f, 0x00, 0x65, 0x04, 0xec, 0xff, 0xfe, 0x05, 0x07, 0x00, 0x0a, 0x03, 0xf5, 0x00, 0x08, 0x04, 0x02, 0x00, 0x09, 0x04, 0x65, 0xff, 0xba, 0x03, 0xc0, 0x00, 0x63, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0x57, 0x00, 0x48, 0x03, 0x72, 0x00, 0x48, 0x04, 0xf0, 0x00, 0x09, 0x05, 0x45, 0x00, 0x0a, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x02, 0x1f, 0xff, 0xa1, 0x02, 0x00, 0xff, 0xdf, 0x05, 0xa0, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x05, 0x00, 0x00, 0x09, 0x02, 0xf5, 0x00, 0x0c, 0x04, 0x65, 0xff, 0xf7, 0x04, 0x42, 0x00, 0x09, 0x04, 0x52, 0x00, 0x9c, 0x04, 0x92, 0x00, 0x65, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x92, 0x00, 0xa7, 0x03, 0xf4, 0x00, 0x72, 0x03, 0xf5, 0x00, 0x65, 0x04, 0x92, 0x00, 0x65, 0x05, 0x03, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x05, 0xe6, 0x00, 0x6f, 0x03, 0xe4, 0x00, 0x77, 0x03, 0xd4, 0x00, 0x77, 0x05, 0x95, 0x00, 0x77, 0x04, 0xc8, 0x00, 0x65, 0x02, 0x00, 0xff, 0xdf, 0x05, 0x02, 0x00, 0x65, 0x04, 0x92, 0x00, 0x65, 0x04, 0x88, 0x00, 0x65, 0x04, 0x4a, 0x00, 0x56, 0x04, 0x4a, 0x00, 0x56, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x6f, 0x00, 0x95, 0x02, 0xac, 0x00, 0x68, 0x02, 0xd9, 0x00, 0x43, 0x03, 0x82, 0x00, 0x45, 0x02, 0x01, 0x00, 0xad, 0x05, 0x15, 0x00, 0xad, 0x07, 0x03, 0x00, 0xa7, 0x07, 0x03, 0x00, 0xa7, 0x07, 0x03, 0x00, 0xa7, 0x04, 0xa6, 0xff, 0xdf, 0x04, 0x9f, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa1, 0x04, 0x67, 0x00, 0x65, 0x06, 0x2d, 0x00, 0x65, 0x05, 0x3d, 0x00, 0x85, 0x04, 0xbf, 0x00, 0x64, 0x02, 0xfb, 0x00, 0x00, 0x02, 0xfb, 0x00, 0x00, 0x02, 0xfa, 0x00, 0x00, 0x02, 0xf5, 0x00, 0xa7, 0x02, 0xf4, 0x00, 0xa7, 0x03, 0xd1, 0x00, 0x76, 0x03, 0xd1, 0x00, 0x68, 0x04, 0x58, 0x00, 0xa7, 0x04, 0x58, 0x00, 0xa7, 0x03, 0xc0, 0x00, 0x63, 0x02, 0x6b, 0xff, 0xdd, 0x02, 0x6b, 0xff, 0xdd, 0x03, 0x52, 0x00, 0x31, 0x02, 0x6b, 0xff, 0x0d, 0x02, 0xd2, 0x00, 0x31, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x90, 0x00, 0x00, 0x04, 0x72, 0x00, 0x65, 0x04, 0x4e, 0x00, 0xad, 0x04, 0x42, 0x00, 0x36, 0x05, 0xe3, 0x00, 0x4d, 0x04, 0x42, 0x00, 0x36, 0x04, 0x65, 0x00, 0x5b, 0x03, 0xc7, 0x00, 0x4f, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0x28, 0x00, 0x4f, 0x04, 0x28, 0x00, 0x62, 0x03, 0xac, 0x00, 0x4f, 0x03, 0xac, 0x00, 0x4f, 0x03, 0xac, 0x00, 0x4f, 0x03, 0xac, 0x00, 0x4f, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x2c, 0x00, 0xa7, 0x04, 0xc8, 0x00, 0x65, 0x05, 0x19, 0x00, 0x65, 0x04, 0xb5, 0x00, 0xa7, 0x02, 0x1a, 0xff, 0x0d, 0x04, 0xcd, 0x00, 0xa7, 0x03, 0xa6, 0x00, 0xa7, 0x05, 0x3c, 0x00, 0x65, 0x03, 0xac, 0x00, 0x4f, 0x03, 0xac, 0x00, 0x4f, 0x07, 0x4d, 0x00, 0x65, 0x07, 0x9d, 0x00, 0x65, 0x07, 0x4a, 0x00, 0x65, 0x05, 0xfa, 0x00, 0x31, 0x04, 0x64, 0x00, 0x31, 0x05, 0x9a, 0x00, 0x31, 0x06, 0x1b, 0x00, 0x2a, 0x05, 0x14, 0x00, 0xad, 0x04, 0xb6, 0x00, 0xad, 0x03, 0xb5, 0x00, 0x30, 0x03, 0xb5, 0x00, 0x30, 0x04, 0xc2, 0x00, 0x00, 0x04, 0xc7, 0x00, 0x00, 0x02, 0xe9, 0x00, 0x69, 0x02, 0xdf, 0x00, 0x69, 0x01, 0x42, 0xff, 0xec, 0x01, 0xdd, 0x00, 0x69, 0x02, 0x20, 0x00, 0x40, 0x02, 0x21, 0x00, 0x40, 0x02, 0xba, 0x00, 0x1c, 0x03, 0xb5, 0x00, 0x30, 0x02, 0xae, 0x00, 0x22, 0x02, 0x01, 0x00, 0x90, 0x03, 0x4f, 0x00, 0x90, 0x02, 0x49, 0x00, 0x9c, 0x02, 0x49, 0x00, 0xa0, 0x02, 0x49, 0x00, 0xb0, 0x02, 0x36, 0x00, 0x69, 0x02, 0x36, 0x00, 0x69, 0x02, 0xa9, 0x00, 0x69, 0x02, 0xa9, 0x00, 0x69, 0x03, 0x99, 0x00, 0xf0, 0x03, 0x99, 0x00, 0xf0, 0x03, 0x99, 0x00, 0xad, 0x03, 0x99, 0x00, 0xad, 0x03, 0x99, 0x00, 0xad, 0x03, 0x99, 0x00, 0xad, 0x01, 0xfa, 0x00, 0xc0, 0x03, 0x99, 0x00, 0xbf, 0x03, 0x99, 0x01, 0x4d, 0x03, 0x99, 0x00, 0x99, 0x01, 0xfa, 0x00, 0xc0, 0x03, 0x99, 0x00, 0xbf, 0x03, 0x99, 0x00, 0x99, 0x03, 0x99, 0x01, 0x4d, 0x02, 0x6d, 0x00, 0x63, 0x02, 0x6d, 0x00, 0x63, 0x02, 0x36, 0x00, 0x69, 0x02, 0x36, 0x00, 0x69, 0x03, 0x99, 0x01, 0x02, 0x03, 0x99, 0x01, 0x02, 0x02, 0xce, 0x00, 0x5a, 0x02, 0x49, 0x00, 0x5a, 0x03, 0x99, 0x00, 0xb3, 0x03, 0x99, 0x01, 0x71, 0x03, 0x99, 0x00, 0xd6, 0x03, 0x99, 0x01, 0x2a, 0x03, 0x99, 0x00, 0xa3, 0x03, 0x99, 0x00, 0xd8, 0x02, 0x45, 0x00, 0x00, 0x03, 0x99, 0x00, 0xd7, 0x03, 0x10, 0x00, 0x69, 0x01, 0x32, 0x00, 0x6d, 0x02, 0xaf, 0x00, 0x69, 0x03, 0x32, 0x00, 0x69, 0x02, 0xa9, 0x00, 0x69, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x99, 0x00, 0xad, 0x03, 0x99, 0x00, 0xbf, 0x03, 0xba, 0x00, 0x9c, 0x03, 0x99, 0x00, 0xd6, 0x03, 0x99, 0x00, 0xa3, 0x00, 0x00, 0xfc, 0xfe, 0x00, 0x00, 0xfd, 0xb3, 0x00, 0x00, 0xfd, 0x15, 0x00, 0x00, 0xfd, 0x09, 0x00, 0x00, 0xfd, 0x2a, 0x00, 0x00, 0xfc, 0x55, 0x00, 0x00, 0xfd, 0x13, 0x00, 0x00, 0xfd, 0xdf, 0x00, 0x00, 0xfd, 0x28, 0x00, 0x00, 0xfd, 0x7f, 0x00, 0x00, 0xfd, 0x3b, 0x00, 0x00, 0xfd, 0x42, 0x00, 0x00, 0xfd, 0x18, 0x00, 0x00, 0xfd, 0xf6, 0x00, 0x00, 0xfd, 0x3f, 0x00, 0x00, 0xfc, 0xbb, 0x00, 0x00, 0xfd, 0x13, 0x00, 0x00, 0xfd, 0x13, 0x00, 0x00, 0xfe, 0x50, 0x00, 0x00, 0xfd, 0xcf, 0x00, 0x00, 0xfd, 0xcf, 0x00, 0x00, 0xff, 0x87, 0x00, 0x00, 0xfc, 0xfe, 0x00, 0x00, 0xfd, 0xb3, 0x00, 0x00, 0xfd, 0x6e, 0x00, 0x00, 0xfd, 0xfe, 0x00, 0x00, 0xfe, 0x80, 0x00, 0x00, 0xff, 0x0c, 0x00, 0x00, 0xfd, 0xc0, 0x00, 0x00, 0xfd, 0x57, 0x00, 0x00, 0xfd, 0x57, 0x00, 0x00, 0xfd, 0x6e, 0x00, 0x00, 0xfd, 0x57, 0x00, 0x00, 0xfd, 0xbb, 0x00, 0x00, 0xfd, 0xb8, 0x00, 0x00, 0xfd, 0xdf, 0x00, 0x00, 0xfd, 0x27, 0x00, 0x00, 0xfd, 0x71, 0x00, 0x00, 0xfd, 0xad, 0x00, 0x00, 0xfd, 0x6d, 0x00, 0x00, 0xfd, 0x92, 0x00, 0x00, 0xfd, 0xf6, 0x00, 0x00, 0xfd, 0x3f, 0x00, 0x00, 0xfc, 0xc0, 0x00, 0x00, 0xfd, 0x18, 0x00, 0x00, 0xfd, 0x13, 0x00, 0x00, 0xfd, 0x13, 0x00, 0x00, 0xfd, 0x13, 0x00, 0x00, 0xfd, 0x09, 0x00, 0x00, 0xfd, 0x2a, 0x00, 0x00, 0xfc, 0x55, 0x00, 0x00, 0xfc, 0x55, 0x00, 0x00, 0xfb, 0xfe, 0x00, 0x00, 0xfd, 0xb9, 0x00, 0x00, 0xfb, 0x6f, 0x00, 0x00, 0xfb, 0xde, 0x00, 0x00, 0xfa, 0xaa, 0x00, 0x00, 0xfd, 0xe8, 0x00, 0x00, 0xfd, 0x40, 0x00, 0x00, 0xfd, 0x6b, 0x00, 0x00, 0xfc, 0xc0, 0x00, 0x00, 0xfd, 0x74, 0x00, 0x00, 0xfe, 0x39, 0x00, 0x00, 0xfc, 0x55, 0x00, 0x00, 0xfc, 0xfe, 0x00, 0x00, 0xfd, 0xb3, 0x00, 0x00, 0xfd, 0x09, 0x00, 0x00, 0xfd, 0xcf, 0x00, 0x00, 0xfd, 0x37, 0x00, 0x00, 0xfd, 0xff, 0x00, 0x00, 0xfd, 0x27, 0x00, 0x00, 0xfd, 0x69, 0x00, 0x00, 0xfd, 0x60, 0x00, 0x00, 0xfd, 0x69, 0x00, 0x00, 0xfd, 0x0b, 0x00, 0x00, 0xfd, 0x0b, 0x00, 0x00, 0xfd, 0x0b, 0x00, 0x00, 0xfc, 0xc0, 0x00, 0x00, 0xfd, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xb9, 0x00, 0x00, 0xfd, 0x13, 0x00, 0x00, 0xfd, 0x74, 0x00, 0x00, 0xfd, 0xb9, 0x00, 0x00, 0xff, 0x43, 0x00, 0x00, 0xfc, 0xe8, 0x00, 0x00, 0xfc, 0xcc, 0x00, 0x00, 0xfc, 0xcc, 0x00, 0x00, 0xfc, 0xcc, 0x00, 0x00, 0xfc, 0xcc, 0x00, 0x00, 0xfd, 0x73, 0x00, 0x00, 0xfc, 0xcc, 0x00, 0x00, 0xfc, 0xd2, 0x04, 0xb6, 0x00, 0xb4, 0x04, 0x16, 0x00, 0xad, 0x06, 0x34, 0x00, 0xb4, 0x04, 0xa9, 0x00, 0xb4, 0x02, 0x01, 0x00, 0x90, 0x02, 0x01, 0x00, 0x90, 0x05, 0x62, 0x00, 0xb4, 0x04, 0xad, 0x00, 0xa7, 0x03, 0x99, 0x01, 0x8a, 0x03, 0xf4, 0x00, 0x72, 0x03, 0xf5, 0x00, 0x65, 0x03, 0xf4, 0x00, 0x72, 0x02, 0x6d, 0x00, 0x8e, 0x03, 0x99, 0x01, 0x4d, 0x03, 0x99, 0x00, 0xc1, 0x04, 0xfc, 0x00, 0x0e, 0x02, 0x49, 0x00, 0xc5, 0x05, 0x5f, 0xff, 0xea, 0x06, 0x45, 0xff, 0xf5, 0x02, 0xf0, 0xff, 0xef, 0x05, 0xd9, 0xff, 0xf4, 0x05, 0xf0, 0xff, 0xe5, 0x05, 0xf1, 0xff, 0xdf, 0x02, 0x6f, 0x00, 0x04, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xf0, 0x00, 0xb4, 0x04, 0x02, 0x00, 0xb4, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0xee, 0x00, 0x52, 0x05, 0x6a, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x02, 0x1f, 0x00, 0xb4, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0xec, 0x00, 0x0e, 0x06, 0x36, 0x00, 0xb4, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x57, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x65, 0xff, 0xfb, 0x04, 0x65, 0xff, 0xfd, 0x05, 0xaa, 0x00, 0x67, 0x04, 0xee, 0x00, 0x36, 0x05, 0xaa, 0x00, 0x67, 0x05, 0x80, 0x00, 0x46, 0x02, 0x1f, 0x00, 0x05, 0x04, 0x65, 0xff, 0xfd, 0x04, 0xbf, 0x00, 0x65, 0x03, 0xe4, 0x00, 0x77, 0x04, 0x90, 0x00, 0xa7, 0x02, 0x6f, 0x00, 0x95, 0x04, 0x2a, 0x00, 0x86, 0x04, 0xbf, 0x00, 0x65, 0x04, 0x98, 0x00, 0xac, 0x04, 0x42, 0x00, 0x1c, 0x04, 0x67, 0x00, 0x65, 0x03, 0xe4, 0x00, 0x77, 0x03, 0xea, 0x00, 0x60, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x67, 0x00, 0x65, 0x02, 0x6f, 0x00, 0x95, 0x04, 0x3e, 0x00, 0xab, 0x04, 0x42, 0x00, 0x36, 0x04, 0x94, 0x00, 0x9c, 0x04, 0x05, 0x00, 0x42, 0x04, 0x03, 0x00, 0x60, 0x04, 0x67, 0x00, 0x65, 0x04, 0x55, 0x00, 0x42, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x39, 0x00, 0x65, 0x04, 0x90, 0x00, 0x65, 0x04, 0x55, 0x00, 0x5a, 0x04, 0x2a, 0x00, 0x86, 0x04, 0xbf, 0x00, 0x64, 0x04, 0x28, 0x00, 0x35, 0x04, 0xbf, 0x00, 0x64, 0x06, 0x07, 0x00, 0x79, 0x02, 0x6f, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x67, 0x00, 0x65, 0x04, 0x2a, 0x00, 0x86, 0x06, 0x07, 0x00, 0x79, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x6c, 0x00, 0x96, 0x04, 0x75, 0x00, 0x65, 0x05, 0x07, 0x00, 0x4e, 0x06, 0x10, 0xff, 0xe5, 0x05, 0x07, 0x00, 0x4e, 0x04, 0xbf, 0x00, 0x64, 0x06, 0x07, 0x00, 0x3a, 0x04, 0xc7, 0x00, 0x64, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x04, 0xab, 0x00, 0x7d, 0x04, 0x39, 0x00, 0x65, 0x04, 0x24, 0x00, 0xb4, 0x03, 0x4d, 0xff, 0x54, 0x04, 0xbf, 0x00, 0xa1, 0x04, 0xbf, 0x00, 0xab, 0x06, 0x3a, 0x00, 0x66, 0x04, 0x84, 0x00, 0x6b, 0x06, 0xb8, 0x00, 0x67, 0x06, 0x07, 0x00, 0x79, 0x05, 0x75, 0x00, 0x67, 0x04, 0xbf, 0x00, 0x65, 0x05, 0xb2, 0x00, 0xb4, 0x04, 0x6d, 0x00, 0x28, 0x04, 0xf1, 0x00, 0x47, 0x04, 0x5e, 0x00, 0x5a, 0x05, 0x86, 0x00, 0x67, 0x04, 0x80, 0x00, 0x30, 0x05, 0x08, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x04, 0x65, 0x00, 0x27, 0x03, 0xdc, 0x00, 0x31, 0x04, 0xc7, 0x00, 0x64, 0x04, 0x92, 0x00, 0xa7, 0x03, 0xf5, 0x00, 0x65, 0x02, 0x00, 0xff, 0xdf, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x6e, 0x00, 0xb0, 0x04, 0x5b, 0x00, 0xb4, 0x04, 0x92, 0x00, 0xa7, 0x05, 0x07, 0x00, 0x67, 0x06, 0x36, 0x00, 0xb4, 0x04, 0xaf, 0x00, 0x72, 0x04, 0x92, 0x00, 0x4c, 0x05, 0x10, 0x00, 0x67, 0x05, 0x07, 0x00, 0x67, 0x05, 0x10, 0x00, 0x67, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x05, 0xa9, 0xff, 0xfb, 0x04, 0x64, 0x00, 0xb4, 0x05, 0x07, 0x00, 0x67, 0x04, 0x92, 0x00, 0x79, 0x02, 0x1f, 0x00, 0xb4, 0x02, 0x1f, 0x00, 0x05, 0x02, 0x1f, 0xff, 0xa1, 0x07, 0xe0, 0x00, 0x4b, 0x07, 0x86, 0x00, 0xb4, 0x05, 0xa9, 0xff, 0xfb, 0x05, 0x1c, 0x00, 0xb4, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x63, 0x00, 0x1f, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xf0, 0x00, 0xb4, 0x04, 0xf0, 0x00, 0xb4, 0x04, 0x64, 0x00, 0xb4, 0x05, 0xa0, 0x00, 0x5a, 0x04, 0x8c, 0x00, 0xb4, 0x07, 0xc1, 0x00, 0x24, 0x04, 0x9d, 0x00, 0x79, 0x05, 0x62, 0x00, 0xb4, 0x05, 0x62, 0x00, 0xb4, 0x05, 0x1c, 0x00, 0xb4, 0x05, 0x6a, 0x00, 0x4b, 0x06, 0x36, 0x00, 0xb4, 0x05, 0x6a, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x57, 0x00, 0xb4, 0x05, 0x07, 0x00, 0x67, 0x04, 0x65, 0xff, 0xfb, 0x04, 0x63, 0x00, 0x1f, 0x06, 0x32, 0x00, 0x6c, 0x04, 0xee, 0x00, 0x36, 0x05, 0x97, 0x00, 0xb4, 0x04, 0xef, 0x00, 0x9d, 0x07, 0xb3, 0x00, 0xb4, 0x07, 0xe0, 0x00, 0xb4, 0x05, 0xfe, 0x00, 0x36, 0x06, 0x5a, 0x00, 0xb4, 0x04, 0xf0, 0x00, 0xb4, 0x05, 0x07, 0x00, 0x63, 0x07, 0xc5, 0x00, 0xbd, 0x05, 0x00, 0x00, 0x7a, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x70, 0x00, 0x64, 0x04, 0x3e, 0x00, 0xa7, 0x03, 0xc8, 0x00, 0xa7, 0x04, 0xfa, 0x00, 0x60, 0x04, 0x6e, 0x00, 0x65, 0x06, 0x7c, 0x00, 0x3f, 0x03, 0xd4, 0x00, 0x77, 0x04, 0xad, 0x00, 0xa7, 0x04, 0xad, 0x00, 0xa7, 0x04, 0x59, 0x00, 0xa7, 0x04, 0x9a, 0x00, 0x44, 0x05, 0x6e, 0x00, 0xa7, 0x04, 0xb5, 0x00, 0xa7, 0x04, 0x67, 0x00, 0x65, 0x04, 0xb5, 0x00, 0xa7, 0x04, 0x92, 0x00, 0xa7, 0x03, 0xf5, 0x00, 0x65, 0x04, 0x31, 0x00, 0x36, 0x04, 0x42, 0x00, 0x36, 0x06, 0x27, 0x00, 0x64, 0x04, 0x42, 0x00, 0x35, 0x04, 0xe6, 0x00, 0xa7, 0x04, 0x41, 0x00, 0x87, 0x06, 0x96, 0x00, 0xa7, 0x06, 0xc8, 0x00, 0xa7, 0x05, 0x16, 0x00, 0x37, 0x05, 0xaf, 0x00, 0xa7, 0x04, 0x3e, 0x00, 0xa7, 0x03, 0xf3, 0x00, 0x65, 0x06, 0x0f, 0x00, 0xad, 0x04, 0x54, 0x00, 0x68, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x80, 0x00, 0x2a, 0x03, 0xc8, 0x00, 0xa7, 0x03, 0xf3, 0x00, 0x65, 0x03, 0xc0, 0x00, 0x63, 0x02, 0x00, 0x00, 0xad, 0x02, 0x00, 0xff, 0xf6, 0x02, 0x00, 0xff, 0xdf, 0x06, 0x7f, 0x00, 0x44, 0x06, 0x78, 0x00, 0xa7, 0x04, 0xb1, 0x00, 0x2a, 0x04, 0x59, 0x00, 0xa7, 0x04, 0xad, 0x00, 0xa7, 0x04, 0x42, 0x00, 0x36, 0x04, 0xb5, 0x00, 0xa7, 0x06, 0xb8, 0x00, 0x67, 0x06, 0x07, 0x00, 0x79, 0x05, 0x8c, 0x00, 0x1b, 0x04, 0xd6, 0x00, 0x1b, 0x06, 0xc9, 0x00, 0xbd, 0x05, 0x64, 0x00, 0xad, 0x06, 0x54, 0x00, 0x0e, 0x05, 0xa3, 0x00, 0x2d, 0x08, 0x59, 0x00, 0xb4, 0x07, 0x35, 0x00, 0xad, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x60, 0x07, 0x64, 0x00, 0xb4, 0x05, 0xef, 0x00, 0xad, 0x04, 0x94, 0x00, 0x67, 0x03, 0xe4, 0x00, 0x51, 0x06, 0x2a, 0x00, 0x0e, 0x06, 0x4f, 0x00, 0x2d, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xa0, 0x00, 0x0e, 0x04, 0xc9, 0x00, 0x2d, 0x05, 0xa0, 0x00, 0x0e, 0x04, 0xc9, 0x00, 0x2d, 0x07, 0x24, 0x00, 0x67, 0x06, 0x82, 0x00, 0x65, 0x06, 0xdc, 0x00, 0x67, 0x05, 0x75, 0x00, 0x65, 0x08, 0x7e, 0x00, 0x6a, 0x07, 0x66, 0x00, 0x88, 0x06, 0xb8, 0x00, 0x67, 0x06, 0x07, 0x00, 0x79, 0x05, 0x07, 0x00, 0x67, 0x03, 0xf5, 0x00, 0x65, 0x03, 0x9e, 0x00, 0x35, 0x00, 0x00, 0xfc, 0x45, 0x00, 0x00, 0xfd, 0x54, 0x00, 0x00, 0xfd, 0xee, 0x00, 0x00, 0xfd, 0xee, 0x00, 0x00, 0xfa, 0x69, 0x03, 0x02, 0xf8, 0xa7, 0x03, 0x02, 0xf9, 0x1c, 0x05, 0x8f, 0x00, 0xb4, 0x04, 0xdf, 0x00, 0xad, 0x04, 0xf0, 0x00, 0x1d, 0x04, 0x3e, 0x00, 0x22, 0x04, 0x57, 0x00, 0xb4, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x64, 0x00, 0xb4, 0x03, 0xc8, 0x00, 0xa7, 0x04, 0xdb, 0x00, 0x3f, 0x04, 0x40, 0x00, 0x32, 0x04, 0x7e, 0x00, 0xb4, 0x03, 0xd0, 0x00, 0xa7, 0x07, 0xc1, 0x00, 0x24, 0x06, 0x7c, 0x00, 0x3f, 0x04, 0x9d, 0x00, 0x79, 0x03, 0xd4, 0x00, 0x77, 0x05, 0x1c, 0x00, 0xb4, 0x04, 0x59, 0x00, 0xa7, 0x05, 0x1c, 0x00, 0xb4, 0x04, 0x59, 0x00, 0xa7, 0x05, 0x1c, 0x00, 0x1d, 0x04, 0x59, 0x00, 0x36, 0x06, 0x2a, 0x00, 0x2d, 0x05, 0xfc, 0x00, 0x25, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0xc1, 0x00, 0xad, 0x07, 0x4d, 0x00, 0xb4, 0x06, 0x50, 0x00, 0xad, 0x07, 0xc8, 0x00, 0xb4, 0x06, 0x97, 0x00, 0xad, 0x06, 0x52, 0x00, 0x67, 0x04, 0xfd, 0x00, 0x65, 0x05, 0x07, 0x00, 0x67, 0x03, 0xf5, 0x00, 0x65, 0x04, 0x65, 0xff, 0xfb, 0x04, 0x31, 0x00, 0x36, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x04, 0xee, 0x00, 0x36, 0x04, 0x42, 0x00, 0x35, 0x06, 0xb9, 0xff, 0xfb, 0x05, 0xce, 0x00, 0x04, 0x04, 0xef, 0x00, 0x9d, 0x04, 0x41, 0x00, 0x87, 0x04, 0xef, 0x00, 0x9d, 0x04, 0x41, 0x00, 0x87, 0x04, 0xef, 0x00, 0x9d, 0x04, 0x90, 0x00, 0xa7, 0x06, 0xc6, 0x00, 0x12, 0x05, 0x3d, 0x00, 0x0d, 0x06, 0xc6, 0x00, 0x12, 0x05, 0x3d, 0x00, 0x0d, 0x02, 0x1f, 0x00, 0xb4, 0x07, 0xc1, 0x00, 0x24, 0x06, 0x7c, 0x00, 0x3f, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x59, 0x00, 0xab, 0x05, 0x96, 0x00, 0x30, 0x04, 0xd3, 0x00, 0x29, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0xc1, 0x00, 0xad, 0x05, 0x97, 0x00, 0xb4, 0x04, 0xe6, 0x00, 0xad, 0x04, 0xef, 0x00, 0x9d, 0x04, 0x41, 0x00, 0x87, 0x06, 0x64, 0x00, 0xb4, 0x05, 0x93, 0x00, 0xad, 0x02, 0x00, 0x00, 0xad, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x07, 0x03, 0x00, 0x07, 0x07, 0x11, 0x00, 0x6e, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x69, 0x04, 0x6e, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x69, 0x04, 0x6e, 0x00, 0x65, 0x07, 0xc1, 0x00, 0x24, 0x06, 0x7c, 0x00, 0x3f, 0x04, 0x9d, 0x00, 0x79, 0x03, 0xd4, 0x00, 0x77, 0x04, 0xcb, 0x00, 0x90, 0x04, 0x28, 0x00, 0x4f, 0x05, 0x62, 0x00, 0xb4, 0x04, 0xad, 0x00, 0xa7, 0x05, 0x62, 0x00, 0xb4, 0x04, 0xad, 0x00, 0xa7, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0x07, 0x00, 0x63, 0x03, 0xf3, 0x00, 0x65, 0x04, 0x63, 0x00, 0x1f, 0x04, 0x42, 0x00, 0x36, 0x04, 0x63, 0x00, 0x1f, 0x04, 0x42, 0x00, 0x36, 0x04, 0x63, 0x00, 0x1f, 0x04, 0x42, 0x00, 0x36, 0x04, 0xef, 0x00, 0x9d, 0x04, 0x41, 0x00, 0x87, 0x04, 0x64, 0x00, 0xb4, 0x03, 0xc8, 0x00, 0xa7, 0x06, 0x5a, 0x00, 0xb4, 0x05, 0xaf, 0x00, 0xa7, 0x04, 0xdb, 0x00, 0x3f, 0x04, 0x40, 0x00, 0x32, 0x04, 0xee, 0x00, 0x36, 0x04, 0x42, 0x00, 0x35, 0x04, 0xee, 0x00, 0x36, 0x04, 0x42, 0x00, 0x35, 0x04, 0xf0, 0x00, 0x82, 0x04, 0x3e, 0x00, 0x65, 0x07, 0x3e, 0x00, 0x82, 0x06, 0x75, 0x00, 0x65, 0x07, 0x04, 0x00, 0xb4, 0x06, 0x42, 0x00, 0x99, 0x04, 0xe3, 0x00, 0xb4, 0x04, 0x3c, 0x00, 0x99, 0x07, 0xb7, 0x00, 0x30, 0x06, 0xe4, 0x00, 0x29, 0x08, 0x03, 0x00, 0xb4, 0x06, 0xf6, 0x00, 0xad, 0x05, 0x94, 0x00, 0x67, 0x04, 0xbf, 0x00, 0x65, 0x05, 0x90, 0xff, 0xfb, 0x05, 0x1e, 0x00, 0x04, 0x04, 0x6c, 0x00, 0x93, 0x03, 0xe4, 0x00, 0x77, 0x05, 0x6a, 0x00, 0x4b, 0x04, 0x9a, 0x00, 0x44, 0x08, 0x6a, 0x00, 0x4b, 0x07, 0x27, 0x00, 0x44, 0x06, 0x6f, 0x00, 0xb4, 0x06, 0x39, 0x00, 0xa7, 0x07, 0x6d, 0x00, 0x7a, 0x07, 0x19, 0x00, 0x68, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x07, 0x1e, 0x00, 0x3d, 0x05, 0xe3, 0x00, 0x4d, 0x05, 0x1c, 0x00, 0xb4, 0x04, 0x59, 0x00, 0xa7, 0x07, 0xc7, 0x00, 0x4b, 0x06, 0x84, 0x00, 0x44, 0x07, 0xc8, 0x00, 0xb4, 0x06, 0x91, 0x00, 0xa7, 0x05, 0xb5, 0x00, 0xb4, 0x04, 0xea, 0x00, 0xa7, 0x04, 0x42, 0x00, 0x36, 0x05, 0x2a, 0x00, 0x09, 0x07, 0x11, 0x00, 0x6e, 0x04, 0x38, 0x00, 0x37, 0x03, 0xf5, 0x00, 0x65, 0x04, 0x5b, 0x00, 0xa7, 0x04, 0x5b, 0x00, 0x20, 0x03, 0x88, 0x00, 0xa7, 0x03, 0xe4, 0x00, 0x75, 0x02, 0x00, 0x00, 0xad, 0x02, 0xd7, 0x00, 0x00, 0x04, 0x2b, 0x00, 0xa7, 0x04, 0x32, 0x00, 0x01, 0x05, 0x6e, 0x00, 0xa7, 0x04, 0xad, 0x00, 0xa7, 0x04, 0x67, 0x00, 0x65, 0x03, 0xf5, 0x00, 0x72, 0x04, 0xec, 0x00, 0x65, 0x04, 0xec, 0x00, 0x65, 0x04, 0xec, 0x00, 0x2d, 0x07, 0x5d, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x03, 0xc6, 0x00, 0x87, 0x04, 0x54, 0x00, 0x2d, 0x04, 0x54, 0x00, 0x2d, 0x04, 0x31, 0x00, 0x36, 0x04, 0x22, 0x00, 0xa7, 0x05, 0x4e, 0x00, 0x9c, 0x06, 0xd2, 0x00, 0x9c, 0x04, 0x97, 0x00, 0x2a, 0x04, 0x42, 0x00, 0x36, 0x05, 0xe3, 0x00, 0x4d, 0x03, 0xc7, 0x00, 0x4f, 0x03, 0xc9, 0x00, 0x6c, 0x04, 0x32, 0x00, 0xa1, 0x04, 0x42, 0x00, 0x36, 0x04, 0x0f, 0x00, 0x87, 0x03, 0xc6, 0x00, 0x87, 0x04, 0x40, 0x00, 0x51, 0x04, 0x9a, 0x00, 0x44, 0x03, 0x19, 0x00, 0x09, 0x04, 0x6a, 0x00, 0x04, 0x03, 0x1c, 0x00, 0x72, 0x03, 0x7d, 0x00, 0x72, 0x02, 0xdd, 0x00, 0x72, 0x02, 0xdd, 0x00, 0x4a, 0x03, 0x83, 0x00, 0x40, 0x03, 0x69, 0x00, 0x72, 0x01, 0x56, 0x00, 0x72, 0x01, 0x56, 0xff, 0xc4, 0x02, 0xf9, 0x00, 0x72, 0x02, 0x86, 0x00, 0x72, 0x03, 0xe9, 0x00, 0x72, 0x03, 0x64, 0x00, 0x72, 0x03, 0x64, 0x00, 0x72, 0x03, 0x91, 0x00, 0x40, 0x03, 0x2a, 0x00, 0x3f, 0x02, 0xbc, 0x00, 0x72, 0x03, 0x26, 0x00, 0x72, 0x02, 0xc5, 0xff, 0xfd, 0x03, 0x51, 0x00, 0x64, 0x04, 0x7b, 0x00, 0x26, 0x02, 0xd1, 0x00, 0x45, 0x02, 0xd1, 0x00, 0x45, 0x02, 0xeb, 0x00, 0x3f, 0x04, 0xaa, 0x00, 0x45, 0x03, 0x15, 0x00, 0x69, 0x02, 0xeb, 0x00, 0x3f, 0x03, 0x00, 0x00, 0x3f, 0x03, 0x00, 0x00, 0x3f, 0x02, 0x98, 0x00, 0x4b, 0x02, 0x96, 0x00, 0x49, 0x02, 0xeb, 0x00, 0x3f, 0x01, 0x49, 0x00, 0x6d, 0x03, 0x10, 0x00, 0x69, 0x04, 0x7c, 0x00, 0x69, 0x02, 0xf1, 0x00, 0x69, 0x02, 0xfa, 0x00, 0x3f, 0x02, 0xaa, 0x00, 0x3f, 0x02, 0xfa, 0x00, 0x3f, 0x02, 0xfa, 0x00, 0x3f, 0x03, 0x15, 0x00, 0x69, 0x02, 0x1f, 0x00, 0x1f, 0x02, 0xea, 0x00, 0x63, 0x03, 0x61, 0x00, 0x63, 0x04, 0x7c, 0x00, 0x69, 0x03, 0x00, 0x00, 0x22, 0x02, 0xe4, 0x00, 0x6c, 0x02, 0xae, 0x00, 0x12, 0x02, 0xc6, 0x00, 0x3f, 0x02, 0xfd, 0x00, 0x3f, 0x02, 0x9e, 0x00, 0x21, 0x01, 0x49, 0x00, 0x6d, 0x01, 0xdd, 0x00, 0x69, 0x02, 0xea, 0x00, 0x63, 0x03, 0x00, 0x00, 0x22, 0x02, 0xe4, 0x00, 0x6c, 0x02, 0xae, 0x00, 0x12, 0x02, 0xf6, 0x00, 0x6c, 0x02, 0xfd, 0x00, 0x3f, 0x02, 0x9e, 0x00, 0x21, 0x04, 0x92, 0x00, 0xa7, 0x03, 0x69, 0x00, 0x72, 0x02, 0xac, 0x00, 0x68, 0x04, 0xcd, 0x00, 0x2d, 0x02, 0x00, 0x00, 0x82, 0x02, 0xeb, 0x00, 0x3f, 0x02, 0xaa, 0x00, 0x3f, 0x02, 0xaa, 0x00, 0x3f, 0x02, 0xfa, 0x00, 0x3f, 0x02, 0x98, 0x00, 0x4b, 0x02, 0x22, 0x00, 0x1b, 0x01, 0xad, 0xff, 0xec, 0x02, 0xeb, 0x00, 0x3f, 0x02, 0xea, 0x00, 0x63, 0x01, 0xe1, 0x00, 0x41, 0x01, 0xcb, 0x00, 0x6d, 0x01, 0xe0, 0x00, 0x41, 0x01, 0xe1, 0x00, 0x41, 0x01, 0xb0, 0xff, 0x67, 0x01, 0xcb, 0x00, 0x6d, 0x01, 0xb0, 0x00, 0x51, 0x02, 0xb5, 0x00, 0x65, 0x04, 0x7c, 0x00, 0x69, 0x04, 0x7c, 0x00, 0x69, 0x02, 0xf4, 0xff, 0xec, 0x03, 0x73, 0x00, 0x69, 0x02, 0xf1, 0x00, 0x65, 0x02, 0xfa, 0x00, 0x3f, 0x02, 0xfa, 0x00, 0x3f, 0x02, 0x98, 0x00, 0x3f, 0x02, 0x10, 0xff, 0xec, 0x02, 0x1f, 0x00, 0x1f, 0x03, 0xa8, 0x00, 0x54, 0x03, 0x03, 0x00, 0x3f, 0x02, 0x9a, 0x00, 0x69, 0x02, 0xec, 0x00, 0x6d, 0x03, 0x00, 0x00, 0x22, 0x02, 0xa3, 0x00, 0x31, 0x03, 0x24, 0x00, 0x31, 0x02, 0xa3, 0x00, 0x31, 0x02, 0xd2, 0x00, 0x31, 0x02, 0xfa, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0xb9, 0x00, 0x00, 0xfc, 0xb9, 0x00, 0x00, 0xfc, 0xb9, 0x00, 0x00, 0xfc, 0xb9, 0x00, 0x00, 0xfc, 0xa2, 0x00, 0x00, 0xfc, 0xa2, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xf0, 0x00, 0xb4, 0x04, 0x92, 0x00, 0xa5, 0x04, 0xf0, 0x00, 0xb4, 0x04, 0x92, 0x00, 0xa7, 0x04, 0xf0, 0x00, 0xb4, 0x04, 0x92, 0x00, 0xa7, 0x05, 0x07, 0x00, 0x67, 0x03, 0xf5, 0x00, 0x65, 0x05, 0x8b, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x65, 0x05, 0x8b, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x65, 0x05, 0x8b, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x65, 0x05, 0x8b, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x65, 0x05, 0x8b, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x24, 0x00, 0xb4, 0x02, 0x88, 0x00, 0x2a, 0x05, 0x94, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa5, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x90, 0xff, 0xef, 0x05, 0x6a, 0x00, 0x0f, 0x04, 0x90, 0x00, 0x01, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x02, 0x1f, 0x00, 0x00, 0x02, 0x00, 0xff, 0xd8, 0x02, 0x1f, 0x00, 0x06, 0x02, 0x00, 0xff, 0xf6, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x2b, 0x00, 0xa7, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x2b, 0x00, 0xa7, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x2b, 0x00, 0xa7, 0x04, 0x02, 0x00, 0xb4, 0x02, 0x12, 0x00, 0xb4, 0x04, 0x02, 0x00, 0x02, 0x02, 0x12, 0xff, 0xfe, 0x04, 0x02, 0x00, 0xb4, 0x02, 0x00, 0xff, 0xf6, 0x04, 0x02, 0x00, 0xb4, 0x02, 0x00, 0xff, 0xe2, 0x06, 0x36, 0x00, 0xb4, 0x07, 0x03, 0x00, 0xa7, 0x06, 0x36, 0x00, 0xb4, 0x07, 0x03, 0x00, 0xa7, 0x06, 0x36, 0x00, 0xb4, 0x07, 0x03, 0x00, 0xa7, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0x62, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x04, 0x57, 0x00, 0xb4, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x57, 0x00, 0xb4, 0x04, 0x92, 0x00, 0xa7, 0x05, 0x00, 0x00, 0xb4, 0x02, 0xf5, 0x00, 0xa7, 0x05, 0x00, 0x00, 0xb4, 0x02, 0xf5, 0x00, 0xa7, 0x05, 0x00, 0x00, 0xb4, 0x02, 0xf5, 0x00, 0xa7, 0x05, 0x00, 0x00, 0xb4, 0x02, 0xf5, 0x00, 0x4b, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x92, 0x00, 0x79, 0x03, 0xc0, 0x00, 0x63, 0x04, 0x65, 0xff, 0xfb, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x65, 0xff, 0xfb, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x65, 0xff, 0xfb, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x65, 0xff, 0xfb, 0x02, 0xd2, 0x00, 0x31, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x42, 0x00, 0x36, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x42, 0x00, 0x36, 0x07, 0x1e, 0x00, 0x3d, 0x05, 0xe3, 0x00, 0x4d, 0x07, 0x1e, 0x00, 0x3d, 0x05, 0xe3, 0x00, 0x4d, 0x07, 0x1e, 0x00, 0x3d, 0x05, 0xe3, 0x00, 0x4d, 0x07, 0x1e, 0x00, 0x3d, 0x05, 0xe3, 0x00, 0x4d, 0x07, 0x1e, 0x00, 0x3d, 0x05, 0xe3, 0x00, 0x4d, 0x04, 0xee, 0x00, 0x36, 0x04, 0x42, 0x00, 0x35, 0x04, 0xee, 0x00, 0x36, 0x04, 0x42, 0x00, 0x35, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0x90, 0x00, 0xa7, 0x02, 0xd2, 0x00, 0x03, 0x05, 0xe3, 0x00, 0x4d, 0x04, 0x42, 0x00, 0x36, 0x04, 0x69, 0x00, 0x6e, 0x02, 0x88, 0x00, 0x2a, 0x02, 0x88, 0x00, 0x01, 0x02, 0x88, 0x00, 0x2a, 0x05, 0x88, 0x00, 0xa0, 0x04, 0x67, 0x00, 0x65, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x6e, 0x00, 0x65, 0x02, 0x1f, 0x00, 0x51, 0x02, 0x00, 0x00, 0x3d, 0x02, 0x1f, 0x00, 0xb4, 0x02, 0x00, 0x00, 0xab, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x67, 0x00, 0x65, 0x06, 0x93, 0x00, 0x5c, 0x04, 0x67, 0x00, 0x6a, 0x06, 0x93, 0x00, 0x5c, 0x04, 0x67, 0x00, 0x6a, 0x06, 0x93, 0x00, 0x5c, 0x04, 0x67, 0x00, 0x6a, 0x06, 0x93, 0x00, 0x5c, 0x04, 0x67, 0x00, 0x6a, 0x06, 0x93, 0x00, 0x5c, 0x04, 0x67, 0x00, 0x6a, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x05, 0x45, 0x00, 0xa0, 0x04, 0x90, 0x00, 0x9c, 0x06, 0x2d, 0x00, 0x9b, 0x04, 0x90, 0x00, 0x9e, 0x06, 0x2d, 0x00, 0x9b, 0x04, 0x90, 0x00, 0x9e, 0x06, 0x2d, 0x00, 0x9b, 0x04, 0x90, 0x00, 0x9e, 0x06, 0x2d, 0x00, 0x9b, 0x04, 0x90, 0x00, 0x9e, 0x06, 0x2d, 0x00, 0x9b, 0x04, 0x90, 0x00, 0x9e, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x42, 0x00, 0x36, 0x05, 0x89, 0x00, 0xb4, 0x03, 0x6f, 0x00, 0x1c, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x06, 0x51, 0x00, 0x04, 0x06, 0x51, 0x00, 0x05, 0x05, 0x89, 0x00, 0x06, 0x05, 0xc4, 0x00, 0x04, 0x05, 0x19, 0x00, 0x06, 0x05, 0x58, 0x00, 0x03, 0x03, 0xe4, 0x00, 0x77, 0x03, 0xe4, 0x00, 0x77, 0x03, 0xe4, 0x00, 0x77, 0x03, 0xe4, 0x00, 0x77, 0x03, 0xe4, 0x00, 0x77, 0x03, 0xe4, 0x00, 0x77, 0x05, 0x1e, 0x00, 0x06, 0x05, 0x1e, 0x00, 0x06, 0x06, 0xf4, 0x00, 0x04, 0x07, 0x04, 0x00, 0x05, 0x06, 0x78, 0x00, 0x06, 0x06, 0xae, 0x00, 0x04, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x06, 0x06, 0x00, 0x06, 0x06, 0x03, 0x00, 0x06, 0x07, 0xd1, 0x00, 0x04, 0x07, 0xd7, 0x00, 0x05, 0x07, 0x64, 0x00, 0x06, 0x07, 0x90, 0x00, 0x04, 0x06, 0xb8, 0x00, 0x06, 0x06, 0xd1, 0x00, 0x03, 0x02, 0x6f, 0x00, 0x8b, 0x02, 0x6f, 0x00, 0x82, 0x02, 0x6f, 0xff, 0xb9, 0x02, 0x6f, 0xff, 0xc2, 0x02, 0x6f, 0x00, 0x04, 0x02, 0x6f, 0xff, 0xd8, 0x02, 0x6f, 0xff, 0xd1, 0x02, 0x6f, 0xff, 0xcc, 0x02, 0xbc, 0x00, 0x06, 0x02, 0xb1, 0x00, 0x06, 0x04, 0x92, 0x00, 0x04, 0x04, 0x92, 0x00, 0x05, 0x04, 0x1b, 0x00, 0x06, 0x04, 0x51, 0x00, 0x04, 0x03, 0x85, 0x00, 0x06, 0x03, 0x8c, 0x00, 0x03, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x05, 0xca, 0x00, 0x06, 0x06, 0x1b, 0x00, 0x06, 0x07, 0xe1, 0x00, 0x04, 0x07, 0xea, 0x00, 0x05, 0x06, 0xc1, 0x00, 0x06, 0x06, 0xfc, 0x00, 0x04, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x05, 0xa4, 0x00, 0x06, 0x07, 0x2e, 0x00, 0x05, 0x07, 0x49, 0x00, 0x04, 0x06, 0x76, 0x00, 0x03, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x05, 0xc6, 0x00, 0x06, 0x06, 0x12, 0x00, 0x06, 0x07, 0xd7, 0x00, 0x04, 0x07, 0xe2, 0x00, 0x05, 0x06, 0xcf, 0x00, 0x06, 0x06, 0xff, 0x00, 0x04, 0x06, 0xa2, 0x00, 0x06, 0x06, 0xdb, 0x00, 0x03, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x03, 0xe4, 0x00, 0x77, 0x03, 0xf2, 0x00, 0x77, 0x04, 0x90, 0x00, 0xa7, 0x04, 0xb6, 0x00, 0xa7, 0x02, 0x6f, 0xff, 0x99, 0x02, 0x6f, 0x00, 0x95, 0x04, 0x67, 0x00, 0x65, 0x04, 0x67, 0x00, 0x65, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x06, 0x51, 0x00, 0x04, 0x06, 0x51, 0x00, 0x05, 0x05, 0x89, 0x00, 0x06, 0x05, 0xc4, 0x00, 0x04, 0x05, 0x19, 0x00, 0x06, 0x05, 0x58, 0x00, 0x03, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x06, 0x06, 0x00, 0x06, 0x06, 0x03, 0x00, 0x06, 0x07, 0xd1, 0x00, 0x04, 0x07, 0xd7, 0x00, 0x05, 0x07, 0x64, 0x00, 0x06, 0x07, 0x90, 0x00, 0x04, 0x06, 0xb8, 0x00, 0x06, 0x06, 0xd1, 0x00, 0x03, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x05, 0xc6, 0x00, 0x06, 0x06, 0x12, 0x00, 0x06, 0x07, 0xd7, 0x00, 0x04, 0x07, 0xe2, 0x00, 0x05, 0x06, 0xcf, 0x00, 0x06, 0x06, 0xff, 0x00, 0x04, 0x06, 0xa2, 0x00, 0x06, 0x06, 0xdb, 0x00, 0x03, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xbf, 0x00, 0x65, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x05, 0x28, 0xff, 0xfd, 0x04, 0xfc, 0x00, 0x0e, 0x04, 0xec, 0x00, 0x0e, 0x03, 0x99, 0x01, 0x5f, 0x03, 0x99, 0x01, 0x8a, 0x03, 0x99, 0x01, 0x5f, 0x03, 0x99, 0x00, 0xa3, 0x03, 0x99, 0x00, 0xa3, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0xb6, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x05, 0xcb, 0xff, 0xfd, 0x05, 0x5f, 0xff, 0xea, 0x06, 0xb3, 0xff, 0xfd, 0x06, 0x45, 0xff, 0xf5, 0x05, 0x6a, 0x00, 0xb4, 0x03, 0x99, 0x00, 0x7b, 0x03, 0x99, 0x00, 0xa2, 0x03, 0x99, 0x00, 0xa3, 0x02, 0x6f, 0xff, 0xee, 0x02, 0x6f, 0xff, 0xe6, 0x02, 0x6f, 0xff, 0xdc, 0x02, 0x6f, 0x00, 0x04, 0x02, 0x6f, 0xff, 0xe7, 0x02, 0x6f, 0xff, 0xe9, 0x02, 0x1f, 0xff, 0xf7, 0x02, 0x1f, 0x00, 0x02, 0x03, 0x6b, 0xff, 0xfd, 0x02, 0xf0, 0xff, 0xef, 0x03, 0x99, 0x00, 0x71, 0x03, 0x99, 0x00, 0x86, 0x03, 0x99, 0x00, 0xa3, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x2a, 0x00, 0x86, 0x04, 0x65, 0xff, 0xfd, 0x04, 0x65, 0xff, 0xfd, 0x06, 0x15, 0xff, 0xfd, 0x05, 0xf0, 0xff, 0xe5, 0x04, 0xee, 0x00, 0x06, 0x03, 0x99, 0x00, 0x99, 0x03, 0x99, 0x00, 0xc1, 0x03, 0x99, 0x00, 0x99, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0x07, 0x00, 0x79, 0x06, 0xc6, 0xff, 0xfd, 0x05, 0xd9, 0xff, 0xf4, 0x06, 0xa4, 0xff, 0xfd, 0x05, 0xf1, 0xff, 0xdf, 0x05, 0x80, 0x00, 0x46, 0x03, 0x99, 0x01, 0x4d, 0x03, 0x99, 0x01, 0x5f, 0x03, 0x99, 0x00, 0x00, 0x07, 0x33, 0x00, 0x00, 0x03, 0x99, 0x00, 0x00, 0x07, 0x33, 0x00, 0x00, 0x02, 0x5f, 0x00, 0x00, 0x01, 0xcc, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x04, 0x94, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x99, 0x00, 0x5a, 0x02, 0x99, 0x00, 0x5a, 0x04, 0x94, 0x00, 0x5a, 0x03, 0x99, 0x00, 0x5a, 0x07, 0x33, 0x00, 0x5a, 0x07, 0x33, 0x00, 0x00, 0x03, 0x99, 0x00, 0xea, 0x03, 0x99, 0xff, 0xee, 0x02, 0x49, 0x00, 0x9c, 0x02, 0x49, 0x00, 0xa0, 0x02, 0x49, 0x00, 0x9c, 0x02, 0x49, 0x00, 0xa0, 0x03, 0xba, 0x00, 0x9c, 0x03, 0xba, 0x00, 0x9c, 0x03, 0xba, 0x00, 0x9c, 0x03, 0xba, 0x00, 0x9c, 0x03, 0x99, 0x00, 0x33, 0x03, 0x99, 0x00, 0x33, 0x04, 0x3f, 0x01, 0x14, 0x04, 0x3f, 0x01, 0x14, 0x02, 0x68, 0x00, 0xd4, 0x04, 0xce, 0x00, 0xd4, 0x07, 0x33, 0x00, 0xd4, 0x02, 0x49, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x09, 0xa9, 0x00, 0x65, 0x0c, 0x7e, 0x00, 0x65, 0x01, 0xa2, 0x00, 0x24, 0x02, 0xb0, 0x00, 0x24, 0x03, 0xbe, 0x00, 0x24, 0x01, 0xa2, 0x00, 0x24, 0x02, 0xb0, 0x00, 0x24, 0x03, 0xbe, 0x00, 0x24, 0x02, 0x70, 0x00, 0x09, 0x02, 0xe1, 0x00, 0x8e, 0x02, 0xe1, 0x00, 0xad, 0x06, 0x08, 0x00, 0xaf, 0x03, 0x7e, 0x00, 0x84, 0x03, 0xd2, 0x00, 0x84, 0x03, 0x99, 0xff, 0xee, 0x05, 0xc9, 0xff, 0xb0, 0x05, 0xc9, 0xff, 0xb0, 0x01, 0xcc, 0xff, 0xb3, 0x07, 0x33, 0x00, 0x36, 0x03, 0x99, 0x00, 0xc6, 0x01, 0x33, 0xfe, 0xaf, 0x02, 0xcf, 0x00, 0x9e, 0x02, 0xcf, 0x00, 0x9e, 0x06, 0xa3, 0x00, 0x42, 0x05, 0x46, 0x00, 0x84, 0x05, 0x46, 0x00, 0x84, 0x03, 0x94, 0x00, 0x5a, 0x04, 0x94, 0x00, 0xd4, 0x03, 0x99, 0x00, 0xc2, 0x03, 0x99, 0x00, 0xc2, 0x03, 0x99, 0x00, 0x36, 0x02, 0x6d, 0x01, 0x00, 0x05, 0xc9, 0xff, 0xb0, 0x03, 0x99, 0x00, 0x36, 0x03, 0x3c, 0x00, 0x82, 0x07, 0x33, 0x00, 0x5a, 0x05, 0xc9, 0xff, 0xb0, 0x06, 0x08, 0x01, 0x18, 0x04, 0x38, 0x00, 0xe1, 0x04, 0xc6, 0x00, 0x24, 0x06, 0x08, 0x01, 0x42, 0x06, 0x08, 0x01, 0x42, 0x02, 0x49, 0x00, 0xc5, 0x05, 0xbd, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x64, 0x02, 0x49, 0x00, 0xc5, 0x02, 0x49, 0x00, 0xc5, 0x01, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe2, 0x00, 0x4e, 0x01, 0x49, 0x00, 0x6d, 0x02, 0xe2, 0x00, 0x38, 0x02, 0xe2, 0x00, 0x5b, 0x02, 0xe2, 0x00, 0x52, 0x02, 0xe2, 0x00, 0x61, 0x02, 0xe2, 0x00, 0x50, 0x02, 0xe2, 0x00, 0x4a, 0x03, 0xcc, 0x00, 0x7b, 0x03, 0xcc, 0x00, 0x7b, 0x03, 0xcc, 0x00, 0x7b, 0x01, 0xc4, 0x00, 0x63, 0x01, 0xc4, 0x00, 0x5c, 0x02, 0xde, 0x00, 0x69, 0x02, 0xe2, 0x00, 0x4e, 0x02, 0xe2, 0x00, 0x7b, 0x02, 0xe2, 0x00, 0x54, 0x02, 0xe2, 0x00, 0x58, 0x02, 0xe2, 0x00, 0x38, 0x02, 0xe2, 0x00, 0x5b, 0x02, 0xe2, 0x00, 0x52, 0x02, 0xe2, 0x00, 0x61, 0x02, 0xe2, 0x00, 0x50, 0x02, 0xe2, 0x00, 0x4a, 0x03, 0xcc, 0x00, 0x7b, 0x03, 0xcc, 0x00, 0x7b, 0x03, 0xcc, 0x00, 0x7b, 0x01, 0xc4, 0x00, 0x63, 0x01, 0xc4, 0x00, 0x5c, 0x02, 0xd1, 0x00, 0x45, 0x03, 0x00, 0x00, 0x3f, 0x02, 0xfa, 0x00, 0x3f, 0x03, 0x32, 0x00, 0x69, 0x03, 0x00, 0x00, 0x3f, 0x02, 0xe9, 0x00, 0x69, 0x03, 0x10, 0x00, 0x69, 0x01, 0x32, 0x00, 0x6d, 0x04, 0x7c, 0x00, 0x69, 0x02, 0xde, 0x00, 0x69, 0x03, 0x15, 0x00, 0x69, 0x02, 0xaf, 0x00, 0x69, 0x02, 0x1f, 0x00, 0x1f, 0x06, 0x50, 0x00, 0x4d, 0x04, 0x94, 0x00, 0x67, 0x04, 0x94, 0x00, 0x56, 0x04, 0x94, 0x00, 0x77, 0x04, 0x94, 0x00, 0x74, 0x07, 0x03, 0x00, 0xa7, 0x05, 0x62, 0x00, 0x69, 0x09, 0x29, 0x00, 0xb4, 0x07, 0xbb, 0x00, 0xb4, 0x07, 0x1e, 0x00, 0x35, 0x05, 0xa5, 0x00, 0x55, 0x04, 0x94, 0x00, 0x65, 0x04, 0x94, 0x00, 0x00, 0x04, 0x94, 0x00, 0x24, 0x04, 0x94, 0x00, 0x12, 0x09, 0x29, 0x00, 0xbb, 0x04, 0x94, 0x00, 0x29, 0x04, 0x94, 0x00, 0x3d, 0x04, 0x94, 0x00, 0x53, 0x04, 0x94, 0x00, 0x0e, 0x05, 0x92, 0x00, 0x69, 0x04, 0x94, 0x00, 0x94, 0x04, 0x94, 0x00, 0x12, 0x04, 0x94, 0x00, 0x5f, 0x04, 0xe3, 0x00, 0x09, 0x00, 0x00, 0xfc, 0x77, 0x00, 0x00, 0xfc, 0x9e, 0x00, 0x00, 0xfc, 0x9e, 0x00, 0x00, 0xfc, 0x9e, 0x00, 0x00, 0xfc, 0x78, 0x00, 0x00, 0xfb, 0xc8, 0x00, 0x00, 0xfc, 0x9e, 0x07, 0x55, 0x00, 0x3c, 0x07, 0x55, 0x00, 0x3c, 0x05, 0x07, 0x00, 0x67, 0x08, 0x16, 0x00, 0xaf, 0x04, 0x9f, 0xff, 0xdb, 0x07, 0x55, 0x00, 0x36, 0x07, 0xae, 0x00, 0x36, 0x04, 0x6c, 0x00, 0x93, 0x05, 0x07, 0x00, 0x63, 0x06, 0xda, 0x00, 0xaf, 0x07, 0x1d, 0x00, 0x41, 0x05, 0x6e, 0x00, 0x01, 0x06, 0x1e, 0x00, 0xb4, 0x04, 0x90, 0x00, 0x40, 0x04, 0x90, 0x00, 0x51, 0x03, 0x61, 0x00, 0x35, 0x05, 0x05, 0x00, 0x5f, 0x05, 0x2f, 0x00, 0x3d, 0x02, 0xf9, 0xff, 0xe7, 0x05, 0xe3, 0x00, 0x1c, 0x05, 0xc4, 0x00, 0xb2, 0x07, 0x7d, 0x00, 0x30, 0x07, 0x33, 0x00, 0xfe, 0x05, 0x05, 0x00, 0x63, 0x05, 0x0c, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x05, 0xbe, 0x00, 0x3b, 0x05, 0xdc, 0x00, 0x4a, 0x05, 0xb3, 0x00, 0xb4, 0x06, 0x74, 0x00, 0x98, 0x04, 0xec, 0x00, 0xb4, 0x07, 0x57, 0x00, 0xe9, 0x07, 0xbc, 0xff, 0xfd, 0x07, 0x33, 0x01, 0x09, 0x04, 0xec, 0x00, 0x0e, 0x05, 0x5c, 0x00, 0x52, 0x04, 0x28, 0x00, 0x4f, 0x05, 0x80, 0x00, 0x46, 0x05, 0x80, 0x00, 0x46, 0x04, 0x6f, 0x00, 0x15, 0x02, 0x6f, 0x00, 0x3d, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0xec, 0x00, 0x0e, 0x05, 0xa9, 0x00, 0x52, 0x05, 0x10, 0x00, 0x75, 0x06, 0x27, 0x00, 0x70, 0x04, 0x42, 0x00, 0x4e, 0x04, 0x5c, 0x00, 0x91, 0x05, 0xa9, 0x00, 0x4b, 0x04, 0x24, 0x00, 0xb4, 0x07, 0xb3, 0x00, 0x33, 0x03, 0x53, 0x00, 0x5d, 0x05, 0x5d, 0x00, 0x5c, 0x04, 0xda, 0xff, 0xfc, 0x03, 0x5a, 0x00, 0x18, 0x04, 0xa4, 0x00, 0x4d, 0x02, 0xbc, 0x00, 0x3f, 0x06, 0xaa, 0x00, 0x51, 0x08, 0x98, 0x00, 0x87, 0x05, 0x0e, 0x00, 0x20, 0x05, 0x3d, 0x00, 0x00, 0x04, 0xb6, 0x00, 0xb4, 0x06, 0x1c, 0x00, 0xb4, 0x05, 0xd6, 0x00, 0x16, 0x05, 0x94, 0x00, 0x92, 0x04, 0x02, 0x00, 0x07, 0x04, 0x02, 0x00, 0x06, 0x04, 0x65, 0xff, 0xfd, 0x05, 0xe5, 0x00, 0x4e, 0x05, 0x19, 0x00, 0x51, 0x04, 0x6e, 0x00, 0x51, 0x02, 0x87, 0x00, 0x47, 0x02, 0x87, 0xff, 0x2e, 0x05, 0x9d, 0x00, 0x35, 0x03, 0xca, 0x00, 0x48, 0x06, 0xfa, 0x00, 0x7b, 0x06, 0xfa, 0x00, 0x7b, 0x09, 0xdd, 0x00, 0x7b, 0x06, 0xfa, 0x00, 0x7b, 0x06, 0xfa, 0x00, 0x54, 0x06, 0xfa, 0x00, 0x7b, 0x06, 0xfa, 0x00, 0x54, 0x06, 0xfa, 0x00, 0x58, 0x06, 0xfa, 0x00, 0x38, 0x06, 0xfa, 0x00, 0x7b, 0x06, 0xfa, 0x00, 0x5b, 0x06, 0xfa, 0x00, 0x7b, 0x06, 0xfa, 0x00, 0x58, 0x06, 0xfa, 0x00, 0x5b, 0x06, 0xfa, 0x00, 0x61, 0x04, 0x16, 0x00, 0x7b, 0x02, 0x1f, 0x00, 0xb4, 0x03, 0x8b, 0x00, 0xb4, 0x04, 0xf6, 0x00, 0xb4, 0x06, 0xa5, 0x00, 0xb4, 0x04, 0xec, 0x00, 0x0e, 0x06, 0xa4, 0x00, 0x0e, 0x08, 0x0f, 0x00, 0x0e, 0x09, 0x7b, 0x00, 0x0e, 0x06, 0x9b, 0x00, 0xb4, 0x04, 0xee, 0x00, 0x36, 0x06, 0xb7, 0x00, 0x36, 0x08, 0x25, 0x00, 0x36, 0x04, 0x02, 0x00, 0xb4, 0x05, 0x07, 0x00, 0x67, 0x05, 0x8b, 0x00, 0xb4, 0x06, 0x36, 0x00, 0xb4, 0x02, 0x00, 0x00, 0xad, 0x03, 0x4b, 0x00, 0xad, 0x04, 0x96, 0x00, 0xad, 0x05, 0xd7, 0x00, 0xad, 0x04, 0x42, 0x00, 0x36, 0x05, 0xd6, 0x00, 0x36, 0x07, 0x22, 0x00, 0x36, 0x08, 0x6d, 0x00, 0x36, 0x05, 0xe5, 0x00, 0xad, 0x04, 0x42, 0x00, 0x35, 0x05, 0xeb, 0x00, 0x35, 0x07, 0x36, 0x00, 0x35, 0x02, 0x00, 0x00, 0xad, 0x03, 0xf5, 0x00, 0x65, 0x04, 0x92, 0x00, 0x65, 0x07, 0x03, 0x00, 0xa7, 0x08, 0xf7, 0x00, 0x6c, 0x05, 0x8b, 0x00, 0xb4, 0x08, 0xf7, 0x00, 0x6c, 0x05, 0x10, 0x00, 0x67, 0x03, 0xf4, 0x00, 0x72, 0x05, 0x07, 0x00, 0x67, 0x06, 0xfa, 0x00, 0x4e, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x27, 0x06, 0x08, 0x00, 0x13, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x01, 0x7a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x01, 0x7a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x01, 0x7a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x01, 0x7a, 0x06, 0x08, 0x01, 0x7a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x6a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x6a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x01, 0x0c, 0x06, 0x08, 0x01, 0x37, 0x06, 0x08, 0x01, 0x81, 0x06, 0x08, 0x01, 0x37, 0x06, 0x08, 0x01, 0x81, 0x06, 0x08, 0x01, 0xad, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x28, 0x06, 0x08, 0x00, 0x47, 0x06, 0x08, 0x00, 0xc7, 0x06, 0x08, 0x00, 0x64, 0x06, 0x08, 0x00, 0xbd, 0x06, 0x08, 0x00, 0x8d, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x02, 0xb7, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x02, 0xb7, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x6b, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x6c, 0x06, 0x08, 0x00, 0x6a, 0x06, 0x08, 0x00, 0x6c, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x01, 0x7a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x01, 0x7a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x01, 0x7a, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x00, 0xa9, 0x06, 0x08, 0x00, 0xa9, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x00, 0x60, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x31, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x00, 0x40, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x01, 0x20, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x6d, 0x06, 0x08, 0x00, 0x6d, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x6b, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x31, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x31, 0x04, 0xec, 0x00, 0x0e, 0x04, 0x94, 0x00, 0x79, 0x03, 0xb9, 0x00, 0x55, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x06, 0x45, 0x00, 0x8b, 0x04, 0xd1, 0xff, 0xfb, 0x04, 0xd1, 0xff, 0xfb, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x05, 0x2b, 0x00, 0xc3, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x05, 0x2b, 0x00, 0xc3, 0x04, 0x94, 0x01, 0x0e, 0x05, 0x73, 0x00, 0x8c, 0x05, 0x73, 0x00, 0x8c, 0x04, 0xda, 0x00, 0x16, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x02, 0x6d, 0x00, 0x00, 0x04, 0x95, 0x01, 0x62, 0x06, 0x08, 0x00, 0xeb, 0x04, 0x81, 0x01, 0x23, 0x04, 0x81, 0x01, 0x35, 0x04, 0x96, 0x00, 0x36, 0x04, 0x96, 0x00, 0x36, 0x04, 0x96, 0x00, 0x36, 0x05, 0x24, 0x00, 0xc6, 0x05, 0xff, 0x00, 0xc6, 0x06, 0x08, 0x00, 0xfe, 0x06, 0x74, 0x00, 0x9d, 0x06, 0x74, 0x00, 0x9d, 0x06, 0x08, 0x00, 0xd5, 0x03, 0x99, 0x01, 0x84, 0x03, 0x99, 0x00, 0x5b, 0x03, 0x99, 0x00, 0xf4, 0x03, 0x99, 0x00, 0x5b, 0x05, 0x45, 0x00, 0xed, 0x05, 0x45, 0x00, 0xed, 0x05, 0x45, 0x00, 0xed, 0x05, 0x45, 0x00, 0xed, 0x03, 0xc0, 0x00, 0x69, 0x05, 0xae, 0x00, 0x69, 0x07, 0x9c, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x05, 0xae, 0x00, 0x69, 0x07, 0x9c, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x04, 0x94, 0x00, 0x6c, 0x04, 0x94, 0x00, 0x6c, 0x01, 0xdf, 0x00, 0x90, 0x04, 0x94, 0x00, 0x6c, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc2, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0x91, 0x06, 0x08, 0x00, 0xc3, 0x02, 0xb3, 0x00, 0xbb, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc2, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x0a, 0x00, 0xc3, 0x06, 0x0a, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xba, 0x07, 0x33, 0x00, 0xb8, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc4, 0x06, 0x08, 0x00, 0xc4, 0x06, 0x08, 0x00, 0xc4, 0x06, 0x08, 0x00, 0xc4, 0x07, 0x89, 0x00, 0x85, 0x07, 0x89, 0x00, 0x85, 0x03, 0x57, 0x00, 0x9e, 0x06, 0x08, 0x00, 0xc2, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc4, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xbb, 0x06, 0x08, 0x00, 0xbb, 0x06, 0x08, 0x00, 0xbb, 0x06, 0x08, 0x00, 0xbb, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xb7, 0x06, 0x08, 0x00, 0xb7, 0x06, 0x08, 0x00, 0xb7, 0x06, 0x08, 0x00, 0xb7, 0x06, 0x08, 0x00, 0xab, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xab, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xab, 0x06, 0x08, 0x00, 0xab, 0x05, 0x45, 0x00, 0xed, 0x05, 0x45, 0x00, 0xed, 0x05, 0x45, 0x00, 0xed, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x05, 0x9e, 0x00, 0xc3, 0x05, 0x9e, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x03, 0xbf, 0x00, 0x9d, 0x03, 0xbf, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x07, 0x33, 0x00, 0x6c, 0x07, 0x33, 0x00, 0x6c, 0x06, 0x08, 0x00, 0x58, 0x06, 0x08, 0x00, 0x6c, 0x03, 0xbf, 0x00, 0xd6, 0x05, 0x45, 0x00, 0xb4, 0x05, 0x45, 0x00, 0xb4, 0x05, 0x45, 0x00, 0xb4, 0x06, 0x08, 0x00, 0xfe, 0x06, 0x08, 0x00, 0xfe, 0x05, 0xe8, 0xff, 0xfb, 0x05, 0xe8, 0xff, 0xfb, 0x05, 0xe8, 0x00, 0x7e, 0x05, 0xe8, 0x00, 0x7e, 0x03, 0x8e, 0x00, 0x05, 0x02, 0x49, 0x00, 0xc5, 0x04, 0x81, 0x00, 0xe0, 0x06, 0x08, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x05, 0x46, 0x00, 0x59, 0x05, 0x46, 0x00, 0x59, 0x06, 0x08, 0x00, 0xab, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xbd, 0x06, 0x08, 0x00, 0xbd, 0x06, 0x08, 0x01, 0x56, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x0a, 0x3d, 0x00, 0x85, 0x0a, 0x3d, 0x00, 0x85, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xca, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xbf, 0x07, 0x33, 0x03, 0x3a, 0x07, 0x33, 0x00, 0xd4, 0x07, 0x33, 0x00, 0xd4, 0x07, 0x33, 0x00, 0xd4, 0x07, 0x33, 0x00, 0x4f, 0x06, 0x45, 0x00, 0x9d, 0x05, 0x2b, 0x00, 0xc3, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x05, 0x2b, 0x00, 0xc3, 0x06, 0x45, 0x00, 0x9d, 0x06, 0x45, 0x00, 0x9d, 0x07, 0x33, 0x00, 0x4f, 0x06, 0x45, 0x00, 0x9d, 0x05, 0x2b, 0x00, 0xc3, 0x06, 0x45, 0x00, 0x9d, 0x05, 0x2b, 0x00, 0xc3, 0x06, 0x45, 0x00, 0xc3, 0x04, 0x55, 0x00, 0x42, 0x04, 0x55, 0x00, 0x66, 0x04, 0x92, 0x00, 0x83, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x01, 0x79, 0x06, 0x08, 0x01, 0x79, 0x03, 0x84, 0x01, 0x1b, 0x02, 0xcf, 0x00, 0x9e, 0x02, 0xcf, 0x00, 0xb3, 0x02, 0xcf, 0x00, 0x9e, 0x02, 0xcf, 0x00, 0xb3, 0x05, 0xd2, 0x02, 0xa8, 0x05, 0xd2, 0x00, 0x5a, 0x05, 0xd2, 0x02, 0xa8, 0x05, 0xd2, 0x00, 0x5a, 0x06, 0x08, 0x00, 0xc3, 0x03, 0xb1, 0x00, 0x05, 0x07, 0x33, 0x00, 0xde, 0x06, 0x08, 0x00, 0xc3, 0x03, 0x60, 0x00, 0x9e, 0x03, 0x60, 0x00, 0x78, 0x03, 0x60, 0x00, 0x9e, 0x03, 0x60, 0x00, 0x78, 0x03, 0xc0, 0x01, 0x83, 0x03, 0xc0, 0x00, 0x25, 0x08, 0x4c, 0x00, 0x8c, 0x08, 0x4c, 0x00, 0x8c, 0x0a, 0x2e, 0x00, 0x8c, 0x08, 0x4c, 0x00, 0x8c, 0x0a, 0x64, 0x00, 0x6c, 0x0a, 0x2e, 0x00, 0x00, 0x06, 0x49, 0x00, 0x87, 0x02, 0x6f, 0x00, 0x95, 0x04, 0x92, 0x00, 0xa7, 0x06, 0x07, 0x00, 0x79, 0x04, 0xbf, 0x00, 0x65, 0x05, 0x73, 0x00, 0x17, 0x08, 0x4c, 0x00, 0x8c, 0x06, 0x49, 0x00, 0x1f, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x02, 0x4b, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x00, 0x9e, 0x03, 0x99, 0x02, 0x4b, 0x03, 0x99, 0x00, 0x9e, 0x05, 0x66, 0x02, 0x5f, 0x05, 0x66, 0x00, 0x97, 0x05, 0x66, 0x02, 0x5f, 0x05, 0x66, 0x02, 0x5f, 0x05, 0x66, 0x00, 0x97, 0x05, 0x66, 0x02, 0x5f, 0x05, 0x66, 0x00, 0x97, 0x03, 0xc0, 0x01, 0x83, 0x06, 0x08, 0x00, 0x31, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0x49, 0x00, 0x87, 0x05, 0x89, 0x00, 0x05, 0x04, 0x94, 0x00, 0x50, 0x04, 0x92, 0xff, 0x8f, 0x04, 0x92, 0x00, 0x83, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0x52, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x52, 0x04, 0x55, 0x01, 0x52, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x52, 0x04, 0x55, 0x01, 0x52, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x01, 0x52, 0x04, 0x55, 0x01, 0x52, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0xff, 0x9e, 0x04, 0x55, 0xff, 0x9e, 0x04, 0x55, 0xff, 0x9e, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0x02, 0x3c, 0x04, 0x55, 0x01, 0xe2, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0x02, 0x3c, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0x9a, 0x04, 0x55, 0xff, 0xee, 0x04, 0x55, 0x01, 0x9a, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0x02, 0xc4, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0x04, 0xe5, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0x02, 0xc4, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0x02, 0xc4, 0x05, 0x89, 0xff, 0xee, 0x05, 0x89, 0xff, 0xee, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x04, 0xe1, 0x00, 0xa7, 0x04, 0xe1, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x03, 0xf6, 0x00, 0xa7, 0x03, 0xf6, 0x00, 0xa7, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x03, 0x9d, 0x00, 0x05, 0x03, 0x9d, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x03, 0x9d, 0x00, 0x05, 0x03, 0x9d, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x03, 0x9d, 0x00, 0x05, 0x03, 0x9d, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x03, 0x9d, 0x00, 0x05, 0x03, 0x9d, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x06, 0x48, 0x00, 0x64, 0x03, 0x8e, 0x00, 0x05, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x66, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x03, 0xcb, 0x00, 0x64, 0x03, 0xcb, 0x00, 0xa7, 0x05, 0xb2, 0x00, 0xa7, 0x06, 0xfc, 0x00, 0xa7, 0x06, 0xfc, 0x00, 0xa7, 0x06, 0xfc, 0x00, 0xa7, 0x02, 0xc9, 0x00, 0x05, 0x02, 0xc9, 0x00, 0x05, 0x02, 0xc9, 0x00, 0x05, 0x02, 0xc9, 0x00, 0x05, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x04, 0x3f, 0x01, 0x14, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x08, 0x0e, 0x00, 0x64, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x06, 0x48, 0x00, 0x64, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0xfa, 0x00, 0xa7, 0x05, 0xfa, 0x00, 0xa7, 0x05, 0x46, 0x00, 0xa7, 0x05, 0x46, 0x00, 0xa7, 0x05, 0x89, 0x00, 0x05, 0x06, 0x74, 0x00, 0x99, 0x07, 0x33, 0x00, 0x5d, 0x06, 0x74, 0x00, 0x5a, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x75, 0x06, 0x74, 0x00, 0x77, 0x06, 0x74, 0x00, 0x77, 0x04, 0x1f, 0x00, 0x99, 0x06, 0x73, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x65, 0x00, 0x70, 0x06, 0x65, 0x00, 0x70, 0x04, 0xd5, 0x00, 0x70, 0x07, 0x4a, 0x00, 0x70, 0x08, 0xf7, 0x00, 0x7e, 0x09, 0x00, 0x00, 0x82, 0x06, 0x74, 0x00, 0xa5, 0x06, 0x74, 0x00, 0xa4, 0x06, 0x74, 0x00, 0xa4, 0x03, 0xd5, 0x00, 0x8a, 0x06, 0x74, 0x00, 0x5a, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x9a, 0x06, 0x74, 0x00, 0x9a, 0x06, 0x74, 0x00, 0x8f, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x9a, 0x06, 0x74, 0x00, 0x9a, 0x06, 0x74, 0x00, 0xa0, 0x04, 0x62, 0x00, 0x84, 0x06, 0x74, 0x00, 0x9f, 0x04, 0x62, 0x00, 0x84, 0x06, 0x74, 0x00, 0x70, 0x06, 0x74, 0x00, 0x9a, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x5a, 0x04, 0xd1, 0x00, 0x5a, 0x05, 0x5f, 0x00, 0x99, 0x04, 0xad, 0x00, 0x99, 0x05, 0xa4, 0x00, 0x99, 0x03, 0xec, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0xa0, 0x06, 0x74, 0x00, 0x99, 0x05, 0x1d, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x79, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x02, 0x93, 0x06, 0x74, 0x00, 0x99, 0x04, 0x6b, 0x00, 0x9d, 0x05, 0x46, 0x00, 0x9d, 0x05, 0x46, 0x00, 0x9d, 0x06, 0x74, 0x00, 0x91, 0x06, 0x74, 0x01, 0x31, 0x06, 0x74, 0x01, 0x93, 0x06, 0x74, 0x00, 0xdf, 0x06, 0x74, 0x00, 0xea, 0x06, 0x74, 0x01, 0xba, 0x06, 0x74, 0x00, 0x53, 0x06, 0x74, 0x00, 0xa4, 0x06, 0x74, 0x00, 0xac, 0x06, 0x74, 0x00, 0xcf, 0x06, 0x74, 0x01, 0x01, 0x06, 0x74, 0x00, 0x62, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x3e, 0x06, 0x74, 0x00, 0x98, 0x06, 0x74, 0x00, 0xac, 0x06, 0x74, 0x00, 0x9e, 0x06, 0x74, 0x01, 0x20, 0x06, 0x74, 0x00, 0xb4, 0x06, 0x74, 0x00, 0xcb, 0x06, 0x74, 0x01, 0x32, 0x06, 0x74, 0x01, 0x8a, 0x06, 0x74, 0x01, 0x2f, 0x06, 0x74, 0x01, 0x11, 0x06, 0x74, 0x00, 0xb4, 0x06, 0x74, 0x00, 0xcb, 0x06, 0x74, 0x01, 0x32, 0x06, 0x74, 0x01, 0x8a, 0x06, 0x74, 0x01, 0x2a, 0x06, 0x74, 0x01, 0x11, 0x06, 0x74, 0x01, 0x22, 0x06, 0x74, 0x00, 0xa6, 0x06, 0x74, 0x01, 0x35, 0x06, 0x74, 0x00, 0xcd, 0x06, 0x74, 0x01, 0x21, 0x06, 0x74, 0x00, 0xa3, 0x06, 0x74, 0x01, 0x35, 0x06, 0x74, 0x00, 0xcd, 0x06, 0x74, 0x00, 0xc2, 0x03, 0x65, 0x00, 0x9a, 0x04, 0x98, 0x00, 0x9a, 0x06, 0x74, 0x01, 0x52, 0x06, 0x74, 0x00, 0xa9, 0x03, 0x65, 0x00, 0xa2, 0x02, 0x92, 0x00, 0x9a, 0x03, 0x7b, 0x00, 0x9b, 0x05, 0x62, 0x00, 0x9a, 0x05, 0x83, 0x00, 0x76, 0x06, 0x74, 0x00, 0x9a, 0x06, 0x74, 0x00, 0x8c, 0x06, 0x74, 0x00, 0x8c, 0x06, 0x74, 0x00, 0x8c, 0x06, 0x74, 0x00, 0x8c, 0x06, 0x74, 0x00, 0x8c, 0x06, 0x74, 0x00, 0x8c, 0x06, 0x74, 0x00, 0x8c, 0x06, 0x74, 0x00, 0x8c, 0x06, 0x74, 0x00, 0x9a, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x01, 0x12, 0x06, 0x42, 0x00, 0x87, 0x06, 0x42, 0x00, 0x87, 0x06, 0x42, 0x00, 0x87, 0x06, 0x42, 0x00, 0x87, 0x06, 0x42, 0x00, 0x87, 0x06, 0x42, 0x00, 0x87, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x01, 0x35, 0x06, 0x74, 0x01, 0x35, 0x06, 0x74, 0x00, 0x5f, 0x06, 0x74, 0x00, 0xb2, 0x06, 0x74, 0x00, 0xf2, 0x03, 0xe5, 0x00, 0x70, 0x06, 0x74, 0x00, 0x6c, 0x06, 0x74, 0x00, 0x70, 0x06, 0x74, 0x01, 0x0b, 0x06, 0x74, 0x00, 0xae, 0x06, 0x74, 0x00, 0xeb, 0x06, 0x74, 0x00, 0xea, 0x06, 0x74, 0x00, 0xea, 0x06, 0x74, 0x00, 0x5a, 0x05, 0x0e, 0x00, 0x99, 0x07, 0x3b, 0x00, 0x9d, 0x07, 0xd7, 0x00, 0x91, 0x08, 0x75, 0x00, 0x9d, 0x06, 0x80, 0x00, 0x9d, 0x06, 0x08, 0x00, 0xf2, 0x06, 0x08, 0x00, 0xba, 0x06, 0x08, 0x01, 0x59, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x01, 0x58, 0x06, 0x08, 0x01, 0x58, 0x06, 0x08, 0x01, 0xc7, 0x06, 0x08, 0x01, 0x40, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0x09, 0x06, 0x13, 0x00, 0xbd, 0x06, 0x08, 0x01, 0x85, 0x05, 0x46, 0x00, 0x9d, 0x05, 0x46, 0x01, 0x36, 0x05, 0x46, 0x00, 0x9e, 0x05, 0x46, 0x00, 0x9e, 0x06, 0x1e, 0x00, 0x6c, 0x05, 0x46, 0x01, 0x66, 0x05, 0x46, 0x01, 0x23, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x4d, 0x05, 0x46, 0x00, 0x9d, 0x06, 0x08, 0x00, 0x13, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x13, 0x06, 0x08, 0x00, 0x41, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x6c, 0x06, 0x08, 0x00, 0x76, 0x06, 0x08, 0x01, 0x87, 0x06, 0x08, 0x00, 0x26, 0x06, 0x08, 0x00, 0xa3, 0x06, 0x08, 0x00, 0x2f, 0x06, 0x08, 0x00, 0xa3, 0x06, 0x08, 0x00, 0x4f, 0x06, 0x08, 0x00, 0x7c, 0x06, 0x08, 0x01, 0x14, 0x06, 0x08, 0x00, 0xd5, 0x06, 0x08, 0x00, 0xe9, 0x06, 0x08, 0x00, 0x9d, 0x06, 0x08, 0x00, 0xd8, 0x06, 0x08, 0x00, 0xe2, 0x06, 0x08, 0x00, 0x64, 0x06, 0x08, 0x00, 0x64, 0x06, 0x08, 0x00, 0x64, 0x06, 0x08, 0x00, 0x64, 0x06, 0x08, 0x01, 0x30, 0x06, 0x08, 0x00, 0xf1, 0x06, 0x08, 0x01, 0x1e, 0x06, 0x08, 0x00, 0x64, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x4a, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0x4e, 0x06, 0x08, 0x00, 0x4e, 0x06, 0x08, 0x00, 0x2a, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x2b, 0x06, 0x08, 0x00, 0x2a, 0x06, 0x08, 0x00, 0x2b, 0x06, 0x08, 0x00, 0x2b, 0x06, 0x08, 0x00, 0x2b, 0x06, 0x08, 0x00, 0x2d, 0x06, 0x08, 0x00, 0x76, 0x06, 0x08, 0x00, 0x88, 0x06, 0x08, 0x00, 0x64, 0x06, 0x08, 0x00, 0x39, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0xa8, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0x64, 0x06, 0x08, 0x00, 0x96, 0x06, 0x08, 0x00, 0x96, 0x06, 0x08, 0x00, 0x90, 0x06, 0x08, 0x00, 0x90, 0x06, 0x08, 0x00, 0x63, 0x06, 0x08, 0x00, 0x63, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0x4d, 0x06, 0x08, 0x00, 0x90, 0x06, 0x08, 0x00, 0xa3, 0x06, 0x08, 0x00, 0x8c, 0x06, 0x08, 0x00, 0x75, 0x06, 0x08, 0x00, 0x90, 0x06, 0x08, 0x00, 0x57, 0x06, 0x08, 0x00, 0x57, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x08, 0x00, 0x4b, 0x06, 0x74, 0x00, 0x5b, 0x06, 0x74, 0x00, 0x6d, 0x06, 0x74, 0x00, 0x6d, 0x06, 0x74, 0x00, 0x6d, 0x06, 0x74, 0x00, 0x6d, 0x06, 0x74, 0x00, 0x99, 0x06, 0x08, 0x02, 0xb7, 0x06, 0x08, 0x02, 0x6b, 0x06, 0x08, 0x01, 0xd2, 0x02, 0x52, 0x00, 0x9c, 0x02, 0x52, 0x00, 0x6c, 0x03, 0xdf, 0x00, 0x9c, 0x03, 0xdf, 0x00, 0x6c, 0x06, 0x08, 0x01, 0x1e, 0x06, 0x08, 0x01, 0x74, 0x06, 0x08, 0x01, 0x2c, 0x06, 0x08, 0x00, 0x63, 0x06, 0x08, 0x01, 0x35, 0x06, 0x08, 0x00, 0x71, 0x06, 0x08, 0x00, 0x90, 0x06, 0x08, 0x01, 0x68, 0x06, 0x08, 0x01, 0x68, 0x06, 0x08, 0x01, 0xe6, 0x06, 0x08, 0x01, 0xe6, 0x06, 0x08, 0x01, 0x8c, 0x06, 0x08, 0x01, 0xab, 0x06, 0x08, 0x01, 0x05, 0x06, 0x08, 0x01, 0x19, 0x06, 0x08, 0x01, 0x32, 0x06, 0x08, 0x01, 0x51, 0x06, 0x08, 0x02, 0x7d, 0x06, 0x08, 0x02, 0x2e, 0x06, 0x08, 0x01, 0x42, 0x06, 0x08, 0x01, 0x77, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x74, 0x00, 0x88, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x08, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0xe2, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0xe2, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0xcd, 0x06, 0x08, 0x00, 0xcd, 0x06, 0x08, 0x00, 0xcd, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x01, 0xba, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x26, 0x06, 0x08, 0x00, 0x26, 0x06, 0x08, 0x00, 0xf9, 0x06, 0x08, 0x00, 0xf9, 0x06, 0x08, 0x00, 0x72, 0x06, 0x08, 0x00, 0x72, 0x06, 0x08, 0x01, 0x1c, 0x06, 0x08, 0x00, 0x75, 0x06, 0x08, 0x00, 0x94, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x96, 0x06, 0x08, 0x00, 0x96, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0x96, 0x06, 0x08, 0x00, 0x67, 0x06, 0x08, 0x00, 0x87, 0x06, 0x08, 0x00, 0x91, 0x06, 0x08, 0x00, 0x91, 0x06, 0x08, 0x00, 0x69, 0x02, 0xcf, 0x00, 0x63, 0x02, 0xcf, 0x00, 0x47, 0x03, 0x8e, 0x00, 0x05, 0x03, 0x90, 0x00, 0x9e, 0x03, 0x90, 0x00, 0x9d, 0x02, 0xcf, 0x00, 0xa4, 0x02, 0xcf, 0x00, 0x93, 0x04, 0x01, 0x00, 0xa4, 0x04, 0x01, 0x00, 0x93, 0x06, 0x08, 0x00, 0x51, 0x06, 0x08, 0x00, 0x50, 0x06, 0x08, 0x00, 0x47, 0x06, 0x08, 0x00, 0x47, 0x08, 0x55, 0x00, 0x69, 0x0a, 0x52, 0x00, 0x5a, 0x0a, 0x52, 0x00, 0x69, 0x0a, 0x52, 0x00, 0x5a, 0x0a, 0x52, 0x00, 0x5a, 0x0a, 0x52, 0x00, 0x69, 0x0a, 0x52, 0x00, 0x5a, 0x0a, 0x52, 0x00, 0x5a, 0x0a, 0x52, 0x00, 0x69, 0x0a, 0x52, 0x00, 0x5a, 0x0a, 0x52, 0x00, 0x69, 0x0a, 0x52, 0x00, 0x69, 0x05, 0x46, 0x00, 0x00, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x03, 0x2a, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x05, 0x46, 0x01, 0x0e, 0x06, 0x08, 0x00, 0x5a, 0x06, 0x08, 0x00, 0x69, 0x06, 0x08, 0x00, 0xe6, 0x06, 0x08, 0x00, 0xe6, 0x04, 0xeb, 0x00, 0x47, 0x04, 0xeb, 0x00, 0x47, 0x05, 0x48, 0x00, 0xe6, 0x05, 0x48, 0x00, 0xe6, 0x06, 0x08, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x07, 0x33, 0x00, 0xc3, 0x03, 0x8e, 0x00, 0x05, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x07, 0x33, 0x00, 0x34, 0x07, 0x33, 0x00, 0x34, 0x07, 0x33, 0x00, 0x34, 0x09, 0x8a, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0xff, 0xc5, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x69, 0x03, 0xc0, 0x00, 0x60, 0x06, 0x08, 0x00, 0xfc, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc4, 0x06, 0x08, 0x00, 0xc4, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xc3, 0x06, 0x08, 0x00, 0xa2, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x00, 0xa2, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x00, 0x31, 0x06, 0x08, 0x00, 0x31, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x08, 0x00, 0xa2, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x00, 0xa2, 0x06, 0x08, 0x01, 0x03, 0x06, 0x08, 0x00, 0x31, 0x06, 0x08, 0x01, 0x3b, 0x06, 0x04, 0x00, 0x69, 0x06, 0x04, 0x00, 0x69, 0x06, 0x04, 0x00, 0x40, 0x06, 0x04, 0x00, 0x40, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0xcd, 0x00, 0xa7, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x05, 0x89, 0x00, 0x05, 0x06, 0xcd, 0x00, 0xa7, 0x06, 0x42, 0x00, 0x20, 0x06, 0x42, 0x00, 0x20, 0x06, 0x49, 0x00, 0x87, 0x06, 0x49, 0x00, 0x87, 0x06, 0x49, 0x00, 0x1e, 0x08, 0x0e, 0x00, 0x64, 0x06, 0x42, 0x00, 0x45, 0x06, 0x42, 0x00, 0x45, 0x04, 0x02, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x04, 0x02, 0xff, 0xdc, 0x04, 0x57, 0x00, 0x09, 0x05, 0x00, 0x00, 0xb4, 0x04, 0x69, 0x00, 0x40, 0x02, 0xd2, 0xff, 0xeb, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x2b, 0x00, 0xa7, 0x04, 0xee, 0x00, 0x52, 0x03, 0xc7, 0x00, 0x4f, 0x05, 0xa0, 0x00, 0x67, 0x06, 0x36, 0x00, 0xb4, 0x04, 0xec, 0x00, 0x0e, 0x05, 0xa0, 0x00, 0x67, 0x05, 0x49, 0x00, 0x36, 0x08, 0x1f, 0x00, 0x3d, 0x06, 0xec, 0x00, 0x4d, 0x04, 0x42, 0x00, 0x5d, 0x04, 0xb6, 0x00, 0xb4, 0x04, 0x16, 0x00, 0xad, 0x04, 0xbf, 0x00, 0x64, 0x02, 0xfb, 0x00, 0x00, 0x04, 0x67, 0x00, 0x65, 0x03, 0x88, 0x00, 0x58, 0x01, 0x42, 0xff, 0xec, 0x03, 0x19, 0x00, 0x09, 0x04, 0x92, 0x00, 0x79, 0x04, 0xee, 0x00, 0x52, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x03, 0x8d, 0x00, 0xc0, 0x02, 0xa8, 0x00, 0x5b, 0x02, 0xa8, 0x00, 0x5b, 0x01, 0xd1, 0x00, 0xaf, 0x01, 0xd1, 0x00, 0xaf, 0x01, 0xd1, 0x00, 0xaf, 0x02, 0xc6, 0x00, 0x7b, 0x02, 0x90, 0x00, 0x7b, 0x03, 0x65, 0x00, 0x67, 0x03, 0x65, 0x00, 0x67, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x06, 0x52, 0xff, 0xfb, 0x05, 0x1b, 0x00, 0x31, 0x04, 0x6c, 0x00, 0x93, 0x03, 0xe4, 0x00, 0x77, 0x03, 0x88, 0x00, 0xa7, 0x03, 0xc0, 0x00, 0x63, 0x08, 0xff, 0x00, 0x0e, 0x07, 0x17, 0x00, 0x6e, 0x08, 0xa9, 0x00, 0x0e, 0x07, 0x20, 0x00, 0x6e, 0x08, 0x39, 0x00, 0x0e, 0x07, 0x10, 0x00, 0x6e, 0x06, 0xfe, 0x00, 0x0e, 0x05, 0xe3, 0x00, 0x6e, 0x06, 0xfe, 0x00, 0x0e, 0x05, 0xe3, 0x00, 0x6e, 0x06, 0xe7, 0x00, 0x0e, 0x05, 0xe3, 0x00, 0x6e, 0x05, 0x10, 0x00, 0x67, 0x03, 0xf4, 0x00, 0x72, 0x04, 0xb8, 0x00, 0x09, 0x04, 0x32, 0x00, 0x0c, 0x04, 0xe5, 0x00, 0xb4, 0x02, 0xd2, 0x00, 0xad, 0x04, 0x2f, 0x00, 0x4a, 0x03, 0x12, 0x00, 0x6c, 0x05, 0xce, 0x00, 0x09, 0x05, 0x11, 0x00, 0x09, 0x09, 0xc6, 0x00, 0x67, 0x07, 0x55, 0x00, 0x65, 0x04, 0x57, 0x00, 0x09, 0x04, 0x92, 0xff, 0xfc, 0x05, 0x48, 0x00, 0x2d, 0x05, 0x93, 0x00, 0x2d, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x92, 0x00, 0x65, 0x04, 0x5b, 0x00, 0x09, 0x04, 0x92, 0xff, 0xfc, 0x04, 0x5b, 0x00, 0x09, 0x04, 0x92, 0xff, 0xfc, 0x04, 0x02, 0x00, 0x09, 0x02, 0x00, 0x00, 0xad, 0x05, 0x4b, 0x00, 0xb4, 0x04, 0x90, 0x00, 0xa7, 0x02, 0x6d, 0x00, 0xd8, 0x02, 0xb5, 0x00, 0x90, 0x02, 0xe2, 0x01, 0x16, 0x01, 0xfa, 0x00, 0xb1, 0x04, 0xef, 0x00, 0x9d, 0x03, 0x82, 0x00, 0x45, 0x05, 0x8f, 0x00, 0xb4, 0x04, 0xcc, 0x00, 0xa7, 0x05, 0x94, 0x00, 0x03, 0x04, 0x92, 0x00, 0x03, 0x04, 0xb8, 0x00, 0x03, 0x04, 0x2b, 0x00, 0x03, 0x05, 0x62, 0x00, 0x03, 0x04, 0x90, 0x00, 0x03, 0x05, 0x00, 0x00, 0x03, 0x02, 0xf5, 0x00, 0x03, 0x04, 0x92, 0x00, 0x03, 0x03, 0xc0, 0x00, 0x03, 0x05, 0xc4, 0xff, 0xa2, 0x06, 0x96, 0x00, 0xa7, 0x04, 0x24, 0x00, 0x6b, 0x04, 0x57, 0x00, 0x3f, 0x06, 0x36, 0x00, 0xb4, 0x02, 0x1f, 0x00, 0xb4, 0x08, 0xa2, 0x00, 0x3d, 0x01, 0x89, 0x00, 0xae, 0x01, 0xb6, 0x00, 0x7e, 0x01, 0xd9, 0x00, 0x63, 0x01, 0xe6, 0x00, 0x56, 0x01, 0xec, 0x00, 0x51, 0x01, 0xb6, 0x00, 0x7e, 0x01, 0x89, 0x00, 0xae, 0x01, 0xb6, 0x00, 0x7e, 0x01, 0xd9, 0x00, 0x63, 0x01, 0xe6, 0x00, 0x56, 0x01, 0xd9, 0x00, 0x63, 0x01, 0xb6, 0x00, 0x7e, 0x01, 0x89, 0x00, 0xae, 0x01, 0xb6, 0x00, 0x7e, 0x01, 0xd9, 0x00, 0x63, 0x01, 0xe6, 0x00, 0x56, 0x01, 0xd9, 0x00, 0x63, 0x01, 0xb6, 0x00, 0x7e, 0x01, 0x89, 0x00, 0xae, 0x01, 0xb6, 0x00, 0x7e, 0x01, 0xec, 0x00, 0x51, 0x01, 0xe6, 0x00, 0x56, 0x01, 0xd9, 0x00, 0x63, 0x01, 0xb6, 0x00, 0x7e, 0x01, 0x89, 0x00, 0xae, 0x01, 0xfa, 0x00, 0xc0, 0x07, 0x08, 0x00, 0x87, 0x07, 0x08, 0x00, 0x87, 0x07, 0x08, 0x00, 0x87, 0x07, 0x08, 0x00, 0x87, 0x04, 0x2d, 0x00, 0x63, 0x04, 0x2d, 0x00, 0x63, 0x04, 0x7d, 0x00, 0x63, 0x06, 0x66, 0x00, 0x63, 0x04, 0x36, 0x00, 0x63, 0x04, 0x2d, 0x00, 0x63, 0x04, 0xb3, 0x00, 0x63, 0x06, 0x59, 0x00, 0x63, 0x03, 0xff, 0x00, 0x63, 0x04, 0x2d, 0x00, 0x63, 0x08, 0x69, 0x00, 0x63, 0x04, 0x3d, 0x00, 0x63, 0x04, 0x3f, 0x00, 0x75, 0x06, 0x42, 0x00, 0x63, 0x04, 0x2d, 0x00, 0x63, 0x04, 0x3e, 0x00, 0x63, 0x06, 0x93, 0x00, 0x63, 0x04, 0x3f, 0x00, 0x75, 0x05, 0x43, 0x00, 0x63, 0x04, 0x32, 0x00, 0x2d, 0x06, 0x47, 0x00, 0x63, 0x04, 0x3e, 0x00, 0x63, 0x06, 0x71, 0x00, 0x63, 0x04, 0x3d, 0x00, 0x63, 0x04, 0x3d, 0x00, 0x63, 0x04, 0x40, 0x00, 0x75, 0x04, 0xac, 0x00, 0x64, 0x04, 0x3d, 0x00, 0x63, 0x04, 0x3e, 0x00, 0x75, 0x04, 0x4f, 0x00, 0x63, 0x04, 0x3f, 0x00, 0x75, 0x03, 0xb7, 0x00, 0x2d, 0x04, 0x2c, 0x00, 0x63, 0x04, 0x34, 0x00, 0x6c, 0x04, 0x2d, 0x00, 0x63, 0x04, 0x2d, 0x00, 0x63, 0x04, 0x2e, 0x00, 0x63, 0x04, 0x98, 0x00, 0x63, 0x06, 0xe0, 0x00, 0x63, 0x06, 0xb4, 0x00, 0x6d, 0x05, 0xd1, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xa8, 0x00, 0x5a, 0x03, 0xba, 0x00, 0x5a, 0x03, 0xba, 0x00, 0x5a, 0x03, 0xba, 0x00, 0x5a, 0x05, 0xa9, 0x00, 0x5a, 0x05, 0xa9, 0x00, 0x5a, 0x05, 0xa9, 0x00, 0x5a, 0x05, 0xa9, 0x00, 0x5a, 0x05, 0xa9, 0x00, 0x5a, 0x03, 0xef, 0x00, 0x36, 0x03, 0xef, 0x00, 0x36, 0x03, 0xef, 0x00, 0x36, 0x03, 0xef, 0x00, 0x36, 0x03, 0xef, 0x00, 0x36, 0x03, 0xef, 0x00, 0x36, 0x04, 0x67, 0x00, 0x65, 0x04, 0xf5, 0x00, 0x2a, 0x04, 0x89, 0x00, 0x2a, 0x04, 0x89, 0x00, 0x2a, 0x06, 0xf6, 0x00, 0x2a, 0x06, 0xf6, 0x00, 0x2a, 0x04, 0xf0, 0x00, 0x2a, 0x06, 0x32, 0x00, 0x63, 0x00, 0x00, 0xfc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x62, 0x00, 0x1b, 0x05, 0x73, 0x00, 0x5a, 0x04, 0x5f, 0x00, 0xb4, 0x04, 0x0c, 0x00, 0x5a, 0x04, 0x53, 0x00, 0xb4, 0x03, 0xf3, 0x00, 0xb4, 0x03, 0xf3, 0x00, 0xb4, 0x03, 0x2a, 0x00, 0x87, 0x04, 0x80, 0x00, 0xb4, 0x06, 0x81, 0x00, 0x87, 0x02, 0x0a, 0x00, 0xb4, 0x04, 0x96, 0x00, 0xb4, 0x03, 0xef, 0x00, 0xb4, 0x0a, 0x45, 0x00, 0xb4, 0x06, 0x58, 0x00, 0xb4, 0x06, 0xa6, 0x00, 0xb4, 0x06, 0x81, 0x00, 0x87, 0x04, 0xf0, 0x00, 0xb4, 0x06, 0x40, 0x00, 0xb4, 0x04, 0x38, 0x00, 0x87, 0x04, 0x5d, 0x00, 0xb4, 0x03, 0x2d, 0x00, 0x87, 0x05, 0x03, 0x00, 0x5a, 0x04, 0x95, 0x00, 0xb4, 0x04, 0xf0, 0x00, 0x87, 0x04, 0xec, 0x00, 0x87, 0x05, 0xd4, 0x00, 0x5a, 0x03, 0xcc, 0x00, 0x87, 0x04, 0x03, 0x00, 0xb4, 0x04, 0x03, 0x00, 0xb4, 0x03, 0x2a, 0x00, 0x5a, 0x05, 0x73, 0x00, 0x5a, 0x02, 0x0a, 0x00, 0xb4, 0x05, 0x73, 0x00, 0x5a, 0x04, 0xf0, 0x00, 0x87, 0x05, 0xe3, 0x00, 0x5a, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x05, 0x55, 0x00, 0x0e, 0x05, 0x43, 0x00, 0xb4, 0x05, 0xe5, 0x00, 0xd0, 0x05, 0x40, 0x00, 0xb4, 0x04, 0xd9, 0x00, 0xb4, 0x05, 0x94, 0x00, 0x67, 0x02, 0xd3, 0x00, 0x5b, 0x02, 0xd1, 0xff, 0xa1, 0x05, 0x6a, 0x00, 0xb4, 0x04, 0xb6, 0x00, 0xb4, 0x07, 0x61, 0x00, 0xb0, 0x05, 0xaa, 0x00, 0x66, 0x04, 0x92, 0x00, 0x7a, 0x05, 0x19, 0xff, 0xfb, 0x05, 0xfa, 0x00, 0x9f, 0x05, 0x34, 0x00, 0x0e, 0x07, 0xfa, 0x00, 0x3d, 0x05, 0xcd, 0x00, 0x61, 0x05, 0x17, 0xff, 0xfd, 0x04, 0xc3, 0x00, 0x6e, 0x05, 0x19, 0x00, 0x85, 0x03, 0xf5, 0x00, 0x65, 0x05, 0x19, 0x00, 0x85, 0x04, 0x6e, 0x00, 0x63, 0x03, 0x59, 0x00, 0x2a, 0x05, 0x19, 0x00, 0x65, 0x05, 0x4e, 0x00, 0xa7, 0x02, 0x87, 0x00, 0xcf, 0x02, 0x87, 0xff, 0xdc, 0x04, 0xaf, 0x00, 0xa7, 0x02, 0x87, 0x00, 0xcf, 0x08, 0x38, 0x00, 0xa7, 0x05, 0x4e, 0x00, 0xa7, 0x04, 0x67, 0x00, 0x65, 0x05, 0x19, 0x00, 0x65, 0x05, 0x19, 0x00, 0x65, 0x03, 0x7b, 0x00, 0xa7, 0x03, 0xc0, 0x00, 0x63, 0x03, 0x59, 0x00, 0x31, 0x05, 0x52, 0x00, 0x9f, 0x04, 0x5f, 0x00, 0x36, 0x06, 0x8d, 0x00, 0x4d, 0x04, 0xdd, 0x00, 0x44, 0x04, 0x7f, 0x00, 0x36, 0x04, 0x3f, 0x00, 0x4f, 0x04, 0xec, 0x00, 0x0e, 0x04, 0xf0, 0x00, 0xb4, 0x05, 0x07, 0x00, 0x67, 0x05, 0x8b, 0x00, 0xb4, 0x04, 0x8c, 0x00, 0xb4, 0x04, 0x24, 0x00, 0xb4, 0x05, 0x94, 0x00, 0x67, 0x05, 0x6a, 0x00, 0xb4, 0x03, 0x31, 0x00, 0x87, 0x02, 0x1f, 0xff, 0xa1, 0x04, 0xb8, 0x00, 0xb4, 0x04, 0x02, 0x00, 0xb4, 0x06, 0x36, 0x00, 0xb4, 0x05, 0x62, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x04, 0x57, 0x00, 0xb4, 0x05, 0xaa, 0x00, 0x67, 0x05, 0x00, 0x00, 0xb4, 0x04, 0x92, 0x00, 0x79, 0x04, 0x65, 0xff, 0xfb, 0x05, 0x45, 0x00, 0xa0, 0x04, 0xec, 0x00, 0x0e, 0x07, 0x1e, 0x00, 0x3d, 0x04, 0xee, 0x00, 0x36, 0x04, 0x65, 0xff, 0xfd, 0x04, 0xee, 0x00, 0x52, 0x04, 0x69, 0x00, 0x6e, 0x04, 0x92, 0x00, 0xa7, 0x03, 0xf5, 0x00, 0x65, 0x04, 0x92, 0x00, 0x65, 0x04, 0x6e, 0x00, 0x65, 0x02, 0x88, 0x00, 0x2a, 0x04, 0x92, 0x00, 0x65, 0x04, 0x90, 0x00, 0xa7, 0x02, 0x00, 0x00, 0xad, 0x02, 0x00, 0xff, 0xdf, 0x04, 0x2b, 0x00, 0xa7, 0x02, 0x00, 0x00, 0xad, 0x07, 0x03, 0x00, 0xa7, 0x04, 0x90, 0x00, 0xa7, 0x04, 0x67, 0x00, 0x65, 0x04, 0x92, 0x00, 0xa7, 0x04, 0x92, 0x00, 0x65, 0x02, 0xf5, 0x00, 0xa7, 0x03, 0xc0, 0x00, 0x63, 0x02, 0xd2, 0x00, 0x31, 0x04, 0x90, 0x00, 0x9c, 0x04, 0x42, 0x00, 0x36, 0x05, 0xe3, 0x00, 0x4d, 0x04, 0x42, 0x00, 0x35, 0x04, 0x42, 0x00, 0x36, 0x03, 0xc7, 0x00, 0x4f, 0x04, 0x94, 0x00, 0x7a, 0x04, 0x94, 0x00, 0x60, 0x04, 0x94, 0x00, 0x75, 0x04, 0x94, 0x00, 0x8c, 0x04, 0x94, 0x00, 0x51, 0x04, 0x94, 0x00, 0x85, 0x04, 0x94, 0x00, 0x65, 0x04, 0x94, 0x00, 0x3a, 0x04, 0x94, 0x00, 0x7d, 0x04, 0x92, 0x00, 0x5f, 0x04, 0x94, 0x00, 0x79, 0x04, 0x94, 0x00, 0xca, 0x04, 0x94, 0x00, 0x87, 0x04, 0x94, 0x00, 0x8c, 0x04, 0x94, 0x00, 0x5a, 0x04, 0x94, 0x00, 0x8e, 0x04, 0x94, 0x00, 0x80, 0x04, 0x94, 0x00, 0x97, 0x04, 0x94, 0x00, 0x7d, 0x04, 0x94, 0x00, 0x74, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x09, 0xd1, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x05, 0xde, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x6c, 0x00, 0xc3, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x5d, 0x00, 0xb4, 0x07, 0x82, 0x00, 0x89, 0x08, 0x85, 0x00, 0x43, 0x07, 0x81, 0x00, 0x36, 0x08, 0x53, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x08, 0x69, 0x00, 0x55, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x80, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x08, 0x69, 0x00, 0x55, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x1f, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x0b, 0x8c, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x99, 0x07, 0x81, 0x00, 0x34, 0x08, 0x69, 0x00, 0x56, 0x07, 0x81, 0x00, 0x34, 0x07, 0x81, 0x00, 0x36, 0x07, 0x81, 0x00, 0x36, 0x07, 0x81, 0x00, 0x36, 0x07, 0x81, 0x00, 0x36, 0x07, 0x81, 0x00, 0x36, 0x07, 0x81, 0x00, 0x36, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0xfd, 0x28, 0x00, 0x00, 0xfd, 0xb5, 0x00, 0x00, 0xfd, 0x0b, 0x00, 0x00, 0xfd, 0x58, 0x00, 0x00, 0xfd, 0x21, 0x00, 0x00, 0xfd, 0x21, 0x00, 0x00, 0xfd, 0x1a, 0x00, 0x00, 0xfd, 0x1a, 0x00, 0x00, 0xfd, 0xd8, 0x00, 0x00, 0xfd, 0x36, 0x00, 0x00, 0xfc, 0xad, 0x00, 0x87, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x07, 0x11, 0x00, 0x75, 0x02, 0x01, 0xff, 0xee, 0x02, 0x2c, 0xff, 0xee, 0x07, 0x74, 0x00, 0x75, 0x03, 0x71, 0xff, 0xee, 0x03, 0xa4, 0xff, 0xee, 0x06, 0x01, 0x00, 0x60, 0x03, 0x71, 0xff, 0xee, 0x03, 0xa4, 0xff, 0xee, 0x02, 0x01, 0xff, 0xee, 0x02, 0x2c, 0xff, 0xee, 0x01, 0x8a, 0x00, 0x00, 0x07, 0x11, 0x00, 0x75, 0x02, 0x01, 0xff, 0xee, 0x02, 0x2c, 0xff, 0xee, 0x07, 0x11, 0x00, 0x75, 0x02, 0x01, 0xff, 0xee, 0x02, 0x2c, 0xff, 0xee, 0x04, 0xa5, 0x00, 0x8d, 0x04, 0x73, 0xff, 0xee, 0x04, 0xa5, 0xff, 0xee, 0x04, 0xa5, 0x00, 0x8d, 0x04, 0x73, 0xff, 0xee, 0x04, 0xa5, 0xff, 0xee, 0x04, 0xa5, 0x00, 0x8d, 0x04, 0x73, 0xff, 0xee, 0x04, 0xa5, 0xff, 0xee, 0x04, 0xa5, 0x00, 0x8d, 0x04, 0x73, 0xff, 0xee, 0x04, 0xa5, 0xff, 0xee, 0x03, 0x08, 0x00, 0x00, 0x05, 0x62, 0x00, 0xbf, 0x02, 0x00, 0x00, 0x0d, 0x02, 0xa3, 0xff, 0x0d, 0x04, 0xec, 0x01, 0x69, 0x04, 0xec, 0x01, 0x69, 0x04, 0xec, 0x01, 0x69, 0x04, 0xec, 0x01, 0x6a, 0x04, 0xec, 0x01, 0x6a, 0x04, 0xec, 0x01, 0x69, 0x04, 0xec, 0x01, 0x69, 0x04, 0xec, 0x01, 0x50, 0x04, 0xec, 0x01, 0x63, 0x04, 0xec, 0x01, 0x50, 0x04, 0xec, 0x01, 0x63, 0x04, 0xec, 0x01, 0x50, 0x04, 0xec, 0x01, 0x63, 0x04, 0xec, 0x01, 0x63, 0x04, 0xec, 0x01, 0x50, 0x04, 0xec, 0x01, 0x50, 0x04, 0xec, 0x01, 0x5c, 0x04, 0xec, 0x01, 0x5c, 0x04, 0xec, 0x01, 0x5c, 0x04, 0xec, 0x01, 0x63, 0x00, 0x00, 0xfc, 0xf1, 0x01, 0x0e, 0x00, 0x00, 0x03, 0xaf, 0x00, 0x00, 0x04, 0x65, 0xff, 0xb4, 0x04, 0x65, 0xff, 0xb4, 0x05, 0x73, 0x00, 0x81, 0x02, 0x31, 0xff, 0xee, 0x02, 0x62, 0xff, 0xee, 0x06, 0x00, 0x00, 0x75, 0x02, 0x01, 0xff, 0xee, 0x02, 0x2c, 0xff, 0xee, 0x03, 0xf9, 0xff, 0xb4, 0x02, 0x00, 0x00, 0xad, 0x03, 0xdc, 0x00, 0x82, 0x05, 0x07, 0x00, 0x65, 0x04, 0x65, 0x00, 0x65, 0x02, 0x00, 0x00, 0x87, 0x02, 0x87, 0x00, 0x47, 0x02, 0x87, 0xff, 0x2e, 0x02, 0x00, 0xff, 0xd8, 0x02, 0x00, 0x00, 0xab, 0x02, 0x6d, 0x00, 0xd8, 0x03, 0x31, 0x00, 0x87, 0x06, 0x08, 0x01, 0x82, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0xc6, 0x02, 0x01, 0x00, 0xad, 0x02, 0x01, 0xff, 0xee, 0x02, 0x01, 0xff, 0xee, 0x04, 0x1d, 0x00, 0x65, 0x04, 0x1d, 0xff, 0xee, 0x04, 0x1d, 0xff, 0xee, 0x03, 0x0d, 0x00, 0x36, 0x03, 0x0d, 0xff, 0xee, 0x03, 0x0d, 0xff, 0xee, 0x04, 0x42, 0x00, 0x36, 0x04, 0x42, 0xff, 0xee, 0x04, 0x42, 0xff, 0xee, 0x04, 0xb5, 0x00, 0xa7, 0x04, 0xb5, 0xff, 0xee, 0x04, 0xb5, 0xff, 0xee, 0x04, 0xb5, 0x00, 0xa7, 0x04, 0xb5, 0xff, 0xee, 0x04, 0xb5, 0xff, 0xee, 0x04, 0x46, 0x00, 0x65, 0x04, 0x46, 0xff, 0xee, 0x04, 0x46, 0xff, 0xee, 0x04, 0xb5, 0x00, 0xa7, 0x04, 0xb5, 0xff, 0xee, 0x04, 0xb5, 0xff, 0xee, 0x05, 0xf7, 0x00, 0x65, 0x05, 0xf7, 0xff, 0xee, 0x05, 0xf7, 0xff, 0xee, 0x03, 0x27, 0x00, 0xad, 0x03, 0x27, 0xff, 0xee, 0x03, 0x27, 0xff, 0xee, 0x03, 0x27, 0x00, 0x36, 0x03, 0x27, 0xff, 0xee, 0x03, 0x27, 0xff, 0xee, 0x04, 0x05, 0x00, 0xa7, 0x04, 0x05, 0xff, 0xee, 0x04, 0x05, 0xff, 0xee, 0x04, 0x67, 0x00, 0xad, 0x04, 0x67, 0xff, 0xee, 0x04, 0x67, 0xff, 0xee, 0x02, 0x85, 0x00, 0x36, 0x02, 0x85, 0xff, 0xee, 0x02, 0x85, 0xff, 0xee, 0x06, 0xe7, 0x00, 0xad, 0x06, 0xe7, 0xff, 0xee, 0x06, 0xe7, 0xff, 0xee, 0x03, 0x67, 0x00, 0x36, 0x03, 0x67, 0xff, 0xee, 0x03, 0x67, 0xff, 0xee, 0x05, 0xa3, 0x00, 0x36, 0x05, 0xa3, 0xff, 0xee, 0x05, 0xa3, 0xff, 0xee, 0x04, 0xb5, 0x00, 0xa7, 0x04, 0xb5, 0xff, 0xee, 0x04, 0xb5, 0xff, 0xee, 0x04, 0x80, 0x00, 0x36, 0x04, 0x80, 0xff, 0xee, 0x04, 0x80, 0xff, 0xee, 0x05, 0x48, 0x00, 0xad, 0x05, 0x48, 0xff, 0xee, 0x05, 0x48, 0xff, 0xee, 0x03, 0xd0, 0x00, 0xad, 0x03, 0xd0, 0xff, 0xee, 0x03, 0xd0, 0xff, 0xee, 0x05, 0x36, 0x00, 0x64, 0x05, 0x36, 0xff, 0xee, 0x05, 0x36, 0xff, 0xee, 0x03, 0x67, 0x00, 0x36, 0x03, 0x67, 0xff, 0xee, 0x03, 0x67, 0xff, 0xee, 0x04, 0x80, 0x00, 0x36, 0x04, 0x80, 0xff, 0xee, 0x04, 0x80, 0xff, 0xee, 0x04, 0x46, 0x00, 0x65, 0x04, 0x46, 0xff, 0xee, 0x04, 0x46, 0xff, 0xee, 0x03, 0xd0, 0x00, 0xad, 0x03, 0xd0, 0xff, 0xee, 0x03, 0xd0, 0xff, 0xee, 0x03, 0xd0, 0x00, 0xad, 0x03, 0xd0, 0xff, 0xee, 0x03, 0xd0, 0xff, 0xee, 0x03, 0xc3, 0x00, 0xad, 0x03, 0xc3, 0xff, 0xee, 0x03, 0xc3, 0xff, 0xee, 0x04, 0x46, 0x00, 0x65, 0x04, 0x46, 0xff, 0xee, 0x04, 0x46, 0xff, 0xee, 0x04, 0x46, 0x00, 0x65, 0x04, 0x46, 0xff, 0xee, 0x04, 0x46, 0xff, 0xee, 0x00, 0x00, 0xfd, 0x3b, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x74, 0x00, 0x99, 0x06, 0x07, 0x01, 0x6e, 0x05, 0x8f, 0x00, 0xb4, 0x04, 0xdf, 0x00, 0xad, 0x04, 0x90, 0x00, 0x9c, 0x03, 0xc7, 0x00, 0x70, 0x03, 0xc7, 0x00, 0x70, 0x03, 0xc7, 0x00, 0x70, 0x03, 0xc7, 0x00, 0x70, 0x03, 0xc7, 0x00, 0x70, 0x03, 0xf9, 0xff, 0xb4, 0x03, 0xf9, 0xff, 0xb4, 0x03, 0xf9, 0xff, 0xb4, 0x03, 0xf9, 0xff, 0xb4, 0x03, 0xf9, 0xff, 0xb4, 0x09, 0x2d, 0x00, 0x75, 0x06, 0x08, 0xff, 0xee, 0x06, 0x6c, 0xff, 0xee, 0x09, 0x2d, 0x00, 0x75, 0x06, 0x08, 0xff, 0xee, 0x06, 0x6c, 0xff, 0xee, 0x09, 0x2d, 0x00, 0x75, 0x06, 0x08, 0xff, 0xee, 0x06, 0x6c, 0xff, 0xee, 0x08, 0xd2, 0x00, 0x75, 0x06, 0x1d, 0xff, 0xee, 0x06, 0x3e, 0xff, 0xee, 0x08, 0xd2, 0x00, 0x75, 0x06, 0x1d, 0xff, 0xee, 0x06, 0x3e, 0xff, 0xee, 0x06, 0xd5, 0x00, 0x81, 0x05, 0xbb, 0xff, 0xee, 0x05, 0xe8, 0xff, 0xee, 0x03, 0xd5, 0x00, 0x69, 0x04, 0x4b, 0xff, 0xee, 0x03, 0x79, 0xff, 0xee, 0x07, 0x74, 0x00, 0x75, 0x03, 0x71, 0xff, 0xee, 0x03, 0xa4, 0xff, 0xee, 0x07, 0x74, 0x00, 0x75, 0x03, 0x71, 0xff, 0xee, 0x03, 0xa4, 0xff, 0xee, 0x07, 0x74, 0x00, 0x75, 0x03, 0x71, 0xff, 0xee, 0x03, 0xa4, 0xff, 0xee, 0x06, 0x01, 0x00, 0x60, 0x03, 0x71, 0xff, 0xee, 0x03, 0xa4, 0xff, 0xee, 0x06, 0x01, 0x00, 0x60, 0x03, 0x71, 0xff, 0xee, 0x03, 0xa4, 0xff, 0xee, 0x07, 0x96, 0x00, 0x75, 0x06, 0x40, 0xff, 0xee, 0x06, 0x40, 0xff, 0xee, 0x06, 0x71, 0x00, 0x75, 0x03, 0x6d, 0xff, 0xee, 0x03, 0xf9, 0xff, 0xee, 0x06, 0x11, 0x00, 0x81, 0x03, 0x6d, 0xff, 0xee, 0x03, 0xf9, 0xff, 0xee, 0x06, 0x11, 0x00, 0x81, 0x03, 0x6d, 0xff, 0xee, 0x03, 0xf9, 0xff, 0xee, 0x06, 0x71, 0x03, 0x69, 0x03, 0x6d, 0x00, 0x64, 0x03, 0xf9, 0x00, 0x64, 0x06, 0x71, 0x02, 0x1c, 0x03, 0x6d, 0x00, 0x64, 0x03, 0xf9, 0x00, 0x64, 0x06, 0x71, 0x03, 0x2a, 0x03, 0x6d, 0x00, 0x43, 0x03, 0xf9, 0x00, 0x43, 0x05, 0x73, 0x00, 0x81, 0x02, 0x31, 0xff, 0xee, 0x02, 0x62, 0xff, 0xee, 0x05, 0x73, 0x00, 0x81, 0x02, 0x31, 0xff, 0xee, 0x02, 0x62, 0xff, 0xee, 0x05, 0x73, 0x00, 0x81, 0x02, 0x31, 0xff, 0xee, 0x02, 0x62, 0xff, 0xee, 0x05, 0x7b, 0x00, 0x84, 0x02, 0x01, 0xff, 0xee, 0x02, 0x2c, 0xff, 0xee, 0x05, 0x7b, 0x00, 0x84, 0x02, 0x01, 0xff, 0xee, 0x02, 0x2c, 0xff, 0xee, 0x05, 0x7b, 0x00, 0x84, 0x02, 0x01, 0xff, 0xee, 0x02, 0x2c, 0xff, 0xee, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x01, 0x0a, 0xa7, 0x30, 0x00, 0x00, 0x0b, 0x0f, 0xea, 0x00, 0x10, 0x00, 0x24, 0xff, 0xd3, 0x00, 0x10, 0x00, 0x25, 0xff, 0xb7, 0x00, 0x10, 0x00, 0x2a, 0x00, 0x4b, 0x00, 0x10, 0x00, 0x2d, 0x00, 0x72, 0x00, 0x10, 0x00, 0x32, 0x00, 0x39, 0x00, 0x10, 0x00, 0x34, 0x00, 0x4b, 0x00, 0x10, 0x00, 0x37, 0xff, 0x44, 0x00, 0x10, 0x00, 0x39, 0xff, 0x88, 0x00, 0x10, 0x00, 0x3a, 0xff, 0xad, 0x00, 0x10, 0x00, 0x3b, 0xff, 0x9a, 0x00, 0x10, 0x00, 0x3c, 0xff, 0x0d, 0x00, 0x10, 0x00, 0x52, 0x00, 0x26, 0x00, 0x10, 0x00, 0x59, 0xff, 0xc9, 0x00, 0x10, 0x00, 0x5c, 0xff, 0xdc, 0x00, 0x10, 0x00, 0x82, 0xff, 0xd3, 0x00, 0x10, 0x00, 0x83, 0xff, 0xd3, 0x00, 0x10, 0x00, 0x84, 0xff, 0xd3, 0x00, 0x10, 0x00, 0x85, 0xff, 0xd3, 0x00, 0x10, 0x00, 0x86, 0xff, 0xd3, 0x00, 0x10, 0x00, 0x94, 0x00, 0x39, 0x00, 0x10, 0x00, 0x95, 0x00, 0x39, 0x00, 0x10, 0x00, 0x96, 0x00, 0x39, 0x00, 0x10, 0x00, 0x97, 0x00, 0x39, 0x00, 0x10, 0x00, 0x98, 0x00, 0x39, 0x00, 0x10, 0x00, 0x9f, 0xff, 0x0d, 0x00, 0x10, 0x00, 0xb4, 0x00, 0x26, 0x00, 0x10, 0x00, 0xb5, 0x00, 0x26, 0x00, 0x10, 0x00, 0xb6, 0x00, 0x26, 0x00, 0x10, 0x00, 0xb7, 0x00, 0x26, 0x00, 0x10, 0x00, 0xb8, 0x00, 0x26, 0x00, 0x10, 0x00, 0xbf, 0xff, 0xdc, 0x00, 0x10, 0x00, 0xc1, 0xff, 0xdc, 0x00, 0x10, 0x00, 0xc2, 0xff, 0xd3, 0x00, 0x10, 0x00, 0xc4, 0xff, 0xd3, 0x00, 0x10, 0x00, 0xc6, 0xff, 0xd3, 0x00, 0x10, 0x00, 0xe0, 0x00, 0x4b, 0x00, 0x10, 0x01, 0x26, 0xff, 0x44, 0x00, 0x10, 0x01, 0x3a, 0xff, 0x0d, 0x00, 0x24, 0x00, 0x10, 0xff, 0xd3, 0x00, 0x24, 0x00, 0x11, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x24, 0x00, 0x39, 0x00, 0x24, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x34, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x37, 0xff, 0x61, 0x00, 0x24, 0x00, 0x39, 0xff, 0x7d, 0x00, 0x24, 0x00, 0x3a, 0xff, 0x90, 0x00, 0x24, 0x00, 0x3c, 0xff, 0x61, 0x00, 0x24, 0x00, 0x46, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x47, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x48, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x49, 0xff, 0xb7, 0x00, 0x24, 0x00, 0x52, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x54, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x57, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x59, 0xff, 0x88, 0x00, 0x24, 0x00, 0x5a, 0xff, 0xad, 0x00, 0x24, 0x00, 0x5c, 0xff, 0x75, 0x00, 0x24, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0x24, 0x00, 0x82, 0x00, 0x39, 0x00, 0x24, 0x00, 0x83, 0x00, 0x39, 0x00, 0x24, 0x00, 0x84, 0x00, 0x39, 0x00, 0x24, 0x00, 0x85, 0x00, 0x39, 0x00, 0x24, 0x00, 0x86, 0x00, 0x39, 0x00, 0x24, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x24, 0x00, 0x9f, 0xff, 0x61, 0x00, 0x24, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xab, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xac, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xad, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xbf, 0xff, 0x75, 0x00, 0x24, 0x00, 0xc1, 0xff, 0x75, 0x00, 0x24, 0x00, 0xc2, 0x00, 0x39, 0x00, 0x24, 0x00, 0xc4, 0x00, 0x39, 0x00, 0x24, 0x00, 0xc6, 0x00, 0x39, 0x00, 0x24, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xc9, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xca, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xcb, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xcf, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xd3, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xde, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xe0, 0xff, 0xdc, 0x00, 0x24, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x10, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x11, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x12, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x13, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x24, 0xff, 0x61, 0x00, 0x24, 0x01, 0x25, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x26, 0xff, 0x61, 0x00, 0x24, 0x01, 0x27, 0xff, 0xdc, 0x00, 0x24, 0x01, 0x36, 0xff, 0x90, 0x00, 0x24, 0x01, 0x37, 0xff, 0xad, 0x00, 0x24, 0x01, 0x38, 0xff, 0x61, 0x00, 0x24, 0x01, 0x39, 0xff, 0x75, 0x00, 0x24, 0x01, 0x3a, 0xff, 0x61, 0x00, 0x24, 0x01, 0x88, 0xff, 0xdc, 0x00, 0x24, 0x01, 0xac, 0xff, 0xdc, 0x00, 0x24, 0x01, 0xad, 0xff, 0xdc, 0x00, 0x24, 0x01, 0xae, 0xff, 0xdc, 0x00, 0x24, 0x01, 0xaf, 0xff, 0xdc, 0x00, 0x24, 0x01, 0xdc, 0xff, 0x61, 0x00, 0x24, 0x01, 0xdd, 0xff, 0xdc, 0x00, 0x24, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0x24, 0x01, 0xf3, 0xff, 0xdc, 0x00, 0x24, 0x01, 0xf4, 0xff, 0x61, 0x00, 0x24, 0x01, 0xf5, 0xff, 0x75, 0x00, 0x24, 0x05, 0xd0, 0xff, 0x90, 0x00, 0x24, 0x05, 0xd1, 0xff, 0xad, 0x00, 0x24, 0x05, 0xd2, 0xff, 0x90, 0x00, 0x24, 0x05, 0xd3, 0xff, 0xad, 0x00, 0x24, 0x05, 0xd4, 0xff, 0x90, 0x00, 0x24, 0x05, 0xd5, 0xff, 0xad, 0x00, 0x24, 0x06, 0x42, 0xff, 0x61, 0x00, 0x24, 0x06, 0x43, 0xff, 0x75, 0x00, 0x24, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0x24, 0x07, 0x52, 0xff, 0x03, 0x00, 0x24, 0x07, 0x53, 0x00, 0x2f, 0x00, 0x25, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x36, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x39, 0xff, 0xc1, 0x00, 0x25, 0x00, 0x3a, 0xff, 0xb7, 0x00, 0x25, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x25, 0x00, 0x6d, 0xff, 0xc1, 0x00, 0x25, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x25, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x25, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x25, 0x00, 0xca, 0xff, 0xdc, 0x00, 0x25, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0x25, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x25, 0x00, 0xde, 0xff, 0xdc, 0x00, 0x25, 0x00, 0xe0, 0xff, 0xdc, 0x00, 0x25, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0x25, 0x00, 0xe4, 0xff, 0xdc, 0x00, 0x25, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0x25, 0x01, 0x10, 0xff, 0xdc, 0x00, 0x25, 0x01, 0x12, 0xff, 0xdc, 0x00, 0x25, 0x01, 0x1c, 0xff, 0xdc, 0x00, 0x25, 0x01, 0x1e, 0xff, 0xdc, 0x00, 0x25, 0x01, 0x20, 0xff, 0xdc, 0x00, 0x25, 0x01, 0x22, 0xff, 0xdc, 0x00, 0x25, 0x01, 0x36, 0xff, 0xb7, 0x00, 0x25, 0x01, 0x38, 0xff, 0x90, 0x00, 0x25, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x25, 0x01, 0xac, 0xff, 0xdc, 0x00, 0x25, 0x01, 0xae, 0xff, 0xdc, 0x00, 0x25, 0x01, 0xda, 0xff, 0xdc, 0x00, 0x25, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0x25, 0x05, 0xd0, 0xff, 0xb7, 0x00, 0x25, 0x05, 0xd2, 0xff, 0xb7, 0x00, 0x25, 0x05, 0xd4, 0xff, 0xb7, 0x00, 0x25, 0x06, 0x42, 0xff, 0x90, 0x00, 0x25, 0x07, 0x51, 0xff, 0x90, 0x00, 0x25, 0x07, 0x52, 0xff, 0x90, 0x00, 0x25, 0x07, 0x53, 0xff, 0xad, 0x00, 0x26, 0x00, 0x3c, 0xff, 0xdc, 0x00, 0x26, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x26, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x26, 0x00, 0x9f, 0xff, 0xdc, 0x00, 0x26, 0x01, 0x38, 0xff, 0xdc, 0x00, 0x26, 0x01, 0x3a, 0xff, 0xdc, 0x00, 0x26, 0x01, 0xf4, 0xff, 0xdc, 0x00, 0x26, 0x06, 0x42, 0xff, 0xdc, 0x00, 0x26, 0x07, 0x52, 0x00, 0x26, 0x00, 0x27, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x39, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x27, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x27, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x27, 0x00, 0xc2, 0xff, 0xdc, 0x00, 0x27, 0x00, 0xc4, 0xff, 0xdc, 0x00, 0x27, 0x00, 0xc6, 0xff, 0xdc, 0x00, 0x27, 0x01, 0x38, 0xff, 0x90, 0x00, 0x27, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x27, 0x01, 0xf4, 0xff, 0x90, 0x00, 0x27, 0x06, 0x42, 0xff, 0x90, 0x00, 0x27, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x27, 0x07, 0x52, 0xff, 0xc9, 0x00, 0x27, 0x07, 0x53, 0xff, 0x44, 0x00, 0x29, 0x00, 0x11, 0xfe, 0xb7, 0x00, 0x29, 0x00, 0x1d, 0xff, 0x61, 0x00, 0x29, 0x00, 0x24, 0xff, 0x44, 0x00, 0x29, 0x00, 0x36, 0xff, 0xdc, 0x00, 0x29, 0x00, 0x37, 0xff, 0xdc, 0x00, 0x29, 0x00, 0x44, 0xff, 0x44, 0x00, 0x29, 0x00, 0x48, 0xff, 0x90, 0x00, 0x29, 0x00, 0x4c, 0xff, 0x6b, 0x00, 0x29, 0x00, 0x52, 0xff, 0xb7, 0x00, 0x29, 0x00, 0x55, 0xff, 0x6b, 0x00, 0x29, 0x00, 0x58, 0xff, 0x90, 0x00, 0x29, 0x00, 0x5c, 0xff, 0x44, 0x00, 0x29, 0x00, 0x82, 0xff, 0x44, 0x00, 0x29, 0x00, 0x83, 0xff, 0x44, 0x00, 0x29, 0x00, 0x84, 0xff, 0x44, 0x00, 0x29, 0x00, 0x85, 0xff, 0x44, 0x00, 0x29, 0x00, 0x86, 0xff, 0x44, 0x00, 0x29, 0x00, 0xa2, 0xff, 0x44, 0x00, 0x29, 0x00, 0xa3, 0xff, 0x44, 0x00, 0x29, 0x00, 0xa4, 0xff, 0x44, 0x00, 0x29, 0x00, 0xa5, 0xff, 0x44, 0x00, 0x29, 0x00, 0xa6, 0xff, 0x44, 0x00, 0x29, 0x00, 0xa7, 0xff, 0x44, 0x00, 0x29, 0x00, 0xaa, 0xff, 0x90, 0x00, 0x29, 0x00, 0xab, 0xff, 0x90, 0x00, 0x29, 0x00, 0xac, 0xff, 0x90, 0x00, 0x29, 0x00, 0xad, 0xff, 0x90, 0x00, 0x29, 0x00, 0xb4, 0xff, 0xb7, 0x00, 0x29, 0x00, 0xb5, 0xff, 0xb7, 0x00, 0x29, 0x00, 0xb6, 0xff, 0xb7, 0x00, 0x29, 0x00, 0xb7, 0xff, 0xb7, 0x00, 0x29, 0x00, 0xb8, 0xff, 0xb7, 0x00, 0x29, 0x00, 0xbb, 0xff, 0x90, 0x00, 0x29, 0x00, 0xbc, 0xff, 0x90, 0x00, 0x29, 0x00, 0xbd, 0xff, 0x90, 0x00, 0x29, 0x00, 0xbe, 0xff, 0x90, 0x00, 0x29, 0x00, 0xbf, 0xff, 0x44, 0x00, 0x29, 0x00, 0xc1, 0xff, 0x44, 0x00, 0x29, 0x00, 0xc2, 0xff, 0x44, 0x00, 0x29, 0x00, 0xc3, 0xff, 0x44, 0x00, 0x29, 0x00, 0xc4, 0xff, 0x44, 0x00, 0x29, 0x00, 0xc5, 0xff, 0x44, 0x00, 0x29, 0x00, 0xc6, 0xff, 0x44, 0x00, 0x29, 0x00, 0xc7, 0xff, 0x44, 0x00, 0x29, 0x00, 0xd5, 0xff, 0x90, 0x00, 0x29, 0x00, 0xd7, 0xff, 0x90, 0x00, 0x29, 0x00, 0xd9, 0xff, 0x90, 0x00, 0x29, 0x00, 0xdb, 0xff, 0x90, 0x00, 0x29, 0x00, 0xdd, 0xff, 0x90, 0x00, 0x29, 0x00, 0xf1, 0xff, 0x6b, 0x00, 0x29, 0x00, 0xf5, 0xff, 0x6b, 0x00, 0x29, 0x01, 0x0f, 0xff, 0xb7, 0x00, 0x29, 0x01, 0x11, 0xff, 0xb7, 0x00, 0x29, 0x01, 0x13, 0xff, 0xb7, 0x00, 0x29, 0x01, 0x17, 0xff, 0x6b, 0x00, 0x29, 0x01, 0x19, 0xff, 0x6b, 0x00, 0x29, 0x01, 0x1b, 0xff, 0x6b, 0x00, 0x29, 0x01, 0x1c, 0xff, 0xdc, 0x00, 0x29, 0x01, 0x1e, 0xff, 0xdc, 0x00, 0x29, 0x01, 0x20, 0xff, 0xdc, 0x00, 0x29, 0x01, 0x22, 0xff, 0xdc, 0x00, 0x29, 0x01, 0x24, 0xff, 0xdc, 0x00, 0x29, 0x01, 0x26, 0xff, 0xdc, 0x00, 0x29, 0x01, 0x28, 0xff, 0xdc, 0x00, 0x29, 0x01, 0x2b, 0xff, 0x90, 0x00, 0x29, 0x01, 0x2d, 0xff, 0x90, 0x00, 0x29, 0x01, 0x2f, 0xff, 0x90, 0x00, 0x29, 0x01, 0x31, 0xff, 0x90, 0x00, 0x29, 0x01, 0x33, 0xff, 0x90, 0x00, 0x29, 0x01, 0x35, 0xff, 0x90, 0x00, 0x29, 0x01, 0x39, 0xff, 0x44, 0x00, 0x29, 0x01, 0xad, 0xff, 0xb7, 0x00, 0x29, 0x01, 0xaf, 0xff, 0xb7, 0x00, 0x29, 0x01, 0xda, 0xff, 0xdc, 0x00, 0x29, 0x01, 0xdc, 0xff, 0xdc, 0x00, 0x29, 0x01, 0xf1, 0xff, 0xb7, 0x00, 0x29, 0x01, 0xf5, 0xff, 0x44, 0x00, 0x29, 0x06, 0x43, 0xff, 0x44, 0x00, 0x29, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x29, 0x07, 0x53, 0xfe, 0x88, 0x00, 0x2a, 0x00, 0x37, 0xff, 0xb7, 0x00, 0x2a, 0x00, 0x3c, 0xff, 0x9a, 0x00, 0x2a, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x2a, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x2a, 0x00, 0x9f, 0xff, 0x9a, 0x00, 0x2a, 0x01, 0x26, 0xff, 0xb7, 0x00, 0x2a, 0x01, 0x3a, 0xff, 0x9a, 0x00, 0x2a, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x2a, 0x07, 0x52, 0xff, 0xd3, 0x00, 0x2a, 0x07, 0x53, 0xff, 0xc9, 0x00, 0x2b, 0x00, 0x11, 0xff, 0xdc, 0x00, 0x2b, 0x07, 0x51, 0xff, 0xb7, 0x00, 0x2b, 0x07, 0x52, 0xff, 0xc1, 0x00, 0x2b, 0x07, 0x53, 0xff, 0xb7, 0x00, 0x2d, 0x00, 0x10, 0xff, 0xb7, 0x00, 0x2d, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x2d, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x2d, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x2d, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x2d, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x2d, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x2d, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x2d, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x2d, 0x07, 0x51, 0xff, 0xb7, 0x00, 0x2d, 0x07, 0x52, 0xff, 0xc1, 0x00, 0x2d, 0x07, 0x53, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x10, 0xff, 0x29, 0x00, 0x2e, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0x26, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x32, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x37, 0xff, 0x61, 0x00, 0x2e, 0x00, 0x38, 0xff, 0xc9, 0x00, 0x2e, 0x00, 0x3a, 0xff, 0xb7, 0x00, 0x2e, 0x00, 0x3c, 0xff, 0xb7, 0x00, 0x2e, 0x00, 0x44, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0x48, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0x52, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0x58, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0x5c, 0xff, 0x6b, 0x00, 0x2e, 0x00, 0x6d, 0xff, 0x7d, 0x00, 0x2e, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0x89, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x94, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x95, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x96, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x97, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x98, 0xff, 0x90, 0x00, 0x2e, 0x00, 0x9b, 0xff, 0xc9, 0x00, 0x2e, 0x00, 0x9c, 0xff, 0xc9, 0x00, 0x2e, 0x00, 0x9d, 0xff, 0xc9, 0x00, 0x2e, 0x00, 0x9e, 0xff, 0xc9, 0x00, 0x2e, 0x00, 0x9f, 0xff, 0xb7, 0x00, 0x2e, 0x00, 0xa2, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0xa3, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0xa4, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0xa5, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0xa6, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0xa7, 0xff, 0xdc, 0x00, 0x2e, 0x00, 0xaa, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xab, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xac, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xad, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xb4, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xb5, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xb6, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xb7, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xb8, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xbb, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xbc, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xbd, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xbe, 0xff, 0x9a, 0x00, 0x2e, 0x00, 0xbf, 0xff, 0x6b, 0x00, 0x2e, 0x00, 0xc1, 0xff, 0x6b, 0x00, 0x2e, 0x00, 0xc8, 0xff, 0x90, 0x00, 0x2e, 0x00, 0xce, 0xff, 0x90, 0x00, 0x2e, 0x00, 0xdd, 0xff, 0x9a, 0x00, 0x2e, 0x01, 0x26, 0xff, 0x61, 0x00, 0x2e, 0x01, 0x30, 0xff, 0xc9, 0x00, 0x2e, 0x01, 0x31, 0xff, 0x9a, 0x00, 0x2e, 0x01, 0x3a, 0xff, 0xb7, 0x00, 0x2e, 0x07, 0x51, 0xff, 0xc1, 0x00, 0x2e, 0x07, 0x52, 0xff, 0xc1, 0x00, 0x2f, 0x00, 0x10, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0x24, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x32, 0xff, 0xb7, 0x00, 0x2f, 0x00, 0x37, 0xfe, 0xe6, 0x00, 0x2f, 0x00, 0x38, 0xff, 0x9a, 0x00, 0x2f, 0x00, 0x39, 0xff, 0x1f, 0x00, 0x2f, 0x00, 0x3a, 0xff, 0x44, 0x00, 0x2f, 0x00, 0x3c, 0xfe, 0xf0, 0x00, 0x2f, 0x00, 0x48, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0x52, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0x58, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0x5c, 0xff, 0x44, 0x00, 0x2f, 0x00, 0x82, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x83, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x84, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x85, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x86, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x94, 0xff, 0xb7, 0x00, 0x2f, 0x00, 0x95, 0xff, 0xb7, 0x00, 0x2f, 0x00, 0x96, 0xff, 0xb7, 0x00, 0x2f, 0x00, 0x97, 0xff, 0xb7, 0x00, 0x2f, 0x00, 0x98, 0xff, 0xb7, 0x00, 0x2f, 0x00, 0x9b, 0xff, 0x9a, 0x00, 0x2f, 0x00, 0x9c, 0xff, 0x9a, 0x00, 0x2f, 0x00, 0x9d, 0xff, 0x9a, 0x00, 0x2f, 0x00, 0x9e, 0xff, 0x9a, 0x00, 0x2f, 0x00, 0x9f, 0xfe, 0xf0, 0x00, 0x2f, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xab, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xac, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xad, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xbb, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xbc, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xbd, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xbe, 0xff, 0xdc, 0x00, 0x2f, 0x00, 0xbf, 0xff, 0x44, 0x00, 0x2f, 0x00, 0xc1, 0xff, 0x44, 0x00, 0x2f, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0x2f, 0x01, 0x26, 0xfe, 0xe6, 0x00, 0x2f, 0x01, 0x30, 0xff, 0x9a, 0x00, 0x2f, 0x01, 0x31, 0xff, 0xdc, 0x00, 0x2f, 0x01, 0x3a, 0xfe, 0xf0, 0x00, 0x2f, 0x07, 0x51, 0xfe, 0x61, 0x00, 0x2f, 0x07, 0x52, 0xfd, 0xe6, 0x00, 0x32, 0x00, 0x10, 0x00, 0x39, 0x00, 0x32, 0x00, 0x11, 0xff, 0xad, 0x00, 0x32, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x39, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x3b, 0xff, 0x7d, 0x00, 0x32, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x32, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x32, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x32, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x32, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x32, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x32, 0x07, 0x53, 0xff, 0x44, 0x00, 0x33, 0x00, 0x10, 0xff, 0xd3, 0x00, 0x33, 0x00, 0x11, 0xfe, 0xc1, 0x00, 0x33, 0x00, 0x24, 0xff, 0x7d, 0x00, 0x33, 0x00, 0x3c, 0xff, 0xd3, 0x00, 0x33, 0x00, 0x44, 0xff, 0xa4, 0x00, 0x33, 0x00, 0x48, 0xff, 0xb7, 0x00, 0x33, 0x00, 0x4c, 0xff, 0xd3, 0x00, 0x33, 0x00, 0x51, 0xff, 0xdc, 0x00, 0x33, 0x00, 0x52, 0xff, 0xb7, 0x00, 0x33, 0x00, 0x55, 0xff, 0xdc, 0x00, 0x33, 0x00, 0x56, 0xff, 0xdc, 0x00, 0x33, 0x00, 0x58, 0xff, 0xdc, 0x00, 0x33, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x33, 0x00, 0x82, 0xff, 0x7d, 0x00, 0x33, 0x00, 0x83, 0xff, 0x7d, 0x00, 0x33, 0x00, 0x84, 0xff, 0x7d, 0x00, 0x33, 0x00, 0x85, 0xff, 0x7d, 0x00, 0x33, 0x00, 0x86, 0xff, 0x7d, 0x00, 0x33, 0x00, 0x9f, 0xff, 0xd3, 0x00, 0x33, 0x00, 0xa2, 0xff, 0xa4, 0x00, 0x33, 0x00, 0xa3, 0xff, 0xa4, 0x00, 0x33, 0x00, 0xa4, 0xff, 0xa4, 0x00, 0x33, 0x00, 0xa5, 0xff, 0xa4, 0x00, 0x33, 0x00, 0xa6, 0xff, 0xa4, 0x00, 0x33, 0x00, 0xa7, 0xff, 0xa4, 0x00, 0x33, 0x00, 0xaa, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xab, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xac, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xad, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xb3, 0xff, 0xdc, 0x00, 0x33, 0x00, 0xb4, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xb5, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xb6, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xb7, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xb8, 0xff, 0xb7, 0x00, 0x33, 0x00, 0xbb, 0xff, 0xdc, 0x00, 0x33, 0x00, 0xbc, 0xff, 0xdc, 0x00, 0x33, 0x00, 0xbd, 0xff, 0xdc, 0x00, 0x33, 0x00, 0xbe, 0xff, 0xdc, 0x00, 0x33, 0x00, 0xdd, 0xff, 0xb7, 0x00, 0x33, 0x01, 0x0a, 0xff, 0xdc, 0x00, 0x33, 0x01, 0x17, 0xff, 0xdc, 0x00, 0x33, 0x01, 0x1b, 0xff, 0xdc, 0x00, 0x33, 0x01, 0x21, 0xff, 0xdc, 0x00, 0x33, 0x01, 0x23, 0xff, 0xdc, 0x00, 0x33, 0x01, 0x31, 0xff, 0xdc, 0x00, 0x33, 0x01, 0x3a, 0xff, 0xd3, 0x00, 0x33, 0x07, 0x51, 0x00, 0x26, 0x00, 0x33, 0x07, 0x52, 0x00, 0x26, 0x00, 0x33, 0x07, 0x53, 0xfe, 0xb7, 0x00, 0x34, 0x00, 0x10, 0x00, 0x39, 0x00, 0x34, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x34, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x34, 0x07, 0x53, 0xff, 0x7d, 0x00, 0x35, 0x00, 0x10, 0xff, 0xad, 0x00, 0x35, 0x00, 0x11, 0xff, 0xb7, 0x00, 0x35, 0x00, 0x1d, 0xff, 0xc1, 0x00, 0x35, 0x00, 0x24, 0xff, 0xad, 0x00, 0x35, 0x00, 0x26, 0xff, 0x9a, 0x00, 0x35, 0x00, 0x37, 0xff, 0x6b, 0x00, 0x35, 0x00, 0x39, 0xff, 0x90, 0x00, 0x35, 0x00, 0x3a, 0xff, 0xad, 0x00, 0x35, 0x00, 0x3c, 0xff, 0x7d, 0x00, 0x35, 0x00, 0x44, 0xff, 0xd3, 0x00, 0x35, 0x00, 0x48, 0xff, 0xa4, 0x00, 0x35, 0x00, 0x52, 0xff, 0xa4, 0x00, 0x35, 0x00, 0x58, 0xff, 0xa4, 0x00, 0x35, 0x00, 0x5c, 0xff, 0x90, 0x00, 0x35, 0x00, 0x6d, 0xff, 0x90, 0x00, 0x35, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x35, 0x00, 0x82, 0xff, 0xad, 0x00, 0x35, 0x00, 0x83, 0xff, 0xad, 0x00, 0x35, 0x00, 0x84, 0xff, 0xad, 0x00, 0x35, 0x00, 0x85, 0xff, 0xad, 0x00, 0x35, 0x00, 0x86, 0xff, 0xad, 0x00, 0x35, 0x00, 0x89, 0xff, 0x9a, 0x00, 0x35, 0x00, 0x9f, 0xff, 0x7d, 0x00, 0x35, 0x00, 0xa2, 0xff, 0xd3, 0x00, 0x35, 0x00, 0xa3, 0xff, 0xd3, 0x00, 0x35, 0x00, 0xa4, 0xff, 0xd3, 0x00, 0x35, 0x00, 0xa5, 0xff, 0xd3, 0x00, 0x35, 0x00, 0xa6, 0xff, 0xd3, 0x00, 0x35, 0x00, 0xa7, 0xff, 0xd3, 0x00, 0x35, 0x00, 0xaa, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xab, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xac, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xad, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xb4, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xb5, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xb6, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xb7, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xb8, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xbb, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xbc, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xbd, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xbe, 0xff, 0xa4, 0x00, 0x35, 0x00, 0xbf, 0xff, 0x90, 0x00, 0x35, 0x00, 0xc1, 0xff, 0x90, 0x00, 0x35, 0x00, 0xc8, 0xff, 0x9a, 0x00, 0x35, 0x00, 0xce, 0xff, 0x9a, 0x00, 0x35, 0x00, 0xdd, 0xff, 0xa4, 0x00, 0x35, 0x01, 0x26, 0xff, 0x6b, 0x00, 0x35, 0x01, 0x31, 0xff, 0xa4, 0x00, 0x35, 0x01, 0x3a, 0xff, 0x7d, 0x00, 0x35, 0x07, 0x51, 0xff, 0x6b, 0x00, 0x35, 0x07, 0x52, 0xff, 0x7d, 0x00, 0x35, 0x07, 0x53, 0xff, 0xdc, 0x00, 0x36, 0x00, 0x24, 0x00, 0x26, 0x00, 0x36, 0x00, 0x82, 0x00, 0x26, 0x00, 0x36, 0x00, 0x83, 0x00, 0x26, 0x00, 0x36, 0x00, 0x84, 0x00, 0x26, 0x00, 0x36, 0x00, 0x85, 0x00, 0x26, 0x00, 0x36, 0x00, 0x86, 0x00, 0x26, 0x00, 0x37, 0x00, 0x10, 0xff, 0x44, 0x00, 0x37, 0x00, 0x11, 0xff, 0x0d, 0x00, 0x37, 0x00, 0x1d, 0xff, 0x1f, 0x00, 0x37, 0x00, 0x24, 0xff, 0x61, 0x00, 0x37, 0x00, 0x26, 0xff, 0x88, 0x00, 0x37, 0x00, 0x37, 0xff, 0xdc, 0x00, 0x37, 0x00, 0x44, 0xfe, 0xad, 0x00, 0x37, 0x00, 0x46, 0xfe, 0xa4, 0x00, 0x37, 0x00, 0x48, 0xfe, 0xa4, 0x00, 0x37, 0x00, 0x4c, 0xff, 0xc1, 0x00, 0x37, 0x00, 0x52, 0xfe, 0xa4, 0x00, 0x37, 0x00, 0x55, 0xfe, 0xd3, 0x00, 0x37, 0x00, 0x56, 0xfe, 0xad, 0x00, 0x37, 0x00, 0x58, 0xfe, 0xc9, 0x00, 0x37, 0x00, 0x5a, 0xfe, 0xad, 0x00, 0x37, 0x00, 0x5c, 0xfe, 0xc1, 0x00, 0x37, 0x00, 0x6d, 0xff, 0x44, 0x00, 0x37, 0x00, 0x7d, 0xff, 0x90, 0x00, 0x37, 0x00, 0x82, 0xff, 0x61, 0x00, 0x37, 0x00, 0x83, 0xff, 0x61, 0x00, 0x37, 0x00, 0x84, 0xff, 0x61, 0x00, 0x37, 0x00, 0x85, 0xff, 0x61, 0x00, 0x37, 0x00, 0x86, 0xff, 0x61, 0x00, 0x37, 0x00, 0x89, 0xff, 0x88, 0x00, 0x37, 0x00, 0xa2, 0xff, 0x11, 0x00, 0x37, 0x00, 0xa3, 0xfe, 0xad, 0x00, 0x37, 0x00, 0xa4, 0xff, 0x11, 0x00, 0x37, 0x00, 0xa5, 0xff, 0x11, 0x00, 0x37, 0x00, 0xa6, 0xff, 0x11, 0x00, 0x37, 0x00, 0xa7, 0xff, 0x11, 0x00, 0x37, 0x00, 0xa9, 0xfe, 0xa4, 0x00, 0x37, 0x00, 0xaa, 0xfe, 0xe0, 0x00, 0x37, 0x00, 0xab, 0xfe, 0xa4, 0x00, 0x37, 0x00, 0xac, 0xfe, 0xe0, 0x00, 0x37, 0x00, 0xad, 0xfe, 0xe0, 0x00, 0x37, 0x00, 0xb4, 0xfe, 0xf4, 0x00, 0x37, 0x00, 0xb5, 0xfe, 0xa4, 0x00, 0x37, 0x00, 0xb6, 0xfe, 0xf4, 0x00, 0x37, 0x00, 0xb7, 0xfe, 0xf4, 0x00, 0x37, 0x00, 0xb8, 0xfe, 0xf4, 0x00, 0x37, 0x00, 0xbb, 0xfe, 0xe7, 0x00, 0x37, 0x00, 0xbc, 0xfe, 0xc9, 0x00, 0x37, 0x00, 0xbd, 0xfe, 0xe7, 0x00, 0x37, 0x00, 0xbe, 0xfe, 0xe7, 0x00, 0x37, 0x00, 0xbf, 0xfe, 0xc1, 0x00, 0x37, 0x00, 0xc1, 0xfe, 0xc1, 0x00, 0x37, 0x00, 0xc8, 0xff, 0x88, 0x00, 0x37, 0x00, 0xc9, 0xfe, 0xa4, 0x00, 0x37, 0x00, 0xce, 0xff, 0x88, 0x00, 0x37, 0x00, 0xcf, 0xfe, 0xa4, 0x00, 0x37, 0x00, 0xdd, 0xfe, 0xa4, 0x00, 0x37, 0x01, 0x17, 0xfe, 0xd3, 0x00, 0x37, 0x01, 0x1b, 0xfe, 0xd3, 0x00, 0x37, 0x01, 0x21, 0xfe, 0xad, 0x00, 0x37, 0x01, 0x23, 0xfe, 0xad, 0x00, 0x37, 0x01, 0x26, 0xff, 0xdc, 0x00, 0x37, 0x01, 0x31, 0xfe, 0xc9, 0x00, 0x37, 0x07, 0x52, 0xff, 0xd3, 0x00, 0x37, 0x07, 0x53, 0xfe, 0xf8, 0x00, 0x38, 0x00, 0x3d, 0xff, 0xdc, 0x00, 0x38, 0x01, 0x3f, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x10, 0xff, 0x88, 0x00, 0x39, 0x00, 0x11, 0xfe, 0xf8, 0x00, 0x39, 0x00, 0x1d, 0xff, 0x59, 0x00, 0x39, 0x00, 0x24, 0xff, 0x7d, 0x00, 0x39, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x44, 0xff, 0x61, 0x00, 0x39, 0x00, 0x48, 0xff, 0x61, 0x00, 0x39, 0x00, 0x4c, 0xff, 0xd3, 0x00, 0x39, 0x00, 0x52, 0xff, 0x61, 0x00, 0x39, 0x00, 0x58, 0xff, 0x75, 0x00, 0x39, 0x00, 0x5c, 0xff, 0xc9, 0x00, 0x39, 0x00, 0x6d, 0xff, 0x4e, 0x00, 0x39, 0x00, 0x7d, 0xff, 0x90, 0x00, 0x39, 0x00, 0x82, 0xff, 0x7d, 0x00, 0x39, 0x00, 0x83, 0xff, 0x7d, 0x00, 0x39, 0x00, 0x84, 0xff, 0x7d, 0x00, 0x39, 0x00, 0x85, 0xff, 0x7d, 0x00, 0x39, 0x00, 0x86, 0xff, 0x7d, 0x00, 0x39, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x39, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x39, 0x00, 0xa2, 0xff, 0x61, 0x00, 0x39, 0x00, 0xa3, 0xff, 0x61, 0x00, 0x39, 0x00, 0xa4, 0xff, 0x61, 0x00, 0x39, 0x00, 0xa5, 0xff, 0x61, 0x00, 0x39, 0x00, 0xa6, 0xff, 0x61, 0x00, 0x39, 0x00, 0xa7, 0xff, 0x61, 0x00, 0x39, 0x00, 0xaa, 0xff, 0x61, 0x00, 0x39, 0x00, 0xab, 0xff, 0x61, 0x00, 0x39, 0x00, 0xac, 0xff, 0x61, 0x00, 0x39, 0x00, 0xad, 0xff, 0x61, 0x00, 0x39, 0x00, 0xb4, 0xff, 0x61, 0x00, 0x39, 0x00, 0xb5, 0xff, 0x61, 0x00, 0x39, 0x00, 0xb6, 0xff, 0x61, 0x00, 0x39, 0x00, 0xb7, 0xff, 0x61, 0x00, 0x39, 0x00, 0xb8, 0xff, 0x61, 0x00, 0x39, 0x00, 0xbb, 0xff, 0x75, 0x00, 0x39, 0x00, 0xbc, 0xff, 0x75, 0x00, 0x39, 0x00, 0xbd, 0xff, 0x75, 0x00, 0x39, 0x00, 0xbe, 0xff, 0x75, 0x00, 0x39, 0x00, 0xbf, 0xff, 0xc9, 0x00, 0x39, 0x00, 0xc1, 0xff, 0xc9, 0x00, 0x39, 0x00, 0xdd, 0xff, 0x61, 0x00, 0x39, 0x01, 0x31, 0xff, 0x75, 0x00, 0x39, 0x07, 0x53, 0xfe, 0xe6, 0x00, 0x3a, 0x00, 0x10, 0xff, 0xad, 0x00, 0x3a, 0x00, 0x11, 0xff, 0x15, 0x00, 0x3a, 0x00, 0x1d, 0xff, 0x88, 0x00, 0x3a, 0x00, 0x24, 0xff, 0x90, 0x00, 0x3a, 0x00, 0x44, 0xff, 0x7d, 0x00, 0x3a, 0x00, 0x48, 0xff, 0x88, 0x00, 0x3a, 0x00, 0x4c, 0xff, 0xd3, 0x00, 0x3a, 0x00, 0x52, 0xff, 0x88, 0x00, 0x3a, 0x00, 0x55, 0xff, 0xa4, 0x00, 0x3a, 0x00, 0x58, 0xff, 0xb7, 0x00, 0x3a, 0x00, 0x5c, 0xff, 0xdc, 0x00, 0x3a, 0x00, 0x6d, 0xff, 0x90, 0x00, 0x3a, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x3a, 0x00, 0x82, 0xff, 0x90, 0x00, 0x3a, 0x00, 0x83, 0xff, 0x90, 0x00, 0x3a, 0x00, 0x84, 0xff, 0x90, 0x00, 0x3a, 0x00, 0x85, 0xff, 0x90, 0x00, 0x3a, 0x00, 0x86, 0xff, 0x90, 0x00, 0x3a, 0x00, 0xa2, 0xff, 0x7d, 0x00, 0x3a, 0x00, 0xa3, 0xff, 0x7d, 0x00, 0x3a, 0x00, 0xa4, 0xff, 0x7d, 0x00, 0x3a, 0x00, 0xa5, 0xff, 0x7d, 0x00, 0x3a, 0x00, 0xa6, 0xff, 0x7d, 0x00, 0x3a, 0x00, 0xa7, 0xff, 0x7d, 0x00, 0x3a, 0x00, 0xaa, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xab, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xac, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xad, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xb4, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xb5, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xb6, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xb7, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xb8, 0xff, 0x88, 0x00, 0x3a, 0x00, 0xbb, 0xff, 0xb7, 0x00, 0x3a, 0x00, 0xbc, 0xff, 0xb7, 0x00, 0x3a, 0x00, 0xbd, 0xff, 0xb7, 0x00, 0x3a, 0x00, 0xbe, 0xff, 0xb7, 0x00, 0x3a, 0x00, 0xbf, 0xff, 0xdc, 0x00, 0x3a, 0x00, 0xc1, 0xff, 0xdc, 0x00, 0x3a, 0x00, 0xdd, 0xff, 0x88, 0x00, 0x3a, 0x01, 0x17, 0xff, 0xa4, 0x00, 0x3a, 0x01, 0x1b, 0xff, 0xa4, 0x00, 0x3a, 0x01, 0x31, 0xff, 0xb7, 0x00, 0x3a, 0x07, 0x51, 0xff, 0xdc, 0x00, 0x3a, 0x07, 0x53, 0xfe, 0xf8, 0x00, 0x3b, 0x00, 0x10, 0xff, 0x9a, 0x00, 0x3b, 0x00, 0x26, 0xff, 0x6b, 0x00, 0x3b, 0x00, 0x32, 0xff, 0x7d, 0x00, 0x3b, 0x00, 0x37, 0xff, 0xdc, 0x00, 0x3b, 0x00, 0x48, 0xff, 0xa4, 0x00, 0x3b, 0x00, 0x6d, 0xff, 0x90, 0x00, 0x3b, 0x00, 0x89, 0xff, 0x6b, 0x00, 0x3b, 0x00, 0x94, 0xff, 0x7d, 0x00, 0x3b, 0x00, 0x95, 0xff, 0x7d, 0x00, 0x3b, 0x00, 0x96, 0xff, 0x7d, 0x00, 0x3b, 0x00, 0x97, 0xff, 0x7d, 0x00, 0x3b, 0x00, 0x98, 0xff, 0x7d, 0x00, 0x3b, 0x00, 0xaa, 0xff, 0xa4, 0x00, 0x3b, 0x00, 0xab, 0xff, 0xa4, 0x00, 0x3b, 0x00, 0xac, 0xff, 0xa4, 0x00, 0x3b, 0x00, 0xad, 0xff, 0xa4, 0x00, 0x3b, 0x00, 0xc8, 0xff, 0x6b, 0x00, 0x3b, 0x00, 0xce, 0xff, 0x6b, 0x00, 0x3b, 0x00, 0xdd, 0xff, 0xa4, 0x00, 0x3b, 0x01, 0x26, 0xff, 0xdc, 0x00, 0x3b, 0x07, 0x51, 0xff, 0x61, 0x00, 0x3b, 0x07, 0x52, 0xff, 0xad, 0x00, 0x3b, 0x07, 0x53, 0xff, 0xd3, 0x00, 0x3c, 0x00, 0x10, 0xff, 0x0d, 0x00, 0x3c, 0x00, 0x11, 0xfe, 0x61, 0x00, 0x3c, 0x00, 0x1d, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0x24, 0xff, 0x61, 0x00, 0x3c, 0x00, 0x26, 0xff, 0x90, 0x00, 0x3c, 0x00, 0x32, 0xff, 0x90, 0x00, 0x3c, 0x00, 0x44, 0xfe, 0xe6, 0x00, 0x3c, 0x00, 0x48, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0x4c, 0xff, 0xb7, 0x00, 0x3c, 0x00, 0x52, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0x58, 0xff, 0x15, 0x00, 0x3c, 0x00, 0x6d, 0xff, 0x1f, 0x00, 0x3c, 0x00, 0x7d, 0xff, 0x6b, 0x00, 0x3c, 0x00, 0x82, 0xff, 0x61, 0x00, 0x3c, 0x00, 0x83, 0xff, 0x61, 0x00, 0x3c, 0x00, 0x84, 0xff, 0x61, 0x00, 0x3c, 0x00, 0x85, 0xff, 0x61, 0x00, 0x3c, 0x00, 0x86, 0xff, 0x61, 0x00, 0x3c, 0x00, 0x89, 0xff, 0x90, 0x00, 0x3c, 0x00, 0x94, 0xff, 0x90, 0x00, 0x3c, 0x00, 0x95, 0xff, 0x90, 0x00, 0x3c, 0x00, 0x96, 0xff, 0x90, 0x00, 0x3c, 0x00, 0x97, 0xff, 0x90, 0x00, 0x3c, 0x00, 0x98, 0xff, 0x90, 0x00, 0x3c, 0x00, 0xa2, 0xfe, 0xe6, 0x00, 0x3c, 0x00, 0xa3, 0xfe, 0xe6, 0x00, 0x3c, 0x00, 0xa4, 0xfe, 0xe6, 0x00, 0x3c, 0x00, 0xa5, 0xfe, 0xe6, 0x00, 0x3c, 0x00, 0xa6, 0xfe, 0xe6, 0x00, 0x3c, 0x00, 0xa7, 0xfe, 0xe6, 0x00, 0x3c, 0x00, 0xaa, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xab, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xac, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xad, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xb4, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xb5, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xb6, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xb7, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xb8, 0xfe, 0xf0, 0x00, 0x3c, 0x00, 0xbb, 0xff, 0x15, 0x00, 0x3c, 0x00, 0xbc, 0xff, 0x15, 0x00, 0x3c, 0x00, 0xbd, 0xff, 0x15, 0x00, 0x3c, 0x00, 0xbe, 0xff, 0x15, 0x00, 0x3c, 0x00, 0xc8, 0xff, 0x90, 0x00, 0x3c, 0x00, 0xce, 0xff, 0x90, 0x00, 0x3c, 0x00, 0xdd, 0xfe, 0xf0, 0x00, 0x3c, 0x01, 0x31, 0xff, 0x15, 0x00, 0x3c, 0x07, 0x51, 0xff, 0x90, 0x00, 0x3c, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x3c, 0x07, 0x53, 0xfe, 0xf8, 0x00, 0x3d, 0x00, 0x10, 0xff, 0xdc, 0x00, 0x3d, 0x07, 0x51, 0xff, 0xdc, 0x00, 0x3d, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x3d, 0x07, 0x53, 0xff, 0xdc, 0x00, 0x48, 0x00, 0x5b, 0xff, 0xdc, 0x00, 0x49, 0x00, 0x10, 0xff, 0x90, 0x00, 0x49, 0x00, 0x11, 0xff, 0x6b, 0x00, 0x49, 0x00, 0x1d, 0xff, 0xb7, 0x00, 0x49, 0x00, 0x57, 0xff, 0xdc, 0x00, 0x49, 0x00, 0x5a, 0xff, 0xdc, 0x00, 0x49, 0x00, 0x5c, 0xff, 0xdc, 0x00, 0x49, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0x49, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x49, 0x00, 0xbf, 0xff, 0xdc, 0x00, 0x49, 0x00, 0xc1, 0xff, 0xdc, 0x00, 0x49, 0x01, 0x27, 0xff, 0xdc, 0x00, 0x49, 0x07, 0x51, 0x00, 0x41, 0x00, 0x49, 0x07, 0x53, 0xff, 0x15, 0x00, 0x4e, 0x00, 0x44, 0xff, 0xdc, 0x00, 0x4e, 0x00, 0x48, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0x52, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0x58, 0xff, 0xc1, 0x00, 0x4e, 0x00, 0x5c, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xa2, 0xff, 0xdc, 0x00, 0x4e, 0x00, 0xa3, 0xff, 0xdc, 0x00, 0x4e, 0x00, 0xa4, 0xff, 0xdc, 0x00, 0x4e, 0x00, 0xa5, 0xff, 0xdc, 0x00, 0x4e, 0x00, 0xa6, 0xff, 0xdc, 0x00, 0x4e, 0x00, 0xa7, 0xff, 0xdc, 0x00, 0x4e, 0x00, 0xaa, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xab, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xac, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xad, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xb4, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xb5, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xb6, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xb7, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xb8, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xbb, 0xff, 0xc1, 0x00, 0x4e, 0x00, 0xbc, 0xff, 0xc1, 0x00, 0x4e, 0x00, 0xbd, 0xff, 0xc1, 0x00, 0x4e, 0x00, 0xbe, 0xff, 0xc1, 0x00, 0x4e, 0x00, 0xbf, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xc1, 0xff, 0xb7, 0x00, 0x4e, 0x00, 0xdd, 0xff, 0xb7, 0x00, 0x4e, 0x01, 0x31, 0xff, 0xc1, 0x00, 0x51, 0x07, 0x51, 0xff, 0x6b, 0x00, 0x51, 0x07, 0x52, 0xff, 0x90, 0x00, 0x51, 0x07, 0x53, 0xff, 0xa4, 0x00, 0x52, 0x00, 0x10, 0x00, 0x26, 0x00, 0x52, 0x00, 0x11, 0xff, 0xdc, 0x00, 0x52, 0x00, 0x5b, 0xff, 0xc1, 0x00, 0x52, 0x07, 0x51, 0xff, 0x6b, 0x00, 0x52, 0x07, 0x52, 0xff, 0xb7, 0x00, 0x52, 0x07, 0x53, 0xff, 0x7d, 0x00, 0x55, 0x00, 0x10, 0xff, 0x7d, 0x00, 0x55, 0x00, 0x11, 0xff, 0x44, 0x00, 0x55, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x55, 0x00, 0x46, 0xff, 0xd3, 0x00, 0x55, 0x00, 0x47, 0xff, 0xdc, 0x00, 0x55, 0x00, 0x48, 0xff, 0xd3, 0x00, 0x55, 0x00, 0x4a, 0xff, 0xdc, 0x00, 0x55, 0x00, 0x4b, 0xff, 0xdc, 0x00, 0x55, 0x00, 0x50, 0xff, 0xdc, 0x00, 0x55, 0x00, 0x51, 0xff, 0xdc, 0x00, 0x55, 0x00, 0x52, 0xff, 0xd3, 0x00, 0x55, 0x00, 0x54, 0xff, 0xdc, 0x00, 0x55, 0x00, 0x55, 0xff, 0xdc, 0x00, 0x55, 0x00, 0x5b, 0xff, 0xc9, 0x00, 0x55, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0x55, 0x00, 0xa9, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xaa, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xab, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xac, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xad, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xb3, 0xff, 0xdc, 0x00, 0x55, 0x00, 0xb4, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xb5, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xb6, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xb7, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xb8, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xc9, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xcf, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xd1, 0x00, 0x48, 0x00, 0x55, 0x00, 0xdd, 0xff, 0xd3, 0x00, 0x55, 0x00, 0xe1, 0xff, 0xdc, 0x00, 0x55, 0x01, 0x0a, 0xff, 0xdc, 0x00, 0x55, 0x01, 0x17, 0xff, 0xdc, 0x00, 0x55, 0x01, 0x1b, 0xff, 0xdc, 0x00, 0x55, 0x07, 0x52, 0x00, 0x56, 0x00, 0x55, 0x07, 0x53, 0xfe, 0xc9, 0x00, 0x59, 0x00, 0x10, 0xff, 0xc9, 0x00, 0x59, 0x00, 0x11, 0xff, 0x61, 0x00, 0x59, 0x00, 0x1d, 0xff, 0x90, 0x00, 0x59, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x59, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x59, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x59, 0x07, 0x53, 0xfe, 0xf0, 0x00, 0x5a, 0x00, 0x11, 0xff, 0x44, 0x00, 0x5a, 0x00, 0x1d, 0xff, 0x90, 0x00, 0x5a, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x5a, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x5a, 0x07, 0x53, 0xff, 0x29, 0x00, 0x5b, 0x00, 0x46, 0xff, 0xdc, 0x00, 0x5b, 0x00, 0x48, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0x52, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0x5b, 0x00, 0xaa, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xab, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xac, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xad, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xb4, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xb5, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xb6, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xb7, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xb8, 0xff, 0xc1, 0x00, 0x5b, 0x00, 0xc9, 0xff, 0xdc, 0x00, 0x5b, 0x00, 0xcf, 0xff, 0xdc, 0x00, 0x5b, 0x00, 0xdd, 0xff, 0xc1, 0x00, 0x5c, 0x00, 0x10, 0xff, 0xdc, 0x00, 0x5c, 0x00, 0x11, 0xfe, 0xdc, 0x00, 0x5c, 0x00, 0x1d, 0xff, 0x6b, 0x00, 0x5c, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x5c, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x5c, 0x07, 0x53, 0xfe, 0xd3, 0x00, 0x6d, 0x00, 0x25, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x27, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x2d, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x37, 0xff, 0x90, 0x00, 0x6d, 0x00, 0x39, 0xff, 0x90, 0x00, 0x6d, 0x00, 0x3a, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x3c, 0xff, 0x6b, 0x00, 0x6d, 0x00, 0x59, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x5a, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x5c, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x88, 0x00, 0x97, 0x00, 0x6d, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0x9f, 0xff, 0x6b, 0x00, 0x6d, 0x00, 0xbf, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0xc1, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0xd0, 0xff, 0xdc, 0x00, 0x6d, 0x00, 0xe0, 0xff, 0xdc, 0x00, 0x6d, 0x01, 0x26, 0xff, 0x90, 0x00, 0x6d, 0x01, 0x3a, 0xff, 0x6b, 0x00, 0x7d, 0x00, 0x24, 0xff, 0xb7, 0x00, 0x7d, 0x00, 0x25, 0xff, 0xb7, 0x00, 0x7d, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x27, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x2d, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x37, 0xff, 0x44, 0x00, 0x7d, 0x00, 0x39, 0xff, 0x4e, 0x00, 0x7d, 0x00, 0x3a, 0xff, 0x90, 0x00, 0x7d, 0x00, 0x3b, 0xff, 0x90, 0x00, 0x7d, 0x00, 0x3c, 0xff, 0x1f, 0x00, 0x7d, 0x00, 0x59, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x5a, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x5c, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x82, 0xff, 0xb7, 0x00, 0x7d, 0x00, 0x83, 0xff, 0xb7, 0x00, 0x7d, 0x00, 0x84, 0xff, 0xb7, 0x00, 0x7d, 0x00, 0x85, 0xff, 0xb7, 0x00, 0x7d, 0x00, 0x86, 0xff, 0xb7, 0x00, 0x7d, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0x9f, 0xff, 0x1f, 0x00, 0x7d, 0x00, 0xbf, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0xc1, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x7d, 0x00, 0xd0, 0xff, 0xdc, 0x00, 0x7d, 0x01, 0x26, 0xff, 0x44, 0x00, 0x7d, 0x01, 0x3a, 0xff, 0x1f, 0x00, 0x82, 0x00, 0x10, 0xff, 0xd3, 0x00, 0x82, 0x00, 0x11, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x24, 0x00, 0x39, 0x00, 0x82, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x34, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x37, 0xff, 0x61, 0x00, 0x82, 0x00, 0x39, 0xff, 0x7d, 0x00, 0x82, 0x00, 0x3a, 0xff, 0x90, 0x00, 0x82, 0x00, 0x3c, 0xff, 0x61, 0x00, 0x82, 0x00, 0x46, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x47, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x48, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x49, 0xff, 0xb7, 0x00, 0x82, 0x00, 0x52, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x54, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x57, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x59, 0xff, 0x88, 0x00, 0x82, 0x00, 0x5a, 0xff, 0xad, 0x00, 0x82, 0x00, 0x5c, 0xff, 0x75, 0x00, 0x82, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0x82, 0x00, 0x82, 0x00, 0x39, 0x00, 0x82, 0x00, 0x83, 0x00, 0x39, 0x00, 0x82, 0x00, 0x84, 0x00, 0x39, 0x00, 0x82, 0x00, 0x85, 0x00, 0x39, 0x00, 0x82, 0x00, 0x86, 0x00, 0x39, 0x00, 0x82, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x82, 0x00, 0x9f, 0xff, 0x61, 0x00, 0x82, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xab, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xac, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xad, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xbf, 0xff, 0x75, 0x00, 0x82, 0x00, 0xc1, 0xff, 0x75, 0x00, 0x82, 0x00, 0xc2, 0x00, 0x39, 0x00, 0x82, 0x00, 0xc4, 0x00, 0x39, 0x00, 0x82, 0x00, 0xc6, 0x00, 0x39, 0x00, 0x82, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xc9, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xca, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xcf, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xde, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xe0, 0xff, 0xdc, 0x00, 0x82, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x10, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x11, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x12, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x13, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x24, 0xff, 0x61, 0x00, 0x82, 0x01, 0x25, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x26, 0xff, 0x61, 0x00, 0x82, 0x01, 0x27, 0xff, 0xdc, 0x00, 0x82, 0x01, 0x36, 0xff, 0x90, 0x00, 0x82, 0x01, 0x37, 0xff, 0xad, 0x00, 0x82, 0x01, 0x38, 0xff, 0x61, 0x00, 0x82, 0x01, 0x39, 0xff, 0x75, 0x00, 0x82, 0x01, 0x3a, 0xff, 0x61, 0x00, 0x82, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0x82, 0x01, 0xf1, 0xff, 0xdc, 0x00, 0x82, 0x05, 0xd0, 0xff, 0x90, 0x00, 0x82, 0x05, 0xd3, 0xff, 0xad, 0x00, 0x82, 0x05, 0xd4, 0xff, 0x90, 0x00, 0x82, 0x05, 0xd5, 0xff, 0xad, 0x00, 0x82, 0x06, 0x42, 0xff, 0x61, 0x00, 0x82, 0x06, 0x43, 0xff, 0x75, 0x00, 0x82, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0x82, 0x07, 0x52, 0xff, 0x03, 0x00, 0x82, 0x07, 0x53, 0x00, 0x2f, 0x00, 0x83, 0x00, 0x10, 0xff, 0xd3, 0x00, 0x83, 0x00, 0x11, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x24, 0x00, 0x39, 0x00, 0x83, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x34, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x37, 0xff, 0x61, 0x00, 0x83, 0x00, 0x39, 0xff, 0x7d, 0x00, 0x83, 0x00, 0x3a, 0xff, 0x90, 0x00, 0x83, 0x00, 0x3c, 0xff, 0x61, 0x00, 0x83, 0x00, 0x46, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x47, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x48, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x49, 0xff, 0xb7, 0x00, 0x83, 0x00, 0x52, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x54, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x57, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x59, 0xff, 0x88, 0x00, 0x83, 0x00, 0x5a, 0xff, 0xad, 0x00, 0x83, 0x00, 0x5c, 0xff, 0x75, 0x00, 0x83, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0x83, 0x00, 0x82, 0x00, 0x39, 0x00, 0x83, 0x00, 0x83, 0x00, 0x39, 0x00, 0x83, 0x00, 0x84, 0x00, 0x39, 0x00, 0x83, 0x00, 0x85, 0x00, 0x39, 0x00, 0x83, 0x00, 0x86, 0x00, 0x39, 0x00, 0x83, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x83, 0x00, 0x9f, 0xff, 0x61, 0x00, 0x83, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xab, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xac, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xad, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xbf, 0xff, 0x75, 0x00, 0x83, 0x00, 0xc1, 0xff, 0x75, 0x00, 0x83, 0x00, 0xc2, 0x00, 0x39, 0x00, 0x83, 0x00, 0xc4, 0x00, 0x39, 0x00, 0x83, 0x00, 0xc6, 0x00, 0x39, 0x00, 0x83, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xc9, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xca, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xcf, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xde, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xe0, 0xff, 0xdc, 0x00, 0x83, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x10, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x11, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x12, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x13, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x24, 0xff, 0x61, 0x00, 0x83, 0x01, 0x25, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x26, 0xff, 0x61, 0x00, 0x83, 0x01, 0x27, 0xff, 0xdc, 0x00, 0x83, 0x01, 0x36, 0xff, 0x90, 0x00, 0x83, 0x01, 0x37, 0xff, 0xad, 0x00, 0x83, 0x01, 0x38, 0xff, 0x61, 0x00, 0x83, 0x01, 0x39, 0xff, 0x75, 0x00, 0x83, 0x01, 0x3a, 0xff, 0x61, 0x00, 0x83, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0x83, 0x01, 0xf1, 0xff, 0xdc, 0x00, 0x83, 0x05, 0xd0, 0xff, 0x90, 0x00, 0x83, 0x05, 0xd2, 0xff, 0x90, 0x00, 0x83, 0x05, 0xd3, 0xff, 0xad, 0x00, 0x83, 0x05, 0xd4, 0xff, 0x90, 0x00, 0x83, 0x05, 0xd5, 0xff, 0xad, 0x00, 0x83, 0x06, 0x42, 0xff, 0x61, 0x00, 0x83, 0x06, 0x43, 0xff, 0x75, 0x00, 0x83, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0x83, 0x07, 0x52, 0xff, 0x03, 0x00, 0x83, 0x07, 0x53, 0x00, 0x2f, 0x00, 0x84, 0x00, 0x10, 0xff, 0xd3, 0x00, 0x84, 0x00, 0x11, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x24, 0x00, 0x39, 0x00, 0x84, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x34, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x37, 0xff, 0x61, 0x00, 0x84, 0x00, 0x39, 0xff, 0x7d, 0x00, 0x84, 0x00, 0x3a, 0xff, 0x90, 0x00, 0x84, 0x00, 0x3c, 0xff, 0x61, 0x00, 0x84, 0x00, 0x46, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x47, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x48, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x49, 0xff, 0xb7, 0x00, 0x84, 0x00, 0x52, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x54, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x57, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x59, 0xff, 0x88, 0x00, 0x84, 0x00, 0x5a, 0xff, 0xad, 0x00, 0x84, 0x00, 0x5c, 0xff, 0x75, 0x00, 0x84, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0x84, 0x00, 0x82, 0x00, 0x39, 0x00, 0x84, 0x00, 0x83, 0x00, 0x39, 0x00, 0x84, 0x00, 0x84, 0x00, 0x39, 0x00, 0x84, 0x00, 0x85, 0x00, 0x39, 0x00, 0x84, 0x00, 0x86, 0x00, 0x39, 0x00, 0x84, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x84, 0x00, 0x9f, 0xff, 0x61, 0x00, 0x84, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xab, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xac, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xad, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xbf, 0xff, 0x75, 0x00, 0x84, 0x00, 0xc1, 0xff, 0x75, 0x00, 0x84, 0x00, 0xc2, 0x00, 0x39, 0x00, 0x84, 0x00, 0xc4, 0x00, 0x39, 0x00, 0x84, 0x00, 0xc6, 0x00, 0x39, 0x00, 0x84, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xc9, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xca, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xcf, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xde, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xe0, 0xff, 0xdc, 0x00, 0x84, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x10, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x11, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x12, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x13, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x24, 0xff, 0x61, 0x00, 0x84, 0x01, 0x25, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x26, 0xff, 0x61, 0x00, 0x84, 0x01, 0x27, 0xff, 0xdc, 0x00, 0x84, 0x01, 0x36, 0xff, 0x90, 0x00, 0x84, 0x01, 0x37, 0xff, 0xad, 0x00, 0x84, 0x01, 0x38, 0xff, 0x61, 0x00, 0x84, 0x01, 0x39, 0xff, 0x75, 0x00, 0x84, 0x01, 0x3a, 0xff, 0x61, 0x00, 0x84, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0x84, 0x01, 0xf1, 0xff, 0xdc, 0x00, 0x84, 0x05, 0xd0, 0xff, 0x90, 0x00, 0x84, 0x05, 0xd2, 0xff, 0x90, 0x00, 0x84, 0x05, 0xd3, 0xff, 0xad, 0x00, 0x84, 0x05, 0xd4, 0xff, 0x90, 0x00, 0x84, 0x05, 0xd5, 0xff, 0xad, 0x00, 0x84, 0x06, 0x42, 0xff, 0x61, 0x00, 0x84, 0x06, 0x43, 0xff, 0x75, 0x00, 0x84, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0x84, 0x07, 0x52, 0xff, 0x03, 0x00, 0x84, 0x07, 0x53, 0x00, 0x2f, 0x00, 0x85, 0x00, 0x10, 0xff, 0xd3, 0x00, 0x85, 0x00, 0x11, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x24, 0x00, 0x39, 0x00, 0x85, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x34, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x37, 0xff, 0x61, 0x00, 0x85, 0x00, 0x39, 0xff, 0x7d, 0x00, 0x85, 0x00, 0x3a, 0xff, 0x90, 0x00, 0x85, 0x00, 0x3c, 0xff, 0x61, 0x00, 0x85, 0x00, 0x46, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x47, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x48, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x49, 0xff, 0xb7, 0x00, 0x85, 0x00, 0x52, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x54, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x57, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x59, 0xff, 0x88, 0x00, 0x85, 0x00, 0x5a, 0xff, 0xad, 0x00, 0x85, 0x00, 0x5c, 0xff, 0x75, 0x00, 0x85, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0x85, 0x00, 0x82, 0x00, 0x39, 0x00, 0x85, 0x00, 0x83, 0x00, 0x39, 0x00, 0x85, 0x00, 0x84, 0x00, 0x39, 0x00, 0x85, 0x00, 0x85, 0x00, 0x39, 0x00, 0x85, 0x00, 0x86, 0x00, 0x39, 0x00, 0x85, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x85, 0x00, 0x9f, 0xff, 0x61, 0x00, 0x85, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xab, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xac, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xad, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xbf, 0xff, 0x75, 0x00, 0x85, 0x00, 0xc1, 0xff, 0x75, 0x00, 0x85, 0x00, 0xc2, 0x00, 0x39, 0x00, 0x85, 0x00, 0xc4, 0x00, 0x39, 0x00, 0x85, 0x00, 0xc6, 0x00, 0x39, 0x00, 0x85, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xc9, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xca, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xcf, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xde, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xe0, 0xff, 0xdc, 0x00, 0x85, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x10, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x11, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x12, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x13, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x24, 0xff, 0x61, 0x00, 0x85, 0x01, 0x25, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x26, 0xff, 0x61, 0x00, 0x85, 0x01, 0x27, 0xff, 0xdc, 0x00, 0x85, 0x01, 0x36, 0xff, 0x90, 0x00, 0x85, 0x01, 0x37, 0xff, 0xad, 0x00, 0x85, 0x01, 0x38, 0xff, 0x61, 0x00, 0x85, 0x01, 0x39, 0xff, 0x75, 0x00, 0x85, 0x01, 0x3a, 0xff, 0x61, 0x00, 0x85, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0x85, 0x05, 0xd0, 0xff, 0x90, 0x00, 0x85, 0x05, 0xd2, 0xff, 0x90, 0x00, 0x85, 0x05, 0xd3, 0xff, 0xad, 0x00, 0x85, 0x05, 0xd4, 0xff, 0x90, 0x00, 0x85, 0x05, 0xd5, 0xff, 0xad, 0x00, 0x85, 0x06, 0x42, 0xff, 0x61, 0x00, 0x85, 0x06, 0x43, 0xff, 0x75, 0x00, 0x85, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0x85, 0x07, 0x52, 0xff, 0x03, 0x00, 0x85, 0x07, 0x53, 0x00, 0x2f, 0x00, 0x86, 0x00, 0x10, 0xff, 0xd3, 0x00, 0x86, 0x00, 0x11, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x24, 0x00, 0x39, 0x00, 0x86, 0x00, 0x26, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x32, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x34, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x37, 0xff, 0x61, 0x00, 0x86, 0x00, 0x39, 0xff, 0x7d, 0x00, 0x86, 0x00, 0x3a, 0xff, 0x90, 0x00, 0x86, 0x00, 0x3c, 0xff, 0x61, 0x00, 0x86, 0x00, 0x46, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x47, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x48, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x49, 0xff, 0xb7, 0x00, 0x86, 0x00, 0x52, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x54, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x57, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x59, 0xff, 0x88, 0x00, 0x86, 0x00, 0x5a, 0xff, 0xad, 0x00, 0x86, 0x00, 0x5c, 0xff, 0x75, 0x00, 0x86, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0x86, 0x00, 0x82, 0x00, 0x39, 0x00, 0x86, 0x00, 0x83, 0x00, 0x39, 0x00, 0x86, 0x00, 0x84, 0x00, 0x39, 0x00, 0x86, 0x00, 0x85, 0x00, 0x39, 0x00, 0x86, 0x00, 0x86, 0x00, 0x39, 0x00, 0x86, 0x00, 0x89, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x94, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x95, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x96, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x97, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x98, 0xff, 0xdc, 0x00, 0x86, 0x00, 0x9f, 0xff, 0x61, 0x00, 0x86, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xab, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xac, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xad, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xbf, 0xff, 0x75, 0x00, 0x86, 0x00, 0xc1, 0xff, 0x75, 0x00, 0x86, 0x00, 0xc2, 0x00, 0x39, 0x00, 0x86, 0x00, 0xc4, 0x00, 0x39, 0x00, 0x86, 0x00, 0xc6, 0x00, 0x39, 0x00, 0x86, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xc9, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xca, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xce, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xcf, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xde, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xe0, 0xff, 0xdc, 0x00, 0x86, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x10, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x11, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x12, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x13, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x24, 0xff, 0x61, 0x00, 0x86, 0x01, 0x25, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x26, 0xff, 0x61, 0x00, 0x86, 0x01, 0x27, 0xff, 0xdc, 0x00, 0x86, 0x01, 0x36, 0xff, 0x90, 0x00, 0x86, 0x01, 0x37, 0xff, 0xad, 0x00, 0x86, 0x01, 0x38, 0xff, 0x61, 0x00, 0x86, 0x01, 0x39, 0xff, 0x75, 0x00, 0x86, 0x01, 0x3a, 0xff, 0x61, 0x00, 0x86, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0x86, 0x01, 0xf1, 0xff, 0xdc, 0x00, 0x86, 0x05, 0xd0, 0xff, 0x90, 0x00, 0x86, 0x05, 0xd2, 0xff, 0x90, 0x00, 0x86, 0x05, 0xd3, 0xff, 0xad, 0x00, 0x86, 0x05, 0xd4, 0xff, 0x90, 0x00, 0x86, 0x05, 0xd5, 0xff, 0xad, 0x00, 0x86, 0x06, 0x42, 0xff, 0x61, 0x00, 0x86, 0x06, 0x43, 0xff, 0x75, 0x00, 0x86, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0x86, 0x07, 0x52, 0xff, 0x03, 0x00, 0x86, 0x07, 0x53, 0x00, 0x2f, 0x00, 0x88, 0x07, 0x51, 0xff, 0xad, 0x00, 0x88, 0x07, 0x52, 0xff, 0xa4, 0x00, 0x88, 0x07, 0x53, 0xff, 0x90, 0x00, 0x89, 0x00, 0x3c, 0xff, 0xdc, 0x00, 0x89, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x89, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x89, 0x00, 0x9f, 0xff, 0xdc, 0x00, 0x89, 0x01, 0x3a, 0xff, 0xdc, 0x00, 0x89, 0x07, 0x52, 0x00, 0x26, 0x00, 0x92, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x39, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x92, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x92, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x92, 0x00, 0xc2, 0xff, 0xdc, 0x00, 0x92, 0x00, 0xc4, 0xff, 0xdc, 0x00, 0x92, 0x00, 0xc6, 0xff, 0xdc, 0x00, 0x92, 0x01, 0x38, 0xff, 0x90, 0x00, 0x92, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x92, 0x01, 0xf4, 0xff, 0x90, 0x00, 0x92, 0x06, 0x42, 0xff, 0x90, 0x00, 0x92, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x92, 0x07, 0x52, 0xff, 0xc9, 0x00, 0x92, 0x07, 0x53, 0xff, 0x44, 0x00, 0x94, 0x00, 0x10, 0x00, 0x39, 0x00, 0x94, 0x00, 0x11, 0xff, 0xad, 0x00, 0x94, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x39, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x3b, 0xff, 0x7d, 0x00, 0x94, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x94, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x94, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x94, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x94, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x94, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x94, 0x07, 0x53, 0xff, 0x44, 0x00, 0x95, 0x00, 0x10, 0x00, 0x39, 0x00, 0x95, 0x00, 0x11, 0xff, 0xad, 0x00, 0x95, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x39, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x3b, 0xff, 0x7d, 0x00, 0x95, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x95, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x95, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x95, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x95, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x95, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x95, 0x07, 0x53, 0xff, 0x44, 0x00, 0x96, 0x00, 0x10, 0x00, 0x39, 0x00, 0x96, 0x00, 0x11, 0xff, 0xad, 0x00, 0x96, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x39, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x3b, 0xff, 0x7d, 0x00, 0x96, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x96, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x96, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x96, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x96, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x96, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x96, 0x07, 0x53, 0xff, 0x44, 0x00, 0x97, 0x00, 0x10, 0x00, 0x39, 0x00, 0x97, 0x00, 0x11, 0xff, 0xad, 0x00, 0x97, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x39, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x3b, 0xff, 0x7d, 0x00, 0x97, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x97, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x97, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x97, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x97, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x97, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x97, 0x07, 0x53, 0xff, 0x44, 0x00, 0x98, 0x00, 0x10, 0x00, 0x39, 0x00, 0x98, 0x00, 0x11, 0xff, 0xad, 0x00, 0x98, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x24, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x39, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x3b, 0xff, 0x7d, 0x00, 0x98, 0x00, 0x3c, 0xff, 0x90, 0x00, 0x98, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x82, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x83, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x84, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x85, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x86, 0xff, 0xdc, 0x00, 0x98, 0x00, 0x9f, 0xff, 0x90, 0x00, 0x98, 0x01, 0x3a, 0xff, 0x90, 0x00, 0x98, 0x07, 0x51, 0xff, 0xd3, 0x00, 0x98, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x98, 0x07, 0x53, 0xff, 0x44, 0x00, 0x9b, 0x00, 0x3d, 0xff, 0xdc, 0x00, 0x9b, 0x01, 0x3f, 0xff, 0xdc, 0x00, 0x9c, 0x00, 0x3d, 0xff, 0xdc, 0x00, 0x9c, 0x01, 0x3f, 0xff, 0xdc, 0x00, 0x9d, 0x00, 0x3d, 0xff, 0xdc, 0x00, 0x9d, 0x01, 0x3f, 0xff, 0xdc, 0x00, 0x9e, 0x00, 0x3d, 0xff, 0xdc, 0x00, 0x9e, 0x01, 0x3f, 0xff, 0xdc, 0x00, 0x9f, 0x00, 0x10, 0xff, 0x0d, 0x00, 0x9f, 0x00, 0x11, 0xfe, 0x61, 0x00, 0x9f, 0x00, 0x1d, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0x24, 0xff, 0x61, 0x00, 0x9f, 0x00, 0x26, 0xff, 0x90, 0x00, 0x9f, 0x00, 0x32, 0xff, 0x90, 0x00, 0x9f, 0x00, 0x44, 0xfe, 0xe6, 0x00, 0x9f, 0x00, 0x48, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0x4c, 0xff, 0xb7, 0x00, 0x9f, 0x00, 0x52, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0x58, 0xff, 0x15, 0x00, 0x9f, 0x00, 0x6d, 0xff, 0x1f, 0x00, 0x9f, 0x00, 0x7d, 0xff, 0x6b, 0x00, 0x9f, 0x00, 0x82, 0xff, 0x61, 0x00, 0x9f, 0x00, 0x83, 0xff, 0x61, 0x00, 0x9f, 0x00, 0x84, 0xff, 0x61, 0x00, 0x9f, 0x00, 0x85, 0xff, 0x61, 0x00, 0x9f, 0x00, 0x86, 0xff, 0x61, 0x00, 0x9f, 0x00, 0x89, 0xff, 0x90, 0x00, 0x9f, 0x00, 0x94, 0xff, 0x90, 0x00, 0x9f, 0x00, 0x95, 0xff, 0x90, 0x00, 0x9f, 0x00, 0x96, 0xff, 0x90, 0x00, 0x9f, 0x00, 0x97, 0xff, 0x90, 0x00, 0x9f, 0x00, 0x98, 0xff, 0x90, 0x00, 0x9f, 0x00, 0xa2, 0xfe, 0xe6, 0x00, 0x9f, 0x00, 0xa3, 0xfe, 0xe6, 0x00, 0x9f, 0x00, 0xa4, 0xfe, 0xe6, 0x00, 0x9f, 0x00, 0xa5, 0xfe, 0xe6, 0x00, 0x9f, 0x00, 0xa6, 0xfe, 0xe6, 0x00, 0x9f, 0x00, 0xa7, 0xfe, 0xe6, 0x00, 0x9f, 0x00, 0xaa, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xab, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xac, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xad, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xb4, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xb5, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xb6, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xb7, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xb8, 0xfe, 0xf0, 0x00, 0x9f, 0x00, 0xbb, 0xff, 0x15, 0x00, 0x9f, 0x00, 0xbc, 0xff, 0x15, 0x00, 0x9f, 0x00, 0xbd, 0xff, 0x15, 0x00, 0x9f, 0x00, 0xbe, 0xff, 0x15, 0x00, 0x9f, 0x00, 0xc8, 0xff, 0x90, 0x00, 0x9f, 0x00, 0xce, 0xff, 0x90, 0x00, 0x9f, 0x00, 0xdd, 0xfe, 0xf0, 0x00, 0x9f, 0x01, 0x31, 0xff, 0x15, 0x00, 0x9f, 0x07, 0x51, 0xff, 0x90, 0x00, 0x9f, 0x07, 0x52, 0xff, 0xdc, 0x00, 0x9f, 0x07, 0x53, 0xfe, 0xf8, 0x00, 0xa0, 0x00, 0x11, 0xff, 0x6b, 0x00, 0xa0, 0x00, 0x1d, 0xff, 0xb7, 0x00, 0xa0, 0x07, 0x51, 0xff, 0xdc, 0x00, 0xa0, 0x07, 0x53, 0xff, 0x44, 0x00, 0xa1, 0x00, 0x10, 0x00, 0x26, 0x00, 0xa1, 0x07, 0x51, 0xff, 0x90, 0x00, 0xa1, 0x07, 0x52, 0xff, 0x90, 0x00, 0xa1, 0x07, 0x53, 0xff, 0xad, 0x00, 0xaa, 0x00, 0x5b, 0xff, 0xdc, 0x00, 0xab, 0x00, 0x5b, 0xff, 0xdc, 0x00, 0xac, 0x00, 0x5b, 0xff, 0xdc, 0x00, 0xad, 0x00, 0x5b, 0xff, 0xdc, 0x00, 0xb2, 0x07, 0x51, 0xff, 0xa4, 0x00, 0xb2, 0x07, 0x52, 0xff, 0x90, 0x00, 0xb2, 0x07, 0x53, 0xff, 0xb7, 0x00, 0xb3, 0x07, 0x51, 0xff, 0x6b, 0x00, 0xb3, 0x07, 0x52, 0xff, 0x90, 0x00, 0xb3, 0x07, 0x53, 0xff, 0xa4, 0x00, 0xb4, 0x00, 0x10, 0x00, 0x26, 0x00, 0xb4, 0x00, 0x11, 0xff, 0xdc, 0x00, 0xb4, 0x00, 0x5b, 0xff, 0xc1, 0x00, 0xb4, 0x07, 0x51, 0xff, 0x6b, 0x00, 0xb4, 0x07, 0x52, 0xff, 0xb7, 0x00, 0xb4, 0x07, 0x53, 0xff, 0x7d, 0x00, 0xb5, 0x00, 0x10, 0x00, 0x26, 0x00, 0xb5, 0x00, 0x11, 0xff, 0xdc, 0x00, 0xb5, 0x00, 0x5b, 0xff, 0xc1, 0x00, 0xb5, 0x07, 0x51, 0xff, 0x6b, 0x00, 0xb5, 0x07, 0x52, 0xff, 0xb7, 0x00, 0xb5, 0x07, 0x53, 0xff, 0x7d, 0x00, 0xb6, 0x00, 0x10, 0x00, 0x26, 0x00, 0xb6, 0x00, 0x11, 0xff, 0xdc, 0x00, 0xb6, 0x00, 0x5b, 0xff, 0xc1, 0x00, 0xb6, 0x07, 0x51, 0xff, 0x6b, 0x00, 0xb6, 0x07, 0x52, 0xff, 0xb7, 0x00, 0xb6, 0x07, 0x53, 0xff, 0x7d, 0x00, 0xb7, 0x00, 0x10, 0x00, 0x26, 0x00, 0xb7, 0x00, 0x11, 0xff, 0xdc, 0x00, 0xb7, 0x00, 0x5b, 0xff, 0xc1, 0x00, 0xb7, 0x07, 0x51, 0xff, 0x6b, 0x00, 0xb7, 0x07, 0x52, 0xff, 0xb7, 0x00, 0xb7, 0x07, 0x53, 0xff, 0x7d, 0x00, 0xb8, 0x00, 0x10, 0x00, 0x26, 0x00, 0xb8, 0x00, 0x11, 0xff, 0xdc, 0x00, 0xb8, 0x00, 0x5b, 0xff, 0xc1, 0x00, 0xb8, 0x07, 0x51, 0xff, 0x6b, 0x00, 0xb8, 0x07, 0x52, 0xff, 0xb7, 0x00, 0xb8, 0x07, 0x53, 0xff, 0x7d, 0x00, 0xbf, 0x00, 0x10, 0xff, 0xdc, 0x00, 0xbf, 0x00, 0x11, 0xfe, 0xdc, 0x00, 0xbf, 0x00, 0x1d, 0xff, 0x6b, 0x00, 0xbf, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0xbf, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0xbf, 0x07, 0x53, 0xfe, 0xd3, 0x00, 0xc1, 0x00, 0x10, 0xff, 0xdc, 0x00, 0xc1, 0x00, 0x11, 0xfe, 0xdc, 0x00, 0xc1, 0x00, 0x1d, 0xff, 0x6b, 0x00, 0xc1, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0xc1, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0xc1, 0x07, 0x53, 0xfe, 0xd3, 0x00, 0xc2, 0x00, 0x10, 0xff, 0xd3, 0x00, 0xc2, 0x00, 0x11, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x24, 0x00, 0x39, 0x00, 0xc2, 0x00, 0x26, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x32, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x34, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x37, 0xff, 0x61, 0x00, 0xc2, 0x00, 0x39, 0xff, 0x7d, 0x00, 0xc2, 0x00, 0x3a, 0xff, 0x90, 0x00, 0xc2, 0x00, 0x3c, 0xff, 0x61, 0x00, 0xc2, 0x00, 0x46, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x47, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x48, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x49, 0xff, 0xb7, 0x00, 0xc2, 0x00, 0x52, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x54, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x57, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x59, 0xff, 0x88, 0x00, 0xc2, 0x00, 0x5a, 0xff, 0xad, 0x00, 0xc2, 0x00, 0x5c, 0xff, 0x75, 0x00, 0xc2, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0xc2, 0x00, 0x82, 0x00, 0x39, 0x00, 0xc2, 0x00, 0x83, 0x00, 0x39, 0x00, 0xc2, 0x00, 0x84, 0x00, 0x39, 0x00, 0xc2, 0x00, 0x85, 0x00, 0x39, 0x00, 0xc2, 0x00, 0x86, 0x00, 0x39, 0x00, 0xc2, 0x00, 0x94, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x95, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x96, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x97, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x98, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0x9f, 0xff, 0x61, 0x00, 0xc2, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xab, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xac, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xad, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xbf, 0xff, 0x75, 0x00, 0xc2, 0x00, 0xc1, 0xff, 0x75, 0x00, 0xc2, 0x00, 0xc2, 0x00, 0x39, 0x00, 0xc2, 0x00, 0xc4, 0x00, 0x39, 0x00, 0xc2, 0x00, 0xc6, 0x00, 0x39, 0x00, 0xc2, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xca, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xce, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xd3, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xde, 0xff, 0xdc, 0x00, 0xc2, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x10, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x11, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x12, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x13, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x24, 0xff, 0x61, 0x00, 0xc2, 0x01, 0x25, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x26, 0xff, 0x61, 0x00, 0xc2, 0x01, 0x27, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0x36, 0xff, 0x90, 0x00, 0xc2, 0x01, 0x37, 0xff, 0xad, 0x00, 0xc2, 0x01, 0x38, 0xff, 0x61, 0x00, 0xc2, 0x01, 0x39, 0xff, 0x75, 0x00, 0xc2, 0x01, 0x3a, 0xff, 0x61, 0x00, 0xc2, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0xc2, 0x01, 0xf1, 0xff, 0xdc, 0x00, 0xc2, 0x05, 0xd0, 0xff, 0x90, 0x00, 0xc2, 0x05, 0xd2, 0xff, 0x90, 0x00, 0xc2, 0x05, 0xd3, 0xff, 0xad, 0x00, 0xc2, 0x05, 0xd4, 0xff, 0x90, 0x00, 0xc2, 0x05, 0xd5, 0xff, 0xad, 0x00, 0xc2, 0x06, 0x42, 0xff, 0x61, 0x00, 0xc2, 0x06, 0x43, 0xff, 0x75, 0x00, 0xc2, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0xc2, 0x07, 0x52, 0xff, 0x02, 0x00, 0xc2, 0x07, 0x53, 0x00, 0x2f, 0x00, 0xc4, 0x00, 0x10, 0xff, 0xd3, 0x00, 0xc4, 0x00, 0x11, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x24, 0x00, 0x39, 0x00, 0xc4, 0x00, 0x26, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x32, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x34, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x37, 0xff, 0x61, 0x00, 0xc4, 0x00, 0x39, 0xff, 0x7d, 0x00, 0xc4, 0x00, 0x3a, 0xff, 0x90, 0x00, 0xc4, 0x00, 0x3c, 0xff, 0x61, 0x00, 0xc4, 0x00, 0x46, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x47, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x48, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x49, 0xff, 0xb7, 0x00, 0xc4, 0x00, 0x52, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x54, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x57, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x59, 0xff, 0x88, 0x00, 0xc4, 0x00, 0x5a, 0xff, 0xad, 0x00, 0xc4, 0x00, 0x5c, 0xff, 0x75, 0x00, 0xc4, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0xc4, 0x00, 0x82, 0x00, 0x39, 0x00, 0xc4, 0x00, 0x83, 0x00, 0x39, 0x00, 0xc4, 0x00, 0x84, 0x00, 0x39, 0x00, 0xc4, 0x00, 0x85, 0x00, 0x39, 0x00, 0xc4, 0x00, 0x86, 0x00, 0x39, 0x00, 0xc4, 0x00, 0x94, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x95, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x96, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x97, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x98, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0x9f, 0xff, 0x61, 0x00, 0xc4, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xab, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xac, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xad, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xbf, 0xff, 0x75, 0x00, 0xc4, 0x00, 0xc1, 0xff, 0x75, 0x00, 0xc4, 0x00, 0xc2, 0x00, 0x39, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0x39, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0x39, 0x00, 0xc4, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xca, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xce, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xd3, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xde, 0xff, 0xdc, 0x00, 0xc4, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x10, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x11, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x12, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x13, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x24, 0xff, 0x61, 0x00, 0xc4, 0x01, 0x25, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x26, 0xff, 0x61, 0x00, 0xc4, 0x01, 0x27, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0x36, 0xff, 0x90, 0x00, 0xc4, 0x01, 0x37, 0xff, 0xad, 0x00, 0xc4, 0x01, 0x38, 0xff, 0x61, 0x00, 0xc4, 0x01, 0x39, 0xff, 0x75, 0x00, 0xc4, 0x01, 0x3a, 0xff, 0x61, 0x00, 0xc4, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0xc4, 0x01, 0xf1, 0xff, 0xdc, 0x00, 0xc4, 0x05, 0xd0, 0xff, 0x90, 0x00, 0xc4, 0x05, 0xd2, 0xff, 0x90, 0x00, 0xc4, 0x05, 0xd3, 0xff, 0xad, 0x00, 0xc4, 0x05, 0xd4, 0xff, 0x90, 0x00, 0xc4, 0x05, 0xd5, 0xff, 0xad, 0x00, 0xc4, 0x06, 0x42, 0xff, 0x61, 0x00, 0xc4, 0x06, 0x43, 0xff, 0x75, 0x00, 0xc4, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0xc4, 0x07, 0x52, 0xff, 0x02, 0x00, 0xc4, 0x07, 0x53, 0x00, 0x2f, 0x00, 0xc6, 0x00, 0x10, 0xff, 0xd3, 0x00, 0xc6, 0x00, 0x11, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x1d, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x24, 0x00, 0x39, 0x00, 0xc6, 0x00, 0x26, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x2a, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x32, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x34, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x37, 0xff, 0x61, 0x00, 0xc6, 0x00, 0x39, 0xff, 0x7d, 0x00, 0xc6, 0x00, 0x3a, 0xff, 0x90, 0x00, 0xc6, 0x00, 0x3c, 0xff, 0x61, 0x00, 0xc6, 0x00, 0x46, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x47, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x48, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x49, 0xff, 0xb7, 0x00, 0xc6, 0x00, 0x52, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x54, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x57, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x59, 0xff, 0x88, 0x00, 0xc6, 0x00, 0x5a, 0xff, 0xad, 0x00, 0xc6, 0x00, 0x6d, 0xff, 0xb7, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x39, 0x00, 0xc6, 0x00, 0x83, 0x00, 0x39, 0x00, 0xc6, 0x00, 0x84, 0x00, 0x39, 0x00, 0xc6, 0x00, 0x85, 0x00, 0x39, 0x00, 0xc6, 0x00, 0x86, 0x00, 0x39, 0x00, 0xc6, 0x00, 0x94, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x95, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x96, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x97, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x98, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0x9f, 0xff, 0x61, 0x00, 0xc6, 0x00, 0xa9, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xab, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xac, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xad, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xc2, 0x00, 0x39, 0x00, 0xc6, 0x00, 0xc4, 0x00, 0x39, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0x39, 0x00, 0xc6, 0x00, 0xc8, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xca, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xcc, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xcd, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xce, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xd1, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xd3, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xd5, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xd7, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xd9, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xdb, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xde, 0xff, 0xdc, 0x00, 0xc6, 0x00, 0xe2, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0x0e, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0x0f, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0x10, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0x11, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0x13, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0x24, 0xff, 0x61, 0x00, 0xc6, 0x01, 0x25, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0x26, 0xff, 0x61, 0x00, 0xc6, 0x01, 0x27, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0x36, 0xff, 0x90, 0x00, 0xc6, 0x01, 0x37, 0xff, 0xad, 0x00, 0xc6, 0x01, 0x38, 0xff, 0x61, 0x00, 0xc6, 0x01, 0x3a, 0xff, 0x61, 0x00, 0xc6, 0x01, 0xf0, 0xff, 0xdc, 0x00, 0xc6, 0x01, 0xf1, 0xff, 0xdc, 0x00, 0xc6, 0x05, 0xd0, 0xff, 0x90, 0x00, 0xc6, 0x05, 0xd2, 0xff, 0x90, 0x00, 0xc6, 0x05, 0xd3, 0xff, 0xad, 0x00, 0xc6, 0x05, 0xd4, 0xff, 0x90, 0x00, 0xc6, 0x05, 0xd5, 0xff, 0xad, 0x00, 0xc6, 0x06, 0x42, 0xff, 0x61, 0x00, 0xc6, 0x07, 0x51, 0xfe, 0xf8, 0x00, 0xc6, 0x07, 0x52, 0xff, 0x02, 0x00, 0xc6, 0x07, 0x53, 0x00, 0x2f, 0x00, 0xc8, 0x00, 0x3c, 0xff, 0xdc, 0x00, 0xc8, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0xc8, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0xc8, 0x00, 0x9f, 0xff, 0xdc, 0x00, 0xc8, 0x01, 0x3a, 0xff, 0xdc, 0x00, 0xc8, 0x07, 0x52, 0x00, 0x26, 0x00, 0xce, 0x00, 0x3c, 0xff, 0xdc, 0x00, 0xce, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0xce, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0xce, 0x00, 0x9f, 0xff, 0xdc, 0x00, 0xce, 0x01, 0x3a, 0xff, 0xdc, 0x00, 0xce, 0x07, 0x52, 0x00, 0x26, 0x00, 0xd0, 0x00, 0x24, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x39, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x3c, 0xff, 0x90, 0x00, 0xd0, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x82, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x83, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x84, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x85, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x86, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0x9f, 0xff, 0x90, 0x00, 0xd0, 0x00, 0xc2, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0xc4, 0xff, 0xdc, 0x00, 0xd0, 0x00, 0xc6, 0xff, 0xdc, 0x00, 0xd0, 0x01, 0x38, 0xff, 0x90, 0x00, 0xd0, 0x01, 0x3a, 0xff, 0x90, 0x00, 0xd0, 0x01, 0xf4, 0xff, 0x90, 0x00, 0xd0, 0x06, 0x42, 0xff, 0x90, 0x00, 0xd0, 0x07, 0x51, 0xff, 0xd3, 0x00, 0xd0, 0x07, 0x52, 0xff, 0xc9, 0x00, 0xd0, 0x07, 0x53, 0xff, 0x44, 0x00, 0xd2, 0x00, 0x24, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x39, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x3c, 0xff, 0x90, 0x00, 0xd2, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x82, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x83, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x84, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x85, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x86, 0xff, 0xdc, 0x00, 0xd2, 0x00, 0x9f, 0xff, 0x90, 0x00, 0xd2, 0x01, 0x3a, 0xff, 0x90, 0x00, 0xd2, 0x07, 0x51, 0xff, 0xd3, 0x00, 0xd2, 0x07, 0x52, 0xff, 0xc9, 0x00, 0xd2, 0x07, 0x53, 0xff, 0x44, 0x00, 0xdd, 0x00, 0x5b, 0xff, 0xdc, 0x00, 0xe0, 0x00, 0x37, 0xff, 0xb7, 0x00, 0xe0, 0x00, 0x3c, 0xff, 0x9a, 0x00, 0xe0, 0x00, 0x6d, 0xff, 0xdc, 0x00, 0xe0, 0x00, 0x7d, 0xff, 0xdc, 0x00, 0xe0, 0x00, 0x9f, 0xff, 0x9a, 0x00, 0xe0, 0x01, 0x26, 0xff, 0xb7, 0x00, 0xe0, 0x01, 0x3a, 0xff, 0x9a, 0x00, 0xe0, 0x07, 0x51, 0xff, 0xd3, 0x00, 0xe0, 0x07, 0x52, 0xff, 0xd3, 0x00, 0xe0, 0x07, 0x53, 0xff, 0xc9, 0x00, 0xfb, 0x00, 0x10, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0x24, 0x00, 0x2f, 0x00, 0xfb, 0x00, 0x32, 0xff, 0xb7, 0x00, 0xfb, 0x00, 0x37, 0xfe, 0xe6, 0x00, 0xfb, 0x00, 0x38, 0xff, 0x9a, 0x00, 0xfb, 0x00, 0x39, 0xff, 0x1f, 0x00, 0xfb, 0x00, 0x3a, 0xff, 0x44, 0x00, 0xfb, 0x00, 0x3c, 0xfe, 0xf0, 0x00, 0xfb, 0x00, 0x48, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0x52, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0x58, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0x5c, 0xff, 0x44, 0x00, 0xfb, 0x00, 0x82, 0x00, 0x2f, 0x00, 0xfb, 0x00, 0x83, 0x00, 0x2f, 0x00, 0xfb, 0x00, 0x84, 0x00, 0x2f, 0x00, 0xfb, 0x00, 0x85, 0x00, 0x2f, 0x00, 0xfb, 0x00, 0x86, 0x00, 0x2f, 0x00, 0xfb, 0x00, 0x94, 0xff, 0xb7, 0x00, 0xfb, 0x00, 0x95, 0xff, 0xb7, 0x00, 0xfb, 0x00, 0x96, 0xff, 0xb7, 0x00, 0xfb, 0x00, 0x97, 0xff, 0xb7, 0x00, 0xfb, 0x00, 0x98, 0xff, 0xb7, 0x00, 0xfb, 0x00, 0x9b, 0xff, 0x9a, 0x00, 0xfb, 0x00, 0x9c, 0xff, 0x9a, 0x00, 0xfb, 0x00, 0x9d, 0xff, 0x9a, 0x00, 0xfb, 0x00, 0x9e, 0xff, 0x9a, 0x00, 0xfb, 0x00, 0x9f, 0xfe, 0xf0, 0x00, 0xfb, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xab, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xac, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xad, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xbb, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xbc, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xbd, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xbe, 0xff, 0xdc, 0x00, 0xfb, 0x00, 0xbf, 0xff, 0x44, 0x00, 0xfb, 0x00, 0xc1, 0xff, 0x44, 0x00, 0xfb, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0xfb, 0x01, 0x26, 0xfe, 0xe6, 0x00, 0xfb, 0x01, 0x30, 0xff, 0x9a, 0x00, 0xfb, 0x01, 0x31, 0xff, 0xdc, 0x00, 0xfb, 0x01, 0x3a, 0xfe, 0xf0, 0x00, 0xfb, 0x07, 0x51, 0xfe, 0x61, 0x00, 0xfb, 0x07, 0x52, 0xfd, 0xe6, 0x00, 0xff, 0x00, 0x10, 0xff, 0xdc, 0x00, 0xff, 0x00, 0x24, 0x00, 0x2f, 0x00, 0xff, 0x00, 0x32, 0xff, 0xb7, 0x00, 0xff, 0x00, 0x37, 0xfe, 0xe6, 0x00, 0xff, 0x00, 0x38, 0xff, 0x9a, 0x00, 0xff, 0x00, 0x39, 0xff, 0x1f, 0x00, 0xff, 0x00, 0x3a, 0xff, 0x44, 0x00, 0xff, 0x00, 0x3c, 0xfe, 0xf0, 0x00, 0xff, 0x00, 0x48, 0xff, 0xdc, 0x00, 0xff, 0x00, 0x52, 0xff, 0xdc, 0x00, 0xff, 0x00, 0x58, 0xff, 0xdc, 0x00, 0xff, 0x00, 0x5c, 0xff, 0x44, 0x00, 0xff, 0x00, 0x82, 0x00, 0x2f, 0x00, 0xff, 0x00, 0x83, 0x00, 0x2f, 0x00, 0xff, 0x00, 0x84, 0x00, 0x2f, 0x00, 0xff, 0x00, 0x85, 0x00, 0x2f, 0x00, 0xff, 0x00, 0x86, 0x00, 0x2f, 0x00, 0xff, 0x00, 0x94, 0xff, 0xb7, 0x00, 0xff, 0x00, 0x95, 0xff, 0xb7, 0x00, 0xff, 0x00, 0x96, 0xff, 0xb7, 0x00, 0xff, 0x00, 0x97, 0xff, 0xb7, 0x00, 0xff, 0x00, 0x98, 0xff, 0xb7, 0x00, 0xff, 0x00, 0x9b, 0xff, 0x9a, 0x00, 0xff, 0x00, 0x9c, 0xff, 0x9a, 0x00, 0xff, 0x00, 0x9d, 0xff, 0x9a, 0x00, 0xff, 0x00, 0x9e, 0xff, 0x9a, 0x00, 0xff, 0x00, 0x9f, 0xfe, 0xf0, 0x00, 0xff, 0x00, 0xaa, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xab, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xac, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xad, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xb4, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xb5, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xb6, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xb7, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xb8, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xbb, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xbc, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xbd, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xbe, 0xff, 0xdc, 0x00, 0xff, 0x00, 0xbf, 0xff, 0x44, 0x00, 0xff, 0x00, 0xc1, 0xff, 0x44, 0x00, 0xff, 0x00, 0xdd, 0xff, 0xdc, 0x00, 0xff, 0x01, 0x26, 0xfe, 0xe6, 0x00, 0xff, 0x01, 0x30, 0xff, 0x9a, 0x00, 0xff, 0x01, 0x31, 0xff, 0xdc, 0x00, 0xff, 0x01, 0x3a, 0xfe, 0xf0, 0x00, 0xff, 0x07, 0x51, 0xfe, 0x61, 0x00, 0xff, 0x07, 0x52, 0xfd, 0xe6, 0x01, 0x02, 0x00, 0x4f, 0xff, 0x3f, 0x01, 0x0a, 0x07, 0x51, 0xff, 0x6b, 0x01, 0x0a, 0x07, 0x52, 0xff, 0x90, 0x01, 0x0a, 0x07, 0x53, 0xff, 0xa4, 0x01, 0x16, 0x00, 0x10, 0xff, 0xad, 0x01, 0x16, 0x00, 0x11, 0xff, 0xb7, 0x01, 0x16, 0x00, 0x1d, 0xff, 0xc1, 0x01, 0x16, 0x00, 0x24, 0xff, 0xad, 0x01, 0x16, 0x00, 0x26, 0xff, 0x9a, 0x01, 0x16, 0x00, 0x37, 0xff, 0x6b, 0x01, 0x16, 0x00, 0x39, 0xff, 0x90, 0x01, 0x16, 0x00, 0x3a, 0xff, 0xad, 0x01, 0x16, 0x00, 0x3c, 0xff, 0x7d, 0x01, 0x16, 0x00, 0x44, 0xff, 0xd3, 0x01, 0x16, 0x00, 0x48, 0xff, 0xa4, 0x01, 0x16, 0x00, 0x52, 0xff, 0xa4, 0x01, 0x16, 0x00, 0x58, 0xff, 0xa4, 0x01, 0x16, 0x00, 0x5c, 0xff, 0x90, 0x01, 0x16, 0x00, 0x6d, 0xff, 0x90, 0x01, 0x16, 0x00, 0x7d, 0xff, 0xdc, 0x01, 0x16, 0x00, 0x82, 0xff, 0xad, 0x01, 0x16, 0x00, 0x83, 0xff, 0xad, 0x01, 0x16, 0x00, 0x84, 0xff, 0xad, 0x01, 0x16, 0x00, 0x85, 0xff, 0xad, 0x01, 0x16, 0x00, 0x86, 0xff, 0xad, 0x01, 0x16, 0x00, 0x89, 0xff, 0x9a, 0x01, 0x16, 0x00, 0x9f, 0xff, 0x7d, 0x01, 0x16, 0x00, 0xa2, 0xff, 0xd3, 0x01, 0x16, 0x00, 0xa3, 0xff, 0xd3, 0x01, 0x16, 0x00, 0xa4, 0xff, 0xd3, 0x01, 0x16, 0x00, 0xa5, 0xff, 0xd3, 0x01, 0x16, 0x00, 0xa6, 0xff, 0xd3, 0x01, 0x16, 0x00, 0xa7, 0xff, 0xd3, 0x01, 0x16, 0x00, 0xaa, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xab, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xac, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xad, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xb4, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xb5, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xb6, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xb7, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xb8, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xbb, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xbc, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xbd, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xbe, 0xff, 0xa4, 0x01, 0x16, 0x00, 0xbf, 0xff, 0x90, 0x01, 0x16, 0x00, 0xc1, 0xff, 0x90, 0x01, 0x16, 0x00, 0xc8, 0xff, 0x9a, 0x01, 0x16, 0x00, 0xce, 0xff, 0x9a, 0x01, 0x16, 0x00, 0xdd, 0xff, 0xa4, 0x01, 0x16, 0x01, 0x26, 0xff, 0x6b, 0x01, 0x16, 0x01, 0x31, 0xff, 0xa4, 0x01, 0x16, 0x01, 0x3a, 0xff, 0x7d, 0x01, 0x16, 0x07, 0x51, 0xff, 0x6b, 0x01, 0x16, 0x07, 0x52, 0xff, 0x7d, 0x01, 0x16, 0x07, 0x53, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x10, 0xff, 0x7d, 0x01, 0x17, 0x00, 0x11, 0xff, 0x44, 0x01, 0x17, 0x00, 0x1d, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x46, 0xff, 0xd3, 0x01, 0x17, 0x00, 0x47, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x48, 0xff, 0xd3, 0x01, 0x17, 0x00, 0x4a, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x4b, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x50, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x51, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x52, 0xff, 0xd3, 0x01, 0x17, 0x00, 0x54, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x55, 0xff, 0xdc, 0x01, 0x17, 0x00, 0x5b, 0xff, 0xc9, 0x01, 0x17, 0x00, 0x6d, 0xff, 0xb7, 0x01, 0x17, 0x00, 0xa9, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xaa, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xab, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xac, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xad, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xb3, 0xff, 0xdc, 0x01, 0x17, 0x00, 0xb4, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xb5, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xb6, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xb7, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xb8, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xc9, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xcf, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xd1, 0x00, 0x48, 0x01, 0x17, 0x00, 0xdd, 0xff, 0xd3, 0x01, 0x17, 0x00, 0xe1, 0xff, 0xdc, 0x01, 0x17, 0x01, 0x0a, 0xff, 0xdc, 0x01, 0x17, 0x01, 0x17, 0xff, 0xdc, 0x01, 0x17, 0x01, 0x1b, 0xff, 0xdc, 0x01, 0x17, 0x07, 0x52, 0x00, 0x56, 0x01, 0x17, 0x07, 0x53, 0xfe, 0xc9, 0x01, 0x1a, 0x00, 0x10, 0xff, 0xad, 0x01, 0x1a, 0x00, 0x11, 0xff, 0xb7, 0x01, 0x1a, 0x00, 0x1d, 0xff, 0xc1, 0x01, 0x1a, 0x00, 0x24, 0xff, 0xad, 0x01, 0x1a, 0x00, 0x26, 0xff, 0x9a, 0x01, 0x1a, 0x00, 0x37, 0xff, 0x6b, 0x01, 0x1a, 0x00, 0x39, 0xff, 0x90, 0x01, 0x1a, 0x00, 0x3a, 0xff, 0xad, 0x01, 0x1a, 0x00, 0x3c, 0xff, 0x7d, 0x01, 0x1a, 0x00, 0x44, 0xff, 0xd3, 0x01, 0x1a, 0x00, 0x48, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0x52, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0x58, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0x5c, 0xff, 0x90, 0x01, 0x1a, 0x00, 0x6d, 0xff, 0x90, 0x01, 0x1a, 0x00, 0x7d, 0xff, 0xdc, 0x01, 0x1a, 0x00, 0x82, 0xff, 0xad, 0x01, 0x1a, 0x00, 0x83, 0xff, 0xad, 0x01, 0x1a, 0x00, 0x84, 0xff, 0xad, 0x01, 0x1a, 0x00, 0x85, 0xff, 0xad, 0x01, 0x1a, 0x00, 0x86, 0xff, 0xad, 0x01, 0x1a, 0x00, 0x89, 0xff, 0x9a, 0x01, 0x1a, 0x00, 0x9f, 0xff, 0x7d, 0x01, 0x1a, 0x00, 0xa2, 0xff, 0xd3, 0x01, 0x1a, 0x00, 0xa3, 0xff, 0xd3, 0x01, 0x1a, 0x00, 0xa4, 0xff, 0xd3, 0x01, 0x1a, 0x00, 0xa5, 0xff, 0xd3, 0x01, 0x1a, 0x00, 0xa6, 0xff, 0xd3, 0x01, 0x1a, 0x00, 0xa7, 0xff, 0xd3, 0x01, 0x1a, 0x00, 0xaa, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xab, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xac, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xad, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xb4, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xb5, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xb6, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xb7, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xb8, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xbb, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xbc, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xbd, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xbe, 0xff, 0xa4, 0x01, 0x1a, 0x00, 0xbf, 0xff, 0x90, 0x01, 0x1a, 0x00, 0xc1, 0xff, 0x90, 0x01, 0x1a, 0x00, 0xc8, 0xff, 0x9a, 0x01, 0x1a, 0x00, 0xce, 0xff, 0x9a, 0x01, 0x1a, 0x00, 0xdd, 0xff, 0xa4, 0x01, 0x1a, 0x01, 0x26, 0xff, 0x6b, 0x01, 0x1a, 0x01, 0x31, 0xff, 0xa4, 0x01, 0x1a, 0x01, 0x3a, 0xff, 0x7d, 0x01, 0x1a, 0x07, 0x51, 0xff, 0x6b, 0x01, 0x1a, 0x07, 0x52, 0xff, 0x7d, 0x01, 0x1a, 0x07, 0x53, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x10, 0xff, 0x7d, 0x01, 0x1b, 0x00, 0x11, 0xff, 0x44, 0x01, 0x1b, 0x00, 0x1d, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x46, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0x47, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x48, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0x4a, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x4b, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x50, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x51, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x52, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0x54, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x55, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0x5b, 0xff, 0xc9, 0x01, 0x1b, 0x00, 0x6d, 0xff, 0xb7, 0x01, 0x1b, 0x00, 0xa9, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xaa, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xab, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xac, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xad, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xb3, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0xb4, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xb5, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xb6, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xb7, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xb8, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xc9, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xcf, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xd1, 0xff, 0xdc, 0x01, 0x1b, 0x00, 0xdd, 0xff, 0xd3, 0x01, 0x1b, 0x00, 0xe1, 0xff, 0xdc, 0x01, 0x1b, 0x01, 0x0a, 0xff, 0xdc, 0x01, 0x1b, 0x01, 0x17, 0xff, 0xdc, 0x01, 0x1b, 0x01, 0x1b, 0xff, 0xdc, 0x01, 0x1b, 0x07, 0x52, 0x00, 0x56, 0x01, 0x1b, 0x07, 0x53, 0xfe, 0xc9, 0x01, 0x20, 0x00, 0x24, 0x00, 0x26, 0x01, 0x20, 0x00, 0x82, 0x00, 0x26, 0x01, 0x20, 0x00, 0x83, 0x00, 0x26, 0x01, 0x20, 0x00, 0x84, 0x00, 0x26, 0x01, 0x20, 0x00, 0x85, 0x00, 0x26, 0x01, 0x20, 0x00, 0x86, 0x00, 0x26, 0x01, 0x22, 0x00, 0x24, 0x00, 0x26, 0x01, 0x22, 0x00, 0x82, 0x00, 0x26, 0x01, 0x22, 0x00, 0x83, 0x00, 0x26, 0x01, 0x22, 0x00, 0x84, 0x00, 0x26, 0x01, 0x22, 0x00, 0x85, 0x00, 0x26, 0x01, 0x22, 0x00, 0x86, 0x00, 0x26, 0x01, 0x26, 0x00, 0x10, 0xff, 0x44, 0x01, 0x26, 0x00, 0x11, 0xff, 0x0d, 0x01, 0x26, 0x00, 0x1d, 0xff, 0x1f, 0x01, 0x26, 0x00, 0x24, 0xff, 0x61, 0x01, 0x26, 0x00, 0x26, 0xff, 0x88, 0x01, 0x26, 0x00, 0x37, 0xff, 0xdc, 0x01, 0x26, 0x00, 0x44, 0xfe, 0xad, 0x01, 0x26, 0x00, 0x46, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0x48, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0x4c, 0xff, 0xc1, 0x01, 0x26, 0x00, 0x52, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0x55, 0xfe, 0xd3, 0x01, 0x26, 0x00, 0x56, 0xfe, 0xad, 0x01, 0x26, 0x00, 0x58, 0xfe, 0xc9, 0x01, 0x26, 0x00, 0x5a, 0xfe, 0xad, 0x01, 0x26, 0x00, 0x5c, 0xfe, 0xc1, 0x01, 0x26, 0x00, 0x6d, 0xff, 0x44, 0x01, 0x26, 0x00, 0x7d, 0xff, 0x90, 0x01, 0x26, 0x00, 0x82, 0xff, 0x61, 0x01, 0x26, 0x00, 0x83, 0xff, 0x61, 0x01, 0x26, 0x00, 0x84, 0xff, 0x61, 0x01, 0x26, 0x00, 0x85, 0xff, 0x61, 0x01, 0x26, 0x00, 0x86, 0xff, 0x61, 0x01, 0x26, 0x00, 0x89, 0xff, 0x88, 0x01, 0x26, 0x00, 0xa2, 0xfe, 0xad, 0x01, 0x26, 0x00, 0xa3, 0xfe, 0xad, 0x01, 0x26, 0x00, 0xa4, 0xfe, 0xad, 0x01, 0x26, 0x00, 0xa5, 0xfe, 0xad, 0x01, 0x26, 0x00, 0xa6, 0xfe, 0xad, 0x01, 0x26, 0x00, 0xa7, 0xfe, 0xad, 0x01, 0x26, 0x00, 0xa9, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xaa, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xab, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xac, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xad, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xb4, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xb5, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xb6, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xb7, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xb8, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xbb, 0xfe, 0xc9, 0x01, 0x26, 0x00, 0xbc, 0xfe, 0xc9, 0x01, 0x26, 0x00, 0xbd, 0xfe, 0xc9, 0x01, 0x26, 0x00, 0xbe, 0xfe, 0xc9, 0x01, 0x26, 0x00, 0xbf, 0xfe, 0xc1, 0x01, 0x26, 0x00, 0xc1, 0xfe, 0xc1, 0x01, 0x26, 0x00, 0xc8, 0xff, 0x88, 0x01, 0x26, 0x00, 0xc9, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xce, 0xff, 0x88, 0x01, 0x26, 0x00, 0xcf, 0xfe, 0xa4, 0x01, 0x26, 0x00, 0xdd, 0xfe, 0xa4, 0x01, 0x26, 0x01, 0x17, 0xfe, 0xd3, 0x01, 0x26, 0x01, 0x1b, 0xfe, 0xd3, 0x01, 0x26, 0x01, 0x21, 0xfe, 0xad, 0x01, 0x26, 0x01, 0x23, 0xfe, 0xad, 0x01, 0x26, 0x01, 0x26, 0xff, 0xdc, 0x01, 0x26, 0x01, 0x31, 0xfe, 0xc9, 0x01, 0x26, 0x07, 0x52, 0xff, 0xd3, 0x01, 0x26, 0x07, 0x53, 0xfe, 0xf8, 0x01, 0x30, 0x00, 0x3d, 0xff, 0xdc, 0x01, 0x30, 0x01, 0x3f, 0xff, 0xdc, 0x01, 0x3a, 0x00, 0x10, 0xff, 0x0d, 0x01, 0x3a, 0x00, 0x11, 0xfe, 0x61, 0x01, 0x3a, 0x00, 0x1d, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0x24, 0xff, 0x61, 0x01, 0x3a, 0x00, 0x26, 0xff, 0x90, 0x01, 0x3a, 0x00, 0x32, 0xff, 0x90, 0x01, 0x3a, 0x00, 0x44, 0xfe, 0xe6, 0x01, 0x3a, 0x00, 0x48, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0x4c, 0xff, 0xb7, 0x01, 0x3a, 0x00, 0x52, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0x58, 0xff, 0x15, 0x01, 0x3a, 0x00, 0x6d, 0xff, 0x1f, 0x01, 0x3a, 0x00, 0x7d, 0xff, 0x6b, 0x01, 0x3a, 0x00, 0x82, 0xff, 0x61, 0x01, 0x3a, 0x00, 0x83, 0xff, 0x61, 0x01, 0x3a, 0x00, 0x84, 0xff, 0x61, 0x01, 0x3a, 0x00, 0x85, 0xff, 0x61, 0x01, 0x3a, 0x00, 0x86, 0xff, 0x61, 0x01, 0x3a, 0x00, 0x89, 0xff, 0x90, 0x01, 0x3a, 0x00, 0x94, 0xff, 0x90, 0x01, 0x3a, 0x00, 0x95, 0xff, 0x90, 0x01, 0x3a, 0x00, 0x96, 0xff, 0x90, 0x01, 0x3a, 0x00, 0x97, 0xff, 0x90, 0x01, 0x3a, 0x00, 0x98, 0xff, 0x90, 0x01, 0x3a, 0x00, 0xa2, 0xfe, 0xe6, 0x01, 0x3a, 0x00, 0xa3, 0xfe, 0xe6, 0x01, 0x3a, 0x00, 0xa4, 0xfe, 0xe6, 0x01, 0x3a, 0x00, 0xa5, 0xfe, 0xe6, 0x01, 0x3a, 0x00, 0xa6, 0xfe, 0xe6, 0x01, 0x3a, 0x00, 0xa7, 0xfe, 0xe6, 0x01, 0x3a, 0x00, 0xaa, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xab, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xac, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xad, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xb4, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xb5, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xb6, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xb7, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xb8, 0xfe, 0xf0, 0x01, 0x3a, 0x00, 0xbb, 0xff, 0x15, 0x01, 0x3a, 0x00, 0xbc, 0xff, 0x15, 0x01, 0x3a, 0x00, 0xbd, 0xff, 0x15, 0x01, 0x3a, 0x00, 0xbe, 0xff, 0x15, 0x01, 0x3a, 0x00, 0xc8, 0xff, 0x90, 0x01, 0x3a, 0x00, 0xce, 0xff, 0x90, 0x01, 0x3a, 0x00, 0xdd, 0xfe, 0xf0, 0x01, 0x3a, 0x01, 0x31, 0xff, 0x15, 0x01, 0x3a, 0x07, 0x51, 0xff, 0x90, 0x01, 0x3a, 0x07, 0x52, 0xff, 0xdc, 0x01, 0x3a, 0x07, 0x53, 0xfe, 0xf8, 0x01, 0x3f, 0x00, 0x10, 0xff, 0xdc, 0x01, 0x3f, 0x07, 0x51, 0xff, 0xdc, 0x01, 0x3f, 0x07, 0x52, 0xff, 0xdc, 0x01, 0x3f, 0x07, 0x53, 0xff, 0xdc, 0x07, 0x45, 0x00, 0x24, 0xff, 0xd3, 0x07, 0x45, 0x00, 0x25, 0xff, 0xb7, 0x07, 0x45, 0x00, 0x2a, 0x00, 0x4b, 0x07, 0x45, 0x00, 0x2d, 0x00, 0x72, 0x07, 0x45, 0x00, 0x32, 0x00, 0x39, 0x07, 0x45, 0x00, 0x34, 0x00, 0x4b, 0x07, 0x45, 0x00, 0x37, 0xff, 0x44, 0x07, 0x45, 0x00, 0x39, 0xff, 0x88, 0x07, 0x45, 0x00, 0x3a, 0xff, 0xad, 0x07, 0x45, 0x00, 0x3b, 0xff, 0x9a, 0x07, 0x45, 0x00, 0x3c, 0xff, 0x0d, 0x07, 0x45, 0x00, 0x52, 0x00, 0x26, 0x07, 0x45, 0x00, 0x59, 0xff, 0xc9, 0x07, 0x45, 0x00, 0x5c, 0xff, 0xdc, 0x07, 0x45, 0x00, 0x82, 0xff, 0xd3, 0x07, 0x45, 0x00, 0x83, 0xff, 0xd3, 0x07, 0x45, 0x00, 0x84, 0xff, 0xd3, 0x07, 0x45, 0x00, 0x85, 0xff, 0xd3, 0x07, 0x45, 0x00, 0x86, 0xff, 0xd3, 0x07, 0x45, 0x00, 0x94, 0x00, 0x39, 0x07, 0x45, 0x00, 0x95, 0x00, 0x39, 0x07, 0x45, 0x00, 0x96, 0x00, 0x39, 0x07, 0x45, 0x00, 0x97, 0x00, 0x39, 0x07, 0x45, 0x00, 0x98, 0x00, 0x39, 0x07, 0x45, 0x00, 0x9f, 0xff, 0x0d, 0x07, 0x45, 0x00, 0xb4, 0x00, 0x26, 0x07, 0x45, 0x00, 0xb5, 0x00, 0x26, 0x07, 0x45, 0x00, 0xb6, 0x00, 0x26, 0x07, 0x45, 0x00, 0xb7, 0x00, 0x26, 0x07, 0x45, 0x00, 0xb8, 0x00, 0x26, 0x07, 0x45, 0x00, 0xbf, 0xff, 0xdc, 0x07, 0x45, 0x00, 0xc1, 0xff, 0xdc, 0x07, 0x45, 0x00, 0xe0, 0x00, 0x4b, 0x07, 0x45, 0x01, 0x26, 0xff, 0x44, 0x07, 0x45, 0x01, 0x3a, 0xff, 0x0d, 0x07, 0x51, 0x00, 0x24, 0xfe, 0xf8, 0x07, 0x51, 0x00, 0x25, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x26, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x27, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x29, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x2a, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x2b, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x2d, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x2e, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x2f, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x32, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x33, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x34, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x35, 0xff, 0xc1, 0x07, 0x51, 0x00, 0x3b, 0xff, 0x88, 0x07, 0x51, 0x00, 0x3d, 0xff, 0xdc, 0x07, 0x51, 0x00, 0x49, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x51, 0xff, 0x90, 0x07, 0x51, 0x00, 0x52, 0xff, 0x6b, 0x07, 0x51, 0x00, 0x55, 0xff, 0x90, 0x07, 0x51, 0x00, 0x59, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x5a, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x5c, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x82, 0xfe, 0xf8, 0x07, 0x51, 0x00, 0x83, 0xfe, 0xf8, 0x07, 0x51, 0x00, 0x84, 0xfe, 0xf8, 0x07, 0x51, 0x00, 0x85, 0xfe, 0xf8, 0x07, 0x51, 0x00, 0x86, 0xfe, 0xf8, 0x07, 0x51, 0x00, 0x88, 0xfe, 0x7d, 0x07, 0x51, 0x00, 0x89, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x94, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x95, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x96, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x97, 0xff, 0xb7, 0x07, 0x51, 0x00, 0x98, 0xff, 0xb7, 0x07, 0x51, 0x00, 0xa0, 0xff, 0xc1, 0x07, 0x51, 0x00, 0xa1, 0xff, 0xc1, 0x07, 0x51, 0x00, 0xb2, 0xff, 0xb7, 0x07, 0x51, 0x00, 0xb3, 0xff, 0x90, 0x07, 0x51, 0x00, 0xb4, 0xff, 0x6b, 0x07, 0x51, 0x00, 0xb5, 0xff, 0x6b, 0x07, 0x51, 0x00, 0xb6, 0xff, 0x6b, 0x07, 0x51, 0x00, 0xb7, 0xff, 0x6b, 0x07, 0x51, 0x00, 0xb8, 0xff, 0x6b, 0x07, 0x51, 0x00, 0xbf, 0xff, 0xb7, 0x07, 0x51, 0x00, 0xc1, 0xff, 0xb7, 0x07, 0x51, 0x00, 0xc8, 0xff, 0xb7, 0x07, 0x51, 0x00, 0xce, 0xff, 0xb7, 0x07, 0x51, 0x00, 0xd0, 0xff, 0xc1, 0x07, 0x51, 0x00, 0xe0, 0xff, 0xb7, 0x07, 0x51, 0x00, 0xfb, 0xff, 0xc1, 0x07, 0x51, 0x00, 0xff, 0xff, 0xc1, 0x07, 0x51, 0x01, 0x0a, 0xff, 0x90, 0x07, 0x51, 0x01, 0x16, 0xff, 0xc1, 0x07, 0x51, 0x01, 0x17, 0xff, 0x90, 0x07, 0x51, 0x01, 0x1a, 0xff, 0xc1, 0x07, 0x51, 0x01, 0x1b, 0xff, 0x90, 0x07, 0x51, 0x01, 0x3f, 0xff, 0xdc, 0x07, 0x51, 0x0e, 0x78, 0xff, 0xc1, 0x07, 0x53, 0x00, 0x24, 0x00, 0x26, 0x07, 0x53, 0x00, 0x25, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x26, 0xff, 0x90, 0x07, 0x53, 0x00, 0x27, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x29, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x2a, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x2b, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x2d, 0x00, 0x2f, 0x07, 0x53, 0x00, 0x2e, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x2f, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x32, 0xff, 0x90, 0x07, 0x53, 0x00, 0x33, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x34, 0xff, 0x90, 0x07, 0x53, 0x00, 0x35, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x37, 0xfe, 0xe6, 0x07, 0x53, 0x00, 0x39, 0xfe, 0x88, 0x07, 0x53, 0x00, 0x3a, 0xff, 0x03, 0x07, 0x53, 0x00, 0x3b, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x3c, 0xfe, 0x88, 0x07, 0x53, 0x00, 0x49, 0xff, 0xdc, 0x07, 0x53, 0x00, 0x51, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x52, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x55, 0xff, 0xb7, 0x07, 0x53, 0x00, 0x59, 0xff, 0x15, 0x07, 0x53, 0x00, 0x5a, 0xff, 0x3c, 0x07, 0x53, 0x00, 0x5c, 0xff, 0x90, 0x07, 0x53, 0x00, 0x82, 0x00, 0x26, 0x07, 0x53, 0x00, 0x83, 0x00, 0x26, 0x07, 0x53, 0x00, 0x84, 0x00, 0x26, 0x07, 0x53, 0x00, 0x85, 0x00, 0x26, 0x07, 0x53, 0x00, 0x86, 0x00, 0x26, 0x07, 0x53, 0x00, 0x88, 0x00, 0x26, 0x07, 0x53, 0x00, 0x89, 0xff, 0x90, 0x07, 0x53, 0x00, 0x94, 0xff, 0x90, 0x07, 0x53, 0x00, 0x95, 0xff, 0x90, 0x07, 0x53, 0x00, 0x96, 0xff, 0x90, 0x07, 0x53, 0x00, 0x97, 0xff, 0x90, 0x07, 0x53, 0x00, 0x98, 0xff, 0x90, 0x07, 0x53, 0x00, 0x9f, 0xfe, 0x88, 0x07, 0x53, 0x00, 0xa0, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xa1, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xb2, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xb3, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xb4, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xb5, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xb6, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xb7, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xb8, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xbf, 0xff, 0x90, 0x07, 0x53, 0x00, 0xc1, 0xff, 0x90, 0x07, 0x53, 0x00, 0xc8, 0xff, 0x90, 0x07, 0x53, 0x00, 0xce, 0xff, 0x90, 0x07, 0x53, 0x00, 0xd0, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xe0, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xfb, 0xff, 0xb7, 0x07, 0x53, 0x00, 0xff, 0xff, 0xb7, 0x07, 0x53, 0x01, 0x0a, 0xff, 0xb7, 0x07, 0x53, 0x01, 0x16, 0xff, 0xb7, 0x07, 0x53, 0x01, 0x17, 0xff, 0xb7, 0x07, 0x53, 0x01, 0x1a, 0xff, 0xb7, 0x07, 0x53, 0x01, 0x1b, 0xff, 0xb7, 0x07, 0x53, 0x01, 0x26, 0xfe, 0xe6, 0x07, 0x53, 0x01, 0x3a, 0xfe, 0x88, 0x07, 0x53, 0x0e, 0x78, 0xff, 0xb7, 0x0e, 0x60, 0x00, 0x10, 0xff, 0x44, 0x0e, 0x60, 0x00, 0x11, 0xff, 0x0d, 0x0e, 0x60, 0x00, 0x1d, 0xff, 0x1f, 0x0e, 0x60, 0x00, 0x24, 0xff, 0x61, 0x0e, 0x60, 0x00, 0x26, 0xff, 0x88, 0x0e, 0x60, 0x00, 0x37, 0xff, 0xdc, 0x0e, 0x60, 0x00, 0x44, 0xfe, 0xad, 0x0e, 0x60, 0x00, 0x46, 0xfe, 0xa4, 0x0e, 0x60, 0x00, 0x48, 0xfe, 0xa4, 0x0e, 0x60, 0x00, 0x4c, 0xff, 0xc1, 0x0e, 0x60, 0x00, 0x52, 0xfe, 0xa4, 0x0e, 0x60, 0x00, 0x55, 0xfe, 0xd3, 0x0e, 0x60, 0x00, 0x56, 0xfe, 0xad, 0x0e, 0x60, 0x00, 0x58, 0xfe, 0xc9, 0x0e, 0x60, 0x00, 0x5a, 0xfe, 0xad, 0x0e, 0x60, 0x00, 0x5c, 0xfe, 0xc1, 0x0e, 0x60, 0x00, 0x6d, 0xff, 0x44, 0x0e, 0x60, 0x00, 0x7d, 0xff, 0x90, 0x0e, 0x60, 0x00, 0x82, 0xff, 0x61, 0x0e, 0x60, 0x00, 0x83, 0xff, 0x61, 0x0e, 0x60, 0x00, 0x84, 0xff, 0x61, 0x0e, 0x60, 0x00, 0x85, 0xff, 0x61, 0x0e, 0x60, 0x00, 0x86, 0xff, 0x61, 0x0e, 0x60, 0x00, 0x89, 0xff, 0x88, 0x0e, 0x60, 0x00, 0xa2, 0xff, 0x11, 0x0e, 0x60, 0x00, 0xa3, 0xfe, 0xad, 0x0e, 0x60, 0x00, 0xa4, 0xff, 0x11, 0x0e, 0x60, 0x00, 0xa5, 0xff, 0x11, 0x0e, 0x60, 0x00, 0xa6, 0xff, 0x11, 0x0e, 0x60, 0x00, 0xa7, 0xff, 0x11, 0x0e, 0x60, 0x00, 0xa9, 0xfe, 0xa4, 0x0e, 0x60, 0x00, 0xaa, 0xfe, 0xe0, 0x0e, 0x60, 0x00, 0xab, 0xfe, 0xa4, 0x0e, 0x60, 0x00, 0xac, 0xfe, 0xe0, 0x0e, 0x60, 0x00, 0xad, 0xfe, 0xe0, 0x0e, 0x60, 0x00, 0xb4, 0xfe, 0xf4, 0x0e, 0x60, 0x00, 0xb5, 0xfe, 0xa4, 0x0e, 0x60, 0x00, 0xb6, 0xfe, 0xf4, 0x0e, 0x60, 0x00, 0xb7, 0xfe, 0xf4, 0x0e, 0x60, 0x00, 0xb8, 0xfe, 0xf4, 0x0e, 0x60, 0x00, 0xbb, 0xfe, 0xe7, 0x0e, 0x60, 0x00, 0xbc, 0xfe, 0xc9, 0x0e, 0x60, 0x00, 0xbd, 0xfe, 0xe7, 0x0e, 0x60, 0x00, 0xbe, 0xfe, 0xe7, 0x0e, 0x60, 0x00, 0xbf, 0xfe, 0xc1, 0x0e, 0x60, 0x00, 0xc1, 0xfe, 0xc1, 0x0e, 0x60, 0x00, 0xc8, 0xff, 0x88, 0x0e, 0x60, 0x00, 0xc9, 0xfe, 0xa4, 0x0e, 0x60, 0x00, 0xce, 0xff, 0x88, 0x0e, 0x60, 0x00, 0xcf, 0xfe, 0xa4, 0x0e, 0x60, 0x00, 0xdd, 0xfe, 0xa4, 0x0e, 0x60, 0x01, 0x17, 0xfe, 0xd3, 0x0e, 0x60, 0x01, 0x1b, 0xfe, 0xd3, 0x0e, 0x60, 0x01, 0x21, 0xfe, 0xad, 0x0e, 0x60, 0x01, 0x23, 0xfe, 0xad, 0x0e, 0x60, 0x01, 0x26, 0xff, 0xdc, 0x0e, 0x60, 0x01, 0x31, 0xfe, 0xc9, 0x0e, 0x60, 0x07, 0x52, 0xff, 0xd3, 0x0e, 0x60, 0x07, 0x53, 0xfe, 0xf8, 0x0e, 0x78, 0x00, 0x10, 0xff, 0x29, 0x0e, 0x78, 0x00, 0x24, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0x26, 0xff, 0x90, 0x0e, 0x78, 0x00, 0x32, 0xff, 0x90, 0x0e, 0x78, 0x00, 0x37, 0xff, 0x61, 0x0e, 0x78, 0x00, 0x38, 0xff, 0xc9, 0x0e, 0x78, 0x00, 0x3a, 0xff, 0xb7, 0x0e, 0x78, 0x00, 0x3c, 0xff, 0xb7, 0x0e, 0x78, 0x00, 0x44, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0x48, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0x52, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0x58, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0x5c, 0xff, 0x6b, 0x0e, 0x78, 0x00, 0x6d, 0xff, 0x7d, 0x0e, 0x78, 0x00, 0x82, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0x83, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0x84, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0x85, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0x86, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0x89, 0xff, 0x90, 0x0e, 0x78, 0x00, 0x94, 0xff, 0x90, 0x0e, 0x78, 0x00, 0x95, 0xff, 0x90, 0x0e, 0x78, 0x00, 0x96, 0xff, 0x90, 0x0e, 0x78, 0x00, 0x97, 0xff, 0x90, 0x0e, 0x78, 0x00, 0x98, 0xff, 0x90, 0x0e, 0x78, 0x00, 0x9b, 0xff, 0xc9, 0x0e, 0x78, 0x00, 0x9c, 0xff, 0xc9, 0x0e, 0x78, 0x00, 0x9d, 0xff, 0xc9, 0x0e, 0x78, 0x00, 0x9e, 0xff, 0xc9, 0x0e, 0x78, 0x00, 0x9f, 0xff, 0xb7, 0x0e, 0x78, 0x00, 0xa2, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0xa3, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0xa4, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0xa5, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0xa6, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0xa7, 0xff, 0xdc, 0x0e, 0x78, 0x00, 0xaa, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xab, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xac, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xad, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xb4, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xb5, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xb6, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xb7, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xb8, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xbb, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xbc, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xbd, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xbe, 0xff, 0x9a, 0x0e, 0x78, 0x00, 0xbf, 0xff, 0x6b, 0x0e, 0x78, 0x00, 0xc1, 0xff, 0x6b, 0x0e, 0x78, 0x00, 0xc8, 0xff, 0x90, 0x0e, 0x78, 0x00, 0xce, 0xff, 0x90, 0x0e, 0x78, 0x00, 0xdd, 0xff, 0x9a, 0x0e, 0x78, 0x01, 0x26, 0xff, 0x61, 0x0e, 0x78, 0x01, 0x30, 0xff, 0xc9, 0x0e, 0x78, 0x01, 0x31, 0xff, 0x9a, 0x0e, 0x78, 0x01, 0x3a, 0xff, 0xb7, 0x0e, 0x78, 0x07, 0x51, 0xff, 0xc1, 0x0e, 0x78, 0x07, 0x52, 0xff, 0xc1, 0x0e, 0x79, 0x00, 0x44, 0xff, 0xdc, 0x0e, 0x79, 0x00, 0x48, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0x52, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0x58, 0xff, 0xc1, 0x0e, 0x79, 0x00, 0x5c, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xa2, 0xff, 0xdc, 0x0e, 0x79, 0x00, 0xa3, 0xff, 0xdc, 0x0e, 0x79, 0x00, 0xa4, 0xff, 0xdc, 0x0e, 0x79, 0x00, 0xa5, 0xff, 0xdc, 0x0e, 0x79, 0x00, 0xa6, 0xff, 0xdc, 0x0e, 0x79, 0x00, 0xa7, 0xff, 0xdc, 0x0e, 0x79, 0x00, 0xaa, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xab, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xac, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xad, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xb4, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xb5, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xb6, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xb7, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xb8, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xbb, 0xff, 0xc1, 0x0e, 0x79, 0x00, 0xbc, 0xff, 0xc1, 0x0e, 0x79, 0x00, 0xbd, 0xff, 0xc1, 0x0e, 0x79, 0x00, 0xbe, 0xff, 0xc1, 0x0e, 0x79, 0x00, 0xbf, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xc1, 0xff, 0xb7, 0x0e, 0x79, 0x00, 0xdd, 0xff, 0xb7, 0x0e, 0x79, 0x01, 0x31, 0xff, 0xc1, 0x0e, 0xaa, 0x0e, 0xc2, 0xff, 0xd8, 0x0e, 0xab, 0x0e, 0xc2, 0xff, 0xb1, 0x0e, 0xac, 0x0e, 0xc2, 0xff, 0xa3, 0x0e, 0xad, 0x0e, 0xc2, 0xff, 0x9c, 0x0e, 0xae, 0x0e, 0xc2, 0xff, 0xd8, 0x0e, 0xb0, 0x0e, 0xc2, 0xff, 0xd8, 0x0e, 0xb1, 0x0e, 0xc2, 0xff, 0xb1, 0x0e, 0xb2, 0x0e, 0xc2, 0xff, 0xa3, 0x0e, 0xb3, 0x0e, 0xc2, 0xff, 0xb1, 0x0e, 0xb4, 0x0e, 0xc2, 0xff, 0xd8, 0x0e, 0xb6, 0x0e, 0xc2, 0xff, 0xd8, 0x0e, 0xb7, 0x0e, 0xc2, 0xff, 0xb1, 0x0e, 0xb8, 0x0e, 0xc2, 0xff, 0xa3, 0x0e, 0xb9, 0x0e, 0xc2, 0xff, 0xb1, 0x0e, 0xba, 0x0e, 0xc2, 0xff, 0xd8, 0x0e, 0xbc, 0x0e, 0xc2, 0xff, 0xd8, 0x0e, 0xbd, 0x0e, 0xc2, 0xff, 0x9c, 0x0e, 0xbe, 0x0e, 0xc2, 0xff, 0xa3, 0x0e, 0xbf, 0x0e, 0xc2, 0xff, 0xb1, 0x0e, 0xc0, 0x0e, 0xc2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x02, 0xc8, 0x00, 0x00, 0x02, 0xe4, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x03, 0x58, 0x00, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x04, 0x2c, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x04, 0xa4, 0x00, 0x00, 0x04, 0xd4, 0x00, 0x00, 0x05, 0x34, 0x00, 0x00, 0x05, 0xac, 0x00, 0x00, 0x05, 0xe8, 0x00, 0x00, 0x06, 0x48, 0x00, 0x00, 0x06, 0xc0, 0x00, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x07, 0x74, 0x00, 0x00, 0x07, 0xec, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x68, 0x00, 0x00, 0x08, 0x90, 0x00, 0x00, 0x08, 0xb8, 0x00, 0x00, 0x09, 0x2c, 0x00, 0x00, 0x0a, 0x14, 0x00, 0x00, 0x0a, 0x4c, 0x00, 0x00, 0x0a, 0xb8, 0x00, 0x00, 0x0b, 0x14, 0x00, 0x00, 0x0b, 0x64, 0x00, 0x00, 0x0b, 0x94, 0x00, 0x00, 0x0b, 0xc0, 0x00, 0x00, 0x0c, 0x28, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x0c, 0x74, 0x00, 0x00, 0x0c, 0xa0, 0x00, 0x00, 0x0c, 0xd4, 0x00, 0x00, 0x0c, 0xf4, 0x00, 0x00, 0x0d, 0x30, 0x00, 0x00, 0x0d, 0x60, 0x00, 0x00, 0x0d, 0xc4, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0e, 0x7c, 0x00, 0x00, 0x0e, 0xe0, 0x00, 0x00, 0x0f, 0x58, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x0f, 0xc4, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x10, 0x30, 0x00, 0x00, 0x10, 0x70, 0x00, 0x00, 0x10, 0xa0, 0x00, 0x00, 0x10, 0xd0, 0x00, 0x00, 0x10, 0xf4, 0x00, 0x00, 0x11, 0x14, 0x00, 0x00, 0x11, 0x38, 0x00, 0x00, 0x11, 0x64, 0x00, 0x00, 0x11, 0x80, 0x00, 0x00, 0x11, 0xa0, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00, 0x12, 0x70, 0x00, 0x00, 0x12, 0xc8, 0x00, 0x00, 0x13, 0x28, 0x00, 0x00, 0x13, 0x8c, 0x00, 0x00, 0x13, 0xcc, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x14, 0x8c, 0x00, 0x00, 0x14, 0xb0, 0x00, 0x00, 0x14, 0xe8, 0x00, 0x00, 0x15, 0x1c, 0x00, 0x00, 0x15, 0x38, 0x00, 0x00, 0x15, 0xa0, 0x00, 0x00, 0x15, 0xe4, 0x00, 0x00, 0x16, 0x38, 0x00, 0x00, 0x16, 0x98, 0x00, 0x00, 0x16, 0xf8, 0x00, 0x00, 0x17, 0x38, 0x00, 0x00, 0x17, 0xb0, 0x00, 0x00, 0x17, 0xf4, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x00, 0x18, 0x64, 0x00, 0x00, 0x18, 0xa0, 0x00, 0x00, 0x18, 0xe0, 0x00, 0x00, 0x19, 0x20, 0x00, 0x00, 0x19, 0x50, 0x00, 0x00, 0x19, 0xb4, 0x00, 0x00, 0x19, 0xd0, 0x00, 0x00, 0x1a, 0x34, 0x00, 0x00, 0x1a, 0x94, 0x00, 0x00, 0x1a, 0x94, 0x00, 0x00, 0x1a, 0xc4, 0x00, 0x00, 0x1b, 0x3c, 0x00, 0x00, 0x1b, 0x94, 0x00, 0x00, 0x1c, 0x28, 0x00, 0x00, 0x1c, 0x84, 0x00, 0x00, 0x1c, 0xb0, 0x00, 0x00, 0x1d, 0x68, 0x00, 0x00, 0x1d, 0x90, 0x00, 0x00, 0x1e, 0x6c, 0x00, 0x00, 0x1e, 0xe8, 0x00, 0x00, 0x1f, 0x2c, 0x00, 0x00, 0x1f, 0x4c, 0x00, 0x00, 0x1f, 0x68, 0x00, 0x00, 0x20, 0x50, 0x00, 0x00, 0x20, 0x6c, 0x00, 0x00, 0x20, 0xc4, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x21, 0x58, 0x00, 0x00, 0x21, 0xcc, 0x00, 0x00, 0x21, 0xe8, 0x00, 0x00, 0x22, 0x4c, 0x00, 0x00, 0x22, 0x84, 0x00, 0x00, 0x22, 0x9c, 0x00, 0x00, 0x22, 0xe0, 0x00, 0x00, 0x23, 0x0c, 0x00, 0x00, 0x23, 0x68, 0x00, 0x00, 0x23, 0xb0, 0x00, 0x00, 0x23, 0xd0, 0x00, 0x00, 0x23, 0xf0, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x24, 0x84, 0x00, 0x00, 0x24, 0x9c, 0x00, 0x00, 0x24, 0xb4, 0x00, 0x00, 0x24, 0xd0, 0x00, 0x00, 0x24, 0xec, 0x00, 0x00, 0x25, 0x08, 0x00, 0x00, 0x25, 0x7c, 0x00, 0x00, 0x25, 0xcc, 0x00, 0x00, 0x25, 0xe4, 0x00, 0x00, 0x25, 0xfc, 0x00, 0x00, 0x26, 0x14, 0x00, 0x00, 0x26, 0x30, 0x00, 0x00, 0x26, 0x4c, 0x00, 0x00, 0x26, 0x64, 0x00, 0x00, 0x26, 0x7c, 0x00, 0x00, 0x26, 0x98, 0x00, 0x00, 0x26, 0xb4, 0x00, 0x00, 0x27, 0x18, 0x00, 0x00, 0x27, 0x34, 0x00, 0x00, 0x27, 0x4c, 0x00, 0x00, 0x27, 0x64, 0x00, 0x00, 0x27, 0x80, 0x00, 0x00, 0x27, 0x9c, 0x00, 0x00, 0x27, 0xb8, 0x00, 0x00, 0x27, 0xfc, 0x00, 0x00, 0x28, 0x94, 0x00, 0x00, 0x28, 0xac, 0x00, 0x00, 0x28, 0xc4, 0x00, 0x00, 0x28, 0xe0, 0x00, 0x00, 0x28, 0xfc, 0x00, 0x00, 0x29, 0x14, 0x00, 0x00, 0x29, 0x5c, 0x00, 0x00, 0x29, 0xe8, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2a, 0x18, 0x00, 0x00, 0x2a, 0x30, 0x00, 0x00, 0x2a, 0x48, 0x00, 0x00, 0x2a, 0x60, 0x00, 0x00, 0x2a, 0x78, 0x00, 0x00, 0x2b, 0x30, 0x00, 0x00, 0x2b, 0x48, 0x00, 0x00, 0x2b, 0x60, 0x00, 0x00, 0x2b, 0x78, 0x00, 0x00, 0x2b, 0x90, 0x00, 0x00, 0x2b, 0xa8, 0x00, 0x00, 0x2b, 0xc0, 0x00, 0x00, 0x2b, 0xd8, 0x00, 0x00, 0x2b, 0xf4, 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x2c, 0x98, 0x00, 0x00, 0x2c, 0xb0, 0x00, 0x00, 0x2c, 0xc8, 0x00, 0x00, 0x2c, 0xe0, 0x00, 0x00, 0x2c, 0xf8, 0x00, 0x00, 0x2d, 0x10, 0x00, 0x00, 0x2d, 0x28, 0x00, 0x00, 0x2d, 0x5c, 0x00, 0x00, 0x2d, 0xec, 0x00, 0x00, 0x2e, 0x04, 0x00, 0x00, 0x2e, 0x1c, 0x00, 0x00, 0x2e, 0x34, 0x00, 0x00, 0x2e, 0x4c, 0x00, 0x00, 0x2e, 0x64, 0x00, 0x00, 0x2e, 0xc4, 0x00, 0x00, 0x2e, 0xdc, 0x00, 0x00, 0x2e, 0xf8, 0x00, 0x00, 0x2f, 0x10, 0x00, 0x00, 0x2f, 0x2c, 0x00, 0x00, 0x2f, 0x44, 0x00, 0x00, 0x2f, 0x5c, 0x00, 0x00, 0x2f, 0x74, 0x00, 0x00, 0x2f, 0x8c, 0x00, 0x00, 0x2f, 0xa4, 0x00, 0x00, 0x2f, 0xc0, 0x00, 0x00, 0x2f, 0xd8, 0x00, 0x00, 0x2f, 0xf0, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x30, 0x24, 0x00, 0x00, 0x30, 0x3c, 0x00, 0x00, 0x30, 0x54, 0x00, 0x00, 0x30, 0x70, 0x00, 0x00, 0x30, 0x80, 0x00, 0x00, 0x30, 0xf4, 0x00, 0x00, 0x31, 0x0c, 0x00, 0x00, 0x31, 0x28, 0x00, 0x00, 0x31, 0x44, 0x00, 0x00, 0x31, 0x60, 0x00, 0x00, 0x31, 0x78, 0x00, 0x00, 0x31, 0x90, 0x00, 0x00, 0x31, 0xa8, 0x00, 0x00, 0x31, 0xc0, 0x00, 0x00, 0x31, 0xdc, 0x00, 0x00, 0x31, 0xf8, 0x00, 0x00, 0x32, 0x14, 0x00, 0x00, 0x32, 0x2c, 0x00, 0x00, 0x32, 0x44, 0x00, 0x00, 0x32, 0x5c, 0x00, 0x00, 0x32, 0x78, 0x00, 0x00, 0x32, 0x90, 0x00, 0x00, 0x32, 0xa8, 0x00, 0x00, 0x32, 0xc0, 0x00, 0x00, 0x32, 0xdc, 0x00, 0x00, 0x32, 0xf8, 0x00, 0x00, 0x33, 0x44, 0x00, 0x00, 0x33, 0x9c, 0x00, 0x00, 0x33, 0xb8, 0x00, 0x00, 0x33, 0xd4, 0x00, 0x00, 0x33, 0xf0, 0x00, 0x00, 0x34, 0x0c, 0x00, 0x00, 0x34, 0x28, 0x00, 0x00, 0x34, 0x44, 0x00, 0x00, 0x34, 0x5c, 0x00, 0x00, 0x34, 0x74, 0x00, 0x00, 0x34, 0x90, 0x00, 0x00, 0x34, 0xb0, 0x00, 0x00, 0x34, 0xcc, 0x00, 0x00, 0x34, 0xe8, 0x00, 0x00, 0x35, 0x04, 0x00, 0x00, 0x35, 0x20, 0x00, 0x00, 0x35, 0x38, 0x00, 0x00, 0x35, 0x50, 0x00, 0x00, 0x35, 0x84, 0x00, 0x00, 0x35, 0x9c, 0x00, 0x00, 0x35, 0xb8, 0x00, 0x00, 0x35, 0xd0, 0x00, 0x00, 0x35, 0xec, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x36, 0x20, 0x00, 0x00, 0x36, 0x38, 0x00, 0x00, 0x36, 0x54, 0x00, 0x00, 0x36, 0x90, 0x00, 0x00, 0x36, 0xc4, 0x00, 0x00, 0x36, 0xe0, 0x00, 0x00, 0x36, 0xf8, 0x00, 0x00, 0x37, 0x10, 0x00, 0x00, 0x37, 0x28, 0x00, 0x00, 0x37, 0x44, 0x00, 0x00, 0x37, 0x5c, 0x00, 0x00, 0x37, 0x74, 0x00, 0x00, 0x37, 0xd0, 0x00, 0x00, 0x38, 0x30, 0x00, 0x00, 0x38, 0x4c, 0x00, 0x00, 0x38, 0x64, 0x00, 0x00, 0x38, 0x80, 0x00, 0x00, 0x38, 0x98, 0x00, 0x00, 0x38, 0xb0, 0x00, 0x00, 0x38, 0xc8, 0x00, 0x00, 0x39, 0x2c, 0x00, 0x00, 0x39, 0xcc, 0x00, 0x00, 0x39, 0xe4, 0x00, 0x00, 0x39, 0xfc, 0x00, 0x00, 0x3a, 0x14, 0x00, 0x00, 0x3a, 0x2c, 0x00, 0x00, 0x3a, 0x48, 0x00, 0x00, 0x3a, 0x60, 0x00, 0x00, 0x3a, 0x78, 0x00, 0x00, 0x3a, 0x90, 0x00, 0x00, 0x3a, 0xac, 0x00, 0x00, 0x3a, 0xc4, 0x00, 0x00, 0x3a, 0xdc, 0x00, 0x00, 0x3a, 0xf4, 0x00, 0x00, 0x3b, 0x10, 0x00, 0x00, 0x3b, 0x2c, 0x00, 0x00, 0x3b, 0x44, 0x00, 0x00, 0x3b, 0x5c, 0x00, 0x00, 0x3b, 0x78, 0x00, 0x00, 0x3b, 0x94, 0x00, 0x00, 0x3b, 0xcc, 0x00, 0x00, 0x3c, 0x24, 0x00, 0x00, 0x3c, 0x40, 0x00, 0x00, 0x3c, 0x58, 0x00, 0x00, 0x3c, 0x74, 0x00, 0x00, 0x3c, 0x8c, 0x00, 0x00, 0x3c, 0xa8, 0x00, 0x00, 0x3c, 0xc0, 0x00, 0x00, 0x3c, 0xd8, 0x00, 0x00, 0x3c, 0xf0, 0x00, 0x00, 0x3d, 0x08, 0x00, 0x00, 0x3d, 0x20, 0x00, 0x00, 0x3d, 0x38, 0x00, 0x00, 0x3d, 0x50, 0x00, 0x00, 0x3d, 0x6c, 0x00, 0x00, 0x3d, 0x88, 0x00, 0x00, 0x3d, 0xa4, 0x00, 0x00, 0x3d, 0xbc, 0x00, 0x00, 0x3d, 0xd8, 0x00, 0x00, 0x3d, 0xf0, 0x00, 0x00, 0x3e, 0x08, 0x00, 0x00, 0x3e, 0x20, 0x00, 0x00, 0x3e, 0x3c, 0x00, 0x00, 0x3e, 0x54, 0x00, 0x00, 0x3e, 0x6c, 0x00, 0x00, 0x3e, 0xa4, 0x00, 0x00, 0x3f, 0x2c, 0x00, 0x00, 0x3f, 0xb0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x40, 0x3c, 0x00, 0x00, 0x40, 0x94, 0x00, 0x00, 0x40, 0xfc, 0x00, 0x00, 0x41, 0x58, 0x00, 0x00, 0x41, 0xd0, 0x00, 0x00, 0x42, 0x3c, 0x00, 0x00, 0x42, 0x4c, 0x00, 0x00, 0x42, 0xb4, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x43, 0x64, 0x00, 0x00, 0x43, 0xe4, 0x00, 0x00, 0x44, 0x18, 0x00, 0x00, 0x44, 0x80, 0x00, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x45, 0x38, 0x00, 0x00, 0x45, 0x8c, 0x00, 0x00, 0x46, 0x08, 0x00, 0x00, 0x46, 0x88, 0x00, 0x00, 0x47, 0x08, 0x00, 0x00, 0x47, 0x34, 0x00, 0x00, 0x47, 0x60, 0x00, 0x00, 0x47, 0xb8, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x2c, 0x00, 0x00, 0x48, 0x74, 0x00, 0x00, 0x48, 0xec, 0x00, 0x00, 0x49, 0x2c, 0x00, 0x00, 0x49, 0x3c, 0x00, 0x00, 0x49, 0xac, 0x00, 0x00, 0x49, 0xc4, 0x00, 0x00, 0x49, 0xdc, 0x00, 0x00, 0x4a, 0x50, 0x00, 0x00, 0x4a, 0xc0, 0x00, 0x00, 0x4b, 0x1c, 0x00, 0x00, 0x4b, 0x8c, 0x00, 0x00, 0x4b, 0xf0, 0x00, 0x00, 0x4c, 0x5c, 0x00, 0x00, 0x4c, 0xd4, 0x00, 0x00, 0x4c, 0xe4, 0x00, 0x00, 0x4d, 0x48, 0x00, 0x00, 0x4d, 0xa0, 0x00, 0x00, 0x4d, 0xd8, 0x00, 0x00, 0x4e, 0x2c, 0x00, 0x00, 0x4e, 0x64, 0x00, 0x00, 0x4e, 0x7c, 0x00, 0x00, 0x4e, 0x94, 0x00, 0x00, 0x4f, 0x04, 0x00, 0x00, 0x4f, 0x64, 0x00, 0x00, 0x4f, 0xbc, 0x00, 0x00, 0x50, 0x24, 0x00, 0x00, 0x50, 0x6c, 0x00, 0x00, 0x50, 0xb0, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x51, 0x90, 0x00, 0x00, 0x51, 0xfc, 0x00, 0x00, 0x52, 0x68, 0x00, 0x00, 0x52, 0xdc, 0x00, 0x00, 0x53, 0x38, 0x00, 0x00, 0x53, 0x90, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x54, 0x54, 0x00, 0x00, 0x54, 0x70, 0x00, 0x00, 0x54, 0x88, 0x00, 0x00, 0x54, 0xcc, 0x00, 0x00, 0x54, 0xdc, 0x00, 0x00, 0x54, 0xf4, 0x00, 0x00, 0x55, 0x0c, 0x00, 0x00, 0x55, 0x24, 0x00, 0x00, 0x55, 0x3c, 0x00, 0x00, 0x55, 0x54, 0x00, 0x00, 0x55, 0x6c, 0x00, 0x00, 0x55, 0x84, 0x00, 0x00, 0x55, 0x9c, 0x00, 0x00, 0x55, 0xb4, 0x00, 0x00, 0x55, 0xd0, 0x00, 0x00, 0x55, 0xe8, 0x00, 0x00, 0x56, 0x04, 0x00, 0x00, 0x56, 0x20, 0x00, 0x00, 0x56, 0x38, 0x00, 0x00, 0x56, 0x50, 0x00, 0x00, 0x56, 0x6c, 0x00, 0x00, 0x56, 0x84, 0x00, 0x00, 0x56, 0x9c, 0x00, 0x00, 0x56, 0xb4, 0x00, 0x00, 0x56, 0xcc, 0x00, 0x00, 0x56, 0xe4, 0x00, 0x00, 0x56, 0xfc, 0x00, 0x00, 0x57, 0x14, 0x00, 0x00, 0x57, 0x2c, 0x00, 0x00, 0x57, 0x44, 0x00, 0x00, 0x57, 0x54, 0x00, 0x00, 0x57, 0x6c, 0x00, 0x00, 0x57, 0x84, 0x00, 0x00, 0x57, 0x9c, 0x00, 0x00, 0x57, 0xb4, 0x00, 0x00, 0x57, 0xcc, 0x00, 0x00, 0x57, 0xe4, 0x00, 0x00, 0x58, 0x5c, 0x00, 0x00, 0x58, 0xf8, 0x00, 0x00, 0x59, 0x14, 0x00, 0x00, 0x59, 0x2c, 0x00, 0x00, 0x59, 0x44, 0x00, 0x00, 0x59, 0x60, 0x00, 0x00, 0x59, 0x78, 0x00, 0x00, 0x59, 0x90, 0x00, 0x00, 0x59, 0xa8, 0x00, 0x00, 0x59, 0xc0, 0x00, 0x00, 0x59, 0xd8, 0x00, 0x00, 0x59, 0xf0, 0x00, 0x00, 0x5a, 0x0c, 0x00, 0x00, 0x5a, 0x24, 0x00, 0x00, 0x5a, 0x3c, 0x00, 0x00, 0x5a, 0x54, 0x00, 0x00, 0x5a, 0x6c, 0x00, 0x00, 0x5a, 0x84, 0x00, 0x00, 0x5a, 0xe4, 0x00, 0x00, 0x5b, 0x3c, 0x00, 0x00, 0x5b, 0x54, 0x00, 0x00, 0x5b, 0x6c, 0x00, 0x00, 0x5b, 0x84, 0x00, 0x00, 0x5b, 0x9c, 0x00, 0x00, 0x5b, 0xb4, 0x00, 0x00, 0x5b, 0xcc, 0x00, 0x00, 0x5b, 0xe4, 0x00, 0x00, 0x5b, 0xfc, 0x00, 0x00, 0x5c, 0x14, 0x00, 0x00, 0x5c, 0x2c, 0x00, 0x00, 0x5c, 0x44, 0x00, 0x00, 0x5c, 0x5c, 0x00, 0x00, 0x5c, 0x74, 0x00, 0x00, 0x5c, 0x8c, 0x00, 0x00, 0x5c, 0xa4, 0x00, 0x00, 0x5c, 0xbc, 0x00, 0x00, 0x5c, 0xd4, 0x00, 0x00, 0x5c, 0xec, 0x00, 0x00, 0x5d, 0x04, 0x00, 0x00, 0x5d, 0x1c, 0x00, 0x00, 0x5d, 0x34, 0x00, 0x00, 0x5d, 0x4c, 0x00, 0x00, 0x5d, 0x64, 0x00, 0x00, 0x5d, 0x7c, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x00, 0x5d, 0xac, 0x00, 0x00, 0x5d, 0xc4, 0x00, 0x00, 0x5d, 0xdc, 0x00, 0x00, 0x5d, 0xf4, 0x00, 0x00, 0x5e, 0x0c, 0x00, 0x00, 0x5e, 0x24, 0x00, 0x00, 0x5e, 0x3c, 0x00, 0x00, 0x5e, 0x54, 0x00, 0x00, 0x5e, 0x6c, 0x00, 0x00, 0x5e, 0x84, 0x00, 0x00, 0x5e, 0x9c, 0x00, 0x00, 0x5f, 0x24, 0x00, 0x00, 0x5f, 0xb4, 0x00, 0x00, 0x5f, 0xcc, 0x00, 0x00, 0x5f, 0xe8, 0x00, 0x00, 0x60, 0x2c, 0x00, 0x00, 0x60, 0xd0, 0x00, 0x00, 0x61, 0x84, 0x00, 0x00, 0x62, 0x28, 0x00, 0x00, 0x62, 0x74, 0x00, 0x00, 0x62, 0xc0, 0x00, 0x00, 0x62, 0xd8, 0x00, 0x00, 0x62, 0xf0, 0x00, 0x00, 0x63, 0x08, 0x00, 0x00, 0x63, 0x20, 0x00, 0x00, 0x63, 0x38, 0x00, 0x00, 0x63, 0x50, 0x00, 0x00, 0x63, 0x68, 0x00, 0x00, 0x63, 0x80, 0x00, 0x00, 0x63, 0x98, 0x00, 0x00, 0x63, 0xb0, 0x00, 0x00, 0x63, 0xc8, 0x00, 0x00, 0x63, 0xe0, 0x00, 0x00, 0x63, 0xf8, 0x00, 0x00, 0x64, 0x10, 0x00, 0x00, 0x64, 0x64, 0x00, 0x00, 0x64, 0xe8, 0x00, 0x00, 0x65, 0x50, 0x00, 0x00, 0x65, 0x7c, 0x00, 0x00, 0x66, 0x1c, 0x00, 0x00, 0x66, 0xbc, 0x00, 0x00, 0x67, 0x28, 0x00, 0x00, 0x67, 0xbc, 0x00, 0x00, 0x68, 0x48, 0x00, 0x00, 0x68, 0x7c, 0x00, 0x00, 0x68, 0xd0, 0x00, 0x00, 0x69, 0x88, 0x00, 0x00, 0x69, 0xe0, 0x00, 0x00, 0x6a, 0x2c, 0x00, 0x00, 0x6a, 0x7c, 0x00, 0x00, 0x6a, 0xfc, 0x00, 0x00, 0x6b, 0x5c, 0x00, 0x00, 0x6b, 0x6c, 0x00, 0x00, 0x6b, 0xd4, 0x00, 0x00, 0x6c, 0x80, 0x00, 0x00, 0x6c, 0xc0, 0x00, 0x00, 0x6d, 0x08, 0x00, 0x00, 0x6d, 0x84, 0x00, 0x00, 0x6d, 0xf8, 0x00, 0x00, 0x6e, 0x64, 0x00, 0x00, 0x6e, 0xb4, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x6f, 0x60, 0x00, 0x00, 0x6f, 0xd0, 0x00, 0x00, 0x70, 0x30, 0x00, 0x00, 0x70, 0x90, 0x00, 0x00, 0x71, 0x04, 0x00, 0x00, 0x71, 0x5c, 0x00, 0x00, 0x71, 0xec, 0x00, 0x00, 0x72, 0x60, 0x00, 0x00, 0x72, 0xd0, 0x00, 0x00, 0x73, 0x44, 0x00, 0x00, 0x73, 0xa4, 0x00, 0x00, 0x74, 0x4c, 0x00, 0x00, 0x74, 0x5c, 0x00, 0x00, 0x74, 0x6c, 0x00, 0x00, 0x75, 0x1c, 0x00, 0x00, 0x75, 0xac, 0x00, 0x00, 0x75, 0xec, 0x00, 0x00, 0x76, 0x7c, 0x00, 0x00, 0x76, 0xf0, 0x00, 0x00, 0x77, 0x50, 0x00, 0x00, 0x77, 0xcc, 0x00, 0x00, 0x78, 0x48, 0x00, 0x00, 0x78, 0x8c, 0x00, 0x00, 0x78, 0xe0, 0x00, 0x00, 0x79, 0x44, 0x00, 0x00, 0x79, 0x7c, 0x00, 0x00, 0x79, 0x8c, 0x00, 0x00, 0x79, 0xb8, 0x00, 0x00, 0x7a, 0x28, 0x00, 0x00, 0x7a, 0x78, 0x00, 0x00, 0x7a, 0xa8, 0x00, 0x00, 0x7b, 0x1c, 0x00, 0x00, 0x7b, 0x90, 0x00, 0x00, 0x7c, 0x04, 0x00, 0x00, 0x7c, 0x90, 0x00, 0x00, 0x7c, 0xe4, 0x00, 0x00, 0x7d, 0x40, 0x00, 0x00, 0x7d, 0x70, 0x00, 0x00, 0x7d, 0xd4, 0x00, 0x00, 0x7e, 0x38, 0x00, 0x00, 0x7e, 0xb8, 0x00, 0x00, 0x7e, 0xc8, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7f, 0x38, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x80, 0x48, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xe4, 0x00, 0x00, 0x81, 0x44, 0x00, 0x00, 0x81, 0xd0, 0x00, 0x00, 0x82, 0x10, 0x00, 0x00, 0x82, 0x6c, 0x00, 0x00, 0x82, 0xac, 0x00, 0x00, 0x83, 0x0c, 0x00, 0x00, 0x83, 0x50, 0x00, 0x00, 0x83, 0x94, 0x00, 0x00, 0x83, 0xf4, 0x00, 0x00, 0x84, 0x58, 0x00, 0x00, 0x84, 0xbc, 0x00, 0x00, 0x84, 0xe4, 0x00, 0x00, 0x85, 0x1c, 0x00, 0x00, 0x85, 0x64, 0x00, 0x00, 0x85, 0x94, 0x00, 0x00, 0x85, 0xd8, 0x00, 0x00, 0x86, 0x48, 0x00, 0x00, 0x86, 0xb0, 0x00, 0x00, 0x87, 0x40, 0x00, 0x00, 0x87, 0x9c, 0x00, 0x00, 0x87, 0xfc, 0x00, 0x00, 0x88, 0x5c, 0x00, 0x00, 0x88, 0xcc, 0x00, 0x00, 0x89, 0x54, 0x00, 0x00, 0x89, 0x64, 0x00, 0x00, 0x89, 0xf8, 0x00, 0x00, 0x8a, 0x70, 0x00, 0x00, 0x8a, 0x80, 0x00, 0x00, 0x8a, 0xd4, 0x00, 0x00, 0x8b, 0x0c, 0x00, 0x00, 0x8b, 0x2c, 0x00, 0x00, 0x8b, 0xa0, 0x00, 0x00, 0x8c, 0x10, 0x00, 0x00, 0x8c, 0x80, 0x00, 0x00, 0x8d, 0x10, 0x00, 0x00, 0x8d, 0xd8, 0x00, 0x00, 0x8e, 0x94, 0x00, 0x00, 0x8f, 0x38, 0x00, 0x00, 0x8f, 0xc4, 0x00, 0x00, 0x90, 0x94, 0x00, 0x00, 0x91, 0x28, 0x00, 0x00, 0x91, 0xa0, 0x00, 0x00, 0x91, 0xdc, 0x00, 0x00, 0x92, 0x40, 0x00, 0x00, 0x92, 0x80, 0x00, 0x00, 0x92, 0xd0, 0x00, 0x00, 0x93, 0x34, 0x00, 0x00, 0x93, 0x78, 0x00, 0x00, 0x93, 0xcc, 0x00, 0x00, 0x94, 0x08, 0x00, 0x00, 0x94, 0x48, 0x00, 0x00, 0x94, 0x88, 0x00, 0x00, 0x94, 0xdc, 0x00, 0x00, 0x95, 0x48, 0x00, 0x00, 0x95, 0x80, 0x00, 0x00, 0x95, 0xc4, 0x00, 0x00, 0x95, 0xd4, 0x00, 0x00, 0x95, 0xec, 0x00, 0x00, 0x95, 0xfc, 0x00, 0x00, 0x96, 0x0c, 0x00, 0x00, 0x96, 0x30, 0x00, 0x00, 0x96, 0x64, 0x00, 0x00, 0x96, 0x9c, 0x00, 0x00, 0x96, 0xf8, 0x00, 0x00, 0x97, 0x58, 0x00, 0x00, 0x97, 0x80, 0x00, 0x00, 0x97, 0xa8, 0x00, 0x00, 0x97, 0xd0, 0x00, 0x00, 0x97, 0xf8, 0x00, 0x00, 0x98, 0x1c, 0x00, 0x00, 0x98, 0x44, 0x00, 0x00, 0x98, 0x60, 0x00, 0x00, 0x98, 0x70, 0x00, 0x00, 0x98, 0x8c, 0x00, 0x00, 0x98, 0xac, 0x00, 0x00, 0x98, 0xc8, 0x00, 0x00, 0x98, 0xdc, 0x00, 0x00, 0x98, 0xfc, 0x00, 0x00, 0x99, 0x18, 0x00, 0x00, 0x99, 0x40, 0x00, 0x00, 0x99, 0x5c, 0x00, 0x00, 0x99, 0x70, 0x00, 0x00, 0x99, 0x84, 0x00, 0x00, 0x99, 0xa8, 0x00, 0x00, 0x99, 0xcc, 0x00, 0x00, 0x99, 0xf8, 0x00, 0x00, 0x9a, 0x14, 0x00, 0x00, 0x9a, 0x48, 0x00, 0x00, 0x9a, 0x64, 0x00, 0x00, 0x9a, 0xb0, 0x00, 0x00, 0x9a, 0xf0, 0x00, 0x00, 0x9b, 0x4c, 0x00, 0x00, 0x9b, 0x78, 0x00, 0x00, 0x9b, 0xb0, 0x00, 0x00, 0x9b, 0xe4, 0x00, 0x00, 0x9c, 0x30, 0x00, 0x00, 0x9c, 0x4c, 0x00, 0x00, 0x9c, 0xe4, 0x00, 0x00, 0x9d, 0x1c, 0x00, 0x00, 0x9d, 0x2c, 0x00, 0x00, 0x9d, 0x4c, 0x00, 0x00, 0x9d, 0x70, 0x00, 0x00, 0x9d, 0x94, 0x00, 0x00, 0x9d, 0xb8, 0x00, 0x00, 0x9d, 0xd8, 0x00, 0x00, 0x9d, 0xec, 0x00, 0x00, 0x9e, 0x04, 0x00, 0x00, 0x9e, 0x14, 0x00, 0x00, 0x9e, 0x28, 0x00, 0x00, 0x9e, 0x94, 0x00, 0x00, 0x9e, 0xbc, 0x00, 0x00, 0x9e, 0xe0, 0x00, 0x00, 0x9f, 0x0c, 0x00, 0x00, 0x9f, 0x20, 0x00, 0x00, 0x9f, 0x34, 0x00, 0x00, 0x9f, 0x48, 0x00, 0x00, 0x9f, 0x5c, 0x00, 0x00, 0x9f, 0x7c, 0x00, 0x00, 0x9f, 0xa8, 0x00, 0x00, 0x9f, 0xfc, 0x00, 0x00, 0xa0, 0x10, 0x00, 0x00, 0xa0, 0x24, 0x00, 0x00, 0xa0, 0x50, 0x00, 0x00, 0xa0, 0x6c, 0x00, 0x00, 0xa0, 0x88, 0x00, 0x00, 0xa0, 0xb4, 0x00, 0x00, 0xa0, 0xd0, 0x00, 0x00, 0xa1, 0x04, 0x00, 0x00, 0xa1, 0x20, 0x00, 0x00, 0xa1, 0x48, 0x00, 0x00, 0xa1, 0x6c, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x00, 0xa1, 0x9c, 0x00, 0x00, 0xa1, 0xb0, 0x00, 0x00, 0xa1, 0xd4, 0x00, 0x00, 0xa1, 0xf4, 0x00, 0x00, 0xa2, 0x14, 0x00, 0x00, 0xa2, 0x58, 0x00, 0x00, 0xa2, 0x8c, 0x00, 0x00, 0xa2, 0xb0, 0x00, 0x00, 0xa2, 0xd4, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa3, 0x1c, 0x00, 0x00, 0xa3, 0x4c, 0x00, 0x00, 0xa3, 0x7c, 0x00, 0x00, 0xa3, 0x94, 0x00, 0x00, 0xa3, 0xa8, 0x00, 0x00, 0xa3, 0xf4, 0x00, 0x00, 0xa4, 0x10, 0x00, 0x00, 0xa4, 0x24, 0x00, 0x00, 0xa4, 0x38, 0x00, 0x00, 0xa4, 0x54, 0x00, 0x00, 0xa4, 0x78, 0x00, 0x00, 0xa4, 0xc0, 0x00, 0x00, 0xa4, 0xd4, 0x00, 0x00, 0xa4, 0xe8, 0x00, 0x00, 0xa4, 0xfc, 0x00, 0x00, 0xa5, 0x30, 0x00, 0x00, 0xa5, 0x44, 0x00, 0x00, 0xa5, 0x58, 0x00, 0x00, 0xa5, 0x6c, 0x00, 0x00, 0xa5, 0x80, 0x00, 0x00, 0xa5, 0xdc, 0x00, 0x00, 0xa5, 0xf8, 0x00, 0x00, 0xa6, 0x14, 0x00, 0x00, 0xa6, 0x34, 0x00, 0x00, 0xa6, 0x54, 0x00, 0x00, 0xa6, 0x84, 0x00, 0x00, 0xa6, 0xa8, 0x00, 0x00, 0xa6, 0xd0, 0x00, 0x00, 0xa7, 0x18, 0x00, 0x00, 0xa7, 0x4c, 0x00, 0x00, 0xa7, 0xac, 0x00, 0x00, 0xa7, 0xc8, 0x00, 0x00, 0xa7, 0xdc, 0x00, 0x00, 0xa7, 0xf0, 0x00, 0x00, 0xa8, 0x04, 0x00, 0x00, 0xa8, 0x14, 0x00, 0x00, 0xa8, 0x28, 0x00, 0x00, 0xa8, 0x3c, 0x00, 0x00, 0xa8, 0x60, 0x00, 0x00, 0xa8, 0x88, 0x00, 0x00, 0xa8, 0xb0, 0x00, 0x00, 0xa8, 0xd0, 0x00, 0x00, 0xa9, 0x4c, 0x00, 0x00, 0xa9, 0xc0, 0x00, 0x00, 0xa9, 0xd8, 0x00, 0x00, 0xaa, 0x10, 0x00, 0x00, 0xaa, 0x38, 0x00, 0x00, 0xaa, 0x38, 0x00, 0x00, 0xaa, 0x78, 0x00, 0x00, 0xaa, 0x90, 0x00, 0x00, 0xaa, 0xa4, 0x00, 0x00, 0xaa, 0xe4, 0x00, 0x00, 0xaa, 0xf8, 0x00, 0x00, 0xab, 0x5c, 0x00, 0x00, 0xab, 0x70, 0x00, 0x00, 0xab, 0x84, 0x00, 0x00, 0xab, 0xa0, 0x00, 0x00, 0xab, 0xbc, 0x00, 0x00, 0xac, 0x30, 0x00, 0x00, 0xac, 0x44, 0x00, 0x00, 0xac, 0x6c, 0x00, 0x00, 0xac, 0x7c, 0x00, 0x00, 0xac, 0x8c, 0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, 0xac, 0xec, 0x00, 0x00, 0xad, 0x08, 0x00, 0x00, 0xad, 0x24, 0x00, 0x00, 0xad, 0x34, 0x00, 0x00, 0xad, 0x44, 0x00, 0x00, 0xad, 0x78, 0x00, 0x00, 0xad, 0x88, 0x00, 0x00, 0xad, 0xa0, 0x00, 0x00, 0xad, 0xb8, 0x00, 0x00, 0xad, 0xc8, 0x00, 0x00, 0xad, 0xe4, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0xae, 0x18, 0x00, 0x00, 0xae, 0x28, 0x00, 0x00, 0xae, 0x44, 0x00, 0x00, 0xae, 0x60, 0x00, 0x00, 0xae, 0x7c, 0x00, 0x00, 0xae, 0x94, 0x00, 0x00, 0xae, 0xb0, 0x00, 0x00, 0xae, 0xc8, 0x00, 0x00, 0xae, 0xe0, 0x00, 0x00, 0xae, 0xf0, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xaf, 0x20, 0x00, 0x00, 0xaf, 0x50, 0x00, 0x00, 0xaf, 0x60, 0x00, 0x00, 0xaf, 0x70, 0x00, 0x00, 0xaf, 0x80, 0x00, 0x00, 0xaf, 0xfc, 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x00, 0xb0, 0x1c, 0x00, 0x00, 0xb0, 0x44, 0x00, 0x00, 0xb0, 0x54, 0x00, 0x00, 0xb0, 0x64, 0x00, 0x00, 0xb0, 0x9c, 0x00, 0x00, 0xb0, 0xac, 0x00, 0x00, 0xb0, 0xbc, 0x00, 0x00, 0xb0, 0xcc, 0x00, 0x00, 0xb1, 0x04, 0x00, 0x00, 0xb1, 0x14, 0x00, 0x00, 0xb1, 0x24, 0x00, 0x00, 0xb1, 0xa8, 0x00, 0x00, 0xb1, 0xb8, 0x00, 0x00, 0xb2, 0x20, 0x00, 0x00, 0xb2, 0x9c, 0x00, 0x00, 0xb2, 0xb8, 0x00, 0x00, 0xb2, 0xd4, 0x00, 0x00, 0xb2, 0xec, 0x00, 0x00, 0xb3, 0x04, 0x00, 0x00, 0xb3, 0x1c, 0x00, 0x00, 0xb3, 0x34, 0x00, 0x00, 0xb3, 0x4c, 0x00, 0x00, 0xb3, 0xd4, 0x00, 0x00, 0xb4, 0x38, 0x00, 0x00, 0xb4, 0x78, 0x00, 0x00, 0xb5, 0x08, 0x00, 0x00, 0xb5, 0x9c, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xb6, 0x48, 0x00, 0x00, 0xb6, 0xc4, 0x00, 0x00, 0xb6, 0xf8, 0x00, 0x00, 0xb7, 0x30, 0x00, 0x00, 0xb7, 0x70, 0x00, 0x00, 0xb7, 0x80, 0x00, 0x00, 0xb7, 0xd0, 0x00, 0x00, 0xb8, 0x4c, 0x00, 0x00, 0xb8, 0x5c, 0x00, 0x00, 0xb8, 0xa8, 0x00, 0x00, 0xb9, 0x0c, 0x00, 0x00, 0xb9, 0x80, 0x00, 0x00, 0xb9, 0xe4, 0x00, 0x00, 0xba, 0x20, 0x00, 0x00, 0xba, 0x80, 0x00, 0x00, 0xbb, 0x04, 0x00, 0x00, 0xbb, 0x60, 0x00, 0x00, 0xbb, 0xbc, 0x00, 0x00, 0xbc, 0x18, 0x00, 0x00, 0xbc, 0x30, 0x00, 0x00, 0xbc, 0x48, 0x00, 0x00, 0xbc, 0x60, 0x00, 0x00, 0xbc, 0x78, 0x00, 0x00, 0xbc, 0x90, 0x00, 0x00, 0xbc, 0xcc, 0x00, 0x00, 0xbd, 0x54, 0x00, 0x00, 0xbd, 0xc4, 0x00, 0x00, 0xbe, 0x34, 0x00, 0x00, 0xbe, 0x50, 0x00, 0x00, 0xbe, 0x68, 0x00, 0x00, 0xbe, 0xf0, 0x00, 0x00, 0xbf, 0x58, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x00, 0xc0, 0x78, 0x00, 0x00, 0xc0, 0xe4, 0x00, 0x00, 0xc1, 0x58, 0x00, 0x00, 0xc1, 0xc0, 0x00, 0x00, 0xc1, 0xd0, 0x00, 0x00, 0xc2, 0x48, 0x00, 0x00, 0xc2, 0xa4, 0x00, 0x00, 0xc2, 0xd0, 0x00, 0x00, 0xc3, 0x44, 0x00, 0x00, 0xc3, 0xa0, 0x00, 0x00, 0xc4, 0x60, 0x00, 0x00, 0xc4, 0xe0, 0x00, 0x00, 0xc5, 0x48, 0x00, 0x00, 0xc5, 0xa8, 0x00, 0x00, 0xc6, 0x24, 0x00, 0x00, 0xc7, 0x0c, 0x00, 0x00, 0xc7, 0x80, 0x00, 0x00, 0xc7, 0xec, 0x00, 0x00, 0xc8, 0x9c, 0x00, 0x00, 0xc9, 0x4c, 0x00, 0x00, 0xc9, 0xe0, 0x00, 0x00, 0xca, 0x78, 0x00, 0x00, 0xca, 0xb0, 0x00, 0x00, 0xca, 0xe8, 0x00, 0x00, 0xcb, 0x84, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xcc, 0x10, 0x00, 0x00, 0xcc, 0x20, 0x00, 0x00, 0xcc, 0x30, 0x00, 0x00, 0xcc, 0x9c, 0x00, 0x00, 0xcd, 0x08, 0x00, 0x00, 0xcd, 0x18, 0x00, 0x00, 0xcd, 0x28, 0x00, 0x00, 0xcd, 0x38, 0x00, 0x00, 0xcd, 0x74, 0x00, 0x00, 0xcd, 0xac, 0x00, 0x00, 0xce, 0x2c, 0x00, 0x00, 0xce, 0x3c, 0x00, 0x00, 0xce, 0x54, 0x00, 0x00, 0xce, 0x6c, 0x00, 0x00, 0xce, 0x84, 0x00, 0x00, 0xce, 0xa0, 0x00, 0x00, 0xce, 0xf8, 0x00, 0x00, 0xcf, 0x10, 0x00, 0x00, 0xcf, 0x68, 0x00, 0x00, 0xcf, 0x78, 0x00, 0x00, 0xcf, 0x88, 0x00, 0x00, 0xcf, 0x98, 0x00, 0x00, 0xcf, 0xa8, 0x00, 0x00, 0xd0, 0x0c, 0x00, 0x00, 0xd0, 0x68, 0x00, 0x00, 0xd0, 0xac, 0x00, 0x00, 0xd0, 0xc4, 0x00, 0x00, 0xd0, 0xdc, 0x00, 0x00, 0xd0, 0xf4, 0x00, 0x00, 0xd1, 0x24, 0x00, 0x00, 0xd1, 0x34, 0x00, 0x00, 0xd1, 0x84, 0x00, 0x00, 0xd1, 0x94, 0x00, 0x00, 0xd1, 0xb4, 0x00, 0x00, 0xd2, 0x0c, 0x00, 0x00, 0xd2, 0x1c, 0x00, 0x00, 0xd2, 0x74, 0x00, 0x00, 0xd2, 0xec, 0x00, 0x00, 0xd3, 0x1c, 0x00, 0x00, 0xd3, 0x38, 0x00, 0x00, 0xd3, 0x70, 0x00, 0x00, 0xd3, 0xac, 0x00, 0x00, 0xd3, 0xbc, 0x00, 0x00, 0xd3, 0xcc, 0x00, 0x00, 0xd3, 0xdc, 0x00, 0x00, 0xd4, 0x04, 0x00, 0x00, 0xd4, 0x14, 0x00, 0x00, 0xd4, 0x24, 0x00, 0x00, 0xd4, 0x34, 0x00, 0x00, 0xd4, 0x78, 0x00, 0x00, 0xd4, 0xf0, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xd5, 0x30, 0x00, 0x00, 0xd5, 0x68, 0x00, 0x00, 0xd5, 0x98, 0x00, 0x00, 0xd5, 0xd4, 0x00, 0x00, 0xd6, 0x28, 0x00, 0x00, 0xd6, 0x40, 0x00, 0x00, 0xd6, 0x90, 0x00, 0x00, 0xd6, 0xe8, 0x00, 0x00, 0xd7, 0x70, 0x00, 0x00, 0xd7, 0xc4, 0x00, 0x00, 0xd7, 0xd4, 0x00, 0x00, 0xd8, 0x60, 0x00, 0x00, 0xd8, 0xcc, 0x00, 0x00, 0xd8, 0xec, 0x00, 0x00, 0xd9, 0x40, 0x00, 0x00, 0xd9, 0x50, 0x00, 0x00, 0xd9, 0xa8, 0x00, 0x00, 0xda, 0x1c, 0x00, 0x00, 0xda, 0x4c, 0x00, 0x00, 0xda, 0x68, 0x00, 0x00, 0xda, 0xa0, 0x00, 0x00, 0xda, 0xdc, 0x00, 0x00, 0xdb, 0x18, 0x00, 0x00, 0xdb, 0x48, 0x00, 0x00, 0xdb, 0x58, 0x00, 0x00, 0xdb, 0x80, 0x00, 0x00, 0xdb, 0x90, 0x00, 0x00, 0xdb, 0xa0, 0x00, 0x00, 0xdb, 0xc8, 0x00, 0x00, 0xdb, 0xd8, 0x00, 0x00, 0xdc, 0x80, 0x00, 0x00, 0xdc, 0x90, 0x00, 0x00, 0xdc, 0xc0, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xdd, 0x30, 0x00, 0x00, 0xdd, 0x6c, 0x00, 0x00, 0xdd, 0xb8, 0x00, 0x00, 0xdd, 0xd0, 0x00, 0x00, 0xde, 0x18, 0x00, 0x00, 0xde, 0x6c, 0x00, 0x00, 0xde, 0xd4, 0x00, 0x00, 0xdf, 0x28, 0x00, 0x00, 0xdf, 0x40, 0x00, 0x00, 0xdf, 0x5c, 0x00, 0x00, 0xdf, 0xc0, 0x00, 0x00, 0xdf, 0xd8, 0x00, 0x00, 0xe0, 0x30, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xe0, 0x50, 0x00, 0x00, 0xe0, 0x60, 0x00, 0x00, 0xe0, 0x70, 0x00, 0x00, 0xe0, 0xd4, 0x00, 0x00, 0xe1, 0x30, 0x00, 0x00, 0xe1, 0x88, 0x00, 0x00, 0xe1, 0xa0, 0x00, 0x00, 0xe1, 0xb8, 0x00, 0x00, 0xe1, 0xd0, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe2, 0xa0, 0x00, 0x00, 0xe2, 0xb0, 0x00, 0x00, 0xe3, 0x10, 0x00, 0x00, 0xe3, 0x68, 0x00, 0x00, 0xe3, 0xf4, 0x00, 0x00, 0xe4, 0x64, 0x00, 0x00, 0xe4, 0xa4, 0x00, 0x00, 0xe4, 0xe4, 0x00, 0x00, 0xe5, 0x3c, 0x00, 0x00, 0xe5, 0x94, 0x00, 0x00, 0xe5, 0xfc, 0x00, 0x00, 0xe6, 0x64, 0x00, 0x00, 0xe6, 0xe0, 0x00, 0x00, 0xe7, 0x58, 0x00, 0x00, 0xe8, 0x44, 0x00, 0x00, 0xe9, 0x20, 0x00, 0x00, 0xe9, 0x84, 0x00, 0x00, 0xe9, 0xe8, 0x00, 0x00, 0xe9, 0xf8, 0x00, 0x00, 0xea, 0x08, 0x00, 0x00, 0xea, 0x54, 0x00, 0x00, 0xea, 0xa4, 0x00, 0x00, 0xea, 0xbc, 0x00, 0x00, 0xea, 0xd4, 0x00, 0x00, 0xeb, 0x78, 0x00, 0x00, 0xeb, 0xfc, 0x00, 0x00, 0xec, 0xf4, 0x00, 0x00, 0xed, 0xdc, 0x00, 0x00, 0xee, 0xb8, 0x00, 0x00, 0xef, 0x68, 0x00, 0x00, 0xef, 0x80, 0x00, 0x00, 0xef, 0x98, 0x00, 0x00, 0xef, 0xfc, 0x00, 0x00, 0xf0, 0x58, 0x00, 0x00, 0xf0, 0xa4, 0x00, 0x00, 0xf1, 0x3c, 0x00, 0x00, 0xf1, 0x70, 0x00, 0x00, 0xf1, 0x98, 0x00, 0x00, 0xf1, 0xc0, 0x00, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xf3, 0x44, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf4, 0x18, 0x00, 0x00, 0xf4, 0x30, 0x00, 0x00, 0xf4, 0x90, 0x00, 0x00, 0xf4, 0xf4, 0x00, 0x00, 0xf5, 0x54, 0x00, 0x00, 0xf5, 0xd8, 0x00, 0x00, 0xf5, 0xfc, 0x00, 0x00, 0xf6, 0x20, 0x00, 0x00, 0xf6, 0x54, 0x00, 0x00, 0xf6, 0x88, 0x00, 0x00, 0xf6, 0xe0, 0x00, 0x00, 0xf7, 0x3c, 0x00, 0x00, 0xf7, 0xa0, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x00, 0x00, 0xf8, 0x30, 0x00, 0x00, 0xf8, 0x74, 0x00, 0x00, 0xf8, 0xb8, 0x00, 0x00, 0xf9, 0x04, 0x00, 0x00, 0xf9, 0x4c, 0x00, 0x00, 0xf9, 0x98, 0x00, 0x00, 0xf9, 0xe4, 0x00, 0x00, 0xfa, 0x24, 0x00, 0x00, 0xfa, 0x64, 0x00, 0x00, 0xfa, 0xa0, 0x00, 0x00, 0xfa, 0xdc, 0x00, 0x00, 0xfb, 0x14, 0x00, 0x00, 0xfb, 0x4c, 0x00, 0x00, 0xfb, 0xac, 0x00, 0x00, 0xfc, 0x10, 0x00, 0x00, 0xfd, 0x04, 0x00, 0x00, 0xfd, 0xe0, 0x00, 0x00, 0xfd, 0xf8, 0x00, 0x00, 0xfe, 0x10, 0x00, 0x00, 0xfe, 0x40, 0x00, 0x00, 0xfe, 0x70, 0x00, 0x00, 0xfe, 0x80, 0x00, 0x00, 0xfe, 0xb0, 0x00, 0x00, 0xfe, 0xf4, 0x00, 0x00, 0xff, 0x34, 0x00, 0x00, 0xff, 0x7c, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x01, 0x00, 0x84, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x01, 0x01, 0x1c, 0x00, 0x01, 0x01, 0x68, 0x00, 0x01, 0x01, 0xa4, 0x00, 0x01, 0x01, 0xb4, 0x00, 0x01, 0x02, 0x44, 0x00, 0x01, 0x02, 0xd4, 0x00, 0x01, 0x03, 0x6c, 0x00, 0x01, 0x04, 0x04, 0x00, 0x01, 0x04, 0x14, 0x00, 0x01, 0x04, 0x2c, 0x00, 0x01, 0x04, 0x44, 0x00, 0x01, 0x04, 0xa0, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x01, 0x05, 0x98, 0x00, 0x01, 0x05, 0xe0, 0x00, 0x01, 0x06, 0x28, 0x00, 0x01, 0x06, 0x64, 0x00, 0x01, 0x06, 0xa0, 0x00, 0x01, 0x06, 0xe8, 0x00, 0x01, 0x07, 0x30, 0x00, 0x01, 0x07, 0x7c, 0x00, 0x01, 0x07, 0xc4, 0x00, 0x01, 0x07, 0xd4, 0x00, 0x01, 0x07, 0xf0, 0x00, 0x01, 0x08, 0x08, 0x00, 0x01, 0x08, 0x24, 0x00, 0x01, 0x08, 0x3c, 0x00, 0x01, 0x08, 0x4c, 0x00, 0x01, 0x08, 0x5c, 0x00, 0x01, 0x08, 0x78, 0x00, 0x01, 0x08, 0x94, 0x00, 0x01, 0x08, 0xa4, 0x00, 0x01, 0x08, 0xb4, 0x00, 0x01, 0x08, 0xcc, 0x00, 0x01, 0x08, 0xe4, 0x00, 0x01, 0x08, 0xfc, 0x00, 0x01, 0x09, 0x14, 0x00, 0x01, 0x09, 0x2c, 0x00, 0x01, 0x09, 0x44, 0x00, 0x01, 0x09, 0x54, 0x00, 0x01, 0x09, 0x64, 0x00, 0x01, 0x09, 0x7c, 0x00, 0x01, 0x09, 0x94, 0x00, 0x01, 0x09, 0xac, 0x00, 0x01, 0x09, 0xc4, 0x00, 0x01, 0x09, 0xe0, 0x00, 0x01, 0x09, 0xf8, 0x00, 0x01, 0x0a, 0x08, 0x00, 0x01, 0x0a, 0x18, 0x00, 0x01, 0x0a, 0x30, 0x00, 0x01, 0x0a, 0x48, 0x00, 0x01, 0x0a, 0x60, 0x00, 0x01, 0x0a, 0x78, 0x00, 0x01, 0x0a, 0x90, 0x00, 0x01, 0x0a, 0xa8, 0x00, 0x01, 0x0a, 0xc0, 0x00, 0x01, 0x0a, 0xd8, 0x00, 0x01, 0x0a, 0xf0, 0x00, 0x01, 0x0b, 0x08, 0x00, 0x01, 0x0b, 0x20, 0x00, 0x01, 0x0b, 0x38, 0x00, 0x01, 0x0b, 0x60, 0x00, 0x01, 0x0b, 0x88, 0x00, 0x01, 0x0b, 0xa0, 0x00, 0x01, 0x0b, 0xb8, 0x00, 0x01, 0x0c, 0x08, 0x00, 0x01, 0x0c, 0x58, 0x00, 0x01, 0x0c, 0xb8, 0x00, 0x01, 0x0d, 0x18, 0x00, 0x01, 0x0d, 0x68, 0x00, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x0e, 0x08, 0x00, 0x01, 0x0e, 0x5c, 0x00, 0x01, 0x0e, 0xf0, 0x00, 0x01, 0x0f, 0x80, 0x00, 0x01, 0x10, 0x20, 0x00, 0x01, 0x10, 0xbc, 0x00, 0x01, 0x11, 0x38, 0x00, 0x01, 0x11, 0xb4, 0x00, 0x01, 0x12, 0x24, 0x00, 0x01, 0x12, 0x90, 0x00, 0x01, 0x12, 0xa0, 0x00, 0x01, 0x12, 0xfc, 0x00, 0x01, 0x13, 0x5c, 0x00, 0x01, 0x13, 0xb4, 0x00, 0x01, 0x14, 0x08, 0x00, 0x01, 0x14, 0x5c, 0x00, 0x01, 0x14, 0x6c, 0x00, 0x01, 0x14, 0x7c, 0x00, 0x01, 0x14, 0xcc, 0x00, 0x01, 0x15, 0x1c, 0x00, 0x01, 0x15, 0x80, 0x00, 0x01, 0x15, 0xe8, 0x00, 0x01, 0x16, 0x48, 0x00, 0x01, 0x16, 0xc0, 0x00, 0x01, 0x17, 0x28, 0x00, 0x01, 0x17, 0xc0, 0x00, 0x01, 0x17, 0xd0, 0x00, 0x01, 0x17, 0xe0, 0x00, 0x01, 0x17, 0xf0, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x18, 0x54, 0x00, 0x01, 0x18, 0xa0, 0x00, 0x01, 0x19, 0x14, 0x00, 0x01, 0x19, 0x88, 0x00, 0x01, 0x19, 0xf0, 0x00, 0x01, 0x1a, 0x5c, 0x00, 0x01, 0x1a, 0x8c, 0x00, 0x01, 0x1a, 0xbc, 0x00, 0x01, 0x1a, 0xf4, 0x00, 0x01, 0x1b, 0x44, 0x00, 0x01, 0x1c, 0x1c, 0x00, 0x01, 0x1c, 0x88, 0x00, 0x01, 0x1c, 0x98, 0x00, 0x01, 0x1c, 0xe0, 0x00, 0x01, 0x1d, 0x38, 0x00, 0x01, 0x1d, 0x68, 0x00, 0x01, 0x1d, 0xf8, 0x00, 0x01, 0x1e, 0x1c, 0x00, 0x01, 0x1e, 0x58, 0x00, 0x01, 0x1e, 0x68, 0x00, 0x01, 0x1e, 0xa0, 0x00, 0x01, 0x1e, 0xb0, 0x00, 0x01, 0x1e, 0xc0, 0x00, 0x01, 0x1e, 0xd0, 0x00, 0x01, 0x1e, 0xe0, 0x00, 0x01, 0x1f, 0x34, 0x00, 0x01, 0x1f, 0x88, 0x00, 0x01, 0x20, 0x18, 0x00, 0x01, 0x20, 0xd4, 0x00, 0x01, 0x21, 0x0c, 0x00, 0x01, 0x21, 0x44, 0x00, 0x01, 0x21, 0x88, 0x00, 0x01, 0x21, 0xf8, 0x00, 0x01, 0x22, 0x68, 0x00, 0x01, 0x22, 0x78, 0x00, 0x01, 0x22, 0xb0, 0x00, 0x01, 0x22, 0xf4, 0x00, 0x01, 0x23, 0x50, 0x00, 0x01, 0x23, 0xc4, 0x00, 0x01, 0x23, 0xd4, 0x00, 0x01, 0x23, 0xe4, 0x00, 0x01, 0x23, 0xf4, 0x00, 0x01, 0x24, 0x44, 0x00, 0x01, 0x24, 0x64, 0x00, 0x01, 0x24, 0x74, 0x00, 0x01, 0x24, 0x9c, 0x00, 0x01, 0x24, 0xac, 0x00, 0x01, 0x25, 0x08, 0x00, 0x01, 0x25, 0x18, 0x00, 0x01, 0x25, 0x4c, 0x00, 0x01, 0x25, 0x98, 0x00, 0x01, 0x26, 0x14, 0x00, 0x01, 0x26, 0x5c, 0x00, 0x01, 0x26, 0x8c, 0x00, 0x01, 0x26, 0xbc, 0x00, 0x01, 0x27, 0x2c, 0x00, 0x01, 0x27, 0x5c, 0x00, 0x01, 0x27, 0x78, 0x00, 0x01, 0x27, 0xa8, 0x00, 0x01, 0x27, 0xdc, 0x00, 0x01, 0x27, 0xfc, 0x00, 0x01, 0x28, 0x34, 0x00, 0x01, 0x28, 0x64, 0x00, 0x01, 0x28, 0x94, 0x00, 0x01, 0x28, 0xf4, 0x00, 0x01, 0x29, 0xb0, 0x00, 0x01, 0x29, 0xfc, 0x00, 0x01, 0x2a, 0x68, 0x00, 0x01, 0x2a, 0x90, 0x00, 0x01, 0x2a, 0xd4, 0x00, 0x01, 0x2b, 0x0c, 0x00, 0x01, 0x2b, 0x8c, 0x00, 0x01, 0x2c, 0x14, 0x00, 0x01, 0x2c, 0x7c, 0x00, 0x01, 0x2d, 0x54, 0x00, 0x01, 0x2d, 0xb8, 0x00, 0x01, 0x2e, 0x20, 0x00, 0x01, 0x2e, 0x94, 0x00, 0x01, 0x2e, 0xf0, 0x00, 0x01, 0x2f, 0x84, 0x00, 0x01, 0x30, 0x14, 0x00, 0x01, 0x30, 0xa8, 0x00, 0x01, 0x30, 0xcc, 0x00, 0x01, 0x31, 0x00, 0x00, 0x01, 0x31, 0x68, 0x00, 0x01, 0x31, 0xc8, 0x00, 0x01, 0x32, 0x14, 0x00, 0x01, 0x32, 0x7c, 0x00, 0x01, 0x32, 0xb8, 0x00, 0x01, 0x32, 0xf0, 0x00, 0x01, 0x33, 0x54, 0x00, 0x01, 0x33, 0x94, 0x00, 0x01, 0x33, 0xe0, 0x00, 0x01, 0x34, 0x2c, 0x00, 0x01, 0x34, 0xa8, 0x00, 0x01, 0x34, 0xcc, 0x00, 0x01, 0x35, 0x2c, 0x00, 0x01, 0x35, 0x64, 0x00, 0x01, 0x35, 0xec, 0x00, 0x01, 0x36, 0x68, 0x00, 0x01, 0x36, 0xc0, 0x00, 0x01, 0x36, 0xd4, 0x00, 0x01, 0x36, 0xe8, 0x00, 0x01, 0x36, 0xfc, 0x00, 0x01, 0x37, 0x10, 0x00, 0x01, 0x37, 0x24, 0x00, 0x01, 0x37, 0x38, 0x00, 0x01, 0x37, 0x94, 0x00, 0x01, 0x37, 0xa8, 0x00, 0x01, 0x37, 0xbc, 0x00, 0x01, 0x38, 0x38, 0x00, 0x01, 0x38, 0x48, 0x00, 0x01, 0x38, 0x88, 0x00, 0x01, 0x39, 0x14, 0x00, 0x01, 0x39, 0x50, 0x00, 0x01, 0x39, 0xb8, 0x00, 0x01, 0x3a, 0x18, 0x00, 0x01, 0x3a, 0x9c, 0x00, 0x01, 0x3b, 0x2c, 0x00, 0x01, 0x3b, 0xbc, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, 0x3c, 0x44, 0x00, 0x01, 0x3c, 0xcc, 0x00, 0x01, 0x3d, 0x18, 0x00, 0x01, 0x3d, 0x50, 0x00, 0x01, 0x3d, 0x80, 0x00, 0x01, 0x3d, 0xac, 0x00, 0x01, 0x3d, 0xe8, 0x00, 0x01, 0x3e, 0x40, 0x00, 0x01, 0x3e, 0x74, 0x00, 0x01, 0x3e, 0xb4, 0x00, 0x01, 0x3e, 0xd4, 0x00, 0x01, 0x3f, 0x6c, 0x00, 0x01, 0x3f, 0xe8, 0x00, 0x01, 0x40, 0x48, 0x00, 0x01, 0x40, 0xac, 0x00, 0x01, 0x40, 0xdc, 0x00, 0x01, 0x41, 0x4c, 0x00, 0x01, 0x41, 0xdc, 0x00, 0x01, 0x42, 0x84, 0x00, 0x01, 0x42, 0xd4, 0x00, 0x01, 0x43, 0x2c, 0x00, 0x01, 0x43, 0x94, 0x00, 0x01, 0x44, 0x08, 0x00, 0x01, 0x44, 0x4c, 0x00, 0x01, 0x44, 0xb0, 0x00, 0x01, 0x44, 0xd8, 0x00, 0x01, 0x45, 0x08, 0x00, 0x01, 0x45, 0x54, 0x00, 0x01, 0x45, 0xac, 0x00, 0x01, 0x46, 0x14, 0x00, 0x01, 0x46, 0x80, 0x00, 0x01, 0x46, 0xa0, 0x00, 0x01, 0x46, 0xc4, 0x00, 0x01, 0x46, 0xe8, 0x00, 0x01, 0x47, 0x08, 0x00, 0x01, 0x47, 0x34, 0x00, 0x01, 0x47, 0x64, 0x00, 0x01, 0x47, 0x7c, 0x00, 0x01, 0x47, 0x94, 0x00, 0x01, 0x47, 0xac, 0x00, 0x01, 0x47, 0xc4, 0x00, 0x01, 0x47, 0xdc, 0x00, 0x01, 0x47, 0xf4, 0x00, 0x01, 0x48, 0x0c, 0x00, 0x01, 0x48, 0x24, 0x00, 0x01, 0x48, 0x3c, 0x00, 0x01, 0x48, 0x54, 0x00, 0x01, 0x48, 0x6c, 0x00, 0x01, 0x48, 0x84, 0x00, 0x01, 0x48, 0x9c, 0x00, 0x01, 0x48, 0xb4, 0x00, 0x01, 0x48, 0xcc, 0x00, 0x01, 0x48, 0xe4, 0x00, 0x01, 0x48, 0xfc, 0x00, 0x01, 0x49, 0x14, 0x00, 0x01, 0x49, 0x2c, 0x00, 0x01, 0x49, 0x44, 0x00, 0x01, 0x49, 0x5c, 0x00, 0x01, 0x49, 0x74, 0x00, 0x01, 0x49, 0x8c, 0x00, 0x01, 0x49, 0xa4, 0x00, 0x01, 0x49, 0xbc, 0x00, 0x01, 0x49, 0xd4, 0x00, 0x01, 0x49, 0xec, 0x00, 0x01, 0x4a, 0x04, 0x00, 0x01, 0x4a, 0x24, 0x00, 0x01, 0x4a, 0x40, 0x00, 0x01, 0x4a, 0x58, 0x00, 0x01, 0x4a, 0x70, 0x00, 0x01, 0x4a, 0x88, 0x00, 0x01, 0x4a, 0xa0, 0x00, 0x01, 0x4a, 0xb8, 0x00, 0x01, 0x4a, 0xd0, 0x00, 0x01, 0x4a, 0xe8, 0x00, 0x01, 0x4b, 0x00, 0x00, 0x01, 0x4b, 0x18, 0x00, 0x01, 0x4b, 0x30, 0x00, 0x01, 0x4b, 0x48, 0x00, 0x01, 0x4b, 0x60, 0x00, 0x01, 0x4b, 0x78, 0x00, 0x01, 0x4b, 0x90, 0x00, 0x01, 0x4b, 0xa8, 0x00, 0x01, 0x4b, 0xc0, 0x00, 0x01, 0x4b, 0xd8, 0x00, 0x01, 0x4b, 0xf0, 0x00, 0x01, 0x4c, 0x08, 0x00, 0x01, 0x4c, 0x20, 0x00, 0x01, 0x4c, 0x38, 0x00, 0x01, 0x4c, 0x50, 0x00, 0x01, 0x4c, 0x68, 0x00, 0x01, 0x4c, 0x80, 0x00, 0x01, 0x4c, 0x98, 0x00, 0x01, 0x4c, 0xb0, 0x00, 0x01, 0x4c, 0xd0, 0x00, 0x01, 0x4c, 0xe8, 0x00, 0x01, 0x4d, 0x00, 0x00, 0x01, 0x4d, 0x18, 0x00, 0x01, 0x4d, 0x30, 0x00, 0x01, 0x4d, 0x48, 0x00, 0x01, 0x4d, 0x60, 0x00, 0x01, 0x4d, 0x78, 0x00, 0x01, 0x4d, 0x90, 0x00, 0x01, 0x4d, 0xa8, 0x00, 0x01, 0x4d, 0xc0, 0x00, 0x01, 0x4d, 0xd8, 0x00, 0x01, 0x4d, 0xf0, 0x00, 0x01, 0x4e, 0x08, 0x00, 0x01, 0x4e, 0x20, 0x00, 0x01, 0x4e, 0x38, 0x00, 0x01, 0x4e, 0x50, 0x00, 0x01, 0x4e, 0x68, 0x00, 0x01, 0x4e, 0x80, 0x00, 0x01, 0x4e, 0x98, 0x00, 0x01, 0x4e, 0xb0, 0x00, 0x01, 0x4e, 0xc8, 0x00, 0x01, 0x4e, 0xe0, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x01, 0x4f, 0x18, 0x00, 0x01, 0x4f, 0x30, 0x00, 0x01, 0x4f, 0x48, 0x00, 0x01, 0x4f, 0x60, 0x00, 0x01, 0x4f, 0x78, 0x00, 0x01, 0x4f, 0x90, 0x00, 0x01, 0x4f, 0xa8, 0x00, 0x01, 0x4f, 0xc0, 0x00, 0x01, 0x4f, 0xd8, 0x00, 0x01, 0x4f, 0xf0, 0x00, 0x01, 0x50, 0x08, 0x00, 0x01, 0x50, 0x20, 0x00, 0x01, 0x50, 0x38, 0x00, 0x01, 0x50, 0x50, 0x00, 0x01, 0x50, 0x68, 0x00, 0x01, 0x50, 0x80, 0x00, 0x01, 0x50, 0x98, 0x00, 0x01, 0x50, 0xb0, 0x00, 0x01, 0x50, 0xc8, 0x00, 0x01, 0x50, 0xe0, 0x00, 0x01, 0x51, 0x00, 0x00, 0x01, 0x51, 0x20, 0x00, 0x01, 0x51, 0x38, 0x00, 0x01, 0x51, 0x50, 0x00, 0x01, 0x51, 0x68, 0x00, 0x01, 0x51, 0x80, 0x00, 0x01, 0x51, 0x98, 0x00, 0x01, 0x51, 0xb0, 0x00, 0x01, 0x51, 0xc8, 0x00, 0x01, 0x51, 0xe0, 0x00, 0x01, 0x51, 0xf8, 0x00, 0x01, 0x52, 0x10, 0x00, 0x01, 0x52, 0x28, 0x00, 0x01, 0x52, 0x40, 0x00, 0x01, 0x52, 0x58, 0x00, 0x01, 0x52, 0x70, 0x00, 0x01, 0x52, 0x88, 0x00, 0x01, 0x52, 0xa0, 0x00, 0x01, 0x52, 0xb8, 0x00, 0x01, 0x52, 0xd0, 0x00, 0x01, 0x52, 0xe8, 0x00, 0x01, 0x53, 0x00, 0x00, 0x01, 0x53, 0x18, 0x00, 0x01, 0x53, 0x30, 0x00, 0x01, 0x53, 0x48, 0x00, 0x01, 0x53, 0x60, 0x00, 0x01, 0x53, 0x78, 0x00, 0x01, 0x53, 0x90, 0x00, 0x01, 0x53, 0xa8, 0x00, 0x01, 0x53, 0xc0, 0x00, 0x01, 0x53, 0xd8, 0x00, 0x01, 0x53, 0xf0, 0x00, 0x01, 0x54, 0x08, 0x00, 0x01, 0x54, 0x20, 0x00, 0x01, 0x54, 0x38, 0x00, 0x01, 0x54, 0x50, 0x00, 0x01, 0x54, 0x68, 0x00, 0x01, 0x54, 0x80, 0x00, 0x01, 0x54, 0x98, 0x00, 0x01, 0x54, 0xb0, 0x00, 0x01, 0x54, 0xc8, 0x00, 0x01, 0x54, 0xe0, 0x00, 0x01, 0x54, 0xf8, 0x00, 0x01, 0x55, 0x10, 0x00, 0x01, 0x55, 0x28, 0x00, 0x01, 0x55, 0x40, 0x00, 0x01, 0x55, 0x58, 0x00, 0x01, 0x55, 0x70, 0x00, 0x01, 0x55, 0x88, 0x00, 0x01, 0x55, 0xa0, 0x00, 0x01, 0x55, 0xb8, 0x00, 0x01, 0x55, 0xd0, 0x00, 0x01, 0x55, 0xe8, 0x00, 0x01, 0x56, 0x00, 0x00, 0x01, 0x56, 0x18, 0x00, 0x01, 0x56, 0x30, 0x00, 0x01, 0x56, 0x80, 0x00, 0x01, 0x56, 0xc8, 0x00, 0x01, 0x57, 0x60, 0x00, 0x01, 0x57, 0x70, 0x00, 0x01, 0x57, 0x88, 0x00, 0x01, 0x57, 0xa0, 0x00, 0x01, 0x57, 0xb8, 0x00, 0x01, 0x57, 0xd0, 0x00, 0x01, 0x57, 0xe8, 0x00, 0x01, 0x58, 0x00, 0x00, 0x01, 0x58, 0x18, 0x00, 0x01, 0x58, 0x30, 0x00, 0x01, 0x58, 0x48, 0x00, 0x01, 0x58, 0x60, 0x00, 0x01, 0x58, 0x78, 0x00, 0x01, 0x58, 0x90, 0x00, 0x01, 0x58, 0xa8, 0x00, 0x01, 0x58, 0xc0, 0x00, 0x01, 0x58, 0xd8, 0x00, 0x01, 0x58, 0xf0, 0x00, 0x01, 0x59, 0x08, 0x00, 0x01, 0x59, 0x20, 0x00, 0x01, 0x59, 0x38, 0x00, 0x01, 0x59, 0x50, 0x00, 0x01, 0x59, 0x68, 0x00, 0x01, 0x59, 0x80, 0x00, 0x01, 0x59, 0x98, 0x00, 0x01, 0x59, 0xb0, 0x00, 0x01, 0x59, 0xc8, 0x00, 0x01, 0x59, 0xe0, 0x00, 0x01, 0x59, 0xf8, 0x00, 0x01, 0x5a, 0x10, 0x00, 0x01, 0x5a, 0x28, 0x00, 0x01, 0x5a, 0x40, 0x00, 0x01, 0x5a, 0x58, 0x00, 0x01, 0x5a, 0x70, 0x00, 0x01, 0x5a, 0x88, 0x00, 0x01, 0x5a, 0xa0, 0x00, 0x01, 0x5a, 0xb8, 0x00, 0x01, 0x5a, 0xd0, 0x00, 0x01, 0x5a, 0xe8, 0x00, 0x01, 0x5b, 0x00, 0x00, 0x01, 0x5b, 0x18, 0x00, 0x01, 0x5b, 0x38, 0x00, 0x01, 0x5b, 0x50, 0x00, 0x01, 0x5b, 0x68, 0x00, 0x01, 0x5b, 0x80, 0x00, 0x01, 0x5b, 0x98, 0x00, 0x01, 0x5b, 0xb0, 0x00, 0x01, 0x5b, 0xc8, 0x00, 0x01, 0x5b, 0xe0, 0x00, 0x01, 0x5b, 0xf8, 0x00, 0x01, 0x5c, 0x10, 0x00, 0x01, 0x5c, 0x28, 0x00, 0x01, 0x5c, 0x40, 0x00, 0x01, 0x5c, 0x58, 0x00, 0x01, 0x5c, 0x70, 0x00, 0x01, 0x5c, 0x88, 0x00, 0x01, 0x5c, 0xa0, 0x00, 0x01, 0x5c, 0xb8, 0x00, 0x01, 0x5c, 0xd0, 0x00, 0x01, 0x5c, 0xf0, 0x00, 0x01, 0x5d, 0x08, 0x00, 0x01, 0x5d, 0x20, 0x00, 0x01, 0x5d, 0x38, 0x00, 0x01, 0x5d, 0x50, 0x00, 0x01, 0x5d, 0x68, 0x00, 0x01, 0x5d, 0x80, 0x00, 0x01, 0x5d, 0x98, 0x00, 0x01, 0x5d, 0xb0, 0x00, 0x01, 0x5d, 0xc8, 0x00, 0x01, 0x5d, 0xe0, 0x00, 0x01, 0x5d, 0xf8, 0x00, 0x01, 0x5e, 0x10, 0x00, 0x01, 0x5e, 0x28, 0x00, 0x01, 0x5e, 0x40, 0x00, 0x01, 0x5e, 0x58, 0x00, 0x01, 0x5e, 0x70, 0x00, 0x01, 0x5e, 0x88, 0x00, 0x01, 0x5e, 0xa0, 0x00, 0x01, 0x5e, 0xb8, 0x00, 0x01, 0x5e, 0xd0, 0x00, 0x01, 0x5e, 0xe8, 0x00, 0x01, 0x5f, 0x00, 0x00, 0x01, 0x5f, 0x18, 0x00, 0x01, 0x5f, 0x30, 0x00, 0x01, 0x5f, 0x48, 0x00, 0x01, 0x5f, 0x60, 0x00, 0x01, 0x5f, 0x78, 0x00, 0x01, 0x5f, 0x90, 0x00, 0x01, 0x5f, 0xa8, 0x00, 0x01, 0x5f, 0xc0, 0x00, 0x01, 0x5f, 0xd8, 0x00, 0x01, 0x5f, 0xf0, 0x00, 0x01, 0x60, 0x1c, 0x00, 0x01, 0x60, 0x58, 0x00, 0x01, 0x60, 0x70, 0x00, 0x01, 0x60, 0x88, 0x00, 0x01, 0x60, 0xa0, 0x00, 0x01, 0x60, 0xb8, 0x00, 0x01, 0x60, 0xd0, 0x00, 0x01, 0x60, 0xe8, 0x00, 0x01, 0x61, 0x00, 0x00, 0x01, 0x61, 0x18, 0x00, 0x01, 0x61, 0x30, 0x00, 0x01, 0x61, 0x48, 0x00, 0x01, 0x61, 0x60, 0x00, 0x01, 0x61, 0x78, 0x00, 0x01, 0x61, 0x94, 0x00, 0x01, 0x61, 0xb0, 0x00, 0x01, 0x61, 0xc8, 0x00, 0x01, 0x61, 0xe0, 0x00, 0x01, 0x61, 0xf8, 0x00, 0x01, 0x62, 0x10, 0x00, 0x01, 0x62, 0x28, 0x00, 0x01, 0x62, 0x40, 0x00, 0x01, 0x62, 0x58, 0x00, 0x01, 0x62, 0x70, 0x00, 0x01, 0x62, 0x8c, 0x00, 0x01, 0x62, 0xa8, 0x00, 0x01, 0x62, 0xc0, 0x00, 0x01, 0x62, 0xd8, 0x00, 0x01, 0x62, 0xf4, 0x00, 0x01, 0x63, 0x10, 0x00, 0x01, 0x63, 0x28, 0x00, 0x01, 0x63, 0x40, 0x00, 0x01, 0x63, 0x58, 0x00, 0x01, 0x63, 0x70, 0x00, 0x01, 0x63, 0x88, 0x00, 0x01, 0x63, 0xa0, 0x00, 0x01, 0x63, 0xb8, 0x00, 0x01, 0x63, 0xd0, 0x00, 0x01, 0x63, 0xec, 0x00, 0x01, 0x64, 0x08, 0x00, 0x01, 0x64, 0x20, 0x00, 0x01, 0x64, 0x38, 0x00, 0x01, 0x64, 0x54, 0x00, 0x01, 0x64, 0x70, 0x00, 0x01, 0x64, 0x8c, 0x00, 0x01, 0x64, 0xa8, 0x00, 0x01, 0x64, 0xc0, 0x00, 0x01, 0x64, 0xd8, 0x00, 0x01, 0x64, 0xf0, 0x00, 0x01, 0x65, 0x08, 0x00, 0x01, 0x65, 0x20, 0x00, 0x01, 0x65, 0x38, 0x00, 0x01, 0x65, 0x50, 0x00, 0x01, 0x65, 0x68, 0x00, 0x01, 0x65, 0x84, 0x00, 0x01, 0x65, 0xa0, 0x00, 0x01, 0x65, 0xb8, 0x00, 0x01, 0x65, 0xd0, 0x00, 0x01, 0x65, 0xec, 0x00, 0x01, 0x66, 0x08, 0x00, 0x01, 0x66, 0x24, 0x00, 0x01, 0x66, 0x40, 0x00, 0x01, 0x66, 0x58, 0x00, 0x01, 0x66, 0x70, 0x00, 0x01, 0x66, 0x88, 0x00, 0x01, 0x66, 0xa0, 0x00, 0x01, 0x66, 0xb8, 0x00, 0x01, 0x66, 0xd0, 0x00, 0x01, 0x66, 0xe8, 0x00, 0x01, 0x67, 0x00, 0x00, 0x01, 0x67, 0x18, 0x00, 0x01, 0x67, 0x30, 0x00, 0x01, 0x67, 0x4c, 0x00, 0x01, 0x67, 0x68, 0x00, 0x01, 0x67, 0x80, 0x00, 0x01, 0x67, 0x98, 0x00, 0x01, 0x67, 0xb0, 0x00, 0x01, 0x67, 0xc8, 0x00, 0x01, 0x67, 0xe0, 0x00, 0x01, 0x67, 0xf8, 0x00, 0x01, 0x68, 0x10, 0x00, 0x01, 0x68, 0x28, 0x00, 0x01, 0x68, 0x44, 0x00, 0x01, 0x68, 0x5c, 0x00, 0x01, 0x68, 0x78, 0x00, 0x01, 0x68, 0x94, 0x00, 0x01, 0x68, 0xac, 0x00, 0x01, 0x68, 0xc4, 0x00, 0x01, 0x68, 0xdc, 0x00, 0x01, 0x68, 0xf4, 0x00, 0x01, 0x69, 0x0c, 0x00, 0x01, 0x69, 0x24, 0x00, 0x01, 0x69, 0x3c, 0x00, 0x01, 0x69, 0x54, 0x00, 0x01, 0x69, 0x6c, 0x00, 0x01, 0x69, 0x88, 0x00, 0x01, 0x69, 0xa0, 0x00, 0x01, 0x69, 0xb8, 0x00, 0x01, 0x69, 0xd4, 0x00, 0x01, 0x69, 0xf0, 0x00, 0x01, 0x6a, 0x0c, 0x00, 0x01, 0x6a, 0x28, 0x00, 0x01, 0x6a, 0x40, 0x00, 0x01, 0x6a, 0x50, 0x00, 0x01, 0x6a, 0x68, 0x00, 0x01, 0x6a, 0x78, 0x00, 0x01, 0x6a, 0x90, 0x00, 0x01, 0x6a, 0xa0, 0x00, 0x01, 0x6a, 0xb8, 0x00, 0x01, 0x6a, 0xc8, 0x00, 0x01, 0x6a, 0xe0, 0x00, 0x01, 0x6a, 0xf0, 0x00, 0x01, 0x6b, 0x08, 0x00, 0x01, 0x6b, 0x18, 0x00, 0x01, 0x6b, 0x30, 0x00, 0x01, 0x6b, 0x40, 0x00, 0x01, 0x6b, 0x58, 0x00, 0x01, 0x6b, 0x70, 0x00, 0x01, 0x6b, 0x88, 0x00, 0x01, 0x6b, 0xa0, 0x00, 0x01, 0x6b, 0xb8, 0x00, 0x01, 0x6b, 0xd0, 0x00, 0x01, 0x6b, 0xe8, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x18, 0x00, 0x01, 0x6c, 0x30, 0x00, 0x01, 0x6c, 0x48, 0x00, 0x01, 0x6c, 0x60, 0x00, 0x01, 0x6c, 0x78, 0x00, 0x01, 0x6c, 0x90, 0x00, 0x01, 0x6c, 0xa8, 0x00, 0x01, 0x6c, 0xc0, 0x00, 0x01, 0x6c, 0xd8, 0x00, 0x01, 0x6c, 0xf0, 0x00, 0x01, 0x6d, 0x08, 0x00, 0x01, 0x6d, 0x20, 0x00, 0x01, 0x6d, 0x38, 0x00, 0x01, 0x6d, 0x50, 0x00, 0x01, 0x6d, 0x68, 0x00, 0x01, 0x6d, 0x80, 0x00, 0x01, 0x6d, 0x98, 0x00, 0x01, 0x6d, 0xb0, 0x00, 0x01, 0x6d, 0xc8, 0x00, 0x01, 0x6d, 0xe0, 0x00, 0x01, 0x6d, 0xf8, 0x00, 0x01, 0x6e, 0x10, 0x00, 0x01, 0x6e, 0x28, 0x00, 0x01, 0x6e, 0x40, 0x00, 0x01, 0x6e, 0x58, 0x00, 0x01, 0x6e, 0x70, 0x00, 0x01, 0x6e, 0x88, 0x00, 0x01, 0x6e, 0xa0, 0x00, 0x01, 0x6e, 0xb8, 0x00, 0x01, 0x6e, 0xd0, 0x00, 0x01, 0x6e, 0xe8, 0x00, 0x01, 0x6f, 0x00, 0x00, 0x01, 0x6f, 0x18, 0x00, 0x01, 0x6f, 0x30, 0x00, 0x01, 0x6f, 0x48, 0x00, 0x01, 0x6f, 0x60, 0x00, 0x01, 0x6f, 0x78, 0x00, 0x01, 0x6f, 0x90, 0x00, 0x01, 0x6f, 0xa8, 0x00, 0x01, 0x6f, 0xc0, 0x00, 0x01, 0x6f, 0xd8, 0x00, 0x01, 0x6f, 0xf0, 0x00, 0x01, 0x70, 0x08, 0x00, 0x01, 0x70, 0x20, 0x00, 0x01, 0x70, 0x38, 0x00, 0x01, 0x70, 0x50, 0x00, 0x01, 0x70, 0x68, 0x00, 0x01, 0x70, 0x80, 0x00, 0x01, 0x70, 0x98, 0x00, 0x01, 0x70, 0xb0, 0x00, 0x01, 0x70, 0xc0, 0x00, 0x01, 0x70, 0xd8, 0x00, 0x01, 0x70, 0xe8, 0x00, 0x01, 0x70, 0xf8, 0x00, 0x01, 0x71, 0x20, 0x00, 0x01, 0x71, 0x30, 0x00, 0x01, 0x71, 0x48, 0x00, 0x01, 0x71, 0x60, 0x00, 0x01, 0x71, 0x78, 0x00, 0x01, 0x71, 0x90, 0x00, 0x01, 0x71, 0xa8, 0x00, 0x01, 0x71, 0xc0, 0x00, 0x01, 0x71, 0xdc, 0x00, 0x01, 0x71, 0xec, 0x00, 0x01, 0x72, 0x08, 0x00, 0x01, 0x72, 0x18, 0x00, 0x01, 0x72, 0x30, 0x00, 0x01, 0x72, 0x4c, 0x00, 0x01, 0x72, 0x64, 0x00, 0x01, 0x72, 0x7c, 0x00, 0x01, 0x72, 0x94, 0x00, 0x01, 0x72, 0xac, 0x00, 0x01, 0x72, 0xc4, 0x00, 0x01, 0x72, 0xd4, 0x00, 0x01, 0x72, 0xec, 0x00, 0x01, 0x73, 0x04, 0x00, 0x01, 0x73, 0x1c, 0x00, 0x01, 0x73, 0x34, 0x00, 0x01, 0x73, 0x50, 0x00, 0x01, 0x73, 0x60, 0x00, 0x01, 0x73, 0x7c, 0x00, 0x01, 0x73, 0x94, 0x00, 0x01, 0x73, 0xac, 0x00, 0x01, 0x73, 0xc4, 0x00, 0x01, 0x73, 0xdc, 0x00, 0x01, 0x73, 0xf4, 0x00, 0x01, 0x74, 0x04, 0x00, 0x01, 0x74, 0x1c, 0x00, 0x01, 0x74, 0x34, 0x00, 0x01, 0x74, 0x4c, 0x00, 0x01, 0x74, 0x64, 0x00, 0x01, 0x74, 0x7c, 0x00, 0x01, 0x74, 0x94, 0x00, 0x01, 0x74, 0xb0, 0x00, 0x01, 0x74, 0xc0, 0x00, 0x01, 0x74, 0xdc, 0x00, 0x01, 0x74, 0xf4, 0x00, 0x01, 0x75, 0x04, 0x00, 0x01, 0x75, 0x14, 0x00, 0x01, 0x75, 0x2c, 0x00, 0x01, 0x75, 0x44, 0x00, 0x01, 0x75, 0x5c, 0x00, 0x01, 0x75, 0x74, 0x00, 0x01, 0x75, 0x8c, 0x00, 0x01, 0x75, 0xa8, 0x00, 0x01, 0x75, 0xb8, 0x00, 0x01, 0x75, 0xd4, 0x00, 0x01, 0x75, 0xe4, 0x00, 0x01, 0x75, 0xfc, 0x00, 0x01, 0x76, 0x0c, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x30, 0x00, 0x01, 0x76, 0x4c, 0x00, 0x01, 0x76, 0x5c, 0x00, 0x01, 0x76, 0x78, 0x00, 0x01, 0x76, 0x94, 0x00, 0x01, 0x76, 0xb0, 0x00, 0x01, 0x76, 0xcc, 0x00, 0x01, 0x76, 0xe4, 0x00, 0x01, 0x76, 0xfc, 0x00, 0x01, 0x77, 0x20, 0x00, 0x01, 0x77, 0x40, 0x00, 0x01, 0x77, 0x60, 0x00, 0x01, 0x77, 0x84, 0x00, 0x01, 0x77, 0xbc, 0x00, 0x01, 0x77, 0xf0, 0x00, 0x01, 0x78, 0x24, 0x00, 0x01, 0x78, 0x58, 0x00, 0x01, 0x78, 0x88, 0x00, 0x01, 0x78, 0xd0, 0x00, 0x01, 0x79, 0x00, 0x00, 0x01, 0x79, 0x1c, 0x00, 0x01, 0x79, 0x34, 0x00, 0x01, 0x79, 0x58, 0x00, 0x01, 0x79, 0x88, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x79, 0xa0, 0x00, 0x01, 0x7a, 0x7c, 0x00, 0x01, 0x7b, 0x8c, 0x00, 0x01, 0x7b, 0xac, 0x00, 0x01, 0x7b, 0xc4, 0x00, 0x01, 0x7b, 0xe4, 0x00, 0x01, 0x7c, 0x00, 0x00, 0x01, 0x7c, 0x18, 0x00, 0x01, 0x7c, 0x38, 0x00, 0x01, 0x7c, 0x5c, 0x00, 0x01, 0x7c, 0x84, 0x00, 0x01, 0x7c, 0xb0, 0x00, 0x01, 0x7c, 0xe0, 0x00, 0x01, 0x7c, 0xfc, 0x00, 0x01, 0x7d, 0x78, 0x00, 0x01, 0x7d, 0x8c, 0x00, 0x01, 0x7d, 0xc8, 0x00, 0x01, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x30, 0x00, 0x01, 0x7e, 0x54, 0x00, 0x01, 0x7e, 0x70, 0x00, 0x01, 0x7e, 0x8c, 0x00, 0x01, 0x7e, 0xbc, 0x00, 0x01, 0x7e, 0xec, 0x00, 0x01, 0x7f, 0x04, 0x00, 0x01, 0x7f, 0x1c, 0x00, 0x01, 0x7f, 0x38, 0x00, 0x01, 0x7f, 0x6c, 0x00, 0x01, 0x7f, 0xa0, 0x00, 0x01, 0x7f, 0xd0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x14, 0x00, 0x01, 0x80, 0x44, 0x00, 0x01, 0x80, 0x5c, 0x00, 0x01, 0x80, 0x78, 0x00, 0x01, 0x80, 0x9c, 0x00, 0x01, 0x80, 0xfc, 0x00, 0x01, 0x81, 0x10, 0x00, 0x01, 0x81, 0x64, 0x00, 0x01, 0x81, 0x98, 0x00, 0x01, 0x81, 0xc0, 0x00, 0x01, 0x82, 0x00, 0x00, 0x01, 0x82, 0x4c, 0x00, 0x01, 0x82, 0x70, 0x00, 0x01, 0x82, 0xac, 0x00, 0x01, 0x83, 0x10, 0x00, 0x01, 0x83, 0x40, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0x7c, 0x00, 0x01, 0x83, 0xd0, 0x00, 0x01, 0x83, 0xf4, 0x00, 0x01, 0x84, 0x2c, 0x00, 0x01, 0x84, 0x90, 0x00, 0x01, 0x85, 0x20, 0x00, 0x01, 0x85, 0x48, 0x00, 0x01, 0x85, 0xf8, 0x00, 0x01, 0x86, 0x84, 0x00, 0x01, 0x86, 0xb8, 0x00, 0x01, 0x86, 0xd4, 0x00, 0x01, 0x86, 0xfc, 0x00, 0x01, 0x87, 0x34, 0x00, 0x01, 0x87, 0x70, 0x00, 0x01, 0x87, 0xb4, 0x00, 0x01, 0x87, 0xc8, 0x00, 0x01, 0x87, 0xdc, 0x00, 0x01, 0x87, 0xf0, 0x00, 0x01, 0x88, 0x04, 0x00, 0x01, 0x88, 0x18, 0x00, 0x01, 0x88, 0x2c, 0x00, 0x01, 0x88, 0x40, 0x00, 0x01, 0x88, 0x54, 0x00, 0x01, 0x88, 0x68, 0x00, 0x01, 0x88, 0x7c, 0x00, 0x01, 0x88, 0x90, 0x00, 0x01, 0x88, 0xa4, 0x00, 0x01, 0x88, 0xb8, 0x00, 0x01, 0x88, 0xcc, 0x00, 0x01, 0x88, 0xe0, 0x00, 0x01, 0x88, 0xf4, 0x00, 0x01, 0x89, 0x08, 0x00, 0x01, 0x89, 0x1c, 0x00, 0x01, 0x89, 0x30, 0x00, 0x01, 0x89, 0x44, 0x00, 0x01, 0x89, 0x58, 0x00, 0x01, 0x89, 0x6c, 0x00, 0x01, 0x89, 0x80, 0x00, 0x01, 0x89, 0x94, 0x00, 0x01, 0x89, 0xa8, 0x00, 0x01, 0x89, 0xbc, 0x00, 0x01, 0x89, 0xd0, 0x00, 0x01, 0x89, 0xe4, 0x00, 0x01, 0x8a, 0x58, 0x00, 0x01, 0x8b, 0x08, 0x00, 0x01, 0x8b, 0x98, 0x00, 0x01, 0x8b, 0xd8, 0x00, 0x01, 0x8c, 0x40, 0x00, 0x01, 0x8c, 0xc4, 0x00, 0x01, 0x8d, 0x48, 0x00, 0x01, 0x8e, 0x2c, 0x00, 0x01, 0x8e, 0xf8, 0x00, 0x01, 0x8f, 0xa4, 0x00, 0x01, 0x90, 0x04, 0x00, 0x01, 0x90, 0x1c, 0x00, 0x01, 0x90, 0xb4, 0x00, 0x01, 0x90, 0xfc, 0x00, 0x01, 0x91, 0x54, 0x00, 0x01, 0x92, 0xe0, 0x00, 0x01, 0x93, 0x7c, 0x00, 0x01, 0x94, 0x14, 0x00, 0x01, 0x94, 0xa8, 0x00, 0x01, 0x95, 0x14, 0x00, 0x01, 0x95, 0xb4, 0x00, 0x01, 0x96, 0x44, 0x00, 0x01, 0x96, 0x78, 0x00, 0x01, 0x96, 0xf8, 0x00, 0x01, 0x97, 0x60, 0x00, 0x01, 0x97, 0x84, 0x00, 0x01, 0x97, 0xa4, 0x00, 0x01, 0x97, 0xcc, 0x00, 0x01, 0x97, 0xf4, 0x00, 0x01, 0x98, 0x2c, 0x00, 0x01, 0x98, 0x70, 0x00, 0x01, 0x98, 0xa8, 0x00, 0x01, 0x99, 0x68, 0x00, 0x01, 0x9a, 0x40, 0x00, 0x01, 0x9a, 0xb8, 0x00, 0x01, 0x9a, 0xd0, 0x00, 0x01, 0x9b, 0x5c, 0x00, 0x01, 0x9b, 0xf8, 0x00, 0x01, 0x9c, 0x90, 0x00, 0x01, 0x9c, 0xa0, 0x00, 0x01, 0x9c, 0xb4, 0x00, 0x01, 0x9c, 0xcc, 0x00, 0x01, 0x9e, 0x0c, 0x00, 0x01, 0x9e, 0xfc, 0x00, 0x01, 0x9f, 0x4c, 0x00, 0x01, 0x9f, 0xa8, 0x00, 0x01, 0xa0, 0x08, 0x00, 0x01, 0xa0, 0xb4, 0x00, 0x01, 0xa1, 0x48, 0x00, 0x01, 0xa2, 0x24, 0x00, 0x01, 0xa2, 0xa4, 0x00, 0x01, 0xa3, 0x20, 0x00, 0x01, 0xa3, 0x64, 0x00, 0x01, 0xa3, 0xf4, 0x00, 0x01, 0xa4, 0x98, 0x00, 0x01, 0xa5, 0x4c, 0x00, 0x01, 0xa5, 0xbc, 0x00, 0x01, 0xa6, 0x58, 0x00, 0x01, 0xa7, 0x70, 0x00, 0x01, 0xa8, 0x6c, 0x00, 0x01, 0xa9, 0x1c, 0x00, 0x01, 0xa9, 0x8c, 0x00, 0x01, 0xaa, 0x34, 0x00, 0x01, 0xaa, 0xd4, 0x00, 0x01, 0xab, 0x34, 0x00, 0x01, 0xab, 0x80, 0x00, 0x01, 0xab, 0xd0, 0x00, 0x01, 0xac, 0x10, 0x00, 0x01, 0xac, 0x7c, 0x00, 0x01, 0xac, 0x8c, 0x00, 0x01, 0xac, 0x9c, 0x00, 0x01, 0xad, 0x90, 0x00, 0x01, 0xad, 0xc4, 0x00, 0x01, 0xad, 0xd4, 0x00, 0x01, 0xad, 0xe4, 0x00, 0x01, 0xae, 0xd8, 0x00, 0x01, 0xaf, 0x9c, 0x00, 0x01, 0xb0, 0x24, 0x00, 0x01, 0xb0, 0xa0, 0x00, 0x01, 0xb1, 0x68, 0x00, 0x01, 0xb2, 0x48, 0x00, 0x01, 0xb2, 0x74, 0x00, 0x01, 0xb3, 0xb8, 0x00, 0x01, 0xb4, 0x0c, 0x00, 0x01, 0xb4, 0xb0, 0x00, 0x01, 0xb5, 0x40, 0x00, 0x01, 0xb5, 0xcc, 0x00, 0x01, 0xb6, 0x44, 0x00, 0x01, 0xb6, 0x8c, 0x00, 0x01, 0xb6, 0xfc, 0x00, 0x01, 0xb7, 0x7c, 0x00, 0x01, 0xb8, 0x10, 0x00, 0x01, 0xb8, 0x84, 0x00, 0x01, 0xb8, 0xb4, 0x00, 0x01, 0xb8, 0xf8, 0x00, 0x01, 0xb9, 0x4c, 0x00, 0x01, 0xb9, 0xb4, 0x00, 0x01, 0xb9, 0xd4, 0x00, 0x01, 0xb9, 0xf8, 0x00, 0x01, 0xba, 0x24, 0x00, 0x01, 0xba, 0xa8, 0x00, 0x01, 0xbb, 0x54, 0x00, 0x01, 0xbb, 0xf4, 0x00, 0x01, 0xbc, 0x2c, 0x00, 0x01, 0xbc, 0x94, 0x00, 0x01, 0xbd, 0x2c, 0x00, 0x01, 0xbd, 0x58, 0x00, 0x01, 0xbd, 0x78, 0x00, 0x01, 0xbd, 0x98, 0x00, 0x01, 0xbd, 0xc0, 0x00, 0x01, 0xbd, 0xe0, 0x00, 0x01, 0xbe, 0x00, 0x00, 0x01, 0xbe, 0x20, 0x00, 0x01, 0xbe, 0x40, 0x00, 0x01, 0xbe, 0x60, 0x00, 0x01, 0xbe, 0x80, 0x00, 0x01, 0xbe, 0xa0, 0x00, 0x01, 0xbe, 0xc0, 0x00, 0x01, 0xbe, 0xe0, 0x00, 0x01, 0xbf, 0x00, 0x00, 0x01, 0xbf, 0x20, 0x00, 0x01, 0xbf, 0x40, 0x00, 0x01, 0xbf, 0x58, 0x00, 0x01, 0xbf, 0x68, 0x00, 0x01, 0xbf, 0x80, 0x00, 0x01, 0xbf, 0xa0, 0x00, 0x01, 0xbf, 0xb8, 0x00, 0x01, 0xbf, 0xc8, 0x00, 0x01, 0xbf, 0xe0, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x01, 0xc0, 0x28, 0x00, 0x01, 0xc0, 0x40, 0x00, 0x01, 0xc0, 0x50, 0x00, 0x01, 0xc0, 0x68, 0x00, 0x01, 0xc0, 0x88, 0x00, 0x01, 0xc0, 0x98, 0x00, 0x01, 0xc0, 0xa8, 0x00, 0x01, 0xc0, 0xb8, 0x00, 0x01, 0xc0, 0xc8, 0x00, 0x01, 0xc0, 0xd8, 0x00, 0x01, 0xc0, 0xf0, 0x00, 0x01, 0xc1, 0x10, 0x00, 0x01, 0xc1, 0x28, 0x00, 0x01, 0xc1, 0x38, 0x00, 0x01, 0xc1, 0x50, 0x00, 0x01, 0xc1, 0x70, 0x00, 0x01, 0xc1, 0x98, 0x00, 0x01, 0xc1, 0xb0, 0x00, 0x01, 0xc1, 0xc0, 0x00, 0x01, 0xc1, 0xd8, 0x00, 0x01, 0xc1, 0xf8, 0x00, 0x01, 0xc2, 0x08, 0x00, 0x01, 0xc2, 0x18, 0x00, 0x01, 0xc2, 0x28, 0x00, 0x01, 0xc2, 0x38, 0x00, 0x01, 0xc2, 0xbc, 0x00, 0x01, 0xc3, 0x38, 0x00, 0x01, 0xc4, 0x14, 0x00, 0x01, 0xc4, 0x24, 0x00, 0x01, 0xc4, 0x34, 0x00, 0x01, 0xc4, 0x9c, 0x00, 0x01, 0xc4, 0xbc, 0x00, 0x01, 0xc4, 0xec, 0x00, 0x01, 0xc5, 0x1c, 0x00, 0x01, 0xc5, 0x4c, 0x00, 0x01, 0xc5, 0x7c, 0x00, 0x01, 0xc5, 0xc0, 0x00, 0x01, 0xc6, 0x04, 0x00, 0x01, 0xc6, 0x34, 0x00, 0x01, 0xc6, 0x64, 0x00, 0x01, 0xc6, 0x94, 0x00, 0x01, 0xc6, 0xc4, 0x00, 0x01, 0xc7, 0x10, 0x00, 0x01, 0xc7, 0x5c, 0x00, 0x01, 0xc8, 0x04, 0x00, 0x01, 0xc8, 0xac, 0x00, 0x01, 0xc8, 0xf8, 0x00, 0x01, 0xc9, 0x44, 0x00, 0x01, 0xc9, 0x90, 0x00, 0x01, 0xc9, 0xdc, 0x00, 0x01, 0xca, 0x24, 0x00, 0x01, 0xca, 0x70, 0x00, 0x01, 0xca, 0xac, 0x00, 0x01, 0xca, 0xe8, 0x00, 0x01, 0xcb, 0x24, 0x00, 0x01, 0xcb, 0x60, 0x00, 0x01, 0xcb, 0xb4, 0x00, 0x01, 0xcc, 0x34, 0x00, 0x01, 0xcc, 0xc0, 0x00, 0x01, 0xcd, 0x84, 0x00, 0x01, 0xce, 0x48, 0x00, 0x01, 0xcf, 0x5c, 0x00, 0x01, 0xcf, 0xbc, 0x00, 0x01, 0xd0, 0x04, 0x00, 0x01, 0xd0, 0x3c, 0x00, 0x01, 0xd0, 0x74, 0x00, 0x01, 0xd0, 0xac, 0x00, 0x01, 0xd0, 0xe4, 0x00, 0x01, 0xd1, 0x1c, 0x00, 0x01, 0xd1, 0x54, 0x00, 0x01, 0xd1, 0xd4, 0x00, 0x01, 0xd2, 0x54, 0x00, 0x01, 0xd2, 0x90, 0x00, 0x01, 0xd2, 0xfc, 0x00, 0x01, 0xd3, 0xa4, 0x00, 0x01, 0xd4, 0x4c, 0x00, 0x01, 0xd4, 0x70, 0x00, 0x01, 0xd4, 0x98, 0x00, 0x01, 0xd4, 0xc0, 0x00, 0x01, 0xd4, 0xe8, 0x00, 0x01, 0xd5, 0x10, 0x00, 0x01, 0xd5, 0x38, 0x00, 0x01, 0xd5, 0x5c, 0x00, 0x01, 0xd5, 0x80, 0x00, 0x01, 0xd5, 0x9c, 0x00, 0x01, 0xd5, 0xb8, 0x00, 0x01, 0xd5, 0xd4, 0x00, 0x01, 0xd6, 0x1c, 0x00, 0x01, 0xd6, 0x64, 0x00, 0x01, 0xd6, 0xac, 0x00, 0x01, 0xd6, 0xf4, 0x00, 0x01, 0xd7, 0x10, 0x00, 0x01, 0xd7, 0x2c, 0x00, 0x01, 0xd7, 0x94, 0x00, 0x01, 0xd8, 0x14, 0x00, 0x01, 0xd8, 0x7c, 0x00, 0x01, 0xd8, 0xbc, 0x00, 0x01, 0xd8, 0xfc, 0x00, 0x01, 0xd9, 0x3c, 0x00, 0x01, 0xd9, 0x7c, 0x00, 0x01, 0xd9, 0xd8, 0x00, 0x01, 0xda, 0x34, 0x00, 0x01, 0xda, 0x74, 0x00, 0x01, 0xda, 0xb4, 0x00, 0x01, 0xda, 0xf4, 0x00, 0x01, 0xdb, 0x34, 0x00, 0x01, 0xdb, 0x74, 0x00, 0x01, 0xdb, 0xb4, 0x00, 0x01, 0xdc, 0x10, 0x00, 0x01, 0xdc, 0x6c, 0x00, 0x01, 0xdc, 0xc4, 0x00, 0x01, 0xdd, 0x1c, 0x00, 0x01, 0xdd, 0x60, 0x00, 0x01, 0xdd, 0xa8, 0x00, 0x01, 0xdd, 0xf0, 0x00, 0x01, 0xde, 0x3c, 0x00, 0x01, 0xde, 0x78, 0x00, 0x01, 0xde, 0xb4, 0x00, 0x01, 0xde, 0xf8, 0x00, 0x01, 0xdf, 0x38, 0x00, 0x01, 0xdf, 0x78, 0x00, 0x01, 0xdf, 0xb4, 0x00, 0x01, 0xe0, 0x10, 0x00, 0x01, 0xe0, 0x60, 0x00, 0x01, 0xe0, 0xc0, 0x00, 0x01, 0xe1, 0x1c, 0x00, 0x01, 0xe1, 0x7c, 0x00, 0x01, 0xe1, 0xf0, 0x00, 0x01, 0xe2, 0x44, 0x00, 0x01, 0xe2, 0x88, 0x00, 0x01, 0xe2, 0xcc, 0x00, 0x01, 0xe3, 0x20, 0x00, 0x01, 0xe3, 0xfc, 0x00, 0x01, 0xe4, 0x18, 0x00, 0x01, 0xe4, 0x78, 0x00, 0x01, 0xe4, 0xbc, 0x00, 0x01, 0xe5, 0x04, 0x00, 0x01, 0xe5, 0x60, 0x00, 0x01, 0xe5, 0xb8, 0x00, 0x01, 0xe6, 0x14, 0x00, 0x01, 0xe6, 0x84, 0x00, 0x01, 0xe6, 0xb8, 0x00, 0x01, 0xe6, 0xec, 0x00, 0x01, 0xe7, 0x3c, 0x00, 0x01, 0xe7, 0x74, 0x00, 0x01, 0xe7, 0xd8, 0x00, 0x01, 0xe8, 0x6c, 0x00, 0x01, 0xe8, 0xa0, 0x00, 0x01, 0xe9, 0x08, 0x00, 0x01, 0xe9, 0xc8, 0x00, 0x01, 0xe9, 0xf4, 0x00, 0x01, 0xea, 0x24, 0x00, 0x01, 0xea, 0x88, 0x00, 0x01, 0xeb, 0x2c, 0x00, 0x01, 0xeb, 0x80, 0x00, 0x01, 0xeb, 0xe4, 0x00, 0x01, 0xec, 0x88, 0x00, 0x01, 0xec, 0xdc, 0x00, 0x01, 0xec, 0xf8, 0x00, 0x01, 0xed, 0x20, 0x00, 0x01, 0xed, 0x48, 0x00, 0x01, 0xed, 0x80, 0x00, 0x01, 0xed, 0x9c, 0x00, 0x01, 0xed, 0xd8, 0x00, 0x01, 0xee, 0x14, 0x00, 0x01, 0xee, 0x24, 0x00, 0x01, 0xee, 0x38, 0x00, 0x01, 0xee, 0x84, 0x00, 0x01, 0xee, 0x98, 0x00, 0x01, 0xee, 0xa8, 0x00, 0x01, 0xee, 0xdc, 0x00, 0x01, 0xee, 0xf4, 0x00, 0x01, 0xef, 0x0c, 0x00, 0x01, 0xef, 0xa4, 0x00, 0x01, 0xf0, 0x5c, 0x00, 0x01, 0xf0, 0x7c, 0x00, 0x01, 0xf0, 0xa0, 0x00, 0x01, 0xf1, 0x0c, 0x00, 0x01, 0xf1, 0x84, 0x00, 0x01, 0xf1, 0xa0, 0x00, 0x01, 0xf1, 0xd4, 0x00, 0x01, 0xf1, 0xfc, 0x00, 0x01, 0xf2, 0x44, 0x00, 0x01, 0xf2, 0x6c, 0x00, 0x01, 0xf2, 0x94, 0x00, 0x01, 0xf2, 0xd4, 0x00, 0x01, 0xf3, 0x14, 0x00, 0x01, 0xf3, 0x64, 0x00, 0x01, 0xf3, 0x7c, 0x00, 0x01, 0xf3, 0x9c, 0x00, 0x01, 0xf4, 0x68, 0x00, 0x01, 0xf5, 0xa0, 0x00, 0x01, 0xf7, 0x48, 0x00, 0x01, 0xf7, 0xe8, 0x00, 0x01, 0xf8, 0xb0, 0x00, 0x01, 0xf9, 0x78, 0x00, 0x01, 0xf9, 0x9c, 0x00, 0x01, 0xf9, 0xc0, 0x00, 0x01, 0xf9, 0xdc, 0x00, 0x01, 0xfa, 0x08, 0x00, 0x01, 0xfa, 0x20, 0x00, 0x01, 0xfa, 0x54, 0x00, 0x01, 0xfa, 0x84, 0x00, 0x01, 0xfa, 0xa4, 0x00, 0x01, 0xfb, 0x04, 0x00, 0x01, 0xfb, 0x64, 0x00, 0x01, 0xfb, 0xe0, 0x00, 0x01, 0xfc, 0x28, 0x00, 0x01, 0xfc, 0x88, 0x00, 0x01, 0xfc, 0xe8, 0x00, 0x01, 0xfd, 0x54, 0x00, 0x01, 0xfd, 0xbc, 0x00, 0x01, 0xfe, 0x3c, 0x00, 0x01, 0xfe, 0xb0, 0x00, 0x01, 0xff, 0x40, 0x00, 0x01, 0xff, 0xd0, 0x00, 0x02, 0x00, 0x84, 0x00, 0x02, 0x01, 0x24, 0x00, 0x02, 0x01, 0xd4, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x02, 0x03, 0x30, 0x00, 0x02, 0x03, 0x88, 0x00, 0x02, 0x04, 0x40, 0x00, 0x02, 0x04, 0xb4, 0x00, 0x02, 0x04, 0xcc, 0x00, 0x02, 0x04, 0xec, 0x00, 0x02, 0x05, 0x0c, 0x00, 0x02, 0x05, 0x2c, 0x00, 0x02, 0x05, 0x50, 0x00, 0x02, 0x05, 0x70, 0x00, 0x02, 0x05, 0xcc, 0x00, 0x02, 0x06, 0x38, 0x00, 0x02, 0x06, 0x7c, 0x00, 0x02, 0x06, 0xc0, 0x00, 0x02, 0x07, 0x00, 0x00, 0x02, 0x07, 0x4c, 0x00, 0x02, 0x07, 0x90, 0x00, 0x02, 0x08, 0x70, 0x00, 0x02, 0x08, 0xf4, 0x00, 0x02, 0x09, 0x80, 0x00, 0x02, 0x09, 0xcc, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x02, 0x0a, 0x60, 0x00, 0x02, 0x0a, 0xa4, 0x00, 0x02, 0x0a, 0xe0, 0x00, 0x02, 0x0b, 0x18, 0x00, 0x02, 0x0b, 0x60, 0x00, 0x02, 0x0b, 0xa0, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x0c, 0x6c, 0x00, 0x02, 0x0c, 0xb4, 0x00, 0x02, 0x0c, 0xf8, 0x00, 0x02, 0x0d, 0x80, 0x00, 0x02, 0x0d, 0xe8, 0x00, 0x02, 0x0e, 0x3c, 0x00, 0x02, 0x0e, 0x90, 0x00, 0x02, 0x0e, 0xfc, 0x00, 0x02, 0x0f, 0x64, 0x00, 0x02, 0x0f, 0xe4, 0x00, 0x02, 0x10, 0x5c, 0x00, 0x02, 0x11, 0x10, 0x00, 0x02, 0x11, 0xc4, 0x00, 0x02, 0x12, 0x08, 0x00, 0x02, 0x12, 0x50, 0x00, 0x02, 0x12, 0xdc, 0x00, 0x02, 0x13, 0x64, 0x00, 0x02, 0x13, 0xa0, 0x00, 0x02, 0x13, 0xd8, 0x00, 0x02, 0x14, 0x2c, 0x00, 0x02, 0x14, 0x7c, 0x00, 0x02, 0x15, 0x0c, 0x00, 0x02, 0x15, 0x98, 0x00, 0x02, 0x16, 0x08, 0x00, 0x02, 0x16, 0x78, 0x00, 0x02, 0x16, 0xbc, 0x00, 0x02, 0x17, 0x00, 0x00, 0x02, 0x17, 0x68, 0x00, 0x02, 0x17, 0xd0, 0x00, 0x02, 0x18, 0x24, 0x00, 0x02, 0x18, 0x74, 0x00, 0x02, 0x18, 0xf0, 0x00, 0x02, 0x19, 0x70, 0x00, 0x02, 0x19, 0xdc, 0x00, 0x02, 0x1a, 0x48, 0x00, 0x02, 0x1a, 0xa8, 0x00, 0x02, 0x1a, 0xc0, 0x00, 0x02, 0x1b, 0x1c, 0x00, 0x02, 0x1b, 0x44, 0x00, 0x02, 0x1b, 0x6c, 0x00, 0x02, 0x1b, 0xa0, 0x00, 0x02, 0x1b, 0xd4, 0x00, 0x02, 0x1b, 0xfc, 0x00, 0x02, 0x1c, 0x20, 0x00, 0x02, 0x1c, 0xe8, 0x00, 0x02, 0x1d, 0x9c, 0x00, 0x02, 0x1e, 0x68, 0x00, 0x02, 0x1f, 0x20, 0x00, 0x02, 0x1f, 0xd0, 0x00, 0x02, 0x20, 0xb8, 0x00, 0x02, 0x21, 0x9c, 0x00, 0x02, 0x22, 0x5c, 0x00, 0x02, 0x23, 0x10, 0x00, 0x02, 0x23, 0x60, 0x00, 0x02, 0x23, 0x9c, 0x00, 0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x38, 0x00, 0x02, 0x24, 0x5c, 0x00, 0x02, 0x24, 0x80, 0x00, 0x02, 0x24, 0xa8, 0x00, 0x02, 0x24, 0xcc, 0x00, 0x02, 0x24, 0xf0, 0x00, 0x02, 0x25, 0x20, 0x00, 0x02, 0x25, 0x50, 0x00, 0x02, 0x25, 0x80, 0x00, 0x02, 0x25, 0xc0, 0x00, 0x02, 0x25, 0xfc, 0x00, 0x02, 0x26, 0x40, 0x00, 0x02, 0x26, 0x9c, 0x00, 0x02, 0x26, 0xf0, 0x00, 0x02, 0x27, 0x58, 0x00, 0x02, 0x27, 0xdc, 0x00, 0x02, 0x28, 0x64, 0x00, 0x02, 0x28, 0x94, 0x00, 0x02, 0x28, 0xc0, 0x00, 0x02, 0x28, 0xf8, 0x00, 0x02, 0x29, 0x30, 0x00, 0x02, 0x29, 0x9c, 0x00, 0x02, 0x2a, 0x08, 0x00, 0x02, 0x2a, 0x58, 0x00, 0x02, 0x2a, 0x9c, 0x00, 0x02, 0x2a, 0xc0, 0x00, 0x02, 0x2a, 0xf4, 0x00, 0x02, 0x2b, 0x2c, 0x00, 0x02, 0x2b, 0x60, 0x00, 0x02, 0x2b, 0xb4, 0x00, 0x02, 0x2b, 0xe4, 0x00, 0x02, 0x2c, 0x10, 0x00, 0x02, 0x2c, 0x3c, 0x00, 0x02, 0x2c, 0x80, 0x00, 0x02, 0x2c, 0xc4, 0x00, 0x02, 0x2c, 0xd4, 0x00, 0x02, 0x2c, 0xec, 0x00, 0x02, 0x2d, 0x20, 0x00, 0x02, 0x2d, 0x8c, 0x00, 0x02, 0x2d, 0xd0, 0x00, 0x02, 0x2e, 0x10, 0x00, 0x02, 0x2e, 0x50, 0x00, 0x02, 0x2e, 0x7c, 0x00, 0x02, 0x2e, 0xac, 0x00, 0x02, 0x2f, 0x10, 0x00, 0x02, 0x2f, 0x48, 0x00, 0x02, 0x2f, 0x80, 0x00, 0x02, 0x30, 0x00, 0x00, 0x02, 0x30, 0x80, 0x00, 0x02, 0x30, 0xf8, 0x00, 0x02, 0x31, 0x70, 0x00, 0x02, 0x31, 0xcc, 0x00, 0x02, 0x32, 0x30, 0x00, 0x02, 0x32, 0x68, 0x00, 0x02, 0x32, 0x9c, 0x00, 0x02, 0x33, 0x04, 0x00, 0x02, 0x33, 0x64, 0x00, 0x02, 0x33, 0xbc, 0x00, 0x02, 0x34, 0x10, 0x00, 0x02, 0x34, 0x48, 0x00, 0x02, 0x34, 0x80, 0x00, 0x02, 0x34, 0xd4, 0x00, 0x02, 0x35, 0x28, 0x00, 0x02, 0x35, 0xb8, 0x00, 0x02, 0x36, 0x48, 0x00, 0x02, 0x36, 0xb0, 0x00, 0x02, 0x37, 0x18, 0x00, 0x02, 0x37, 0x64, 0x00, 0x02, 0x37, 0xb0, 0x00, 0x02, 0x38, 0x28, 0x00, 0x02, 0x38, 0xa0, 0x00, 0x02, 0x39, 0x28, 0x00, 0x02, 0x39, 0xb0, 0x00, 0x02, 0x3a, 0x08, 0x00, 0x02, 0x3a, 0x60, 0x00, 0x02, 0x3a, 0xd4, 0x00, 0x02, 0x3b, 0x44, 0x00, 0x02, 0x3b, 0x68, 0x00, 0x02, 0x3b, 0x88, 0x00, 0x02, 0x3b, 0xac, 0x00, 0x02, 0x3b, 0xd0, 0x00, 0x02, 0x3c, 0x44, 0x00, 0x02, 0x3c, 0xa8, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x02, 0x3d, 0x18, 0x00, 0x02, 0x3d, 0x8c, 0x00, 0x02, 0x3d, 0xec, 0x00, 0x02, 0x3e, 0x60, 0x00, 0x02, 0x3e, 0xcc, 0x00, 0x02, 0x3f, 0x40, 0x00, 0x02, 0x3f, 0xa4, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x74, 0x00, 0x02, 0x40, 0xd8, 0x00, 0x02, 0x41, 0x0c, 0x00, 0x02, 0x41, 0x84, 0x00, 0x02, 0x41, 0xb0, 0x00, 0x02, 0x41, 0xe8, 0x00, 0x02, 0x42, 0x18, 0x00, 0x02, 0x42, 0x44, 0x00, 0x02, 0x42, 0x5c, 0x00, 0x02, 0x42, 0x7c, 0x00, 0x02, 0x42, 0xd4, 0x00, 0x02, 0x42, 0xf4, 0x00, 0x02, 0x43, 0x14, 0x00, 0x02, 0x43, 0x34, 0x00, 0x02, 0x43, 0x54, 0x00, 0x02, 0x43, 0x7c, 0x00, 0x02, 0x43, 0xa4, 0x00, 0x02, 0x43, 0xcc, 0x00, 0x02, 0x43, 0xf4, 0x00, 0x02, 0x44, 0x14, 0x00, 0x02, 0x44, 0x64, 0x00, 0x02, 0x45, 0x5c, 0x00, 0x02, 0x45, 0x80, 0x00, 0x02, 0x45, 0xa4, 0x00, 0x02, 0x45, 0xc4, 0x00, 0x02, 0x45, 0xe4, 0x00, 0x02, 0x46, 0x04, 0x00, 0x02, 0x46, 0x5c, 0x00, 0x02, 0x46, 0xb4, 0x00, 0x02, 0x47, 0x00, 0x00, 0x02, 0x47, 0x38, 0x00, 0x02, 0x47, 0xa4, 0x00, 0x02, 0x48, 0x04, 0x00, 0x02, 0x4c, 0xb8, 0x00, 0x02, 0x4d, 0x24, 0x00, 0x02, 0x4d, 0x98, 0x00, 0x02, 0x4d, 0xa8, 0x00, 0x02, 0x4d, 0xb8, 0x00, 0x02, 0x4d, 0xc8, 0x00, 0x02, 0x4d, 0xd8, 0x00, 0x02, 0x4e, 0x08, 0x00, 0x02, 0x4e, 0x54, 0x00, 0x02, 0x4e, 0x98, 0x00, 0x02, 0x4e, 0xd0, 0x00, 0x02, 0x4e, 0xec, 0x00, 0x02, 0x4f, 0x24, 0x00, 0x02, 0x4f, 0x5c, 0x00, 0x02, 0x4f, 0x78, 0x00, 0x02, 0x4f, 0xb0, 0x00, 0x02, 0x4f, 0xd0, 0x00, 0x02, 0x4f, 0xec, 0x00, 0x02, 0x50, 0x10, 0x00, 0x02, 0x50, 0x34, 0x00, 0x02, 0x50, 0x50, 0x00, 0x02, 0x50, 0x70, 0x00, 0x02, 0x50, 0xa4, 0x00, 0x02, 0x50, 0xfc, 0x00, 0x02, 0x51, 0x30, 0x00, 0x02, 0x51, 0x4c, 0x00, 0x02, 0x51, 0x80, 0x00, 0x02, 0x51, 0xd8, 0x00, 0x02, 0x52, 0x0c, 0x00, 0x02, 0x52, 0x28, 0x00, 0x02, 0x52, 0x78, 0x00, 0x02, 0x52, 0xa4, 0x00, 0x02, 0x53, 0x4c, 0x00, 0x02, 0x53, 0x5c, 0x00, 0x02, 0x53, 0xc8, 0x00, 0x02, 0x54, 0x38, 0x00, 0x02, 0x54, 0x60, 0x00, 0x02, 0x54, 0xf4, 0x00, 0x02, 0x55, 0xb8, 0x00, 0x02, 0x56, 0x90, 0x00, 0x02, 0x57, 0x2c, 0x00, 0x02, 0x57, 0xec, 0x00, 0x02, 0x58, 0xc0, 0x00, 0x02, 0x59, 0x4c, 0x00, 0x02, 0x5a, 0x3c, 0x00, 0x02, 0x5b, 0x10, 0x00, 0x02, 0x5b, 0xe0, 0x00, 0x02, 0x5b, 0xfc, 0x00, 0x02, 0x5c, 0x18, 0x00, 0x02, 0x5c, 0x34, 0x00, 0x02, 0x5c, 0x50, 0x00, 0x02, 0x5c, 0x84, 0x00, 0x02, 0x5c, 0xbc, 0x00, 0x02, 0x5c, 0xf4, 0x00, 0x02, 0x5d, 0x30, 0x00, 0x02, 0x5d, 0x68, 0x00, 0x02, 0x5d, 0xa8, 0x00, 0x02, 0x5d, 0xf0, 0x00, 0x02, 0x5e, 0x3c, 0x00, 0x02, 0x5e, 0x60, 0x00, 0x02, 0x5e, 0x84, 0x00, 0x02, 0x5e, 0xa8, 0x00, 0x02, 0x5e, 0xcc, 0x00, 0x02, 0x5e, 0xf0, 0x00, 0x02, 0x5f, 0x14, 0x00, 0x02, 0x5f, 0x38, 0x00, 0x02, 0x5f, 0x5c, 0x00, 0x02, 0x5f, 0x7c, 0x00, 0x02, 0x5f, 0xa0, 0x00, 0x02, 0x5f, 0xc4, 0x00, 0x02, 0x5f, 0xe8, 0x00, 0x02, 0x60, 0x08, 0x00, 0x02, 0x60, 0x28, 0x00, 0x02, 0x60, 0x48, 0x00, 0x02, 0x60, 0x6c, 0x00, 0x02, 0x60, 0x94, 0x00, 0x02, 0x60, 0xbc, 0x00, 0x02, 0x60, 0xe8, 0x00, 0x02, 0x61, 0x14, 0x00, 0x02, 0x61, 0x3c, 0x00, 0x02, 0x61, 0x6c, 0x00, 0x02, 0x61, 0x98, 0x00, 0x02, 0x61, 0xc0, 0x00, 0x02, 0x61, 0xe8, 0x00, 0x02, 0x62, 0x10, 0x00, 0x02, 0x62, 0x3c, 0x00, 0x02, 0x62, 0x68, 0x00, 0x02, 0x62, 0x90, 0x00, 0x02, 0x62, 0xc0, 0x00, 0x02, 0x62, 0xec, 0x00, 0x02, 0x63, 0x14, 0x00, 0x02, 0x63, 0x3c, 0x00, 0x02, 0x63, 0x68, 0x00, 0x02, 0x63, 0x94, 0x00, 0x02, 0x63, 0xbc, 0x00, 0x02, 0x63, 0xe4, 0x00, 0x02, 0x64, 0x10, 0x00, 0x02, 0x64, 0x3c, 0x00, 0x02, 0x64, 0x64, 0x00, 0x02, 0x64, 0x88, 0x00, 0x02, 0x64, 0xb4, 0x00, 0x02, 0x64, 0xe0, 0x00, 0x02, 0x65, 0x08, 0x00, 0x02, 0x65, 0x30, 0x00, 0x02, 0x65, 0x5c, 0x00, 0x02, 0x65, 0x88, 0x00, 0x02, 0x65, 0xb0, 0x00, 0x02, 0x65, 0xe0, 0x00, 0x02, 0x66, 0x14, 0x00, 0x02, 0x66, 0x48, 0x00, 0x02, 0x66, 0x7c, 0x00, 0x02, 0x66, 0xb0, 0x00, 0x02, 0x66, 0xe4, 0x00, 0x02, 0x67, 0x18, 0x00, 0x02, 0x67, 0x50, 0x00, 0x02, 0x67, 0x88, 0x00, 0x02, 0x67, 0xc0, 0x00, 0x02, 0x67, 0xf8, 0x00, 0x02, 0x68, 0x2c, 0x00, 0x02, 0x68, 0x60, 0x00, 0x02, 0x68, 0x94, 0x00, 0x02, 0x68, 0xc8, 0x00, 0x02, 0x68, 0xfc, 0x00, 0x02, 0x69, 0x20, 0x00, 0x02, 0x69, 0x4c, 0x00, 0x02, 0x69, 0x78, 0x00, 0x02, 0x69, 0xa4, 0x00, 0x02, 0x69, 0xcc, 0x00, 0x02, 0x69, 0xf4, 0x00, 0x02, 0x6a, 0x20, 0x00, 0x02, 0x6a, 0x4c, 0x00, 0x02, 0x6a, 0x80, 0x00, 0x02, 0x6a, 0xac, 0x00, 0x02, 0x6a, 0xd8, 0x00, 0x02, 0x6b, 0x0c, 0x00, 0x02, 0x6b, 0x38, 0x00, 0x02, 0x6b, 0x64, 0x00, 0x02, 0x6b, 0x98, 0x00, 0x02, 0x6b, 0xc4, 0x00, 0x02, 0x6b, 0xf0, 0x00, 0x02, 0x6c, 0x24, 0x00, 0x02, 0x6c, 0x54, 0x00, 0x02, 0x6c, 0x88, 0x00, 0x02, 0x6c, 0xcc, 0x00, 0x02, 0x6c, 0xfc, 0x00, 0x02, 0x6d, 0x30, 0x00, 0x02, 0x6d, 0x70, 0x00, 0x02, 0x6d, 0xa4, 0x00, 0x02, 0x6d, 0xd4, 0x00, 0x02, 0x6e, 0x14, 0x00, 0x02, 0x6e, 0x48, 0x00, 0x02, 0x6e, 0x78, 0x00, 0x02, 0x6e, 0xb8, 0x00, 0x02, 0x6f, 0x00, 0x00, 0x02, 0x6f, 0x44, 0x00, 0x02, 0x6f, 0xa0, 0x00, 0x02, 0x6f, 0xd4, 0x00, 0x02, 0x70, 0x0c, 0x00, 0x02, 0x70, 0x3c, 0x00, 0x02, 0x70, 0x70, 0x00, 0x02, 0x70, 0x90, 0x00, 0x02, 0x70, 0xac, 0x00, 0x02, 0x70, 0xec, 0x00, 0x02, 0x71, 0x08, 0x00, 0x02, 0x71, 0x24, 0x00, 0x02, 0x71, 0x40, 0x00, 0x02, 0x71, 0x5c, 0x00, 0x02, 0x71, 0x78, 0x00, 0x02, 0x71, 0x94, 0x00, 0x02, 0x71, 0xb0, 0x00, 0x02, 0x71, 0xcc, 0x00, 0x02, 0x71, 0xf0, 0x00, 0x02, 0x72, 0x18, 0x00, 0x02, 0x72, 0x3c, 0x00, 0x02, 0x72, 0x64, 0x00, 0x02, 0x72, 0x78, 0x00, 0x02, 0x72, 0x94, 0x00, 0x02, 0x72, 0xb0, 0x00, 0x02, 0x72, 0xcc, 0x00, 0x02, 0x72, 0xe8, 0x00, 0x02, 0x73, 0x04, 0x00, 0x02, 0x73, 0x20, 0x00, 0x02, 0x73, 0x3c, 0x00, 0x02, 0x73, 0x58, 0x00, 0x02, 0x73, 0x74, 0x00, 0x02, 0x73, 0x90, 0x00, 0x02, 0x73, 0xac, 0x00, 0x02, 0x73, 0xc8, 0x00, 0x02, 0x73, 0xe4, 0x00, 0x02, 0x74, 0x00, 0x00, 0x02, 0x74, 0x1c, 0x00, 0x02, 0x74, 0x30, 0x00, 0x02, 0x74, 0xe4, 0x00, 0x02, 0x77, 0xf8, 0x00, 0x02, 0x78, 0xa0, 0x00, 0x02, 0x78, 0xb4, 0x00, 0x02, 0x78, 0xc8, 0x00, 0x02, 0x78, 0xe4, 0x00, 0x02, 0x79, 0x00, 0x00, 0x02, 0x79, 0x1c, 0x00, 0x02, 0x79, 0x40, 0x00, 0x02, 0x79, 0x68, 0x00, 0x02, 0x79, 0x8c, 0x00, 0x02, 0x79, 0xb0, 0x00, 0x02, 0x79, 0xcc, 0x00, 0x02, 0x79, 0xf4, 0x00, 0x02, 0x7a, 0x18, 0x00, 0x02, 0x7a, 0x34, 0x00, 0x02, 0x7a, 0x60, 0x00, 0x02, 0x7a, 0xb4, 0x00, 0x02, 0x7a, 0xcc, 0x00, 0x02, 0x7b, 0x24, 0x00, 0x02, 0x7b, 0x84, 0x00, 0x02, 0x7c, 0xc0, 0x00, 0x02, 0x7d, 0x48, 0x00, 0x02, 0x7d, 0xd0, 0x00, 0x02, 0x7f, 0x8c, 0x00, 0x02, 0x7f, 0xa8, 0x00, 0x02, 0x7f, 0xd4, 0x00, 0x02, 0x7f, 0xf0, 0x00, 0x02, 0x80, 0x1c, 0x00, 0x02, 0x80, 0x38, 0x00, 0x02, 0x80, 0x64, 0x00, 0x02, 0x80, 0x84, 0x00, 0x02, 0x80, 0xb4, 0x00, 0x02, 0x80, 0xd0, 0x00, 0x02, 0x80, 0xf8, 0x00, 0x02, 0x81, 0x14, 0x00, 0x02, 0x81, 0x3c, 0x00, 0x02, 0x81, 0x58, 0x00, 0x02, 0x81, 0x84, 0x00, 0x02, 0x81, 0xa0, 0x00, 0x02, 0x81, 0xcc, 0x00, 0x02, 0x81, 0xe8, 0x00, 0x02, 0x82, 0x14, 0x00, 0x02, 0x82, 0x30, 0x00, 0x02, 0x82, 0x5c, 0x00, 0x02, 0x82, 0x78, 0x00, 0x02, 0x82, 0xa4, 0x00, 0x02, 0x82, 0xc0, 0x00, 0x02, 0x82, 0xec, 0x00, 0x02, 0x83, 0x08, 0x00, 0x02, 0x83, 0x34, 0x00, 0x02, 0x83, 0x50, 0x00, 0x02, 0x83, 0x7c, 0x00, 0x02, 0x83, 0x9c, 0x00, 0x02, 0x83, 0xd0, 0x00, 0x02, 0x84, 0x14, 0x00, 0x02, 0x84, 0xa4, 0x00, 0x02, 0x84, 0xd8, 0x00, 0x02, 0x85, 0x40, 0x00, 0x02, 0x86, 0x38, 0x00, 0x02, 0x86, 0xec, 0x00, 0x02, 0x87, 0xa8, 0x00, 0x02, 0x87, 0xf8, 0x00, 0x02, 0x88, 0x50, 0x00, 0x02, 0x88, 0xa8, 0x00, 0x02, 0x89, 0x04, 0x00, 0x02, 0x89, 0x60, 0x00, 0x02, 0x89, 0xc8, 0x00, 0x02, 0x8a, 0x18, 0x00, 0x02, 0x8a, 0x40, 0x00, 0x02, 0x8a, 0x68, 0x00, 0x02, 0x8a, 0xa4, 0x00, 0x02, 0x8b, 0x1c, 0x00, 0x02, 0x8b, 0x70, 0x00, 0x02, 0x8b, 0xc4, 0x00, 0x02, 0x8b, 0xf0, 0x00, 0x02, 0x8c, 0x1c, 0x00, 0x02, 0x8c, 0x48, 0x00, 0x02, 0x8c, 0x78, 0x00, 0x02, 0x8c, 0xbc, 0x00, 0x02, 0x8d, 0x00, 0x00, 0x02, 0x8d, 0x1c, 0x00, 0x02, 0x8d, 0x38, 0x00, 0x02, 0x8d, 0x50, 0x00, 0x02, 0x8d, 0x68, 0x00, 0x02, 0x8d, 0xb0, 0x00, 0x02, 0x8d, 0xdc, 0x00, 0x02, 0x8e, 0x08, 0x00, 0x02, 0x8e, 0x30, 0x00, 0x02, 0x8e, 0x58, 0x00, 0x02, 0x8e, 0x94, 0x00, 0x02, 0x8e, 0xd8, 0x00, 0x02, 0x8f, 0x04, 0x00, 0x02, 0x8f, 0x2c, 0x00, 0x02, 0x8f, 0x94, 0x00, 0x02, 0x8f, 0xd4, 0x00, 0x02, 0x90, 0x14, 0x00, 0x02, 0x90, 0x54, 0x00, 0x02, 0x90, 0x94, 0x00, 0x02, 0x91, 0x14, 0x00, 0x02, 0x91, 0x94, 0x00, 0x02, 0x92, 0x14, 0x00, 0x02, 0x92, 0x94, 0x00, 0x02, 0x92, 0xbc, 0x00, 0x02, 0x92, 0xe4, 0x00, 0x02, 0x93, 0x0c, 0x00, 0x02, 0x93, 0x38, 0x00, 0x02, 0x93, 0x54, 0x00, 0x02, 0x93, 0x80, 0x00, 0x02, 0x93, 0x9c, 0x00, 0x02, 0x93, 0xc4, 0x00, 0x02, 0x94, 0xb4, 0x00, 0x02, 0x95, 0x20, 0x00, 0x02, 0x95, 0xd4, 0x00, 0x02, 0x9e, 0xb4, 0x00, 0x02, 0xa1, 0x94, 0x00, 0x02, 0xa1, 0xcc, 0x00, 0x02, 0xa2, 0x30, 0x00, 0x02, 0xa2, 0x80, 0x00, 0x02, 0xa2, 0xe4, 0x00, 0x02, 0xa3, 0x78, 0x00, 0x02, 0xa4, 0x44, 0x00, 0x02, 0xa5, 0x10, 0x00, 0x02, 0xa5, 0x74, 0x00, 0x02, 0xa6, 0x10, 0x00, 0x02, 0xa8, 0x90, 0x00, 0x02, 0xab, 0x70, 0x00, 0x02, 0xab, 0xa8, 0x00, 0x02, 0xac, 0x20, 0x00, 0x02, 0xac, 0x94, 0x00, 0x02, 0xac, 0xec, 0x00, 0x02, 0xae, 0x48, 0x00, 0x02, 0xaf, 0xf4, 0x00, 0x02, 0xb0, 0x3c, 0x00, 0x02, 0xb0, 0x70, 0x00, 0x02, 0xb1, 0x64, 0x00, 0x02, 0xb2, 0x34, 0x00, 0x02, 0xb2, 0xc8, 0x00, 0x02, 0xb3, 0x5c, 0x00, 0x02, 0xb4, 0x20, 0x00, 0x02, 0xb4, 0xe8, 0x00, 0x02, 0xb5, 0xac, 0x00, 0x02, 0xb6, 0x70, 0x00, 0x02, 0xb9, 0xf4, 0x00, 0x02, 0xba, 0x70, 0x00, 0x02, 0xbb, 0x90, 0x00, 0x02, 0xbd, 0x2c, 0x00, 0x02, 0xc0, 0x88, 0x00, 0x02, 0xc1, 0x08, 0x00, 0x02, 0xc1, 0x8c, 0x00, 0x02, 0xc2, 0x00, 0x00, 0x02, 0xc2, 0x64, 0x00, 0x02, 0xc2, 0xe8, 0x00, 0x02, 0xc3, 0x78, 0x00, 0x02, 0xc4, 0xbc, 0x00, 0x02, 0xc5, 0xec, 0x00, 0x02, 0xc6, 0x88, 0x00, 0x02, 0xc7, 0x1c, 0x00, 0x02, 0xc7, 0xd0, 0x00, 0x02, 0xc7, 0xf0, 0x00, 0x02, 0xc8, 0x10, 0x00, 0x02, 0xc8, 0x30, 0x00, 0x02, 0xc8, 0x50, 0x00, 0x02, 0xc8, 0x70, 0x00, 0x02, 0xc8, 0x90, 0x00, 0x02, 0xc8, 0xb0, 0x00, 0x02, 0xc8, 0xd0, 0x00, 0x02, 0xca, 0x44, 0x00, 0x02, 0xcb, 0x20, 0x00, 0x02, 0xcb, 0xfc, 0x00, 0x02, 0xcc, 0xa8, 0x00, 0x02, 0xcd, 0xc4, 0x00, 0x02, 0xce, 0x54, 0x00, 0x02, 0xce, 0xe4, 0x00, 0x02, 0xcf, 0x9c, 0x00, 0x02, 0xd0, 0x10, 0x00, 0x02, 0xd0, 0x84, 0x00, 0x02, 0xd0, 0xf8, 0x00, 0x02, 0xd1, 0x50, 0x00, 0x02, 0xd1, 0xac, 0x00, 0x02, 0xd2, 0x40, 0x00, 0x02, 0xd2, 0xec, 0x00, 0x02, 0xd3, 0x54, 0x00, 0x02, 0xd3, 0xc8, 0x00, 0x02, 0xd4, 0x60, 0x00, 0x02, 0xd4, 0xc4, 0x00, 0x02, 0xd5, 0x84, 0x00, 0x02, 0xd6, 0x64, 0x00, 0x02, 0xd7, 0x34, 0x00, 0x02, 0xd7, 0xa8, 0x00, 0x02, 0xd8, 0x4c, 0x00, 0x02, 0xd8, 0xa8, 0x00, 0x02, 0xd9, 0x44, 0x00, 0x02, 0xda, 0x2c, 0x00, 0x02, 0xda, 0xa8, 0x00, 0x02, 0xdb, 0xd0, 0x00, 0x02, 0xdd, 0xfc, 0x00, 0x02, 0xde, 0x94, 0x00, 0x02, 0xdf, 0xb0, 0x00, 0x02, 0xe0, 0xf8, 0x00, 0x02, 0xe2, 0x0c, 0x00, 0x02, 0xe3, 0xa0, 0x00, 0x02, 0xe4, 0x98, 0x00, 0x02, 0xe5, 0x18, 0x00, 0x02, 0xe5, 0xdc, 0x00, 0x02, 0xe6, 0xc4, 0x00, 0x02, 0xe7, 0x58, 0x00, 0x02, 0xe7, 0xcc, 0x00, 0x02, 0xe8, 0x6c, 0x00, 0x02, 0xe8, 0xb4, 0x00, 0x02, 0xe9, 0x54, 0x00, 0x02, 0xea, 0x1c, 0x00, 0x02, 0xea, 0x70, 0x00, 0x02, 0xea, 0xa0, 0x00, 0x02, 0xeb, 0xc0, 0x00, 0x02, 0xec, 0xac, 0x00, 0x02, 0xec, 0xec, 0x00, 0x02, 0xed, 0x48, 0x00, 0x02, 0xed, 0xac, 0x00, 0x02, 0xee, 0x0c, 0x00, 0x02, 0xee, 0x60, 0x00, 0x02, 0xee, 0xac, 0x00, 0x02, 0xef, 0x40, 0x00, 0x02, 0xf0, 0x00, 0x00, 0x02, 0xf0, 0xe8, 0x00, 0x02, 0xf2, 0xf4, 0x00, 0x02, 0xf3, 0xe8, 0x00, 0x02, 0xf5, 0x0c, 0x00, 0x02, 0xf6, 0x48, 0x00, 0x02, 0xf7, 0x48, 0x00, 0x02, 0xf8, 0x6c, 0x00, 0x02, 0xf9, 0xa0, 0x00, 0x02, 0xfa, 0x90, 0x00, 0x02, 0xfb, 0x64, 0x00, 0x02, 0xfc, 0x70, 0x00, 0x02, 0xfd, 0xa4, 0x00, 0x02, 0xfe, 0xfc, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x98, 0x00, 0x03, 0x01, 0x08, 0x00, 0x03, 0x01, 0xbc, 0x00, 0x03, 0x02, 0xb0, 0x00, 0x03, 0x03, 0xe8, 0x00, 0x03, 0x05, 0x64, 0x00, 0x03, 0x07, 0x24, 0x00, 0x03, 0x07, 0xc0, 0x00, 0x03, 0x08, 0x80, 0x00, 0x03, 0x08, 0xe8, 0x00, 0x03, 0x09, 0x74, 0x00, 0x03, 0x09, 0x90, 0x00, 0x03, 0x09, 0xb8, 0x00, 0x03, 0x09, 0xd0, 0x00, 0x03, 0x09, 0xe8, 0x00, 0x03, 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x18, 0x00, 0x03, 0x0a, 0x98, 0x00, 0x03, 0x0a, 0xe8, 0x00, 0x03, 0x0b, 0x6c, 0x00, 0x03, 0x0c, 0x64, 0x00, 0x03, 0x0d, 0x0c, 0x00, 0x03, 0x0e, 0x2c, 0x00, 0x03, 0x0e, 0xdc, 0x00, 0x03, 0x0f, 0x64, 0x00, 0x03, 0x10, 0x08, 0x00, 0x03, 0x11, 0x0c, 0x00, 0x03, 0x12, 0xf4, 0x00, 0x03, 0x15, 0xb8, 0x00, 0x03, 0x17, 0x78, 0x00, 0x03, 0x17, 0xfc, 0x00, 0x03, 0x18, 0x48, 0x00, 0x03, 0x19, 0x20, 0x00, 0x03, 0x1a, 0x08, 0x00, 0x03, 0x1a, 0xec, 0x00, 0x03, 0x1b, 0x78, 0x00, 0x03, 0x1c, 0x58, 0x00, 0x03, 0x1d, 0x68, 0x00, 0x03, 0x1e, 0x40, 0x00, 0x03, 0x1f, 0x1c, 0x00, 0x03, 0x1f, 0x6c, 0x00, 0x03, 0x1f, 0xa0, 0x00, 0x03, 0x1f, 0xec, 0x00, 0x03, 0x20, 0x8c, 0x00, 0x03, 0x21, 0xd8, 0x00, 0x03, 0x23, 0x1c, 0x00, 0x03, 0x23, 0x58, 0x00, 0x03, 0x23, 0xd8, 0x00, 0x03, 0x24, 0x30, 0x00, 0x03, 0x24, 0x8c, 0x00, 0x03, 0x24, 0xe4, 0x00, 0x03, 0x25, 0x50, 0x00, 0x03, 0x25, 0xb4, 0x00, 0x03, 0x26, 0x1c, 0x00, 0x03, 0x26, 0x80, 0x00, 0x03, 0x27, 0x28, 0x00, 0x03, 0x28, 0x08, 0x00, 0x03, 0x29, 0x18, 0x00, 0x03, 0x2a, 0x84, 0x00, 0x03, 0x2b, 0x18, 0x00, 0x03, 0x2c, 0xa8, 0x00, 0x03, 0x2e, 0x0c, 0x00, 0x03, 0x2f, 0x98, 0x00, 0x03, 0x33, 0x58, 0x00, 0x03, 0x34, 0xe4, 0x00, 0x03, 0x36, 0x5c, 0x00, 0x03, 0x36, 0xe8, 0x00, 0x03, 0x37, 0x98, 0x00, 0x03, 0x3a, 0x4c, 0x00, 0x03, 0x3b, 0xec, 0x00, 0x03, 0x3d, 0x04, 0x00, 0x03, 0x3d, 0xf0, 0x00, 0x03, 0x3f, 0x04, 0x00, 0x03, 0x3f, 0xec, 0x00, 0x03, 0x40, 0x74, 0x00, 0x03, 0x40, 0xd8, 0x00, 0x03, 0x41, 0x3c, 0x00, 0x03, 0x41, 0x80, 0x00, 0x03, 0x41, 0xc0, 0x00, 0x03, 0x42, 0x8c, 0x00, 0x03, 0x43, 0x84, 0x00, 0x03, 0x44, 0x04, 0x00, 0x03, 0x44, 0x38, 0x00, 0x03, 0x44, 0x74, 0x00, 0x03, 0x44, 0xb8, 0x00, 0x03, 0x44, 0xe8, 0x00, 0x03, 0x45, 0x48, 0x00, 0x03, 0x45, 0xbc, 0x00, 0x03, 0x46, 0xa0, 0x00, 0x03, 0x47, 0x38, 0x00, 0x03, 0x47, 0xf4, 0x00, 0x03, 0x49, 0x74, 0x00, 0x03, 0x4a, 0xf8, 0x00, 0x03, 0x4e, 0x58, 0x00, 0x03, 0x4e, 0xb8, 0x00, 0x03, 0x4f, 0x68, 0x00, 0x03, 0x4f, 0xd0, 0x00, 0x03, 0x50, 0x5c, 0x00, 0x03, 0x50, 0xec, 0x00, 0x03, 0x51, 0xac, 0x00, 0x03, 0x52, 0x38, 0x00, 0x03, 0x52, 0xb8, 0x00, 0x03, 0x53, 0x34, 0x00, 0x03, 0x53, 0xa4, 0x00, 0x03, 0x53, 0xf8, 0x00, 0x03, 0x54, 0x60, 0x00, 0x03, 0x54, 0xc4, 0x00, 0x03, 0x55, 0x1c, 0x00, 0x03, 0x55, 0xe0, 0x00, 0x03, 0x56, 0x24, 0x00, 0x03, 0x56, 0x78, 0x00, 0x03, 0x56, 0xc8, 0x00, 0x03, 0x57, 0x34, 0x00, 0x03, 0x57, 0xf0, 0x00, 0x03, 0x59, 0x9c, 0x00, 0x03, 0x5b, 0x90, 0x00, 0x03, 0x5c, 0xbc, 0x00, 0x03, 0x5e, 0xec, 0x00, 0x03, 0x60, 0x4c, 0x00, 0x03, 0x62, 0xc4, 0x00, 0x03, 0x68, 0x14, 0x00, 0x03, 0x69, 0x4c, 0x00, 0x03, 0x6b, 0x9c, 0x00, 0x03, 0x6c, 0x60, 0x00, 0x03, 0x6d, 0x24, 0x00, 0x03, 0x6d, 0xf0, 0x00, 0x03, 0x6f, 0x74, 0x00, 0x03, 0x70, 0xf4, 0x00, 0x03, 0x72, 0x54, 0x00, 0x03, 0x73, 0xb0, 0x00, 0x03, 0x74, 0xfc, 0x00, 0x03, 0x75, 0x80, 0x00, 0x03, 0x75, 0xb4, 0x00, 0x03, 0x75, 0xe8, 0x00, 0x03, 0x76, 0x18, 0x00, 0x03, 0x76, 0x48, 0x00, 0x03, 0x76, 0xa0, 0x00, 0x03, 0x76, 0xbc, 0x00, 0x03, 0x76, 0xd8, 0x00, 0x03, 0x76, 0xf4, 0x00, 0x03, 0x77, 0x1c, 0x00, 0x03, 0x77, 0x40, 0x00, 0x03, 0x77, 0x58, 0x00, 0x03, 0x77, 0x70, 0x00, 0x03, 0x78, 0x4c, 0x00, 0x03, 0x78, 0xe4, 0x00, 0x03, 0x79, 0xa0, 0x00, 0x03, 0x7a, 0x10, 0x00, 0x03, 0x7a, 0x84, 0x00, 0x03, 0x7b, 0xa4, 0x00, 0x03, 0x7c, 0x8c, 0x00, 0x03, 0x7c, 0xf8, 0x00, 0x03, 0x7d, 0x68, 0x00, 0x03, 0x7d, 0xa4, 0x00, 0x03, 0x7d, 0xe0, 0x00, 0x03, 0x7e, 0x08, 0x00, 0x03, 0x7e, 0x34, 0x00, 0x03, 0x7e, 0x5c, 0x00, 0x03, 0x7e, 0x88, 0x00, 0x03, 0x7e, 0xb0, 0x00, 0x03, 0x7e, 0xdc, 0x00, 0x03, 0x7f, 0x08, 0x00, 0x03, 0x7f, 0x34, 0x00, 0x03, 0x7f, 0x98, 0x00, 0x03, 0x7f, 0xfc, 0x00, 0x03, 0x80, 0x5c, 0x00, 0x03, 0x80, 0xec, 0x00, 0x03, 0x81, 0x94, 0x00, 0x03, 0x82, 0x00, 0x00, 0x03, 0x82, 0x90, 0x00, 0x03, 0x83, 0x34, 0x00, 0x03, 0x83, 0x90, 0x00, 0x03, 0x84, 0x54, 0x00, 0x03, 0x84, 0xf8, 0x00, 0x03, 0x85, 0x98, 0x00, 0x03, 0x86, 0x6c, 0x00, 0x03, 0x87, 0x70, 0x00, 0x03, 0x88, 0x88, 0x00, 0x03, 0x89, 0x64, 0x00, 0x03, 0x8a, 0x64, 0x00, 0x03, 0x8b, 0x7c, 0x00, 0x03, 0x8c, 0x48, 0x00, 0x03, 0x8d, 0x70, 0x00, 0x03, 0x8e, 0x88, 0x00, 0x03, 0x8f, 0xb8, 0x00, 0x03, 0x90, 0x38, 0x00, 0x03, 0x90, 0xe8, 0x00, 0x03, 0x91, 0xb0, 0x00, 0x03, 0x92, 0x3c, 0x00, 0x03, 0x92, 0xec, 0x00, 0x03, 0x93, 0xb4, 0x00, 0x03, 0x94, 0x2c, 0x00, 0x03, 0x95, 0x04, 0x00, 0x03, 0x95, 0xcc, 0x00, 0x03, 0x96, 0x90, 0x00, 0x03, 0x96, 0xc0, 0x00, 0x03, 0x96, 0xec, 0x00, 0x03, 0x97, 0x18, 0x00, 0x03, 0x97, 0x44, 0x00, 0x03, 0x97, 0x74, 0x00, 0x03, 0x98, 0x00, 0x00, 0x03, 0x98, 0x28, 0x00, 0x03, 0x98, 0x50, 0x00, 0x03, 0x98, 0xa4, 0x00, 0x03, 0x98, 0xf8, 0x00, 0x03, 0x99, 0x20, 0x00, 0x03, 0x99, 0x50, 0x00, 0x03, 0x99, 0x80, 0x00, 0x03, 0x99, 0xa0, 0x00, 0x03, 0x99, 0xf0, 0x00, 0x03, 0x9a, 0x40, 0x00, 0x03, 0x9a, 0x6c, 0x00, 0x03, 0x9a, 0x9c, 0x00, 0x03, 0x9a, 0xe4, 0x00, 0x03, 0x9b, 0x2c, 0x00, 0x03, 0x9b, 0x80, 0x00, 0x03, 0x9b, 0xd0, 0x00, 0x03, 0x9c, 0x1c, 0x00, 0x03, 0x9c, 0x6c, 0x00, 0x03, 0x9c, 0xc0, 0x00, 0x03, 0x9d, 0x14, 0x00, 0x03, 0x9d, 0x80, 0x00, 0x03, 0x9e, 0x24, 0x00, 0x03, 0x9e, 0x7c, 0x00, 0x03, 0x9e, 0xc4, 0x00, 0x03, 0x9f, 0x1c, 0x00, 0x03, 0x9f, 0xa8, 0x00, 0x03, 0xa0, 0x28, 0x00, 0x03, 0xa0, 0xb4, 0x00, 0x03, 0xa1, 0x84, 0x00, 0x03, 0xa2, 0x14, 0x00, 0x03, 0xa3, 0x38, 0x00, 0x03, 0xa4, 0x64, 0x00, 0x03, 0xa4, 0xf0, 0x00, 0x03, 0xa5, 0x50, 0x00, 0x03, 0xa5, 0xb0, 0x00, 0x03, 0xa5, 0xec, 0x00, 0x03, 0xa6, 0x20, 0x00, 0x03, 0xa6, 0x54, 0x00, 0x03, 0xa6, 0x78, 0x00, 0x03, 0xa6, 0x9c, 0x00, 0x03, 0xa6, 0xb4, 0x00, 0x03, 0xa6, 0xcc, 0x00, 0x03, 0xa7, 0x24, 0x00, 0x03, 0xa7, 0x78, 0x00, 0x03, 0xa8, 0x3c, 0x00, 0x03, 0xa8, 0xfc, 0x00, 0x03, 0xa9, 0xf8, 0x00, 0x03, 0xaa, 0x28, 0x00, 0x03, 0xaa, 0x58, 0x00, 0x03, 0xaa, 0x9c, 0x00, 0x03, 0xaa, 0xdc, 0x00, 0x03, 0xab, 0x1c, 0x00, 0x03, 0xab, 0x78, 0x00, 0x03, 0xab, 0xb4, 0x00, 0x03, 0xab, 0xf0, 0x00, 0x03, 0xac, 0x3c, 0x00, 0x03, 0xac, 0x88, 0x00, 0x03, 0xad, 0x0c, 0x00, 0x03, 0xad, 0x0c, 0x00, 0x03, 0xad, 0x20, 0x00, 0x03, 0xad, 0x34, 0x00, 0x03, 0xad, 0x50, 0x00, 0x03, 0xad, 0x64, 0x00, 0x03, 0xad, 0x80, 0x00, 0x03, 0xad, 0x9c, 0x00, 0x03, 0xad, 0xc0, 0x00, 0x03, 0xad, 0xd4, 0x00, 0x03, 0xad, 0xf0, 0x00, 0x03, 0xae, 0x0c, 0x00, 0x03, 0xae, 0x30, 0x00, 0x03, 0xae, 0x4c, 0x00, 0x03, 0xae, 0x70, 0x00, 0x03, 0xae, 0x94, 0x00, 0x03, 0xae, 0xc0, 0x00, 0x03, 0xae, 0xd4, 0x00, 0x03, 0xae, 0xf0, 0x00, 0x03, 0xaf, 0x0c, 0x00, 0x03, 0xaf, 0x30, 0x00, 0x03, 0xaf, 0x4c, 0x00, 0x03, 0xaf, 0x70, 0x00, 0x03, 0xaf, 0x94, 0x00, 0x03, 0xaf, 0xc0, 0x00, 0x03, 0xaf, 0xdc, 0x00, 0x03, 0xb0, 0x00, 0x00, 0x03, 0xb0, 0x24, 0x00, 0x03, 0xb0, 0x50, 0x00, 0x03, 0xb0, 0x74, 0x00, 0x03, 0xb0, 0xa0, 0x00, 0x03, 0xb0, 0xcc, 0x00, 0x03, 0xb1, 0x00, 0x00, 0x03, 0xb1, 0x14, 0x00, 0x03, 0xb1, 0x30, 0x00, 0x03, 0xb1, 0x4c, 0x00, 0x03, 0xb1, 0x70, 0x00, 0x03, 0xb1, 0x8c, 0x00, 0x03, 0xb1, 0xb0, 0x00, 0x03, 0xb1, 0xd4, 0x00, 0x03, 0xb2, 0x00, 0x00, 0x03, 0xb2, 0x1c, 0x00, 0x03, 0xb2, 0x40, 0x00, 0x03, 0xb2, 0x64, 0x00, 0x03, 0xb2, 0x90, 0x00, 0x03, 0xb2, 0xb4, 0x00, 0x03, 0xb2, 0xe0, 0x00, 0x03, 0xb3, 0x0c, 0x00, 0x03, 0xb3, 0x40, 0x00, 0x03, 0xb3, 0x5c, 0x00, 0x03, 0xb3, 0x80, 0x00, 0x03, 0xb3, 0xa4, 0x00, 0x03, 0xb3, 0xd0, 0x00, 0x03, 0xb3, 0xf4, 0x00, 0x03, 0xb4, 0x20, 0x00, 0x03, 0xb4, 0x4c, 0x00, 0x03, 0xb4, 0x80, 0x00, 0x03, 0xb4, 0xa4, 0x00, 0x03, 0xb4, 0xd0, 0x00, 0x03, 0xb4, 0xfc, 0x00, 0x03, 0xb5, 0x30, 0x00, 0x03, 0xb5, 0x5c, 0x00, 0x03, 0xb5, 0x90, 0x00, 0x03, 0xb5, 0xc4, 0x00, 0x03, 0xb6, 0x00, 0x00, 0x03, 0xb6, 0x14, 0x00, 0x03, 0xb6, 0x30, 0x00, 0x03, 0xb6, 0x4c, 0x00, 0x03, 0xb6, 0x70, 0x00, 0x03, 0xb6, 0x8c, 0x00, 0x03, 0xb6, 0xb0, 0x00, 0x03, 0xb6, 0xd4, 0x00, 0x03, 0xb7, 0x00, 0x00, 0x03, 0xb7, 0x1c, 0x00, 0x03, 0xb7, 0x40, 0x00, 0x03, 0xb7, 0x64, 0x00, 0x03, 0xb7, 0x90, 0x00, 0x03, 0xb7, 0xb4, 0x00, 0x03, 0xb7, 0xe0, 0x00, 0x03, 0xb8, 0x0c, 0x00, 0x03, 0xb8, 0x40, 0x00, 0x03, 0xb8, 0x5c, 0x00, 0x03, 0xb8, 0x80, 0x00, 0x03, 0xb8, 0xa4, 0x00, 0x03, 0xb8, 0xd0, 0x00, 0x03, 0xb8, 0xf4, 0x00, 0x03, 0xb9, 0x20, 0x00, 0x03, 0xb9, 0x4c, 0x00, 0x03, 0xb9, 0x80, 0x00, 0x03, 0xb9, 0xa4, 0x00, 0x03, 0xb9, 0xd0, 0x00, 0x03, 0xb9, 0xfc, 0x00, 0x03, 0xba, 0x30, 0x00, 0x03, 0xba, 0x5c, 0x00, 0x03, 0xba, 0x90, 0x00, 0x03, 0xba, 0xc4, 0x00, 0x03, 0xbb, 0x00, 0x00, 0x03, 0xbb, 0x1c, 0x00, 0x03, 0xbb, 0x40, 0x00, 0x03, 0xbb, 0x64, 0x00, 0x03, 0xbb, 0x90, 0x00, 0x03, 0xbb, 0xb4, 0x00, 0x03, 0xbb, 0xe0, 0x00, 0x03, 0xbc, 0x0c, 0x00, 0x03, 0xbc, 0x40, 0x00, 0x03, 0xbc, 0x64, 0x00, 0x03, 0xbc, 0x90, 0x00, 0x03, 0xbc, 0xbc, 0x00, 0x03, 0xbc, 0xf0, 0x00, 0x03, 0xbd, 0x1c, 0x00, 0x03, 0xbd, 0x50, 0x00, 0x03, 0xbd, 0x84, 0x00, 0x03, 0xbd, 0xc0, 0x00, 0x03, 0xbd, 0xe4, 0x00, 0x03, 0xbe, 0x10, 0x00, 0x03, 0xbe, 0x3c, 0x00, 0x03, 0xbe, 0x70, 0x00, 0x03, 0xbe, 0x9c, 0x00, 0x03, 0xbe, 0xd0, 0x00, 0x03, 0xbf, 0x04, 0x00, 0x03, 0xbf, 0x40, 0x00, 0x03, 0xbf, 0x6c, 0x00, 0x03, 0xbf, 0xa0, 0x00, 0x03, 0xbf, 0xd4, 0x00, 0x03, 0xc0, 0x10, 0x00, 0x03, 0xc0, 0x44, 0x00, 0x03, 0xc0, 0x80, 0x00, 0x03, 0xc0, 0xbc, 0x00, 0x03, 0xc1, 0x00, 0x00, 0x03, 0xc1, 0x14, 0x00, 0x03, 0xc1, 0x30, 0x00, 0x03, 0xc1, 0x4c, 0x00, 0x03, 0xc1, 0x70, 0x00, 0x03, 0xc1, 0x8c, 0x00, 0x03, 0xc1, 0xb0, 0x00, 0x03, 0xc1, 0xd4, 0x00, 0x03, 0xc2, 0x00, 0x00, 0x03, 0xc2, 0x1c, 0x00, 0x03, 0xc2, 0x40, 0x00, 0x03, 0xc2, 0x64, 0x00, 0x03, 0xc2, 0x90, 0x00, 0x03, 0xc2, 0xb4, 0x00, 0x03, 0xc2, 0xe0, 0x00, 0x03, 0xc3, 0x0c, 0x00, 0x03, 0xc3, 0x40, 0x00, 0x03, 0xc3, 0x5c, 0x00, 0x03, 0xc3, 0x80, 0x00, 0x03, 0xc3, 0xa4, 0x00, 0x03, 0xc3, 0xd0, 0x00, 0x03, 0xc3, 0xf4, 0x00, 0x03, 0xc4, 0x20, 0x00, 0x03, 0xc4, 0x4c, 0x00, 0x03, 0xc4, 0x80, 0x00, 0x03, 0xc4, 0xa4, 0x00, 0x03, 0xc4, 0xd0, 0x00, 0x03, 0xc4, 0xfc, 0x00, 0x03, 0xc5, 0x30, 0x00, 0x03, 0xc5, 0x5c, 0x00, 0x03, 0xc5, 0x90, 0x00, 0x03, 0xc5, 0xc4, 0x00, 0x03, 0xc6, 0x00, 0x00, 0x03, 0xc6, 0x1c, 0x00, 0x03, 0xc6, 0x40, 0x00, 0x03, 0xc6, 0x64, 0x00, 0x03, 0xc6, 0x90, 0x00, 0x03, 0xc6, 0xb4, 0x00, 0x03, 0xc6, 0xe0, 0x00, 0x03, 0xc7, 0x0c, 0x00, 0x03, 0xc7, 0x40, 0x00, 0x03, 0xc7, 0x64, 0x00, 0x03, 0xc7, 0x90, 0x00, 0x03, 0xc7, 0xbc, 0x00, 0x03, 0xc7, 0xf0, 0x00, 0x03, 0xc8, 0x1c, 0x00, 0x03, 0xc8, 0x50, 0x00, 0x03, 0xc8, 0x84, 0x00, 0x03, 0xc8, 0xc0, 0x00, 0x03, 0xc8, 0xe4, 0x00, 0x03, 0xc9, 0x10, 0x00, 0x03, 0xc9, 0x3c, 0x00, 0x03, 0xc9, 0x70, 0x00, 0x03, 0xc9, 0x9c, 0x00, 0x03, 0xc9, 0xd0, 0x00, 0x03, 0xca, 0x04, 0x00, 0x03, 0xca, 0x40, 0x00, 0x03, 0xca, 0x6c, 0x00, 0x03, 0xca, 0xa0, 0x00, 0x03, 0xca, 0xd4, 0x00, 0x03, 0xcb, 0x10, 0x00, 0x03, 0xcb, 0x44, 0x00, 0x03, 0xcb, 0x80, 0x00, 0x03, 0xcb, 0xbc, 0x00, 0x03, 0xcc, 0x00, 0x00, 0x03, 0xcc, 0x1c, 0x00, 0x03, 0xcc, 0x40, 0x00, 0x03, 0xcc, 0x64, 0x00, 0x03, 0xcc, 0x90, 0x00, 0x03, 0xcc, 0xb4, 0x00, 0x03, 0xcc, 0xe0, 0x00, 0x03, 0xcd, 0x0c, 0x00, 0x03, 0xcd, 0x40, 0x00, 0x03, 0xcd, 0x64, 0x00, 0x03, 0xcd, 0x90, 0x00, 0x03, 0xcd, 0xbc, 0x00, 0x03, 0xcd, 0xf0, 0x00, 0x03, 0xce, 0x1c, 0x00, 0x03, 0xce, 0x50, 0x00, 0x03, 0xce, 0x84, 0x00, 0x03, 0xce, 0xc0, 0x00, 0x03, 0xce, 0xe4, 0x00, 0x03, 0xcf, 0x10, 0x00, 0x03, 0xcf, 0x3c, 0x00, 0x03, 0xcf, 0x70, 0x00, 0x03, 0xcf, 0x9c, 0x00, 0x03, 0xcf, 0xd0, 0x00, 0x03, 0xd0, 0x04, 0x00, 0x03, 0xd0, 0x40, 0x00, 0x03, 0xd0, 0x6c, 0x00, 0x03, 0xd0, 0xa0, 0x00, 0x03, 0xd0, 0xd4, 0x00, 0x03, 0xd1, 0x10, 0x00, 0x03, 0xd1, 0x44, 0x00, 0x03, 0xd1, 0x80, 0x00, 0x03, 0xd1, 0xbc, 0x00, 0x03, 0xd2, 0x00, 0x00, 0x03, 0xd2, 0x24, 0x00, 0x03, 0xd2, 0x50, 0x00, 0x03, 0xd2, 0x7c, 0x00, 0x03, 0xd2, 0xb0, 0x00, 0x03, 0xd2, 0xdc, 0x00, 0x03, 0xd3, 0x10, 0x00, 0x03, 0xd3, 0x44, 0x00, 0x03, 0xd3, 0x80, 0x00, 0x03, 0xd3, 0xac, 0x00, 0x03, 0xd3, 0xe0, 0x00, 0x03, 0xd4, 0x14, 0x00, 0x03, 0xd4, 0x50, 0x00, 0x03, 0xd4, 0x84, 0x00, 0x03, 0xd4, 0xc0, 0x00, 0x03, 0xd4, 0xfc, 0x00, 0x03, 0xd5, 0x40, 0x00, 0x03, 0xd5, 0x6c, 0x00, 0x03, 0xd5, 0xa0, 0x00, 0x03, 0xd5, 0xd4, 0x00, 0x03, 0xd6, 0x10, 0x00, 0x03, 0xd6, 0x44, 0x00, 0x03, 0xd6, 0x80, 0x00, 0x03, 0xd6, 0xbc, 0x00, 0x03, 0xd7, 0x00, 0x00, 0x03, 0xd7, 0x34, 0x00, 0x03, 0xd7, 0x70, 0x00, 0x03, 0xd7, 0xac, 0x00, 0x03, 0xd7, 0xf0, 0x00, 0x03, 0xd8, 0x2c, 0x00, 0x03, 0xd8, 0x70, 0x00, 0x03, 0xd8, 0xb4, 0x00, 0x03, 0xd9, 0x00, 0x00, 0x03, 0xd9, 0x4c, 0x00, 0x03, 0xd9, 0x98, 0x00, 0x03, 0xd9, 0xe0, 0x00, 0x03, 0xda, 0x24, 0x00, 0x03, 0xda, 0xf0, 0x00, 0x03, 0xdb, 0xb8, 0x00, 0x03, 0xdc, 0x40, 0x00, 0x03, 0xdc, 0xc8, 0x00, 0x03, 0xdd, 0x14, 0x00, 0x03, 0xdd, 0x50, 0x00, 0x03, 0xdd, 0x8c, 0x00, 0x03, 0xdd, 0xc0, 0x00, 0x03, 0xdd, 0xf4, 0x00, 0x03, 0xde, 0x1c, 0x00, 0x03, 0xde, 0x50, 0x00, 0x03, 0xde, 0x84, 0x00, 0x03, 0xde, 0xa4, 0x00, 0x03, 0xde, 0xec, 0x00, 0x03, 0xdf, 0x44, 0x00, 0x03, 0xe0, 0x04, 0x00, 0x03, 0xe0, 0xd8, 0x00, 0x03, 0xe1, 0xbc, 0x00, 0x03, 0xe1, 0xe4, 0x00, 0x03, 0xe2, 0x44, 0x00, 0x03, 0xe2, 0xbc, 0x00, 0x03, 0xe3, 0x28, 0x00, 0x03, 0xe3, 0xd4, 0x00, 0x03, 0xe4, 0x74, 0x00, 0x03, 0xe4, 0xe8, 0x00, 0x03, 0xe5, 0x78, 0x00, 0x03, 0xe6, 0x0c, 0x00, 0x03, 0xe6, 0xb0, 0x00, 0x03, 0xe7, 0x30, 0x00, 0x03, 0xe7, 0xc8, 0x00, 0x03, 0xe8, 0x44, 0x00, 0x03, 0xe8, 0xcc, 0x00, 0x03, 0xe9, 0x50, 0x00, 0x03, 0xe9, 0xb0, 0x00, 0x03, 0xea, 0x10, 0x00, 0x03, 0xea, 0x20, 0x00, 0x03, 0xea, 0x38, 0x00, 0x03, 0xea, 0x58, 0x00, 0x03, 0xea, 0x94, 0x00, 0x03, 0xea, 0xcc, 0x00, 0x03, 0xea, 0xe4, 0x00, 0x03, 0xea, 0xfc, 0x00, 0x03, 0xeb, 0x14, 0x00, 0x03, 0xeb, 0x2c, 0x00, 0x03, 0xeb, 0x44, 0x00, 0x03, 0xeb, 0x5c, 0x00, 0x03, 0xec, 0x2c, 0x00, 0x03, 0xec, 0xf8, 0x00, 0x03, 0xed, 0x48, 0x00, 0x03, 0xed, 0x98, 0x00, 0x03, 0xee, 0x5c, 0x00, 0x03, 0xef, 0x18, 0x00, 0x03, 0xef, 0x7c, 0x00, 0x03, 0xef, 0xd8, 0x00, 0x03, 0xf0, 0x5c, 0x00, 0x03, 0xf0, 0xdc, 0x00, 0x03, 0xf1, 0x6c, 0x00, 0x03, 0xf1, 0xfc, 0x00, 0x03, 0xf2, 0x58, 0x00, 0x03, 0xf2, 0xbc, 0x00, 0x03, 0xf3, 0x24, 0x00, 0x03, 0xf3, 0x88, 0x00, 0x03, 0xf3, 0xc4, 0x00, 0x03, 0xf4, 0x00, 0x00, 0x03, 0xf4, 0x18, 0x00, 0x03, 0xf4, 0x30, 0x00, 0x03, 0xf4, 0x74, 0x00, 0x03, 0xf4, 0xbc, 0x00, 0x03, 0xf5, 0x04, 0x00, 0x03, 0xf5, 0x54, 0x00, 0x03, 0xf5, 0xcc, 0x00, 0x03, 0xf6, 0x48, 0x00, 0x03, 0xf6, 0xdc, 0x00, 0x03, 0xf7, 0x74, 0x00, 0x03, 0xf7, 0xf4, 0x00, 0x03, 0xf8, 0x3c, 0x00, 0x03, 0xf8, 0x80, 0x00, 0x03, 0xf8, 0xe4, 0x00, 0x03, 0xf9, 0x44, 0x00, 0x03, 0xf9, 0x98, 0x00, 0x03, 0xf9, 0xec, 0x00, 0x03, 0xfa, 0x64, 0x00, 0x03, 0xfa, 0xd8, 0x00, 0x03, 0xfb, 0xb8, 0x00, 0x03, 0xfc, 0x98, 0x00, 0x03, 0xfd, 0x68, 0x00, 0x03, 0xfe, 0x38, 0x00, 0x03, 0xfe, 0x84, 0x00, 0x03, 0xfe, 0xcc, 0x00, 0x03, 0xff, 0x14, 0x00, 0x03, 0xff, 0x5c, 0x00, 0x03, 0xff, 0xa4, 0x00, 0x03, 0xff, 0xec, 0x00, 0x04, 0x00, 0x44, 0x00, 0x04, 0x00, 0x6c, 0x00, 0x04, 0x00, 0x94, 0x00, 0x04, 0x00, 0xbc, 0x00, 0x04, 0x00, 0xe8, 0x00, 0x04, 0x01, 0x14, 0x00, 0x04, 0x01, 0x40, 0x00, 0x04, 0x01, 0x6c, 0x00, 0x04, 0x01, 0xa4, 0x00, 0x04, 0x01, 0xd8, 0x00, 0x04, 0x02, 0x0c, 0x00, 0x04, 0x02, 0x44, 0x00, 0x04, 0x02, 0x7c, 0x00, 0x04, 0x02, 0xb0, 0x00, 0x04, 0x02, 0xdc, 0x00, 0x04, 0x03, 0x08, 0x00, 0x04, 0x03, 0x34, 0x00, 0x04, 0x03, 0x5c, 0x00, 0x04, 0x03, 0x8c, 0x00, 0x04, 0x03, 0xbc, 0x00, 0x04, 0x03, 0xec, 0x00, 0x04, 0x04, 0x1c, 0x00, 0x04, 0x04, 0xc8, 0x00, 0x04, 0x04, 0xec, 0x00, 0x04, 0x05, 0x24, 0x00, 0x04, 0x05, 0x68, 0x00, 0x04, 0x05, 0x90, 0x00, 0x04, 0x05, 0xbc, 0x00, 0x04, 0x05, 0xf4, 0x00, 0x04, 0x06, 0x18, 0x00, 0x04, 0x06, 0x54, 0x00, 0x04, 0x06, 0x9c, 0x00, 0x04, 0x06, 0xdc, 0x00, 0x04, 0x07, 0x4c, 0x00, 0x04, 0x07, 0xa8, 0x00, 0x04, 0x08, 0x1c, 0x00, 0x04, 0x08, 0xcc, 0x00, 0x04, 0x09, 0x28, 0x00, 0x04, 0x09, 0x38, 0x00, 0x04, 0x09, 0x88, 0x00, 0x04, 0x09, 0xc4, 0x00, 0x04, 0x0a, 0x04, 0x00, 0x04, 0x0a, 0x38, 0x00, 0x04, 0x0a, 0x6c, 0x00, 0x04, 0x0a, 0xd4, 0x00, 0x04, 0x0b, 0x24, 0x00, 0x04, 0x0b, 0x5c, 0x00, 0x04, 0x0b, 0xb8, 0x00, 0x04, 0x0c, 0x04, 0x00, 0x04, 0x0c, 0x70, 0x00, 0x04, 0x0c, 0xd0, 0x00, 0x04, 0x0d, 0x30, 0x00, 0x04, 0x0d, 0x58, 0x00, 0x04, 0x0d, 0x80, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x04, 0x0e, 0x4c, 0x00, 0x04, 0x0e, 0xc4, 0x00, 0x04, 0x0e, 0xf8, 0x00, 0x04, 0x0f, 0x0c, 0x00, 0x04, 0x0f, 0x38, 0x00, 0x04, 0x0f, 0xe4, 0x00, 0x04, 0x10, 0x3c, 0x00, 0x04, 0x10, 0x64, 0x00, 0x04, 0x10, 0x8c, 0x00, 0x04, 0x10, 0xb4, 0x00, 0x04, 0x10, 0xdc, 0x00, 0x04, 0x11, 0x04, 0x00, 0x04, 0x11, 0x2c, 0x00, 0x04, 0x11, 0x54, 0x00, 0x04, 0x11, 0x7c, 0x00, 0x04, 0x11, 0xa4, 0x00, 0x04, 0x11, 0xc8, 0x00, 0x04, 0x11, 0xe8, 0x00, 0x04, 0x12, 0x0c, 0x00, 0x04, 0x12, 0x30, 0x00, 0x04, 0x12, 0x54, 0x00, 0x04, 0x12, 0x74, 0x00, 0x04, 0x12, 0xa0, 0x00, 0x04, 0x12, 0xcc, 0x00, 0x04, 0x12, 0xf8, 0x00, 0x04, 0x13, 0x24, 0x00, 0x04, 0x13, 0x38, 0x00, 0x04, 0x13, 0x7c, 0x00, 0x04, 0x13, 0xc0, 0x00, 0x04, 0x13, 0xf0, 0x00, 0x04, 0x14, 0x20, 0x00, 0x04, 0x14, 0x64, 0x00, 0x04, 0x14, 0xbc, 0x00, 0x04, 0x15, 0x40, 0x00, 0x04, 0x15, 0xd0, 0x00, 0x04, 0x15, 0xe0, 0x00, 0x04, 0x16, 0x70, 0x00, 0x04, 0x16, 0x9c, 0x00, 0x04, 0x16, 0xac, 0x00, 0x04, 0x17, 0x0c, 0x00, 0x04, 0x17, 0xe4, 0x00, 0x04, 0x18, 0x68, 0x00, 0x04, 0x19, 0x14, 0x00, 0x04, 0x19, 0x70, 0x00, 0x04, 0x1a, 0x04, 0x00, 0x04, 0x1a, 0x4c, 0x00, 0x04, 0x1a, 0xc8, 0x00, 0x04, 0x1b, 0x24, 0x00, 0x04, 0x1b, 0xb4, 0x00, 0x04, 0x1c, 0x14, 0x00, 0x04, 0x1c, 0xa8, 0x00, 0x04, 0x1c, 0xb8, 0x00, 0x04, 0x1c, 0xc8, 0x00, 0x04, 0x1d, 0x10, 0x00, 0x04, 0x1d, 0x58, 0x00, 0x04, 0x1d, 0x84, 0x00, 0x04, 0x1d, 0xac, 0x00, 0x04, 0x1d, 0xdc, 0x00, 0x04, 0x1e, 0x08, 0x00, 0x04, 0x1e, 0x90, 0x00, 0x04, 0x1f, 0x14, 0x00, 0x04, 0x1f, 0xc8, 0x00, 0x04, 0x20, 0x68, 0x00, 0x04, 0x20, 0xc4, 0x00, 0x04, 0x21, 0x2c, 0x00, 0x04, 0x21, 0xa0, 0x00, 0x04, 0x22, 0x38, 0x00, 0x04, 0x22, 0xc0, 0x00, 0x04, 0x23, 0x28, 0x00, 0x04, 0x23, 0x80, 0x00, 0x04, 0x23, 0xe8, 0x00, 0x04, 0x24, 0x40, 0x00, 0x04, 0x24, 0xac, 0x00, 0x04, 0x24, 0xcc, 0x00, 0x04, 0x24, 0xec, 0x00, 0x04, 0x25, 0x34, 0x00, 0x04, 0x25, 0x78, 0x00, 0x04, 0x25, 0x88, 0x00, 0x04, 0x25, 0xb0, 0x00, 0x04, 0x25, 0xd4, 0x00, 0x04, 0x25, 0xf0, 0x00, 0x04, 0x26, 0x00, 0x00, 0x04, 0x26, 0x60, 0x00, 0x04, 0x26, 0x98, 0x00, 0x04, 0x26, 0xe4, 0x00, 0x04, 0x27, 0x6c, 0x00, 0x04, 0x28, 0x20, 0x00, 0x04, 0x28, 0x7c, 0x00, 0x04, 0x28, 0xd8, 0x00, 0x04, 0x29, 0x40, 0x00, 0x04, 0x29, 0xb0, 0x00, 0x04, 0x2a, 0x44, 0x00, 0x04, 0x2a, 0x9c, 0x00, 0x04, 0x2b, 0x30, 0x00, 0x04, 0x2b, 0xc4, 0x00, 0x04, 0x2c, 0x0c, 0x00, 0x04, 0x2c, 0x1c, 0x00, 0x04, 0x2c, 0x48, 0x00, 0x04, 0x2c, 0x8c, 0x00, 0x04, 0x2c, 0xc8, 0x00, 0x04, 0x2c, 0xe4, 0x00, 0x04, 0x2d, 0x30, 0x00, 0x04, 0x2d, 0x4c, 0x00, 0x04, 0x2d, 0x6c, 0x00, 0x04, 0x2d, 0x90, 0x00, 0x04, 0x2d, 0xb4, 0x00, 0x04, 0x2d, 0xd8, 0x00, 0x04, 0x2d, 0xf8, 0x00, 0x04, 0x2e, 0x0c, 0x00, 0x04, 0x2e, 0x20, 0x00, 0x04, 0x2e, 0x34, 0x00, 0x04, 0x2e, 0x48, 0x00, 0x04, 0x2e, 0x6c, 0x00, 0x04, 0x2e, 0x80, 0x00, 0x04, 0x2e, 0x94, 0x00, 0x04, 0x2e, 0xa8, 0x00, 0x04, 0x2e, 0xbc, 0x00, 0x04, 0x2e, 0xe0, 0x00, 0x04, 0x2e, 0xf4, 0x00, 0x04, 0x2f, 0x08, 0x00, 0x04, 0x2f, 0x1c, 0x00, 0x04, 0x2f, 0x30, 0x00, 0x04, 0x2f, 0x54, 0x00, 0x04, 0x2f, 0x68, 0x00, 0x04, 0x2f, 0x7c, 0x00, 0x04, 0x2f, 0x90, 0x00, 0x04, 0x2f, 0xa4, 0x00, 0x04, 0x2f, 0xbc, 0x00, 0x04, 0x30, 0x8c, 0x00, 0x04, 0x31, 0x5c, 0x00, 0x04, 0x32, 0x2c, 0x00, 0x04, 0x32, 0xfc, 0x00, 0x04, 0x33, 0x50, 0x00, 0x04, 0x33, 0xb8, 0x00, 0x04, 0x34, 0x2c, 0x00, 0x04, 0x34, 0xc8, 0x00, 0x04, 0x35, 0x20, 0x00, 0x04, 0x35, 0x90, 0x00, 0x04, 0x36, 0x14, 0x00, 0x04, 0x36, 0x90, 0x00, 0x04, 0x36, 0xe4, 0x00, 0x04, 0x37, 0x48, 0x00, 0x04, 0x37, 0xf4, 0x00, 0x04, 0x38, 0x60, 0x00, 0x04, 0x38, 0xc0, 0x00, 0x04, 0x39, 0x34, 0x00, 0x04, 0x39, 0x98, 0x00, 0x04, 0x39, 0xf0, 0x00, 0x04, 0x3a, 0x74, 0x00, 0x04, 0x3a, 0xc4, 0x00, 0x04, 0x3b, 0x44, 0x00, 0x04, 0x3b, 0xac, 0x00, 0x04, 0x3c, 0x54, 0x00, 0x04, 0x3c, 0xb4, 0x00, 0x04, 0x3d, 0x44, 0x00, 0x04, 0x3d, 0xac, 0x00, 0x04, 0x3e, 0x20, 0x00, 0x04, 0x3e, 0x88, 0x00, 0x04, 0x3f, 0x04, 0x00, 0x04, 0x3f, 0x58, 0x00, 0x04, 0x3f, 0xcc, 0x00, 0x04, 0x40, 0x44, 0x00, 0x04, 0x40, 0x98, 0x00, 0x04, 0x41, 0x0c, 0x00, 0x04, 0x41, 0x7c, 0x00, 0x04, 0x41, 0xf4, 0x00, 0x04, 0x42, 0x68, 0x00, 0x04, 0x42, 0xcc, 0x00, 0x04, 0x43, 0x38, 0x00, 0x04, 0x43, 0xbc, 0x00, 0x04, 0x44, 0x4c, 0x00, 0x04, 0x44, 0xd8, 0x00, 0x04, 0x45, 0xa4, 0x00, 0x04, 0x45, 0xf8, 0x00, 0x04, 0x46, 0x58, 0x00, 0x04, 0x46, 0xc8, 0x00, 0x04, 0x47, 0x1c, 0x00, 0x04, 0x47, 0x80, 0x00, 0x04, 0x47, 0xe4, 0x00, 0x04, 0x48, 0x44, 0x00, 0x04, 0x48, 0xa4, 0x00, 0x04, 0x49, 0x14, 0x00, 0x04, 0x49, 0x84, 0x00, 0x04, 0x49, 0xdc, 0x00, 0x04, 0x4a, 0x34, 0x00, 0x04, 0x4a, 0x98, 0x00, 0x04, 0x4b, 0x0c, 0x00, 0x04, 0x4b, 0x8c, 0x00, 0x04, 0x4c, 0x1c, 0x00, 0x04, 0x4c, 0x90, 0x00, 0x04, 0x4d, 0x14, 0x00, 0x04, 0x4d, 0x8c, 0x00, 0x04, 0x4e, 0x10, 0x00, 0x04, 0x4e, 0xa0, 0x00, 0x04, 0x4f, 0x18, 0x00, 0x04, 0x4f, 0xa0, 0x00, 0x04, 0x50, 0x24, 0x00, 0x04, 0x50, 0x94, 0x00, 0x04, 0x50, 0xfc, 0x00, 0x04, 0x51, 0x50, 0x00, 0x04, 0x51, 0x98, 0x00, 0x04, 0x52, 0x1c, 0x00, 0x04, 0x52, 0x8c, 0x00, 0x04, 0x53, 0x0c, 0x00, 0x04, 0x54, 0x04, 0x00, 0x04, 0x54, 0x2c, 0x00, 0x04, 0x54, 0x54, 0x00, 0x04, 0x54, 0x9c, 0x00, 0x04, 0x54, 0xe4, 0x00, 0x04, 0x54, 0xe4, 0x00, 0x04, 0x54, 0xe4, 0x00, 0x04, 0x54, 0xe4, 0x00, 0x04, 0x54, 0xe4, 0x00, 0x04, 0x55, 0x70, 0x00, 0x04, 0x55, 0xa8, 0x00, 0x04, 0x56, 0x20, 0x00, 0x04, 0x56, 0x4c, 0x00, 0x04, 0x56, 0x9c, 0x00, 0x04, 0x56, 0xdc, 0x00, 0x04, 0x57, 0x0c, 0x00, 0x04, 0x57, 0x38, 0x00, 0x04, 0x57, 0x74, 0x00, 0x04, 0x58, 0x0c, 0x00, 0x04, 0x58, 0x28, 0x00, 0x04, 0x58, 0x60, 0x00, 0x04, 0x58, 0x88, 0x00, 0x04, 0x58, 0xc8, 0x00, 0x04, 0x58, 0xf8, 0x00, 0x04, 0x59, 0x54, 0x00, 0x04, 0x59, 0xe4, 0x00, 0x04, 0x5a, 0x2c, 0x00, 0x04, 0x5a, 0x64, 0x00, 0x04, 0x5a, 0xcc, 0x00, 0x04, 0x5b, 0x20, 0x00, 0x04, 0x5b, 0x58, 0x00, 0x04, 0x5b, 0x84, 0x00, 0x04, 0x5b, 0xac, 0x00, 0x04, 0x5b, 0xf0, 0x00, 0x04, 0x5c, 0x6c, 0x00, 0x04, 0x5c, 0xa4, 0x00, 0x04, 0x5d, 0x24, 0x00, 0x04, 0x5d, 0x68, 0x00, 0x04, 0x5d, 0xb0, 0x00, 0x04, 0x5d, 0xd4, 0x00, 0x04, 0x5e, 0x1c, 0x00, 0x04, 0x5e, 0x2c, 0x00, 0x04, 0x5e, 0x58, 0x00, 0x04, 0x5e, 0x68, 0x00, 0x04, 0x5e, 0x9c, 0x00, 0x04, 0x5e, 0xd4, 0x00, 0x04, 0x5e, 0xf0, 0x00, 0x04, 0x5f, 0x0c, 0x00, 0x04, 0x5f, 0x28, 0x00, 0x04, 0x5f, 0x44, 0x00, 0x04, 0x5f, 0x60, 0x00, 0x04, 0x5f, 0x88, 0x00, 0x04, 0x5f, 0xb0, 0x00, 0x04, 0x5f, 0xdc, 0x00, 0x04, 0x60, 0x04, 0x00, 0x04, 0x60, 0x2c, 0x00, 0x04, 0x60, 0x58, 0x00, 0x04, 0x60, 0x80, 0x00, 0x04, 0x60, 0xa8, 0x00, 0x04, 0x60, 0xd0, 0x00, 0x04, 0x60, 0xf8, 0x00, 0x04, 0x61, 0x20, 0x00, 0x04, 0x61, 0x4c, 0x00, 0x04, 0x61, 0x74, 0x00, 0x04, 0x61, 0x9c, 0x00, 0x04, 0x61, 0xc8, 0x00, 0x04, 0x61, 0xf0, 0x00, 0x04, 0x62, 0x18, 0x00, 0x04, 0x62, 0x40, 0x00, 0x04, 0x62, 0x68, 0x00, 0x04, 0x62, 0x90, 0x00, 0x04, 0x62, 0xbc, 0x00, 0x04, 0x62, 0xe4, 0x00, 0x04, 0x63, 0x0c, 0x00, 0x04, 0x63, 0x38, 0x00, 0x04, 0x63, 0x60, 0x00, 0x04, 0x63, 0x88, 0x00, 0x04, 0x63, 0xb0, 0x00, 0x04, 0x63, 0xd8, 0x00, 0x04, 0x64, 0x00, 0x00, 0x04, 0x64, 0x2c, 0x00, 0x04, 0x64, 0x54, 0x00, 0x04, 0x64, 0x7c, 0x00, 0x04, 0x64, 0xa8, 0x00, 0x04, 0x64, 0xd0, 0x00, 0x04, 0x64, 0xf8, 0x00, 0x04, 0x65, 0x20, 0x00, 0x04, 0x65, 0x48, 0x00, 0x04, 0x65, 0x70, 0x00, 0x04, 0x65, 0x9c, 0x00, 0x04, 0x65, 0xc4, 0x00, 0x04, 0x65, 0xec, 0x00, 0x04, 0x66, 0x18, 0x00, 0x04, 0x66, 0x40, 0x00, 0x04, 0x66, 0x68, 0x00, 0x04, 0x66, 0x90, 0x00, 0x04, 0x66, 0xb8, 0x00, 0x04, 0x66, 0xe0, 0x00, 0x04, 0x67, 0x0c, 0x00, 0x04, 0x67, 0x34, 0x00, 0x04, 0x67, 0x5c, 0x00, 0x04, 0x67, 0x88, 0x00, 0x04, 0x67, 0xb0, 0x00, 0x04, 0x67, 0xd8, 0x00, 0x04, 0x68, 0x00, 0x00, 0x04, 0x68, 0x28, 0x00, 0x04, 0x68, 0x50, 0x00, 0x04, 0x68, 0x7c, 0x00, 0x04, 0x68, 0xa4, 0x00, 0x04, 0x68, 0xcc, 0x00, 0x04, 0x68, 0xf8, 0x00, 0x04, 0x69, 0x20, 0x00, 0x04, 0x69, 0x48, 0x00, 0x04, 0x69, 0x70, 0x00, 0x04, 0x69, 0x98, 0x00, 0x04, 0x69, 0xc0, 0x00, 0x04, 0x69, 0xec, 0x00, 0x04, 0x6a, 0x14, 0x00, 0x04, 0x6a, 0x3c, 0x00, 0x04, 0x6a, 0x68, 0x00, 0x04, 0x6a, 0x90, 0x00, 0x04, 0x6a, 0xb8, 0x00, 0x04, 0x6a, 0xe0, 0x00, 0x04, 0x6b, 0x08, 0x00, 0x04, 0x6b, 0x30, 0x00, 0x04, 0x6b, 0x5c, 0x00, 0x04, 0x6b, 0x84, 0x00, 0x04, 0x6b, 0xac, 0x00, 0x04, 0x6b, 0xd8, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x04, 0x6c, 0x28, 0x00, 0x04, 0x6c, 0x50, 0x00, 0x04, 0x6c, 0x9c, 0x00, 0x04, 0x6d, 0x2c, 0x00, 0x04, 0x6d, 0x98, 0x00, 0x04, 0x6d, 0xd8, 0x00, 0x04, 0x6e, 0x14, 0x00, 0x04, 0x6e, 0x9c, 0x00, 0x04, 0x6e, 0xd8, 0x00, 0x04, 0x6f, 0x24, 0x00, 0x04, 0x6f, 0x68, 0x00, 0x04, 0x6f, 0x98, 0x00, 0x04, 0x6f, 0xf4, 0x00, 0x04, 0x70, 0x8c, 0x00, 0x04, 0x71, 0x28, 0x00, 0x04, 0x71, 0x60, 0x00, 0x04, 0x71, 0xd4, 0x00, 0x04, 0x72, 0x10, 0x00, 0x04, 0x72, 0x78, 0x00, 0x04, 0x72, 0xcc, 0x00, 0x04, 0x73, 0x14, 0x00, 0x04, 0x73, 0xb8, 0x00, 0x04, 0x74, 0x54, 0x00, 0x04, 0x74, 0xcc, 0x00, 0x04, 0x75, 0x68, 0x00, 0x04, 0x75, 0xdc, 0x00, 0x04, 0x76, 0x44, 0x00, 0x04, 0x77, 0x0c, 0x00, 0x04, 0x77, 0x80, 0x00, 0x04, 0x77, 0xb8, 0x00, 0x04, 0x78, 0x14, 0x00, 0x04, 0x78, 0x58, 0x00, 0x04, 0x78, 0xa4, 0x00, 0x04, 0x79, 0x60, 0x00, 0x04, 0x79, 0xd4, 0x00, 0x04, 0x7a, 0x5c, 0x00, 0x04, 0x7a, 0xf8, 0x00, 0x04, 0x7b, 0x94, 0x00, 0x04, 0x7b, 0xe0, 0x00, 0x04, 0x7c, 0xac, 0x00, 0x04, 0x7d, 0x08, 0x00, 0x04, 0x7d, 0x7c, 0x00, 0x04, 0x7d, 0xb8, 0x00, 0x04, 0x7e, 0x14, 0x00, 0x04, 0x7e, 0x68, 0x00, 0x04, 0x7e, 0xb8, 0x00, 0x04, 0x7e, 0xfc, 0x00, 0x04, 0x7f, 0x0c, 0x00, 0x04, 0x7f, 0x1c, 0x00, 0x04, 0x7f, 0x2c, 0x00, 0x04, 0x7f, 0x3c, 0x00, 0x04, 0x7f, 0x4c, 0x00, 0x04, 0x7f, 0x5c, 0x00, 0x04, 0x7f, 0x6c, 0x00, 0x04, 0x7f, 0x7c, 0x00, 0x04, 0x7f, 0x8c, 0x00, 0x04, 0x7f, 0x9c, 0x00, 0x04, 0x7f, 0xac, 0x00, 0x04, 0x7f, 0xbc, 0x00, 0x04, 0x7f, 0xcc, 0x00, 0x04, 0x7f, 0xdc, 0x00, 0x04, 0x7f, 0xec, 0x00, 0x04, 0x7f, 0xfc, 0x00, 0x04, 0x80, 0x0c, 0x00, 0x04, 0x80, 0x1c, 0x00, 0x04, 0x80, 0x2c, 0x00, 0x04, 0x80, 0x3c, 0x00, 0x04, 0x80, 0x4c, 0x00, 0x04, 0x80, 0x5c, 0x00, 0x04, 0x80, 0x6c, 0x00, 0x04, 0x80, 0x7c, 0x00, 0x04, 0x80, 0x8c, 0x00, 0x04, 0x80, 0x9c, 0x00, 0x04, 0x80, 0xac, 0x00, 0x04, 0x80, 0xbc, 0x00, 0x04, 0x80, 0xcc, 0x00, 0x04, 0x80, 0xdc, 0x00, 0x04, 0x80, 0xec, 0x00, 0x04, 0x80, 0xfc, 0x00, 0x04, 0x81, 0x0c, 0x00, 0x04, 0x81, 0x1c, 0x00, 0x04, 0x81, 0x2c, 0x00, 0x04, 0x81, 0x3c, 0x00, 0x04, 0x81, 0x4c, 0x00, 0x04, 0x81, 0x5c, 0x00, 0x04, 0x81, 0x6c, 0x00, 0x04, 0x81, 0x7c, 0x00, 0x04, 0x81, 0x8c, 0x00, 0x04, 0x81, 0x9c, 0x00, 0x04, 0x81, 0xac, 0x00, 0x04, 0x81, 0xbc, 0x00, 0x04, 0x81, 0xcc, 0x00, 0x04, 0x81, 0xdc, 0x00, 0x04, 0x81, 0xec, 0x00, 0x04, 0x81, 0xfc, 0x00, 0x04, 0x82, 0x0c, 0x00, 0x04, 0x82, 0x1c, 0x00, 0x04, 0x82, 0x2c, 0x00, 0x04, 0x82, 0x3c, 0x00, 0x04, 0x82, 0xa8, 0x00, 0x04, 0x82, 0xe8, 0x00, 0x04, 0x83, 0x74, 0x00, 0x04, 0x84, 0x04, 0x00, 0x04, 0x84, 0x50, 0x00, 0x04, 0x84, 0xc0, 0x00, 0x04, 0x85, 0x48, 0x00, 0x04, 0x85, 0x84, 0x00, 0x04, 0x86, 0x5c, 0x00, 0x04, 0x86, 0xe8, 0x00, 0x04, 0x86, 0xf8, 0x00, 0x04, 0x87, 0x08, 0x00, 0x04, 0x87, 0x18, 0x00, 0x04, 0x87, 0x28, 0x00, 0x04, 0x87, 0x38, 0x00, 0x04, 0x87, 0x48, 0x00, 0x04, 0x87, 0x58, 0x00, 0x04, 0x87, 0x68, 0x00, 0x04, 0x87, 0x78, 0x00, 0x04, 0x87, 0x88, 0x00, 0x04, 0x87, 0xb4, 0x00, 0x04, 0x87, 0xec, 0x00, 0x04, 0x88, 0x68, 0x00, 0x04, 0x89, 0x24, 0x00, 0x04, 0x8a, 0x20, 0x00, 0x04, 0x8b, 0x5c, 0x00, 0x04, 0x8c, 0xd8, 0x00, 0x04, 0x8e, 0x8c, 0x00, 0x04, 0x8f, 0x08, 0x00, 0x04, 0x8f, 0xc4, 0x00, 0x04, 0x90, 0xc4, 0x00, 0x04, 0x92, 0x00, 0x00, 0x04, 0x93, 0x7c, 0x00, 0x04, 0x95, 0x38, 0x00, 0x04, 0x97, 0x2c, 0x00, 0x04, 0x97, 0xe8, 0x00, 0x04, 0x98, 0xe4, 0x00, 0x04, 0x9a, 0x20, 0x00, 0x04, 0x9b, 0x9c, 0x00, 0x04, 0x9d, 0x4c, 0x00, 0x04, 0x9f, 0x48, 0x00, 0x04, 0xa1, 0x7c, 0x00, 0x04, 0xa2, 0x78, 0x00, 0x04, 0xa3, 0xb4, 0x00, 0x04, 0xa5, 0x34, 0x00, 0x04, 0xa6, 0xf0, 0x00, 0x04, 0xa8, 0xec, 0x00, 0x04, 0xab, 0x28, 0x00, 0x04, 0xad, 0x9c, 0x00, 0x04, 0xae, 0xd0, 0x00, 0x04, 0xb0, 0x44, 0x00, 0x04, 0xb2, 0x04, 0x00, 0x04, 0xb4, 0x00, 0x00, 0x04, 0xb6, 0x3c, 0x00, 0x04, 0xb8, 0xb8, 0x00, 0x04, 0xbb, 0x6c, 0x00, 0x04, 0xbc, 0xe4, 0x00, 0x04, 0xbe, 0xa0, 0x00, 0x04, 0xc0, 0x9c, 0x00, 0x04, 0xc2, 0xd8, 0x00, 0x04, 0xc5, 0x54, 0x00, 0x04, 0xc8, 0x10, 0x00, 0x04, 0xcb, 0x04, 0x00, 0x04, 0xcc, 0xc4, 0x00, 0x04, 0xce, 0xcc, 0x00, 0x04, 0xd1, 0x14, 0x00, 0x04, 0xd3, 0x9c, 0x00, 0x04, 0xd6, 0x60, 0x00, 0x04, 0xd9, 0x64, 0x00, 0x04, 0xdc, 0x94, 0x00, 0x04, 0xdc, 0xc0, 0x00, 0x04, 0xdc, 0xf8, 0x00, 0x04, 0xdd, 0x74, 0x00, 0x04, 0xde, 0x30, 0x00, 0x04, 0xdf, 0x28, 0x00, 0x04, 0xe0, 0x64, 0x00, 0x04, 0xe1, 0xe0, 0x00, 0x04, 0xe3, 0x94, 0x00, 0x04, 0xe4, 0x10, 0x00, 0x04, 0xe4, 0xcc, 0x00, 0x04, 0xe5, 0xcc, 0x00, 0x04, 0xe7, 0x08, 0x00, 0x04, 0xe8, 0x84, 0x00, 0x04, 0xea, 0x40, 0x00, 0x04, 0xec, 0x34, 0x00, 0x04, 0xec, 0xf0, 0x00, 0x04, 0xed, 0xec, 0x00, 0x04, 0xef, 0x28, 0x00, 0x04, 0xf0, 0xa0, 0x00, 0x04, 0xf2, 0x5c, 0x00, 0x04, 0xf4, 0x58, 0x00, 0x04, 0xf6, 0x8c, 0x00, 0x04, 0xf7, 0x84, 0x00, 0x04, 0xf8, 0xc0, 0x00, 0x04, 0xfa, 0x3c, 0x00, 0x04, 0xfb, 0xf8, 0x00, 0x04, 0xfd, 0xf0, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x05, 0x02, 0x9c, 0x00, 0x05, 0x03, 0xd0, 0x00, 0x05, 0x05, 0x44, 0x00, 0x05, 0x07, 0x00, 0x00, 0x05, 0x08, 0xfc, 0x00, 0x05, 0x0b, 0x38, 0x00, 0x05, 0x0d, 0xa4, 0x00, 0x05, 0x10, 0x58, 0x00, 0x05, 0x11, 0xd0, 0x00, 0x05, 0x13, 0x8c, 0x00, 0x05, 0x15, 0x7c, 0x00, 0x05, 0x17, 0xb8, 0x00, 0x05, 0x1a, 0x34, 0x00, 0x05, 0x1c, 0xf0, 0x00, 0x05, 0x1f, 0xe4, 0x00, 0x05, 0x21, 0xa8, 0x00, 0x05, 0x23, 0xb0, 0x00, 0x05, 0x25, 0xf8, 0x00, 0x05, 0x28, 0x7c, 0x00, 0x05, 0x2b, 0x40, 0x00, 0x05, 0x2e, 0x30, 0x00, 0x05, 0x31, 0x60, 0x00, 0x05, 0x31, 0xbc, 0x00, 0x05, 0x32, 0x78, 0x00, 0x05, 0x33, 0x54, 0x00, 0x05, 0x34, 0x50, 0x00, 0x05, 0x35, 0x10, 0x00, 0x05, 0x35, 0xfc, 0x00, 0x05, 0x37, 0x14, 0x00, 0x05, 0x37, 0xc0, 0x00, 0x05, 0x38, 0xf4, 0x00, 0x05, 0x3a, 0x08, 0x00, 0x05, 0x3a, 0xf8, 0x00, 0x05, 0x3b, 0xac, 0x00, 0x05, 0x3c, 0x84, 0x00, 0x05, 0x3d, 0x64, 0x00, 0x05, 0x3e, 0x20, 0x00, 0x05, 0x3e, 0xd8, 0x00, 0x05, 0x3f, 0xb0, 0x00, 0x05, 0x40, 0xa8, 0x00, 0x05, 0x41, 0x64, 0x00, 0x05, 0x42, 0x4c, 0x00, 0x05, 0x43, 0x60, 0x00, 0x05, 0x44, 0x08, 0x00, 0x05, 0x45, 0x38, 0x00, 0x05, 0x46, 0x48, 0x00, 0x05, 0x47, 0x34, 0x00, 0x05, 0x47, 0xe4, 0x00, 0x05, 0x48, 0xb8, 0x00, 0x05, 0x49, 0x94, 0x00, 0x05, 0x4a, 0x4c, 0x00, 0x05, 0x4a, 0xd8, 0x00, 0x05, 0x4b, 0x88, 0x00, 0x05, 0x4c, 0x58, 0x00, 0x05, 0x4c, 0xe8, 0x00, 0x05, 0x4d, 0xa4, 0x00, 0x05, 0x4e, 0x8c, 0x00, 0x05, 0x4f, 0x0c, 0x00, 0x05, 0x50, 0x14, 0x00, 0x05, 0x50, 0xfc, 0x00, 0x05, 0x51, 0xc0, 0x00, 0x05, 0x52, 0x48, 0x00, 0x05, 0x52, 0xf4, 0x00, 0x05, 0x53, 0xa8, 0x00, 0x05, 0x54, 0x34, 0x00, 0x05, 0x54, 0xb0, 0x00, 0x05, 0x55, 0x84, 0x00, 0x05, 0x56, 0x7c, 0x00, 0x05, 0x57, 0x94, 0x00, 0x05, 0x58, 0x6c, 0x00, 0x05, 0x59, 0x70, 0x00, 0x05, 0x5a, 0xa0, 0x00, 0x05, 0x5b, 0x68, 0x00, 0x05, 0x5c, 0xb8, 0x00, 0x05, 0x5d, 0xe8, 0x00, 0x05, 0x5e, 0xf4, 0x00, 0x05, 0x5f, 0xc4, 0x00, 0x05, 0x60, 0xb8, 0x00, 0x05, 0x61, 0xb4, 0x00, 0x05, 0x62, 0x88, 0x00, 0x05, 0x63, 0x28, 0x00, 0x05, 0x65, 0x30, 0x00, 0x05, 0x68, 0x14, 0x00, 0x05, 0x6a, 0x3c, 0x00, 0x05, 0x6c, 0x58, 0x00, 0x05, 0x6d, 0x58, 0x00, 0x05, 0x6e, 0x58, 0x00, 0x05, 0x6f, 0xf0, 0x00, 0x05, 0x70, 0xd0, 0x00, 0x05, 0x71, 0xb0, 0x00, 0x05, 0x72, 0xb4, 0x00, 0x05, 0x73, 0x88, 0x00, 0x05, 0x74, 0xc0, 0x00, 0x05, 0x75, 0xcc, 0x00, 0x05, 0x76, 0xa4, 0x00, 0x05, 0x77, 0x84, 0x00, 0x05, 0x78, 0x90, 0x00, 0x05, 0x79, 0x70, 0x00, 0x05, 0x7a, 0x98, 0x00, 0x05, 0x7b, 0x6c, 0x00, 0x05, 0x7c, 0x10, 0x00, 0x05, 0x7c, 0xc8, 0x00, 0x05, 0x7d, 0x5c, 0x00, 0x05, 0x7e, 0x1c, 0x00, 0x05, 0x7f, 0x10, 0x00, 0x05, 0x7f, 0xc8, 0x00, 0x05, 0x80, 0x80, 0x00, 0x05, 0x81, 0x74, 0x00, 0x05, 0x82, 0x48, 0x00, 0x05, 0x83, 0x5c, 0x00, 0x05, 0x84, 0x30, 0x00, 0x05, 0x85, 0x04, 0x00, 0x05, 0x85, 0xdc, 0x00, 0x05, 0x86, 0xac, 0x00, 0x05, 0x87, 0x78, 0x00, 0x05, 0x88, 0x78, 0x00, 0x05, 0x89, 0xa8, 0x00, 0x05, 0x8a, 0xa8, 0x00, 0x05, 0x8b, 0xdc, 0x00, 0x05, 0x8c, 0xec, 0x00, 0x05, 0x8d, 0xc0, 0x00, 0x05, 0x8e, 0xa0, 0x00, 0x05, 0x8f, 0x80, 0x00, 0x05, 0x90, 0x7c, 0x00, 0x05, 0x92, 0x78, 0x00, 0x05, 0x93, 0x5c, 0x00, 0x05, 0x94, 0x70, 0x00, 0x05, 0x95, 0x44, 0x00, 0x05, 0x96, 0x90, 0x00, 0x05, 0x97, 0x54, 0x00, 0x05, 0x98, 0x34, 0x00, 0x05, 0x99, 0x30, 0x00, 0x05, 0x9a, 0xf8, 0x00, 0x05, 0x9c, 0x38, 0x00, 0x05, 0x9d, 0xb4, 0x00, 0x05, 0x9e, 0xd4, 0x00, 0x05, 0x9f, 0xa8, 0x00, 0x05, 0xa0, 0x50, 0x00, 0x05, 0xa1, 0x30, 0x00, 0x05, 0xa3, 0x74, 0x00, 0x05, 0xa5, 0xf4, 0x00, 0x05, 0xa8, 0x60, 0x00, 0x05, 0xaa, 0x68, 0x00, 0x05, 0xac, 0xa0, 0x00, 0x05, 0xae, 0xdc, 0x00, 0x05, 0xb1, 0x2c, 0x00, 0x05, 0xb2, 0xec, 0x00, 0x05, 0xb4, 0xa8, 0x00, 0x05, 0xb4, 0xc4, 0x00, 0x05, 0xb4, 0xec, 0x00, 0x05, 0xb5, 0x08, 0x00, 0x05, 0xb5, 0x64, 0x00, 0x05, 0xb5, 0x84, 0x00, 0x05, 0xb5, 0xa8, 0x00, 0x05, 0xb5, 0xd0, 0x00, 0x05, 0xb6, 0x04, 0x00, 0x05, 0xb6, 0x38, 0x00, 0x05, 0xb6, 0x54, 0x00, 0x05, 0xb6, 0x7c, 0x00, 0x05, 0xb6, 0xa8, 0x00, 0x05, 0xb6, 0xc0, 0x00, 0x05, 0xb6, 0xe4, 0x00, 0x05, 0xb7, 0x14, 0x00, 0x05, 0xb7, 0x44, 0x00, 0x05, 0xb7, 0x68, 0x00, 0x05, 0xb7, 0xa0, 0x00, 0x05, 0xb8, 0x18, 0x00, 0x05, 0xb8, 0x48, 0x00, 0x05, 0xb8, 0x88, 0x00, 0x05, 0xb9, 0x44, 0x00, 0x05, 0xb9, 0xe0, 0x00, 0x05, 0xba, 0x80, 0x00, 0x05, 0xbb, 0x44, 0x00, 0x05, 0xbb, 0x54, 0x00, 0x05, 0xbb, 0x64, 0x00, 0x05, 0xbb, 0x7c, 0x00, 0x05, 0xbb, 0x94, 0x00, 0x05, 0xbb, 0xe4, 0x00, 0x05, 0xbc, 0x04, 0x00, 0x05, 0xbc, 0x24, 0x00, 0x05, 0xbc, 0x44, 0x00, 0x05, 0xbc, 0x5c, 0x00, 0x05, 0xbc, 0x74, 0x00, 0x05, 0xbc, 0x8c, 0x00, 0x05, 0xbd, 0x64, 0x00, 0x05, 0xbe, 0x10, 0x00, 0x05, 0xbe, 0xd8, 0x00, 0x05, 0xbf, 0x84, 0x00, 0x05, 0xc0, 0x00, 0x00, 0x05, 0xc0, 0x98, 0x00, 0x05, 0xc1, 0x4c, 0x00, 0x05, 0xc1, 0xd4, 0x00, 0x05, 0xc2, 0x78, 0x00, 0x05, 0xc3, 0x3c, 0x00, 0x05, 0xc3, 0xd0, 0x00, 0x05, 0xc4, 0x80, 0x00, 0x05, 0xc4, 0xa0, 0x00, 0x05, 0xc4, 0xe8, 0x00, 0x05, 0xc5, 0x14, 0x00, 0x05, 0xc5, 0x64, 0x00, 0x05, 0xc5, 0x80, 0x00, 0x05, 0xc5, 0x9c, 0x00, 0x05, 0xc5, 0xb8, 0x00, 0x05, 0xc5, 0xd4, 0x00, 0x05, 0xc5, 0xf0, 0x00, 0x05, 0xc6, 0x0c, 0x00, 0x05, 0xc6, 0x28, 0x00, 0x05, 0xc6, 0x44, 0x00, 0x05, 0xc6, 0x60, 0x00, 0x05, 0xc6, 0x7c, 0x00, 0x05, 0xc6, 0x98, 0x00, 0x05, 0xc6, 0xb4, 0x00, 0x05, 0xc6, 0xd0, 0x00, 0x05, 0xc6, 0xec, 0x00, 0x05, 0xc7, 0x08, 0x00, 0x05, 0xc7, 0x24, 0x00, 0x05, 0xc7, 0x40, 0x00, 0x05, 0xc7, 0x5c, 0x00, 0x05, 0xc7, 0x78, 0x00, 0x05, 0xc7, 0x94, 0x00, 0x05, 0xc7, 0xac, 0x00, 0x05, 0xc7, 0xc8, 0x00, 0x05, 0xc8, 0x00, 0x00, 0x05, 0xc8, 0x70, 0x00, 0x05, 0xc8, 0xc4, 0x00, 0x05, 0xc9, 0x4c, 0x00, 0x05, 0xc9, 0x98, 0x00, 0x05, 0xc9, 0xf4, 0x00, 0x05, 0xca, 0xb0, 0x00, 0x05, 0xcb, 0x10, 0x00, 0x05, 0xcb, 0x80, 0x00, 0x05, 0xcb, 0xec, 0x00, 0x05, 0xcc, 0x18, 0x00, 0x05, 0xcc, 0x90, 0x00, 0x05, 0xcc, 0xa0, 0x00, 0x05, 0xcc, 0xb0, 0x00, 0x05, 0xcc, 0xc8, 0x00, 0x05, 0xcc, 0xf4, 0x00, 0x05, 0xcd, 0x4c, 0x00, 0x05, 0xcd, 0x64, 0x00, 0x05, 0xcd, 0x7c, 0x00, 0x05, 0xcd, 0xa0, 0x00, 0x05, 0xcd, 0xcc, 0x00, 0x05, 0xcd, 0xe8, 0x00, 0x05, 0xce, 0x80, 0x00, 0x05, 0xcf, 0x8c, 0x00, 0x05, 0xd0, 0x24, 0x00, 0x05, 0xd0, 0xac, 0x00, 0x05, 0xd1, 0xa4, 0x00, 0x05, 0xd2, 0x2c, 0x00, 0x05, 0xd2, 0x8c, 0x00, 0x05, 0xd3, 0x5c, 0x00, 0x05, 0xd3, 0x78, 0x00, 0x05, 0xd3, 0x9c, 0x00, 0x05, 0xd3, 0xbc, 0x00, 0x05, 0xd4, 0x0c, 0x00, 0x05, 0xd4, 0x64, 0x00, 0x05, 0xd4, 0xb4, 0x00, 0x05, 0xd4, 0xe8, 0x00, 0x05, 0xd5, 0x20, 0x00, 0x05, 0xd5, 0x50, 0x00, 0x05, 0xd5, 0x80, 0x00, 0x05, 0xd5, 0xb0, 0x00, 0x05, 0xd5, 0xdc, 0x00, 0x05, 0xd6, 0x08, 0x00, 0x05, 0xd6, 0x38, 0x00, 0x05, 0xd6, 0x60, 0x00, 0x05, 0xd6, 0x88, 0x00, 0x05, 0xd6, 0xb0, 0x00, 0x05, 0xd6, 0xd8, 0x00, 0x05, 0xd7, 0x44, 0x00, 0x05, 0xd7, 0xb4, 0x00, 0x05, 0xd8, 0x20, 0x00, 0x05, 0xd8, 0x54, 0x00, 0x05, 0xd8, 0x88, 0x00, 0x05, 0xd8, 0xbc, 0x00, 0x05, 0xd9, 0x1c, 0x00, 0x05, 0xd9, 0x84, 0x00, 0x05, 0xd9, 0xe8, 0x00, 0x05, 0xda, 0x18, 0x00, 0x05, 0xda, 0x4c, 0x00, 0x05, 0xda, 0x7c, 0x00, 0x05, 0xda, 0xac, 0x00, 0x05, 0xda, 0xe0, 0x00, 0x05, 0xdb, 0x10, 0x00, 0x05, 0xdb, 0x64, 0x00, 0x05, 0xdb, 0xb8, 0x00, 0x05, 0xdc, 0x10, 0x00, 0x05, 0xdc, 0x5c, 0x00, 0x05, 0xdc, 0xac, 0x00, 0x05, 0xdc, 0xf8, 0x00, 0x05, 0xdd, 0x20, 0x00, 0x05, 0xdd, 0x4c, 0x00, 0x05, 0xdd, 0x74, 0x00, 0x05, 0xdd, 0xe8, 0x00, 0x05, 0xde, 0x60, 0x00, 0x05, 0xde, 0xd0, 0x00, 0x05, 0xdf, 0x04, 0x00, 0x05, 0xdf, 0x3c, 0x00, 0x05, 0xdf, 0x70, 0x00, 0x05, 0xdf, 0xc0, 0x00, 0x05, 0xe0, 0x14, 0x00, 0x05, 0xe0, 0x64, 0x00, 0x05, 0xe0, 0x94, 0x00, 0x05, 0xe0, 0xc8, 0x00, 0x05, 0xe0, 0xf8, 0x00, 0x05, 0xe1, 0x2c, 0x00, 0x05, 0xe1, 0x64, 0x00, 0x05, 0xe1, 0x98, 0x00, 0x05, 0xe2, 0x08, 0x00, 0x05, 0xe2, 0x7c, 0x00, 0x05, 0xe2, 0xec, 0x00, 0x05, 0xe3, 0x20, 0x00, 0x05, 0xe3, 0x58, 0x00, 0x05, 0xe3, 0x8c, 0x00, 0x05, 0xe3, 0xf4, 0x00, 0x05, 0xe4, 0x60, 0x00, 0x05, 0xe4, 0xc8, 0x00, 0x05, 0xe4, 0xf4, 0x00, 0x05, 0xe5, 0x24, 0x00, 0x05, 0xe5, 0x50, 0x00, 0x05, 0xe5, 0x84, 0x00, 0x05, 0xe5, 0xbc, 0x00, 0x05, 0xe5, 0xf0, 0x00, 0x05, 0xe6, 0x74, 0x00, 0x05, 0xe6, 0xfc, 0x00, 0x05, 0xe7, 0x80, 0x00, 0x05, 0xe7, 0xac, 0x00, 0x05, 0xe7, 0xdc, 0x00, 0x05, 0xe8, 0x08, 0x00, 0x05, 0xe8, 0x38, 0x00, 0x05, 0xe8, 0x6c, 0x00, 0x05, 0xe8, 0x9c, 0x00, 0x05, 0xe8, 0xd8, 0x00, 0x05, 0xe9, 0x18, 0x00, 0x05, 0xe9, 0x54, 0x00, 0x05, 0xe9, 0xd4, 0x00, 0x05, 0xea, 0x58, 0x00, 0x05, 0xea, 0xd8, 0x00, 0x05, 0xeb, 0x60, 0x00, 0x05, 0xeb, 0xec, 0x00, 0x05, 0xec, 0x74, 0x00, 0x05, 0xec, 0x88, 0x00, 0x05, 0xec, 0xac, 0x00, 0x05, 0xec, 0xd0, 0x00, 0x05, 0xec, 0xf4, 0x00, 0x05, 0xed, 0x18, 0x00, 0x05, 0xed, 0x3c, 0x00, 0x05, 0xed, 0x60, 0x00, 0x05, 0xed, 0x84, 0x00, 0x05, 0xed, 0xa8, 0x00, 0x05, 0xed, 0xd8, 0x00, 0x05, 0xee, 0x14, 0x00, 0x05, 0xee, 0x50, 0x00, 0x05, 0xee, 0xb8, 0x00, 0x05, 0xef, 0x60, 0x00, 0x05, 0xef, 0xd0, 0x00, 0x05, 0xf0, 0x90, 0x00, 0x05, 0xf1, 0x18, 0x00, 0x05, 0xf1, 0xac, 0x00, 0x05, 0xf2, 0x44, 0x00, 0x05, 0xf2, 0xa4, 0x00, 0x05, 0xf3, 0x14, 0x00, 0x05, 0xf3, 0x80, 0x00, 0x05, 0xf4, 0x04, 0x00, 0x05, 0xf4, 0xec, 0x00, 0x05, 0xf5, 0x98, 0x00, 0x05, 0xf6, 0x54, 0x00, 0x05, 0xf7, 0x48, 0x00, 0x05, 0xf7, 0xfc, 0x00, 0x05, 0xf8, 0xc0, 0x00, 0x05, 0xf9, 0xd8, 0x00, 0x05, 0xfa, 0xb0, 0x00, 0x05, 0xfb, 0x98, 0x00, 0x05, 0xfc, 0x8c, 0x00, 0x05, 0xfd, 0x30, 0x00, 0x05, 0xfd, 0xe8, 0x00, 0x05, 0xfe, 0xe4, 0x00, 0x05, 0xff, 0x94, 0x00, 0x06, 0x00, 0x58, 0x00, 0x06, 0x00, 0xfc, 0x00, 0x06, 0x01, 0x88, 0x00, 0x06, 0x02, 0x2c, 0x00, 0x06, 0x02, 0xd4, 0x00, 0x06, 0x03, 0x50, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x04, 0x18, 0x00, 0x06, 0x04, 0x30, 0x00, 0x06, 0x04, 0x48, 0x00, 0x06, 0x04, 0x68, 0x00, 0x06, 0x04, 0x88, 0x00, 0x06, 0x04, 0xa8, 0x00, 0x06, 0x04, 0xc0, 0x00, 0x06, 0x04, 0xd8, 0x00, 0x06, 0x04, 0xf0, 0x00, 0x06, 0x05, 0x08, 0x00, 0x06, 0x05, 0x20, 0x00, 0x06, 0x05, 0x38, 0x00, 0x06, 0x05, 0x50, 0x00, 0x06, 0x05, 0x68, 0x00, 0x06, 0x05, 0x80, 0x00, 0x06, 0x06, 0x2c, 0x00, 0x06, 0x06, 0x9c, 0x00, 0x06, 0x07, 0x20, 0x00, 0x06, 0x08, 0x10, 0x00, 0x06, 0x08, 0xc0, 0x00, 0x06, 0x09, 0x8c, 0x00, 0x06, 0x0a, 0x64, 0x00, 0x06, 0x0a, 0xdc, 0x00, 0x06, 0x0b, 0x70, 0x00, 0x06, 0x0c, 0x60, 0x00, 0x06, 0x0c, 0xec, 0x00, 0x06, 0x0d, 0x94, 0x00, 0x06, 0x0d, 0xf8, 0x00, 0x06, 0x0e, 0x5c, 0x00, 0x06, 0x0e, 0xc0, 0x00, 0x06, 0x0e, 0xf8, 0x00, 0x06, 0x0f, 0x30, 0x00, 0x06, 0x0f, 0x68, 0x00, 0x06, 0x0f, 0xac, 0x00, 0x06, 0x0f, 0xf0, 0x00, 0x06, 0x10, 0x34, 0x00, 0x06, 0x10, 0xb0, 0x00, 0x06, 0x10, 0xf0, 0x00, 0x06, 0x11, 0x40, 0x00, 0x06, 0x11, 0xd4, 0x00, 0x06, 0x12, 0x28, 0x00, 0x06, 0x12, 0x8c, 0x00, 0x06, 0x13, 0x20, 0x00, 0x06, 0x13, 0x78, 0x00, 0x06, 0x13, 0xdc, 0x00, 0x06, 0x14, 0x6c, 0x00, 0x06, 0x14, 0x8c, 0x00, 0x06, 0x14, 0xac, 0x00, 0x06, 0x15, 0x74, 0x00, 0x06, 0x15, 0x94, 0x00, 0x06, 0x15, 0xb4, 0x00, 0x06, 0x16, 0x50, 0x00, 0x06, 0x16, 0x68, 0x00, 0x06, 0x16, 0x80, 0x00, 0x01, 0x00, 0x00, 0x12, 0x0e, 0x03, 0x54, 0x00, 0x2b, 0x00, 0x68, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x10, 0x00, 0x99, 0x00, 0x08, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1a, 0x01, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x32, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x19, 0x01, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x02, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x19, 0x02, 0x5c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x19, 0x02, 0xaa, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x02, 0xde, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x16, 0x03, 0x19, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x11, 0x03, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x1d, 0x03, 0xa2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x12, 0x9d, 0x28, 0xfc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x34, 0x3c, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0f, 0x3c, 0x59, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x09, 0x3c, 0x7d, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x32, 0x01, 0xcb, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x08, 0x02, 0x19, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x32, 0x02, 0x28, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x32, 0x02, 0x76, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x18, 0x02, 0xc4, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x2c, 0x02, 0xeb, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x08, 0x00, 0x22, 0x03, 0x30, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x0b, 0x00, 0x3a, 0x03, 0x66, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x0d, 0x25, 0x3a, 0x03, 0xc0, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x0e, 0x00, 0x68, 0x3b, 0x9a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x10, 0x00, 0x1e, 0x3c, 0x39, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x11, 0x00, 0x12, 0x3c, 0x69, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x41, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x52, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x52, 0x00, 0x65, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x36, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x54, 0x00, 0x61, 0x00, 0x76, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x42, 0x00, 0x61, 0x00, 0x68, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x41, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x52, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x52, 0x00, 0x65, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x56, 0x00, 0x75, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x75, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x0a, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x33, 0x20, 0x62, 0x79, 0x20, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x62, 0x79, 0x20, 0x54, 0x61, 0x76, 0x6d, 0x6a, 0x6f, 0x6e, 0x67, 0x20, 0x42, 0x61, 0x68, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x44, 0x65, 0x6a, 0x61, 0x56, 0x75, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0a, 0x00, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x56, 0x00, 0x75, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x47, 0x00, 0x43, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x44, 0x65, 0x6a, 0x61, 0x56, 0x75, 0x20, 0x4c, 0x47, 0x43, 0x20, 0x53, 0x61, 0x6e, 0x73, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x00, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x6b, 0x00, 0x00, 0x42, 0x6f, 0x6f, 0x6b, 0x00, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x56, 0x00, 0x75, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x47, 0x00, 0x43, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x44, 0x65, 0x6a, 0x61, 0x56, 0x75, 0x20, 0x4c, 0x47, 0x43, 0x20, 0x53, 0x61, 0x6e, 0x73, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x00, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x56, 0x00, 0x75, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x47, 0x00, 0x43, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x44, 0x65, 0x6a, 0x61, 0x56, 0x75, 0x20, 0x4c, 0x47, 0x43, 0x20, 0x53, 0x61, 0x6e, 0x73, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x00, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x33, 0x00, 0x34, 0x00, 0x00, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x33, 0x34, 0x00, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x56, 0x00, 0x75, 0x00, 0x4c, 0x00, 0x47, 0x00, 0x43, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x44, 0x65, 0x6a, 0x61, 0x56, 0x75, 0x4c, 0x47, 0x43, 0x53, 0x61, 0x6e, 0x73, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x00, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x56, 0x00, 0x75, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x00, 0x44, 0x65, 0x6a, 0x61, 0x56, 0x75, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x65, 0x61, 0x6d, 0x00, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x76, 0x00, 0x75, 0x00, 0x2e, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x67, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x74, 0x00, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x6a, 0x61, 0x76, 0x75, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x00, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x28, 0x00, 0x73, 0x00, 0x65, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x29, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x56, 0x00, 0x75, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x75, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x47, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x70, 0x00, 0x68, 0x00, 0x73, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x66, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x54, 0x00, 0x61, 0x00, 0x76, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x42, 0x00, 0x61, 0x00, 0x68, 0x00, 0x20, 0x00, 0x28, 0x00, 0x73, 0x00, 0x65, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x29, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x0a, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x41, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x52, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x52, 0x00, 0x65, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x20, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x50, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x65, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x66, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x74, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x28, 0x00, 0x22, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x22, 0x00, 0x29, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x69, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x22, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x22, 0x00, 0x29, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x62, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x64, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x72, 0x00, 0x67, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x75, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x62, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x2f, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x73, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x69, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x74, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x77, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x66, 0x00, 0x75, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x73, 0x00, 0x75, 0x00, 0x62, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x65, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x0a, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x64, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x69, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x79, 0x00, 0x70, 0x00, 0x65, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x64, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x0a, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x73, 0x00, 0x69, 0x00, 0x67, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x70, 0x00, 0x68, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x64, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x70, 0x00, 0x68, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x64, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x20, 0x00, 0x69, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x65, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x64, 0x00, 0x73, 0x00, 0x20, 0x00, 0x22, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x22, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x64, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x76, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x0a, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x61, 0x00, 0x74, 0x00, 0x20, 0x00, 0x68, 0x00, 0x61, 0x00, 0x73, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x62, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x22, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x22, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x75, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x0a, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x79, 0x00, 0x70, 0x00, 0x65, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x66, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x53, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x54, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x45, 0x00, 0x20, 0x00, 0x49, 0x00, 0x53, 0x00, 0x20, 0x00, 0x50, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x56, 0x00, 0x49, 0x00, 0x44, 0x00, 0x45, 0x00, 0x44, 0x00, 0x20, 0x00, 0x22, 0x00, 0x41, 0x00, 0x53, 0x00, 0x20, 0x00, 0x49, 0x00, 0x53, 0x00, 0x22, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x57, 0x00, 0x49, 0x00, 0x54, 0x00, 0x48, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x54, 0x00, 0x20, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x52, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x59, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x20, 0x00, 0x4b, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x45, 0x00, 0x58, 0x00, 0x50, 0x00, 0x52, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00, 0x0a, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x50, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x45, 0x00, 0x44, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x43, 0x00, 0x4c, 0x00, 0x55, 0x00, 0x44, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x20, 0x00, 0x42, 0x00, 0x55, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x49, 0x00, 0x54, 0x00, 0x45, 0x00, 0x44, 0x00, 0x20, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x20, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x52, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x49, 0x00, 0x45, 0x00, 0x53, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x52, 0x00, 0x43, 0x00, 0x48, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x41, 0x00, 0x42, 0x00, 0x49, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x54, 0x00, 0x59, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x49, 0x00, 0x54, 0x00, 0x4e, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x41, 0x00, 0x20, 0x00, 0x50, 0x00, 0x41, 0x00, 0x52, 0x00, 0x54, 0x00, 0x49, 0x00, 0x43, 0x00, 0x55, 0x00, 0x4c, 0x00, 0x41, 0x00, 0x52, 0x00, 0x20, 0x00, 0x50, 0x00, 0x55, 0x00, 0x52, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x45, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x52, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x45, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x59, 0x00, 0x52, 0x00, 0x49, 0x00, 0x47, 0x00, 0x48, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x50, 0x00, 0x41, 0x00, 0x54, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x52, 0x00, 0x41, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x20, 0x00, 0x52, 0x00, 0x49, 0x00, 0x47, 0x00, 0x48, 0x00, 0x54, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x20, 0x00, 0x45, 0x00, 0x56, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x53, 0x00, 0x48, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x20, 0x00, 0x42, 0x00, 0x49, 0x00, 0x54, 0x00, 0x53, 0x00, 0x54, 0x00, 0x52, 0x00, 0x45, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x20, 0x00, 0x47, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x42, 0x00, 0x45, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x41, 0x00, 0x42, 0x00, 0x4c, 0x00, 0x45, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4c, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x44, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x47, 0x00, 0x45, 0x00, 0x53, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x41, 0x00, 0x42, 0x00, 0x49, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x54, 0x00, 0x59, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x43, 0x00, 0x4c, 0x00, 0x55, 0x00, 0x44, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x0a, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x20, 0x00, 0x47, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x45, 0x00, 0x52, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x53, 0x00, 0x50, 0x00, 0x45, 0x00, 0x43, 0x00, 0x49, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x49, 0x00, 0x52, 0x00, 0x45, 0x00, 0x43, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x43, 0x00, 0x49, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x53, 0x00, 0x45, 0x00, 0x51, 0x00, 0x55, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x49, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x20, 0x00, 0x44, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x47, 0x00, 0x45, 0x00, 0x53, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x48, 0x00, 0x45, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x41, 0x00, 0x43, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x52, 0x00, 0x41, 0x00, 0x43, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x57, 0x00, 0x49, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x52, 0x00, 0x49, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x20, 0x00, 0x46, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x45, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x42, 0x00, 0x49, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x54, 0x00, 0x59, 0x00, 0x20, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x45, 0x00, 0x20, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x53, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x54, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x45, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x46, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x20, 0x00, 0x44, 0x00, 0x45, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x53, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x53, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x54, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x45, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x78, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x47, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x47, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x73, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x77, 0x00, 0x69, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x73, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x77, 0x00, 0x72, 0x00, 0x69, 0x00, 0x74, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x69, 0x00, 0x7a, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x66, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x47, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x0a, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x70, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x66, 0x00, 0x75, 0x00, 0x72, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3a, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x74, 0x00, 0x20, 0x00, 0x67, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x20, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x67, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x0a, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x36, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x54, 0x00, 0x61, 0x00, 0x76, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x42, 0x00, 0x61, 0x00, 0x68, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x41, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x52, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x52, 0x00, 0x65, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x50, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x65, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x66, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x74, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x28, 0x00, 0x22, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x22, 0x00, 0x29, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x69, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x22, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x22, 0x00, 0x29, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x62, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x42, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x64, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x72, 0x00, 0x67, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x70, 0x00, 0x75, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x62, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x2f, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x73, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x69, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x74, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x77, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x66, 0x00, 0x75, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x73, 0x00, 0x75, 0x00, 0x62, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x0a, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x65, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x73, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x64, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x69, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x74, 0x00, 0x79, 0x00, 0x70, 0x00, 0x65, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x64, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x73, 0x00, 0x69, 0x00, 0x67, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x70, 0x00, 0x68, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x64, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x70, 0x00, 0x68, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x63, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x64, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x20, 0x00, 0x69, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x65, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x0a, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x64, 0x00, 0x73, 0x00, 0x20, 0x00, 0x22, 0x00, 0x54, 0x00, 0x61, 0x00, 0x76, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x42, 0x00, 0x61, 0x00, 0x68, 0x00, 0x22, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x64, 0x00, 0x20, 0x00, 0x22, 0x00, 0x41, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x22, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x76, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x61, 0x00, 0x70, 0x00, 0x70, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x61, 0x00, 0x74, 0x00, 0x20, 0x00, 0x68, 0x00, 0x61, 0x00, 0x73, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x62, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x54, 0x00, 0x61, 0x00, 0x76, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x42, 0x00, 0x61, 0x00, 0x68, 0x00, 0x20, 0x00, 0x41, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x22, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x20, 0x00, 0x62, 0x00, 0x75, 0x00, 0x74, 0x00, 0x0a, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x79, 0x00, 0x70, 0x00, 0x65, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x79, 0x00, 0x20, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x0a, 0x00, 0x69, 0x00, 0x74, 0x00, 0x73, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x66, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x53, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x54, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x45, 0x00, 0x20, 0x00, 0x49, 0x00, 0x53, 0x00, 0x20, 0x00, 0x50, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x56, 0x00, 0x49, 0x00, 0x44, 0x00, 0x45, 0x00, 0x44, 0x00, 0x20, 0x00, 0x22, 0x00, 0x41, 0x00, 0x53, 0x00, 0x20, 0x00, 0x49, 0x00, 0x53, 0x00, 0x22, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x57, 0x00, 0x49, 0x00, 0x54, 0x00, 0x48, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x54, 0x00, 0x20, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x52, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x59, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x20, 0x00, 0x4b, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x58, 0x00, 0x50, 0x00, 0x52, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x50, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x45, 0x00, 0x44, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x43, 0x00, 0x4c, 0x00, 0x55, 0x00, 0x44, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x20, 0x00, 0x42, 0x00, 0x55, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x49, 0x00, 0x54, 0x00, 0x45, 0x00, 0x44, 0x00, 0x20, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x20, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x52, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x49, 0x00, 0x45, 0x00, 0x53, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x0a, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x52, 0x00, 0x43, 0x00, 0x48, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x41, 0x00, 0x42, 0x00, 0x49, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x54, 0x00, 0x59, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x46, 0x00, 0x49, 0x00, 0x54, 0x00, 0x4e, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x41, 0x00, 0x20, 0x00, 0x50, 0x00, 0x41, 0x00, 0x52, 0x00, 0x54, 0x00, 0x49, 0x00, 0x43, 0x00, 0x55, 0x00, 0x4c, 0x00, 0x41, 0x00, 0x52, 0x00, 0x20, 0x00, 0x50, 0x00, 0x55, 0x00, 0x52, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x45, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x52, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x45, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x59, 0x00, 0x52, 0x00, 0x49, 0x00, 0x47, 0x00, 0x48, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x50, 0x00, 0x41, 0x00, 0x54, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x54, 0x00, 0x52, 0x00, 0x41, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x20, 0x00, 0x52, 0x00, 0x49, 0x00, 0x47, 0x00, 0x48, 0x00, 0x54, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x20, 0x00, 0x45, 0x00, 0x56, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x53, 0x00, 0x48, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x0a, 0x00, 0x54, 0x00, 0x41, 0x00, 0x56, 0x00, 0x4d, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x20, 0x00, 0x42, 0x00, 0x41, 0x00, 0x48, 0x00, 0x20, 0x00, 0x42, 0x00, 0x45, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x41, 0x00, 0x42, 0x00, 0x4c, 0x00, 0x45, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4c, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x44, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x47, 0x00, 0x45, 0x00, 0x53, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x41, 0x00, 0x42, 0x00, 0x49, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x54, 0x00, 0x59, 0x00, 0x2c, 0x00, 0x0a, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x43, 0x00, 0x4c, 0x00, 0x55, 0x00, 0x44, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x59, 0x00, 0x20, 0x00, 0x47, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x45, 0x00, 0x52, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x53, 0x00, 0x50, 0x00, 0x45, 0x00, 0x43, 0x00, 0x49, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x49, 0x00, 0x52, 0x00, 0x45, 0x00, 0x43, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x43, 0x00, 0x49, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x53, 0x00, 0x45, 0x00, 0x51, 0x00, 0x55, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x49, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x0a, 0x00, 0x44, 0x00, 0x41, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x47, 0x00, 0x45, 0x00, 0x53, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x57, 0x00, 0x48, 0x00, 0x45, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x41, 0x00, 0x43, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x20, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x52, 0x00, 0x41, 0x00, 0x43, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x57, 0x00, 0x49, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x52, 0x00, 0x49, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x54, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x20, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x45, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x42, 0x00, 0x49, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x54, 0x00, 0x59, 0x00, 0x20, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x45, 0x00, 0x20, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x53, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x54, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x45, 0x00, 0x20, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x20, 0x00, 0x46, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x0a, 0x00, 0x4f, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x52, 0x00, 0x20, 0x00, 0x44, 0x00, 0x45, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x47, 0x00, 0x53, 0x00, 0x20, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x20, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x20, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x54, 0x00, 0x20, 0x00, 0x53, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x54, 0x00, 0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x45, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x78, 0x00, 0x63, 0x00, 0x65, 0x00, 0x70, 0x00, 0x74, 0x00, 0x20, 0x00, 0x61, 0x00, 0x73, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x54, 0x00, 0x61, 0x00, 0x76, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x42, 0x00, 0x61, 0x00, 0x68, 0x00, 0x20, 0x00, 0x73, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x0a, 0x00, 0x62, 0x00, 0x65, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x74, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x77, 0x00, 0x69, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x73, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x0a, 0x00, 0x64, 0x00, 0x65, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x73, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x77, 0x00, 0x72, 0x00, 0x69, 0x00, 0x74, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x69, 0x00, 0x7a, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x54, 0x00, 0x61, 0x00, 0x76, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x42, 0x00, 0x61, 0x00, 0x68, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x66, 0x00, 0x75, 0x00, 0x72, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3a, 0x00, 0x20, 0x00, 0x74, 0x00, 0x61, 0x00, 0x76, 0x00, 0x6d, 0x00, 0x6a, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x40, 0x00, 0x20, 0x00, 0x66, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x0a, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x66, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x00, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x28, 0x63, 0x29, 0x20, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x28, 0x73, 0x65, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x29, 0x2e, 0x20, 0x44, 0x65, 0x6a, 0x61, 0x56, 0x75, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x47, 0x6c, 0x79, 0x70, 0x68, 0x73, 0x20, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x41, 0x72, 0x65, 0x76, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x28, 0x63, 0x29, 0x20, 0x54, 0x61, 0x76, 0x6d, 0x6a, 0x75, 0x6e, 0x67, 0x20, 0x42, 0x61, 0x68, 0x20, 0x28, 0x73, 0x65, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x29, 0x0a, 0x0a, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x56, 0x65, 0x72, 0x61, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x33, 0x20, 0x62, 0x79, 0x20, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x20, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x56, 0x65, 0x72, 0x61, 0x20, 0x69, 0x73, 0x0a, 0x61, 0x20, 0x74, 0x72, 0x61, 0x64, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x0a, 0x0a, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x68, 0x65, 0x72, 0x65, 0x62, 0x79, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x62, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x0a, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x28, 0x22, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x22, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x0a, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x22, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x22, 0x29, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x2c, 0x20, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x2c, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x2c, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x66, 0x75, 0x72, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x20, 0x73, 0x6f, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x72, 0x61, 0x64, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x0a, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x66, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6c, 0x79, 0x70, 0x68, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x67, 0x6c, 0x79, 0x70, 0x68, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x73, 0x0a, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x22, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x22, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x0a, 0x22, 0x56, 0x65, 0x72, 0x61, 0x22, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x0a, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x0a, 0x56, 0x65, 0x72, 0x61, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x0a, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x66, 0x61, 0x63, 0x65, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x64, 0x20, 0x62, 0x79, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x0a, 0x0a, 0x54, 0x48, 0x45, 0x20, 0x46, 0x4f, 0x4e, 0x54, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x49, 0x53, 0x20, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x44, 0x20, 0x22, 0x41, 0x53, 0x20, 0x49, 0x53, 0x22, 0x2c, 0x20, 0x57, 0x49, 0x54, 0x48, 0x4f, 0x55, 0x54, 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59, 0x20, 0x4f, 0x46, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x4b, 0x49, 0x4e, 0x44, 0x2c, 0x20, 0x45, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x0a, 0x4f, 0x52, 0x20, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x45, 0x44, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x49, 0x4e, 0x47, 0x20, 0x42, 0x55, 0x54, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x45, 0x44, 0x20, 0x54, 0x4f, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x49, 0x45, 0x53, 0x20, 0x4f, 0x46, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x2c, 0x0a, 0x46, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52, 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, 0x52, 0x50, 0x4f, 0x53, 0x45, 0x20, 0x41, 0x4e, 0x44, 0x20, 0x4e, 0x4f, 0x4e, 0x49, 0x4e, 0x46, 0x52, 0x49, 0x4e, 0x47, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x4f, 0x46, 0x20, 0x43, 0x4f, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x2c, 0x20, 0x50, 0x41, 0x54, 0x45, 0x4e, 0x54, 0x2c, 0x0a, 0x54, 0x52, 0x41, 0x44, 0x45, 0x4d, 0x41, 0x52, 0x4b, 0x2c, 0x20, 0x4f, 0x52, 0x20, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x20, 0x52, 0x49, 0x47, 0x48, 0x54, 0x2e, 0x20, 0x49, 0x4e, 0x20, 0x4e, 0x4f, 0x20, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x20, 0x53, 0x48, 0x41, 0x4c, 0x4c, 0x20, 0x42, 0x49, 0x54, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x20, 0x4f, 0x52, 0x20, 0x54, 0x48, 0x45, 0x20, 0x47, 0x4e, 0x4f, 0x4d, 0x45, 0x0a, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x42, 0x45, 0x20, 0x4c, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x46, 0x4f, 0x52, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x2c, 0x20, 0x44, 0x41, 0x4d, 0x41, 0x47, 0x45, 0x53, 0x20, 0x4f, 0x52, 0x20, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x20, 0x4c, 0x49, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x49, 0x4e, 0x47, 0x0a, 0x41, 0x4e, 0x59, 0x20, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x2c, 0x20, 0x53, 0x50, 0x45, 0x43, 0x49, 0x41, 0x4c, 0x2c, 0x20, 0x49, 0x4e, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x49, 0x44, 0x45, 0x4e, 0x54, 0x41, 0x4c, 0x2c, 0x20, 0x4f, 0x52, 0x20, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x51, 0x55, 0x45, 0x4e, 0x54, 0x49, 0x41, 0x4c, 0x20, 0x44, 0x41, 0x4d, 0x41, 0x47, 0x45, 0x53, 0x2c, 0x0a, 0x57, 0x48, 0x45, 0x54, 0x48, 0x45, 0x52, 0x20, 0x49, 0x4e, 0x20, 0x41, 0x4e, 0x20, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x4f, 0x46, 0x20, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x54, 0x2c, 0x20, 0x54, 0x4f, 0x52, 0x54, 0x20, 0x4f, 0x52, 0x20, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x57, 0x49, 0x53, 0x45, 0x2c, 0x20, 0x41, 0x52, 0x49, 0x53, 0x49, 0x4e, 0x47, 0x20, 0x46, 0x52, 0x4f, 0x4d, 0x2c, 0x20, 0x4f, 0x55, 0x54, 0x20, 0x4f, 0x46, 0x0a, 0x54, 0x48, 0x45, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x52, 0x20, 0x49, 0x4e, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x20, 0x54, 0x4f, 0x20, 0x55, 0x53, 0x45, 0x20, 0x54, 0x48, 0x45, 0x20, 0x46, 0x4f, 0x4e, 0x54, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x4f, 0x52, 0x20, 0x46, 0x52, 0x4f, 0x4d, 0x20, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x20, 0x44, 0x45, 0x41, 0x4c, 0x49, 0x4e, 0x47, 0x53, 0x20, 0x49, 0x4e, 0x20, 0x54, 0x48, 0x45, 0x0a, 0x46, 0x4f, 0x4e, 0x54, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x2e, 0x0a, 0x0a, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x6e, 0x6f, 0x6d, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x6e, 0x6f, 0x6d, 0x65, 0x0a, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x2c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6c, 0x65, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x64, 0x65, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x0a, 0x49, 0x6e, 0x63, 0x2e, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x2e, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x3a, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x74, 0x20, 0x67, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x64, 0x6f, 0x74, 0x0a, 0x6f, 0x72, 0x67, 0x2e, 0x20, 0x0a, 0x0a, 0x41, 0x72, 0x65, 0x76, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x62, 0x79, 0x20, 0x54, 0x61, 0x76, 0x6d, 0x6a, 0x6f, 0x6e, 0x67, 0x20, 0x42, 0x61, 0x68, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x68, 0x65, 0x72, 0x65, 0x62, 0x79, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x62, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x0a, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x28, 0x22, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x22, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x28, 0x74, 0x68, 0x65, 0x20, 0x22, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x22, 0x29, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x56, 0x65, 0x72, 0x61, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2c, 0x0a, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x2c, 0x20, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x2c, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x2c, 0x0a, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x66, 0x75, 0x72, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x20, 0x73, 0x6f, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x72, 0x61, 0x64, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x0a, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x66, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x0a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6c, 0x79, 0x70, 0x68, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x67, 0x6c, 0x79, 0x70, 0x68, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x0a, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x22, 0x54, 0x61, 0x76, 0x6d, 0x6a, 0x6f, 0x6e, 0x67, 0x20, 0x42, 0x61, 0x68, 0x22, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x22, 0x41, 0x72, 0x65, 0x76, 0x22, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x73, 0x0a, 0x6f, 0x72, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x0a, 0x22, 0x54, 0x61, 0x76, 0x6d, 0x6a, 0x6f, 0x6e, 0x67, 0x20, 0x42, 0x61, 0x68, 0x20, 0x41, 0x72, 0x65, 0x76, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x20, 0x62, 0x75, 0x74, 0x0a, 0x6e, 0x6f, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x66, 0x61, 0x63, 0x65, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x64, 0x20, 0x62, 0x79, 0x0a, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x0a, 0x0a, 0x54, 0x48, 0x45, 0x20, 0x46, 0x4f, 0x4e, 0x54, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x49, 0x53, 0x20, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x44, 0x20, 0x22, 0x41, 0x53, 0x20, 0x49, 0x53, 0x22, 0x2c, 0x20, 0x57, 0x49, 0x54, 0x48, 0x4f, 0x55, 0x54, 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59, 0x20, 0x4f, 0x46, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x4b, 0x49, 0x4e, 0x44, 0x2c, 0x0a, 0x45, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x4f, 0x52, 0x20, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x45, 0x44, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x49, 0x4e, 0x47, 0x20, 0x42, 0x55, 0x54, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x45, 0x44, 0x20, 0x54, 0x4f, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x49, 0x45, 0x53, 0x20, 0x4f, 0x46, 0x0a, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x2c, 0x20, 0x46, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52, 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, 0x52, 0x50, 0x4f, 0x53, 0x45, 0x20, 0x41, 0x4e, 0x44, 0x20, 0x4e, 0x4f, 0x4e, 0x49, 0x4e, 0x46, 0x52, 0x49, 0x4e, 0x47, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x0a, 0x4f, 0x46, 0x20, 0x43, 0x4f, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x2c, 0x20, 0x50, 0x41, 0x54, 0x45, 0x4e, 0x54, 0x2c, 0x20, 0x54, 0x52, 0x41, 0x44, 0x45, 0x4d, 0x41, 0x52, 0x4b, 0x2c, 0x20, 0x4f, 0x52, 0x20, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x20, 0x52, 0x49, 0x47, 0x48, 0x54, 0x2e, 0x20, 0x49, 0x4e, 0x20, 0x4e, 0x4f, 0x20, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x20, 0x53, 0x48, 0x41, 0x4c, 0x4c, 0x0a, 0x54, 0x41, 0x56, 0x4d, 0x4a, 0x4f, 0x4e, 0x47, 0x20, 0x42, 0x41, 0x48, 0x20, 0x42, 0x45, 0x20, 0x4c, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x46, 0x4f, 0x52, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x2c, 0x20, 0x44, 0x41, 0x4d, 0x41, 0x47, 0x45, 0x53, 0x20, 0x4f, 0x52, 0x20, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x20, 0x4c, 0x49, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x2c, 0x0a, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x49, 0x4e, 0x47, 0x20, 0x41, 0x4e, 0x59, 0x20, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x4c, 0x2c, 0x20, 0x53, 0x50, 0x45, 0x43, 0x49, 0x41, 0x4c, 0x2c, 0x20, 0x49, 0x4e, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x49, 0x44, 0x45, 0x4e, 0x54, 0x41, 0x4c, 0x2c, 0x20, 0x4f, 0x52, 0x20, 0x43, 0x4f, 0x4e, 0x53, 0x45, 0x51, 0x55, 0x45, 0x4e, 0x54, 0x49, 0x41, 0x4c, 0x0a, 0x44, 0x41, 0x4d, 0x41, 0x47, 0x45, 0x53, 0x2c, 0x20, 0x57, 0x48, 0x45, 0x54, 0x48, 0x45, 0x52, 0x20, 0x49, 0x4e, 0x20, 0x41, 0x4e, 0x20, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x4f, 0x46, 0x20, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x54, 0x2c, 0x20, 0x54, 0x4f, 0x52, 0x54, 0x20, 0x4f, 0x52, 0x20, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x57, 0x49, 0x53, 0x45, 0x2c, 0x20, 0x41, 0x52, 0x49, 0x53, 0x49, 0x4e, 0x47, 0x0a, 0x46, 0x52, 0x4f, 0x4d, 0x2c, 0x20, 0x4f, 0x55, 0x54, 0x20, 0x4f, 0x46, 0x20, 0x54, 0x48, 0x45, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x52, 0x20, 0x49, 0x4e, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x20, 0x54, 0x4f, 0x20, 0x55, 0x53, 0x45, 0x20, 0x54, 0x48, 0x45, 0x20, 0x46, 0x4f, 0x4e, 0x54, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x4f, 0x52, 0x20, 0x46, 0x52, 0x4f, 0x4d, 0x0a, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x20, 0x44, 0x45, 0x41, 0x4c, 0x49, 0x4e, 0x47, 0x53, 0x20, 0x49, 0x4e, 0x20, 0x54, 0x48, 0x45, 0x20, 0x46, 0x4f, 0x4e, 0x54, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x2e, 0x0a, 0x0a, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x54, 0x61, 0x76, 0x6d, 0x6a, 0x6f, 0x6e, 0x67, 0x20, 0x42, 0x61, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x0a, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6c, 0x65, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x0a, 0x64, 0x65, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x46, 0x6f, 0x6e, 0x74, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x54, 0x61, 0x76, 0x6d, 0x6a, 0x6f, 0x6e, 0x67, 0x20, 0x42, 0x61, 0x68, 0x2e, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x3a, 0x20, 0x74, 0x61, 0x76, 0x6d, 0x6a, 0x6f, 0x6e, 0x67, 0x20, 0x40, 0x20, 0x66, 0x72, 0x65, 0x65, 0x0a, 0x2e, 0x20, 0x66, 0x72, 0x2e, 0x00, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x76, 0x00, 0x75, 0x00, 0x2e, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x67, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x74, 0x00, 0x2f, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6b, 0x00, 0x69, 0x00, 0x2f, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x78, 0x00, 0x2e, 0x00, 0x70, 0x00, 0x68, 0x00, 0x70, 0x00, 0x2f, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x6a, 0x61, 0x76, 0x75, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x77, 0x69, 0x6b, 0x69, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x70, 0x68, 0x70, 0x2f, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x00, 0x00, 0x44, 0x00, 0x65, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x56, 0x00, 0x75, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x47, 0x00, 0x43, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x00, 0x44, 0x65, 0x6a, 0x61, 0x56, 0x75, 0x20, 0x4c, 0x47, 0x43, 0x20, 0x53, 0x61, 0x6e, 0x73, 0x00, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x65, 0x00, 0x64, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x28, 0x00, 0x29, 0x00, 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x2e, 0x00, 0x2f, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, 0x5c, 0x00, 0x5d, 0x00, 0x5e, 0x00, 0x5f, 0x00, 0x60, 0x00, 0x61, 0x00, 0xac, 0x00, 0xa3, 0x00, 0x84, 0x00, 0x85, 0x00, 0xbd, 0x00, 0x96, 0x00, 0xe8, 0x00, 0x86, 0x00, 0x8e, 0x00, 0x8b, 0x00, 0x9d, 0x00, 0xa9, 0x00, 0xa4, 0x01, 0x02, 0x00, 0x8a, 0x00, 0xda, 0x00, 0x83, 0x00, 0x93, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0x8d, 0x00, 0x97, 0x00, 0x88, 0x00, 0xc3, 0x00, 0xde, 0x00, 0xf1, 0x00, 0x9e, 0x00, 0xaa, 0x00, 0xf5, 0x00, 0xf4, 0x00, 0xf6, 0x00, 0xa2, 0x00, 0xad, 0x00, 0xc9, 0x00, 0xc7, 0x00, 0xae, 0x00, 0x62, 0x00, 0x63, 0x00, 0x90, 0x00, 0x64, 0x00, 0xcb, 0x00, 0x65, 0x00, 0xc8, 0x00, 0xca, 0x00, 0xcf, 0x00, 0xcc, 0x00, 0xcd, 0x00, 0xce, 0x00, 0xe9, 0x00, 0x66, 0x00, 0xd3, 0x00, 0xd0, 0x00, 0xd1, 0x00, 0xaf, 0x00, 0x67, 0x00, 0xf0, 0x00, 0x91, 0x00, 0xd6, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0x68, 0x00, 0xeb, 0x00, 0xed, 0x00, 0x89, 0x00, 0x6a, 0x00, 0x69, 0x00, 0x6b, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0x6e, 0x00, 0xa0, 0x00, 0x6f, 0x00, 0x71, 0x00, 0x70, 0x00, 0x72, 0x00, 0x73, 0x00, 0x75, 0x00, 0x74, 0x00, 0x76, 0x00, 0x77, 0x00, 0xea, 0x00, 0x78, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x7b, 0x00, 0x7d, 0x00, 0x7c, 0x00, 0xb8, 0x00, 0xa1, 0x00, 0x7f, 0x00, 0x7e, 0x00, 0x80, 0x00, 0x81, 0x00, 0xec, 0x00, 0xee, 0x00, 0xba, 0x01, 0x03, 0x01, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x00, 0xfd, 0x00, 0xfe, 0x01, 0x09, 0x01, 0x0a, 0x01, 0x0b, 0x01, 0x0c, 0x00, 0xff, 0x01, 0x00, 0x01, 0x0d, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x01, 0x01, 0x10, 0x01, 0x11, 0x01, 0x12, 0x01, 0x13, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x01, 0x18, 0x01, 0x19, 0x01, 0x1a, 0x01, 0x1b, 0x00, 0xf8, 0x00, 0xf9, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x1e, 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x23, 0x01, 0x24, 0x01, 0x25, 0x01, 0x26, 0x01, 0x27, 0x01, 0x28, 0x01, 0x29, 0x01, 0x2a, 0x01, 0x2b, 0x00, 0xfa, 0x00, 0xd7, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x33, 0x01, 0x34, 0x01, 0x35, 0x01, 0x36, 0x01, 0x37, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x00, 0xe2, 0x00, 0xe3, 0x01, 0x3b, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x3f, 0x01, 0x40, 0x01, 0x41, 0x01, 0x42, 0x01, 0x43, 0x01, 0x44, 0x01, 0x45, 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x49, 0x00, 0xb0, 0x00, 0xb1, 0x01, 0x4a, 0x01, 0x4b, 0x01, 0x4c, 0x01, 0x4d, 0x01, 0x4e, 0x01, 0x4f, 0x01, 0x50, 0x01, 0x51, 0x01, 0x52, 0x01, 0x53, 0x00, 0xfb, 0x00, 0xfc, 0x00, 0xe4, 0x00, 0xe5, 0x01, 0x54, 0x01, 0x55, 0x01, 0x56, 0x01, 0x57, 0x01, 0x58, 0x01, 0x59, 0x01, 0x5a, 0x01, 0x5b, 0x01, 0x5c, 0x01, 0x5d, 0x01, 0x5e, 0x01, 0x5f, 0x01, 0x60, 0x01, 0x61, 0x01, 0x62, 0x01, 0x63, 0x01, 0x64, 0x01, 0x65, 0x01, 0x66, 0x01, 0x67, 0x01, 0x68, 0x01, 0x69, 0x00, 0xbb, 0x01, 0x6a, 0x01, 0x6b, 0x01, 0x6c, 0x01, 0x6d, 0x00, 0xe6, 0x00, 0xe7, 0x01, 0x6e, 0x01, 0x6f, 0x01, 0x70, 0x01, 0x71, 0x01, 0x72, 0x01, 0x73, 0x01, 0x74, 0x01, 0x75, 0x01, 0x76, 0x01, 0x77, 0x01, 0x78, 0x01, 0x79, 0x01, 0x7a, 0x01, 0x7b, 0x01, 0x7c, 0x01, 0x7d, 0x01, 0x7e, 0x01, 0x7f, 0x01, 0x80, 0x00, 0xa6, 0x01, 0x81, 0x01, 0x82, 0x01, 0x83, 0x01, 0x84, 0x01, 0x85, 0x01, 0x86, 0x01, 0x87, 0x01, 0x88, 0x01, 0x89, 0x01, 0x8a, 0x01, 0x8b, 0x01, 0x8c, 0x01, 0x8d, 0x01, 0x8e, 0x01, 0x8f, 0x01, 0x90, 0x01, 0x91, 0x01, 0x92, 0x01, 0x93, 0x01, 0x94, 0x01, 0x95, 0x01, 0x96, 0x01, 0x97, 0x01, 0x98, 0x01, 0x99, 0x01, 0x9a, 0x01, 0x9b, 0x01, 0x9c, 0x01, 0x9d, 0x01, 0x9e, 0x01, 0x9f, 0x01, 0xa0, 0x01, 0xa1, 0x01, 0xa2, 0x01, 0xa3, 0x01, 0xa4, 0x01, 0xa5, 0x01, 0xa6, 0x01, 0xa7, 0x01, 0xa8, 0x01, 0xa9, 0x01, 0xaa, 0x01, 0xab, 0x01, 0xac, 0x01, 0xad, 0x01, 0xae, 0x01, 0xaf, 0x01, 0xb0, 0x01, 0xb1, 0x01, 0xb2, 0x01, 0xb3, 0x01, 0xb4, 0x01, 0xb5, 0x01, 0xb6, 0x01, 0xb7, 0x01, 0xb8, 0x01, 0xb9, 0x01, 0xba, 0x01, 0xbb, 0x01, 0xbc, 0x01, 0xbd, 0x01, 0xbe, 0x01, 0xbf, 0x01, 0xc0, 0x01, 0xc1, 0x01, 0xc2, 0x01, 0xc3, 0x01, 0xc4, 0x01, 0xc5, 0x01, 0xc6, 0x01, 0xc7, 0x01, 0xc8, 0x01, 0xc9, 0x01, 0xca, 0x01, 0xcb, 0x01, 0xcc, 0x01, 0xcd, 0x01, 0xce, 0x01, 0xcf, 0x01, 0xd0, 0x01, 0xd1, 0x01, 0xd2, 0x01, 0xd3, 0x01, 0xd4, 0x01, 0xd5, 0x01, 0xd6, 0x01, 0xd7, 0x01, 0xd8, 0x01, 0xd9, 0x01, 0xda, 0x01, 0xdb, 0x01, 0xdc, 0x01, 0xdd, 0x01, 0xde, 0x01, 0xdf, 0x01, 0xe0, 0x01, 0xe1, 0x01, 0xe2, 0x01, 0xe3, 0x01, 0xe4, 0x01, 0xe5, 0x01, 0xe6, 0x01, 0xe7, 0x01, 0xe8, 0x01, 0xe9, 0x01, 0xea, 0x01, 0xeb, 0x01, 0xec, 0x01, 0xed, 0x01, 0xee, 0x01, 0xef, 0x01, 0xf0, 0x01, 0xf1, 0x01, 0xf2, 0x01, 0xf3, 0x01, 0xf4, 0x01, 0xf5, 0x01, 0xf6, 0x01, 0xf7, 0x01, 0xf8, 0x01, 0xf9, 0x01, 0xfa, 0x01, 0xfb, 0x01, 0xfc, 0x01, 0xfd, 0x01, 0xfe, 0x01, 0xff, 0x02, 0x00, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02, 0x07, 0x02, 0x08, 0x02, 0x09, 0x02, 0x0a, 0x02, 0x0b, 0x02, 0x0c, 0x02, 0x0d, 0x02, 0x0e, 0x02, 0x0f, 0x02, 0x10, 0x02, 0x11, 0x02, 0x12, 0x02, 0x13, 0x02, 0x14, 0x02, 0x15, 0x02, 0x16, 0x02, 0x17, 0x02, 0x18, 0x02, 0x19, 0x02, 0x1a, 0x02, 0x1b, 0x02, 0x1c, 0x02, 0x1d, 0x02, 0x1e, 0x02, 0x1f, 0x02, 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x23, 0x02, 0x24, 0x02, 0x25, 0x02, 0x26, 0x02, 0x27, 0x02, 0x28, 0x02, 0x29, 0x02, 0x2a, 0x02, 0x2b, 0x02, 0x2c, 0x02, 0x2d, 0x02, 0x2e, 0x02, 0x2f, 0x02, 0x30, 0x02, 0x31, 0x02, 0x32, 0x02, 0x33, 0x02, 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02, 0x38, 0x02, 0x39, 0x02, 0x3a, 0x02, 0x3b, 0x02, 0x3c, 0x02, 0x3d, 0x02, 0x3e, 0x02, 0x3f, 0x02, 0x40, 0x02, 0x41, 0x02, 0x42, 0x02, 0x43, 0x02, 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x47, 0x02, 0x48, 0x02, 0x49, 0x02, 0x4a, 0x02, 0x4b, 0x02, 0x4c, 0x02, 0x4d, 0x02, 0x4e, 0x02, 0x4f, 0x02, 0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x53, 0x02, 0x54, 0x02, 0x55, 0x02, 0x56, 0x02, 0x57, 0x02, 0x58, 0x02, 0x59, 0x02, 0x5a, 0x02, 0x5b, 0x02, 0x5c, 0x02, 0x5d, 0x02, 0x5e, 0x02, 0x5f, 0x02, 0x60, 0x02, 0x61, 0x02, 0x62, 0x02, 0x63, 0x02, 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, 0x68, 0x02, 0x69, 0x02, 0x6a, 0x02, 0x6b, 0x02, 0x6c, 0x02, 0x6d, 0x02, 0x6e, 0x02, 0x6f, 0x02, 0x70, 0x02, 0x71, 0x02, 0x72, 0x02, 0x73, 0x02, 0x74, 0x02, 0x75, 0x02, 0x76, 0x02, 0x77, 0x02, 0x78, 0x02, 0x79, 0x02, 0x7a, 0x02, 0x7b, 0x02, 0x7c, 0x02, 0x7d, 0x02, 0x7e, 0x02, 0x7f, 0x02, 0x80, 0x02, 0x81, 0x02, 0x82, 0x02, 0x83, 0x02, 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02, 0x88, 0x02, 0x89, 0x02, 0x8a, 0x02, 0x8b, 0x02, 0x8c, 0x02, 0x8d, 0x02, 0x8e, 0x02, 0x8f, 0x02, 0x90, 0x02, 0x91, 0x02, 0x92, 0x02, 0x93, 0x02, 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02, 0x98, 0x02, 0x99, 0x02, 0x9a, 0x02, 0x9b, 0x02, 0x9c, 0x02, 0x9d, 0x02, 0x9e, 0x02, 0x9f, 0x02, 0xa0, 0x02, 0xa1, 0x02, 0xa2, 0x02, 0xa3, 0x02, 0xa4, 0x02, 0xa5, 0x02, 0xa6, 0x02, 0xa7, 0x02, 0xa8, 0x02, 0xa9, 0x02, 0xaa, 0x02, 0xab, 0x02, 0xac, 0x02, 0xad, 0x02, 0xae, 0x02, 0xaf, 0x02, 0xb0, 0x02, 0xb1, 0x02, 0xb2, 0x02, 0xb3, 0x00, 0xd8, 0x00, 0xe1, 0x02, 0xb4, 0x02, 0xb5, 0x02, 0xb6, 0x02, 0xb7, 0x02, 0xb8, 0x02, 0xb9, 0x02, 0xba, 0x02, 0xbb, 0x02, 0xbc, 0x02, 0xbd, 0x02, 0xbe, 0x02, 0xbf, 0x02, 0xc0, 0x02, 0xc1, 0x02, 0xc2, 0x02, 0xc3, 0x00, 0xdb, 0x00, 0xdc, 0x00, 0xdd, 0x00, 0xe0, 0x00, 0xd9, 0x00, 0xdf, 0x02, 0xc4, 0x02, 0xc5, 0x02, 0xc6, 0x02, 0xc7, 0x02, 0xc8, 0x02, 0xc9, 0x02, 0xca, 0x02, 0xcb, 0x02, 0xcc, 0x02, 0xcd, 0x02, 0xce, 0x02, 0xcf, 0x02, 0xd0, 0x02, 0xd1, 0x02, 0xd2, 0x02, 0xd3, 0x02, 0xd4, 0x02, 0xd5, 0x02, 0xd6, 0x02, 0xd7, 0x02, 0xd8, 0x02, 0xd9, 0x02, 0xda, 0x02, 0xdb, 0x02, 0xdc, 0x02, 0xdd, 0x02, 0xde, 0x02, 0xdf, 0x02, 0xe0, 0x02, 0xe1, 0x02, 0xe2, 0x02, 0xe3, 0x02, 0xe4, 0x02, 0xe5, 0x02, 0xe6, 0x02, 0xe7, 0x02, 0xe8, 0x02, 0xe9, 0x02, 0xea, 0x02, 0xeb, 0x02, 0xec, 0x02, 0xed, 0x02, 0xee, 0x02, 0xef, 0x02, 0xf0, 0x02, 0xf1, 0x02, 0xf2, 0x02, 0xf3, 0x02, 0xf4, 0x02, 0xf5, 0x02, 0xf6, 0x02, 0xf7, 0x02, 0xf8, 0x02, 0xf9, 0x02, 0xfa, 0x02, 0xfb, 0x02, 0xfc, 0x02, 0xfd, 0x02, 0xfe, 0x02, 0xff, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03, 0x08, 0x03, 0x09, 0x03, 0x0a, 0x03, 0x0b, 0x03, 0x0c, 0x03, 0x0d, 0x03, 0x0e, 0x03, 0x0f, 0x03, 0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03, 0x18, 0x03, 0x19, 0x03, 0x1a, 0x03, 0x1b, 0x03, 0x1c, 0x03, 0x1d, 0x03, 0x1e, 0x03, 0x1f, 0x03, 0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03, 0x28, 0x03, 0x29, 0x03, 0x2a, 0x03, 0x2b, 0x03, 0x2c, 0x03, 0x2d, 0x03, 0x2e, 0x03, 0x2f, 0x03, 0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03, 0x38, 0x03, 0x39, 0x03, 0x3a, 0x03, 0x3b, 0x03, 0x3c, 0x03, 0x3d, 0x03, 0x3e, 0x03, 0x3f, 0x03, 0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03, 0x48, 0x03, 0x49, 0x03, 0x4a, 0x03, 0x4b, 0x03, 0x4c, 0x03, 0x4d, 0x03, 0x4e, 0x03, 0x4f, 0x03, 0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03, 0x58, 0x03, 0x59, 0x03, 0x5a, 0x03, 0x5b, 0x03, 0x5c, 0x03, 0x5d, 0x03, 0x5e, 0x03, 0x5f, 0x03, 0x60, 0x00, 0x9f, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03, 0x68, 0x03, 0x69, 0x03, 0x6a, 0x03, 0x6b, 0x03, 0x6c, 0x03, 0x6d, 0x03, 0x6e, 0x03, 0x6f, 0x03, 0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, 0x74, 0x03, 0x75, 0x03, 0x76, 0x00, 0x9b, 0x03, 0x77, 0x03, 0x78, 0x03, 0x79, 0x03, 0x7a, 0x03, 0x7b, 0x03, 0x7c, 0x03, 0x7d, 0x03, 0x7e, 0x03, 0x7f, 0x03, 0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8a, 0x03, 0x8b, 0x03, 0x8c, 0x03, 0x8d, 0x03, 0x8e, 0x03, 0x8f, 0x03, 0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, 0x98, 0x03, 0x99, 0x03, 0x9a, 0x03, 0x9b, 0x03, 0x9c, 0x03, 0x9d, 0x03, 0x9e, 0x03, 0x9f, 0x03, 0xa0, 0x03, 0xa1, 0x03, 0xa2, 0x03, 0xa3, 0x03, 0xa4, 0x03, 0xa5, 0x03, 0xa6, 0x03, 0xa7, 0x03, 0xa8, 0x03, 0xa9, 0x03, 0xaa, 0x03, 0xab, 0x03, 0xac, 0x03, 0xad, 0x03, 0xae, 0x03, 0xaf, 0x03, 0xb0, 0x03, 0xb1, 0x03, 0xb2, 0x03, 0xb3, 0x03, 0xb4, 0x03, 0xb5, 0x03, 0xb6, 0x03, 0xb7, 0x03, 0xb8, 0x03, 0xb9, 0x03, 0xba, 0x03, 0xbb, 0x03, 0xbc, 0x03, 0xbd, 0x03, 0xbe, 0x03, 0xbf, 0x03, 0xc0, 0x03, 0xc1, 0x03, 0xc2, 0x03, 0xc3, 0x03, 0xc4, 0x03, 0xc5, 0x03, 0xc6, 0x03, 0xc7, 0x03, 0xc8, 0x03, 0xc9, 0x03, 0xca, 0x03, 0xcb, 0x03, 0xcc, 0x03, 0xcd, 0x03, 0xce, 0x03, 0xcf, 0x03, 0xd0, 0x03, 0xd1, 0x03, 0xd2, 0x03, 0xd3, 0x03, 0xd4, 0x03, 0xd5, 0x03, 0xd6, 0x03, 0xd7, 0x03, 0xd8, 0x03, 0xd9, 0x03, 0xda, 0x03, 0xdb, 0x03, 0xdc, 0x03, 0xdd, 0x03, 0xde, 0x03, 0xdf, 0x03, 0xe0, 0x03, 0xe1, 0x03, 0xe2, 0x03, 0xe3, 0x03, 0xe4, 0x03, 0xe5, 0x03, 0xe6, 0x03, 0xe7, 0x03, 0xe8, 0x03, 0xe9, 0x03, 0xea, 0x03, 0xeb, 0x03, 0xec, 0x03, 0xed, 0x03, 0xee, 0x03, 0xef, 0x03, 0xf0, 0x03, 0xf1, 0x03, 0xf2, 0x03, 0xf3, 0x03, 0xf4, 0x03, 0xf5, 0x03, 0xf6, 0x03, 0xf7, 0x03, 0xf8, 0x03, 0xf9, 0x03, 0xfa, 0x03, 0xfb, 0x03, 0xfc, 0x03, 0xfd, 0x03, 0xfe, 0x03, 0xff, 0x04, 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, 0x08, 0x04, 0x09, 0x04, 0x0a, 0x04, 0x0b, 0x04, 0x0c, 0x04, 0x0d, 0x04, 0x0e, 0x04, 0x0f, 0x04, 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, 0x18, 0x04, 0x19, 0x04, 0x1a, 0x04, 0x1b, 0x04, 0x1c, 0x04, 0x1d, 0x04, 0x1e, 0x04, 0x1f, 0x04, 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, 0x28, 0x04, 0x29, 0x04, 0x2a, 0x04, 0x2b, 0x04, 0x2c, 0x04, 0x2d, 0x04, 0x2e, 0x04, 0x2f, 0x04, 0x30, 0x04, 0x31, 0x04, 0x32, 0x04, 0x33, 0x04, 0x34, 0x04, 0x35, 0x04, 0x36, 0x04, 0x37, 0x04, 0x38, 0x04, 0x39, 0x04, 0x3a, 0x04, 0x3b, 0x04, 0x3c, 0x04, 0x3d, 0x04, 0x3e, 0x04, 0x3f, 0x04, 0x40, 0x04, 0x41, 0x04, 0x42, 0x04, 0x43, 0x04, 0x44, 0x04, 0x45, 0x04, 0x46, 0x04, 0x47, 0x04, 0x48, 0x04, 0x49, 0x04, 0x4a, 0x04, 0x4b, 0x04, 0x4c, 0x04, 0x4d, 0x04, 0x4e, 0x04, 0x4f, 0x04, 0x50, 0x04, 0x51, 0x04, 0x52, 0x04, 0x53, 0x04, 0x54, 0x04, 0x55, 0x04, 0x56, 0x04, 0x57, 0x04, 0x58, 0x04, 0x59, 0x04, 0x5a, 0x04, 0x5b, 0x04, 0x5c, 0x04, 0x5d, 0x04, 0x5e, 0x04, 0x5f, 0x04, 0x60, 0x04, 0x61, 0x04, 0x62, 0x04, 0x63, 0x04, 0x64, 0x04, 0x65, 0x04, 0x66, 0x04, 0x67, 0x04, 0x68, 0x04, 0x69, 0x04, 0x6a, 0x04, 0x6b, 0x04, 0x6c, 0x04, 0x6d, 0x04, 0x6e, 0x04, 0x6f, 0x04, 0x70, 0x04, 0x71, 0x04, 0x72, 0x04, 0x73, 0x04, 0x74, 0x04, 0x75, 0x04, 0x76, 0x04, 0x77, 0x04, 0x78, 0x04, 0x79, 0x04, 0x7a, 0x04, 0x7b, 0x04, 0x7c, 0x04, 0x7d, 0x04, 0x7e, 0x04, 0x7f, 0x04, 0x80, 0x04, 0x81, 0x04, 0x82, 0x04, 0x83, 0x04, 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04, 0x88, 0x04, 0x89, 0x04, 0x8a, 0x04, 0x8b, 0x04, 0x8c, 0x04, 0x8d, 0x04, 0x8e, 0x04, 0x8f, 0x04, 0x90, 0x04, 0x91, 0x04, 0x92, 0x04, 0x93, 0x04, 0x94, 0x04, 0x95, 0x04, 0x96, 0x04, 0x97, 0x04, 0x98, 0x04, 0x99, 0x04, 0x9a, 0x04, 0x9b, 0x04, 0x9c, 0x04, 0x9d, 0x04, 0x9e, 0x04, 0x9f, 0x04, 0xa0, 0x04, 0xa1, 0x04, 0xa2, 0x04, 0xa3, 0x04, 0xa4, 0x04, 0xa5, 0x04, 0xa6, 0x04, 0xa7, 0x04, 0xa8, 0x04, 0xa9, 0x04, 0xaa, 0x04, 0xab, 0x04, 0xac, 0x04, 0xad, 0x04, 0xae, 0x04, 0xaf, 0x04, 0xb0, 0x04, 0xb1, 0x04, 0xb2, 0x04, 0xb3, 0x04, 0xb4, 0x04, 0xb5, 0x04, 0xb6, 0x04, 0xb7, 0x04, 0xb8, 0x04, 0xb9, 0x04, 0xba, 0x04, 0xbb, 0x04, 0xbc, 0x04, 0xbd, 0x04, 0xbe, 0x04, 0xbf, 0x04, 0xc0, 0x04, 0xc1, 0x04, 0xc2, 0x04, 0xc3, 0x04, 0xc4, 0x04, 0xc5, 0x04, 0xc6, 0x04, 0xc7, 0x04, 0xc8, 0x04, 0xc9, 0x04, 0xca, 0x04, 0xcb, 0x04, 0xcc, 0x04, 0xcd, 0x04, 0xce, 0x04, 0xcf, 0x04, 0xd0, 0x04, 0xd1, 0x04, 0xd2, 0x04, 0xd3, 0x04, 0xd4, 0x04, 0xd5, 0x04, 0xd6, 0x04, 0xd7, 0x04, 0xd8, 0x04, 0xd9, 0x04, 0xda, 0x04, 0xdb, 0x04, 0xdc, 0x04, 0xdd, 0x04, 0xde, 0x04, 0xdf, 0x04, 0xe0, 0x04, 0xe1, 0x04, 0xe2, 0x04, 0xe3, 0x04, 0xe4, 0x04, 0xe5, 0x04, 0xe6, 0x04, 0xe7, 0x04, 0xe8, 0x04, 0xe9, 0x04, 0xea, 0x04, 0xeb, 0x04, 0xec, 0x04, 0xed, 0x04, 0xee, 0x04, 0xef, 0x04, 0xf0, 0x04, 0xf1, 0x04, 0xf2, 0x04, 0xf3, 0x04, 0xf4, 0x04, 0xf5, 0x04, 0xf6, 0x04, 0xf7, 0x04, 0xf8, 0x04, 0xf9, 0x04, 0xfa, 0x04, 0xfb, 0x04, 0xfc, 0x04, 0xfd, 0x04, 0xfe, 0x04, 0xff, 0x05, 0x00, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03, 0x05, 0x04, 0x05, 0x05, 0x05, 0x06, 0x05, 0x07, 0x05, 0x08, 0x05, 0x09, 0x05, 0x0a, 0x05, 0x0b, 0x05, 0x0c, 0x05, 0x0d, 0x05, 0x0e, 0x05, 0x0f, 0x05, 0x10, 0x05, 0x11, 0x05, 0x12, 0x05, 0x13, 0x05, 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05, 0x18, 0x05, 0x19, 0x05, 0x1a, 0x05, 0x1b, 0x05, 0x1c, 0x05, 0x1d, 0x05, 0x1e, 0x05, 0x1f, 0x05, 0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05, 0x28, 0x05, 0x29, 0x05, 0x2a, 0x05, 0x2b, 0x05, 0x2c, 0x05, 0x2d, 0x05, 0x2e, 0x05, 0x2f, 0x05, 0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, 0x38, 0x05, 0x39, 0x05, 0x3a, 0x05, 0x3b, 0x05, 0x3c, 0x05, 0x3d, 0x05, 0x3e, 0x05, 0x3f, 0x05, 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, 0x48, 0x05, 0x49, 0x05, 0x4a, 0x05, 0x4b, 0x05, 0x4c, 0x05, 0x4d, 0x05, 0x4e, 0x05, 0x4f, 0x05, 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05, 0x58, 0x05, 0x59, 0x05, 0x5a, 0x05, 0x5b, 0x05, 0x5c, 0x05, 0x5d, 0x05, 0x5e, 0x05, 0x5f, 0x05, 0x60, 0x05, 0x61, 0x05, 0x62, 0x05, 0x63, 0x05, 0x64, 0x05, 0x65, 0x05, 0x66, 0x05, 0x67, 0x05, 0x68, 0x05, 0x69, 0x05, 0x6a, 0x05, 0x6b, 0x05, 0x6c, 0x05, 0x6d, 0x05, 0x6e, 0x05, 0x6f, 0x05, 0x70, 0x05, 0x71, 0x05, 0x72, 0x05, 0x73, 0x05, 0x74, 0x05, 0x75, 0x05, 0x76, 0x05, 0x77, 0x05, 0x78, 0x05, 0x79, 0x05, 0x7a, 0x05, 0x7b, 0x05, 0x7c, 0x05, 0x7d, 0x05, 0x7e, 0x05, 0x7f, 0x05, 0x80, 0x05, 0x81, 0x05, 0x82, 0x05, 0x83, 0x05, 0x84, 0x05, 0x85, 0x05, 0x86, 0x05, 0x87, 0x05, 0x88, 0x05, 0x89, 0x05, 0x8a, 0x05, 0x8b, 0x05, 0x8c, 0x05, 0x8d, 0x05, 0x8e, 0x05, 0x8f, 0x05, 0x90, 0x05, 0x91, 0x05, 0x92, 0x05, 0x93, 0x05, 0x94, 0x05, 0x95, 0x05, 0x96, 0x05, 0x97, 0x05, 0x98, 0x05, 0x99, 0x05, 0x9a, 0x05, 0x9b, 0x05, 0x9c, 0x05, 0x9d, 0x05, 0x9e, 0x05, 0x9f, 0x05, 0xa0, 0x05, 0xa1, 0x05, 0xa2, 0x05, 0xa3, 0x05, 0xa4, 0x05, 0xa5, 0x05, 0xa6, 0x05, 0xa7, 0x05, 0xa8, 0x05, 0xa9, 0x05, 0xaa, 0x05, 0xab, 0x05, 0xac, 0x05, 0xad, 0x05, 0xae, 0x05, 0xaf, 0x05, 0xb0, 0x05, 0xb1, 0x05, 0xb2, 0x05, 0xb3, 0x05, 0xb4, 0x05, 0xb5, 0x05, 0xb6, 0x05, 0xb7, 0x05, 0xb8, 0x05, 0xb9, 0x05, 0xba, 0x05, 0xbb, 0x05, 0xbc, 0x05, 0xbd, 0x05, 0xbe, 0x05, 0xbf, 0x05, 0xc0, 0x05, 0xc1, 0x05, 0xc2, 0x05, 0xc3, 0x05, 0xc4, 0x05, 0xc5, 0x05, 0xc6, 0x05, 0xc7, 0x05, 0xc8, 0x05, 0xc9, 0x05, 0xca, 0x05, 0xcb, 0x05, 0xcc, 0x05, 0xcd, 0x05, 0xce, 0x05, 0xcf, 0x05, 0xd0, 0x05, 0xd1, 0x05, 0xd2, 0x05, 0xd3, 0x05, 0xd4, 0x05, 0xd5, 0x05, 0xd6, 0x05, 0xd7, 0x05, 0xd8, 0x05, 0xd9, 0x05, 0xda, 0x05, 0xdb, 0x05, 0xdc, 0x05, 0xdd, 0x05, 0xde, 0x05, 0xdf, 0x05, 0xe0, 0x05, 0xe1, 0x05, 0xe2, 0x05, 0xe3, 0x05, 0xe4, 0x05, 0xe5, 0x05, 0xe6, 0x05, 0xe7, 0x05, 0xe8, 0x05, 0xe9, 0x05, 0xea, 0x05, 0xeb, 0x05, 0xec, 0x05, 0xed, 0x05, 0xee, 0x05, 0xef, 0x05, 0xf0, 0x05, 0xf1, 0x05, 0xf2, 0x05, 0xf3, 0x05, 0xf4, 0x05, 0xf5, 0x05, 0xf6, 0x05, 0xf7, 0x05, 0xf8, 0x05, 0xf9, 0x05, 0xfa, 0x05, 0xfb, 0x05, 0xfc, 0x05, 0xfd, 0x05, 0xfe, 0x05, 0xff, 0x06, 0x00, 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x06, 0x04, 0x06, 0x05, 0x06, 0x06, 0x06, 0x07, 0x06, 0x08, 0x06, 0x09, 0x06, 0x0a, 0x06, 0x0b, 0x06, 0x0c, 0x06, 0x0d, 0x06, 0x0e, 0x06, 0x0f, 0x06, 0x10, 0x06, 0x11, 0x06, 0x12, 0x06, 0x13, 0x06, 0x14, 0x06, 0x15, 0x06, 0x16, 0x06, 0x17, 0x06, 0x18, 0x06, 0x19, 0x06, 0x1a, 0x06, 0x1b, 0x06, 0x1c, 0x06, 0x1d, 0x06, 0x1e, 0x06, 0x1f, 0x06, 0x20, 0x06, 0x21, 0x06, 0x22, 0x06, 0x23, 0x06, 0x24, 0x06, 0x25, 0x06, 0x26, 0x06, 0x27, 0x06, 0x28, 0x06, 0x29, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2c, 0x06, 0x2d, 0x06, 0x2e, 0x06, 0x2f, 0x06, 0x30, 0x06, 0x31, 0x06, 0x32, 0x06, 0x33, 0x06, 0x34, 0x06, 0x35, 0x06, 0x36, 0x06, 0x37, 0x06, 0x38, 0x06, 0x39, 0x06, 0x3a, 0x06, 0x3b, 0x06, 0x3c, 0x06, 0x3d, 0x06, 0x3e, 0x06, 0x3f, 0x06, 0x40, 0x06, 0x41, 0x06, 0x42, 0x06, 0x43, 0x06, 0x44, 0x06, 0x45, 0x06, 0x46, 0x06, 0x47, 0x06, 0x48, 0x06, 0x49, 0x06, 0x4a, 0x06, 0x4b, 0x06, 0x4c, 0x06, 0x4d, 0x06, 0x4e, 0x06, 0x4f, 0x06, 0x50, 0x06, 0x51, 0x06, 0x52, 0x06, 0x53, 0x06, 0x54, 0x06, 0x55, 0x06, 0x56, 0x06, 0x57, 0x06, 0x58, 0x06, 0x59, 0x06, 0x5a, 0x06, 0x5b, 0x06, 0x5c, 0x06, 0x5d, 0x06, 0x5e, 0x06, 0x5f, 0x06, 0x60, 0x06, 0x61, 0x06, 0x62, 0x06, 0x63, 0x06, 0x64, 0x06, 0x65, 0x06, 0x66, 0x06, 0x67, 0x06, 0x68, 0x06, 0x69, 0x06, 0x6a, 0x06, 0x6b, 0x06, 0x6c, 0x06, 0x6d, 0x06, 0x6e, 0x06, 0x6f, 0x06, 0x70, 0x06, 0x71, 0x06, 0x72, 0x06, 0x73, 0x06, 0x74, 0x06, 0x75, 0x06, 0x76, 0x06, 0x77, 0x06, 0x78, 0x06, 0x79, 0x06, 0x7a, 0x06, 0x7b, 0x06, 0x7c, 0x06, 0x7d, 0x06, 0x7e, 0x06, 0x7f, 0x06, 0x80, 0x06, 0x81, 0x06, 0x82, 0x06, 0x83, 0x06, 0x84, 0x06, 0x85, 0x06, 0x86, 0x06, 0x87, 0x06, 0x88, 0x06, 0x89, 0x06, 0x8a, 0x06, 0x8b, 0x06, 0x8c, 0x06, 0x8d, 0x06, 0x8e, 0x06, 0x8f, 0x06, 0x90, 0x06, 0x91, 0x06, 0x92, 0x06, 0x93, 0x06, 0x94, 0x06, 0x95, 0x06, 0x96, 0x06, 0x97, 0x06, 0x98, 0x06, 0x99, 0x06, 0x9a, 0x06, 0x9b, 0x06, 0x9c, 0x06, 0x9d, 0x06, 0x9e, 0x06, 0x9f, 0x06, 0xa0, 0x06, 0xa1, 0x06, 0xa2, 0x06, 0xa3, 0x06, 0xa4, 0x06, 0xa5, 0x06, 0xa6, 0x06, 0xa7, 0x06, 0xa8, 0x06, 0xa9, 0x06, 0xaa, 0x06, 0xab, 0x06, 0xac, 0x06, 0xad, 0x06, 0xae, 0x06, 0xaf, 0x06, 0xb0, 0x06, 0xb1, 0x06, 0xb2, 0x06, 0xb3, 0x06, 0xb4, 0x06, 0xb5, 0x06, 0xb6, 0x06, 0xb7, 0x06, 0xb8, 0x06, 0xb9, 0x06, 0xba, 0x06, 0xbb, 0x06, 0xbc, 0x06, 0xbd, 0x06, 0xbe, 0x06, 0xbf, 0x06, 0xc0, 0x06, 0xc1, 0x06, 0xc2, 0x06, 0xc3, 0x06, 0xc4, 0x06, 0xc5, 0x06, 0xc6, 0x06, 0xc7, 0x06, 0xc8, 0x06, 0xc9, 0x06, 0xca, 0x06, 0xcb, 0x06, 0xcc, 0x06, 0xcd, 0x06, 0xce, 0x06, 0xcf, 0x06, 0xd0, 0x06, 0xd1, 0x06, 0xd2, 0x06, 0xd3, 0x06, 0xd4, 0x06, 0xd5, 0x06, 0xd6, 0x06, 0xd7, 0x06, 0xd8, 0x06, 0xd9, 0x06, 0xda, 0x06, 0xdb, 0x06, 0xdc, 0x06, 0xdd, 0x06, 0xde, 0x06, 0xdf, 0x06, 0xe0, 0x06, 0xe1, 0x06, 0xe2, 0x06, 0xe3, 0x06, 0xe4, 0x06, 0xe5, 0x06, 0xe6, 0x06, 0xe7, 0x06, 0xe8, 0x06, 0xe9, 0x06, 0xea, 0x06, 0xeb, 0x06, 0xec, 0x06, 0xed, 0x06, 0xee, 0x06, 0xef, 0x06, 0xf0, 0x06, 0xf1, 0x06, 0xf2, 0x06, 0xf3, 0x06, 0xf4, 0x06, 0xf5, 0x06, 0xf6, 0x06, 0xf7, 0x06, 0xf8, 0x06, 0xf9, 0x06, 0xfa, 0x06, 0xfb, 0x06, 0xfc, 0x06, 0xfd, 0x06, 0xfe, 0x06, 0xff, 0x07, 0x00, 0x07, 0x01, 0x07, 0x02, 0x07, 0x03, 0x07, 0x04, 0x07, 0x05, 0x07, 0x06, 0x07, 0x07, 0x07, 0x08, 0x07, 0x09, 0x07, 0x0a, 0x07, 0x0b, 0x07, 0x0c, 0x07, 0x0d, 0x07, 0x0e, 0x07, 0x0f, 0x07, 0x10, 0x07, 0x11, 0x07, 0x12, 0x07, 0x13, 0x07, 0x14, 0x07, 0x15, 0x07, 0x16, 0x07, 0x17, 0x07, 0x18, 0x07, 0x19, 0x07, 0x1a, 0x07, 0x1b, 0x07, 0x1c, 0x07, 0x1d, 0x07, 0x1e, 0x07, 0x1f, 0x07, 0x20, 0x07, 0x21, 0x07, 0x22, 0x07, 0x23, 0x07, 0x24, 0x07, 0x25, 0x07, 0x26, 0x07, 0x27, 0x07, 0x28, 0x07, 0x29, 0x07, 0x2a, 0x07, 0x2b, 0x07, 0x2c, 0x07, 0x2d, 0x07, 0x2e, 0x07, 0x2f, 0x07, 0x30, 0x07, 0x31, 0x07, 0x32, 0x07, 0x33, 0x07, 0x34, 0x07, 0x35, 0x07, 0x36, 0x07, 0x37, 0x07, 0x38, 0x07, 0x39, 0x07, 0x3a, 0x07, 0x3b, 0x07, 0x3c, 0x07, 0x3d, 0x07, 0x3e, 0x07, 0x3f, 0x07, 0x40, 0x07, 0x41, 0x07, 0x42, 0x07, 0x43, 0x07, 0x44, 0x07, 0x45, 0x07, 0x46, 0x07, 0x47, 0x07, 0x48, 0x07, 0x49, 0x07, 0x4a, 0x07, 0x4b, 0x07, 0x4c, 0x07, 0x4d, 0x07, 0x4e, 0x07, 0x4f, 0x07, 0x50, 0x07, 0x51, 0x07, 0x52, 0x07, 0x53, 0x07, 0x54, 0x07, 0x55, 0x07, 0x56, 0x07, 0x57, 0x07, 0x58, 0x07, 0x59, 0x07, 0x5a, 0x07, 0x5b, 0x07, 0x5c, 0x07, 0x5d, 0x07, 0x5e, 0x07, 0x5f, 0x07, 0x60, 0x07, 0x61, 0x07, 0x62, 0x07, 0x63, 0x07, 0x64, 0x07, 0x65, 0x07, 0x66, 0x07, 0x67, 0x07, 0x68, 0x07, 0x69, 0x00, 0xb2, 0x00, 0xb3, 0x07, 0x6a, 0x07, 0x6b, 0x07, 0x6c, 0x00, 0xb6, 0x00, 0xb7, 0x00, 0xc4, 0x07, 0x6d, 0x00, 0xb4, 0x00, 0xb5, 0x00, 0xc5, 0x07, 0x6e, 0x00, 0x82, 0x00, 0xc2, 0x00, 0x87, 0x07, 0x6f, 0x07, 0x70, 0x07, 0x71, 0x00, 0xab, 0x07, 0x72, 0x07, 0x73, 0x07, 0x74, 0x07, 0x75, 0x07, 0x76, 0x07, 0x77, 0x07, 0x78, 0x07, 0x79, 0x07, 0x7a, 0x00, 0xc6, 0x07, 0x7b, 0x07, 0x7c, 0x07, 0x7d, 0x07, 0x7e, 0x07, 0x7f, 0x07, 0x80, 0x07, 0x81, 0x07, 0x82, 0x00, 0xbe, 0x00, 0xbf, 0x07, 0x83, 0x07, 0x84, 0x07, 0x85, 0x07, 0x86, 0x07, 0x87, 0x07, 0x88, 0x07, 0x89, 0x07, 0x8a, 0x07, 0x8b, 0x00, 0xbc, 0x07, 0x8c, 0x07, 0x8d, 0x07, 0x8e, 0x07, 0x8f, 0x07, 0x90, 0x07, 0x91, 0x07, 0x92, 0x07, 0x93, 0x07, 0x94, 0x07, 0x95, 0x07, 0x96, 0x07, 0x97, 0x07, 0x98, 0x07, 0x99, 0x07, 0x9a, 0x07, 0x9b, 0x07, 0x9c, 0x07, 0x9d, 0x07, 0x9e, 0x07, 0x9f, 0x07, 0xa0, 0x07, 0xa1, 0x07, 0xa2, 0x07, 0xa3, 0x07, 0xa4, 0x07, 0xa5, 0x07, 0xa6, 0x07, 0xa7, 0x07, 0xa8, 0x07, 0xa9, 0x07, 0xaa, 0x07, 0xab, 0x07, 0xac, 0x07, 0xad, 0x07, 0xae, 0x07, 0xaf, 0x07, 0xb0, 0x07, 0xb1, 0x07, 0xb2, 0x07, 0xb3, 0x07, 0xb4, 0x07, 0xb5, 0x07, 0xb6, 0x07, 0xb7, 0x07, 0xb8, 0x07, 0xb9, 0x07, 0xba, 0x07, 0xbb, 0x07, 0xbc, 0x07, 0xbd, 0x07, 0xbe, 0x07, 0xbf, 0x07, 0xc0, 0x07, 0xc1, 0x07, 0xc2, 0x07, 0xc3, 0x07, 0xc4, 0x07, 0xc5, 0x07, 0xc6, 0x07, 0xc7, 0x07, 0xc8, 0x07, 0xc9, 0x07, 0xca, 0x07, 0xcb, 0x07, 0xcc, 0x07, 0xcd, 0x07, 0xce, 0x07, 0xcf, 0x07, 0xd0, 0x07, 0xd1, 0x07, 0xd2, 0x07, 0xd3, 0x07, 0xd4, 0x07, 0xd5, 0x07, 0xd6, 0x07, 0xd7, 0x07, 0xd8, 0x07, 0xd9, 0x07, 0xda, 0x07, 0xdb, 0x07, 0xdc, 0x07, 0xdd, 0x07, 0xde, 0x00, 0xf7, 0x07, 0xdf, 0x07, 0xe0, 0x07, 0xe1, 0x07, 0xe2, 0x07, 0xe3, 0x07, 0xe4, 0x07, 0xe5, 0x07, 0xe6, 0x07, 0xe7, 0x07, 0xe8, 0x07, 0xe9, 0x07, 0xea, 0x07, 0xeb, 0x07, 0xec, 0x07, 0xed, 0x07, 0xee, 0x07, 0xef, 0x07, 0xf0, 0x07, 0xf1, 0x07, 0xf2, 0x07, 0xf3, 0x07, 0xf4, 0x07, 0xf5, 0x07, 0xf6, 0x07, 0xf7, 0x07, 0xf8, 0x07, 0xf9, 0x07, 0xfa, 0x07, 0xfb, 0x07, 0xfc, 0x07, 0xfd, 0x07, 0xfe, 0x07, 0xff, 0x08, 0x00, 0x08, 0x01, 0x08, 0x02, 0x08, 0x03, 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x08, 0x07, 0x08, 0x08, 0x08, 0x09, 0x08, 0x0a, 0x08, 0x0b, 0x08, 0x0c, 0x08, 0x0d, 0x08, 0x0e, 0x08, 0x0f, 0x08, 0x10, 0x08, 0x11, 0x08, 0x12, 0x08, 0x13, 0x08, 0x14, 0x08, 0x15, 0x08, 0x16, 0x08, 0x17, 0x08, 0x18, 0x08, 0x19, 0x08, 0x1a, 0x08, 0x1b, 0x00, 0x8c, 0x08, 0x1c, 0x08, 0x1d, 0x08, 0x1e, 0x08, 0x1f, 0x08, 0x20, 0x08, 0x21, 0x08, 0x22, 0x08, 0x23, 0x08, 0x24, 0x08, 0x25, 0x08, 0x26, 0x08, 0x27, 0x08, 0x28, 0x08, 0x29, 0x08, 0x2a, 0x08, 0x2b, 0x08, 0x2c, 0x08, 0x2d, 0x08, 0x2e, 0x08, 0x2f, 0x08, 0x30, 0x08, 0x31, 0x08, 0x32, 0x08, 0x33, 0x08, 0x34, 0x08, 0x35, 0x08, 0x36, 0x08, 0x37, 0x08, 0x38, 0x08, 0x39, 0x08, 0x3a, 0x08, 0x3b, 0x08, 0x3c, 0x08, 0x3d, 0x08, 0x3e, 0x08, 0x3f, 0x08, 0x40, 0x08, 0x41, 0x08, 0x42, 0x08, 0x43, 0x08, 0x44, 0x08, 0x45, 0x08, 0x46, 0x08, 0x47, 0x08, 0x48, 0x08, 0x49, 0x08, 0x4a, 0x08, 0x4b, 0x08, 0x4c, 0x08, 0x4d, 0x08, 0x4e, 0x08, 0x4f, 0x08, 0x50, 0x08, 0x51, 0x08, 0x52, 0x08, 0x53, 0x08, 0x54, 0x08, 0x55, 0x08, 0x56, 0x08, 0x57, 0x08, 0x58, 0x08, 0x59, 0x08, 0x5a, 0x08, 0x5b, 0x08, 0x5c, 0x08, 0x5d, 0x08, 0x5e, 0x08, 0x5f, 0x08, 0x60, 0x08, 0x61, 0x08, 0x62, 0x08, 0x63, 0x08, 0x64, 0x08, 0x65, 0x08, 0x66, 0x08, 0x67, 0x08, 0x68, 0x08, 0x69, 0x08, 0x6a, 0x08, 0x6b, 0x08, 0x6c, 0x08, 0x6d, 0x08, 0x6e, 0x08, 0x6f, 0x08, 0x70, 0x08, 0x71, 0x08, 0x72, 0x08, 0x73, 0x08, 0x74, 0x08, 0x75, 0x08, 0x76, 0x08, 0x77, 0x08, 0x78, 0x08, 0x79, 0x08, 0x7a, 0x08, 0x7b, 0x08, 0x7c, 0x08, 0x7d, 0x08, 0x7e, 0x08, 0x7f, 0x08, 0x80, 0x08, 0x81, 0x08, 0x82, 0x08, 0x83, 0x08, 0x84, 0x08, 0x85, 0x08, 0x86, 0x08, 0x87, 0x08, 0x88, 0x08, 0x89, 0x08, 0x8a, 0x08, 0x8b, 0x08, 0x8c, 0x08, 0x8d, 0x08, 0x8e, 0x08, 0x8f, 0x08, 0x90, 0x08, 0x91, 0x08, 0x92, 0x08, 0x93, 0x08, 0x94, 0x08, 0x95, 0x08, 0x96, 0x08, 0x97, 0x08, 0x98, 0x08, 0x99, 0x08, 0x9a, 0x08, 0x9b, 0x08, 0x9c, 0x08, 0x9d, 0x08, 0x9e, 0x08, 0x9f, 0x08, 0xa0, 0x08, 0xa1, 0x08, 0xa2, 0x08, 0xa3, 0x08, 0xa4, 0x08, 0xa5, 0x08, 0xa6, 0x08, 0xa7, 0x08, 0xa8, 0x08, 0xa9, 0x08, 0xaa, 0x08, 0xab, 0x08, 0xac, 0x08, 0xad, 0x08, 0xae, 0x08, 0xaf, 0x08, 0xb0, 0x08, 0xb1, 0x08, 0xb2, 0x08, 0xb3, 0x08, 0xb4, 0x08, 0xb5, 0x08, 0xb6, 0x08, 0xb7, 0x08, 0xb8, 0x08, 0xb9, 0x08, 0xba, 0x08, 0xbb, 0x08, 0xbc, 0x08, 0xbd, 0x08, 0xbe, 0x08, 0xbf, 0x08, 0xc0, 0x08, 0xc1, 0x08, 0xc2, 0x08, 0xc3, 0x08, 0xc4, 0x08, 0xc5, 0x08, 0xc6, 0x08, 0xc7, 0x08, 0xc8, 0x08, 0xc9, 0x08, 0xca, 0x08, 0xcb, 0x08, 0xcc, 0x08, 0xcd, 0x08, 0xce, 0x08, 0xcf, 0x08, 0xd0, 0x08, 0xd1, 0x08, 0xd2, 0x08, 0xd3, 0x08, 0xd4, 0x08, 0xd5, 0x08, 0xd6, 0x08, 0xd7, 0x08, 0xd8, 0x08, 0xd9, 0x08, 0xda, 0x08, 0xdb, 0x08, 0xdc, 0x08, 0xdd, 0x08, 0xde, 0x08, 0xdf, 0x08, 0xe0, 0x08, 0xe1, 0x08, 0xe2, 0x08, 0xe3, 0x08, 0xe4, 0x08, 0xe5, 0x08, 0xe6, 0x08, 0xe7, 0x08, 0xe8, 0x08, 0xe9, 0x08, 0xea, 0x08, 0xeb, 0x08, 0xec, 0x08, 0xed, 0x00, 0x98, 0x08, 0xee, 0x08, 0xef, 0x08, 0xf0, 0x00, 0xa8, 0x08, 0xf1, 0x08, 0xf2, 0x08, 0xf3, 0x08, 0xf4, 0x08, 0xf5, 0x08, 0xf6, 0x08, 0xf7, 0x08, 0xf8, 0x00, 0x9a, 0x08, 0xf9, 0x00, 0x99, 0x00, 0xef, 0x08, 0xfa, 0x08, 0xfb, 0x08, 0xfc, 0x08, 0xfd, 0x08, 0xfe, 0x08, 0xff, 0x09, 0x00, 0x00, 0xa5, 0x09, 0x01, 0x09, 0x02, 0x09, 0x03, 0x00, 0x92, 0x09, 0x04, 0x09, 0x05, 0x09, 0x06, 0x09, 0x07, 0x09, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x09, 0x0b, 0x09, 0x0c, 0x09, 0x0d, 0x09, 0x0e, 0x09, 0x0f, 0x00, 0x9c, 0x09, 0x10, 0x09, 0x11, 0x09, 0x12, 0x09, 0x13, 0x09, 0x14, 0x09, 0x15, 0x09, 0x16, 0x09, 0x17, 0x09, 0x18, 0x09, 0x19, 0x09, 0x1a, 0x09, 0x1b, 0x09, 0x1c, 0x09, 0x1d, 0x09, 0x1e, 0x09, 0x1f, 0x09, 0x20, 0x09, 0x21, 0x09, 0x22, 0x09, 0x23, 0x09, 0x24, 0x09, 0x25, 0x09, 0x26, 0x09, 0x27, 0x09, 0x28, 0x09, 0x29, 0x09, 0x2a, 0x09, 0x2b, 0x00, 0xa7, 0x09, 0x2c, 0x09, 0x2d, 0x09, 0x2e, 0x09, 0x2f, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x33, 0x09, 0x34, 0x09, 0x35, 0x09, 0x36, 0x09, 0x37, 0x09, 0x38, 0x09, 0x39, 0x09, 0x3a, 0x09, 0x3b, 0x09, 0x3c, 0x09, 0x3d, 0x09, 0x3e, 0x09, 0x3f, 0x09, 0x40, 0x09, 0x41, 0x09, 0x42, 0x00, 0x8f, 0x09, 0x43, 0x09, 0x44, 0x09, 0x45, 0x00, 0x94, 0x00, 0x95, 0x09, 0x46, 0x09, 0x47, 0x09, 0x48, 0x09, 0x49, 0x09, 0x4a, 0x09, 0x4b, 0x09, 0x4c, 0x09, 0x4d, 0x09, 0x4e, 0x09, 0x4f, 0x09, 0x50, 0x09, 0x51, 0x09, 0x52, 0x09, 0x53, 0x09, 0x54, 0x09, 0x55, 0x09, 0x56, 0x09, 0x57, 0x09, 0x58, 0x09, 0x59, 0x09, 0x5a, 0x09, 0x5b, 0x09, 0x5c, 0x09, 0x5d, 0x09, 0x5e, 0x09, 0x5f, 0x09, 0x60, 0x09, 0x61, 0x09, 0x62, 0x09, 0x63, 0x09, 0x64, 0x09, 0x65, 0x09, 0x66, 0x09, 0x67, 0x09, 0x68, 0x09, 0x69, 0x09, 0x6a, 0x09, 0x6b, 0x09, 0x6c, 0x09, 0x6d, 0x09, 0x6e, 0x09, 0x6f, 0x09, 0x70, 0x09, 0x71, 0x09, 0x72, 0x09, 0x73, 0x09, 0x74, 0x09, 0x75, 0x09, 0x76, 0x09, 0x77, 0x09, 0x78, 0x09, 0x79, 0x09, 0x7a, 0x09, 0x7b, 0x09, 0x7c, 0x09, 0x7d, 0x09, 0x7e, 0x09, 0x7f, 0x09, 0x80, 0x09, 0x81, 0x09, 0x82, 0x09, 0x83, 0x09, 0x84, 0x09, 0x85, 0x09, 0x86, 0x09, 0x87, 0x09, 0x88, 0x09, 0x89, 0x09, 0x8a, 0x09, 0x8b, 0x09, 0x8c, 0x09, 0x8d, 0x09, 0x8e, 0x09, 0x8f, 0x09, 0x90, 0x09, 0x91, 0x09, 0x92, 0x09, 0x93, 0x09, 0x94, 0x09, 0x95, 0x09, 0x96, 0x09, 0x97, 0x09, 0x98, 0x09, 0x99, 0x09, 0x9a, 0x09, 0x9b, 0x09, 0x9c, 0x09, 0x9d, 0x09, 0x9e, 0x09, 0x9f, 0x09, 0xa0, 0x09, 0xa1, 0x09, 0xa2, 0x09, 0xa3, 0x09, 0xa4, 0x09, 0xa5, 0x09, 0xa6, 0x09, 0xa7, 0x09, 0xa8, 0x09, 0xa9, 0x09, 0xaa, 0x09, 0xab, 0x09, 0xac, 0x09, 0xad, 0x09, 0xae, 0x09, 0xaf, 0x09, 0xb0, 0x09, 0xb1, 0x09, 0xb2, 0x09, 0xb3, 0x09, 0xb4, 0x09, 0xb5, 0x09, 0xb6, 0x09, 0xb7, 0x09, 0xb8, 0x09, 0xb9, 0x09, 0xba, 0x09, 0xbb, 0x09, 0xbc, 0x09, 0xbd, 0x09, 0xbe, 0x09, 0xbf, 0x09, 0xc0, 0x09, 0xc1, 0x09, 0xc2, 0x09, 0xc3, 0x09, 0xc4, 0x09, 0xc5, 0x09, 0xc6, 0x09, 0xc7, 0x09, 0xc8, 0x09, 0xc9, 0x09, 0xca, 0x09, 0xcb, 0x09, 0xcc, 0x09, 0xcd, 0x09, 0xce, 0x09, 0xcf, 0x09, 0xd0, 0x09, 0xd1, 0x09, 0xd2, 0x09, 0xd3, 0x09, 0xd4, 0x09, 0xd5, 0x09, 0xd6, 0x09, 0xd7, 0x09, 0xd8, 0x09, 0xd9, 0x09, 0xda, 0x09, 0xdb, 0x09, 0xdc, 0x09, 0xdd, 0x09, 0xde, 0x09, 0xdf, 0x09, 0xe0, 0x09, 0xe1, 0x09, 0xe2, 0x09, 0xe3, 0x09, 0xe4, 0x09, 0xe5, 0x09, 0xe6, 0x09, 0xe7, 0x09, 0xe8, 0x09, 0xe9, 0x09, 0xea, 0x09, 0xeb, 0x09, 0xec, 0x09, 0xed, 0x09, 0xee, 0x09, 0xef, 0x09, 0xf0, 0x09, 0xf1, 0x09, 0xf2, 0x09, 0xf3, 0x09, 0xf4, 0x09, 0xf5, 0x09, 0xf6, 0x09, 0xf7, 0x09, 0xf8, 0x09, 0xf9, 0x09, 0xfa, 0x09, 0xfb, 0x09, 0xfc, 0x09, 0xfd, 0x09, 0xfe, 0x09, 0xff, 0x0a, 0x00, 0x0a, 0x01, 0x0a, 0x02, 0x0a, 0x03, 0x0a, 0x04, 0x0a, 0x05, 0x0a, 0x06, 0x0a, 0x07, 0x0a, 0x08, 0x0a, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x0c, 0x0a, 0x0d, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, 0x10, 0x0a, 0x11, 0x0a, 0x12, 0x0a, 0x13, 0x0a, 0x14, 0x0a, 0x15, 0x0a, 0x16, 0x0a, 0x17, 0x0a, 0x18, 0x0a, 0x19, 0x0a, 0x1a, 0x0a, 0x1b, 0x0a, 0x1c, 0x0a, 0x1d, 0x0a, 0x1e, 0x0a, 0x1f, 0x0a, 0x20, 0x0a, 0x21, 0x0a, 0x22, 0x0a, 0x23, 0x0a, 0x24, 0x0a, 0x25, 0x0a, 0x26, 0x0a, 0x27, 0x0a, 0x28, 0x0a, 0x29, 0x0a, 0x2a, 0x0a, 0x2b, 0x0a, 0x2c, 0x0a, 0x2d, 0x0a, 0x2e, 0x0a, 0x2f, 0x0a, 0x30, 0x0a, 0x31, 0x0a, 0x32, 0x0a, 0x33, 0x0a, 0x34, 0x0a, 0x35, 0x0a, 0x36, 0x0a, 0x37, 0x0a, 0x38, 0x0a, 0x39, 0x0a, 0x3a, 0x0a, 0x3b, 0x0a, 0x3c, 0x0a, 0x3d, 0x0a, 0x3e, 0x0a, 0x3f, 0x0a, 0x40, 0x0a, 0x41, 0x0a, 0x42, 0x0a, 0x43, 0x0a, 0x44, 0x0a, 0x45, 0x0a, 0x46, 0x0a, 0x47, 0x0a, 0x48, 0x0a, 0x49, 0x0a, 0x4a, 0x0a, 0x4b, 0x0a, 0x4c, 0x0a, 0x4d, 0x0a, 0x4e, 0x0a, 0x4f, 0x0a, 0x50, 0x0a, 0x51, 0x0a, 0x52, 0x0a, 0x53, 0x0a, 0x54, 0x0a, 0x55, 0x0a, 0x56, 0x0a, 0x57, 0x0a, 0x58, 0x0a, 0x59, 0x0a, 0x5a, 0x0a, 0x5b, 0x0a, 0x5c, 0x0a, 0x5d, 0x0a, 0x5e, 0x0a, 0x5f, 0x0a, 0x60, 0x0a, 0x61, 0x0a, 0x62, 0x0a, 0x63, 0x0a, 0x64, 0x0a, 0x65, 0x0a, 0x66, 0x0a, 0x67, 0x0a, 0x68, 0x0a, 0x69, 0x0a, 0x6a, 0x0a, 0x6b, 0x0a, 0x6c, 0x0a, 0x6d, 0x0a, 0x6e, 0x0a, 0x6f, 0x0a, 0x70, 0x0a, 0x71, 0x0a, 0x72, 0x0a, 0x73, 0x0a, 0x74, 0x0a, 0x75, 0x0a, 0x76, 0x0a, 0x77, 0x0a, 0x78, 0x0a, 0x79, 0x0a, 0x7a, 0x0a, 0x7b, 0x0a, 0x7c, 0x0a, 0x7d, 0x0a, 0x7e, 0x0a, 0x7f, 0x0a, 0x80, 0x0a, 0x81, 0x0a, 0x82, 0x0a, 0x83, 0x0a, 0x84, 0x0a, 0x85, 0x0a, 0x86, 0x0a, 0x87, 0x0a, 0x88, 0x0a, 0x89, 0x0a, 0x8a, 0x0a, 0x8b, 0x0a, 0x8c, 0x0a, 0x8d, 0x0a, 0x8e, 0x0a, 0x8f, 0x0a, 0x90, 0x0a, 0x91, 0x0a, 0x92, 0x0a, 0x93, 0x0a, 0x94, 0x0a, 0x95, 0x0a, 0x96, 0x0a, 0x97, 0x0a, 0x98, 0x0a, 0x99, 0x0a, 0x9a, 0x0a, 0x9b, 0x0a, 0x9c, 0x0a, 0x9d, 0x0a, 0x9e, 0x0a, 0x9f, 0x0a, 0xa0, 0x0a, 0xa1, 0x0a, 0xa2, 0x0a, 0xa3, 0x0a, 0xa4, 0x0a, 0xa5, 0x0a, 0xa6, 0x0a, 0xa7, 0x0a, 0xa8, 0x0a, 0xa9, 0x0a, 0xaa, 0x0a, 0xab, 0x0a, 0xac, 0x0a, 0xad, 0x0a, 0xae, 0x0a, 0xaf, 0x0a, 0xb0, 0x0a, 0xb1, 0x0a, 0xb2, 0x0a, 0xb3, 0x0a, 0xb4, 0x0a, 0xb5, 0x0a, 0xb6, 0x0a, 0xb7, 0x0a, 0xb8, 0x0a, 0xb9, 0x0a, 0xba, 0x0a, 0xbb, 0x0a, 0xbc, 0x0a, 0xbd, 0x0a, 0xbe, 0x0a, 0xbf, 0x0a, 0xc0, 0x0a, 0xc1, 0x0a, 0xc2, 0x0a, 0xc3, 0x0a, 0xc4, 0x0a, 0xc5, 0x0a, 0xc6, 0x0a, 0xc7, 0x0a, 0xc8, 0x0a, 0xc9, 0x0a, 0xca, 0x0a, 0xcb, 0x0a, 0xcc, 0x0a, 0xcd, 0x0a, 0xce, 0x0a, 0xcf, 0x0a, 0xd0, 0x0a, 0xd1, 0x0a, 0xd2, 0x0a, 0xd3, 0x0a, 0xd4, 0x0a, 0xd5, 0x0a, 0xd6, 0x0a, 0xd7, 0x0a, 0xd8, 0x0a, 0xd9, 0x0a, 0xda, 0x0a, 0xdb, 0x0a, 0xdc, 0x0a, 0xdd, 0x0a, 0xde, 0x0a, 0xdf, 0x0a, 0xe0, 0x0a, 0xe1, 0x0a, 0xe2, 0x0a, 0xe3, 0x0a, 0xe4, 0x0a, 0xe5, 0x0a, 0xe6, 0x0a, 0xe7, 0x0a, 0xe8, 0x0a, 0xe9, 0x0a, 0xea, 0x0a, 0xeb, 0x0a, 0xec, 0x0a, 0xed, 0x0a, 0xee, 0x0a, 0xef, 0x0a, 0xf0, 0x0a, 0xf1, 0x0a, 0xf2, 0x0a, 0xf3, 0x0a, 0xf4, 0x0a, 0xf5, 0x0a, 0xf6, 0x00, 0xb9, 0x0a, 0xf7, 0x0a, 0xf8, 0x0a, 0xf9, 0x0a, 0xfa, 0x0a, 0xfb, 0x0a, 0xfc, 0x0a, 0xfd, 0x0a, 0xfe, 0x0a, 0xff, 0x0b, 0x00, 0x0b, 0x01, 0x0b, 0x02, 0x0b, 0x03, 0x0b, 0x04, 0x0b, 0x05, 0x0b, 0x06, 0x0b, 0x07, 0x0b, 0x08, 0x0b, 0x09, 0x0b, 0x0a, 0x0b, 0x0b, 0x0b, 0x0c, 0x0b, 0x0d, 0x0b, 0x0e, 0x0b, 0x0f, 0x0b, 0x10, 0x0b, 0x11, 0x0b, 0x12, 0x0b, 0x13, 0x0b, 0x14, 0x0b, 0x15, 0x0b, 0x16, 0x0b, 0x17, 0x0b, 0x18, 0x0b, 0x19, 0x0b, 0x1a, 0x0b, 0x1b, 0x0b, 0x1c, 0x0b, 0x1d, 0x0b, 0x1e, 0x0b, 0x1f, 0x0b, 0x20, 0x0b, 0x21, 0x0b, 0x22, 0x0b, 0x23, 0x0b, 0x24, 0x0b, 0x25, 0x0b, 0x26, 0x0b, 0x27, 0x0b, 0x28, 0x0b, 0x29, 0x0b, 0x2a, 0x0b, 0x2b, 0x0b, 0x2c, 0x0b, 0x2d, 0x0b, 0x2e, 0x0b, 0x2f, 0x0b, 0x30, 0x0b, 0x31, 0x0b, 0x32, 0x0b, 0x33, 0x0b, 0x34, 0x0b, 0x35, 0x0b, 0x36, 0x0b, 0x37, 0x0b, 0x38, 0x0b, 0x39, 0x0b, 0x3a, 0x0b, 0x3b, 0x0b, 0x3c, 0x0b, 0x3d, 0x0b, 0x3e, 0x0b, 0x3f, 0x0b, 0x40, 0x0b, 0x41, 0x0b, 0x42, 0x0b, 0x43, 0x0b, 0x44, 0x0b, 0x45, 0x0b, 0x46, 0x0b, 0x47, 0x0b, 0x48, 0x0b, 0x49, 0x0b, 0x4a, 0x0b, 0x4b, 0x0b, 0x4c, 0x0b, 0x4d, 0x0b, 0x4e, 0x0b, 0x4f, 0x0b, 0x50, 0x0b, 0x51, 0x0b, 0x52, 0x0b, 0x53, 0x0b, 0x54, 0x0b, 0x55, 0x0b, 0x56, 0x0b, 0x57, 0x0b, 0x58, 0x0b, 0x59, 0x0b, 0x5a, 0x0b, 0x5b, 0x0b, 0x5c, 0x0b, 0x5d, 0x0b, 0x5e, 0x0b, 0x5f, 0x0b, 0x60, 0x0b, 0x61, 0x0b, 0x62, 0x0b, 0x63, 0x0b, 0x64, 0x0b, 0x65, 0x0b, 0x66, 0x0b, 0x67, 0x0b, 0x68, 0x0b, 0x69, 0x0b, 0x6a, 0x0b, 0x6b, 0x0b, 0x6c, 0x0b, 0x6d, 0x0b, 0x6e, 0x0b, 0x6f, 0x0b, 0x70, 0x0b, 0x71, 0x0b, 0x72, 0x0b, 0x73, 0x0b, 0x74, 0x0b, 0x75, 0x0b, 0x76, 0x0b, 0x77, 0x0b, 0x78, 0x0b, 0x79, 0x0b, 0x7a, 0x0b, 0x7b, 0x0b, 0x7c, 0x0b, 0x7d, 0x0b, 0x7e, 0x0b, 0x7f, 0x0b, 0x80, 0x0b, 0x81, 0x0b, 0x82, 0x0b, 0x83, 0x0b, 0x84, 0x0b, 0x85, 0x0b, 0x86, 0x0b, 0x87, 0x0b, 0x88, 0x0b, 0x89, 0x0b, 0x8a, 0x0b, 0x8b, 0x0b, 0x8c, 0x0b, 0x8d, 0x0b, 0x8e, 0x0b, 0x8f, 0x0b, 0x90, 0x0b, 0x91, 0x0b, 0x92, 0x0b, 0x93, 0x0b, 0x94, 0x0b, 0x95, 0x0b, 0x96, 0x0b, 0x97, 0x0b, 0x98, 0x0b, 0x99, 0x0b, 0x9a, 0x0b, 0x9b, 0x0b, 0x9c, 0x0b, 0x9d, 0x0b, 0x9e, 0x0b, 0x9f, 0x0b, 0xa0, 0x0b, 0xa1, 0x0b, 0xa2, 0x0b, 0xa3, 0x0b, 0xa4, 0x0b, 0xa5, 0x0b, 0xa6, 0x0b, 0xa7, 0x0b, 0xa8, 0x0b, 0xa9, 0x0b, 0xaa, 0x0b, 0xab, 0x0b, 0xac, 0x0b, 0xad, 0x0b, 0xae, 0x0b, 0xaf, 0x0b, 0xb0, 0x0b, 0xb1, 0x0b, 0xb2, 0x0b, 0xb3, 0x0b, 0xb4, 0x0b, 0xb5, 0x0b, 0xb6, 0x0b, 0xb7, 0x0b, 0xb8, 0x0b, 0xb9, 0x0b, 0xba, 0x0b, 0xbb, 0x0b, 0xbc, 0x0b, 0xbd, 0x0b, 0xbe, 0x0b, 0xbf, 0x0b, 0xc0, 0x0b, 0xc1, 0x0b, 0xc2, 0x0b, 0xc3, 0x0b, 0xc4, 0x0b, 0xc5, 0x0b, 0xc6, 0x0b, 0xc7, 0x0b, 0xc8, 0x0b, 0xc9, 0x0b, 0xca, 0x0b, 0xcb, 0x0b, 0xcc, 0x0b, 0xcd, 0x0b, 0xce, 0x0b, 0xcf, 0x0b, 0xd0, 0x0b, 0xd1, 0x0b, 0xd2, 0x0b, 0xd3, 0x0b, 0xd4, 0x0b, 0xd5, 0x0b, 0xd6, 0x0b, 0xd7, 0x0b, 0xd8, 0x0b, 0xd9, 0x0b, 0xda, 0x0b, 0xdb, 0x0b, 0xdc, 0x0b, 0xdd, 0x0b, 0xde, 0x0b, 0xdf, 0x0b, 0xe0, 0x0b, 0xe1, 0x0b, 0xe2, 0x0b, 0xe3, 0x0b, 0xe4, 0x0b, 0xe5, 0x0b, 0xe6, 0x0b, 0xe7, 0x0b, 0xe8, 0x0b, 0xe9, 0x0b, 0xea, 0x0b, 0xeb, 0x0b, 0xec, 0x0b, 0xed, 0x0b, 0xee, 0x0b, 0xef, 0x0b, 0xf0, 0x0b, 0xf1, 0x0b, 0xf2, 0x0b, 0xf3, 0x0b, 0xf4, 0x0b, 0xf5, 0x0b, 0xf6, 0x0b, 0xf7, 0x0b, 0xf8, 0x0b, 0xf9, 0x0b, 0xfa, 0x0b, 0xfb, 0x0b, 0xfc, 0x0b, 0xfd, 0x0b, 0xfe, 0x0b, 0xff, 0x0c, 0x00, 0x0c, 0x01, 0x0c, 0x02, 0x0c, 0x03, 0x0c, 0x04, 0x0c, 0x05, 0x0c, 0x06, 0x0c, 0x07, 0x0c, 0x08, 0x0c, 0x09, 0x0c, 0x0a, 0x0c, 0x0b, 0x0c, 0x0c, 0x0c, 0x0d, 0x0c, 0x0e, 0x0c, 0x0f, 0x0c, 0x10, 0x0c, 0x11, 0x0c, 0x12, 0x0c, 0x13, 0x0c, 0x14, 0x0c, 0x15, 0x0c, 0x16, 0x0c, 0x17, 0x0c, 0x18, 0x0c, 0x19, 0x0c, 0x1a, 0x0c, 0x1b, 0x0c, 0x1c, 0x0c, 0x1d, 0x0c, 0x1e, 0x0c, 0x1f, 0x0c, 0x20, 0x0c, 0x21, 0x0c, 0x22, 0x0c, 0x23, 0x0c, 0x24, 0x0c, 0x25, 0x0c, 0x26, 0x0c, 0x27, 0x0c, 0x28, 0x0c, 0x29, 0x0c, 0x2a, 0x0c, 0x2b, 0x0c, 0x2c, 0x0c, 0x2d, 0x0c, 0x2e, 0x0c, 0x2f, 0x0c, 0x30, 0x0c, 0x31, 0x0c, 0x32, 0x0c, 0x33, 0x0c, 0x34, 0x0c, 0x35, 0x0c, 0x36, 0x0c, 0x37, 0x0c, 0x38, 0x0c, 0x39, 0x0c, 0x3a, 0x0c, 0x3b, 0x0c, 0x3c, 0x0c, 0x3d, 0x0c, 0x3e, 0x0c, 0x3f, 0x0c, 0x40, 0x0c, 0x41, 0x0c, 0x42, 0x0c, 0x43, 0x0c, 0x44, 0x0c, 0x45, 0x0c, 0x46, 0x0c, 0x47, 0x0c, 0x48, 0x0c, 0x49, 0x0c, 0x4a, 0x0c, 0x4b, 0x0c, 0x4c, 0x0c, 0x4d, 0x0c, 0x4e, 0x0c, 0x4f, 0x0c, 0x50, 0x0c, 0x51, 0x0c, 0x52, 0x0c, 0x53, 0x0c, 0x54, 0x0c, 0x55, 0x0c, 0x56, 0x0c, 0x57, 0x0c, 0x58, 0x0c, 0x59, 0x0c, 0x5a, 0x0c, 0x5b, 0x0c, 0x5c, 0x0c, 0x5d, 0x0c, 0x5e, 0x0c, 0x5f, 0x0c, 0x60, 0x0c, 0x61, 0x0c, 0x62, 0x0c, 0x63, 0x0c, 0x64, 0x0c, 0x65, 0x0c, 0x66, 0x0c, 0x67, 0x0c, 0x68, 0x0c, 0x69, 0x0c, 0x6a, 0x0c, 0x6b, 0x0c, 0x6c, 0x0c, 0x6d, 0x0c, 0x6e, 0x0c, 0x6f, 0x0c, 0x70, 0x0c, 0x71, 0x0c, 0x72, 0x0c, 0x73, 0x0c, 0x74, 0x0c, 0x75, 0x0c, 0x76, 0x0c, 0x77, 0x0c, 0x78, 0x0c, 0x79, 0x0c, 0x7a, 0x0c, 0x7b, 0x0c, 0x7c, 0x0c, 0x7d, 0x0c, 0x7e, 0x0c, 0x7f, 0x0c, 0x80, 0x0c, 0x81, 0x0c, 0x82, 0x0c, 0x83, 0x0c, 0x84, 0x0c, 0x85, 0x0c, 0x86, 0x0c, 0x87, 0x0c, 0x88, 0x0c, 0x89, 0x0c, 0x8a, 0x0c, 0x8b, 0x0c, 0x8c, 0x0c, 0x8d, 0x0c, 0x8e, 0x0c, 0x8f, 0x0c, 0x90, 0x0c, 0x91, 0x0c, 0x92, 0x0c, 0x93, 0x0c, 0x94, 0x0c, 0x95, 0x0c, 0x96, 0x0c, 0x97, 0x0c, 0x98, 0x0c, 0x99, 0x0c, 0x9a, 0x0c, 0x9b, 0x0c, 0x9c, 0x0c, 0x9d, 0x0c, 0x9e, 0x0c, 0x9f, 0x0c, 0xa0, 0x0c, 0xa1, 0x0c, 0xa2, 0x0c, 0xa3, 0x0c, 0xa4, 0x0c, 0xa5, 0x0c, 0xa6, 0x0c, 0xa7, 0x0c, 0xa8, 0x0c, 0xa9, 0x0c, 0xaa, 0x0c, 0xab, 0x0c, 0xac, 0x0c, 0xad, 0x0c, 0xae, 0x0c, 0xaf, 0x0c, 0xb0, 0x0c, 0xb1, 0x0c, 0xb2, 0x0c, 0xb3, 0x0c, 0xb4, 0x0c, 0xb5, 0x0c, 0xb6, 0x0c, 0xb7, 0x0c, 0xb8, 0x0c, 0xb9, 0x0c, 0xba, 0x0c, 0xbb, 0x0c, 0xbc, 0x0c, 0xbd, 0x0c, 0xbe, 0x0c, 0xbf, 0x0c, 0xc0, 0x0c, 0xc1, 0x0c, 0xc2, 0x0c, 0xc3, 0x0c, 0xc4, 0x0c, 0xc5, 0x0c, 0xc6, 0x0c, 0xc7, 0x0c, 0xc8, 0x0c, 0xc9, 0x0c, 0xca, 0x0c, 0xcb, 0x0c, 0xcc, 0x0c, 0xcd, 0x0c, 0xce, 0x0c, 0xcf, 0x0c, 0xd0, 0x0c, 0xd1, 0x0c, 0xd2, 0x0c, 0xd3, 0x0c, 0xd4, 0x0c, 0xd5, 0x0c, 0xd6, 0x0c, 0xd7, 0x0c, 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0xdb, 0x0c, 0xdc, 0x0c, 0xdd, 0x0c, 0xde, 0x0c, 0xdf, 0x0c, 0xe0, 0x0c, 0xe1, 0x0c, 0xe2, 0x0c, 0xe3, 0x0c, 0xe4, 0x0c, 0xe5, 0x0c, 0xe6, 0x0c, 0xe7, 0x0c, 0xe8, 0x0c, 0xe9, 0x0c, 0xea, 0x0c, 0xeb, 0x0c, 0xec, 0x0c, 0xed, 0x0c, 0xee, 0x0c, 0xef, 0x0c, 0xf0, 0x0c, 0xf1, 0x0c, 0xf2, 0x0c, 0xf3, 0x0c, 0xf4, 0x0c, 0xf5, 0x0c, 0xf6, 0x0c, 0xf7, 0x0c, 0xf8, 0x0c, 0xf9, 0x0c, 0xfa, 0x0c, 0xfb, 0x0c, 0xfc, 0x0c, 0xfd, 0x0c, 0xfe, 0x0c, 0xff, 0x0d, 0x00, 0x0d, 0x01, 0x0d, 0x02, 0x0d, 0x03, 0x0d, 0x04, 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x08, 0x0d, 0x09, 0x0d, 0x0a, 0x0d, 0x0b, 0x0d, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0d, 0x0f, 0x0d, 0x10, 0x0d, 0x11, 0x0d, 0x12, 0x0d, 0x13, 0x0d, 0x14, 0x0d, 0x15, 0x0d, 0x16, 0x0d, 0x17, 0x0d, 0x18, 0x0d, 0x19, 0x0d, 0x1a, 0x0d, 0x1b, 0x0d, 0x1c, 0x0d, 0x1d, 0x0d, 0x1e, 0x0d, 0x1f, 0x0d, 0x20, 0x0d, 0x21, 0x0d, 0x22, 0x0d, 0x23, 0x0d, 0x24, 0x0d, 0x25, 0x0d, 0x26, 0x0d, 0x27, 0x0d, 0x28, 0x0d, 0x29, 0x0d, 0x2a, 0x0d, 0x2b, 0x0d, 0x2c, 0x0d, 0x2d, 0x0d, 0x2e, 0x0d, 0x2f, 0x0d, 0x30, 0x0d, 0x31, 0x0d, 0x32, 0x0d, 0x33, 0x0d, 0x34, 0x0d, 0x35, 0x0d, 0x36, 0x0d, 0x37, 0x0d, 0x38, 0x0d, 0x39, 0x0d, 0x3a, 0x0d, 0x3b, 0x0d, 0x3c, 0x0d, 0x3d, 0x0d, 0x3e, 0x0d, 0x3f, 0x0d, 0x40, 0x0d, 0x41, 0x0d, 0x42, 0x0d, 0x43, 0x0d, 0x44, 0x0d, 0x45, 0x0d, 0x46, 0x0d, 0x47, 0x0d, 0x48, 0x0d, 0x49, 0x0d, 0x4a, 0x0d, 0x4b, 0x0d, 0x4c, 0x0d, 0x4d, 0x0d, 0x4e, 0x0d, 0x4f, 0x0d, 0x50, 0x0d, 0x51, 0x0d, 0x52, 0x0d, 0x53, 0x0d, 0x54, 0x0d, 0x55, 0x0d, 0x56, 0x0d, 0x57, 0x0d, 0x58, 0x0d, 0x59, 0x0d, 0x5a, 0x0d, 0x5b, 0x0d, 0x5c, 0x0d, 0x5d, 0x0d, 0x5e, 0x0d, 0x5f, 0x0d, 0x60, 0x0d, 0x61, 0x0d, 0x62, 0x0d, 0x63, 0x0d, 0x64, 0x0d, 0x65, 0x0d, 0x66, 0x0d, 0x67, 0x0d, 0x68, 0x0d, 0x69, 0x0d, 0x6a, 0x0d, 0x6b, 0x0d, 0x6c, 0x0d, 0x6d, 0x0d, 0x6e, 0x0d, 0x6f, 0x0d, 0x70, 0x0d, 0x71, 0x0d, 0x72, 0x0d, 0x73, 0x0d, 0x74, 0x0d, 0x75, 0x0d, 0x76, 0x0d, 0x77, 0x0d, 0x78, 0x0d, 0x79, 0x0d, 0x7a, 0x0d, 0x7b, 0x0d, 0x7c, 0x0d, 0x7d, 0x0d, 0x7e, 0x0d, 0x7f, 0x0d, 0x80, 0x0d, 0x81, 0x0d, 0x82, 0x0d, 0x83, 0x0d, 0x84, 0x0d, 0x85, 0x0d, 0x86, 0x0d, 0x87, 0x0d, 0x88, 0x0d, 0x89, 0x0d, 0x8a, 0x0d, 0x8b, 0x0d, 0x8c, 0x0d, 0x8d, 0x0d, 0x8e, 0x0d, 0x8f, 0x0d, 0x90, 0x0d, 0x91, 0x0d, 0x92, 0x0d, 0x93, 0x0d, 0x94, 0x0d, 0x95, 0x0d, 0x96, 0x0d, 0x97, 0x0d, 0x98, 0x0d, 0x99, 0x0d, 0x9a, 0x0d, 0x9b, 0x0d, 0x9c, 0x0d, 0x9d, 0x0d, 0x9e, 0x0d, 0x9f, 0x0d, 0xa0, 0x0d, 0xa1, 0x0d, 0xa2, 0x0d, 0xa3, 0x0d, 0xa4, 0x0d, 0xa5, 0x0d, 0xa6, 0x0d, 0xa7, 0x0d, 0xa8, 0x0d, 0xa9, 0x0d, 0xaa, 0x0d, 0xab, 0x0d, 0xac, 0x0d, 0xad, 0x0d, 0xae, 0x0d, 0xaf, 0x0d, 0xb0, 0x0d, 0xb1, 0x0d, 0xb2, 0x0d, 0xb3, 0x0d, 0xb4, 0x0d, 0xb5, 0x0d, 0xb6, 0x0d, 0xb7, 0x0d, 0xb8, 0x0d, 0xb9, 0x0d, 0xba, 0x0d, 0xbb, 0x0d, 0xbc, 0x0d, 0xbd, 0x0d, 0xbe, 0x0d, 0xbf, 0x0d, 0xc0, 0x0d, 0xc1, 0x0d, 0xc2, 0x0d, 0xc3, 0x0d, 0xc4, 0x0d, 0xc5, 0x0d, 0xc6, 0x0d, 0xc7, 0x0d, 0xc8, 0x0d, 0xc9, 0x0d, 0xca, 0x0d, 0xcb, 0x0d, 0xcc, 0x0d, 0xcd, 0x0d, 0xce, 0x0d, 0xcf, 0x0d, 0xd0, 0x0d, 0xd1, 0x0d, 0xd2, 0x0d, 0xd3, 0x0d, 0xd4, 0x0d, 0xd5, 0x0d, 0xd6, 0x0d, 0xd7, 0x0d, 0xd8, 0x0d, 0xd9, 0x0d, 0xda, 0x0d, 0xdb, 0x0d, 0xdc, 0x0d, 0xdd, 0x0d, 0xde, 0x0d, 0xdf, 0x0d, 0xe0, 0x0d, 0xe1, 0x0d, 0xe2, 0x0d, 0xe3, 0x0d, 0xe4, 0x0d, 0xe5, 0x0d, 0xe6, 0x0d, 0xe7, 0x0d, 0xe8, 0x0d, 0xe9, 0x0d, 0xea, 0x0d, 0xeb, 0x0d, 0xec, 0x0d, 0xed, 0x0d, 0xee, 0x0d, 0xef, 0x0d, 0xf0, 0x0d, 0xf1, 0x0d, 0xf2, 0x0d, 0xf3, 0x0d, 0xf4, 0x0d, 0xf5, 0x0d, 0xf6, 0x0d, 0xf7, 0x0d, 0xf8, 0x0d, 0xf9, 0x0d, 0xfa, 0x0d, 0xfb, 0x0d, 0xfc, 0x0d, 0xfd, 0x0d, 0xfe, 0x0d, 0xff, 0x0e, 0x00, 0x0e, 0x01, 0x0e, 0x02, 0x0e, 0x03, 0x0e, 0x04, 0x0e, 0x05, 0x0e, 0x06, 0x0e, 0x07, 0x0e, 0x08, 0x0e, 0x09, 0x0e, 0x0a, 0x0e, 0x0b, 0x0e, 0x0c, 0x0e, 0x0d, 0x0e, 0x0e, 0x0e, 0x0f, 0x0e, 0x10, 0x0e, 0x11, 0x0e, 0x12, 0x0e, 0x13, 0x0e, 0x14, 0x0e, 0x15, 0x0e, 0x16, 0x0e, 0x17, 0x0e, 0x18, 0x0e, 0x19, 0x0e, 0x1a, 0x0e, 0x1b, 0x0e, 0x1c, 0x0e, 0x1d, 0x0e, 0x1e, 0x0e, 0x1f, 0x0e, 0x20, 0x0e, 0x21, 0x0e, 0x22, 0x0e, 0x23, 0x0e, 0x24, 0x0e, 0x25, 0x0e, 0x26, 0x0e, 0x27, 0x0e, 0x28, 0x0e, 0x29, 0x0e, 0x2a, 0x0e, 0x2b, 0x0e, 0x2c, 0x0e, 0x2d, 0x0e, 0x2e, 0x0e, 0x2f, 0x0e, 0x30, 0x0e, 0x31, 0x0e, 0x32, 0x0e, 0x33, 0x0e, 0x34, 0x0e, 0x35, 0x0e, 0x36, 0x0e, 0x37, 0x0e, 0x38, 0x0e, 0x39, 0x0e, 0x3a, 0x0e, 0x3b, 0x0e, 0x3c, 0x0e, 0x3d, 0x0e, 0x3e, 0x0e, 0x3f, 0x0e, 0x40, 0x0e, 0x41, 0x0e, 0x42, 0x0e, 0x43, 0x0e, 0x44, 0x0e, 0x45, 0x0e, 0x46, 0x0e, 0x47, 0x0e, 0x48, 0x0e, 0x49, 0x0e, 0x4a, 0x0e, 0x4b, 0x0e, 0x4c, 0x0e, 0x4d, 0x0e, 0x4e, 0x0e, 0x4f, 0x0e, 0x50, 0x0e, 0x51, 0x0e, 0x52, 0x0e, 0x53, 0x0e, 0x54, 0x0e, 0x55, 0x0e, 0x56, 0x0e, 0x57, 0x0e, 0x58, 0x0e, 0x59, 0x0e, 0x5a, 0x0e, 0x5b, 0x0e, 0x5c, 0x0e, 0x5d, 0x0e, 0x5e, 0x0e, 0x5f, 0x0e, 0x60, 0x0e, 0x61, 0x0e, 0x62, 0x0e, 0x63, 0x0e, 0x64, 0x0e, 0x65, 0x0e, 0x66, 0x0e, 0x67, 0x0e, 0x68, 0x0e, 0x69, 0x0e, 0x6a, 0x0e, 0x6b, 0x0e, 0x6c, 0x0e, 0x6d, 0x0e, 0x6e, 0x0e, 0x6f, 0x0e, 0x70, 0x0e, 0x71, 0x0e, 0x72, 0x0e, 0x73, 0x0e, 0x74, 0x0e, 0x75, 0x0e, 0x76, 0x0e, 0x77, 0x0e, 0x78, 0x0e, 0x79, 0x0e, 0x7a, 0x0e, 0x7b, 0x0e, 0x7c, 0x0e, 0x7d, 0x0e, 0x7e, 0x0e, 0x7f, 0x0e, 0x80, 0x0e, 0x81, 0x0e, 0x82, 0x0e, 0x83, 0x0e, 0x84, 0x0e, 0x85, 0x0e, 0x86, 0x0e, 0x87, 0x0e, 0x88, 0x0e, 0x89, 0x0e, 0x8a, 0x0e, 0x8b, 0x0e, 0x8c, 0x0e, 0x8d, 0x0e, 0x8e, 0x0e, 0x8f, 0x0e, 0x90, 0x0e, 0x91, 0x0e, 0x92, 0x0e, 0x93, 0x0e, 0x94, 0x0e, 0x95, 0x0e, 0x96, 0x0e, 0x97, 0x0e, 0x98, 0x0e, 0x99, 0x0e, 0x9a, 0x0e, 0x9b, 0x0e, 0x9c, 0x0e, 0x9d, 0x0e, 0x9e, 0x0e, 0x9f, 0x0e, 0xa0, 0x0e, 0xa1, 0x0e, 0xa2, 0x0e, 0xa3, 0x0e, 0xa4, 0x0e, 0xa5, 0x0e, 0xa6, 0x0e, 0xa7, 0x0e, 0xa8, 0x0e, 0xa9, 0x0e, 0xaa, 0x0e, 0xab, 0x0e, 0xac, 0x0e, 0xad, 0x0e, 0xae, 0x0e, 0xaf, 0x0e, 0xb0, 0x0e, 0xb1, 0x0e, 0xb2, 0x0e, 0xb3, 0x0e, 0xb4, 0x0e, 0xb5, 0x0e, 0xb6, 0x0e, 0xb7, 0x0e, 0xb8, 0x0e, 0xb9, 0x0e, 0xba, 0x0e, 0xbb, 0x0e, 0xbc, 0x0e, 0xbd, 0x0e, 0xbe, 0x0e, 0xbf, 0x0e, 0xc0, 0x0e, 0xc1, 0x0e, 0xc2, 0x0e, 0xc3, 0x0e, 0xc4, 0x0e, 0xc5, 0x0e, 0xc6, 0x0e, 0xc7, 0x0e, 0xc8, 0x0e, 0xc9, 0x0e, 0xca, 0x0e, 0xcb, 0x0e, 0xcc, 0x0e, 0xcd, 0x0e, 0xce, 0x0e, 0xcf, 0x0e, 0xd0, 0x0e, 0xd1, 0x0e, 0xd2, 0x0e, 0xd3, 0x0e, 0xd4, 0x0e, 0xd5, 0x0e, 0xd6, 0x0e, 0xd7, 0x0e, 0xd8, 0x0e, 0xd9, 0x0e, 0xda, 0x0e, 0xdb, 0x0e, 0xdc, 0x0e, 0xdd, 0x0e, 0xde, 0x0e, 0xdf, 0x0e, 0xe0, 0x0e, 0xe1, 0x0e, 0xe2, 0x0e, 0xe3, 0x0e, 0xe4, 0x0e, 0xe5, 0x0e, 0xe6, 0x0e, 0xe7, 0x0e, 0xe8, 0x0e, 0xe9, 0x0e, 0xea, 0x0e, 0xeb, 0x0e, 0xec, 0x0e, 0xed, 0x0e, 0xee, 0x0e, 0xef, 0x0e, 0xf0, 0x0e, 0xf1, 0x0e, 0xf2, 0x0e, 0xf3, 0x0e, 0xf4, 0x0e, 0xf5, 0x0e, 0xf6, 0x0e, 0xf7, 0x0e, 0xf8, 0x0e, 0xf9, 0x0e, 0xfa, 0x0e, 0xfb, 0x0e, 0xfc, 0x0e, 0xfd, 0x0e, 0xfe, 0x0e, 0xff, 0x0f, 0x00, 0x0f, 0x01, 0x0f, 0x02, 0x0f, 0x03, 0x0f, 0x04, 0x0f, 0x05, 0x0f, 0x06, 0x0f, 0x07, 0x0f, 0x08, 0x0f, 0x09, 0x0f, 0x0a, 0x0f, 0x0b, 0x0f, 0x0c, 0x00, 0xc0, 0x00, 0xc1, 0x0f, 0x0d, 0x0f, 0x0e, 0x0f, 0x0f, 0x0f, 0x10, 0x0f, 0x11, 0x0f, 0x12, 0x0f, 0x13, 0x0f, 0x14, 0x0f, 0x15, 0x0f, 0x16, 0x0f, 0x17, 0x0f, 0x18, 0x0f, 0x19, 0x0f, 0x1a, 0x0f, 0x1b, 0x0f, 0x1c, 0x0f, 0x1d, 0x0f, 0x1e, 0x0f, 0x1f, 0x0f, 0x20, 0x0f, 0x21, 0x0f, 0x22, 0x0f, 0x23, 0x0f, 0x24, 0x0f, 0x25, 0x0f, 0x26, 0x0f, 0x27, 0x0f, 0x28, 0x0f, 0x29, 0x0f, 0x2a, 0x0f, 0x2b, 0x0f, 0x2c, 0x0f, 0x2d, 0x0f, 0x2e, 0x0f, 0x2f, 0x0f, 0x30, 0x0f, 0x31, 0x0f, 0x32, 0x0f, 0x33, 0x0f, 0x34, 0x0f, 0x35, 0x0f, 0x36, 0x0f, 0x37, 0x0f, 0x38, 0x0f, 0x39, 0x0f, 0x3a, 0x0f, 0x3b, 0x0f, 0x3c, 0x0f, 0x3d, 0x0f, 0x3e, 0x0f, 0x3f, 0x0f, 0x40, 0x0f, 0x41, 0x0f, 0x42, 0x0f, 0x43, 0x0f, 0x44, 0x0f, 0x45, 0x0f, 0x46, 0x0f, 0x47, 0x0f, 0x48, 0x0f, 0x49, 0x0f, 0x4a, 0x0f, 0x4b, 0x0f, 0x4c, 0x0f, 0x4d, 0x0f, 0x4e, 0x0f, 0x4f, 0x0f, 0x50, 0x0f, 0x51, 0x0f, 0x52, 0x0f, 0x53, 0x0f, 0x54, 0x0f, 0x55, 0x0f, 0x56, 0x0f, 0x57, 0x0f, 0x58, 0x0f, 0x59, 0x0f, 0x5a, 0x0f, 0x5b, 0x0f, 0x5c, 0x0f, 0x5d, 0x0f, 0x5e, 0x0f, 0x5f, 0x0f, 0x60, 0x0f, 0x61, 0x0f, 0x62, 0x0f, 0x63, 0x0f, 0x64, 0x0f, 0x65, 0x0f, 0x66, 0x0f, 0x67, 0x0f, 0x68, 0x0f, 0x69, 0x0f, 0x6a, 0x0f, 0x6b, 0x0f, 0x6c, 0x0f, 0x6d, 0x0f, 0x6e, 0x0f, 0x6f, 0x0f, 0x70, 0x0f, 0x71, 0x0f, 0x72, 0x0f, 0x73, 0x0f, 0x74, 0x0f, 0x75, 0x0f, 0x76, 0x0f, 0x77, 0x0f, 0x78, 0x0f, 0x79, 0x0f, 0x7a, 0x0f, 0x7b, 0x0f, 0x7c, 0x0f, 0x7d, 0x0f, 0x7e, 0x0f, 0x7f, 0x0f, 0x80, 0x0f, 0x81, 0x0f, 0x82, 0x0f, 0x83, 0x0f, 0x84, 0x0f, 0x85, 0x0f, 0x86, 0x0f, 0x87, 0x0f, 0x88, 0x0f, 0x89, 0x0f, 0x8a, 0x0f, 0x8b, 0x0f, 0x8c, 0x0f, 0x8d, 0x0f, 0x8e, 0x0f, 0x8f, 0x0f, 0x90, 0x0f, 0x91, 0x0f, 0x92, 0x0f, 0x93, 0x0f, 0x94, 0x0f, 0x95, 0x0f, 0x96, 0x0f, 0x97, 0x0f, 0x98, 0x0f, 0x99, 0x0f, 0x9a, 0x0f, 0x9b, 0x0f, 0x9c, 0x0f, 0x9d, 0x0f, 0x9e, 0x0f, 0x9f, 0x0f, 0xa0, 0x0f, 0xa1, 0x0f, 0xa2, 0x0f, 0xa3, 0x0f, 0xa4, 0x0f, 0xa5, 0x0f, 0xa6, 0x0f, 0xa7, 0x0f, 0xa8, 0x0f, 0xa9, 0x0f, 0xaa, 0x0f, 0xab, 0x0f, 0xac, 0x0f, 0xad, 0x0f, 0xae, 0x0f, 0xaf, 0x0f, 0xb0, 0x0f, 0xb1, 0x0f, 0xb2, 0x0f, 0xb3, 0x0f, 0xb4, 0x0f, 0xb5, 0x0f, 0xb6, 0x0f, 0xb7, 0x0f, 0xb8, 0x0f, 0xb9, 0x0f, 0xba, 0x0f, 0xbb, 0x0f, 0xbc, 0x0f, 0xbd, 0x0f, 0xbe, 0x0f, 0xbf, 0x0f, 0xc0, 0x0f, 0xc1, 0x0f, 0xc2, 0x0f, 0xc3, 0x0f, 0xc4, 0x0f, 0xc5, 0x0f, 0xc6, 0x0f, 0xc7, 0x0f, 0xc8, 0x0f, 0xc9, 0x0f, 0xca, 0x0f, 0xcb, 0x0f, 0xcc, 0x0f, 0xcd, 0x0f, 0xce, 0x0f, 0xcf, 0x0f, 0xd0, 0x0f, 0xd1, 0x0f, 0xd2, 0x0f, 0xd3, 0x0f, 0xd4, 0x0f, 0xd5, 0x0f, 0xd6, 0x0f, 0xd7, 0x0f, 0xd8, 0x0f, 0xd9, 0x0f, 0xda, 0x0f, 0xdb, 0x0f, 0xdc, 0x0f, 0xdd, 0x0f, 0xde, 0x0f, 0xdf, 0x0f, 0xe0, 0x0f, 0xe1, 0x0f, 0xe2, 0x0f, 0xe3, 0x0f, 0xe4, 0x0f, 0xe5, 0x0f, 0xe6, 0x0f, 0xe7, 0x0f, 0xe8, 0x0f, 0xe9, 0x0f, 0xea, 0x0f, 0xeb, 0x0f, 0xec, 0x0f, 0xed, 0x0f, 0xee, 0x0f, 0xef, 0x0f, 0xf0, 0x0f, 0xf1, 0x0f, 0xf2, 0x0f, 0xf3, 0x0f, 0xf4, 0x0f, 0xf5, 0x0f, 0xf6, 0x0f, 0xf7, 0x0f, 0xf8, 0x0f, 0xf9, 0x0f, 0xfa, 0x0f, 0xfb, 0x0f, 0xfc, 0x0f, 0xfd, 0x0f, 0xfe, 0x0f, 0xff, 0x10, 0x00, 0x10, 0x01, 0x10, 0x02, 0x10, 0x03, 0x10, 0x04, 0x10, 0x05, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 0x09, 0x10, 0x0a, 0x10, 0x0b, 0x10, 0x0c, 0x10, 0x0d, 0x10, 0x0e, 0x10, 0x0f, 0x10, 0x10, 0x10, 0x11, 0x10, 0x12, 0x10, 0x13, 0x10, 0x14, 0x10, 0x15, 0x10, 0x16, 0x10, 0x17, 0x10, 0x18, 0x10, 0x19, 0x10, 0x1a, 0x10, 0x1b, 0x10, 0x1c, 0x10, 0x1d, 0x10, 0x1e, 0x10, 0x1f, 0x10, 0x20, 0x10, 0x21, 0x10, 0x22, 0x10, 0x23, 0x10, 0x24, 0x10, 0x25, 0x10, 0x26, 0x10, 0x27, 0x10, 0x28, 0x10, 0x29, 0x10, 0x2a, 0x10, 0x2b, 0x10, 0x2c, 0x10, 0x2d, 0x10, 0x2e, 0x10, 0x2f, 0x10, 0x30, 0x10, 0x31, 0x10, 0x32, 0x10, 0x33, 0x10, 0x34, 0x10, 0x35, 0x10, 0x36, 0x10, 0x37, 0x10, 0x38, 0x10, 0x39, 0x10, 0x3a, 0x10, 0x3b, 0x10, 0x3c, 0x10, 0x3d, 0x10, 0x3e, 0x10, 0x3f, 0x10, 0x40, 0x10, 0x41, 0x10, 0x42, 0x10, 0x43, 0x10, 0x44, 0x10, 0x45, 0x10, 0x46, 0x10, 0x47, 0x10, 0x48, 0x10, 0x49, 0x10, 0x4a, 0x10, 0x4b, 0x10, 0x4c, 0x10, 0x4d, 0x10, 0x4e, 0x10, 0x4f, 0x10, 0x50, 0x10, 0x51, 0x10, 0x52, 0x10, 0x53, 0x10, 0x54, 0x10, 0x55, 0x10, 0x56, 0x10, 0x57, 0x10, 0x58, 0x10, 0x59, 0x10, 0x5a, 0x10, 0x5b, 0x10, 0x5c, 0x10, 0x5d, 0x10, 0x5e, 0x10, 0x5f, 0x10, 0x60, 0x10, 0x61, 0x10, 0x62, 0x10, 0x63, 0x10, 0x64, 0x10, 0x65, 0x10, 0x66, 0x10, 0x67, 0x10, 0x68, 0x10, 0x69, 0x10, 0x6a, 0x10, 0x6b, 0x10, 0x6c, 0x10, 0x6d, 0x10, 0x6e, 0x10, 0x6f, 0x10, 0x70, 0x10, 0x71, 0x10, 0x72, 0x10, 0x73, 0x10, 0x74, 0x10, 0x75, 0x10, 0x76, 0x10, 0x77, 0x10, 0x78, 0x10, 0x79, 0x10, 0x7a, 0x10, 0x7b, 0x10, 0x7c, 0x10, 0x7d, 0x10, 0x7e, 0x10, 0x7f, 0x10, 0x80, 0x10, 0x81, 0x10, 0x82, 0x10, 0x83, 0x10, 0x84, 0x10, 0x85, 0x10, 0x86, 0x10, 0x87, 0x10, 0x88, 0x10, 0x89, 0x10, 0x8a, 0x10, 0x8b, 0x10, 0x8c, 0x10, 0x8d, 0x10, 0x8e, 0x10, 0x8f, 0x10, 0x90, 0x10, 0x91, 0x10, 0x92, 0x10, 0x93, 0x10, 0x94, 0x10, 0x95, 0x10, 0x96, 0x10, 0x97, 0x10, 0x98, 0x10, 0x99, 0x10, 0x9a, 0x10, 0x9b, 0x10, 0x9c, 0x10, 0x9d, 0x10, 0x9e, 0x10, 0x9f, 0x10, 0xa0, 0x10, 0xa1, 0x10, 0xa2, 0x10, 0xa3, 0x10, 0xa4, 0x10, 0xa5, 0x10, 0xa6, 0x10, 0xa7, 0x10, 0xa8, 0x10, 0xa9, 0x10, 0xaa, 0x10, 0xab, 0x10, 0xac, 0x10, 0xad, 0x10, 0xae, 0x10, 0xaf, 0x10, 0xb0, 0x10, 0xb1, 0x10, 0xb2, 0x10, 0xb3, 0x10, 0xb4, 0x10, 0xb5, 0x10, 0xb6, 0x10, 0xb7, 0x10, 0xb8, 0x10, 0xb9, 0x10, 0xba, 0x10, 0xbb, 0x10, 0xbc, 0x10, 0xbd, 0x10, 0xbe, 0x10, 0xbf, 0x10, 0xc0, 0x10, 0xc1, 0x10, 0xc2, 0x10, 0xc3, 0x10, 0xc4, 0x10, 0xc5, 0x10, 0xc6, 0x10, 0xc7, 0x10, 0xc8, 0x10, 0xc9, 0x10, 0xca, 0x10, 0xcb, 0x10, 0xcc, 0x10, 0xcd, 0x10, 0xce, 0x10, 0xcf, 0x10, 0xd0, 0x10, 0xd1, 0x10, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0x10, 0xd5, 0x10, 0xd6, 0x10, 0xd7, 0x10, 0xd8, 0x10, 0xd9, 0x10, 0xda, 0x10, 0xdb, 0x10, 0xdc, 0x10, 0xdd, 0x10, 0xde, 0x10, 0xdf, 0x10, 0xe0, 0x10, 0xe1, 0x10, 0xe2, 0x10, 0xe3, 0x10, 0xe4, 0x10, 0xe5, 0x10, 0xe6, 0x10, 0xe7, 0x10, 0xe8, 0x10, 0xe9, 0x10, 0xea, 0x10, 0xeb, 0x10, 0xec, 0x10, 0xed, 0x10, 0xee, 0x10, 0xef, 0x10, 0xf0, 0x10, 0xf1, 0x10, 0xf2, 0x10, 0xf3, 0x10, 0xf4, 0x10, 0xf5, 0x10, 0xf6, 0x10, 0xf7, 0x10, 0xf8, 0x10, 0xf9, 0x10, 0xfa, 0x10, 0xfb, 0x10, 0xfc, 0x10, 0xfd, 0x10, 0xfe, 0x10, 0xff, 0x11, 0x00, 0x11, 0x01, 0x11, 0x02, 0x11, 0x03, 0x11, 0x04, 0x11, 0x05, 0x11, 0x06, 0x11, 0x07, 0x11, 0x08, 0x11, 0x09, 0x11, 0x0a, 0x11, 0x0b, 0x11, 0x0c, 0x11, 0x0d, 0x11, 0x0e, 0x11, 0x0f, 0x11, 0x10, 0x11, 0x11, 0x11, 0x12, 0x11, 0x13, 0x11, 0x14, 0x11, 0x15, 0x11, 0x16, 0x11, 0x17, 0x11, 0x18, 0x11, 0x19, 0x11, 0x1a, 0x11, 0x1b, 0x11, 0x1c, 0x11, 0x1d, 0x11, 0x1e, 0x11, 0x1f, 0x11, 0x20, 0x11, 0x21, 0x11, 0x22, 0x11, 0x23, 0x11, 0x24, 0x11, 0x25, 0x11, 0x26, 0x11, 0x27, 0x11, 0x28, 0x11, 0x29, 0x11, 0x2a, 0x11, 0x2b, 0x11, 0x2c, 0x11, 0x2d, 0x11, 0x2e, 0x11, 0x2f, 0x11, 0x30, 0x11, 0x31, 0x11, 0x32, 0x11, 0x33, 0x11, 0x34, 0x11, 0x35, 0x11, 0x36, 0x11, 0x37, 0x11, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x11, 0x3b, 0x11, 0x3c, 0x11, 0x3d, 0x11, 0x3e, 0x11, 0x3f, 0x11, 0x40, 0x11, 0x41, 0x11, 0x42, 0x11, 0x43, 0x11, 0x44, 0x11, 0x45, 0x11, 0x46, 0x11, 0x47, 0x11, 0x48, 0x11, 0x49, 0x11, 0x4a, 0x11, 0x4b, 0x11, 0x4c, 0x11, 0x4d, 0x11, 0x4e, 0x11, 0x4f, 0x11, 0x50, 0x11, 0x51, 0x11, 0x52, 0x11, 0x53, 0x11, 0x54, 0x11, 0x55, 0x11, 0x56, 0x11, 0x57, 0x11, 0x58, 0x11, 0x59, 0x11, 0x5a, 0x11, 0x5b, 0x11, 0x5c, 0x11, 0x5d, 0x11, 0x5e, 0x11, 0x5f, 0x11, 0x60, 0x11, 0x61, 0x11, 0x62, 0x11, 0x63, 0x11, 0x64, 0x11, 0x65, 0x11, 0x66, 0x11, 0x67, 0x11, 0x68, 0x11, 0x69, 0x11, 0x6a, 0x11, 0x6b, 0x11, 0x6c, 0x11, 0x6d, 0x11, 0x6e, 0x11, 0x6f, 0x11, 0x70, 0x11, 0x71, 0x11, 0x72, 0x11, 0x73, 0x11, 0x74, 0x11, 0x75, 0x11, 0x76, 0x11, 0x77, 0x11, 0x78, 0x11, 0x79, 0x11, 0x7a, 0x11, 0x7b, 0x11, 0x7c, 0x11, 0x7d, 0x11, 0x7e, 0x11, 0x7f, 0x11, 0x80, 0x11, 0x81, 0x11, 0x82, 0x11, 0x83, 0x11, 0x84, 0x11, 0x85, 0x11, 0x86, 0x11, 0x87, 0x11, 0x88, 0x11, 0x89, 0x11, 0x8a, 0x11, 0x8b, 0x11, 0x8c, 0x11, 0x8d, 0x11, 0x8e, 0x11, 0x8f, 0x11, 0x90, 0x11, 0x91, 0x11, 0x92, 0x11, 0x93, 0x11, 0x94, 0x11, 0x95, 0x11, 0x96, 0x11, 0x97, 0x11, 0x98, 0x11, 0x99, 0x11, 0x9a, 0x11, 0x9b, 0x11, 0x9c, 0x11, 0x9d, 0x11, 0x9e, 0x11, 0x9f, 0x11, 0xa0, 0x11, 0xa1, 0x11, 0xa2, 0x11, 0xa3, 0x11, 0xa4, 0x11, 0xa5, 0x11, 0xa6, 0x11, 0xa7, 0x11, 0xa8, 0x11, 0xa9, 0x11, 0xaa, 0x11, 0xab, 0x11, 0xac, 0x11, 0xad, 0x11, 0xae, 0x11, 0xaf, 0x11, 0xb0, 0x11, 0xb1, 0x11, 0xb2, 0x11, 0xb3, 0x11, 0xb4, 0x11, 0xb5, 0x11, 0xb6, 0x11, 0xb7, 0x11, 0xb8, 0x11, 0xb9, 0x11, 0xba, 0x11, 0xbb, 0x11, 0xbc, 0x11, 0xbd, 0x11, 0xbe, 0x11, 0xbf, 0x11, 0xc0, 0x11, 0xc1, 0x11, 0xc2, 0x11, 0xc3, 0x11, 0xc4, 0x11, 0xc5, 0x11, 0xc6, 0x11, 0xc7, 0x11, 0xc8, 0x11, 0xc9, 0x11, 0xca, 0x11, 0xcb, 0x11, 0xcc, 0x11, 0xcd, 0x11, 0xce, 0x11, 0xcf, 0x11, 0xd0, 0x11, 0xd1, 0x11, 0xd2, 0x11, 0xd3, 0x11, 0xd4, 0x11, 0xd5, 0x11, 0xd6, 0x11, 0xd7, 0x11, 0xd8, 0x11, 0xd9, 0x11, 0xda, 0x11, 0xdb, 0x11, 0xdc, 0x11, 0xdd, 0x11, 0xde, 0x11, 0xdf, 0x11, 0xe0, 0x11, 0xe1, 0x11, 0xe2, 0x11, 0xe3, 0x11, 0xe4, 0x11, 0xe5, 0x11, 0xe6, 0x11, 0xe7, 0x11, 0xe8, 0x11, 0xe9, 0x11, 0xea, 0x11, 0xeb, 0x11, 0xec, 0x11, 0xed, 0x11, 0xee, 0x11, 0xef, 0x11, 0xf0, 0x11, 0xf1, 0x11, 0xf2, 0x11, 0xf3, 0x11, 0xf4, 0x11, 0xf5, 0x11, 0xf6, 0x11, 0xf7, 0x11, 0xf8, 0x11, 0xf9, 0x11, 0xfa, 0x11, 0xfb, 0x11, 0xfc, 0x11, 0xfd, 0x11, 0xfe, 0x11, 0xff, 0x12, 0x00, 0x12, 0x01, 0x12, 0x02, 0x12, 0x03, 0x12, 0x04, 0x12, 0x05, 0x12, 0x06, 0x12, 0x07, 0x12, 0x08, 0x12, 0x09, 0x12, 0x0a, 0x12, 0x0b, 0x12, 0x0c, 0x12, 0x0d, 0x12, 0x0e, 0x09, 0x73, 0x66, 0x74, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x07, 0x41, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x61, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x06, 0x41, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06, 0x61, 0x62, 0x72, 0x65, 0x76, 0x65, 0x07, 0x41, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07, 0x61, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x0b, 0x43, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0b, 0x63, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0a, 0x43, 0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0a, 0x63, 0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x44, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x64, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x44, 0x63, 0x72, 0x6f, 0x61, 0x74, 0x07, 0x45, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x65, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x06, 0x45, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06, 0x65, 0x62, 0x72, 0x65, 0x76, 0x65, 0x0a, 0x45, 0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0a, 0x65, 0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x45, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07, 0x65, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x06, 0x45, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x65, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x0b, 0x47, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0b, 0x67, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0a, 0x47, 0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0a, 0x67, 0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x47, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x67, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0b, 0x48, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0b, 0x68, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x04, 0x48, 0x62, 0x61, 0x72, 0x04, 0x68, 0x62, 0x61, 0x72, 0x06, 0x49, 0x74, 0x69, 0x6c, 0x64, 0x65, 0x06, 0x69, 0x74, 0x69, 0x6c, 0x64, 0x65, 0x07, 0x49, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x69, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x06, 0x49, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06, 0x69, 0x62, 0x72, 0x65, 0x76, 0x65, 0x07, 0x49, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07, 0x69, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x02, 0x49, 0x4a, 0x02, 0x69, 0x6a, 0x0b, 0x4a, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0b, 0x6a, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0c, 0x4b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x6b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x6b, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x63, 0x06, 0x4c, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x6c, 0x61, 0x63, 0x75, 0x74, 0x65, 0x0c, 0x4c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x6c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x4c, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x6c, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x04, 0x4c, 0x64, 0x6f, 0x74, 0x04, 0x6c, 0x64, 0x6f, 0x74, 0x06, 0x4e, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x6e, 0x61, 0x63, 0x75, 0x74, 0x65, 0x0c, 0x4e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x6e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x4e, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x6e, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x0b, 0x6e, 0x61, 0x70, 0x6f, 0x73, 0x74, 0x72, 0x6f, 0x70, 0x68, 0x65, 0x03, 0x45, 0x6e, 0x67, 0x03, 0x65, 0x6e, 0x67, 0x07, 0x4f, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x6f, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x06, 0x4f, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06, 0x6f, 0x62, 0x72, 0x65, 0x76, 0x65, 0x0d, 0x4f, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d, 0x6c, 0x61, 0x75, 0x74, 0x0d, 0x6f, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d, 0x6c, 0x61, 0x75, 0x74, 0x06, 0x52, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x72, 0x61, 0x63, 0x75, 0x74, 0x65, 0x0c, 0x52, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x52, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x72, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x53, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x73, 0x61, 0x63, 0x75, 0x74, 0x65, 0x0b, 0x53, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0b, 0x73, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0c, 0x54, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x06, 0x54, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x74, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x04, 0x54, 0x62, 0x61, 0x72, 0x04, 0x74, 0x62, 0x61, 0x72, 0x06, 0x55, 0x74, 0x69, 0x6c, 0x64, 0x65, 0x06, 0x75, 0x74, 0x69, 0x6c, 0x64, 0x65, 0x07, 0x55, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x07, 0x75, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x6e, 0x06, 0x55, 0x62, 0x72, 0x65, 0x76, 0x65, 0x06, 0x75, 0x62, 0x72, 0x65, 0x76, 0x65, 0x05, 0x55, 0x72, 0x69, 0x6e, 0x67, 0x05, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x0d, 0x55, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d, 0x6c, 0x61, 0x75, 0x74, 0x0d, 0x75, 0x68, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d, 0x6c, 0x61, 0x75, 0x74, 0x07, 0x55, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x07, 0x75, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x0b, 0x57, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0b, 0x77, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0b, 0x59, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x0b, 0x79, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x06, 0x5a, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x7a, 0x61, 0x63, 0x75, 0x74, 0x65, 0x0a, 0x5a, 0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0a, 0x7a, 0x64, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x05, 0x6c, 0x6f, 0x6e, 0x67, 0x73, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x39, 0x46, 0x05, 0x4f, 0x68, 0x6f, 0x72, 0x6e, 0x05, 0x6f, 0x68, 0x6f, 0x72, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x41, 0x45, 0x05, 0x55, 0x68, 0x6f, 0x72, 0x6e, 0x05, 0x75, 0x68, 0x6f, 0x72, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x35, 0x06, 0x47, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x06, 0x67, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x31, 0x46, 0x39, 0x0a, 0x41, 0x72, 0x69, 0x6e, 0x67, 0x61, 0x63, 0x75, 0x74, 0x65, 0x0a, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x61, 0x63, 0x75, 0x74, 0x65, 0x07, 0x41, 0x45, 0x61, 0x63, 0x75, 0x74, 0x65, 0x07, 0x61, 0x65, 0x61, 0x63, 0x75, 0x74, 0x65, 0x0b, 0x4f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x61, 0x63, 0x75, 0x74, 0x65, 0x0b, 0x6f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x61, 0x63, 0x75, 0x74, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x37, 0x0c, 0x53, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x73, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x36, 0x08, 0x64, 0x6f, 0x74, 0x6c, 0x65, 0x73, 0x73, 0x6a, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x46, 0x37, 0x09, 0x67, 0x72, 0x61, 0x76, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x09, 0x61, 0x63, 0x75, 0x74, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x32, 0x09, 0x74, 0x69, 0x6c, 0x64, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x38, 0x0d, 0x68, 0x6f, 0x6f, 0x6b, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x63, 0x6f, 0x6d, 0x62, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x32, 0x0c, 0x64, 0x6f, 0x74, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6d, 0x62, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x37, 0x45, 0x05, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x0d, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x0a, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x09, 0x61, 0x6e, 0x6f, 0x74, 0x65, 0x6c, 0x65, 0x69, 0x61, 0x0c, 0x45, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x08, 0x45, 0x74, 0x61, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x09, 0x49, 0x6f, 0x74, 0x61, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x0c, 0x4f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x0c, 0x55, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x0a, 0x4f, 0x6d, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x11, 0x69, 0x6f, 0x74, 0x61, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x05, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x04, 0x42, 0x65, 0x74, 0x61, 0x05, 0x47, 0x61, 0x6d, 0x6d, 0x61, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x39, 0x34, 0x07, 0x45, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x04, 0x5a, 0x65, 0x74, 0x61, 0x03, 0x45, 0x74, 0x61, 0x05, 0x54, 0x68, 0x65, 0x74, 0x61, 0x04, 0x49, 0x6f, 0x74, 0x61, 0x05, 0x4b, 0x61, 0x70, 0x70, 0x61, 0x06, 0x4c, 0x61, 0x6d, 0x62, 0x64, 0x61, 0x02, 0x4d, 0x75, 0x02, 0x4e, 0x75, 0x02, 0x58, 0x69, 0x07, 0x4f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6e, 0x02, 0x50, 0x69, 0x03, 0x52, 0x68, 0x6f, 0x05, 0x53, 0x69, 0x67, 0x6d, 0x61, 0x03, 0x54, 0x61, 0x75, 0x07, 0x55, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x03, 0x50, 0x68, 0x69, 0x03, 0x43, 0x68, 0x69, 0x03, 0x50, 0x73, 0x69, 0x0c, 0x49, 0x6f, 0x74, 0x61, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x0f, 0x55, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x0a, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x0c, 0x65, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x08, 0x65, 0x74, 0x61, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x09, 0x69, 0x6f, 0x74, 0x61, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x14, 0x75, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x05, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x04, 0x62, 0x65, 0x74, 0x61, 0x05, 0x67, 0x61, 0x6d, 0x6d, 0x61, 0x05, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x07, 0x65, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x04, 0x7a, 0x65, 0x74, 0x61, 0x03, 0x65, 0x74, 0x61, 0x05, 0x74, 0x68, 0x65, 0x74, 0x61, 0x04, 0x69, 0x6f, 0x74, 0x61, 0x05, 0x6b, 0x61, 0x70, 0x70, 0x61, 0x06, 0x6c, 0x61, 0x6d, 0x62, 0x64, 0x61, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x42, 0x43, 0x02, 0x6e, 0x75, 0x02, 0x78, 0x69, 0x07, 0x6f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6e, 0x03, 0x72, 0x68, 0x6f, 0x06, 0x73, 0x69, 0x67, 0x6d, 0x61, 0x31, 0x05, 0x73, 0x69, 0x67, 0x6d, 0x61, 0x03, 0x74, 0x61, 0x75, 0x07, 0x75, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x03, 0x70, 0x68, 0x69, 0x03, 0x63, 0x68, 0x69, 0x03, 0x70, 0x73, 0x69, 0x05, 0x6f, 0x6d, 0x65, 0x67, 0x61, 0x0c, 0x69, 0x6f, 0x74, 0x61, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x0f, 0x75, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x0c, 0x6f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x0c, 0x75, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x0a, 0x6f, 0x6d, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x6e, 0x6f, 0x73, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x30, 0x06, 0x74, 0x68, 0x65, 0x74, 0x61, 0x31, 0x08, 0x55, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x34, 0x04, 0x70, 0x68, 0x69, 0x31, 0x06, 0x6f, 0x6d, 0x65, 0x67, 0x61, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x46, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x46, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x35, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x43, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x44, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x37, 0x46, 0x06, 0x57, 0x67, 0x72, 0x61, 0x76, 0x65, 0x06, 0x77, 0x67, 0x72, 0x61, 0x76, 0x65, 0x06, 0x57, 0x61, 0x63, 0x75, 0x74, 0x65, 0x06, 0x77, 0x61, 0x63, 0x75, 0x74, 0x65, 0x09, 0x57, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x09, 0x77, 0x64, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x31, 0x06, 0x59, 0x67, 0x72, 0x61, 0x76, 0x65, 0x06, 0x79, 0x67, 0x72, 0x61, 0x76, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x31, 0x46, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x31, 0x31, 0x0a, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x61, 0x73, 0x68, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x31, 0x36, 0x0d, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x64, 0x62, 0x6c, 0x0d, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x64, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x33, 0x0e, 0x6f, 0x6e, 0x65, 0x64, 0x6f, 0x74, 0x65, 0x6e, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0e, 0x74, 0x77, 0x6f, 0x64, 0x6f, 0x74, 0x65, 0x6e, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x31, 0x06, 0x6d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x06, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x42, 0x09, 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, 0x64, 0x62, 0x6c, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x30, 0x0d, 0x63, 0x6f, 0x6c, 0x6f, 0x6e, 0x6d, 0x6f, 0x6e, 0x65, 0x74, 0x61, 0x72, 0x79, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x32, 0x04, 0x6c, 0x69, 0x72, 0x61, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x36, 0x06, 0x70, 0x65, 0x73, 0x65, 0x74, 0x61, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x41, 0x04, 0x64, 0x6f, 0x6e, 0x67, 0x04, 0x45, 0x75, 0x72, 0x6f, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x30, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x30, 0x08, 0x49, 0x66, 0x72, 0x61, 0x6b, 0x74, 0x75, 0x72, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x37, 0x0b, 0x77, 0x65, 0x69, 0x65, 0x72, 0x73, 0x74, 0x72, 0x61, 0x73, 0x73, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x42, 0x08, 0x52, 0x66, 0x72, 0x61, 0x6b, 0x74, 0x75, 0x72, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x44, 0x0c, 0x70, 0x72, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x44, 0x09, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x34, 0x05, 0x61, 0x6c, 0x65, 0x70, 0x68, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x32, 0x08, 0x6f, 0x6e, 0x65, 0x74, 0x68, 0x69, 0x72, 0x64, 0x09, 0x74, 0x77, 0x6f, 0x74, 0x68, 0x69, 0x72, 0x64, 0x73, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x41, 0x09, 0x6f, 0x6e, 0x65, 0x65, 0x69, 0x67, 0x68, 0x74, 0x68, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x65, 0x65, 0x69, 0x67, 0x68, 0x74, 0x68, 0x73, 0x0b, 0x66, 0x69, 0x76, 0x65, 0x65, 0x69, 0x67, 0x68, 0x74, 0x68, 0x73, 0x0c, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x74, 0x68, 0x73, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x38, 0x39, 0x09, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x65, 0x66, 0x74, 0x07, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x75, 0x70, 0x0a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x72, 0x69, 0x67, 0x68, 0x74, 0x09, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x77, 0x6e, 0x09, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x62, 0x6f, 0x74, 0x68, 0x09, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x75, 0x70, 0x64, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x37, 0x0c, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x75, 0x70, 0x64, 0x6e, 0x62, 0x73, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x34, 0x0e, 0x63, 0x61, 0x72, 0x72, 0x69, 0x61, 0x67, 0x65, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x43, 0x46, 0x0c, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x62, 0x6c, 0x6c, 0x65, 0x66, 0x74, 0x0a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x62, 0x6c, 0x75, 0x70, 0x0d, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x62, 0x6c, 0x72, 0x69, 0x67, 0x68, 0x74, 0x0c, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x62, 0x6c, 0x64, 0x6f, 0x77, 0x6e, 0x0c, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x62, 0x6c, 0x62, 0x6f, 0x74, 0x68, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x46, 0x46, 0x09, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x30, 0x31, 0x0b, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x30, 0x34, 0x08, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x73, 0x65, 0x74, 0x08, 0x67, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x6e, 0x6f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x30, 0x41, 0x08, 0x73, 0x75, 0x63, 0x68, 0x74, 0x68, 0x61, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x36, 0x0c, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x6d, 0x61, 0x74, 0x68, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x31, 0x43, 0x0c, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x0a, 0x6f, 0x72, 0x74, 0x68, 0x6f, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x05, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x36, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x09, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x6f, 0x72, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x05, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x33, 0x09, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x42, 0x07, 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x34, 0x09, 0x63, 0x6f, 0x6e, 0x67, 0x72, 0x75, 0x65, 0x6e, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x35, 0x46, 0x0b, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x63, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x31, 0x0c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x73, 0x75, 0x70, 0x65, 0x72, 0x73, 0x65, 0x74, 0x09, 0x6e, 0x6f, 0x74, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x35, 0x0c, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x0e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x78, 0x73, 0x75, 0x70, 0x65, 0x72, 0x73, 0x65, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x34, 0x0a, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x70, 0x6c, 0x75, 0x73, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x36, 0x0e, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x34, 0x0d, 0x70, 0x65, 0x72, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x34, 0x07, 0x64, 0x6f, 0x74, 0x6d, 0x61, 0x74, 0x68, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x32, 0x46, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x31, 0x05, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x30, 0x46, 0x0d, 0x72, 0x65, 0x76, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x6e, 0x6f, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x31, 0x46, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x6c, 0x74, 0x70, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x6c, 0x62, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x33, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x34, 0x36, 0x39, 0x08, 0x53, 0x46, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x31, 0x08, 0x53, 0x46, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x42, 0x08, 0x53, 0x46, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x30, 0x46, 0x08, 0x53, 0x46, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x33, 0x08, 0x53, 0x46, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x37, 0x08, 0x53, 0x46, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x42, 0x08, 0x53, 0x46, 0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x33, 0x08, 0x53, 0x46, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x42, 0x08, 0x53, 0x46, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x33, 0x08, 0x53, 0x46, 0x30, 0x37, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x42, 0x08, 0x53, 0x46, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x34, 0x46, 0x08, 0x53, 0x46, 0x34, 0x33, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x35, 0x31, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x35, 0x32, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x33, 0x39, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x31, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x35, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x39, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x33, 0x38, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x38, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x33, 0x36, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x33, 0x37, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x32, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x31, 0x39, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x37, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x38, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x31, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x35, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x36, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x35, 0x34, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x35, 0x33, 0x30, 0x30, 0x30, 0x30, 0x08, 0x53, 0x46, 0x34, 0x34, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x37, 0x46, 0x07, 0x75, 0x70, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x33, 0x07, 0x64, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x37, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x42, 0x07, 0x6c, 0x66, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x38, 0x46, 0x07, 0x72, 0x74, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x07, 0x6c, 0x74, 0x73, 0x68, 0x61, 0x64, 0x65, 0x05, 0x73, 0x68, 0x61, 0x64, 0x65, 0x07, 0x64, 0x6b, 0x73, 0x68, 0x61, 0x64, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x39, 0x46, 0x09, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x62, 0x6f, 0x78, 0x06, 0x48, 0x32, 0x32, 0x30, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x39, 0x06, 0x48, 0x31, 0x38, 0x35, 0x34, 0x33, 0x06, 0x48, 0x31, 0x38, 0x35, 0x35, 0x31, 0x0a, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x72, 0x65, 0x63, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x31, 0x07, 0x74, 0x72, 0x69, 0x61, 0x67, 0x75, 0x70, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x39, 0x07, 0x74, 0x72, 0x69, 0x61, 0x67, 0x72, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x42, 0x07, 0x74, 0x72, 0x69, 0x61, 0x67, 0x64, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x33, 0x07, 0x74, 0x72, 0x69, 0x61, 0x67, 0x6c, 0x66, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x39, 0x06, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x43, 0x45, 0x06, 0x48, 0x31, 0x38, 0x35, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x37, 0x09, 0x69, 0x6e, 0x76, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x09, 0x69, 0x6e, 0x76, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x35, 0x0a, 0x6f, 0x70, 0x65, 0x6e, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x35, 0x46, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x39, 0x09, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x66, 0x61, 0x63, 0x65, 0x0c, 0x69, 0x6e, 0x76, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x66, 0x61, 0x63, 0x65, 0x03, 0x73, 0x75, 0x6e, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x46, 0x06, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x31, 0x04, 0x6d, 0x61, 0x6c, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x35, 0x46, 0x05, 0x73, 0x70, 0x61, 0x64, 0x65, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x32, 0x04, 0x63, 0x6c, 0x75, 0x62, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x34, 0x05, 0x68, 0x65, 0x61, 0x72, 0x74, 0x07, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x39, 0x0b, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x6e, 0x6f, 0x74, 0x65, 0x0e, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x6e, 0x6f, 0x74, 0x65, 0x64, 0x62, 0x6c, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x37, 0x46, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x35, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x42, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x44, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x45, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x38, 0x46, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x43, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x43, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x44, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x44, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x44, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x44, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x44, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x44, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x45, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x39, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x38, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x39, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x41, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x41, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x42, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x41, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x42, 0x35, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x36, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x32, 0x43, 0x37, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x34, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x35, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x35, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x35, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x35, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x35, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x35, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x36, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x36, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x36, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x36, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x38, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x39, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x39, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x41, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x46, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x46, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x41, 0x37, 0x46, 0x46, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x35, 0x2e, 0x35, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x36, 0x2e, 0x35, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x37, 0x2e, 0x35, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x38, 0x2e, 0x35, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x39, 0x2e, 0x35, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x35, 0x2e, 0x34, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x36, 0x2e, 0x34, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x37, 0x2e, 0x34, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x38, 0x2e, 0x34, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x39, 0x2e, 0x34, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x35, 0x2e, 0x33, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x36, 0x2e, 0x33, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x37, 0x2e, 0x33, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x38, 0x2e, 0x33, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x39, 0x2e, 0x33, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x35, 0x2e, 0x32, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x36, 0x2e, 0x32, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x37, 0x2e, 0x32, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x38, 0x2e, 0x32, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x39, 0x2e, 0x32, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x35, 0x2e, 0x31, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x36, 0x2e, 0x31, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x37, 0x2e, 0x31, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x38, 0x2e, 0x31, 0x09, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x45, 0x39, 0x2e, 0x31, 0x04, 0x73, 0x74, 0x65, 0x6d, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x30, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x30, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x30, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x30, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x31, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x32, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x45, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x33, 0x46, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x34, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x34, 0x34, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x36, 0x43, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x42, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x42, 0x30, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x42, 0x30, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x42, 0x30, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x42, 0x30, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x45, 0x32, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x45, 0x32, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x45, 0x32, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x45, 0x32, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x46, 0x46, 0x39, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x46, 0x46, 0x41, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x46, 0x46, 0x42, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x46, 0x46, 0x43, 0x07, 0x75, 0x6e, 0x69, 0x46, 0x46, 0x46, 0x44, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x30, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x31, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x32, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x33, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x34, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x35, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x36, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x37, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x38, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x39, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x41, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x42, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x43, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x44, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x45, 0x06, 0x75, 0x31, 0x30, 0x33, 0x30, 0x46, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x30, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x31, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x32, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x33, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x34, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x35, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x36, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x37, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x38, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x39, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x41, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x42, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x43, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x44, 0x06, 0x75, 0x31, 0x30, 0x33, 0x31, 0x45, 0x06, 0x75, 0x31, 0x30, 0x33, 0x32, 0x30, 0x06, 0x75, 0x31, 0x30, 0x33, 0x32, 0x31, 0x06, 0x75, 0x31, 0x30, 0x33, 0x32, 0x32, 0x06, 0x75, 0x31, 0x30, 0x33, 0x32, 0x33, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x30, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x31, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x32, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x33, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x34, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x35, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x36, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x37, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x38, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x39, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x41, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x42, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x43, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x44, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x45, 0x06, 0x75, 0x31, 0x44, 0x33, 0x30, 0x46, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x30, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x31, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x32, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x33, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x34, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x35, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x36, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x37, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x38, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x39, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x41, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x42, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x43, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x44, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x45, 0x06, 0x75, 0x31, 0x44, 0x33, 0x31, 0x46, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x30, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x31, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x32, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x33, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x34, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x35, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x36, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x37, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x38, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x39, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x41, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x42, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x43, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x44, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x45, 0x06, 0x75, 0x31, 0x44, 0x33, 0x32, 0x46, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x30, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x31, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x32, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x33, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x34, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x35, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x36, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x37, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x38, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x39, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x41, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x42, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x43, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x44, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x45, 0x06, 0x75, 0x31, 0x44, 0x33, 0x33, 0x46, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x30, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x31, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x32, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x33, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x34, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x35, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x36, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x37, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x38, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x39, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x41, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x42, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x43, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x44, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x45, 0x06, 0x75, 0x31, 0x44, 0x33, 0x34, 0x46, 0x06, 0x75, 0x31, 0x44, 0x33, 0x35, 0x30, 0x06, 0x75, 0x31, 0x44, 0x33, 0x35, 0x31, 0x06, 0x75, 0x31, 0x44, 0x33, 0x35, 0x32, 0x06, 0x75, 0x31, 0x44, 0x33, 0x35, 0x33, 0x06, 0x75, 0x31, 0x44, 0x33, 0x35, 0x34, 0x06, 0x75, 0x31, 0x44, 0x33, 0x35, 0x35, 0x06, 0x75, 0x31, 0x44, 0x33, 0x35, 0x36, 0x06, 0x75, 0x31, 0x44, 0x35, 0x33, 0x38, 0x06, 0x75, 0x31, 0x44, 0x35, 0x33, 0x39, 0x06, 0x75, 0x31, 0x44, 0x35, 0x33, 0x42, 0x06, 0x75, 0x31, 0x44, 0x35, 0x33, 0x43, 0x06, 0x75, 0x31, 0x44, 0x35, 0x33, 0x44, 0x06, 0x75, 0x31, 0x44, 0x35, 0x33, 0x45, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x30, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x31, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x32, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x33, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x34, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x36, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x41, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x42, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x43, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x44, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x45, 0x06, 0x75, 0x31, 0x44, 0x35, 0x34, 0x46, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x30, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x32, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x33, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x34, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x35, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x36, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x37, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x38, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x39, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x41, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x42, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x43, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x44, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x45, 0x06, 0x75, 0x31, 0x44, 0x35, 0x35, 0x46, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x30, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x31, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x32, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x33, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x34, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x35, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x36, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x37, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x38, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x39, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x41, 0x06, 0x75, 0x31, 0x44, 0x35, 0x36, 0x42, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x30, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x31, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x32, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x33, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x34, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x35, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x36, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x37, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x38, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x39, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x41, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x42, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x43, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x44, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x45, 0x06, 0x75, 0x31, 0x44, 0x35, 0x41, 0x46, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x30, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x31, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x32, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x33, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x34, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x35, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x36, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x37, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x38, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x39, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x41, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x42, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x43, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x44, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x45, 0x06, 0x75, 0x31, 0x44, 0x35, 0x42, 0x46, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x30, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x31, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x32, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x33, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x34, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x35, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x36, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x37, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x38, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x39, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x41, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x42, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x43, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x44, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x45, 0x06, 0x75, 0x31, 0x44, 0x35, 0x43, 0x46, 0x06, 0x75, 0x31, 0x44, 0x35, 0x44, 0x30, 0x06, 0x75, 0x31, 0x44, 0x35, 0x44, 0x31, 0x06, 0x75, 0x31, 0x44, 0x35, 0x44, 0x32, 0x06, 0x75, 0x31, 0x44, 0x35, 0x44, 0x33, 0x06, 0x75, 0x31, 0x44, 0x37, 0x44, 0x38, 0x06, 0x75, 0x31, 0x44, 0x37, 0x44, 0x39, 0x06, 0x75, 0x31, 0x44, 0x37, 0x44, 0x41, 0x06, 0x75, 0x31, 0x44, 0x37, 0x44, 0x42, 0x06, 0x75, 0x31, 0x44, 0x37, 0x44, 0x43, 0x06, 0x75, 0x31, 0x44, 0x37, 0x44, 0x44, 0x06, 0x75, 0x31, 0x44, 0x37, 0x44, 0x45, 0x06, 0x75, 0x31, 0x44, 0x37, 0x44, 0x46, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x30, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x31, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x32, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x33, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x34, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x35, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x36, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x37, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x38, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x39, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x41, 0x06, 0x75, 0x31, 0x44, 0x37, 0x45, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x30, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x33, 0x46, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x30, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x34, 0x46, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x30, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x35, 0x46, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x30, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x36, 0x46, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x30, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x37, 0x46, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x30, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x38, 0x46, 0x06, 0x75, 0x31, 0x46, 0x30, 0x39, 0x30, 0x06, 0x75, 0x31, 0x46, 0x30, 0x39, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x39, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x39, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x30, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x41, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x42, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x43, 0x46, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x31, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x32, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x33, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x34, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x35, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x36, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x37, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x38, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x39, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x41, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x42, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x43, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x44, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x45, 0x06, 0x75, 0x31, 0x46, 0x30, 0x44, 0x46, 0x06, 0x75, 0x31, 0x46, 0x34, 0x32, 0x44, 0x06, 0x75, 0x31, 0x46, 0x34, 0x32, 0x45, 0x06, 0x75, 0x31, 0x46, 0x34, 0x33, 0x31, 0x06, 0x75, 0x31, 0x46, 0x34, 0x33, 0x35, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x30, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x31, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x32, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x33, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x34, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x35, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x36, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x37, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x38, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x39, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x41, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x42, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x43, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x44, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x45, 0x06, 0x75, 0x31, 0x46, 0x36, 0x30, 0x46, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x30, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x31, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x32, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x33, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x34, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x35, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x36, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x37, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x38, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x39, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x41, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x42, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x43, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x44, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x45, 0x06, 0x75, 0x31, 0x46, 0x36, 0x31, 0x46, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x30, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x31, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x32, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x33, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x35, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x36, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x37, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x38, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x39, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x41, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x42, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x44, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x45, 0x06, 0x75, 0x31, 0x46, 0x36, 0x32, 0x46, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x30, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x31, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x32, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x33, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x34, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x35, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x36, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x37, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x38, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x39, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x41, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x42, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x43, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x44, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x45, 0x06, 0x75, 0x31, 0x46, 0x36, 0x33, 0x46, 0x06, 0x75, 0x31, 0x46, 0x36, 0x34, 0x30, 0x09, 0x64, 0x6c, 0x4c, 0x74, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x08, 0x44, 0x69, 0x65, 0x72, 0x65, 0x73, 0x69, 0x73, 0x05, 0x41, 0x63, 0x75, 0x74, 0x65, 0x05, 0x54, 0x69, 0x6c, 0x64, 0x65, 0x05, 0x47, 0x72, 0x61, 0x76, 0x65, 0x0a, 0x43, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x66, 0x6c, 0x65, 0x78, 0x05, 0x43, 0x61, 0x72, 0x6f, 0x6e, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x31, 0x31, 0x2e, 0x63, 0x61, 0x73, 0x65, 0x05, 0x42, 0x72, 0x65, 0x76, 0x65, 0x09, 0x44, 0x6f, 0x74, 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x0c, 0x48, 0x75, 0x6e, 0x67, 0x61, 0x72, 0x75, 0x6d, 0x6c, 0x61, 0x75, 0x74, 0x0b, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x76, 0x65, 0x0a, 0x61, 0x72, 0x61, 0x62, 0x69, 0x63, 0x5f, 0x64, 0x6f, 0x74, 0x0c, 0x61, 0x72, 0x61, 0x62, 0x69, 0x63, 0x5f, 0x32, 0x64, 0x6f, 0x74, 0x73, 0x0c, 0x61, 0x72, 0x61, 0x62, 0x69, 0x63, 0x5f, 0x33, 0x64, 0x6f, 0x74, 0x73, 0x0e, 0x61, 0x72, 0x61, 0x62, 0x69, 0x63, 0x5f, 0x33, 0x64, 0x6f, 0x74, 0x73, 0x5f, 0x61, 0x0e, 0x61, 0x72, 0x61, 0x62, 0x69, 0x63, 0x5f, 0x32, 0x64, 0x6f, 0x74, 0x73, 0x5f, 0x61, 0x0c, 0x61, 0x72, 0x61, 0x62, 0x69, 0x63, 0x5f, 0x34, 0x64, 0x6f, 0x74, 0x73, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x36, 0x45, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x36, 0x45, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x36, 0x45, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x31, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x31, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x31, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x36, 0x46, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x36, 0x46, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x36, 0x46, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x41, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x41, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0b, 0x61, 0x72, 0x61, 0x62, 0x69, 0x63, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x37, 0x43, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x37, 0x43, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x37, 0x43, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x37, 0x44, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x37, 0x44, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x37, 0x44, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x31, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x31, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x31, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x32, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x32, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x32, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x35, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x35, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x35, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x46, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x46, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x46, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0e, 0x61, 0x72, 0x61, 0x62, 0x69, 0x63, 0x5f, 0x67, 0x61, 0x66, 0x5f, 0x62, 0x61, 0x72, 0x07, 0x45, 0x6e, 0x67, 0x2e, 0x61, 0x6c, 0x74, 0x0f, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x36, 0x38, 0x2e, 0x64, 0x6f, 0x74, 0x6c, 0x65, 0x73, 0x73, 0x0f, 0x75, 0x6e, 0x69, 0x30, 0x32, 0x39, 0x44, 0x2e, 0x64, 0x6f, 0x74, 0x6c, 0x65, 0x73, 0x73, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x38, 0x30, 0x33, 0x30, 0x34, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x34, 0x30, 0x33, 0x30, 0x38, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x37, 0x30, 0x33, 0x30, 0x34, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x38, 0x30, 0x33, 0x30, 0x31, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x38, 0x30, 0x33, 0x30, 0x30, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x34, 0x30, 0x33, 0x30, 0x31, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x34, 0x30, 0x33, 0x30, 0x30, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x34, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x38, 0x30, 0x33, 0x30, 0x43, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x38, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x43, 0x30, 0x33, 0x30, 0x37, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x31, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x32, 0x30, 0x33, 0x30, 0x31, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x32, 0x30, 0x33, 0x30, 0x30, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x32, 0x30, 0x33, 0x30, 0x33, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x36, 0x30, 0x33, 0x30, 0x33, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x36, 0x30, 0x33, 0x30, 0x31, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x36, 0x30, 0x33, 0x30, 0x30, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x36, 0x30, 0x33, 0x30, 0x39, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x32, 0x30, 0x33, 0x30, 0x39, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x33, 0x30, 0x31, 0x30, 0x33, 0x30, 0x37, 0x0a, 0x62, 0x72, 0x61, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x6f, 0x74, 0x05, 0x4a, 0x2e, 0x61, 0x6c, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x35, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x16, 0x75, 0x6e, 0x69, 0x46, 0x45, 0x41, 0x45, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x2e, 0x6c, 0x6f, 0x6e, 0x67, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x35, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x35, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x35, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x43, 0x45, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x43, 0x45, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x43, 0x45, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x32, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x05, 0x6c, 0x2e, 0x61, 0x6c, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x44, 0x35, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x11, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x38, 0x2e, 0x6d, 0x6f, 0x6e, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x11, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x39, 0x2e, 0x6d, 0x6f, 0x6e, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x0f, 0x69, 0x6f, 0x67, 0x6f, 0x6e, 0x65, 0x6b, 0x2e, 0x64, 0x6f, 0x74, 0x6c, 0x65, 0x73, 0x73, 0x0f, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x38, 0x2e, 0x64, 0x6f, 0x74, 0x6c, 0x65, 0x73, 0x73, 0x0f, 0x75, 0x6e, 0x69, 0x32, 0x31, 0x34, 0x39, 0x2e, 0x64, 0x6f, 0x74, 0x6c, 0x65, 0x73, 0x73, 0x0f, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x32, 0x44, 0x2e, 0x64, 0x6f, 0x74, 0x6c, 0x65, 0x73, 0x73, 0x0f, 0x75, 0x6e, 0x69, 0x31, 0x45, 0x43, 0x42, 0x2e, 0x64, 0x6f, 0x74, 0x6c, 0x65, 0x73, 0x73, 0x03, 0x64, 0x63, 0x6f, 0x05, 0x49, 0x2e, 0x61, 0x6c, 0x74, 0x0a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x35, 0x31, 0x30, 0x36, 0x34, 0x42, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x35, 0x31, 0x30, 0x36, 0x34, 0x43, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x34, 0x42, 0x30, 0x36, 0x35, 0x31, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x35, 0x31, 0x30, 0x36, 0x34, 0x45, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x35, 0x31, 0x30, 0x36, 0x34, 0x46, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x34, 0x45, 0x30, 0x36, 0x35, 0x31, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x35, 0x34, 0x30, 0x36, 0x34, 0x45, 0x0b, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x35, 0x34, 0x30, 0x36, 0x34, 0x46, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x41, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x41, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x41, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x42, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x42, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x42, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x43, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x43, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x43, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x44, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x44, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x44, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x45, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x45, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x45, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x46, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x46, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x43, 0x46, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x30, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x30, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x30, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x31, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x31, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x31, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x32, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x32, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x32, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x33, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x33, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x33, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x34, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x34, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x34, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x35, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x35, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x35, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x36, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x36, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x36, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x37, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x37, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x37, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x38, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x38, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x38, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x39, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x39, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x39, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x41, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x41, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x41, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x42, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x42, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x42, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x43, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x43, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x43, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x44, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x44, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x44, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x45, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x45, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x45, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x46, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x46, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x44, 0x46, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x30, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x30, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x30, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x31, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x31, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x31, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x32, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x32, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x32, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x33, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x33, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x33, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x34, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x34, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x34, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x35, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x35, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x35, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x36, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x36, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x36, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x37, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x37, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x37, 0x45, 0x37, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x09, 0x52, 0x69, 0x6e, 0x67, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x0b, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x30, 0x2e, 0x61, 0x6c, 0x74, 0x0b, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x31, 0x2e, 0x61, 0x6c, 0x74, 0x0b, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x32, 0x2e, 0x61, 0x6c, 0x74, 0x0b, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x33, 0x2e, 0x61, 0x6c, 0x74, 0x0b, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x34, 0x2e, 0x61, 0x6c, 0x74, 0x0b, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x35, 0x2e, 0x61, 0x6c, 0x74, 0x0b, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x36, 0x2e, 0x61, 0x6c, 0x74, 0x0b, 0x75, 0x6e, 0x69, 0x32, 0x36, 0x33, 0x37, 0x2e, 0x61, 0x6c, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x37, 0x45, 0x2e, 0x64, 0x69, 0x61, 0x63, 0x11, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x41, 0x2e, 0x62, 0x72, 0x65, 0x76, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x11, 0x75, 0x6e, 0x69, 0x30, 0x34, 0x38, 0x42, 0x2e, 0x62, 0x72, 0x65, 0x76, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x05, 0x79, 0x2e, 0x61, 0x6c, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x39, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x41, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x42, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x38, 0x46, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x30, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x33, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x34, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x36, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x37, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x39, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x41, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x41, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x41, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x42, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x42, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x42, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x43, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x43, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x43, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x44, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x44, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x44, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x45, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x45, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x45, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x46, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x46, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x39, 0x46, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x30, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x30, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x30, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x32, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x32, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x32, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x33, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x33, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x33, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x35, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x35, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x35, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x37, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x37, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x37, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x38, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x38, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x38, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x41, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x41, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x41, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x42, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x42, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x42, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x43, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x43, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x43, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x45, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x45, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x41, 0x45, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x30, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x30, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x30, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x32, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x32, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x32, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x34, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x34, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x34, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x36, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x36, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x36, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x37, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x37, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x37, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x38, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x38, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x38, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x39, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x39, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x39, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x43, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x43, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x43, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x44, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x44, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x0c, 0x75, 0x6e, 0x69, 0x30, 0x36, 0x42, 0x44, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x00, 0x00, 0x00, 0xb8, 0x02, 0x80, 0x40, 0xff, 0xfb, 0xfe, 0x03, 0xfa, 0x14, 0x03, 0xf9, 0x25, 0x03, 0xf8, 0x32, 0x03, 0xf7, 0x96, 0x03, 0xf6, 0x0e, 0x03, 0xf5, 0xfe, 0x03, 0xf4, 0xfe, 0x03, 0xf3, 0x25, 0x03, 0xf2, 0x0e, 0x03, 0xf1, 0x96, 0x03, 0xf0, 0x25, 0x03, 0xef, 0x8a, 0x41, 0x05, 0xef, 0xfe, 0x03, 0xee, 0x96, 0x03, 0xed, 0x96, 0x03, 0xec, 0xfa, 0x03, 0xeb, 0xfa, 0x03, 0xea, 0xfe, 0x03, 0xe9, 0x3a, 0x03, 0xe8, 0x42, 0x03, 0xe7, 0xfe, 0x03, 0xe6, 0x32, 0x03, 0xe5, 0xe4, 0x53, 0x05, 0xe5, 0x96, 0x03, 0xe4, 0x8a, 0x41, 0x05, 0xe4, 0x53, 0x03, 0xe3, 0xe2, 0x2f, 0x05, 0xe3, 0xfa, 0x03, 0xe2, 0x2f, 0x03, 0xe1, 0xfe, 0x03, 0xe0, 0xfe, 0x03, 0xdf, 0x32, 0x03, 0xde, 0x14, 0x03, 0xdd, 0x96, 0x03, 0xdc, 0xfe, 0x03, 0xdb, 0x12, 0x03, 0xda, 0x7d, 0x03, 0xd9, 0xbb, 0x03, 0xd8, 0xfe, 0x03, 0xd6, 0x8a, 0x41, 0x05, 0xd6, 0x7d, 0x03, 0xd5, 0xd4, 0x47, 0x05, 0xd5, 0x7d, 0x03, 0xd4, 0x47, 0x03, 0xd3, 0xd2, 0x1b, 0x05, 0xd3, 0xfe, 0x03, 0xd2, 0x1b, 0x03, 0xd1, 0xfe, 0x03, 0xd0, 0xfe, 0x03, 0xcf, 0xfe, 0x03, 0xce, 0xfe, 0x03, 0xcd, 0x96, 0x03, 0xcc, 0xcb, 0x1e, 0x05, 0xcc, 0xfe, 0x03, 0xcb, 0x1e, 0x03, 0xca, 0x32, 0x03, 0xc9, 0xfe, 0x03, 0xc6, 0x85, 0x11, 0x05, 0xc6, 0x1c, 0x03, 0xc5, 0x16, 0x03, 0xc4, 0xfe, 0x03, 0xc3, 0xfe, 0x03, 0xc2, 0xfe, 0x03, 0xc1, 0xfe, 0x03, 0xc0, 0xfe, 0x03, 0xbf, 0xfe, 0x03, 0xbe, 0xfe, 0x03, 0xbd, 0xfe, 0x03, 0xbc, 0xfe, 0x03, 0xbb, 0xfe, 0x03, 0xba, 0x11, 0x03, 0xb9, 0x86, 0x25, 0x05, 0xb9, 0xfe, 0x03, 0xb8, 0xb7, 0xbb, 0x05, 0xb8, 0xfe, 0x03, 0xb7, 0xb6, 0x5d, 0x05, 0xb7, 0xbb, 0x03, 0xb7, 0x80, 0x04, 0xb6, 0xb5, 0x25, 0x05, 0xb6, 0x5d, 0x40, 0xff, 0x03, 0xb6, 0x40, 0x04, 0xb5, 0x25, 0x03, 0xb4, 0xfe, 0x03, 0xb3, 0x96, 0x03, 0xb2, 0xfe, 0x03, 0xb1, 0xfe, 0x03, 0xb0, 0xfe, 0x03, 0xaf, 0xfe, 0x03, 0xae, 0x64, 0x03, 0xad, 0x0e, 0x03, 0xac, 0xab, 0x25, 0x05, 0xac, 0x64, 0x03, 0xab, 0xaa, 0x12, 0x05, 0xab, 0x25, 0x03, 0xaa, 0x12, 0x03, 0xa9, 0x8a, 0x41, 0x05, 0xa9, 0xfa, 0x03, 0xa8, 0xfe, 0x03, 0xa7, 0xfe, 0x03, 0xa6, 0xfe, 0x03, 0xa5, 0x12, 0x03, 0xa4, 0xfe, 0x03, 0xa3, 0xa2, 0x0e, 0x05, 0xa3, 0x32, 0x03, 0xa2, 0x0e, 0x03, 0xa1, 0x64, 0x03, 0xa0, 0x8a, 0x41, 0x05, 0xa0, 0x96, 0x03, 0x9f, 0xfe, 0x03, 0x9e, 0x9d, 0x0c, 0x05, 0x9e, 0xfe, 0x03, 0x9d, 0x0c, 0x03, 0x9c, 0x9b, 0x19, 0x05, 0x9c, 0x64, 0x03, 0x9b, 0x9a, 0x10, 0x05, 0x9b, 0x19, 0x03, 0x9a, 0x10, 0x03, 0x99, 0x0a, 0x03, 0x98, 0xfe, 0x03, 0x97, 0x96, 0x0d, 0x05, 0x97, 0xfe, 0x03, 0x96, 0x0d, 0x03, 0x95, 0x8a, 0x41, 0x05, 0x95, 0x96, 0x03, 0x94, 0x93, 0x0e, 0x05, 0x94, 0x28, 0x03, 0x93, 0x0e, 0x03, 0x92, 0xfa, 0x03, 0x91, 0x90, 0xbb, 0x05, 0x91, 0xfe, 0x03, 0x90, 0x8f, 0x5d, 0x05, 0x90, 0xbb, 0x03, 0x90, 0x80, 0x04, 0x8f, 0x8e, 0x25, 0x05, 0x8f, 0x5d, 0x03, 0x8f, 0x40, 0x04, 0x8e, 0x25, 0x03, 0x8d, 0xfe, 0x03, 0x8c, 0x8b, 0x2e, 0x05, 0x8c, 0xfe, 0x03, 0x8b, 0x2e, 0x03, 0x8a, 0x86, 0x25, 0x05, 0x8a, 0x41, 0x03, 0x89, 0x88, 0x0b, 0x05, 0x89, 0x14, 0x03, 0x88, 0x0b, 0x03, 0x87, 0x86, 0x25, 0x05, 0x87, 0x64, 0x03, 0x86, 0x85, 0x11, 0x05, 0x86, 0x25, 0x03, 0x85, 0x11, 0x03, 0x84, 0xfe, 0x03, 0x83, 0x82, 0x11, 0x05, 0x83, 0xfe, 0x03, 0x82, 0x11, 0x03, 0x81, 0xfe, 0x03, 0x80, 0xfe, 0x03, 0x7f, 0xfe, 0x03, 0x40, 0xff, 0x7e, 0x7d, 0x7d, 0x05, 0x7e, 0xfe, 0x03, 0x7d, 0x7d, 0x03, 0x7c, 0x64, 0x03, 0x7b, 0x54, 0x15, 0x05, 0x7b, 0x25, 0x03, 0x7a, 0xfe, 0x03, 0x79, 0xfe, 0x03, 0x78, 0x0e, 0x03, 0x77, 0x0c, 0x03, 0x76, 0x0a, 0x03, 0x75, 0xfe, 0x03, 0x74, 0xfa, 0x03, 0x73, 0xfa, 0x03, 0x72, 0xfa, 0x03, 0x71, 0xfa, 0x03, 0x70, 0xfe, 0x03, 0x6f, 0xfe, 0x03, 0x6e, 0xfe, 0x03, 0x6c, 0x21, 0x03, 0x6b, 0xfe, 0x03, 0x6a, 0x11, 0x42, 0x05, 0x6a, 0x53, 0x03, 0x69, 0xfe, 0x03, 0x68, 0x7d, 0x03, 0x67, 0x11, 0x42, 0x05, 0x66, 0xfe, 0x03, 0x65, 0xfe, 0x03, 0x64, 0xfe, 0x03, 0x63, 0xfe, 0x03, 0x62, 0xfe, 0x03, 0x61, 0x3a, 0x03, 0x60, 0xfa, 0x03, 0x5e, 0x0c, 0x03, 0x5d, 0xfe, 0x03, 0x5b, 0xfe, 0x03, 0x5a, 0xfe, 0x03, 0x59, 0x58, 0x0a, 0x05, 0x59, 0xfa, 0x03, 0x58, 0x0a, 0x03, 0x57, 0x16, 0x19, 0x05, 0x57, 0x32, 0x03, 0x56, 0xfe, 0x03, 0x55, 0x54, 0x15, 0x05, 0x55, 0x42, 0x03, 0x54, 0x15, 0x03, 0x53, 0x01, 0x10, 0x05, 0x53, 0x18, 0x03, 0x52, 0x14, 0x03, 0x51, 0x4a, 0x13, 0x05, 0x51, 0xfe, 0x03, 0x50, 0x0b, 0x03, 0x4f, 0xfe, 0x03, 0x4e, 0x4d, 0x10, 0x05, 0x4e, 0xfe, 0x03, 0x4d, 0x10, 0x03, 0x4c, 0xfe, 0x03, 0x4b, 0x4a, 0x13, 0x05, 0x4b, 0xfe, 0x03, 0x4a, 0x49, 0x10, 0x05, 0x4a, 0x13, 0x03, 0x49, 0x1d, 0x0d, 0x05, 0x49, 0x10, 0x03, 0x48, 0x0d, 0x03, 0x47, 0xfe, 0x03, 0x46, 0x96, 0x03, 0x45, 0x96, 0x03, 0x44, 0xfe, 0x03, 0x43, 0x02, 0x2d, 0x05, 0x43, 0xfa, 0x03, 0x42, 0xbb, 0x03, 0x41, 0x4b, 0x03, 0x40, 0xfe, 0x03, 0x3f, 0xfe, 0x03, 0x3e, 0x3d, 0x12, 0x05, 0x3e, 0x14, 0x03, 0x3d, 0x3c, 0x0f, 0x05, 0x3d, 0x12, 0x03, 0x3c, 0x3b, 0x0d, 0x05, 0x3c, 0x40, 0xff, 0x0f, 0x03, 0x3b, 0x0d, 0x03, 0x3a, 0xfe, 0x03, 0x39, 0xfe, 0x03, 0x38, 0x37, 0x14, 0x05, 0x38, 0xfa, 0x03, 0x37, 0x36, 0x10, 0x05, 0x37, 0x14, 0x03, 0x36, 0x35, 0x0b, 0x05, 0x36, 0x10, 0x03, 0x35, 0x0b, 0x03, 0x34, 0x1e, 0x03, 0x33, 0x0d, 0x03, 0x32, 0x31, 0x0b, 0x05, 0x32, 0xfe, 0x03, 0x31, 0x0b, 0x03, 0x30, 0x2f, 0x0b, 0x05, 0x30, 0x0d, 0x03, 0x2f, 0x0b, 0x03, 0x2e, 0x2d, 0x09, 0x05, 0x2e, 0x10, 0x03, 0x2d, 0x09, 0x03, 0x2c, 0x32, 0x03, 0x2b, 0x2a, 0x25, 0x05, 0x2b, 0x64, 0x03, 0x2a, 0x29, 0x12, 0x05, 0x2a, 0x25, 0x03, 0x29, 0x12, 0x03, 0x28, 0x27, 0x25, 0x05, 0x28, 0x41, 0x03, 0x27, 0x25, 0x03, 0x26, 0x25, 0x0b, 0x05, 0x26, 0x0f, 0x03, 0x25, 0x0b, 0x03, 0x24, 0xfe, 0x03, 0x23, 0xfe, 0x03, 0x22, 0x0f, 0x03, 0x21, 0x01, 0x10, 0x05, 0x21, 0x12, 0x03, 0x20, 0x64, 0x03, 0x1f, 0xfa, 0x03, 0x1e, 0x1d, 0x0d, 0x05, 0x1e, 0x64, 0x03, 0x1d, 0x0d, 0x03, 0x1c, 0x11, 0x42, 0x05, 0x1c, 0xfe, 0x03, 0x1b, 0xfa, 0x03, 0x1a, 0x42, 0x03, 0x19, 0x11, 0x42, 0x05, 0x19, 0xfe, 0x03, 0x18, 0x64, 0x03, 0x17, 0x16, 0x19, 0x05, 0x17, 0xfe, 0x03, 0x16, 0x01, 0x10, 0x05, 0x16, 0x19, 0x03, 0x15, 0xfe, 0x03, 0x14, 0xfe, 0x03, 0x13, 0xfe, 0x03, 0x12, 0x11, 0x42, 0x05, 0x12, 0xfe, 0x03, 0x11, 0x02, 0x2d, 0x05, 0x11, 0x42, 0x03, 0x10, 0x7d, 0x03, 0x0f, 0x64, 0x03, 0x0e, 0xfe, 0x03, 0x0d, 0x0c, 0x16, 0x05, 0x0d, 0xfe, 0x03, 0x0c, 0x01, 0x10, 0x05, 0x0c, 0x16, 0x03, 0x0b, 0xfe, 0x03, 0x0a, 0x10, 0x03, 0x09, 0xfe, 0x03, 0x08, 0x02, 0x2d, 0x05, 0x08, 0xfe, 0x03, 0x07, 0x14, 0x03, 0x06, 0x64, 0x03, 0x04, 0x01, 0x10, 0x05, 0x04, 0xfe, 0x03, 0x40, 0x15, 0x03, 0x02, 0x2d, 0x05, 0x03, 0xfe, 0x03, 0x02, 0x01, 0x10, 0x05, 0x02, 0x2d, 0x03, 0x01, 0x10, 0x03, 0x00, 0xfe, 0x03, 0x01, 0xb8, 0x01, 0x64, 0x85, 0x8d, 0x01, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x00, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x1d }; unsigned int dejavu_sans_condensed_ttf_len = 552620; #endif mapserver-7.4.3/dxfcolor.h000066400000000000000000000120621357574274700155500ustar00rootroot00000000000000struct dxfcolor { int r,g,b; }; struct dxfcolor ctable[256] = { {0, 0, 0}, {255, 0, 0}, {255, 255, 0}, {0, 255, 0}, {0, 255, 255}, {0, 0, 255}, {255, 0, 255}, {255, 255, 255}, {128, 128, 128}, {192, 192, 192}, {255, 0, 0}, {255, 127, 127}, {204, 0, 0}, {204, 102, 102}, {153, 0, 0}, {153, 76, 76}, {127, 0, 0}, {127, 63, 63}, {76, 0, 0}, {76, 38, 38}, {255, 63, 0}, {255, 159, 127}, {204, 51, 0}, {204, 127, 102}, {153, 38, 0}, {153, 95, 76}, {127, 31, 0}, {127, 79, 63}, {76, 19, 0}, {76, 47, 38}, {255, 127, 0}, {255, 191, 127}, {204, 102, 0}, {204, 153, 102}, {153, 76, 0}, {153, 114, 76}, {127, 63, 0}, {127, 95, 63}, {76, 38, 0}, {76, 57, 38}, {255, 191, 0}, {255, 223, 127}, {204, 153, 0}, {204, 178, 102}, {153, 114, 0}, {153, 133, 76}, {127, 95, 0}, {127, 111, 63}, {76, 57, 0}, {76, 66, 38}, {255, 255, 0}, {255, 255, 127}, {204, 204, 0}, {204, 204, 102}, {153, 153, 0}, {153, 153, 76}, {127, 127, 0}, {127, 127, 63}, {76, 76, 0}, {76, 76, 38}, {191, 255, 0}, {223, 255, 127}, {153, 204, 0}, {178, 204, 102}, {114, 153, 0}, {133, 153, 76}, {95, 127, 0}, {111, 127, 63}, {57, 76, 0}, {66, 76, 38}, {127, 255, 0}, {191, 255, 127}, {102, 204, 0}, {153, 204, 102}, {76, 153, 0}, {114, 153, 76}, {63, 127, 0}, {95, 127, 63}, {38, 76, 0}, {57, 76, 38}, {63, 255, 0}, {159, 255, 127}, {51, 204, 0}, {127, 204, 102}, {38, 153, 0}, {95, 153, 76}, {31, 127, 0}, {79, 127, 63}, {19, 76, 0}, {47, 76, 38}, {0, 255, 0}, {127, 255, 127}, {0, 204, 0}, {102, 204, 102}, {0, 153, 0}, {76, 153, 76}, {0, 127, 0}, {63, 127, 63}, {0, 76, 0}, {38, 76, 38}, {0, 255, 63}, {127, 255, 159}, {0, 204, 51}, {102, 204, 127}, {0, 153, 38}, {76, 153, 95}, {0, 127, 31}, {63, 127, 79}, {0, 76, 19}, {38, 76, 47}, {0, 255, 127}, {127, 255, 191}, {0, 204, 102}, {102, 204, 153}, {0, 153, 76}, {76, 153, 114}, {0, 127, 63}, {63, 127, 95}, {0, 76, 38}, {38, 76, 57}, {0, 255, 191}, {127, 255, 223}, {0, 204, 153}, {102, 204, 178}, {0, 153, 114}, {76, 153, 133}, {0, 127, 95}, {63, 127, 111}, {0, 76, 57}, {38, 76, 66}, {0, 255, 255}, {127, 255, 255}, {0, 204, 204}, {102, 204, 204}, {0, 153, 153}, {76, 153, 153}, {0, 127, 127}, {63, 127, 127}, {0, 76, 76}, {38, 76, 76}, {0, 191, 255}, {127, 223, 255}, {0, 153, 204}, {102, 178, 204}, {0, 114, 153}, {76, 133, 153}, {0, 95, 127}, {63, 111, 127}, {0, 57, 76}, {38, 66, 76}, {0, 127, 255}, {127, 191, 255}, {0, 102, 204}, {102, 153, 204}, {0, 76, 153}, {76, 114, 153}, {0, 63, 127}, {63, 95, 127}, {0, 38, 76}, {38, 57, 76}, {0, 63, 255}, {127, 159, 255}, {0, 51, 204}, {102, 127, 204}, {0, 38, 153}, {76, 95, 153}, {0, 31, 127}, {63, 79, 127}, {0, 19, 76}, {38, 47, 76}, {0, 0, 255}, {127, 127, 255}, {0, 0, 204}, {102, 102, 204}, {0, 0, 153}, {76, 76, 153}, {0, 0, 127}, {63, 63, 127}, {0, 0, 76}, {38, 38, 76}, {63, 0, 255}, {159, 127, 255}, {51, 0, 204}, {127, 102, 204}, {38, 0, 153}, {95, 76, 153}, {31, 0, 127}, {79, 63, 127}, {19, 0, 76}, {47, 38, 76}, {127, 0, 255}, {191, 127, 255}, {102, 0, 204}, {153, 102, 204}, {76, 0, 153}, {114, 76, 153}, {63, 0, 127}, {95, 63, 127}, {38, 0, 76}, {57, 38, 76}, {191, 0, 255}, {223, 127, 255}, {153, 0, 204}, {178, 102, 204}, {114, 0, 153}, {133, 76, 153}, {95, 0, 127}, {111, 63, 127}, {57, 0, 76}, {66, 38, 76}, {255, 0, 255}, {255, 127, 255}, {204, 0, 204}, {204, 102, 204}, {153, 0, 153}, {153, 76, 153}, {127, 0, 127}, {127, 63, 127}, {76, 0, 76}, {76, 38, 76}, {255, 0, 191}, {255, 127, 223}, {204, 0, 153}, {204, 102, 178}, {153, 0, 114}, {153, 76, 133}, {127, 0, 95}, {127, 63, 111}, {76, 0, 57}, {76, 38, 66}, {255, 0, 127}, {255, 127, 191}, {204, 0, 102}, {204, 102, 153}, {153, 0, 76}, {153, 76, 114}, {127, 0, 63}, {127, 63, 95}, {76, 0, 38}, {76, 38, 57}, {255, 0, 63}, {255, 127, 159}, {204, 0, 51}, {204, 102, 127}, {153, 0, 38}, {153, 76, 95}, {127, 0, 31}, {127, 63, 79}, {76, 0, 19}, {76, 38, 47}, {51, 51, 51}, {91, 91, 91}, {132, 132, 132}, {173, 173, 173}, {214, 214, 214}, {255, 255, 255}, }; mapserver-7.4.3/fontcache.c000066400000000000000000000263331357574274700156630ustar00rootroot00000000000000/****************************************************************************** * * Project: MapServer * Purpose: Freetype Font helper functions * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2013 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "mapthread.h" #include "fontcache.h" #include "dejavu-sans-condensed.h" typedef struct { FT_Library library; face_element *face_cache; glyph_element *bitmap_glyph_cache; } ft_cache; #ifdef USE_THREAD typedef struct ft_thread_cache ft_thread_cache; struct ft_thread_cache{ void* thread_id; ft_thread_cache *next; ft_cache cache; }; ft_thread_cache *ft_caches; int use_global_ft_cache; #else ft_cache global_ft_cache; #endif void msInitFontCache(ft_cache *c) { memset(c,0,sizeof(ft_cache)); FT_Init_FreeType(&c->library); } void msFreeFontCache(ft_cache *c) { /* ... TODO ... */ face_element *cur_face,*tmp_face; glyph_element *cur_bitmap, *tmp_bitmap; UT_HASH_ITER(hh, c->face_cache, cur_face, tmp_face) { index_element *cur_index,*tmp_index; outline_element *cur_outline,*tmp_outline; glyph_element *cur_glyph,*tmp_glyph; UT_HASH_ITER(hh, cur_face->index_cache, cur_index, tmp_index) { UT_HASH_DEL(cur_face->index_cache,cur_index); free(cur_index); } UT_HASH_ITER(hh, cur_face->outline_cache, cur_outline, tmp_outline) { UT_HASH_DEL(cur_face->outline_cache,cur_outline); FT_Outline_Done(c->library,&cur_outline->outline); free(cur_outline); } UT_HASH_ITER(hh, cur_face->glyph_cache, cur_glyph, tmp_glyph) { UT_HASH_DEL(cur_face->glyph_cache,cur_glyph); free(cur_glyph); } #ifdef USE_HARFBUZZ if(cur_face->hbfont) { hb_font_destroy(cur_face->hbfont->hbfont); hb_font_destroy(cur_face->hbfont->hbparentfont); hb_font_funcs_destroy(cur_face->hbfont->funcs); free(cur_face->hbfont); } #endif FT_Done_Face(cur_face->face); free(cur_face->font); UT_HASH_DEL(c->face_cache,cur_face); free(cur_face); } FT_Done_FreeType(c->library); UT_HASH_ITER(hh,c->bitmap_glyph_cache, cur_bitmap, tmp_bitmap) { UT_HASH_DEL(c->bitmap_glyph_cache, cur_bitmap); free(cur_bitmap); } } ft_cache* msGetFontCache() { #ifndef USE_THREAD return &global_ft_cache; #else void* nThreadId = 0; ft_thread_cache *prev = NULL, *cur = ft_caches; if (!use_global_ft_cache) nThreadId = msGetThreadId(); if( cur != NULL && cur->thread_id == nThreadId ) return &cur->cache; /* -------------------------------------------------------------------- */ /* Search for cache for this thread */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_TTF ); cur = ft_caches; while( cur != NULL && cur->thread_id != nThreadId ) { prev = cur; cur = cur->next; } /* -------------------------------------------------------------------- */ /* If we found it, make sure it is pushed to the front of the */ /* link for faster finding next time, and return it. */ /* -------------------------------------------------------------------- */ if( cur != NULL ) { if( prev != NULL ) { prev->next = cur->next; cur->next = ft_caches; ft_caches = cur; } msReleaseLock( TLOCK_TTF ); return &cur->cache; } /* -------------------------------------------------------------------- */ /* Create a new context group for this thread. */ /* -------------------------------------------------------------------- */ cur = msSmallMalloc(sizeof(ft_thread_cache)); cur->next = NULL; cur->thread_id = nThreadId; msInitFontCache(&cur->cache); cur->next = ft_caches; ft_caches = cur; msReleaseLock( TLOCK_TTF ); return &cur->cache; #endif } void msFontCacheSetup() { #ifndef USE_THREAD ft_cache *c = msGetFontCache(); msInitFontCache(c); #else char* use_global_cache = getenv("MS_USE_GLOBAL_FT_CACHE"); if (use_global_cache) use_global_ft_cache = atoi(use_global_cache); else use_global_ft_cache = 0; ft_caches = NULL; #endif } void msFontCacheCleanup() { #ifndef USE_THREAD ft_cache *c = msGetFontCache(); msFreeFontCache(c); #else ft_thread_cache *cur,*next; msAcquireLock( TLOCK_TTF ); cur = ft_caches; while( cur != NULL ) { msFreeFontCache(&cur->cache); next = cur->next; free(cur); cur = next; } ft_caches = NULL; msReleaseLock( TLOCK_TTF ); #endif } unsigned int msGetGlyphIndex(face_element *face, unsigned int unicode) { index_element *ic; if(face->face->charmap && face->face->charmap->encoding == FT_ENCODING_MS_SYMBOL) { unicode |= 0xf000; /* why? */ } UT_HASH_FIND_INT(face->index_cache,&unicode,ic); if(!ic) { ic = msSmallMalloc(sizeof(index_element)); ic->codepoint = FT_Get_Char_Index(face->face,unicode); ic->unicode = unicode; UT_HASH_ADD_INT(face->index_cache,unicode,ic); } return ic->codepoint; } #define MS_DEFAULT_FONT_KEY "_ms_default_" face_element* msGetFontFace(char *key, fontSetObj *fontset) { face_element *fc; int error; ft_cache *cache = msGetFontCache(); if(!key) { key = MS_DEFAULT_FONT_KEY; } #ifdef USE_THREAD if (use_global_ft_cache) msAcquireLock(TLOCK_TTF); #endif UT_HASH_FIND_STR(cache->face_cache,key,fc); if(!fc) { const char *fontfile = NULL; fc = msSmallCalloc(1,sizeof(face_element)); if(fontset && strcmp(key,MS_DEFAULT_FONT_KEY)) { fontfile = msLookupHashTable(&(fontset->fonts),key); if(!fontfile) { msSetError(MS_MISCERR, "Could not find font with key \"%s\" in fontset", "msGetFontFace()", key); free(fc); #ifdef USE_THREAD if (use_global_ft_cache) msReleaseLock(TLOCK_TTF); #endif return NULL; } error = FT_New_Face(cache->library,fontfile,0, &(fc->face)); } else { error = FT_New_Memory_Face(cache->library,dejavu_sans_condensed_ttf, dejavu_sans_condensed_ttf_len , 0, &(fc->face)); } if(error) { msSetError(MS_MISCERR, "Freetype was unable to load font file \"%s\" for key \"%s\"", "msGetFontFace()", fontfile, key); free(fc); #ifdef USE_THREAD if (use_global_ft_cache) msReleaseLock(TLOCK_TTF); #endif return NULL; } if(!fc->face->charmap) { /* The font file has no unicode charmap, select an alternate one */ if( FT_Select_Charmap(fc->face, FT_ENCODING_MS_SYMBOL) ) FT_Select_Charmap(fc->face, FT_ENCODING_APPLE_ROMAN); /* the previous calls may have failed, we ignore as there's nothing much left to do */ } fc->font = msStrdup(key); UT_HASH_ADD_KEYPTR(hh,cache->face_cache,fc->font, strlen(key), fc); } #ifdef USE_THREAD if (use_global_ft_cache) msReleaseLock(TLOCK_TTF); #endif return fc; } glyph_element* msGetGlyphByIndex(face_element *face, unsigned int size, unsigned int codepoint) { glyph_element *gc; glyph_element_key key; memset(&key,0,sizeof(glyph_element_key)); key.codepoint = codepoint; key.size = size; UT_HASH_FIND(hh,face->glyph_cache,&key,sizeof(glyph_element_key),gc); if(!gc) { FT_Error error; gc = msSmallMalloc(sizeof(glyph_element)); if(MS_NINT(size * 96.0/72.0) != face->face->size->metrics.x_ppem) { FT_Set_Pixel_Sizes(face->face,0,MS_NINT(size * 96/72.0)); } error = FT_Load_Glyph(face->face,key.codepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); if(error) { msSetError(MS_MISCERR, "unable to load glyph %ud for font \"%s\"", "msGetGlyphByIndex()",key.codepoint, face->font); free(gc); return NULL; } gc->metrics.minx = face->face->glyph->metrics.horiBearingX / 64.0; gc->metrics.maxx = gc->metrics.minx + face->face->glyph->metrics.width / 64.0; gc->metrics.maxy = face->face->glyph->metrics.horiBearingY / 64.0; gc->metrics.miny = gc->metrics.maxy - face->face->glyph->metrics.height / 64.0; gc->metrics.advance = face->face->glyph->metrics.horiAdvance / 64.0; gc->key = key; UT_HASH_ADD(hh,face->glyph_cache,key,sizeof(glyph_element_key), gc); } return gc; } outline_element* msGetGlyphOutline(face_element *face, glyph_element *glyph) { outline_element *oc; outline_element_key key; ft_cache *cache = msGetFontCache(); memset(&key,0,sizeof(outline_element_key)); key.glyph = glyph; #ifdef USE_THREAD if (use_global_ft_cache) msAcquireLock(TLOCK_TTF); #endif UT_HASH_FIND(hh,face->outline_cache,&key, sizeof(outline_element_key),oc); if(!oc) { FT_Matrix matrix; FT_Vector pen; FT_Error error; oc = msSmallMalloc(sizeof(outline_element)); if(MS_NINT(glyph->key.size * 96.0/72.0) != face->face->size->metrics.x_ppem) { FT_Set_Pixel_Sizes(face->face,0,MS_NINT(glyph->key.size * 96/72.0)); } matrix.xx = matrix.yy = 0x10000L; matrix.xy = matrix.yx = 0x00000L; pen.x = pen.y = 0; FT_Set_Transform(face->face, &matrix, &pen); error = FT_Load_Glyph(face->face,glyph->key.codepoint,FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP/*|FT_LOAD_IGNORE_TRANSFORM*/|FT_LOAD_NO_HINTING|FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); if(error) { msSetError(MS_MISCERR, "unable to load glyph %ud for font \"%s\"", "msGetGlyphByIndex()",glyph->key.codepoint, face->font); #ifdef USE_THREAD if (use_global_ft_cache) msReleaseLock(TLOCK_TTF); #endif return NULL; } error = FT_Outline_New(cache->library, face->face->glyph->outline.n_points, face->face->glyph->outline.n_contours, &oc->outline); FT_Outline_Copy(&face->face->glyph->outline, &oc->outline); oc->key = key; UT_HASH_ADD(hh,face->outline_cache,key,sizeof(outline_element_key), oc); } #ifdef USE_THREAD if (use_global_ft_cache) msReleaseLock(TLOCK_TTF); #endif return oc; } int msIsGlyphASpace(glyphObj *glyph) { /* space or tab, for now */ unsigned int space,tab; space = msGetGlyphIndex(glyph->face,0x20); tab = msGetGlyphIndex(glyph->face,0x9); return glyph->glyph->key.codepoint == space || glyph->glyph->key.codepoint == tab; } mapserver-7.4.3/fontcache.h000066400000000000000000000034111357574274700156600ustar00rootroot00000000000000#include "mapserver.h" #include "uthash.h" #include #include FT_FREETYPE_H #include FT_GLYPH_H #include FT_OUTLINE_H #ifdef USE_FRIBIDI #if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(HAVE_FRIBIDI2) #include "fribidi.h" #else #include #endif #include #endif #ifdef __cplusplus extern "C" { #endif typedef struct { /* this one can remain private */ unsigned int unicode; unsigned int codepoint; UT_hash_handle hh; } index_element; typedef struct { void *hbparentfont; void *hbfont; void *funcs; int cursize; } hb_font_element; typedef struct { unsigned int codepoint; unsigned int size; } glyph_element_key; struct glyph_element{ glyph_element_key key; glyph_metrics metrics; UT_hash_handle hh; }; typedef struct { glyph_element *glyph; } outline_element_key; typedef struct { outline_element_key key; FT_Outline outline; UT_hash_handle hh; } outline_element; typedef struct { glyph_element *glyph; } bitmap_element_key; typedef struct { bitmap_element_key key; void *bitmap; UT_hash_handle hh; } bitmap_element; struct face_element{ char *font; FT_Face face; index_element *index_cache; glyph_element *glyph_cache; outline_element *outline_cache; hb_font_element *hbfont; UT_hash_handle hh; }; face_element* msGetFontFace(char *key, fontSetObj *fontset); outline_element* msGetGlyphOutline(face_element *face, glyph_element *glyph); glyph_element* msGetBitmapGlyph(rendererVTableObj *renderer, unsigned int size, unsigned int unicode); unsigned int msGetGlyphIndex(face_element *face, unsigned int unicode); glyph_element* msGetGlyphByIndex(face_element *face, unsigned int size, unsigned int codepoint); int msIsGlyphASpace(glyphObj *glyph); #ifdef __cplusplus } #endif mapserver-7.4.3/fonts/000077500000000000000000000000001357574274700147075ustar00rootroot00000000000000mapserver-7.4.3/fonts/README000066400000000000000000000010501357574274700155630ustar00rootroot00000000000000Fontsets are very simple lookup tables so that you can use simple aliases to refer to fonts rather than cryptic file names. The format is as follows: [font file] [font alias] The font file is either fullpath or a path relative to the fontset file. Font alias can be up to 20 chars and is a short name by which you may refer to fonts in your map files. We can't distribute any TrueType fonts with the system, but there are lots of good free ones available on the net. Visit the FreeType homepage (http://www.freetype.org/) for lots of good pointers. mapserver-7.4.3/fonts/fonts.list.example000066400000000000000000000014741357574274700203750ustar00rootroot00000000000000arial arial.ttf arial-bold arialbd.ttf arial-italic ariali.ttf arial-bold-italic arialbi.ttf arial_black ariblk.ttf comic_sans comic.ttf comic_sans-bold comicbd.ttf courier cour.ttf courier-bold courbd.ttf courier-italic couri.ttf courier-bold-italic courbi.ttf georgia georgia.ttf georgia-bold georgiab.ttf georgia-italic georgiai.ttf georgia-bold-italic georgiaz.ttf impact impact.ttf monotype.com monotype.ttf recreation_symbols recreate.ttf times times.ttf times-bold timesbd.ttf times-italic timesi.ttf times-bold-italic timesbi.ttf trebuchet_ms trebuc.ttf trebuchet_ms-bold trebucbd.ttf trebuchet_ms-italic trebucit.ttf trebuchet_ms-bold-italic trebucbi.ttf verdana verdana.ttf verdana-bold verdanab.ttf verdana-italic verdanai.ttf verdana-bold-italic verdanaz.ttf mapserver-7.4.3/hittest.c000066400000000000000000000227151357574274700154150ustar00rootroot00000000000000/***************************************************************************** * * Project: MapServer * Purpose: Content Dependant Legend rendering support * Author: Thomas Bonfort (tbonfort@terriscope.fr) * ****************************************************************************** * Copyright (c) 1996-2013 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" void initStyleHitTests(styleObj *s, style_hittest *sh, int default_status) { sh->status = default_status; } void initLabelHitTests(labelObj *l, label_hittest *lh, int default_status) { int i; lh->stylehits = msSmallCalloc(l->numstyles,sizeof(style_hittest)); lh->status = default_status; for(i=0; inumstyles; i++) { initStyleHitTests(l->styles[i],&lh->stylehits[i],default_status); } } void initClassHitTests(classObj *c, class_hittest *ch, int default_status) { int i; ch->stylehits = msSmallCalloc(c->numstyles,sizeof(style_hittest)); ch->labelhits = msSmallCalloc(c->numlabels,sizeof(label_hittest)); ch->status = default_status; for(i=0; inumstyles; i++) { initStyleHitTests(c->styles[i],&ch->stylehits[i],default_status); } for(i=0; inumlabels; i++) { initLabelHitTests(c->labels[i],&ch->labelhits[i],default_status); } } void initLayerHitTests(layerObj *l, layer_hittest *lh) { int i,default_status; lh->classhits = msSmallCalloc(l->numclasses,sizeof(class_hittest)); switch(l->type) { case MS_LAYER_POLYGON: case MS_LAYER_POINT: case MS_LAYER_LINE: case MS_LAYER_ANNOTATION: default_status = 0; /* needs testing */ break; default: default_status = 1; /* no hittesting needed, use traditional mode */ break; } lh->status = default_status; for(i=0; inumclasses; i++) { initClassHitTests(l->class[i],&lh->classhits[i], default_status); } } void initMapHitTests(mapObj *map, map_hittest *mh) { int i; mh->layerhits = msSmallCalloc(map->numlayers,sizeof(layer_hittest)); for(i=0; inumlayers; i++) { initLayerHitTests(GET_LAYER(map,i),&mh->layerhits[i]); } } void freeLabelHitTests(labelObj *l, label_hittest *lh) { free(lh->stylehits); } void freeClassHitTests(classObj *c, class_hittest *ch) { int i; for(i=0; inumlabels; i++) { freeLabelHitTests(c->labels[i],&ch->labelhits[i]); } free(ch->stylehits); free(ch->labelhits); } void freeLayerHitTests(layerObj *l, layer_hittest *lh) { int i; for(i=0; inumclasses; i++) { freeClassHitTests(l->class[i],&lh->classhits[i]); } free(lh->classhits); } void freeMapHitTests(mapObj *map, map_hittest *mh) { int i; for(i=0; inumlayers; i++) { freeLayerHitTests(GET_LAYER(map,i),&mh->layerhits[i]); } free(mh->layerhits); } int msHitTestShape(mapObj *map, layerObj *layer, shapeObj *shape, int drawmode, class_hittest *hittest) { int i; classObj *cp = layer->class[shape->classindex]; if(MS_DRAW_FEATURES(drawmode)) { for(i=0;inumstyles;i++) { styleObj *sp = cp->styles[i]; if(msScaleInBounds(map->scaledenom,sp->minscaledenom,sp->maxscaledenom)) { hittest->stylehits[i].status = 1; } } } if(MS_DRAW_LABELS(drawmode)) { for(i=0;inumlabels;i++) { labelObj *l = cp->labels[i]; if(msGetLabelStatus(map,layer,shape,l) == MS_ON) { int s; hittest->labelhits[i].status = 1; for(s=0; snumstyles;s++) { hittest->labelhits[i].stylehits[s].status = 1; } } } } return MS_SUCCESS; } int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest) { int status; #ifdef USE_GEOS shapeObj searchpoly; #endif if(!msLayerIsVisible(map,layer)) { hittest->status = 0; return MS_SUCCESS; } if(layer->type == MS_LAYER_LINE || layer->type == MS_LAYER_POLYGON || layer->type == MS_LAYER_POINT || layer->type == MS_LAYER_ANNOTATION) { int maxfeatures=msLayerGetMaxFeaturesToDraw(layer, NULL); int annotate = msEvalContext(map, layer, layer->labelrequires); shapeObj shape; int nclasses,featuresdrawn = 0; int *classgroup; rectObj searchrect; int minfeaturesize=-1; if(map->scaledenom > 0) { if((layer->labelmaxscaledenom != -1) && (map->scaledenom >= layer->labelmaxscaledenom)) annotate = MS_FALSE; if((layer->labelminscaledenom != -1) && (map->scaledenom < layer->labelminscaledenom)) annotate = MS_FALSE; } status = msLayerOpen(layer); if(status != MS_SUCCESS) return MS_FAILURE; /* build item list */ status = msLayerWhichItems(layer, MS_FALSE, NULL); if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* identify target shapes */ if(layer->transform == MS_TRUE) { searchrect = map->extent; #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif } else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } #ifdef USE_GEOS msInitShape(&searchpoly); msRectToPolygon(searchrect,&searchpoly); #endif status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ #ifdef USE_GEOS msFreeShape(&searchpoly); #endif msLayerClose(layer); hittest->status = 0; return MS_SUCCESS; } else if(status != MS_SUCCESS) { #ifdef USE_GEOS msFreeShape(&searchpoly); #endif msLayerClose(layer); return MS_FAILURE; } /* step through the target shapes */ msInitShape(&shape); nclasses = 0; classgroup = NULL; if(layer->classgroup && layer->numclasses > 0) classgroup = msAllocateValidClassGroups(layer, &nclasses); if(layer->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, layer, layer->minfeaturesize); while((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) { int drawmode = MS_DRAWMODE_FEATURES; #ifdef USE_GEOS if(!msGEOSIntersects(&shape,&searchpoly)) { msFreeShape(&shape); continue; } #else if(shape.type == MS_SHAPE_POLYGON) { msClipPolygonRect(&shape, map->extent); } else { msClipPolylineRect(&shape, map->extent); } if(shape.numlines == 0) { msFreeShape(&shape); continue; } #endif /* Check if the shape size is ok to be drawn, we need to clip */ if((shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0)) { msTransformShape(&shape, map->extent, map->cellsize, NULL); msComputeBounds(&shape); if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(layer, map, &shape, classgroup, nclasses); if((shape.classindex == -1) || (layer->class[shape.classindex]->status == MS_OFF)) { msFreeShape(&shape); continue; } hittest->classhits[shape.classindex].status = 1; hittest->status = 1; if(maxfeatures >=0 && featuresdrawn >= maxfeatures) { msFreeShape(&shape); status = MS_DONE; break; } featuresdrawn++; if(annotate && layer->class[shape.classindex]->numlabels > 0) { drawmode |= MS_DRAWMODE_LABELS; } status = msHitTestShape(map, layer, &shape, drawmode, &hittest->classhits[shape.classindex]); /* all styles */ msFreeShape(&shape); } #ifdef USE_GEOS msFreeShape(&searchpoly); #endif if (classgroup) msFree(classgroup); if(status != MS_DONE) { msLayerClose(layer); return MS_FAILURE; } msLayerClose(layer); return MS_SUCCESS; } else { /* we don't hittest these layers, skip as they already have been initialised */ return MS_SUCCESS; } } int msHitTestMap(mapObj *map, map_hittest *hittest) { int i,status; map->cellsize = msAdjustExtent(&(map->extent),map->width,map->height); status = msCalculateScale(map->extent,map->units,map->width,map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) { return MS_FAILURE; } for(i=0; inumlayers; i++) { layerObj *lp = map->layers[i]; status = msHitTestLayer(map,lp,&hittest->layerhits[i]); if(status != MS_SUCCESS) { return MS_FAILURE; } } return MS_SUCCESS; } mapserver-7.4.3/hittest.h000066400000000000000000000051211357574274700154120ustar00rootroot00000000000000/***************************************************************************** * * Project: MapServer * Purpose: Content Dependant Legend rendering support * Author: Thomas Bonfort (tbonfort@terriscope.fr) * ****************************************************************************** * Copyright (c) 1996-2013 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef HITTEST_H #define HITTEST_H typedef struct { int status; } style_hittest; typedef struct { style_hittest *stylehits; int status; } label_hittest; typedef struct { style_hittest *stylehits; label_hittest *labelhits; int status; } class_hittest; typedef struct { class_hittest *classhits; int status; } layer_hittest; typedef struct map_hittest{ layer_hittest *layerhits; } map_hittest; int msHitTestMap(mapObj *map, map_hittest *hittest); int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest); void initStyleHitTests(styleObj *s, style_hittest *sh, int default_status); void initLabelHitTests(labelObj *l, label_hittest *lh, int default_status); void initClassHitTests(classObj *c, class_hittest *ch, int default_status); void initLayerHitTests(layerObj *l, layer_hittest *lh); void initMapHitTests(mapObj *map, map_hittest *mh); void freeLabelHitTests(labelObj *l, label_hittest *lh); void freeClassHitTests(classObj *c, class_hittest *ch); void freeLayerHitTests(layerObj *l, layer_hittest *lh); void freeMapHitTests(mapObj *map, map_hittest *mh); #endif mapserver-7.4.3/kerneldensity.c000066400000000000000000000273641357574274700166160ustar00rootroot00000000000000/****************************************************************************** * * Project: MapServer * Purpose: KernelDensity layer implementation and related functions. * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 2014 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include #ifdef USE_GDAL #include "gdal.h" #include "cpl_string.h" void gaussian_blur(float *values, int width, int height, int radius) { float *tmp = (float*)msSmallMalloc(width*height*sizeof(float)); int length = radius*2+1; float *kernel = (float*)msSmallMalloc(length*sizeof(float)); float sigma=radius/3.0; float a=1.0/ sqrt(2.0*M_PI*sigma*sigma); float den=2.0*sigma*sigma; int i,x,y; for (i=0; iwidth, im_height = image->height; int expand_searchrect=1; float normalization_scale=0.0; double invcellsize = 1.0 / map->cellsize, georadius=0; float valmax=FLT_MIN, valmin=FLT_MAX; unsigned char *iValues; GDALDatasetH hDS; const char *pszProcessing; int *classgroup = NULL; assert(kerneldensity_layer->connectiontype == MS_KERNELDENSITY); *cleanup_ptr = NULL; if(!kerneldensity_layer->connection || !*kerneldensity_layer->connection) { msSetError(MS_MISCERR, "msComputeKernelDensityDataset()", "KernelDensity layer has no CONNECTION defined"); return MS_FAILURE; } pszProcessing = msLayerGetProcessingKey( kerneldensity_layer, "KERNELDENSITY_RADIUS" ); if(pszProcessing) radius = atoi(pszProcessing); else radius = 10; pszProcessing = msLayerGetProcessingKey( kerneldensity_layer, "KERNELDENSITY_COMPUTE_BORDERS" ); if(pszProcessing && strcasecmp(pszProcessing,"OFF")) expand_searchrect = 1; else expand_searchrect = 0; pszProcessing = msLayerGetProcessingKey( kerneldensity_layer, "KERNELDENSITY_NORMALIZATION" ); if(!pszProcessing || !strcasecmp(pszProcessing,"AUTO")) normalization_scale = 0.0; else { normalization_scale = atof(pszProcessing); if(normalization_scale != 0) { normalization_scale = 1.0 / normalization_scale; } else { normalization_scale = 1.0; } } layer_idx = msGetLayerIndex(map,kerneldensity_layer->connection); if(layer_idx == -1) { int nLayers, *aLayers; aLayers = msGetLayersIndexByGroup(map, kerneldensity_layer->connection, &nLayers); if(!aLayers || !nLayers) { msSetError(MS_MISCERR, "KernelDensity layer (%s) references unknown layer (%s)", "msComputeKernelDensityDataset()", kerneldensity_layer->name,kerneldensity_layer->connection); return (MS_FAILURE); } for(i=0; iscaledenom, layer->minscaledenom, layer->maxscaledenom)) break; } free(aLayers); if(i == nLayers) { msSetError(MS_MISCERR, "KernelDensity layer (%s) references no layer for current scale", "msComputeKernelDensityDataset()", kerneldensity_layer->name); return (MS_FAILURE); } } else { layer = GET_LAYER(map, layer_idx); } /* open the linked layer */ status = msLayerOpen(layer); if(status != MS_SUCCESS) return MS_FAILURE; status = msLayerWhichItems(layer, MS_FALSE, NULL); if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* identify target shapes */ if(layer->transform == MS_TRUE) { searchrect = map->extent; if(expand_searchrect) { georadius = radius * map->cellsize; searchrect.minx -= georadius; searchrect.miny -= georadius; searchrect.maxx += georadius; searchrect.maxy += georadius; im_width += 2 * radius; im_height += 2 * radius; } } else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } #ifdef USE_PROJ layer->project = msProjectionsDiffer(&(layer->projection), &(map->projection)); if(layer->project) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif status = msLayerWhichShapes(layer, searchrect, MS_FALSE); /* nothing to do */ if(status == MS_SUCCESS) { /* at least one sample may have overlapped */ if(layer->classgroup && layer->numclasses > 0) classgroup = msAllocateValidClassGroups(layer, &nclasses); msInitShape(&shape); while((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) { int l,p,s,c; double weight = 1.0; if(!values) /* defer allocation until we effectively have a feature */ values = (float*) msSmallCalloc(im_width * im_height, sizeof(float)); #ifdef USE_PROJ if(layer->project) msProjectShape(&layer->projection, &map->projection, &shape); #endif /* the weight for the sample is set to 1.0 by default. If the * layer has some classes defined, we will read the weight from * the class->style->size (which can be binded to an attribute) */ if(layer->numclasses > 0) { c = msShapeGetClass(layer, map, &shape, classgroup, nclasses); if((c == -1) || (layer->class[c]->status == MS_OFF)) { goto nextshape; /* no class matched, skip */ } for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) { if(layer->class[c]->styles[s]->bindings[MS_STYLE_BINDING_SIZE].index != -1) { weight = atof(shape.values[layer->class[c]->styles[s]->bindings[MS_STYLE_BINDING_SIZE].index]); } else { weight = layer->class[c]->styles[s]->size; } break; } } if(s == layer->class[c]->numstyles) { /* no style in scale bounds */ goto nextshape; } } for(l=0; lextent.minx - georadius, invcellsize); int y = MS_MAP2IMAGE_YCELL_IC(shape.line[l].point[p].y, map->extent.maxy + georadius, invcellsize); if(x>=0 && y>=0 && x0 && val>valmax) { valmax = val; } if(val>0 && valwidth*image->height*sizeof(unsigned char)); for (j=0; jheight; j++) { for (i=0; iwidth; i++) { float norm=(values[(j+radius)*im_width + i + radius] - valmin) / valmax; int v=255 * norm; if (v<0) v=0; else if (v>255) v=255; iValues[j*image->width + i] = v; } } } else { iValues = msSmallCalloc(1,image->width*image->height*sizeof(unsigned char)); if(have_sample) { for (j=radius; jheight-radius; j++) { for (i=radius; iwidth-radius; i++) { float norm=(values[j*im_width + i] - valmin) / valmax; int v=255 * norm; if (v<0) v=0; else if (v>255) v=255; iValues[j*image->width + i]=v; } } } } free(values); { char pointer[64]; char ds_string [1024]; double adfGeoTransform[6]; memset(pointer, 0, sizeof(pointer)); CPLPrintPointer(pointer, iValues, sizeof(pointer)); snprintf(ds_string,1024,"MEM:::DATAPOINTER=%s,PIXELS=%u,LINES=%u,BANDS=1,DATATYPE=Byte,PIXELOFFSET=1,LINEOFFSET=%u", pointer,image->width,image->height,image->width); hDS = GDALOpenShared( ds_string, GA_ReadOnly ); if(hDS==NULL) { msSetError(MS_MISCERR,"msComputeKernelDensityDataset()","failed to create in-memory gdal dataset for interpolated data"); status = MS_FAILURE; free(iValues); return status; } adfGeoTransform[0] = map->extent.minx - map->cellsize * 0.5; /* top left x */ adfGeoTransform[1] = map->cellsize;/* w-e pixel resolution */ adfGeoTransform[2] = 0; /* 0 */ adfGeoTransform[3] = map->extent.maxy + map->cellsize * 0.5;/* top left y */ adfGeoTransform[4] =0; /* 0 */ adfGeoTransform[5] = -map->cellsize;/* n-s pixel resolution (negative value) */ GDALSetGeoTransform(hDS,adfGeoTransform); *hDSvoid = hDS; *cleanup_ptr = (void*)iValues; } return status; } #else int msComputeKernelDensityDataset(mapObj *map, imageObj *image, layerObj *layer, void **hDSvoid, void **cleanup_ptr) { msSetError(MS_MISCERR,"msComputeKernelDensityDataset()", "KernelDensity layers require GDAL support, however GDAL support is not compiled in this build"); return MS_FAILURE; } #endif int msCleanupKernelDensityDataset(mapObj *map, imageObj *image, layerObj *layer, void *cleanup_ptr) { free(cleanup_ptr); return MS_SUCCESS; } mapserver-7.4.3/layerobject.c000066400000000000000000000143151357574274700162310ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions for operating on a layerObj that don't belong in a * more specific file such as mapfile.c. * Adapted from mapobject.c. * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * Copyright (c) 2004, Sean Gillies * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #ifdef USE_GDAL # include "gdal.h" # include "cpl_conv.h" #endif /* =========================================================================== msInsertClass Returns the index at which the class was inserted. ======================================================================== */ int msInsertClass(layerObj *layer, classObj *classobj, int nIndex) { int i; if (!classobj) { msSetError(MS_CHILDERR, "Cannot insert NULL class", "msInsertClass()"); return -1; } /* Ensure there is room for a new class */ if (msGrowLayerClasses(layer) == NULL) { return -1; } /* Catch attempt to insert past end of styles array */ else if (nIndex >= layer->numclasses) { msSetError(MS_CHILDERR, "Cannot insert class beyond index %d", "msInsertClass()", layer->numclasses-1); return -1; } else if (nIndex < 0) { /* Insert at the end by default */ #ifndef __cplusplus layer->class[layer->numclasses]=classobj; #else layer->_class[layer->numclasses]=classobj; #endif /* set parent pointer */ classobj->layer=layer; MS_REFCNT_INCR(classobj); layer->numclasses++; return layer->numclasses-1; } else if (nIndex >= 0 && nIndex < layer->numclasses) { /* Copy classes existing at the specified nIndex or greater */ /* to an index one higher */ #ifndef __cplusplus for (i=layer->numclasses-1; i>=nIndex; i--) layer->class[i+1] = layer->class[i]; layer->class[nIndex]=classobj; #else for (i=layer->numclasses-1; i>=nIndex; i--) layer->_class[i+1] = layer->_class[i]; layer->_class[nIndex]=classobj; #endif /* set parent pointer */ classobj->layer=layer; MS_REFCNT_INCR(classobj); /* increment number of classes and return */ layer->numclasses++; return nIndex; } else { msSetError(MS_CHILDERR, "Invalid index", "msInsertClass()"); return -1; } } /* =========================================================================== msRemoveClass remove the class at an index from a layer, returning a copy ======================================================================== */ classObj *msRemoveClass(layerObj *layer, int nIndex) { int i; classObj *classobj; if (nIndex < 0 || nIndex >= layer->numclasses) { msSetError(MS_CHILDERR, "Cannot remove class, invalid index %d", "removeClass()", nIndex); return NULL; } else { #ifndef __cplusplus classobj=layer->class[nIndex]; #else classobj=layer->_class[nIndex]; #endif classobj->layer=NULL; MS_REFCNT_DECR(classobj); /* Iteratively copy the higher index classes down one index */ for (i=nIndex; inumclasses-1; i++) { #ifndef __cplusplus layer->class[i]=layer->class[i+1]; #else layer->_class[i]=layer->_class[i+1]; #endif } #ifndef __cplusplus layer->class[i]=NULL; #else layer->_class[i]=NULL; #endif /* decrement number of layers and return copy of removed layer */ layer->numclasses--; return classobj; } } /** * Move the class up inside the array of classes. */ int msMoveClassUp(layerObj *layer, int nClassIndex) { classObj *psTmpClass = NULL; if (layer && nClassIndex < layer->numclasses && nClassIndex >0) { psTmpClass=layer->class[nClassIndex]; layer->class[nClassIndex] = layer->class[nClassIndex-1]; layer->class[nClassIndex-1] = psTmpClass; return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveClassUp()", nClassIndex); return (MS_FAILURE); } /** * Move the class down inside the array of classes. */ int msMoveClassDown(layerObj *layer, int nClassIndex) { classObj *psTmpClass = NULL; if (layer && nClassIndex < layer->numclasses-1 && nClassIndex >=0) { psTmpClass=layer->class[nClassIndex]; layer->class[nClassIndex] = layer->class[nClassIndex+1]; layer->class[nClassIndex+1] = psTmpClass; return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveClassDown()", nClassIndex); return (MS_FAILURE); } /** * Set the extent of a layer. */ int msLayerSetExtent( layerObj *layer, double minx, double miny, double maxx, double maxy) { layer->extent.minx = minx; layer->extent.miny = miny; layer->extent.maxx = maxx; layer->extent.maxy = maxy; if (minx == -1.0 && miny == -1.0 && maxx == -1.0 && maxy == -1.0) return(MS_SUCCESS); if (!MS_VALID_EXTENT(layer->extent)) { msSetError(MS_MISCERR, "Given layer extent is invalid. minx=%lf, miny=%lf, maxx=%lf, maxy=%lf.", "msLayerSetExtent()", layer->extent.minx, layer->extent.miny, layer->extent.maxx, layer->extent.maxy); return(MS_FAILURE); } return(MS_SUCCESS); } mapserver-7.4.3/legend.c000066400000000000000000000041551357574274700151650ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Mainline of commandline legend generation test utility. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" int main(int argc, char *argv[]) { mapObj *map=NULL; imageObj *img=NULL; msSetup(); if(argc > 1 && strcmp(argv[1], "-v") == 0) { printf("%s\n", msGetVersion()); exit(0); } if( argc < 3 ) { fprintf(stdout,"Syntax: legend [mapfile] [output image]\n" ); exit(0); } map = msLoadMap(argv[1], NULL); if(!map) { msWriteError(stderr); exit(0); } img = msDrawLegend(map, MS_FALSE, NULL); if(!img) { msWriteError(stderr); exit(0); } msSaveImage(NULL, img, argv[2]); msFreeImage(img); msFreeMap(map); return(MS_TRUE); } mapserver-7.4.3/mapagg.cpp000066400000000000000000001403101357574274700155150ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: AGG rendering and other AGG related functions. * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "fontcache.h" #include "mapagg.h" #include #include "renderers/agg/include/agg_color_rgba.h" #include "renderers/agg/include/agg_pixfmt_rgba.h" #include "renderers/agg/include/agg_renderer_base.h" #include "renderers/agg/include/agg_renderer_scanline.h" #include "renderers/agg/include/agg_math_stroke.h" #include "renderers/agg/include/agg_scanline_p.h" #include "renderers/agg/include/agg_scanline_u.h" #include "renderers/agg/include/agg_rasterizer_scanline_aa.h" #include "renderers/agg/include/agg_span_pattern_rgba.h" #include "renderers/agg/include/agg_span_allocator.h" #include "renderers/agg/include/agg_span_interpolator_linear.h" #include "renderers/agg/include/agg_pattern_filters_rgba.h" #include "renderers/agg/include/agg_image_accessors.h" #include "renderers/agg/include/agg_conv_stroke.h" #include "renderers/agg/include/agg_conv_dash.h" #include "renderers/agg/include/agg_font_freetype.h" #include "renderers/agg/include/agg_conv_contour.h" #include "renderers/agg/include/agg_ellipse.h" #include "renderers/agg/include/agg_gamma_functions.h" #include "renderers/agg/include/agg_blur.h" #include "renderers/agg/include/agg_rasterizer_outline_aa.h" #include "renderers/agg/include/agg_renderer_outline_aa.h" #include "renderers/agg/include/agg_renderer_outline_image.h" #include "renderers/agg/include/agg_span_pattern_rgba.h" #include "renderers/agg/include/agg_span_image_filter_rgba.h" #include "renderers/agg/include/agg_glyph_raster_bin.h" #include "renderers/agg/include/agg_renderer_raster_text.h" #include "renderers/agg/include/agg_path_storage_integer.h" #include "renderers/agg/include/agg_conv_clipper.h" #ifdef USE_PIXMAN #include #endif #ifdef AGG_ALIASED_ENABLED #include "renderers/agg/include/agg_renderer_primitives.h" #include "renderers/agg/include/agg_rasterizer_outline.h" #endif typedef mapserver::order_bgra band_order; #define AGG_LINESPACE 1.33 typedef mapserver::int8u band_type; typedef mapserver::rgba8 color_type; typedef mapserver::pixel32_type pixel_type; typedef mapserver::blender_rgba_pre blender_pre; typedef mapserver::comp_op_adaptor_rgba_pre compop_blender_pre; typedef mapserver::pixfmt_alpha_blend_rgba pixel_format; typedef mapserver::pixfmt_custom_blend_rgba compop_pixel_format; typedef mapserver::rendering_buffer rendering_buffer; typedef mapserver::renderer_base renderer_base; typedef mapserver::renderer_base compop_renderer_base; typedef mapserver::renderer_scanline_aa_solid renderer_scanline; typedef mapserver::rasterizer_scanline_aa<> rasterizer_scanline; typedef mapserver::font_engine_freetype_int16 font_engine_type; typedef mapserver::font_cache_manager font_manager_type; typedef mapserver::conv_curve font_curve_type; typedef mapserver::glyph_raster_bin glyph_gen; #ifdef AGG_ALIASED_ENABLED typedef mapserver::renderer_primitives renderer_primitives; typedef mapserver::rasterizer_outline rasterizer_outline; #endif static color_type AGG_NO_COLOR = color_type(0, 0, 0, 0); #define aggColor(c) mapserver::rgba8_pre((c)->red, (c)->green, (c)->blue, (c)->alpha) class aggRendererCache { public: font_engine_type m_feng; font_manager_type m_fman; aggRendererCache(): m_fman(m_feng) {} }; class AGG2Renderer { public: AGG2Renderer() #ifdef AGG_ALIASED_ENABLED : m_renderer_primitives(m_renderer_base), m_rasterizer_primitives(m_renderer_primitives) #endif { stroke = NULL; dash = NULL; stroke_dash = NULL; } ~AGG2Renderer() { if(stroke) { delete stroke; } if(dash) { delete dash; } if(stroke_dash) { delete stroke_dash; } } band_type* buffer; rendering_buffer m_rendering_buffer; pixel_format m_pixel_format; compop_pixel_format m_compop_pixel_format; renderer_base m_renderer_base; compop_renderer_base m_compop_renderer_base; renderer_scanline m_renderer_scanline; #ifdef AGG_ALIASED_ENABLED renderer_primitives m_renderer_primitives; rasterizer_outline m_rasterizer_primitives; #endif rasterizer_scanline m_rasterizer_aa; rasterizer_scanline m_rasterizer_aa_gamma; mapserver::scanline_p8 sl_poly; /*packed scanlines, works faster when the area is larger than the perimeter, in number of pixels*/ mapserver::scanline_u8 sl_line; /*unpacked scanlines, works faster if the area is roughly equal to the perimeter, in number of pixels*/ bool use_alpha; mapserver::conv_stroke *stroke; mapserver::conv_dash *dash; mapserver::conv_stroke > *stroke_dash; double default_gamma; mapserver::gamma_linear gamma_function; }; #define AGG_RENDERER(image) ((AGG2Renderer*) (image)->img.plugin) template static void applyCJC(VertexSource &stroke, int caps, int joins) { switch (joins) { case MS_CJC_ROUND: stroke.line_join(mapserver::round_join); break; case MS_CJC_MITER: stroke.line_join(mapserver::miter_join); break; case MS_CJC_BEVEL: case MS_CJC_NONE: stroke.line_join(mapserver::bevel_join); break; } switch (caps) { case MS_CJC_BUTT: case MS_CJC_NONE: stroke.line_cap(mapserver::butt_cap); break; case MS_CJC_ROUND: stroke.line_cap(mapserver::round_cap); break; case MS_CJC_SQUARE: stroke.line_cap(mapserver::square_cap); break; } } int agg2RenderLine(imageObj *img, shapeObj *p, strokeStyleObj *style) { AGG2Renderer *r = AGG_RENDERER(img); line_adaptor lines = line_adaptor(p); #ifdef AGG_ALIASED_ENABLED r->m_rasterizer_primitives.reset(); r->m_renderer_primitives.line_color(aggColor(style->color)); r->m_rasterizer_primitives.add_path(lines); return MS_SUCCESS; #endif r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_renderer_scanline.color(aggColor(style->color)); if (style->patternlength <= 0) { if(!r->stroke) { r->stroke = new mapserver::conv_stroke(lines); } else { r->stroke->attach(lines); } r->stroke->width(style->width); if(style->width>1) { applyCJC(*r->stroke, style->linecap, style->linejoin); } else { r->stroke->inner_join(mapserver::inner_bevel); r->stroke->line_join(mapserver::bevel_join); } r->m_rasterizer_aa.add_path(*r->stroke); } else { if(!r->dash) { r->dash = new mapserver::conv_dash(lines); } else { r->dash->remove_all_dashes(); r->dash->dash_start(0.0); r->dash->attach(lines); } if(!r->stroke_dash) { r->stroke_dash = new mapserver::conv_stroke > (*r->dash); } else { r->stroke_dash->attach(*r->dash); } int patt_length = 0; for (int i = 0; i < style->patternlength; i += 2) { if (i < style->patternlength - 1) { r->dash->add_dash(MS_MAX(1,MS_NINT(style->pattern[i])), MS_MAX(1,MS_NINT(style->pattern[i + 1]))); if(style->patternoffset) { patt_length += MS_MAX(1,MS_NINT(style->pattern[i])) + MS_MAX(1,MS_NINT(style->pattern[i + 1])); } } } if(style->patternoffset > 0) { r->dash->dash_start(patt_length - style->patternoffset); } r->stroke_dash->width(style->width); if(style->width>1) { applyCJC(*r->stroke_dash, style->linecap, style->linejoin); } else { r->stroke_dash->inner_join(mapserver::inner_bevel); r->stroke_dash->line_join(mapserver::bevel_join); } r->m_rasterizer_aa.add_path(*r->stroke_dash); } mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); return MS_SUCCESS; } int agg2RenderLineTiled(imageObj *img, shapeObj *p, imageObj * tile) { mapserver::pattern_filter_bilinear_rgba8 fltr; typedef mapserver::line_image_pattern pattern_type; typedef mapserver::renderer_outline_image renderer_img_type; typedef mapserver::rasterizer_outline_aa rasterizer_img_type; pattern_type patt(fltr); AGG2Renderer *r = AGG_RENDERER(img); AGG2Renderer *tileRenderer = AGG_RENDERER(tile); line_adaptor lines(p); patt.create(tileRenderer->m_pixel_format); renderer_img_type ren_img(r->m_renderer_base, patt); rasterizer_img_type ras_img(ren_img); ras_img.add_path(lines); return MS_SUCCESS; } int agg2RenderPolygon(imageObj *img, shapeObj *p, colorObj * color) { AGG2Renderer *r = AGG_RENDERER(img); polygon_adaptor polygons(p); r->m_rasterizer_aa_gamma.reset(); r->m_rasterizer_aa_gamma.filling_rule(mapserver::fill_even_odd); r->m_rasterizer_aa_gamma.add_path(polygons); r->m_renderer_scanline.color(aggColor(color)); mapserver::render_scanlines(r->m_rasterizer_aa_gamma, r->sl_poly, r->m_renderer_scanline); return MS_SUCCESS; } static inline double int26p6_to_dbl(int p) { return double(p) / 64.0; } template bool decompose_ft_outline(const FT_Outline& outline, bool flip_y, const mapserver::trans_affine& mtx, PathStorage& path) { FT_Vector v_last; FT_Vector v_control; FT_Vector v_start; double x1, y1, x2, y2, x3, y3; FT_Vector* point; FT_Vector* limit; char* tags; int n; // index of contour in outline int first; // index of first point in contour char tag; // current point's state first = 0; for(n = 0; n < outline.n_contours; n++) { int last; // index of last point in contour last = outline.contours[n]; limit = outline.points + last; v_start = outline.points[first]; v_last = outline.points[last]; v_control = v_start; point = outline.points + first; tags = outline.tags + first; tag = FT_CURVE_TAG(tags[0]); // A contour cannot start with a cubic control point! if(tag == FT_CURVE_TAG_CUBIC) return false; // check first point to determine origin if( tag == FT_CURVE_TAG_CONIC) { // first point is conic control. Yes, this happens. if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) { // start at last point if it is on the curve v_start = v_last; limit--; } else { // if both first and last points are conic, // start at their middle and record its position // for closure v_start.x = (v_start.x + v_last.x) / 2; v_start.y = (v_start.y + v_last.y) / 2; v_last = v_start; } point--; tags--; } x1 = int26p6_to_dbl(v_start.x); y1 = int26p6_to_dbl(v_start.y); if(flip_y) y1 = -y1; mtx.transform(&x1, &y1); path.move_to(x1,y1); while(point < limit) { point++; tags++; tag = FT_CURVE_TAG(tags[0]); switch(tag) { case FT_CURVE_TAG_ON: // emit a single line_to { x1 = int26p6_to_dbl(point->x); y1 = int26p6_to_dbl(point->y); if(flip_y) y1 = -y1; mtx.transform(&x1, &y1); path.line_to(x1,y1); //path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y)); continue; } case FT_CURVE_TAG_CONIC: // consume conic arcs { v_control.x = point->x; v_control.y = point->y; Do_Conic: if(point < limit) { FT_Vector vec; FT_Vector v_middle; point++; tags++; tag = FT_CURVE_TAG(tags[0]); vec.x = point->x; vec.y = point->y; if(tag == FT_CURVE_TAG_ON) { x1 = int26p6_to_dbl(v_control.x); y1 = int26p6_to_dbl(v_control.y); x2 = int26p6_to_dbl(vec.x); y2 = int26p6_to_dbl(vec.y); if(flip_y) { y1 = -y1; y2 = -y2; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); path.curve3(x1,y1,x2,y2); continue; } if(tag != FT_CURVE_TAG_CONIC) return false; v_middle.x = (v_control.x + vec.x) / 2; v_middle.y = (v_control.y + vec.y) / 2; x1 = int26p6_to_dbl(v_control.x); y1 = int26p6_to_dbl(v_control.y); x2 = int26p6_to_dbl(v_middle.x); y2 = int26p6_to_dbl(v_middle.y); if(flip_y) { y1 = -y1; y2 = -y2; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); path.curve3(x1,y1,x2,y2); //path.curve3(conv(v_control.x), // flip_y ? -conv(v_control.y) : conv(v_control.y), // conv(v_middle.x), // flip_y ? -conv(v_middle.y) : conv(v_middle.y)); v_control = vec; goto Do_Conic; } x1 = int26p6_to_dbl(v_control.x); y1 = int26p6_to_dbl(v_control.y); x2 = int26p6_to_dbl(v_start.x); y2 = int26p6_to_dbl(v_start.y); if(flip_y) { y1 = -y1; y2 = -y2; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); path.curve3(x1,y1,x2,y2); //path.curve3(conv(v_control.x), // flip_y ? -conv(v_control.y) : conv(v_control.y), // conv(v_start.x), // flip_y ? -conv(v_start.y) : conv(v_start.y)); goto Close; } default: // FT_CURVE_TAG_CUBIC { FT_Vector vec1, vec2; if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) { return false; } vec1.x = point[0].x; vec1.y = point[0].y; vec2.x = point[1].x; vec2.y = point[1].y; point += 2; tags += 2; if(point <= limit) { FT_Vector vec; vec.x = point->x; vec.y = point->y; x1 = int26p6_to_dbl(vec1.x); y1 = int26p6_to_dbl(vec1.y); x2 = int26p6_to_dbl(vec2.x); y2 = int26p6_to_dbl(vec2.y); x3 = int26p6_to_dbl(vec.x); y3 = int26p6_to_dbl(vec.y); if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); mtx.transform(&x3, &y3); path.curve4(x1,y1,x2,y2,x3,y3); //path.curve4(conv(vec1.x), // flip_y ? -conv(vec1.y) : conv(vec1.y), // conv(vec2.x), // flip_y ? -conv(vec2.y) : conv(vec2.y), // conv(vec.x), // flip_y ? -conv(vec.y) : conv(vec.y)); continue; } x1 = int26p6_to_dbl(vec1.x); y1 = int26p6_to_dbl(vec1.y); x2 = int26p6_to_dbl(vec2.x); y2 = int26p6_to_dbl(vec2.y); x3 = int26p6_to_dbl(v_start.x); y3 = int26p6_to_dbl(v_start.y); if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } mtx.transform(&x1, &y1); mtx.transform(&x2, &y2); mtx.transform(&x3, &y3); path.curve4(x1,y1,x2,y2,x3,y3); //path.curve4(conv(vec1.x), // flip_y ? -conv(vec1.y) : conv(vec1.y), // conv(vec2.x), // flip_y ? -conv(vec2.y) : conv(vec2.y), // conv(v_start.x), // flip_y ? -conv(v_start.y) : conv(v_start.y)); goto Close; } } } path.close_polygon(); Close: first = last + 1; } return true; } int agg2RenderPolygonTiled(imageObj *img, shapeObj *p, imageObj * tile) { assert(img->format->renderer == tile->format->renderer); AGG2Renderer *r = AGG_RENDERER(img); AGG2Renderer *tileRenderer = AGG_RENDERER(tile); polygon_adaptor polygons(p); typedef mapserver::wrap_mode_repeat wrap_type; typedef mapserver::image_accessor_wrap img_source_type; typedef mapserver::span_pattern_rgba span_gen_type; mapserver::span_allocator sa; r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_even_odd); img_source_type img_src(tileRenderer->m_pixel_format); span_gen_type sg(img_src, 0, 0); r->m_rasterizer_aa.add_path(polygons); mapserver::render_scanlines_aa(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_base, sa , sg); return MS_SUCCESS; } int agg2RenderGlyphsPath(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow) { mapserver::path_storage glyphs; mapserver::trans_affine trans; AGG2Renderer *r = AGG_RENDERER(img); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); for(int i=0; inumglyphs; i++) { glyphObj *gl = tp->glyphs + i; trans.reset(); trans.rotate(-gl->rot); trans.translate(gl->pnt.x, gl->pnt.y); outline_element *ol = msGetGlyphOutline(gl->face,gl->glyph); if(!ol) { return MS_FAILURE; } decompose_ft_outline(ol->outline,true,trans,glyphs); } mapserver::conv_curve m_curves(glyphs); if (oc) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_contour > cc(m_curves); cc.width(ow + 1); r->m_rasterizer_aa.add_path(cc); r->m_renderer_scanline.color(aggColor(oc)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if(c) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa.add_path(m_curves); r->m_renderer_scanline.color(aggColor(c)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } return MS_SUCCESS; } mapserver::path_storage imageVectorSymbol(symbolObj *symbol) { mapserver::path_storage path; int is_new=1; for(int i=0; i < symbol->numpoints; i++) { if((symbol->points[i].x == -99) && (symbol->points[i].y == -99)) is_new=1; else { if(is_new) { path.move_to(symbol->points[i].x,symbol->points[i].y); is_new=0; } else { path.line_to(symbol->points[i].x,symbol->points[i].y); } } } return path; } int agg2RenderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(img); double ox = symbol->sizex * 0.5; double oy = symbol->sizey * 0.5; mapserver::path_storage path = imageVectorSymbol(symbol); mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-ox,-oy); mtx *= mapserver::trans_affine_scaling(style->scale); mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x, y); path.transform(mtx); if (style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_even_odd); r->m_rasterizer_aa.add_path(path); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_scanline); } if(style->outlinecolor) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::conv_stroke stroke(path); stroke.width(style->outlinewidth); r->m_rasterizer_aa.add_path(stroke); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_scanline); } return MS_SUCCESS; } int agg2RenderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(img); rasterBufferObj *pixmap = symbol->pixmap_buffer; assert(pixmap->type == MS_BUFFER_BYTE_RGBA); rendering_buffer b(pixmap->data.rgba.pixels,pixmap->width,pixmap->height,pixmap->data.rgba.row_step); pixel_format pf(b); r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); if ( (style->rotation != 0 && style->rotation != MS_PI*2.)|| style->scale != 1) { mapserver::trans_affine image_mtx; image_mtx *= mapserver::trans_affine_translation(-(pf.width()/2.),-(pf.height()/2.)); /*agg angles are antitrigonometric*/ image_mtx *= mapserver::trans_affine_rotation(-style->rotation); image_mtx *= mapserver::trans_affine_scaling(style->scale); image_mtx *= mapserver::trans_affine_translation(x,y); image_mtx.invert(); typedef mapserver::span_interpolator_linear<> interpolator_type; interpolator_type interpolator(image_mtx); mapserver::span_allocator sa; // "hardcoded" bilinear filter //------------------------------------------ typedef mapserver::span_image_filter_rgba_bilinear_clip span_gen_type; span_gen_type sg(pf, mapserver::rgba(0,0,0,0), interpolator); mapserver::path_storage pixmap_bbox; int ims_2 = MS_NINT(MS_MAX(pixmap->width,pixmap->height)*style->scale*1.415)/2+1; pixmap_bbox.move_to(x-ims_2,y-ims_2); pixmap_bbox.line_to(x+ims_2,y-ims_2); pixmap_bbox.line_to(x+ims_2,y+ims_2); pixmap_bbox.line_to(x-ims_2,y+ims_2); r->m_rasterizer_aa.add_path(pixmap_bbox); mapserver::render_scanlines_aa(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_base, sa, sg); } else { //just copy the image at the correct location (we place the pixmap on //the nearest integer pixel to avoid blurring) r->m_renderer_base.blend_from(pf,0,MS_NINT(x-pixmap->width/2.),MS_NINT(y-pixmap->height/2.)); } return MS_SUCCESS; } int agg2RenderEllipseSymbol(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(image); mapserver::path_storage path; mapserver::ellipse ellipse(x,y,symbol->sizex*style->scale/2,symbol->sizey*style->scale/2); path.concat_path(ellipse); if( style->rotation != 0) { mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-x,-y); /*agg angles are antitrigonometric*/ mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x,y); path.transform(mtx); } if(style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_even_odd); r->m_rasterizer_aa.add_path(path); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if(style->outlinewidth) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_stroke stroke(path); stroke.width(style->outlinewidth); r->m_rasterizer_aa.add_path(stroke); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_scanline); } return MS_SUCCESS; } int agg2RenderTile(imageObj *img, imageObj *tile, double x, double y) { /* AGG2Renderer *imgRenderer = agg2GetRenderer(img); AGG2Renderer *tileRenderer = agg2GetRenderer(tile); */ return MS_FAILURE; } int aggInitializeRasterBuffer(rasterBufferObj *rb, int width, int height, int mode) { rb->type = MS_BUFFER_BYTE_RGBA; rb->data.rgba.pixel_step = 4; rb->data.rgba.row_step = rb->data.rgba.pixel_step * width; rb->width = width; rb->height = height; int nBytes = rb->data.rgba.row_step * height; rb->data.rgba.pixels = (band_type*)msSmallCalloc(nBytes,sizeof(band_type)); rb->data.rgba.r = &(rb->data.rgba.pixels[band_order::R]); rb->data.rgba.g = &(rb->data.rgba.pixels[band_order::G]); rb->data.rgba.b = &(rb->data.rgba.pixels[band_order::B]); if(mode == MS_IMAGEMODE_RGBA) { rb->data.rgba.a = &(rb->data.rgba.pixels[band_order::A]); } return MS_SUCCESS; } int aggGetRasterBufferHandle(imageObj *img, rasterBufferObj * rb) { AGG2Renderer *r = AGG_RENDERER(img); rb->type =MS_BUFFER_BYTE_RGBA; rb->data.rgba.pixels = r->buffer; rb->data.rgba.row_step = r->m_rendering_buffer.stride(); rb->data.rgba.pixel_step = 4; rb->width = r->m_rendering_buffer.width(); rb->height = r->m_rendering_buffer.height(); rb->data.rgba.r = &(r->buffer[band_order::R]); rb->data.rgba.g = &(r->buffer[band_order::G]); rb->data.rgba.b = &(r->buffer[band_order::B]); if(r->use_alpha) rb->data.rgba.a = &(r->buffer[band_order::A]); else rb->data.rgba.a = NULL; return MS_SUCCESS; } int aggGetRasterBufferCopy(imageObj *img, rasterBufferObj *rb) { AGG2Renderer *r = AGG_RENDERER(img); aggInitializeRasterBuffer(rb, img->width, img->height, MS_IMAGEMODE_RGBA); int nBytes = r->m_rendering_buffer.stride()*r->m_rendering_buffer.height(); memcpy(rb->data.rgba.pixels,r->buffer, nBytes); return MS_SUCCESS; } int agg2MergeRasterBuffer(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { assert(overlay->type == MS_BUFFER_BYTE_RGBA); rendering_buffer b(overlay->data.rgba.pixels, overlay->width, overlay->height, overlay->data.rgba.row_step); pixel_format pf(b); AGG2Renderer *r = AGG_RENDERER(dest); mapserver::rect_base src_rect(srcX,srcY,srcX+width,srcY+height); r->m_renderer_base.blend_from(pf,&src_rect, dstX-srcX, dstY-srcY, unsigned(opacity * 255)); return MS_SUCCESS; } /* image i/o */ imageObj *agg2CreateImage(int width, int height, outputFormatObj *format, colorObj * bg) { imageObj *image = NULL; if (format->imagemode != MS_IMAGEMODE_RGB && format->imagemode != MS_IMAGEMODE_RGBA) { msSetError(MS_MISCERR, "AGG2 driver only supports RGB or RGBA pixel models.", "agg2CreateImage()"); return image; } image = (imageObj *) calloc(1, sizeof (imageObj)); MS_CHECK_ALLOC(image, sizeof (imageObj), NULL); AGG2Renderer *r = new AGG2Renderer(); /* Compute size on 64bit and check that it is compatible of the platform size_t */ AGG_INT64U bufSize64 = (AGG_INT64U)width * height * 4 * sizeof(band_type); size_t bufSize = (size_t)bufSize64; if( (AGG_INT64U)bufSize != bufSize64 ) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating " AGG_INT64U_FRMT " bytes.\n", "agg2CreateImage()", __FILE__, __LINE__, bufSize64); free(image); delete r; return NULL; } r->buffer = (band_type*)malloc(bufSize); if (r->buffer == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating " AGG_INT64U_FRMT " bytes.\n", "agg2CreateImage()", __FILE__, __LINE__, bufSize64); free(image); delete r; return NULL; } r->m_rendering_buffer.attach(r->buffer, width, height, width * 4); r->m_pixel_format.attach(r->m_rendering_buffer); r->m_compop_pixel_format.attach(r->m_rendering_buffer); r->m_renderer_base.attach(r->m_pixel_format); r->m_compop_renderer_base.attach(r->m_compop_pixel_format); r->m_renderer_scanline.attach(r->m_renderer_base); r->default_gamma = atof(msGetOutputFormatOption( format, "GAMMA", "0.75" )); if(r->default_gamma <= 0.0 || r->default_gamma >= 1.0) { r->default_gamma = 0.75; } r->gamma_function.set(0,r->default_gamma); r->m_rasterizer_aa_gamma.gamma(r->gamma_function); if( bg && !format->transparent ) r->m_renderer_base.clear(aggColor(bg)); else r->m_renderer_base.clear(AGG_NO_COLOR); if (!bg || format->transparent || format->imagemode == MS_IMAGEMODE_RGBA ) { r->use_alpha = true; } else { r->use_alpha = false; } image->img.plugin = (void*) r; return image; } int agg2SaveImage(imageObj *img, mapObj* map, FILE *fp, outputFormatObj * format) { return MS_FAILURE; } int agg2StartNewLayer(imageObj *img, mapObj*map, layerObj *layer) { AGG2Renderer *r = AGG_RENDERER(img); char *sgamma = msLayerGetProcessingKey( layer, "GAMMA" ); double gamma; if(sgamma) { gamma = atof(sgamma); if(gamma <= 0 || gamma >= 1) gamma = 0.75; } else { gamma = r->default_gamma; } if(r->gamma_function.end() != gamma) { r->gamma_function.end(gamma); r->m_rasterizer_aa_gamma.gamma(r->gamma_function); } return MS_SUCCESS; } int agg2CloseNewLayer(imageObj *img, mapObj *map, layerObj *layer) { return MS_SUCCESS; } int agg2FreeImage(imageObj * image) { AGG2Renderer *r = AGG_RENDERER(image); free(r->buffer); delete r; image->img.plugin = NULL; return MS_SUCCESS; } int agg2FreeSymbol(symbolObj * symbol) { return MS_SUCCESS; } int agg2InitCache(void **vcache) { aggRendererCache *cache = new aggRendererCache(); *vcache = (void*)cache; return MS_SUCCESS; } int agg2Cleanup(void *vcache) { aggRendererCache *cache = (aggRendererCache*)vcache; delete cache; return MS_SUCCESS; } // ------------------------------------------------------------------------ // Function to create a custom hatch symbol based on an arbitrary angle. // ------------------------------------------------------------------------ static mapserver::path_storage createHatch(double ox, double oy, double rx, double ry, int sx, int sy, double angle, double step) { mapserver::path_storage path; //restrict the angle to [0 180[, i.e ]-pi/2,pi/2] in radians angle = fmod(angle, 360.0); if(angle < 0) angle += 360; if(angle >= 180) angle -= 180; //treat 2 easy cases which would cause divide by 0 in generic case if(angle==0) { double y0 = step-fmod(oy-ry,step); if((oy - ry) < 0) { y0 -= step; } for(double y=y0; y=0&&y<=sy) { pt[2*inter]=x; pt[2*inter+1]=y; inter++; } x=sx; y=(r-sx*ct)*invst;// test for intersection with right of image if(y>=0&&y<=sy) { pt[2*inter]=x; pt[2*inter+1]=y; inter++; } if(inter<2) { y=0; x=r*invct;// test for intersection with top of image if(x>=0&&x<=sx) { pt[2*inter]=x; pt[2*inter+1]=y; inter++; } } if(inter<2) { y=sy; x=(r-sy*st)*invct;// test for intersection with bottom of image if(x>=0&&x<=sx) { pt[2*inter]=x; pt[2*inter+1]=y; inter++; } } if(inter==2 && (pt[0]!=pt[2] || pt[1]!=pt[3])) { //the line intersects with two sides of the image, it should therefore be drawn if(angle<90) { path.move_to(pt[0],pt[1]); path.line_to(pt[2],pt[3]); } else { path.move_to(pt[0],sy-pt[1]); path.line_to(pt[2],sy-pt[3]); } } } return path; } template int renderPolygonHatches(imageObj *img,VertexSource &clipper, colorObj *color) { if(img->format->renderer == MS_RENDER_WITH_AGG) { AGG2Renderer *r = AGG_RENDERER(img); r->m_rasterizer_aa_gamma.reset(); r->m_rasterizer_aa_gamma.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa_gamma.add_path(clipper); r->m_renderer_scanline.color(aggColor(color)); mapserver::render_scanlines(r->m_rasterizer_aa_gamma, r->sl_poly, r->m_renderer_scanline); } else { shapeObj shape; msInitShape(&shape); int allocated = 20; lineObj line; shape.line = &line; shape.numlines = 1; shape.line[0].point = (pointObj*)msSmallCalloc(allocated,sizeof(pointObj)); shape.line[0].numpoints = 0; double x=0,y=0; unsigned int cmd; clipper.rewind(0); while((cmd = clipper.vertex(&x,&y)) != mapserver::path_cmd_stop) { switch(cmd) { case mapserver::path_cmd_line_to: if(shape.line[0].numpoints == allocated) { allocated *= 2; shape.line[0].point = (pointObj*)msSmallRealloc(shape.line[0].point, allocated*sizeof(pointObj)); } shape.line[0].point[shape.line[0].numpoints].x = x; shape.line[0].point[shape.line[0].numpoints].y = y; shape.line[0].numpoints++; break; case mapserver::path_cmd_move_to: shape.line[0].point[0].x = x; shape.line[0].point[0].y = y; shape.line[0].numpoints = 1; break; case mapserver::path_cmd_end_poly|mapserver::path_flags_close: if(shape.line[0].numpoints > 2) { if(UNLIKELY(MS_FAILURE == MS_IMAGE_RENDERER(img)->renderPolygon(img,&shape,color))) { free(shape.line[0].point); return MS_FAILURE; } } break; default: assert(0); //WTF? } } free(shape.line[0].point); } return MS_SUCCESS; } int msHatchPolygon(imageObj *img, shapeObj *poly, double spacing, double width, double *pattern, int patternlength, double angle, colorObj *color) { assert(MS_RENDERER_PLUGIN(img->format)); msComputeBounds(poly); /* amount we should expand the bounding box by */ double exp = width * 0.7072; /* width and height of the bounding box we will be creating the hatch in */ int pw=(int)(poly->bounds.maxx-poly->bounds.minx+exp*2)+1; int ph=(int)(poly->bounds.maxy-poly->bounds.miny+exp*2)+1; /* position of the top-left corner of the bounding box */ double ox = poly->bounds.minx - exp; double oy = poly->bounds.miny - exp; //create a rectangular hatch of size pw,ph starting at 0,0 //the created hatch is of the size of the shape's bounding box mapserver::path_storage hatch = createHatch(ox,oy, img->refpt.x,img->refpt.y,pw,ph,angle,spacing); if(hatch.total_vertices()<=0) return MS_SUCCESS; //translate the hatch so it overlaps the current shape hatch.transform(mapserver::trans_affine_translation(ox,oy)); polygon_adaptor polygons(poly); if(patternlength>1) { //dash the color-hatch and render it clipped by the shape mapserver::conv_dash dash(hatch); mapserver::conv_stroke > stroke(dash); for (int i=0; i > > clipper(polygons,stroke, mapserver::clipper_and); renderPolygonHatches(img,clipper,color); } else { //render the hatch clipped by the shape mapserver::conv_stroke stroke(hatch); stroke.width(width); stroke.line_cap(mapserver::butt_cap); mapserver::conv_clipper > clipper(polygons,stroke, mapserver::clipper_and); renderPolygonHatches(img,clipper,color); } //assert(prevCmd == mapserver::path_cmd_line_to); //delete lines; return MS_SUCCESS; } #ifdef USE_PIXMAN static pixman_op_t ms2pixman_compop(CompositingOperation c) { switch(c) { case MS_COMPOP_CLEAR: return PIXMAN_OP_CLEAR; case MS_COMPOP_SRC: return PIXMAN_OP_SRC; case MS_COMPOP_DST: return PIXMAN_OP_DST; case MS_COMPOP_SRC_OVER: return PIXMAN_OP_OVER; case MS_COMPOP_DST_OVER: return PIXMAN_OP_OVER_REVERSE; case MS_COMPOP_SRC_IN: return PIXMAN_OP_IN; case MS_COMPOP_DST_IN: return PIXMAN_OP_IN_REVERSE; case MS_COMPOP_SRC_OUT: return PIXMAN_OP_OUT; case MS_COMPOP_DST_OUT: return PIXMAN_OP_OUT_REVERSE; case MS_COMPOP_SRC_ATOP: return PIXMAN_OP_ATOP; case MS_COMPOP_DST_ATOP: return PIXMAN_OP_ATOP_REVERSE; case MS_COMPOP_XOR: return PIXMAN_OP_XOR; case MS_COMPOP_PLUS: return PIXMAN_OP_ADD; case MS_COMPOP_MULTIPLY: return PIXMAN_OP_MULTIPLY; case MS_COMPOP_SCREEN: return PIXMAN_OP_SCREEN; case MS_COMPOP_OVERLAY: return PIXMAN_OP_OVERLAY; case MS_COMPOP_DARKEN: return PIXMAN_OP_DARKEN; case MS_COMPOP_LIGHTEN: return PIXMAN_OP_LIGHTEN; case MS_COMPOP_COLOR_DODGE: return PIXMAN_OP_COLOR_DODGE; case MS_COMPOP_COLOR_BURN: return PIXMAN_OP_COLOR_DODGE; case MS_COMPOP_HARD_LIGHT: return PIXMAN_OP_HARD_LIGHT; case MS_COMPOP_SOFT_LIGHT: return PIXMAN_OP_SOFT_LIGHT; case MS_COMPOP_DIFFERENCE: return PIXMAN_OP_DIFFERENCE; case MS_COMPOP_EXCLUSION: return PIXMAN_OP_EXCLUSION; case MS_COMPOP_INVERT: case MS_COMPOP_INVERT_RGB: case MS_COMPOP_MINUS: case MS_COMPOP_CONTRAST: default: return PIXMAN_OP_OVER; } } #else static mapserver::comp_op_e ms2agg_compop(CompositingOperation c) { switch(c) { case MS_COMPOP_CLEAR: return mapserver::comp_op_clear; case MS_COMPOP_SRC: return mapserver::comp_op_src; case MS_COMPOP_DST: return mapserver::comp_op_dst; case MS_COMPOP_SRC_OVER: return mapserver::comp_op_src_over; case MS_COMPOP_DST_OVER: return mapserver::comp_op_dst_over; case MS_COMPOP_SRC_IN: return mapserver::comp_op_src_in; case MS_COMPOP_DST_IN: return mapserver::comp_op_dst_in; case MS_COMPOP_SRC_OUT: return mapserver::comp_op_src_out; case MS_COMPOP_DST_OUT: return mapserver::comp_op_dst_out; case MS_COMPOP_SRC_ATOP: return mapserver::comp_op_src_atop; case MS_COMPOP_DST_ATOP: return mapserver::comp_op_dst_atop; case MS_COMPOP_XOR: return mapserver::comp_op_xor; case MS_COMPOP_PLUS: return mapserver::comp_op_plus; case MS_COMPOP_MINUS: return mapserver::comp_op_minus; case MS_COMPOP_MULTIPLY: return mapserver::comp_op_multiply; case MS_COMPOP_SCREEN: return mapserver::comp_op_screen; case MS_COMPOP_OVERLAY: return mapserver::comp_op_overlay; case MS_COMPOP_DARKEN: return mapserver::comp_op_darken; case MS_COMPOP_LIGHTEN: return mapserver::comp_op_lighten; case MS_COMPOP_COLOR_DODGE: return mapserver::comp_op_color_dodge; case MS_COMPOP_COLOR_BURN: return mapserver::comp_op_color_burn; case MS_COMPOP_HARD_LIGHT: return mapserver::comp_op_hard_light; case MS_COMPOP_SOFT_LIGHT: return mapserver::comp_op_soft_light; case MS_COMPOP_DIFFERENCE: return mapserver::comp_op_difference; case MS_COMPOP_EXCLUSION: return mapserver::comp_op_exclusion; case MS_COMPOP_CONTRAST: return mapserver::comp_op_contrast; case MS_COMPOP_INVERT: return mapserver::comp_op_invert; case MS_COMPOP_INVERT_RGB: return mapserver::comp_op_invert_rgb; default: return mapserver::comp_op_src_over; } } #endif int aggCompositeRasterBuffer(imageObj *dest, rasterBufferObj *overlay, CompositingOperation comp, int opacity) { assert(overlay->type == MS_BUFFER_BYTE_RGBA); AGG2Renderer *r = AGG_RENDERER(dest); #ifdef USE_PIXMAN pixman_image_t *si = pixman_image_create_bits(PIXMAN_a8r8g8b8,overlay->width,overlay->height, (uint32_t*)overlay->data.rgba.pixels,overlay->data.rgba.row_step); pixman_image_t *bi = pixman_image_create_bits(PIXMAN_a8r8g8b8,dest->width,dest->height, (uint32_t*)r->buffer,dest->width*4); pixman_image_t *alpha_mask_i=NULL, *alpha_mask_i_ptr; pixman_image_set_filter(si,PIXMAN_FILTER_NEAREST, NULL, 0); unsigned char *alpha_mask = NULL; if(opacity > 0) { if(opacity == 100) { alpha_mask_i_ptr = NULL; } else { unsigned char alpha = (unsigned char)(opacity * 2.55); if(!alpha_mask_i) { alpha_mask = (unsigned char*)msSmallMalloc(dest->width * dest->height); alpha_mask_i = pixman_image_create_bits(PIXMAN_a8,dest->width,dest->height, (uint32_t*)alpha_mask,dest->width); } memset(alpha_mask,alpha,dest->width*dest->height); alpha_mask_i_ptr = alpha_mask_i; } pixman_image_composite (ms2pixman_compop(comp), si, alpha_mask_i_ptr, bi, 0, 0, 0, 0, 0, 0, dest->width,dest->height); } pixman_image_unref(si); pixman_image_unref(bi); if(alpha_mask_i) { pixman_image_unref(alpha_mask_i); msFree(alpha_mask); } return MS_SUCCESS; #else rendering_buffer b(overlay->data.rgba.pixels, overlay->width, overlay->height, overlay->data.rgba.row_step); pixel_format pf(b); mapserver::comp_op_e comp_op = ms2agg_compop(comp); if(comp_op == mapserver::comp_op_src_over) { r->m_renderer_base.blend_from(pf,0,0,0,unsigned(opacity * 2.55)); } else { compop_pixel_format pixf(r->m_rendering_buffer); compop_renderer_base ren(pixf); pixf.comp_op(comp_op); ren.blend_from(pf,0,0,0,unsigned(opacity * 2.55)); } return MS_SUCCESS; #endif } void msApplyBlurringCompositingFilter(rasterBufferObj *rb, unsigned int radius) { rendering_buffer b(rb->data.rgba.pixels, rb->width, rb->height, rb->data.rgba.row_step); pixel_format pf(b); mapserver::stack_blur_rgba32(pf,radius,radius); } int msPopulateRendererVTableAGG(rendererVTableObj * renderer) { renderer->compositeRasterBuffer = &aggCompositeRasterBuffer; renderer->supports_pixel_buffer = 1; renderer->use_imagecache = 0; renderer->supports_clipping = 0; renderer->supports_svg = 0; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; agg2InitCache(&(MS_RENDERER_CACHE(renderer))); renderer->cleanup = agg2Cleanup; renderer->renderLine = &agg2RenderLine; renderer->renderPolygon = &agg2RenderPolygon; renderer->renderPolygonTiled = &agg2RenderPolygonTiled; renderer->renderLineTiled = &agg2RenderLineTiled; renderer->renderGlyphs = &agg2RenderGlyphsPath; renderer->renderVectorSymbol = &agg2RenderVectorSymbol; renderer->renderPixmapSymbol = &agg2RenderPixmapSymbol; renderer->renderEllipseSymbol = &agg2RenderEllipseSymbol; renderer->renderTile = &agg2RenderTile; renderer->getRasterBufferHandle = &aggGetRasterBufferHandle; renderer->getRasterBufferCopy = aggGetRasterBufferCopy; renderer->initializeRasterBuffer = aggInitializeRasterBuffer; renderer->mergeRasterBuffer = &agg2MergeRasterBuffer; renderer->loadImageFromFile = msLoadMSRasterBufferFromFile; renderer->createImage = &agg2CreateImage; renderer->saveImage = &agg2SaveImage; renderer->startLayer = &agg2StartNewLayer; renderer->endLayer = &agg2CloseNewLayer; renderer->freeImage = &agg2FreeImage; renderer->freeSymbol = &agg2FreeSymbol; renderer->cleanup = agg2Cleanup; return MS_SUCCESS; } mapserver-7.4.3/mapagg.h000066400000000000000000000140531357574274700151660ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: AGG template library types. * Author: John Novak (jnovak@novacell.com) * Author: Thomas Bonfort (tbonfort@terriscope.fr) * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ******************************************************************************/ #include "renderers/agg/include/agg_path_storage.h" /* * interface to a shapeObj representing lines, providing the functions * needed by the agg rasterizer. treats shapeObjs with multiple linestrings. */ class line_adaptor { public: line_adaptor(shapeObj *shape):s(shape) { m_line=s->line; /*first line*/ m_point=m_line->point; /*current vertex is first vertex of first line*/ m_lend=&(s->line[s->numlines]); /*pointer to after last line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } /* a class with virtual functions should also provide a virtual destructor */ virtual ~line_adaptor() {} void rewind(unsigned) { m_line=s->line; /*first line*/ m_point=m_line->point; /*current vertex is first vertex of first line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } virtual unsigned vertex(double* x, double* y) { if(m_point < m_pend) { /*here we treat the case where a real vertex is returned*/ bool first = m_point == m_line->point; /*is this the first vertex of a line*/ *x = m_point->x; *y = m_point->y; m_point++; return first ? mapserver::path_cmd_move_to : mapserver::path_cmd_line_to; } /*if here, we're at the end of a line*/ m_line++; *x = *y = 0.0; if(m_line>=m_lend) /*is this the last line of the shapObj. normally, (m_line==m_lend) should be a sufficient test, as the caller should not call this function if a previous call returned path_cmd_stop.*/ return mapserver::path_cmd_stop; /*no more points to process*/ /*if here, there are more lines in the shapeObj, continue with next one*/ m_point=m_line->point; /*pointer to first point of next line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last point of next line*/ return vertex(x,y); /*this will return the first point of the next line*/ } protected: shapeObj *s; lineObj *m_line, /*current line pointer*/ *m_lend; /*points to after the last line*/ pointObj *m_point, /*current point*/ *m_pend; /*points to after last point of current line*/ }; class polygon_adaptor { public: polygon_adaptor(shapeObj *shape):s(shape),m_stop(false) { m_line=s->line; /*first lines*/ m_point=m_line->point; /*first vertex of first line*/ m_lend=&(s->line[s->numlines]); /*pointer to after last line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of first line*/ } /* a class with virtual functions should also provide a virtual destructor */ virtual ~polygon_adaptor() {} void rewind(unsigned) { /*reset pointers*/ m_stop=false; m_line=s->line; m_point=m_line->point; m_pend=&(m_line->point[m_line->numpoints]); } virtual unsigned vertex(double* x, double* y) { if(m_point < m_pend) { /*if here, we have a real vertex*/ bool first = m_point == m_line->point; *x = m_point->x; *y = m_point->y; m_point++; return first ? mapserver::path_cmd_move_to : mapserver::path_cmd_line_to; } *x = *y = 0.0; if(!m_stop) { /*if here, we're after the last vertex of the current line * we return the command to close the current polygon*/ m_line++; if(m_line>=m_lend) { /*if here, we've finished all the vertexes of the shape. * we still return the command to close the current polygon, * but set m_stop so the subsequent call to vertex() will return * the stop command*/ m_stop=true; return mapserver::path_cmd_end_poly; } /*if here, there's another line in the shape, so we set the pointers accordingly * and return the command to close the current polygon*/ m_point=m_line->point; /*first vertex of next line*/ m_pend=&(m_line->point[m_line->numpoints]); /*pointer to after last vertex of next line*/ return mapserver::path_cmd_end_poly; } /*if here, a previous call to vertex informed us that we'd consumed all the vertexes * of the shape. return the command to stop processing this shape*/ return mapserver::path_cmd_stop; } protected: shapeObj *s; double ox,oy; lineObj *m_line, /*pointer to current line*/ *m_lend; /*pointer to after last line of the shape*/ pointObj *m_point, /*pointer to current vertex*/ *m_pend; /*pointer to after last vertex of current line*/ bool m_stop; /*should next call return stop command*/ }; mapserver::path_storage imageVectorSymbol(symbolObj *); mapserver-7.4.3/mapaxisorder.h000066400000000000000000011732421357574274700164370ustar00rootroot00000000000000/****************************************************************************** * $Id: $ * * Project: MapServer * Purpose: Axis lookup table * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* * Generated file * * This file was generated from by means of a script. Do not edit manually. */ #ifdef __cplusplus extern "C" { #endif static unsigned char axisOrientationEpsgCodes[] = { 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 1 << 6 | 1 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 1 << 2 | 1 << 1 | 1 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0, 0 << 7 | 0 << 6 | 0 << 5 | 0 << 4 | 0 << 3 | 0 << 2 | 0 << 1 | 0 << 0 }; #ifdef __cplusplus } #endif mapserver-7.4.3/mapbits.c000066400000000000000000000072761357574274700153750ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of bit array functions. * Author: Steve Lime and the MapServer team. * * Notes: Derived from code placed in the public domain by Bob Stout, for more * information see http://c.snippets.org/snip_lister.php?fname=bitarray.c. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include /* * Hardcoded size of our bit array. * See function msGetNextBit for another hardcoded value. */ /* #define msGetBit(array, index) (*((array) + (index)/MS_ARRAY_BIT) & ( 1 << ((index) % MS_ARRAY_BIT))) */ size_t msGetBitArraySize(int numbits) { return((numbits + MS_ARRAY_BIT - 1) / MS_ARRAY_BIT); } ms_bitarray msAllocBitArray(int numbits) { ms_bitarray array = calloc((numbits + MS_ARRAY_BIT - 1) / MS_ARRAY_BIT, MS_ARRAY_BIT); return(array); } int msGetBit(ms_const_bitarray array, int index) { array += index / MS_ARRAY_BIT; return (*array & (1 << (index % MS_ARRAY_BIT))) != 0; /* 0 or 1 */ } /* ** msGetNextBit( status, start, size) ** ** Quickly find the next bit set. If start == 0 and 0 is set, will return 0. ** If hits end of bitmap without finding set bit, will return -1. ** */ int msGetNextBit(ms_const_bitarray array, int i, int size) { register ms_uint32 b; while(i < size) { b = *(array + (i/MS_ARRAY_BIT)); if( b && (b >> (i % MS_ARRAY_BIT)) ) { /* There is something in this byte */ /* And it is not to the right of us */ if( b & ( 1 << (i % MS_ARRAY_BIT)) ) { /* There is something at this bit! */ return i; } else { i++; } } else { /* Nothing in this byte, move to start of next byte */ i += MS_ARRAY_BIT - (i % MS_ARRAY_BIT); } } /* Got to the last byte with no hits! */ return -1; } void msSetBit(ms_bitarray array, int index, int value) { array += index / MS_ARRAY_BIT; if (value) *array |= 1 << (index % MS_ARRAY_BIT); /* set bit */ else *array &= ~(1 << (index % MS_ARRAY_BIT)); /* clear bit */ } void msSetAllBits(ms_bitarray array, int numbits, int value) { if (value) memset(array, 0xff, ((numbits + 7) / 8) ); /* set bit */ else memset(array, 0x0, ((numbits + 7) / 8) ); /* clear bit */ } void msFlipBit(ms_bitarray array, int index) { array += index / MS_ARRAY_BIT; *array ^= 1 << (index % MS_ARRAY_BIT); /* flip bit */ } mapserver-7.4.3/mapcairo.c000066400000000000000000001102301357574274700155120ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Cairo Rendering functions * Author: Thomas Bonfort * ****************************************************************************** * Copyright (c) 1996-2009 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #ifdef USE_CAIRO #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #else #include #include #endif #ifdef USE_SVG_CAIRO #include #else #ifdef USE_RSVG #include #ifndef LIBRSVG_CHECK_VERSION #include #endif #ifndef RSVG_CAIRO_H #include #endif #include #endif #endif #ifdef USE_GDAL #include #include #endif #include "fontcache.h" # include /* #include #include */ #include /* #include #include FT_FREETYPE_H */ typedef struct cairoFaceCache cairoFaceCache; struct cairoFaceCache { cairo_font_face_t *face; FT_Face ftface; cairo_font_options_t *options; cairoFaceCache *next; }; void freeCairoFaceCache(cairoFaceCache *fc) { cairo_font_face_destroy(fc->face); cairo_font_options_destroy(fc->options); } typedef struct { cairoFaceCache *cairofacecache; /* dummy surface and context */ unsigned char dummydata[4]; cairo_surface_t *dummysurface; cairo_t *dummycr; } cairoCacheData; void initializeCache(void **vcache) { cairoCacheData *cache = (cairoCacheData*)malloc(sizeof(cairoCacheData)); *vcache = cache; cache->cairofacecache = NULL; /* dummy surface and context */ cache->dummysurface = cairo_image_surface_create_for_data(cache->dummydata, CAIRO_FORMAT_ARGB32, 1,1,4); cache->dummycr = cairo_create(cache->dummysurface); } int cleanupCairo(void *cache) { cairoCacheData *ccache = (cairoCacheData*)cache; if(ccache->dummycr) { cairo_destroy(ccache->dummycr); } if(ccache->dummysurface) { cairo_surface_destroy(ccache->dummysurface); } if(ccache->cairofacecache) { cairoFaceCache *next,*cur; cur = ccache->cairofacecache; do { next = cur->next; freeCairoFaceCache(cur); free(cur); cur=next; } while(cur); } free(ccache); return MS_SUCCESS; } typedef struct { cairo_surface_t *surface; cairo_t *cr; bufferObj *outputStream; int use_alpha; } cairo_renderer; #define CAIRO_RENDERER(im) ((cairo_renderer*)(im->img.plugin)) int freeImageCairo(imageObj *img) { cairo_renderer *r = CAIRO_RENDERER(img); if(r) { cairo_destroy(r->cr); cairo_surface_finish(r->surface); cairo_surface_destroy(r->surface); if(r->outputStream) { msBufferFree(r->outputStream); free(r->outputStream); } free(r); } return MS_SUCCESS; } static cairoFaceCache* getCairoFontFace(cairoCacheData *cache, FT_Face ftface) { cairoFaceCache *cur = cache->cairofacecache; while(cur) { if(cur->ftface == ftface) return cur; cur = cur->next; } cur = msSmallMalloc(sizeof(cairoFaceCache)); cur->next = cache->cairofacecache; cache->cairofacecache = cur; cur->ftface = ftface; cur->face = cairo_ft_font_face_create_for_ft_face(ftface, 0); cur->options = cairo_font_options_create(); cairo_font_options_set_hint_style(cur->options,CAIRO_HINT_STYLE_NONE); return cur; } #define msCairoSetSourceColor(cr, c) cairo_set_source_rgba((cr),(c)->red/255.0,(c)->green/255.0,(c)->blue/255.0,(c)->alpha/255.0); int renderLineCairo(imageObj *img, shapeObj *p, strokeStyleObj *stroke) { int i,j; cairo_renderer *r = CAIRO_RENDERER(img); assert(stroke->color); cairo_new_path(r->cr); msCairoSetSourceColor(r->cr,stroke->color); for(i=0; inumlines; i++) { lineObj *l = &(p->line[i]); if(l->numpoints == 0) continue; cairo_move_to(r->cr,l->point[0].x,l->point[0].y); for(j=1; jnumpoints; j++) { cairo_line_to(r->cr,l->point[j].x,l->point[j].y); } } if(stroke->patternlength>0) { cairo_set_dash(r->cr,stroke->pattern,stroke->patternlength,-stroke->patternoffset); } switch(stroke->linecap) { case MS_CJC_BUTT: cairo_set_line_cap(r->cr,CAIRO_LINE_CAP_BUTT); break; case MS_CJC_SQUARE: cairo_set_line_cap(r->cr,CAIRO_LINE_CAP_SQUARE); break; case MS_CJC_ROUND: case MS_CJC_NONE: default: cairo_set_line_cap(r->cr,CAIRO_LINE_CAP_ROUND); } cairo_set_line_width (r->cr, stroke->width); cairo_stroke (r->cr); if(stroke->patternlength>0) { cairo_set_dash(r->cr,stroke->pattern,0,0); } return MS_SUCCESS; } int renderPolygonCairo(imageObj *img, shapeObj *p, colorObj *c) { cairo_renderer *r = CAIRO_RENDERER(img); int i,j; cairo_new_path(r->cr); cairo_set_fill_rule(r->cr,CAIRO_FILL_RULE_EVEN_ODD); msCairoSetSourceColor(r->cr,c); for(i=0; inumlines; i++) { lineObj *l = &(p->line[i]); cairo_move_to(r->cr,l->point[0].x,l->point[0].y); for(j=1; jnumpoints; j++) { cairo_line_to(r->cr,l->point[j].x,l->point[j].y); } cairo_close_path(r->cr); } cairo_fill(r->cr); return MS_SUCCESS; } int renderPolygonTiledCairo(imageObj *img, shapeObj *p, imageObj *tile) { int i,j; cairo_renderer *r = CAIRO_RENDERER(img); cairo_renderer *tileRenderer = CAIRO_RENDERER(tile); cairo_pattern_t *pattern = cairo_pattern_create_for_surface(tileRenderer->surface); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_set_source(r->cr, pattern); for (i = 0; i < p->numlines; i++) { lineObj *l = &(p->line[i]); cairo_move_to(r->cr, l->point[0].x, l->point[0].y); for (j = 1; j < l->numpoints; j++) { cairo_line_to(r->cr, l->point[j].x, l->point[j].y); } /* cairo_close_path(r->cr); */ } cairo_fill(r->cr); cairo_pattern_destroy(pattern); return MS_SUCCESS; } cairo_surface_t *createSurfaceFromBuffer(rasterBufferObj *b) { assert(b->type == MS_BUFFER_BYTE_RGBA); return cairo_image_surface_create_for_data (b->data.rgba.pixels, CAIRO_FORMAT_ARGB32, b->width, b->height, b->data.rgba.row_step); } int renderPixmapSymbolCairo(imageObj *img, double x, double y,symbolObj *symbol, symbolStyleObj *style) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_surface_t *im; rasterBufferObj *b = symbol->pixmap_buffer; assert(b); if(!symbol->renderer_cache) { symbol->renderer_cache = (void*)createSurfaceFromBuffer(b); } assert(symbol->renderer_cache); im=(cairo_surface_t*)symbol->renderer_cache; cairo_save(r->cr); if(style->rotation != 0 || style->scale != 1) { cairo_translate (r->cr, x,y); cairo_rotate (r->cr, -style->rotation); cairo_scale (r->cr, style->scale,style->scale); cairo_translate (r->cr, -0.5*b->width, -0.5*b->height); } else { cairo_translate (r->cr, MS_NINT(x-0.5*b->width),MS_NINT(y-0.5*b->height)); } cairo_set_source_surface (r->cr, im, 0, 0); cairo_paint (r->cr); cairo_restore(r->cr); return MS_SUCCESS; } int renderVectorSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { cairo_renderer *r = CAIRO_RENDERER(img); double ox=symbol->sizex*0.5,oy=symbol->sizey*0.5; int is_new = 1,i; cairo_new_path(r->cr); cairo_save(r->cr); cairo_translate(r->cr,x,y); cairo_scale(r->cr,style->scale,style->scale); cairo_rotate(r->cr,-style->rotation); cairo_translate(r->cr,-ox,-oy); for (i = 0; i < symbol->numpoints; i++) { if ((symbol->points[i].x == -99) && (symbol->points[i].y == -99)) { /* (PENUP) */ is_new = 1; } else { if (is_new) { cairo_move_to(r->cr,symbol->points[i].x,symbol->points[i].y); is_new = 0; } else { cairo_line_to(r->cr,symbol->points[i].x,symbol->points[i].y); } } } cairo_restore(r->cr); if(style->color) { msCairoSetSourceColor(r->cr,style->color); cairo_fill_preserve(r->cr); } if(style->outlinewidth>0) { msCairoSetSourceColor(r->cr,style->outlinecolor); cairo_set_line_width (r->cr, style->outlinewidth); cairo_stroke_preserve(r->cr); } cairo_new_path(r->cr); return MS_SUCCESS; } #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache { rasterBufferObj *pixmap_buffer; #ifdef USE_RSVG RsvgHandle *svgc; #else svg_cairo_t *svgc; #endif double scale,rotation; } ; #endif int renderSVGSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *cache; cairo_renderer *r = CAIRO_RENDERER(img); msPreloadSVGSymbol(symbol); assert(symbol->renderer_cache); cache = symbol->renderer_cache; cairo_save(r->cr); cairo_translate(r->cr,x,y); cairo_scale(r->cr,style->scale,style->scale); if (style->rotation != 0) { cairo_rotate(r->cr, -style->rotation); cairo_translate (r->cr, -(int)(symbol->sizex/2), -(int)(symbol->sizey/2)); } else cairo_translate (r->cr, -(int)(symbol->sizex/2), -(int)(symbol->sizey/2)); #ifdef USE_SVG_CAIRO { svg_cairo_status_t status; status = svg_cairo_render(cache->svgc, r->cr); if(status != SVG_CAIRO_STATUS_SUCCESS) { cairo_restore(r->cr); return MS_FAILURE; } } #else rsvg_handle_render_cairo(cache->svgc, r->cr); #endif cairo_restore(r->cr); return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but is not built with libsvgcairo", "renderSVGSymbolCairo()"); return MS_FAILURE; #endif } int renderTileCairo(imageObj *img, imageObj *tile, double x, double y) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_surface_t *im = CAIRO_RENDERER(tile)->surface; int w = cairo_image_surface_get_width (im); int h = cairo_image_surface_get_height (im); cairo_save(r->cr); cairo_translate(r->cr, MS_NINT(x-0.5 * w), MS_NINT(y -0.5 * h)); cairo_set_source_surface(r->cr, im, 0, 0); cairo_pattern_set_filter (cairo_get_source (r->cr), CAIRO_FILTER_NEAREST); cairo_paint(r->cr); cairo_restore(r->cr); return MS_SUCCESS; } int renderGlyphs2Cairo(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow) { cairo_renderer *r = CAIRO_RENDERER(img); cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img); cairoFaceCache *cairo_face = NULL; FT_Face prevface = NULL; int g; cairo_set_font_size(r->cr,MS_NINT(tp->glyph_size * 96.0/72.0)); for(g=0;gnumglyphs;g++) { glyphObj *gl = &tp->glyphs[g]; cairo_glyph_t glyph; /* load the glyph's face into cairo, if not already present */ if(gl->face->face != prevface) { cairo_face = getCairoFontFace(cache,gl->face->face); cairo_set_font_face(r->cr, cairo_face->face); cairo_set_font_options(r->cr,cairo_face->options); prevface = gl->face->face; cairo_set_font_size(r->cr,MS_NINT(tp->glyph_size * 96.0/72.0)); } cairo_save(r->cr); cairo_translate(r->cr,gl->pnt.x,gl->pnt.y); if(gl->rot != 0.0) cairo_rotate(r->cr, -gl->rot); glyph.x = glyph.y = 0; glyph.index = gl->glyph->key.codepoint; cairo_glyph_path(r->cr,&glyph,1); cairo_restore(r->cr); } if (oc) { cairo_save(r->cr); msCairoSetSourceColor(r->cr, oc); cairo_set_line_width(r->cr, ow + 1); cairo_stroke_preserve(r->cr); cairo_restore(r->cr); } if(c) { msCairoSetSourceColor(r->cr, c); cairo_fill(r->cr); } cairo_new_path(r->cr); return MS_SUCCESS; } cairo_status_t _stream_write_fn(void *b, const unsigned char *data, unsigned int length) { msBufferAppend((bufferObj*)b,(void*)data,length); return CAIRO_STATUS_SUCCESS; } imageObj* createImageCairo(int width, int height, outputFormatObj *format,colorObj* bg) { imageObj *image = NULL; cairo_renderer *r=NULL; if (format->imagemode != MS_IMAGEMODE_RGB && format->imagemode!= MS_IMAGEMODE_RGBA) { msSetError(MS_MISCERR, "Cairo driver only supports RGB or RGBA pixel models.","msImageCreateCairo()"); return image; } if (width > 0 && height > 0) { image = (imageObj *) calloc(1, sizeof(imageObj)); r = (cairo_renderer*)calloc(1,sizeof(cairo_renderer)); if(!strcasecmp(format->driver,"cairo/pdf")) { r->outputStream = (bufferObj*)malloc(sizeof(bufferObj)); msBufferInit(r->outputStream); r->surface = cairo_pdf_surface_create_for_stream( _stream_write_fn, r->outputStream, width,height); } else if(!strcasecmp(format->driver,"cairo/svg")) { r->outputStream = (bufferObj*)malloc(sizeof(bufferObj)); msBufferInit(r->outputStream); r->surface = cairo_svg_surface_create_for_stream( _stream_write_fn, r->outputStream, width,height); } else if(!strcasecmp(format->driver,"cairo/winGDI") && format->device) { #if CAIRO_HAS_WIN32_SURFACE r->outputStream = NULL; r->surface = cairo_win32_surface_create(format->device); #else msSetError(MS_RENDERERERR, "Cannot create cairo image. Cairo was not compiled with support for the win32 backend.", "msImageCreateCairo()"); #endif } else if(!strcasecmp(format->driver,"cairo/winGDIPrint") && format->device) { #if CAIRO_HAS_WIN32_SURFACE r->outputStream = NULL; r->surface = cairo_win32_printing_surface_create(format->device); #else msSetError(MS_RENDERERERR, "Cannot create cairo image. Cairo was not compiled with support for the win32 backend.", "msImageCreateCairo()"); #endif } else { r->outputStream = NULL; r->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); } r->cr = cairo_create(r->surface); if(format->transparent || !bg || !MS_VALID_COLOR(*bg)) { r->use_alpha = 1; cairo_set_source_rgba (r->cr, 0,0,0,0); } else { r->use_alpha = 0; msCairoSetSourceColor(r->cr,bg); } cairo_save (r->cr); cairo_set_operator (r->cr, CAIRO_OPERATOR_SOURCE); cairo_paint (r->cr); cairo_restore (r->cr); cairo_set_line_cap (r->cr,CAIRO_LINE_CAP_ROUND); cairo_set_line_join(r->cr,CAIRO_LINE_JOIN_ROUND); image->img.plugin = (void*)r; } else { msSetError(MS_RENDERERERR, "Cannot create cairo image of size %dx%d.", "msImageCreateCairo()", width, height); } return image; } /* msSaveImagePostPDFProcessing() will call the GDAL PDF driver to add geospatial */ /* information to the regular PDF generated by cairo. This is only triggered if the */ /* GEO_ENCODING outputformat option is set (to ISO32000 or OGC_BP). Additionnal */ /* options can be provided by specifying outputformat options starting with */ /* METADATA_ITEM: prefix. For example METADATA_ITEM:PRODUCER=MapServer */ /* Those options are AUTHOR, CREATOR, CREATION_DATE, KEYWORDS, PRODUCER, SUBJECT, TITLE */ /* See http://gdal.org/frmt_pdf.html documentation. */ static void msTransformToGeospatialPDF(imageObj *img, mapObj *map, cairo_renderer *r) { /* We need a GDAL 1.10 PDF driver at runtime, but as far as the C API is concerned, GDAL 1.9 is */ /* largely sufficient. */ #if defined(USE_GDAL) && defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900 GDALDatasetH hDS = NULL; const char* pszGEO_ENCODING = NULL; GDALDriverH hPDFDriver = NULL; const char* pszVirtualIO = NULL; int bVirtualIO = FALSE; char* pszTmpFilename = NULL; VSILFILE* fp = NULL; if (map == NULL) return; pszGEO_ENCODING = msGetOutputFormatOption(img->format, "GEO_ENCODING", NULL); if (pszGEO_ENCODING == NULL) return; msGDALInitialize(); hPDFDriver = GDALGetDriverByName("PDF"); if (hPDFDriver == NULL) return; /* When compiled against libpoppler, the PDF driver is VirtualIO capable */ /* but not, when it is compiled against libpodofo. */ pszVirtualIO = GDALGetMetadataItem( hPDFDriver, GDAL_DCAP_VIRTUALIO, NULL ); if (pszVirtualIO) bVirtualIO = CSLTestBoolean(pszVirtualIO); if (bVirtualIO) pszTmpFilename = msTmpFile(map, NULL, "/vsimem/mscairopdf/", "pdf"); else pszTmpFilename = msTmpFile(map, map->mappath, NULL, "pdf"); /* Copy content of outputStream buffer into file */ fp = VSIFOpenL(pszTmpFilename, "wb"); if (fp == NULL) { msFree(pszTmpFilename); return; } VSIFWriteL(r->outputStream->data, 1, r->outputStream->size, fp); VSIFCloseL(fp); fp = NULL; hDS = GDALOpen(pszTmpFilename, GA_Update); if ( hDS != NULL ) { char* pszWKT = msProjectionObj2OGCWKT( &(map->projection) ); if( pszWKT != NULL ) { double adfGeoTransform[6]; int i; /* Add user-specified options */ for( i = 0; i < img->format->numformatoptions; i++ ) { const char* pszOption = img->format->formatoptions[i]; if( strncasecmp(pszOption,"METADATA_ITEM:",14) == 0 ) { char* pszKey = NULL; const char* pszValue = CPLParseNameValue(pszOption + 14, &pszKey); if( pszKey != NULL ) { GDALSetMetadataItem(hDS, pszKey, pszValue, NULL); CPLFree(pszKey); } } } /* We need to rescale the geotransform because GDAL will not necessary */ /* open the PDF with the DPI that was used to generate it */ memcpy(adfGeoTransform, map->gt.geotransform, 6 * sizeof(double)); adfGeoTransform[1] = adfGeoTransform[1] * map->width / GDALGetRasterXSize(hDS); adfGeoTransform[5] = adfGeoTransform[5] * map->height / GDALGetRasterYSize(hDS); GDALSetGeoTransform(hDS, adfGeoTransform); GDALSetProjection(hDS, pszWKT); msFree( pszWKT ); pszWKT = NULL; CPLSetThreadLocalConfigOption("GDAL_PDF_GEO_ENCODING", pszGEO_ENCODING); GDALClose(hDS); hDS = NULL; CPLSetThreadLocalConfigOption("GDAL_PDF_GEO_ENCODING", NULL); /* We need to replace the buffer with the content of the GDAL file */ fp = VSIFOpenL(pszTmpFilename, "rb"); if( fp != NULL ) { int nFileSize; VSIFSeekL(fp, 0, SEEK_END); nFileSize = (int)VSIFTellL(fp); msBufferResize(r->outputStream, nFileSize); VSIFSeekL(fp, 0, SEEK_SET); r->outputStream->size = VSIFReadL(r->outputStream->data, 1, nFileSize, fp); VSIFCloseL(fp); fp = NULL; } } } if ( hDS != NULL ) GDALClose(hDS); VSIUnlink(pszTmpFilename); msFree(pszTmpFilename); #endif } int saveImageCairo(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { cairo_renderer *r = CAIRO_RENDERER(img); if(!strcasecmp(img->format->driver,"cairo/pdf") || !strcasecmp(img->format->driver,"cairo/svg")) { cairo_surface_finish (r->surface); if (map != NULL && !strcasecmp(img->format->driver,"cairo/pdf")) msTransformToGeospatialPDF(img, map, r); msIO_fwrite(r->outputStream->data,r->outputStream->size,1,fp); } else { /* not supported */ } return MS_SUCCESS; } unsigned char* saveImageBufferCairo(imageObj *img, int *size_ptr, outputFormatObj *format) { cairo_renderer *r = CAIRO_RENDERER(img); unsigned char *data; assert(!strcasecmp(img->format->driver,"cairo/pdf") || !strcasecmp(img->format->driver,"cairo/svg")); cairo_surface_finish (r->surface); data = msSmallMalloc(r->outputStream->size); memcpy(data,r->outputStream->data,r->outputStream->size); *size_ptr = (int)r->outputStream->size; return data; } int renderEllipseSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_save(r->cr); cairo_set_line_cap(r->cr, CAIRO_LINE_CAP_BUTT); cairo_set_line_join(r->cr, CAIRO_LINE_JOIN_MITER); cairo_translate(r->cr,x,y); cairo_rotate(r->cr,-style->rotation); cairo_scale(r->cr,symbol->sizex*style->scale/2,symbol->sizey*style->scale/2); cairo_arc (r->cr, 0,0,1, 0, 2 * MS_PI); cairo_restore(r->cr); if(style->color) { msCairoSetSourceColor(r->cr, style->color); cairo_fill_preserve(r->cr); } if(style->outlinewidth > 0) { cairo_set_line_width (r->cr, style->outlinewidth); msCairoSetSourceColor(r->cr, style->outlinecolor); cairo_stroke_preserve(r->cr); } cairo_new_path(r->cr); return MS_SUCCESS; } int startLayerVectorCairo(imageObj *img, mapObj *map, layerObj *layer) { if(layer->compositer && layer->compositer->opacity<100) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_push_group (r->cr); } return MS_SUCCESS; } int closeLayerVectorCairo(imageObj *img, mapObj *map, layerObj *layer) { if(layer->compositer && layer->compositer->opacity<100) { cairo_renderer *r = CAIRO_RENDERER(img); cairo_pop_group_to_source (r->cr); cairo_paint_with_alpha (r->cr, layer->compositer->opacity*0.01); } return MS_SUCCESS; } int startLayerRasterCairo(imageObj *img, mapObj *map, layerObj *layer) { return MS_SUCCESS; } int closeLayerRasterCairo(imageObj *img, mapObj *map, layerObj *layer) { return MS_SUCCESS; } int getRasterBufferHandleCairo(imageObj *img, rasterBufferObj *rb) { unsigned char *pb; cairo_renderer *r = CAIRO_RENDERER(img); rb->type = MS_BUFFER_BYTE_RGBA; pb = cairo_image_surface_get_data(r->surface); rb->data.rgba.pixels = pb; rb->data.rgba.row_step = cairo_image_surface_get_stride(r->surface); rb->data.rgba.pixel_step=4; rb->width = cairo_image_surface_get_width(r->surface); rb->height = cairo_image_surface_get_height(r->surface); rb->data.rgba.r = &(pb[2]); rb->data.rgba.g = &(pb[1]); rb->data.rgba.b = &(pb[0]); if(r->use_alpha) rb->data.rgba.a = &(pb[3]); else rb->data.rgba.a = NULL; return MS_SUCCESS; } int getRasterBufferCopyCairo(imageObj *img, rasterBufferObj *rb) { cairo_renderer *r = CAIRO_RENDERER(img); unsigned char *pb; rb->type = MS_BUFFER_BYTE_RGBA; rb->data.rgba.row_step = cairo_image_surface_get_stride(r->surface); rb->data.rgba.pixel_step=4; rb->width = cairo_image_surface_get_width(r->surface); rb->height = cairo_image_surface_get_height(r->surface); pb = (unsigned char*)malloc(rb->height * rb->data.rgba.row_step * sizeof(unsigned char)); memcpy(pb,cairo_image_surface_get_data(r->surface),rb->height * rb->data.rgba.row_step); rb->data.rgba.pixels = pb; rb->data.rgba.r = &(pb[2]); rb->data.rgba.g = &(pb[1]); rb->data.rgba.b = &(pb[0]); if(r->use_alpha) rb->data.rgba.a = &(pb[3]); else rb->data.rgba.a = NULL; return MS_SUCCESS; } static cairo_operator_t ms2cairo_compop(CompositingOperation op) { switch(op) { case MS_COMPOP_CLEAR: return CAIRO_OPERATOR_CLEAR; case MS_COMPOP_SRC: return CAIRO_OPERATOR_SOURCE; case MS_COMPOP_DST: return CAIRO_OPERATOR_DEST; case MS_COMPOP_SRC_OVER: return CAIRO_OPERATOR_OVER; case MS_COMPOP_DST_OVER: return CAIRO_OPERATOR_DEST_OVER; case MS_COMPOP_SRC_IN: return CAIRO_OPERATOR_IN; case MS_COMPOP_DST_IN: return CAIRO_OPERATOR_DEST_IN; case MS_COMPOP_SRC_OUT: return CAIRO_OPERATOR_OUT; case MS_COMPOP_DST_OUT: return CAIRO_OPERATOR_DEST_OUT; case MS_COMPOP_SRC_ATOP: return CAIRO_OPERATOR_ATOP; case MS_COMPOP_DST_ATOP: return CAIRO_OPERATOR_DEST_ATOP; case MS_COMPOP_XOR: return CAIRO_OPERATOR_XOR; case MS_COMPOP_PLUS: return CAIRO_OPERATOR_ADD; case MS_COMPOP_MULTIPLY: return CAIRO_OPERATOR_MULTIPLY; case MS_COMPOP_SCREEN: return CAIRO_OPERATOR_SCREEN; case MS_COMPOP_OVERLAY: return CAIRO_OPERATOR_OVERLAY; case MS_COMPOP_DARKEN: return CAIRO_OPERATOR_DARKEN; case MS_COMPOP_LIGHTEN: return CAIRO_OPERATOR_LIGHTEN; case MS_COMPOP_COLOR_DODGE: return CAIRO_OPERATOR_COLOR_DODGE; case MS_COMPOP_COLOR_BURN: return CAIRO_OPERATOR_COLOR_BURN; case MS_COMPOP_HARD_LIGHT: return CAIRO_OPERATOR_HARD_LIGHT; case MS_COMPOP_SOFT_LIGHT: return CAIRO_OPERATOR_SOFT_LIGHT; case MS_COMPOP_DIFFERENCE: return CAIRO_OPERATOR_DIFFERENCE; case MS_COMPOP_EXCLUSION: return CAIRO_OPERATOR_EXCLUSION; case MS_COMPOP_INVERT: case MS_COMPOP_INVERT_RGB: case MS_COMPOP_MINUS: case MS_COMPOP_CONTRAST: default: return CAIRO_OPERATOR_OVER; } } int cairoCompositeRasterBuffer(imageObj *img, rasterBufferObj *rb, CompositingOperation comp, int opacity) { cairo_surface_t *src; cairo_renderer *r; if(rb->type != MS_BUFFER_BYTE_RGBA) { return MS_FAILURE; } r = CAIRO_RENDERER(img); src = cairo_image_surface_create_for_data(rb->data.rgba.pixels,CAIRO_FORMAT_ARGB32, rb->width,rb->height, rb->data.rgba.row_step); cairo_set_source_surface (r->cr,src,0,0); cairo_set_operator(r->cr, ms2cairo_compop(comp)); cairo_paint_with_alpha(r->cr,opacity/100.0); cairo_surface_finish(src); cairo_surface_destroy(src); cairo_set_operator(r->cr,CAIRO_OPERATOR_OVER); return MS_SUCCESS; } int mergeRasterBufferCairo(imageObj *img, rasterBufferObj *rb, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { cairo_surface_t *src; cairo_renderer *r; /* not implemented for src,dst,width and height */ if(rb->type != MS_BUFFER_BYTE_RGBA) { return MS_FAILURE; } r = CAIRO_RENDERER(img); src = cairo_image_surface_create_for_data(rb->data.rgba.pixels,CAIRO_FORMAT_ARGB32, rb->width,rb->height, rb->data.rgba.row_step); if(dstX||dstY||srcX||srcY||width!=img->width||height!=img->height) { cairo_set_source_surface (r->cr, src, dstX - srcX, dstY - srcY); cairo_rectangle (r->cr, dstX, dstY, width, height); cairo_fill (r->cr); } else { cairo_set_source_surface (r->cr,src,0,0); cairo_paint_with_alpha(r->cr,opacity); } cairo_surface_finish(src); cairo_surface_destroy(src); return MS_SUCCESS; } void freeSVGCache(symbolObj *s) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *cache = s->renderer_cache; if(!cache) return; assert(cache->svgc); #ifdef USE_SVG_CAIRO svg_cairo_destroy(cache->svgc); #else rsvg_handle_close(cache->svgc, NULL); #if LIBRSVG_CHECK_VERSION(2,35,0) g_object_unref(cache->svgc); #else rsvg_handle_free(cache->svgc); #endif #endif if(cache->pixmap_buffer) { msFreeRasterBuffer(cache->pixmap_buffer); free(cache->pixmap_buffer); } msFree(s->renderer_cache); s->renderer_cache = NULL; #endif } int freeSymbolCairo(symbolObj *s) { if(!s->renderer_cache) return MS_SUCCESS; switch(s->type) { case MS_SYMBOL_VECTOR: cairo_path_destroy(s->renderer_cache); break; case MS_SYMBOL_PIXMAP: cairo_surface_destroy(s->renderer_cache); break; case MS_SYMBOL_SVG: freeSVGCache(s); break; } s->renderer_cache=NULL; return MS_SUCCESS; } int initializeRasterBufferCairo(rasterBufferObj *rb, int width, int height, int mode) { rb->type = MS_BUFFER_BYTE_RGBA; rb->width = width; rb->height = height; rb->data.rgba.pixel_step = 4; rb->data.rgba.row_step = width * 4; rb->data.rgba.pixels = (unsigned char*)calloc(width*height*4,sizeof(unsigned char)); rb->data.rgba.r = &(rb->data.rgba.pixels[2]); rb->data.rgba.g = &(rb->data.rgba.pixels[1]); rb->data.rgba.b = &(rb->data.rgba.pixels[0]); rb->data.rgba.a = &(rb->data.rgba.pixels[3]); return MS_SUCCESS; } int msPreloadSVGSymbol(symbolObj *symbol) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *cache; if(!symbol->renderer_cache) { cache = msSmallCalloc(1,sizeof(struct svg_symbol_cache)); symbol->renderer_free_func = &freeSVGCache; } else { cache = symbol->renderer_cache; } if(cache->svgc) return MS_SUCCESS; #ifdef USE_SVG_CAIRO { unsigned int svg_width, svg_height; int status; status = svg_cairo_create(&cache->svgc); if (status) { msSetError(MS_RENDERERERR, "problem creating cairo svg", "msPreloadSVGSymbol()"); return MS_FAILURE; } status = svg_cairo_parse(cache->svgc, symbol->full_pixmap_path); if (status) { msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()"); return MS_FAILURE; } svg_cairo_get_size (cache->svgc, &svg_width, &svg_height); if (svg_width == 0 || svg_height == 0) { msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()"); return MS_FAILURE; } symbol->sizex = svg_width; symbol->sizey = svg_height; } #else { RsvgDimensionData dim; cache->svgc = rsvg_handle_new_from_file(symbol->full_pixmap_path,NULL); if(!cache->svgc) { msSetError(MS_RENDERERERR,"failed to load svg file %s", "msPreloadSVGSymbol()", symbol->full_pixmap_path); return MS_FAILURE; } rsvg_handle_get_dimensions_sub (cache->svgc, &dim, NULL); symbol->sizex = dim.width; symbol->sizey = dim.height; } #endif symbol->renderer_cache = cache; return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but is not built with libsvgcairo", "msPreloadSVGSymbol()"); return MS_FAILURE; #endif } int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *svg_cache; symbolStyleObj pixstyle; symbolObj pixsymbol; int status; if(MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; svg_cache = (struct svg_symbol_cache*) symbol->renderer_cache; //already rendered at the right size and scale? return if(svg_cache->scale != style->scale || svg_cache->rotation != style->rotation) { cairo_t *cr; cairo_surface_t *surface; unsigned char *pb; int width, height, surface_w, surface_h; /* need to recompute the pixmap */ if(svg_cache->pixmap_buffer) { msFreeRasterBuffer(svg_cache->pixmap_buffer); } else { svg_cache->pixmap_buffer = msSmallCalloc(1,sizeof(rasterBufferObj)); } //increase pixmap size to accomodate scaling/rotation if (style->scale != 1.0) { width = surface_w = (symbol->sizex * style->scale + 0.5); height = surface_h = (symbol->sizey * style->scale + 0.5); } else { width = surface_w = symbol->sizex; height = surface_h = symbol->sizey; } if (style->rotation != 0) { surface_w = surface_h = MS_NINT(MS_MAX(height, width) * 1.415); } surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h); cr = cairo_create(surface); if (style->rotation != 0) { cairo_translate(cr, surface_w / 2, surface_h / 2); cairo_rotate(cr, -style->rotation); cairo_translate(cr, -width / 2, -height / 2); } if (style->scale != 1.0) { cairo_scale(cr, style->scale, style->scale); } #ifdef USE_SVG_CAIRO if(svg_cairo_render(svg_cache->svgc, cr) != SVG_CAIRO_STATUS_SUCCESS) { return MS_FAILURE; } #else rsvg_handle_render_cairo(svg_cache->svgc, cr); #endif pb = cairo_image_surface_get_data(surface); //set up raster initializeRasterBufferCairo(svg_cache->pixmap_buffer, surface_w, surface_h, 0); memcpy(svg_cache->pixmap_buffer->data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof (unsigned char)); svg_cache->scale = style->scale; svg_cache->rotation = style->rotation; cairo_destroy(cr); cairo_surface_destroy(surface); } assert(svg_cache->pixmap_buffer->height && svg_cache->pixmap_buffer->width); pixstyle = *style; pixstyle.rotation = 0.0; pixstyle.scale = 1.0; pixsymbol.pixmap_buffer = svg_cache->pixmap_buffer; pixsymbol.type = MS_SYMBOL_PIXMAP; status = MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle); MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol); return status; #else msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo", "renderSVGSymbolCairo()"); return MS_FAILURE; #endif } void msCairoCleanup() { cairo_debug_reset_static_data(); } #endif /*USE_CAIRO*/ int msPopulateRendererVTableCairoRaster( rendererVTableObj *renderer ) { #ifdef USE_CAIRO renderer->supports_pixel_buffer=1; renderer->compositeRasterBuffer = cairoCompositeRasterBuffer; renderer->supports_svg = 1; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; initializeCache(&MS_RENDERER_CACHE(renderer)); renderer->startLayer = startLayerRasterCairo; renderer->endLayer = closeLayerRasterCairo; renderer->renderLineTiled = NULL; renderer->renderLine=&renderLineCairo; renderer->createImage=&createImageCairo; renderer->saveImage=&saveImageCairo; renderer->getRasterBufferHandle=&getRasterBufferHandleCairo; renderer->getRasterBufferCopy=&getRasterBufferCopyCairo; renderer->renderPolygon=&renderPolygonCairo; renderer->renderGlyphs=&renderGlyphs2Cairo; renderer->freeImage=&freeImageCairo; renderer->renderEllipseSymbol = &renderEllipseSymbolCairo; renderer->renderVectorSymbol = &renderVectorSymbolCairo; renderer->renderSVGSymbol = &renderSVGSymbolCairo; renderer->renderPixmapSymbol = &renderPixmapSymbolCairo; renderer->mergeRasterBuffer = &mergeRasterBufferCairo; renderer->renderTile = &renderTileCairo; renderer->loadImageFromFile = &msLoadMSRasterBufferFromFile; renderer->renderPolygonTiled = &renderPolygonTiledCairo; renderer->freeSymbol = &freeSymbolCairo; renderer->cleanup = &cleanupCairo; return MS_SUCCESS; #else msSetError(MS_MISCERR, "Cairo Driver requested but MapServer is not built in", "msPopulateRendererVTableCairoRaster()"); return MS_FAILURE; #endif } int populateRendererVTableCairoVector( rendererVTableObj *renderer ) { #ifdef USE_CAIRO renderer->use_imagecache=0; renderer->supports_pixel_buffer=0; renderer->compositeRasterBuffer = NULL; renderer->supports_svg = 1; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; initializeCache(&MS_RENDERER_CACHE(renderer)); renderer->startLayer = startLayerVectorCairo; renderer->endLayer = closeLayerVectorCairo; renderer->renderLine=&renderLineCairo; renderer->renderLineTiled = NULL; renderer->createImage=&createImageCairo; renderer->saveImage=&saveImageCairo; renderer->saveImageBuffer = &saveImageBufferCairo; renderer->getRasterBufferHandle=&getRasterBufferHandleCairo; renderer->renderPolygon=&renderPolygonCairo; renderer->renderGlyphs=&renderGlyphs2Cairo; renderer->freeImage=&freeImageCairo; renderer->renderEllipseSymbol = &renderEllipseSymbolCairo; renderer->renderVectorSymbol = &renderVectorSymbolCairo; renderer->renderSVGSymbol = &renderSVGSymbolCairo; renderer->renderPixmapSymbol = &renderPixmapSymbolCairo; renderer->loadImageFromFile = &msLoadMSRasterBufferFromFile; renderer->mergeRasterBuffer = &mergeRasterBufferCairo; renderer->initializeRasterBuffer = initializeRasterBufferCairo; renderer->renderTile = &renderTileCairo; renderer->renderPolygonTiled = &renderPolygonTiledCairo; renderer->freeSymbol = &freeSymbolCairo; renderer->cleanup = &cleanupCairo; return MS_SUCCESS; #else msSetError(MS_MISCERR, "Cairo Driver requested but MapServer is not built in", "msPopulateRendererVTableCairoRaster()"); return MS_FAILURE; #endif } int msPopulateRendererVTableCairoSVG( rendererVTableObj *renderer ) { return populateRendererVTableCairoVector(renderer); } int msPopulateRendererVTableCairoPDF( rendererVTableObj *renderer ) { return populateRendererVTableCairoVector(renderer); } mapserver-7.4.3/mapchart.c000066400000000000000000000540521357574274700155270ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of dynamic charting (MS-RFC-29) * Author: Thomas Bonfort ( thomas.bonfort[at]gmail.com ) * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #define MS_CHART_TYPE_PIE 1 #define MS_CHART_TYPE_BAR 2 #define MS_CHART_TYPE_VBAR 3 /* ** check if an object of width w and height h placed at point x,y can fit in an image of width mw and height mh */ #define MS_CHART_FITS(x,y,w,h,mw,mh) (((x)-(w)/2.>0.)&&((x)+(w)/2.<(mw))&&((y)-(h)/2.>0.)&&((y)+(h)/2.)<(mh)) /* ** find a point on a shape. check if it fits in image ** returns ** MS_SUCCESS and point coordinates in 'p' if chart fits in image ** MS_FAILURE if no point could be found */ int findChartPoint(mapObj *map, shapeObj *shape, int width, int height, pointObj *center) { int middle,numpoints,idx,offset; double invcellsize = 1.0/map->cellsize; /*speed up MAP2IMAGE_X/Y_IC_DBL*/ switch(shape->type) { case MS_SHAPE_POINT: center->x=MS_MAP2IMAGE_X_IC_DBL(shape->line[0].point[0].x, map->extent.minx, invcellsize); center->y=MS_MAP2IMAGE_Y_IC_DBL(shape->line[0].point[0].y, map->extent.maxy, invcellsize); if(MS_CHART_FITS(center->x,center->y,width,height,map->width,map->height)) return MS_SUCCESS; else return MS_FAILURE; break; case MS_SHAPE_LINE: /*loop through line segments starting from middle (alternate between before and after middle point) **first segment that fits is chosen */ middle=shape->line[0].numpoints/2; /*start with middle segment of line*/ numpoints=shape->line[0].numpoints; for(offset=1; offset<=middle; offset++) { idx=middle+offset; if(idxx=(shape->line[0].point[idx-1].x+shape->line[0].point[idx].x)/2.; center->y=(shape->line[0].point[idx-1].y+shape->line[0].point[idx].y)/2.; center->x=MS_MAP2IMAGE_X_IC_DBL(center->x, map->extent.minx, invcellsize); center->y=MS_MAP2IMAGE_Y_IC_DBL(center->y, map->extent.maxy, invcellsize); if(MS_CHART_FITS(center->x,center->y,width,height,map->width,map->height)) return MS_SUCCESS; break; } idx=middle-offset; if(idx>=0) { center->x=(shape->line[0].point[idx].x+shape->line[0].point[idx+1].x)/2; center->y=(shape->line[0].point[idx].y+shape->line[0].point[idx+1].y)/2; center->x=MS_MAP2IMAGE_X_IC_DBL(center->x, map->extent.minx, invcellsize); center->y=MS_MAP2IMAGE_Y_IC_DBL(center->y, map->extent.maxy, invcellsize); if(MS_CHART_FITS(center->x,center->y,width,height,map->width,map->height)) return MS_SUCCESS; break; } } return MS_FAILURE; break; case MS_SHAPE_POLYGON: msPolygonLabelPoint(shape, center, -1); center->x=MS_MAP2IMAGE_X_IC_DBL(center->x, map->extent.minx, invcellsize); center->y=MS_MAP2IMAGE_Y_IC_DBL(center->y, map->extent.maxy, invcellsize); if(MS_CHART_FITS(center->x,center->y,width,height,map->width,map->height)) return MS_SUCCESS; else return MS_FAILURE; break; default: return MS_FAILURE; } } int WARN_UNUSED drawRectangle(mapObj *map, imageObj *image, double mx, double my, double Mx, double My, styleObj *style) { shapeObj shape; lineObj line; pointObj point[5]; line.point = point; line.numpoints = 5; shape.line = &line; shape.numlines = 1; point[0].x = point[4].x = point[3].x = mx; point[0].y = point[4].y = point[1].y = my; point[1].x = point[2].x = Mx; point[2].y = point[3].y = My; return msDrawShadeSymbol(map,image,&shape,style,1.0); } int WARN_UNUSED msDrawVBarChart(mapObj *map, imageObj *image, pointObj *center, double *values, styleObj **styles, int numvalues, double barWidth) { int c; double left,bottom,cur; /*shortcut to pixel boundaries of the chart*/ double height = 0; for(c=0; cy+height/2.; left = center->x-barWidth/2.; for(c=0; cy-height/2.; bottom=center->y+height/2.; left=center->x-width/2.; shapeMaxVal=shapeMinVal=values[0]; for(c=1; cshapeMaxVal) shapeMaxVal=values[c]; if(values[c]bottom) ? bottom : vertOrigin; horizStart=left; for(c=0; cbottom) ? bottom : vertOrigin-barHeight; if(y!=vertOriginClipped) { /*don't draw bars of height == 0 (i.e. either values==0, or clipped)*/ if(values[c]>0) { if(UNLIKELY(MS_FAILURE == drawRectangle(map, image, horizStart, y, horizStart+barWidth-1, vertOriginClipped, styles[c]))) return MS_FAILURE; } else { if(UNLIKELY(MS_FAILURE == drawRectangle(map,image, horizStart, vertOriginClipped, horizStart+barWidth-1 , y, styles[c]))) return MS_FAILURE; } } horizStart+=barWidth; } return MS_SUCCESS; } int WARN_UNUSED msDrawPieChart(mapObj *map, imageObj *image, pointObj *center, double diameter, double *values, styleObj **styles, int numvalues) { int i; double dTotal=0.,start=0; for(i=0; iproject) msProjectShape(&layer->projection, &map->projection, shape); #endif if(msBindLayerToShape(layer, shape, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS) != MS_SUCCESS) return MS_FAILURE; /* error message is set in msBindLayerToShape() */ *nvalues = 0; for(c=0; cnumclasses; c++) { if(msEvalExpression(layer, shape, &(layer->class[c]->expression), layer->classitemindex) == MS_TRUE) { values[*nvalues]=(layer->class[c]->styles[0]->size); styles[*nvalues]=layer->class[c]->styles[0]; (*nvalues)++; } } } return status; } /* eventually add a class to the layer to get the diameter from an attribute */ int pieLayerProcessDynamicDiameter(layerObj *layer) { const char *chartRangeProcessingKey=NULL; char *attrib; double mindiameter=-1, maxdiameter, minvalue, maxvalue; classObj *newclass; styleObj *newstyle; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); if(chartSizeProcessingKey != NULL) return MS_FALSE; chartRangeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE_RANGE" ); if(chartRangeProcessingKey==NULL) return MS_FALSE; attrib = msSmallMalloc(strlen(chartRangeProcessingKey)+1); switch(sscanf(chartRangeProcessingKey,"%s %lf %lf %lf %lf",attrib, &mindiameter,&maxdiameter,&minvalue,&maxvalue)) { case 1: /*we only have the attribute*/ case 5: /*we have the attribute and the four range values*/ break; default: free(attrib); msSetError(MS_MISCERR, "Chart Layer format error for processing key \"CHART_RANGE\"", "msDrawChartLayer()"); return MS_FAILURE; } /*create a new class in the layer containing the wanted attribute * as the SIZE of its first STYLE*/ newclass=msGrowLayerClasses(layer); if(newclass==NULL) { free(attrib); return MS_FAILURE; } initClass(newclass); layer->numclasses++; /*create and attach a new styleObj to our temp class * and bind the wanted attribute to its SIZE */ newstyle=msGrowClassStyles(newclass); if(newstyle==NULL) { free(attrib); return MS_FAILURE; } initStyle(newstyle); newclass->numstyles++; newclass->name=(char*)msStrdup("__MS_SIZE_ATTRIBUTE_"); newstyle->bindings[MS_STYLE_BINDING_SIZE].item=msStrdup(attrib); newstyle->numbindings++; free(attrib); return MS_TRUE; } /* clean up the class added temporarily */ static void pieLayerCleanupDynamicDiameter(layerObj *layer) { if( layer->numclasses > 0 && EQUALN(layer->class[layer->numclasses - 1]->name, "__MS_SIZE_ATTRIBUTE_", 20) ) { classObj *c=msRemoveClass(layer, layer->numclasses - 1); freeClass(c); msFree(c); } } int msDrawPieChartLayer(mapObj *map, layerObj *layer, imageObj *image) { shapeObj shape; int status=MS_SUCCESS; const char *chartRangeProcessingKey=NULL; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); double diameter, mindiameter=-1, maxdiameter, minvalue, maxvalue, exponent=0; double *values; styleObj **styles; pointObj center; int numvalues = layer->numclasses; /* the number of classes to represent in the graph */ int numvalues_for_shape = 0; if(chartSizeProcessingKey==NULL) { chartRangeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE_RANGE" ); if(chartRangeProcessingKey==NULL) diameter=20; else { sscanf(chartRangeProcessingKey,"%*s %lf %lf %lf %lf %lf", &mindiameter,&maxdiameter,&minvalue,&maxvalue,&exponent); } } else { if(sscanf(chartSizeProcessingKey ,"%lf",&diameter)!=1) { msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawPieChartLayer()"); return MS_FAILURE; } } #ifdef USE_PROJ layer->project = msProjectionsDiffer(&(layer->projection), &(map->projection)); #endif /* step through the target shapes */ msInitShape(&shape); values=(double*)calloc(numvalues,sizeof(double)); MS_CHECK_ALLOC(values, numvalues*sizeof(double), MS_FAILURE); styles = (styleObj**)malloc((numvalues)*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawPieChartLayer()", __FILE__, __LINE__, (unsigned int)(numvalues*sizeof(styleObj*))); free(values); return MS_FAILURE; } while(MS_SUCCESS == getNextShape(map,layer,values,&numvalues_for_shape,styles,&shape)) { if(chartRangeProcessingKey!=NULL) numvalues_for_shape--; if(numvalues_for_shape == 0) { msFreeShape(&shape); continue; } msDrawStartShape(map, layer, image, &shape); if(chartRangeProcessingKey!=NULL) { diameter = values[numvalues_for_shape]; if(mindiameter>=0) { if(diameter<=minvalue) diameter=mindiameter; else if(diameter>=maxvalue) diameter=maxdiameter; else { if (exponent <= 0) diameter=MS_NINT( mindiameter+ ((diameter-minvalue)/(maxvalue-minvalue))* (maxdiameter-mindiameter) ); else diameter=MS_NINT( mindiameter+ pow((diameter-minvalue)/(maxvalue-minvalue),1.0/exponent)* (maxdiameter-mindiameter) ); } } } if(findChartPoint(map, &shape, diameter, diameter, ¢er) == MS_SUCCESS) { status = msDrawPieChart(map,image, ¢er, diameter, values,styles,numvalues_for_shape); } msDrawEndShape(map,layer,image,&shape); msFreeShape(&shape); } free(values); free(styles); return status; } int msDrawVBarChartLayer(mapObj *map, layerObj *layer, imageObj *image) { shapeObj shape; int status=MS_SUCCESS; const char *chartSizeProcessingKey=msLayerGetProcessingKey( layer,"CHART_SIZE" ); const char *chartScaleProcessingKey=msLayerGetProcessingKey( layer,"CHART_SCALE" ); double barWidth,scale=1.0; double *values; styleObj **styles; pointObj center; int numvalues = layer->numclasses; int numvalues_for_shape; if(chartSizeProcessingKey==NULL) { barWidth=20; } else { if(sscanf(chartSizeProcessingKey ,"%lf",&barWidth) != 1) { msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawVBarChartLayer()"); return MS_FAILURE; } } if(chartScaleProcessingKey) { if(sscanf(chartScaleProcessingKey,"%lf",&scale)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_SCALE\"", "msDrawVBarChartLayer()"); return MS_FAILURE; } } msInitShape(&shape); values=(double*)calloc(numvalues,sizeof(double)); MS_CHECK_ALLOC(values, numvalues*sizeof(double), MS_FAILURE); styles = (styleObj**)malloc(numvalues*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawVBarChartLayer()", __FILE__, __LINE__, (unsigned int)(numvalues*sizeof(styleObj*))); free(values); return MS_FAILURE; } while(MS_SUCCESS == getNextShape(map,layer,values,&numvalues_for_shape,styles,&shape)) { int i; double h=0; if(numvalues_for_shape == 0) { continue; } for(i=0; inumclasses; int numvalues_for_shape; if(chartSizeProcessingKey==NULL) { width=height=20; } else { switch(sscanf(chartSizeProcessingKey ,"%lf %lf",&width,&height)) { case 2: break; case 1: height = width; break; default: msSetError(MS_MISCERR, "msDrawChart format error for processing key \"CHART_SIZE\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMax) { if(sscanf(barMax,"%lf",&barMaxVal)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_BAR_MAXVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMin) { if(sscanf(barMin,"%lf",&barMinVal)!=1) { msSetError(MS_MISCERR, "Error reading value for processing key \"CHART_BAR_MINVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } } if(barMin && barMax && barMinVal>=barMaxVal) { msSetError(MS_MISCERR, "\"CHART_BAR_MINVAL\" must be less than \"CHART_BAR_MAXVAL\"", "msDrawBarChartLayer()"); return MS_FAILURE; } barWidth=(double)width/(double)layer->numclasses; if(!barWidth) { msSetError(MS_MISCERR, "Specified width of chart too small to fit given number of classes", "msDrawBarChartLayer()"); return MS_FAILURE; } msInitShape(&shape); values=(double*)calloc(numvalues,sizeof(double)); MS_CHECK_ALLOC(values, numvalues*sizeof(double), MS_FAILURE); styles = (styleObj**)malloc(numvalues*sizeof(styleObj*)); if (styles == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawBarChartLayer()", __FILE__, __LINE__, (unsigned int)(numvalues*sizeof(styleObj*))); free(values); return MS_FAILURE; } while(MS_SUCCESS == getNextShape(map,layer,values,&numvalues_for_shape,styles,&shape)) { if(numvalues_for_shape == 0 ) continue; msDrawStartShape(map, layer, image, &shape); if(findChartPoint(map, &shape, width,height, ¢er)==MS_SUCCESS) { status = msDrawBarChart(map,image, ¢er, values, styles, numvalues_for_shape, width,height, (barMax!=NULL)?&barMaxVal:NULL, (barMin!=NULL)?&barMinVal:NULL, barWidth); } msDrawEndShape(map,layer,image,&shape); msFreeShape(&shape); } free(values); free(styles); return status; } /** * Generic function to render chart layers. */ int msDrawChartLayer(mapObj *map, layerObj *layer, imageObj *image) { rectObj searchrect; const char *chartTypeProcessingKey=msLayerGetProcessingKey( layer,"CHART_TYPE" ); int chartType=MS_CHART_TYPE_PIE; int status = MS_FAILURE; if (image && map && layer) { if( !(MS_RENDERER_PLUGIN(image->format) )) { msSetError(MS_MISCERR, "chart drawing currently only supports GD and AGG renderers", "msDrawChartLayer()"); return MS_FAILURE; } if(chartTypeProcessingKey!=NULL) { if( strcasecmp(chartTypeProcessingKey,"PIE") == 0 ) { chartType=MS_CHART_TYPE_PIE; } else if( strcasecmp(chartTypeProcessingKey,"BAR") == 0 ) { chartType=MS_CHART_TYPE_BAR; } else if( strcasecmp(chartTypeProcessingKey,"VBAR") == 0 ) { chartType=MS_CHART_TYPE_VBAR; } else { msSetError(MS_MISCERR,"unknown chart type for processing key \"CHART_TYPE\", must be one of \"PIE\" or \"BAR\"", "msDrawChartLayer()"); return MS_FAILURE; } } if(chartType == MS_CHART_TYPE_PIE) { pieLayerProcessDynamicDiameter(layer); } /* open this layer */ status = msLayerOpen(layer); if(status != MS_SUCCESS) return MS_FAILURE; status = msLayerWhichItems(layer, MS_FALSE, NULL); if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* identify target shapes */ if(layer->transform == MS_TRUE) searchrect = map->extent; else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ msLayerClose(layer); if(chartType == MS_CHART_TYPE_PIE) pieLayerCleanupDynamicDiameter(layer); return MS_SUCCESS; } else if(status != MS_SUCCESS) { msLayerClose(layer); if(chartType == MS_CHART_TYPE_PIE) pieLayerCleanupDynamicDiameter(layer); return MS_FAILURE; } switch(chartType) { case MS_CHART_TYPE_PIE: status = msDrawPieChartLayer(map, layer, image); break; case MS_CHART_TYPE_BAR: status = msDrawBarChartLayer(map, layer, image); break; case MS_CHART_TYPE_VBAR: status = msDrawVBarChartLayer(map, layer, image); break; default: return MS_FAILURE;/*shouldn't be here anyways*/ } msLayerClose(layer); if(chartType == MS_CHART_TYPE_PIE) pieLayerCleanupDynamicDiameter(layer); } return status; } mapserver-7.4.3/mapcluster.c000066400000000000000000001573071357574274700161160ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of the cluster layer data provider (RFC-69). * Author: Tamas Szekeres (szekerest@gmail.com). * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #define _CRT_SECURE_NO_WARNINGS 1 /* $Id$ */ #include #include "mapserver.h" #ifdef USE_CLUSTER_PLUGIN #define USE_CLUSTER_EXTERNAL #endif /* custom attributes provided by this layer data source */ #define MSCLUSTER_NUMITEMS 3 #define MSCLUSTER_FEATURECOUNT "Cluster_FeatureCount" #define MSCLUSTER_FEATURECOUNTINDEX -100 #define MSCLUSTER_GROUP "Cluster_Group" #define MSCLUSTER_GROUPINDEX -101 #define MSCLUSTER_BASEFID "Cluster_BaseFID" #define MSCLUSTER_BASEFIDINDEX -102 typedef struct cluster_tree_node clusterTreeNode; typedef struct cluster_info clusterInfo; typedef struct cluster_layer_info msClusterLayerInfo; /* forward declarations */ void msClusterLayerCopyVirtualTable(layerVTableObj* vtable); static void clusterTreeNodeDestroy(msClusterLayerInfo* layerinfo, clusterTreeNode *node); /* cluster compare func */ typedef int (*clusterCompareRegionFunc)(clusterInfo* current, clusterInfo* other); /* quadtree constants */ #define SPLITRATIO 0.55 #define TREE_MAX_DEPTH 10 /* cluster algorithm */ #define MSCLUSTER_ALGORITHM_FULL 0 #define MSCLUSTER_ALGORITHM_SIMPLE 1 /* cluster data */ struct cluster_info { double x; /* x position of the current point */ double y; /* y position of the current point */ double avgx; /* average x positions of this cluster */ double avgy; /* average y positions of this cluster */ double varx; /* variance of the x positions of this cluster */ double vary; /* variance of the y positions of this cluster */ shapeObj shape; /* current shape */ rectObj bounds; /* clustering region */ /* number of the neighbouring shapes */ int numsiblings; /* diagnostics */ int numcollected; int numremoved; int index; clusterTreeNode* node; /* collection of the siblings */ clusterInfo* siblings; /* next shape in the linked list */ clusterInfo* next; /* current group */ char* group; int filter; }; /* quadtree node */ struct cluster_tree_node { /* area covered by this node */ rectObj rect; /* linked list of the shapes stored at this node. */ int numshapes; int index; int position; clusterInfo* shapes; /* quad tree subnodes */ clusterTreeNode* subnode[4]; }; /* layeinfo */ struct cluster_layer_info { /* array of features (finalized clusters) */ clusterInfo* finalized; clusterInfo* finalizedSiblings; clusterInfo* filtered; int numFeatures; int numFinalized; int numFinalizedSiblings; int numFiltered; /* variables for collecting the best cluster and iterating with NextShape */ clusterInfo* current; /* check whether all shapes should be returned behind a cluster */ int get_all_shapes; /* check whether the location of the shapes should be preserved (no averaging) */ int keep_locations; /* the maxdistance and the buffer parameters are specified in map units (scale independent clustering) */ int use_map_units; double rank; /* root node of the quad tree */ clusterTreeNode* root; int numNodes; clusterTreeNode* finalizedNodes; int numFinalizedNodes; /* map extent used for building cluster data */ rectObj searchRect; /* source layer parameters */ layerObj srcLayer; /* distance comparator function */ clusterCompareRegionFunc fnCompare; /* diagnostics */ int depth; /* processing algorithm */ int algorithm; }; extern int yyparse(parseObj *p); /* evaluate the filter expression */ int msClusterEvaluateFilter(expressionObj* expression, shapeObj *shape) { if (expression->type == MS_EXPRESSION) { int status; parseObj p; p.shape = shape; p.expr = expression; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_BOOLEAN; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to parse expression: %s", "msClusterEvaluateFilter", expression->string); return 0; } return p.result.intval; } return 0; } /* get the group text when creating the clusters */ char *msClusterGetGroupText(expressionObj* expression, shapeObj *shape) { char *tmpstr=NULL; if(expression->string) { switch(expression->type) { case(MS_STRING): tmpstr = msStrdup(expression->string); break; case(MS_EXPRESSION): { int status; parseObj p; p.shape = shape; p.expr = expression; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_STRING; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process text expression: %s", "msClusterGetGroupText", expression->string); return NULL; } tmpstr = p.result.strval; break; } default: break; } } return(tmpstr); } int CompareEllipseRegion(clusterInfo* current, clusterInfo* other) { if (current->group && other->group && !EQUAL(current->group, other->group)) return MS_FALSE; if ((other->x - current->x) * (other->x - current->x) / ((current->bounds.maxx - current->x) * (current->bounds.maxx - current->x)) + (other->y - current->y) * (other->y - current->y) / ((current->bounds.maxy - current->y) * (current->bounds.maxy - current->y)) > 1) return MS_FALSE; return MS_TRUE; } int CompareRectangleRegion(clusterInfo* current, clusterInfo* other) { if (current->group && other->group && !EQUAL(current->group, other->group)) return MS_FALSE; if (other->x < current->bounds.minx) return MS_FALSE; if (other->x > current->bounds.maxx) return MS_FALSE; if (other->y < current->bounds.miny) return MS_FALSE; if (other->y > current->bounds.maxy) return MS_FALSE; return MS_TRUE; } static void treeSplitBounds( rectObj *in, rectObj *out1, rectObj *out2) { double range; /* -------------------------------------------------------------------- */ /* The output bounds will be very similar to the input bounds, */ /* so just copy over to start. */ /* -------------------------------------------------------------------- */ memcpy(out1, in, sizeof(rectObj)); memcpy(out2, in, sizeof(rectObj)); /* -------------------------------------------------------------------- */ /* Split in X direction. */ /* -------------------------------------------------------------------- */ if((in->maxx - in->minx) > (in->maxy - in->miny)) { range = in->maxx - in->minx; out1->maxx = in->minx + range * SPLITRATIO; out2->minx = in->maxx - range * SPLITRATIO; } /* -------------------------------------------------------------------- */ /* Otherwise split in Y direction. */ /* -------------------------------------------------------------------- */ else { range = in->maxy - in->miny; out1->maxy = in->miny + range * SPLITRATIO; out2->miny = in->maxy - range * SPLITRATIO; } } /* alloc memory for a new tentative cluster */ static clusterInfo *clusterInfoCreate(msClusterLayerInfo* layerinfo) { clusterInfo* feature = (clusterInfo*)msSmallMalloc(sizeof(clusterInfo)); msInitShape(&feature->shape); feature->numsiblings = 0; feature->numcollected = 0; feature->numremoved = 0; feature->next = NULL; feature->group = NULL; feature->node = NULL; feature->siblings = NULL; feature->index = layerinfo->numFeatures; feature->filter = -1; /* not yet calculated */ ++layerinfo->numFeatures; return feature; } /* destroy memory of the cluster list */ static void clusterInfoDestroyList(msClusterLayerInfo* layerinfo, clusterInfo* feature) { clusterInfo* s = feature; clusterInfo* next; /* destroy the shapes added to this node */ while (s) { next = s->next; if (s->siblings) { clusterInfoDestroyList(layerinfo, s->siblings); } msFreeShape(&s->shape); msFree(s->group); msFree(s); --layerinfo->numFeatures; s = next; } } /* alloc memory for a new treenode */ static clusterTreeNode *clusterTreeNodeCreate(msClusterLayerInfo* layerinfo, rectObj rect) { clusterTreeNode* node = (clusterTreeNode*)msSmallMalloc(sizeof(clusterTreeNode)); node->rect = rect; node->numshapes = 0; node->shapes = NULL; node->subnode[0] = node->subnode[1] = node->subnode[2] = node->subnode[3] = NULL; node->index = layerinfo->numNodes; node->position = 0; ++layerinfo->numNodes; return node; } /* traverse the quadtree and destroy all sub elements */ static void clusterTreeNodeDestroy(msClusterLayerInfo* layerinfo, clusterTreeNode *node) { int i; /* destroy the shapes added to this node */ clusterInfoDestroyList(layerinfo, node->shapes); /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) clusterTreeNodeDestroy(layerinfo, node->subnode[i]); } msFree(node); --layerinfo->numNodes; } /* destroy memory of the cluster finalized list (without recursion) */ static void clusterTreeNodeDestroyList(msClusterLayerInfo* layerinfo, clusterTreeNode *node) { clusterTreeNode* n = node; clusterTreeNode* next; /* destroy the list of nodes */ while (n) { next = n->subnode[0]; n->subnode[0] = NULL; clusterTreeNodeDestroy(layerinfo, n); --layerinfo->numFinalizedNodes; n = next; } } void clusterDestroyData(msClusterLayerInfo *layerinfo) { if (layerinfo->finalized) { clusterInfoDestroyList(layerinfo, layerinfo->finalized); layerinfo->finalized = NULL; } layerinfo->numFinalized = 0; if (layerinfo->finalizedSiblings) { clusterInfoDestroyList(layerinfo, layerinfo->finalizedSiblings); layerinfo->finalizedSiblings = NULL; } layerinfo->numFinalizedSiblings = 0; if (layerinfo->filtered) { clusterInfoDestroyList(layerinfo, layerinfo->filtered); layerinfo->filtered = NULL; } layerinfo->numFiltered = 0; if (layerinfo->finalizedNodes) { clusterTreeNodeDestroyList(layerinfo, layerinfo->finalizedNodes); layerinfo->finalizedNodes = NULL; } layerinfo->numFinalizedNodes = 0; if (layerinfo->root) { clusterTreeNodeDestroy(layerinfo, layerinfo->root); layerinfo->root = NULL; } layerinfo->numNodes = 0; } /* traverse the quadtree to find the neighbouring shapes and update some data on the related shapes (when adding a new feature)*/ static void findRelatedShapes(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current) { int i; clusterInfo* s; /* -------------------------------------------------------------------- */ /* Does this node overlap the area of interest at all? If not, */ /* return without adding to the list at all. */ /* -------------------------------------------------------------------- */ if(!msRectOverlap(&node->rect, ¤t->bounds)) return; /* Modify the feature count of the related shapes */ s = node->shapes; while (s) { if (layerinfo->fnCompare(current, s)) { ++current->numsiblings; /* calculating the average positions */ current->avgx = (current->avgx * current->numsiblings + s->x) / (current->numsiblings + 1); current->avgy = (current->avgy * current->numsiblings + s->y) / (current->numsiblings + 1); /* calculating the variance */ current->varx = current->varx * current->numsiblings / (current->numsiblings + 1) + (s->x - current->avgx) * (s->x - current->avgx) / (current->numsiblings + 1); current->vary = current->vary * current->numsiblings / (current->numsiblings + 1) + (s->y - current->avgy) * (s->y - current->avgy) / (current->numsiblings + 1); if (layerinfo->fnCompare(s, current)) { /* this feature falls into the region of the other as well */ ++s->numsiblings; /* calculating the average positions */ s->avgx = (s->avgx * s->numsiblings + current->x) / (s->numsiblings + 1); s->avgy = (s->avgy * s->numsiblings + current->y) / (s->numsiblings + 1); /* calculating the variance */ s->varx = s->varx * s->numsiblings / (s->numsiblings + 1) + (current->x - s->avgx) * (current->x - s->avgx) / (s->numsiblings + 1); s->vary = s->vary * s->numsiblings / (s->numsiblings + 1) + (current->y - s->avgy) * (current->y - s->avgy) / (s->numsiblings + 1); } } s = s->next; } if (node->subnode[0] == NULL) return; /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) findRelatedShapes(layerinfo, node->subnode[i], current); } } /* traverse the quadtree to find the neighbouring clusters and update data on the cluster*/ static void findRelatedShapes2(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current) { int i; clusterInfo* s; /* -------------------------------------------------------------------- */ /* Does this node overlap the area of interest at all? If not, */ /* return without adding to the list at all. */ /* -------------------------------------------------------------------- */ if(!msRectOverlap(&node->rect, ¤t->bounds)) return; /* Modify the feature count of the related shapes */ s = node->shapes; while (s) { if (layerinfo->fnCompare(s, current)) { if (layerinfo->rank > 0) { double r = (current->x - s->x) * (current->x - s->x) + (current->y - s->y) * (current->y - s->y); if (r < layerinfo->rank) { layerinfo->current = s; layerinfo->rank = r; } } else { /* no rank was specified, return immediately */ layerinfo->current = s; return; } } s = s->next; } if (node->subnode[0] == NULL) return; /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) findRelatedShapes2(layerinfo, node->subnode[i], current); } } /* traverse the quadtree to find the neighbouring shapes and update some data on the related shapes (when removing a feature) */ static void findRelatedShapesRemove(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current) { int i; clusterInfo* s; /* -------------------------------------------------------------------- */ /* Does this node overlap the area of interest at all? If not, */ /* return without adding to the list at all. */ /* -------------------------------------------------------------------- */ if(!msRectOverlap(&node->rect, ¤t->bounds)) return; /* Modify the feature count of the related shapes */ s = node->shapes; while (s) { if (layerinfo->fnCompare(current, s)) { if (s->numsiblings > 0) { /* calculating the average positions */ s->avgx = (s->avgx * (s->numsiblings + 1) - current->x) / s->numsiblings; s->avgy = (s->avgy * (s->numsiblings + 1) - current->y) / s->numsiblings; /* calculating the variance */ s->varx = (s->varx - (current->x - s->avgx) * (current->x - s->avgx) / s->numsiblings) * (s->numsiblings + 1) / s->numsiblings; s->vary = (s->vary - (current->y - s->avgy) * (current->y - s->avgy) / s->numsiblings) * (s->numsiblings + 1) / s->numsiblings; --s->numsiblings; ++s->numremoved; } } s = s->next; } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) findRelatedShapesRemove(layerinfo, node->subnode[i], current); } } /* setting the aggregated attributes */ static void InitShapeAttributes(layerObj* layer, clusterInfo* base) { int i; int* itemindexes = layer->iteminfo; for (i = 0; i < layer->numitems; i++) { if (base->shape.numvalues <= i) break; if (itemindexes[i] == MSCLUSTER_FEATURECOUNTINDEX) { if (base->shape.values[i]) msFree(base->shape.values[i]); base->shape.values[i] = msIntToString(base->numsiblings + 1); } else if (itemindexes[i] == MSCLUSTER_GROUPINDEX) { if (base->shape.values[i]) msFree(base->shape.values[i]); if (base->group) base->shape.values[i] = msStrdup(base->group); else base->shape.values[i] = msStrdup(""); } else if (itemindexes[i] == MSCLUSTER_BASEFIDINDEX) { if (base->shape.values[i]) msFree(base->shape.values[i]); base->shape.values[i] = msIntToString(base->shape.index); } else if (EQUALN(layer->items[i], "Count:", 6)) { if (base->shape.values[i]) msFree(base->shape.values[i]); base->shape.values[i] = msStrdup("1"); /* initial count */ } } } /* update the shape attributes (aggregate) */ static void UpdateShapeAttributes(layerObj* layer, clusterInfo* base, clusterInfo* current) { int i; int* itemindexes = layer->iteminfo; for (i = 0; i < layer->numitems; i++) { if (base->shape.numvalues <= i) break; if (itemindexes[i] == MSCLUSTER_FEATURECOUNTINDEX || itemindexes[i] == MSCLUSTER_GROUPINDEX) continue; if (current->shape.numvalues <= i) break; /* setting the base feature index for each cluster member */ if (itemindexes[i] == MSCLUSTER_BASEFIDINDEX) { msFree(current->shape.values[i]); current->shape.values[i] = msIntToString(base->shape.index); } if (current->shape.values[i]) { if (EQUALN(layer->items[i], "Min:", 4)) { if (strcasecmp(base->shape.values[i], current->shape.values[i]) > 0) { msFree(base->shape.values[i]); base->shape.values[i] = msStrdup(current->shape.values[i]); } } else if (EQUALN(layer->items[i], "Max:", 4)) { if (strcasecmp(base->shape.values[i], current->shape.values[i]) < 0) { msFree(base->shape.values[i]); base->shape.values[i] = msStrdup(current->shape.values[i]); } } else if (EQUALN(layer->items[i], "Sum:", 4)) { double sum = atof(base->shape.values[i]) + atof(current->shape.values[i]); msFree(base->shape.values[i]); base->shape.values[i] = msDoubleToString(sum, MS_FALSE); } else if (EQUALN(layer->items[i], "Count:", 6)) { int count = atoi(base->shape.values[i]) + 1; msFree(base->shape.values[i]); base->shape.values[i] = msIntToString(count); } } } } static int BuildFeatureAttributes(layerObj* layer, msClusterLayerInfo* layerinfo, shapeObj* shape) { char** values; int i; int* itemindexes = layer->iteminfo; if (layer->numitems == layerinfo->srcLayer.numitems) return MS_SUCCESS; /* we don't have custom attributes, no need to reconstruct the array */ values = msSmallMalloc(sizeof(char*) * (layer->numitems)); for (i = 0; i < layer->numitems; i++) { if (itemindexes[i] == MSCLUSTER_FEATURECOUNTINDEX) { values[i] = NULL; /* not yet assigned */ } else if (itemindexes[i] == MSCLUSTER_GROUPINDEX) { values[i] = NULL; /* not yet assigned */ } else if (itemindexes[i] == MSCLUSTER_BASEFIDINDEX) { values[i] = NULL; /* not yet assigned */ } else if (shape->values[itemindexes[i]]) values[i] = msStrdup(shape->values[itemindexes[i]]); else values[i] = msStrdup(""); } if (shape->values) msFreeCharArray(shape->values, shape->numvalues); shape->values = values; shape->numvalues = layer->numitems; return MS_SUCCESS; } /* traverse the quadtree to find the best renking cluster */ static void findBestCluster(layerObj* layer, msClusterLayerInfo* layerinfo, clusterTreeNode *node) { int i; double rank; clusterInfo* s = node->shapes; while (s) { if (s->filter < 0 && layer->cluster.filter.string != NULL) { InitShapeAttributes(layer, s); s->filter = msClusterEvaluateFilter(&layer->cluster.filter, &s->shape); } if (s->numsiblings == 0 || s->filter == 0) { /* individual or filtered shapes must be removed for sure */ layerinfo->current = s; return; } /* calculating the rank */ rank = (s->x - s->avgx) * (s->x - s->avgx) + (s->y - s->avgy) * (s->y - s->avgy) /*+ s->varx + s->vary*/ + (double)1/ (1 + s->numsiblings); if (rank < layerinfo->rank) { layerinfo->current = s; layerinfo->rank = rank; } s = s->next; } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) findBestCluster(layer, layerinfo, node->subnode[i]); } } /* adding the shape based on the shape bounds (point) */ static int treeNodeAddShape(msClusterLayerInfo* layerinfo, clusterTreeNode* node, clusterInfo* shape, int depth) { int i; /* -------------------------------------------------------------------- */ /* If there are subnodes, then consider whether this object */ /* will fit in them. */ /* -------------------------------------------------------------------- */ if( depth > 1 && node->subnode[0] != NULL ) { for(i = 0; i < 4; i++ ) { if( msRectContained(&shape->shape.bounds, &node->subnode[i]->rect)) { return treeNodeAddShape( layerinfo, node->subnode[i], shape, depth-1); } } } /* -------------------------------------------------------------------- */ /* Otherwise, consider creating four subnodes if could fit into */ /* them, and adding to the appropriate subnode. */ /* -------------------------------------------------------------------- */ else if( depth > 1 && node->subnode[0] == NULL ) { rectObj half1, half2, quad1, quad2, quad3, quad4; int subnode = -1; treeSplitBounds(&node->rect, &half1, &half2); treeSplitBounds(&half1, &quad1, &quad2); treeSplitBounds(&half2, &quad3, &quad4); if(msRectContained(&shape->shape.bounds, &quad1)) subnode = 0; else if(msRectContained(&shape->shape.bounds, &quad2)) subnode = 1; else if(msRectContained(&shape->shape.bounds, &quad3)) subnode = 2; else if(msRectContained(&shape->shape.bounds, &quad4)) subnode = 3; if (subnode >= 0) { if ((node->subnode[0] = clusterTreeNodeCreate(layerinfo, quad1)) == NULL) return MS_FAILURE; node->subnode[0]->position = node->position * 4; if ((node->subnode[1] = clusterTreeNodeCreate(layerinfo, quad2)) == NULL) return MS_FAILURE; node->subnode[1]->position = node->position * 4 + 1; if ((node->subnode[2] = clusterTreeNodeCreate(layerinfo, quad3)) == NULL) return MS_FAILURE; node->subnode[2]->position = node->position * 4 + 2; if ((node->subnode[3] = clusterTreeNodeCreate(layerinfo, quad4)) == NULL) return MS_FAILURE; node->subnode[3]->position = node->position * 4 + 3; /* add to subnode */ return treeNodeAddShape(layerinfo, node->subnode[subnode], shape, depth-1); } } /* found the right place, add this shape to the node */ node->numshapes++; shape->next = node->shapes; node->shapes = shape; shape->node = node; return MS_SUCCESS; } /* collecting the cluster shapes, returns true if this subnode must be removed */ static int collectClusterShapes(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo* current) { int i; clusterInfo* prev = NULL; clusterInfo* s = node->shapes; if(!msRectOverlap(&node->rect, ¤t->bounds)) return (!node->shapes && !node->subnode[0] && !node->subnode[1] && !node->subnode[2] && !node->subnode[3]); /* removing the shapes from this node if overlap with the cluster */ while (s) { if (s == current || layerinfo->fnCompare(current, s)) { if (s != current && current->filter == 0) { /* skip siblings of the filtered shapes */ prev = s; s = prev->next; continue; } /* removing from the list */ if (!prev) node->shapes = s->next; else prev->next = s->next; ++current->numcollected; /* adding the shape to the finalization list */ if (s == current) { if (s->filter) { s->next = layerinfo->finalized; layerinfo->finalized = s; ++layerinfo->numFinalized; } else { /* this shape is filtered */ s->next = layerinfo->filtered; layerinfo->filtered = s; ++layerinfo->numFiltered; } } else { s->next = layerinfo->finalizedSiblings; layerinfo->finalizedSiblings = s; ++layerinfo->numFinalizedSiblings; } if (!prev) s = node->shapes; else s = prev->next; } else { prev = s; s = prev->next; } } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i] && collectClusterShapes(layerinfo, node->subnode[i], current)) { /* placing this empty node to the finalization queue */ node->subnode[i]->subnode[0] = layerinfo->finalizedNodes; layerinfo->finalizedNodes = node->subnode[i]; node->subnode[i] = NULL; ++layerinfo->numFinalizedNodes; } } /* returns true is this subnode must be removed */ return (!node->shapes && !node->subnode[0] && !node->subnode[1] && !node->subnode[2] && !node->subnode[3]); } /* collecting the cluster shapes, returns true if this subnode must be removed */ static int collectClusterShapes2(layerObj* layer, msClusterLayerInfo* layerinfo, clusterTreeNode *node) { int i; clusterInfo* current = NULL; clusterInfo* s; while (node->shapes) { s = node->shapes; /* removing from the list */ node->shapes = s->next; InitShapeAttributes(layer, s); if (s->filter) { s->next = layerinfo->finalized; layerinfo->finalized = s; ++layerinfo->numFinalized; } else { /* this shape is filtered */ s->next = layerinfo->filtered; layerinfo->filtered = s; ++layerinfo->numFiltered; } /* update the parameters of the related shapes if any */ if (s->siblings) { current = s->siblings; while(current) { UpdateShapeAttributes(layer, s, current); /* setting the average position to the cluster position */ current->avgx = s->x; current->avgy = s->y; if (current->next == NULL) { if (layerinfo->get_all_shapes == MS_TRUE) { /* insert the siblings into the finalization list */ current->next = layerinfo->finalized; layerinfo->finalized = s->siblings; s->siblings = NULL; } break; } current = current->next; } } } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i] && collectClusterShapes2(layer, layerinfo, node->subnode[i])) { /* placing this empty node to the finalization queue */ node->subnode[i]->subnode[0] = layerinfo->finalizedNodes; layerinfo->finalizedNodes = node->subnode[i]; node->subnode[i] = NULL; ++layerinfo->numFinalizedNodes; } } /* returns true is this subnode must be removed */ return (!node->shapes && !node->subnode[0] && !node->subnode[1] && !node->subnode[2] && !node->subnode[3]); } int selectClusterShape(layerObj* layer, long shapeindex) { int i; clusterInfo* current; msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer not open: %s", "selectClusterShape()", layer->name); return MS_FAILURE; } i = 0; current = layerinfo->finalized; while (current && i < shapeindex) { ++i; current = current->next; } current->next = current->siblings; layerinfo->current = current; if (layerinfo->keep_locations == MS_FALSE) { current->shape.line[0].point[0].x = current->shape.bounds.minx = current->shape.bounds.maxx = current->avgx; current->shape.line[0].point[0].y = current->shape.bounds.miny = current->shape.bounds.maxy = current->avgy; } return MS_SUCCESS; } /* update the parameters from the related shapes */ #ifdef ms_notused static void UpdateClusterParameters(msClusterLayerInfo* layerinfo, clusterTreeNode *node, clusterInfo *shape) { int i; clusterInfo* s = node->shapes; while (s) { if (layerinfo->fnCompare(shape, s)) { shape->avgx += s->x; shape->avgy += s->y; ++shape->numsiblings; } s = s->next; } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i]) UpdateClusterParameters(layerinfo, node->subnode[i], shape); } } /* check for the validity of the clusters added to the tree (for debug purposes) */ static int ValidateTree(msClusterLayerInfo* layerinfo, clusterTreeNode *node) { int i; int isValid = MS_TRUE; clusterInfo* s = node->shapes; while (s) { double avgx = s->avgx; double avgy = s->avgy; int numsiblings = s->numsiblings; s->avgx = 0; s->avgy = 0; s->numsiblings = 0; UpdateClusterParameters(layerinfo, layerinfo->root, s); if (numsiblings + 1 != s->numsiblings) isValid = MS_FALSE; else if ((avgx * s->numsiblings - s->avgx) / s->avgx > 0.000001) isValid = MS_FALSE; else if ((avgy * s->numsiblings - s->avgy) / s->avgy > 0.000001) isValid = MS_FALSE; s->avgx = avgx; s->avgy = avgy; s->numsiblings = numsiblings; if (isValid == MS_FALSE) return MS_FALSE; s = s->next; } /* Recurse to subnodes if they exist */ for (i = 0; i < 4; i++) { if (node->subnode[i] && ValidateTree(layerinfo, node->subnode[i]) == MS_FALSE) return MS_FALSE; } /* returns true if this node contains only valid clusters */ return MS_TRUE; } #endif /* rebuild the clusters according to the current extent */ int RebuildClusters(layerObj *layer, int isQuery) { mapObj* map; layerObj* srcLayer; double distance, maxDistanceX, maxDistanceY, cellSizeX, cellSizeY; rectObj searchrect; int status; clusterInfo* current; int depth; char *pszProcessing; #ifdef USE_CLUSTER_EXTERNAL int layerIndex; #endif msClusterLayerInfo* layerinfo = layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer is not open: %s", "RebuildClusters()", layer->name); return MS_FAILURE; } if (!layer->map) { msSetError(MS_MISCERR, "No map associated with this layer: %s", "RebuildClusters()", layer->name); return MS_FAILURE; } if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Clustering started.\n"); map = layer->map; layerinfo->current = layerinfo->finalized; /* restart */ /* check whether the simplified algorithm was selected */ pszProcessing = msLayerGetProcessingKey(layer, "CLUSTER_ALGORITHM"); if(pszProcessing && !strncasecmp(pszProcessing,"SIMPLE",6)) layerinfo->algorithm = MSCLUSTER_ALGORITHM_SIMPLE; else layerinfo->algorithm = MSCLUSTER_ALGORITHM_FULL; /* check whether all shapes should be returned from a query */ if(msLayerGetProcessingKey(layer, "CLUSTER_GET_ALL_SHAPES") != NULL) layerinfo->get_all_shapes = MS_TRUE; else layerinfo->get_all_shapes = MS_FALSE; /* check whether the location of the shapes should be preserved */ if(msLayerGetProcessingKey(layer, "CLUSTER_KEEP_LOCATIONS") != NULL) layerinfo->keep_locations = MS_TRUE; else layerinfo->keep_locations = MS_FALSE; /* check whether the maxdistance and the buffer parameters are specified in map units (scale independent clustering) */ if(msLayerGetProcessingKey(layer, "CLUSTER_USE_MAP_UNITS") != NULL) layerinfo->use_map_units = MS_TRUE; else layerinfo->use_map_units = MS_FALSE; /* identify the current extent */ if(layer->transform == MS_TRUE) searchrect = map->extent; else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } if (searchrect.minx == layerinfo->searchRect.minx && searchrect.miny == layerinfo->searchRect.miny && searchrect.maxx == layerinfo->searchRect.maxx && searchrect.maxy == layerinfo->searchRect.maxy) { /* already built */ return MS_SUCCESS; } /* destroy previous data*/ clusterDestroyData(layerinfo); layerinfo->searchRect = searchrect; /* reproject the rectangle to layer coordinates */ #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif /* determine the compare method */ layerinfo->fnCompare = CompareRectangleRegion; if (layer->cluster.region) { if (EQUAL(layer->cluster.region, "ellipse")) layerinfo->fnCompare = CompareEllipseRegion; } /* trying to find a reasonable quadtree depth */ depth = 0; distance = layer->cluster.maxdistance; if (layerinfo->use_map_units == MS_TRUE) { while ((distance < (searchrect.maxx - searchrect.minx) || distance < (searchrect.maxy - searchrect.miny)) && depth <= TREE_MAX_DEPTH) { distance *= 2; ++depth; } cellSizeX = 1; cellSizeY = 1; } else { while ((distance < map->width || distance < map->height) && depth <= TREE_MAX_DEPTH) { distance *= 2; ++depth; } cellSizeX = MS_CELLSIZE(searchrect.minx, searchrect.maxx, map->width); cellSizeY = MS_CELLSIZE(searchrect.miny, searchrect.maxy, map->height); } layerinfo->depth = depth; maxDistanceX = layer->cluster.maxdistance * cellSizeX; maxDistanceY = layer->cluster.maxdistance * cellSizeY; /* increase the search rectangle so that the neighbouring shapes are also retrieved */ searchrect.minx -= layer->cluster.buffer * cellSizeX; searchrect.maxx += layer->cluster.buffer * cellSizeX; searchrect.miny -= layer->cluster.buffer * cellSizeY; searchrect.maxy += layer->cluster.buffer * cellSizeY; /* create the root node */ if (layerinfo->root) clusterTreeNodeDestroy(layerinfo, layerinfo->root); layerinfo->root = clusterTreeNodeCreate(layerinfo, searchrect); srcLayer = &layerinfo->srcLayer; /* start retrieving the shapes */ status = msLayerWhichShapes(srcLayer, searchrect, isQuery); if(status == MS_DONE) { /* no overlap */ return MS_SUCCESS; } else if(status != MS_SUCCESS) { return MS_FAILURE; } /* step through the source shapes and populate the quadtree with the tentative clusters */ if ((current = clusterInfoCreate(layerinfo)) == NULL) return MS_FAILURE; while((status = msLayerNextShape(srcLayer, ¤t->shape)) == MS_SUCCESS) { #if defined(USE_PROJ) && defined(USE_CLUSTER_EXTERNAL) /* transform the shape to the projection of this layer */ if(srcLayer->transform == MS_TRUE && srcLayer->project && layer->transform == MS_TRUE && layer->project &&msProjectionsDiffer(&(srcLayer->projection), &(layer->projection))) msProjectShape(&srcLayer->projection, &layer->projection, ¤t->shape); #endif /* set up positions and variance */ current->avgx = current->x = current->shape.bounds.minx; current->avgy = current->y = current->shape.bounds.miny; current->varx = current->vary = 0; /* set up the area of interest when searching for the neighboring shapes */ current->bounds.minx = current->x - maxDistanceX; current->bounds.miny = current->y - maxDistanceY; current->bounds.maxx = current->x + maxDistanceX; current->bounds.maxy = current->y + maxDistanceY; /* if the shape doesn't overlap we must skip it to avoid further issues */ if(!msRectOverlap(&searchrect, ¤t->bounds)) { msFreeShape(¤t->shape); msInitShape(¤t->shape); msDebug("Skipping an invalid shape falling outside of the given extent\n"); continue; } /* construct the item array */ if (layer->iteminfo) BuildFeatureAttributes(layer, layerinfo, ¤t->shape); /* evaluate the group expression */ if (layer->cluster.group.string) current->group = msClusterGetGroupText(&layer->cluster.group, ¤t->shape); if (layerinfo->algorithm == MSCLUSTER_ALGORITHM_FULL) { /*start a query for the related shapes */ findRelatedShapes(layerinfo, layerinfo->root, current); /* add this shape to the tree */ if (treeNodeAddShape(layerinfo, layerinfo->root, current, depth) != MS_SUCCESS) { clusterInfoDestroyList(layerinfo, current); return MS_FAILURE; } } else if (layerinfo->algorithm == MSCLUSTER_ALGORITHM_SIMPLE) { /* find a related cluster and try to assign */ layerinfo->rank = 0; layerinfo->current = NULL; findRelatedShapes2(layerinfo, layerinfo->root, current); if (layerinfo->current) { /* store these points until all clusters are created */ current->next = layerinfo->finalizedSiblings; layerinfo->finalizedSiblings = current; } else { /* if not found add this shape as a new cluster */ if (treeNodeAddShape(layerinfo, layerinfo->root, current, depth) != MS_SUCCESS) { clusterInfoDestroyList(layerinfo, current); return MS_FAILURE; } } } if ((current = clusterInfoCreate(layerinfo)) == NULL) { clusterInfoDestroyList(layerinfo, current); return MS_FAILURE; } } clusterInfoDestroyList(layerinfo, current); if (layerinfo->algorithm == MSCLUSTER_ALGORITHM_FULL) { while (layerinfo->root) { #ifdef TESTCOUNT int n; double avgx, avgy; #endif /* pick up the best cluster from the tree and do the finalization */ /* the initial rank must be big enough */ layerinfo->rank = (searchrect.maxx - searchrect.minx) * (searchrect.maxx - searchrect.minx) + (searchrect.maxy - searchrect.miny) * (searchrect.maxy - searchrect.miny) + 1; layerinfo->current = NULL; findBestCluster(layer, layerinfo, layerinfo->root); if (layerinfo->current == NULL) { if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Clustering terminated.\n"); break; /* completed */ } /* Update the feature count of the shape */ InitShapeAttributes(layer, layerinfo->current); /* collecting the shapes of the cluster */ collectClusterShapes(layerinfo, layerinfo->root, layerinfo->current); if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("processing cluster %p: rank=%lf fcount=%d ncoll=%d nfin=%d nfins=%d nflt=%d bounds={%lf %lf %lf %lf}\n", layerinfo->current, layerinfo->rank, layerinfo->current->numsiblings + 1, layerinfo->current->numcollected, layerinfo->numFinalized, layerinfo->numFinalizedSiblings, layerinfo->numFiltered, layerinfo->current->bounds.minx, layerinfo->current->bounds.miny, layerinfo->current->bounds.maxx, layerinfo->current->bounds.maxy); if (layerinfo->current->node) { char pszBuffer[TREE_MAX_DEPTH + 1]; clusterTreeNode* node = layerinfo->current->node; int position = node->position; int i = 1; while (position > 0 && i <= TREE_MAX_DEPTH) { pszBuffer[TREE_MAX_DEPTH - i] = '0' + (position % 4); position = position >> 2; ++i; } pszBuffer[TREE_MAX_DEPTH] = 0; msDebug(" ->node %p: count=%d index=%d pos=%s subn={%p %p %p %p} rect={%lf %lf %lf %lf}\n", node, node->numshapes, node->index, pszBuffer + TREE_MAX_DEPTH - i + 1, node->subnode[0], node->subnode[1], node->subnode[2], node->subnode[3], node->rect.minx, node->rect.miny, node->rect.maxx, node->rect.maxy); } } #ifdef TESTCOUNT avgx = layerinfo->current->x; avgy = layerinfo->current->y; n = 0; #endif if (layerinfo->current->numsiblings > 0) { /* update the parameters due to the shape removal */ findRelatedShapesRemove(layerinfo, layerinfo->root, layerinfo->current); if (layerinfo->current->filter == 0) { /* filtered shapes has no siblings */ layerinfo->current->numsiblings = 0; layerinfo->current->avgx = layerinfo->current->x; layerinfo->current->avgy = layerinfo->current->y; } /* update the parameters of the related shapes if any */ if (layerinfo->finalizedSiblings) { current = layerinfo->finalizedSiblings; while(current) { /* update the parameters due to the shape removal */ findRelatedShapesRemove(layerinfo, layerinfo->root, current); UpdateShapeAttributes(layer, layerinfo->current, current); #ifdef TESTCOUNT avgx += current->x; avgy += current->y; ++n; #endif /* setting the average position to the same value */ current->avgx = layerinfo->current->avgx; current->avgy = layerinfo->current->avgy; if (current->next == NULL) { if (layerinfo->get_all_shapes == MS_TRUE) { /* insert the siblings into the finalization list */ current->next = layerinfo->finalized; layerinfo->finalized = layerinfo->finalizedSiblings; } else { /* preserve the clustered siblings for later use */ layerinfo->current->siblings = layerinfo->finalizedSiblings; } break; } current = current->next; } layerinfo->finalizedSiblings = NULL; } } #ifdef TESTCOUNT avgx /= (n + 1); avgy /= (n + 1); if (layerinfo->current->numsiblings != n) layerinfo->current->numsiblings = n; if (fabs(layerinfo->current->avgx - avgx) / avgx > 0.000000001 || fabs(layerinfo->current->avgy - avgy) / avgy > 0.000000001) { layerinfo->current->avgx = avgx; layerinfo->current->avgy = avgy; } #endif } } else if (layerinfo->algorithm == MSCLUSTER_ALGORITHM_SIMPLE) { /* assingn stired points to clusters */ while (layerinfo->finalizedSiblings) { current = layerinfo->finalizedSiblings; layerinfo->rank = maxDistanceX * maxDistanceX + maxDistanceY * maxDistanceY; layerinfo->current = NULL; findRelatedShapes2(layerinfo, layerinfo->root, current); if (layerinfo->current) { clusterInfo* s = layerinfo->current; /* found a matching cluster */ ++s->numsiblings; /* assign to cluster */ layerinfo->finalizedSiblings = current->next; current->next = s->siblings; s->siblings = current; } else { /* this appears to be a bug */ layerinfo->finalizedSiblings = current->next; current->next = layerinfo->filtered; layerinfo->filtered = current; ++layerinfo->numFiltered; } } /* collecting the shapes of the cluster */ collectClusterShapes2(layer, layerinfo, layerinfo->root); } /* set the pointer to the first shape */ layerinfo->current = layerinfo->finalized; return MS_SUCCESS; } /* Close the the combined layer */ int msClusterLayerClose(layerObj *layer) { msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) return MS_SUCCESS; clusterDestroyData(layerinfo); msLayerClose(&layerinfo->srcLayer); freeLayer(&layerinfo->srcLayer); msFree(layerinfo); layer->layerinfo = NULL; #ifndef USE_CLUSTER_EXTERNAL /* switch back to the source layer vtable */ msInitializeVirtualTable(layer); #endif return MS_SUCCESS; } /* Return MS_TRUE if layer is open, MS_FALSE otherwise. */ int msClusterLayerIsOpen(layerObj *layer) { if (layer->layerinfo) return(MS_TRUE); else return(MS_FALSE); } /* Free the itemindexes array in a layer. */ void msClusterLayerFreeItemInfo(layerObj *layer) { msFree(layer->iteminfo); layer->iteminfo = NULL; } /* allocate the iteminfo index array - same order as the item list */ int msClusterLayerInitItemInfo(layerObj *layer) { int i, numitems; int *itemindexes; msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if(layer->numitems == 0) { return MS_SUCCESS; } if (!layerinfo) return MS_FAILURE; /* Cleanup any previous item selection */ msClusterLayerFreeItemInfo(layer); layer->iteminfo = (int *) msSmallMalloc(sizeof(int) * layer->numitems); itemindexes = layer->iteminfo; /* check whether we require attributes from the source layers also */ numitems = 0; for (i = 0; i < layer->numitems; i++) { if (EQUAL(layer->items[i], MSCLUSTER_FEATURECOUNT)) itemindexes[i] = MSCLUSTER_FEATURECOUNTINDEX; else if (EQUAL(layer->items[i], MSCLUSTER_GROUP)) itemindexes[i] = MSCLUSTER_GROUPINDEX; else if (EQUAL(layer->items[i], MSCLUSTER_BASEFID)) itemindexes[i] = MSCLUSTER_BASEFIDINDEX; else itemindexes[i] = numitems++; } msLayerFreeItemInfo(&layerinfo->srcLayer); if(layerinfo->srcLayer.items) { msFreeCharArray(layerinfo->srcLayer.items, layerinfo->srcLayer.numitems); layerinfo->srcLayer.items = NULL; layerinfo->srcLayer.numitems = 0; } if (numitems > 0) { /* now allocate and set the layer item parameters */ layerinfo->srcLayer.items = (char **)msSmallMalloc(sizeof(char *)*numitems); layerinfo->srcLayer.numitems = numitems; for (i = 0; i < layer->numitems; i++) { if (itemindexes[i] >= 0) { if (EQUALN(layer->items[i], "Min:", 4)) layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i] + 4); else if (EQUALN(layer->items[i], "Max:", 4)) layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i] + 4); else if (EQUALN(layer->items[i], "Sum:", 4)) layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i] + 4); else if (EQUALN(layer->items[i], "Count:", 6)) layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i] + 6); else layerinfo->srcLayer.items[itemindexes[i]] = msStrdup(layer->items[i]); } } if (msLayerInitItemInfo(&layerinfo->srcLayer) != MS_SUCCESS) return MS_FAILURE; } return MS_SUCCESS; } /* Execute a query for this layer */ int msClusterLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { /* rebuild the cluster database */ return RebuildClusters(layer, isQuery); } static int prepareShape(layerObj* layer, msClusterLayerInfo* layerinfo, clusterInfo* current, shapeObj* shape) { if (msCopyShape(&(current->shape), shape) != MS_SUCCESS) { msSetError(MS_SHPERR, "Cannot retrieve inline shape. There some problem with the shape", "msClusterLayerNextShape()"); return MS_FAILURE; } /* update the positions of the cluster shape */ if (layerinfo->keep_locations == MS_FALSE) { shape->line[0].point[0].x = shape->bounds.minx = shape->bounds.maxx = current->avgx; shape->line[0].point[0].y = shape->bounds.miny = shape->bounds.maxy = current->avgy; } return MS_SUCCESS; } /* Execute a query on the DB based on fid. */ int msClusterLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { clusterInfo* current; msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer not open: %s", "msClusterLayerGetShape()", layer->name); return MS_FAILURE; } current = layerinfo->finalized; while (current) { if (record->shapeindex == current->shape.index && record->tileindex == current->shape.tileindex) break; current = current->next; } if (current == NULL) { msSetError(MS_SHPERR, "No feature with this index.", "msClusterLayerGetShape()"); return MS_FAILURE; } return prepareShape(layer, layerinfo, current, shape); } /* find the next shape with the appropriate shape type */ /* also, load in the attribute data */ /* MS_DONE => no more data */ int msClusterLayerNextShape(layerObj *layer, shapeObj *shape) { int rv; msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer not open: %s", "msClusterLayerNextShape()", layer->name); return MS_FAILURE; } if (!layerinfo->current) return MS_DONE; rv = prepareShape(layer, layerinfo, layerinfo->current, shape); layerinfo->current = layerinfo->current->next; return rv; } /* Query for the items collection */ int msClusterLayerGetItems(layerObj *layer) { /* we support certain built in attributes */ layer->numitems = MSCLUSTER_NUMITEMS; layer->items = msSmallMalloc(sizeof(char*) * (layer->numitems)); layer->items[0] = msStrdup(MSCLUSTER_FEATURECOUNT); layer->items[1] = msStrdup(MSCLUSTER_GROUP); layer->items[2] = msStrdup(MSCLUSTER_BASEFID); return msClusterLayerInitItemInfo(layer); } int msClusterLayerGetNumFeatures(layerObj *layer) { msClusterLayerInfo* layerinfo = (msClusterLayerInfo*)layer->layerinfo; if (!layerinfo) return -1; return layerinfo->numFinalized; } static int msClusterLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { /* TODO */ return MS_SUCCESS; } msClusterLayerInfo* msClusterInitialize(layerObj *layer) { msClusterLayerInfo *layerinfo =(msClusterLayerInfo*)msSmallMalloc(sizeof(msClusterLayerInfo)); layer->layerinfo = layerinfo; layerinfo->searchRect.minx = -1; layerinfo->searchRect.miny = -1; layerinfo->searchRect.maxx = -1; layerinfo->searchRect.maxy = -1; layerinfo->root = NULL; layerinfo->get_all_shapes = MS_FALSE; layerinfo->numFeatures = 0; layerinfo->numNodes = 0; layerinfo->finalized = NULL; layerinfo->numFinalized = 0; layerinfo->finalizedSiblings = NULL; layerinfo->numFinalizedSiblings = 0; layerinfo->filtered = NULL; layerinfo->numFiltered = 0; layerinfo->finalizedNodes = NULL; layerinfo->numFinalizedNodes = 0; return layerinfo; } int msClusterLayerOpen(layerObj *layer) { msClusterLayerInfo* layerinfo; if (layer->type != MS_LAYER_POINT) { msSetError(MS_MISCERR, "Only point layers are supported for clustering: %s", "msClusterLayerOpen()", layer->name); return MS_FAILURE; } if (!layer->map) return MS_FAILURE; if (layer->layerinfo) { if (layer->vtable->LayerOpen != msClusterLayerOpen) msLayerClose(layer); else return MS_SUCCESS; /* already open */ } layerinfo = msClusterInitialize(layer); if (!layer->layerinfo) return MS_FAILURE; /* prepare the source layer */ if(initLayer(&layerinfo->srcLayer, layer->map) == -1) return MS_FAILURE; #ifdef USE_CLUSTER_EXTERNAL if (!layer->map) return MS_FAILURE; layerIndex = msGetLayerIndex(layer->map, layer->connection); if (layerIndex < 0 && layerIndex >= layer->map->numlayers) { msSetError(MS_MISCERR, "No source layers specified in layer: %s", "msClusterLayerOpen()", layer->name); return MS_FAILURE; } if (layer->map->layers[layerIndex]->type != MS_LAYER_POINT) { msSetError(MS_MISCERR, "Only point layers are supported for cluster data source: %s", "msClusterLayerOpen()", layer->name); return MS_FAILURE; } if (msCopyLayer(&layerinfo->srcLayer, layer->map->layers[layerIndex]) != MS_SUCCESS) return(MS_FAILURE); #else /* hook the vtable to this driver, will be restored in LayerClose*/ if (!layer->vtable) { if (msInitializeVirtualTable(layer) != MS_SUCCESS) return MS_FAILURE; } msClusterLayerCopyVirtualTable(layer->vtable); if (msCopyLayer(&layerinfo->srcLayer, layer) != MS_SUCCESS) return(MS_FAILURE); #endif /* disable the connection pool for this layer */ msLayerSetProcessingKey(&layerinfo->srcLayer, "CLOSE_CONNECTION", "ALWAYS"); /* open the source layer */ if ( !layerinfo->srcLayer.vtable) { if (msInitializeVirtualTable(&layerinfo->srcLayer) != MS_SUCCESS) return MS_FAILURE; } if (layerinfo->srcLayer.vtable->LayerOpen(&layerinfo->srcLayer) != MS_SUCCESS) { return MS_FAILURE; } return MS_SUCCESS; } int msClusterLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) { msClusterLayerInfo* layerinfo = layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerTranslateFilter()", layer->name); return MS_FAILURE; } if (layerinfo->srcLayer.filter.type == MS_EXPRESSION && layerinfo->srcLayer.filter.tokens == NULL) msTokenizeExpression(&(layerinfo->srcLayer.filter), layer->items, &(layer->numitems)); return layerinfo->srcLayer.vtable->LayerTranslateFilter(&layerinfo->srcLayer, &layerinfo->srcLayer.filter, filteritem); } char* msClusterLayerEscapeSQLParam(layerObj *layer, const char* pszString) { msClusterLayerInfo* layerinfo = layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerEscapeSQLParam()", layer->name); return msStrdup(""); } return layerinfo->srcLayer.vtable->LayerEscapeSQLParam(&layerinfo->srcLayer, pszString); } int msClusterLayerGetAutoProjection(layerObj *layer, projectionObj* projection) { msClusterLayerInfo* layerinfo = layer->layerinfo; if (!layerinfo) { msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerGetAutoProjection()", layer->name); return MS_FAILURE; } return layerinfo->srcLayer.vtable->LayerGetAutoProjection(&layerinfo->srcLayer, projection); } int msClusterLayerGetPaging(layerObj *layer) { return MS_FALSE; } void msClusterLayerEnablePaging(layerObj *layer, int value) { return; } void msClusterLayerCopyVirtualTable(layerVTableObj* vtable) { vtable->LayerInitItemInfo = msClusterLayerInitItemInfo; vtable->LayerFreeItemInfo = msClusterLayerFreeItemInfo; vtable->LayerOpen = msClusterLayerOpen; vtable->LayerIsOpen = msClusterLayerIsOpen; vtable->LayerWhichShapes = msClusterLayerWhichShapes; vtable->LayerNextShape = msClusterLayerNextShape; vtable->LayerGetShape = msClusterLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ vtable->LayerClose = msClusterLayerClose; vtable->LayerGetItems = msClusterLayerGetItems; vtable->LayerCloseConnection = msClusterLayerClose; vtable->LayerGetNumFeatures = msClusterLayerGetNumFeatures; vtable->LayerGetAutoStyle = msClusterLayerGetAutoStyle; vtable->LayerTranslateFilter = msClusterLayerTranslateFilter; /* vtable->LayerSupportsCommonFilters, use driver implementation */ vtable->LayerEscapeSQLParam = msClusterLayerEscapeSQLParam; /* vtable->LayerEscapePropertyName, use driver implementation */ vtable->LayerEnablePaging = msClusterLayerEnablePaging; vtable->LayerGetPaging = msClusterLayerGetPaging; vtable->LayerGetAutoProjection = msClusterLayerGetAutoProjection; } #ifdef USE_CLUSTER_PLUGIN MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) { assert(layer != NULL); assert(vtable != NULL); msClusterLayerCopyVirtualTable(vtable); return MS_SUCCESS; } #endif int msClusterLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); msClusterLayerCopyVirtualTable(layer->vtable); return MS_SUCCESS; } mapserver-7.4.3/mapcompositingfilter.c000066400000000000000000000174511357574274700201710ustar00rootroot00000000000000/****************************************************************************** * * Project: MapServer * Purpose: RFC 113 Layer compositing * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2015 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include #define pixmove(rb,srcx,srcy,dstx,dsty) \ memcpy(rb->data.rgba.pixels+dsty*rb->data.rgba.row_step+dstx*4,\ rb->data.rgba.pixels+srcy*rb->data.rgba.row_step+srcx*4,\ 4) #define pixerase(rb,x,y) memset(rb->data.rgba.pixels+y*rb->data.rgba.row_step+x*4,0,4) void msApplyTranslationCompositingFilter(rasterBufferObj *rb, int xtrans, int ytrans) { int src_sx,src_sy,dst_sx,dst_sy,x,y,dst_x,dst_y; if(abs(xtrans)>=rb->width || abs(ytrans)>=rb->height) { for(y = 0; yheight; y++) for(x = 0; xwidth; x++) pixerase(rb,x,y); } if(xtrans == 0 && ytrans == 0) return; if(xtrans>=0) { if(ytrans>=0) { src_sx = rb->width - xtrans - 1; src_sy = rb->height - ytrans - 1; dst_sx = rb->width - 1; dst_sy = rb->height -1; for(y = src_sy,dst_y= dst_sy;y>=0;y--,dst_y--) { for(x = src_sx,dst_x= dst_sx;x>=0;x--,dst_x--) { pixmove(rb,x,y,dst_x,dst_y); } } for(y=0;ywidth;x++) pixerase(rb,x,y); for(y=ytrans;yheight;y++) for(x=0;xwidth - xtrans - 1; src_sy = - ytrans; dst_sx = rb->width - 1; dst_sy = 0; for(y = src_sy,dst_y= dst_sy;yheight;y++,dst_y++) { for(x = src_sx,dst_x= dst_sx;x>=0;x--,dst_x--) { pixmove(rb,x,y,dst_x,dst_y); } } for(y=0;yheight+ytrans;y++) for(x=0;xheight+ytrans;yheight;y++) for(x=0;xwidth;x++) pixerase(rb,x,y); } } else { if(ytrans>=0) { src_sx = - xtrans; src_sy = rb->height - ytrans - 1; dst_sx = 0; dst_sy = rb->height -1; for(y = src_sy,dst_y= dst_sy;y>=0;y--,dst_y--) { for(x = src_sx,dst_x= dst_sx;xwidth;x++,dst_x++) { pixmove(rb,x,y,dst_x,dst_y); } } for(y=0;ywidth;x++) pixerase(rb,x,y); for(y=ytrans;yheight;y++) for(x=rb->width+xtrans;xwidth;x++) pixerase(rb,x,y); } else { src_sx = - xtrans; src_sy = - ytrans; dst_sx = 0; dst_sy = 0; for(y = src_sy,dst_y= dst_sy;yheight;y++,dst_y++) { for(x = src_sx,dst_x= dst_sx;xwidth;x++,dst_x++) { pixmove(rb,x,y,dst_x,dst_y); } } for(y=0;yheight+ytrans;y++) for(x=rb->width+xtrans;xwidth;x++) pixerase(rb,x,y); for(y=rb->height+ytrans;yheight;y++) for(x=0;xwidth;x++) pixerase(rb,x,y); } } } void msApplyBlackeningCompositingFilter(rasterBufferObj *rb) { int row,col; unsigned char *r,*g,*b; for(row=0;rowheight;row++) { r = rb->data.rgba.r + row*rb->data.rgba.row_step; g = rb->data.rgba.g + row*rb->data.rgba.row_step; b = rb->data.rgba.b + row*rb->data.rgba.row_step; for(col=0;colwidth;col++) { *r = *g = *b = 0; r+=4;g+=4;b+=4; } } } void msApplyWhiteningCompositingFilter(rasterBufferObj *rb) { int row,col; unsigned char *r,*g,*b,*a; for(row=0;rowheight;row++) { r = rb->data.rgba.r + row*rb->data.rgba.row_step; g = rb->data.rgba.g + row*rb->data.rgba.row_step; b = rb->data.rgba.b + row*rb->data.rgba.row_step; a = rb->data.rgba.a + row*rb->data.rgba.row_step; for(col=0;colwidth;col++) { *r = *g = *b = *a; r+=4;g+=4;b+=4;a+=4; } } } void msApplyGrayscaleCompositingFilter(rasterBufferObj *rb) { int row,col; unsigned char *r,*g,*b; for(row=0;rowheight;row++) { r = rb->data.rgba.r + row*rb->data.rgba.row_step; g = rb->data.rgba.g + row*rb->data.rgba.row_step; b = rb->data.rgba.b + row*rb->data.rgba.row_step; for(col=0;colwidth;col++) { unsigned int mix = (unsigned int)*r + (unsigned int)*g + (unsigned int)*b; mix /=3; *r = *g = *b = (unsigned char)mix; r+=4;g+=4;b+=4; } } } int msApplyCompositingFilter(mapObj *map, rasterBufferObj *rb, CompositingFilter *filter) { int rstatus; regex_t regex; regmatch_t pmatch[3]; /* test for blurring filter */ regcomp(®ex, "blur\\(([0-9]+)\\)", REG_EXTENDED); rstatus = regexec(®ex, filter->filter, 2, pmatch, 0); regfree(®ex); if(!rstatus) { char *rad = malloc(pmatch[1].rm_eo - pmatch[1].rm_so + 1); unsigned int irad; strncpy(rad,filter->filter+pmatch[1].rm_so,pmatch[1].rm_eo-pmatch[1].rm_so); rad[pmatch[1].rm_eo - pmatch[1].rm_so]=0; //msDebug("got blur filter with radius %s\n",rad); irad = atoi(rad); free(rad); irad = MS_NINT(irad*map->resolution/map->defresolution); msApplyBlurringCompositingFilter(rb,irad); return MS_SUCCESS; } /* test for translation filter */ regcomp(®ex, "translate\\((-?[0-9]+),(-?[0-9]+)\\)", REG_EXTENDED); rstatus = regexec(®ex, filter->filter, 3, pmatch, 0); regfree(®ex); if(!rstatus) { char *num; int xtrans,ytrans; num = malloc(pmatch[1].rm_eo - pmatch[1].rm_so + 1); strncpy(num,filter->filter+pmatch[1].rm_so,pmatch[1].rm_eo-pmatch[1].rm_so); num[pmatch[1].rm_eo - pmatch[1].rm_so]=0; xtrans = atoi(num); free(num); num = malloc(pmatch[2].rm_eo - pmatch[2].rm_so + 1); strncpy(num,filter->filter+pmatch[2].rm_so,pmatch[2].rm_eo-pmatch[2].rm_so); num[pmatch[2].rm_eo - pmatch[2].rm_so]=0; ytrans = atoi(num); free(num); //msDebug("got translation filter of radius %d,%d\n",xtrans,ytrans); xtrans = MS_NINT(xtrans*map->resolution/map->defresolution); ytrans = MS_NINT(ytrans*map->resolution/map->defresolution); msApplyTranslationCompositingFilter(rb,xtrans,ytrans); return MS_SUCCESS; } /* test for grayscale filter */ if(!strncmp(filter->filter,"grayscale()",strlen("grayscale()"))) { msApplyGrayscaleCompositingFilter(rb); return MS_SUCCESS; } if(!strncmp(filter->filter,"blacken()",strlen("blacken()"))) { msApplyBlackeningCompositingFilter(rb); return MS_SUCCESS; } if(!strncmp(filter->filter,"whiten()",strlen("whiten()"))) { msApplyWhiteningCompositingFilter(rb); return MS_SUCCESS; } msSetError(MS_MISCERR,"unknown compositing filter (%s)", "msApplyCompositingFilter()", filter->filter); return MS_FAILURE; } mapserver-7.4.3/mapcontext.c000066400000000000000000002110251357574274700161050ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Web Map Context implementation * Author: Julien-Samuel Lacroix, DM Solutions Group (lacroix@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2002-2003, Julien-Samuel Lacroix, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #include "mapserver.h" #include "mapows.h" #if defined(USE_WMS_LYR) && defined(USE_OGR) /* There is a dependency to GDAL/OGR for the GML driver and MiniXML parser */ #include "cpl_minixml.h" #endif /* msGetMapContextFileText() ** ** Read a file and return is content ** ** Take the filename in argument ** Return value must be freed by caller */ char * msGetMapContextFileText(char *filename) { char *pszBuffer; FILE *stream; int nLength; /* open file */ if(filename != NULL && strlen(filename) > 0) { stream = fopen(filename, "rb"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename); return NULL; } } else { msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename); return NULL; } fseek( stream, 0, SEEK_END ); nLength = ftell( stream ); fseek( stream, 0, SEEK_SET ); pszBuffer = (char *) malloc(nLength+1); if( pszBuffer == NULL ) { msSetError(MS_MEMERR, "(%s)", "msGetMapContextFileText()", filename); fclose( stream ); return NULL; } if(fread( pszBuffer, nLength, 1, stream ) == 0 && !feof(stream)) { free( pszBuffer ); fclose( stream ); msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename); return NULL; } pszBuffer[nLength] = '\0'; fclose( stream ); return pszBuffer; } #if defined(USE_WMS_LYR) && defined(USE_OGR) /* **msGetMapContextXMLHashValue() ** **Get the xml value and put it in the hash table ** */ int msGetMapContextXMLHashValue( CPLXMLNode *psRoot, const char *pszXMLPath, hashTableObj *metadata, char *pszMetadata ) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( metadata != NULL ) { msInsertHashTable(metadata, pszMetadata, pszValue ); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* **msGetMapContextXMLHashValue() ** **Get the xml value and put it in the hash table ** */ int msGetMapContextXMLHashValueDecode( CPLXMLNode *psRoot, const char *pszXMLPath, hashTableObj *metadata, char *pszMetadata ) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( metadata != NULL ) { msDecodeHTMLEntities(pszValue); msInsertHashTable(metadata, pszMetadata, pszValue ); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* **msGetMapContextXMLStringValue() ** **Get the xml value and put it in the string field ** */ int msGetMapContextXMLStringValue( CPLXMLNode *psRoot, char *pszXMLPath, char **pszField) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( pszField != NULL ) { *pszField = msStrdup(pszValue); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* **msGetMapContextXMLStringValue() ** **Get the xml value and put it in the string field ** */ int msGetMapContextXMLStringValueDecode( CPLXMLNode *psRoot, char *pszXMLPath, char **pszField) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( pszField != NULL ) { msDecodeHTMLEntities(pszValue); *pszField = msStrdup(pszValue); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* **msGetMapContextXMLFloatValue() ** **Get the xml value and put it in the string field ** */ int msGetMapContextXMLFloatValue( CPLXMLNode *psRoot, char *pszXMLPath, double *pszField) { char *pszValue; pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL); if(pszValue != NULL) { if( pszField != NULL ) { *pszField = atof(pszValue); } else { return MS_FAILURE; } } else { return MS_FAILURE; } return MS_SUCCESS; } /* ** msLoadMapContextURLELements ** ** Take a Node and get the width, height, format and href from it. ** Then put this info in metadatas. */ int msLoadMapContextURLELements( CPLXMLNode *psRoot, hashTableObj *metadata, const char *pszMetadataRoot) { char *pszMetadataName; if( psRoot == NULL || metadata == NULL || pszMetadataRoot == NULL ) return MS_FAILURE; pszMetadataName = (char*) malloc( strlen(pszMetadataRoot) + 10 ); sprintf( pszMetadataName, "%s_width", pszMetadataRoot ); msGetMapContextXMLHashValue( psRoot, "width", metadata, pszMetadataName ); sprintf( pszMetadataName, "%s_height", pszMetadataRoot ); msGetMapContextXMLHashValue( psRoot, "height", metadata, pszMetadataName ); sprintf( pszMetadataName, "%s_format", pszMetadataRoot ); msGetMapContextXMLHashValue( psRoot, "format", metadata, pszMetadataName ); sprintf( pszMetadataName, "%s_href", pszMetadataRoot ); msGetMapContextXMLHashValue( psRoot, "OnlineResource.xlink:href", metadata, pszMetadataName ); free(pszMetadataName); return MS_SUCCESS; } /* msLoadMapContextKeyword ** ** Put the keywords from a XML node and put them in a metadata. ** psRoot should be set to keywordlist */ int msLoadMapContextListInMetadata( CPLXMLNode *psRoot, hashTableObj *metadata, char *pszXMLName, char *pszMetadataName, char *pszHashDelimiter) { const char *pszHash, *pszXMLValue; char *pszMetadata; if(psRoot == NULL || psRoot->psChild == NULL || metadata == NULL || pszMetadataName == NULL || pszXMLName == NULL) return MS_FAILURE; /* Pass from KeywordList to Keyword level */ psRoot = psRoot->psChild; /* Loop on all elements and append keywords to the hash table */ while (psRoot) { if (psRoot->psChild && strcasecmp(psRoot->pszValue, pszXMLName) == 0) { pszXMLValue = psRoot->psChild->pszValue; pszHash = msLookupHashTable(metadata, pszMetadataName); if (pszHash != NULL) { pszMetadata = (char*)malloc(strlen(pszHash)+ strlen(pszXMLValue)+2); if(pszHashDelimiter == NULL) sprintf( pszMetadata, "%s%s", pszHash, pszXMLValue ); else sprintf( pszMetadata, "%s%s%s", pszHash, pszHashDelimiter, pszXMLValue ); msInsertHashTable(metadata, pszMetadataName, pszMetadata); free(pszMetadata); } else msInsertHashTable(metadata, pszMetadataName, pszXMLValue); } psRoot = psRoot->psNext; } return MS_SUCCESS; } /* msLoadMapContextContactInfo ** ** Put the Contact informations from a XML node and put them in a metadata. ** */ int msLoadMapContextContactInfo( CPLXMLNode *psRoot, hashTableObj *metadata ) { if(psRoot == NULL || metadata == NULL) return MS_FAILURE; /* Contact Person primary */ msGetMapContextXMLHashValue(psRoot, "ContactPersonPrimary.ContactPerson", metadata, "wms_contactperson"); msGetMapContextXMLHashValue(psRoot, "ContactPersonPrimary.ContactOrganization", metadata, "wms_contactorganization"); /* Contact Position */ msGetMapContextXMLHashValue(psRoot, "ContactPosition", metadata, "wms_contactposition"); /* Contact Address */ msGetMapContextXMLHashValue(psRoot, "ContactAddress.AddressType", metadata, "wms_addresstype"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.Address", metadata, "wms_address"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.City", metadata, "wms_city"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.StateOrProvince", metadata, "wms_stateorprovince"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.PostCode", metadata, "wms_postcode"); msGetMapContextXMLHashValue(psRoot, "ContactAddress.Country", metadata, "wms_country"); /* Others */ msGetMapContextXMLHashValue(psRoot, "ContactVoiceTelephone", metadata, "wms_contactvoicetelephone"); msGetMapContextXMLHashValue(psRoot, "ContactFacsimileTelephone", metadata, "wms_contactfacsimiletelephone"); msGetMapContextXMLHashValue(psRoot, "ContactElectronicMailAddress", metadata, "wms_contactelectronicmailaddress"); return MS_SUCCESS; } /* ** msLoadMapContextLayerFormat ** ** */ int msLoadMapContextLayerFormat(CPLXMLNode *psFormat, layerObj *layer) { const char *pszValue; char *pszValue1; const char* pszHash; if(psFormat->psChild != NULL && strcasecmp(psFormat->pszValue, "Format") == 0 ) { if(psFormat->psChild->psNext == NULL) pszValue = psFormat->psChild->pszValue; else pszValue = psFormat->psChild->psNext->pszValue; } else pszValue = NULL; if(pszValue != NULL && strcasecmp(pszValue, "") != 0) { /* wms_format */ pszValue1 = (char*)CPLGetXMLValue(psFormat, "current", NULL); if(pszValue1 != NULL && (strcasecmp(pszValue1, "1") == 0 || strcasecmp(pszValue1, "true")==0)) msInsertHashTable(&(layer->metadata), "wms_format", pszValue); /* wms_formatlist */ pszHash = msLookupHashTable(&(layer->metadata), "wms_formatlist"); if(pszHash != NULL) { pszValue1 = (char*)malloc(strlen(pszHash)+ strlen(pszValue)+2); sprintf(pszValue1, "%s,%s", pszHash, pszValue); msInsertHashTable(&(layer->metadata), "wms_formatlist", pszValue1); free(pszValue1); } else msInsertHashTable(&(layer->metadata), "wms_formatlist", pszValue); } /* Make sure selected format is supported or select another * supported format. Note that we can efficiently do this * only for GIF/PNG/JPEG, can't try to handle all GDAL * formats. */ pszValue = msLookupHashTable(&(layer->metadata), "wms_format"); if ( pszValue && ( #if !(defined USE_PNG) strcasecmp(pszValue, "image/png") == 0 || strcasecmp(pszValue, "PNG") == 0 || #endif #if !(defined USE_JPEG) strcasecmp(pszValue, "image/jpeg") == 0 || strcasecmp(pszValue, "JPEG") == 0 || #endif 0 )) { char **papszList=NULL; int i, numformats=0; pszValue = msLookupHashTable(&(layer->metadata), "wms_formatlist"); papszList = msStringSplit(pszValue, ',', &numformats); for(i=0; i < numformats; i++) { if ( #if (defined USE_PNG) strcasecmp(papszList[i], "image/png") == 0 || strcasecmp(papszList[i], "PNG") == 0 || #endif #if (defined USE_JPEG) strcasecmp(papszList[i], "image/jpeg") == 0 || strcasecmp(papszList[i], "JPEG") == 0 || #endif #ifdef USE_GD_GIF strcasecmp(papszList[i], "image/gif") == 0 || strcasecmp(papszList[i], "GIF") == 0 || #endif 0 ) { /* Found a match */ msInsertHashTable(&(layer->metadata), "wms_format", papszList[i]); break; } } if(papszList) msFreeCharArray(papszList, numformats); } /* end if unsupported format */ return MS_SUCCESS; } int msLoadMapContextLayerStyle(CPLXMLNode *psStyle, layerObj *layer, int nStyle) { char *pszValue, *pszValue1, *pszValue2; const char *pszHash; char* pszStyle=NULL; char *pszStyleName; CPLXMLNode *psStyleSLDBody; pszStyleName =(char*)CPLGetXMLValue(psStyle,"Name",NULL); if(pszStyleName == NULL) { pszStyleName = (char*)malloc(20); sprintf(pszStyleName, "Style{%d}", nStyle); } else pszStyleName = msStrdup(pszStyleName); /* wms_style */ pszValue = (char*)CPLGetXMLValue(psStyle,"current",NULL); if(pszValue != NULL && (strcasecmp(pszValue, "1") == 0 || strcasecmp(pszValue, "true") == 0)) msInsertHashTable(&(layer->metadata), "wms_style", pszStyleName); /* wms_stylelist */ pszHash = msLookupHashTable(&(layer->metadata), "wms_stylelist"); if(pszHash != NULL) { pszValue1 = (char*)malloc(strlen(pszHash)+ strlen(pszStyleName)+2); sprintf(pszValue1, "%s,%s", pszHash, pszStyleName); msInsertHashTable(&(layer->metadata), "wms_stylelist", pszValue1); free(pszValue1); } else msInsertHashTable(&(layer->metadata), "wms_stylelist", pszStyleName); /* Title */ pszStyle = (char*)malloc(strlen(pszStyleName)+20); sprintf(pszStyle,"wms_style_%s_title",pszStyleName); if( msGetMapContextXMLHashValue(psStyle, "Title", &(layer->metadata), pszStyle) == MS_FAILURE ) msInsertHashTable(&(layer->metadata), pszStyle, layer->name); free(pszStyle); /* SLD */ pszStyle = (char*)malloc(strlen(pszStyleName)+15); sprintf(pszStyle, "wms_style_%s_sld", pszStyleName); msGetMapContextXMLHashValueDecode( psStyle, "SLD.OnlineResource.xlink:href", &(layer->metadata), pszStyle ); free(pszStyle); /* SLDBODY */ pszStyle = (char*)malloc(strlen(pszStyleName)+20); sprintf(pszStyle, "wms_style_%s_sld_body", pszStyleName); psStyleSLDBody = CPLGetXMLNode(psStyle, "SLD.StyledLayerDescriptor"); /*some clients such as OpenLayers add a name space, which I believe is wrong but added this additional test for compatibility #3115*/ if (psStyleSLDBody == NULL) psStyleSLDBody = CPLGetXMLNode(psStyle, "SLD.sld:StyledLayerDescriptor"); if(psStyleSLDBody != NULL && &(layer->metadata) != NULL) { pszValue = CPLSerializeXMLTree(psStyleSLDBody); if(pszValue != NULL) { /* Before including SLDBody in the mapfile, we must replace the */ /* double quote for single quote. This is to prevent having this: */ /* "metadata" "" */ char *c; for(c=pszValue; *c != '\0'; c++) if(*c == '"') *c = '\''; msInsertHashTable(&(layer->metadata), pszStyle, pszValue ); msFree(pszValue); } } free(pszStyle); /* LegendURL */ pszStyle = (char*) malloc(strlen(pszStyleName) + 25); sprintf( pszStyle, "wms_style_%s_legendurl", pszStyleName); msLoadMapContextURLELements( CPLGetXMLNode(psStyle, "LegendURL"), &(layer->metadata), pszStyle ); free(pszStyle); free(pszStyleName); /* */ /* Add the stylelist to the layer connection */ /* */ if(msLookupHashTable(&(layer->metadata), "wms_stylelist") == NULL) { if(layer->connection) pszValue = msStrdup(layer->connection); else pszValue = msStrdup( "" ); pszValue1 = strstr(pszValue, "STYLELIST="); if(pszValue1 != NULL) { pszValue1 += 10; pszValue2 = strchr(pszValue, '&'); if(pszValue2 != NULL) pszValue1[pszValue2-pszValue1] = '\0'; msInsertHashTable(&(layer->metadata), "wms_stylelist", pszValue1); } free(pszValue); } /* */ /* Add the style to the layer connection */ /* */ if(msLookupHashTable(&(layer->metadata), "wms_style") == NULL) { if(layer->connection) pszValue = msStrdup(layer->connection); else pszValue = msStrdup( "" ); pszValue1 = strstr(pszValue, "STYLE="); if(pszValue1 != NULL) { pszValue1 += 6; pszValue2 = strchr(pszValue, '&'); if(pszValue2 != NULL) pszValue1[pszValue2-pszValue1] = '\0'; msInsertHashTable(&(layer->metadata), "wms_style", pszValue1); } free(pszValue); } return MS_SUCCESS; } int msLoadMapContextLayerDimension(CPLXMLNode *psDimension, layerObj *layer) { char *pszValue; const char *pszHash; char *pszDimension=NULL, *pszDimensionName=NULL; pszDimensionName =(char*)CPLGetXMLValue(psDimension,"name",NULL); if(pszDimensionName == NULL) { return MS_FALSE; } else pszDimensionName = msStrdup(pszDimensionName); pszDimension = (char*)malloc(strlen(pszDimensionName)+50); /* wms_dimension: This is the current dimension */ pszValue = (char*)CPLGetXMLValue(psDimension, "current", NULL); if(pszValue != NULL && (strcasecmp(pszValue, "1") == 0 || strcasecmp(pszValue, "true") == 0)) msInsertHashTable(&(layer->metadata), "wms_dimension", pszDimensionName); /* wms_dimensionlist */ pszHash = msLookupHashTable(&(layer->metadata), "wms_dimensionlist"); if(pszHash != NULL) { pszValue = (char*)malloc(strlen(pszHash)+ strlen(pszDimensionName)+2); sprintf(pszValue, "%s,%s", pszHash, pszDimensionName); msInsertHashTable(&(layer->metadata), "wms_dimensionlist", pszValue); free(pszValue); } else msInsertHashTable(&(layer->metadata), "wms_dimensionlist", pszDimensionName); /* Units */ sprintf(pszDimension, "wms_dimension_%s_units", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "units", &(layer->metadata), pszDimension); /* UnitSymbol */ sprintf(pszDimension, "wms_dimension_%s_unitsymbol", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "unitSymbol", &(layer->metadata), pszDimension); /* userValue */ sprintf(pszDimension, "wms_dimension_%s_uservalue", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "userValue", &(layer->metadata), pszDimension); if(strcasecmp(pszDimensionName, "time") == 0) msGetMapContextXMLHashValue(psDimension, "userValue", &(layer->metadata), "wms_time"); /* default */ sprintf(pszDimension, "wms_dimension_%s_default", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "default", &(layer->metadata), pszDimension); /* multipleValues */ sprintf(pszDimension, "wms_dimension_%s_multiplevalues", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "multipleValues",&(layer->metadata), pszDimension); /* nearestValue */ sprintf(pszDimension, "wms_dimension_%s_nearestvalue", pszDimensionName); msGetMapContextXMLHashValue(psDimension, "nearestValue", &(layer->metadata), pszDimension); free(pszDimension); free(pszDimensionName); return MS_SUCCESS; } /* ** msLoadMapContextGeneral ** ** Load the General block of the mapcontext document */ int msLoadMapContextGeneral(mapObj *map, CPLXMLNode *psGeneral, CPLXMLNode *psMapContext, int nVersion, char *filename) { char *pszProj=NULL; char *pszValue, *pszValue1, *pszValue2; int nTmp; /* Projection */ pszValue = (char*)CPLGetXMLValue(psGeneral, "BoundingBox.SRS", NULL); if(pszValue != NULL) { if(strncasecmp(pszValue, "AUTO:", 5) == 0) { pszProj = msStrdup(pszValue); } else { pszProj = (char*) malloc(sizeof(char)*(strlen(pszValue)+10)); sprintf(pszProj, "init=epsg:%s", pszValue+5); } msInitProjection(&map->projection); map->projection.args[map->projection.numargs] = msStrdup(pszProj); map->projection.numargs++; msProcessProjection(&map->projection); if( (nTmp = GetMapserverUnitUsingProj(&(map->projection))) == -1) { free(pszProj); msSetError( MS_MAPCONTEXTERR, "Unable to set units for projection '%s'", "msLoadMapContext()", pszProj ); return MS_FAILURE; } else { map->units = nTmp; } free(pszProj); } else { msDebug("Mandatory data General.BoundingBox.SRS missing in %s.", filename); } /* Extent */ if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.minx", &(map->extent.minx)) == MS_FAILURE) { msDebug("Mandatory data General.BoundingBox.minx missing in %s.", filename); } if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.miny", &(map->extent.miny)) == MS_FAILURE) { msDebug("Mandatory data General.BoundingBox.miny missing in %s.", filename); } if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.maxx", &(map->extent.maxx)) == MS_FAILURE) { msDebug("Mandatory data General.BoundingBox.maxx missing in %s.", filename); } if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.maxy", &(map->extent.maxy)) == MS_FAILURE) { msDebug("Mandatory data General.BoundingBox.maxy missing in %s.", filename); } /* Title */ if( msGetMapContextXMLHashValue(psGeneral, "Title", &(map->web.metadata), "wms_title") == MS_FAILURE) { if ( nVersion >= OWS_1_0_0 ) msDebug("Mandatory data General.Title missing in %s.", filename); else { if( msGetMapContextXMLHashValue(psGeneral, "gml:name", &(map->web.metadata), "wms_title") == MS_FAILURE ) { if( nVersion < OWS_0_1_7 ) msDebug("Mandatory data General.Title missing in %s.", filename); else msDebug("Mandatory data General.gml:name missing in %s.", filename); } } } /* Name */ if( nVersion >= OWS_1_0_0 ) { pszValue = (char*)CPLGetXMLValue(psMapContext, "id", NULL); if (pszValue) map->name = msStrdup(pszValue); } else { if(msGetMapContextXMLStringValue(psGeneral, "Name", &(map->name)) == MS_FAILURE) { msGetMapContextXMLStringValue(psGeneral, "gml:name", &(map->name)); } } /* Keyword */ if( nVersion >= OWS_1_0_0 ) { msLoadMapContextListInMetadata( CPLGetXMLNode(psGeneral, "KeywordList"), &(map->web.metadata), "KEYWORD", "wms_keywordlist", "," ); } else msGetMapContextXMLHashValue(psGeneral, "Keywords", &(map->web.metadata), "wms_keywordlist"); /* Window */ pszValue1 = (char*)CPLGetXMLValue(psGeneral,"Window.width",NULL); pszValue2 = (char*)CPLGetXMLValue(psGeneral,"Window.height",NULL); if(pszValue1 != NULL && pszValue2 != NULL) { map->width = atoi(pszValue1); map->height = atoi(pszValue2); } /* Abstract */ if( msGetMapContextXMLHashValue( psGeneral, "Abstract", &(map->web.metadata), "wms_abstract") == MS_FAILURE ) { msGetMapContextXMLHashValue( psGeneral, "gml:description", &(map->web.metadata), "wms_abstract"); } /* DataURL */ msGetMapContextXMLHashValueDecode(psGeneral, "DataURL.OnlineResource.xlink:href", &(map->web.metadata), "wms_dataurl"); /* LogoURL */ /* The logourl have a width, height, format and an URL */ msLoadMapContextURLELements( CPLGetXMLNode(psGeneral, "LogoURL"), &(map->web.metadata), "wms_logourl" ); /* DescriptionURL */ /* The descriptionurl have a width, height, format and an URL */ msLoadMapContextURLELements( CPLGetXMLNode(psGeneral, "DescriptionURL"), &(map->web.metadata), "wms_descriptionurl" ); /* Contact Info */ msLoadMapContextContactInfo( CPLGetXMLNode(psGeneral, "ContactInformation"), &(map->web.metadata) ); return MS_SUCCESS; } /* ** msLoadMapContextLayer ** ** Load a Layer block from a MapContext document */ int msLoadMapContextLayer(mapObj *map, CPLXMLNode *psLayer, int nVersion, char *filename, int unique_layer_names) { char *pszProj=NULL; char *pszValue; const char *pszHash; char *pszName=NULL; CPLXMLNode *psFormatList, *psFormat, *psStyleList, *psStyle, *psExtension; CPLXMLNode *psDimensionList, *psDimension; int nStyle; layerObj *layer; /* Init new layer */ if(msGrowMapLayers(map) == NULL) return MS_FAILURE; layer = (GET_LAYER(map, map->numlayers)); initLayer(layer, map); layer->map = (mapObj *)map; layer->type = MS_LAYER_RASTER; /* save the index */ GET_LAYER(map, map->numlayers)->index = map->numlayers; map->layerorder[map->numlayers] = map->numlayers; map->numlayers++; /* Status */ pszValue = (char*)CPLGetXMLValue(psLayer, "hidden", "1"); if((pszValue != NULL) && (atoi(pszValue) == 0 && !strcasecmp(pszValue, "true") == 0)) layer->status = MS_ON; else layer->status = MS_OFF; /* Queryable */ pszValue = (char*)CPLGetXMLValue(psLayer, "queryable", "0"); if(pszValue !=NULL && (atoi(pszValue) == 1 || strcasecmp(pszValue, "true") == 0)) layer->template = msStrdup("ttt"); /* Name and Title */ pszValue = (char*)CPLGetXMLValue(psLayer, "Name", NULL); if(pszValue != NULL) { msInsertHashTable( &(layer->metadata), "wms_name", pszValue ); if (unique_layer_names) { pszName = (char*)malloc(sizeof(char)*(strlen(pszValue)+15)); sprintf(pszName, "l%d:%s", layer->index, pszValue); layer->name = msStrdup(pszName); free(pszName); } else layer->name = msStrdup(pszValue); } else { pszName = (char*)malloc(sizeof(char)*15); sprintf(pszName, "l%d:", layer->index); layer->name = msStrdup(pszName); free(pszName); } if(msGetMapContextXMLHashValue(psLayer, "Title", &(layer->metadata), "wms_title") == MS_FAILURE) { if(msGetMapContextXMLHashValue(psLayer, "Server.title", &(layer->metadata), "wms_title") == MS_FAILURE) { msDebug("Mandatory data Layer.Title missing in %s.", filename); } } /* Server Title */ msGetMapContextXMLHashValue(psLayer, "Server.title", &(layer->metadata), "wms_server_title"); /* Abstract */ msGetMapContextXMLHashValue(psLayer, "Abstract", &(layer->metadata), "wms_abstract"); /* DataURL */ if(nVersion <= OWS_0_1_4) { msGetMapContextXMLHashValueDecode(psLayer, "DataURL.OnlineResource.xlink:href", &(layer->metadata), "wms_dataurl"); } else { /* The DataURL have a width, height, format and an URL */ /* Width and height are not used, but they are included to */ /* be consistent with the spec. */ msLoadMapContextURLELements( CPLGetXMLNode(psLayer, "DataURL"), &(layer->metadata), "wms_dataurl" ); } /* The MetadataURL have a width, height, format and an URL */ /* Width and height are not used, but they are included to */ /* be consistent with the spec. */ msLoadMapContextURLELements( CPLGetXMLNode(psLayer, "MetadataURL"), &(layer->metadata), "wms_metadataurl" ); /* MinScale && MaxScale */ pszValue = (char*)CPLGetXMLValue(psLayer, "sld:MinScaleDenominator", NULL); if(pszValue != NULL) { layer->minscaledenom = atof(pszValue); } pszValue = (char*)CPLGetXMLValue(psLayer, "sld:MaxScaleDenominator", NULL); if(pszValue != NULL) { layer->maxscaledenom = atof(pszValue); } /* */ /* Server */ /* */ if(nVersion >= OWS_0_1_4) { if(msGetMapContextXMLStringValueDecode(psLayer, "Server.OnlineResource.xlink:href", &(layer->connection)) == MS_FAILURE) { msSetError(MS_MAPCONTEXTERR, "Mandatory data Server.OnlineResource.xlink:href missing in %s.", "msLoadMapContext()", filename); return MS_FAILURE; } else { msGetMapContextXMLHashValueDecode(psLayer, "Server.OnlineResource.xlink:href", &(layer->metadata), "wms_onlineresource"); layer->connectiontype = MS_WMS; } } else { if(msGetMapContextXMLStringValueDecode(psLayer, "Server.onlineResource", &(layer->connection)) == MS_FAILURE) { msSetError(MS_MAPCONTEXTERR, "Mandatory data Server.onlineResource missing in %s.", "msLoadMapContext()", filename); return MS_FAILURE; } else { msGetMapContextXMLHashValueDecode(psLayer, "Server.onlineResource", &(layer->metadata), "wms_onlineresource"); layer->connectiontype = MS_WMS; } } if(nVersion >= OWS_0_1_4) { if(msGetMapContextXMLHashValue(psLayer, "Server.version", &(layer->metadata), "wms_server_version") == MS_FAILURE) { msSetError(MS_MAPCONTEXTERR, "Mandatory data Server.version missing in %s.", "msLoadMapContext()", filename); return MS_FAILURE; } } else { if(msGetMapContextXMLHashValue(psLayer, "Server.wmtver", &(layer->metadata), "wms_server_version") == MS_FAILURE) { msSetError(MS_MAPCONTEXTERR, "Mandatory data Server.wmtver missing in %s.", "msLoadMapContext()", filename); return MS_FAILURE; } } /* Projection */ msLoadMapContextListInMetadata( psLayer, &(layer->metadata), "SRS", "wms_srs", " " ); pszHash = msLookupHashTable(&(layer->metadata), "wms_srs"); if(((pszHash == NULL) || (strcasecmp(pszHash, "") == 0)) && map->projection.numargs != 0) { pszProj = map->projection.args[map->projection.numargs-1]; if(pszProj != NULL) { if(strncasecmp(pszProj, "AUTO:", 5) == 0) { msInsertHashTable(&(layer->metadata),"wms_srs", pszProj); } else { if(strlen(pszProj) > 10) { pszProj = (char*) malloc(sizeof(char) * (strlen(pszProj))); sprintf( pszProj, "EPSG:%s", map->projection.args[map->projection.numargs-1]+10); msInsertHashTable(&(layer->metadata),"wms_srs", pszProj); } else { msDebug("Unable to set data for layer wms_srs from this" " value %s.", pszProj); } } } } /* */ /* Format */ /* */ if( nVersion >= OWS_0_1_4 ) { psFormatList = CPLGetXMLNode(psLayer, "FormatList"); } else { psFormatList = psLayer; } if(psFormatList != NULL) { for(psFormat = psFormatList->psChild; psFormat != NULL; psFormat = psFormat->psNext) { msLoadMapContextLayerFormat(psFormat, layer); } } /* end FormatList parsing */ /* Style */ if( nVersion >= OWS_0_1_4 ) { psStyleList = CPLGetXMLNode(psLayer, "StyleList"); } else { psStyleList = psLayer; } if(psStyleList != NULL) { nStyle = 0; for(psStyle = psStyleList->psChild; psStyle != NULL; psStyle = psStyle->psNext) { if(strcasecmp(psStyle->pszValue, "Style") == 0) { nStyle++; msLoadMapContextLayerStyle(psStyle, layer, nStyle); } } } /* Dimension */ psDimensionList = CPLGetXMLNode(psLayer, "DimensionList"); if(psDimensionList != NULL) { for(psDimension = psDimensionList->psChild; psDimension != NULL; psDimension = psDimension->psNext) { if(strcasecmp(psDimension->pszValue, "Dimension") == 0) { msLoadMapContextLayerDimension(psDimension, layer); } } } /* Extension */ psExtension = CPLGetXMLNode(psLayer, "Extension"); if (psExtension != NULL) { pszValue = (char*)CPLGetXMLValue(psExtension, "ol:opacity", NULL); if(pszValue != NULL) { if(!layer->compositer) { layer->compositer = msSmallMalloc(sizeof(LayerCompositer)); initLayerCompositer(layer->compositer); } layer->compositer->opacity = atof(pszValue)*100; } } return MS_SUCCESS; } #endif /* msLoadMapContextURL() ** ** load an OGC Web Map Context format from an URL ** ** Take a map object and a URL to a conect file in arguments */ int msLoadMapContextURL(mapObj *map, char *urlfilename, int unique_layer_names) { #if defined(USE_WMS_LYR) && defined(USE_OGR) char *pszTmpFile = NULL; int status = 0; if (!map || !urlfilename) { msSetError(MS_MAPCONTEXTERR, "Invalid map or url given.", "msGetMapContextURL()"); return MS_FAILURE; } pszTmpFile = msTmpFile(map, map->mappath, NULL, "context.xml"); if (msHTTPGetFile(urlfilename, pszTmpFile, &status,-1, 0, 0, 0) == MS_SUCCESS) { return msLoadMapContext(map, pszTmpFile, unique_layer_names); } else { msSetError(MS_MAPCONTEXTERR, "Could not open context file %s.", "msGetMapContextURL()", urlfilename); return MS_FAILURE; } #else msSetError(MS_MAPCONTEXTERR, "Not implemented since Map Context is not enabled.", "msGetMapContextURL()"); return MS_FAILURE; #endif } /* msLoadMapContext() ** ** Get a mapfile from a OGC Web Map Context format ** ** Take as first map object and a file in arguments ** If The 2nd aregument unique_layer_names is set to MS_TRUE, the layer ** name created would be unique and be prefixed with an l plus the layers's index ** (eg l:1:park. l:2:road ...). If It is set to MS_FALSE, the layer name ** would be the same name as the layer name in the context */ int msLoadMapContext(mapObj *map, char *filename, int unique_layer_names) { #if defined(USE_WMS_LYR) && defined(USE_OGR) char *pszWholeText, *pszValue; CPLXMLNode *psRoot, *psMapContext, *psLayer, *psLayerList, *psChild; char szPath[MS_MAXPATHLEN]; int nVersion=-1; char szVersionBuf[OWS_VERSION_MAXLEN]; /* */ /* Load the raw XML file */ /* */ pszWholeText = msGetMapContextFileText( msBuildPath(szPath, map->mappath, filename)); if(pszWholeText == NULL) { msSetError( MS_MAPCONTEXTERR, "Unable to read %s", "msLoadMapContext()", filename ); return MS_FAILURE; } if( ( strstr( pszWholeText, "eType == CXT_Element && (EQUAL(psChild->pszValue,"WMS_Viewer_Context") || EQUAL(psChild->pszValue,"View_Context") || EQUAL(psChild->pszValue,"ViewContext")) ) { psMapContext = psChild; break; } else { psChild = psChild->psNext; } } if( psMapContext == NULL ) { CPLDestroyXMLNode(psRoot); msSetError( MS_MAPCONTEXTERR, "Invalid Map Context File (%s)", "msLoadMapContext()", filename ); return MS_FAILURE; } /* Fetch document version number */ pszValue = (char*)CPLGetXMLValue(psMapContext, "version", NULL); if( !pszValue ) { msDebug( "msLoadMapContext(): Mandatory data version missing in %s, assuming 0.1.4.", filename ); pszValue = "0.1.4"; } nVersion = msOWSParseVersionString(pszValue); /* Make sure this is a supported version */ switch (nVersion) { case OWS_0_1_2: case OWS_0_1_4: case OWS_0_1_7: case OWS_1_0_0: case OWS_1_1_0: /* All is good, this is a supported version. */ break; default: /* Not a supported version */ msSetError(MS_MAPCONTEXTERR, "This version of Map Context is not supported (%s).", "msLoadMapContext()", pszValue); CPLDestroyXMLNode(psRoot); return MS_FAILURE; } /* Reformat and save Version in metadata */ msInsertHashTable( &(map->web.metadata), "wms_context_version", msOWSGetVersionString(nVersion, szVersionBuf)); if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0) { if( msGetMapContextXMLHashValue(psMapContext, "fid", &(map->web.metadata), "wms_context_fid") == MS_FAILURE ) { msDebug("Mandatory data fid missing in %s.", filename); } } /* */ /* Load the General bloc */ /* */ psChild = CPLGetXMLNode( psMapContext, "General" ); if( psChild == NULL ) { CPLDestroyXMLNode(psRoot); msSetError(MS_MAPCONTEXTERR, "The Map Context document provided (%s) does not contain any " "General elements.", "msLoadMapContext()", filename); return MS_FAILURE; } if( msLoadMapContextGeneral(map, psChild, psMapContext, nVersion, filename) == MS_FAILURE ) { CPLDestroyXMLNode(psRoot); return MS_FAILURE; } /* */ /* Load the bloc LayerList */ /* */ psLayerList = CPLGetXMLNode(psMapContext, "LayerList"); if( psLayerList != NULL ) { for(psLayer = psLayerList->psChild; psLayer != NULL; psLayer = psLayer->psNext) { if(EQUAL(psLayer->pszValue, "Layer")) { if( msLoadMapContextLayer(map, psLayer, nVersion, filename, unique_layer_names) == MS_FAILURE ) { CPLDestroyXMLNode(psRoot); return MS_FAILURE; } }/* end Layer parsing */ }/* for */ } CPLDestroyXMLNode(psRoot); return MS_SUCCESS; #else msSetError(MS_MAPCONTEXTERR, "Not implemented since Map Context is not enabled.", "msGetMapContext()"); return MS_FAILURE; #endif } /* msSaveMapContext() ** ** Save a mapfile into the OGC Web Map Context format ** ** Take a map object and a file in arguments */ int msSaveMapContext(mapObj *map, char *filename) { #if defined(USE_WMS_LYR) && defined(USE_OGR) FILE *stream; char szPath[MS_MAXPATHLEN]; int nStatus; /* open file */ if(filename != NULL && strlen(filename) > 0) { stream = fopen(msBuildPath(szPath, map->mappath, filename), "wb"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msSaveMapContext()", filename); return(MS_FAILURE); } } else { msSetError(MS_IOERR, "Filename is undefined.", "msSaveMapContext()"); return MS_FAILURE; } nStatus = msWriteMapContext(map, stream); fclose(stream); return nStatus; #else msSetError(MS_MAPCONTEXTERR, "Not implemented since Map Context is not enabled.", "msSaveMapContext()"); return MS_FAILURE; #endif } int msWriteMapContext(mapObj *map, FILE *stream) { #if defined(USE_WMS_LYR) && defined(USE_OGR) const char * version; char *pszEPSG; char * tabspace=NULL, *pszChar,*pszSLD=NULL,*pszURL,*pszSLD2=NULL; char *pszStyle, *pszStyleItem, *pszSLDBody; char *pszEncodedVal; int i, nValue, nVersion=OWS_VERSION_NOTSET; /* Dimension element */ char *pszDimension; const char *pszDimUserValue=NULL, *pszDimUnits=NULL, *pszDimDefault=NULL; const char *pszDimNearValue=NULL, *pszDimUnitSymbol=NULL; const char *pszDimMultiValue=NULL; int bDimensionList = 0; /* Decide which version we're going to return... */ version = msLookupHashTable(&(map->web.metadata), "wms_context_version"); if(version == NULL) version = "1.1.0"; nVersion = msOWSParseVersionString(version); if (nVersion == OWS_VERSION_BADFORMAT) return MS_FAILURE; /* msSetError() already called. */ /* Make sure this is a supported version */ /* Note that we don't write 0.1.2 even if we read it. */ switch (nVersion) { case OWS_0_1_4: case OWS_0_1_7: case OWS_1_0_0: case OWS_1_1_0: /* All is good, this is a supported version. */ break; default: /* Not a supported version */ msSetError(MS_MAPCONTEXTERR, "This version of Map Context is not supported (%s).", "msSaveMapContext()", version); return MS_FAILURE; } /* file header */ msIO_fprintf( stream, "\n"); /* set the WMS_Viewer_Context information */ pszEncodedVal = msEncodeHTMLEntities(version); if(nVersion >= OWS_1_0_0) { msIO_fprintf( stream, "= OWS_0_1_7) { msIO_fprintf( stream, "= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_context_fid", OWS_NOERR," fid=\"%s\"","0"); } if ( nVersion >= OWS_1_0_0 ) msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR, " id=\"%s\"", NULL); msIO_fprintf( stream, " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); msIO_fprintf( stream, " xmlns:ogc=\"http://www.opengis.net/ogc\""); if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { msIO_fprintf( stream, " xmlns:gml=\"http://www.opengis.net/gml\""); } if( nVersion >= OWS_1_0_0 ) { msIO_fprintf( stream, " xmlns:xlink=\"http://www.w3.org/1999/xlink\""); msIO_fprintf( stream, " xmlns=\"http://www.opengis.net/context\""); msIO_fprintf( stream, " xmlns:sld=\"http://www.opengis.net/sld\""); pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); if( nVersion >= OWS_1_1_0 ) msIO_fprintf( stream, " xsi:schemaLocation=\"http://www.opengis.net/context %s/context/1.1.0/context.xsd\">\n", pszEncodedVal); else msIO_fprintf( stream, " xsi:schemaLocation=\"http://www.opengis.net/context %s/context/1.0.0/context.xsd\">\n", pszEncodedVal); msFree(pszEncodedVal); } else { msIO_fprintf( stream, " xmlns:xlink=\"http://www.w3.org/TR/xlink\""); pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); msIO_fprintf( stream, " xsi:noNamespaceSchemaLocation=\"%s/contexts/", pszEncodedVal ); msFree(pszEncodedVal); pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); msIO_fprintf( stream, "%s/context.xsd\">\n", pszEncodedVal); msFree(pszEncodedVal); } /* set the General information */ msIO_fprintf( stream, " \n" ); /* Window */ if( map->width != -1 || map->height != -1 ) msIO_fprintf( stream, " \n", map->width, map->height ); /* Bounding box corners and spatial reference system */ if(tabspace) free(tabspace); tabspace = msStrdup(" "); msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_TRUE, &pszEPSG); msIO_fprintf( stream, "%s\n", tabspace ); if(!pszEPSG || (strcasecmp(pszEPSG, "(null)") == 0)) msIO_fprintf(stream, "\n"); pszEncodedVal = msEncodeHTMLEntities(pszEPSG); msIO_fprintf( stream, "%s\n", tabspace, pszEncodedVal, map->extent.minx, map->extent.miny, map->extent.maxx, map->extent.maxy ); msFree(pszEncodedVal); msFree(pszEPSG); /* Title, name */ if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR, " %s\n", NULL); } else { if (nVersion < OWS_0_1_7) msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR, " %s\n", NULL); msIO_fprintf( stream, "%s\n", tabspace ); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_title", OWS_WARN, " %s\n", map->name); } /* keyword */ if (nVersion >= OWS_1_0_0) { if (msLookupHashTable(&(map->web.metadata),"wms_keywordlist")!=NULL) { char **papszKeywords; int nKeywords, iKey; const char* pszValue = msLookupHashTable(&(map->web.metadata), "wms_keywordlist"); papszKeywords = msStringSplit(pszValue, ',', &nKeywords); if(nKeywords > 0 && papszKeywords) { msIO_fprintf( stream, " \n"); for(iKey=0; iKey%s\n", pszEncodedVal); msFree(pszEncodedVal); } msIO_fprintf( stream, " \n"); } } } else msOWSPrintEncodeMetadataList(stream, &(map->web.metadata), NULL, "wms_keywordlist", " \n", " \n", " %s\n", NULL); /* abstract */ if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) { msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_abstract", OWS_NOERR, " %s\n", NULL); } else { msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_abstract", OWS_NOERR, " %s\n", NULL); } /* LogoURL */ /* The LogoURL have a width, height, format and an URL */ msOWSPrintURLType(stream, &(map->web.metadata), "MO", "logourl", OWS_NOERR, NULL, "LogoURL", NULL, " width=\"%s\"", " height=\"%s\""," format=\"%s\"", " \n", MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); /* DataURL */ msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL, "wms_dataurl", OWS_NOERR, " \n \n \n", NULL); /* DescriptionURL */ /* The DescriptionURL have a width, height, format and an URL */ /* The metadata is structured like this: "width height format url" */ msOWSPrintURLType(stream, &(map->web.metadata), "MO", "descriptionurl", OWS_NOERR, NULL, "DescriptionURL", NULL, " width=\"%s\"", " height=\"%s\""," format=\"%s\"", " \n", MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE, NULL, NULL, NULL, NULL, NULL, " "); /* Contact Info */ msOWSPrintContactInfo( stream, tabspace, OWS_1_1_0, &(map->web.metadata), "MO" ); /* Close General */ msIO_fprintf( stream, " \n" ); free(tabspace); /* Set the layer list */ msIO_fprintf(stream, " \n"); /* Loop on all layer */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->status != MS_DELETE && GET_LAYER(map, i)->connectiontype == MS_WMS) { const char* pszValue; char* pszValueMod; const char* pszCurrent; if(GET_LAYER(map, i)->status == MS_OFF) nValue = 1; else nValue = 0; msIO_fprintf(stream, " \n"); } } /* Close layer list */ msIO_fprintf(stream, " \n"); /* Close Map Context */ if(nVersion >= OWS_1_0_0) { msIO_fprintf(stream, "\n"); } else if(nVersion >= OWS_0_1_7) { msIO_fprintf(stream, "\n"); } else { /* 0.1.4 */ msIO_fprintf(stream, "\n"); } return MS_SUCCESS; #else msSetError(MS_MAPCONTEXTERR, "Not implemented since Map Context is not enabled.", "msWriteMapContext()"); return MS_FAILURE; #endif } mapserver-7.4.3/mapcontour.c000066400000000000000000001034461357574274700161210ustar00rootroot00000000000000/********************************************************************** * $Id: mapcontour.c 12629 2011-10-06 18:06:34Z aboudreault $ * * Project: MapServer * Purpose: Contour Layer * Author: Alan Boudreault (aboudreault@mapgears.com) * Author: Daniel Morissette (dmorissette@mapgears.com) * ********************************************************************** * Copyright (c) 2011, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "mapserver.h" #include "mapcopy.h" #include "mapresample.h" #ifdef USE_GDAL #include "ogr_api.h" #include "ogr_srs_api.h" #include "gdal.h" #include "gdal_alg.h" #include "mapthread.h" #include "mapraster.h" #include "cpl_string.h" #define GEO_TRANS(tr,x,y) ((tr)[0]+(tr)[1]*(x)+(tr)[2]*(y)) extern int InvGeoTransform(double *gt_in, double *gt_out); typedef struct { /* OGR DataSource */ layerObj ogrLayer; /* internal use */ GDALDatasetH hOrigDS; GDALDatasetH hDS; double *buffer; /* memory dataset buffer */ rectObj extent; /* original dataset extent */ OGRDataSourceH hOGRDS; double cellsize; } contourLayerInfo; static int msContourLayerInitItemInfo(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerInitItemInfo()"); return MS_FAILURE; } return msLayerInitItemInfo(&clinfo->ogrLayer); } static void msContourLayerFreeItemInfo(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerFreeItemInfo()"); return; } msLayerFreeItemInfo(&clinfo->ogrLayer); } static void msContourLayerInfoInitialize(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo != NULL) return; clinfo = (contourLayerInfo *) msSmallCalloc(1,sizeof(contourLayerInfo)); layer->layerinfo = clinfo; clinfo->hOrigDS = NULL; clinfo->hDS = NULL; clinfo->extent.minx = -1.0; clinfo->extent.miny = -1.0; clinfo->extent.maxx = -1.0; clinfo->extent.maxy = -1.0; initLayer(&clinfo->ogrLayer, layer->map); clinfo->ogrLayer.type = layer->type; clinfo->ogrLayer.debug = layer->debug; clinfo->ogrLayer.connectiontype = MS_OGR; clinfo->ogrLayer.name = msStrdup(layer->name); clinfo->ogrLayer.connection = (char*)msSmallMalloc(strlen(clinfo->ogrLayer.name)+13); sprintf(clinfo->ogrLayer.connection, "__%s_CONTOUR__", clinfo->ogrLayer.name); clinfo->ogrLayer.units = layer->units; } static void msContourLayerInfoFree(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo == NULL) return; freeLayer(&clinfo->ogrLayer); free(clinfo); layer->layerinfo = NULL; } static int msContourLayerReadRaster(layerObj *layer, rectObj rect) { mapObj *map = layer->map; char **bands; char pointer[64], memDSPointer[128]; int band = 1; double adfGeoTransform[6], adfInvGeoTransform[6]; double llx, lly, urx, ury; rectObj copyRect, mapRect; int dst_xsize, dst_ysize; int virtual_grid_step_x, virtual_grid_step_y; int src_xoff, src_yoff, src_xsize, src_ysize; double map_cellsize_x, map_cellsize_y, dst_cellsize_x, dst_cellsize_y; GDALRasterBandH hBand = NULL; CPLErr eErr; contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerReadRaster().\n"); if (clinfo == NULL || clinfo->hOrigDS == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerReadRaster()"); return MS_FAILURE; } bands = CSLTokenizeStringComplex( CSLFetchNameValue(layer->processing,"BANDS"), " ,", FALSE, FALSE ); if (CSLCount(bands) > 0) { band = atoi(bands[0]); if (band < 1 || band > GDALGetRasterCount(clinfo->hOrigDS)) { msSetError( MS_IMGERR, "BANDS PROCESSING directive includes illegal band '%d', should be from 1 to %d.", "msContourLayerReadRaster()", band, GDALGetRasterCount(clinfo->hOrigDS)); CSLDestroy(bands); return MS_FAILURE; } } CSLDestroy(bands); hBand = GDALGetRasterBand(clinfo->hOrigDS, band); if (hBand == NULL) { msSetError(MS_IMGERR, "Band %d does not exist on dataset.", "msContourLayerReadRaster()", band); return MS_FAILURE; } if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { const char *wkt; wkt = GDALGetProjectionRef(clinfo->hOrigDS); if (wkt != NULL && strlen(wkt) > 0) { if (msOGCWKT2ProjectionObj(wkt, &(layer->projection), layer->debug) != MS_SUCCESS) { char msg[MESSAGELENGTH*2]; errorObj *ms_error = msGetErrorObj(); snprintf( msg, sizeof(msg), "%s\n" "PROJECTION AUTO cannot be used for this " "GDAL raster (`%s').", ms_error->message, layer->data); msg[MESSAGELENGTH-1] = '\0'; msSetError(MS_OGRERR, "%s","msDrawRasterLayer()", msg); return MS_FAILURE; } } } /* * Compute the georeferenced window of overlap, and read the source data * downsampled to match output resolution, or at full resolution if * output resolution is lower than the source resolution. * * A large portion of this overlap calculation code was borrowed from * msDrawRasterLayerGDAL(). * Would be possible to move some of this to a reusable function? * * Note: This code works only if no reprojection is involved. It would * need rework to support cases where output projection differs from source * data file projection. */ src_xsize = GDALGetRasterXSize(clinfo->hOrigDS); src_ysize = GDALGetRasterYSize(clinfo->hOrigDS); /* set the Dataset extent */ msGetGDALGeoTransform(clinfo->hOrigDS, map, layer, adfGeoTransform); clinfo->extent.minx = adfGeoTransform[0]; clinfo->extent.maxy = adfGeoTransform[3]; clinfo->extent.maxx = adfGeoTransform[0] + src_xsize * adfGeoTransform[1]; clinfo->extent.miny = adfGeoTransform[3] + src_ysize * adfGeoTransform[5]; if (layer->transform) { if (layer->debug) msDebug("msContourLayerReadRaster(): Entering transform.\n"); InvGeoTransform(adfGeoTransform, adfInvGeoTransform); mapRect = rect; map_cellsize_x = map_cellsize_y = map->cellsize; #ifdef USE_PROJ /* if necessary, project the searchrect to source coords */ if (msProjectionsDiffer( &(map->projection), &(layer->projection))) { if ( msProjectRect(&map->projection, &layer->projection, &mapRect) != MS_SUCCESS ) { msDebug("msContourLayerReadRaster(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name); return MS_FAILURE; } map_cellsize_x = MS_CELLSIZE(mapRect.minx, mapRect.maxx, map->width); map_cellsize_y = MS_CELLSIZE(mapRect.miny, mapRect.maxy, map->height); /* if the projection failed to project the extent requested, we need to calculate the cellsize to preserve the initial map cellsize ratio */ if ( (mapRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize)) || (mapRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0)) || (mapRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize)) || (mapRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0)) ) { int src_unit, dst_unit; src_unit = GetMapserverUnitUsingProj(&map->projection); dst_unit = GetMapserverUnitUsingProj(&layer->projection); if (src_unit == -1 || dst_unit == -1) { msDebug("msContourLayerReadRaster(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name); return MS_FAILURE; } map_cellsize_x = MS_CONVERT_UNIT(src_unit, dst_unit, MS_CELLSIZE(rect.minx, rect.maxx, map->width)); map_cellsize_y = MS_CONVERT_UNIT(src_unit, dst_unit, MS_CELLSIZE(rect.miny, rect.maxy, map->height)); } } #endif if (map_cellsize_x == 0 || map_cellsize_y == 0) { if (layer->debug) msDebug("msContourLayerReadRaster(): Cellsize can't be 0.\n"); return MS_FAILURE; } /* Adjust MapServer pixel model to GDAL pixel model */ mapRect.minx -= map_cellsize_x*0.5; mapRect.maxx += map_cellsize_x*0.5; mapRect.miny -= map_cellsize_y*0.5; mapRect.maxy += map_cellsize_y*0.5; /* * If raw data cellsize (from geotransform) is larger than output map_cellsize * then we want to extract only enough data to match the output map resolution * which means that GDAL will automatically sample the data on read. * * To prevent bad contour effects on tile edges, we adjust the target cellsize * to align the extracted window with a virtual grid based on the origin of the * raw data and a virtual grid step size corresponding to an integer sampling step. * * If source data has a greater cellsize (i.e. lower res) that requested ouptut map * then we use the raw data cellsize as target cellsize since there is no point in * interpolating the data for contours in this case. */ virtual_grid_step_x = (int)floor(map_cellsize_x / ABS(adfGeoTransform[1])); if (virtual_grid_step_x < 1) virtual_grid_step_x = 1; /* Do not interpolate data if grid sampling step < 1 */ virtual_grid_step_y = (int)floor(map_cellsize_y / ABS(adfGeoTransform[5])); if (virtual_grid_step_y < 1) virtual_grid_step_y = 1; /* Do not interpolate data if grid sampling step < 1 */ /* target cellsize is a multiple of raw data cellsize based on grid step*/ dst_cellsize_x = ABS(adfGeoTransform[1]) * virtual_grid_step_x; dst_cellsize_y = ABS(adfGeoTransform[5]) * virtual_grid_step_y; /* Compute overlap between source and target views */ copyRect = mapRect; if (copyRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize)) copyRect.minx = GEO_TRANS(adfGeoTransform,0,src_ysize); if (copyRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0)) copyRect.maxx = GEO_TRANS(adfGeoTransform,src_xsize,0); if (copyRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize)) copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_ysize); if (copyRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0)) copyRect.maxy = GEO_TRANS(adfGeoTransform+3,src_xsize,0); if (copyRect.minx >= copyRect.maxx || copyRect.miny >= copyRect.maxy) { if (layer->debug) msDebug("msContourLayerReadRaster(): No overlap.\n"); return MS_SUCCESS; } /* * Convert extraction window to raster coordinates */ llx = GEO_TRANS(adfInvGeoTransform+0,copyRect.minx,copyRect.miny); lly = GEO_TRANS(adfInvGeoTransform+3,copyRect.minx,copyRect.miny); urx = GEO_TRANS(adfInvGeoTransform+0,copyRect.maxx,copyRect.maxy); ury = GEO_TRANS(adfInvGeoTransform+3,copyRect.maxx,copyRect.maxy); /* * Align extraction window with virtual grid * (keep in mind raster coordinates origin is at upper-left) * We also add an extra buffer to fix tile boundarie issues when zoomed */ llx = floor(llx / virtual_grid_step_x) * virtual_grid_step_x - (virtual_grid_step_x*5); urx = ceil(urx / virtual_grid_step_x) * virtual_grid_step_x + (virtual_grid_step_x*5); ury = floor(ury / virtual_grid_step_y) * virtual_grid_step_y - (virtual_grid_step_x*5); lly = ceil(lly / virtual_grid_step_y) * virtual_grid_step_y + (virtual_grid_step_x*5); src_xoff = MS_MAX(0,(int) floor(llx+0.5)); src_yoff = MS_MAX(0,(int) floor(ury+0.5)); src_xsize = MS_MIN(MS_MAX(0,(int) (urx - llx + 0.5)), GDALGetRasterXSize(clinfo->hOrigDS) - src_xoff); src_ysize = MS_MIN(MS_MAX(0,(int) (lly - ury + 0.5)), GDALGetRasterYSize(clinfo->hOrigDS) - src_yoff); /* Update the geographic extent (buffer added) */ /* TODO: a better way to go the geo_trans */ copyRect.minx = GEO_TRANS(adfGeoTransform+0,src_xoff,0); copyRect.maxx = GEO_TRANS(adfGeoTransform+0,src_xoff+src_xsize,0); copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_yoff+src_ysize); copyRect.maxy = GEO_TRANS(adfGeoTransform+3,0,src_yoff); /* * If input window is to small then stop here */ if (src_xsize < 2 || src_ysize < 2) { if (layer->debug) msDebug("msContourLayerReadRaster(): input window too small, or no apparent overlap between map view and this window(1).\n"); return MS_SUCCESS; } /* Target buffer size */ dst_xsize = (int)ceil((copyRect.maxx - copyRect.minx) / dst_cellsize_x); dst_ysize = (int)ceil((copyRect.maxy - copyRect.miny) / dst_cellsize_y); if (dst_xsize == 0 || dst_ysize == 0) { if (layer->debug) msDebug("msContourLayerReadRaster(): no apparent overlap between map view and this window(2).\n"); return MS_SUCCESS; } if (layer->debug) msDebug( "msContourLayerReadRaster(): src=%d,%d,%d,%d, dst=%d,%d,%d,%d\n", src_xoff, src_yoff, src_xsize, src_ysize, 0, 0, dst_xsize, dst_ysize ); } else { src_xoff = 0; src_yoff = 0; dst_xsize = src_xsize = MS_MIN(map->width,src_xsize); dst_ysize = src_ysize = MS_MIN(map->height,src_ysize); copyRect.minx = copyRect.miny = 0; copyRect.maxx = map->width; copyRect.maxy = map->height; dst_cellsize_y = dst_cellsize_x = 1; } /* -------------------------------------------------------------------- */ /* Allocate buffer, and read data into it. */ /* -------------------------------------------------------------------- */ clinfo->buffer = (double *) malloc(sizeof(double) * dst_xsize * dst_ysize); if (clinfo->buffer == NULL) { msSetError(MS_MEMERR, "Malloc(): Out of memory.", "msContourLayerReadRaster()"); return MS_FAILURE; } eErr = GDALRasterIO(hBand, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, clinfo->buffer, dst_xsize, dst_ysize, GDT_Float64, 0, 0); if (eErr != CE_None) { msSetError( MS_IOERR, "GDALRasterIO() failed: %s", "msContourLayerReadRaster()", CPLGetLastErrorMsg() ); free(clinfo->buffer); return MS_FAILURE; } memset(pointer, 0, sizeof(pointer)); CPLPrintPointer(pointer, clinfo->buffer, sizeof(pointer)); sprintf(memDSPointer,"MEM:::DATAPOINTER=%s,PIXELS=%d,LINES=%d,BANDS=1,DATATYPE=Float64", pointer, dst_xsize, dst_ysize); clinfo->hDS = GDALOpen(memDSPointer, GA_ReadOnly); if (clinfo->hDS == NULL) { msSetError(MS_IMGERR, "Unable to open GDAL Memory dataset.", "msContourLayerReadRaster()"); free(clinfo->buffer); return MS_FAILURE; } adfGeoTransform[0] = copyRect.minx; adfGeoTransform[1] = dst_cellsize_x; adfGeoTransform[2] = 0; adfGeoTransform[3] = copyRect.maxy; adfGeoTransform[4] = 0; adfGeoTransform[5] = -dst_cellsize_y; clinfo->cellsize = MS_MAX(dst_cellsize_x, dst_cellsize_y); { char buf[64]; sprintf(buf, "%lf", clinfo->cellsize); msInsertHashTable(&layer->metadata, "__data_cellsize__", buf); } GDALSetGeoTransform(clinfo->hDS, adfGeoTransform); return MS_SUCCESS; } static void msContourOGRCloseConnection(void *conn_handle) { OGRDataSourceH hDS = (OGRDataSourceH) conn_handle; msAcquireLock(TLOCK_OGR); OGR_DS_Destroy(hDS); msReleaseLock(TLOCK_OGR); } /* Function that parses multiple options in the a list. It also supports min/maxscaledenom checks. ie. "CONTOUR_INTERVAL=0,3842942:10" */ static char* msContourGetOption(layerObj *layer, const char *name) { int c, i, found = MS_FALSE; char **values, **tmp, **options; double maxscaledenom, minscaledenom; char *value = NULL; options = CSLFetchNameValueMultiple(layer->processing, name); c = CSLCount(options); /* First pass to find the value among options that have min/maxscaledenom */ /* specified */ for (i=0; imap->scaledenom <= 0 || (((maxscaledenom <= 0) || (layer->map->scaledenom <= maxscaledenom)) && ((minscaledenom <= 0) || (layer->map->scaledenom > minscaledenom)))) { value = msStrdup(values[1]); found = MS_TRUE; } } CSLDestroy(tmp); } CSLDestroy(values); } /* Second pass to find the value among options that do NOT have */ /* min/maxscaledenom specified */ for (i=0; ilayerinfo; OGRRegisterAll(); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerCreateOGRDataSource()"); return MS_FAILURE; } if (!clinfo->hDS) { /* no overlap */ return MS_SUCCESS; } hBand = GDALGetRasterBand(clinfo->hDS, 1); if (hBand == NULL) { msSetError(MS_IMGERR, "Band %d does not exist on dataset.", "msContourLayerGenerateContour()", 1); return MS_FAILURE; } /* Create the OGR DataSource */ hDriver = OGRGetDriverByName("Memory"); if (hDriver == NULL) { msSetError(MS_OGRERR, "Unable to get OGR driver 'Memory'.", "msContourLayerCreateOGRDataSource()"); return MS_FAILURE; } clinfo->hOGRDS = OGR_Dr_CreateDataSource(hDriver, "", NULL); if (clinfo->hOGRDS == NULL) { msSetError(MS_OGRERR, "Unable to create OGR DataSource.", "msContourLayerCreateOGRDataSource()"); return MS_FAILURE; } hLayer = OGR_DS_CreateLayer(clinfo->hOGRDS, clinfo->ogrLayer.name, NULL, wkbLineString, NULL ); hFld = OGR_Fld_Create("ID", OFTInteger); OGR_Fld_SetWidth(hFld, 8); OGR_L_CreateField(hLayer, hFld, FALSE); OGR_Fld_Destroy(hFld); /* Check if we have a coutour item specified */ elevItem = CSLFetchNameValue(layer->processing,"CONTOUR_ITEM"); if (elevItem && strlen(elevItem) > 0) { hFld = OGR_Fld_Create(elevItem, OFTReal); OGR_Fld_SetWidth(hFld, 12); OGR_Fld_SetPrecision(hFld, 3); OGR_L_CreateField(hLayer, hFld, FALSE); OGR_Fld_Destroy(hFld); } else { elevItem = NULL; } option = msContourGetOption(layer, "CONTOUR_INTERVAL"); if (option) { interval = atof(option); free(option); } option = msContourGetOption(layer, "CONTOUR_LEVELS"); if (option) { int i,c; char **levelsTmp; levelsTmp = CSLTokenizeStringComplex(option, ",", FALSE, FALSE); c = CSLCount(levelsTmp); for (i=0;iogrLayer, clinfo->hOGRDS, msContourOGRCloseConnection); return MS_SUCCESS; } int msContourLayerOpen(layerObj *layer) { char *decrypted_path; char szPath[MS_MAXPATHLEN]; contourLayerInfo *clinfo; if (layer->debug) msDebug("Entering msContourLayerOpen().\n"); /* If we don't have info, initialize an empty one now */ if (layer->layerinfo == NULL) msContourLayerInfoInitialize(layer); clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->data == NULL && layer->tileindex == NULL ) { msSetError(MS_MISCERR, "Layer %s has neither DATA nor TILEINDEX defined.", "msContourLayerOpen()", layer->name); return MS_FAILURE; } if( layer->tileindex != NULL ) { char szTilename[MS_MAXPATHLEN]; int status; int tilelayerindex, tileitemindex, tilesrsindex; rectObj searchrect; layerObj* tlp; shapeObj tshp; char tilesrsname[1]; msInitShape(&tshp); searchrect = layer->map->extent; status = msDrawRasterSetupTileLayer(layer->map, layer, &searchrect, MS_FALSE, &tilelayerindex, &tileitemindex, &tilesrsindex, &tlp); if( status == MS_FAILURE ) { return MS_FAILURE; } status = msDrawRasterIterateTileIndex(layer, tlp, &tshp, tileitemindex, -1, szTilename, sizeof(szTilename), tilesrsname, sizeof(tilesrsname)); if( status == MS_FAILURE || status == MS_DONE ) { if( status == MS_DONE ) { if (layer->debug) msDebug("No raster matching filter.\n"); } msDrawRasterCleanupTileLayer(tlp, tilelayerindex); return MS_FAILURE; } msDrawRasterCleanupTileLayer(tlp, tilelayerindex); msDrawRasterBuildRasterPath(layer->map, layer, szTilename, szPath); decrypted_path = msStrdup(szPath); /* Cancel the time filter that might have been set on ours in case of */ /* a inline tileindex */ msFreeExpression(&layer->filter); msInitExpression(&layer->filter); } else { msTryBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, layer->data); decrypted_path = msDecryptStringTokens(layer->map, szPath); } GDALAllRegister(); /* Open the original Dataset */ msAcquireLock(TLOCK_GDAL); if (decrypted_path) { clinfo->hOrigDS = GDALOpen(decrypted_path, GA_ReadOnly); msFree(decrypted_path); } else clinfo->hOrigDS = NULL; msReleaseLock(TLOCK_GDAL); if (clinfo->hOrigDS == NULL) { msSetError(MS_IMGERR, "Unable to open GDAL dataset.", "msContourLayerOpen()"); return MS_FAILURE; } /* Open the raster source */ if (msContourLayerReadRaster(layer, layer->map->extent) != MS_SUCCESS) return MS_FAILURE; /* Generate Contour Dataset */ if (msContourLayerGenerateContour(layer) != MS_SUCCESS) return MS_FAILURE; if (clinfo->hDS) { GDALClose(clinfo->hDS); clinfo->hDS = NULL; free(clinfo->buffer); } /* Open our virtual ogr layer */ if (clinfo->hOGRDS && (msLayerOpen(&clinfo->ogrLayer) != MS_SUCCESS)) return MS_FAILURE; return MS_SUCCESS; } int msContourLayerIsOpen(layerObj *layer) { if (layer->layerinfo) return MS_TRUE; return MS_FALSE; } int msContourLayerClose(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerClose().\n"); if (clinfo) { if (clinfo->hOGRDS) msConnPoolRelease(&clinfo->ogrLayer, clinfo->hOGRDS); msLayerClose(&clinfo->ogrLayer); if (clinfo->hDS) { GDALClose(clinfo->hDS); clinfo->hDS = NULL; free(clinfo->buffer); } if (clinfo->hOrigDS) { GDALClose(clinfo->hOrigDS); clinfo->hOrigDS = NULL; } msContourLayerInfoFree(layer); } return MS_SUCCESS; } int msContourLayerGetItems(layerObj *layer) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerGetItems()"); return MS_FAILURE; } return msContourLayerGetItems(&clinfo->ogrLayer); } int msContourLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int i; rectObj newRect; contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerWhichShapes().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerWhichShapes()"); return MS_FAILURE; } newRect = rect; #ifdef USE_PROJ /* if necessary, project the searchrect to source coords */ if (msProjectionsDiffer( &(layer->map->projection), &(layer->projection))) { if (msProjectRect(&layer->projection, &layer->map->projection, &newRect) != MS_SUCCESS ) { msDebug("msContourLayerWhichShapes(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name); return MS_FAILURE; } } #endif /* regenerate the raster io */ if (clinfo->hOGRDS) msConnPoolRelease(&clinfo->ogrLayer, clinfo->hOGRDS); msLayerClose(&clinfo->ogrLayer); /* Open the raster source */ if (msContourLayerReadRaster(layer, newRect) != MS_SUCCESS) return MS_FAILURE; /* Generate Contour Dataset */ if (msContourLayerGenerateContour(layer) != MS_SUCCESS) return MS_FAILURE; if (clinfo->hDS) { GDALClose(clinfo->hDS); clinfo->hDS = NULL; free(clinfo->buffer); } if (!clinfo->hOGRDS) /* no overlap */ return MS_DONE; /* Open our virtual ogr layer */ if (msLayerOpen(&clinfo->ogrLayer) != MS_SUCCESS) return MS_FAILURE; clinfo->ogrLayer.numitems = layer->numitems; clinfo->ogrLayer.items = (char **) msSmallMalloc(sizeof(char *)*layer->numitems); for (i=0; inumitems;++i) { clinfo->ogrLayer.items[i] = msStrdup(layer->items[i]); } return msLayerWhichShapes(&clinfo->ogrLayer, rect, isQuery); } int msContourLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerGetShape().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerGetShape()"); return MS_FAILURE; } return msLayerGetShape(&clinfo->ogrLayer, shape, record); } int msContourLayerNextShape(layerObj *layer, shapeObj *shape) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerNextShape().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerNextShape()"); return MS_FAILURE; } return msLayerNextShape(&clinfo->ogrLayer, shape); } /************************************************************************/ /* msContourLayerGetExtent() */ /* Simple copy of the maprasterquery.c file. might change in the future */ /************************************************************************/ int msContourLayerGetExtent(layerObj *layer, rectObj *extent) { contourLayerInfo *clinfo = (contourLayerInfo *) layer->layerinfo; if (layer->debug) msDebug("Entering msContourLayerGetExtent().\n"); if (clinfo == NULL) { msSetError(MS_MISCERR, "Assertion failed: Contour layer not opened!!!", "msContourLayerGetExtent()"); return MS_FAILURE; } MS_COPYRECT(extent, &clinfo->extent); return MS_SUCCESS; } /************************************************************************/ /* msContourLayerSetTimeFilter() */ /* */ /* This function is actually just used in the context of */ /* setting a filter on the tileindex for time based queries. */ /* For instance via WMS requests. */ /* */ /* If a local shapefile tileindex is in use, we will set a */ /* backtics filter (shapefile compatible). If another layer is */ /* being used as the tileindex then we will forward the */ /* SetTimeFilter call to it. If there is no tileindex in */ /* place, we do nothing. */ /************************************************************************/ int msContourLayerSetTimeFilter(layerObj *layer, const char *timestring, const char *timefield) { int tilelayerindex; if (layer->debug) msDebug("msContourLayerSetTimeFilter(%s,%s).\n", timestring, timefield); /* -------------------------------------------------------------------- */ /* If we don't have a tileindex the time filter has no effect. */ /* -------------------------------------------------------------------- */ if( layer->tileindex == NULL ) { if (layer->debug) msDebug("msContourLayerSetTimeFilter(): time filter without effect on layers without tileindex.\n"); return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Find the tileindex layer. */ /* -------------------------------------------------------------------- */ tilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); /* -------------------------------------------------------------------- */ /* If we are using a local shapefile as our tileindex (that is */ /* to say, the tileindex name is not of another layer), then we */ /* just install a backtics style filter on the current layer. */ /* -------------------------------------------------------------------- */ if( tilelayerindex == -1 ) return msLayerMakeBackticsTimeFilter( layer, timestring, timefield ); /* -------------------------------------------------------------------- */ /* Otherwise we invoke the tileindex layers SetTimeFilter */ /* method. */ /* -------------------------------------------------------------------- */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; return msLayerSetTimeFilter( layer->GET_LAYER(map,tilelayerindex), timestring, timefield ); } /************************************************************************/ /* msRASTERLayerInitializeVirtualTable() */ /************************************************************************/ int msContourLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msContourLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msContourLayerFreeItemInfo; layer->vtable->LayerOpen = msContourLayerOpen; layer->vtable->LayerIsOpen = msContourLayerIsOpen; layer->vtable->LayerWhichShapes = msContourLayerWhichShapes; layer->vtable->LayerNextShape = msContourLayerNextShape; layer->vtable->LayerGetShape = msContourLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerClose = msContourLayerClose; layer->vtable->LayerGetItems = msContourLayerGetItems; layer->vtable->LayerGetExtent = msContourLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /*layer->vtable->LayerCloseConnection = msContourLayerClose;*/ /* we use backtics for proper tileindex shapefile functioning */ layer->vtable->LayerSetTimeFilter = msContourLayerSetTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } #else int msContourLayerInitializeVirtualTable(layerObj *layer) { msSetError(MS_MISCERR, "Contour Layer needs GDAL support, but it it not compiled in", "msContourLayerInitializeVirtualTable()"); return MS_FAILURE; } #endif mapserver-7.4.3/mapcopy.c000066400000000000000000001217051357574274700154000ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions to allow copying/cloning of maps * Author: Sean Gillies, sgillies@frii.com * * Notes: * These functions are not in mapfile.c because that file is * cumbersome enough as it is. There is agreement that this code and * that in mapfile.c should eventually be split up by object into * mapobj.c, layerobj.c, etc. Or something like that. * * Unit tests are written in Python using PyUnit and are in * mapscript/python/tests/testCopyMap.py. The tests can be * executed from the python directory as * * python2 tests/testCopyMap.py * * I just find Python to be very handy for unit testing, that's all. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include "mapserver.h" #include "mapsymbol.h" #include "mapcopy.h" /*********************************************************************** * msCopyProjectioExtended() * * * * Copy a projectionObj while adding additional arguments * **********************************************************************/ int msCopyProjectionExtended(projectionObj *dst, projectionObj *src, char ** args, int num_args) { #ifdef USE_PROJ int i; MS_COPYSTELEM(numargs); MS_COPYSTELEM(gt); MS_COPYSTELEM(automatic); for (i = 0; i < dst->numargs; i++) { /* Our destination consists of unallocated pointers */ dst->args[i] = msStrdup(src->args[i]); } for(i=0 ; i< num_args; i++) { dst->args[dst->numargs++] = msStrdup(args[i]); } if (dst->numargs != 0) { if (msProcessProjection(dst) != MS_SUCCESS) return MS_FAILURE; } #endif MS_COPYSTELEM(wellknownprojection); return MS_SUCCESS; } /*********************************************************************** * msCopyProjection() * * * * Copy a projectionObj * **********************************************************************/ int msCopyProjection(projectionObj *dst, projectionObj *src) { return msCopyProjectionExtended(dst,src,NULL,0); } /*********************************************************************** * msCopyLine() * * * * Copy a lineObj, using msCopyPoint() * **********************************************************************/ int msCopyLine(lineObj *dst, lineObj *src) { int i; dst->numpoints = src->numpoints; for (i = 0; i < dst->numpoints; i++) { MS_COPYPOINT(&(dst->point[i]), &(src->point[i])); } return MS_SUCCESS; } /*********************************************************************** * msCopyShape() * * * * Copy a shapeObj, using msCopyLine(), msCopyRect() * * Not completely implemented or tested. * **********************************************************************/ /* int msCopyShapeObj(shapeObj *dst, shapeObj *src) { int i; copyProperty(&(dst->numlines), &(src->numlines), sizeof(int)); for (i = 0; i < dst->numlines; i++) { msCopyLine(&(dst->line[i]), &(src->line[i])); } msCopyRect(&(dst->bounds), &(src->bounds)); copyProperty(&(dst->type), &(src->type), sizeof(int)); copyProperty(&(dst->index), &(src->index), sizeof(long)); copyProperty(&(dst->tileindex), &(src->tileindex), sizeof(int)); copyProperty(&(dst->classindex), &(src->classindex), sizeof(int)); copyStringPropertyRealloc(&(dst->text), src->text); copyProperty(&(dst->numvalues), &(src->numvalues), sizeof(int)); for (i = 0; i < dst->numvalues; i++) { copyStringPropertyRealloc(&(dst->values[i]), src->values[i]); } return(0); } */ /********************************************************************** * msCopyItem() * * * * Copy an itemObj * **********************************************************************/ int msCopyItem(itemObj *dst, itemObj *src) { MS_COPYSTRING(dst->name, src->name); MS_COPYSTELEM(type); MS_COPYSTELEM(index); MS_COPYSTELEM(size); MS_COPYSTELEM(numdecimals); return MS_SUCCESS; } /*********************************************************************** * msCopyHashTable() * * * * Copy a hashTableObj, using msInsertHashTable() * **********************************************************************/ int msCopyHashTable(hashTableObj *dst, hashTableObj *src) { const char *key=NULL; while (1) { key = msNextKeyFromHashTable(src, key); if (!key) break; else msInsertHashTable(dst, key, msLookupHashTable(src, key)); } return MS_SUCCESS; } /*********************************************************************** * msCopyFontSet() * * * * Copy a fontSetObj, using msCreateHashTable() and msCopyHashTable() * **********************************************************************/ int msCopyFontSet(fontSetObj *dst, fontSetObj *src, mapObj *map) { MS_COPYSTRING(dst->filename, src->filename); MS_COPYSTELEM(numfonts); if (&(src->fonts)) { /* if (!dst->fonts) */ /* dst->fonts = msCreateHashTable(); */ if (msCopyHashTable(&(dst->fonts), &(src->fonts)) != MS_SUCCESS) return MS_FAILURE; } dst->map = map; return MS_SUCCESS; } /*********************************************************************** * msCopyExpression() * * * * Copy an expressionObj, but only its string, type and flags * **********************************************************************/ int msCopyExpression(expressionObj *dst, expressionObj *src) { if((dst->type == MS_REGEX) && dst->compiled) ms_regfree(&(dst->regex)); dst->compiled = MS_FALSE; MS_COPYSTRING(dst->string, src->string); MS_COPYSTELEM(type); MS_COPYSTELEM(flags); return MS_SUCCESS; } /*********************************************************************** * msCopyJoin() * * * * Copy a joinObj * **********************************************************************/ int msCopyJoin(joinObj *dst, joinObj *src) { MS_COPYSTRING(dst->name, src->name); /* makes no sense to copy the items or values since they are runtime additions to the mapfile */ MS_COPYSTRING(dst->table, src->table); MS_COPYSTRING(dst->from, src->from); MS_COPYSTRING(dst->to, src->to); MS_COPYSTRING(dst->header, src->header); #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif MS_COPYSTRING(dst->footer, src->footer); dst->type = src->type; MS_COPYSTRING(dst->connection, src->connection); MS_COPYSTELEM(connectiontype); /* TODO: need to handle joininfo (probably should be just set to NULL) */ dst->joininfo = NULL; return MS_SUCCESS; } /*********************************************************************** * msCopyQueryMap() * * * * Copy a queryMapObj, using msCopyColor() * **********************************************************************/ int msCopyQueryMap(queryMapObj *dst, queryMapObj *src) { MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYSTELEM(status); MS_COPYSTELEM(style); MS_COPYCOLOR(&(dst->color), &(src->color)); return MS_SUCCESS; } /*********************************************************************** * msCopyLeader() * * * * Copy a labelLeaderObj, using msCopyStyle() * **********************************************************************/ int msCopyLabelLeader(labelLeaderObj *dst, labelLeaderObj *src) { int i; assert(dst && src); MS_COPYSTELEM(gridstep); MS_COPYSTELEM(maxdistance); /* ** now the styles */ /* free any previous styles on the dst label */ for(i=0; inumstyles; i++) { /* each style */ if (dst->styles[i]!=NULL) { if( freeStyle(dst->styles[i]) == MS_SUCCESS ) msFree(dst->styles[i]); } } dst->numstyles = 0; for (i = 0; i < src->numstyles; i++) { if (msGrowLeaderStyles(dst) == NULL) return MS_FAILURE; if (initStyle(dst->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to init style.", "msCopyLabel()"); return MS_FAILURE; } if (msCopyStyle(dst->styles[i], src->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy style.", "msCopyLabel()"); return MS_FAILURE; } dst->numstyles++; } return MS_SUCCESS; } /*********************************************************************** * msCopyLabel() * * * * Copy a labelObj, using msCopyColor() and msCopyStyle() * **********************************************************************/ int msCopyLabel(labelObj *dst, labelObj *src) { int i; for(i=0; ibindings[i].item, src->bindings[i].item); dst->bindings[i].index = src->bindings[i].index; /* no way to use the macros */ } MS_COPYSTELEM(numbindings); MS_COPYSTRING(dst->font, src->font); MS_COPYCOLOR(&(dst->color), &(src->color)); MS_COPYCOLOR(&(dst->outlinecolor), &(src->outlinecolor)); MS_COPYCOLOR(&(dst->shadowcolor), &(src->shadowcolor)); MS_COPYSTELEM(shadowsizex); MS_COPYSTELEM(shadowsizey); MS_COPYSTELEM(size); MS_COPYSTELEM(minsize); MS_COPYSTELEM(maxsize); MS_COPYSTELEM(position); MS_COPYSTELEM(offsetx); MS_COPYSTELEM(offsety); MS_COPYSTELEM(angle); MS_COPYSTELEM(anglemode); MS_COPYSTELEM(buffer); MS_COPYSTELEM(wrap); MS_COPYSTELEM(align); MS_COPYSTELEM(maxlength); MS_COPYSTELEM(minfeaturesize); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); MS_COPYSTELEM(autominfeaturesize); MS_COPYSTELEM(mindistance); MS_COPYSTELEM(partials); MS_COPYSTELEM(force); MS_COPYSTELEM(priority); MS_COPYSTELEM(repeatdistance); MS_COPYSTELEM(maxoverlapangle); MS_COPYSTRING(dst->encoding, src->encoding); MS_COPYSTELEM(outlinewidth); MS_COPYSTELEM(space_size_10); if (msCopyExpression(&(dst->expression), &(src->expression)) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy expression.", "msCopyLabel()"); return MS_FAILURE; } if (msCopyExpression(&(dst->text), &(src->text)) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy text.", "msCopyLabel()"); return MS_FAILURE; } /* ** now the styles */ /* free any previous styles on the dst label */ for(i=0; inumstyles; i++) { /* each style */ if (dst->styles[i]!=NULL) { if( freeStyle(dst->styles[i]) == MS_SUCCESS ) msFree(dst->styles[i]); } } dst->numstyles = 0; for (i = 0; i < src->numstyles; i++) { if (msGrowLabelStyles(dst) == NULL) return MS_FAILURE; if (initStyle(dst->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to init style.", "msCopyLabel()"); return MS_FAILURE; } if (msCopyStyle(dst->styles[i], src->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy style.", "msCopyLabel()"); return MS_FAILURE; } dst->numstyles++; } if(src->leader) { dst->leader = msSmallMalloc(sizeof(labelLeaderObj)); initLeader(dst->leader); msCopyLabelLeader(dst->leader,src->leader); } else { if(dst->leader) { freeLabelLeader(dst->leader); msFree(dst->leader); } dst->leader = NULL; } return MS_SUCCESS; } /*********************************************************************** * msCopyWeb() * * * * Copy webObj, using msCopyRect(), msCreateHashTable(), and * * msCopyHashTable() * **********************************************************************/ int msCopyWeb(webObj *dst, webObj *src, mapObj *map) { MS_COPYSTRING(dst->log, src->log); MS_COPYSTRING(dst->imagepath, src->imagepath); MS_COPYSTRING(dst->imageurl, src->imageurl); dst->map = map; #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif MS_COPYSTRING(dst->header, src->header); MS_COPYSTRING(dst->footer, src->footer); MS_COPYSTRING(dst->empty, src->empty); MS_COPYSTRING(dst->error, src->error); MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); MS_COPYSTRING(dst->mintemplate, src->mintemplate); MS_COPYSTRING(dst->maxtemplate, src->maxtemplate); if (&(src->metadata)) { /* dst->metadata = msCreateHashTable(); */ if (msCopyHashTable(&(dst->metadata), &(src->metadata)) != MS_SUCCESS) return MS_FAILURE; } msCopyHashTable(&dst->validation,&src->validation); MS_COPYSTRING(dst->queryformat, src->queryformat); MS_COPYSTRING(dst->legendformat, src->legendformat); MS_COPYSTRING(dst->browseformat, src->browseformat); return MS_SUCCESS ; } /*********************************************************************** * msCopyStyle() * * * * Copy a styleObj, using msCopyColor() * **********************************************************************/ int msCopyStyle(styleObj *dst, styleObj *src) { int i; for(i=0; ibindings[i].item, src->bindings[i].item); dst->bindings[i].index = src->bindings[i].index; /* no way to use the macros */ } MS_COPYSTELEM(numbindings); MS_COPYCOLOR(&(dst->color), &(src->color)); MS_COPYCOLOR(&(dst->outlinecolor),&(src->outlinecolor)); MS_COPYCOLOR(&(dst->backgroundcolor), &(src->backgroundcolor)); MS_COPYCOLOR(&(dst->mincolor), &(src->mincolor)); MS_COPYCOLOR(&(dst->maxcolor), &(src->maxcolor)); MS_COPYSTRING(dst->symbolname, src->symbolname); MS_COPYSTELEM(patternlength); for(i=0; ipatternlength; i++) dst->pattern[i]=src->pattern[i]; MS_COPYSTELEM(initialgap); MS_COPYSTELEM(gap); MS_COPYSTELEM(linejoin); MS_COPYSTELEM(linejoinmaxsize); MS_COPYSTELEM(linecap); MS_COPYSTELEM(symbol); MS_COPYSTELEM(size); MS_COPYSTELEM(minsize); MS_COPYSTELEM(maxsize); MS_COPYSTELEM(width); MS_COPYSTELEM(minwidth); MS_COPYSTELEM(maxwidth); MS_COPYSTELEM(offsetx); MS_COPYSTELEM(offsety); MS_COPYSTELEM(angle); MS_COPYSTELEM(autoangle); MS_COPYSTELEM(minvalue); MS_COPYSTELEM(maxvalue); MS_COPYSTELEM(opacity); MS_COPYSTRING(dst->_geomtransform.string, src->_geomtransform.string); MS_COPYSTELEM(_geomtransform.type); MS_COPYSTRING(dst->rangeitem, src->rangeitem); MS_COPYSTELEM(rangeitemindex); MS_COPYSTELEM(outlinewidth); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); /* TODO: add copy for bindings */ return MS_SUCCESS; } /*********************************************************************** * msCopyClass() * * * * Copy a classObj, using msCopyExpression(), msCopyStyle(), * * msCopyLabel(), msCreateHashTable(), msCopyHashTable() * **********************************************************************/ int msCopyClass(classObj *dst, classObj *src, layerObj *layer) { int i, return_value; return_value = msCopyExpression(&(dst->expression),&(src->expression)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy expression.", "msCopyClass()"); return MS_FAILURE; } MS_COPYSTELEM(status); /* free any previous styles on the dst layer */ for(i=0; inumstyles; i++) { /* each style */ if (dst->styles[i]!=NULL) { if( freeStyle(dst->styles[i]) == MS_SUCCESS ) { msFree(dst->styles[i]); } } } dst->numstyles = 0; for (i = 0; i < src->numstyles; i++) { if (msGrowClassStyles(dst) == NULL) return MS_FAILURE; if (initStyle(dst->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to init style.", "msCopyClass()"); return MS_FAILURE; } if (msCopyStyle(dst->styles[i], src->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy style.", "msCopyClass()"); return MS_FAILURE; } dst->numstyles++; } for (i=0; inumlabels; i++) { if (msGrowClassLabels(dst) == NULL) return MS_FAILURE; initLabel(dst->labels[i]); if (msCopyLabel(dst->labels[i], src->labels[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy label.", "msCopyClass()"); return MS_FAILURE; } dst->numlabels++; } MS_COPYSTELEM(numlabels); if(src->leader) { if(dst->leader) { freeLabelLeader(dst->leader); } if(!dst->leader) { dst->leader = msSmallMalloc(sizeof(labelLeaderObj)); initLeader(dst->leader); } msCopyLabelLeader(dst->leader,src->leader); } MS_COPYSTRING(dst->keyimage, src->keyimage); MS_COPYSTRING(dst->name, src->name); MS_COPYSTRING(dst->title, src->title); MS_COPYSTRING(dst->group, src->group); if (msCopyExpression(&(dst->text), &(src->text)) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy text.", "msCopyClass()"); return MS_FAILURE; } #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif if (&(src->metadata) != NULL) { /* dst->metadata = msCreateHashTable(); */ msCopyHashTable(&(dst->metadata), &(src->metadata)); } msCopyHashTable(&dst->validation,&src->validation); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); MS_COPYSTELEM(layer); MS_COPYSTELEM(debug); return MS_SUCCESS; } int msCopyCluster(clusterObj *dst, clusterObj *src) { int return_value; MS_COPYSTELEM(maxdistance); MS_COPYSTELEM(buffer); MS_COPYSTRING(dst->region, src->region); return_value = msCopyExpression(&(dst->group),&(src->group)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy cluster group.", "msCopyCluster()"); return MS_FAILURE; } return_value = msCopyExpression(&(dst->filter),&(src->filter)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy cluster filter.", "msCopyCluster()"); return MS_FAILURE; } return MS_SUCCESS; } /*********************************************************************** * msCopyGrid() * **********************************************************************/ int msCopyGrid(graticuleObj *dst, graticuleObj *src) { MS_COPYSTELEM(dwhichlatitude); MS_COPYSTELEM(dwhichlongitude); MS_COPYSTELEM(dstartlatitude); MS_COPYSTELEM(dstartlongitude); MS_COPYSTELEM(dendlatitude); MS_COPYSTELEM(dendlongitude); MS_COPYSTELEM(dincrementlatitude); MS_COPYSTELEM(dincrementlongitude); MS_COPYSTELEM(minarcs); MS_COPYSTELEM(maxarcs); MS_COPYSTELEM(minincrement); MS_COPYSTELEM(maxincrement); MS_COPYSTELEM(minsubdivides); MS_COPYSTELEM(maxsubdivides); MS_COPYSTELEM(bvertical); MS_COPYSTELEM(blabelaxes); MS_COPYSTELEM(ilabelstate); MS_COPYSTELEM(ilabeltype); MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTRING(dst->labelformat, src->labelformat); return MS_SUCCESS; } #ifdef why_on_earth_would_you_copy_a_labelcache /*********************************************************************** * msCopyLabelCacheMember() * * * * Copy a labelCacheMemberObj using msCopyStyle(), msCopyPoint() * * * * Note: since it seems most users will want to clone maps rather than * * make exact copies, this method might not get much use. * **********************************************************************/ int msCopyLabelCacheMember(labelCacheMemberObj *dst, labelCacheMemberObj *src) { int i; MS_COPYSTELEM(featuresize); MS_COPYSTELEM(numstyles); for (i = 0; i < dst->numstyles; i++) { msCopyStyle(&(dst->styles[i]), &(src->styles[i])); } MS_COPYSTELEM(numlabels); dst->labels = (labelObj *) msSmallMalloc(sizeof(labelObj)*dst->numlabels); for (i = 0; i < dst->numlabels; i++) { msCopyLabel(&(dst->labels[i]), &(src->labels[i])); } MS_COPYSTELEM(layerindex); MS_COPYSTELEM(classindex); MS_COPYSTELEM(tileindex); MS_COPYSTELEM(shapeindex); MS_COPYPOINT(&(dst->point), &(src->point)); /* msCopyShape(&(dst->poly), &(src->poly)); */ MS_COPYSTELEM(status); return MS_SUCCESS; } /*********************************************************************** * msCopyMarkerCacheMember() * * * * Copy a markerCacheMemberObj * **********************************************************************/ int msCopyMarkerCacheMember(markerCacheMemberObj *dst, markerCacheMemberObj *src) { MS_COPYSTELEM(id); /* msCopyShape(&(dst->poly), &(src->poly)); */ return MS_SUCCESS; } /*********************************************************************** * msCopyLabelCacheSlot() * **********************************************************************/ int msCopyLabelCacheSlot(labelCacheSlotObj *dst, labelCacheSlotObj *src) { int i; for (i = 0; i < dst->numlabels; i++) { msCopyLabelCacheMember(&(dst->labels[i]), &(src->labels[i])); } MS_COPYSTELEM(cachesize); MS_COPYSTELEM(nummarkers); for (i = 0; i < dst->nummarkers; i++) { msCopyMarkerCacheMember(&(dst->markers[i]), &(src->markers[i])); } MS_COPYSTELEM(markercachesize); return MS_SUCCESS; } /*********************************************************************** * msCopyLabelCache() * **********************************************************************/ int msCopyLabelCache(labelCacheObj *dst, labelCacheObj *src) { int p; MS_COPYSTELEM(numlabels); for (p=0; pslots[p]), &(src->slots[p])); } return MS_SUCCESS; } #endif /*********************************************************************** * msCopyResult() * **********************************************************************/ int msCopyResult(resultObj *dst, resultObj *src) { MS_COPYSTELEM(shapeindex); MS_COPYSTELEM(tileindex); MS_COPYSTELEM(classindex); MS_COPYSTELEM(resultindex); return MS_SUCCESS; } /*********************************************************************** * msCopyResultCache() * **********************************************************************/ int msCopyResultCache(resultCacheObj *dst, resultCacheObj *src) { int i; MS_COPYSTELEM(cachesize); MS_COPYSTELEM(numresults); for (i = 0; i < dst->numresults; i++) { msCopyResult(&(dst->results[i]), &(src->results[i])); } MS_COPYRECT(&(dst->bounds), &(src->bounds)); return MS_SUCCESS; } /*********************************************************************** * msCopyReferenceMap() * * * * Copy a referenceMapObj using mapfile.c:initReferenceMap(), * * msCopyRect(), msCopyColor() * **********************************************************************/ int msCopyReferenceMap(referenceMapObj *dst, referenceMapObj *src, mapObj *map) { initReferenceMap(dst); MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYCOLOR(&(dst->color), &(src->color)); MS_COPYCOLOR(&(dst->outlinecolor),&(src->outlinecolor)); MS_COPYSTRING(dst->image, src->image); MS_COPYSTELEM(status); MS_COPYSTELEM(marker); MS_COPYSTRING(dst->markername, src->markername); MS_COPYSTELEM(markersize); MS_COPYSTELEM(minboxsize); MS_COPYSTELEM(maxboxsize); dst->map = map; return MS_SUCCESS; } /*********************************************************************** * msCopyScalebar() * * * * Copy a scalebarObj, using initScalebar(), msCopyColor(), * * and msCopyLabel() * **********************************************************************/ int msCopyScalebar(scalebarObj *dst, scalebarObj *src) { initScalebar(dst); MS_COPYCOLOR(&(dst->imagecolor), &(src->imagecolor)); MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYSTELEM(style); MS_COPYSTELEM(intervals); if (msCopyLabel(&(dst->label), &(src->label)) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy label.","msCopyScalebar()"); return MS_FAILURE; } MS_COPYCOLOR(&(dst->color), &(src->color)); MS_COPYCOLOR(&(dst->backgroundcolor), &(src->backgroundcolor)); MS_COPYCOLOR(&(dst->outlinecolor), &(src->outlinecolor)); MS_COPYSTELEM(units); MS_COPYSTELEM(status); MS_COPYSTELEM(position); MS_COPYSTELEM(transparent); MS_COPYSTELEM(interlace); MS_COPYSTELEM(postlabelcache); MS_COPYSTELEM(align); return MS_SUCCESS; } /*********************************************************************** * msCopyLegend() * * * * Copy a legendObj, using msCopyColor() * **********************************************************************/ int msCopyLegend(legendObj *dst, legendObj *src, mapObj *map) { int return_value; MS_COPYCOLOR(&(dst->imagecolor), &(src->imagecolor)); return_value = msCopyLabel(&(dst->label), &(src->label)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy label.", "msCopyLegend()"); return MS_FAILURE; } MS_COPYSTELEM(keysizex); MS_COPYSTELEM(keysizey); MS_COPYSTELEM(keyspacingx); MS_COPYSTELEM(keyspacingy); MS_COPYCOLOR(&(dst->outlinecolor),&(src->outlinecolor)); MS_COPYSTELEM(status); MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYSTELEM(position); MS_COPYSTELEM(transparent); MS_COPYSTELEM(interlace); MS_COPYSTELEM(postlabelcache); #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif dst->map = map; return MS_SUCCESS; } int msCopyScaleTokenEntry(scaleTokenEntryObj *src, scaleTokenEntryObj *dst) { MS_COPYSTRING(dst->value,src->value); MS_COPYSTELEM(minscale); MS_COPYSTELEM(maxscale); return MS_SUCCESS; } int msCopyScaleToken(scaleTokenObj *src, scaleTokenObj *dst) { int i; MS_COPYSTRING(dst->name,src->name); MS_COPYSTELEM(n_entries); dst->tokens = (scaleTokenEntryObj*)msSmallCalloc(src->n_entries,sizeof(scaleTokenEntryObj)); for(i=0;in_entries;i++) { msCopyScaleTokenEntry(&src->tokens[i],&dst->tokens[i]); } return MS_SUCCESS; } int msCopyCompositingFilter(CompositingFilter **pdst, CompositingFilter *src) { CompositingFilter *dst = NULL; if(!src) { *pdst = NULL; return MS_SUCCESS; } while(src) { if(!dst) { dst = *pdst = msSmallMalloc(sizeof(CompositingFilter)); } else { dst->next = msSmallMalloc(sizeof(CompositingFilter)); dst = dst->next; } dst->filter = msStrdup(src->filter); dst->next = NULL; src = src->next; } return MS_SUCCESS; } int msCopyCompositer(LayerCompositer **ldst, LayerCompositer *src) { LayerCompositer *dst = NULL; if(!src) { *ldst = NULL; return MS_SUCCESS; } while(src) { if(!dst) { dst = *ldst = msSmallMalloc(sizeof(LayerCompositer)); } else { dst->next = msSmallMalloc(sizeof(LayerCompositer)); dst = dst->next; } dst->comp_op = src->comp_op; dst->opacity = src->opacity; dst->next = NULL; msCopyCompositingFilter(&dst->filter, src->filter); src = src->next; } return MS_SUCCESS; } /*********************************************************************** * msCopyLayer() * * * * Copy a layerObj, using mapfile.c:initClass(), msCopyClass(), * * msCopyColor(), msCopyProjection(), msShapefileOpen(), * * msCreateHashTable(), msCopyHashTable(), msCopyExpression() * * * * As it stands, we are not copying a layer's resultcache * **********************************************************************/ int msCopyLayer(layerObj *dst, layerObj *src) { int i, return_value; featureListNodeObjPtr current; MS_COPYSTELEM(index); MS_COPYSTRING(dst->classitem, src->classitem); MS_COPYSTELEM(classitemindex); for(i = 0; i < src->numscaletokens; i++) { if(msGrowLayerScaletokens(dst) == NULL) return MS_FAILURE; initScaleToken(&dst->scaletokens[i]); msCopyScaleToken(&src->scaletokens[i],&dst->scaletokens[i]); dst->numscaletokens++; } for (i = 0; i < src->numclasses; i++) { if (msGrowLayerClasses(dst) == NULL) return MS_FAILURE; #ifndef __cplusplus initClass(dst->class[i]); return_value = msCopyClass(dst->class[i], src->class[i], dst); #else initClass(dst->_class[i]); return_value = msCopyClass(dst->_class[i], src->_class[i], dst); #endif if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy class.", "msCopyLayer()"); return MS_FAILURE; } dst->numclasses++; } MS_COPYSTRING(dst->header, src->header); MS_COPYSTRING(dst->footer, src->footer); #ifndef __cplusplus MS_COPYSTRING(dst->template, src->template); #else MS_COPYSTRING(dst->_template, src->_template); #endif MS_COPYSTRING(dst->name, src->name); MS_COPYSTRING(dst->group, src->group); MS_COPYSTRING(dst->data, src->data); MS_COPYSTRING(dst->encoding, src->encoding); MS_COPYSTELEM(status); MS_COPYSTELEM(type); MS_COPYSTELEM(tolerance); MS_COPYSTELEM(toleranceunits); MS_COPYSTELEM(symbolscaledenom); MS_COPYSTELEM(scalefactor); MS_COPYSTELEM(minscaledenom); MS_COPYSTELEM(maxscaledenom); MS_COPYSTELEM(labelminscaledenom); MS_COPYSTELEM(labelmaxscaledenom); MS_COPYSTELEM(mingeowidth); MS_COPYSTELEM(maxgeowidth); MS_COPYSTELEM(sizeunits); MS_COPYSTELEM(maxfeatures); MS_COPYCOLOR(&(dst->offsite), &(src->offsite)); MS_COPYSTELEM(transform); MS_COPYSTELEM(labelcache); MS_COPYSTELEM(postlabelcache); MS_COPYSTRING(dst->labelitem, src->labelitem); MS_COPYSTELEM(labelitemindex); MS_COPYSTRING(dst->tileitem, src->tileitem); MS_COPYSTELEM(tileitemindex); MS_COPYSTRING(dst->tilesrs, src->tilesrs); MS_COPYSTRING(dst->tileindex, src->tileindex); return_value = msCopyProjection(&(dst->projection),&(src->projection)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy projection.", "msCopyLayer()"); return MS_FAILURE; } return_value = msCopyCluster(&(dst->cluster),&(src->cluster)); if (return_value != MS_SUCCESS) { return MS_FAILURE; } MS_COPYSTELEM(project); MS_COPYSTELEM(units); current = src->features; while(current != NULL) { insertFeatureList(&(dst->features), &(current->shape)); current = current->next; } MS_COPYSTRING(dst->connection, src->connection); MS_COPYSTELEM(connectiontype); MS_COPYSTRING(dst->plugin_library, src->plugin_library); MS_COPYSTRING(dst->plugin_library_original, src->plugin_library_original); /* Do not copy *layerinfo, items, or iteminfo. these are all initialized when the copied layer is opened */ return_value = msCopyExpression(&(dst->filter), &(src->filter)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy filter.", "msCopyLayer()"); return MS_FAILURE; } MS_COPYSTRING(dst->filteritem, src->filteritem); MS_COPYSTELEM(filteritemindex); MS_COPYSTRING(dst->styleitem, src->styleitem); MS_COPYSTELEM(styleitemindex); MS_COPYSTRING(dst->requires, src->requires); MS_COPYSTRING(dst->labelrequires, src->labelrequires); if (&(src->metadata)) { msCopyHashTable(&(dst->metadata), &(src->metadata)); } msCopyHashTable(&dst->validation,&src->validation); MS_COPYSTELEM(dump); MS_COPYSTELEM(debug); /* No need to copy the numprocessing member, as it is incremented by msLayerAddProcessing */ for (i = 0; i < src->numprocessing; i++) { msLayerAddProcessing(dst, msLayerGetProcessing(src, i)); } MS_COPYSTELEM(numjoins); for (i = 0; i < dst->numjoins; i++) { initJoin(&(dst->joins[i])); return_value = msCopyJoin(&(dst->joins[i]), &(src->joins[i])); if (return_value != MS_SUCCESS) return MS_FAILURE; } MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTRING(dst->classgroup, src->classgroup); MS_COPYSTRING(dst->mask, src->mask); if (src->grid) { if (dst->grid) { freeGrid(dst->grid); msFree(dst->grid); } dst->grid = (void *) malloc(sizeof(graticuleObj)); MS_CHECK_ALLOC(dst->grid, sizeof(graticuleObj), -1); initGrid(dst->grid); msCopyGrid(dst->grid, src->grid); } if(src->compositer) { msCopyCompositer(&dst->compositer, src->compositer); } return MS_SUCCESS; } /*********************************************************************** * msCopyMap() * * * * Copy a mapObj, using mapfile.c:initLayer(), msCopyLayer(), * * msCopyLegend(), msCopyScalebar(), msCopyProjection() * * msCopyOutputFormat(), msCopyWeb(), msCopyReferenceMap() * **********************************************************************/ int msCopyMap(mapObj *dst, mapObj *src) { int i, return_value; outputFormatObj *format; MS_COPYSTRING(dst->name, src->name); MS_COPYSTELEM(status); MS_COPYSTELEM(height); MS_COPYSTELEM(width); MS_COPYSTELEM(maxsize); for (i = 0; i < src->numlayers; i++) { if (msGrowMapLayers(dst) == NULL) return MS_FAILURE; initLayer((GET_LAYER(dst, i)), dst); return_value = msCopyLayer((GET_LAYER(dst, i)), (GET_LAYER(src, i))); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy layer.", "msCopyMap()"); return MS_FAILURE; } dst->numlayers++; } return_value = msCopyFontSet(&(dst->fontset), &(src->fontset), dst); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy fontset.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopySymbolSet(&(dst->symbolset), &(src->symbolset), dst); if(return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy symbolset.", "msCopyMap()"); return MS_FAILURE; } /* msCopyLabelCache(&(dst->labelcache), &(src->labelcache)); */ MS_COPYSTELEM(transparent); MS_COPYSTELEM(interlace); MS_COPYSTELEM(imagequality); MS_COPYRECT(&(dst->extent), &(src->extent)); MS_COPYSTELEM(cellsize); MS_COPYSTELEM(units); MS_COPYSTELEM(scaledenom); MS_COPYSTELEM(defresolution); MS_COPYSTELEM(resolution); MS_COPYSTRING(dst->shapepath, src->shapepath); MS_COPYSTRING(dst->mappath, src->mappath); MS_COPYCOLOR(&(dst->imagecolor), &(src->imagecolor)); /* clear existing destination format list */ if( dst->outputformat && --dst->outputformat->refcount < 1 ) { msFreeOutputFormat( dst->outputformat ); dst->outputformat = NULL; } for(i=0; i < dst->numoutputformats; i++ ) { if( --dst->outputformatlist[i]->refcount < 1 ) msFreeOutputFormat( dst->outputformatlist[i] ); } if( dst->outputformatlist != NULL ) msFree( dst->outputformatlist ); dst->outputformatlist = NULL; dst->outputformat = NULL; dst->numoutputformats = 0; for (i = 0; i < src->numoutputformats; i++) msAppendOutputFormat( dst, msCloneOutputFormat( src->outputformatlist[i]) ); /* set the active output format */ MS_COPYSTRING(dst->imagetype, src->imagetype); format = msSelectOutputFormat( dst, dst->imagetype ); msApplyOutputFormat(&(dst->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); return_value = msCopyProjection(&(dst->projection),&(src->projection)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy projection.", "msCopyMap()"); return MS_FAILURE; } /* No need to copy latlon projection */ return_value = msCopyReferenceMap(&(dst->reference),&(src->reference), dst); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy reference.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopyScalebar(&(dst->scalebar), &(src->scalebar)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy scalebar.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopyLegend(&(dst->legend), &(src->legend),dst); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy legend.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopyQueryMap(&(dst->querymap), &(src->querymap)); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy querymap.", "msCopyMap()"); return MS_FAILURE; } return_value = msCopyWeb(&(dst->web), &(src->web), dst); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy web.", "msCopyMap()"); return MS_FAILURE; } for (i = 0; i < dst->numlayers; i++) { MS_COPYSTELEM(layerorder[i]); } MS_COPYSTELEM(debug); MS_COPYSTRING(dst->datapattern, src->datapattern); MS_COPYSTRING(dst->templatepattern, src->templatepattern); if( msCopyHashTable( &(dst->configoptions), &(src->configoptions) ) != MS_SUCCESS ) return MS_FAILURE; return MS_SUCCESS; } int msCopyRasterBuffer(rasterBufferObj *dst, const rasterBufferObj *src) { *dst = *src; if(src->type == MS_BUFFER_BYTE_RGBA) { dst->data.rgba = src->data.rgba; dst->data.rgba.pixels = msSmallMalloc(src->height * src->data.rgba.row_step); memcpy(dst->data.rgba.pixels, src->data.rgba.pixels, src->data.rgba.row_step*src->height); dst->data.rgba.r = dst->data.rgba.pixels + (src->data.rgba.r - src->data.rgba.pixels); dst->data.rgba.g = dst->data.rgba.pixels + (src->data.rgba.g - src->data.rgba.pixels); dst->data.rgba.b = dst->data.rgba.pixels + (src->data.rgba.b - src->data.rgba.pixels); if(src->data.rgba.a) { dst->data.rgba.a = dst->data.rgba.pixels + (src->data.rgba.a - src->data.rgba.pixels); } else { dst->data.rgba.a = NULL; } } return MS_SUCCESS; } mapserver-7.4.3/mapcopy.h000066400000000000000000000062071357574274700154040ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations related to copyng mapObjs. Provided by Mladen Turk * for resolution of bug 701 * http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=701. * Author: Mladen Turk (and Sean Gilles?) * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* Following works for GCC and MSVC. That's ~98% of our users, if Tyler * Mitchell's survey is correct */ #define MS_COPYSTELEM(_name) (dst)->/**/_name = (src)->/**/_name #define MS_MACROBEGIN do { #define MS_MACROEND } while (0) #define MS_COPYRECT(_dst, _src) \ MS_MACROBEGIN \ (_dst)->minx = (_src)->minx; \ (_dst)->miny = (_src)->miny; \ (_dst)->maxx = (_src)->maxx; \ (_dst)->maxy = (_src)->maxy; \ MS_MACROEND #ifdef USE_POINT_Z_M #define MS_COPYPOINT(_dst, _src) \ MS_MACROBEGIN \ (_dst)->x = (_src)->x; \ (_dst)->y = (_src)->y; \ (_dst)->m = (_src)->m; \ MS_MACROEND #else #define MS_COPYPOINT(_dst, _src) \ MS_MACROBEGIN \ (_dst)->x = (_src)->x; \ (_dst)->y = (_src)->y; \ MS_MACROEND #endif #define MS_COPYCOLOR(_dst, _src) \ MS_MACROBEGIN \ (_dst)->red = (_src)->red; \ (_dst)->green = (_src)->green;\ (_dst)->blue = (_src)->blue; \ (_dst)->alpha = (_src)->alpha; \ MS_MACROEND #define MS_COPYSTRING(_dst, _src) \ MS_MACROBEGIN \ if ((_dst) != NULL) \ msFree((_dst)); \ if ((_src)) \ (_dst) = msStrdup((_src)); \ else \ (_dst) = NULL; \ MS_MACROEND mapserver-7.4.3/mapcpl.c000066400000000000000000000220611357574274700151770ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions copied from GDAL's CPL. This file contain utility * functions that come from the GDAL/OGR cpl library. The idea * behind it is to have access in mapserver to all these * utilities, without being constrained to link with GDAL/OGR. * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * * * Note: * Names of functions used here are the same as those in the cpl * library with the exception the the CPL prefix is changed to ms * (eg : CPLGetBasename() would become msGetBasename()) * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* $Id$ */ #include #include "mapserver.h" /* should be size of largest possible filename */ #define MS_PATH_BUF_SIZE 2048 static char szStaticResult[MS_PATH_BUF_SIZE]; /************************************************************************/ /* msFindFilenameStart() */ /************************************************************************/ static int msFindFilenameStart( const char * pszFilename ) { int iFileStart; for( iFileStart = strlen(pszFilename); iFileStart > 0 && pszFilename[iFileStart-1] != '/' && pszFilename[iFileStart-1] != '\\'; iFileStart-- ) {} return iFileStart; } /************************************************************************/ /* msGetBasename() */ /************************************************************************/ /** * Extract basename (non-directory, non-extension) portion of filename. * * Returns a string containing the file basename portion of the passed * name. If there is no basename (passed value ends in trailing directory * separator, or filename starts with a dot) an empty string is returned. * *
 * msGetBasename( "abc/def.xyz" ) == "def"
 * msGetBasename( "abc/def" ) == "def"
 * msGetBasename( "abc/def/" ) == ""
 * 
* * @param pszFullFilename the full filename potentially including a path. * * @return just the non-directory, non-extension portion of the path in * an internal string which must not be freed. The string * may be destroyed by the next ms filename handling call. */ const char *msGetBasename( const char *pszFullFilename ) { int iFileStart = msFindFilenameStart( pszFullFilename ); int iExtStart, nLength; for( iExtStart = strlen(pszFullFilename); iExtStart > iFileStart && pszFullFilename[iExtStart] != '.'; iExtStart-- ) {} if( iExtStart == iFileStart ) iExtStart = strlen(pszFullFilename); nLength = iExtStart - iFileStart; assert( nLength < MS_PATH_BUF_SIZE ); strlcpy( szStaticResult, pszFullFilename + iFileStart, nLength+1 ); return szStaticResult; } /* Id: GDAL/port/cplgetsymbol.cpp,v 1.14 2004/11/11 20:40:38 fwarmerdam Exp */ /* ==================================================================== */ /* Unix Implementation */ /* ==================================================================== */ #if defined(HAVE_DLFCN_H) #define GOT_GETSYMBOL #include /************************************************************************/ /* msGetSymbol() */ /************************************************************************/ /** * Fetch a function pointer from a shared library / DLL. * * This function is meant to abstract access to shared libraries and * DLLs and performs functions similar to dlopen()/dlsym() on Unix and * LoadLibrary() / GetProcAddress() on Windows. * * If no support for loading entry points from a shared library is available * this function will always return NULL. Rules on when this function * issues a msError() or not are not currently well defined, and will have * to be resolved in the future. * * Currently msGetSymbol() doesn't try to: *
    *
  • prevent the reference count on the library from going up * for every request, or given any opportunity to unload * the library. *
  • Attempt to look for the library in non-standard * locations. *
  • Attempt to try variations on the symbol name, like * pre-prending or post-pending an underscore. *
* * Some of these issues may be worked on in the future. * * @param pszLibrary the name of the shared library or DLL containing * the function. May contain path to file. If not system supplies search * paths will be used. * @param pszSymbolName the name of the function to fetch a pointer to. * @return A pointer to the function if found, or NULL if the function isn't * found, or the shared library can't be loaded. */ void *msGetSymbol( const char * pszLibrary, const char * pszSymbolName ) { void *pLibrary; void *pSymbol; pLibrary = dlopen(pszLibrary, RTLD_LAZY); if( pLibrary == NULL ) { msSetError(MS_MISCERR, "Dynamic loading failed: %s", "msGetSymbol()", dlerror()); return NULL; } pSymbol = dlsym( pLibrary, pszSymbolName ); #if (defined(__APPLE__) && defined(__MACH__)) /* On mach-o systems, C symbols have a leading underscore and depending * on how dlcompat is configured it may or may not add the leading * underscore. So if dlsym() fails add an underscore and try again. */ if( pSymbol == NULL ) { char withUnder[strlen(pszSymbolName) + 2]; withUnder[0] = '_'; withUnder[1] = 0; strcat(withUnder, pszSymbolName); pSymbol = dlsym( pLibrary, withUnder ); } #endif if( pSymbol == NULL ) { msSetError(MS_MISCERR, "Dynamic loading failed: %s", "msGetSymbol()", dlerror()); return NULL; } return( pSymbol ); } #endif /* def __unix__ && defined(HAVE_DLFCN_H) */ /* ==================================================================== */ /* Windows Implementation */ /* ==================================================================== */ #ifdef WIN32 #define GOT_GETSYMBOL #include /************************************************************************/ /* msGetSymbol() */ /************************************************************************/ void *msGetSymbol( const char * pszLibrary, const char * pszSymbolName ) { void *pLibrary; void *pSymbol; pLibrary = LoadLibrary(pszLibrary); if( pLibrary == NULL ) { msSetError(MS_MISCERR, "Can't load requested dynamic library: %s", "msGetSymbol()", pszLibrary); return NULL; } pSymbol = (void *) GetProcAddress( (HINSTANCE) pLibrary, pszSymbolName ); if( pSymbol == NULL ) { msSetError(MS_MISCERR, "Can't find requested entry point: %s in lib %s", "msGetSymbol()", pszSymbolName, pLibrary); return NULL; } return( pSymbol ); } #endif /* def _WIN32 */ /* ==================================================================== */ /* Dummy implementation. */ /* ==================================================================== */ #ifndef GOT_GETSYMBOL /************************************************************************/ /* msGetSymbol() */ /* */ /* Dummy implementation. */ /************************************************************************/ void *msGetSymbol(const char *pszLibrary, const char *pszEntryPoint) { msSetError(MS_MISCERR, "msGetSymbol(%s,%s) called. Failed as this is stub implementation.", "msGetSymbol()", pszLibrary, pszEntryPoint); return NULL; } #endif mapserver-7.4.3/mapcrypto.c000066400000000000000000000451311357574274700157440ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Encryption functions (see MS-RFC-18) * Author: Daniel Morissette * ****************************************************************************** * Copyright (c) 1996-2006 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include /* isxdigit() */ #include /* rand() */ #include /* time() */ #include "mapserver.h" /********************************************************************** * encipher() and decipher() from the Tiny Encryption Algorithm (TEA) * website at: * http://www.simonshepherd.supanet.com/tea.htm * * TEA was developed and placed in the public domain by David Wheeler * and Roger Needham at the Computer Laboratory of Cambridge University. * * The source below came with the following public domain notice: * * "Please feel free to use any of this code in your applications. * The TEA algorithm (including new-variant TEA) has been placed * in the public domain, as have my assembly language implementations." * * ... and the following usage notes: * * All the routines have the general form * * void encipher(const unsigned long *const v,unsigned long *const w, * const unsigned long * const k); * * void decipher(const unsigned long *const v,unsigned long *const w, * const unsigned long * const k); * * TEA takes 64 bits of data in v[0] and v[1], and 128 bits of key in * k[0] - k[3]. The result is returned in w[0] and w[1]. Returning the * result separately makes implementation of cipher modes other than * Electronic Code Book a little bit easier. * * TEA can be operated in any of the modes of DES. * * n is the number of iterations. 32 is ample, 16 is sufficient, as few * as eight should be OK for most applications, especially ones where * the data age quickly (real-time video, for example). The algorithm * achieves good dispersion after six iterations. The iteration count * can be made variable if required. * * Note this algorithm is optimised for 32-bit CPUs with fast shift * capabilities. It can very easily be ported to assembly language * on most CPUs. * * delta is chosen to be the Golden ratio ((5/4)1/2 - 1/2 ~ 0.618034) * multiplied by 232. On entry to decipher(), sum is set to be delta * n. * Which way round you call the functions is arbitrary: DK(EK(P)) = EK(DK(P)) * where EK and DK are encryption and decryption under key K respectively. * **********************************************************************/ static void encipher(const ms_uint32 *const v, ms_uint32 *const w, const ms_uint32 *const k) { register ms_uint32 y=v[0],z=v[1],sum=0,delta=0x9E3779B9,n=32; while(n-->0) { y += ((z << 4 ^ z >> 5) + z) ^ (sum + k[sum&3]); sum += delta; z += ((y << 4 ^ y >> 5) + y) ^ (sum + k[sum>>11 & 3]); } w[0]=y; w[1]=z; } static void decipher(const ms_uint32 *const v, ms_uint32 *const w, const ms_uint32 *const k) { register ms_uint32 y=v[0],z=v[1],sum=0xC6EF3720, delta=0x9E3779B9,n=32; /* sum = delta<<5, in general sum = delta * n */ while(n-->0) { z -= ((y << 4 ^ y >> 5) + y) ^ (sum + k[sum>>11 & 3]); sum -= delta; y -= ((z << 4 ^ z >> 5) + z) ^ (sum + k[sum&3]); } w[0]=y; w[1]=z; } /********************************************************************** * msHexEncode() * * Hex-encode numbytes from in[] and return the result in out[]. * * out[] should be preallocated by the caller to be at least 2*numbytes+1 * (+1 for the terminating '\0') **********************************************************************/ void msHexEncode(const unsigned char *in, char *out, int numbytes) { char *hex = "0123456789ABCDEF"; while (numbytes-- > 0) { *out++ = hex[*in/16]; *out++ = hex[*in%16]; in++; } *out = '\0'; } /********************************************************************** * msHexDecode() * * Hex-decode numchars from in[] and return the result in out[]. * * If numchars > 0 then only up to this number of chars from in[] are * processed, otherwise the full in[] string up to the '\0' is processed. * * out[] should be preallocated by the caller to be large enough to hold * the resulting bytes. * * Returns the number of bytes written to out[] which may be different from * numchars/2 if an error or a '\0' is encountered. **********************************************************************/ int msHexDecode(const char *in, unsigned char *out, int numchars) { int numbytes_out = 0; /* Make sure numchars is even */ numchars = (numchars/2) * 2; if (numchars < 2) numchars = -1; /* Will result in this value being ignored in the loop*/ while (*in != '\0' && *(in+1) != '\0' && numchars != 0) { *out = 0x10 * (*in >= 'A' ? ((*in & 0xdf) - 'A')+10 : (*in - '0')); in++; *out += (*in >= 'A' ? ((*in & 0xdf) - 'A')+10 : (*in - '0')); in++; out++; numbytes_out++; numchars -= 2; } return numbytes_out; } /********************************************************************** * msGenerateEncryptionKey() * * Create a new encryption key. * * The output buffer should be at least MS_ENCRYPTION_KEY_SIZE bytes. **********************************************************************/ int msGenerateEncryptionKey(unsigned char *k) { int i; /* Use current time as seed for rand() */ srand( (unsigned int) time( NULL )); for(i=0; iencryption_key. * If the key is already set in the mapObj then it does nothing and returns. * * The location of the encryption key can be specified in two ways, * either by setting the environment variable MS_ENCRYPTION_KEY or using * a CONFIG directive: * CONFIG MS_ENCRYPTION_KEY "/path/to/mykey.txt" * Returns MS_SUCCESS/MS_FAILURE. **********************************************************************/ static int msLoadEncryptionKey(mapObj *map) { const char *keyfile; if (map == NULL) { msSetError(MS_MISCERR, "NULL MapObj.", "msLoadEncryptionKey()"); return MS_FAILURE; } if (map->encryption_key_loaded) return MS_SUCCESS; /* Already loaded */ keyfile = msGetConfigOption(map, "MS_ENCRYPTION_KEY"); if (keyfile == NULL) keyfile = getenv("MS_ENCRYPTION_KEY"); if (keyfile && msReadEncryptionKeyFromFile(keyfile,map->encryption_key) == MS_SUCCESS) { map->encryption_key_loaded = MS_TRUE; } else { msSetError(MS_MISCERR, "Failed reading encryption key. Make sure " "MS_ENCRYPTION_KEY is set and points to a valid key file.", "msLoadEncryptionKey()"); return MS_FAILURE; } return MS_SUCCESS; } /********************************************************************** * msEncryptStringWithKey() * * Encrypts and hex-encodes the contents of string in[] and returns the * result in out[] which should have been pre-allocated by the caller * to be at least twice the size of in[] + 16+1 bytes (for padding + '\0'). * **********************************************************************/ void msEncryptStringWithKey(const unsigned char *key, const char *in, char *out) { ms_uint32 v[4], w[4]; const ms_uint32 *k; int last_block = MS_FALSE; /* Casting the key this way is safe only as long as longs are 4 bytes * on this platform */ assert(sizeof(ms_uint32) == 4); k = (const ms_uint32 *) key; while(!last_block) { int i, j; /* encipher() takes v[2] (64 bits) as input. * Copy bytes from in[] to the v[2] input array (pair of 4 bytes) * v[] is padded with zeros if string doesn't align with 8 bytes */ v[0] = 0; v[1] = 0; for(i=0; !last_block && i<2; i++) { for(j=0; j<4; j++) { if (*in == '\0') { last_block = MS_TRUE; break; } v[i] |= *in << (j*8); in++; } } if (*in == '\0') last_block = MS_TRUE; /* Do the actual encryption */ encipher(v, w, k); /* Append hex-encoded bytes to output, 4 bytes at a time */ msHexEncode((unsigned char *)w, out, 4); out += 8; msHexEncode((unsigned char *)(w+1), out, 4); out += 8; } /* Make sure output is 0-terminated */ *out = '\0'; } /********************************************************************** * msDecryptStringWithKey() * * Hex-decodes and then decrypts the contents of string in[] and returns the * result in out[] which should have been pre-allocated by the caller * to be at least half the size of in[]. * **********************************************************************/ void msDecryptStringWithKey(const unsigned char *key, const char *in, char *out) { ms_uint32 v[4], w[4]; const ms_uint32 *k; int last_block = MS_FALSE; /* Casting the key this way is safe only as long as longs are 4 bytes * on this platform */ assert(sizeof(ms_uint32) == 4); k = (const ms_uint32 *) key; while(!last_block) { int i; /* decipher() takes v[2] (64 bits) as input. * Copy bytes from in[] to the v[2] input array (pair of 4 bytes) * v[] is padded with zeros if string doesn't align with 8 bytes */ v[0] = 0; v[1] = 0; if (msHexDecode(in, (unsigned char *)v, 8) != 4) last_block = MS_TRUE; else { in += 8; if (msHexDecode(in, (unsigned char *)(v+1), 8) != 4) last_block = MS_TRUE; else in += 8; } /* Do the actual decryption */ decipher(v, w, k); /* Copy the results to out[] */ for(i=0; i<2; i++) { *out++ = (w[i] & 0x000000ff); *out++ = (w[i] & 0x0000ff00) >> 8; *out++ = (w[i] & 0x00ff0000) >> 16; *out++ = (w[i] & 0xff000000) >> 24; } if (*in == '\0') last_block = MS_TRUE; } /* Make sure output is 0-terminated */ *out = '\0'; } /********************************************************************** * msDecryptStringTokens() * * Returns a newly allocated string (to be msFree'd by the caller) in * which all occurences of encrypted strings delimited by {...} have * been decrypted. * **********************************************************************/ char *msDecryptStringTokens(mapObj *map, const char *in) { char *outbuf, *out; if (map == NULL) { msSetError(MS_MISCERR, "NULL MapObj.", "msLoadEncryptionKey()"); return NULL; } /* Start with a copy of the string. Decryption can only result in * a string with the same or shorter length */ if ((outbuf = (char *)malloc((strlen(in)+1)*sizeof(char))) == NULL) { msSetError(MS_MEMERR, NULL, "msDecryptStringTokens()"); return NULL; } out = outbuf; while(*in != '\0') { if (*in == '{') { /* Possibly beginning of a token, look for closing bracket ** and make sure all chars in between are valid hex encoding chars */ const char *pszStart, *pszEnd; int valid_token = MS_FALSE; pszStart = in+1; if ( (pszEnd = strchr(pszStart, '}')) != NULL && pszEnd - pszStart > 1) { const char *pszTmp; valid_token = MS_TRUE; for(pszTmp = pszStart; pszTmp < pszEnd; pszTmp++) { if (!isxdigit(*pszTmp)) { valid_token = MS_FALSE; break; } } } if (valid_token) { /* Go ahead and decrypt the token */ char *pszTmp; /* Make sure encryption key is loaded. We do this here instead * of at the beginning of the function to avoid loading the * key unless ready necessary. This is a very cheap call if * the key is already loaded */ if (msLoadEncryptionKey(map) != MS_SUCCESS) return NULL; pszTmp = (char*)malloc( (pszEnd-pszStart+1)*sizeof(char)); strlcpy(pszTmp, pszStart, (pszEnd-pszStart)+1); msDecryptStringWithKey(map->encryption_key, pszTmp, out); out += strlen(out); in = pszEnd+1; free(pszTmp); } else { /* Not a valid token, just copy the '{' and keep going */ *out++ = *in++; } } else { /* Just copy any other chars */ *out++ = *in++; } } *out = '\0'; return outbuf; } #ifdef TEST_MAPCRYPTO /* Test for mapcrypto.c functions. To run these tests, use the following ** Makefile directive: test_mapcrypto: $(LIBMAP_STATIC) mapcrypto.c $(CC) $(CFLAGS) mapcrypto.c -DTEST_MAPCRYPTO $(EXE_LDFLAGS) -o test_mapcrypto ** */ int main(int argc, char *argv[]) { const unsigned char bytes_in[] = {0x12, 0x34, 0xff, 0x00, 0x44, 0x22}; unsigned char bytes_out[8], encryption_key[MS_ENCRYPTION_KEY_SIZE*2+1]; char string_buf[256], string_buf2[256]; int numbytes = 0; /* ** Test msHexEncode() */ msHexEncode(bytes_in, string_buf, 6); printf("msHexEncode returned '%s'\n", string_buf); /* ** Test msHexDecode() */ memset(bytes_out, 0, 8); numbytes = msHexDecode(string_buf, bytes_out, -1); printf("msHexDecode(%s, -1) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); memset(bytes_out, 0, 8); numbytes = msHexDecode(string_buf, bytes_out, 4); printf("msHexDecode(%s, 4) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); memset(bytes_out, 0, 8); numbytes = msHexDecode(string_buf, bytes_out, 20); printf("msHexDecode(%s, 20) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); /* ** Test loading encryption key */ if (msReadEncryptionKeyFromFile("/tmp/test.key", encryption_key) != MS_SUCCESS) { printf("msReadEncryptionKeyFromFile() = MS_FAILURE\n"); printf("Aborting tests!\n"); msWriteError(stderr); return -1; } else { msHexEncode(encryption_key, string_buf, MS_ENCRYPTION_KEY_SIZE); printf("msReadEncryptionKeyFromFile() returned '%s'\n", string_buf); } /* ** Test Encryption/Decryption */ /* First with an 8 bytes input string (test boundaries) */ msEncryptStringWithKey(encryption_key, "test1234", string_buf); printf("msEncryptStringWithKey('test1234') returned '%s'\n", string_buf); msDecryptStringWithKey(encryption_key, string_buf, string_buf2); printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, string_buf2); /* Next with an 1 byte input string */ msEncryptStringWithKey(encryption_key, "t", string_buf); printf("msEncryptStringWithKey('t') returned '%s'\n", string_buf); msDecryptStringWithKey(encryption_key, string_buf, string_buf2); printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, string_buf2); /* Next with an 12 bytes input string */ msEncryptStringWithKey(encryption_key, "test123456", string_buf); printf("msEncryptStringWithKey('test123456') returned '%s'\n", string_buf); msDecryptStringWithKey(encryption_key, string_buf, string_buf2); printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, string_buf2); /* ** Test decryption with tokens */ { char *pszBuf; mapObj *map; /* map = msNewMapObj(); */ map = msLoadMap("/tmp/test.map", NULL); sprintf(string_buf2, "string with a {%s} encrypted token", string_buf); pszBuf = msDecryptStringTokens(map, string_buf2); if (pszBuf == NULL) { printf("msDecryptStringTokens() failed.\n"); printf("Aborting tests!\n"); msWriteError(stderr); return -1; } else { printf("msDecryptStringTokens('%s') returned '%s'\n", string_buf2, pszBuf); } msFree(pszBuf); msFreeMap(map); } return 0; } #endif /* TEST_MAPCRYPTO */ mapserver-7.4.3/mapdebug.c000066400000000000000000000235051357574274700155130ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of debug/logging, msDebug() and related functions. * Author: Daniel Morissette * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "maperror.h" #include "mapthread.h" #include "maptime.h" #include #ifndef _WIN32 #include #include #endif #include #ifdef NEED_NONBLOCKING_STDERR #include #endif #ifdef _WIN32 #include /* OutputDebugStringA() */ #endif #ifndef USE_THREAD debugInfoObj *msGetDebugInfoObj() { static debugInfoObj debuginfo = {MS_DEBUGLEVEL_ERRORSONLY, MS_DEBUGMODE_OFF, NULL, NULL }; return &debuginfo; } #else static debugInfoObj *debuginfo_list = NULL; debugInfoObj *msGetDebugInfoObj() { debugInfoObj *link; void* thread_id; debugInfoObj *ret_obj; msAcquireLock( TLOCK_DEBUGOBJ ); thread_id = msGetThreadId(); /* find link for this thread */ for( link = debuginfo_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} /* If the target thread link is already at the head of the list were ok */ if( debuginfo_list != NULL && debuginfo_list->thread_id == thread_id ) { } /* We don't have one ... initialize one. */ else if( link == NULL || link->next == NULL ) { debugInfoObj *new_link; new_link = (debugInfoObj *) msSmallMalloc(sizeof(debugInfoObj)); new_link->next = debuginfo_list; new_link->thread_id = thread_id; new_link->global_debug_level = MS_DEBUGLEVEL_ERRORSONLY; new_link->debug_mode = MS_DEBUGMODE_OFF; new_link->errorfile = NULL; new_link->fp = NULL; debuginfo_list = new_link; } /* If the link is not already at the head of the list, promote it */ else if( link != NULL && link->next != NULL ) { debugInfoObj *target = link->next; link->next = link->next->next; target->next = debuginfo_list; debuginfo_list = target; } ret_obj = debuginfo_list; msReleaseLock( TLOCK_DEBUGOBJ ); return ret_obj; } #endif /* msSetErrorFile() ** ** Set output target, ready to write to it, open file if necessary ** ** If pszRelToPath != NULL then we will try to make the value relative to ** this path if it is not absolute already and it's not one of the special ** values (stderr, stdout, windowsdebug) ** ** Returns MS_SUCCESS/MS_FAILURE */ int msSetErrorFile(const char *pszErrorFile, const char *pszRelToPath) { char extended_path[MS_MAXPATHLEN]; debugInfoObj *debuginfo = msGetDebugInfoObj(); if (strcmp(pszErrorFile, "stderr") != 0 && strcmp(pszErrorFile, "stdout") != 0 && strcmp(pszErrorFile, "windowsdebug") != 0) { /* Try to make the path relative */ if(msBuildPath(extended_path, pszRelToPath, pszErrorFile) == NULL) return MS_FAILURE; pszErrorFile = extended_path; } if (debuginfo->errorfile && pszErrorFile && strcmp(debuginfo->errorfile, pszErrorFile) == 0) { /* Nothing to do, already writing to the right place */ return MS_SUCCESS; } /* Close current output file if any */ msCloseErrorFile(); /* NULL or empty target will just close current output and return */ if (pszErrorFile == NULL || *pszErrorFile == '\0') return MS_SUCCESS; if (strcmp(pszErrorFile, "stderr") == 0) { debuginfo->fp = stderr; debuginfo->errorfile = msStrdup(pszErrorFile); debuginfo->debug_mode = MS_DEBUGMODE_STDERR; } else if (strcmp(pszErrorFile, "stdout") == 0) { debuginfo->fp = stdout; debuginfo->errorfile = msStrdup(pszErrorFile); debuginfo->debug_mode = MS_DEBUGMODE_STDOUT; } else if (strcmp(pszErrorFile, "windowsdebug") == 0) { #ifdef _WIN32 debuginfo->errorfile = msStrdup(pszErrorFile); debuginfo->fp = NULL; debuginfo->debug_mode = MS_DEBUGMODE_WINDOWSDEBUG; #else msSetError(MS_MISCERR, "'MS_ERRORFILE windowsdebug' is available only on Windows platforms.", "msSetErrorFile()"); return MS_FAILURE; #endif } else { debuginfo->fp = fopen(pszErrorFile, "a"); if (debuginfo->fp == NULL) { msSetError(MS_MISCERR, "Failed to open MS_ERRORFILE %s", "msSetErrorFile()", pszErrorFile); return MS_FAILURE; } debuginfo->errorfile = msStrdup(pszErrorFile); debuginfo->debug_mode = MS_DEBUGMODE_FILE; } return MS_SUCCESS; } /* msCloseErrorFile() ** ** Close current output file (if one is open) and reset related members */ void msCloseErrorFile() { debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo && debuginfo->debug_mode != MS_DEBUGMODE_OFF) { if (debuginfo->fp && debuginfo->debug_mode == MS_DEBUGMODE_FILE) fclose(debuginfo->fp); if (debuginfo->fp && (debuginfo->debug_mode == MS_DEBUGMODE_STDERR || debuginfo->debug_mode == MS_DEBUGMODE_STDOUT)) fflush(debuginfo->fp); /* just flush stderr or stdout */ debuginfo->fp = NULL; msFree(debuginfo->errorfile); debuginfo->errorfile = NULL; debuginfo->debug_mode = MS_DEBUGMODE_OFF; } } /* msGetErrorFile() ** ** Returns name of current error file ** ** Returns NULL if not set. */ const char *msGetErrorFile() { debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo) return debuginfo->errorfile; return NULL; } /* Set/Get the current global debug level value, used as default value for ** new map and layer objects and to control msDebug() calls outside of ** the context of mapObj or layerObj. ** */ void msSetGlobalDebugLevel(int level) { debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo) debuginfo->global_debug_level = (debugLevel)level; } debugLevel msGetGlobalDebugLevel() { debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo) return debuginfo->global_debug_level; return MS_DEBUGLEVEL_ERRORSONLY; } /* msDebugInitFromEnv() ** ** Init debug state from MS_ERRORFILE and MS_DEBUGLEVEL env vars if set ** ** Returns MS_SUCCESS/MS_FAILURE */ int msDebugInitFromEnv() { const char *val; if( (val=getenv( "MS_ERRORFILE" )) != NULL ) { if ( msSetErrorFile(val, NULL) != MS_SUCCESS ) return MS_FAILURE; } if( (val=getenv( "MS_DEBUGLEVEL" )) != NULL ) msSetGlobalDebugLevel(atoi(val)); return MS_SUCCESS; } /* msDebugCleanup() ** ** Called by msCleanup to remove info related to this thread. */ void msDebugCleanup() { /* make sure file is closed */ msCloseErrorFile(); #ifdef USE_THREAD { void* thread_id = msGetThreadId(); debugInfoObj *link; msAcquireLock( TLOCK_DEBUGOBJ ); /* find link for this thread */ for( link = debuginfo_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} if( link->thread_id == thread_id ) { /* presumably link is at head of list. */ if( debuginfo_list == link ) debuginfo_list = link->next; free( link ); } else if( link->next != NULL && link->next->thread_id == thread_id ) { debugInfoObj *next_link = link->next; link->next = link->next->next; free( next_link ); } msReleaseLock( TLOCK_DEBUGOBJ ); } #endif } /* msDebug() ** ** Outputs/logs messages to the MS_ERRORFILE if one is set ** (see msSetErrorFile()) ** */ void msDebug( const char * pszFormat, ... ) { va_list args; debugInfoObj *debuginfo = msGetDebugInfoObj(); if (debuginfo == NULL || debuginfo->debug_mode == MS_DEBUGMODE_OFF) return; /* Don't waste time here! */ if (debuginfo->fp) { /* Writing to a stdio file handle */ #if defined(USE_FASTCGI) /* It seems the FastCGI stuff inserts a timestamp anyways, so */ /* we might as well skip this one if writing to stderr w/ FastCGI. */ if (debuginfo->debug_mode != MS_DEBUGMODE_STDERR) #endif { struct mstimeval tv; time_t t; msGettimeofday(&tv, NULL); t = tv.tv_sec; msIO_fprintf(debuginfo->fp, "[%s].%ld ", msStringChop(ctime(&t)), (long)tv.tv_usec); } va_start(args, pszFormat); msIO_vfprintf(debuginfo->fp, pszFormat, args); va_end(args); } #ifdef _WIN32 else if (debuginfo->debug_mode == MS_DEBUGMODE_WINDOWSDEBUG) { /* Writing to Windows Debug Console */ char szMessage[MESSAGELENGTH]; va_start(args, pszFormat); vsnprintf( szMessage, MESSAGELENGTH, pszFormat, args ); va_end(args); szMessage[MESSAGELENGTH-1] = '\0'; OutputDebugStringA(szMessage); } #endif } /* msDebug2() ** ** Variadic function with no operation ** */ void msDebug2( int level, ... ) { } mapserver-7.4.3/mapdraw.c000066400000000000000000004356111357574274700153670ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: High level msDrawMap() implementation and related functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include #include #include "mapserver.h" #include "maptime.h" #include "mapcopy.h" #include "mapfile.h" #include "mapows.h" /* msPrepareImage() * * Returns a new imageObj ready for rendering the current map. * * If allow_nonsquare is set to MS_TRUE then the caller should call * msMapRestoreRealExtent() once they are done with the image. * This should be set to MS_TRUE only when called from msDrawMap(), see bug 945. */ imageObj *msPrepareImage(mapObj *map, int allow_nonsquare) { int i, status; imageObj *image=NULL; double geo_cellsize; if(map->width == -1 || map->height == -1) { msSetError(MS_MISCERR, "Image dimensions not specified.", "msPrepareImage()"); return(NULL); } msFreeLabelCache(&(map->labelcache)); msInitLabelCache(&(map->labelcache)); /* this clears any previously allocated cache */ /* clear any previously created mask layer images */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->maskimage) { msFreeImage(GET_LAYER(map, i)->maskimage); GET_LAYER(map, i)->maskimage = NULL; } } status = msValidateContexts(map); /* make sure there are no recursive REQUIRES or LABELREQUIRES expressions */ if(status != MS_SUCCESS) return NULL; if(!map->outputformat) { msSetError(MS_IMGERR, "Map outputformat not set!", "msPrepareImage()"); return(NULL); } else if (MS_RENDERER_PLUGIN(map->outputformat)) { rendererVTableObj *renderer = map->outputformat->vtable; colorObj *bg = &map->imagecolor; map->imagecolor.alpha=255; if(map->transparent == MS_TRUE) { /* don't set the image color */ bg = NULL; } image = renderer->createImage(map->width, map->height, map->outputformat,bg); if (image == NULL) return(NULL); image->format = map->outputformat; image->format->refcount++; image->width = map->width; image->height = map->height; image->resolution = map->resolution; image->resolutionfactor = map->resolution/map->defresolution; if (map->web.imagepath) image->imagepath = msStrdup(map->web.imagepath); if (map->web.imageurl) image->imageurl = msStrdup(map->web.imageurl); } else if( MS_RENDERER_IMAGEMAP(map->outputformat) ) { image = msImageCreateIM(map->width, map->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution); } else if( MS_RENDERER_RAWDATA(map->outputformat) ) { image = msImageCreate(map->width, map->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->imagecolor); } else { image = NULL; } if(!image) { msSetError(MS_IMGERR, "Unable to initialize image.", "msPrepareImage()"); return(NULL); } image->map = map; /* * If we want to support nonsquare pixels, note that now, otherwise * adjust the extent size to have square pixels. * * If allow_nonsquare is set to MS_TRUE then the caller should call * msMapRestoreRealExtent() once they are done with the image. * This should be set to MS_TRUE only when called from msDrawMap(), see bug 945. */ if( allow_nonsquare && msTestConfigOption( map, "MS_NONSQUARE", MS_FALSE ) ) { double cellsize_x = (map->extent.maxx - map->extent.minx)/map->width; double cellsize_y = (map->extent.maxy - map->extent.miny)/map->height; if( cellsize_y != 0.0 && (fabs(cellsize_x/cellsize_y) > 1.00001 || fabs(cellsize_x/cellsize_y) < 0.99999) ) { map->gt.need_geotransform = MS_TRUE; if (map->debug) msDebug( "msDrawMap(): kicking into non-square pixel preserving mode.\n" ); } map->cellsize = (cellsize_x*0.5 + cellsize_y*0.5); } else map->cellsize = msAdjustExtent(&(map->extent),map->width,map->height); status = msCalculateScale(map->extent,map->units,map->width,map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) { msFreeImage(image); return(NULL); } /* update geotransform based on adjusted extent. */ msMapComputeGeotransform( map ); /* Do we need to fake out stuff for rotated support? */ if( map->gt.need_geotransform ) msMapSetFakedExtent( map ); /* We will need a cellsize that represents a real georeferenced */ /* coordinate cellsize here, so compute it from saved extents. */ geo_cellsize = map->cellsize; if( map->gt.need_geotransform == MS_TRUE ) { double cellsize_x = (map->saved_extent.maxx - map->saved_extent.minx) / map->width; double cellsize_y = (map->saved_extent.maxy - map->saved_extent.miny) / map->height; geo_cellsize = sqrt(cellsize_x*cellsize_x + cellsize_y*cellsize_y) / sqrt(2.0); } /* compute layer scale factors now */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->sizeunits != MS_PIXELS) GET_LAYER(map, i)->scalefactor = (msInchesPerUnit(GET_LAYER(map, i)->sizeunits,0)/msInchesPerUnit(map->units,0)) / geo_cellsize; else if(GET_LAYER(map, i)->symbolscaledenom > 0 && map->scaledenom > 0) GET_LAYER(map, i)->scalefactor = GET_LAYER(map, i)->symbolscaledenom/map->scaledenom*map->resolution/map->defresolution; else GET_LAYER(map, i)->scalefactor = map->resolution/map->defresolution; } image->refpt.x = MS_MAP2IMAGE_X_IC_DBL(0, map->extent.minx, 1.0/map->cellsize); image->refpt.y = MS_MAP2IMAGE_Y_IC_DBL(0, map->extent.maxy, 1.0/map->cellsize); return image; } static int msCompositeRasterBuffer(mapObj *map, imageObj *img, rasterBufferObj *rb, LayerCompositer *comp) { int ret = MS_SUCCESS; if(MS_IMAGE_RENDERER(img)->compositeRasterBuffer) { while(comp && ret == MS_SUCCESS) { rasterBufferObj *rb_ptr = rb; CompositingFilter *filter = comp->filter; if(filter && comp->next) { /* if we have another compositor to apply, then we need to copy the rasterBufferObj. Otherwise * we can work on it directly */ rb_ptr = (rasterBufferObj*)msSmallCalloc(sizeof(rasterBufferObj),1); msCopyRasterBuffer(rb_ptr,rb); } while(filter && ret == MS_SUCCESS) { ret = msApplyCompositingFilter(map,rb_ptr,filter); filter = filter->next; } if(ret == MS_SUCCESS) ret = MS_IMAGE_RENDERER(img)->compositeRasterBuffer(img,rb_ptr,comp->comp_op, comp->opacity); if(rb_ptr != rb) { msFreeRasterBuffer(rb_ptr); msFree(rb_ptr); } comp = comp->next; } } else { ret = MS_FAILURE; } return ret; } /* * Generic function to render the map file. * The type of the image created is based on the imagetype parameter in the map file. * * mapObj *map - map object loaded in MapScript or via a mapfile to use * int querymap - is this map the result of a query operation, MS_TRUE|MS_FALSE */ imageObj *msDrawMap(mapObj *map, int querymap) { int i; layerObj *lp=NULL; int status = MS_FAILURE; imageObj *image = NULL; struct mstimeval mapstarttime, mapendtime; struct mstimeval starttime, endtime; #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) enum MS_CONNECTION_TYPE lastconnectiontype; httpRequestObj *pasOWSReqInfo=NULL; int numOWSLayers=0; int numOWSRequests=0; wmsParamsObj sLastWMSParams; #endif if(map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&mapstarttime, NULL); if(querymap) { /* use queryMapObj image dimensions */ if(map->querymap.width != -1) map->width = map->querymap.width; if(map->querymap.height != -1) map->height = map->querymap.height; } msApplyMapConfigOptions(map); image = msPrepareImage(map, MS_TRUE); if(!image) { msSetError(MS_IMGERR, "Unable to initialize image.", "msDrawMap()"); return(NULL); } if( map->debug >= MS_DEBUGLEVEL_DEBUG ) msDebug( "msDrawMap(): rendering using outputformat named %s (%s).\n", map->outputformat->name, map->outputformat->driver ); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) /* Time the OWS query phase */ if(map->debug >= MS_DEBUGLEVEL_TUNING ) msGettimeofday(&starttime, NULL); /* How many OWS (WMS/WFS) layers do we have to draw? * Note: numOWSLayers is the number of actual layers and numOWSRequests is * the number of HTTP requests which could be lower if multiple layers * are merged into the same request. */ numOWSLayers=0; for(i=0; inumlayers; i++) { if(map->layerorder[i] == -1 ) continue; lp = GET_LAYER(map,map->layerorder[i]); if( lp->connectiontype != MS_WMS && lp->connectiontype != MS_WFS ) { continue; } numOWSLayers++; } if (numOWSLayers > 0) { /* Alloc and init pasOWSReqInfo... */ pasOWSReqInfo = (httpRequestObj *)malloc(numOWSLayers*sizeof(httpRequestObj)); if (pasOWSReqInfo == NULL) { msSetError(MS_MEMERR, "Allocation of httpRequestObj failed.", "msDrawMap()"); return NULL; } msHTTPInitRequestObj(pasOWSReqInfo, numOWSLayers); msInitWmsParamsObj(&sLastWMSParams); /* Pre-download all WMS/WFS layers in parallel before starting to draw map */ lastconnectiontype = MS_SHAPEFILE; for(i=0; inumlayers; i++) { if(map->layerorder[i] == -1 ) continue; lp = GET_LAYER(map,map->layerorder[i]); if( lp->connectiontype != MS_WMS && lp->connectiontype != MS_WFS ) { continue; } if( !msLayerIsVisible(map, lp) ) continue; #ifdef USE_WMS_LYR if(lp->connectiontype == MS_WMS) { if(msPrepareWMSLayerRequest(map->layerorder[i], map, lp, 1, lastconnectiontype, &sLastWMSParams, 0, 0, 0, NULL, pasOWSReqInfo, &numOWSRequests) == MS_FAILURE) { msFreeWmsParamsObj(&sLastWMSParams); msFreeImage(image); msFree(pasOWSReqInfo); return NULL; } } #endif #ifdef USE_WFS_LYR if(lp->connectiontype == MS_WFS) { if(msPrepareWFSLayerRequest(map->layerorder[i], map, lp, pasOWSReqInfo, &numOWSRequests) == MS_FAILURE) { msFreeWmsParamsObj(&sLastWMSParams); msFreeImage(image); msFree(pasOWSReqInfo); return NULL; } } #endif lastconnectiontype = lp->connectiontype; } msFreeWmsParamsObj(&sLastWMSParams); } /* if numOWSLayers > 0 */ if(numOWSRequests && msOWSExecuteRequests(pasOWSReqInfo, numOWSRequests, map, MS_TRUE) == MS_FAILURE) { msFreeImage(image); msFree(pasOWSReqInfo); return NULL; } if(map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawMap(): WMS/WFS set-up and query, %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ /* OK, now we can start drawing */ for(i=0; inumlayers; i++) { if(map->layerorder[i] != -1) { char *force_draw_label_cache = NULL; lp = (GET_LAYER(map, map->layerorder[i])); if(lp->postlabelcache) /* wait to draw */ continue; if(map->debug >= MS_DEBUGLEVEL_TUNING || lp->debug >= MS_DEBUGLEVEL_TUNING ) msGettimeofday(&starttime, NULL); if(!msLayerIsVisible(map, lp)) continue; if(lp->connectiontype == MS_WMS) { #ifdef USE_WMS_LYR if(MS_RENDERER_PLUGIN(image->format) || MS_RENDERER_RAWDATA(image->format)) status = msDrawWMSLayerLow(map->layerorder[i], pasOWSReqInfo, numOWSRequests, map, lp, image); else { msSetError(MS_WMSCONNERR, "Output format '%s' doesn't support WMS layers.", "msDrawMap()", image->format->name); status = MS_FAILURE; } if(status == MS_FAILURE) { msSetError(MS_WMSCONNERR, "Failed to draw WMS layer named '%s'. This most likely happened because " "the remote WMS server returned an invalid image, and XML exception " "or another unexpected result in response to the GetMap request. Also check " "and make sure that the layer's connection URL is valid.", "msDrawMap()", lp->name); msFreeImage(image); msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); return(NULL); } #else /* ndef USE_WMS_LYR */ msSetError(MS_WMSCONNERR, "MapServer not built with WMS Client support, unable to render layer '%s'.", "msDrawMap()", lp->name); msFreeImage(image); return(NULL); #endif } else { /* Default case: anything but WMS layers */ if(querymap) status = msDrawQueryLayer(map, lp, image); else status = msDrawLayer(map, lp, image); if(status == MS_FAILURE) { msSetError(MS_IMGERR, "Failed to draw layer named '%s'.", "msDrawMap()", lp->name); msFreeImage(image); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ return(NULL); } } if(map->debug >= MS_DEBUGLEVEL_TUNING || lp->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawMap(): Layer %d (%s), %.3fs\n", map->layerorder[i], lp->name?lp->name:"(null)", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } /* Flush layer cache in-between layers if requested by PROCESSING directive*/ force_draw_label_cache = msLayerGetProcessingKey(lp, "FORCE_DRAW_LABEL_CACHE"); if (force_draw_label_cache && strncasecmp(force_draw_label_cache,"FLUSH",5)==0) { if(map->debug >= MS_DEBUGLEVEL_V) msDebug("msDrawMap(): PROCESSING FORCE_DRAW_LABEL_CACHE=FLUSH found.\n"); if(msDrawLabelCache(map, image) != MS_SUCCESS) { msFreeImage(image); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ return(NULL); } msFreeLabelCache(&(map->labelcache)); msInitLabelCache(&(map->labelcache)); } /* PROCESSING FORCE_DRAW_LABEL_CACHE */ } } if(map->scalebar.status == MS_EMBED && !map->scalebar.postlabelcache) { /* We need to temporarily restore the original extent for drawing */ /* the scalebar as it uses the extent to recompute cellsize. */ if(map->gt.need_geotransform) msMapRestoreRealExtent(map); if(MS_SUCCESS != msEmbedScalebar(map, image)) { msFreeImage( image ); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) /* Cleanup WMS/WFS Request stuff */ if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif return NULL; } if(map->gt.need_geotransform) msMapSetFakedExtent(map); } if(map->legend.status == MS_EMBED && !map->legend.postlabelcache) { if( msEmbedLegend(map, image) != MS_SUCCESS ) { msFreeImage( image ); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) /* Cleanup WMS/WFS Request stuff */ if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif return NULL; } } if(msDrawLabelCache(map, image) != MS_SUCCESS) { msFreeImage(image); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ return(NULL); } for(i=0; inumlayers; i++) { /* for each layer, check for postlabelcache layers */ lp = (GET_LAYER(map, map->layerorder[i])); if(!lp->postlabelcache) continue; if(!msLayerIsVisible(map, lp)) continue; if(map->debug >= MS_DEBUGLEVEL_TUNING || lp->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&starttime, NULL); if(lp->connectiontype == MS_WMS) { #ifdef USE_WMS_LYR if(MS_RENDERER_PLUGIN(image->format) || MS_RENDERER_RAWDATA(image->format)) status = msDrawWMSLayerLow(map->layerorder[i], pasOWSReqInfo, numOWSRequests, map, lp, image); #else status = MS_FAILURE; #endif } else { if(querymap) status = msDrawQueryLayer(map, lp, image); else status = msDrawLayer(map, lp, image); } if(status == MS_FAILURE) { msFreeImage(image); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif /* USE_WMS_LYR || USE_WFS_LYR */ return(NULL); } if(map->debug >= MS_DEBUGLEVEL_TUNING || lp->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawMap(): Layer %d (%s), %.3fs\n", map->layerorder[i], lp->name?lp->name:"(null)", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } } /* Do we need to fake out stuff for rotated support? */ /* This really needs to be done on every preceeding exit point too... */ if(map->gt.need_geotransform) msMapRestoreRealExtent(map); if(map->legend.status == MS_EMBED && map->legend.postlabelcache) if(UNLIKELY(MS_FAILURE == msEmbedLegend(map, image))) { msFreeImage( image ); return NULL; } if(map->scalebar.status == MS_EMBED && map->scalebar.postlabelcache) { /* We need to temporarily restore the original extent for drawing */ /* the scalebar as it uses the extent to recompute cellsize. */ if(map->gt.need_geotransform) msMapRestoreRealExtent(map); if(MS_SUCCESS != msEmbedScalebar(map, image)) { msFreeImage( image ); #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) /* Cleanup WMS/WFS Request stuff */ if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif return NULL; } if(map->gt.need_geotransform) msMapSetFakedExtent(map); } #if defined(USE_WMS_LYR) || defined(USE_WFS_LYR) /* Cleanup WMS/WFS Request stuff */ if (pasOWSReqInfo) { msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests); msFree(pasOWSReqInfo); } #endif if(map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&mapendtime, NULL); msDebug("msDrawMap() total time: %.3fs\n", (mapendtime.tv_sec+mapendtime.tv_usec/1.0e6)- (mapstarttime.tv_sec+mapstarttime.tv_usec/1.0e6) ); } return(image); } /* * Test whether a layer should be drawn or not in the current map view and * at the current scale. * Returns TRUE if layer is visible, FALSE if not. */ int msLayerIsVisible(mapObj *map, layerObj *layer) { int i; if(!layer->data && !layer->tileindex && !layer->connection && !layer->features && !layer->grid) return(MS_FALSE); /* no data associated with this layer, not an error since layer may be used as a template from MapScript */ if(layer->type == MS_LAYER_QUERY || layer->type == MS_LAYER_TILEINDEX) return(MS_FALSE); if((layer->status != MS_ON) && (layer->status != MS_DEFAULT)) return(MS_FALSE); /* Do comparisons of layer scale vs map scale now, since msExtentsOverlap() */ /* can be slow */ if(map->scaledenom > 0) { /* layer scale boundaries should be checked first */ if((layer->maxscaledenom > 0) && (map->scaledenom > layer->maxscaledenom)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.MAXSCALE is too small for this MAP scale\n", layer->name); } return(MS_FALSE); } if(/*(layer->minscaledenom > 0) &&*/ (map->scaledenom <= layer->minscaledenom)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.MINSCALE is too large for this MAP scale\n", layer->name); } return(MS_FALSE); } } /* Only return MS_FALSE if it is definitely false. Sometimes it will return MS_UNKNOWN, which we ** consider true, for this use case (it might be visible, try and draw it, see what happens). */ if ( msExtentsOverlap(map, layer) == MS_FALSE ) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER.EXTENT does not intersect MAP.EXTENT\n", layer->name); } return(MS_FALSE); } if(msEvalContext(map, layer, layer->requires) == MS_FALSE) return(MS_FALSE); if(map->scaledenom > 0) { /* now check class scale boundaries (all layers *must* pass these tests) */ if(layer->numclasses > 0) { for(i=0; inumclasses; i++) { if((layer->class[i]->maxscaledenom > 0) && (map->scaledenom > layer->class[i]->maxscaledenom)) continue; /* can skip this one, next class */ if((layer->class[i]->minscaledenom > 0) && (map->scaledenom <= layer->class[i]->minscaledenom)) continue; /* can skip this one, next class */ break; /* can't skip this class (or layer for that matter) */ } if(i == layer->numclasses) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because no CLASS in the layer is in-scale for this MAP scale\n", layer->name); } return(MS_FALSE); } } } if (layer->maxscaledenom <= 0 && layer->minscaledenom <= 0) { if((layer->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > layer->maxgeowidth)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER width is much smaller than map width\n", layer->name); } return(MS_FALSE); } if((layer->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < layer->mingeowidth)) { if( layer->debug >= MS_DEBUGLEVEL_V ) { msDebug("msLayerIsVisible(): Skipping layer (%s) because LAYER width is much larger than map width\n", layer->name); } return(MS_FALSE); } } return MS_TRUE; /* All tests passed. Layer is visible. */ } #define LAYER_NEEDS_COMPOSITING(layer) (((layer)->compositer != NULL) && ((layer)->compositer->next || (layer)->compositor->opacity < 100 || (layer)->compositor->compop != MS_COMPOP_SRC_OVER || (layer)->compositer->filter )) /* * Generic function to render a layer object. */ int msDrawLayer(mapObj *map, layerObj *layer, imageObj *image) { imageObj *image_draw = image; outputFormatObj *altFormat=NULL; int retcode=MS_SUCCESS; const char *alternativeFomatString = NULL; layerObj *maskLayer = NULL; if(!msLayerIsVisible(map, layer)) return MS_SUCCESS; if(layer->compositer && !layer->compositer->next && layer->compositer->opacity == 0) return MS_SUCCESS; /* layer is completely transparent, skip it */ /* conditions may have changed since this layer last drawn, so retest layer->project (Bug #673) */ layer->project = msProjectionsDiffer(&(layer->projection),&(map->projection)); /* make sure labelcache setting is set correctly if postlabelcache is set. This is done by the parser but may have been altered by a mapscript. see #5142 */ if(layer->postlabelcache) { layer->labelcache = MS_FALSE; } if(layer->mask) { int maskLayerIdx; /* render the mask layer in its own imageObj */ if(!MS_IMAGE_RENDERER(image)->supports_pixel_buffer) { msSetError(MS_MISCERR, "Layer (%s) references references a mask layer, but the selected renderer does not support them", "msDrawLayer()", layer->name); return (MS_FAILURE); } maskLayerIdx = msGetLayerIndex(map,layer->mask); if(maskLayerIdx == -1) { msSetError(MS_MISCERR, "Layer (%s) references unknown mask layer (%s)", "msDrawLayer()", layer->name,layer->mask); return (MS_FAILURE); } maskLayer = GET_LAYER(map, maskLayerIdx); if(!maskLayer->maskimage) { int i; int origstatus, origlabelcache; altFormat = msSelectOutputFormat(map, "png24"); msInitializeRendererVTable(altFormat); /* TODO: check the png24 format hasn't been tampered with, i.e. it's agg */ maskLayer->maskimage= msImageCreate(image->width, image->height,altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!maskLayer->maskimage) { msSetError(MS_MISCERR, "Unable to initialize mask image.", "msDrawLayer()"); return (MS_FAILURE); } /* * force the masked layer to status on, and turn off the labelcache so that * eventual labels are added to the temporary image instead of being added * to the labelcache */ origstatus = maskLayer->status; origlabelcache = maskLayer->labelcache; maskLayer->status = MS_ON; maskLayer->labelcache = MS_OFF; /* draw the mask layer in the temporary image */ retcode = msDrawLayer(map, maskLayer, maskLayer->maskimage); maskLayer->status = origstatus; maskLayer->labelcache = origlabelcache; if(retcode != MS_SUCCESS) { return MS_FAILURE; } /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; isymbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == MS_IMAGE_RENDERER(maskLayer->maskimage)) { MS_IMAGE_RENDERER(maskLayer->maskimage)->freeSymbol(s); s->renderer = NULL; } } } /* set the imagetype from the original outputformat back (it was removed by msSelectOutputFormat() */ msFree(map->imagetype); map->imagetype = msStrdup(image->format->name); } } altFormat = NULL; /* inform the rendering device that layer draw is starting. */ msImageStartLayer(map, layer, image); /*check if an alternative renderer should be used for this layer*/ alternativeFomatString = msLayerGetProcessingKey( layer, "RENDERER"); if (MS_RENDERER_PLUGIN(image_draw->format) && alternativeFomatString!=NULL && (altFormat= msSelectOutputFormat(map, alternativeFomatString))) { rendererVTableObj *renderer=NULL; msInitializeRendererVTable(altFormat); image_draw = msImageCreate(image->width, image->height, altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, &map->imagecolor); renderer = MS_IMAGE_RENDERER(image_draw); renderer->startLayer(image_draw,map,layer); } else if (MS_RENDERER_PLUGIN(image_draw->format)) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw); if ((layer->mask && layer->connectiontype!=MS_WMS && layer->type != MS_LAYER_RASTER) || layer->compositer) { /* masking occurs at the pixel/layer level for raster images, so we don't need to create a temporary image in these cases */ if (layer->mask || renderer->compositeRasterBuffer) { image_draw = msImageCreate(image->width, image->height, image->format, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!image_draw) { msSetError(MS_MISCERR, "Unable to initialize temporary transparent image.", "msDrawLayer()"); return (MS_FAILURE); } image_draw->map = map; renderer->startLayer(image_draw,map,layer); } } } /* ** redirect procesing of some layer types. */ if(layer->connectiontype == MS_WMS) { #ifdef USE_WMS_LYR retcode = msDrawWMSLayer(map, layer, image_draw); #else retcode = MS_FAILURE; #endif } else if(layer->type == MS_LAYER_RASTER) { retcode = msDrawRasterLayer(map, layer, image_draw); } else if(layer->type == MS_LAYER_CHART) { retcode = msDrawChartLayer(map, layer, image_draw); } else { /* must be a Vector layer */ retcode = msDrawVectorLayer(map, layer, image_draw); } if (altFormat) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); rendererVTableObj *altrenderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; int i; memset(&rb,0,sizeof(rasterBufferObj)); altrenderer->endLayer(image_draw,map,layer); retcode = altrenderer->getRasterBufferHandle(image_draw,&rb); if(UNLIKELY(retcode == MS_FAILURE)) { goto altformat_cleanup; } retcode = renderer->mergeRasterBuffer(image,&rb,((layer->compositer)?(layer->compositer->opacity*0.01):(1.0)),0,0,0,0,rb.width,rb.height); if(UNLIKELY(retcode == MS_FAILURE)) { goto altformat_cleanup; } altformat_cleanup: /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; isymbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == altrenderer) { altrenderer->freeSymbol(s); s->renderer = NULL; } } } msFreeImage(image_draw); /* set the imagetype from the original outputformat back (it was removed by msSelectOutputFormat() */ msFree(map->imagetype); map->imagetype = msStrdup(image->format->name); } else if( image != image_draw) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); renderer->endLayer(image_draw,map,layer); retcode = renderer->getRasterBufferHandle(image_draw,&rb); if(UNLIKELY(retcode == MS_FAILURE)) { goto imagedraw_cleanup; } if(maskLayer && maskLayer->maskimage) { rasterBufferObj mask; unsigned int row,col; memset(&mask,0,sizeof(rasterBufferObj)); retcode = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,&mask); if(UNLIKELY(retcode == MS_FAILURE)) { goto imagedraw_cleanup; } /* modify the pixels of the overlay */ if(rb.type == MS_BUFFER_BYTE_RGBA) { for(row=0; rowcompositer) { /*we have a mask layer with no composition configured, do a nomral blend */ retcode = renderer->mergeRasterBuffer(image,&rb,1.0,0,0,0,0,rb.width,rb.height); } else { retcode = msCompositeRasterBuffer(map,image,&rb,layer->compositer); } if(UNLIKELY(retcode == MS_FAILURE)) { goto imagedraw_cleanup; } imagedraw_cleanup: msFreeImage(image_draw); } msImageEndLayer(map,layer,image); return(retcode); } int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image) { int status, retcode=MS_SUCCESS; int drawmode=MS_DRAWMODE_FEATURES; char annotate=MS_TRUE; shapeObj shape; rectObj searchrect; char cache=MS_FALSE; int maxnumstyles=1; featureListNodeObjPtr shpcache=NULL, current=NULL; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; int maxfeatures=-1; int featuresdrawn=0; if (image) maxfeatures=msLayerGetMaxFeaturesToDraw(layer, image->format); /* TODO TBT: draw as raster layer in vector renderers */ annotate = msEvalContext(map, layer, layer->labelrequires); if(map->scaledenom > 0) { if((layer->labelmaxscaledenom != -1) && (map->scaledenom >= layer->labelmaxscaledenom)) annotate = MS_FALSE; if((layer->labelminscaledenom != -1) && (map->scaledenom < layer->labelminscaledenom)) annotate = MS_FALSE; } /* open this layer */ status = msLayerOpen(layer); if(status != MS_SUCCESS) return MS_FAILURE; /* build item list. STYLEITEM javascript needs the shape attributes */ if (layer->styleitem && (strncasecmp(layer->styleitem, "javascript://", 13) == 0)) { status = msLayerWhichItems(layer, MS_TRUE, NULL); } else { status = msLayerWhichItems(layer, MS_FALSE, NULL); } if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* identify target shapes */ if(layer->transform == MS_TRUE) { searchrect = map->extent; #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) { int bDone = MS_FALSE; #ifdef USE_GDAL if( layer->connectiontype == MS_UVRASTER ) { /* Nasty hack to make msUVRASTERLayerWhichShapes() aware that the */ /* original area of interest is (map->extent, map->projection)... */ /* Useful when dealin with UVRASTER that extend beyond 180 deg */ msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes( layer, map ); } #endif /* For UVRaster, it is important that the searchrect is not too large */ /* to avoid insufficient intermediate raster resolution, which could */ /* happen if we use the default code path, given potential reprojection */ /* issues when using a map extent that is not in the validity area of */ /* the layer projection. */ if( layer->connectiontype == MS_UVRASTER && !layer->projection.gt.need_geotransform && !(pj_is_latlong(map->projection.proj) && pj_is_latlong(layer->projection.proj)) ) { rectObj layer_ori_extent; if( msLayerGetExtent(layer, &layer_ori_extent) == MS_SUCCESS ) { projectionObj map_proj; double map_extent_minx = map->extent.minx; double map_extent_miny = map->extent.miny; double map_extent_maxx = map->extent.maxx; double map_extent_maxy = map->extent.maxy; rectObj layer_extent = layer_ori_extent; /* Create a variant of map->projection without geotransform for */ /* conveniency */ msInitProjection(&map_proj); msCopyProjection(&map_proj, &map->projection); map_proj.gt.need_geotransform = MS_FALSE; if( map->projection.gt.need_geotransform ) { map_extent_minx = map->projection.gt.geotransform[0] + map->projection.gt.geotransform[1] * map->extent.minx + map->projection.gt.geotransform[2] * map->extent.miny; map_extent_miny = map->projection.gt.geotransform[3] + map->projection.gt.geotransform[4] * map->extent.minx + map->projection.gt.geotransform[5] * map->extent.miny; map_extent_maxx = map->projection.gt.geotransform[0] + map->projection.gt.geotransform[1] * map->extent.maxx + map->projection.gt.geotransform[2] * map->extent.maxy; map_extent_maxy = map->projection.gt.geotransform[3] + map->projection.gt.geotransform[4] * map->extent.maxx + map->projection.gt.geotransform[5] * map->extent.maxy; } /* Reproject layer extent to map projection */ msProjectRect(&layer->projection, &map_proj, &layer_extent); if( layer_extent.minx <= map_extent_minx && layer_extent.miny <= map_extent_miny && layer_extent.maxx >= map_extent_maxx && layer_extent.maxy >= map_extent_maxy ) { /* do nothing special if area to map is inside layer extent */ } else { if( layer_extent.minx >= map_extent_minx && layer_extent.maxx <= map_extent_maxx && layer_extent.miny >= map_extent_miny && layer_extent.maxy <= map_extent_maxy ) { /* if the area to map is larger than the layer extent, then */ /* use full layer extent and add some margin to reflect the */ /* proportion of the useful area over the requested bbox */ double extra_x = (map_extent_maxx - map_extent_minx) / (layer_extent.maxx - layer_extent.minx) * (layer_ori_extent.maxx - layer_ori_extent.minx); double extra_y = (map_extent_maxy - map_extent_miny) / (layer_extent.maxy - layer_extent.miny) * (layer_ori_extent.maxy - layer_ori_extent.miny); searchrect.minx = layer_ori_extent.minx - extra_x / 2; searchrect.maxx = layer_ori_extent.maxx + extra_x / 2; searchrect.miny = layer_ori_extent.miny - extra_y / 2; searchrect.maxy = layer_ori_extent.maxy + extra_y / 2; } else { /* otherwise clip the map extent with the reprojected layer */ /* extent */ searchrect.minx = MS_MAX( map_extent_minx, layer_extent.minx ); searchrect.maxx = MS_MIN( map_extent_maxx, layer_extent.maxx ); searchrect.miny = MS_MAX( map_extent_miny, layer_extent.miny ); searchrect.maxy = MS_MIN( map_extent_maxy, layer_extent.maxy ); /* and reproject into the layer projection */ msProjectRect(&map_proj, &layer->projection, &searchrect); } bDone = MS_TRUE; } msFreeProjection(&map_proj); } } if( !bDone ) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ } #endif } else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } status = msLayerWhichShapes(layer, searchrect, MS_FALSE); #ifdef USE_GDAL if( layer->connectiontype == MS_UVRASTER ) { msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes( layer, NULL ); } #endif if(status == MS_DONE) { /* no overlap */ msLayerClose(layer); return MS_SUCCESS; } else if(status != MS_SUCCESS) { msLayerClose(layer); return MS_FAILURE; } /* step through the target shapes */ msInitShape(&shape); nclasses = 0; classgroup = NULL; if(layer->classgroup && layer->numclasses > 0) classgroup = msAllocateValidClassGroups(layer, &nclasses); if(layer->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, layer, layer->minfeaturesize); while((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) { /* Check if the shape size is ok to be drawn */ if((shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) && (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE)) { if(layer->debug >= MS_DEBUGLEVEL_V) msDebug("msDrawVectorLayer(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } shape.classindex = msShapeGetClass(layer, map, &shape, classgroup, nclasses); if((shape.classindex == -1) || (layer->class[shape.classindex]->status == MS_OFF)) { msFreeShape(&shape); continue; } if(maxfeatures >=0 && featuresdrawn >= maxfeatures) { msFreeShape(&shape); status = MS_DONE; break; } featuresdrawn++; cache = MS_FALSE; if(layer->type == MS_LAYER_LINE && (layer->class[shape.classindex]->numstyles > 1 || (layer->class[shape.classindex]->numstyles == 1 && layer->class[shape.classindex]->styles[0]->outlinewidth > 0))) { int i; cache = MS_TRUE; /* only line layers with multiple styles need be cached (I don't think POLYLINE layers need caching - SDL) */ /* we can't handle caching with attribute binding other than for the first style (#3976) */ for(i=1; iclass[shape.classindex]->numstyles; i++) { if(layer->class[shape.classindex]->styles[i]->numbindings > 0) cache = MS_FALSE; } } /* With 'STYLEITEM AUTO', we will have the datasource fill the class' */ /* style parameters for this shape. */ if(layer->styleitem) { if(strcasecmp(layer->styleitem, "AUTO") == 0) { if(msLayerGetAutoStyle(map, layer, layer->class[shape.classindex], &shape) != MS_SUCCESS) { retcode = MS_FAILURE; msFreeShape(&shape); break; } } else { /* Generic feature style handling as per RFC-61 */ if(msLayerGetFeatureStyle(map, layer, layer->class[shape.classindex], &shape) != MS_SUCCESS) { retcode = MS_FAILURE; msFreeShape(&shape); break; } } /* __TODO__ For now, we can't cache features with 'AUTO' style */ cache = MS_FALSE; } /* RFC77 TODO: check return value, may need a more sophisticated if-then test. */ if(annotate && layer->class[shape.classindex]->numlabels > 0) { drawmode |= MS_DRAWMODE_LABELS; if (msLayerGetProcessingKey(layer, "LABEL_NO_CLIP")) { drawmode |= MS_DRAWMODE_UNCLIPPEDLABELS; } } if (layer->type == MS_LAYER_LINE && msLayerGetProcessingKey(layer, "POLYLINE_NO_CLIP")) { drawmode |= MS_DRAWMODE_UNCLIPPEDLINES; } if (cache) { styleObj *pStyle = layer->class[shape.classindex]->styles[0]; if (pStyle->outlinewidth > 0) { /* * RFC 49 implementation * if an outlinewidth is used: * - augment the style's width to account for the outline width * - swap the style color and outlinecolor * - draw the shape (the outline) in the first pass of the * caching mechanism */ msOutlineRenderingPrepareStyle(pStyle, map, layer, image); } status = msDrawShape(map, layer, &shape, image, 0, drawmode|MS_DRAWMODE_SINGLESTYLE); /* draw a single style */ if (pStyle->outlinewidth > 0) { /* * RFC 49 implementation: switch back the styleobj to its * original state, so the line fill will be drawn in the * second pass of the caching mechanism */ msOutlineRenderingRestoreStyle(pStyle, map, layer, image); } } else status = msDrawShape(map, layer, &shape, image, -1, drawmode); /* all styles */ if(status != MS_SUCCESS) { msFreeShape(&shape); retcode = MS_FAILURE; break; } if(shape.numlines == 0) { /* once clipped the shape didn't need to be drawn */ msFreeShape(&shape); continue; } if(cache) { if(insertFeatureList(&shpcache, &shape) == NULL) { msFreeShape(&shape); retcode = MS_FAILURE; /* problem adding to the cache */ break; } } maxnumstyles = MS_MAX(maxnumstyles, layer->class[shape.classindex]->numstyles); msFreeShape(&shape); } if (classgroup) msFree(classgroup); if(status != MS_DONE || retcode == MS_FAILURE) { msLayerClose(layer); if(shpcache) { freeFeatureList(shpcache); shpcache = NULL; } return MS_FAILURE; } if(shpcache && MS_DRAW_FEATURES(drawmode)) { int s; for(s=0; snext) { if(layer->class[current->shape.classindex]->numstyles > s) { styleObj *pStyle = layer->class[current->shape.classindex]->styles[s]; if(pStyle->_geomtransform.type != MS_GEOMTRANSFORM_NONE) continue; /*skip this as it has already been rendered*/ if(map->scaledenom > 0) { if((pStyle->maxscaledenom != -1) && (map->scaledenom >= pStyle->maxscaledenom)) continue; if((pStyle->minscaledenom != -1) && (map->scaledenom < pStyle->minscaledenom)) continue; } if(s==0 && pStyle->outlinewidth>0 && MS_VALID_COLOR(pStyle->color)) { if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map, image, ¤t->shape, pStyle, layer->scalefactor))) { return MS_FAILURE; } } else if(s>0) { if (pStyle->outlinewidth > 0 && MS_VALID_COLOR(pStyle->outlinecolor)) { /* * RFC 49 implementation * if an outlinewidth is used: * - augment the style's width to account for the outline width * - swap the style color and outlinecolor * - draw the shape (the outline) in the first pass of the * caching mechanism */ msOutlineRenderingPrepareStyle(pStyle, map, layer, image); if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map, image, ¤t->shape, pStyle, layer->scalefactor))) { return MS_FAILURE; } /* * RFC 49 implementation: switch back the styleobj to its * original state, so the line fill will be drawn in the * second pass of the caching mechanism */ msOutlineRenderingRestoreStyle(pStyle, map, layer, image); } /* draw a valid line, i.e. one with a color defined or of type pixmap*/ if(MS_VALID_COLOR(pStyle->color) || ( pStyle->symbolsymbolset.numsymbols && ( map->symbolset.symbol[pStyle->symbol]->type == MS_SYMBOL_PIXMAP || map->symbolset.symbol[pStyle->symbol]->type == MS_SYMBOL_SVG ) ) ) { if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map, image, ¤t->shape, pStyle, layer->scalefactor))) return MS_FAILURE; } } } } } freeFeatureList(shpcache); shpcache = NULL; } msLayerClose(layer); return MS_SUCCESS; } /* ** Function to draw a layer IF it already has a result cache associated with it. Called by msDrawMap and via MapScript. */ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image) { int i, status; char annotate=MS_TRUE, cache=MS_FALSE; int drawmode = MS_DRAWMODE_FEATURES|MS_DRAWMODE_QUERY; shapeObj shape; int maxnumstyles=1; featureListNodeObjPtr shpcache=NULL, current=NULL; colorObj *colorbuffer = NULL; int *mindistancebuffer = NULL; if(!layer->resultcache) return(msDrawLayer(map, layer, image)); if(!msLayerIsVisible(map, layer)) return(MS_SUCCESS); /* not an error, just nothing to do */ /* conditions may have changed since this layer last drawn, so reset layer->project to recheck projection needs (Bug #673) */ layer->project = msProjectionsDiffer(&(layer->projection),&(map->projection)); /* set annotation status */ annotate = msEvalContext(map, layer, layer->labelrequires); if(map->scaledenom > 0) { if((layer->labelmaxscaledenom != -1) && (map->scaledenom >= layer->labelmaxscaledenom)) annotate = MS_FALSE; if((layer->labelminscaledenom != -1) && (map->scaledenom < layer->labelminscaledenom)) annotate = MS_FALSE; } /* ** Certain query map styles require us to render all features only (MS_NORMAL) or first (MS_HILITE). With ** single-pass queries we have to make a copy of the layer and work from it instead. */ if(map->querymap.style == MS_NORMAL || map->querymap.style == MS_HILITE) { layerObj tmp_layer; if(initLayer(&tmp_layer, map) == -1) return(MS_FAILURE); if (msCopyLayer(&tmp_layer, layer) != MS_SUCCESS) return(MS_FAILURE); /* disable the connection pool for this layer */ msLayerSetProcessingKey(&tmp_layer, "CLOSE_CONNECTION", "ALWAYS"); status = msDrawLayer(map, &tmp_layer, image); freeLayer(&tmp_layer); if(map->querymap.style == MS_NORMAL || status != MS_SUCCESS) return(status); } /* if MS_HILITE, alter the one style (always at least 1 style), and set a MINDISTANCE for the labelObj to avoid duplicates */ if(map->querymap.style == MS_HILITE) { if (layer->numclasses > 0) { colorbuffer = (colorObj*)msSmallMalloc(layer->numclasses*sizeof(colorObj)); mindistancebuffer = (int*)msSmallMalloc(layer->numclasses*sizeof(int)); } for(i=0; inumclasses; i++) { if(layer->type == MS_LAYER_POLYGON) { /* alter BOTTOM style since that's almost always the fill */ if (layer->class[i]->styles == NULL) { msSetError(MS_MISCERR, "Don't know how to draw class %s of layer %s without a style definition.", "msDrawQueryLayer()", layer->class[i]->name, layer->name); msFree(colorbuffer); msFree(mindistancebuffer); return(MS_FAILURE); } if(MS_VALID_COLOR(layer->class[i]->styles[0]->color)) { colorbuffer[i] = layer->class[i]->styles[0]->color; /* save the color from the BOTTOM style */ layer->class[i]->styles[0]->color = map->querymap.color; } else if(MS_VALID_COLOR(layer->class[i]->styles[0]->outlinecolor)) { colorbuffer[i] = layer->class[i]->styles[0]->outlinecolor; /* if no color, save the outlinecolor from the BOTTOM style */ layer->class[i]->styles[0]->outlinecolor = map->querymap.color; } } else if (layer->type == MS_LAYER_LINE && layer->class[i]->numstyles > 0 && layer->class[i]->styles[0]->outlinewidth > 0) { /* alter BOTTOM style for lines with outlines */ if(MS_VALID_COLOR(layer->class[i]->styles[0]->color)) { colorbuffer[i] = layer->class[i]->styles[0]->color; /* save the color from the BOTTOM style */ layer->class[i]->styles[0]->color = map->querymap.color; } /* else ??? */ } else if (layer->class[i]->numstyles > 0) { if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->color)) { colorbuffer[i] = layer->class[i]->styles[layer->class[i]->numstyles-1]->color; /* save the color from the TOP style */ layer->class[i]->styles[layer->class[i]->numstyles-1]->color = map->querymap.color; } else if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor)) { colorbuffer[i] = layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor; /* if no color, save the outlinecolor from the TOP style */ layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor = map->querymap.color; } } else if (layer->class[i]->numlabels > 0) { colorbuffer[i] = layer->class[i]->labels[0]->color; layer->class[i]->labels[0]->color = map->querymap.color; } /* else ??? */ mindistancebuffer[i] = -1; /* RFC77 TODO: only using the first label, is that cool? */ if(layer->class[i]->numlabels > 0) { mindistancebuffer[i] = layer->class[i]->labels[0]->mindistance; layer->class[i]->labels[0]->mindistance = MS_MAX(0, layer->class[i]->labels[0]->mindistance); } } } /* ** Layer was opened as part of the query process, msLayerWhichItems() has also been run, shapes have been classified - start processing! */ msInitShape(&shape); for(i=0; iresultcache->numresults; i++) { status = msLayerGetShape(layer, &shape, &(layer->resultcache->results[i])); if(status != MS_SUCCESS) { msFree(colorbuffer); msFree(mindistancebuffer); return(MS_FAILURE); } shape.classindex = layer->resultcache->results[i].classindex; /* classindex may be -1 here if there was a template at the top level * in this layer and the current shape selected even if it didn't * match any class * * FrankW: classindex is also sometimes 0 even if there are no classes, so * we are careful not to use out of range class values as an index. */ if(shape.classindex==-1 || shape.classindex >= layer->numclasses || layer->class[shape.classindex]->status == MS_OFF) { msFreeShape(&shape); continue; } cache = MS_FALSE; if(layer->type == MS_LAYER_LINE && (layer->class[shape.classindex]->numstyles > 1 || (layer->class[shape.classindex]->numstyles == 1 && layer->class[shape.classindex]->styles[0]->outlinewidth > 0))) { int i; cache = MS_TRUE; /* only line layers with multiple styles need be cached (I don't think POLYLINE layers need caching - SDL) */ /* we can't handle caching with attribute binding other than for the first style (#3976) */ for(i=1; iclass[shape.classindex]->numstyles; i++) { if(layer->class[shape.classindex]->styles[i]->numbindings > 0) cache = MS_FALSE; } } if(annotate && layer->class[shape.classindex]->numlabels > 0) { drawmode |= MS_DRAWMODE_LABELS; } if(cache) { styleObj *pStyle = layer->class[shape.classindex]->styles[0]; if (pStyle->outlinewidth > 0) msOutlineRenderingPrepareStyle(pStyle, map, layer, image); status = msDrawShape(map, layer, &shape, image, 0, drawmode|MS_DRAWMODE_SINGLESTYLE); /* draw only the first style */ if (pStyle->outlinewidth > 0) msOutlineRenderingRestoreStyle(pStyle, map, layer, image); } else { status = msDrawShape(map, layer, &shape, image, -1, drawmode); /* all styles */ } if(status != MS_SUCCESS) { msLayerClose(layer); msFree(colorbuffer); msFree(mindistancebuffer); return(MS_FAILURE); } if(shape.numlines == 0) { /* once clipped the shape didn't need to be drawn */ msFreeShape(&shape); continue; } if(cache) { if(insertFeatureList(&shpcache, &shape) == NULL) { msFree(colorbuffer); msFree(mindistancebuffer); return(MS_FAILURE); /* problem adding to the cache */ } } maxnumstyles = MS_MAX(maxnumstyles, layer->class[shape.classindex]->numstyles); msFreeShape(&shape); } if(shpcache) { int s; for(s=0; snext) { if(layer->class[current->shape.classindex]->numstyles > s) { styleObj *pStyle = layer->class[current->shape.classindex]->styles[s]; if(pStyle->_geomtransform.type != MS_GEOMTRANSFORM_NONE) continue; /* skip this as it has already been rendered */ if(map->scaledenom > 0) { if((pStyle->maxscaledenom != -1) && (map->scaledenom >= pStyle->maxscaledenom)) continue; if((pStyle->minscaledenom != -1) && (map->scaledenom < pStyle->minscaledenom)) continue; } if(s==0 && pStyle->outlinewidth>0 && MS_VALID_COLOR(pStyle->color)) { if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map, image, ¤t->shape, pStyle, layer->scalefactor))) { return MS_FAILURE; } } else if(s>0) { if (pStyle->outlinewidth > 0 && MS_VALID_COLOR(pStyle->outlinecolor)) { msOutlineRenderingPrepareStyle(pStyle, map, layer, image); if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map, image, ¤t->shape, pStyle, layer->scalefactor))) { return MS_FAILURE; } msOutlineRenderingRestoreStyle(pStyle, map, layer, image); } /* draw a valid line, i.e. one with a color defined or of type pixmap */ if(MS_VALID_COLOR(pStyle->color) || (pStyle->symbolsymbolset.numsymbols && (map->symbolset.symbol[pStyle->symbol]->type == MS_SYMBOL_PIXMAP || map->symbolset.symbol[pStyle->symbol]->type == MS_SYMBOL_SVG))) { if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map, image, ¤t->shape, pStyle, layer->scalefactor))) return MS_FAILURE; } } } } } freeFeatureList(shpcache); shpcache = NULL; } /* if MS_HILITE, restore color and mindistance values */ if(map->querymap.style == MS_HILITE) { for(i=0; inumclasses; i++) { if(layer->type == MS_LAYER_POLYGON) { if(MS_VALID_COLOR(layer->class[i]->styles[0]->color)) layer->class[i]->styles[0]->color = colorbuffer[i]; else if(MS_VALID_COLOR(layer->class[i]->styles[0]->outlinecolor)) layer->class[i]->styles[0]->outlinecolor = colorbuffer[i]; /* if no color, restore outlinecolor for the BOTTOM style */ } else if (layer->type == MS_LAYER_LINE && layer->class[i]->numstyles > 0 && layer->class[i]->styles[0]->outlinewidth > 0) { if(MS_VALID_COLOR(layer->class[i]->styles[0]->color)) layer->class[i]->styles[0]->color = colorbuffer[i]; } else if (layer->class[i]->numstyles > 0) { if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->color)) layer->class[i]->styles[layer->class[i]->numstyles-1]->color = colorbuffer[i]; else if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor)) layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor = colorbuffer[i]; /* if no color, restore outlinecolor for the TOP style */ } else if (layer->class[i]->numlabels > 0) { if(MS_VALID_COLOR(layer->class[i]->labels[0]->color)) layer->class[i]->labels[0]->color = colorbuffer[i]; } if(layer->class[i]->numlabels > 0) layer->class[i]->labels[0]->mindistance = mindistancebuffer[i]; /* RFC77 TODO: again, only using the first label, is that cool? */ } msFree(colorbuffer); msFree(mindistancebuffer); } return(MS_SUCCESS); } /** * msDrawRasterLayerPlugin() */ static int msDrawRasterLayerPlugin( mapObj *map, layerObj *layer, imageObj *image) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); rasterBufferObj *rb = msSmallCalloc(1,sizeof(rasterBufferObj)); int ret; if( renderer->supports_pixel_buffer ) { if (MS_SUCCESS != renderer->getRasterBufferHandle( image, rb )) { msSetError(MS_MISCERR,"renderer failed to extract raster buffer","msDrawRasterLayer()"); return MS_FAILURE; } ret = msDrawRasterLayerLow( map, layer, image, rb ); } else { if (MS_SUCCESS != renderer->initializeRasterBuffer( rb, image->width, image->height, MS_IMAGEMODE_RGBA )) { msSetError(MS_MISCERR,"renderer failed to create raster buffer","msDrawRasterLayer()"); return MS_FAILURE; } ret = msDrawRasterLayerLow( map, layer, image, rb ); if( ret == 0 ) { ret = renderer->mergeRasterBuffer( image, rb, 1.0, 0, 0, 0, 0, rb->width, rb->height ); } msFreeRasterBuffer(rb); } #define RB_GET_R(rb,x,y) *((rb)->data.rgba.r + (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step) #define RB_GET_G(rb,x,y) *((rb)->data.rgba.g + (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step) #define RB_GET_B(rb,x,y) *((rb)->data.rgba.b + (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step) #define RB_GET_A(rb,x,y) *((rb)->data.rgba.a + (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step) free(rb); return ret; } /** * Generic function to render raster layers. */ int msDrawRasterLayer(mapObj *map, layerObj *layer, imageObj *image) { int rv = MS_FAILURE; if (!image || !map || !layer) { return rv; } /* RFC-86 Scale dependant token replacements*/ rv = msLayerApplyScaletokens(layer,(layer->map)?layer->map->scaledenom:-1); if (rv != MS_SUCCESS) return rv; if( MS_RENDERER_PLUGIN(image->format) ) rv = msDrawRasterLayerPlugin(map, layer, image); else if( MS_RENDERER_RAWDATA(image->format) ) rv = msDrawRasterLayerLow(map, layer, image, NULL); msLayerRestoreFromScaletokens(layer); return rv; } /** * msDrawWMSLayer() * * Draw a single WMS layer. * Multiple WMS layers in a map are preloaded and then drawn using * msDrawWMSLayerLow() */ #ifdef USE_WMS_LYR int msDrawWMSLayer(mapObj *map, layerObj *layer, imageObj *image) { int nStatus = MS_FAILURE; if (image && map && layer) { /* ------------------------------------------------------------------ * Start by downloading the layer * ------------------------------------------------------------------ */ httpRequestObj asReqInfo[2]; int numReq = 0; msHTTPInitRequestObj(asReqInfo, 2); if ( msPrepareWMSLayerRequest(1, map, layer, 1, 0, NULL, 0, 0, 0, NULL, asReqInfo, &numReq) == MS_FAILURE || msOWSExecuteRequests(asReqInfo, numReq, map, MS_TRUE) == MS_FAILURE ) { return MS_FAILURE; } /* ------------------------------------------------------------------ * Then draw layer based on output format * ------------------------------------------------------------------ */ if( MS_RENDERER_PLUGIN(image->format) ) nStatus = msDrawWMSLayerLow(1, asReqInfo, numReq, map, layer, image) ; else if( MS_RENDERER_RAWDATA(image->format) ) nStatus = msDrawWMSLayerLow(1, asReqInfo, numReq, map, layer, image) ; else { msSetError(MS_WMSCONNERR, "Output format '%s' doesn't support WMS layers.", "msDrawWMSLayer()", image->format->name); nStatus = MS_SUCCESS; /* Should we fail if output doesn't support WMS? */ } /* Cleanup */ msHTTPFreeRequestObj(asReqInfo, numReq); } return nStatus; } #endif int circleLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape) { pointObj center; double r; int s; int c = shape->classindex; if (shape->numlines != 1) return (MS_SUCCESS); /* invalid shape */ if (shape->line[0].numpoints != 2) return (MS_SUCCESS); /* invalid shape */ center.x = (shape->line[0].point[0].x + shape->line[0].point[1].x) / 2.0; center.y = (shape->line[0].point[0].y + shape->line[0].point[1].y) / 2.0; r = MS_ABS(center.x - shape->line[0].point[0].x); if (r == 0) r = MS_ABS(center.y - shape->line[0].point[0].y); if (r == 0) return (MS_SUCCESS); if (layer->transform == MS_TRUE) { #ifdef USE_PROJ if (layer->project) msProjectPoint(&layer->projection, &map->projection, ¢er); #endif center.x = MS_MAP2IMAGE_X(center.x, map->extent.minx, map->cellsize); center.y = MS_MAP2IMAGE_Y(center.y, map->extent.maxy, map->cellsize); r /= map->cellsize; } else msOffsetPointRelativeTo(¢er, layer); for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) if(UNLIKELY(MS_FAILURE == msCircleDrawShadeSymbol(map, image, ¢er, r, layer->class[c]->styles[s], layer->scalefactor))) { return MS_FAILURE; } } return MS_SUCCESS; /* TODO: need to handle circle annotation */ } int pointLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape, int drawmode) { int l, c = shape->classindex, j, i, s; pointObj *point; int ret = MS_FAILURE; #ifdef USE_PROJ if (layer->project && layer->transform == MS_TRUE) msProjectShape(&layer->projection, &map->projection, shape); #endif // Only take into account map rotation if the label and style angles are // non-zero. if( map->gt.rotation_angle ) { for (l = 0; l < layer->class[c]->numlabels; l++) { if( layer->class[c]->labels[l]->angle != 0 ) layer->class[c]->labels[l]->angle -= map->gt.rotation_angle; } for (s = 0; s < layer->class[c]->numstyles; s++) { if( layer->class[c]->styles[s]->angle != 0 ) layer->class[c]->styles[s]->angle -= map->gt.rotation_angle; } } for (j = 0; j < shape->numlines; j++) { for (i = 0; i < shape->line[j].numpoints; i++) { point = &(shape->line[j].point[i]); if (layer->transform == MS_TRUE) { if (!msPointInRect(point, &map->extent)) continue; /* next point */ msTransformPoint(point, &map->extent, map->cellsize, image); } else msOffsetPointRelativeTo(point, layer); if(MS_DRAW_FEATURES(drawmode)) { for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, image, point, layer->class[c]->styles[s], layer->scalefactor))) { goto end; } } } if(MS_DRAW_LABELS(drawmode)) { if (layer->labelcache) { if (msAddLabelGroup(map, image, layer, c, shape, point, -1) != MS_SUCCESS) goto end; } else { for (l = 0; l < layer->class[c]->numlabels; l++) if(msGetLabelStatus(map,layer,shape,layer->class[c]->labels[l]) == MS_ON) { char *annotext = msShapeGetLabelAnnotation(layer,shape,layer->class[c]->labels[l]); if(UNLIKELY(MS_FAILURE == msDrawLabel(map, image, *point, annotext, layer->class[c]->labels[l], layer->scalefactor))) { goto end; } } } } } } ret = MS_SUCCESS; end: if( map->gt.rotation_angle ) { for (l = 0; l < layer->class[c]->numlabels; l++) { if( layer->class[c]->labels[l]->angle != 0 ) layer->class[c]->labels[l]->angle += map->gt.rotation_angle; } for (s = 0; s < layer->class[c]->numstyles; s++) { if( layer->class[c]->styles[s]->angle != 0 ) layer->class[c]->styles[s]->angle += map->gt.rotation_angle; } } return ret; } int lineLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape, shapeObj *anno_shape, shapeObj *unclipped_shape, int style, int drawmode) { int c = shape->classindex; int ret = MS_SUCCESS; int i, s, l = 0; /* RFC48: loop through the styles, and pass off to the type-specific function if the style has an appropriate type */ if(MS_DRAW_FEATURES(drawmode)) { for (s = 0; s < layer->class[c]->numstyles; s++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom)) { if (layer->class[c]->styles[s]->_geomtransform.type != MS_GEOMTRANSFORM_NONE) { if(UNLIKELY(MS_FAILURE == msDrawTransformedShape(map, image, unclipped_shape, layer->class[c]->styles[s], layer->scalefactor))) { return MS_FAILURE; } } else if (!MS_DRAW_SINGLESTYLE(drawmode) || s == style) { if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map, image, shape, layer->class[c]->styles[s], layer->scalefactor))) { return MS_FAILURE; } } } } } if(MS_DRAW_LABELS(drawmode)) { for (l = 0; l < layer->class[c]->numlabels; l++) { labelObj *label = layer->class[c]->labels[l]; textSymbolObj ts; char *annotext; if(!msGetLabelStatus(map,layer,shape,label)) { continue; } annotext = msShapeGetLabelAnnotation(layer,anno_shape,label); if(!annotext) continue; initTextSymbol(&ts); msPopulateTextSymbolForLabelAndString(&ts,label,annotext,layer->scalefactor,image->resolutionfactor, layer->labelcache); if (label->anglemode == MS_FOLLOW) { /* bug #1620 implementation */ struct label_follow_result lfr; if (!layer->labelcache) { msSetError(MS_MISCERR, "Angle mode 'FOLLOW' is supported only with labelcache on", "msDrawShape()"); ret = MS_FAILURE; goto line_cleanup; } memset(&lfr,0,sizeof(lfr)); msPolylineLabelPath(map, image, anno_shape, &ts, label, &lfr); for (i = 0; i < lfr.num_follow_labels; i++) { if (msAddLabel(map, image, label, layer->index, c, anno_shape, NULL, -1, lfr.follow_labels[i]) != MS_SUCCESS) { ret = MS_FAILURE; goto line_cleanup; } } free(lfr.follow_labels); for(i=0; irotation = lfr.lar.angles[i]; if (layer->labelcache) { if (msAddLabel(map, image, label, layer->index, c, anno_shape, &lfr.lar.label_points[i], -1, ts_auto) != MS_SUCCESS) { ret = MS_FAILURE; free(lfr.lar.angles); free(lfr.lar.label_points); goto line_cleanup; } } else { ret = msDrawTextSymbol(map,image,lfr.lar.label_points[i],ts_auto); freeTextSymbol(ts_auto); free(ts_auto); /* TODO RFC98: could we not re-use the original ts instead of duplicating into ts_auto ? * we cannot for now, as the rendering code will modify the glyph positions to apply * the labelpoint and rotation offsets */ if(UNLIKELY(MS_FAILURE == ret)) goto line_cleanup; } } free(lfr.lar.angles); free(lfr.lar.label_points); } else { struct label_auto_result lar; memset(&lar,0,sizeof(struct label_auto_result)); ret = msPolylineLabelPoint(map, anno_shape, &ts, label, &lar, image->resolutionfactor); if(UNLIKELY(MS_FAILURE == ret)) goto line_cleanup; if (label->angle != 0) label->angle -= map->gt.rotation_angle; /* apply rotation angle */ for(i=0; irotation = lar.angles[i]; if (layer->labelcache) { if (msAddLabel(map, image, label, layer->index, c, anno_shape, &lar.label_points[i], -1, ts_auto) != MS_SUCCESS) { ret = MS_FAILURE; free(lar.angles); free(lar.label_points); freeTextSymbol(ts_auto); free(ts_auto); goto line_cleanup; } } else { if(!ts_auto->textpath) { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,ts_auto))) { ret = MS_FAILURE; free(lar.angles); free(lar.label_points); freeTextSymbol(ts_auto); free(ts_auto); goto line_cleanup; } } ret = msDrawTextSymbol(map,image,lar.label_points[i],ts_auto); freeTextSymbol(ts_auto); free(ts_auto); /* TODO RFC98: could we not re-use the original ts instead of duplicating into ts_auto ? * we cannot for now, as the rendering code will modify the glyph positions to apply * the labelpoint and rotation offsets */ ts_auto = NULL; if(UNLIKELY(MS_FAILURE == ret)) goto line_cleanup; } } free(lar.angles); free(lar.label_points); } line_cleanup: /* clean up and reset */ if (ret == MS_FAILURE) { break; /* from the label looping */ } freeTextSymbol(&ts); } /* next label */ } return ret; } int polygonLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj *shape, shapeObj *anno_shape, shapeObj *unclipped_shape, int drawmode) { int c = shape->classindex; pointObj annopnt; int i; if(MS_DRAW_FEATURES(drawmode)) { for (i = 0; i < layer->class[c]->numstyles; i++) { if (msScaleInBounds(map->scaledenom, layer->class[c]->styles[i]->minscaledenom, layer->class[c]->styles[i]->maxscaledenom)) { if (layer->class[c]->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE) { if(UNLIKELY(MS_FAILURE == msDrawShadeSymbol(map, image, shape, layer->class[c]->styles[i], layer->scalefactor))) { return MS_FAILURE; } } else { if(UNLIKELY(MS_FAILURE == msDrawTransformedShape(map, image, unclipped_shape, layer->class[c]->styles[i], layer->scalefactor))) { return MS_FAILURE; } } } } } if(MS_DRAW_LABELS(drawmode)) { if (layer->class[c]->numlabels > 0) { double minfeaturesize = layer->class[c]->labels[0]->minfeaturesize * image->resolutionfactor; if (msPolygonLabelPoint(anno_shape, &annopnt, minfeaturesize) == MS_SUCCESS) { for (i = 0; i < layer->class[c]->numlabels; i++) if (layer->class[c]->labels[i]->angle != 0) layer->class[c]->labels[i]->angle -= map->gt.rotation_angle; /* TODO: is this correct ??? */ if (layer->labelcache) { if (msAddLabelGroup(map, image, layer, c, anno_shape, &annopnt, MS_MIN(shape->bounds.maxx - shape->bounds.minx, shape->bounds.maxy - shape->bounds.miny)) != MS_SUCCESS) { return MS_FAILURE; } } else { for (i = 0; i < layer->class[c]->numlabels; i++) if(msGetLabelStatus(map,layer,shape,layer->class[c]->labels[i]) == MS_ON) { char *annotext = msShapeGetLabelAnnotation(layer,shape,layer->class[c]->labels[i]); /*ownership taken by msDrawLabel, no need to free */ if(UNLIKELY(MS_FAILURE == msDrawLabel(map, image, annopnt, annotext, layer->class[c]->labels[i], layer->scalefactor))) { return MS_FAILURE; } } } } } } return MS_SUCCESS; } /* ** Function to render an individual shape, the style variable enables/disables the drawing of a single style ** versus a single style. This is necessary when drawing entire layers as proper overlay can only be achived ** through caching. "querymapMode" parameter is used to tell msBindLayerToShape to not override the ** QUERYMAP HILITE color. */ int msDrawShape(mapObj *map, layerObj *layer, shapeObj *shape, imageObj *image, int style, int drawmode) { int c,s,ret=MS_SUCCESS; shapeObj *anno_shape, *unclipped_shape = shape; int bNeedUnclippedShape = MS_FALSE; int bNeedUnclippedAnnoShape = MS_FALSE; int bShapeNeedsClipping = MS_TRUE; if(shape->numlines == 0 || shape->type == MS_SHAPE_NULL) return MS_SUCCESS; c = shape->classindex; /* Before we do anything else, we will check for a rangeitem. If its there, we need to change the style's color to map the range to the shape */ for(s=0; sclass[c]->numstyles; s++) { styleObj *style = layer->class[c]->styles[s]; if(style->rangeitem != NULL) msShapeToRange((layer->class[c]->styles[s]), shape); } /* circle and point layers go through their own treatment */ if(layer->type == MS_LAYER_CIRCLE) { if(msBindLayerToShape(layer, shape, drawmode) != MS_SUCCESS) return MS_FAILURE; msDrawStartShape(map, layer, image, shape); ret = circleLayerDrawShape(map,image,layer,shape); msDrawEndShape(map,layer,image,shape); return ret; } else if(layer->type == MS_LAYER_POINT || layer->type == MS_LAYER_RASTER) { if(msBindLayerToShape(layer, shape, drawmode) != MS_SUCCESS) return MS_FAILURE; msDrawStartShape(map, layer, image, shape); ret = pointLayerDrawShape(map,image,layer,shape,drawmode); msDrawEndShape(map,layer,image,shape); return ret; } if (layer->type == MS_LAYER_POLYGON && shape->type != MS_SHAPE_POLYGON) { msSetError(MS_MISCERR, "Only polygon shapes can be drawn using a polygon layer definition.", "polygonLayerDrawShape()"); return (MS_FAILURE); } if (layer->type == MS_LAYER_LINE && shape->type != MS_SHAPE_POLYGON && shape->type != MS_SHAPE_LINE) { msSetError(MS_MISCERR, "Only polygon or line shapes can be drawn using a line layer definition.", "msDrawShape()"); return (MS_FAILURE); } #ifdef USE_PROJ if (layer->project && layer->transform == MS_TRUE) msProjectShape(&layer->projection, &map->projection, shape); #endif /* check if we'll need the unclipped shape */ if (shape->type != MS_SHAPE_POINT) { if(MS_DRAW_FEATURES(drawmode)) { for (s = 0; s < layer->class[c]->numstyles; s++) { styleObj *style = layer->class[c]->styles[s]; if (style->_geomtransform.type != MS_GEOMTRANSFORM_NONE) bNeedUnclippedShape = MS_TRUE; } } /* check if we need to clip the shape */ if (shape->bounds.minx < map->extent.minx || shape->bounds.miny < map->extent.miny || shape->bounds.maxx > map->extent.maxx || shape->bounds.maxy > map->extent.maxy) { bShapeNeedsClipping = MS_TRUE; } if(MS_DRAW_LABELS(drawmode) && MS_DRAW_UNCLIPPED_LABELS(drawmode)) { bNeedUnclippedAnnoShape = MS_TRUE; bNeedUnclippedShape = MS_TRUE; } if(MS_DRAW_UNCLIPPED_LINES(drawmode)) { bShapeNeedsClipping = MS_FALSE; } } else { bShapeNeedsClipping = MS_FALSE; } if(layer->transform == MS_TRUE && bShapeNeedsClipping) { /* compute the size of the clipping buffer, in pixels. This buffer must account for the size of symbols drawn to avoid artifacts around the image edges */ int clip_buf = 0; int s; rectObj cliprect; for (s=0;sclass[c]->numstyles;s++) { double maxsize, maxunscaledsize; symbolObj *symbol; styleObj *style = layer->class[c]->styles[s]; if (!MS_IS_VALID_ARRAY_INDEX(style->symbol, map->symbolset.numsymbols)) { msSetError(MS_SYMERR, "Invalid symbol index: %d", "msDrawShape()", style->symbol); return MS_FAILURE; } symbol = map->symbolset.symbol[style->symbol]; if (symbol->type == MS_SYMBOL_PIXMAP) { if (MS_SUCCESS != msPreloadImageSymbol(MS_MAP_RENDERER(map), symbol)) return MS_FAILURE; } else if (symbol->type == MS_SYMBOL_SVG) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) if (MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msDrawShape()"); return MS_FAILURE; #endif } maxsize = MS_MAX(msSymbolGetDefaultSize(symbol), MS_MAX(style->size, style->width)); maxunscaledsize = MS_MAX(style->minsize*image->resolutionfactor, style->minwidth*image->resolutionfactor); if(shape->type == MS_SHAPE_POLYGON && !IS_PARALLEL_OFFSET(style->offsety)) { maxsize += MS_MAX(fabs(style->offsety),fabs(style->offsetx)); } clip_buf = MS_MAX(clip_buf,MS_NINT(MS_MAX(maxsize * layer->scalefactor, maxunscaledsize) + 1)); } /* if we need a copy of the unclipped shape, transform first, then clip to avoid transforming twice */ if(bNeedUnclippedShape) { msTransformShape(shape, map->extent, map->cellsize, image); if(shape->numlines == 0) return MS_SUCCESS; msComputeBounds(shape); /* TODO: there's an optimization here that can be implemented: - no need to allocate unclipped_shape for each call to this function - the calls to msClipXXXRect will discard the original lineObjs, whereas we have just copied them because they where needed. These two functions could be changed so they are instructed not to free the original lineObjs. */ unclipped_shape = (shapeObj *) msSmallMalloc(sizeof (shapeObj)); msInitShape(unclipped_shape); msCopyShape(shape, unclipped_shape); if(shape->type == MS_SHAPE_POLYGON) { /* #179: additional buffer for polygons */ clip_buf += 2; } cliprect.minx = cliprect.miny = -clip_buf; cliprect.maxx = image->width + clip_buf; cliprect.maxy = image->height + clip_buf; if(shape->type == MS_SHAPE_POLYGON) { msClipPolygonRect(shape, cliprect); } else { assert(shape->type == MS_SHAPE_LINE); msClipPolylineRect(shape, cliprect); } if(bNeedUnclippedAnnoShape) { anno_shape = unclipped_shape; } else { anno_shape = shape; } } else { /* clip first, then transform. This means we are clipping in geographical space */ double clip_buf_d; if(shape->type == MS_SHAPE_POLYGON) { /* * add a small buffer around the cliping rectangle to * avoid lines around the edges : #179 */ clip_buf += 2; } clip_buf_d = clip_buf * map->cellsize; cliprect.minx = map->extent.minx - clip_buf_d; cliprect.miny = map->extent.miny - clip_buf_d; cliprect.maxx = map->extent.maxx + clip_buf_d; cliprect.maxy = map->extent.maxy + clip_buf_d; if(shape->type == MS_SHAPE_POLYGON) { msClipPolygonRect(shape, cliprect); } else { assert(shape->type == MS_SHAPE_LINE); msClipPolylineRect(shape, cliprect); } msTransformShape(shape, map->extent, map->cellsize, image); msComputeBounds(shape); anno_shape = shape; } } else { /* the shape is fully in the map extent, * or is a point type layer where out of bounds points are treated differently*/ if (layer->transform == MS_TRUE) { msTransformShape(shape, map->extent, map->cellsize, image); msComputeBounds(shape); } else { msOffsetShapeRelativeTo(shape, layer); } anno_shape = shape; } if(shape->numlines == 0) { ret = MS_SUCCESS; /* error message is set in msBindLayerToShape() */ goto draw_shape_cleanup; } if(msBindLayerToShape(layer, shape, drawmode) != MS_SUCCESS) { ret = MS_FAILURE; /* error message is set in msBindLayerToShape() */ goto draw_shape_cleanup; } switch(layer->type) { case MS_LAYER_LINE: msDrawStartShape(map, layer, image, shape); ret = lineLayerDrawShape(map, image, layer, shape, anno_shape, unclipped_shape, style, drawmode); break; case MS_LAYER_POLYGON: msDrawStartShape(map, layer, image, shape); ret = polygonLayerDrawShape(map, image, layer, shape, anno_shape, unclipped_shape, drawmode); break; case MS_LAYER_POINT: case MS_LAYER_RASTER: assert(0); //bug ! default: msSetError(MS_MISCERR, "Unknown layer type.", "msDrawShape()"); ret = MS_FAILURE; } draw_shape_cleanup: msDrawEndShape(map,layer,image,shape); if(unclipped_shape != shape) { msFreeShape(unclipped_shape); msFree(unclipped_shape); } return ret; } /* ** Function to render an individual point, used as a helper function for mapscript only. Since a point ** can't carry attributes you can't do attribute based font size or angle. */ int msDrawPoint(mapObj *map, layerObj *layer, pointObj *point, imageObj *image, int classindex, char *labeltext) { int s,ret; classObj *theclass=layer->class[classindex]; labelObj *label=NULL; #ifdef USE_PROJ if(layer->transform == MS_TRUE && layer->project) msProjectPoint(&layer->projection, &map->projection, point); #endif if(labeltext && theclass->numlabels > 0) { label = theclass->labels[0]; } switch(layer->type) { case MS_LAYER_POINT: if(layer->transform == MS_TRUE) { if(!msPointInRect(point, &map->extent)) return(0); point->x = MS_MAP2IMAGE_X(point->x, map->extent.minx, map->cellsize); point->y = MS_MAP2IMAGE_Y(point->y, map->extent.maxy, map->cellsize); } else msOffsetPointRelativeTo(point, layer); for(s=0; snumstyles; s++) { if(msScaleInBounds(map->scaledenom, theclass->styles[s]->minscaledenom, theclass->styles[s]->maxscaledenom)) if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, image, point, theclass->styles[s], layer->scalefactor))) { return MS_FAILURE; } } if(labeltext && *labeltext) { textSymbolObj *ts = msSmallMalloc(sizeof(textSymbolObj)); initTextSymbol(ts); msPopulateTextSymbolForLabelAndString(ts, label, msStrdup(labeltext), layer->scalefactor, image->resolutionfactor, layer->labelcache); if(layer->labelcache) { if(msAddLabel(map, image, label, layer->index, classindex, NULL, point, -1, ts) != MS_SUCCESS) { return(MS_FAILURE); } } else { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,ts))) { freeTextSymbol(ts); free(ts); return MS_FAILURE; } ret = msDrawTextSymbol(map,image,*point,ts); freeTextSymbol(ts); free(ts); if(UNLIKELY(ret == MS_FAILURE)) return MS_FAILURE; } } break; default: break; /* don't do anything with layer of other types */ } return(MS_SUCCESS); /* all done, no cleanup */ } /* ** Draws a single label independently of the label cache. No collision avoidance is performed. */ int msDrawLabel(mapObj *map, imageObj *image, pointObj labelPnt, char *string, labelObj *label, double scalefactor) { shapeObj labelPoly; label_bounds lbounds; lineObj labelPolyLine; pointObj labelPolyPoints[5]; textSymbolObj ts; int needLabelPoly=MS_TRUE; int needLabelPoint=MS_TRUE; int haveLabelText=MS_TRUE; if(!string || !*string) haveLabelText = MS_FALSE; if(haveLabelText) { initTextSymbol(&ts); msPopulateTextSymbolForLabelAndString(&ts, label, string, scalefactor, image->resolutionfactor, 0); if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,&ts))) { freeTextSymbol(&ts); return MS_FAILURE; } } labelPoly.line = &labelPolyLine; /* setup the label polygon structure */ labelPoly.numlines = 1; lbounds.poly = &labelPolyLine; /* setup the label polygon structure */ labelPoly.line->point = labelPolyPoints; labelPoly.line->numpoints = 5; if(label->position != MS_XY) { pointObj p; if(label->numstyles > 0) { int i; for(i=0; inumstyles; i++) { if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE) { if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, image, &labelPnt, label->styles[i], scalefactor))) { if(haveLabelText) freeTextSymbol(&ts); return MS_FAILURE; } } else if(haveLabelText && (label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY || label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELCENTER)) { if(needLabelPoly) { p = get_metrics(&labelPnt, label->position, ts.textpath, label->offsetx * ts.scalefactor, label->offsety * ts.scalefactor, ts.rotation, 1, &lbounds); if(!lbounds.poly) { /* we need the full shape to draw the label background */ labelPolyPoints[0].x = labelPolyPoints[4].x = lbounds.bbox.minx; labelPolyPoints[0].y = labelPolyPoints[4].y = lbounds.bbox.miny; labelPolyPoints[1].x = lbounds.bbox.minx; labelPolyPoints[1].y = lbounds.bbox.maxy; labelPolyPoints[2].x = lbounds.bbox.maxx; labelPolyPoints[2].y = lbounds.bbox.maxy; labelPolyPoints[3].x = lbounds.bbox.maxx; labelPolyPoints[3].y = lbounds.bbox.miny; } needLabelPoint = MS_FALSE; /* don't re-compute */ needLabelPoly = MS_FALSE; } if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { if(UNLIKELY(MS_FAILURE == msDrawShadeSymbol(map, image, &labelPoly, label->styles[i], ts.scalefactor))) { freeTextSymbol(&ts); return MS_FAILURE; } } else { pointObj labelCenter; labelCenter.x = (lbounds.bbox.maxx + lbounds.bbox.minx)/2; labelCenter.y = (lbounds.bbox.maxy + lbounds.bbox.miny)/2; if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, image, &labelCenter, label->styles[i], scalefactor))) { freeTextSymbol(&ts); return MS_FAILURE; } } } else { msSetError(MS_MISCERR,"Unknown label geomtransform %s", "msDrawLabel()",label->styles[i]->_geomtransform.string); if(haveLabelText) freeTextSymbol(&ts); return MS_FAILURE; } } } if(haveLabelText) { if(needLabelPoint) p = get_metrics(&labelPnt, label->position, ts.textpath, label->offsetx * ts.scalefactor, label->offsety * ts.scalefactor, ts.rotation, 0, &lbounds); /* draw the label text */ if(UNLIKELY(MS_FAILURE == msDrawTextSymbol(map,image,p,&ts))) { freeTextSymbol(&ts); return MS_FAILURE; } } } else { labelPnt.x += label->offsetx * ts.scalefactor; labelPnt.y += label->offsety * ts.scalefactor; if(label->numstyles > 0) { int i; for(i=0; inumstyles; i++) { if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE) { if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, image, &labelPnt, label->styles[i], scalefactor))) { freeTextSymbol(&ts); return MS_FAILURE; } } else if(haveLabelText && (label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY || label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELCENTER)) { if(needLabelPoly) { get_metrics(&labelPnt, label->position, ts.textpath, label->offsetx * ts.scalefactor, label->offsety * ts.scalefactor, ts.rotation, 1, &lbounds); needLabelPoly = MS_FALSE; /* don't re-compute */ if(!lbounds.poly) { /* we need the full shape to draw the label background */ labelPolyPoints[0].x = labelPolyPoints[4].x = lbounds.bbox.minx; labelPolyPoints[0].y = labelPolyPoints[4].y = lbounds.bbox.miny; labelPolyPoints[1].x = lbounds.bbox.minx; labelPolyPoints[1].y = lbounds.bbox.maxy; labelPolyPoints[2].x = lbounds.bbox.maxx; labelPolyPoints[2].y = lbounds.bbox.maxy; labelPolyPoints[3].x = lbounds.bbox.maxx; labelPolyPoints[3].y = lbounds.bbox.miny; } } if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { if(UNLIKELY(MS_FAILURE == msDrawShadeSymbol(map, image, &labelPoly, label->styles[i], scalefactor))) { freeTextSymbol(&ts); return MS_FAILURE; } } else { pointObj labelCenter; labelCenter.x = (lbounds.bbox.maxx + lbounds.bbox.minx)/2; labelCenter.y = (lbounds.bbox.maxy + lbounds.bbox.miny)/2; if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, image, &labelCenter, label->styles[i], scalefactor))) { freeTextSymbol(&ts); return MS_FAILURE; } } } else { msSetError(MS_MISCERR,"Unknown label geomtransform %s", "msDrawLabel()",label->styles[i]->_geomtransform.string); if(haveLabelText) freeTextSymbol(&ts); return MS_FAILURE; } } } if(haveLabelText) { /* draw the label text */ if(UNLIKELY(MS_FAILURE == msDrawTextSymbol(map,image,labelPnt,&ts))) { freeTextSymbol(&ts); return MS_FAILURE; } } } if(haveLabelText) freeTextSymbol(&ts); return MS_SUCCESS; } static inline void offset_bbox(const rectObj *from, rectObj *to, double ox, double oy) { to->minx = from->minx + ox; to->miny = from->miny + oy; to->maxx = from->maxx + ox; to->maxy = from->maxy + oy; } static inline void offset_label_bounds(const label_bounds *from, label_bounds *to, double ox, double oy) { if(from->poly) { int i; for(i=0; ipoly->numpoints; i++) { to->poly->point[i].x = from->poly->point[i].x + ox; to->poly->point[i].y = from->poly->point[i].y + oy; } to->poly->numpoints = from->poly->numpoints; } else { to->poly = NULL; } offset_bbox(&from->bbox, &to->bbox, ox, oy); } /* private shortcut function to try a leader offsetted label * the caller must ensure that scratch->poly->points has been sufficiently allocated * to hold the points from the cachePtr's label_bounds */ void offsetAndTest(mapObj *map, labelCacheMemberObj *cachePtr, double ox, double oy, int priority, int label_idx, label_bounds *scratch) { int i,j,status; pointObj leaderpt; lineObj *scratch_line = scratch->poly; for(i=0; inumtextsymbols; i++) { textSymbolObj *ts = cachePtr->textsymbols[i]; if(ts->textpath) { offset_label_bounds(&ts->textpath->bounds, scratch, ox, oy); status = msTestLabelCacheCollisions(map, cachePtr, scratch, priority, label_idx); if(!status) { return; } } for(j=0; jlabel->numstyles; j++) { if(ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { scratch->poly = scratch_line; offset_label_bounds(ts->style_bounds[j], scratch, ox, oy); status = msTestLabelCacheCollisions(map, cachePtr, scratch, priority, label_idx); if(!status) { return; } } } } leaderpt.x = cachePtr->point.x + ox; leaderpt.y = cachePtr->point.y + oy; status = msTestLabelCacheLeaderCollision(map, &cachePtr->point, &leaderpt); if(!status) { return; } /* the current offset is ok */ cachePtr->leaderbbox = msSmallMalloc(sizeof(rectObj)); cachePtr->leaderline = msSmallMalloc(sizeof(lineObj)); cachePtr->leaderline->point = msSmallMalloc(2 * sizeof(pointObj)); cachePtr->leaderline->numpoints = 2; cachePtr->leaderline->point[0] = cachePtr->point; cachePtr->leaderline->point[1] = leaderpt; cachePtr->leaderbbox->minx = MS_MIN(leaderpt.x,cachePtr->point.x); cachePtr->leaderbbox->maxx = MS_MAX(leaderpt.x,cachePtr->point.x); cachePtr->leaderbbox->miny = MS_MIN(leaderpt.y,cachePtr->point.y); cachePtr->leaderbbox->maxy = MS_MAX(leaderpt.y,cachePtr->point.y); cachePtr->status = MS_ON; offset_bbox(&cachePtr->bbox,&cachePtr->bbox,ox,oy); for(i=0; inumtextsymbols; i++) { textSymbolObj *ts = cachePtr->textsymbols[i]; if(ts->textpath) { offset_label_bounds(&ts->textpath->bounds, &ts->textpath->bounds, ox, oy); ts->annopoint.x += ox; ts->annopoint.y += oy; } if(ts->style_bounds) { for(j=0; jlabel->numstyles; j++) { if(ts->label->styles[j]->_geomtransform.type != MS_GEOMTRANSFORM_NONE) offset_label_bounds(ts->style_bounds[j], ts->style_bounds[j], ox, oy); } } } } int msDrawOffsettedLabels(imageObj *image, mapObj *map, int priority) { int retval = MS_SUCCESS; int l; labelCacheObj *labelcache = &(map->labelcache); labelCacheSlotObj *cacheslot; labelCacheMemberObj *cachePtr; label_bounds scratch; lineObj scratch_line; pointObj *scratch_points = NULL; int num_allocated_scratch_points = 0; assert(MS_RENDERER_PLUGIN(image->format)); cacheslot = &(labelcache->slots[priority]); scratch.poly = &scratch_line; for(l=cacheslot->numlabels-1; l>=0; l--) { cachePtr = &(cacheslot->labels[l]); /* point to right spot in the label cache */ if(cachePtr->status == MS_OFF) { /* only test regular labels that have had their bounding box computed and that haven't been rendered */ classObj *classPtr = (GET_CLASS(map,cachePtr->layerindex,cachePtr->classindex)); layerObj *layerPtr = (GET_LAYER(map,cachePtr->layerindex)); int steps,i,num_scratch_points_to_allocate = 0; assert(classPtr->leader); /* cachePtrs that don't need to be tested have been marked as status on or delete */ if(cachePtr->point.x < labelcache->gutter || cachePtr->point.y < labelcache->gutter || cachePtr->point.x >= image->width - labelcache->gutter || cachePtr->point.y >= image->height - labelcache->gutter) { /* don't look for leaders if point is in edge buffer as the leader line would end up chopped off */ continue; } for(i=0; inumtextsymbols; i++) { int j; textSymbolObj *ts = cachePtr->textsymbols[i]; if(ts->textpath && ts->textpath->bounds.poly) { num_scratch_points_to_allocate = MS_MAX(num_scratch_points_to_allocate, ts->textpath->bounds.poly->numpoints); } if(ts->style_bounds) { for(j=0;jlabel->numstyles; j++) { if(ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT && ts->style_bounds[j]->poly) { num_scratch_points_to_allocate = MS_MAX(num_scratch_points_to_allocate, ts->style_bounds[j]->poly->numpoints); } } } } if(num_scratch_points_to_allocate > num_allocated_scratch_points) { scratch_points = msSmallRealloc(scratch_points, num_scratch_points_to_allocate * sizeof(pointObj)); num_allocated_scratch_points = num_scratch_points_to_allocate; } steps = classPtr->leader->maxdistance / classPtr->leader->gridstep; #define x0 (cachePtr->point.x) #define y0 (cachePtr->point.y) #define gridstepsc (classPtr->leader->gridstep) #define otest(ox,oy) if((x0+(ox)) >= labelcache->gutter &&\ (y0+(oy)) >= labelcache->gutter &&\ (x0+(ox)) < image->width - labelcache->gutter &&\ (y0+(oy)) < image->height - labelcache->gutter) {\ scratch_line.point = scratch_points;\ scratch.poly = &scratch_line; \ offsetAndTest(map,cachePtr,(ox),(oy),priority,l,&scratch); \ if(cachePtr->status == MS_ON) break;\ } /* loop through possible offsetted positions */ for(i=1; i<=steps; i++) { /* test the intermediate points on the ring */ /* (points marked "0" are the ones being tested) X00X00X 0XXXXX0 0XXXXX0 XXX.XXX 0XXXXX0 0XXXXX0 X00X00X */ int j; for(j=1; jstatus == MS_ON) { int ll; shapeObj labelLeader; /* label polygon (bounding box, possibly rotated) */ labelLeader.line = cachePtr->leaderline; /* setup the label polygon structure */ labelLeader.numlines = 1; insertRenderedLabelMember(map, cachePtr); for(ll=0; llleader->numstyles; ll++) { retval = msDrawLineSymbol(map, image,&labelLeader , classPtr->leader->styles[ll], layerPtr->scalefactor); if(UNLIKELY(retval == MS_FAILURE)) { goto offset_cleanup; } } for(ll=0; llnumtextsymbols; ll++) { textSymbolObj *ts = cachePtr->textsymbols[ll]; if(ts->style_bounds) { /* here's where we draw the label styles */ for(i=0; ilabel->numstyles; i++) { if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { retval = msDrawMarkerSymbol(map, image, &(labelLeader.line->point[1]), ts->label->styles[i], layerPtr->scalefactor); if(UNLIKELY(retval == MS_FAILURE)) { goto offset_cleanup; } } else if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { retval = msDrawLabelBounds(map,image,ts->style_bounds[i],ts->label->styles[i], ts->scalefactor); if(UNLIKELY(retval == MS_FAILURE)) { goto offset_cleanup; } } else if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELCENTER) { pointObj labelCenter; labelCenter.x = (ts->style_bounds[i]->bbox.maxx + ts->style_bounds[i]->bbox.minx)/2; labelCenter.y = (ts->style_bounds[i]->bbox.maxy + ts->style_bounds[i]->bbox.miny)/2; retval = msDrawMarkerSymbol(map, image, &labelCenter, ts->label->styles[i], layerPtr->scalefactor); if(UNLIKELY(retval == MS_FAILURE)) { goto offset_cleanup; } } else { msSetError(MS_MISCERR,"Labels only support LABELPNT, LABELPOLY and LABELCENTER GEOMTRANSFORMS", "msDrawOffsettedLabels()"); retval = MS_FAILURE; } } } if(ts->annotext) { retval = msDrawTextSymbol(map,image,ts->annopoint,ts); if(UNLIKELY(retval == MS_FAILURE)) { goto offset_cleanup; } } } /* TODO: draw cachePtr->marker, but where ? */ /* styleObj tstyle; static int foo =0; if(!foo) { srand(time(NULL)); foo = 1; initStyle(&tstyle); tstyle.width = 1; tstyle.color.alpha = 255; } tstyle.color.red = random()%255; tstyle.color.green = random()%255; tstyle.color.blue =random()%255; msDrawLineSymbol(&map->symbolset, image, cachePtr->poly, &tstyle, layerPtr->scalefactor); */ } } } offset_cleanup: free(scratch_points); return retval; } void fastComputeBounds(lineObj *line, rectObj *bounds) { int j; bounds->minx = bounds->maxx = line->point[0].x; bounds->miny = bounds->maxy = line->point[0].y; for( j=0; jnumpoints; j++ ) { bounds->minx = MS_MIN(bounds->minx, line->point[j].x); bounds->maxx = MS_MAX(bounds->maxx, line->point[j].x); bounds->miny = MS_MIN(bounds->miny, line->point[j].y); bounds->maxy = MS_MAX(bounds->maxy, line->point[j].y); } } int computeMarkerBounds(mapObj *map, pointObj *annopoint, textSymbolObj *ts, label_bounds *poly) { int i; for (i=0; ilabel->numstyles; i++) { styleObj *style = ts->label->styles[i]; if(style->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT && style->symbol < map->symbolset.numsymbols && style->symbol >= 0) { double sx,sy; int p; double aox,aoy; symbolObj *symbol = map->symbolset.symbol[style->symbol]; if(msGetMarkerSize(map, style, &sx, &sy, ts->scalefactor) != MS_SUCCESS) return MS_FALSE; if(style->angle) { pointObj *point = poly->poly->point; point[0].x = sx / 2.0; point[0].y = sy / 2.0; point[1].x = point[0].x; point[1].y = -point[0].y; point[2].x = -point[0].x; point[2].y = -point[0].y; point[3].x = -point[0].x; point[3].y = point[0].y; point[4].x = point[0].x; point[4].y = point[0].y; if(symbol->anchorpoint_x != 0.5 || symbol->anchorpoint_y != 0.5) { aox = (0.5 - symbol->anchorpoint_x) * sx; aoy = (0.5 - symbol->anchorpoint_y) * sy; for(p=0; p<5; p++) { point[p].x += aox; point[p].y += aoy; } } if(style->angle) { double rot = -style->angle * MS_DEG_TO_RAD; double sina = sin(rot); double cosa = cos(rot); for(p=0; p<5; p++) { double tmpx = point[p].x; point[p].x = point[p].x * cosa - point[p].y * sina; point[p].y = tmpx * sina + point[p].y * cosa; } } aox = annopoint->x + style->offsetx * ts->scalefactor; aoy = annopoint->y + style->offsety * ts->scalefactor; for(p=0; p<5; p++) { point[p].x += aox; point[p].y += aoy; } fastComputeBounds(poly->poly,&poly->bbox); } else { double aox = (0.5 - symbol->anchorpoint_x)*sx + annopoint->x + style->offsetx * ts->scalefactor; double aoy = (0.5 - symbol->anchorpoint_y)*sy + annopoint->y + style->offsety * ts->scalefactor; poly->poly = NULL; poly->bbox.maxx = sx/2.0 + aox; poly->bbox.minx = -sx/2.0 + aox; poly->bbox.maxy = sy/2.0 + aoy; poly->bbox.miny = -sy/2.0 + aoy; } break; } } if(i == ts->label->numstyles) return MS_FALSE; /* the label has no marker styles */ else return MS_TRUE; } /* check that the current entry does not fall close to a label with identical text, if configured so. * Currently only checks the first label/text */ int msCheckLabelMinDistance(mapObj *map, labelCacheMemberObj *lc) { int i; textSymbolObj *s; /* shortcut */ textSymbolObj *ts; rectObj buffered; if (lc->numtextsymbols == 0) return MS_FALSE; /* no label with text */ s = lc->textsymbols[0]; if (!s->annotext || s->label->mindistance <= 0.0 || s->label->force == MS_TRUE) return MS_FALSE; /* min distance is not checked */ /* we buffer the label and check for intersection instead of calculating the distance of two textpaths. we also buffer only the bbox of lc for faster computation (it is still compared to the full textpath of the label cache members). */ buffered = lc->bbox; buffered.minx -= s->label->mindistance * s->resolutionfactor; buffered.miny -= s->label->mindistance * s->resolutionfactor; buffered.maxx += s->label->mindistance * s->resolutionfactor; buffered.maxy += s->label->mindistance * s->resolutionfactor; for (i = 0; i < map->labelcache.num_rendered_members; i++) { labelCacheMemberObj *ilc = map->labelcache.rendered_text_symbols[i]; if (ilc->numtextsymbols == 0 || !ilc->textsymbols[0]->annotext) continue; ts = ilc->textsymbols[0]; if (strcmp(s->annotext, ts->annotext) != 0) { /* only check min distance against same label */ continue; } if (msPointInRect(&ilc->point, &buffered) == MS_TRUE) { return MS_TRUE; } if(ts->textpath && ts->textpath->absolute) { if (intersectLabelPolygons(ts->textpath->bounds.poly, &ilc->bbox, NULL, &buffered) == MS_TRUE) { return MS_TRUE; } continue; } if (intersectLabelPolygons(NULL, &ilc->bbox, NULL, &buffered) == MS_TRUE) { return MS_TRUE; } } return MS_FALSE; } void copyLabelBounds(label_bounds *dst, label_bounds *src) { *dst = *src; if(src->poly) { int i; dst->poly = msSmallMalloc(sizeof(lineObj)); dst->poly->numpoints = src->poly->numpoints; dst->poly->point = msSmallMalloc(dst->poly->numpoints * sizeof(pointObj)); for(i=0; ipoly->numpoints; i++) { dst->poly->point[i] = src->poly->point[i]; } } } static int getLabelPositionFromString(char *pszString) { if (strcasecmp(pszString, "UL")==0) return MS_UL; else if (strcasecmp(pszString, "LR")==0) return MS_LR; else if (strcasecmp(pszString, "UR")==0) return MS_UR; else if (strcasecmp(pszString, "LL")==0) return MS_LL; else if (strcasecmp(pszString, "CR")==0) return MS_CR; else if (strcasecmp(pszString, "CL")==0) return MS_CL; else if (strcasecmp(pszString, "UC")==0) return MS_UC; else if (strcasecmp(pszString, "LC")==0) return MS_LC; else return MS_CC; } int msDrawLabelCache(mapObj *map, imageObj *image) { int nReturnVal = MS_SUCCESS; struct mstimeval starttime, endtime; if(map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&starttime, NULL); if(image) { if(MS_RENDERER_PLUGIN(image->format)) { int i, l, ll, priority, its; double marker_offset_x, marker_offset_y; int label_offset_x, label_offset_y; const char *value; labelCacheMemberObj *cachePtr=NULL; layerObj *layerPtr=NULL; classObj *classPtr=NULL; textSymbolObj *textSymbolPtr=NULL; /* * some statically allocated containers for storing label bounds before * copying them into the cachePtr: we avoid allocating these structures * at runtime, except for the labels that are actually rendered. */ lineObj labelpoly_line; pointObj labelpoly_points[5]; label_bounds labelpoly_bounds; lineObj label_marker_line; pointObj label_marker_points[5]; label_bounds label_marker_bounds; lineObj metrics_line; pointObj metrics_points[5]; label_bounds metrics_bounds; label_marker_line.point = label_marker_points; label_marker_line.numpoints = 5; metrics_line.point = metrics_points; metrics_line.numpoints = 5; labelpoly_line.point = labelpoly_points; labelpoly_line.numpoints = 5; /* Look for labelcache_map_edge_buffer map metadata * If set then the value defines a buffer (in pixels) along the edge of the * map image where labels can't fall */ if((value = msLookupHashTable(&(map->web.metadata), "labelcache_map_edge_buffer")) != NULL) { map->labelcache.gutter = MS_ABS(atoi(value)); if(map->debug) msDebug("msDrawLabelCache(): labelcache_map_edge_buffer = %d\n", map->labelcache.gutter); } for(priority=MS_MAX_LABEL_PRIORITY-1; priority>=0; priority--) { labelCacheSlotObj *cacheslot; cacheslot = &(map->labelcache.slots[priority]); for(l=cacheslot->numlabels-1; l>=0; l--) { cachePtr = &(cacheslot->labels[l]); /* point to right spot in the label cache */ layerPtr = (GET_LAYER(map, cachePtr->layerindex)); /* set a couple of other pointers, avoids nasty references */ classPtr = (GET_CLASS(map, cachePtr->layerindex, cachePtr->classindex)); if(cachePtr->textsymbols[0]->textpath && cachePtr->textsymbols[0]->textpath->absolute) { /* we have an angle follow label */ cachePtr->bbox = cachePtr->textsymbols[0]->textpath->bounds.bbox; /* before going any futher, check that mindistance is respected */ if (cachePtr->numtextsymbols && cachePtr->textsymbols[0]->label->mindistance > 0.0 && cachePtr->textsymbols[0]->annotext) { if (msCheckLabelMinDistance(map, cachePtr) == MS_TRUE) { cachePtr->status = MS_DELETE; MS_DEBUG(MS_DEBUGLEVEL_DEVDEBUG, map, "Skipping labelgroup %d \"%s\" in layer \"%s\": too close to an identical label (mindistance)\n", l, cachePtr->textsymbols[0]->annotext, layerPtr->name); continue; /* move on to next entry, this one is too close to an already placed one */ } } if(!cachePtr->textsymbols[0]->label->force) cachePtr->status = msTestLabelCacheCollisions(map,cachePtr,&cachePtr->textsymbols[0]->textpath->bounds, priority, l); else cachePtr->status = MS_ON; if(cachePtr->status) { if (UNLIKELY(MS_FAILURE == msDrawTextSymbol(map, image, cachePtr->textsymbols[0]->annopoint /*not used*/, cachePtr->textsymbols[0]))) { return MS_FAILURE; } insertRenderedLabelMember(map, cachePtr); } else { MS_DEBUG(MS_DEBUGLEVEL_DEVDEBUG,map, "Skipping follow labelgroup %d \"%s\" in layer \"%s\": text collided\n", l, cachePtr->textsymbols[0]->annotext, layerPtr->name); } cachePtr->status = MS_DELETE; /* we're done with this label, it won't even have a second chance in the leader phase */ } else { marker_offset_x = marker_offset_y = 0; /* assume no marker */ if (layerPtr->type == MS_LAYER_POINT && cachePtr->markerid!=-1) { /* there is a marker already in the image that we need to account for */ markerCacheMemberObj *markerPtr = &(cacheslot->markers[cachePtr->markerid]); /* point to the right spot in the marker cache*/ marker_offset_x = (markerPtr->bounds.maxx-markerPtr->bounds.minx)/2.0; marker_offset_y = (markerPtr->bounds.maxy-markerPtr->bounds.miny)/2.0; } /* ** all other cases *could* have multiple labels defined */ cachePtr->status = MS_ON; /* assume this cache element can be placed */ for(ll=0; llnumtextsymbols; ll++) { /* RFC 77 TODO: Still may want to step through backwards... */ int label_marker_status = MS_ON, have_label_marker, metrics_status = MS_ON; int need_labelpoly = 0; /* reset the lineObj which may have been unset by a previous call to get_metrics() */ label_marker_bounds.poly = &label_marker_line; labelpoly_bounds.poly = &labelpoly_line; textSymbolPtr = cachePtr->textsymbols[ll]; for(i=0; ilabel->numstyles; i++) { if(textSymbolPtr->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY || textSymbolPtr->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELCENTER) { need_labelpoly = 1; break; } } /* compute the poly of the label styles */ if((have_label_marker = computeMarkerBounds(map,&cachePtr->point,textSymbolPtr, &label_marker_bounds)) == MS_TRUE) { if(cachePtr->numtextsymbols > 1) { /* FIXME this test doesn't seem right, should probably check if we have an annotation layer with a regular style defined */ marker_offset_x = (label_marker_bounds.bbox.maxx-label_marker_bounds.bbox.minx)/2.0; marker_offset_y = (label_marker_bounds.bbox.maxy-label_marker_bounds.bbox.miny)/2.0; } else { /* we might be using an old style behavior with a markerPtr */ marker_offset_x = MS_MAX(marker_offset_x,(label_marker_bounds.bbox.maxx-label_marker_bounds.bbox.minx)/2.0); marker_offset_y = MS_MAX(marker_offset_y,(label_marker_bounds.bbox.maxy-label_marker_bounds.bbox.miny)/2.0); } /* add marker to cachePtr->poly */ if(textSymbolPtr->label->force != MS_TRUE) { label_marker_status = msTestLabelCacheCollisions(map, cachePtr, &label_marker_bounds ,priority, l); } if(label_marker_status == MS_OFF && !(textSymbolPtr->label->force==MS_ON || classPtr->leader)) { cachePtr->status = MS_DELETE; MS_DEBUG(MS_DEBUGLEVEL_DEVDEBUG, map, "Skipping label %d of labelgroup %d of class %d in layer \"%s\": marker collided\n", ll, l, cachePtr->classindex, layerPtr->name); break; /* the marker collided, break from multi-label loop */ } } if(textSymbolPtr->annotext) { /* * if we don't have an offset defined, first check that the labelpoint itself does not collide * this helps speed things up in dense labelling, as if the labelpoint collides there's * no use in computing the labeltext bounds (i.e. going into shaping+freetype). * We do however skip collision testing against the marker cache, as we want to allow rendering * a label for points that overlap each other: this is done by setting priority to MAX_PRIORITY * in the call to msTestLabelCacheCollisions (which is a hack!!) */ if(!have_label_marker && textSymbolPtr->label->force != MS_TRUE && !classPtr->leader && !textSymbolPtr->label->offsetx && !textSymbolPtr->label->offsety) { label_bounds labelpoint_bounds; labelpoint_bounds.poly = NULL; labelpoint_bounds.bbox.minx = cachePtr->point.x - 0.1; labelpoint_bounds.bbox.maxx = cachePtr->point.x + 0.1; labelpoint_bounds.bbox.miny = cachePtr->point.y - 0.1; labelpoint_bounds.bbox.maxy = cachePtr->point.y + 0.1; if(MS_OFF == msTestLabelCacheCollisions(map, cachePtr, &labelpoint_bounds, MS_MAX_LABEL_PRIORITY, l)) { cachePtr->status = MS_DELETE; /* we won't check for leader offseted positions, as the anchor point colided */ MS_DEBUG(MS_DEBUGLEVEL_DEVDEBUG, map, "Skipping label %d \"%s\" of labelgroup %d of class %d in layer \"%s\": labelpoint collided\n", ll, textSymbolPtr->annotext, l, cachePtr->classindex, layerPtr->name); break; } } /* compute label size */ if(!textSymbolPtr->textpath) { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,textSymbolPtr))) { return MS_FAILURE; } } /* if our label has an outline, adjust the marker offset so the outlinecolor does * not bleed into the marker */ if(marker_offset_x && MS_VALID_COLOR(textSymbolPtr->label->outlinecolor)) { marker_offset_x += textSymbolPtr->label->outlinewidth/2.0 * textSymbolPtr->scalefactor; marker_offset_y += textSymbolPtr->label->outlinewidth/2.0 * textSymbolPtr->scalefactor; } /* apply offset and buffer settings */ if(textSymbolPtr->label->anglemode != MS_FOLLOW) { label_offset_x = textSymbolPtr->label->offsetx * textSymbolPtr->scalefactor; label_offset_y = textSymbolPtr->label->offsety * textSymbolPtr-> scalefactor; } else { label_offset_x = 0; label_offset_y = 0; } if(textSymbolPtr->label->position == MS_AUTO) { /* no point in using auto positionning if the marker cannot be placed */ int positions[MS_POSITIONS_LENGTH], npositions=0; /* ** (Note: might be able to re-order this for more speed.) */ if(msLayerGetProcessingKey(layerPtr, "LABEL_POSITIONS")) { int p, ncustom_positions=0; char **custom_positions = msStringSplitComplex(msLayerGetProcessingKey(layerPtr, "LABEL_POSITIONS"), ",", &ncustom_positions, MS_STRIPLEADSPACES|MS_STRIPENDSPACES); for(p=0; ptype == MS_LAYER_POLYGON && marker_offset_x==0 ) { positions[0]=MS_CC; positions[1]=MS_UC; positions[2]=MS_LC; positions[3]=MS_CL; positions[4]=MS_CR; npositions = 5; } else if(layerPtr->type == MS_LAYER_LINE && marker_offset_x == 0) { positions[0]=MS_UC; positions[1]=MS_LC; positions[2]=MS_CC; npositions = 3; } else { positions[0]=MS_UL; positions[1]=MS_LR; positions[2]=MS_UR; positions[3]=MS_LL; positions[4]=MS_CR; positions[5]=MS_CL; positions[6]=MS_UC; positions[7]=MS_LC; npositions = 8; } for(i=0; iannopoint = get_metrics(&(cachePtr->point), positions[i], textSymbolPtr->textpath, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, textSymbolPtr->rotation, textSymbolPtr->label->buffer * textSymbolPtr->scalefactor, &metrics_bounds); if(textSymbolPtr->label->force == MS_OFF) { for(its=0;itstextsymbols[its],&metrics_bounds) == MS_TRUE) { /* there was a self intersection */ break; /* next position, will break out to next position in containing loop*/ } if(its != ll) continue; /* goto next position, this one had an intersection with our own label group */ } } metrics_status = msTestLabelCacheCollisions(map, cachePtr,&metrics_bounds, priority, l); /* found a suitable place for this label */ if(metrics_status == MS_TRUE || (i==(npositions-1) && textSymbolPtr->label->force == MS_ON)) { metrics_status = MS_TRUE; /* set to true in case we are forcing it */ /* compute anno poly for label background if needed */ if(need_labelpoly) get_metrics(&(cachePtr->point), positions[i], textSymbolPtr->textpath, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, textSymbolPtr->rotation, 1, &labelpoly_bounds); break; /* ...out of position loop */ } } /* next position */ /* if position auto didn't manage to find a position, but we have leader configured * for the class, then we want to compute the label poly anyway, placed as MS_CC */ if(classPtr->leader && metrics_status == MS_FALSE) { metrics_bounds.poly = &metrics_line; textSymbolPtr->annopoint = get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath, label_offset_x, label_offset_y, textSymbolPtr->rotation, textSymbolPtr->label->buffer * textSymbolPtr->scalefactor, &metrics_bounds); if(need_labelpoly) get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath, label_offset_x, label_offset_y, textSymbolPtr->rotation, 1, &labelpoly_bounds); } } else { /* explicit position */ if(textSymbolPtr->label->position == MS_CC) { /* don't need the marker_offset */ metrics_bounds.poly = &metrics_line; textSymbolPtr->annopoint = get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath, label_offset_x, label_offset_y, textSymbolPtr->rotation, textSymbolPtr->label->buffer * textSymbolPtr->scalefactor, &metrics_bounds); if(need_labelpoly) get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath, label_offset_x, label_offset_y, textSymbolPtr->rotation, 1, &labelpoly_bounds); } else { metrics_bounds.poly = &metrics_line; textSymbolPtr->annopoint = get_metrics(&(cachePtr->point), textSymbolPtr->label->position, textSymbolPtr->textpath, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, textSymbolPtr->rotation, textSymbolPtr->label->buffer * textSymbolPtr->scalefactor, &metrics_bounds); if(need_labelpoly) get_metrics(&(cachePtr->point), textSymbolPtr->label->position, textSymbolPtr->textpath, marker_offset_x + label_offset_x, marker_offset_y + label_offset_y, textSymbolPtr->rotation, 1, &labelpoly_bounds); } if(textSymbolPtr->label->force == MS_ON) { metrics_status = MS_ON; } else { if(textSymbolPtr->label->force == MS_OFF) { /* check for collisions inside the label group unless the label is FORCE GROUP */ for(its=0;itstextsymbols[its],&metrics_bounds) == MS_TRUE) { /* there was a self intersection */ break; /* will break out to next position in containing loop*/ } if(its != ll) { cachePtr->status = MS_DELETE; /* TODO RFC98: check if this is correct */ MS_DEBUG(MS_DEBUGLEVEL_DEVDEBUG,map, "Skipping label %d (\"%s\") of labelgroup %d of class %d in layer \"%s\": intercollision with label text inside labelgroup\n", ll, textSymbolPtr->annotext, l,cachePtr->classindex, layerPtr->name); break; /* collision within the group, break out of textSymbol loop */ } } } /* TODO: in case we have leader lines and multiple labels, there's no use in testing for labelcache collisions * once a first collision has been found. we only need to know that the label group has collided, and the * poly of the whole label group: if(label_group) testLabelCacheCollisions */ metrics_status = msTestLabelCacheCollisions(map, cachePtr,&metrics_bounds, priority, l); } } /* end POSITION AUTO vs Fixed POSITION */ if(!metrics_status && classPtr->leader == 0) { cachePtr->status = MS_DELETE; MS_DEBUG(MS_DEBUGLEVEL_DEVDEBUG,map, "Skipping label %d \"%s\" of labelgroup %d of class %d in layer \"%s\": text collided\n", ll, textSymbolPtr->annotext, l, cachePtr->classindex, layerPtr->name); break; /* no point looking at more labels, unless their is a leader defined */ } } /* if we're here, we can either fit the label directly, or we need to put it in the leader queue */ assert((metrics_status && label_marker_status) || classPtr->leader); if(textSymbolPtr->annotext) { copyLabelBounds(&textSymbolPtr->textpath->bounds, &metrics_bounds); } if(have_label_marker) { if(!textSymbolPtr->style_bounds) textSymbolPtr->style_bounds = msSmallCalloc(textSymbolPtr->label->numstyles, sizeof(label_bounds*)); for(its=0;itslabel->numstyles; its++) { if(textSymbolPtr->label->styles[its]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { textSymbolPtr->style_bounds[its] = msSmallMalloc(sizeof(label_bounds)); copyLabelBounds(textSymbolPtr->style_bounds[its], &label_marker_bounds); } } } if(!label_marker_status || ! metrics_status) { MS_DEBUG(MS_DEBUGLEVEL_DEVDEBUG, map, "Putting label %d of labelgroup %d of class %d , layer \"%s\" in leader queue\n", ll, l, cachePtr->classindex, layerPtr->name); cachePtr->status = MS_OFF; /* we have a collision, but this entry is a candidate for leader testing */ } /* do we need to copy the labelpoly, or can we use the static one ?*/ if(cachePtr->numtextsymbols > 1 || (cachePtr->status == MS_OFF && classPtr->leader)) { /* * if we have more than one label, or if we have a single one which didn't fit but needs * to go through leader offset testing */ if(!textSymbolPtr->style_bounds) textSymbolPtr->style_bounds = msSmallCalloc(textSymbolPtr->label->numstyles, sizeof(label_bounds*)); for(its=0;itslabel->numstyles; its++) { if(textSymbolPtr->label->styles[its]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY || textSymbolPtr->label->styles[its]->_geomtransform.type == MS_GEOMTRANSFORM_LABELCENTER) { textSymbolPtr->style_bounds[its] = msSmallMalloc(sizeof(label_bounds)); copyLabelBounds(textSymbolPtr->style_bounds[its], &labelpoly_bounds); } } } /* else: we'll use labelpoly_bounds directly below */ } /* next label in the group */ if(cachePtr->status != MS_DELETE) { /* compute the global label bbox */ int inited = 0,s; for(its=0;itsnumtextsymbols;its++) { if(cachePtr->textsymbols[its]->annotext) { if(inited == 0) { cachePtr->bbox = cachePtr->textsymbols[its]->textpath->bounds.bbox; inited = 1; } else { cachePtr->bbox.minx = MS_MIN(cachePtr->bbox.minx, cachePtr->textsymbols[its]->textpath->bounds.bbox.minx); cachePtr->bbox.miny = MS_MIN(cachePtr->bbox.miny, cachePtr->textsymbols[its]->textpath->bounds.bbox.miny); cachePtr->bbox.maxx = MS_MAX(cachePtr->bbox.maxx, cachePtr->textsymbols[its]->textpath->bounds.bbox.maxx); cachePtr->bbox.maxy = MS_MAX(cachePtr->bbox.maxy, cachePtr->textsymbols[its]->textpath->bounds.bbox.maxy); } } for(s=0; stextsymbols[its]->label->numstyles; s++) { if(cachePtr->textsymbols[its]->label->styles[s]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { if(inited == 0) { cachePtr->bbox = cachePtr->textsymbols[its]->style_bounds[s]->bbox; inited = 1; break; } else { cachePtr->bbox.minx = MS_MIN(cachePtr->bbox.minx, cachePtr->textsymbols[its]->style_bounds[s]->bbox.minx); cachePtr->bbox.miny = MS_MIN(cachePtr->bbox.miny, cachePtr->textsymbols[its]->style_bounds[s]->bbox.miny); cachePtr->bbox.maxx = MS_MAX(cachePtr->bbox.maxx, cachePtr->textsymbols[its]->style_bounds[s]->bbox.maxx); cachePtr->bbox.maxy = MS_MAX(cachePtr->bbox.maxy, cachePtr->textsymbols[its]->style_bounds[s]->bbox.maxy); break; } } } } } /* check that mindistance is respected */ if (cachePtr->numtextsymbols && cachePtr->textsymbols[0]->label->mindistance > 0.0 && cachePtr->textsymbols[0]->annotext) { if (msCheckLabelMinDistance(map, cachePtr) == MS_TRUE) { cachePtr->status = MS_DELETE; MS_DEBUG(MS_DEBUGLEVEL_DEVDEBUG, map, "Skipping labelgroup %d \"%s\" in layer \"%s\": too close to an identical label (mindistance)\n", l, cachePtr->textsymbols[0]->annotext, layerPtr->name); } } if(cachePtr->status == MS_OFF || cachePtr->status == MS_DELETE) continue; /* next labelCacheMemberObj, as we had a collision */ /* insert the rendered label */ insertRenderedLabelMember(map, cachePtr); for(ll=0; llnumtextsymbols; ll++) { textSymbolPtr = cachePtr->textsymbols[ll]; /* here's where we draw the label styles */ for(i=0; ilabel->numstyles; i++) { if(textSymbolPtr->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, image, &(cachePtr->point), textSymbolPtr->label->styles[i], textSymbolPtr->scalefactor))) { return MS_FAILURE; } } else if(textSymbolPtr->annotext && textSymbolPtr->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { if(textSymbolPtr->style_bounds && textSymbolPtr->style_bounds[i]) { if(UNLIKELY(MS_FAILURE == msDrawLabelBounds(map,image,textSymbolPtr->style_bounds[i],textSymbolPtr->label->styles[i], textSymbolPtr->scalefactor))) { return MS_FAILURE; } } else { if(UNLIKELY(MS_FAILURE == msDrawLabelBounds(map,image,&labelpoly_bounds,textSymbolPtr->label->styles[i], textSymbolPtr->scalefactor))) { return MS_FAILURE; } } } else if(textSymbolPtr->annotext && textSymbolPtr->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELCENTER) { pointObj labelCenter; if(textSymbolPtr->style_bounds && textSymbolPtr->style_bounds[i]) { labelCenter.x = (textSymbolPtr->style_bounds[i]->bbox.maxx + textSymbolPtr->style_bounds[i]->bbox.minx)/2; labelCenter.y = (textSymbolPtr->style_bounds[i]->bbox.maxy + textSymbolPtr->style_bounds[i]->bbox.miny)/2; if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map,image,&labelCenter,textSymbolPtr->label->styles[i], textSymbolPtr->scalefactor))) { return MS_FAILURE; } } else { labelCenter.x = (labelpoly_bounds.bbox.maxx + labelpoly_bounds.bbox.minx)/2; labelCenter.y = (labelpoly_bounds.bbox.maxy + labelpoly_bounds.bbox.miny)/2; if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map,image,&labelCenter,textSymbolPtr->label->styles[i], textSymbolPtr->scalefactor))) { return MS_FAILURE; } } } else { msSetError(MS_MISCERR,"Labels only support LABELPNT, LABELPOLY and LABELCENTER GEOMTRANSFORMS", "msDrawLabelCache()"); return MS_FAILURE; } } if(textSymbolPtr->annotext) { if(UNLIKELY(MS_FAILURE == msDrawTextSymbol(map,image,textSymbolPtr->annopoint,textSymbolPtr))) { return MS_FAILURE; } } } } } /* next label(group) from cacheslot */ if(UNLIKELY(MS_FAILURE == msDrawOffsettedLabels(image, map, priority))) { return MS_FAILURE; } } /* next priority */ #ifdef TBDEBUG styleObj tstyle; initStyle(&tstyle); tstyle.width = 1; tstyle.color.alpha = 255; tstyle.color.red = 255; tstyle.color.green = 0; tstyle.color.blue = 0; for(priority=MS_MAX_LABEL_PRIORITY-1; priority>=0; priority--) { labelCacheSlotObj *cacheslot; cacheslot = &(map->labelcache.slots[priority]); for(l=cacheslot->numlabels-1; l>=0; l--) { cachePtr = &(cacheslot->labels[l]); /* point to right spot in the label cache */ /* assert((cachePtr->poly == NULL && cachePtr->status == MS_OFF) || (cachePtr->poly && (cachePtr->status == MS_ON)); */ if(cachePtr->status) { msDrawLineSymbol(map, image, cachePtr->poly, &tstyle, layerPtr->scalefactor); } } } #endif nReturnVal = MS_SUCCESS; /* necessary? */ } } if(map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawMap(): Drawing Label Cache, %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } return nReturnVal; } /** * Generic function to tell the underline device that layer * drawing is stating */ void msImageStartLayer(mapObj *map, layerObj *layer, imageObj *image) { if (image) { if( MS_RENDERER_PLUGIN(image->format) ) { char *approximation_scale = msLayerGetProcessingKey( layer, "APPROXIMATION_SCALE" ); if(approximation_scale) { if(!strncasecmp(approximation_scale,"ROUND",5)) { MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_ROUND; } else if(!strncasecmp(approximation_scale,"FULL",4)) { MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_FULLRESOLUTION; } else if(!strncasecmp(approximation_scale,"SIMPLIFY",8)) { MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_SIMPLIFY; } else { MS_IMAGE_RENDERER(image)->transform_mode = MS_TRANSFORM_SNAPTOGRID; MS_IMAGE_RENDERER(image)->approximation_scale = atof(approximation_scale); } } else { MS_IMAGE_RENDERER(image)->transform_mode = MS_IMAGE_RENDERER(image)->default_transform_mode; MS_IMAGE_RENDERER(image)->approximation_scale = MS_IMAGE_RENDERER(image)->default_approximation_scale; } MS_IMAGE_RENDERER(image)->startLayer(image, map, layer); } else if( MS_RENDERER_IMAGEMAP(image->format) ) msImageStartLayerIM(map, layer, image); } } /** * Generic function to tell the underline device that layer * drawing is ending */ void msImageEndLayer(mapObj *map, layerObj *layer, imageObj *image) { if(image) { if( MS_RENDERER_PLUGIN(image->format) ) { MS_IMAGE_RENDERER(image)->endLayer(image,map,layer); } } } /** * Generic function to tell the underline device that shape * drawing is starting */ void msDrawStartShape(mapObj *map, layerObj *layer, imageObj *image, shapeObj *shape) { if (image) { if(MS_RENDERER_PLUGIN(image->format)) { if (image->format->vtable->startShape) image->format->vtable->startShape(image, shape); } } } /** * Generic function to tell the underline device that shape * drawing is ending */ void msDrawEndShape(mapObj *map, layerObj *layer, imageObj *image, shapeObj *shape) { if(MS_RENDERER_PLUGIN(image->format)) { if (image->format->vtable->endShape) image->format->vtable->endShape(image, shape); } } /** * take the value from the shape and use it to change the * color in the style to match the range map */ int msShapeToRange(styleObj *style, shapeObj *shape) { double fieldVal; char* fieldStr; /*first, get the value of the rangeitem, which should*/ /*evaluate to a double*/ fieldStr = shape->values[style->rangeitemindex]; if (fieldStr == NULL) { /*if there's not value, bail*/ return MS_FAILURE; } fieldVal = 0.0; fieldVal = atof(fieldStr); /*faith that it's ok -- */ /*should switch to strtod*/ return msValueToRange(style, fieldVal, MS_COLORSPACE_RGB); } /** * Allow direct mapping of a value so that mapscript can use the * Ranges. The styls passed in is updated to reflect the right color * based on the fieldVal */ int msValueToRange(styleObj *style, double fieldVal, colorspace cs) { double range; double scaledVal; range = style->maxvalue - style->minvalue; scaledVal = (fieldVal - style->minvalue)/range; if(cs == MS_COLORSPACE_RGB) { /*At this point, we know where on the range we need to be*/ /*However, we don't know how to map it yet, since RGB(A) can */ /*Go up or down*/ style->color.red = (int)(MS_MAX(0,(MS_MIN(255, (style->mincolor.red + ((style->maxcolor.red - style->mincolor.red) * scaledVal)))))); style->color.green = (int)(MS_MAX(0,(MS_MIN(255,(style->mincolor.green + ((style->maxcolor.green - style->mincolor.green) * scaledVal)))))); style->color.blue = (int)(MS_MAX(0,(MS_MIN(255,(style->mincolor.blue + ((style->maxcolor.blue - style->mincolor.blue) * scaledVal)))))); style->color.alpha = (int)(MS_MAX(0,(MS_MIN(255,(style->mincolor.alpha + ((style->maxcolor.alpha - style->mincolor.alpha) * scaledVal)))))); } else { /* HSL */ assert(cs == MS_COLORSPACE_HSL); if(fieldVal <= style->minvalue) style->color = style->mincolor; else if(fieldVal >= style->maxvalue) style->color = style->maxcolor; else { double mh,ms,ml,Mh,Ms,Ml; msRGBtoHSL(&style->mincolor,&mh,&ms,&ml); msRGBtoHSL(&style->maxcolor,&Mh,&Ms,&Ml); mh+=(Mh-mh)*scaledVal; ms+=(Ms-ms)*scaledVal; ml+=(Ml-ml)*scaledVal; msHSLtoRGB(mh,ms,ml,&style->color); style->color.alpha = style->mincolor.alpha + (style->maxcolor.alpha - style->mincolor.alpha)*scaledVal; } } /*( "msMapRange(): %i %i %i", style->color.red , style->color.green, style->color.blue);*/ #if ALPHACOLOR_ENABLED /*NO ALPHA RANGE YET style->color.alpha = style->mincolor.alpha + ((style->maxcolor.alpha - style->mincolor.alpha) * scaledVal);*/ #endif return MS_SUCCESS; } mapserver-7.4.3/mapdrawgdal.c000066400000000000000000002423451357574274700162170ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Code for drawing GDAL raster layers. Called from * msDrawRasterLayerLow() in mapraster.c. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include #include "mapserver.h" #include "mapresample.h" #include "mapthread.h" #include "maptime.h" extern int InvGeoTransform( double *gt_in, double *gt_out ); #define MAXCOLORS 256 #define GEO_TRANS(tr,x,y) ((tr)[0]+(tr)[1]*(x)+(tr)[2]*(y)) #define SKIP_MASK(x,y) (mask_rb && !*(mask_rb->data.rgba.a+(y)*mask_rb->data.rgba.row_step+(x)*mask_rb->data.rgba.pixel_step)) #if defined(USE_GDAL) #include "gdal.h" #include "cpl_string.h" #include "gdal_alg.h" static int LoadGDALImages( GDALDatasetH hDS, int band_numbers[4], int band_count, layerObj *layer, int src_xoff, int src_yoff, int src_xsize, int src_ysize, GByte *pabyBuffer, int dst_xsize, int dst_ysize, int *pbHaveRGBNoData, int *pnNoData1, int *pnNoData2, int *pnNoData3 ); static int msDrawRasterLayerGDAL_RawMode( mapObj *map, layerObj *layer, imageObj *image, GDALDatasetH hDS, int src_xoff, int src_yoff, int src_xsize, int src_ysize, int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize ); static int msDrawRasterLayerGDAL_16BitClassification( mapObj *map, layerObj *layer, rasterBufferObj *rb, GDALDatasetH hDS, GDALRasterBandH hBand, int src_xoff, int src_yoff, int src_xsize, int src_ysize, int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize ); /* * rasterBufferObj setting macros. */ /************************************************************************/ /* msDrawRasterLayerGDAL() */ /************************************************************************/ int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void *hDSVoid ) { int i,j, k; /* loop counters */ int cmap[MAXCOLORS]; #ifndef NDEBUG int cmap_set = FALSE; #endif unsigned char rb_cmap[4][MAXCOLORS]; double adfGeoTransform[6], adfInvGeoTransform[6]; int dst_xoff, dst_yoff, dst_xsize, dst_ysize; int src_xoff, src_yoff, src_xsize, src_ysize; double llx, lly, urx, ury; rectObj copyRect, mapRect; unsigned char *pabyRaw1=NULL, *pabyRaw2=NULL, *pabyRaw3=NULL, *pabyRawAlpha = NULL; int classified = FALSE; int red_band=0, green_band=0, blue_band=0, alpha_band=0; int band_count, band_numbers[4]; GDALDatasetH hDS = hDSVoid; GDALColorTableH hColorMap=NULL; GDALRasterBandH hBand1=NULL, hBand2=NULL, hBand3=NULL, hBandAlpha=NULL; int bHaveRGBNoData = FALSE; int nNoData1=-1,nNoData2=-1,nNoData3=-1; rasterBufferObj *mask_rb = NULL; rasterBufferObj s_mask_rb; if(layer->mask) { int ret; layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask)); mask_rb = &s_mask_rb; memset(mask_rb, 0, sizeof(s_mask_rb)); ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb); if(ret != MS_SUCCESS) return -1; } /*only support rawdata and pluggable renderers*/ assert(MS_RENDERER_RAWDATA(image->format) || (MS_RENDERER_PLUGIN(image->format) && rb)); memset( cmap, 0xff, MAXCOLORS * sizeof(int) ); memset( rb_cmap, 0, sizeof(rb_cmap) ); /* -------------------------------------------------------------------- */ /* Test the image format instead of the map format. */ /* Normally the map format and the image format should be the */ /* same but In somes cases like swf and pdf support, a temporary */ /* GD image object is created and used to render raster layers */ /* and then dumped into the SWF or the PDF file. */ /* -------------------------------------------------------------------- */ src_xsize = GDALGetRasterXSize( hDS ); src_ysize = GDALGetRasterYSize( hDS ); /* * If the RAW_WINDOW attribute is set, use that to establish what to * load. This is normally just set by the mapresample.c module to avoid * problems with rotated maps. */ if( CSLFetchNameValue( layer->processing, "RAW_WINDOW" ) != NULL ) { char **papszTokens = CSLTokenizeString( CSLFetchNameValue( layer->processing, "RAW_WINDOW" ) ); if( layer->debug ) msDebug( "msDrawGDAL(%s): using RAW_WINDOW=%s, dst=0,0,%d,%d\n", layer->name, CSLFetchNameValue( layer->processing, "RAW_WINDOW" ), image->width, image->height ); if( CSLCount(papszTokens) != 4 ) { CSLDestroy( papszTokens ); msSetError( MS_IMGERR, "RAW_WINDOW PROCESSING directive corrupt.", "msDrawGDAL()" ); return -1; } src_xoff = atoi(papszTokens[0]); src_yoff = atoi(papszTokens[1]); src_xsize = atoi(papszTokens[2]); src_ysize = atoi(papszTokens[3]); dst_xoff = 0; dst_yoff = 0; dst_xsize = image->width; dst_ysize = image->height; CSLDestroy( papszTokens ); } /* * Compute the georeferenced window of overlap, and do nothing if there * is no overlap between the map extents, and the file we are operating on. */ else if( layer->transform ) { int dst_lrx, dst_lry; if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): Entering transform.\n" ); msGetGDALGeoTransform( hDS, map, layer, adfGeoTransform ); InvGeoTransform( adfGeoTransform, adfInvGeoTransform ); mapRect = map->extent; mapRect.minx -= map->cellsize*0.5; mapRect.maxx += map->cellsize*0.5; mapRect.miny -= map->cellsize*0.5; mapRect.maxy += map->cellsize*0.5; copyRect = mapRect; if( copyRect.minx < GEO_TRANS(adfGeoTransform,0,src_ysize) ) copyRect.minx = GEO_TRANS(adfGeoTransform,0,src_ysize); if( copyRect.maxx > GEO_TRANS(adfGeoTransform,src_xsize,0) ) copyRect.maxx = GEO_TRANS(adfGeoTransform,src_xsize,0); if( copyRect.miny < GEO_TRANS(adfGeoTransform+3,0,src_ysize) ) copyRect.miny = GEO_TRANS(adfGeoTransform+3,0,src_ysize); if( copyRect.maxy > GEO_TRANS(adfGeoTransform+3,src_xsize,0) ) copyRect.maxy = GEO_TRANS(adfGeoTransform+3,src_xsize,0); if( copyRect.minx >= copyRect.maxx || copyRect.miny >= copyRect.maxy ) { if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): Error in overlap calculation.\n" ); return 0; } /* * Copy the source and destination raster coordinates. */ llx = GEO_TRANS(adfInvGeoTransform+0,copyRect.minx,copyRect.miny); lly = GEO_TRANS(adfInvGeoTransform+3,copyRect.minx,copyRect.miny); urx = GEO_TRANS(adfInvGeoTransform+0,copyRect.maxx,copyRect.maxy); ury = GEO_TRANS(adfInvGeoTransform+3,copyRect.maxx,copyRect.maxy); src_xoff = MS_MAX(0,(int) floor(llx+0.5)); src_yoff = MS_MAX(0,(int) floor(ury+0.5)); src_xsize = MS_MIN(MS_MAX(0,(int) (urx - llx + 0.5)), GDALGetRasterXSize(hDS) - src_xoff); src_ysize = MS_MIN(MS_MAX(0,(int) (lly - ury + 0.5)), GDALGetRasterYSize(hDS) - src_yoff); /* We want very small windows to use at least one source pixel (#4172) */ if( src_xsize == 0 && (urx - llx) > 0.0 ) { src_xsize = 1; src_xoff = MS_MIN(src_xoff,GDALGetRasterXSize(hDS)-1); } if( src_ysize == 0 && (lly - ury) > 0.0 ) { src_ysize = 1; src_yoff = MS_MIN(src_yoff,GDALGetRasterYSize(hDS)-1); } if( src_xsize == 0 || src_ysize == 0 ) { if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): no apparent overlap between map view and this window(1).\n" ); return 0; } if (map->cellsize == 0) { if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): Cellsize can't be 0.\n" ); return 0; } dst_xoff = (int) ((copyRect.minx - mapRect.minx) / map->cellsize); dst_yoff = (int) ((mapRect.maxy - copyRect.maxy) / map->cellsize); dst_lrx = (int) ((copyRect.maxx - mapRect.minx) / map->cellsize + 0.5); dst_lry = (int) ((mapRect.maxy - copyRect.miny) / map->cellsize + 0.5); dst_lrx = MS_MAX(0,MS_MIN(image->width,dst_lrx)); dst_lry = MS_MAX(0,MS_MIN(image->height,dst_lry)); dst_xsize = MS_MAX(0,MS_MIN(image->width,dst_lrx - dst_xoff)); dst_ysize = MS_MAX(0,MS_MIN(image->height,dst_lry - dst_yoff)); if( dst_xsize == 0 || dst_ysize == 0 ) { if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): no apparent overlap between map view and this window(2).\n" ); return 0; } if( layer->debug ) msDebug( "msDrawRasterLayerGDAL(): src=%d,%d,%d,%d, dst=%d,%d,%d,%d\n", src_xoff, src_yoff, src_xsize, src_ysize, dst_xoff, dst_yoff, dst_xsize, dst_ysize ); #ifndef notdef if( layer->debug ) { double d_src_xoff, d_src_yoff, geo_x, geo_y; geo_x = mapRect.minx + dst_xoff * map->cellsize; geo_y = mapRect.maxy - dst_yoff * map->cellsize; d_src_xoff = (geo_x - adfGeoTransform[0]) / adfGeoTransform[1]; d_src_yoff = (geo_y - adfGeoTransform[3]) / adfGeoTransform[5]; msDebug( "msDrawRasterLayerGDAL(): source raster PL (%.3f,%.3f) for dst PL (%d,%d).\n", d_src_xoff, d_src_yoff, dst_xoff, dst_yoff ); } #endif } /* * If layer transforms are turned off, just map 1:1. */ else { dst_xoff = src_xoff = 0; dst_yoff = src_yoff = 0; dst_xsize = src_xsize = MS_MIN(image->width,src_xsize); dst_ysize = src_ysize = MS_MIN(image->height,src_ysize); } /* * In RAWDATA mode we don't fool with colors. Do the raw processing, * and return from the function early. */ if( MS_RENDERER_RAWDATA( image->format ) ) { return msDrawRasterLayerGDAL_RawMode( map, layer, image, hDS, src_xoff, src_yoff, src_xsize, src_ysize, dst_xoff, dst_yoff, dst_xsize, dst_ysize ); } /* * Is this image classified? We consider it classified if there are * classes with an expression string *or* a color range. We don't want * to treat the raster as classified if there is just a bogus class here * to force inclusion in the legend. */ for( i = 0; i < layer->numclasses; i++ ) { int s; /* change colour based on colour range? */ for(s=0; sclass[i]->numstyles; s++) { if( MS_VALID_COLOR(layer->class[i]->styles[s]->mincolor) && MS_VALID_COLOR(layer->class[i]->styles[s]->maxcolor) ) { classified = TRUE; break; } } if( layer->class[i]->expression.string != NULL ) { classified = TRUE; break; } } /* * Set up the band selection. We look for a BANDS directive in the * the PROCESSING options. If not found we default to grey=1, grey=1,alpha=2, * red=1,green=2,blue=3 or red=1,green=2,blue=3,alpha>=4. */ if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) { const int gdal_band_count = GDALGetRasterCount( hDS ); red_band = 1; if( gdal_band_count >= 4 ) { /* The alpha band is not necessarily the 4th one */ for( i = 4; i <= gdal_band_count; i ++ ) { if( GDALGetRasterColorInterpretation( GDALGetRasterBand( hDS, i ) ) == GCI_AlphaBand ) { alpha_band = i; break; } } } if( gdal_band_count >= 3 ) { green_band = 2; blue_band = 3; } if( gdal_band_count == 2 && GDALGetRasterColorInterpretation( GDALGetRasterBand( hDS, 2 ) ) == GCI_AlphaBand ) alpha_band = 2; hBand1 = GDALGetRasterBand( hDS, red_band ); if( classified || GDALGetRasterColorTable( hBand1 ) != NULL ) { alpha_band = 0; green_band = 0; blue_band = 0; } } else { int *band_list; band_list = msGetGDALBandList( layer, hDS, 4, &band_count ); if( band_list == NULL ) return -1; if( band_count > 0 ) red_band = band_list[0]; else red_band = 0; if( band_count > 2 ) { green_band = band_list[1]; blue_band = band_list[2]; } else { green_band = 0; blue_band = 0; } if( band_count > 3 ) alpha_band = band_list[3]; else alpha_band = 0; free( band_list ); } band_numbers[0] = red_band; band_numbers[1] = green_band; band_numbers[2] = blue_band; band_numbers[3] = 0; if( blue_band != 0 && alpha_band != 0 ) { band_numbers[3] = alpha_band; band_count = 4; } else if( blue_band != 0 && alpha_band == 0 ) band_count = 3; else if( alpha_band != 0 ) { band_numbers[1] = alpha_band; band_count = 2; } else band_count = 1; if( layer->debug > 1 || (layer->debug > 0 && green_band != 0) ) { msDebug( "msDrawRasterLayerGDAL(): red,green,blue,alpha bands = %d,%d,%d,%d\n", red_band, green_band, blue_band, alpha_band ); } /* * Get band handles for PC256, RGB or RGBA cases. */ hBand1 = GDALGetRasterBand( hDS, red_band ); if( hBand1 == NULL ) return -1; hBand2 = hBand3 = hBandAlpha = NULL; if( green_band != 0 ) { hBand1 = GDALGetRasterBand( hDS, red_band ); hBand2 = GDALGetRasterBand( hDS, green_band ); hBand3 = GDALGetRasterBand( hDS, blue_band ); if( hBand1 == NULL || hBand2 == NULL || hBand3 == NULL ) return -1; } if( alpha_band != 0 ) hBandAlpha = GDALGetRasterBand( hDS, alpha_band ); /* * The logic for a classification rendering of non-8bit raster bands * is sufficiently different than the normal mechanism of loading * into an 8bit buffer, that we isolate it into it's own subfunction. */ if( classified && hBand1 != NULL && GDALGetRasterDataType( hBand1 ) != GDT_Byte ) { return msDrawRasterLayerGDAL_16BitClassification( map, layer, rb, hDS, hBand1, src_xoff, src_yoff, src_xsize, src_ysize, dst_xoff, dst_yoff, dst_xsize, dst_ysize ); } /* * Get colormap for this image. If there isn't one, and we have only * one band create a greyscale colormap. */ if( hBand2 != NULL ) hColorMap = NULL; else { hColorMap = GDALGetRasterColorTable( hBand1 ); if( hColorMap != NULL ) hColorMap = GDALCloneColorTable( hColorMap ); else if( hBand2 == NULL ) { hColorMap = GDALCreateColorTable( GPI_RGB ); for( i = 0; i < 256; i++ ) { colorObj pixel; GDALColorEntry sEntry; pixel.red = i; pixel.green = i; pixel.blue = i; if(MS_COMPARE_COLORS(pixel, layer->offsite)) { sEntry.c1 = 0; sEntry.c2 = 0; sEntry.c3 = 0; sEntry.c4 = 0; /* alpha set to zero */ } else { sEntry.c1 = i; sEntry.c2 = i; sEntry.c3 = i; sEntry.c4 = 255; } GDALSetColorEntry( hColorMap, i, &sEntry ); } } /* ** If we have a known NODATA value, mark it now as transparent. */ { int bGotNoData; double dfNoDataValue = msGetGDALNoDataValue( layer, hBand1, &bGotNoData); if( bGotNoData && dfNoDataValue >= 0 && dfNoDataValue < GDALGetColorEntryCount( hColorMap ) ) { GDALColorEntry sEntry; memcpy( &sEntry, GDALGetColorEntry( hColorMap, (int) dfNoDataValue ), sizeof(GDALColorEntry) ); sEntry.c4 = 0; GDALSetColorEntry( hColorMap, (int) dfNoDataValue, &sEntry ); } } } /* * Setup the mapping between source eight bit pixel values, and the * output images color table. There are two general cases, where the * class colors are provided by the MAP file, or where we use the native * color table. */ if( classified ) { int c, color_count; const char* pszRangeColorspace = msLayerGetProcessingKey( layer, "RANGE_COLORSPACE" ); colorspace iRangeColorspace; #ifndef NDEBUG cmap_set = TRUE; #endif if( hColorMap == NULL ) { msSetError(MS_IOERR, "Attempt to classify 24bit image, this is unsupported.", "drawGDAL()"); return -1; } if(!pszRangeColorspace || !strcasecmp(pszRangeColorspace, "RGB")) { iRangeColorspace = MS_COLORSPACE_RGB; } else if(!strcasecmp(pszRangeColorspace, "HSL")) { iRangeColorspace = MS_COLORSPACE_HSL; } else { msSetError(MS_MISCERR, "Unknown RANGE_COLORSPACE \"%s\", expecting RGB or HSL", "drawGDAL()", pszRangeColorspace); GDALDestroyColorTable( hColorMap ); return -1; } color_count = MS_MIN(256,GDALGetColorEntryCount(hColorMap)); for(i=0; i < color_count; i++) { colorObj pixel; int colormap_index; GDALColorEntry sEntry; GDALGetColorEntryAsRGB( hColorMap, i, &sEntry ); pixel.red = sEntry.c1; pixel.green = sEntry.c2; pixel.blue = sEntry.c3; colormap_index = i; if(!MS_COMPARE_COLORS(pixel, layer->offsite)) { c = msGetClass(layer, &pixel, colormap_index); if(c != -1) { /* belongs to any class */ int s; /* change colour based on colour range? Currently we only address the greyscale case properly. */ if( MS_VALID_COLOR(layer->class[c]->styles[0]->mincolor) ) { for(s=0; sclass[c]->numstyles; s++) { if( MS_VALID_COLOR(layer->class[c]->styles[s]->mincolor) && MS_VALID_COLOR(layer->class[c]->styles[s]->maxcolor)) { if( layer->class[c]->numstyles == 1 || (sEntry.c1 >= layer->class[c]->styles[s]->minvalue && sEntry.c1 <= layer->class[c]->styles[s]->maxvalue )) { msValueToRange(layer->class[c]->styles[s], sEntry.c1, iRangeColorspace); if(MS_VALID_COLOR(layer->class[c]->styles[s]->color)) { rb_cmap[0][i] = layer->class[c]->styles[s]->color.red; rb_cmap[1][i] = layer->class[c]->styles[s]->color.green; rb_cmap[2][i] = layer->class[c]->styles[s]->color.blue; rb_cmap[3][i] = (layer->class[c]->styles[s]->color.alpha != 255)?(layer->class[c]->styles[s]->color.alpha):(255*layer->class[c]->styles[0]->opacity / 100); break; } } } } } else if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color)) /* leave it transparent */; else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { rb_cmap[0][i] = layer->class[c]->styles[0]->color.red; rb_cmap[1][i] = layer->class[c]->styles[0]->color.green; rb_cmap[2][i] = layer->class[c]->styles[0]->color.blue; rb_cmap[3][i] = (255*layer->class[c]->styles[0]->opacity / 100); } else { /* Use raster color */ rb_cmap[0][i] = pixel.red; rb_cmap[1][i] = pixel.green; rb_cmap[2][i] = pixel.blue; rb_cmap[3][i] = 255; } } } } } else if( hBand2 == NULL && hColorMap != NULL && rb->type == MS_BUFFER_BYTE_RGBA ) { int color_count; #ifndef NDEBUG cmap_set = TRUE; #endif color_count = MS_MIN(256,GDALGetColorEntryCount(hColorMap)); for(i=0; i < color_count; i++) { GDALColorEntry sEntry; GDALGetColorEntryAsRGB( hColorMap, i, &sEntry ); if( sEntry.c4 != 0 && (!MS_VALID_COLOR( layer->offsite ) || layer->offsite.red != sEntry.c1 || layer->offsite.green != sEntry.c2 || layer->offsite.blue != sEntry.c3 ) ) { rb_cmap[0][i] = sEntry.c1; rb_cmap[1][i] = sEntry.c2; rb_cmap[2][i] = sEntry.c3; rb_cmap[3][i] = sEntry.c4; } } } /* * Allocate imagery buffers. */ pabyRaw1 = (unsigned char *) malloc(dst_xsize * dst_ysize * band_count); if( pabyRaw1 == NULL ) { msSetError(MS_MEMERR, "Allocating work image of size %dx%dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count ); if( hColorMap != NULL ) GDALDestroyColorTable( hColorMap ); return -1; } if( hBand2 != NULL && hBand3 != NULL ) { pabyRaw2 = pabyRaw1 + dst_xsize * dst_ysize * 1; pabyRaw3 = pabyRaw1 + dst_xsize * dst_ysize * 2; } if( hBandAlpha != NULL ) { if( hBand2 != NULL ) pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 3; else pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 1; } /* * Load image data into buffers with scaling, etc. */ if( LoadGDALImages( hDS, band_numbers, band_count, layer, src_xoff, src_yoff, src_xsize, src_ysize, pabyRaw1, dst_xsize, dst_ysize, &bHaveRGBNoData, &nNoData1, &nNoData2, &nNoData3 ) == -1 ) { free( pabyRaw1 ); if( hColorMap != NULL ) GDALDestroyColorTable( hColorMap ); return -1; } if( bHaveRGBNoData && layer->debug ) msDebug( "msDrawGDAL(): using RGB nodata values from GDAL dataset.\n" ); /* -------------------------------------------------------------------- */ /* If there was no alpha band, but we have a dataset level mask */ /* load it as massage it so it will function as our alpha for */ /* transparency purposes. */ /* -------------------------------------------------------------------- */ if( hBandAlpha == NULL ) { int nMaskFlags = GDALGetMaskFlags(hBand1); if( (CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) && (nMaskFlags & GMF_PER_DATASET) != 0 && (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 ) { CPLErr eErr; unsigned char * pabyOrig = pabyRaw1; if( layer->debug ) msDebug( "msDrawGDAL(): using GDAL mask band for alpha.\n" ); band_count++; pabyRaw1 = (unsigned char *) realloc(pabyOrig,dst_xsize * dst_ysize * band_count); if( pabyRaw1 == NULL ) { msSetError(MS_MEMERR, "Allocating work image of size %dx%dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count ); free(pabyOrig); if( hColorMap != NULL ) GDALDestroyColorTable( hColorMap ); return -1; } if( hBand2 != NULL ) { pabyRaw2 = pabyRaw1 + dst_xsize * dst_ysize * 1; pabyRaw3 = pabyRaw1 + dst_xsize * dst_ysize * 2; pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 3; } else { pabyRawAlpha = pabyRaw1 + dst_xsize * dst_ysize * 1; } hBandAlpha = GDALGetMaskBand(hBand1); eErr = GDALRasterIO( hBandAlpha, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pabyRawAlpha, dst_xsize, dst_ysize, GDT_Byte, 0,0); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALRasterIO() failed: %s", "drawGDAL()", CPLGetLastErrorMsg() ); free( pabyRaw1 ); if( hColorMap != NULL ) GDALDestroyColorTable( hColorMap ); return -1; } /* In case the mask is not an alpha channel, expand values of 1 to 255, */ /* so we can deal as it was an alpha band afterwards */ if ((nMaskFlags & GMF_ALPHA) == 0) { for(i=0; itype == MS_BUFFER_BYTE_RGBA && hBandAlpha != NULL ) { assert( cmap_set ); k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int src_pixel, src_alpha, cmap_alpha, merged_alpha; if(SKIP_MASK(j,i)) { k++; continue; } src_pixel = pabyRaw1[k]; src_alpha = pabyRawAlpha[k]; cmap_alpha = rb_cmap[3][src_pixel]; merged_alpha = (src_alpha * cmap_alpha) / 255; if( merged_alpha < 2 ) /* do nothing - transparent */; else if( merged_alpha > 253 ) { RB_SET_PIXEL( rb, j, i, rb_cmap[0][src_pixel], rb_cmap[1][src_pixel], rb_cmap[2][src_pixel], cmap_alpha ); } else { RB_MIX_PIXEL( rb, j, i, rb_cmap[0][src_pixel], rb_cmap[1][src_pixel], rb_cmap[2][src_pixel], merged_alpha ); } k++; } } } /* -------------------------------------------------------------------- */ /* Single band plus colormap (no alpha) to truecolor (RB) */ /* -------------------------------------------------------------------- */ else if( hBand2 == NULL && rb->type == MS_BUFFER_BYTE_RGBA ) { assert( cmap_set ); k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int src_pixel = pabyRaw1[k++]; if(SKIP_MASK(j,i)) { continue; } if( rb_cmap[3][src_pixel] > 253 ) { RB_SET_PIXEL( rb, j, i, rb_cmap[0][src_pixel], rb_cmap[1][src_pixel], rb_cmap[2][src_pixel], rb_cmap[3][src_pixel] ); } else if( rb_cmap[3][src_pixel] > 1 ) { RB_MIX_PIXEL( rb, j, i, rb_cmap[0][src_pixel], rb_cmap[1][src_pixel], rb_cmap[2][src_pixel], rb_cmap[3][src_pixel] ); } } } } /* -------------------------------------------------------------------- */ /* Input is 3 band RGB. Alpha blending is mixed into the loop */ /* since this case is less commonly used and has lots of other */ /* overhead. (RB) */ /* -------------------------------------------------------------------- */ else if( hBand3 != NULL && rb->type == MS_BUFFER_BYTE_RGBA ) { k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++, k++ ) { if(SKIP_MASK(j,i)) { continue; } if( MS_VALID_COLOR( layer->offsite ) && pabyRaw1[k] == layer->offsite.red && pabyRaw2[k] == layer->offsite.green && pabyRaw3[k] == layer->offsite.blue ) continue; if( bHaveRGBNoData && pabyRaw1[k] == nNoData1 && pabyRaw2[k] == nNoData2 && pabyRaw3[k] == nNoData3 ) continue; if( pabyRawAlpha == NULL || pabyRawAlpha[k] == 255 ) { RB_SET_PIXEL( rb, j, i, pabyRaw1[k], pabyRaw2[k], pabyRaw3[k], 255 ); } else if( pabyRawAlpha[k] != 0 ) { RB_MIX_PIXEL( rb, j, i, pabyRaw1[k], pabyRaw2[k], pabyRaw3[k], pabyRawAlpha[k] ); } } } } /* ** Cleanup */ free( pabyRaw1 ); if( hColorMap != NULL ) GDALDestroyColorTable( hColorMap ); return 0; } /************************************************************************/ /* ParseDefaultLUT() */ /************************************************************************/ static int ParseDefaultLUT( const char *lut_def, GByte *lut, int nMaxValIn ) { const char *lut_read; int last_in=0, last_out=0, all_done=FALSE; /* -------------------------------------------------------------------- */ /* Parse definition, applying to lut on the fly. */ /* -------------------------------------------------------------------- */ lut_read = lut_def; while( !all_done ) { int this_in=0, this_out=0; int lut_i; while( isspace(*lut_read) ) lut_read++; /* if we are at end, assume nMaxValIn:255 */ if( *lut_read == '\0' ) { all_done = TRUE; if ( last_in != nMaxValIn ) { this_in = nMaxValIn; this_out = 255; } } /* otherwise read "in:out", and skip past */ else { this_in = atoi(lut_read); while( *lut_read != ':' && *lut_read ) lut_read++; if( *lut_read == ':' ) lut_read++; while( isspace(*lut_read) ) lut_read++; this_out = atoi(lut_read); while( *lut_read && *lut_read != ',' && *lut_read != '\n' ) lut_read++; if( *lut_read == ',' || *lut_read == '\n' ) lut_read++; while( isspace(*lut_read) ) lut_read++; } this_in = MS_MAX(0,MS_MIN(nMaxValIn,this_in)); this_out = MS_MAX(0,MS_MIN(255,this_out)); /* apply linear values from last in:out to this in:out */ for( lut_i = last_in; lut_i <= this_in; lut_i++ ) { double ratio; if( last_in == this_in ) ratio = 1.0; else ratio = (lut_i - last_in) / (double) (this_in - last_in); lut[lut_i] = (int) floor(((1.0 - ratio)*last_out + ratio*this_out) + 0.5); } last_in = this_in; last_out = this_out; } return 0; } /************************************************************************/ /* LutFromGimpLine() */ /************************************************************************/ static int LutFromGimpLine( char *lut_line, GByte *lut ) { char wrkLUTDef[1000]; int i, count = 0; char **tokens; /* cleanup white space at end of line (DOS LF, etc) */ i = strlen(lut_line) - 1; while( i > 0 && isspace(lut_line[i]) ) lut_line[i--] = '\0'; while( *lut_line == 10 || *lut_line == 13 ) lut_line++; /* tokenize line */ tokens = CSLTokenizeString( lut_line ); if( CSLCount(tokens) != 17 * 2 ) { CSLDestroy( tokens ); msSetError(MS_MISCERR, "GIMP curve file appears corrupt.", "LutFromGimpLine()" ); return -1; } /* Convert to our own format */ wrkLUTDef[0] = '\0'; for( i = 0; i < 17; i++ ) { if( atoi(tokens[i*2]) >= 0 ) { if( count++ > 0 ) strlcat( wrkLUTDef, ",", sizeof(wrkLUTDef)); snprintf( wrkLUTDef + strlen(wrkLUTDef), sizeof(wrkLUTDef)-strlen(wrkLUTDef), "%s:%s", tokens[i*2], tokens[i*2+1] ); } } CSLDestroy( tokens ); return ParseDefaultLUT( wrkLUTDef, lut, 255 ); } /************************************************************************/ /* ParseGimpLUT() */ /* */ /* Parse a Gimp style LUT. */ /************************************************************************/ static int ParseGimpLUT( const char *lut_def, GByte *lut, int iColorIndex ) { int i; GByte lutValue[256]; GByte lutColorBand[256]; char **lines = CSLTokenizeStringComplex( lut_def, "\n", FALSE, FALSE ); if( !EQUALN(lines[0],"# GIMP Curves File",18) || CSLCount(lines) < 6 ) { msSetError(MS_MISCERR, "GIMP curve file appears corrupt.", "ParseGimpLUT()" ); CSLDestroy( lines ); return -1; } /* * Convert the overall curve, and the color band specific curve into LUTs. */ if( LutFromGimpLine( lines[1], lutValue ) != 0 || LutFromGimpLine( lines[iColorIndex + 1], lutColorBand ) != 0 ) { CSLDestroy( lines ); return -1; } CSLDestroy( lines ); /* * Compose the two luts as if the raw value passed through the color band * specific lut, and then the general value lut. Usually one or the * other will be the identity mapping, but not always. */ for( i = 0; i < 256; i++ ) { lut[i] = lutValue[lutColorBand[i]]; } return 0; } /************************************************************************/ /* LoadLUT() */ /* */ /* Load a LUT according to RFC 21. */ /************************************************************************/ static int LoadLUT( layerObj *layer, int iColorIndex, char** ppszLutDef ) { const char *lut_def; char key[20], lut_def_fromfile[2500]; *ppszLutDef = NULL; /* -------------------------------------------------------------------- */ /* Get lut specifier from processing directives. Do nothing if */ /* none are found. */ /* -------------------------------------------------------------------- */ sprintf( key, "LUT_%d", iColorIndex ); lut_def = msLayerGetProcessingKey( layer, key ); if( lut_def == NULL ) lut_def = msLayerGetProcessingKey( layer, "LUT" ); if( lut_def == NULL ) return 0; /* -------------------------------------------------------------------- */ /* Does this look like a file? If so, read it into memory. */ /* -------------------------------------------------------------------- */ if( strspn(lut_def,"0123456789:, ") != strlen(lut_def) ) { FILE *fp; char path[MS_MAXPATHLEN]; int len; msBuildPath(path, layer->map->mappath, lut_def); fp = fopen( path, "rb" ); if( fp == NULL ) { msSetError(MS_IOERR, "Failed to open LUT file '%s'.", "drawGDAL()", path ); return -1; } len = fread( lut_def_fromfile, 1, sizeof(lut_def_fromfile), fp ); fclose( fp ); if( len == sizeof(lut_def_fromfile) ) { msSetError(MS_IOERR, "LUT definition from file %s longer than maximum buffer size (%d bytes).", "drawGDAL()", path, (int)sizeof(lut_def_fromfile) ); return -1; } lut_def_fromfile[len] = '\0'; lut_def = lut_def_fromfile; } *ppszLutDef = msStrdup(lut_def); return 0; } /************************************************************************/ /* FreeLUTs() */ /************************************************************************/ static void FreeLUTs(char** apszLUTs) { int i; for( i = 0; i < 4; i++ ) msFree(apszLUTs[i]); msFree(apszLUTs); } /************************************************************************/ /* LoadLUTs() */ /* */ /* Return an array of 4 strings (some possibly NULL) with loaded LUTs */ /* or NULL in case of failure. */ /************************************************************************/ static char** LoadLUTs(layerObj *layer, int band_count) { int i; char** apszLUTs; assert(band_count <= 4); apszLUTs = (char**) msSmallCalloc( 4, sizeof(char*) ); for( i = 0; i < band_count; i++ ) { if( LoadLUT( layer, i+1, &apszLUTs[i] ) != 0 ) { FreeLUTs(apszLUTs); return NULL; } } return apszLUTs; } /************************************************************************/ /* GetDataTypeAppropriateForLUTS() */ /* */ /* This does a quick examination of the LUT strings to determine */ /* if they have input values > 255, in which case the raster data */ /* must be queries on 16-bits. */ /************************************************************************/ static GDALDataType GetDataTypeAppropriateForLUTS(char** apszLUTs) { GDALDataType eDT = GDT_Byte; int i; for( i = 0; i < 4; i++ ) { const char* pszLastTuple; int nLastInValue; if( apszLUTs[i] == NULL ) continue; if( EQUALN(apszLUTs[i],"# GIMP",6) ) continue; /* Find last in:out tuple in string */ pszLastTuple = strrchr( apszLUTs[i], ',' ); if( pszLastTuple == NULL ) pszLastTuple = apszLUTs[i]; else pszLastTuple ++; while( *pszLastTuple == ' ' ) pszLastTuple ++; nLastInValue = atoi(pszLastTuple); if( nLastInValue > 255 ) { eDT = GDT_UInt16; break; } } return eDT; } /************************************************************************/ /* ApplyLUT() */ /************************************************************************/ static int ApplyLUT( int iColorIndex, const char* lut_def, const void* pInBuffer, GDALDataType eDT, GByte* pabyOutBuffer, int nPixelCount ) { int i, err; GByte byteLut[256]; GByte* uint16Lut = NULL; assert( eDT == GDT_Byte || eDT == GDT_UInt16 ); if( lut_def == NULL ) { if( pInBuffer != pabyOutBuffer ) { GDALCopyWords( (void*)pInBuffer, eDT, GDALGetDataTypeSize(eDT) / 8, pabyOutBuffer, GDT_Byte, 1, nPixelCount ); } return 0; } /* -------------------------------------------------------------------- */ /* Parse the LUT description. */ /* -------------------------------------------------------------------- */ if( EQUALN(lut_def,"# GIMP",6) ) { if( eDT != GDT_Byte ) { msSetError(MS_MISCERR, "Cannot apply a GIMP LUT on a 16-bit buffer", "ApplyLUT()"); return -1; } err = ParseGimpLUT( lut_def, byteLut, iColorIndex ); } else { if( eDT == GDT_Byte ) err = ParseDefaultLUT( lut_def, byteLut, 255 ); else { uint16Lut = (GByte*) malloc( 65536 ); if( uint16Lut == NULL ) { msSetError(MS_MEMERR, "Cannot allocate 16-bit LUT", "ApplyLUT()" ); return -1; } err = ParseDefaultLUT( lut_def, uint16Lut, 65535 ); } } /* -------------------------------------------------------------------- */ /* Apply LUT. */ /* -------------------------------------------------------------------- */ if( eDT == GDT_Byte ) { for( i = 0; i < nPixelCount; i++ ) pabyOutBuffer[i] = byteLut[((GByte*)pInBuffer)[i]]; } else { for( i = 0; i < nPixelCount; i++ ) pabyOutBuffer[i] = uint16Lut[((GUInt16*)pInBuffer)[i]]; free(uint16Lut); } return err; } /************************************************************************/ /* LoadGDALImages() */ /* */ /* This call will load and process 1-4 bands of input for the */ /* selected rectangle, loading the result into the passed 8bit */ /* buffer. The processing options include scaling. */ /************************************************************************/ static int LoadGDALImages( GDALDatasetH hDS, int band_numbers[4], int band_count, layerObj *layer, int src_xoff, int src_yoff, int src_xsize, int src_ysize, GByte *pabyWholeBuffer, int dst_xsize, int dst_ysize, int *pbHaveRGBNoData, int *pnNoData1, int *pnNoData2, int *pnNoData3 ) { int iColorIndex, result_code=0; CPLErr eErr; float *pafWholeRawData; char** papszLUTs; /* -------------------------------------------------------------------- */ /* If we have no alpha band, but we do have three input */ /* bands, then check for nodata values. If we only have one */ /* input band, then nodata will already have been adderssed as */ /* part of the real or manufactured color table. */ /* -------------------------------------------------------------------- */ if( band_count == 3 ) { *pnNoData1 = (int) msGetGDALNoDataValue( layer, GDALGetRasterBand(hDS,band_numbers[0]), pbHaveRGBNoData); if( *pbHaveRGBNoData ) *pnNoData2 = (int) msGetGDALNoDataValue( layer, GDALGetRasterBand(hDS,band_numbers[1]), pbHaveRGBNoData); if( *pbHaveRGBNoData ) *pnNoData3 = (int) msGetGDALNoDataValue( layer, GDALGetRasterBand(hDS,band_numbers[2]), pbHaveRGBNoData); } /* -------------------------------------------------------------------- */ /* Are we doing a simple, non-scaling case? If so, read directly */ /* and return. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( layer->processing, "SCALE" ) == NULL && CSLFetchNameValue( layer->processing, "SCALE_1" ) == NULL && CSLFetchNameValue( layer->processing, "SCALE_2" ) == NULL && CSLFetchNameValue( layer->processing, "SCALE_3" ) == NULL && CSLFetchNameValue( layer->processing, "SCALE_4" ) == NULL ) { GDALDataType eDT; GUInt16* panBuffer = NULL; void* pBuffer; papszLUTs = LoadLUTs(layer, band_count); if( papszLUTs == NULL ) { return -1; } eDT = GetDataTypeAppropriateForLUTS(papszLUTs); if( eDT == GDT_UInt16 ) { panBuffer = (GUInt16 *) malloc(sizeof(GUInt16) * dst_xsize * dst_ysize * band_count ); if( panBuffer == NULL ) { msSetError(MS_MEMERR, "Allocating work uint16 image of size %dx%dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count ); FreeLUTs(papszLUTs); return -1; } pBuffer = panBuffer; } else pBuffer = pabyWholeBuffer; eErr = GDALDatasetRasterIO( hDS, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pBuffer, dst_xsize, dst_ysize, eDT, band_count, band_numbers, 0,0,0); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALDatasetRasterIO() failed: %s", "drawGDAL()", CPLGetLastErrorMsg() ); FreeLUTs(papszLUTs); msFree(panBuffer); return -1; } for( iColorIndex = 0; iColorIndex < band_count && result_code == 0; iColorIndex++ ) { result_code = ApplyLUT( iColorIndex+1, papszLUTs[iColorIndex], (GByte*)pBuffer + dst_xsize*dst_ysize*iColorIndex*(GDALGetDataTypeSize(eDT)/8), eDT, pabyWholeBuffer + dst_xsize*dst_ysize*iColorIndex, dst_xsize * dst_ysize ); } FreeLUTs(papszLUTs); msFree(panBuffer); return result_code; } /* -------------------------------------------------------------------- */ /* Disable use of nodata if we are doing scaling. */ /* -------------------------------------------------------------------- */ *pbHaveRGBNoData = FALSE; /* -------------------------------------------------------------------- */ /* We need to do some scaling. Will load into either a 16bit */ /* unsigned or a floating point buffer depending on the source */ /* data. We offer a special case for 16U data because it is */ /* common and it is a substantial win to avoid alot of floating */ /* point operations on it. */ /* -------------------------------------------------------------------- */ /* TODO */ /* -------------------------------------------------------------------- */ /* Allocate the raw imagery buffer, and load into it (band */ /* interleaved). */ /* -------------------------------------------------------------------- */ pafWholeRawData = (float *) malloc(sizeof(float) * dst_xsize * dst_ysize * band_count ); if( pafWholeRawData == NULL ) { msSetError(MS_MEMERR, "Allocating work float image of size %dx%dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize, band_count ); return -1; } eErr = GDALDatasetRasterIO( hDS, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pafWholeRawData, dst_xsize, dst_ysize, GDT_Float32, band_count, band_numbers, 0, 0, 0 ); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALDatasetRasterIO() failed: %s", "drawGDAL()", CPLGetLastErrorMsg() ); free( pafWholeRawData ); return -1; } papszLUTs = LoadLUTs(layer, band_count); if( papszLUTs == NULL ) { free( pafWholeRawData ); return -1; } if( GetDataTypeAppropriateForLUTS(papszLUTs) != GDT_Byte ) { msDebug( "LoadGDALImage(%s): One of the LUT contains a input value > 255.\n" "This is not properly supported in combination with SCALE\n", layer->name ); } /* -------------------------------------------------------------------- */ /* Fetch the scale processing option. */ /* -------------------------------------------------------------------- */ for( iColorIndex = 0; iColorIndex < band_count; iColorIndex++ ) { unsigned char *pabyBuffer; double dfScaleMin=0.0, dfScaleMax=255.0, dfScaleRatio, dfNoDataValue; const char *pszScaleInfo; float *pafRawData; int nPixelCount = dst_xsize * dst_ysize, i, bGotNoData = FALSE; GDALRasterBandH hBand =GDALGetRasterBand(hDS,band_numbers[iColorIndex]); pszScaleInfo = CSLFetchNameValue( layer->processing, "SCALE" ); if( pszScaleInfo == NULL ) { char szBandScalingName[20]; sprintf( szBandScalingName, "SCALE_%d", iColorIndex+1 ); pszScaleInfo = CSLFetchNameValue( layer->processing, szBandScalingName); } if( pszScaleInfo != NULL ) { char **papszTokens; papszTokens = CSLTokenizeStringComplex( pszScaleInfo, " ,", FALSE, FALSE ); if( CSLCount(papszTokens) == 1 && EQUAL(papszTokens[0],"AUTO") ) { dfScaleMin = dfScaleMax = 0.0; } else if( CSLCount(papszTokens) != 2 ) { free( pafWholeRawData ); CSLDestroy( papszTokens ); FreeLUTs( papszLUTs ); msSetError( MS_MISCERR, "SCALE PROCESSING option unparsable for layer %s.", "msDrawGDAL()", layer->name ); return -1; } else { dfScaleMin = atof(papszTokens[0]); dfScaleMax = atof(papszTokens[1]); } CSLDestroy( papszTokens ); } /* -------------------------------------------------------------------- */ /* If we are using autoscaling, then compute the max and min */ /* now. Perhaps we should eventually honour the offsite value */ /* as a nodata value, or get it from GDAL. */ /* -------------------------------------------------------------------- */ pafRawData = pafWholeRawData + iColorIndex * dst_xsize * dst_ysize; dfNoDataValue = msGetGDALNoDataValue( layer, hBand, &bGotNoData ); if( dfScaleMin == dfScaleMax ) { int bMinMaxSet = 0; /* we force assignment to a float rather than letting pafRawData[i] get promoted to double later to avoid float precision issues. */ float fNoDataValue = (float) dfNoDataValue; for( i = 0; i < nPixelCount; i++ ) { if( bGotNoData && pafRawData[i] == fNoDataValue ) continue; if( CPLIsNan(pafRawData[i]) ) continue; if( !bMinMaxSet ) { dfScaleMin = dfScaleMax = pafRawData[i]; bMinMaxSet = TRUE; } dfScaleMin = MS_MIN(dfScaleMin,pafRawData[i]); dfScaleMax = MS_MAX(dfScaleMax,pafRawData[i]); } if( dfScaleMin == dfScaleMax ) dfScaleMax = dfScaleMin + 1.0; } if( layer->debug > 0 ) msDebug( "msDrawGDAL(%s): scaling to 8bit, src range=%g,%g\n", layer->name, dfScaleMin, dfScaleMax ); /* -------------------------------------------------------------------- */ /* Now process the data. */ /* -------------------------------------------------------------------- */ dfScaleRatio = 256.0 / (dfScaleMax - dfScaleMin); pabyBuffer = pabyWholeBuffer + iColorIndex * nPixelCount; for( i = 0; i < nPixelCount; i++ ) { float fScaledValue = (float) ((pafRawData[i]-dfScaleMin)*dfScaleRatio); if( fScaledValue < 0.0 ) pabyBuffer[i] = 0; else if( fScaledValue > 255.0 ) pabyBuffer[i] = 255; else pabyBuffer[i] = (int) fScaledValue; } /* -------------------------------------------------------------------- */ /* Report a warning if NODATA keyword was applied. We are */ /* unable to utilize it since we can't return any pixels marked */ /* as nodata from this function. Need to fix someday. */ /* -------------------------------------------------------------------- */ if( bGotNoData ) msDebug( "LoadGDALImage(%s): NODATA value %g in GDAL\n" "file or PROCESSING directive largely ignored. Not yet fully supported for\n" "unclassified scaled data. The NODATA value is excluded from auto-scaling\n" "min/max computation, but will not be transparent.\n", layer->name, dfNoDataValue ); /* -------------------------------------------------------------------- */ /* Apply LUT if there is one. */ /* -------------------------------------------------------------------- */ result_code = ApplyLUT( iColorIndex+1, papszLUTs[iColorIndex], pabyBuffer, GDT_Byte, pabyBuffer, dst_xsize * dst_ysize ); if( result_code == -1 ) { free( pafWholeRawData ); FreeLUTs( papszLUTs ); return result_code; } } free( pafWholeRawData ); FreeLUTs( papszLUTs ); return result_code; } /************************************************************************/ /* msGetGDALGeoTransform() */ /* */ /* Cover function that tries GDALGetGeoTransform(), a world */ /* file or OWS extents. It is assumed that TLOCK_GDAL is held */ /* before this function is called. */ /************************************************************************/ int msGetGDALGeoTransform( GDALDatasetH hDS, mapObj *map, layerObj *layer, double *padfGeoTransform ) { const char *extent_priority = NULL; const char *value; const char *gdalDesc; const char *fullPath; char *fileExtension = NULL; char szPath[MS_MAXPATHLEN]; int fullPathLen; int success = 0; rectObj rect; /* -------------------------------------------------------------------- */ /* some GDAL drivers (ie. GIF) don't set geotransform on failure. */ /* -------------------------------------------------------------------- */ padfGeoTransform[0] = 0.0; padfGeoTransform[1] = 1.0; padfGeoTransform[2] = 0.0; padfGeoTransform[3] = GDALGetRasterYSize(hDS); padfGeoTransform[4] = 0.0; padfGeoTransform[5] = -1.0; /* -------------------------------------------------------------------- */ /* Do we want to override GDAL with a worldfile if one is present? */ /* -------------------------------------------------------------------- */ extent_priority = CSLFetchNameValue( layer->processing, "EXTENT_PRIORITY" ); if( extent_priority != NULL && EQUALN(extent_priority,"WORLD",5) ) { /* is there a user configured worldfile? */ value = CSLFetchNameValue( layer->processing, "WORLDFILE" ); if( value != NULL ) { /* at this point, fullPath may be a filePath or path only */ fullPath = msBuildPath(szPath, map->mappath, value); /* fullPath is a path only, so let's append the dataset filename */ if( strrchr(szPath,'.') == NULL ) { fullPathLen = strlen(fullPath); gdalDesc = msStripPath((char*)GDALGetDescription(hDS)); if ( (fullPathLen + strlen(gdalDesc)) < MS_MAXPATHLEN ) { strcpy((char*)(fullPath + fullPathLen), gdalDesc); } else { msDebug("Path length to alternative worldfile exceeds MS_MAXPATHLEN.\n"); fullPath = NULL; } } /* fullPath has a filename included, so get the extension */ else { fileExtension = msStrdup(strrchr(szPath,'.') + 1); } } /* common behaviour with worldfile generated from basename + .wld */ else { fullPath = GDALGetDescription(hDS); fileExtension = msStrdup("wld"); } if( fullPath ) success = GDALReadWorldFile(fullPath, fileExtension, padfGeoTransform); if( success && layer->debug >= MS_DEBUGLEVEL_VVV ) { msDebug("Worldfile location: %s.\n", fullPath); } else if( layer->debug >= MS_DEBUGLEVEL_VVV ) { msDebug("Failed using worldfile location: %s.\n", fullPath); } msFree(fileExtension); if( success ) return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Try GDAL. */ /* */ /* Make sure that ymax is always at the top, and ymin at the */ /* bottom ... that is flip any files without the usual */ /* orientation. This is intended to enable display of "raw" */ /* files with no coordinate system otherwise they break down in */ /* many ways. */ /* -------------------------------------------------------------------- */ if (GDALGetGeoTransform( hDS, padfGeoTransform ) == CE_None ) { if( padfGeoTransform[5] == 1.0 && padfGeoTransform[3] == 0.0 ) { padfGeoTransform[5] = -1.0; padfGeoTransform[3] = GDALGetRasterYSize(hDS); } return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Try worldfile. */ /* -------------------------------------------------------------------- */ if( GDALGetDescription(hDS) != NULL && GDALReadWorldFile(GDALGetDescription(hDS), "wld", padfGeoTransform) ) { return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Do we have the extent keyword on the layer? We only use */ /* this if we have a single raster associated with the layer as */ /* opposed to a tile index. */ /* */ /* Arguably this ought to take priority over all the other */ /* stuff. */ /* -------------------------------------------------------------------- */ if (MS_VALID_EXTENT(layer->extent) && layer->data != NULL) { rect = layer->extent; padfGeoTransform[0] = rect.minx; padfGeoTransform[1] = (rect.maxx - rect.minx) / (double) GDALGetRasterXSize( hDS ); padfGeoTransform[2] = 0; padfGeoTransform[3] = rect.maxy; padfGeoTransform[4] = 0; padfGeoTransform[5] = (rect.miny - rect.maxy) / (double) GDALGetRasterYSize( hDS ); return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* We didn't find any info ... use the default. */ /* Reset our default geotransform. GDALGetGeoTransform() may */ /* have altered it even if GDALGetGeoTransform() failed. */ /* -------------------------------------------------------------------- */ padfGeoTransform[0] = 0.0; padfGeoTransform[1] = 1.0; padfGeoTransform[2] = 0.0; padfGeoTransform[3] = GDALGetRasterYSize(hDS); padfGeoTransform[4] = 0.0; padfGeoTransform[5] = -1.0; return MS_FAILURE; } /************************************************************************/ /* msDrawRasterLayerGDAL_RawMode() */ /* */ /* Handle the loading and application of data in rawmode. */ /************************************************************************/ static int msDrawRasterLayerGDAL_RawMode( mapObj *map, layerObj *layer, imageObj *image, GDALDatasetH hDS, int src_xoff, int src_yoff, int src_xsize, int src_ysize, int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize ) { void *pBuffer; GDALDataType eDataType; int *band_list, band_count; int i, j, k, band; CPLErr eErr; float *f_nodatas = NULL; unsigned char *b_nodatas = NULL; GInt16 *i_nodatas = NULL; int got_nodata=FALSE; rasterBufferObj *mask_rb = NULL; rasterBufferObj s_mask_rb; if(layer->mask) { int ret; layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask)); mask_rb = &s_mask_rb; memset(mask_rb, 0, sizeof(s_mask_rb)); ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb); if(ret != MS_SUCCESS) return -1; } if( image->format->bands > 256 ) { msSetError( MS_IMGERR, "Too many bands (more than 256).", "msDrawRasterLayerGDAL_RawMode()" ); return -1; } /* -------------------------------------------------------------------- */ /* What data type do we need? */ /* -------------------------------------------------------------------- */ if( image->format->imagemode == MS_IMAGEMODE_INT16 ) eDataType = GDT_Int16; else if( image->format->imagemode == MS_IMAGEMODE_FLOAT32 ) eDataType = GDT_Float32; else if( image->format->imagemode == MS_IMAGEMODE_BYTE ) eDataType = GDT_Byte; else return -1; /* -------------------------------------------------------------------- */ /* Work out the band list. */ /* -------------------------------------------------------------------- */ band_list = msGetGDALBandList( layer, hDS, image->format->bands, &band_count ); if( band_list == NULL ) return -1; if( band_count != image->format->bands ) { free( band_list ); msSetError( MS_IMGERR, "BANDS PROCESSING directive has wrong number of bands, expected %d, got %d.", "msDrawRasterLayerGDAL_RawMode()", image->format->bands, band_count ); return -1; } /* -------------------------------------------------------------------- */ /* Do we have nodata values? */ /* -------------------------------------------------------------------- */ f_nodatas = (float *) calloc(sizeof(float),band_count); if (f_nodatas == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDrawRasterLayerGDAL_RawMode()", __FILE__, __LINE__, (unsigned int)(sizeof(float)*band_count)); free( band_list ); return -1; } if( band_count <= 3 && (layer->offsite.red != -1 || layer->offsite.green != -1 || layer->offsite.blue != -1) ) { if( band_count > 0 ) f_nodatas[0] = layer->offsite.red; if( band_count > 1 ) f_nodatas[1] = layer->offsite.green; if( band_count > 2 ) f_nodatas[2] = layer->offsite.blue; got_nodata = TRUE; } if( !got_nodata ) { got_nodata = TRUE; for( band = 0; band < band_count && got_nodata; band++ ) { f_nodatas[band] = msGetGDALNoDataValue( layer, GDALGetRasterBand(hDS,band_list[band]), &got_nodata ); } } if( !got_nodata ) { free( f_nodatas ); f_nodatas = NULL; } else if( eDataType == GDT_Byte ) { b_nodatas = (unsigned char *) f_nodatas; for( band = 0; band < band_count; band++ ) b_nodatas[band] = (unsigned char) f_nodatas[band]; } else if( eDataType == GDT_Int16 ) { i_nodatas = (GInt16 *) f_nodatas; for( band = 0; band < band_count; band++ ) i_nodatas[band] = (GInt16) f_nodatas[band]; } /* -------------------------------------------------------------------- */ /* Allocate buffer, and read data into it. */ /* -------------------------------------------------------------------- */ pBuffer = malloc(dst_xsize * dst_ysize * image->format->bands * (GDALGetDataTypeSize(eDataType)/8) ); if( pBuffer == NULL ) { msSetError(MS_MEMERR, "Allocating work image of size %dx%d failed.", "msDrawRasterLayerGDAL()", dst_xsize, dst_ysize ); free( band_list ); free( f_nodatas ); return -1; } eErr = GDALDatasetRasterIO( hDS, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pBuffer, dst_xsize, dst_ysize, eDataType, image->format->bands, band_list, 0, 0, 0 ); free( band_list ); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALRasterIO() failed: %s", "msDrawRasterLayerGDAL_RawMode()", CPLGetLastErrorMsg() ); free( pBuffer ); free( f_nodatas ); return -1; } /* -------------------------------------------------------------------- */ /* Transfer the data to the imageObj. */ /* -------------------------------------------------------------------- */ k = 0; for( band = 0; band < image->format->bands; band++ ) { for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { if( image->format->imagemode == MS_IMAGEMODE_INT16 ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int off = j + i * image->width + band*image->width*image->height; int off_mask = j + i * image->width; if( ( i_nodatas && ((GInt16 *) pBuffer)[k] == i_nodatas[band] ) || SKIP_MASK(j,i)) { k++; continue; } image->img.raw_16bit[off] = ((GInt16 *) pBuffer)[k++]; MS_SET_BIT(image->img_mask,off_mask); } } else if( image->format->imagemode == MS_IMAGEMODE_FLOAT32 ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int off = j + i * image->width + band*image->width*image->height; int off_mask = j + i * image->width; if( ( f_nodatas && ((float *) pBuffer)[k] == f_nodatas[band] ) || SKIP_MASK(j,i)) { k++; continue; } image->img.raw_float[off] = ((float *) pBuffer)[k++]; MS_SET_BIT(image->img_mask,off_mask); } } else if( image->format->imagemode == MS_IMAGEMODE_BYTE ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { int off = j + i * image->width + band*image->width*image->height; int off_mask = j + i * image->width; if( ( b_nodatas && ((unsigned char *) pBuffer)[k] == b_nodatas[band] ) || SKIP_MASK(j,i)) { k++; continue; } image->img.raw_byte[off] = ((unsigned char *) pBuffer)[k++]; MS_SET_BIT(image->img_mask,off_mask); } } } } free( pBuffer ); free( f_nodatas ); return 0; } /************************************************************************/ /* msDrawRasterLayerGDAL_16BitClassifcation() */ /* */ /* Handle the rendering of rasters going through a 16bit */ /* classification lookup instead of the more common 8bit one. */ /* */ /* Currently we are using one data path where we load the */ /* raster into a floating point buffer, and then scale to */ /* 16bit. Eventually we could add optimizations for some of */ /* the 16bit cases at the cost of some complication. */ /************************************************************************/ static int msDrawRasterLayerGDAL_16BitClassification( mapObj *map, layerObj *layer, rasterBufferObj *rb, GDALDatasetH hDS, GDALRasterBandH hBand, int src_xoff, int src_yoff, int src_xsize, int src_ysize, int dst_xoff, int dst_yoff, int dst_xsize, int dst_ysize ) { float *pafRawData; double dfScaleMin=0.0, dfScaleMax=0.0, dfScaleRatio; int nPixelCount = dst_xsize * dst_ysize, i, nBucketCount=0; GDALDataType eDataType; float fDataMin=0.0, fDataMax=255.0, fNoDataValue; const char *pszScaleInfo; const char *pszBuckets; int *cmap, c, j, k, bGotNoData = FALSE, bGotFirstValue; unsigned char *rb_cmap[4]; CPLErr eErr; rasterBufferObj *mask_rb = NULL; rasterBufferObj s_mask_rb; int lastC; struct mstimeval starttime, endtime; if(layer->mask) { int ret; layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask)); mask_rb = &s_mask_rb; memset(mask_rb, 0, sizeof(s_mask_rb)); ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb); if(ret != MS_SUCCESS) return -1; } assert( rb->type == MS_BUFFER_BYTE_RGBA ); /* ==================================================================== */ /* Read the requested data in one gulp into a floating point */ /* buffer. */ /* ==================================================================== */ pafRawData = (float *) malloc(sizeof(float) * dst_xsize * dst_ysize ); if( pafRawData == NULL ) { msSetError( MS_MEMERR, "Out of memory allocating working buffer.", "msDrawRasterLayerGDAL_16BitClassification()" ); return -1; } eErr = GDALRasterIO( hBand, GF_Read, src_xoff, src_yoff, src_xsize, src_ysize, pafRawData, dst_xsize, dst_ysize, GDT_Float32, 0, 0 ); if( eErr != CE_None ) { free( pafRawData ); msSetError( MS_IOERR, "GDALRasterIO() failed: %s", "msDrawRasterLayerGDAL_16BitClassification()", CPLGetLastErrorMsg() ); return -1; } fNoDataValue = (float) msGetGDALNoDataValue( layer, hBand, &bGotNoData ); /* ==================================================================== */ /* Determine scaling. */ /* ==================================================================== */ eDataType = GDALGetRasterDataType( hBand ); /* -------------------------------------------------------------------- */ /* Scan for absolute min/max of this block. */ /* -------------------------------------------------------------------- */ bGotFirstValue = FALSE; for( i = 1; i < nPixelCount; i++ ) { if( bGotNoData && pafRawData[i] == fNoDataValue ) continue; if( CPLIsNan(pafRawData[i]) ) continue; if( !bGotFirstValue ) { fDataMin = fDataMax = pafRawData[i]; bGotFirstValue = TRUE; } else { fDataMin = MS_MIN(fDataMin,pafRawData[i]); fDataMax = MS_MAX(fDataMax,pafRawData[i]); } } /* -------------------------------------------------------------------- */ /* Fetch the scale processing option. */ /* -------------------------------------------------------------------- */ pszBuckets = CSLFetchNameValue( layer->processing, "SCALE_BUCKETS" ); pszScaleInfo = CSLFetchNameValue( layer->processing, "SCALE" ); if( pszScaleInfo != NULL ) { char **papszTokens; papszTokens = CSLTokenizeStringComplex( pszScaleInfo, " ,", FALSE, FALSE ); if( CSLCount(papszTokens) == 1 && EQUAL(papszTokens[0],"AUTO") ) { dfScaleMin = dfScaleMax = 0.0; } else if( CSLCount(papszTokens) != 2 ) { free( pafRawData ); CSLDestroy( papszTokens ); msSetError( MS_MISCERR, "SCALE PROCESSING option unparsable for layer %s.", "msDrawGDAL()", layer->name ); return -1; } else { dfScaleMin = atof(papszTokens[0]); dfScaleMax = atof(papszTokens[1]); } CSLDestroy( papszTokens ); } /* -------------------------------------------------------------------- */ /* Special integer cases for scaling. */ /* */ /* TODO: Treat Int32 and UInt32 case the same way *if* the min */ /* and max are less than 65536 apart. */ /* -------------------------------------------------------------------- */ if( eDataType == GDT_Byte || eDataType == GDT_Int16 || eDataType == GDT_UInt16 ) { if( pszScaleInfo == NULL ) { dfScaleMin = fDataMin - 0.5; dfScaleMax = fDataMax + 0.5; } if( pszBuckets == NULL ) { nBucketCount = (int) floor(fDataMax - fDataMin + 1.1); } } /* -------------------------------------------------------------------- */ /* General case if no scaling values provided in mapfile. */ /* -------------------------------------------------------------------- */ else if( dfScaleMin == 0.0 && dfScaleMax == 0.0 ) { double dfEpsilon = (fDataMax - fDataMin) / (65536*2); dfScaleMin = fDataMin - dfEpsilon; dfScaleMax = fDataMax + dfEpsilon; } /* -------------------------------------------------------------------- */ /* How many buckets? Only set if we don't already have a value. */ /* -------------------------------------------------------------------- */ if( pszBuckets == NULL ) { if( nBucketCount == 0 ) nBucketCount = 65536; } else { nBucketCount = atoi(pszBuckets); if( nBucketCount < 2 ) { free( pafRawData ); msSetError( MS_MISCERR, "SCALE_BUCKETS PROCESSING option is not a value of 2 or more: %s.", "msDrawRasterLayerGDAL_16BitClassification()", pszBuckets ); return -1; } } /* -------------------------------------------------------------------- */ /* Compute scaling ratio. */ /* -------------------------------------------------------------------- */ if( dfScaleMax == dfScaleMin ) dfScaleMax = dfScaleMin + 1.0; dfScaleRatio = nBucketCount / (dfScaleMax - dfScaleMin); if( layer->debug > 0 ) msDebug( "msDrawRasterGDAL_16BitClassification(%s):\n" " scaling to %d buckets from range=%g,%g.\n", layer->name, nBucketCount, dfScaleMin, dfScaleMax ); /* ==================================================================== */ /* Compute classification lookup table. */ /* ==================================================================== */ cmap = (int *) msSmallCalloc(sizeof(int),nBucketCount); rb_cmap[0] = (unsigned char *) msSmallCalloc(1,nBucketCount); rb_cmap[1] = (unsigned char *) msSmallCalloc(1,nBucketCount); rb_cmap[2] = (unsigned char *) msSmallCalloc(1,nBucketCount); rb_cmap[3] = (unsigned char *) msSmallCalloc(1,nBucketCount); if(layer->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&starttime, NULL); } lastC = -1; for(i=0; i < nBucketCount; i++) { double dfOriginalValue; cmap[i] = -1; dfOriginalValue = (i+0.5) / dfScaleRatio + dfScaleMin; /* The creation of buckets takes a significant time when they are many, and many classes as well. When iterating over buckets, a faster strategy is to reuse first the last used class index. */ c = msGetClass_FloatRGB_WithFirstClassToTry(layer, (float) dfOriginalValue, -1, -1, -1, lastC); lastC = c; if( c != -1 ) { int s; /* change colour based on colour range? */ for(s=0; sclass[c]->numstyles; s++) { if( MS_VALID_COLOR(layer->class[c]->styles[s]->mincolor) && MS_VALID_COLOR(layer->class[c]->styles[s]->maxcolor) ) msValueToRange(layer->class[c]->styles[s],dfOriginalValue, MS_COLORSPACE_RGB); } if( MS_TRANSPARENT_COLOR(layer->class[c]->styles[0]->color) ) { /* leave it transparent */ } else if( MS_VALID_COLOR(layer->class[c]->styles[0]->color)) { /* use class color */ rb_cmap[0][i] = layer->class[c]->styles[0]->color.red; rb_cmap[1][i] = layer->class[c]->styles[0]->color.green; rb_cmap[2][i] = layer->class[c]->styles[0]->color.blue; rb_cmap[3][i] = (255*layer->class[c]->styles[0]->opacity / 100); } } } if(layer->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msDrawRasterGDAL_16BitClassification() bucket creation time: %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } /* ==================================================================== */ /* Now process the data, applying to the working imageObj. */ /* ==================================================================== */ k = 0; for( i = dst_yoff; i < dst_yoff + dst_ysize; i++ ) { for( j = dst_xoff; j < dst_xoff + dst_xsize; j++ ) { float fRawValue = pafRawData[k++]; int iMapIndex; /* * Skip nodata pixels ... no processing. */ if( bGotNoData && fRawValue == fNoDataValue ) { continue; } if( CPLIsNan(fRawValue) ) continue; if(SKIP_MASK(j,i)) continue; /* * The funny +1/-1 is to avoid odd rounding around zero. * We could use floor() but sometimes it is expensive. */ iMapIndex = (int) ((fRawValue - dfScaleMin) * dfScaleRatio+1)-1; if( iMapIndex >= nBucketCount || iMapIndex < 0 ) { continue; } /* currently we never have partial alpha so keep simple */ if( rb_cmap[3][iMapIndex] > 0 ) RB_SET_PIXEL( rb, j, i, rb_cmap[0][iMapIndex], rb_cmap[1][iMapIndex], rb_cmap[2][iMapIndex], rb_cmap[3][iMapIndex] ); } } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ free( pafRawData ); free( cmap ); free( rb_cmap[0] ); free( rb_cmap[1] ); free( rb_cmap[2] ); free( rb_cmap[3] ); assert( k == dst_xsize * dst_ysize ); return 0; } /************************************************************************/ /* msGetGDALNoDataValue() */ /************************************************************************/ double msGetGDALNoDataValue( layerObj *layer, void *hBand, int *pbGotNoData ) { const char *pszNODATAOpt; *pbGotNoData = FALSE; /* -------------------------------------------------------------------- */ /* Check for a NODATA setting in the .map file. */ /* -------------------------------------------------------------------- */ pszNODATAOpt = CSLFetchNameValue(layer->processing,"NODATA"); if( pszNODATAOpt != NULL ) { if( EQUAL(pszNODATAOpt,"OFF") || strlen(pszNODATAOpt) == 0 ) return -1234567.0; if( !EQUAL(pszNODATAOpt,"AUTO") ) { *pbGotNoData = TRUE; return atof(pszNODATAOpt); } } /* -------------------------------------------------------------------- */ /* Check for a NODATA setting on the raw file. */ /* -------------------------------------------------------------------- */ if( hBand == NULL ) return -1234567.0; else return GDALGetRasterNoDataValue( hBand, pbGotNoData ); } /************************************************************************/ /* msGetGDALBandList() */ /* */ /* max_bands - pass zero for no limit. */ /* band_count - location in which length of the return band */ /* list is placed. */ /* */ /* returns malloc() list of band numbers (*band_count long). */ /************************************************************************/ int *msGetGDALBandList( layerObj *layer, void *hDS, int max_bands, int *band_count ) { int i, file_bands; int *band_list = NULL; file_bands = GDALGetRasterCount( hDS ); if( file_bands == 0 ) { msSetError( MS_IMGERR, "Attempt to operate on GDAL file with no bands, layer=%s.", "msGetGDALBandList()", layer->name ); return NULL; } /* -------------------------------------------------------------------- */ /* Use all (or first) bands. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) { if( max_bands > 0 ) *band_count = MS_MIN(file_bands,max_bands); else *band_count = file_bands; band_list = (int *) malloc(sizeof(int) * *band_count ); /* FIXME MS_CHECK_ALLOC leaks papszItems */ MS_CHECK_ALLOC(band_list, sizeof(int) * *band_count, NULL); for( i = 0; i < *band_count; i++ ) band_list[i] = i+1; return band_list; } /* -------------------------------------------------------------------- */ /* get bands from BANDS processing directive. */ /* -------------------------------------------------------------------- */ else { char **papszItems = CSLTokenizeStringComplex( CSLFetchNameValue(layer->processing,"BANDS"), " ,", FALSE, FALSE ); if( CSLCount(papszItems) == 0 ) { CSLDestroy( papszItems ); msSetError( MS_IMGERR, "BANDS PROCESSING directive has no items.", "msGetGDALBandList()" ); return NULL; } else if( max_bands != 0 && CSLCount(papszItems) > max_bands ) { msSetError( MS_IMGERR, "BANDS PROCESSING directive has wrong number of bands, expected at most %d, got %d.", "msGetGDALBandList()", max_bands, CSLCount(papszItems) ); CSLDestroy( papszItems ); return NULL; } *band_count = CSLCount(papszItems); band_list = (int *) malloc(sizeof(int) * *band_count); MS_CHECK_ALLOC(band_list, sizeof(int) * *band_count, NULL); for( i = 0; i < *band_count; i++ ) { band_list[i] = atoi(papszItems[i]); if( band_list[i] < 1 || band_list[i] > GDALGetRasterCount(hDS) ) { msSetError( MS_IMGERR, "BANDS PROCESSING directive includes illegal band '%s', should be from 1 to %d.", "msGetGDALBandList()", papszItems[i], GDALGetRasterCount(hDS) ); CSLDestroy( papszItems ); free( band_list ); return NULL; } } CSLDestroy( papszItems ); return band_list; } } #endif /* def USE_GDAL */ mapserver-7.4.3/mapdummyrenderer.c000066400000000000000000000225761357574274700173160ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Dummy functions to implement when using a pluggable renderer * Author: Thomas Bonfort, thomas.bonfort@gmail.com * ****************************************************************************** * Copyright (c) 2010, Thomas Bonfort * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" int renderLineDummy(imageObj *img, shapeObj *p, strokeStyleObj *style) { msSetError(MS_RENDERERERR,"renderLine not implemented","renderLine()"); return MS_FAILURE; } int renderPolygonDummy(imageObj *img, shapeObj *p, colorObj *color) { msSetError(MS_RENDERERERR,"renderPolygon not implemented","renderPolygon()"); return MS_FAILURE; } int renderPolygonTiledDummy(imageObj *img, shapeObj *p, imageObj *tile) { msSetError(MS_RENDERERERR,"renderPolygonTiled not implemented","renderPolygonTiled()"); return MS_FAILURE; } int renderLineTiledDummy(imageObj *img, shapeObj *p, imageObj *tile) { msSetError(MS_RENDERERERR,"renderLineTiled not implemented","renderLineTiled()"); return MS_FAILURE; } int renderRasterGlyphsDummy(imageObj *img, double x, double y, int fontIndex, colorObj *color, char* text) { msSetError(MS_RENDERERERR,"renderRasterGlyphs not implemented","renderRasterGlyphs()"); return MS_FAILURE; } int renderGlyphsLineDummy(imageObj *img,labelPathObj *labelpath, labelStyleObj *style, char *text) { msSetError(MS_RENDERERERR,"renderGlyphsLine not implemented","renderGlyphsLine()"); return MS_FAILURE; } int renderVectorSymbolDummy(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderVectorSymbol not implemented","renderVectorSymbol()"); return MS_FAILURE; } void* createVectorSymbolTileDummy(int width, int height, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"createVectorSymbolTile not implemented","createVectorSymbolTile()"); return NULL; } int renderPixmapSymbolDummy(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderPixmapSymbol not implemented","renderPixmapSymbol()"); return MS_FAILURE; } void* createPixmapSymbolTileDummy(int width, int height, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"createPixmapSymbolTile not implemented","createPixmapSymbolTile()"); return NULL; } int renderEllipseSymbolDummy(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderEllipseSymbol not implemented","renderEllipseSymbol()"); return MS_FAILURE; } void* createEllipseSymbolTileDummy(int width, int height, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"createEllipseSymbolTile not implemented","createEllipseSymbolTile()"); return NULL; } int renderTruetypeSymbolDummy(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"renderTruetypeSymbol not implemented","renderTruetypeSymbol()"); return MS_FAILURE; } void* createTruetypeSymbolTileDummy(int width, int height, symbolObj *symbol, symbolStyleObj *style) { msSetError(MS_RENDERERERR,"createTruetypeSymbolTile not implemented","createTruetypeSymbolTile()"); return NULL; } int renderTileDummy(imageObj *img, imageObj *tile, double x, double y) { msSetError(MS_RENDERERERR,"renderTile not implemented","renderTile()"); return MS_FAILURE; } rasterBufferObj* loadImageFromFileDummy(char *path) { msSetError(MS_RENDERERERR,"loadImageFromFile not implemented","loadImageFromFile()"); return NULL; } int getRasterBufferHandleDummy(imageObj *img, rasterBufferObj *rb) { msSetError(MS_RENDERERERR,"getRasterBufferHandle not implemented","getRasterBufferHandle()"); return MS_FAILURE; } int getRasterBufferCopyDummy(imageObj *img, rasterBufferObj *rb) { msSetError(MS_RENDERERERR,"getRasterBufferCopy not implemented","getRasterBufferCopy()"); return MS_FAILURE; } rasterBufferObj* createRasterBufferDummy(int width, int height) { msSetError(MS_RENDERERERR,"createRasterBuffer not implemented","createRasterBuffer()"); return NULL; } int mergeRasterBufferDummy(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { msSetError(MS_RENDERERERR,"mergeRasterBuffer not implemented","mergeRasterBuffer()"); return MS_FAILURE; } int initializeRasterBufferDummy(rasterBufferObj *rb, int width, int height, int mode) { msSetError(MS_RENDERERERR,"initializeRasterBuffer not implemented","initializeRasterBuffer()"); return MS_FAILURE; } /* image i/o */ imageObj* createImageDummy(int width, int height, outputFormatObj *format, colorObj* bg) { msSetError(MS_RENDERERERR,"createImage not implemented","createImage()"); return NULL; } int saveImageDummy(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { msSetError(MS_RENDERERERR,"saveImage not implemented","saveImage()"); return MS_FAILURE; } /*...*/ /* helper functions */ int getTruetypeTextBBoxDummy(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string,rectObj *rect, double **advances, int bAdjustBaseline) { msSetError(MS_RENDERERERR,"getTruetypeTextBBox not implemented","getTruetypeTextBBox()"); return MS_FAILURE; } int startLayerDummy(imageObj *img, mapObj *map, layerObj *layer) { msSetError(MS_RENDERERERR,"startLayer not implemented","startLayer()"); return MS_FAILURE; } int endLayerDummy(imageObj *img, mapObj *map, layerObj *layer) { msSetError(MS_RENDERERERR,"endLayer not implemented","endLayer()"); return MS_FAILURE; } int startShapeDummy(imageObj *img, shapeObj *shape) { msSetError(MS_RENDERERERR,"startShape not implemented","startShape()"); return MS_FAILURE; } int endShapeDummy(imageObj *img, shapeObj *shape) { msSetError(MS_RENDERERERR,"endShape not implemented","endShape()"); return MS_FAILURE; } int setClipDummy(imageObj *img, rectObj clipRect) { msSetError(MS_RENDERERERR,"setClip not implemented","setClip()"); return MS_FAILURE; } int resetClipDummy(imageObj *img) { msSetError(MS_RENDERERERR,"resetClip not implemented","resetClip()"); return MS_FAILURE; } int freeImageDummy(imageObj *image) { msSetError(MS_RENDERERERR,"freeImage not implemented","freeImage()"); return MS_FAILURE; } int freeTileDummy(imageObj *tile) { msSetError(MS_RENDERERERR,"freeTile not implemented","freeTile()"); return MS_FAILURE; } int freeSymbolDummy(symbolObj *symbol) { msSetError(MS_RENDERERERR,"freeSymbol not implemented","freeSymbol()"); return MS_FAILURE; } int cleanupDummy(void *renderer_data) { return MS_SUCCESS; } int msInitializeDummyRenderer(rendererVTableObj *renderer) { renderer->use_imagecache = 0; renderer->supports_pixel_buffer = 0; renderer->compositeRasterBuffer = NULL; renderer->supports_clipping = 0; renderer->supports_svg = 0; renderer->renderer_data = NULL; renderer->transform_mode = MS_TRANSFORM_SIMPLIFY; renderer->startLayer = &startLayerDummy; renderer->endLayer = &endLayerDummy; renderer->renderLine=&renderLineDummy; renderer->renderLineTiled = NULL; renderer->createImage=&createImageDummy; renderer->saveImage=&saveImageDummy; renderer->getRasterBufferHandle=&getRasterBufferHandleDummy; renderer->getRasterBufferCopy=getRasterBufferCopyDummy; renderer->initializeRasterBuffer=initializeRasterBufferDummy; renderer->renderPolygon=&renderPolygonDummy; renderer->freeImage=&freeImageDummy; renderer->renderEllipseSymbol = &renderEllipseSymbolDummy; renderer->renderVectorSymbol = &renderVectorSymbolDummy; renderer->renderPixmapSymbol = &renderPixmapSymbolDummy; renderer->mergeRasterBuffer = &mergeRasterBufferDummy; renderer->renderTile = &renderTileDummy; renderer->renderPolygonTiled = &renderPolygonTiledDummy; renderer->freeSymbol = &freeSymbolDummy; renderer->cleanup = &cleanupDummy; renderer->startShape = NULL; renderer->endShape = NULL; renderer->renderGlyphs = NULL; return MS_SUCCESS; } mapserver-7.4.3/mapentities.h000066400000000000000000000155211357574274700162550ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: HTML entity to unicode lookup table * Author: Thomas Bonfort * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* * Generated file * * This file was generated from: * http://www.w3.org/TR/REC-html40/sgml/entities.html * by means of the libgd script: * entities.tcl * and modified to avoid namespace collisions */ #ifdef __cplusplus extern "C" { #endif static struct mapentities_s { char *name; int value; } mapentities[] = { {"AElig", 198}, {"Aacute", 193}, {"Acirc", 194}, {"Agrave", 192}, {"Alpha", 913}, {"Aring", 197}, {"Atilde", 195}, {"Auml", 196}, {"Beta", 914}, {"Ccedil", 199}, {"Chi", 935}, {"Dagger", 8225}, {"Delta", 916}, {"ETH", 208}, {"Eacute", 201}, {"Ecirc", 202}, {"Egrave", 200}, {"Epsilon", 917}, {"Eta", 919}, {"Euml", 203}, {"Gamma", 915}, {"Iacute", 205}, {"Icirc", 206}, {"Igrave", 204}, {"Iota", 921}, {"Iuml", 207}, {"Kappa", 922}, {"Lambda", 923}, {"Mu", 924}, {"Ntilde", 209}, {"Nu", 925}, {"OElig", 338}, {"Oacute", 211}, {"Ocirc", 212}, {"Ograve", 210}, {"Omega", 937}, {"Omicron", 927}, {"Oslash", 216}, {"Otilde", 213}, {"Ouml", 214}, {"Phi", 934}, {"Pi", 928}, {"Prime", 8243}, {"Psi", 936}, {"Rho", 929}, {"Scaron", 352}, {"Sigma", 931}, {"THORN", 222}, {"Tau", 932}, {"Theta", 920}, {"Uacute", 218}, {"Ucirc", 219}, {"Ugrave", 217}, {"Upsilon", 933}, {"Uuml", 220}, {"Xi", 926}, {"Yacute", 221}, {"Yuml", 376}, {"Zeta", 918}, {"aacute", 225}, {"acirc", 226}, {"acute", 180}, {"aelig", 230}, {"agrave", 224}, {"alefsym", 8501}, {"alpha", 945}, {"amp", 38}, {"and", 8743}, {"ang", 8736}, {"aring", 229}, {"asymp", 8776}, {"atilde", 227}, {"auml", 228}, {"bdquo", 8222}, {"beta", 946}, {"brvbar", 166}, {"bull", 8226}, {"cap", 8745}, {"ccedil", 231}, {"cedil", 184}, {"cent", 162}, {"chi", 967}, {"circ", 710}, {"clubs", 9827}, {"cong", 8773}, {"copy", 169}, {"crarr", 8629}, {"cup", 8746}, {"curren", 164}, {"dArr", 8659}, {"dagger", 8224}, {"darr", 8595}, {"deg", 176}, {"delta", 948}, {"diams", 9830}, {"divide", 247}, {"eacute", 233}, {"ecirc", 234}, {"egrave", 232}, {"empty", 8709}, {"emsp", 8195}, {"ensp", 8194}, {"epsilon", 949}, {"equiv", 8801}, {"eta", 951}, {"eth", 240}, {"euml", 235}, {"euro", 8364}, {"exist", 8707}, {"fnof", 402}, {"forall", 8704}, {"frac12", 189}, {"frac14", 188}, {"frac34", 190}, {"frasl", 8260}, {"gamma", 947}, {"ge", 8805}, {"gt", 62}, {"hArr", 8660}, {"harr", 8596}, {"hearts", 9829}, {"hellip", 8230}, {"iacute", 237}, {"icirc", 238}, {"iexcl", 161}, {"igrave", 236}, {"image", 8465}, {"infin", 8734}, {"int", 8747}, {"iota", 953}, {"iquest", 191}, {"isin", 8712}, {"iuml", 239}, {"kappa", 954}, {"lArr", 8656}, {"lambda", 955}, {"lang", 9001}, {"laquo", 171}, {"larr", 8592}, {"lceil", 8968}, {"ldquo", 8220}, {"le", 8804}, {"lfloor", 8970}, {"lowast", 8727}, {"loz", 9674}, {"lrm", 8206}, {"lsaquo", 8249}, {"lsquo", 8216}, {"lt", 60}, {"macr", 175}, {"mdash", 8212}, {"micro", 181}, {"middot", 183}, {"minus", 8722}, {"mu", 956}, {"nabla", 8711}, {"nbsp", 160}, {"ndash", 8211}, {"ne", 8800}, {"ni", 8715}, {"not", 172}, {"notin", 8713}, {"nsub", 8836}, {"ntilde", 241}, {"nu", 957}, {"oacute", 243}, {"ocirc", 244}, {"oelig", 339}, {"ograve", 242}, {"oline", 8254}, {"omega", 969}, {"omicron", 959}, {"oplus", 8853}, {"or", 8744}, {"ordf", 170}, {"ordm", 186}, {"oslash", 248}, {"otilde", 245}, {"otimes", 8855}, {"ouml", 246}, {"para", 182}, {"part", 8706}, {"permil", 8240}, {"perp", 8869}, {"phi", 966}, {"pi", 960}, {"piv", 982}, {"plusmn", 177}, {"pound", 163}, {"prime", 8242}, {"prod", 8719}, {"prop", 8733}, {"psi", 968}, {"quot", 34}, {"rArr", 8658}, {"radic", 8730}, {"rang", 9002}, {"raquo", 187}, {"rarr", 8594}, {"rceil", 8969}, {"rdquo", 8221}, {"real", 8476}, {"reg", 174}, {"rfloor", 8971}, {"rho", 961}, {"rlm", 8207}, {"rsaquo", 8250}, {"rsquo", 8217}, {"sbquo", 8218}, {"scaron", 353}, {"sdot", 8901}, {"sect", 167}, {"shy", 173}, {"sigma", 963}, {"sigmaf", 962}, {"sim", 8764}, {"spades", 9824}, {"sub", 8834}, {"sube", 8838}, {"sum", 8721}, {"sup", 8835}, {"sup1", 185}, {"sup2", 178}, {"sup3", 179}, {"supe", 8839}, {"szlig", 223}, {"tau", 964}, {"there4", 8756}, {"theta", 952}, {"thetasym", 977}, {"thinsp", 8201}, {"thorn", 254}, {"tilde", 732}, {"times", 215}, {"trade", 8482}, {"uArr", 8657}, {"uacute", 250}, {"uarr", 8593}, {"ucirc", 251}, {"ugrave", 249}, {"uml", 168}, {"upsih", 978}, {"upsilon", 965}, {"uuml", 252}, {"weierp", 8472}, {"xi", 958}, {"yacute", 253}, {"yen", 165}, {"yuml", 255}, {"zeta", 950}, {"zwj", 8205}, {"zwnj", 8204}, }; #define MAP_ENTITY_NAME_LENGTH_MAX 8 #define MAP_NR_OF_ENTITIES 252 #ifdef __cplusplus } #endif mapserver-7.4.3/maperror.c000066400000000000000000000431421357574274700155550ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of msSetError(), msDebug() and related functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "maperror.h" #include "mapthread.h" #include "maptime.h" #include #ifndef _WIN32 #include #include #endif #include static char *ms_errorCodes[MS_NUMERRORCODES] = {"", "Unable to access file.", "Memory allocation error.", "Incorrect data type.", "Symbol definition error.", "Regular expression error.", "TrueType Font error.", "DBASE file error.", "GD library error.", "Unknown identifier.", "Premature End-of-File.", "Projection library error.", "General error message.", "CGI error.", "Web application error.", "Image handling error.", "Hash table error.", "Join error.", "Search returned no results.", "Shapefile error.", "Expression parser error.", "SDE error.", "OGR error.", "Query error.", "WMS server error.", "WMS connection error.", "OracleSpatial error.", "WFS server error.", "WFS connection error.", "WMS Map Context error.", "HTTP request error.", "Child array error.", "WCS server error.", "GEOS library error.", "Invalid rectangle.", "Date/time error.", "GML encoding error.", "SOS server error.", "NULL parent pointer error.", "AGG library error.", "OWS error.", "OpenGL renderer error.", "Renderer error.", "V8 engine error." }; #ifndef USE_THREAD errorObj *msGetErrorObj() { static errorObj ms_error = {MS_NOERR, "", "", MS_FALSE, 0, NULL}; return &ms_error; } #endif #ifdef USE_THREAD typedef struct te_info { struct te_info *next; void* thread_id; errorObj ms_error; } te_info_t; static te_info_t *error_list = NULL; errorObj *msGetErrorObj() { te_info_t *link; void* thread_id; errorObj *ret_obj; msAcquireLock( TLOCK_ERROROBJ ); thread_id = msGetThreadId(); /* find link for this thread */ for( link = error_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} /* If the target thread link is already at the head of the list were ok */ if( error_list != NULL && error_list->thread_id == thread_id ) { } /* We don't have one ... initialize one. */ else if( link == NULL || link->next == NULL ) { te_info_t *new_link; errorObj error_obj = { MS_NOERR, "", "", 0 }; new_link = (te_info_t *) malloc(sizeof(te_info_t)); new_link->next = error_list; new_link->thread_id = thread_id; new_link->ms_error = error_obj; error_list = new_link; } /* If the link is not already at the head of the list, promote it */ else if( link != NULL && link->next != NULL ) { te_info_t *target = link->next; link->next = link->next->next; target->next = error_list; error_list = target; } ret_obj = &(error_list->ms_error); msReleaseLock( TLOCK_ERROROBJ ); return ret_obj; } #endif /* msInsertErrorObj() ** ** We maintain a chained list of errorObj in which the first errorObj is ** the most recent (i.e. a stack). msErrorReset() should be used to clear ** the list. ** ** Note that since some code in MapServer will fetch the head of the list and ** keep a handle on it for a while, the head of the chained list is static ** and never changes. ** A new errorObj is always inserted after the head, and only if the ** head of the list already contains some information. i.e. If the static ** errorObj at the head of the list is empty then it is returned directly, ** otherwise a new object is inserted after the head and the data that was in ** the head is moved to the new errorObj, freeing the head errorObj to receive ** the new error information. */ static errorObj *msInsertErrorObj(void) { errorObj *ms_error; ms_error = msGetErrorObj(); if (ms_error->code != MS_NOERR) { /* Head of the list already in use, insert a new errorObj after the head * and move head contents to this new errorObj, freeing the errorObj * for reuse. */ errorObj *new_error; new_error = (errorObj *)malloc(sizeof(errorObj)); /* Note: if malloc() failed then we simply do nothing and the head will * be overwritten by the caller... we cannot produce an error here * since we are already inside a msSetError() call. */ if (new_error) { new_error->next = ms_error->next; new_error->code = ms_error->code; new_error->isreported = ms_error->isreported; strlcpy(new_error->routine, ms_error->routine, sizeof(new_error->routine)); strlcpy(new_error->message, ms_error->message, sizeof(new_error->message)); new_error->errorcount = ms_error->errorcount; ms_error->next = new_error; ms_error->code = MS_NOERR; ms_error->isreported = MS_FALSE; ms_error->routine[0] = '\0'; ms_error->message[0] = '\0'; ms_error->errorcount = 0; } } return ms_error; } /* msResetErrorList() ** ** Clear the list of error objects. */ void msResetErrorList() { errorObj *ms_error, *this_error; ms_error = msGetErrorObj(); this_error = ms_error->next; while( this_error != NULL) { errorObj *next_error; next_error = this_error->next; msFree(this_error); this_error = next_error; } ms_error->next = NULL; ms_error->code = MS_NOERR; ms_error->routine[0] = '\0'; ms_error->message[0] = '\0'; ms_error->errorcount = 0; /* -------------------------------------------------------------------- */ /* Cleanup our entry in the thread list. This is mainly */ /* imprortant when msCleanup() calls msResetErrorList(). */ /* -------------------------------------------------------------------- */ #ifdef USE_THREAD { void* thread_id = msGetThreadId(); te_info_t *link; msAcquireLock( TLOCK_ERROROBJ ); /* find link for this thread */ for( link = error_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} if( link->thread_id == thread_id ) { /* presumably link is at head of list. */ if( error_list == link ) error_list = link->next; free( link ); } else if( link->next != NULL && link->next->thread_id == thread_id ) { te_info_t *next_link = link->next; link->next = link->next->next; free( next_link ); } msReleaseLock( TLOCK_ERROROBJ ); } #endif } char *msGetErrorCodeString(int code) { if(code<0 || code>MS_NUMERRORCODES-1) return("Invalid error code."); return(ms_errorCodes[code]); } /* -------------------------------------------------------------------- */ /* Adding the displayable error string to a given string */ /* and reallocates the memory enough to hold the characters. */ /* If source is null returns a newly allocated string */ /* -------------------------------------------------------------------- */ char *msAddErrorDisplayString(char *source, errorObj *error) { if((source = msStringConcatenate(source, error->routine)) == NULL) return(NULL); if((source = msStringConcatenate(source, ": ")) == NULL) return(NULL); if((source = msStringConcatenate(source, ms_errorCodes[error->code])) == NULL) return(NULL); if((source = msStringConcatenate(source, " ")) == NULL) return(NULL); if((source = msStringConcatenate(source, error->message)) == NULL) return(NULL); if (error->errorcount > 0) { char* pszTmp; if((source = msStringConcatenate(source, " (message repeated ")) == NULL) return(NULL); pszTmp = msIntToString(error->errorcount); if((source = msStringConcatenate(source, pszTmp)) == NULL) { msFree(pszTmp); return(NULL); } msFree(pszTmp); if((source = msStringConcatenate(source, " times)")) == NULL) return(NULL); } return source; } char *msGetErrorString(char *delimiter) { char *errstr=NULL; errorObj *error = msGetErrorObj(); if(!delimiter || !error) return(NULL); while(error && error->code != MS_NOERR) { if((errstr = msAddErrorDisplayString(errstr, error)) == NULL) return(NULL); if(error->next && error->next->code != MS_NOERR) { /* (peek ahead) more errors, use delimiter */ if((errstr = msStringConcatenate(errstr, delimiter)) == NULL) return(NULL); } error = error->next; } return(errstr); } void msSetError(int code, const char *message_fmt, const char *routine, ...) { errorObj *ms_error; va_list args; char message[MESSAGELENGTH]; if(!message_fmt) strcpy(message, ""); else { va_start(args, routine); vsnprintf( message, MESSAGELENGTH, message_fmt, args ); va_end(args); } ms_error = msGetErrorObj(); /* Insert the error to the list if it is not the same as the previous error*/ if (ms_error->code != code || !EQUAL(message, ms_error->message) || !EQUAL(routine, ms_error->routine)) { ms_error = msInsertErrorObj(); if(!routine) strcpy(ms_error->routine, ""); else { strlcpy(ms_error->routine, routine, sizeof(ms_error->routine)); } strlcpy(ms_error->message, message, sizeof(ms_error->message)); ms_error->code = code; ms_error->errorcount = 0; } else ++ms_error->errorcount; /* Log a copy of errors to MS_ERRORFILE if set (handled automatically inside msDebug()) */ msDebug("%s: %s %s\n", ms_error->routine, ms_errorCodes[ms_error->code], ms_error->message); } void msWriteError(FILE *stream) { errorObj *ms_error = msGetErrorObj(); while (ms_error && ms_error->code != MS_NOERR) { msIO_fprintf(stream, "%s: %s %s
\n", ms_error->routine, ms_errorCodes[ms_error->code], ms_error->message); ms_error->isreported = MS_TRUE; ms_error = ms_error->next; } } void msWriteErrorXML(FILE *stream) { char *message; errorObj *ms_error = msGetErrorObj(); while (ms_error && ms_error->code != MS_NOERR) { message = msEncodeHTMLEntities(ms_error->message); msIO_fprintf(stream, "%s: %s %s\n", ms_error->routine, ms_errorCodes[ms_error->code], message); ms_error->isreported = MS_TRUE; ms_error = ms_error->next; msFree(message); } } void msWriteErrorImage(mapObj *map, char *filename, int blank) { imageObj *img; int width=400, height=300; int nMargin =5; int nTextLength = 0; int nUsableWidth = 0; int nMaxCharsPerLine = 0; int nLines = 0; int i = 0; int nStart = 0; int nEnd = 0; int nLength = 0; char **papszLines = NULL; pointObj pnt; int nWidthTxt = 0; outputFormatObj *format = NULL; char *errormsg = msGetErrorString("; "); errorObj *error = msGetErrorObj(); char *imagepath = NULL, *imageurl = NULL; colorObj imagecolor, *imagecolorptr=NULL; textSymbolObj ts; labelObj label; int charWidth = 5, charHeight = 8; /* hardcoded, should be looked up from ft face */ if(!errormsg) { errormsg = msStrdup("No error found sorry. This is likely a bug"); } if (map) { if( map->width > 0 && map->height > 0 ) { width = map->width; height = map->height; } format = map->outputformat; imagepath = map->web.imagepath; imageurl = map->web.imageurl; } /* Default to GIF if no suitable GD output format set */ if (format == NULL || !MS_RENDERER_PLUGIN(format)) format = msCreateDefaultOutputFormat( NULL, "AGG/PNG8", "png" ); if(!format->transparent) { if(map && MS_VALID_COLOR(map->imagecolor)) { imagecolorptr = &map->imagecolor; } else { MS_INIT_COLOR(imagecolor,255,255,255,255); imagecolorptr = &imagecolor; } } img = msImageCreate(width,height,format,imagepath,imageurl,MS_DEFAULT_RESOLUTION,MS_DEFAULT_RESOLUTION,imagecolorptr); nTextLength = strlen(errormsg); nWidthTxt = nTextLength * charWidth; nUsableWidth = width - (nMargin*2); /* Check to see if it all fits on one line. If not, split the text on several lines. */ if(!blank) { if (nWidthTxt > nUsableWidth) { nMaxCharsPerLine = nUsableWidth/charWidth; nLines = (int) ceil ((double)nTextLength / (double)nMaxCharsPerLine); if (nLines > 0) { papszLines = (char **)malloc(nLines*sizeof(char *)); for (i=0; i nTextLength) nEnd = nTextLength; nLength = nEnd-nStart; strncpy(papszLines[i], errormsg+nStart, nLength); papszLines[i][nLength] = '\0'; } } } else { nLines = 1; papszLines = (char **)malloc(nLines*sizeof(char *)); papszLines[0] = msStrdup(errormsg); } initLabel(&label); MS_INIT_COLOR(label.color,0,0,0,255); MS_INIT_COLOR(label.outlinecolor,255,255,255,255); label.outlinewidth = 1; label.size = MS_SMALL; MS_REFCNT_INCR((&label)); for (i=0; icode != MS_NOERR) { error->isreported = MS_TRUE; error = error->next; } if (format->refcount == 0) msFreeOutputFormat(format); msFree(errormsg); } char *msGetVersion() { static char version[1024]; sprintf(version, "MapServer version %s", MS_VERSION); #if (defined USE_PNG) strcat(version, " OUTPUT=PNG"); #endif #if (defined USE_JPEG) strcat(version, " OUTPUT=JPEG"); #endif #ifdef USE_KML strcat(version, " OUTPUT=KML"); #endif #ifdef USE_PROJ strcat(version, " SUPPORTS=PROJ"); #endif strcat(version, " SUPPORTS=AGG"); strcat(version, " SUPPORTS=FREETYPE"); #ifdef USE_CAIRO strcat(version, " SUPPORTS=CAIRO"); #endif #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) strcat(version, " SUPPORTS=SVG_SYMBOLS"); #ifdef USE_SVG_CAIRO strcat(version, " SUPPORTS=SVGCAIRO"); #else strcat(version, " SUPPORTS=RSVG"); #endif #endif #ifdef USE_OGL strcat(version, " SUPPORTS=OPENGL"); #endif #ifdef USE_ICONV strcat(version, " SUPPORTS=ICONV"); #endif #ifdef USE_EXEMPI strcat(version, " SUPPORTS=XMP"); #endif #ifdef USE_FRIBIDI strcat(version, " SUPPORTS=FRIBIDI"); #endif #ifdef USE_WMS_SVR strcat(version, " SUPPORTS=WMS_SERVER"); #endif #ifdef USE_WMS_LYR strcat(version, " SUPPORTS=WMS_CLIENT"); #endif #ifdef USE_WFS_SVR strcat(version, " SUPPORTS=WFS_SERVER"); #endif #ifdef USE_WFS_LYR strcat(version, " SUPPORTS=WFS_CLIENT"); #endif #ifdef USE_WCS_SVR strcat(version, " SUPPORTS=WCS_SERVER"); #endif #ifdef USE_SOS_SVR strcat(version, " SUPPORTS=SOS_SERVER"); #endif #ifdef USE_FASTCGI strcat(version, " SUPPORTS=FASTCGI"); #endif #ifdef USE_THREAD strcat(version, " SUPPORTS=THREADS"); #endif #ifdef USE_GEOS strcat(version, " SUPPORTS=GEOS"); #endif #ifdef USE_POINT_Z_M strcat(version, " SUPPORTS=POINT_Z_M"); #endif #ifdef USE_V8_MAPSCRIPT strcat(version, " SUPPORTS=V8"); #endif #ifdef USE_PBF strcat(version, " SUPPORTS=PBF"); #endif #ifdef USE_JPEG strcat(version, " INPUT=JPEG"); #endif #ifdef USE_SDE strcat(version, " INPUT=SDE"); #endif #ifdef USE_POSTGIS strcat(version, " INPUT=POSTGIS"); #endif #ifdef USE_ORACLESPATIAL strcat(version, " INPUT=ORACLESPATIAL"); #endif #ifdef USE_OGR strcat(version, " INPUT=OGR"); #endif #ifdef USE_GDAL strcat(version, " INPUT=GDAL"); #endif strcat(version, " INPUT=SHAPEFILE"); return(version); } int msGetVersionInt() { return MS_VERSION_NUM; } mapserver-7.4.3/maperror.h000066400000000000000000000144021357574274700155570ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations for Error and Debug functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPERROR_H #define MAPERROR_H #include "mapthread.h" #ifdef __cplusplus extern "C" { #endif /*==================================================================== * maperror.c *====================================================================*/ #define MS_NOERR 0 /* general error codes */ #define MS_IOERR 1 #define MS_MEMERR 2 #define MS_TYPEERR 3 #define MS_SYMERR 4 #define MS_REGEXERR 5 #define MS_TTFERR 6 #define MS_DBFERR 7 #define MS_IDENTERR 9 #define MS_EOFERR 10 #define MS_PROJERR 11 #define MS_MISCERR 12 #define MS_CGIERR 13 #define MS_WEBERR 14 #define MS_IMGERR 15 #define MS_HASHERR 16 #define MS_JOINERR 17 #define MS_NOTFOUND 18 /* empty search results */ #define MS_SHPERR 19 #define MS_PARSEERR 20 #define MS_UNUSEDERR 21 #define MS_OGRERR 22 #define MS_QUERYERR 23 #define MS_WMSERR 24 /* WMS server error */ #define MS_WMSCONNERR 25 /* WMS connectiontype error */ #define MS_ORACLESPATIALERR 26 #define MS_WFSERR 27 /* WFS server error */ #define MS_WFSCONNERR 28 /* WFS connectiontype error */ #define MS_MAPCONTEXTERR 29 /* Map Context error */ #define MS_HTTPERR 30 #define MS_CHILDERR 31 /* Errors involving arrays of child objects */ #define MS_WCSERR 32 #define MS_GEOSERR 33 #define MS_RECTERR 34 #define MS_TIMEERR 35 #define MS_GMLERR 36 #define MS_SOSERR 37 #define MS_NULLPARENTERR 38 #define MS_AGGERR 39 #define MS_OWSERR 40 #define MS_OGLERR 41 #define MS_RENDERERERR 42 #define MS_V8ERR 43 #define MS_NUMERRORCODES 44 #define MESSAGELENGTH 2048 #define ROUTINELENGTH 64 #define MS_ERROR_LANGUAGE "en-US" #if defined(_WIN32) && !defined(__CYGWIN__) # define MS_DLL_EXPORT __declspec(dllexport) #else #define MS_DLL_EXPORT #endif #ifndef MS_PRINT_FUNC_FORMAT #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP) #define MS_PRINT_FUNC_FORMAT( format_idx, arg_idx ) __attribute__((__format__ (__printf__, format_idx, arg_idx))) #else #define MS_PRINT_FUNC_FORMAT( format_idx, arg_idx ) #endif #endif typedef struct errorObj { int code; char routine[ROUTINELENGTH]; char message[MESSAGELENGTH]; int isreported; int errorcount; /* number of subsequent errors */ #ifndef SWIG struct errorObj *next; #endif } errorObj; /* ** Function prototypes */ MS_DLL_EXPORT errorObj *msGetErrorObj(void); MS_DLL_EXPORT void msResetErrorList(void); MS_DLL_EXPORT char *msGetVersion(void); MS_DLL_EXPORT int msGetVersionInt(void); MS_DLL_EXPORT char *msGetErrorString(char *delimiter); #ifndef SWIG MS_DLL_EXPORT void msSetError(int code, const char *message, const char *routine, ...) MS_PRINT_FUNC_FORMAT(2,4) ; MS_DLL_EXPORT void msWriteError(FILE *stream); MS_DLL_EXPORT void msWriteErrorXML(FILE *stream); MS_DLL_EXPORT char *msGetErrorCodeString(int code); MS_DLL_EXPORT char *msAddErrorDisplayString(char *source, errorObj *error); struct mapObj; MS_DLL_EXPORT void msWriteErrorImage(struct mapObj *map, char *filename, int blank); #endif /* SWIG */ /*==================================================================== * mapdebug.c (See also MS-RFC-28) *====================================================================*/ typedef enum { MS_DEBUGLEVEL_ERRORSONLY = 0, /* DEBUG OFF, log fatal errors */ MS_DEBUGLEVEL_DEBUG = 1, /* DEBUG ON */ MS_DEBUGLEVEL_TUNING = 2, /* Reports timing info */ MS_DEBUGLEVEL_V = 3, /* Verbose */ MS_DEBUGLEVEL_VV = 4, /* Very verbose */ MS_DEBUGLEVEL_VVV = 5, /* Very very verbose */ MS_DEBUGLEVEL_DEVDEBUG = 20, /* Undocumented, will trigger debug messages only useful for developers */ } debugLevel; #ifndef SWIG typedef enum { MS_DEBUGMODE_OFF, MS_DEBUGMODE_FILE, MS_DEBUGMODE_STDERR, MS_DEBUGMODE_STDOUT, MS_DEBUGMODE_WINDOWSDEBUG } debugMode; typedef struct debug_info_obj { debugLevel global_debug_level; debugMode debug_mode; char *errorfile; FILE *fp; /* The following 2 members are used only with USE_THREAD (but we won't #ifndef them) */ void* thread_id; struct debug_info_obj *next; } debugInfoObj; MS_DLL_EXPORT void msDebug( const char * pszFormat, ... ) MS_PRINT_FUNC_FORMAT(1,2) ; MS_DLL_EXPORT int msSetErrorFile(const char *pszErrorFile, const char *pszRelToPath); MS_DLL_EXPORT void msCloseErrorFile( void ); MS_DLL_EXPORT const char *msGetErrorFile( void ); MS_DLL_EXPORT void msSetGlobalDebugLevel(int level); MS_DLL_EXPORT debugLevel msGetGlobalDebugLevel( void ); MS_DLL_EXPORT int msDebugInitFromEnv( void ); MS_DLL_EXPORT void msDebugCleanup( void ); #endif /* SWIG */ #ifdef __cplusplus } #endif #endif /* MAPERROR_H */ mapserver-7.4.3/mapfile.c000066400000000000000000007570661357574274700153640ustar00rootroot00000000000000/****************************************************************************** * $id: mapfile.c 7854 2008-08-14 19:22:48Z dmorissette $ * * Project: MapServer * Purpose: High level Map file parsing code. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include "mapserver.h" #include "mapfile.h" #include "mapthread.h" #include "maptime.h" #ifdef USE_GDAL # include "cpl_conv.h" # include "gdal.h" #endif extern int msyylex(void); extern void msyyrestart(FILE *); extern int msyylex_destroy(void); extern double msyynumber; extern int msyylineno; extern FILE *msyyin; extern int msyysource; extern int msyystate; extern char *msyystring; extern char *msyybasepath; extern int msyyreturncomments; extern char *msyystring_buffer; extern int msyystring_icase; extern int loadSymbol(symbolObj *s, char *symbolpath); /* in mapsymbol.c */ extern void writeSymbol(symbolObj *s, FILE *stream); /* in mapsymbol.c */ static int loadGrid( layerObj *pLayer ); static int loadStyle(styleObj *style); static void writeStyle(FILE* stream, int indent, styleObj *style); static int resolveSymbolNames(mapObj *map); static int loadExpression(expressionObj *exp); static void writeExpression(FILE *stream, int indent, const char *name, expressionObj *exp); /* ** Symbol to string static arrays needed for writing map files. ** Must be kept in sync with enumerations and defines found in mapserver.h. */ /* static char *msUnits[9]={"INCHES", "FEET", "MILES", "METERS", "KILOMETERS", "DD", "PIXELS", "PERCENTAGES", "NAUTICALMILES"}; */ /* static char *msLayerTypes[10]={"POINT", "LINE", "POLYGON", "RASTER", "ANNOTATION", "QUERY", "CIRCLE", "TILEINDEX","CHART"}; */ char *msPositionsText[MS_POSITIONS_LENGTH] = {"UL", "LR", "UR", "LL", "CR", "CL", "UC", "LC", "CC", "AUTO", "XY", "FOLLOW"}; /* msLabelPositions[] also used in mapsymbols.c (not static) */ /* static char *msBitmapFontSizes[5]={"TINY", "SMALL", "MEDIUM", "LARGE", "GIANT"}; */ /* static char *msQueryMapStyles[4]={"NORMAL", "HILITE", "SELECTED", "INVERTED"}; */ /* static char *msStatus[4]={"OFF", "ON", "DEFAULT", "EMBED"}; */ /* static char *msOnOff[2]={"OFF", "ON"}; */ /* static char *msTrueFalse[2]={"FALSE", "TRUE"}; */ /* static char *msYesNo[2]={"NO", "YES"}; */ /* static char *msJoinType[2]={"ONE-TO-ONE", "ONE-TO-MANY"}; */ /* static char *msAlignValue[3]={"LEFT","CENTER","RIGHT"}; */ /* ** Validates a string (value) against a series of patterns. We support up to four to allow cascading from classObj to ** layerObj to webObj plus a legacy pattern like TEMPLATEPATTERN. */ int msValidateParameter(const char *value, const char *pattern1, const char *pattern2, const char *pattern3, const char *pattern4) { if(msEvalRegex(pattern1, value) == MS_TRUE) return MS_SUCCESS; if(msEvalRegex(pattern2, value) == MS_TRUE) return MS_SUCCESS; if(msEvalRegex(pattern3, value) == MS_TRUE) return MS_SUCCESS; if(msEvalRegex(pattern4, value) == MS_TRUE) return MS_SUCCESS; return(MS_FAILURE); } int msEvalRegex(const char *e, const char *s) { ms_regex_t re; if(!e || !s) return(MS_FALSE); if(ms_regcomp(&re, e, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e); return(MS_FALSE); } if(ms_regexec(&re, s, 0, NULL, 0) != 0) { /* no match */ ms_regfree(&re); return(MS_FALSE); } ms_regfree(&re); return(MS_TRUE); } #ifdef USE_MSFREE void msFree(void *p) { if(p) free(p); } #endif /* ** Free memory allocated for a character array */ void msFreeCharArray(char **array, int num_items) { int i; if(!array) return; for(i=0; iconfigoptions), "MS_PLUGIN_DIR"); /* do nothing on windows, filename without .dll will be loaded by default*/ #if !defined(_WIN32) if (lib_str) { size_t len = strlen(lib_str); if (3 < len && strcmp(lib_str + len-3, ".so")) { strlcpy(szLibPathExt, lib_str, MS_MAXPATHLEN); strlcat(szLibPathExt, ".so", MS_MAXPATHLEN); lib_str = szLibPathExt; } } #endif /* !defined(_WIN32) */ if (NULL == msBuildPath(szLibPath, plugin_dir, lib_str)) { return MS_FAILURE; } *dest = msStrdup(szLibPath); return MS_SUCCESS; } /* ** Returns the index of specified symbol or -1 if not found. ** ** If try_addimage_if_notfound==MS_TRUE then msAddImageSymbol() will be called ** to try to allocate the symbol as an image symbol. */ int msGetSymbolIndex(symbolSetObj *symbols, char *name, int try_addimage_if_notfound) { int i; if(!symbols || !name) return(-1); /* symbol 0 has no name */ for(i=1; inumsymbols; i++) { if(symbols->symbol[i]->name) if(strcasecmp(symbols->symbol[i]->name, name) == 0) return(i); } if (try_addimage_if_notfound) return(msAddImageSymbol(symbols, name)); /* make sure it's not a filename */ return(-1); } /* ** Return the index number for a given layer based on its name. */ int msGetLayerIndex(mapObj *map, const char *name) { int i; if(!name) return(-1); for(i=0; inumlayers; i++) { if(!GET_LAYER(map, i)->name) /* skip it */ continue; if(strcmp(name, GET_LAYER(map, i)->name) == 0) return(i); } return(-1); } static int msGetClassIndex(layerObj *layer, const char *name) { int i; if(!name) return(-1); for(i=0; inumclasses; i++) { if(!layer->class[i]->name) /* skip it */ continue; if(strcmp(name, layer->class[i]->name) == 0) return(i); } return(-1); } int loadColor(colorObj *color, attributeBindingObj *binding) { int symbol; char hex[2]; if(binding) { if((symbol = getSymbol(3, MS_NUMBER, MS_BINDING, MS_STRING)) == -1) return MS_FAILURE; } else { if((symbol = getSymbol(2, MS_NUMBER, MS_STRING)) == -1) return MS_FAILURE; } color->alpha=255; if(symbol == MS_NUMBER) { color->red = (int) msyynumber; if(getInteger(&(color->green)) == -1) return MS_FAILURE; if(getInteger(&(color->blue)) == -1) return MS_FAILURE; } else if(symbol == MS_STRING) { int len = strlen(msyystring_buffer); if(msyystring_buffer[0] == '#' && (len == 7 || len == 9)) { /* got a hex color w/optional alpha */ hex[0] = msyystring_buffer[1]; hex[1] = msyystring_buffer[2]; color->red = msHexToInt(hex); hex[0] = msyystring_buffer[3]; hex[1] = msyystring_buffer[4]; color->green = msHexToInt(hex); hex[0] = msyystring_buffer[5]; hex[1] = msyystring_buffer[6]; color->blue = msHexToInt(hex); if(len == 9) { hex[0] = msyystring_buffer[7]; hex[1] = msyystring_buffer[8]; color->alpha = msHexToInt(hex); } } else { /* TODO: consider named colors here */ msSetError(MS_SYMERR, "Invalid hex color (%s):(line %d)", "loadColor()", msyystring_buffer, msyylineno); return MS_FAILURE; } } else { binding->item = msStrdup(msyystring_buffer); binding->index = -1; } return MS_SUCCESS; } #if ALPHACOLOR_ENABLED int loadColorWithAlpha(colorObj *color) { char hex[2]; if(getInteger(&(color->red)) == -1) { if(msyystring_buffer[0] == '#' && strlen(msyystring_buffer) == 7) { /* got a hex color */ hex[0] = msyystring_buffer[1]; hex[1] = msyystring_buffer[2]; color->red = msHexToInt(hex); hex[0] = msyystring_buffer[3]; hex[1] = msyystring_buffer[4]; color->green = msHexToInt(hex); hex[0] = msyystring_buffer[5]; hex[1] = msyystring_buffer[6]; color->blue = msHexToInt(hex); color->alpha = 0; return(MS_SUCCESS); } else if(msyystring_buffer[0] == '#' && strlen(msyystring_buffer) == 9) { /* got a hex color with alpha */ hex[0] = msyystring_buffer[1]; hex[1] = msyystring_buffer[2]; color->red = msHexToInt(hex); hex[0] = msyystring_buffer[3]; hex[1] = msyystring_buffer[4]; color->green = msHexToInt(hex); hex[0] = msyystring_buffer[5]; hex[1] = msyystring_buffer[6]; color->blue = msHexToInt(hex); hex[0] = msyystring_buffer[7]; hex[1] = msyystring_buffer[8]; color->alpha = msHexToInt(hex); return(MS_SUCCESS); } return(MS_FAILURE); } if(getInteger(&(color->green)) == -1) return(MS_FAILURE); if(getInteger(&(color->blue)) == -1) return(MS_FAILURE); if(getInteger(&(color->alpha)) == -1) return(MS_FAILURE); return(MS_SUCCESS); } #endif /* ** Helper functions for writing mapfiles. */ static void writeLineFeed(FILE *stream) { msIO_fprintf(stream, "\n"); } static void writeIndent(FILE *stream, int indent) { const char *str=" "; /* change this string to define the indent */ int i; for(i=0; iitem) return; writeIndent(stream, ++indent); msIO_fprintf(stream, "%s [%s]\n", name, binding->item); } static void writeColor(FILE *stream, int indent, const char *name, colorObj *defaultColor, colorObj *color) { if (!defaultColor && !MS_VALID_COLOR(*color)) return; else if(defaultColor && MS_COMPARE_COLOR(*defaultColor, *color)) return; /* if defaultColor has the same value than the color, return.*/ writeIndent(stream, ++indent); #if ALPHACOLOR_ENABLED msIO_fprintf(stream, "%s %d %d %d\n", name, color->red, color->green, color->blue, color->alpha); #else if(color->alpha != 255) { char buffer[9]; sprintf(buffer, "%02x", color->red); sprintf(buffer+2, "%02x", color->green); sprintf(buffer+4, "%02x", color->blue); sprintf(buffer+6, "%02x", color->alpha); *(buffer+8) = 0; msIO_fprintf(stream, "%s \"#%s\"\n", name, buffer); } else { msIO_fprintf(stream, "%s %d %d %d\n", name, color->red, color->green, color->blue); } #endif } /* todo: deal with alpha's... */ static void writeColorRange(FILE *stream, int indent, const char *name, colorObj *mincolor, colorObj *maxcolor) { if(!MS_VALID_COLOR(*mincolor) || !MS_VALID_COLOR(*maxcolor)) return; writeIndent(stream, ++indent); msIO_fprintf(stream, "%s %d %d %d %d %d %d\n", name, mincolor->red, mincolor->green, mincolor->blue, maxcolor->red, maxcolor->green, maxcolor->blue); } /* ** Initialize, load and free a single join */ void initJoin(joinObj *join) { join->numitems = 0; join->name = NULL; /* unique join name, used for variable substitution */ join->items = NULL; /* array to hold item names for the joined table */ join->values = NULL; /* arrays of strings to holds one record worth of data */ join->table = NULL; join->joininfo = NULL; join->from = NULL; /* join items */ join->to = NULL; join->header = NULL; join->template = NULL; /* only html type templates are supported */ join->footer = NULL; join->type = MS_JOIN_ONE_TO_ONE; join->connection = NULL; join->connectiontype = MS_DB_XBASE; } void freeJoin(joinObj *join) { msFree(join->name); msFree(join->table); msFree(join->from); msFree(join->to); msFree(join->header); msFree(join->template); msFree(join->footer); msFreeCharArray(join->items, join->numitems); /* these may have been free'd elsewhere */ msFreeCharArray(join->values, join->numitems); join->numitems = 0; msJoinClose(join); msFree(join->connection); } int loadJoin(joinObj *join) { int nTmp; initJoin(join); for(;;) { switch(msyylex()) { case(CONNECTION): if(getString(&join->connection) == MS_FAILURE) return(-1); break; case(CONNECTIONTYPE): if((nTmp = getSymbol(5, MS_DB_XBASE, MS_DB_MYSQL, MS_DB_ORACLE, MS_DB_POSTGRES, MS_DB_CSV)) == -1) return(-1); join->connectiontype = nTmp; break; case(EOF): msSetError(MS_EOFERR, NULL, "loadJoin()"); return(-1); case(END): if((join->from == NULL) || (join->to == NULL) || (join->table == NULL)) { msSetError(MS_EOFERR, "Join must define table, name, from and to properties.", "loadJoin()"); return(-1); } if((join->type == MS_MULTIPLE) && ((join->template == NULL) || (join->name == NULL))) { msSetError(MS_EOFERR, "One-to-many joins must define template and name properties.", "loadJoin()"); return(-1); } return(0); case(FOOTER): if(getString(&join->footer) == MS_FAILURE) return(-1); break; case(FROM): if(getString(&join->from) == MS_FAILURE) return(-1); break; case(HEADER): if(getString(&join->header) == MS_FAILURE) return(-1); break; case(JOIN): break; /* for string loads */ case(NAME): if(getString(&join->name) == MS_FAILURE) return(-1); break; case(TABLE): if(getString(&join->table) == MS_FAILURE) return(-1); break; case(TEMPLATE): if(getString(&join->template) == MS_FAILURE) return(-1); break; case(TO): if(getString(&join->to) == MS_FAILURE) return(-1); break; case(TYPE): if((nTmp = getSymbol(2, MS_JOIN_ONE_TO_ONE, MS_JOIN_ONE_TO_MANY)) == -1) return(-1); join->type = nTmp; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadJoin()", msyystring_buffer, msyylineno); return(-1); } } /* next token */ } static void writeScaleToken(FILE *stream, int indent, scaleTokenObj *token) { int i; indent++; writeBlockBegin(stream,indent,"SCALETOKEN"); writeString(stream, indent, "NAME", NULL, token->name); indent++; writeBlockBegin(stream,indent,"VALUES"); for(i=0;in_entries;i++) { char minscale[32]; sprintf(minscale,"%g",token->tokens[i].minscale); writeNameValuePair(stream, indent, minscale, token->tokens[i].value); } writeBlockEnd(stream,indent,"VALUES"); indent--; writeBlockEnd(stream,indent,"SCALETOKEN"); } static void writeJoin(FILE *stream, int indent, joinObj *join) { indent++; writeBlockBegin(stream, indent, "JOIN"); writeString(stream, indent, "FOOTER", NULL, join->footer); writeString(stream, indent, "FROM", NULL, join->from); writeString(stream, indent, "HEADER", NULL, join->header); writeString(stream, indent, "NAME", NULL, join->name); writeString(stream, indent, "TABLE", NULL, join->table); writeString(stream, indent, "TEMPLATE", NULL, join->template); writeString(stream, indent, "TO", NULL, join->to); writeKeyword(stream, indent, "CONNECTIONTYPE", join->connectiontype, 3, MS_DB_CSV, "CSV", MS_DB_POSTGRES, "POSTRESQL", MS_DB_MYSQL, "MYSQL"); writeKeyword(stream, indent, "TYPE", join->type, 1, MS_JOIN_ONE_TO_MANY, "ONE-TO-MANY"); writeBlockEnd(stream, indent, "JOIN"); } /* inserts a feature at the end of the list, can create a new list */ featureListNodeObjPtr insertFeatureList(featureListNodeObjPtr *list, shapeObj *shape) { featureListNodeObjPtr node; node = (featureListNodeObjPtr) msSmallMalloc(sizeof(featureListNodeObj)); msInitShape(&(node->shape)); if(msCopyShape(shape, &(node->shape)) == -1) { msFree(node); return(NULL); } /* AJS - alans@wunderground.com O(n^2) -> O(n) conversion, keep a pointer to the end */ /* set the tailifhead to NULL, since it is only set for the head of the list */ node->tailifhead = NULL; node->next = NULL; /* if we are at the head of the list, we need to set the list to node, before pointing tailifhead somewhere */ if(*list == NULL) { *list=node; } else { if((*list)->tailifhead!=NULL) /* this should never be NULL, but just in case */ (*list)->tailifhead->next=node; /* put the node at the end of the list */ } /* repoint the head of the list to the end - our new element this causes a loop if we are at the head, be careful not to walk in a loop */ (*list)->tailifhead = node; return(node); /* a pointer to last object in the list */ } void freeFeatureList(featureListNodeObjPtr list) { featureListNodeObjPtr listNext = NULL; while (list!=NULL) { listNext = list->next; msFreeShape(&(list->shape)); msFree(list); list = listNext; } } /* lineObj = multipointObj */ static int loadFeaturePoints(lineObj *points) { int buffer_size=0; points->point = (pointObj *)malloc(sizeof(pointObj)*MS_FEATUREINITSIZE); MS_CHECK_ALLOC(points->point, sizeof(pointObj)*MS_FEATUREINITSIZE, MS_FAILURE); points->numpoints = 0; buffer_size = MS_FEATUREINITSIZE; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadFeaturePoints()"); return(MS_FAILURE); case(END): return(MS_SUCCESS); case(MS_NUMBER): if(points->numpoints == buffer_size) { /* just add it to the end */ points->point = (pointObj *) realloc(points->point, sizeof(pointObj)*(buffer_size+MS_FEATUREINCREMENT)); MS_CHECK_ALLOC(points->point, sizeof(pointObj)*(buffer_size+MS_FEATUREINCREMENT), MS_FAILURE); buffer_size+=MS_FEATUREINCREMENT; } points->point[points->numpoints].x = atof(msyystring_buffer); if(getDouble(&(points->point[points->numpoints].y)) == -1) return(MS_FAILURE); points->numpoints++; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadFeaturePoints()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } } static int loadFeature(layerObj *player, int type) { int status=MS_SUCCESS; featureListNodeObjPtr *list = &(player->features); multipointObj points= {0,NULL}; shapeObj *shape=NULL; shape = (shapeObj *) malloc(sizeof(shapeObj)); MS_CHECK_ALLOC(shape, sizeof(shapeObj), MS_FAILURE); msInitShape(shape); shape->type = type; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadFeature()"); msFreeShape(shape); /* clean up */ msFree(shape); return(MS_FAILURE); case(END): if(player->features != NULL && player->features->tailifhead != NULL) shape->index = player->features->tailifhead->shape.index + 1; else shape->index = 0; if(insertFeatureList(list, shape) == NULL) status = MS_FAILURE; msFreeShape(shape); /* clean up */ msFree(shape); return(status); case(FEATURE): break; /* for string loads */ case(POINTS): if(loadFeaturePoints(&points) == MS_FAILURE) { msFreeShape(shape); /* clean up */ msFree(shape); return(MS_FAILURE); } status = msAddLine(shape, &points); msFree(points.point); /* clean up */ points.numpoints = 0; if(status == MS_FAILURE) { msFreeShape(shape); /* clean up */ msFree(shape); return(MS_FAILURE); } break; case(ITEMS): { char *string=NULL; if(getString(&string) == MS_FAILURE) { msFreeShape(shape); /* clean up */ msFree(shape); return(MS_FAILURE); } if (string) { if(shape->values) msFreeCharArray(shape->values, shape->numvalues); shape->values = msStringSplitComplex(string, ";", &shape->numvalues,MS_ALLOWEMPTYTOKENS); msFree(string); /* clean up */ } break; } case(TEXT): if(getString(&shape->text) == MS_FAILURE) { msFreeShape(shape); /* clean up */ msFree(shape); return(MS_FAILURE); } break; case(WKT): { char *string=NULL; /* todo, what do we do with multiple WKT property occurances? */ msFreeShape(shape); msFree(shape); if(getString(&string) == MS_FAILURE) return(MS_FAILURE); if((shape = msShapeFromWKT(string)) == NULL) status = MS_FAILURE; msFree(string); /* clean up */ if(status == MS_FAILURE) { msFreeShape(shape); /* clean up */ msFree(shape); return(MS_FAILURE); } break; } default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadfeature()", msyystring_buffer, msyylineno); msFreeShape(shape); /* clean up */ msFree(shape); return(MS_FAILURE); } } /* next token */ } static void writeFeature(FILE *stream, int indent, shapeObj *feature) { int i,j; indent++; writeBlockBegin(stream, indent, "FEATURE"); indent++; for(i=0; inumlines; i++) { writeBlockBegin(stream, indent, "POINTS"); for(j=0; jline[i].numpoints; j++) { writeIndent(stream, indent); msIO_fprintf(stream, "%.15g %.15g\n", feature->line[i].point[j].x, feature->line[i].point[j].y); } writeBlockEnd(stream, indent, "POINTS"); } indent--; if (feature->numvalues) { writeIndent(stream, indent); msIO_fprintf(stream, "ITEMS \""); for (i=0; inumvalues; i++) { if (i == 0) msIO_fprintf(stream, "%s", feature->values[i]); else msIO_fprintf(stream, ";%s", feature->values[i]); } msIO_fprintf(stream, "\"\n"); } writeString(stream, indent, "TEXT", NULL, feature->text); writeBlockEnd(stream, indent, "FEATURE"); } void initGrid( graticuleObj *pGraticule ) { memset( pGraticule, 0, sizeof( graticuleObj ) ); } void freeGrid( graticuleObj *pGraticule ) { msFree(pGraticule->labelformat); msFree(pGraticule->pboundingpoints); msFree(pGraticule->pboundinglines); } static int loadGrid( layerObj *pLayer ) { for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadGrid()"); return(-1); case(END): return(0); case(GRID): break; /* for string loads */ case( LABELFORMAT ): if(getString(&(pLayer->grid->labelformat)) == MS_FAILURE) { if(strcasecmp(msyystring_buffer, "DD") == 0) /* DD triggers a symbol to be returned instead of a string so check for this special case */ pLayer->grid->labelformat = msStrdup("DD"); else return(-1); } break; case( MINARCS ): if(getDouble(&(pLayer->grid->minarcs)) == -1) return(-1); break; case( MAXARCS ): if(getDouble(&(pLayer->grid->maxarcs)) == -1) return(-1); break; case( MININTERVAL ): if(getDouble(&(pLayer->grid->minincrement)) == -1) return(-1); break; case( MAXINTERVAL ): if(getDouble(&(pLayer->grid->maxincrement)) == -1) return(-1); break; case( MINSUBDIVIDE ): if(getDouble(&(pLayer->grid->minsubdivides)) == -1) return(-1); break; case( MAXSUBDIVIDE ): if(getDouble(&(pLayer->grid->maxsubdivides)) == -1) return(-1); break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadGrid()", msyystring_buffer, msyylineno); return(-1); } } } static void writeGrid(FILE *stream, int indent, graticuleObj *pGraticule) { if(!pGraticule) return; indent++; writeBlockBegin(stream, indent, "GRID"); writeString(stream, indent, "LABELFORMAT", NULL, pGraticule->labelformat); writeNumber(stream, indent, "MAXARCS", 0, pGraticule->maxarcs); writeNumber(stream, indent, "MAXSUBDIVIDE", 0, pGraticule->maxsubdivides); writeNumber(stream, indent, "MAXINTERVAL", 0, pGraticule->maxincrement); writeNumber(stream, indent, "MINARCS", 0, pGraticule->minarcs); writeNumber(stream, indent, "MININTERVAL", 0, pGraticule->minincrement); writeNumber(stream, indent, "MINSUBDIVIDE", 0, pGraticule->minsubdivides); writeBlockEnd(stream, indent, "GRID"); } /* ** Initialize, load and free a projectionObj structure */ int msInitProjection(projectionObj *p) { p->gt.need_geotransform = MS_FALSE; p->numargs = 0; p->args = NULL; p->wellknownprojection = wkp_none; #ifdef USE_PROJ p->proj = NULL; p->args = (char **)malloc(MS_MAXPROJARGS*sizeof(char *)); MS_CHECK_ALLOC(p->args, MS_MAXPROJARGS*sizeof(char *), -1); #if PJ_VERSION >= 480 p->proj_ctx = NULL; #endif #endif return(0); } void msFreeProjection(projectionObj *p) { #ifdef USE_PROJ if(p->proj) { pj_free(p->proj); p->proj = NULL; } #if PJ_VERSION >= 480 if(p->proj_ctx) { pj_ctx_free(p->proj_ctx); p->proj_ctx = NULL; } #endif msFreeCharArray(p->args, p->numargs); p->args = NULL; p->numargs = 0; #endif } /* ** Handle OGC WMS/WFS AUTO projection in the format: ** "AUTO:proj_id,units_id,lon0,lat0" */ #ifdef USE_PROJ static int _msProcessAutoProjection(projectionObj *p) { char **args; int numargs, nProjId, nUnitsId, nZone; double dLat0, dLon0; const char *pszUnits = "m"; char szProjBuf[512]=""; /* WMS/WFS AUTO projection: "AUTO:proj_id,units_id,lon0,lat0" */ args = msStringSplit(p->args[0], ',', &numargs); if (numargs != 4 || (strncasecmp(args[0], "AUTO:", 5) != 0 && strncasecmp(args[0], "AUTO2:", 6) != 0)) { msSetError(MS_PROJERR, "WMS/WFS AUTO/AUTO2 PROJECTION must be in the format " "'AUTO:proj_id,units_id,lon0,lat0' or 'AUTO2:crs_id,factor,lon0,lat0'(got '%s').\n", "_msProcessAutoProjection()", p->args[0]); return -1; } if (strncasecmp(args[0], "AUTO:", 5)==0) nProjId = atoi(args[0]+5); else nProjId = atoi(args[0]+6); nUnitsId = atoi(args[1]); dLon0 = atof(args[2]); dLat0 = atof(args[3]); /*There is no unit parameter for AUTO2. The 2nd parameter is factor. Set the units to always be meter*/ if (strncasecmp(args[0], "AUTO2:", 6) == 0) nUnitsId = 9001; msFreeCharArray(args, numargs); /* Handle EPSG Units. Only meters for now. */ switch(nUnitsId) { case 9001: /* Meters */ pszUnits = "m"; break; default: msSetError(MS_PROJERR, "WMS/WFS AUTO PROJECTION: EPSG Units %d not supported.\n", "_msProcessAutoProjection()", nUnitsId); return -1; } /* Build PROJ4 definition. * This is based on the definitions found in annex E of the WMS 1.1.1 * spec and online at http://www.digitalearth.org/wmt/auto.html * The conversion from the original WKT definitions to PROJ4 format was * done using the MapScript setWKTProjection() function (based on OGR). */ switch(nProjId) { case 42001: /** WGS 84 / Auto UTM **/ nZone = (int) floor( (dLon0 + 180.0) / 6.0 ) + 1; sprintf( szProjBuf, "+proj=tmerc+lat_0=0+lon_0=%.16g+k=0.999600+x_0=500000" "+y_0=%.16g+ellps=WGS84+datum=WGS84+units=%s", -183.0 + nZone * 6.0, (dLat0 >= 0.0) ? 0.0 : 10000000.0, pszUnits); break; case 42002: /** WGS 84 / Auto Tr. Mercator **/ sprintf( szProjBuf, "+proj=tmerc+lat_0=0+lon_0=%.16g+k=0.999600+x_0=500000" "+y_0=%.16g+ellps=WGS84+datum=WGS84+units=%s", dLon0, (dLat0 >= 0.0) ? 0.0 : 10000000.0, pszUnits); break; case 42003: /** WGS 84 / Auto Orthographic **/ sprintf( szProjBuf, "+proj=ortho+lon_0=%.16g+lat_0=%.16g+x_0=0+y_0=0" "+ellps=WGS84+datum=WGS84+units=%s", dLon0, dLat0, pszUnits ); break; case 42004: /** WGS 84 / Auto Equirectangular **/ /* Note that we have to pass lon_0 as lon_ts for this one to */ /* work. Either a PROJ4 bug or a PROJ4 documentation issue. */ sprintf( szProjBuf, "+proj=eqc+lon_ts=%.16g+lat_ts=%.16g+x_0=0+y_0=0" "+ellps=WGS84+datum=WGS84+units=%s", dLon0, dLat0, pszUnits); break; case 42005: /** WGS 84 / Auto Mollweide **/ sprintf( szProjBuf, "+proj=moll+lon_0=%.16g+x_0=0+y_0=0+ellps=WGS84" "+datum=WGS84+units=%s", dLon0, pszUnits); break; default: msSetError(MS_PROJERR, "WMS/WFS AUTO PROJECTION %d not supported.\n", "_msProcessAutoProjection()", nProjId); return -1; } /* msDebug("%s = %s\n", p->args[0], szProjBuf); */ /* OK, pass the definition to pj_init() */ args = msStringSplit(szProjBuf, '+', &numargs); msAcquireLock( TLOCK_PROJ ); if( !(p->proj = pj_init(numargs, args)) ) { int *pj_errno_ref = pj_get_errno_ref(); msReleaseLock( TLOCK_PROJ ); msSetError(MS_PROJERR, "proj error \"%s\" for \"%s\"", "msProcessProjection()", pj_strerrno(*pj_errno_ref), szProjBuf) ; return(-1); } msReleaseLock( TLOCK_PROJ ); msFreeCharArray(args, numargs); return(0); } #endif /* USE_PROJ */ int msProcessProjection(projectionObj *p) { #ifdef USE_PROJ assert( p->proj == NULL ); if( strcasecmp(p->args[0],"GEOGRAPHIC") == 0 ) { msSetError(MS_PROJERR, "PROJECTION 'GEOGRAPHIC' no longer supported.\n" "Provide explicit definition.\n" "ie. proj=latlong\n" " ellps=clrk66\n", "msProcessProjection()"); return(-1); } if (strcasecmp(p->args[0], "AUTO") == 0) { p->proj = NULL; return 0; } if (strncasecmp(p->args[0], "AUTO:", 5) == 0 || strncasecmp(p->args[0], "AUTO2:", 6) == 0) { /* WMS/WFS AUTO projection: "AUTO:proj_id,units_id,lon0,lat0" */ /*WMS 1.3.0: AUTO2:auto_crs_id,factor,lon0,lat0*/ return _msProcessAutoProjection(p); } msAcquireLock( TLOCK_PROJ ); #if PJ_VERSION < 480 if( !(p->proj = pj_init(p->numargs, p->args)) ) { #else p->proj_ctx = pj_ctx_alloc(); if( !(p->proj=pj_init_ctx(p->proj_ctx, p->numargs, p->args)) ) { #endif int *pj_errno_ref = pj_get_errno_ref(); msReleaseLock( TLOCK_PROJ ); if(p->numargs>1) { msSetError(MS_PROJERR, "proj error \"%s\" for \"%s:%s\"", "msProcessProjection()", pj_strerrno(*pj_errno_ref), p->args[0],p->args[1]) ; } else { msSetError(MS_PROJERR, "proj error \"%s\" for \"%s\"", "msProcessProjection()", pj_strerrno(*pj_errno_ref), p->args[0]) ; } return(-1); } msReleaseLock( TLOCK_PROJ ); #ifdef USE_PROJ_FASTPATHS if(strcasestr(p->args[0],"epsg:4326")) { p->wellknownprojection = wkp_lonlat; } else if(strcasestr(p->args[0],"epsg:3857")) { p->wellknownprojection = wkp_gmerc; } else { p->wellknownprojection = wkp_none; } #endif return(0); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProcessProjection()"); return(-1); #endif } static int loadProjection(projectionObj *p) { #ifdef USE_PROJ int i=0; #endif p->gt.need_geotransform = MS_FALSE; #ifdef USE_PROJ if ( p->proj != NULL ) { msSetError(MS_MISCERR, "Projection is already initialized. Multiple projection definitions are not allowed in this object. (line %d)", "loadProjection()", msyylineno); return(-1); } for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadProjection()"); return(-1); case(END): if( i == 1 && strstr(p->args[0],"+") != NULL ) { char *one_line_def = p->args[0]; int result; p->args[0] = NULL; result = msLoadProjectionString( p, one_line_def ); free( one_line_def ); return result; } else { p->numargs = i; if(p->numargs != 0) return msProcessProjection(p); else return 0; } break; case(MS_STRING): case(MS_AUTO): p->args[i] = msStrdup(msyystring_buffer); p->automatic = MS_TRUE; i++; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadProjection()", msyystring_buffer, msyylineno); return(-1); } } /* next token */ #else msSetError(MS_PROJERR, "Projection support is not available.", "loadProjection()"); return(-1); #endif } /************************************************************************/ /* msLoadProjectionStringEPSGLike */ /************************************************************************/ static int msLoadProjectionStringEPSGLike(projectionObj *p, const char *value, const char* pszPrefix, int bFollowEPSGAxisOrder) { size_t buffer_size = 0; char *init_string = NULL; const char *code; const char *next_sep; size_t prefix_len; prefix_len = strlen(pszPrefix); if( strncasecmp(value, pszPrefix, prefix_len) != 0 ) return -1; code = value + prefix_len; next_sep = strchr(code, pszPrefix[prefix_len-1]); if( next_sep != NULL ) code = next_sep + 1; buffer_size = 10 + strlen(code) + 1; init_string = (char*)msSmallMalloc(buffer_size); /* translate into PROJ.4 format. */ snprintf( init_string, buffer_size, "init=epsg:%s", code ); p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = init_string; p->numargs = 1; if( bFollowEPSGAxisOrder && msIsAxisInverted(atoi(code))) { p->args[1] = msStrdup("+epsgaxis=ne"); p->numargs = 2; } return 0; } /************************************************************************/ /* msLoadProjectionStringCRSLike */ /************************************************************************/ static int msLoadProjectionStringCRSLike(projectionObj *p, const char *value, const char* pszPrefix) { char init_string[100]; const char *id; const char *next_sep; size_t prefix_len; prefix_len = strlen(pszPrefix); if( strncasecmp(value, pszPrefix, prefix_len) != 0 ) return -1; id = value + prefix_len; next_sep = strchr(id, pszPrefix[prefix_len-1]); if( next_sep != NULL ) id = next_sep + 1; init_string[0] = '\0'; if( strcasecmp(id,"84") == 0 || strcasecmp(id,"CRS84") == 0 ) strncpy( init_string, "init=epsg:4326", sizeof(init_string) ); else if( strcasecmp(id,"83") == 0 || strcasecmp(id,"CRS83") == 0 ) strncpy( init_string, "init=epsg:4269", sizeof(init_string) ); else if( strcasecmp(id,"27") == 0 || strcasecmp(id,"CRS27") == 0 ) strncpy( init_string, "init=epsg:4267", sizeof(init_string) ); else { msSetError( MS_PROJERR, "Unrecognised OGC CRS def '%s'.", "msLoadProjectionString()", value ); return -1; } p->args = (char**)msSmallMalloc(sizeof(char*) * 2); p->args[0] = msStrdup(init_string); p->numargs = 1; return 0; } /************************************************************************/ /* msLoadProjectionStringEPSG */ /* */ /* Checks for EPSG type projection and set the axes for a */ /* certain code ranges. */ /* Use for now in WMS 1.3.0 and WFS >= 1.1.0 */ /************************************************************************/ int msLoadProjectionStringEPSG(projectionObj *p, const char *value) { #ifdef USE_PROJ assert(p); msFreeProjection(p); p->gt.need_geotransform = MS_FALSE; #ifdef USE_PROJ_FASTPATHS if(strcasestr(value,"epsg:4326")) { p->wellknownprojection = wkp_lonlat; } else if(strcasestr(value,"epsg:3857")) { p->wellknownprojection = wkp_gmerc; } else { p->wellknownprojection = wkp_none; } #endif if( msLoadProjectionStringEPSGLike(p, value, "EPSG:", MS_TRUE) == 0 ) { return msProcessProjection( p ); } return msLoadProjectionString(p, value); #else msSetError(MS_PROJERR, "Projection support is not available.", "msLoadProjectionStringEPSG()"); return(-1); #endif } int msLoadProjectionString(projectionObj *p, const char *value) { assert(p); p->gt.need_geotransform = MS_FALSE; #ifdef USE_PROJ msFreeProjection(p); /* * Handle new style definitions, the same as they would be given to * the proj program. * eg. * "+proj=utm +zone=11 +ellps=WGS84" */ if( value[0] == '+' ) { char *trimmed; int i, i_out=0; trimmed = msStrdup(value+1); for( i = 1; value[i] != '\0'; i++ ) { if( !isspace( value[i] ) ) trimmed[i_out++] = value[i]; } trimmed[i_out] = '\0'; p->args = msStringSplit(trimmed,'+', &p->numargs); free( trimmed ); } else if (strncasecmp(value, "AUTO:", 5) == 0 || strncasecmp(value, "AUTO2:", 6) == 0) { /* WMS/WFS AUTO projection: "AUTO:proj_id,units_id,lon0,lat0" */ /* WMS 1.3.0 projection: "AUTO2:auto_crs_id,factor,lon0,lat0"*/ /* Keep the projection defn into a single token for writeProjection() */ /* to work fine. */ p->args = (char**)msSmallMalloc(sizeof(char*)); p->args[0] = msStrdup(value); p->numargs = 1; } else if (msLoadProjectionStringEPSGLike(p, value, "EPSG:", MS_FALSE) == 0 ) { /* Assume lon/lat ordering. Use msLoadProjectionStringEPSG() if wanting to follow EPSG axis */ } else if (msLoadProjectionStringEPSGLike(p, value, "urn:ogc:def:crs:EPSG:", MS_TRUE) == 0 ) { } else if (msLoadProjectionStringEPSGLike(p, value, "urn:EPSG:geographicCRS:", MS_TRUE) == 0 ) { } else if (msLoadProjectionStringEPSGLike(p, value, "urn:x-ogc:def:crs:EPSG:", MS_TRUE) == 0 ) { /*this case is to account for OGC CITE tests where x-ogc was used before the ogc name became an official NID. Note also we also account for the fact that a space for the version of the espg is not used with CITE tests. (Syntax used could be urn:ogc:def:objectType:authority:code)*/ } else if (msLoadProjectionStringCRSLike(p, value, "urn:ogc:def:crs:OGC:") == 0 ) { } else if (msLoadProjectionStringEPSGLike(p, value, "http://www.opengis.net/def/crs/EPSG/", MS_TRUE) == 0 ) { /* URI projection support */ } else if (msLoadProjectionStringCRSLike(p, value, "http://www.opengis.net/def/crs/OGC/") == 0 ) { /* Mandatory support for this URI format specified in WFS1.1 (also in 1.0?) */ } else if (msLoadProjectionStringEPSGLike(p, value, "http://www.opengis.net/gml/srs/epsg.xml#", MS_FALSE) == 0 ) { /* We assume always lon/lat ordering, as that is what GeoServer does... */ } else if (msLoadProjectionStringCRSLike(p, value, "CRS:") == 0 ) { } /* * Handle old style comma delimited. eg. "proj=utm,zone=11,ellps=WGS84". */ else { p->args = msStringSplit(value,',', &p->numargs); } return msProcessProjection( p ); #else msSetError(MS_PROJERR, "Projection support is not available.", "msLoadProjectionString()"); return(-1); #endif } static void writeProjection(FILE *stream, int indent, projectionObj *p) { #ifdef USE_PROJ int i; if(!p || p->numargs <= 0) return; indent++; writeBlockBegin(stream, indent, "PROJECTION"); for(i=0; inumargs; i++) writeString(stream, indent, NULL, NULL, p->args[i]); writeBlockEnd(stream, indent, "PROJECTION"); #endif } void initLeader(labelLeaderObj *leader) { leader->gridstep = 5; leader->maxdistance = 0; /* Set maxstyles = 0, styles[] will be allocated as needed on first call * to msGrowLabelLeaderStyles() */ leader->numstyles = leader->maxstyles = 0; leader->styles = NULL; } /* ** Initialize, load and free a labelObj structure */ void initLabel(labelObj *label) { int i; MS_REFCNT_INIT(label); label->align = MS_ALIGN_DEFAULT; MS_INIT_COLOR(label->color, 0,0,0,255); MS_INIT_COLOR(label->outlinecolor, -1,-1,-1,255); /* don't use it */ label->outlinewidth=1; MS_INIT_COLOR(label->shadowcolor, -1,-1,-1,255); /* don't use it */ label->shadowsizex = label->shadowsizey = 1; label->font = NULL; label->size = MS_MEDIUM; label->position = MS_CC; label->angle = 0; label->anglemode = MS_NONE; label->minsize = MS_MINFONTSIZE; label->maxsize = MS_MAXFONTSIZE; label->buffer = 0; label->offsetx = label->offsety = 0; label->minscaledenom=-1; label->maxscaledenom=-1; label->minfeaturesize = -1; /* no limit */ label->autominfeaturesize = MS_FALSE; label->mindistance = -1; /* no limit */ label->repeatdistance = 0; /* no repeat */ label->maxoverlapangle = 22.5; /* default max overlap angle */ label->partials = MS_FALSE; label->wrap = '\0'; label->maxlength = 0; label->minlength = 0; label->space_size_10=0.0; label->encoding = NULL; label->force = MS_OFF; label->priority = MS_DEFAULT_LABEL_PRIORITY; /* Set maxstyles = 0, styles[] will be allocated as needed on first call * to msGrowLabelStyles() */ label->numstyles = label->maxstyles = 0; label->styles = NULL; label->numbindings = 0; for(i=0; ibindings[i].item = NULL; label->bindings[i].index = -1; } msInitExpression(&(label->expression)); msInitExpression(&(label->text)); label->leader = NULL; return; } int freeLabelLeader(labelLeaderObj *leader) { int i; for(i=0; inumstyles; i++) { msFree(leader->styles[i]); } msFree(leader->styles); return MS_SUCCESS; } int freeLabel(labelObj *label) { int i; if( MS_REFCNT_DECR_IS_NOT_ZERO(label) ) { return MS_FAILURE; } msFree(label->font); msFree(label->encoding); for(i=0; inumstyles; i++) { /* each style */ if(label->styles[i]!=NULL) { if(freeStyle(label->styles[i]) == MS_SUCCESS) { msFree(label->styles[i]); } } } msFree(label->styles); for(i=0; ibindings[i].item); msFreeExpression(&(label->expression)); msFreeExpression(&(label->text)); if(label->leader) { freeLabelLeader(label->leader); msFree(label->leader); label->leader = NULL; } return MS_SUCCESS; } static int loadLeader(labelLeaderObj *leader) { for(;;) { switch(msyylex()) { case(END): return(0); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadLeader()"); return(-1); case GRIDSTEP: if(getInteger(&(leader->gridstep)) == -1) return(-1); break; case MAXDISTANCE: if(getInteger(&(leader->maxdistance)) == -1) return(-1); break; case STYLE: if(msGrowLeaderStyles(leader) == NULL) return(-1); initStyle(leader->styles[leader->numstyles]); if(loadStyle(leader->styles[leader->numstyles]) != MS_SUCCESS) return(-1); leader->numstyles++; break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadLeader()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } } static int loadLabel(labelObj *label) { int symbol; for(;;) { switch(msyylex()) { case(ANGLE): if((symbol = getSymbol(5, MS_NUMBER,MS_AUTO,MS_AUTO2,MS_FOLLOW,MS_BINDING)) == -1) return(-1); if(symbol == MS_NUMBER) label->angle = msyynumber; else if(symbol == MS_BINDING) { if (label->bindings[MS_LABEL_BINDING_ANGLE].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_ANGLE].item); label->bindings[MS_LABEL_BINDING_ANGLE].item = msStrdup(msyystring_buffer); label->numbindings++; } else { label->anglemode = symbol; } break; case(ALIGN): if((label->align = getSymbol(3, MS_ALIGN_LEFT,MS_ALIGN_CENTER,MS_ALIGN_RIGHT)) == -1) return(-1); break; case(ANTIALIAS): /*ignore*/ msyylex(); break; case(BUFFER): if(getInteger(&(label->buffer)) == -1) return(-1); break; case(COLOR): if(loadColor(&(label->color), &(label->bindings[MS_LABEL_BINDING_COLOR])) != MS_SUCCESS) return(-1); if(label->bindings[MS_LABEL_BINDING_COLOR].item) label->numbindings++; break; case(ENCODING): if((getString(&label->encoding)) == MS_FAILURE) return(-1); break; case(END): return(0); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadLabel()"); freeLabel(label); /* free any structures allocated before EOF */ return(-1); case(EXPRESSION): if(loadExpression(&(label->expression)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { msSetError(MS_MISCERR, "URL-based EXPRESSION configuration not supported." , "loadLabel()"); msFreeExpression(&(label->expression)); return(-1); } break; case(FONT): if((symbol = getSymbol(2, MS_STRING, MS_BINDING)) == -1) return(-1); if(symbol == MS_STRING) { if (label->font != NULL) msFree(label->font); label->font = msStrdup(msyystring_buffer); } else { if (label->bindings[MS_LABEL_BINDING_FONT].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_FONT].item); label->bindings[MS_LABEL_BINDING_FONT].item = msStrdup(msyystring_buffer); label->numbindings++; } break; case(FORCE): switch(msyylex()) { case MS_ON: label->force = MS_ON; break; case MS_OFF: label->force = MS_OFF; break; case GROUP: label->force = MS_LABEL_FORCE_GROUP; break; default: msSetError(MS_MISCERR, "Invalid FORCE, must be ON,OFF,or GROUP" , "loadLabel()"); return(-1); } break; case(LABEL): break; /* for string loads */ case(LEADER): msSetError(MS_MISCERR, "LABEL LEADER not implemented. LEADER goes at the CLASS level." , "loadLabel()"); return(-1); label->leader = msSmallMalloc(sizeof(labelLeaderObj)); if(loadLeader(label->leader) == -1) return(-1); break; case(MAXSIZE): if(getInteger(&(label->maxsize)) == -1) return(-1); break; case(MAXSCALEDENOM): if(getDouble(&(label->maxscaledenom)) == -1) return(-1); break; case(MAXLENGTH): if(getInteger(&(label->maxlength)) == -1) return(-1); break; case(MINLENGTH): if(getInteger(&(label->minlength)) == -1) return(-1); break; case(MINDISTANCE): if(getInteger(&(label->mindistance)) == -1) return(-1); break; case(REPEATDISTANCE): if(getInteger(&(label->repeatdistance)) == -1) return(-1); break; case(MAXOVERLAPANGLE): if(getDouble(&(label->maxoverlapangle)) == -1) return(-1); break; case(MINFEATURESIZE): if((symbol = getSymbol(2, MS_NUMBER,MS_AUTO)) == -1) return(-1); if(symbol == MS_NUMBER) label->minfeaturesize = (int)msyynumber; else label->autominfeaturesize = MS_TRUE; break; case(MINSCALEDENOM): if(getDouble(&(label->minscaledenom)) == -1) return(-1); break; case(MINSIZE): if(getInteger(&(label->minsize)) == -1) return(-1); break; case(OFFSET): if(getInteger(&(label->offsetx)) == -1) return(-1); if(getInteger(&(label->offsety)) == -1) return(-1); break; case(OUTLINECOLOR): if(loadColor(&(label->outlinecolor), &(label->bindings[MS_LABEL_BINDING_OUTLINECOLOR])) != MS_SUCCESS) return(-1); if(label->bindings[MS_LABEL_BINDING_OUTLINECOLOR].item) label->numbindings++; break; case(OUTLINEWIDTH): if(getInteger(&(label->outlinewidth)) == -1) return(-1); break; case(PARTIALS): if((label->partials = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(POSITION): if((label->position = getSymbol(11, MS_UL,MS_UC,MS_UR,MS_CL,MS_CC,MS_CR,MS_LL,MS_LC,MS_LR,MS_AUTO,MS_BINDING)) == -1) return(-1); if(label->position == MS_BINDING) { if(label->bindings[MS_LABEL_BINDING_POSITION].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_POSITION].item); label->bindings[MS_LABEL_BINDING_POSITION].item = msStrdup(msyystring_buffer); label->numbindings++; } break; case(PRIORITY): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(-1); if(symbol == MS_NUMBER) { label->priority = (int) msyynumber; if(label->priority < 1 || label->priority > MS_MAX_LABEL_PRIORITY) { msSetError(MS_MISCERR, "Invalid PRIORITY, must be an integer between 1 and %d." , "loadLabel()", MS_MAX_LABEL_PRIORITY); return(-1); } } else { if (label->bindings[MS_LABEL_BINDING_PRIORITY].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_PRIORITY].item); label->bindings[MS_LABEL_BINDING_PRIORITY].item = msStrdup(msyystring_buffer); label->numbindings++; } break; case(SHADOWCOLOR): if(loadColor(&(label->shadowcolor), NULL) != MS_SUCCESS) return(-1); break; case(SHADOWSIZE): /* if(getInteger(&(label->shadowsizex)) == -1) return(-1); */ if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(-1); if(symbol == MS_NUMBER) { label->shadowsizex = (int) msyynumber; } else { if (label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].item); label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].item = msStrdup(msyystring_buffer); label->numbindings++; } /* if(getInteger(&(label->shadowsizey)) == -1) return(-1); */ if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(-1); if(symbol == MS_NUMBER) { label->shadowsizey = (int) msyynumber; } else { if (label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].item != NULL) msFree(label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].item); label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].item = msStrdup(msyystring_buffer); label->numbindings++; } break; case(SIZE): if(label->bindings[MS_LABEL_BINDING_SIZE].item) { msFree(label->bindings[MS_LABEL_BINDING_SIZE].item); label->bindings[MS_LABEL_BINDING_SIZE].item = NULL; label->numbindings--; } if((symbol = getSymbol(7, MS_NUMBER,MS_BINDING,MS_TINY,MS_SMALL,MS_MEDIUM,MS_LARGE,MS_GIANT)) == -1) return(-1); if(symbol == MS_NUMBER) { label->size = (double) msyynumber; } else if(symbol == MS_BINDING) { label->bindings[MS_LABEL_BINDING_SIZE].item = msStrdup(msyystring_buffer); label->numbindings++; } else label->size = symbol; break; case(STYLE): if(msGrowLabelStyles(label) == NULL) return(-1); initStyle(label->styles[label->numstyles]); if(loadStyle(label->styles[label->numstyles]) != MS_SUCCESS) return(-1); if(label->styles[label->numstyles]->_geomtransform.type == MS_GEOMTRANSFORM_NONE) label->styles[label->numstyles]->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOINT; /* set a default, a marker? */ label->numstyles++; break; case(TEXT): if(loadExpression(&(label->text)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { msSetError(MS_MISCERR, "URL-based TEXT configuration not supported for labels." , "loadLabel()"); msFreeExpression(&(label->text)); return(-1); } if((label->text.type != MS_STRING) && (label->text.type != MS_EXPRESSION)) { msSetError(MS_MISCERR, "Text expressions support constant or tagged replacement strings." , "loadLabel()"); return(-1); } break; case(TYPE): if(getSymbol(2, MS_TRUETYPE,MS_BITMAP) == -1) return(-1); /* ignore TYPE */ break; case(WRAP): if(getCharacter(&(label->wrap)) == -1) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadLabel()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateLabelFromString(labelObj *label, char *string, int url_string) { if(!label || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadLabel(label) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeLeader(FILE *stream, int indent, labelLeaderObj *leader) { int i; if(leader->maxdistance == 0 && leader->numstyles == 0) { return; } indent++; writeBlockBegin(stream, indent, "LEADER"); writeNumber(stream, indent, "MAXDISTANCE", 0, leader->maxdistance); writeNumber(stream, indent, "GRIDSTEP", 5, leader->gridstep); for(i=0; inumstyles; i++) writeStyle(stream, indent, leader->styles[i]); writeBlockEnd(stream, indent, "LEADER"); } static void writeLabel(FILE *stream, int indent, labelObj *label) { int i; colorObj c; if(label->size == -1) return; /* there is no default label anymore */ indent++; writeBlockBegin(stream, indent, "LABEL"); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_ANGLE].item) writeAttributeBinding(stream, indent, "ANGLE", &(label->bindings[MS_LABEL_BINDING_ANGLE])); else writeNumberOrKeyword(stream, indent, "ANGLE", 0, label->angle, label->anglemode, 3, MS_FOLLOW, "FOLLOW", MS_AUTO, "AUTO", MS_AUTO2, "AUTO2"); writeExpression(stream, indent, "EXPRESSION", &(label->expression)); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_FONT].item) writeAttributeBinding(stream, indent, "FONT", &(label->bindings[MS_LABEL_BINDING_FONT])); else writeString(stream, indent, "FONT", NULL, label->font); writeNumber(stream, indent, "MAXSIZE", MS_MAXFONTSIZE, label->maxsize); writeNumber(stream, indent, "MINSIZE", MS_MINFONTSIZE, label->minsize); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_SIZE].item) writeAttributeBinding(stream, indent, "SIZE", &(label->bindings[MS_LABEL_BINDING_SIZE])); else writeNumber(stream, indent, "SIZE", -1, label->size); writeKeyword(stream, indent, "ALIGN", label->align, 3, MS_ALIGN_LEFT, "LEFT", MS_ALIGN_CENTER, "CENTER", MS_ALIGN_RIGHT, "RIGHT"); writeNumber(stream, indent, "BUFFER", 0, label->buffer); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_COLOR].item) writeAttributeBinding(stream, indent, "COLOR", &(label->bindings[MS_LABEL_BINDING_COLOR])); else { MS_INIT_COLOR(c,0,0,0,255); writeColor(stream, indent, "COLOR", &c, &(label->color)); } writeString(stream, indent, "ENCODING", NULL, label->encoding); if(label->leader) writeLeader(stream,indent,label->leader); writeKeyword(stream, indent, "FORCE", label->force, 2, MS_TRUE, "TRUE", MS_LABEL_FORCE_GROUP, "GROUP"); writeNumber(stream, indent, "MAXLENGTH", 0, label->maxlength); writeNumber(stream, indent, "MAXSCALEDENOM", -1, label->maxscaledenom); writeNumber(stream, indent, "MINDISTANCE", -1, label->mindistance); writeNumberOrKeyword(stream, indent, "MINFEATURESIZE", -1, label->minfeaturesize, 1, label->autominfeaturesize, MS_TRUE, "AUTO"); writeNumber(stream, indent, "MINLENGTH", 0, label->minlength); writeNumber(stream, indent, "MINSCALEDENOM", -1, label->minscaledenom); writeDimension(stream, indent, "OFFSET", label->offsetx, label->offsety, NULL, NULL); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_OUTLINECOLOR].item) writeAttributeBinding(stream, indent, "OUTLINECOLOR", &(label->bindings[MS_LABEL_BINDING_OUTLINECOLOR])); else writeColor(stream, indent, "OUTLINECOLOR", NULL, &(label->outlinecolor)); writeNumber(stream, indent, "OUTLINEWIDTH", 1, label->outlinewidth); writeKeyword(stream, indent, "PARTIALS", label->partials, 1, MS_TRUE, "TRUE"); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_POSITION].item) writeAttributeBinding(stream, indent, "POSITION", &(label->bindings[MS_LABEL_BINDING_POSITION])); else writeKeyword(stream, indent, "POSITION", label->position, 10, MS_UL, "UL", MS_UC, "UC", MS_UR, "UR", MS_CL, "CL", MS_CC, "CC", MS_CR, "CR", MS_LL, "LL", MS_LC, "LC", MS_LR, "LR", MS_AUTO, "AUTO"); if(label->numbindings > 0 && label->bindings[MS_LABEL_BINDING_PRIORITY].item) writeAttributeBinding(stream, indent, "PRIORITY", &(label->bindings[MS_LABEL_BINDING_PRIORITY])); else writeNumber(stream, indent, "PRIORITY", MS_DEFAULT_LABEL_PRIORITY, label->priority); writeNumber(stream, indent, "REPEATDISTANCE", 0, label->repeatdistance); writeColor(stream, indent, "SHADOWCOLOR", NULL, &(label->shadowcolor)); writeDimension(stream, indent, "SHADOWSIZE", label->shadowsizex, label->shadowsizey, label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].item, label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].item); writeNumber(stream, indent, "MAXOVERLAPANGLE", 22.5, label->maxoverlapangle); for(i=0; inumstyles; i++) writeStyle(stream, indent, label->styles[i]); writeExpression(stream, indent, "TEXT", &(label->text)); writeCharacter(stream, indent, "WRAP", '\0', label->wrap); writeBlockEnd(stream, indent, "LABEL"); } char* msWriteLabelToString(labelObj *label) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeLabel(stdout, -1, label); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } void msInitExpression(expressionObj *exp) { exp->type = MS_STRING; exp->string = NULL; exp->native_string = NULL; exp->compiled = MS_FALSE; exp->flags = 0; exp->tokens = exp->curtoken = NULL; } void msFreeExpressionTokens(expressionObj *exp) { tokenListNodeObjPtr node = NULL; tokenListNodeObjPtr nextNode = NULL; if(!exp) return; if(exp->tokens) { node = exp->tokens; while (node != NULL) { nextNode = node->next; msFree(node->tokensrc); /* not set very often */ switch(node->token) { case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: case MS_TOKEN_BINDING_STRING: case MS_TOKEN_BINDING_TIME: msFree(node->tokenval.bindval.item); break; case MS_TOKEN_LITERAL_TIME: /* anything to do? */ break; case MS_TOKEN_LITERAL_STRING: msFree(node->tokenval.strval); break; case MS_TOKEN_LITERAL_SHAPE: msFreeShape(node->tokenval.shpval); free(node->tokenval.shpval); break; } msFree(node); node = nextNode; } exp->tokens = exp->curtoken = NULL; } } void msFreeExpression(expressionObj *exp) { if(!exp) return; msFree(exp->string); msFree(exp->native_string); if((exp->type == MS_REGEX) && exp->compiled) ms_regfree(&(exp->regex)); msFreeExpressionTokens(exp); msInitExpression(exp); /* re-initialize */ } int loadExpression(expressionObj *exp) { /* TODO: should we fall msFreeExpression if exp->string != NULL? We do some checking to avoid a leak but is it enough... */ msyystring_icase = MS_TRUE; if((exp->type = getSymbol(6, MS_STRING,MS_EXPRESSION,MS_REGEX,MS_ISTRING,MS_IREGEX,MS_LIST)) == -1) return(-1); if (exp->string != NULL) { msFree(exp->string); msFree(exp->native_string); } exp->string = msStrdup(msyystring_buffer); if(exp->type == MS_ISTRING) { exp->flags = exp->flags | MS_EXP_INSENSITIVE; exp->type = MS_STRING; } else if(exp->type == MS_IREGEX) { exp->flags = exp->flags | MS_EXP_INSENSITIVE; exp->type = MS_REGEX; } return(0); } /* --------------------------------------------------------------------------- msLoadExpressionString and loadExpressionString msLoadExpressionString wraps call to loadExpressionString with mutex acquisition and release. This function should be used everywhere outside the mapfile loading phase of an application. loadExpressionString does not check for a mutex! It should be used only within code that has properly acquired a mutex. See bug 339 for more details -- SG. ------------------------------------------------------------------------ */ int msLoadExpressionString(expressionObj *exp, char *value) { int retval = MS_FAILURE; msAcquireLock( TLOCK_PARSER ); retval = loadExpressionString( exp, value ); msReleaseLock( TLOCK_PARSER ); return retval; } int loadExpressionString(expressionObj *exp, char *value) { msyystate = MS_TOKENIZE_STRING; msyystring = value; msyylex(); /* sets things up but processes no tokens */ msFreeExpression(exp); /* we're totally replacing the old expression so free (which re-inits) to start over */ msyystring_icase = MS_TRUE; if((exp->type = getSymbol2(5, MS_EXPRESSION,MS_REGEX,MS_IREGEX,MS_ISTRING,MS_LIST)) != -1) { exp->string = msStrdup(msyystring_buffer); if(exp->type == MS_ISTRING) { exp->type = MS_STRING; exp->flags = exp->flags | MS_EXP_INSENSITIVE; } else if(exp->type == MS_IREGEX) { exp->type = MS_REGEX; exp->flags = exp->flags | MS_EXP_INSENSITIVE; } } else { /* failure above is not an error since we'll consider anything not matching (like an unquoted number) as a STRING) */ exp->type = MS_STRING; if((strlen(value) - strlen(msyystring_buffer)) == 2) exp->string = msStrdup(msyystring_buffer); /* value was quoted */ else exp->string = msStrdup(value); /* use the whole value */ } return(0); } /* msGetExpressionString() * * Returns the string representation of this expression, including delimiters * and any flags (e.g. i = case-insensitive). * * Returns a newly allocated buffer that should be freed by the caller or NULL. */ char *msGetExpressionString(expressionObj *exp) { if(exp->string) { char *exprstring; size_t buffer_size; const char *case_insensitive = ""; if(exp->flags & MS_EXP_INSENSITIVE) case_insensitive = "i"; /* Alloc buffer big enough for string + 2 delimiters + 'i' + \0 */ buffer_size = strlen(exp->string)+4; exprstring = (char*)msSmallMalloc(buffer_size); switch(exp->type) { case(MS_REGEX): snprintf(exprstring, buffer_size, "/%s/%s", exp->string, case_insensitive); return exprstring; case(MS_STRING): snprintf(exprstring, buffer_size, "\"%s\"%s", exp->string, case_insensitive); return exprstring; case(MS_EXPRESSION): snprintf(exprstring, buffer_size, "(%s)", exp->string); return exprstring; case(MS_LIST): snprintf(exprstring, buffer_size, "{%s}", exp->string); return exprstring; default: /* We should never get to here really! */ free(exprstring); return NULL; } } return NULL; } static void writeExpression(FILE *stream, int indent, const char *name, expressionObj *exp) { if(!exp || !exp->string) return; writeIndent(stream, ++indent); switch(exp->type) { case(MS_LIST): fprintf(stream, "%s {%s}", name, exp->string); break; case(MS_REGEX): msIO_fprintf(stream, "%s /%s/", name, exp->string); break; case(MS_STRING): msIO_fprintf(stream, "%s ", name); writeStringElement(stream, exp->string); break; case(MS_EXPRESSION): msIO_fprintf(stream, "%s (%s)", name, exp->string); break; } if((exp->type == MS_STRING || exp->type == MS_REGEX) && (exp->flags & MS_EXP_INSENSITIVE)) msIO_fprintf(stream, "i"); writeLineFeed(stream); } int loadHashTable(hashTableObj *ptable) { char *key=NULL, *data=NULL; assert(ptable); for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadHashTable()"); return(MS_FAILURE); case(END): return(MS_SUCCESS); case(MS_STRING): key = msStrdup(msyystring_buffer); /* the key is *always* a string */ if(getString(&data) == MS_FAILURE) return(MS_FAILURE); msInsertHashTable(ptable, key, data); free(key); free(data); data=NULL; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadHashTable()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } return(MS_SUCCESS); } static void writeHashTable(FILE *stream, int indent, const char *title, hashTableObj *table) { struct hashObj *tp; int i; if(!table) return; if(msHashIsEmpty(table)) return; indent++; writeBlockBegin(stream, indent, title); for (i=0; iitems[i] != NULL) { for (tp=table->items[i]; tp!=NULL; tp=tp->next) writeNameValuePair(stream, indent, tp->key, tp->data); } } writeBlockEnd(stream, indent, title); } static void writeHashTableInline(FILE *stream, int indent, char *name, hashTableObj* table) { struct hashObj *tp = NULL; int i; if(!table) return; if(msHashIsEmpty(table)) return; ++indent; for (i=0; iitems[i] != NULL) { for (tp=table->items[i]; tp!=NULL; tp=tp->next) { writeIndent(stream, indent); msIO_fprintf(stream, "%s ", name); writeStringElement(stream, tp->key); msIO_fprintf(stream," "); writeStringElement(stream, tp->data); writeLineFeed(stream); } } } } /* ** Initialize, load and free a cluster object */ void initCluster(clusterObj *cluster) { cluster->maxdistance = 10; cluster->buffer = 0; cluster->region = NULL; msInitExpression(&(cluster->group)); msInitExpression(&(cluster->filter)); } void freeCluster(clusterObj *cluster) { msFree(cluster->region); msFreeExpression(&(cluster->group)); msFreeExpression(&(cluster->filter)); } int loadCluster(clusterObj *cluster) { for(;;) { switch(msyylex()) { case(CLUSTER): break; /* for string loads */ case(MAXDISTANCE): if(getDouble(&(cluster->maxdistance)) == -1) return(-1); break; case(BUFFER): if(getDouble(&(cluster->buffer)) == -1) return(-1); break; case(REGION): if(getString(&cluster->region) == MS_FAILURE) return(-1); break; case(END): return(0); break; case(GROUP): if(loadExpression(&(cluster->group)) == -1) return(-1); break; case(FILTER): if(loadExpression(&(cluster->filter)) == -1) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadCluster()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } return(MS_SUCCESS); } int msUpdateClusterFromString(clusterObj *cluster, char *string) { if(!cluster || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadCluster(cluster) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeCluster(FILE *stream, int indent, clusterObj *cluster) { if (cluster->maxdistance == 10 && cluster->buffer == 0.0 && cluster->region == NULL && cluster->group.string == NULL && cluster->filter.string == NULL) return; /* Nothing to write */ indent++; writeBlockBegin(stream, indent, "CLUSTER"); writeNumber(stream, indent, "MAXDISTANCE", 10, cluster->maxdistance); writeNumber(stream, indent, "BUFFER", 0, cluster->buffer); writeString(stream, indent, "REGION", NULL, cluster->region); writeExpression(stream, indent, "GROUP", &(cluster->group)); writeExpression(stream, indent, "FILTER", &(cluster->filter)); writeBlockEnd(stream, indent, "CLUSTER"); } char* msWriteClusterToString(clusterObj *cluster) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeCluster(stdout, -1, cluster); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a single style */ int initStyle(styleObj *style) { int i; MS_REFCNT_INIT(style); MS_INIT_COLOR(style->color, -1,-1,-1,255); /* must explictly set colors */ MS_INIT_COLOR(style->backgroundcolor, -1,-1,-1,255); MS_INIT_COLOR(style->outlinecolor, -1,-1,-1,255); /* New Color Range fields*/ MS_INIT_COLOR(style->mincolor, -1,-1,-1,255); MS_INIT_COLOR(style->maxcolor, -1,-1,-1,255); style->minvalue = 0.0; style->maxvalue = 1.0; style->rangeitem = NULL; /* End Color Range fields*/ style->symbol = 0; /* there is always a default symbol*/ style->symbolname = NULL; style->size = -1; /* in SIZEUNITS (layerObj) */ style->minsize = MS_MINSYMBOLSIZE; style->maxsize = MS_MAXSYMBOLSIZE; style->width = 1; /* in pixels */ style->outlinewidth = 0; /* in pixels */ style->minwidth = MS_MINSYMBOLWIDTH; style->maxwidth = MS_MAXSYMBOLWIDTH; style->minscaledenom=style->maxscaledenom = -1.0; style->offsetx = style->offsety = 0; /* no offset */ style->polaroffsetpixel = style->polaroffsetangle = 0; /* no polar offset */ style->angle = 0; style->autoangle= MS_FALSE; style->opacity = 100; /* fully opaque */ msInitExpression(&(style->_geomtransform)); style->_geomtransform.type = MS_GEOMTRANSFORM_NONE; style->patternlength = 0; /* solid line */ style->gap = 0; style->initialgap = -1; style->position = MS_CC; style->linecap = MS_CJC_DEFAULT_CAPS; style->linejoin = MS_CJC_DEFAULT_JOINS; style->linejoinmaxsize = MS_CJC_DEFAULT_JOIN_MAXSIZE; style->numbindings = 0; for(i=0; ibindings[i].item = NULL; style->bindings[i].index = -1; } return MS_SUCCESS; } int loadStyle(styleObj *style) { int symbol; for(;;) { switch(msyylex()) { /* New Color Range fields*/ case (COLORRANGE): /*These are both in one line now*/ if(loadColor(&(style->mincolor), NULL) != MS_SUCCESS) return(MS_FAILURE); if(loadColor(&(style->maxcolor), NULL) != MS_SUCCESS) return(MS_FAILURE); break; case(DATARANGE): /*These are both in one line now*/ if(getDouble(&(style->minvalue)) == -1) return(-1); if(getDouble(&(style->maxvalue)) == -1) return(-1); break; case(RANGEITEM): if(getString(&style->rangeitem) == MS_FAILURE) return(-1); break; /* End Range fields*/ case(ANGLE): if((symbol = getSymbol(3, MS_NUMBER,MS_BINDING,MS_AUTO)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->angle = (double) msyynumber; else if(symbol==MS_BINDING) { if (style->bindings[MS_STYLE_BINDING_ANGLE].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_ANGLE].item); style->bindings[MS_STYLE_BINDING_ANGLE].item = msStrdup(msyystring_buffer); style->numbindings++; } else { style->autoangle=MS_TRUE; } break; case(ANTIALIAS): /*ignore*/ msyylex(); break; case(BACKGROUNDCOLOR): if(loadColor(&(style->backgroundcolor), NULL) != MS_SUCCESS) return(MS_FAILURE); break; case(COLOR): if(loadColor(&(style->color), &(style->bindings[MS_STYLE_BINDING_COLOR])) != MS_SUCCESS) return(MS_FAILURE); if(style->bindings[MS_STYLE_BINDING_COLOR].item) style->numbindings++; break; case(EOF): msSetError(MS_EOFERR, NULL, "loadStyle()"); return(MS_FAILURE); /* missing END (probably) */ case(END): { int alpha; /* apply opacity as the alpha channel color(s) */ if(style->opacity < 100) { alpha = MS_NINT(style->opacity*2.55); style->color.alpha = alpha; style->outlinecolor.alpha = alpha; style->backgroundcolor.alpha = alpha; style->mincolor.alpha = alpha; style->maxcolor.alpha = alpha; } return(MS_SUCCESS); } break; case(GAP): if((getDouble(&style->gap)) == -1) return(MS_FAILURE); break; case(INITIALGAP): if((getDouble(&style->initialgap)) == -1) return(MS_FAILURE); if(style->initialgap < 0) { msSetError(MS_MISCERR, "INITIALGAP requires a positive values", "loadStyle()"); return(MS_FAILURE); } break; case(MAXSCALEDENOM): if(getDouble(&(style->maxscaledenom)) == -1) return(MS_FAILURE); break; case(MINSCALEDENOM): if(getDouble(&(style->minscaledenom)) == -1) return(MS_FAILURE); break; case(GEOMTRANSFORM): { int s; if((s = getSymbol(2, MS_STRING, MS_EXPRESSION)) == -1) return(MS_FAILURE); if(s == MS_STRING) msStyleSetGeomTransform(style, msyystring_buffer); else { /* handle expression case here for the moment */ msFree(style->_geomtransform.string); style->_geomtransform.string = msStrdup(msyystring_buffer); style->_geomtransform.type = MS_GEOMTRANSFORM_EXPRESSION; } } break; case(LINECAP): if((style->linecap = getSymbol(4,MS_CJC_BUTT, MS_CJC_ROUND, MS_CJC_SQUARE, MS_CJC_TRIANGLE)) == -1) return(MS_FAILURE); break; case(LINEJOIN): if((style->linejoin = getSymbol(4,MS_CJC_NONE, MS_CJC_ROUND, MS_CJC_MITER, MS_CJC_BEVEL)) == -1) return(MS_FAILURE); break; case(LINEJOINMAXSIZE): if((getDouble(&style->linejoinmaxsize)) == -1) return(MS_FAILURE); break; case(MAXSIZE): if(getDouble(&(style->maxsize)) == -1) return(MS_FAILURE); break; case(MINSIZE): if(getDouble(&(style->minsize)) == -1) return(MS_FAILURE); break; case(MAXWIDTH): if(getDouble(&(style->maxwidth)) == -1) return(MS_FAILURE); break; case(MINWIDTH): if(getDouble(&(style->minwidth)) == -1) return(MS_FAILURE); break; case(OFFSET): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->offsetx = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_OFFSET_X].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_OFFSET_X].item); style->bindings[MS_STYLE_BINDING_OFFSET_X].item = msStrdup(msyystring_buffer); style->numbindings++; } if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->offsety = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_OFFSET_Y].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_OFFSET_Y].item); style->bindings[MS_STYLE_BINDING_OFFSET_Y].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(OPACITY): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->opacity = MS_MAX(MS_MIN((int) msyynumber, 100), 0); /* force opacity to between 0 and 100 */ else { if (style->bindings[MS_STYLE_BINDING_OPACITY].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_OPACITY].item); style->bindings[MS_STYLE_BINDING_OPACITY].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(OUTLINECOLOR): if(loadColor(&(style->outlinecolor), &(style->bindings[MS_STYLE_BINDING_OUTLINECOLOR])) != MS_SUCCESS) return(MS_FAILURE); if(style->bindings[MS_STYLE_BINDING_OUTLINECOLOR].item) style->numbindings++; break; case(PATTERN): { int done = MS_FALSE; for(;;) { /* read till the next END */ switch(msyylex()) { case(END): if(style->patternlength < 2) { msSetError(MS_SYMERR, "Not enough pattern elements. A minimum of 2 are required", "loadStyle()"); return(MS_FAILURE); } done = MS_TRUE; break; case(MS_NUMBER): /* read the pattern values */ if(style->patternlength == MS_MAXPATTERNLENGTH) { msSetError(MS_SYMERR, "Pattern too long.", "loadStyle()"); return(-1); } style->pattern[style->patternlength] = atof(msyystring_buffer); style->patternlength++; break; default: msSetError(MS_TYPEERR, "Parsing error near (%s):(line %d)", "loadStyle()", msyystring_buffer, msyylineno); return(-1); } if(done == MS_TRUE) break; } break; } case(POSITION): /* if((s->position = getSymbol(3, MS_UC,MS_CC,MS_LC)) == -1) */ /* return(-1); */ if((style->position = getSymbol(9, MS_UL,MS_UC,MS_UR,MS_CL,MS_CC,MS_CR,MS_LL,MS_LC,MS_LR)) == -1) return(-1); break; case(OUTLINEWIDTH): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) { style->outlinewidth = (double) msyynumber; if(style->outlinewidth < 0) { msSetError(MS_MISCERR, "Invalid OUTLINEWIDTH, must be greater than 0" , "loadStyle()"); return(MS_FAILURE); } } else { if (style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].item); style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(SIZE): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->size = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_SIZE].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_SIZE].item); style->bindings[MS_STYLE_BINDING_SIZE].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(STYLE): break; /* for string loads */ case(SYMBOL): if((symbol = getSymbol(3, MS_NUMBER,MS_STRING,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) { if (style->symbolname != NULL) { msFree(style->symbolname); style->symbolname = NULL; } style->symbol = (int) msyynumber; } else if(symbol == MS_STRING) { if (style->symbolname != NULL) msFree(style->symbolname); style->symbolname = msStrdup(msyystring_buffer); } else { if (style->bindings[MS_STYLE_BINDING_SYMBOL].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_SYMBOL].item); style->bindings[MS_STYLE_BINDING_SYMBOL].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(WIDTH): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->width = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_WIDTH].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_WIDTH].item); style->bindings[MS_STYLE_BINDING_WIDTH].item = msStrdup(msyystring_buffer); style->numbindings++; } break; case(POLAROFFSET): if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->polaroffsetpixel = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item); style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item = msStrdup(msyystring_buffer); style->numbindings++; } if((symbol = getSymbol(2, MS_NUMBER,MS_BINDING)) == -1) return(MS_FAILURE); if(symbol == MS_NUMBER) style->polaroffsetangle = (double) msyynumber; else { if (style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item != NULL) msFree(style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item); style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item = msStrdup(msyystring_buffer); style->numbindings++; } break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadStyle()", msyystring_buffer, msyylineno); return(MS_FAILURE); } else { return(MS_SUCCESS); /* end of a string, not an error */ } } } } int msUpdateStyleFromString(styleObj *style, char *string, int url_string) { if(!style || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadStyle(style) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } int freeStyle(styleObj *style) { int i; if( MS_REFCNT_DECR_IS_NOT_ZERO(style) ) { return MS_FAILURE; } msFree(style->symbolname); msFreeExpression(&style->_geomtransform); msFree(style->rangeitem); for(i=0; ibindings[i].item); return MS_SUCCESS; } void writeStyle(FILE *stream, int indent, styleObj *style) { indent++; writeBlockBegin(stream, indent, "STYLE"); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_ANGLE].item) writeAttributeBinding(stream, indent, "ANGLE", &(style->bindings[MS_STYLE_BINDING_ANGLE])); else writeNumberOrKeyword(stream, indent, "ANGLE", 0, style->angle, style->autoangle, 1, MS_TRUE, "AUTO"); writeColor(stream, indent, "BACKGROUNDCOLOR", NULL, &(style->backgroundcolor)); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_COLOR].item) writeAttributeBinding(stream, indent, "COLOR", &(style->bindings[MS_STYLE_BINDING_COLOR])); else writeColor(stream, indent, "COLOR", NULL, &(style->color)); writeNumber(stream, indent, "GAP", 0, style->gap); writeNumber(stream, indent, "INITIALGAP", -1, style->initialgap); if(style->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) { writeIndent(stream, indent + 1); msIO_fprintf(stream, "GEOMTRANSFORM (%s)\n", style->_geomtransform.string); } else if(style->_geomtransform.type != MS_GEOMTRANSFORM_NONE) { writeKeyword(stream, indent, "GEOMTRANSFORM", style->_geomtransform.type, 7, MS_GEOMTRANSFORM_BBOX, "\"bbox\"", MS_GEOMTRANSFORM_END, "\"end\"", MS_GEOMTRANSFORM_LABELPOINT, "\"labelpnt\"", MS_GEOMTRANSFORM_LABELPOLY, "\"labelpoly\"", MS_GEOMTRANSFORM_LABELCENTER, "\"labelcenter\"", MS_GEOMTRANSFORM_START, "\"start\"", MS_GEOMTRANSFORM_VERTICES, "\"vertices\"", MS_GEOMTRANSFORM_CENTROID, "\"centroid\"" ); } if(style->linecap != MS_CJC_DEFAULT_CAPS) { writeKeyword(stream,indent,"LINECAP",(int)style->linecap,5, MS_CJC_NONE,"NONE", MS_CJC_ROUND, "ROUND", MS_CJC_SQUARE, "SQUARE", MS_CJC_BUTT, "BUTT", MS_CJC_TRIANGLE, "TRIANGLE"); } if(style->linejoin != MS_CJC_DEFAULT_JOINS) { writeKeyword(stream,indent,"LINEJOIN",(int)style->linejoin,5, MS_CJC_NONE,"NONE", MS_CJC_ROUND, "ROUND", MS_CJC_BEVEL, "BEVEL", MS_CJC_MITER, "MITER"); } writeNumber(stream, indent, "LINEJOINMAXSIZE", MS_CJC_DEFAULT_JOIN_MAXSIZE , style->linejoinmaxsize); writeNumber(stream, indent, "MAXSCALEDENOM", -1, style->maxscaledenom); writeNumber(stream, indent, "MAXSIZE", MS_MAXSYMBOLSIZE, style->maxsize); writeNumber(stream, indent, "MAXWIDTH", MS_MAXSYMBOLWIDTH, style->maxwidth); writeNumber(stream, indent, "MINSCALEDENOM", -1, style->minscaledenom); writeNumber(stream, indent, "MINSIZE", MS_MINSYMBOLSIZE, style->minsize); writeNumber(stream, indent, "MINWIDTH", MS_MINSYMBOLWIDTH, style->minwidth); if((style->numbindings > 0 && (style->bindings[MS_STYLE_BINDING_OFFSET_X].item||style->bindings[MS_STYLE_BINDING_OFFSET_Y].item))||style->offsetx!=0||style->offsety!=0) writeDimension(stream, indent, "OFFSET", style->offsetx, style->offsety, style->bindings[MS_STYLE_BINDING_OFFSET_X].item, style->bindings[MS_STYLE_BINDING_OFFSET_Y].item); if((style->numbindings > 0 && (style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item||style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item))||style->polaroffsetangle!=0||style->polaroffsetpixel!=0) writeDimension(stream, indent, "POLAROFFSET", style->polaroffsetpixel, style->polaroffsetangle, style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].item, style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].item); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_OPACITY].item) writeAttributeBinding(stream, indent, "OPACITY", &(style->bindings[MS_STYLE_BINDING_OPACITY])); else writeNumber(stream, indent, "OPACITY", 100, style->opacity); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_OUTLINECOLOR].item) writeAttributeBinding(stream, indent, "OUTLINECOLOR", &(style->bindings[MS_STYLE_BINDING_OUTLINECOLOR])); else writeColor(stream, indent, "OUTLINECOLOR", NULL, &(style->outlinecolor)); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].item) writeAttributeBinding(stream, indent, "OUTLINEWIDTH", &(style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH])); else writeNumber(stream, indent, "OUTLINEWIDTH", 0, style->outlinewidth); /* PATTERN */ if(style->patternlength != 0) { int i; indent++; writeBlockBegin(stream,indent,"PATTERN"); writeIndent(stream, indent); for(i=0; ipatternlength; i++) msIO_fprintf(stream, " %.2f", style->pattern[i]); msIO_fprintf(stream,"\n"); writeBlockEnd(stream,indent,"PATTERN"); indent--; } if(style->position != MS_CC) { writeKeyword(stream, indent, "POSITION", style->position, 9, MS_UL, "UL", MS_UC, "UC", MS_UR, "UR", MS_CL, "CL", MS_CC, "CC", MS_CR, "CR", MS_LL, "LL", MS_LC, "LC", MS_LR, "LR"); } if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_SIZE].item) writeAttributeBinding(stream, indent, "SIZE", &(style->bindings[MS_STYLE_BINDING_SIZE])); else writeNumber(stream, indent, "SIZE", -1, style->size); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_SYMBOL].item) writeAttributeBinding(stream, indent, "SYMBOL", &(style->bindings[MS_STYLE_BINDING_SYMBOL])); else writeNumberOrString(stream, indent, "SYMBOL", 0, style->symbol, style->symbolname); if(style->numbindings > 0 && style->bindings[MS_STYLE_BINDING_WIDTH].item) writeAttributeBinding(stream, indent, "WIDTH", &(style->bindings[MS_STYLE_BINDING_WIDTH])); else writeNumber(stream, indent, "WIDTH", 1, style->width); if(style->rangeitem) { writeString(stream, indent, "RANGEITEM", NULL, style->rangeitem); writeColorRange(stream, indent, "COLORRANGE", &(style->mincolor), &(style->maxcolor)); writeDoubleRange(stream, indent, "DATARANGE", style->minvalue, style->maxvalue); } writeBlockEnd(stream, indent, "STYLE"); } char* msWriteStyleToString(styleObj *style) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeStyle(stdout, -1, style); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a single class */ int initClass(classObj *class) { class->status = MS_ON; class->debug = MS_OFF; MS_REFCNT_INIT(class); msInitExpression(&(class->expression)); class->name = NULL; class->title = NULL; msInitExpression(&(class->text)); class->template = NULL; initHashTable(&(class->metadata)); initHashTable(&(class->validation)); class->maxscaledenom = class->minscaledenom = -1.0; class->minfeaturesize = -1; /* no limit */ /* Set maxstyles = 0, styles[] will be allocated as needed on first call * to msGrowClassStyles() */ class->numstyles = class->maxstyles = 0; class->styles = NULL; class->numlabels = class->maxlabels = 0; class->labels = NULL; class->keyimage = NULL; class->group = NULL; class->leader = NULL; return(0); } int freeClass(classObj *class) { int i; if( MS_REFCNT_DECR_IS_NOT_ZERO(class) ) { return MS_FAILURE; } msFreeExpression(&(class->expression)); msFreeExpression(&(class->text)); msFree(class->name); msFree(class->title); msFree(class->template); msFree(class->group); if (&(class->metadata)) msFreeHashItems(&(class->metadata)); if (&(class->validation)) msFreeHashItems(&(class->validation)); for(i=0; inumstyles; i++) { /* each style */ if(class->styles[i]!=NULL) { if(freeStyle(class->styles[i]) == MS_SUCCESS) { msFree(class->styles[i]); } } } msFree(class->styles); for(i=0; inumlabels; i++) { /* each label */ if(class->labels[i]!=NULL) { if(freeLabel(class->labels[i]) == MS_SUCCESS) { msFree(class->labels[i]); } } } msFree(class->labels); msFree(class->keyimage); if(class->leader) { freeLabelLeader(class->leader); msFree(class->leader); class->leader = NULL; } return MS_SUCCESS; } /* ** Ensure there is at least one free entry in the sttyles array of this ** classObj. Grow the allocated styles array if necessary and allocate ** a new style for styles[numstyles] if there is not already one, ** setting its contents to all zero bytes (i.e. does not call initStyle() ** on it). ** ** This function is safe to use for the initial allocation of the styles[] ** array as well (i.e. when maxstyles==0 and styles==NULL) ** ** Returns a reference to the new styleObj on success, NULL on error. */ styleObj *msGrowClassStyles( classObj *class ) { /* Do we need to increase the size of styles[] by MS_STYLE_ALLOCSIZE? */ if (class->numstyles == class->maxstyles) { styleObj **newStylePtr; int i, newsize; newsize = class->maxstyles + MS_STYLE_ALLOCSIZE; /* Alloc/realloc styles */ newStylePtr = (styleObj**)realloc(class->styles, newsize*sizeof(styleObj*)); MS_CHECK_ALLOC(newStylePtr, newsize*sizeof(styleObj*), NULL); class->styles = newStylePtr; class->maxstyles = newsize; for(i=class->numstyles; imaxstyles; i++) { class->styles[i] = NULL; } } if (class->styles[class->numstyles]==NULL) { class->styles[class->numstyles]=(styleObj*)calloc(1,sizeof(styleObj)); MS_CHECK_ALLOC(class->styles[class->numstyles], sizeof(styleObj), NULL); } return class->styles[class->numstyles]; } /* exactly the same as for a classObj */ styleObj *msGrowLabelStyles( labelObj *label ) { /* Do we need to increase the size of styles[] by MS_STYLE_ALLOCSIZE? */ if (label->numstyles == label->maxstyles) { styleObj **newStylePtr; int i, newsize; newsize = label->maxstyles + MS_STYLE_ALLOCSIZE; /* Alloc/realloc styles */ newStylePtr = (styleObj**)realloc(label->styles, newsize*sizeof(styleObj*)); MS_CHECK_ALLOC(newStylePtr, newsize*sizeof(styleObj*), NULL); label->styles = newStylePtr; label->maxstyles = newsize; for(i=label->numstyles; imaxstyles; i++) { label->styles[i] = NULL; } } if (label->styles[label->numstyles]==NULL) { label->styles[label->numstyles]=(styleObj*)calloc(1,sizeof(styleObj)); MS_CHECK_ALLOC(label->styles[label->numstyles], sizeof(styleObj), NULL); } return label->styles[label->numstyles]; } /* exactly the same as for a labelLeaderObj, needs refactoring */ styleObj *msGrowLeaderStyles( labelLeaderObj *leader ) { /* Do we need to increase the size of styles[] by MS_STYLE_ALLOCSIZE? */ if (leader->numstyles == leader->maxstyles) { styleObj **newStylePtr; int i, newsize; newsize = leader->maxstyles + MS_STYLE_ALLOCSIZE; /* Alloc/realloc styles */ newStylePtr = (styleObj**)realloc(leader->styles, newsize*sizeof(styleObj*)); MS_CHECK_ALLOC(newStylePtr, newsize*sizeof(styleObj*), NULL); leader->styles = newStylePtr; leader->maxstyles = newsize; for(i=leader->numstyles; imaxstyles; i++) { leader->styles[i] = NULL; } } if (leader->styles[leader->numstyles]==NULL) { leader->styles[leader->numstyles]=(styleObj*)calloc(1,sizeof(styleObj)); MS_CHECK_ALLOC(leader->styles[leader->numstyles], sizeof(styleObj), NULL); } return leader->styles[leader->numstyles]; } /* msMaybeAllocateClassStyle() ** ** Ensure that requested style index exists and has been initialized. ** ** Returns MS_SUCCESS/MS_FAILURE. */ int msMaybeAllocateClassStyle(classObj* c, int idx) { if (c==NULL) return MS_FAILURE; if ( idx < 0 ) { msSetError(MS_MISCERR, "Invalid style index: %d", "msMaybeAllocateClassStyle()", idx); return MS_FAILURE; } /* Alloc empty styles as needed up to idx. * Nothing to do if requested style already exists */ while(c->numstyles <= idx) { if (msGrowClassStyles(c) == NULL) return MS_FAILURE; if ( initStyle(c->styles[c->numstyles]) == MS_FAILURE ) { msSetError(MS_MISCERR, "Failed to init new styleObj", "msMaybeAllocateClassStyle()"); return(MS_FAILURE); } c->numstyles++; } return MS_SUCCESS; } /* * Reset style info in the class to defaults * the only members we don't touch are name, expression, and join/query stuff * This is used with STYLEITEM before overwriting the contents of a class. */ void resetClassStyle(classObj *class) { int i; /* reset labels */ for(i=0; inumlabels; i++) { if(class->labels[i] != NULL) { if(freeLabel(class->labels[i]) == MS_SUCCESS ) { msFree(class->labels[i]); } class->labels[i] = NULL; } } class->numlabels = 0; msFreeExpression(&(class->text)); msInitExpression(&(class->text)); /* reset styles */ for(i=0; inumstyles; i++) { if(class->styles[i] != NULL) { if( freeStyle(class->styles[i]) == MS_SUCCESS ) { msFree(class->styles[i]); } class->styles[i] = NULL; } } class->numstyles = 0; class->layer = NULL; } labelObj *msGrowClassLabels( classObj *class ) { /* Do we need to increase the size of labels[] by MS_LABEL_ALLOCSIZE? */ if (class->numlabels == class->maxlabels) { labelObj **newLabelPtr; int i, newsize; newsize = class->maxlabels + MS_LABEL_ALLOCSIZE; /* Alloc/realloc labels */ newLabelPtr = (labelObj**)realloc(class->labels, newsize*sizeof(labelObj*)); MS_CHECK_ALLOC(newLabelPtr, newsize*sizeof(labelObj*), NULL); class->labels = newLabelPtr; class->maxlabels = newsize; for(i=class->numlabels; imaxlabels; i++) { class->labels[i] = NULL; } } if (class->labels[class->numlabels]==NULL) { class->labels[class->numlabels]=(labelObj*)calloc(1,sizeof(labelObj)); MS_CHECK_ALLOC(class->labels[class->numlabels], sizeof(labelObj), NULL); } return class->labels[class->numlabels]; } int loadClass(classObj *class, layerObj *layer) { int state; mapObj *map=NULL; class->layer = (layerObj *) layer; if(layer && layer->map) map = layer->map; for(;;) { switch(msyylex()) { case(CLASS): break; /* for string loads */ case(DEBUG): if((class->debug = getSymbol(3, MS_ON,MS_OFF, MS_NUMBER)) == -1) return(-1); if(class->debug == MS_NUMBER) class->debug = (int) msyynumber; break; case(EOF): msSetError(MS_EOFERR, NULL, "loadClass()"); return(-1); case(END): return(0); break; case(EXPRESSION): if(loadExpression(&(class->expression)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->expression.string, msLookupHashTable(&(class->validation), "expression"), msLookupHashTable(&(layer->validation), "expression"), msLookupHashTable(&(map->web.validation), "expression"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based EXPRESSION configuration failed pattern validation." , "loadClass()"); msFreeExpression(&(class->expression)); return(-1); } } break; case(GROUP): if(getString(&class->group) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->group, msLookupHashTable(&(class->validation), "group"), msLookupHashTable(&(layer->validation), "group"), msLookupHashTable(&(map->web.validation), "group"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based GROUP configuration failed pattern validation." , "loadClass()"); msFree(class->group); class->group=NULL; return(-1); } } break; case(KEYIMAGE): if(getString(&class->keyimage) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->keyimage, msLookupHashTable(&(class->validation), "keyimage"), msLookupHashTable(&(layer->validation), "keyimage"), msLookupHashTable(&(map->web.validation), "keyimage"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based KEYIMAGE configuration failed pattern validation." , "loadClass()"); msFree(class->keyimage); class->keyimage=NULL; return(-1); } } break; case(LABEL): if(msGrowClassLabels(class) == NULL) return(-1); initLabel(class->labels[class->numlabels]); class->labels[class->numlabels]->size = MS_MEDIUM; /* only set a default if the LABEL section is present */ if(loadLabel(class->labels[class->numlabels]) == -1) { msFree(class->labels[class->numlabels]); return(-1); } class->numlabels++; break; case(LEADER): if(!class->leader) { class->leader = msSmallMalloc(sizeof(labelLeaderObj)); initLeader(class->leader); } if(loadLeader(class->leader) == -1) return(-1); break; case(MAXSCALE): case(MAXSCALEDENOM): if(getDouble(&(class->maxscaledenom)) == -1) return(-1); break; case(METADATA): if(loadHashTable(&(class->metadata)) != MS_SUCCESS) return(-1); break; case(MINSCALE): case(MINSCALEDENOM): if(getDouble(&(class->minscaledenom)) == -1) return(-1); break; case(MINFEATURESIZE): if(getInteger(&(class->minfeaturesize)) == -1) return(-1); break; case(NAME): if(getString(&class->name) == MS_FAILURE) return(-1); break; case(STATUS): if((class->status = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(STYLE): if(msGrowClassStyles(class) == NULL) return(-1); initStyle(class->styles[class->numstyles]); if(loadStyle(class->styles[class->numstyles]) != MS_SUCCESS) return(-1); class->numstyles++; break; case(TEMPLATE): if(getString(&class->template) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->template, msLookupHashTable(&(class->validation), "template"), msLookupHashTable(&(layer->validation), "template"), msLookupHashTable(&(map->web.validation), "template"), map->templatepattern) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TEMPLATE configuration failed pattern validation." , "loadClass()"); msFree(class->template); class->template=NULL; return(-1); } } break; case(TEXT): if(loadExpression(&(class->text)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->text.string, msLookupHashTable(&(class->validation), "text"), msLookupHashTable(&(layer->validation), "text"), msLookupHashTable(&(map->web.validation), "text"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TEXT configuration failed pattern validation." , "loadClass()"); msFreeExpression(&(class->text)); return(-1); } } if((class->text.type != MS_STRING) && (class->text.type != MS_EXPRESSION)) { msSetError(MS_MISCERR, "Text expressions support constant or tagged replacement strings." , "loadClass()"); return(-1); } break; case(TITLE): if(getString(&class->title) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(class->title, msLookupHashTable(&(class->validation), "title"), msLookupHashTable(&(layer->validation), "title"), msLookupHashTable(&(map->web.validation), "title"), NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TITLE configuration failed pattern validation." , "loadClass()"); msFree(class->title); class->title=NULL; return(-1); } } break; /* ** for backwards compatability, these are shortcuts for style 0 */ case(BACKGROUNDCOLOR): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(loadColor(&(class->styles[0]->backgroundcolor), NULL) != MS_SUCCESS) return(-1); break; case(COLOR): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(loadColor(&(class->styles[0]->color), NULL) != MS_SUCCESS) return(-1); class->numstyles = 1; /* must *always* set a color or outlinecolor */ break; case(MAXSIZE): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(getDouble(&(class->styles[0]->maxsize)) == -1) return(-1); break; case(MINSIZE): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(getDouble(&(class->styles[0]->minsize)) == -1) return(-1); break; case(OUTLINECOLOR): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(loadColor(&(class->styles[0]->outlinecolor), NULL) != MS_SUCCESS) return(-1); class->numstyles = 1; /* must *always* set a color, symbol or outlinecolor */ break; case(SIZE): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if(getDouble(&(class->styles[0]->size)) == -1) return(-1); break; case(SYMBOL): if (msMaybeAllocateClassStyle(class, 0)) return MS_FAILURE; if((state = getSymbol(2, MS_NUMBER,MS_STRING)) == -1) return(-1); if(state == MS_NUMBER) class->styles[0]->symbol = (int) msyynumber; else { if (class->styles[0]->symbolname != NULL) msFree(class->styles[0]->symbolname); class->styles[0]->symbolname = msStrdup(msyystring_buffer); class->numstyles = 1; } break; /* ** for backwards compatability, these are shortcuts for style 1 */ case(OVERLAYBACKGROUNDCOLOR): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(loadColor(&(class->styles[1]->backgroundcolor), NULL) != MS_SUCCESS) return(-1); break; case(OVERLAYCOLOR): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(loadColor(&(class->styles[1]->color), NULL) != MS_SUCCESS) return(-1); class->numstyles = 2; /* must *always* set a color, symbol or outlinecolor */ break; case(OVERLAYMAXSIZE): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(getDouble(&(class->styles[1]->maxsize)) == -1) return(-1); break; case(OVERLAYMINSIZE): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(getDouble(&(class->styles[1]->minsize)) == -1) return(-1); break; case(OVERLAYOUTLINECOLOR): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(loadColor(&(class->styles[1]->outlinecolor), NULL) != MS_SUCCESS) return(-1); class->numstyles = 2; /* must *always* set a color, symbol or outlinecolor */ break; case(OVERLAYSIZE): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if(getDouble(&(class->styles[1]->size)) == -1) return(-1); break; case(OVERLAYSYMBOL): if (msMaybeAllocateClassStyle(class, 1)) return MS_FAILURE; if((state = getSymbol(2, MS_NUMBER,MS_STRING)) == -1) return(-1); if(state == MS_NUMBER) class->styles[1]->symbol = (int) msyynumber; else { if (class->styles[1]->symbolname != NULL) msFree(class->styles[1]->symbolname); class->styles[1]->symbolname = msStrdup(msyystring_buffer); } class->numstyles = 2; break; case(VALIDATION): if(loadHashTable(&(class->validation)) != MS_SUCCESS) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadClass()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } } static int classResolveSymbolNames(classObj *class) { int i,j; /* step through styles and labels to resolve symbol names */ /* class styles */ for(i=0; inumstyles; i++) { if(class->styles[i]->symbolname) { if((class->styles[i]->symbol = msGetSymbolIndex(&(class->layer->map->symbolset), class->styles[i]->symbolname, MS_TRUE)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class, style %d of layer %s.", "classResolveSymbolNames()", class->styles[i]->symbolname, i, class->layer->name); return MS_FAILURE; } } } /* label styles */ for(i=0; inumlabels; i++) { for(j=0; jlabels[i]->numstyles; j++) { if(class->labels[i]->styles[j]->symbolname) { if((class->labels[i]->styles[j]->symbol = msGetSymbolIndex(&(class->layer->map->symbolset), class->labels[i]->styles[j]->symbolname, MS_TRUE)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class, label style %d of layer %s.", "classResolveSymbolNames()", class->labels[i]->styles[j]->symbolname, j, class->layer->name); return MS_FAILURE; } } } } return MS_SUCCESS; } int msUpdateClassFromString(classObj *class, char *string, int url_string) { if(!class || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadClass(class, class->layer) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); if(classResolveSymbolNames(class) != MS_SUCCESS) return MS_FAILURE; return MS_SUCCESS; } static void writeClass(FILE *stream, int indent, classObj *class) { int i; if(class->status == MS_DELETE) return; indent++; writeBlockBegin(stream, indent, "CLASS"); writeString(stream, indent, "NAME", NULL, class->name); writeString(stream, indent, "GROUP", NULL, class->group); writeNumber(stream, indent, "DEBUG", 0, class->debug); writeExpression(stream, indent, "EXPRESSION", &(class->expression)); writeString(stream, indent, "KEYIMAGE", NULL, class->keyimage); for(i=0; inumlabels; i++) writeLabel(stream, indent, class->labels[i]); if(class->leader) writeLeader(stream,indent,class->leader); writeNumber(stream, indent, "MAXSCALEDENOM", -1, class->maxscaledenom); writeHashTable(stream, indent, "METADATA", &(class->metadata)); writeNumber(stream, indent, "MINSCALEDENOM", -1, class->minscaledenom); writeNumber(stream, indent, "MINFEATURESIZE", -1, class->minfeaturesize); writeKeyword(stream, indent, "STATUS", class->status, 1, MS_OFF, "OFF"); for(i=0; inumstyles; i++) writeStyle(stream, indent, class->styles[i]); writeString(stream, indent, "TEMPLATE", NULL, class->template); writeExpression(stream, indent, "TEXT", &(class->text)); writeString(stream, indent, "TITLE", NULL, class->title); writeHashTable(stream, indent, "VALIDATION", &(class->validation)); writeBlockEnd(stream, indent, "CLASS"); } char* msWriteClassToString(classObj *class) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeClass(stdout, -1, class); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } int initCompositingFilter(CompositingFilter *filter) { filter->filter = NULL; filter->next = NULL; return MS_SUCCESS; } void freeCompositingFilter(CompositingFilter *filter) { if(!filter) return; if(filter->next) freeCompositingFilter(filter->next); free(filter->filter); free(filter); } int initLayerCompositer(LayerCompositer *compositer) { compositer->comp_op = MS_COMPOP_SRC_OVER; compositer->opacity = 100; compositer->next = NULL; compositer->filter = NULL; return MS_SUCCESS; } void freeLayerCompositer(LayerCompositer *compositer) { if(!compositer) return; if(compositer->next) freeLayerCompositer(compositer->next); freeCompositingFilter(compositer->filter); free(compositer); } /* ** Initialize, load and free a single layer structure */ int initLayer(layerObj *layer, mapObj *map) { if (layer==NULL) { msSetError(MS_MEMERR, "Layer is null", "initLayer()"); return(-1); } layer->debug = (int)msGetGlobalDebugLevel(); MS_REFCNT_INIT(layer); /* Set maxclasses = 0, class[] will be allocated as needed on first call * to msGrowLayerClasses() */ layer->numclasses = 0; layer->maxclasses = 0; layer->class = NULL; layer->name = NULL; layer->group = NULL; layer->status = MS_OFF; layer->data = NULL; layer->map = map; /* point back to the encompassing structure */ layer->type = -1; layer->toleranceunits = MS_PIXELS; layer->tolerance = -1; /* perhaps this should have a different value based on type */ layer->symbolscaledenom = -1.0; /* -1 means nothing is set */ layer->scalefactor = 1.0; layer->maxscaledenom = -1.0; layer->minscaledenom = -1.0; layer->minfeaturesize = -1; /* no limit */ layer->maxgeowidth = -1.0; layer->mingeowidth = -1.0; layer->sizeunits = MS_PIXELS; layer->maxfeatures = -1; /* no quota */ layer->startindex = -1; /*used for pagination*/ layer->scaletokens = NULL; layer->numscaletokens = 0; layer->template = layer->header = layer->footer = NULL; layer->transform = MS_TRUE; layer->classitem = NULL; layer->classitemindex = -1; layer->units = MS_METERS; if(msInitProjection(&(layer->projection)) == -1) return(-1); layer->project = MS_TRUE; initCluster(&layer->cluster); MS_INIT_COLOR(layer->offsite, -1,-1,-1, 255); layer->labelcache = MS_ON; layer->postlabelcache = MS_FALSE; layer->labelitem = NULL; layer->labelitemindex = -1; layer->labelmaxscaledenom = -1; layer->labelminscaledenom = -1; layer->tileitem = msStrdup("location"); layer->tileitemindex = -1; layer->tileindex = NULL; layer->tilesrs = NULL; layer->bandsitem = NULL; layer->bandsitemindex = -1; layer->currentfeature = layer->features = NULL; layer->connection = NULL; layer->plugin_library = NULL; layer->plugin_library_original = NULL; layer->connectiontype = MS_SHAPEFILE; layer->vtable = NULL; layer->classgroup = NULL; layer->layerinfo = NULL; layer->wfslayerinfo = NULL; layer->items = NULL; layer->iteminfo = NULL; layer->numitems = 0; layer->resultcache= NULL; msInitExpression(&(layer->filter)); layer->filteritem = NULL; layer->filteritemindex = -1; layer->requires = layer->labelrequires = NULL; initHashTable(&(layer->metadata)); initHashTable(&(layer->bindvals)); initHashTable(&(layer->validation)); layer->dump = MS_FALSE; layer->styleitem = NULL; layer->styleitemindex = -1; layer->numprocessing = 0; layer->processing = NULL; layer->numjoins = 0; layer->joins = (joinObj *) malloc(MS_MAXJOINS*sizeof(joinObj)); MS_CHECK_ALLOC(layer->joins, MS_MAXJOINS*sizeof(joinObj), -1); layer->extent.minx = -1.0; layer->extent.miny = -1.0; layer->extent.maxx = -1.0; layer->extent.maxy = -1.0; layer->mask = NULL; layer->maskimage = NULL; layer->grid = NULL; msInitExpression(&(layer->_geomtransform)); layer->_geomtransform.type = MS_GEOMTRANSFORM_NONE; msInitExpression(&(layer->utfdata)); layer->utfitem = NULL; layer->utfitemindex = -1; layer->encoding = NULL; layer->sortBy.nProperties = 0; layer->sortBy.properties = NULL; layer->orig_st = NULL; layer->compositer = NULL; return(0); } int initScaleToken(scaleTokenObj* token) { token->n_entries = 0; token->name = NULL; token->tokens = NULL; return MS_SUCCESS; } int freeScaleTokenEntry( scaleTokenEntryObj *token) { msFree(token->value); return MS_SUCCESS; } int freeScaleToken(scaleTokenObj *scaletoken) { int i; msFree(scaletoken->name); for(i=0;in_entries;i++) { freeScaleTokenEntry(&scaletoken->tokens[i]); } msFree(scaletoken->tokens); return MS_SUCCESS; } int freeLayer(layerObj *layer) { int i; if (!layer) return MS_FAILURE; if( MS_REFCNT_DECR_IS_NOT_ZERO(layer) ) { return MS_FAILURE; } if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("freeLayer(): freeing layer at %p.\n",layer); if(msLayerIsOpen(layer)) msLayerClose(layer); msFree(layer->name); msFree(layer->encoding); msFree(layer->group); msFree(layer->data); msFree(layer->classitem); msFree(layer->labelitem); msFree(layer->header); msFree(layer->footer); msFree(layer->template); msFree(layer->tileindex); msFree(layer->tileitem); msFree(layer->tilesrs); msFree(layer->bandsitem); msFree(layer->plugin_library); msFree(layer->plugin_library_original); msFree(layer->connection); msFree(layer->vtable); msFree(layer->classgroup); msFreeProjection(&(layer->projection)); msFreeExpression(&layer->_geomtransform); freeCluster(&layer->cluster); for(i=0; imaxclasses; i++) { if (layer->class[i] != NULL) { layer->class[i]->layer=NULL; if ( freeClass(layer->class[i]) == MS_SUCCESS ) { msFree(layer->class[i]); } } } msFree(layer->class); if(layer->numscaletokens>0) { for(i=0;inumscaletokens;i++) { freeScaleToken(&layer->scaletokens[i]); } msFree(layer->scaletokens); } if(layer->features) freeFeatureList(layer->features); if(layer->resultcache) { cleanupResultCache(layer->resultcache); msFree(layer->resultcache); } msFree(layer->styleitem); msFree(layer->filteritem); msFreeExpression(&(layer->filter)); msFree(layer->requires); msFree(layer->labelrequires); if(&(layer->metadata)) msFreeHashItems(&(layer->metadata)); if(&(layer->validation)) msFreeHashItems(&(layer->validation)); if(&(layer->bindvals)) msFreeHashItems(&layer->bindvals); if(layer->numprocessing > 0) msFreeCharArray(layer->processing, layer->numprocessing); for(i=0; inumjoins; i++) /* each join */ freeJoin(&(layer->joins[i])); msFree(layer->joins); layer->numjoins = 0; layer->classgroup = NULL; msFree(layer->mask); if(layer->maskimage) { msFreeImage(layer->maskimage); } if(layer->compositer) { freeLayerCompositer(layer->compositer); } if (layer->grid) { freeGrid(layer->grid); msFree(layer->grid); } msFreeExpression(&(layer->utfdata)); msFree(layer->utfitem); for(i=0;isortBy.nProperties;i++) msFree(layer->sortBy.properties[i].item); msFree(layer->sortBy.properties); return MS_SUCCESS; } /* ** Ensure there is at least one free entry in the class array of this ** layerObj. Grow the allocated class array if necessary and allocate ** a new class for class[numclasses] if there is not already one, ** setting its contents to all zero bytes (i.e. does not call initClass() ** on it). ** ** This function is safe to use for the initial allocation of the class[] ** array as well (i.e. when maxclasses==0 and class==NULL) ** ** Returns a reference to the new classObj on success, NULL on error. */ classObj *msGrowLayerClasses( layerObj *layer ) { /* Do we need to increase the size of class[] by MS_CLASS_ALLOCSIZE? */ if (layer->numclasses == layer->maxclasses) { classObj **newClassPtr; int i, newsize; newsize = layer->maxclasses + MS_CLASS_ALLOCSIZE; /* Alloc/realloc classes */ newClassPtr = (classObj**)realloc(layer->class, newsize*sizeof(classObj*)); MS_CHECK_ALLOC(newClassPtr, newsize*sizeof(classObj*), NULL); layer->class = newClassPtr; layer->maxclasses = newsize; for(i=layer->numclasses; imaxclasses; i++) { layer->class[i] = NULL; } } if (layer->class[layer->numclasses]==NULL) { layer->class[layer->numclasses]=(classObj*)calloc(1,sizeof(classObj)); MS_CHECK_ALLOC(layer->class[layer->numclasses], sizeof(classObj), NULL); } return layer->class[layer->numclasses]; } scaleTokenObj *msGrowLayerScaletokens( layerObj *layer ) { layer->scaletokens = msSmallRealloc(layer->scaletokens,(layer->numscaletokens+1)*sizeof(scaleTokenObj)); memset(&layer->scaletokens[layer->numscaletokens],0,sizeof(scaleTokenObj)); return &layer->scaletokens[layer->numscaletokens]; } int loadScaletoken(scaleTokenObj *token, layerObj *layer) { for(;;) { int stop = 0; switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadScaletoken()"); return(MS_FAILURE); case(NAME): if(getString(&token->name) == MS_FAILURE) return(MS_FAILURE); break; case(VALUES): for(;;) { if(stop) break; switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadScaletoken()"); return(MS_FAILURE); case(END): stop = 1; if(token->n_entries == 0) { msSetError(MS_PARSEERR,"Scaletoken (line:%d) has no VALUES defined","loadScaleToken()",msyylineno); return(MS_FAILURE); } token->tokens[token->n_entries-1].maxscale = DBL_MAX; break; case(MS_STRING): /* we have a key */ token->tokens = msSmallRealloc(token->tokens,(token->n_entries+1)*sizeof(scaleTokenEntryObj)); if(1 != sscanf(msyystring_buffer,"%lf",&token->tokens[token->n_entries].minscale)) { msSetError(MS_PARSEERR, "failed to parse SCALETOKEN VALUE (%s):(line %d), expecting \"minscale\"", "loadScaletoken()", msyystring_buffer,msyylineno); return(MS_FAILURE); } if(token->n_entries == 0) { /* check supplied value was 0*/ if(token->tokens[0].minscale != 0) { msSetError(MS_PARSEERR, "First SCALETOKEN VALUE (%s):(line %d) must be zero, expecting \"0\"", "loadScaletoken()", msyystring_buffer,msyylineno); return(MS_FAILURE); } } else { /* set max scale of previous token */ token->tokens[token->n_entries-1].maxscale = token->tokens[token->n_entries].minscale; } token->tokens[token->n_entries].value = NULL; if(getString(&(token->tokens[token->n_entries].value)) == MS_FAILURE) return(MS_FAILURE); token->n_entries++; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadScaletoken()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } break; case(END): if(!token->name || !*(token->name)) { msSetError(MS_PARSEERR,"ScaleToken missing mandatory NAME entry (line %d)","loadScaleToken()",msyylineno); return MS_FAILURE; } if(token->n_entries == 0) { msSetError(MS_PARSEERR,"ScaleToken missing at least one VALUES entry (line %d)","loadScaleToken()",msyylineno); return MS_FAILURE; } return MS_SUCCESS; default: msSetError(MS_IDENTERR, "Parsing error 2 near (%s):(line %d)", "loadScaletoken()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } /* next token*/ } int loadLayerCompositer(LayerCompositer *compositer) { for(;;) { switch(msyylex()) { case COMPFILTER: { CompositingFilter **filter = &compositer->filter; while(*filter) { filter = &((*filter)->next); } *filter = msSmallMalloc(sizeof(CompositingFilter)); initCompositingFilter(*filter); if(getString(&((*filter)->filter)) == MS_FAILURE) return(MS_FAILURE); } break; case COMPOP: { char *compop=NULL; if(getString(&compop) == MS_FAILURE) return(MS_FAILURE); else if(!strcmp(compop,"clear")) compositer->comp_op = MS_COMPOP_CLEAR; else if(!strcmp(compop,"color-burn")) compositer->comp_op = MS_COMPOP_COLOR_BURN; else if(!strcmp(compop,"color-dodge")) compositer->comp_op = MS_COMPOP_COLOR_DODGE; else if(!strcmp(compop,"contrast")) compositer->comp_op = MS_COMPOP_CONTRAST; else if(!strcmp(compop,"darken")) compositer->comp_op = MS_COMPOP_DARKEN; else if(!strcmp(compop,"difference")) compositer->comp_op = MS_COMPOP_DIFFERENCE; else if(!strcmp(compop,"dst")) compositer->comp_op = MS_COMPOP_DST; else if(!strcmp(compop,"dst-atop")) compositer->comp_op = MS_COMPOP_DST_ATOP; else if(!strcmp(compop,"dst-in")) compositer->comp_op = MS_COMPOP_DST_IN; else if(!strcmp(compop,"dst-out")) compositer->comp_op = MS_COMPOP_DST_OUT; else if(!strcmp(compop,"dst-over")) compositer->comp_op = MS_COMPOP_DST_OVER; else if(!strcmp(compop,"exclusion")) compositer->comp_op = MS_COMPOP_EXCLUSION; else if(!strcmp(compop,"hard-light")) compositer->comp_op = MS_COMPOP_HARD_LIGHT; else if(!strcmp(compop,"invert")) compositer->comp_op = MS_COMPOP_INVERT; else if(!strcmp(compop,"invert-rgb")) compositer->comp_op = MS_COMPOP_INVERT_RGB; else if(!strcmp(compop,"lighten")) compositer->comp_op = MS_COMPOP_LIGHTEN; else if(!strcmp(compop,"minus")) compositer->comp_op = MS_COMPOP_MINUS; else if(!strcmp(compop,"multiply")) compositer->comp_op = MS_COMPOP_MULTIPLY; else if(!strcmp(compop,"overlay")) compositer->comp_op = MS_COMPOP_OVERLAY; else if(!strcmp(compop,"plus")) compositer->comp_op = MS_COMPOP_PLUS; else if(!strcmp(compop,"screen")) compositer->comp_op = MS_COMPOP_SCREEN; else if(!strcmp(compop,"soft-light")) compositer->comp_op = MS_COMPOP_SOFT_LIGHT; else if(!strcmp(compop,"src")) compositer->comp_op = MS_COMPOP_SRC; else if(!strcmp(compop,"src-atop")) compositer->comp_op = MS_COMPOP_SRC_ATOP; else if(!strcmp(compop,"src-in")) compositer->comp_op = MS_COMPOP_SRC_IN; else if(!strcmp(compop,"src-out")) compositer->comp_op = MS_COMPOP_SRC_OUT; else if(!strcmp(compop,"src-over")) compositer->comp_op = MS_COMPOP_SRC_OVER; else if(!strcmp(compop,"xor")) compositer->comp_op = MS_COMPOP_XOR; else { msSetError(MS_PARSEERR,"Unknown COMPOP \"%s\"", "loadLayerCompositer()", compop); free(compop); if (compositer->filter) { msFree(compositer->filter->filter); msFree(compositer->filter); compositer->filter=NULL; } return MS_FAILURE; } free(compop); } break; case END: return MS_SUCCESS; case OPACITY: if (getInteger(&(compositer->opacity)) == -1) { if (compositer->filter) { msFree(compositer->filter->filter); msFree(compositer->filter); compositer->filter=NULL; } return MS_FAILURE; } if(compositer->opacity<0 || compositer->opacity>100) { if (compositer->filter) { msFree(compositer->filter->filter); msFree(compositer->filter); compositer->filter=NULL; } msSetError(MS_PARSEERR,"OPACITY must be between 0 and 100 (line %d)","loadLayerCompositer()",msyylineno); return MS_FAILURE; } break; default: if (compositer->filter) { msFree(compositer->filter->filter); msFree(compositer->filter); compositer->filter=NULL; } msSetError(MS_IDENTERR, "Parsing error 2 near (%s):(line %d)", "loadLayerCompositer()", msyystring_buffer, msyylineno ); return(MS_FAILURE); } } } int loadLayer(layerObj *layer, mapObj *map) { int type; layer->map = (mapObj *)map; for(;;) { switch(msyylex()) { case(BINDVALS): if(loadHashTable(&(layer->bindvals)) != MS_SUCCESS) return(-1); break; case(CLASS): if (msGrowLayerClasses(layer) == NULL) return(-1); initClass(layer->class[layer->numclasses]); if(loadClass(layer->class[layer->numclasses], layer) == -1) return(-1); layer->numclasses++; break; case(CLUSTER): initCluster(&layer->cluster); if(loadCluster(&layer->cluster) == -1) return(-1); break; case(CLASSGROUP): if(getString(&layer->classgroup) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->classgroup, msLookupHashTable(&(layer->validation), "classgroup"), msLookupHashTable(&(map->web.validation), "classgroup"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based CLASSGROUP configuration failed pattern validation." , "loadLayer()"); msFree(layer->classgroup); layer->classgroup=NULL; return(-1); } } break; case(CLASSITEM): if(getString(&layer->classitem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->classitem, msLookupHashTable(&(layer->validation), "classitem"), msLookupHashTable(&(map->web.validation), "classitem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based CLASSITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->classitem); layer->classitem=NULL; return(-1); } } break; case(COMPOSITE): { LayerCompositer *compositer = msSmallMalloc(sizeof(LayerCompositer)); initLayerCompositer(compositer); if(MS_FAILURE == loadLayerCompositer(compositer)) { msFree(compositer); return -1; } if(!layer->compositer) { layer->compositer = compositer; } else { LayerCompositer *lctmp = layer->compositer; while(lctmp->next) lctmp = lctmp->next; lctmp->next = compositer; } break; } case(CONNECTION): if(getString(&layer->connection) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->connection, msLookupHashTable(&(layer->validation), "connection"), msLookupHashTable(&(map->web.validation), "connection"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based CONNECTION configuration failed pattern validation." , "loadLayer()"); msFree(layer->connection); layer->connection=NULL; return(-1); } } break; case(CONNECTIONTYPE): if((type = getSymbol(11, MS_OGR, MS_POSTGIS, MS_WMS, MS_ORACLESPATIAL, MS_WFS, MS_GRATICULE, MS_PLUGIN, MS_UNION, MS_UVRASTER, MS_CONTOUR, MS_KERNELDENSITY)) == -1) return(-1); layer->connectiontype = type; break; case(DATA): if(getString(&layer->data) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->data, msLookupHashTable(&(layer->validation), "data"), msLookupHashTable(&(map->web.validation), "data"), map->datapattern, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based DATA configuration failed pattern validation." , "loadLayer()"); msFree(layer->data); layer->data=NULL; return(-1); } } break; case(DEBUG): if((layer->debug = getSymbol(3, MS_ON,MS_OFF, MS_NUMBER)) == -1) return(-1); if(layer->debug == MS_NUMBER) layer->debug = (int) msyynumber; break; case(DUMP): if((layer->dump = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadLayer()"); return(-1); break; case(ENCODING): if(getString(&layer->encoding) == MS_FAILURE) return(-1); break; case(END): if(layer->type == -1) { msSetError(MS_MISCERR, "Layer type not set.", "loadLayer()"); return(-1); } return(0); break; case(EXTENT): { if(getDouble(&(layer->extent.minx)) == -1) return(-1); if(getDouble(&(layer->extent.miny)) == -1) return(-1); if(getDouble(&(layer->extent.maxx)) == -1) return(-1); if(getDouble(&(layer->extent.maxy)) == -1) return(-1); if (!MS_VALID_EXTENT(layer->extent)) { msSetError(MS_MISCERR, "Given layer extent is invalid. Check that it is in the form: minx, miny, maxx, maxy", "loadLayer()"); return(-1); } break; } case(FEATURE): if(layer->type == -1) { msSetError(MS_MISCERR, "Layer type must be set before defining inline features.", "loadLayer()"); return(-1); } if(layer->type == MS_LAYER_POLYGON) type = MS_SHAPE_POLYGON; else if(layer->type == MS_LAYER_LINE) type = MS_SHAPE_LINE; else type = MS_SHAPE_POINT; layer->connectiontype = MS_INLINE; if(loadFeature(layer, type) == MS_FAILURE) return(-1); break; case(FILTER): if(loadExpression(&(layer->filter)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->filter.string, msLookupHashTable(&(layer->validation), "filter"), msLookupHashTable(&(map->web.validation), "filter"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based FILTER configuration failed pattern validation." , "loadLayer()"); msFreeExpression(&(layer->filter)); return(-1); } } break; case(FILTERITEM): if(getString(&layer->filteritem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->filteritem, msLookupHashTable(&(layer->validation), "filteritem"), msLookupHashTable(&(map->web.validation), "filteritem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based FILTERITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->filteritem); layer->filteritem=NULL; return(-1); } } break; case(FOOTER): if(getString(&layer->footer) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->footer, msLookupHashTable(&(layer->validation), "footer"), msLookupHashTable(&(map->web.validation), "footer"), map->templatepattern, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based FOOTER configuration failed pattern validation." , "loadLayer()"); msFree(layer->footer); layer->footer=NULL; return(-1); } } break; case(GRID): layer->connectiontype = MS_GRATICULE; if (layer->grid) { freeGrid(layer->grid); msFree(layer->grid); } layer->grid = (void *) malloc(sizeof(graticuleObj)); MS_CHECK_ALLOC(layer->grid, sizeof(graticuleObj), -1); initGrid(layer->grid); loadGrid(layer); break; case(GROUP): if(getString(&layer->group) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->group, msLookupHashTable(&(layer->validation), "group"), msLookupHashTable(&(map->web.validation), "group"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based GROUP configuration failed pattern validation." , "loadLayer()"); msFree(layer->group); layer->group=NULL; return(-1); } } break; case(GEOMTRANSFORM): { int s; if((s = getSymbol(1, MS_EXPRESSION)) == -1) return(MS_FAILURE); /* handle expression case here for the moment */ msFree(layer->_geomtransform.string); layer->_geomtransform.string = msStrdup(msyystring_buffer); layer->_geomtransform.type = MS_GEOMTRANSFORM_EXPRESSION; } break; case(HEADER): if(getString(&layer->header) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->header, msLookupHashTable(&(layer->validation), "header"), msLookupHashTable(&(map->web.validation), "header"), map->templatepattern, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based HEADER configuration failed pattern validation." , "loadLayer()"); msFree(layer->header); layer->header=NULL; return(-1); } } break; case(JOIN): if(layer->numjoins == MS_MAXJOINS) { /* no room */ msSetError(MS_IDENTERR, "Maximum number of joins reached.", "loadLayer()"); return(-1); } if(loadJoin(&(layer->joins[layer->numjoins])) == -1) return(-1); layer->numjoins++; break; case(LABELCACHE): if((layer->labelcache = getSymbol(2, MS_ON, MS_OFF)) == -1) return(-1); break; case(LABELITEM): if(getString(&layer->labelitem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->labelitem, msLookupHashTable(&(layer->validation), "labelitem"), msLookupHashTable(&(map->web.validation), "labelitem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based LABELITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->labelitem); layer->labelitem=NULL; return(-1); } } break; case(LABELMAXSCALE): case(LABELMAXSCALEDENOM): if(getDouble(&(layer->labelmaxscaledenom)) == -1) return(-1); break; case(LABELMINSCALE): case(LABELMINSCALEDENOM): if(getDouble(&(layer->labelminscaledenom)) == -1) return(-1); break; case(LABELREQUIRES): if(getString(&layer->labelrequires) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->labelrequires, msLookupHashTable(&(layer->validation), "labelrequires"), msLookupHashTable(&(map->web.validation), "labelrequires"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based LABELREQUIRES configuration failed pattern validation." , "loadLayer()"); msFree(layer->labelrequires); layer->labelrequires=NULL; return(-1); } } break; case(LAYER): break; /* for string loads */ case(MASK): if(getString(&layer->mask) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->mask, msLookupHashTable(&(layer->validation), "mask"), msLookupHashTable(&(map->web.validation), "mask"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based MASK configuration failed pattern validation." , "loadLayer()"); msFree(layer->mask); layer->mask=NULL; return(-1); } } break; case(MAXFEATURES): if(getInteger(&(layer->maxfeatures)) == -1) return(-1); break; case(MAXSCALE): case(MAXSCALEDENOM): if(getDouble(&(layer->maxscaledenom)) == -1) return(-1); break; case(MAXGEOWIDTH): if(getDouble(&(layer->maxgeowidth)) == -1) return(-1); break; case(METADATA): if(loadHashTable(&(layer->metadata)) != MS_SUCCESS) return(-1); break; case(MINSCALE): case(MINSCALEDENOM): if(getDouble(&(layer->minscaledenom)) == -1) return(-1); break; case(MINGEOWIDTH): if(getDouble(&(layer->mingeowidth)) == -1) return(-1); break; case(MINFEATURESIZE): if(getInteger(&(layer->minfeaturesize)) == -1) return(-1); break; case(NAME): if(getString(&layer->name) == MS_FAILURE) return(-1); break; case(OFFSITE): if(loadColor(&(layer->offsite), NULL) != MS_SUCCESS) return(-1); break; case(OPACITY): case(TRANSPARENCY): /* keyword supported for mapfile backwards compatability */ { int opacity; if (getInteger(&opacity) == -1) return(-1); if(opacity != 100) { if(layer->compositer) { msSetError(MS_PARSEERR, "Cannot use OPACITY and COMPOSITER simultaneously at the LAYER level (line %d)", "loadLayer()", msyylineno ); return -1; } layer->compositer = msSmallMalloc(sizeof(LayerCompositer)); initLayerCompositer(layer->compositer); layer->compositer->opacity = opacity; } } break; case(MS_PLUGIN): { int rv; if(getString(&layer->plugin_library_original) == MS_FAILURE) return(-1); rv = msBuildPluginLibraryPath(&layer->plugin_library, layer->plugin_library_original, map); if (rv == MS_FAILURE) return(-1); } break; case(PROCESSING): { /* NOTE: processing array maintained as size+1 with NULL terminator. This ensure that CSL (GDAL string list) functions can be used on the list for easy processing. */ char *value=NULL; if(getString(&value) == MS_FAILURE) return(-1); if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(value, msLookupHashTable(&(layer->validation), "processing"), msLookupHashTable(&(map->web.validation), "processing"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based PROCESSING configuration failed pattern validation." , "loadLayer()"); free(value); value=NULL; return(-1); } } msLayerAddProcessing( layer, value ); free(value); value=NULL; } break; case(POSTLABELCACHE): if((layer->postlabelcache = getSymbol(2, MS_TRUE, MS_FALSE)) == -1) return(-1); if(layer->postlabelcache) layer->labelcache = MS_OFF; break; case(PROJECTION): if(loadProjection(&(layer->projection)) == -1) return(-1); layer->project = MS_TRUE; break; case(REQUIRES): if(getString(&layer->requires) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->requires, msLookupHashTable(&(layer->validation), "requires"), msLookupHashTable(&(map->web.validation), "requires"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based REQUIRES configuration failed pattern validation." , "loadLayer()"); msFree(layer->requires); layer->requires=NULL; return(-1); } } break; case(SCALETOKEN): if (msGrowLayerScaletokens(layer) == NULL) return(-1); initScaleToken(&layer->scaletokens[layer->numscaletokens]); if(loadScaletoken(&layer->scaletokens[layer->numscaletokens], layer) == -1) return(-1); layer->numscaletokens++; break; case(SIZEUNITS): if((layer->sizeunits = getSymbol(8, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD,MS_PIXELS)) == -1) return(-1); break; case(STATUS): if((layer->status = getSymbol(3, MS_ON,MS_OFF,MS_DEFAULT)) == -1) return(-1); break; case(STYLEITEM): if(getString(&layer->styleitem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->styleitem, msLookupHashTable(&(layer->validation), "styleitem"), msLookupHashTable(&(map->web.validation), "styleitem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based STYLEITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->styleitem); layer->styleitem=NULL; return(-1); } } break; case(SYMBOLSCALE): case(SYMBOLSCALEDENOM): if(getDouble(&(layer->symbolscaledenom)) == -1) return(-1); break; case(TEMPLATE): if(getString(&layer->template) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->template, msLookupHashTable(&(layer->validation), "template"), msLookupHashTable(&(map->web.validation), "template"), map->templatepattern, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TEMPLATE configuration failed pattern validation." , "loadLayer()"); msFree(layer->template); layer->template=NULL; return(-1); } } break; case(TILEINDEX): if(getString(&layer->tileindex) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->tileindex, msLookupHashTable(&(layer->validation), "tileindex"), msLookupHashTable(&(map->web.validation), "tileindex"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TILEINDEX configuration failed pattern validation." , "loadLayer()"); msFree(layer->tileindex); layer->tileindex=NULL; return(-1); } } break; case(TILEITEM): if(getString(&layer->tileitem) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->tileitem, msLookupHashTable(&(layer->validation), "tileitem"), msLookupHashTable(&(map->web.validation), "tileitem"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TILEITEM configuration failed pattern validation." , "loadLayer()"); msFree(layer->tileitem); layer->tileitem=NULL; return(-1); } } break; case(TILESRS): if(getString(&layer->tilesrs) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(layer->tilesrs, msLookupHashTable(&(layer->validation), "tilesrs"), msLookupHashTable(&(map->web.validation), "tilesrs"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TILESRS configuration failed pattern validation." , "loadLayer()"); msFree(layer->tilesrs); layer->tilesrs=NULL; return(-1); } } break; case(TOLERANCE): if(getDouble(&(layer->tolerance)) == -1) return(-1); break; case(TOLERANCEUNITS): if((layer->toleranceunits = getSymbol(8, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD,MS_PIXELS)) == -1) return(-1); break; case(TRANSFORM): if((layer->transform = getSymbol(11, MS_TRUE,MS_FALSE, MS_UL,MS_UC,MS_UR,MS_CL,MS_CC,MS_CR,MS_LL,MS_LC,MS_LR)) == -1) return(-1); break; case(TYPE): if((type = getSymbol(9, MS_LAYER_POINT,MS_LAYER_LINE,MS_LAYER_RASTER,MS_LAYER_POLYGON,MS_LAYER_ANNOTATION,MS_LAYER_QUERY,MS_LAYER_CIRCLE,MS_LAYER_CHART,TILEINDEX)) == -1) return(-1); if(type == TILEINDEX) type = MS_LAYER_TILEINDEX; /* TILEINDEX is also a parameter */ if(type == MS_LAYER_ANNOTATION) { msSetError(MS_IDENTERR, "Annotation Layers have been removed. To obtain same functionality, use a layer with label->styles and no class->styles", "loadLayer()"); return -1; } layer->type = type; break; case(UNITS): if((layer->units = getSymbol(9, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD,MS_PIXELS,MS_PERCENTAGES)) == -1) return(-1); break; case(UTFDATA): if(loadExpression(&(layer->utfdata)) == -1) return(-1); /* loadExpression() cleans up previously allocated expression */ break; case(UTFITEM): if(getString(&layer->utfitem) == MS_FAILURE) return(-1); /* loadExpression() cleans up previously allocated expression */ break; case(VALIDATION): if(loadHashTable(&(layer->validation)) != MS_SUCCESS) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadLayer()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateLayerFromString(layerObj *layer, char *string, int url_string) { int i; if(!layer || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadLayer(layer, layer->map) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); /* step through classes to resolve symbol names */ for(i=0; inumclasses; i++) { if(classResolveSymbolNames(layer->class[i]) != MS_SUCCESS) return MS_FAILURE; } return MS_SUCCESS; } static void writeCompositingFilter(FILE *stream, int indent, CompositingFilter *filter) { while(filter) { writeString(stream, indent, "COMPFILTER", "", filter->filter); filter = filter->next; } } static void writeLayerCompositer(FILE *stream, int indent, LayerCompositer *compositor) { indent++; while(compositor) { writeBlockBegin(stream, indent, "COMPOSITE"); writeCompositingFilter(stream, indent, compositor->filter); if(compositor->comp_op != MS_COMPOP_SRC_OVER) { switch(compositor->comp_op) { case MS_COMPOP_CLEAR: writeString(stream, indent, "COMPOP", NULL, "clear"); break; case MS_COMPOP_COLOR_BURN: writeString(stream, indent, "COMPOP", NULL, "color-burn"); break; case MS_COMPOP_COLOR_DODGE: writeString(stream, indent, "COMPOP", NULL, "color-dodge"); break; case MS_COMPOP_CONTRAST: writeString(stream, indent, "COMPOP", NULL, "contrast"); break; case MS_COMPOP_DARKEN: writeString(stream, indent, "COMPOP", NULL, "darken"); break; case MS_COMPOP_DIFFERENCE: writeString(stream, indent, "COMPOP", NULL, "difference"); break; case MS_COMPOP_DST: writeString(stream, indent, "COMPOP", NULL, "dst"); break; case MS_COMPOP_DST_ATOP: writeString(stream, indent, "COMPOP", NULL, "dst-atop"); break; case MS_COMPOP_DST_IN: writeString(stream, indent, "COMPOP", NULL, "dst-in"); break; case MS_COMPOP_DST_OUT: writeString(stream, indent, "COMPOP", NULL, "dst-out"); break; case MS_COMPOP_DST_OVER: writeString(stream, indent, "COMPOP", NULL, "dst-over"); break; case MS_COMPOP_EXCLUSION: writeString(stream, indent, "COMPOP", NULL, "exclusion"); break; case MS_COMPOP_HARD_LIGHT: writeString(stream, indent, "COMPOP", NULL, "hard-light"); break; case MS_COMPOP_INVERT: writeString(stream, indent, "COMPOP", NULL, "invert"); break; case MS_COMPOP_INVERT_RGB: writeString(stream, indent, "COMPOP", NULL, "invert-rgb"); break; case MS_COMPOP_LIGHTEN: writeString(stream, indent, "COMPOP", NULL, "lighten"); break; case MS_COMPOP_MINUS: writeString(stream, indent, "COMPOP", NULL, "minus"); break; case MS_COMPOP_MULTIPLY: writeString(stream, indent, "COMPOP", NULL, "multiply"); break; case MS_COMPOP_OVERLAY: writeString(stream, indent, "COMPOP", NULL, "overlay"); break; case MS_COMPOP_PLUS: writeString(stream, indent, "COMPOP", NULL, "plus"); break; case MS_COMPOP_SCREEN: writeString(stream, indent, "COMPOP", NULL, "screen"); break; case MS_COMPOP_SOFT_LIGHT: writeString(stream, indent, "COMPOP", NULL, "soft-light"); break; case MS_COMPOP_SRC: writeString(stream, indent, "COMPOP", NULL, "src"); break; case MS_COMPOP_SRC_ATOP: writeString(stream, indent, "COMPOP", NULL, "src-atop"); break; case MS_COMPOP_SRC_IN: writeString(stream, indent, "COMPOP", NULL, "src-in"); break; case MS_COMPOP_SRC_OUT: writeString(stream, indent, "COMPOP", NULL, "src-out"); break; case MS_COMPOP_SRC_OVER: writeString(stream, indent, "COMPOP", NULL, "src-over"); break; case MS_COMPOP_XOR: writeString(stream, indent, "COMPOP", NULL, "xor"); break; } } writeNumber(stream,indent,"OPACITY",100,compositor->opacity); writeBlockEnd(stream,indent,"COMPOSITE"); compositor = compositor->next; } } static void writeLayer(FILE *stream, int indent, layerObj *layer) { int i; featureListNodeObjPtr current=NULL; if(layer->status == MS_DELETE) return; indent++; writeBlockBegin(stream, indent, "LAYER"); /* bindvals */ /* class - see below */ writeString(stream, indent, "CLASSGROUP", NULL, layer->classgroup); writeString(stream, indent, "CLASSITEM", NULL, layer->classitem); writeCluster(stream, indent, &(layer->cluster)); writeLayerCompositer(stream, indent, layer->compositer); writeString(stream, indent, "CONNECTION", NULL, layer->connection); writeKeyword(stream, indent, "CONNECTIONTYPE", layer->connectiontype, 10, MS_OGR, "OGR", MS_POSTGIS, "POSTGIS", MS_WMS, "WMS", MS_ORACLESPATIAL, "ORACLESPATIAL", MS_WFS, "WFS", MS_PLUGIN, "PLUGIN", MS_UNION, "UNION", MS_UVRASTER, "UVRASTER", MS_CONTOUR, "CONTOUR", MS_KERNELDENSITY, "KERNELDENSITY"); writeString(stream, indent, "DATA", NULL, layer->data); writeNumber(stream, indent, "DEBUG", 0, layer->debug); /* is this right? see loadLayer() */ writeString(stream, indent, "ENCODING", NULL, layer->encoding); writeExtent(stream, indent, "EXTENT", layer->extent); writeExpression(stream, indent, "FILTER", &(layer->filter)); writeString(stream, indent, "FILTERITEM", NULL, layer->filteritem); writeString(stream, indent, "FOOTER", NULL, layer->footer); writeString(stream, indent, "GROUP", NULL, layer->group); if(layer->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) { writeIndent(stream, indent + 1); fprintf(stream, "GEOMTRANSFORM (%s)\n", layer->_geomtransform.string); } writeString(stream, indent, "HEADER", NULL, layer->header); /* join - see below */ writeKeyword(stream, indent, "LABELCACHE", layer->labelcache, 1, MS_OFF, "OFF"); writeString(stream, indent, "LABELITEM", NULL, layer->labelitem); writeNumber(stream, indent, "LABELMAXSCALEDENOM", -1, layer->labelmaxscaledenom); writeNumber(stream, indent, "LABELMINSCALEDENOM", -1, layer->labelminscaledenom); writeString(stream, indent, "LABELREQUIRES", NULL, layer->labelrequires); writeNumber(stream, indent, "MAXFEATURES", -1, layer->maxfeatures); writeNumber(stream, indent, "MAXGEOWIDTH", -1, layer->maxgeowidth); writeNumber(stream, indent, "MAXSCALEDENOM", -1, layer->maxscaledenom); writeString(stream, indent, "MASK", NULL, layer->mask); writeHashTable(stream, indent, "METADATA", &(layer->metadata)); writeNumber(stream, indent, "MINGEOWIDTH", -1, layer->mingeowidth); writeNumber(stream, indent, "MINSCALEDENOM", -1, layer->minscaledenom); writeNumber(stream, indent, "MINFEATURESIZE", -1, layer->minfeaturesize); writeString(stream, indent, "NAME", NULL, layer->name); writeColor(stream, indent, "OFFSITE", NULL, &(layer->offsite)); writeString(stream, indent, "PLUGIN", NULL, layer->plugin_library_original); writeKeyword(stream, indent, "POSTLABELCACHE", layer->postlabelcache, 1, MS_TRUE, "TRUE"); for(i=0; inumprocessing; i++) writeString(stream, indent, "PROCESSING", NULL, layer->processing[i]); writeProjection(stream, indent, &(layer->projection)); writeString(stream, indent, "REQUIRES", NULL, layer->requires); writeKeyword(stream, indent, "SIZEUNITS", layer->sizeunits, 7, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD"); writeKeyword(stream, indent, "STATUS", layer->status, 3, MS_ON, "ON", MS_OFF, "OFF", MS_DEFAULT, "DEFAULT"); writeString(stream, indent, "STYLEITEM", NULL, layer->styleitem); writeNumber(stream, indent, "SYMBOLSCALEDENOM", -1, layer->symbolscaledenom); writeString(stream, indent, "TEMPLATE", NULL, layer->template); writeString(stream, indent, "TILEINDEX", NULL, layer->tileindex); writeString(stream, indent, "TILEITEM", NULL, layer->tileitem); writeString(stream, indent, "TILESRS", NULL, layer->tilesrs); writeNumber(stream, indent, "TOLERANCE", -1, layer->tolerance); writeKeyword(stream, indent, "TOLERANCEUNITS", layer->toleranceunits, 7, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD"); writeKeyword(stream, indent, "TRANSFORM", layer->transform, 10, MS_FALSE, "FALSE", MS_UL, "UL", MS_UC, "UC", MS_UR, "UR", MS_CL, "CL", MS_CC, "CC", MS_CR, "CR", MS_LL, "LL", MS_LC, "LC", MS_LR, "LR"); writeKeyword(stream, indent, "TYPE", layer->type, 9, MS_LAYER_POINT, "POINT", MS_LAYER_LINE, "LINE", MS_LAYER_POLYGON, "POLYGON", MS_LAYER_RASTER, "RASTER", MS_LAYER_ANNOTATION, "ANNOTATION", MS_LAYER_QUERY, "QUERY", MS_LAYER_CIRCLE, "CIRCLE", MS_LAYER_TILEINDEX, "TILEINDEX", MS_LAYER_CHART, "CHART"); writeKeyword(stream, indent, "UNITS", layer->units, 9, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD", MS_PIXELS, "PIXELS", MS_PERCENTAGES, "PERCENTATGES"); writeHashTable(stream, indent, "VALIDATION", &(layer->validation)); /* write potentially multiply occuring objects last */ for(i=0; inumscaletokens; i++) writeScaleToken(stream, indent, &(layer->scaletokens[i])); for(i=0; inumjoins; i++) writeJoin(stream, indent, &(layer->joins[i])); for(i=0; inumclasses; i++) writeClass(stream, indent, layer->class[i]); if( layer->grid && layer->connectiontype == MS_GRATICULE) writeGrid(stream, indent, layer->grid); else { current = layer->features; while(current != NULL) { writeFeature(stream, indent, &(current->shape)); current = current->next; } } writeBlockEnd(stream, indent, "LAYER"); writeLineFeed(stream); } char* msWriteLayerToString(layerObj *layer) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeLayer(stdout, -1, layer); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a referenceMapObj structure */ void initReferenceMap(referenceMapObj *ref) { ref->height = ref->width = 0; ref->extent.minx = ref->extent.miny = ref->extent.maxx = ref->extent.maxy = -1.0; ref->image = NULL; MS_INIT_COLOR(ref->color, 255, 0, 0, 255); MS_INIT_COLOR(ref->outlinecolor, 0, 0, 0, 255); ref->status = MS_OFF; ref->marker = 0; ref->markername = NULL; ref->markersize = 0; ref->minboxsize = 3; ref->maxboxsize = 0; ref->map = NULL; } void freeReferenceMap(referenceMapObj *ref) { msFree(ref->image); msFree(ref->markername); } int loadReferenceMap(referenceMapObj *ref, mapObj *map) { int state; ref->map = (mapObj *)map; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadReferenceMap()"); return(-1); case(END): if(!ref->image) { msSetError(MS_MISCERR, "No image defined for the reference map.", "loadReferenceMap()"); return(-1); } if(ref->width == 0 || ref->height == 0) { msSetError(MS_MISCERR, "No image size defined for the reference map.", "loadReferenceMap()"); return(-1); } return(0); break; case(COLOR): if(loadColor(&(ref->color), NULL) != MS_SUCCESS) return(-1); break; case(EXTENT): if(getDouble(&(ref->extent.minx)) == -1) return(-1); if(getDouble(&(ref->extent.miny)) == -1) return(-1); if(getDouble(&(ref->extent.maxx)) == -1) return(-1); if(getDouble(&(ref->extent.maxy)) == -1) return(-1); if (!MS_VALID_EXTENT(ref->extent)) { msSetError(MS_MISCERR, "Given reference extent is invalid. Check that it " \ "is in the form: minx, miny, maxx, maxy", "loadReferenceMap()"); return(-1); } break; case(IMAGE): if(getString(&ref->image) == MS_FAILURE) return(-1); break; case(OUTLINECOLOR): if(loadColor(&(ref->outlinecolor), NULL) != MS_SUCCESS) return(-1); break; case(SIZE): if(getInteger(&(ref->width)) == -1) return(-1); if(getInteger(&(ref->height)) == -1) return(-1); break; case(STATUS): if((ref->status = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(MARKER): if((state = getSymbol(2, MS_NUMBER,MS_STRING)) == -1) return(-1); if(state == MS_NUMBER) ref->marker = (int) msyynumber; else { if (ref->markername != NULL) msFree(ref->markername); ref->markername = msStrdup(msyystring_buffer); } break; case(MARKERSIZE): if(getInteger(&(ref->markersize)) == -1) return(-1); break; case(MINBOXSIZE): if(getInteger(&(ref->minboxsize)) == -1) return(-1); break; case(MAXBOXSIZE): if(getInteger(&(ref->maxboxsize)) == -1) return(-1); break; case(REFERENCE): break; /* for string loads */ default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadReferenceMap()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateReferenceMapFromString(referenceMapObj *ref, char *string, int url_string) { if(!ref || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadReferenceMap(ref, ref->map) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeReferenceMap(FILE *stream, int indent, referenceMapObj *ref) { colorObj c; if(!ref->image) return; indent++; writeBlockBegin(stream, indent, "REFERENCE"); MS_INIT_COLOR(c,255,0,0,255); writeColor(stream, indent, "COLOR", &c, &(ref->color)); writeExtent(stream, indent, "EXTENT", ref->extent); writeString(stream, indent, "IMAGE", NULL, ref->image); MS_INIT_COLOR(c,0,0,0,255); writeColor(stream, indent, "OUTLINECOLOR", &c, &(ref->outlinecolor)); writeDimension(stream, indent, "SIZE", ref->width, ref->height, NULL, NULL); writeKeyword(stream, indent, "STATUS", ref->status, 2, MS_ON, "ON", MS_OFF, "OFF"); writeNumberOrString(stream, indent, "MARKER", 0, ref->marker, ref->markername); writeNumber(stream, indent, "MARKERSIZE", -1, ref->markersize); writeNumber(stream, indent, "MAXBOXSIZE", -1, ref->maxboxsize); writeNumber(stream, indent, "MINBOXSIZE", -1, ref->minboxsize); writeBlockEnd(stream, indent, "REFERENCE"); writeLineFeed(stream); } char* msWriteReferenceMapToString(referenceMapObj *ref) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeReferenceMap(stdout, -1, ref); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } #define MAX_FORMATOPTIONS 100 static int loadOutputFormat(mapObj *map) { char *name = NULL; char *mimetype = NULL; char *driver = NULL; char *extension = NULL; int imagemode = MS_NOOVERRIDE; int transparent = MS_NOOVERRIDE; char *formatoptions[MAX_FORMATOPTIONS]; int numformatoptions = 0; char *value = NULL; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadOutputFormat()"); goto load_output_error; case(END): { outputFormatObj *format; if( driver == NULL ) { msSetError(MS_MISCERR, "OUTPUTFORMAT clause lacks DRIVER keyword near (%s):(%d)", "loadOutputFormat()", msyystring_buffer, msyylineno ); goto load_output_error; } format = msCreateDefaultOutputFormat( map, driver, name ); if( format == NULL ) { msSetError(MS_MISCERR, "OUTPUTFORMAT (%s) clause references driver (%s), but this driver isn't configured.", "loadOutputFormat()", name, driver ); goto load_output_error; } msFree( name ); name = NULL; msFree( driver ); driver = NULL; if( transparent != MS_NOOVERRIDE ) format->transparent = transparent; if( extension != NULL ) { msFree( format->extension ); format->extension = extension; extension = NULL; } if( mimetype != NULL ) { msFree( format->mimetype ); format->mimetype = mimetype; mimetype = NULL; } if( imagemode != MS_NOOVERRIDE ) { if(format->renderer != MS_RENDER_WITH_AGG || imagemode != MS_IMAGEMODE_PC256) { /* don't force to PC256 with agg, this can happen when using mapfile defined GD * ouputformats that are now falling back to agg/png8 */ format->imagemode = imagemode; } if( transparent == MS_NOOVERRIDE ) { if( imagemode == MS_IMAGEMODE_RGB ) format->transparent = MS_FALSE; else if( imagemode == MS_IMAGEMODE_RGBA ) format->transparent = MS_TRUE; } if( format->imagemode == MS_IMAGEMODE_INT16 || format->imagemode == MS_IMAGEMODE_FLOAT32 || format->imagemode == MS_IMAGEMODE_BYTE ) format->renderer = MS_RENDER_WITH_RAWDATA; } while(numformatoptions--) { char *key = strchr(formatoptions[numformatoptions],'='); if(!key || !*(key+1)) { msSetError(MS_MISCERR,"Failed to parse FORMATOPTION, expecting \"KEY=VALUE\" syntax.","loadOutputFormat()"); goto load_output_error; } *key = 0; key++; msSetOutputFormatOption(format,formatoptions[numformatoptions],key); free(formatoptions[numformatoptions]); } format->inmapfile = MS_TRUE; msOutputFormatValidate( format, MS_FALSE ); return(0); } case(NAME): msFree( name ); if((name = getToken()) == NULL) goto load_output_error; break; case(MIMETYPE): if(getString(&mimetype) == MS_FAILURE) goto load_output_error; break; case(DRIVER): { int s; if((s = getSymbol(2, MS_STRING, TEMPLATE)) == -1) /* allow the template to be quoted or not in the mapfile */ goto load_output_error; free(driver); if(s == MS_STRING) driver = msStrdup(msyystring_buffer); else driver = msStrdup("TEMPLATE"); } break; case(EXTENSION): if(getString(&extension) == MS_FAILURE) goto load_output_error; if( extension[0] == '.' ) { char *temp = msStrdup(extension+1); free( extension ); extension = temp; } break; case(FORMATOPTION): if(getString(&value) == MS_FAILURE) goto load_output_error; if( numformatoptions < MAX_FORMATOPTIONS ) formatoptions[numformatoptions++] = value; value=NULL; break; case(IMAGEMODE): value = getToken(); if( strcasecmp(value,"PC256") == 0 ) imagemode = MS_IMAGEMODE_PC256; else if( strcasecmp(value,"RGB") == 0 ) imagemode = MS_IMAGEMODE_RGB; else if( strcasecmp(value,"RGBA") == 0) imagemode = MS_IMAGEMODE_RGBA; else if( strcasecmp(value,"INT16") == 0) imagemode = MS_IMAGEMODE_INT16; else if( strcasecmp(value,"FLOAT32") == 0) imagemode = MS_IMAGEMODE_FLOAT32; else if( strcasecmp(value,"BYTE") == 0) imagemode = MS_IMAGEMODE_BYTE; else if( strcasecmp(value,"FEATURE") == 0) imagemode = MS_IMAGEMODE_FEATURE; else { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d), expected PC256, RGB, RGBA, FEATURE, BYTE, INT16, or FLOAT32 for IMAGEMODE.", "loadOutputFormat()", msyystring_buffer, msyylineno); goto load_output_error; } free(value); value=NULL; break; case(TRANSPARENT): if((transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) goto load_output_error; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadOutputFormat()", msyystring_buffer, msyylineno); goto load_output_error; } } /* next token */ load_output_error: msFree( driver ); msFree( extension ); msFree( mimetype ); msFree( name ); msFree( value ); return -1; } /* ** utility function to write an output format structure to file */ static void writeOutputformatobject(FILE *stream, int indent, outputFormatObj *outputformat) { int i = 0; if(!outputformat) return; indent++; writeBlockBegin(stream, indent, "OUTPUTFORMAT"); writeString(stream, indent, "NAME", NULL, outputformat->name); writeString(stream, indent, "MIMETYPE", NULL, outputformat->mimetype); writeString(stream, indent, "DRIVER", NULL, outputformat->driver); writeString(stream, indent, "EXTENSION", NULL, outputformat->extension); writeKeyword(stream, indent, "IMAGEMODE", outputformat->imagemode, 7, MS_IMAGEMODE_PC256, "PC256", MS_IMAGEMODE_RGB, "RGB", MS_IMAGEMODE_RGBA, "RGBA", MS_IMAGEMODE_INT16, "INT16", MS_IMAGEMODE_FLOAT32, "FLOAT32", MS_IMAGEMODE_BYTE, "BYTE", MS_IMAGEMODE_FEATURE, "FEATURE"); writeKeyword(stream, indent, "TRANSPARENT", outputformat->transparent, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); for (i=0; inumformatoptions; i++) writeString(stream, indent, "FORMATOPTION", NULL, outputformat->formatoptions[i]); writeBlockEnd(stream, indent, "OUTPUTFORMAT"); writeLineFeed(stream); } /* ** Write the output formats to file */ static void writeOutputformat(FILE *stream, int indent, mapObj *map) { int i=0; if(!map->outputformat) return; writeOutputformatobject(stream, indent, map->outputformat); for(i=0; inumoutputformats; i++) { if(map->outputformatlist[i]->inmapfile == MS_TRUE && strcmp(map->outputformatlist[i]->name, map->outputformat->name) != 0) writeOutputformatobject(stream, indent, map->outputformatlist[i]); } } /* ** Initialize, load and free a legendObj structure */ void initLegend(legendObj *legend) { legend->height = legend->width = 0; MS_INIT_COLOR(legend->imagecolor, 255,255,255,255); /* white */ MS_INIT_COLOR(legend->outlinecolor, -1,-1,-1,255); initLabel(&legend->label); legend->label.position = MS_XY; /* override */ legend->keysizex = 20; legend->keysizey = 10; legend->keyspacingx = 5; legend->keyspacingy = 5; legend->status = MS_OFF; legend->transparent = MS_NOOVERRIDE; legend->interlace = MS_NOOVERRIDE; legend->position = MS_LL; legend->postlabelcache = MS_FALSE; /* draw with labels */ legend->template = NULL; legend->map = NULL; } void freeLegend(legendObj *legend) { if (legend->template) free(legend->template); freeLabel(&(legend->label)); } int loadLegend(legendObj *legend, mapObj *map) { legend->map = (mapObj *)map; for(;;) { switch(msyylex()) { case(EOF): msSetError(MS_EOFERR, NULL, "loadLegend()"); return(-1); case(END): legend->label.position = MS_XY; /* overrides go here */ return(0); break; case(IMAGECOLOR): if(loadColor(&(legend->imagecolor), NULL) != MS_SUCCESS) return(-1); break; case(INTERLACE): if((legend->interlace = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(KEYSIZE): if(getInteger(&(legend->keysizex)) == -1) return(-1); if(getInteger(&(legend->keysizey)) == -1) return(-1); break; case(KEYSPACING): if(getInteger(&(legend->keyspacingx)) == -1) return(-1); if(getInteger(&(legend->keyspacingy)) == -1) return(-1); break; case(LABEL): if(loadLabel(&(legend->label)) == -1) return(-1); legend->label.angle = 0; /* force */ break; case(LEGEND): break; /* for string loads */ case(OUTLINECOLOR): if(loadColor(&(legend->outlinecolor), NULL) != MS_SUCCESS) return(-1); break; case(POSITION): if((legend->position = getSymbol(6, MS_UL,MS_UR,MS_LL,MS_LR,MS_UC,MS_LC)) == -1) return(-1); break; case(POSTLABELCACHE): if((legend->postlabelcache = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(STATUS): if((legend->status = getSymbol(3, MS_ON,MS_OFF,MS_EMBED)) == -1) return(-1); break; case(TRANSPARENT): if((legend->transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(TEMPLATE): if(getString(&legend->template) == MS_FAILURE) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadLegend()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateLegendFromString(legendObj *legend, char *string, int url_string) { if(!legend || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadLegend(legend, legend->map) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeLegend(FILE *stream, int indent, legendObj *legend) { colorObj c; indent++; writeBlockBegin(stream, indent, "LEGEND"); MS_INIT_COLOR(c,255,255,255,255); writeColor(stream, indent, "IMAGECOLOR", &c, &(legend->imagecolor)); writeKeyword(stream, indent, "INTERLACE", legend->interlace, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeDimension(stream, indent, "KEYSIZE", legend->keysizex, legend->keysizey, NULL, NULL); writeDimension(stream, indent, "KEYSPACING", legend->keyspacingx, legend->keyspacingy, NULL, NULL); writeLabel(stream, indent, &(legend->label)); writeColor(stream, indent, "OUTLINECOLOR", NULL, &(legend->outlinecolor)); if(legend->status == MS_EMBED) writeKeyword(stream, indent, "POSITION", legend->position, 6, MS_LL, "LL", MS_UL, "UL", MS_UR, "UR", MS_LR, "LR", MS_UC, "UC", MS_LC, "LC"); writeKeyword(stream, indent, "POSTLABELCACHE", legend->postlabelcache, 1, MS_TRUE, "TRUE"); writeKeyword(stream, indent, "STATUS", legend->status, 3, MS_ON, "ON", MS_OFF, "OFF", MS_EMBED, "EMBED"); writeKeyword(stream, indent, "TRANSPARENT", legend->transparent, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeString(stream, indent, "TEMPLATE", NULL, legend->template); writeBlockEnd(stream, indent, "LEGEND"); writeLineFeed(stream); } char* msWriteLegendToString(legendObj *legend) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeLegend(stdout, -1, legend); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize, load and free a scalebarObj structure */ void initScalebar(scalebarObj *scalebar) { MS_INIT_COLOR(scalebar->imagecolor, -1,-1,-1,255); scalebar->width = 200; scalebar->height = 3; scalebar->style = 0; /* only 2 styles at this point */ scalebar->intervals = 4; initLabel(&scalebar->label); scalebar->label.position = MS_XY; /* override */ MS_INIT_COLOR(scalebar->backgroundcolor, -1,-1,-1,255); /* if not set, scalebar creation needs to set this to match the background color */ MS_INIT_COLOR(scalebar->color, 0,0,0,255); /* default to black */ MS_INIT_COLOR(scalebar->outlinecolor, -1,-1,-1,255); scalebar->units = MS_MILES; scalebar->status = MS_OFF; scalebar->position = MS_LL; scalebar->transparent = MS_NOOVERRIDE; /* no transparency */ scalebar->interlace = MS_NOOVERRIDE; scalebar->postlabelcache = MS_FALSE; /* draw with labels */ scalebar->align = MS_ALIGN_CENTER; scalebar->offsetx = 0; scalebar->offsety = 0; } void freeScalebar(scalebarObj *scalebar) { freeLabel(&(scalebar->label)); } int loadScalebar(scalebarObj *scalebar) { for(;;) { switch(msyylex()) { case(ALIGN): if((scalebar->align = getSymbol(3, MS_ALIGN_LEFT,MS_ALIGN_CENTER,MS_ALIGN_RIGHT)) == -1) return(-1); break; case(BACKGROUNDCOLOR): if(loadColor(&(scalebar->backgroundcolor), NULL) != MS_SUCCESS) return(-1); break; case(COLOR): if(loadColor(&(scalebar->color), NULL) != MS_SUCCESS) return(-1); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadScalebar()"); return(-1); case(END): return(0); break; case(IMAGECOLOR): if(loadColor(&(scalebar->imagecolor), NULL) != MS_SUCCESS) return(-1); break; case(INTERLACE): if((scalebar->interlace = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(INTERVALS): if(getInteger(&(scalebar->intervals)) == -1) return(-1); break; case(LABEL): if(loadLabel(&(scalebar->label)) == -1) return(-1); scalebar->label.angle = 0; break; case(OUTLINECOLOR): if(loadColor(&(scalebar->outlinecolor), NULL) != MS_SUCCESS) return(-1); break; case(POSITION): if((scalebar->position = getSymbol(6, MS_UL,MS_UR,MS_LL,MS_LR,MS_UC,MS_LC)) == -1) return(-1); break; case(POSTLABELCACHE): if((scalebar->postlabelcache = getSymbol(2, MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(SCALEBAR): break; /* for string loads */ case(SIZE): if(getInteger(&(scalebar->width)) == -1) return(-1); if(getInteger(&(scalebar->height)) == -1) return(-1); break; case(STATUS): if((scalebar->status = getSymbol(3, MS_ON,MS_OFF,MS_EMBED)) == -1) return(-1); break; case(STYLE): if(getInteger(&(scalebar->style)) == -1) return(-1); break; case(TRANSPARENT): if((scalebar->transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(UNITS): if((scalebar->units = getSymbol(6, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES)) == -1) return(-1); break; case(OFFSET): if(getInteger(&(scalebar->offsetx)) == -1) return(-1); if(getInteger(&(scalebar->offsety)) == -1) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadScalebar()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } /* next token */ } int msUpdateScalebarFromString(scalebarObj *scalebar, char *string, int url_string) { if(!scalebar || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadScalebar(scalebar) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeScalebar(FILE *stream, int indent, scalebarObj *scalebar) { colorObj c; indent++; writeBlockBegin(stream, indent, "SCALEBAR"); writeKeyword(stream, indent, "ALIGN", scalebar->align, 2, MS_ALIGN_LEFT, "LEFT", MS_ALIGN_RIGHT, "RIGHT"); writeColor(stream, indent, "BACKGROUNDCOLOR", NULL, &(scalebar->backgroundcolor)); MS_INIT_COLOR(c,0,0,0,255); writeColor(stream, indent, "COLOR", &c, &(scalebar->color)); writeColor(stream, indent, "IMAGECOLOR", NULL, &(scalebar->imagecolor)); writeKeyword(stream, indent, "INTERLACE", scalebar->interlace, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeNumber(stream, indent, "INTERVALS", -1, scalebar->intervals); writeLabel(stream, indent, &(scalebar->label)); writeColor(stream, indent, "OUTLINECOLOR", NULL, &(scalebar->outlinecolor)); if(scalebar->status == MS_EMBED) writeKeyword(stream, indent, "POSITION", scalebar->position, 6, MS_LL, "LL", MS_UL, "UL", MS_UR, "UR", MS_LR, "LR", MS_UC, "UC", MS_LC, "LC"); writeKeyword(stream, indent, "POSTLABELCACHE", scalebar->postlabelcache, 1, MS_TRUE, "TRUE"); writeDimension(stream, indent, "SIZE", scalebar->width, scalebar->height, NULL, NULL); writeKeyword(stream, indent, "STATUS", scalebar->status, 3, MS_ON, "ON", MS_OFF, "OFF", MS_EMBED, "EMBED"); writeNumber(stream, indent, "STYLE", 0, scalebar->style); writeKeyword(stream, indent, "TRANSPARENT", scalebar->transparent, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeKeyword(stream, indent, "UNITS", scalebar->units, 6, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES"); writeBlockEnd(stream, indent, "SCALEBAR"); writeLineFeed(stream); } char* msWriteScalebarToString(scalebarObj *scalebar) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeScalebar(stdout, -1, scalebar); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize a queryMapObj structure */ void initQueryMap(queryMapObj *querymap) { querymap->width = querymap->height = -1; querymap->style = MS_HILITE; querymap->status = MS_OFF; MS_INIT_COLOR(querymap->color, 255,255,0,255); /* yellow */ } int loadQueryMap(queryMapObj *querymap) { for(;;) { switch(msyylex()) { case(QUERYMAP): break; /* for string loads */ case(COLOR): if(loadColor(&(querymap->color), NULL) != MS_SUCCESS) return MS_FAILURE; break; case(EOF): msSetError(MS_EOFERR, NULL, "loadQueryMap()"); return(-1); case(END): return(0); break; case(SIZE): if(getInteger(&(querymap->width)) == -1) return(-1); if(getInteger(&(querymap->height)) == -1) return(-1); break; case(STATUS): if((querymap->status = getSymbol(2, MS_ON,MS_OFF)) == -1) return(-1); break; case(STYLE): case(TYPE): if((querymap->style = getSymbol(3, MS_NORMAL,MS_HILITE,MS_SELECTED)) == -1) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadQueryMap()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } } int msUpdateQueryMapFromString(queryMapObj *querymap, char *string, int url_string) { if(!querymap || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadQueryMap(querymap) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } static void writeQueryMap(FILE *stream, int indent, queryMapObj *querymap) { colorObj c; indent++; writeBlockBegin(stream, indent, "QUERYMAP"); MS_INIT_COLOR(c,255,255,0,255); writeColor(stream, indent, "COLOR", &c, &(querymap->color)); writeDimension(stream, indent, "SIZE", querymap->width, querymap->height, NULL, NULL); writeKeyword(stream, indent, "STATUS", querymap->status, 2, MS_ON, "ON", MS_OFF, "OFF"); writeKeyword(stream, indent, "STYLE", querymap->style, 3, MS_NORMAL, "NORMAL", MS_HILITE, "HILITE", MS_SELECTED, "SELECTED"); writeBlockEnd(stream, indent, "QUERYMAP"); writeLineFeed(stream); } char* msWriteQueryMapToString(queryMapObj *querymap) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeQueryMap(stdout, -1, querymap); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } /* ** Initialize a webObj structure */ void initWeb(webObj *web) { web->extent.minx = web->extent.miny = web->extent.maxx = web->extent.maxy = -1.0; web->template = NULL; web->header = web->footer = NULL; web->error = web->empty = NULL; web->mintemplate = web->maxtemplate = NULL; web->minscaledenom = web->maxscaledenom = -1; web->log = NULL; web->imagepath = msStrdup(""); web->temppath = NULL; web->imageurl = msStrdup(""); initHashTable(&(web->metadata)); initHashTable(&(web->validation)); web->map = NULL; web->queryformat = msStrdup("text/html"); web->legendformat = msStrdup("text/html"); web->browseformat = msStrdup("text/html"); } void freeWeb(webObj *web) { msFree(web->template); msFree(web->header); msFree(web->footer); msFree(web->error); msFree(web->empty); msFree(web->maxtemplate); msFree(web->mintemplate); msFree(web->log); msFree(web->imagepath); msFree(web->temppath); msFree(web->imageurl); msFree(web->queryformat); msFree(web->legendformat); msFree(web->browseformat); if(&(web->metadata)) msFreeHashItems(&(web->metadata)); if(&(web->validation)) msFreeHashItems(&(web->validation)); } static void writeWeb(FILE *stream, int indent, webObj *web) { indent++; writeBlockBegin(stream, indent, "WEB"); writeString(stream, indent, "BROWSEFORMAT", "text/html", web->browseformat); writeString(stream, indent, "EMPTY", NULL, web->empty); writeString(stream, indent, "ERROR", NULL, web->error); writeExtent(stream, indent, "EXTENT", web->extent); writeString(stream, indent, "FOOTER", NULL, web->footer); writeString(stream, indent, "HEADER", NULL, web->header); writeString(stream, indent, "IMAGEPATH", "", web->imagepath); writeString(stream, indent, "TEMPPATH", NULL, web->temppath); writeString(stream, indent, "IMAGEURL", "", web->imageurl); writeString(stream, indent, "LEGENDFORMAT", "text/html", web->legendformat); writeString(stream, indent, "LOG", NULL, web->log); writeNumber(stream, indent, "MAXSCALEDENOM", -1, web->maxscaledenom); writeString(stream, indent, "MAXTEMPLATE", NULL, web->maxtemplate); writeHashTable(stream, indent, "METADATA", &(web->metadata)); writeNumber(stream, indent, "MINSCALEDENOM", -1, web->minscaledenom); writeString(stream, indent, "MINTEMPLATE", NULL, web->mintemplate); writeString(stream, indent, "QUERYFORMAT", "text/html", web->queryformat); writeString(stream, indent, "TEMPLATE", NULL, web->template); writeHashTable(stream, indent, "VALIDATION", &(web->validation)); writeBlockEnd(stream, indent, "WEB"); writeLineFeed(stream); } char* msWriteWebToString(webObj *web) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeWeb(stdout, -1, web); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } int loadWeb(webObj *web, mapObj *map) { web->map = (mapObj *)map; for(;;) { switch(msyylex()) { case(BROWSEFORMAT): /* change to use validation in 6.0 */ free(web->browseformat); web->browseformat = NULL; /* there is a default */ if(getString(&web->browseformat) == MS_FAILURE) return(-1); break; case(EMPTY): if(getString(&web->empty) == MS_FAILURE) return(-1); break; case(WEB): break; /* for string loads */ case(EOF): msSetError(MS_EOFERR, NULL, "loadWeb()"); return(-1); case(END): return(0); break; case(ERROR): if(getString(&web->error) == MS_FAILURE) return(-1); break; case(EXTENT): if(getDouble(&(web->extent.minx)) == -1) return(-1); if(getDouble(&(web->extent.miny)) == -1) return(-1); if(getDouble(&(web->extent.maxx)) == -1) return(-1); if(getDouble(&(web->extent.maxy)) == -1) return(-1); if (!MS_VALID_EXTENT(web->extent)) { msSetError(MS_MISCERR, "Given web extent is invalid. Check that it is in the form: minx, miny, maxx, maxy", "loadWeb()"); return(-1); } break; case(FOOTER): if(getString(&web->footer) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(web->footer, msLookupHashTable(&(web->validation), "footer"), map->templatepattern, NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based FOOTER configuration failed pattern validation." , "loadWeb()"); msFree(web->footer); web->footer=NULL; return(-1); } } break; case(HEADER): if(getString(&web->header) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(web->header, msLookupHashTable(&(web->validation), "header"), map->templatepattern, NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based HEADER configuration failed pattern validation." , "loadWeb()"); msFree(web->header); web->header=NULL; return(-1); } } break; case(IMAGEPATH): if(getString(&web->imagepath) == MS_FAILURE) return(-1); break; case(TEMPPATH): if(getString(&web->temppath) == MS_FAILURE) return(-1); break; case(IMAGEURL): if(getString(&web->imageurl) == MS_FAILURE) return(-1); break; case(LEGENDFORMAT): /* change to use validation in 6.0 */ free(web->legendformat); web->legendformat = NULL; /* there is a default */ if(getString(&web->legendformat) == MS_FAILURE) return(-1); break; case(LOG): if(getString(&web->log) == MS_FAILURE) return(-1); break; case(MAXSCALE): case(MAXSCALEDENOM): if(getDouble(&web->maxscaledenom) == -1) return(-1); break; case(MAXTEMPLATE): if(getString(&web->maxtemplate) == MS_FAILURE) return(-1); break; case(METADATA): if(loadHashTable(&(web->metadata)) != MS_SUCCESS) return(-1); break; case(MINSCALE): case(MINSCALEDENOM): if(getDouble(&web->minscaledenom) == -1) return(-1); break; case(MINTEMPLATE): if(getString(&web->mintemplate) == MS_FAILURE) return(-1); break; case(QUERYFORMAT): /* change to use validation in 6.0 */ free(web->queryformat); web->queryformat = NULL; /* there is a default */ if(getString(&web->queryformat) == MS_FAILURE) return(-1); break; case(TEMPLATE): if(getString(&web->template) == MS_FAILURE) return(-1); /* getString() cleans up previously allocated string */ if(msyysource == MS_URL_TOKENS) { if(msValidateParameter(web->template, msLookupHashTable(&(web->validation), "template"), map->templatepattern, NULL, NULL) != MS_SUCCESS) { msSetError(MS_MISCERR, "URL-based TEMPLATE configuration failed pattern validation." , "loadWeb()"); msFree(web->template); web->template=NULL; return(-1); } } break; case(VALIDATION): if(loadHashTable(&(web->validation)) != MS_SUCCESS) return(-1); break; default: if(strlen(msyystring_buffer) > 0) { msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadWeb()", msyystring_buffer, msyylineno); return(-1); } else { return(0); /* end of a string, not an error */ } } } } int msUpdateWebFromString(webObj *web, char *string, int url_string) { if(!web || !string) return MS_FAILURE; msAcquireLock( TLOCK_PARSER ); if(url_string) msyystate = MS_TOKENIZE_URL_STRING; else msyystate = MS_TOKENIZE_STRING; msyystring = string; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 */ if(loadWeb(web, web->map) == -1) { msReleaseLock( TLOCK_PARSER ); return MS_FAILURE; /* parse error */; } msReleaseLock( TLOCK_PARSER ); msyylex_destroy(); return MS_SUCCESS; } /* ** Initialize, load and free a mapObj structure ** ** This really belongs in mapobject.c, but currently it also depends on ** lots of other init methods in this file. */ int initMap(mapObj *map) { int i=0; MS_REFCNT_INIT(map); map->debug = (int)msGetGlobalDebugLevel(); /* Set maxlayers = 0, layers[] and layerorder[] will be allocated as needed, * on the first call to msGrowMapLayers() */ map->numlayers = 0; map->maxlayers = 0; map->layers = NULL; map->layerorder = NULL; /* used to modify the order in which the layers are drawn */ map->status = MS_ON; map->name = msStrdup("MS"); map->extent.minx = map->extent.miny = map->extent.maxx = map->extent.maxy = -1.0; map->scaledenom = -1.0; map->resolution = MS_DEFAULT_RESOLUTION; /* pixels per inch */ map->defresolution = MS_DEFAULT_RESOLUTION; /* pixels per inch */ map->height = map->width = -1; map->maxsize = MS_MAXIMAGESIZE_DEFAULT; map->gt.need_geotransform = MS_FALSE; map->gt.rotation_angle = 0.0; map->units = MS_METERS; map->cellsize = 0; map->shapepath = NULL; map->mappath = NULL; MS_INIT_COLOR(map->imagecolor, 255,255,255,255); /* white */ map->numoutputformats = 0; map->outputformatlist = NULL; map->outputformat = NULL; /* map->configoptions = msCreateHashTable();; */ initHashTable(&(map->configoptions)); map->imagetype = NULL; map->palette.numcolors = 0; map->transparent = MS_NOOVERRIDE; map->interlace = MS_NOOVERRIDE; map->imagequality = MS_NOOVERRIDE; for(i=0; ilabelcache.slots[i].labels = NULL; /* cache is initialize at draw time */ map->labelcache.slots[i].cachesize = 0; map->labelcache.slots[i].numlabels = 0; map->labelcache.slots[i].markers = NULL; map->labelcache.slots[i].markercachesize = 0; map->labelcache.slots[i].nummarkers = 0; } map->fontset.filename = NULL; map->fontset.numfonts = 0; /* map->fontset.fonts = NULL; */ initHashTable(&(map->fontset.fonts)); msInitSymbolSet(&map->symbolset); map->symbolset.fontset = &(map->fontset); map->symbolset.map = map; initLegend(&map->legend); initScalebar(&map->scalebar); initWeb(&map->web); initReferenceMap(&map->reference); initQueryMap(&map->querymap); #ifdef USE_PROJ if(msInitProjection(&(map->projection)) == -1) return(-1); if(msInitProjection(&(map->latlon)) == -1) return(-1); /* initialize a default "geographic" projection */ map->latlon.numargs = 2; map->latlon.args[0] = msStrdup("proj=latlong"); map->latlon.args[1] = msStrdup("ellps=WGS84"); /* probably want a different ellipsoid */ if(msProcessProjection(&(map->latlon)) == -1) return(-1); #endif map->templatepattern = map->datapattern = NULL; /* Encryption key information - see mapcrypto.c */ map->encryption_key_loaded = MS_FALSE; msInitQuery(&(map->query)); #ifdef USE_V8_MAPSCRIPT map->v8context = NULL; #endif return(0); } /* ** Ensure there is at least one free entry in the layers and layerorder ** arrays of this mapObj. Grow the allocated layers/layerorder arrays if ** necessary and allocate a new layer for layers[numlayers] if there is ** not already one, setting its contents to all zero bytes (i.e. does not ** call initLayer() on it). ** ** This function is safe to use for the initial allocation of the layers[] ** and layerorder[] arrays as well (i.e. when maxlayers==0 and layers==NULL) ** ** Returns a reference to the new layerObj on success, NULL on error. */ layerObj *msGrowMapLayers( mapObj *map ) { /* Do we need to increase the size of layers/layerorder by * MS_LAYER_ALLOCSIZE? */ if (map->numlayers == map->maxlayers) { layerObj **newLayersPtr; int *newLayerorderPtr; int i, newsize; newsize = map->maxlayers + MS_LAYER_ALLOCSIZE; /* Alloc/realloc layers */ newLayersPtr = (layerObj**)realloc(map->layers, newsize*sizeof(layerObj*)); MS_CHECK_ALLOC(newLayersPtr, newsize*sizeof(layerObj*), NULL); map->layers = newLayersPtr; /* Alloc/realloc layerorder */ newLayerorderPtr = (int *)realloc(map->layerorder, newsize*sizeof(int)); MS_CHECK_ALLOC(newLayerorderPtr, newsize*sizeof(int), NULL); map->layerorder = newLayerorderPtr; map->maxlayers = newsize; for(i=map->numlayers; imaxlayers; i++) { map->layers[i] = NULL; map->layerorder[i] = 0; } } if (map->layers[map->numlayers]==NULL) { map->layers[map->numlayers]=(layerObj*)calloc(1,sizeof(layerObj)); MS_CHECK_ALLOC(map->layers[map->numlayers], sizeof(layerObj), NULL); } return map->layers[map->numlayers]; } int msFreeLabelCacheSlot(labelCacheSlotObj *cacheslot) { int i, j; /* free the labels */ if (cacheslot->labels) { for(i=0; inumlabels; i++) { for(j=0; jlabels[i].numtextsymbols; j++) { freeTextSymbol(cacheslot->labels[i].textsymbols[j]); free(cacheslot->labels[i].textsymbols[j]); } msFree(cacheslot->labels[i].textsymbols); #ifdef include_deprecated for(j=0; jlabels[i].numstyles; j++) freeStyle(&(cacheslot->labels[i].styles[j])); msFree(cacheslot->labels[i].styles); #endif if(cacheslot->labels[i].leaderline) { msFree(cacheslot->labels[i].leaderline->point); msFree(cacheslot->labels[i].leaderline); msFree(cacheslot->labels[i].leaderbbox); } } } msFree(cacheslot->labels); cacheslot->labels = NULL; cacheslot->cachesize = 0; cacheslot->numlabels = 0; msFree(cacheslot->markers); cacheslot->markers = NULL; cacheslot->markercachesize = 0; cacheslot->nummarkers = 0; return(MS_SUCCESS); } int msFreeLabelCache(labelCacheObj *cache) { int p; for(p=0; pslots[p])) != MS_SUCCESS) return MS_FAILURE; } cache->num_allocated_rendered_members = cache->num_rendered_members = 0; msFree(cache->rendered_text_symbols); return MS_SUCCESS; } int msInitLabelCacheSlot(labelCacheSlotObj *cacheslot) { if(cacheslot->labels || cacheslot->markers) msFreeLabelCacheSlot(cacheslot); cacheslot->labels = (labelCacheMemberObj *)malloc(sizeof(labelCacheMemberObj)*MS_LABELCACHEINITSIZE); MS_CHECK_ALLOC(cacheslot->labels, sizeof(labelCacheMemberObj)*MS_LABELCACHEINITSIZE, MS_FAILURE); cacheslot->cachesize = MS_LABELCACHEINITSIZE; cacheslot->numlabels = 0; cacheslot->markers = (markerCacheMemberObj *)malloc(sizeof(markerCacheMemberObj)*MS_LABELCACHEINITSIZE); MS_CHECK_ALLOC(cacheslot->markers, sizeof(markerCacheMemberObj)*MS_LABELCACHEINITSIZE, MS_FAILURE); cacheslot->markercachesize = MS_LABELCACHEINITSIZE; cacheslot->nummarkers = 0; return(MS_SUCCESS); } int msInitLabelCache(labelCacheObj *cache) { int p; for(p=0; pslots[p])) != MS_SUCCESS) return MS_FAILURE; } cache->gutter = 0; cache->num_allocated_rendered_members = cache->num_rendered_members = 0; cache->rendered_text_symbols = NULL; return MS_SUCCESS; } static void writeMap(FILE *stream, int indent, mapObj *map) { int i; colorObj c; writeBlockBegin(stream, indent, "MAP"); writeNumber(stream, indent, "ANGLE", 0, map->gt.rotation_angle); writeHashTableInline(stream, indent, "CONFIG", &(map->configoptions)); writeString(stream, indent, "DATAPATTERN", NULL, map->datapattern); /* depricated */ writeNumber(stream, indent, "DEBUG", 0, map->debug); writeNumber(stream, indent, "DEFRESOLUTION", 72.0, map->defresolution); writeExtent(stream, indent, "EXTENT", map->extent); writeString(stream, indent, "FONTSET", NULL, map->fontset.filename); MS_INIT_COLOR(c,255,255,255,255); writeColor(stream, indent, "IMAGECOLOR", &c, &(map->imagecolor)); writeString(stream, indent, "IMAGETYPE", NULL, map->imagetype); writeKeyword(stream, indent, "INTERLACE", map->interlace, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeNumber(stream, indent, "MAXSIZE", MS_MAXIMAGESIZE_DEFAULT, map->maxsize); writeString(stream, indent, "NAME", NULL, map->name); writeNumber(stream, indent, "RESOLUTION", 72.0, map->resolution); writeString(stream, indent, "SHAPEPATH", NULL, map->shapepath); writeDimension(stream, indent, "SIZE", map->width, map->height, NULL, NULL); writeKeyword(stream, indent, "STATUS", map->status, 2, MS_ON, "ON", MS_OFF, "OFF"); writeString(stream, indent, "SYMBOLSET", NULL, map->symbolset.filename); writeString(stream, indent, "TEMPLATEPATTERN", NULL, map->templatepattern); /* depricated */ writeKeyword(stream, indent, "TRANSPARENT", map->transparent, 2, MS_TRUE, "TRUE", MS_FALSE, "FALSE"); writeKeyword(stream, indent, "UNITS", map->units, 7, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD"); writeLineFeed(stream); writeOutputformat(stream, indent, map); /* write symbol with INLINE tag in mapfile */ for(i=0; isymbolset.numsymbols; i++) { if(map->symbolset.symbol[i]->inmapfile) writeSymbol(map->symbolset.symbol[i], stream); } writeProjection(stream, indent, &(map->projection)); writeLegend(stream, indent, &(map->legend)); writeQueryMap(stream, indent, &(map->querymap)); writeReferenceMap(stream, indent, &(map->reference)); writeScalebar(stream, indent, &(map->scalebar)); writeWeb(stream, indent, &(map->web)); for(i=0; inumlayers; i++) writeLayer(stream, indent, GET_LAYER(map, map->layerorder[i])); writeBlockEnd(stream, indent, "MAP"); } char* msWriteMapToString(mapObj *map) { msIOContext context; msIOBuffer buffer; context.label = NULL; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = &buffer; buffer.data = NULL; buffer.data_len = 0; buffer.data_offset = 0; msIO_installHandlers( NULL, &context, NULL ); writeMap(stdout, 0, map); msIO_bufferWrite( &buffer, "", 1 ); msIO_installHandlers( NULL, NULL, NULL ); return (char*)buffer.data; } int msSaveMap(mapObj *map, char *filename) { FILE *stream; char szPath[MS_MAXPATHLEN]; if(!map) { msSetError(MS_MISCERR, "Map is undefined.", "msSaveMap()"); return(-1); } if(!filename) { msSetError(MS_MISCERR, "Filename is undefined.", "msSaveMap()"); return(-1); } stream = fopen(msBuildPath(szPath, map->mappath, filename), "w"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msSaveMap()", filename); return(-1); } writeMap(stream, 0, map); fclose(stream); return(0); } static int loadMapInternal(mapObj *map) { int foundMapToken=MS_FALSE; int foundBomToken = MS_FALSE; int token; for(;;) { token = msyylex(); if(!foundBomToken && token == BOM) { foundBomToken = MS_TRUE; if(!foundMapToken) { continue; /*skip a leading bom*/ } } if(!foundMapToken && token != MAP) { msSetError(MS_IDENTERR, "First token must be MAP, this doesn't look like a mapfile.", "msLoadMap()"); return(MS_FAILURE); } switch(token) { case(CONFIG): { char *key=NULL, *value=NULL; if( getString(&key) == MS_FAILURE ) return MS_FAILURE; if( getString(&value) == MS_FAILURE ) { free(key); return MS_FAILURE; } if (msSetConfigOption( map, key, value ) == MS_FAILURE) { free(key); free(value); return MS_FAILURE; } free( key ); free( value ); } break; case(DATAPATTERN): if(getString(&map->datapattern) == MS_FAILURE) return MS_FAILURE; break; case(DEBUG): if((map->debug = getSymbol(3, MS_ON,MS_OFF, MS_NUMBER)) == -1) return MS_FAILURE; if(map->debug == MS_NUMBER) map->debug = (int) msyynumber; break; case(END): if(msyyin) { fclose(msyyin); msyyin = NULL; } /*** Make config options current ***/ msApplyMapConfigOptions( map ); /*** Compute rotated extent info if applicable ***/ msMapComputeGeotransform( map ); /*** OUTPUTFORMAT related setup ***/ if( msPostMapParseOutputFormatSetup( map ) == MS_FAILURE ) return MS_FAILURE; if(loadSymbolSet(&(map->symbolset), map) == -1) return MS_FAILURE; if (resolveSymbolNames(map) == MS_FAILURE) return MS_FAILURE; if(msLoadFontSet(&(map->fontset), map) == -1) return MS_FAILURE; return MS_SUCCESS; break; case(EOF): msSetError(MS_EOFERR, NULL, "msLoadMap()"); return MS_FAILURE; case(EXTENT): { if(getDouble(&(map->extent.minx)) == -1) return MS_FAILURE; if(getDouble(&(map->extent.miny)) == -1) return MS_FAILURE; if(getDouble(&(map->extent.maxx)) == -1) return MS_FAILURE; if(getDouble(&(map->extent.maxy)) == -1) return MS_FAILURE; if (!MS_VALID_EXTENT(map->extent)) { msSetError(MS_MISCERR, "Given map extent is invalid. Check that it " \ "is in the form: minx, miny, maxx, maxy", "loadMapInternal()"); return MS_FAILURE; } } break; case(ANGLE): { double rotation_angle; if(getDouble(&(rotation_angle)) == -1) return MS_FAILURE; msMapSetRotation( map, rotation_angle ); } break; case(TEMPLATEPATTERN): if(getString(&map->templatepattern) == MS_FAILURE) return MS_FAILURE; break; case(FONTSET): if(getString(&map->fontset.filename) == MS_FAILURE) return MS_FAILURE; break; case(IMAGECOLOR): if(loadColor(&(map->imagecolor), NULL) != MS_SUCCESS) return MS_FAILURE; break; case(IMAGEQUALITY): if(getInteger(&(map->imagequality)) == -1) return MS_FAILURE; break; case(IMAGETYPE): msFree(map->imagetype); map->imagetype = getToken(); break; case(INTERLACE): if((map->interlace = getSymbol(2, MS_ON,MS_OFF)) == -1) return MS_FAILURE; break; case(LATLON): msFreeProjection(&map->latlon); if(loadProjection(&map->latlon) == -1) return MS_FAILURE; break; case(LAYER): if(msGrowMapLayers(map) == NULL) return MS_FAILURE; if(initLayer((GET_LAYER(map, map->numlayers)), map) == -1) return MS_FAILURE; if(loadLayer((GET_LAYER(map, map->numlayers)), map) == -1) return MS_FAILURE; GET_LAYER(map, map->numlayers)->index = map->numlayers; /* save the index */ /* Update the layer order list with the layer's index. */ map->layerorder[map->numlayers] = map->numlayers; map->numlayers++; break; case(OUTPUTFORMAT): if(loadOutputFormat(map) == -1) return MS_FAILURE; break; case(LEGEND): if(loadLegend(&(map->legend), map) == -1) return MS_FAILURE; break; case(MAP): foundMapToken = MS_TRUE; break; case(MAXSIZE): if(getInteger(&(map->maxsize)) == -1) return MS_FAILURE; break; case(NAME): free(map->name); map->name = NULL; /* erase default */ if(getString(&map->name) == MS_FAILURE) return MS_FAILURE; break; case(PROJECTION): if(loadProjection(&map->projection) == -1) return MS_FAILURE; break; case(QUERYMAP): if(loadQueryMap(&(map->querymap)) == -1) return MS_FAILURE; break; case(REFERENCE): if(loadReferenceMap(&(map->reference), map) == -1) return MS_FAILURE; break; case(RESOLUTION): if(getDouble(&(map->resolution)) == -1) return MS_FAILURE; break; case(DEFRESOLUTION): if(getDouble(&(map->defresolution)) == -1) return MS_FAILURE; break; case(SCALE): case(SCALEDENOM): if(getDouble(&(map->scaledenom)) == -1) return MS_FAILURE; break; case(SCALEBAR): if(loadScalebar(&(map->scalebar)) == -1) return MS_FAILURE; break; case(SHAPEPATH): if(getString(&map->shapepath) == MS_FAILURE) return MS_FAILURE; break; case(SIZE): if(getInteger(&(map->width)) == -1) return MS_FAILURE; if(getInteger(&(map->height)) == -1) return MS_FAILURE; break; case(STATUS): if((map->status = getSymbol(2, MS_ON,MS_OFF)) == -1) return MS_FAILURE; break; case(SYMBOL): if(msGrowSymbolSet(&(map->symbolset)) == NULL) return MS_FAILURE; if((loadSymbol(map->symbolset.symbol[map->symbolset.numsymbols], map->mappath) == -1)) return MS_FAILURE; map->symbolset.symbol[map->symbolset.numsymbols]->inmapfile = MS_TRUE; map->symbolset.numsymbols++; break; case(SYMBOLSET): if(getString(&map->symbolset.filename) == MS_FAILURE) return MS_FAILURE; break; case(TRANSPARENT): if((map->transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) return MS_FAILURE; break; case(UNITS): if((map->units = getSymbol(7, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD)) == -1) return MS_FAILURE; break; case(WEB): if(loadWeb(&(map->web), map) == -1) return MS_FAILURE; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "msLoadMap()", msyystring_buffer, msyylineno); return MS_FAILURE; } } /* next token */ } /* ** Sets up string-based mapfile loading and calls loadMapInternal to do the work. */ mapObj *msLoadMapFromString(char *buffer, char *new_mappath) { mapObj *map; struct mstimeval starttime, endtime; char szPath[MS_MAXPATHLEN], szCWDPath[MS_MAXPATHLEN]; char *mappath=NULL; int debuglevel; debuglevel = (int)msGetGlobalDebugLevel(); if (debuglevel >= MS_DEBUGLEVEL_TUNING) { /* In debug mode, track time spent loading/parsing mapfile. */ msGettimeofday(&starttime, NULL); } if(!buffer) { msSetError(MS_MISCERR, "No buffer to load.", "msLoadMapFromString()"); return(NULL); } /* ** Allocate mapObj structure */ map = (mapObj *)calloc(sizeof(mapObj),1); MS_CHECK_ALLOC(map, sizeof(mapObj), NULL); if(initMap(map) == -1) { /* initialize this map */ msFree(map); return(NULL); } msAcquireLock( TLOCK_PARSER ); /* might need to move this lock a bit higher, yup (bug 2108) */ msyystate = MS_TOKENIZE_STRING; msyystring = buffer; msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 1; /* start at line 1 (do lines mean anything here?) */ /* If new_mappath is provided then use it, otherwise use the CWD */ if(NULL == getcwd(szCWDPath, MS_MAXPATHLEN)) { msSetError(MS_MISCERR, "getcwd() returned a too long path", "msLoadMapFromString()"); msFreeMap(map); msReleaseLock( TLOCK_PARSER ); } if (new_mappath) { mappath = msStrdup(new_mappath); map->mappath = msStrdup(msBuildPath(szPath, szCWDPath, mappath)); } else map->mappath = msStrdup(szCWDPath); msyybasepath = map->mappath; /* for INCLUDEs */ if(loadMapInternal(map) != MS_SUCCESS) { msFreeMap(map); msReleaseLock( TLOCK_PARSER ); if(mappath != NULL) free(mappath); return NULL; } if (mappath != NULL) free(mappath); msyylex_destroy(); msReleaseLock( TLOCK_PARSER ); if (debuglevel >= MS_DEBUGLEVEL_TUNING) { /* In debug mode, report time spent loading/parsing mapfile. */ msGettimeofday(&endtime, NULL); msDebug("msLoadMap(): %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } if (resolveSymbolNames(map) == MS_FAILURE) return NULL; return map; } /* ** Sets up file-based mapfile loading and calls loadMapInternal to do the work. */ mapObj *msLoadMap(char *filename, char *new_mappath) { mapObj *map; struct mstimeval starttime, endtime; char szPath[MS_MAXPATHLEN], szCWDPath[MS_MAXPATHLEN]; int debuglevel; debuglevel = (int)msGetGlobalDebugLevel(); if (debuglevel >= MS_DEBUGLEVEL_TUNING) { /* In debug mode, track time spent loading/parsing mapfile. */ msGettimeofday(&starttime, NULL); } if(!filename) { msSetError(MS_MISCERR, "Filename is undefined.", "msLoadMap()"); return(NULL); } if(getenv("MS_MAPFILE_PATTERN")) { /* user override */ if(msEvalRegex(getenv("MS_MAPFILE_PATTERN"), filename) != MS_TRUE) { msSetError(MS_REGEXERR, "MS_MAPFILE_PATTERN validation failed." , "msLoadMap()"); return(NULL); } } else { /* check the default */ if(msEvalRegex(MS_DEFAULT_MAPFILE_PATTERN, filename) != MS_TRUE) { msSetError(MS_REGEXERR, "MS_DEFAULT_MAPFILE_PATTERN validation failed." , "msLoadMap()"); return(NULL); } } /* ** Allocate mapObj structure */ map = (mapObj *)calloc(sizeof(mapObj),1); MS_CHECK_ALLOC(map, sizeof(mapObj), NULL); if(initMap(map) == -1) { /* initialize this map */ msFree(map); return(NULL); } msAcquireLock( TLOCK_PARSER ); /* Steve: might need to move this lock a bit higher; Umberto: done */ #ifdef USE_XMLMAPFILE /* If the mapfile is an xml mapfile, transform it */ if ((getenv("MS_XMLMAPFILE_XSLT")) && (msEvalRegex(MS_DEFAULT_XMLMAPFILE_PATTERN, filename) == MS_TRUE)) { msyyin = tmpfile(); if (msyyin == NULL) { msSetError(MS_IOERR, "tmpfile() failed to create temporary file", "msLoadMap()"); msReleaseLock( TLOCK_PARSER ); } if (msTransformXmlMapfile(getenv("MS_XMLMAPFILE_XSLT"), filename, msyyin) != MS_SUCCESS) { fclose(msyyin); return NULL; } fseek ( msyyin , 0 , SEEK_SET ); } else { #endif if((msyyin = fopen(filename,"r")) == NULL) { msSetError(MS_IOERR, "(%s)", "msLoadMap()", filename); msReleaseLock( TLOCK_PARSER ); return NULL; } #ifdef USE_XMLMAPFILE } #endif msyystate = MS_TOKENIZE_FILE; msyylex(); /* sets things up, but doesn't process any tokens */ msyyrestart(msyyin); /* start at line begining, line 1 */ msyylineno = 1; /* If new_mappath is provided then use it, otherwise use the location */ /* of the mapfile as the default path */ if(NULL == getcwd(szCWDPath, MS_MAXPATHLEN)) { msSetError(MS_MISCERR, "getcwd() returned a too long path", "msLoadMap()"); msFreeMap(map); msReleaseLock( TLOCK_PARSER ); } if (new_mappath) map->mappath = msStrdup(msBuildPath(szPath, szCWDPath, new_mappath)); else { char *path = msGetPath(filename); map->mappath = msStrdup(msBuildPath(szPath, szCWDPath, path)); free( path ); } msyybasepath = map->mappath; /* for INCLUDEs */ if(loadMapInternal(map) != MS_SUCCESS) { msFreeMap(map); msReleaseLock( TLOCK_PARSER ); if( msyyin ) { fclose(msyyin); msyyin = NULL; } return NULL; } msReleaseLock( TLOCK_PARSER ); if (debuglevel >= MS_DEBUGLEVEL_TUNING) { /* In debug mode, report time spent loading/parsing mapfile. */ msGettimeofday(&endtime, NULL); msDebug("msLoadMap(): %.3fs\n", (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } return map; } /* ** Loads mapfile snippets via a URL (only via the CGI so don't worry about thread locks) */ int msUpdateMapFromURL(mapObj *map, char *variable, char *string) { int i, j, k, s; errorObj *ms_error; /* make sure this configuration can be modified */ if(msLookupHashTable(&(map->web.validation), "immutable")) return(MS_SUCCESS); /* fail silently */ msyystate = MS_TOKENIZE_URL_VARIABLE; /* set lexer state and input to tokenize */ msyystring = variable; msyylineno = 1; ms_error = msGetErrorObj(); ms_error->code = MS_NOERR; /* init error code */ switch(msyylex()) { case(MAP): switch(msyylex()) { case(CONFIG): { char *key=NULL, *value=NULL; if((getString(&key) != MS_FAILURE) && (getString(&value) != MS_FAILURE)) { msSetConfigOption( map, key, value ); free( key ); key=NULL; free( value ); value=NULL; } } break; case(EXTENT): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getDouble(&(map->extent.minx)) == -1) break; if(getDouble(&(map->extent.miny)) == -1) break; if(getDouble(&(map->extent.maxx)) == -1) break; if(getDouble(&(map->extent.maxy)) == -1) break; if (!MS_VALID_EXTENT(map->extent)) { msSetError(MS_MISCERR, "Given map extent is invalid. Check that it is in the form: minx, miny, maxx, maxy", "msLoadMapParameterFromUrl()"); break; } msMapComputeGeotransform( map ); break; case(ANGLE): { double rotation_angle; msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getDouble(&(rotation_angle)) == -1) break; msMapSetRotation( map, rotation_angle ); } break; case(IMAGECOLOR): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(loadColor(&(map->imagecolor), NULL) != MS_SUCCESS) break; break; case(IMAGETYPE): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); /* TODO: should validate or does msPostMapParseOutputFormatSetup() do enough? */ msFree(map->imagetype); map->imagetype = getToken(); msPostMapParseOutputFormatSetup( map ); break; case(LAYER): if((s = getSymbol(2, MS_NUMBER, MS_STRING)) == -1) { return MS_FAILURE; } if(s == MS_STRING) i = msGetLayerIndex(map, msyystring_buffer); else i = (int) msyynumber; if(i>=map->numlayers || i<0) { msSetError(MS_MISCERR, "Layer to be modified not valid.", "msUpdateMapFromURL()"); return MS_FAILURE; } /* make sure this layer can be modified */ if(msLookupHashTable(&(GET_LAYER(map, i)->validation), "immutable")) return(MS_SUCCESS); /* fail silently */ if(msyylex() == CLASS) { if((s = getSymbol(2, MS_NUMBER, MS_STRING)) == -1) return MS_FAILURE; if(s == MS_STRING) j = msGetClassIndex(GET_LAYER(map, i), msyystring_buffer); else j = (int) msyynumber; if(j>=GET_LAYER(map, i)->numclasses || j<0) { msSetError(MS_MISCERR, "Class to be modified not valid.", "msUpdateMapFromURL()"); return MS_FAILURE; } /* make sure this class can be modified */ if(msLookupHashTable(&(GET_LAYER(map, i)->class[j]->validation), "immutable")) return(MS_SUCCESS); /* fail silently */ switch(msyylex()) { case STYLE: if(getInteger(&k) == -1) return MS_FAILURE; if(k>=GET_LAYER(map, i)->class[j]->numstyles || k<0) { msSetError(MS_MISCERR, "Style to be modified not valid.", "msUpdateMapFromURL()"); return MS_FAILURE; } if(msUpdateStyleFromString((GET_LAYER(map, i))->class[j]->styles[k], string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; break; case LABEL: if(getInteger(&k) == -1) return MS_FAILURE; if(k>=GET_LAYER(map, i)->class[j]->numlabels || k<0) { msSetError(MS_MISCERR, "Label to be modified not valid.", "msUpdateMapFromURL()"); return MS_FAILURE; } if(msUpdateLabelFromString((GET_LAYER(map, i))->class[j]->labels[k], string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; break; default: if(msUpdateClassFromString((GET_LAYER(map, i))->class[j], string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; } } else { if(msUpdateLayerFromString((GET_LAYER(map, i)), string, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; } /* make sure any symbol names for this layer have been resolved (bug #2700) */ for(j=0; jnumclasses; j++) { for(k=0; kclass[j]->numstyles; k++) { if(GET_LAYER(map, i)->class[j]->styles[k]->symbolname && GET_LAYER(map, i)->class[j]->styles[k]->symbol == 0) { if((GET_LAYER(map, i)->class[j]->styles[k]->symbol = msGetSymbolIndex(&(map->symbolset), GET_LAYER(map, i)->class[j]->styles[k]->symbolname, MS_TRUE)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class %d, style %d of layer %s.", "msUpdateMapFromURL()", GET_LAYER(map, i)->class[j]->styles[k]->symbolname, j, k, GET_LAYER(map, i)->name); return MS_FAILURE; } } if(!MS_IS_VALID_ARRAY_INDEX(GET_LAYER(map, i)->class[j]->styles[k]->symbol, map->symbolset.numsymbols)) { msSetError(MS_MISCERR, "Invalid symbol index in class %d, style %d of layer %s.", "msUpdateMapFromURL()", j, k, GET_LAYER(map, i)->name); return MS_FAILURE; } } } break; case(LEGEND): if(msyylex() == LABEL) { return msUpdateLabelFromString(&map->legend.label, string, MS_TRUE); } else { return msUpdateLegendFromString(&(map->legend), string, MS_TRUE); } case(PROJECTION): msLoadProjectionString(&(map->projection), string); break; case(QUERYMAP): return msUpdateQueryMapFromString(&(map->querymap), string, MS_TRUE); case(REFERENCE): return msUpdateReferenceMapFromString(&(map->reference), string, MS_TRUE); case(RESOLUTION): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getDouble(&(map->resolution)) == -1) break; break; case(DEFRESOLUTION): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getDouble(&(map->defresolution)) == -1) break; break; case(SCALEBAR): return msUpdateScalebarFromString(&(map->scalebar), string, MS_TRUE); case(SIZE): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if(getInteger(&(map->width)) == -1) break; if(getInteger(&(map->height)) == -1) break; if(map->width > map->maxsize || map->height > map->maxsize || map->width < 0 || map->height < 0) { msSetError(MS_WEBERR, "Image size out of range.", "msUpdateMapFromURL()"); break; } msMapComputeGeotransform( map ); break; case(TRANSPARENT): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if((map->transparent = getSymbol(2, MS_ON,MS_OFF)) == -1) break; msPostMapParseOutputFormatSetup( map ); break; case(UNITS): msyystate = MS_TOKENIZE_URL_STRING; msyystring = string; msyylex(); if((map->units = getSymbol(7, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD)) == -1) break; break; case(WEB): return msUpdateWebFromString(&(map->web), string, MS_TRUE); default: break; /* malformed string */ } break; default: break; } /* msyystate = 3; */ /* restore lexer state */ /* msyylex(); */ if(ms_error->code != MS_NOERR) return(MS_FAILURE); return(MS_SUCCESS); } static void hashTableSubstituteString(hashTableObj *hash, const char *from, const char *to) { const char *key, *val; char *new_val; key = msFirstKeyFromHashTable(hash); while(key != NULL) { val = msLookupHashTable(hash, key); if(strcasestr(val, from)) { new_val = msCaseReplaceSubstring(msStrdup(val), from, to); msInsertHashTable(hash, key, new_val); msFree(new_val); } key = msNextKeyFromHashTable(hash, key); } } static void classSubstituteString(classObj *class, const char *from, const char *to) { if(class->expression.string) class->expression.string = msCaseReplaceSubstring(class->expression.string, from, to); if(class->text.string) class->text.string = msCaseReplaceSubstring(class->text.string, from, to); if(class->title) class->title = msCaseReplaceSubstring(class->title, from, to); } static void layerSubstituteString(layerObj *layer, const char *from, const char *to) { int c; if(layer->data) layer->data = msCaseReplaceSubstring(layer->data, from, to); if(layer->tileindex) layer->tileindex = msCaseReplaceSubstring(layer->tileindex, from, to); if(layer->connection) layer->connection = msCaseReplaceSubstring(layer->connection, from, to); if(layer->filter.string) layer->filter.string = msCaseReplaceSubstring(layer->filter.string, from, to); /* The bindvalues are most useful when able to substitute values from the URL */ hashTableSubstituteString(&layer->bindvals, from, to); hashTableSubstituteString(&layer->metadata, from, to); msLayerSubstituteProcessing( layer, from, to ); for(c=0; cnumclasses;c++) { classSubstituteString(layer->class[c], from, to); } } static void mapSubstituteString(mapObj *map, const char *from, const char *to) { int l; for(l=0;lnumlayers; l++) { layerSubstituteString(GET_LAYER(map,l), from, to); } /* output formats (#3751) */ for(l=0; lnumoutputformats; l++) { int o; for(o=0; ooutputformatlist[l]->numformatoptions; o++) { map->outputformatlist[l]->formatoptions[o] = msCaseReplaceSubstring(map->outputformatlist[l]->formatoptions[o], from, to); } } hashTableSubstituteString(&map->web.metadata, from, to); } static void applyOutputFormatDefaultSubstitutions(outputFormatObj *format, const char *option, hashTableObj *table) { const char *filename; filename = msGetOutputFormatOption(format, option, NULL); if(filename && strlen(filename)>0) { char *tmpfilename = msStrdup(filename); const char *default_key = msFirstKeyFromHashTable(table); while(default_key) { if(!strncmp(default_key,"default_",8)) { char *new_filename = NULL; size_t buffer_size = (strlen(default_key)-5); char *tag = (char *)msSmallMalloc(buffer_size); snprintf(tag, buffer_size, "%%%s%%", &(default_key[8])); new_filename = msStrdup(tmpfilename); new_filename = msCaseReplaceSubstring(new_filename, tag, msLookupHashTable(table, default_key)); free(tag); msSetOutputFormatOption(format, option, new_filename); free(new_filename); } default_key = msNextKeyFromHashTable(table, default_key); } msFree(tmpfilename); } return; } static void applyClassDefaultSubstitutions(classObj *class, hashTableObj *table) { const char *default_key = msFirstKeyFromHashTable(table); while(default_key) { if(!strncmp(default_key,"default_",8)) { size_t buffer_size = (strlen(default_key)-5); char *tag = (char *)msSmallMalloc(buffer_size); snprintf(tag, buffer_size, "%%%s%%", &(default_key[8])); classSubstituteString(class, tag, msLookupHashTable(table, default_key)); free(tag); } default_key = msNextKeyFromHashTable(table, default_key); } return; } static void applyLayerDefaultSubstitutions(layerObj *layer, hashTableObj *table) { int i; const char *default_key = msFirstKeyFromHashTable(table); while(default_key) { if(!strncmp(default_key,"default_",8)) { size_t buffer_size = (strlen(default_key)-5); const char *to = msLookupHashTable(table, default_key); char *tag = (char *)msSmallMalloc(buffer_size); snprintf(tag, buffer_size, "%%%s%%", &(default_key[8])); for(i=0; inumclasses; i++) { classSubstituteString(layer->class[i], tag, to); } layerSubstituteString(layer, tag, to); free(tag); } default_key = msNextKeyFromHashTable(table, default_key); } return; } static void applyHashTableDefaultSubstitutions(hashTableObj *hashTab, hashTableObj *table) { const char *default_key = msFirstKeyFromHashTable(table); while (default_key) { if (!strncmp(default_key, "default_", 8)) { size_t buffer_size = (strlen(default_key) - 5); const char *to = msLookupHashTable(table, default_key); char *tag = (char *)msSmallMalloc(buffer_size); snprintf(tag, buffer_size, "%%%s%%", &(default_key[8])); hashTableSubstituteString(hashTab, tag, to); free(tag); } default_key = msNextKeyFromHashTable(table, default_key); } return; } /* ** Loop through layer metadata for keys that have a default_%key% pattern to replace ** remaining %key% entries by their default value. */ void msApplyDefaultSubstitutions(mapObj *map) { int i,j; /* output formats (#3751) */ for(i=0; inumoutputformats; i++) { applyOutputFormatDefaultSubstitutions(map->outputformatlist[i], "filename", &(map->web.validation)); applyOutputFormatDefaultSubstitutions(map->outputformatlist[i], "JSONP", &(map->web.validation)); } for(i=0; inumlayers; i++) { layerObj *layer = GET_LAYER(map, i); for(j=0; jnumclasses; j++) { /* class settings take precedence... */ classObj *class = GET_CLASS(map, i, j); applyClassDefaultSubstitutions(class, &(class->validation)); } applyLayerDefaultSubstitutions(layer, &(layer->validation)); /* ...then layer settings... */ applyLayerDefaultSubstitutions(layer, &(map->web.validation)); /* ...and finally web settings */ } applyHashTableDefaultSubstitutions(&map->web.metadata, &(map->web.validation)); } char *_get_param_value(const char *key, char **names, char **values, int npairs) { if(getenv(key)) { /* envirronment override */ return getenv(key); } while(npairs) { npairs--; if(strcasecmp(key, names[npairs]) == 0) { return values[npairs]; } } return NULL; } void msApplySubstitutions(mapObj *map, char **names, char **values, int npairs) { int l; const char *key, *value, *validation; char *tag; for(l=0; lnumlayers; l++) { int c; layerObj *lp = GET_LAYER(map,l); for(c=0; cnumclasses; c++) { classObj *cp = lp->class[c]; key = NULL; while( (key = msNextKeyFromHashTable(&cp->validation, key)) ) { value = _get_param_value(key,names,values,npairs); if(!value) continue; /*parameter was not in url*/ validation = msLookupHashTable(&cp->validation, key); if(msEvalRegex(validation, value)) { /* we've found a substitution and it validates correctly, now let's apply it */ tag = msSmallMalloc(strlen(key)+3); sprintf(tag,"%%%s%%",key); classSubstituteString(cp,tag,value); free(tag); } else { msSetError(MS_REGEXERR, "Parameter pattern validation failed." , "msApplySubstitutions()"); if(map->debug || lp->debug) { msDebug("layer (%s), class %d: failed to validate (%s=%s) for regex (%s)\n", lp->name, c, key, value, validation); } } } } key = NULL; while( (key = msNextKeyFromHashTable(&lp->validation, key)) ) { value = _get_param_value(key,names,values,npairs); if(!value) continue; /*parameter was not in url*/ validation = msLookupHashTable(&lp->validation, key); if(msEvalRegex(validation, value)) { /* we've found a substitution and it validates correctly, now let's apply it */ tag = msSmallMalloc(strlen(key)+3); sprintf(tag,"%%%s%%",key); layerSubstituteString(lp,tag,value); free(tag); } else { msSetError(MS_REGEXERR, "Parameter pattern validation failed." , "msApplySubstitutions()"); if(map->debug || lp->debug) { msDebug("layer (%s): failed to validate (%s=%s) for regex (%s)\n", lp->name, key, value, validation); } } } } key = NULL; while( (key = msNextKeyFromHashTable(&map->web.validation, key)) ) { value = _get_param_value(key,names,values,npairs); if(!value) continue; /*parameter was not in url*/ validation = msLookupHashTable(&map->web.validation, key); if(msEvalRegex(validation, value)) { /* we've found a substitution and it validates correctly, now let's apply it */ tag = msSmallMalloc(strlen(key)+3); sprintf(tag,"%%%s%%",key); mapSubstituteString(map,tag,value); free(tag); } else { msSetError(MS_REGEXERR, "Parameter pattern validation failed." , "msApplySubstitutions()"); if(map->debug) { msDebug("failed to validate (%s=%s) for regex (%s)\n", key, value, validation); } } } } /* ** Returns an array with one entry per mapfile token. Useful to manipulate ** mapfiles in MapScript. ** ** The returned array should be freed using msFreeCharArray(). */ static char **tokenizeMapInternal(char *filename, int *ret_numtokens) { char **tokens = NULL; int numtokens=0, numtokens_allocated=0; size_t buffer_size = 0; *ret_numtokens = 0; if(!filename) { msSetError(MS_MISCERR, "Filename is undefined.", "msTokenizeMap()"); return NULL; } /* ** Check map filename to make sure it's legal */ if(getenv("MS_MAPFILE_PATTERN")) { /* user override */ if(msEvalRegex(getenv("MS_MAPFILE_PATTERN"), filename) != MS_TRUE) { msSetError(MS_REGEXERR, "MS_MAPFILE_PATTERN validation failed." , "msLoadMap()"); return(NULL); } } else { /* check the default */ if(msEvalRegex(MS_DEFAULT_MAPFILE_PATTERN, filename) != MS_TRUE) { msSetError(MS_REGEXERR, "MS_DEFAULT_MAPFILE_PATTERN validation failed." , "msLoadMap()"); return(NULL); } } if((msyyin = fopen(filename,"r")) == NULL) { msSetError(MS_IOERR, "(%s)", "msTokenizeMap()", filename); return NULL; } msyystate = MS_TOKENIZE_FILE; /* restore lexer state to INITIAL, and do return comments */ msyylex(); msyyreturncomments = 1; /* want all tokens, including comments */ msyyrestart(msyyin); /* start at line begining, line 1 */ msyylineno = 1; numtokens = 0; numtokens_allocated = 256; tokens = (char **) malloc(numtokens_allocated*sizeof(char*)); if(tokens == NULL) { msSetError(MS_MEMERR, NULL, "msTokenizeMap()"); fclose(msyyin); return NULL; } for(;;) { if(numtokens_allocated <= numtokens) { numtokens_allocated *= 2; /* double size of the array every time we reach the limit */ tokens = (char **)realloc(tokens, numtokens_allocated*sizeof(char*)); if(tokens == NULL) { msSetError(MS_MEMERR, "Realloc() error.", "msTokenizeMap()"); fclose(msyyin); return NULL; } } switch(msyylex()) { case(EOF): /* This is the normal way out... cleanup and exit */ fclose(msyyin); *ret_numtokens = numtokens; return(tokens); break; case(MS_STRING): buffer_size = strlen(msyystring_buffer)+2+1; tokens[numtokens] = (char*) msSmallMalloc(buffer_size); snprintf(tokens[numtokens], buffer_size, "\"%s\"", msyystring_buffer); break; case(MS_EXPRESSION): buffer_size = strlen(msyystring_buffer)+2+1; tokens[numtokens] = (char*) msSmallMalloc(buffer_size); snprintf(tokens[numtokens], buffer_size, "(%s)", msyystring_buffer); break; case(MS_REGEX): buffer_size = strlen(msyystring_buffer)+2+1; tokens[numtokens] = (char*) msSmallMalloc(buffer_size); snprintf(tokens[numtokens], buffer_size, "/%s/", msyystring_buffer); break; default: tokens[numtokens] = msStrdup(msyystring_buffer); break; } if(tokens[numtokens] == NULL) { int i; msSetError(MS_MEMERR, NULL, "msTokenizeMap()"); fclose(msyyin); for(i=0; inumlayers; i++) { lp = (GET_LAYER(map, i)); /* If the vtable is null, then the layer is never accessed or used -> skip it */ if (lp->vtable) { lp->vtable->LayerCloseConnection(lp); } } } void initResultCache(resultCacheObj *resultcache) { if (resultcache) { resultcache->results = NULL; resultcache->numresults = 0; resultcache->cachesize = 0; resultcache->bounds.minx = resultcache->bounds.miny = resultcache->bounds.maxx = resultcache->bounds.maxy = -1; resultcache->previousBounds = resultcache->bounds; resultcache->usegetshape = MS_FALSE; } } void cleanupResultCache(resultCacheObj *resultcache) { if(resultcache) { if(resultcache->results) { int i; for( i = 0; i < resultcache->numresults; i++ ) { if( resultcache->results[i].shape ) { msFreeShape( resultcache->results[i].shape ); msFree( resultcache->results[i].shape ); } } free(resultcache->results); } resultcache->results = NULL; initResultCache(resultcache); } } static int resolveSymbolNames(mapObj* map) { int i, j; /* step through layers and classes to resolve symbol names */ for(i=0; inumlayers; i++) { for(j=0; jnumclasses; j++) { if(classResolveSymbolNames(GET_LAYER(map, i)->class[j]) != MS_SUCCESS) return MS_FAILURE; } } return MS_SUCCESS; } mapserver-7.4.3/mapfile.dtd000066400000000000000000000154611357574274700156770ustar00rootroot00000000000000 mapserver-7.4.3/mapfile.h000066400000000000000000000161411357574274700153470ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Keyword definitions for the mapfiles and symbolfiles. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPFILE_H #define MAPFILE_H enum MS_LEXER_STATES {MS_TOKENIZE_DEFAULT=0, MS_TOKENIZE_FILE, MS_TOKENIZE_STRING, MS_TOKENIZE_EXPRESSION, MS_TOKENIZE_URL_VARIABLE, MS_TOKENIZE_URL_STRING, MS_TOKENIZE_VALUE, MS_TOKENIZE_NAME}; enum MS_TOKEN_SOURCES {MS_FILE_TOKENS=0, MS_STRING_TOKENS, MS_URL_TOKENS}; /* ** Keyword definitions for the mapfiles and symbolfiles (used by lexer) */ #define ANGLE 1000 #define ANTIALIAS 1001 #define BACKGROUNDCOLOR 1002 #define BUFFER 1003 #define CLASS 1004 #define CLASSITEM 1005 #define COLOR 1006 #define DATA 1007 #define DD 1008 #define EMPTY 1010 #define END 1011 #define ERROR 1012 #define EXPRESSION 1013 #define EXTENT 1014 #define FEATURE 1015 #define FILLED 1016 #define FOOTER 1017 #define FONT 1018 #define FONTSET 1019 #define FROM 1020 #define GROUP 1021 #define HEADER 1022 #define IMAGE 1023 #define IMAGECOLOR 1024 #define IMAGEPATH 1025 #define IMAGEURL 1026 #define INDEX 1027 #define INTERLACE 1028 #define INTERVALS 1029 #define JOIN 1030 #define KEYSIZE 1031 #define KEYSPACING 1032 #define LABEL 1033 #define LABELCACHE 1035 #define LABELITEM 1036 #define LABELMAXSCALE 1037 #define LABELMINSCALE 1038 #define LAYER 1040 #define LEGEND 1041 #define LOG 1043 #define MAP 1044 #define MAXFEATURES 1047 #define MAXSCALE 1048 #define MAXSIZE 1049 #define MAXTEMPLATE 1050 #define MINDISTANCE 1051 #define MINFEATURESIZE 1053 #define MINSCALE 1054 #define MINSIZE 1055 #define MINTEMPLATE 1056 #define NAME 1057 #define NFTEMPLATE 1058 #define OFFSET 1060 #define OFFSITE 1061 #define OUTLINECOLOR 1062 #define PARTIALS 1063 #define POINTS 1064 #define POSITION 1065 #define POSTLABELCACHE 1098 #define PROJECTION 1066 #define QUERY 1067 #define QUERYITEM 1068 #define QUERYMAP 1069 #define REFERENCE 1070 #define SCALE 1071 #define SCALEBAR 1072 #define SHADOWCOLOR 1074 #define SHADOWSIZE 1075 #define SHAPEPATH 1076 #define SIZE 1077 #define STATUS 1078 #define STYLE 1080 #define SYMBOL 1081 #define SYMBOLSCALE 1082 #define TABLE 1083 #define TEMPLATE 1084 #define TEXT 1085 #define TEXTITEM 1086 #define TILEINDEX 1088 #define TILEITEM 1089 #define TOLERANCE 1090 #define TO 1091 #define TRANSPARENT 1092 #define TRANSFORM 1093 #define TYPE 1094 #define UNITS 1095 #define WEB 1096 #define WRAP 1097 #define FORCE 1098 #define TOLERANCEUNITS 1099 #define CHARACTER 1100 #define CONNECTION 1101 #define CONNECTIONTYPE 1102 #define SYMBOLSET 1105 #define OVERLAYBACKGROUNDCOLOR 1106 #define OVERLAYCOLOR 1107 #define OVERLAYMAXSIZE 1108 #define OVERLAYMINSIZE 1109 #define OVERLAYOUTLINECOLOR 1110 #define OVERLAYSIZE 1111 #define OVERLAYSYMBOL 1112 #define IMAGETYPE 1113 #define IMAGEQUALITY 1114 #define GAP 1115 #define FILTER 1116 #define FILTERITEM 1117 #define REQUIRES 1118 #define LABELREQUIRES 1119 #define METADATA 1120 #define LATLON 1121 #define RESOLUTION 1122 #define SIZEUNITS 1123 #define STYLEITEM 1124 #define DUMP 1125 #define TITLE 1126 #define LINECAP 1127 #define LINEJOIN 1128 #define LINEJOINMAXSIZE 1129 #define TRANSPARENCY 1130 #define MARKER 1131 #define MARKERSIZE 1132 #define MINBOXSIZE 1133 #define MAXBOXSIZE 1134 #define OUTPUTFORMAT 1135 #define MIMETYPE 1136 #define DRIVER 1137 #define IMAGEMODE 1138 #define FORMATOPTION 1139 #define GRATICULE 1140 #define GRID 1141 #define MAXARCS 1142 #define MINARCS 1143 #define MAXINTERVAL 1144 #define MININTERVAL 1145 #define MAXSUBDIVIDE 1146 #define MINSUBDIVIDE 1147 #define LABELFORMAT 1148 #define DATAPATTERN 1150 #define FILEPATTERN 1151 #define TEMPLATEPATTERN 1152 #define PROCESSING 1153 /* The DEBUG macro is also used to request debugging output. Redefine for keyword purposes. */ #ifdef DEBUG #undef DEBUG #endif #define DEBUG 1154 #define EXTENSION 1155 #define KEYIMAGE 1156 #define QUERYFORMAT 1157 #define CONFIG 1158 #define BANDSITEM 1159 #define ENCODING 1162 #define WIDTH 1163 #define MINWIDTH 1164 #define MAXWIDTH 1165 #define OUTLINEWIDTH 1166 /* Color Range support (was Gradient Support)*/ #define COLORRANGE 1170 #define DATARANGE 1172 #define RANGEITEM 1173 /* WKT support (bug 1466) */ #define WKT 1180 #define LEGENDFORMAT 1190 /* bug 1518 */ #define BROWSEFORMAT 1191 #define RELATIVETO 1192 #define OPACITY 1193 #define PRIORITY 1194 #define PATTERN 1195 #define MAXSCALEDENOM 1196 #define MINSCALEDENOM 1197 #define LABELMAXSCALEDENOM 1198 #define LABELMINSCALEDENOM 1199 #define SYMBOLSCALEDENOM 1200 #define SCALEDENOM 1201 #define CLASSGROUP 1202 #define ALIGN 1203 /* bug 2468 */ #define MAXGEOWIDTH 1204 #define MINGEOWIDTH 1205 #define ITEMS 1206 /* rfc40 label wrapping */ #define MAXLENGTH 1210 #define MINLENGTH 1211 /* rfc44 URL configuration support */ #define VALIDATION 1212 /* rfc48 geometry transforms */ #define GEOMTRANSFORM 1220 /* rfc55 output resolution */ #define DEFRESOLUTION 1221 /* label repeat enhancement */ #define REPEATDISTANCE 1222 /* rfc60 label collision detection */ #define MAXOVERLAPANGLE 1223 /* rfc66 temporary path */ #define TEMPPATH 1224 /* rfc68 union connection type */ #define UNION 1225 /* rfc69 cluster */ #define CLUSTER 1226 #define MAXDISTANCE 1227 #define REGION 1228 #define INITIALGAP 1229 #define ANCHORPOINT 1230 #define MASK 1250 #define POLAROFFSET 1251 /* rfc78 leader-lines labels */ #define LEADER 1260 #define GRIDSTEP 1261 /* rfc 86 scale-dependant token substitutions */ #define SCALETOKEN 1270 #define VALUES 1271 #define TILESRS 1272 /* rfc 93 support for utfgrid */ #define UTFDATA 1280 #define UTFITEM 1281 /* rfc 113 layer compositing */ #define COMPOSITE 1290 #define COMPOP 1291 #define COMPFILTER 1292 #define BOM 1300 /* rfc59 bindvals objects */ #define BINDVALS 2000 #endif /* MAPFILE_H */ mapserver-7.4.3/mapgdal.c000066400000000000000000000564611357574274700153430ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of support for output using GDAL. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "mapthread.h" #include #if defined(USE_GDAL) || defined(USE_OGR) #include "cpl_conv.h" #include "cpl_string.h" #include "ogr_srs_api.h" #endif #ifdef USE_GDAL #include "gdal.h" static int bGDALInitialized = 0; /************************************************************************/ /* msGDALInitialize() */ /************************************************************************/ void msGDALInitialize( void ) { if( !bGDALInitialized ) { msAcquireLock( TLOCK_GDAL ); GDALAllRegister(); CPLPushErrorHandler( CPLQuietErrorHandler ); msReleaseLock( TLOCK_GDAL ); bGDALInitialized = 1; } } /************************************************************************/ /* msGDALCleanup() */ /************************************************************************/ void msGDALCleanup( void ) { if( bGDALInitialized ) { int iRepeat = 5; msAcquireLock( TLOCK_GDAL ); #if GDAL_RELEASE_DATE > 20101207 { /* ** Cleanup any unreferenced but open datasets as will tend ** to exist due to deferred close requests. We are careful ** to only close one file at a time before refecting the ** list as closing some datasets may cause others to be ** closed (subdatasets in a VRT for instance). */ GDALDatasetH *pahDSList = NULL; int nDSCount = 0; int bDidSomething; do { int i; GDALGetOpenDatasets( &pahDSList, &nDSCount ); bDidSomething = FALSE; for( i = 0; i < nDSCount && !bDidSomething; i++ ) { if( GDALReferenceDataset( pahDSList[i] ) == 1 ) { GDALClose( pahDSList[i] ); bDidSomething = TRUE; } else GDALDereferenceDataset( pahDSList[i] ); } } while( bDidSomething ); } #endif while( iRepeat-- ) CPLPopErrorHandler(); msReleaseLock( TLOCK_GDAL ); bGDALInitialized = 0; } } /************************************************************************/ /* msCleanVSIDir() */ /* */ /* For the temporary /vsimem/msout directory we need to be sure */ /* things are clean before we start, and after we are done. */ /************************************************************************/ void msCleanVSIDir( const char *pszDir ) { char **papszFiles = CPLReadDir( pszDir ); int i, nFileCount = CSLCount( papszFiles ); for( i = 0; i < nFileCount; i++ ) { if( strcasecmp(papszFiles[i],".") == 0 || strcasecmp(papszFiles[i],"..") == 0 ) continue; VSIUnlink( CPLFormFilename(pszDir, papszFiles[i], NULL) ); } CSLDestroy( papszFiles ); } /************************************************************************/ /* msSaveImageGDAL() */ /************************************************************************/ int msSaveImageGDAL( mapObj *map, imageObj *image, const char *filenameIn ) { int bFileIsTemporary = MS_FALSE; GDALDatasetH hMemDS, hOutputDS; GDALDriverH hMemDriver, hOutputDriver; int nBands = 1; int iLine; GByte *pabyAlphaLine = NULL; char **papszOptions = NULL; outputFormatObj *format = image->format; rasterBufferObj rb; GDALDataType eDataType = GDT_Byte; int bUseXmp = MS_FALSE; const char *filename = NULL; char *filenameToFree = NULL; msGDALInitialize(); memset(&rb,0,sizeof(rasterBufferObj)); #ifdef USE_EXEMPI if( map != NULL ) { bUseXmp = msXmpPresent(map); } #endif /* -------------------------------------------------------------------- */ /* Identify the proposed output driver. */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_GDAL ); hOutputDriver = GDALGetDriverByName( format->driver+5 ); if( hOutputDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find %s driver.", "msSaveImageGDAL()", format->driver+5 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* We will need to write the output to a temporary file and */ /* then stream to stdout if no filename is passed. If the */ /* driver supports virtualio then we hold the temporary file in */ /* memory, otherwise we try to put it in a reasonable temporary */ /* file location. */ /* -------------------------------------------------------------------- */ if( filenameIn == NULL ) { const char *pszExtension = format->extension; if( pszExtension == NULL ) pszExtension = "img.tmp"; if( bUseXmp == MS_FALSE && GDALGetMetadataItem( hOutputDriver, GDAL_DCAP_VIRTUALIO, NULL ) != NULL ) { msCleanVSIDir( "/vsimem/msout" ); filenameToFree = msTmpFile(map, NULL, "/vsimem/msout/", pszExtension ); } if( filenameToFree == NULL && map != NULL) filenameToFree = msTmpFile(map, map->mappath,NULL,pszExtension); else if( filenameToFree == NULL ) { filenameToFree = msTmpFile(map, NULL, NULL, pszExtension ); } filename = filenameToFree; bFileIsTemporary = MS_TRUE; } else { filename = filenameIn; } /* -------------------------------------------------------------------- */ /* Establish the characteristics of our memory, and final */ /* dataset. */ /* -------------------------------------------------------------------- */ if( format->imagemode == MS_IMAGEMODE_RGB ) { nBands = 3; assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer ); if(UNLIKELY(MS_FAILURE == format->vtable->getRasterBufferHandle(image,&rb))) { msReleaseLock( TLOCK_GDAL ); return MS_FAILURE; } } else if( format->imagemode == MS_IMAGEMODE_RGBA ) { pabyAlphaLine = (GByte *) calloc(image->width,1); if (pabyAlphaLine == NULL) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", image->width); return MS_FAILURE; } nBands = 4; assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer ); if(UNLIKELY(MS_FAILURE == format->vtable->getRasterBufferHandle(image,&rb))) { msReleaseLock( TLOCK_GDAL ); return MS_FAILURE; } } else if( format->imagemode == MS_IMAGEMODE_INT16 ) { nBands = format->bands; eDataType = GDT_Int16; } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { nBands = format->bands; eDataType = GDT_Float32; } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { nBands = format->bands; eDataType = GDT_Byte; } else { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Unknown format. This is a bug.", "msSaveImageGDAL()"); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Create a memory dataset which we can use as a source for a */ /* CreateCopy(). */ /* -------------------------------------------------------------------- */ hMemDriver = GDALGetDriverByName( "MEM" ); if( hMemDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find MEM driver.", "msSaveImageGDAL()" ); return MS_FAILURE; } hMemDS = GDALCreate( hMemDriver, "msSaveImageGDAL_temp", image->width, image->height, nBands, eDataType, NULL ); if( hMemDS == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to create MEM dataset.", "msSaveImageGDAL()" ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Copy the gd image into the memory dataset. */ /* -------------------------------------------------------------------- */ for( iLine = 0; iLine < image->height; iLine++ ) { int iBand; for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 ); if( format->imagemode == MS_IMAGEMODE_INT16 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_16bit + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Int16, 2, 0 ); } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_float + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Float32, 4, 0 ); } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_byte + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Byte, 1, 0 ); } else { GByte *pabyData; unsigned char *pixptr = NULL; assert( rb.type == MS_BUFFER_BYTE_RGBA ); switch(iBand) { case 0: pixptr = rb.data.rgba.r; break; case 1: pixptr = rb.data.rgba.g; break; case 2: pixptr = rb.data.rgba.b; break; case 3: pixptr = rb.data.rgba.a; break; } assert(pixptr); if( pixptr == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Missing RGB or A buffer.\n", "msSaveImageGDAL()" ); return MS_FAILURE; } pabyData = (GByte *)(pixptr + iLine*rb.data.rgba.row_step); if( rb.data.rgba.a == NULL || iBand == 3 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, pabyData, image->width, 1, GDT_Byte, rb.data.rgba.pixel_step, 0 ); } else { /* We need to un-pre-multiple RGB by alpha. */ GByte *pabyUPM = (GByte*) malloc(image->width); GByte *pabyAlpha= (GByte *)(rb.data.rgba.a + iLine*rb.data.rgba.row_step); int i; for( i = 0; i < image->width; i++ ) { int alpha = pabyAlpha[i*rb.data.rgba.pixel_step]; if( alpha == 0 ) pabyUPM[i] = 0; else { int result = (pabyData[i*rb.data.rgba.pixel_step] * 255) / alpha; if( result > 255 ) result = 255; pabyUPM[i] = result; } } GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, pabyUPM, image->width, 1, GDT_Byte, 1, 0 ); free( pabyUPM ); } } } } if( pabyAlphaLine != NULL ) free( pabyAlphaLine ); /* -------------------------------------------------------------------- */ /* Attach the palette if appropriate. */ /* -------------------------------------------------------------------- */ if( format->imagemode == MS_IMAGEMODE_RGB ) { GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand ); } else if( format->imagemode == MS_IMAGEMODE_RGBA ) { GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 4 ), GCI_AlphaBand ); } /* -------------------------------------------------------------------- */ /* Assign the projection and coordinate system to the memory */ /* dataset. */ /* -------------------------------------------------------------------- */ if( map != NULL ) { char *pszWKT; GDALSetGeoTransform( hMemDS, map->gt.geotransform ); pszWKT = msProjectionObj2OGCWKT( &(map->projection) ); if( pszWKT != NULL ) { GDALSetProjection( hMemDS, pszWKT ); msFree( pszWKT ); } } /* -------------------------------------------------------------------- */ /* Possibly assign a nodata value. */ /* -------------------------------------------------------------------- */ if( msGetOutputFormatOption(format,"NULLVALUE",NULL) != NULL ) { int iBand; const char *nullvalue = msGetOutputFormatOption(format, "NULLVALUE",NULL); for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 ); GDALSetRasterNoDataValue( hBand, atof(nullvalue) ); } } /* -------------------------------------------------------------------- */ /* Try to save resolution in the output file. */ /* -------------------------------------------------------------------- */ if( image->resolution > 0 ) { char res[30]; sprintf( res, "%lf", image->resolution ); GDALSetMetadataItem( hMemDS, "TIFFTAG_XRESOLUTION", res, NULL ); GDALSetMetadataItem( hMemDS, "TIFFTAG_YRESOLUTION", res, NULL ); GDALSetMetadataItem( hMemDS, "TIFFTAG_RESOLUTIONUNIT", "2", NULL ); } /* -------------------------------------------------------------------- */ /* Create a disk image in the selected output format from the */ /* memory image. */ /* -------------------------------------------------------------------- */ papszOptions = (char**)calloc(sizeof(char *),(format->numformatoptions+1)); if (papszOptions == NULL) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", (unsigned int)(sizeof(char *)*(format->numformatoptions+1))); return MS_FAILURE; } memcpy( papszOptions, format->formatoptions, sizeof(char *) * format->numformatoptions ); hOutputDS = GDALCreateCopy( hOutputDriver, filename, hMemDS, FALSE, papszOptions, NULL, NULL ); free( papszOptions ); if( hOutputDS == NULL ) { GDALClose( hMemDS ); msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to create output %s file.\n%s", "msSaveImageGDAL()", format->driver+5, CPLGetLastErrorMsg() ); return MS_FAILURE; } /* closing the memory DS also frees all associated resources. */ GDALClose( hMemDS ); GDALClose( hOutputDS ); msReleaseLock( TLOCK_GDAL ); /* -------------------------------------------------------------------- */ /* Are we writing license info into the image? */ /* If so, add it to the temp file on disk now. */ /* -------------------------------------------------------------------- */ #ifdef USE_EXEMPI if ( bUseXmp == MS_TRUE ) { if( msXmpWrite(map, filename) == MS_FAILURE ) { /* Something bad happened. */ msSetError( MS_MISCERR, "XMP write to %s failed.\n", "msSaveImageGDAL()", filename); return MS_FAILURE; } } #endif /* -------------------------------------------------------------------- */ /* Is this supposed to be a temporary file? If so, stream to */ /* stdout and delete the file. */ /* -------------------------------------------------------------------- */ if( bFileIsTemporary ) { FILE *fp; unsigned char block[4000]; int bytes_read; if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; /* We aren't sure how far back GDAL exports the VSI*L API, so we only use it if we suspect we need it. But we do need it if holding temporary file in memory. */ fp = VSIFOpenL( filename, "rb" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open %s for streaming to stdout.", "msSaveImageGDAL()", filename ); return MS_FAILURE; } while( (bytes_read = VSIFReadL(block, 1, sizeof(block), fp)) > 0 ) msIO_fwrite( block, 1, bytes_read, stdout ); VSIFCloseL( fp ); VSIUnlink( filename ); msCleanVSIDir( "/vsimem/msout" ); msFree( filenameToFree ); } return MS_SUCCESS; } /************************************************************************/ /* msInitGDALOutputFormat() */ /************************************************************************/ int msInitDefaultGDALOutputFormat( outputFormatObj *format ) { GDALDriverH hDriver; msGDALInitialize(); /* -------------------------------------------------------------------- */ /* check that this driver exists. Note visiting drivers should */ /* be pretty threadsafe so don't bother acquiring the GDAL */ /* lock. */ /* -------------------------------------------------------------------- */ hDriver = GDALGetDriverByName( format->driver+5 ); if( hDriver == NULL ) { msSetError( MS_MISCERR, "No GDAL driver named `%s' available.", "msInitGDALOutputFormat()", format->driver+5 ); return MS_FAILURE; } if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL && GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL ) { msSetError( MS_MISCERR, "GDAL `%s' driver does not support output.", "msInitGDALOutputFormat()", format->driver+5 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Initialize the object. */ /* -------------------------------------------------------------------- */ format->imagemode = MS_IMAGEMODE_RGB; format->renderer = MS_RENDER_WITH_AGG; if( GDALGetMetadataItem( hDriver, GDAL_DMD_MIMETYPE, NULL ) != NULL ) format->mimetype = msStrdup(GDALGetMetadataItem(hDriver,GDAL_DMD_MIMETYPE,NULL)); if( GDALGetMetadataItem( hDriver, GDAL_DMD_EXTENSION, NULL ) != NULL ) format->extension = msStrdup(GDALGetMetadataItem(hDriver,GDAL_DMD_EXTENSION,NULL)); return MS_SUCCESS; } #else void msGDALInitialize( void ) {} void msGDALCleanup(void) {} #endif /* def USE_GDAL */ /************************************************************************/ /* msProjectionObj2OGCWKT() */ /* */ /* We stick to the C API for OGRSpatialReference object access */ /* to allow MapServer+GDAL to be built without C++ */ /* complications. */ /* */ /* Note that this function will return NULL on failure, and the */ /* returned string should be freed with msFree(). */ /************************************************************************/ char *msProjectionObj2OGCWKT( projectionObj *projection ) { #if !defined(USE_GDAL) && !defined(USE_OGR) msSetError(MS_OGRERR, "Not implemented since neither OGR nor GDAL is enabled.", "msProjectionObj2OGCWKT()"); return NULL; #else /* defined USE_GDAL or USE_OGR */ OGRSpatialReferenceH hSRS; char *pszWKT=NULL, *pszProj4, *pszInitEpsg=NULL; int nLength = 0, i; OGRErr eErr; if( projection->proj == NULL ) return NULL; hSRS = OSRNewSpatialReference( NULL ); /* -------------------------------------------------------------------- */ /* Look for an EPSG-like projection argument */ /* -------------------------------------------------------------------- */ if( projection->numargs == 1 && (pszInitEpsg = strcasestr(projection->args[0],"init=epsg:"))) { int nEpsgCode = atoi(pszInitEpsg + strlen("init=epsg:")); eErr = OSRImportFromEPSG(hSRS, nEpsgCode); } else { /* -------------------------------------------------------------------- */ /* Form arguments into a full Proj.4 definition string. */ /* -------------------------------------------------------------------- */ for( i = 0; i < projection->numargs; i++ ) nLength += strlen(projection->args[i]) + 2; pszProj4 = (char *) CPLMalloc(nLength+2); pszProj4[0] = '\0'; for( i = 0; i < projection->numargs; i++ ) { strcat( pszProj4, "+" ); strcat( pszProj4, projection->args[i] ); strcat( pszProj4, " " ); } /* -------------------------------------------------------------------- */ /* Ingest the string into OGRSpatialReference. */ /* -------------------------------------------------------------------- */ eErr = OSRImportFromProj4( hSRS, pszProj4 ); CPLFree( pszProj4 ); } /* -------------------------------------------------------------------- */ /* Export as a WKT string. */ /* -------------------------------------------------------------------- */ if( eErr == OGRERR_NONE ) eErr = OSRExportToWkt( hSRS, &pszWKT ); OSRDestroySpatialReference( hSRS ); if( pszWKT ) { char *pszWKT2 = msStrdup(pszWKT); CPLFree( pszWKT ); return pszWKT2; } else return NULL; #endif /* defined USE_GDAL or USE_OGR */ } mapserver-7.4.3/mapgeomtransform.c000066400000000000000000000254311357574274700173100ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: RFC48 implementation of geometry transformations for styling * Author: Thomas Bonfort , Camptocamp (thomas.bonfort at camptocamp.com) * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "mapthread.h" extern int yyparse(parseObj *p); void msStyleSetGeomTransform(styleObj *s, char *transform) { msFree(s->_geomtransform.string); if (!transform) { s->_geomtransform.type = MS_GEOMTRANSFORM_NONE; s->_geomtransform.string = NULL; return; } s->_geomtransform.string = msStrdup(transform); if(!strncasecmp("start",transform,5)) { s->_geomtransform.type = MS_GEOMTRANSFORM_START; } else if(!strncasecmp("end",transform,3)) { s->_geomtransform.type = MS_GEOMTRANSFORM_END; } else if(!strncasecmp("vertices",transform,8)) { s->_geomtransform.type = MS_GEOMTRANSFORM_VERTICES; } else if(!strncasecmp("bbox",transform,4)) { s->_geomtransform.type = MS_GEOMTRANSFORM_BBOX; } else if(!strncasecmp("labelpnt",transform,8)) { s->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOINT; } else if(!strncasecmp("labelpoly",transform,9)) { s->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOLY; } else if(!strncasecmp("labelcenter",transform,11)) { s->_geomtransform.type = MS_GEOMTRANSFORM_LABELCENTER; } else if(!strncasecmp("centroid",transform,8)) { s->_geomtransform.type = MS_GEOMTRANSFORM_CENTROID; } else { s->_geomtransform.type = MS_GEOMTRANSFORM_NONE; msSetError(MS_MISCERR,"unknown transform expression","msStyleSetGeomTransform()"); msFree(s->_geomtransform.string); s->_geomtransform.string = NULL; } } /* * return a copy of the geometry transform expression * returned char* must be freed by the caller */ char *msStyleGetGeomTransform(styleObj *s) { return msStrdup(s->_geomtransform.string); } double calcOrientation(pointObj *p1, pointObj *p2) { double theta; theta = atan2(p2->x - p1->x,p2->y - p1->y); return MS_RAD_TO_DEG*(theta-MS_PI2); } double calcMidAngle(pointObj *p1, pointObj *p2, pointObj *p3) { pointObj p1n; double dx12, dy12, dx23, dy23, l12, l23; /* We treat both segments as vector 1-2 and vector 2-3 and * compute their dx,dy and length */ dx12 = p2->x - p1->x; dy12 = p2->y - p1->y; l12 = sqrt(dx12*dx12 + dy12*dy12); dx23 = p3->x - p2->x; dy23 = p3->y - p2->y; l23 = sqrt(dx23*dx23 + dy23*dy23); /* Normalize length of vector 1-2 to same as length of vector 2-3 */ if (l12 > 0.0) { p1n.x = p2->x - dx12*(l23/l12); p1n.y = p2->y - dy12*(l23/l12); } else p1n = *p2; /* segment 1-2 is 0-length, use segment 2-3 for orientation */ /* Return the orientation defined by the sum of the normalized vectors */ return calcOrientation(&p1n, p3); } /* * RFC48 implementation: * - transform the original shapeobj * - use the styleObj to render the transformed shapeobj */ int msDrawTransformedShape(mapObj *map, imageObj *image, shapeObj *shape, styleObj *style, double scalefactor) { int type = style->_geomtransform.type; int i,j,status = MS_SUCCESS; switch(type) { case MS_GEOMTRANSFORM_END: /*render point on last vertex only*/ for(j=0; jnumlines; j++) { lineObj *line = &(shape->line[j]); pointObj *p = &(line->point[line->numpoints-1]); if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE && line->numpoints>1) { style->angle = calcOrientation(&(line->point[line->numpoints-2]),p); } status = msDrawMarkerSymbol(map,image,p,style,scalefactor); } break; case MS_GEOMTRANSFORM_START: /*render point on first vertex only*/ for(j=0; jnumlines; j++) { lineObj *line = &(shape->line[j]); pointObj *p = &(line->point[0]); /*skip if outside image*/ if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE && line->numpoints>1) { style->angle = calcOrientation(p,&(line->point[1])); } status = msDrawMarkerSymbol(map,image,p,style,scalefactor); } break; case MS_GEOMTRANSFORM_VERTICES: for(j=0; jnumlines; j++) { lineObj *line = &(shape->line[j]); for(i=1; inumpoints-1; i++) { pointObj *p = &(line->point[i]); /*skip points outside image*/ if(p->x<0||p->x>image->width||p->y<0||p->y>image->height) continue; if(style->autoangle==MS_TRUE) { style->angle = calcMidAngle(&(line->point[i-1]),&(line->point[i]),&(line->point[i+1])); } status = msDrawMarkerSymbol(map,image,p,style,scalefactor); } } break; case MS_GEOMTRANSFORM_BBOX: { shapeObj bbox; lineObj bbox_line; pointObj bbox_points[5]; int padding = MS_MAX(style->width,style->size)+3; /* so clipped shape does not extent into image */ /*create a shapeObj representing the bounding box (clipped by the image size)*/ bbox.numlines = 1; bbox.line = &bbox_line; bbox.line->numpoints = 5; bbox.line->point = bbox_points; msComputeBounds(shape); bbox_points[0].x=bbox_points[4].x=bbox_points[1].x = (shape->bounds.minx < -padding) ? -padding : shape->bounds.minx; bbox_points[2].x=bbox_points[3].x = (shape->bounds.maxx > image->width+padding) ? image->width+padding : shape->bounds.maxx; bbox_points[0].y=bbox_points[4].y=bbox_points[3].y = (shape->bounds.miny < -padding) ? -padding : shape->bounds.miny; bbox_points[1].y=bbox_points[2].y = (shape->bounds.maxy > image->height+padding) ? image->height+padding : shape->bounds.maxy; status = msDrawShadeSymbol(map, image, &bbox, style, scalefactor); } break; case MS_GEOMTRANSFORM_CENTROID: { double unused; /*used by centroid function*/ pointObj centroid; if(MS_SUCCESS == msGetPolygonCentroid(shape,¢roid,&unused,&unused)) { status = msDrawMarkerSymbol(map,image,¢roid,style,scalefactor); } } break; case MS_GEOMTRANSFORM_EXPRESSION: { int status; shapeObj *tmpshp; parseObj p; p.shape = shape; /* set a few parser globals (hence the lock) */ p.expr = &(style->_geomtransform); if(p.expr->tokens == NULL) { /* this could happen if drawing originates from legend code (#5193) */ status = msTokenizeExpression(p.expr, NULL, NULL); if(status != MS_SUCCESS) { msSetError(MS_MISCERR, "Unable to tokenize expression.", "msDrawTransformedShape()"); return MS_FAILURE; } } p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_SHAPE; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process shape expression: %s", "msDrawTransformedShape", style->_geomtransform.string); return MS_FAILURE; } tmpshp = p.result.shpval; switch (tmpshp->type) { case MS_SHAPE_POINT: case MS_SHAPE_POLYGON: status = msDrawShadeSymbol(map, image, tmpshp, style, scalefactor); break; case MS_SHAPE_LINE: status = msDrawLineSymbol(map, image, tmpshp, style, scalefactor); break; } msFreeShape(tmpshp); msFree(tmpshp); } break; case MS_GEOMTRANSFORM_LABELPOINT: case MS_GEOMTRANSFORM_LABELPOLY: break; default: msSetError(MS_MISCERR, "unknown geomtransform", "msDrawTransformedShape()"); return MS_FAILURE; } return status; } /* * RFC89 implementation: * - transform directly the shapeobj */ int msGeomTransformShape(mapObj *map, layerObj *layer, shapeObj *shape) { int i; expressionObj *e = &layer->_geomtransform; #ifdef USE_V8_MAPSCRIPT if (!map->v8context) { msV8CreateContext(map); if (!map->v8context) { msSetError(MS_V8ERR, "Unable to create v8 context.", "msGeomTransformShape()"); return MS_FAILURE; } } msV8ContextSetLayer(map, layer); #endif switch(e->type) { case MS_GEOMTRANSFORM_EXPRESSION: { int status; shapeObj *tmpshp; parseObj p; p.shape = shape; /* set a few parser globals (hence the lock) */ p.expr = e; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_SHAPE; p.dblval = map->cellsize * (msInchesPerUnit(map->units,0)/msInchesPerUnit(layer->units,0)); p.dblval2 = 0; /* data_cellsize is only set with contour layer */ if (layer->connectiontype == MS_CONTOUR) { const char *value = msLookupHashTable(&layer->metadata, "__data_cellsize__"); if (value) p.dblval2 = atof(value); } status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process shape expression: %s", "msGeomTransformShape()", e->string); return MS_FAILURE; } tmpshp = p.result.shpval; for (i= 0; i < shape->numlines; i++) free(shape->line[i].point); shape->numlines = 0; if (shape->line) free(shape->line); for(i=0; inumlines; i++) msAddLine(shape, &(tmpshp->line[i])); /* copy each line */ msFreeShape(tmpshp); msFree(tmpshp); } break; default: msSetError(MS_MISCERR, "unknown geomtransform", "msGeomTransformShape()"); return MS_FAILURE; } return MS_SUCCESS; } mapserver-7.4.3/mapgeomutil.cpp000066400000000000000000000076441357574274700166200ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Rendering utility functions * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2011 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "renderers/agg/include/agg_arc.h" #include "renderers/agg/include/agg_basics.h" shapeObj *msRasterizeArc(double x0, double y0, double radius, double startAngle, double endAngle, int isSlice) { static int allocated_size=100; shapeObj *shape = (shapeObj*)calloc(1,sizeof(shapeObj)); MS_CHECK_ALLOC(shape, sizeof(shapeObj), NULL); mapserver::arc arc ( x0, y0,radius,radius, startAngle*MS_DEG_TO_RAD, endAngle*MS_DEG_TO_RAD,true ); arc.approximation_scale ( 1 ); arc.rewind(1); msInitShape(shape); lineObj *line = (lineObj*)calloc(1,sizeof(lineObj)); if (!line) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msRasterizeArc()" , __FILE__, __LINE__, (unsigned int)sizeof(lineObj)); free(shape); return NULL; } shape->line = line; shape->numlines = 1; line->point = (pointObj*)calloc(allocated_size,sizeof(pointObj)); if (!line->point) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msRasterizeArc()" , __FILE__, __LINE__, (unsigned int)(allocated_size*sizeof(pointObj))); free(line); free(shape); return NULL; } line->numpoints = 0; double x,y; //first segment from center to first point of arc if(isSlice) { line->point[0].x = x0; line->point[0].y = y0; line->numpoints = 1; } while(arc.vertex(&x,&y) != mapserver::path_cmd_stop) { if(line->numpoints == allocated_size) { allocated_size *= 2; line->point = (pointObj*)realloc(line->point, allocated_size * sizeof(pointObj)); if (!line->point) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msRasterizeArc()" , __FILE__, __LINE__, (unsigned int)(allocated_size * sizeof(pointObj))); free(line); free(shape); return NULL; } } line->point[line->numpoints].x = x; line->point[line->numpoints].y = y; line->numpoints++; } //make sure the shape is closed if(line->point[line->numpoints-1].x != line->point[0].x || line->point[line->numpoints-1].y != line->point[0].y) { if(line->numpoints == allocated_size) { allocated_size *= 2; line->point = (pointObj*)msSmallRealloc(line->point, allocated_size * sizeof(pointObj)); } line->point[line->numpoints].x = line->point[0].x; line->point[line->numpoints].y = line->point[0].y; line->numpoints++; } return shape; } mapserver-7.4.3/mapgeos.c000066400000000000000000001156211357574274700153630ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapServer-GEOS integration. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #ifdef USE_GEOS // To avoid accidental use of non reentrant GEOS API. // (check only effective in GEOS >= 3.5) #define GEOS_USE_ONLY_R_API #include /* ** Error handling... */ static void msGEOSError(const char *format, ...) { va_list args; va_start (args, format); msSetError(MS_GEOSERR, format, "msGEOSError()", args); /* just pass along to MapServer error handling */ va_end(args); return; } static void msGEOSNotice(const char *fmt, ...) { return; /* do nothing with notices at this point */ } #ifndef USE_THREAD static GEOSContextHandle_t geos_handle; static inline GEOSContextHandle_t msGetGeosContextHandle() { return geos_handle; } #else #include "mapthread.h" typedef struct geos_thread_info { struct geos_thread_info *next; void* thread_id; GEOSContextHandle_t geos_handle; } geos_thread_info_t; static geos_thread_info_t *geos_list = NULL; static GEOSContextHandle_t msGetGeosContextHandle() { geos_thread_info_t *link; GEOSContextHandle_t ret_obj; void* thread_id; msAcquireLock( TLOCK_GEOS ); thread_id = msGetThreadId(); /* find link for this thread */ for( link = geos_list; link != NULL && link->thread_id != thread_id && link->next != NULL && link->next->thread_id != thread_id; link = link->next ) {} /* If the target thread link is already at the head of the list were ok */ if( geos_list != NULL && geos_list->thread_id == thread_id ) { } /* We don't have one ... initialize one. */ else if( link == NULL || link->next == NULL ) { geos_thread_info_t *new_link; new_link = (geos_thread_info_t *) malloc(sizeof(geos_thread_info_t)); new_link->next = geos_list; new_link->thread_id = thread_id; new_link->geos_handle = initGEOS_r(msGEOSNotice, msGEOSError); geos_list = new_link; } /* If the link is not already at the head of the list, promote it */ else if( link != NULL && link->next != NULL ) { geos_thread_info_t *target = link->next; link->next = link->next->next; target->next = geos_list; geos_list = target; } ret_obj = geos_list->geos_handle; msReleaseLock( TLOCK_GEOS ); return ret_obj; } #endif /* ** Setup/Cleanup wrappers */ void msGEOSSetup() { #ifndef USE_THREAD geos_handle = initGEOS_r(msGEOSNotice, msGEOSError); #endif } void msGEOSCleanup() { #ifndef USE_THREAD finishGEOS_r(geos_handle); #else geos_thread_info_t *link; msAcquireLock( TLOCK_GEOS ); for( link = geos_list; link != NULL;) { geos_thread_info_t *cur = link; link = link->next; finishGEOS_r(cur->geos_handle); free(cur); } geos_list = NULL; msReleaseLock( TLOCK_GEOS ); #endif } /* ** Translation functions */ static GEOSGeom msGEOSShape2Geometry_point(pointObj *point) { GEOSCoordSeq coords; GEOSGeom g; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!point) return NULL; coords = GEOSCoordSeq_create_r(handle,1, 2); /* todo handle z's */ if(!coords) return NULL; GEOSCoordSeq_setX_r(handle,coords, 0, point->x); GEOSCoordSeq_setY_r(handle,coords, 0, point->y); /* GEOSCoordSeq_setY(coords, 0, point->z); */ g = GEOSGeom_createPoint_r(handle,coords); /* g owns the coordinate in coords */ return g; } static GEOSGeom msGEOSShape2Geometry_multipoint(lineObj *multipoint) { int i; GEOSGeom g; GEOSGeom *points; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!multipoint) return NULL; points = malloc(multipoint->numpoints*sizeof(GEOSGeom)); if(!points) return NULL; for(i=0; inumpoints; i++) points[i] = msGEOSShape2Geometry_point(&(multipoint->point[i])); g = GEOSGeom_createCollection_r(handle,GEOS_MULTIPOINT, points, multipoint->numpoints); free(points); return g; } static GEOSGeom msGEOSShape2Geometry_line(lineObj *line) { int i; GEOSGeom g; GEOSCoordSeq coords; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!line) return NULL; coords = GEOSCoordSeq_create_r(handle,line->numpoints, 2); /* todo handle z's */ if(!coords) return NULL; for(i=0; inumpoints; i++) { GEOSCoordSeq_setX_r(handle,coords, i, line->point[i].x); GEOSCoordSeq_setY_r(handle,coords, i, line->point[i].y); /* GEOSCoordSeq_setZ(coords, i, line->point[i].z); */ } g = GEOSGeom_createLineString_r(handle,coords); /* g owns the coordinates in coords */ return g; } static GEOSGeom msGEOSShape2Geometry_multiline(shapeObj *multiline) { int i; GEOSGeom g; GEOSGeom *lines; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!multiline) return NULL; lines = malloc(multiline->numlines*sizeof(GEOSGeom)); if(!lines) return NULL; for(i=0; inumlines; i++) lines[i] = msGEOSShape2Geometry_line(&(multiline->line[i])); g = GEOSGeom_createCollection_r(handle,GEOS_MULTILINESTRING, lines, multiline->numlines); free(lines); return g; } static GEOSGeom msGEOSShape2Geometry_simplepolygon(shapeObj *shape, int r, int *outerList) { int i, j, k; GEOSCoordSeq coords; GEOSGeom g; GEOSGeom outerRing; GEOSGeom *innerRings=NULL; int numInnerRings=0, *innerList; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape || !outerList) return NULL; /* build the outer shell */ coords = GEOSCoordSeq_create_r(handle,shape->line[r].numpoints, 2); /* todo handle z's */ if(!coords) return NULL; for(i=0; iline[r].numpoints; i++) { GEOSCoordSeq_setX_r(handle,coords, i, shape->line[r].point[i].x); GEOSCoordSeq_setY_r(handle,coords, i, shape->line[r].point[i].y); /* GEOSCoordSeq_setZ(coords, i, shape->line[r].point[i].z); */ } outerRing = GEOSGeom_createLinearRing_r(handle,coords); /* outerRing owns the coordinates in coords */ /* build the holes */ innerList = msGetInnerList(shape, r, outerList); for(j=0; jnumlines; j++) if(innerList[j] == MS_TRUE) numInnerRings++; if(numInnerRings > 0) { k = 0; /* inner ring counter */ innerRings = msSmallMalloc(numInnerRings*sizeof(GEOSGeom)); for(j=0; jnumlines; j++) { if(innerList[j] == MS_FALSE) continue; coords = GEOSCoordSeq_create_r(handle,shape->line[j].numpoints, 2); /* todo handle z's */ if(!coords) { free(innerRings); free(innerList); return NULL; /* todo, this will leak memory (shell + allocated holes) */ } for(i=0; iline[j].numpoints; i++) { GEOSCoordSeq_setX_r(handle,coords, i, shape->line[j].point[i].x); GEOSCoordSeq_setY_r(handle,coords, i, shape->line[j].point[i].y); /* GEOSCoordSeq_setZ(coords, i, shape->line[j].point[i].z); */ } innerRings[k] = GEOSGeom_createLinearRing_r(handle,coords); /* innerRings[k] owns the coordinates in coords */ k++; } } g = GEOSGeom_createPolygon_r(handle,outerRing, innerRings, numInnerRings); free(innerList); /* clean up */ free(innerRings); /* clean up */ return g; } static GEOSGeom msGEOSShape2Geometry_polygon(shapeObj *shape) { int i, j; GEOSGeom *polygons; int *outerList, numOuterRings=0, lastOuterRing=0; GEOSGeom g; GEOSContextHandle_t handle = msGetGeosContextHandle(); outerList = msGetOuterList(shape); for(i=0; inumlines; i++) { if(outerList[i] == MS_TRUE) { numOuterRings++; lastOuterRing = i; /* save for the simple case */ } } if(numOuterRings == 1) { g = msGEOSShape2Geometry_simplepolygon(shape, lastOuterRing, outerList); } else { /* a true multipolygon */ polygons = msSmallMalloc(numOuterRings*sizeof(GEOSGeom)); j = 0; /* part counter */ for(i=0; inumlines; i++) { if(outerList[i] == MS_FALSE) continue; polygons[j] = msGEOSShape2Geometry_simplepolygon(shape, i, outerList); /* TODO: account for NULL return values */ j++; } g = GEOSGeom_createCollection_r(handle,GEOS_MULTIPOLYGON, polygons, numOuterRings); free(polygons); } free(outerList); return g; } GEOSGeom msGEOSShape2Geometry(shapeObj *shape) { if(!shape) return NULL; /* a NULL shape generates a NULL geometry */ switch(shape->type) { case MS_SHAPE_POINT: if(shape->numlines == 0 || shape->line[0].numpoints == 0) /* not enough info for a point */ return NULL; if(shape->line[0].numpoints == 1) /* simple point */ return msGEOSShape2Geometry_point(&(shape->line[0].point[0])); else /* multi-point */ return msGEOSShape2Geometry_multipoint(&(shape->line[0])); break; case MS_SHAPE_LINE: if(shape->numlines == 0 || shape->line[0].numpoints < 2) /* not enough info for a line */ return NULL; if(shape->numlines == 1) /* simple line */ return msGEOSShape2Geometry_line(&(shape->line[0])); else /* multi-line */ return msGEOSShape2Geometry_multiline(shape); break; case MS_SHAPE_POLYGON: if(shape->numlines == 0 || shape->line[0].numpoints < 4) /* not enough info for a polygon (first=last) */ return NULL; return msGEOSShape2Geometry_polygon(shape); /* simple and multipolygon cases are addressed */ break; default: break; } return NULL; /* should not get here */ } static shapeObj *msGEOSGeometry2Shape_point(GEOSGeom g) { GEOSCoordSeq coords; shapeObj *shape=NULL; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!g) return NULL; shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)); shape->line[0].numpoints = 1; shape->geometry = (GEOSGeom) g; coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(handle,g); GEOSCoordSeq_getX_r(handle,coords, 0, &(shape->line[0].point[0].x)); GEOSCoordSeq_getY_r(handle,coords, 0, &(shape->line[0].point[0].y)); /* GEOSCoordSeq_getZ(coords, 0, &(shape->line[0].point[0].z)); */ shape->bounds.minx = shape->bounds.maxx = shape->line[0].point[0].x; shape->bounds.miny = shape->bounds.maxy = shape->line[0].point[0].y; return shape; } static shapeObj *msGEOSGeometry2Shape_multipoint(GEOSGeom g) { int i; int numPoints; GEOSCoordSeq coords; GEOSGeom point; shapeObj *shape=NULL; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!g) return NULL; numPoints = GEOSGetNumGeometries_r(handle,g); /* each geometry has 1 point */ shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints); shape->line[0].numpoints = numPoints; shape->geometry = (GEOSGeom) g; for(i=0; iline[0].point[i].x)); GEOSCoordSeq_getY_r(handle,coords, 0, &(shape->line[0].point[i].y)); /* GEOSCoordSeq_getZ(coords, 0, &(shape->line[0].point[i].z)); */ } msComputeBounds(shape); return shape; } static shapeObj *msGEOSGeometry2Shape_line(GEOSGeom g) { shapeObj *shape=NULL; GEOSContextHandle_t handle = msGetGeosContextHandle(); int i; int numPoints; GEOSCoordSeq coords; if(!g) return NULL; numPoints = GEOSGetNumCoordinates_r(handle,g); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(handle,g); shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_LINE; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)*numPoints); shape->line[0].numpoints = numPoints; shape->geometry = (GEOSGeom) g; for(i=0; iline[0].point[i].x)); GEOSCoordSeq_getY_r(handle,coords, i, &(shape->line[0].point[i].y)); /* GEOSCoordSeq_getZ(coords, i, &(shape->line[0].point[i].z)); */ } msComputeBounds(shape); return shape; } static shapeObj *msGEOSGeometry2Shape_multiline(GEOSGeom g) { int i, j; int numPoints, numLines; GEOSCoordSeq coords; GEOSGeom lineString; shapeObj *shape=NULL; lineObj line; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!g) return NULL; numLines = GEOSGetNumGeometries_r(handle,g); shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_LINE; shape->geometry = (GEOSGeom) g; for(j=0; jtype = MS_SHAPE_POLYGON; shape->geometry = (GEOSGeom) g; /* exterior ring */ ring = (GEOSGeom) GEOSGetExteriorRing_r(handle,g); numPoints = GEOSGetNumCoordinates_r(handle,ring); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(handle,ring); line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints); line.numpoints = numPoints; for(i=0; itype = MS_SHAPE_POLYGON; shape->geometry = (GEOSGeom) g; for(k=0; ktype = MS_SHAPE_LINE; shape->geometry = (GEOSGeom) g; numGeoms = GEOSGetNumGeometries_r(handle,g); for(i = 0; i < numGeoms; i++) { /* for each geometry */ shapeObj* shape2 = msGEOSGeometry2Shape((GEOSGeom)GEOSGetGeometryN_r(handle,g, i)); if (shape2) { for (j = 0; j < shape2->numlines; j++) msAddLineDirectly(shape, &shape2->line[j]); shape2->numlines = 0; shape2->geometry = NULL; /* not owned */ msFreeShape(shape2); } } msComputeBounds(shape); return shape; } break; default: msSetError(MS_GEOSERR, "Unsupported GEOS geometry type (%d).", "msGEOSGeometry2Shape()", type); } return NULL; } #endif /* ** Maintenence functions exposed to MapServer/MapScript. */ void msGEOSFreeGeometry(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g=NULL; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape || !shape->geometry) return; g = (GEOSGeom) shape->geometry; GEOSGeom_destroy_r(handle,g); shape->geometry = NULL; #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSFreeGEOSGeom()"); return; #endif } /* ** WKT input and output functions */ shapeObj *msGEOSShapeFromWKT(const char *wkt) { #ifdef USE_GEOS GEOSGeom g; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!wkt) return NULL; g = GEOSGeomFromWKT_r(handle,wkt); if(!g) { msSetError(MS_GEOSERR, "Error reading WKT geometry \"%s\".", "msGEOSShapeFromWKT()", wkt); return NULL; } else { return msGEOSGeometry2Shape(g); } #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSShapeFromWKT()"); return NULL; #endif } /* Return should be freed with msGEOSFreeWKT */ char *msGEOSShapeToWKT(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; /* if we have a geometry, we should update it*/ msGEOSFreeGeometry(shape); shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g = (GEOSGeom) shape->geometry; if(!g) return NULL; return GEOSGeomToWKT_r(handle,g); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSShapeToWKT()"); return NULL; #endif } void msGEOSFreeWKT(char* pszGEOSWKT) { #ifdef USE_GEOS GEOSContextHandle_t handle = msGetGeosContextHandle(); #if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 2) GEOSFree_r(handle,pszGEOSWKT); #endif #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSFreeWKT()"); #endif } shapeObj *msGEOSOffsetCurve(shapeObj *p, double offset) { #if defined USE_GEOS && (GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 3)) GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!p) return NULL; if(!p->geometry) /* if no geometry for the shape then build one */ p->geometry = (GEOSGeom) msGEOSShape2Geometry(p); g1 = (GEOSGeom) p->geometry; if(!g1) return NULL; g2 = GEOSOffsetCurve_r(handle,g1, offset, 4, GEOSBUF_JOIN_MITRE, fabs(offset*1.5)); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS Offset Curve support is not available.", "msGEOSingleSidedBuffer()"); return NULL; #endif } /* ** Analytical functions exposed to MapServer/MapScript. */ shapeObj *msGEOSBuffer(shapeObj *shape, double width) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSBuffer_r(handle,g1, width, 30); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSBuffer()"); return NULL; #endif } shapeObj *msGEOSSimplify(shapeObj *shape, double tolerance) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSSimplify_r(handle,g1, tolerance); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS Simplify support is not available.", "msGEOSSimplify()"); return NULL; #endif } shapeObj *msGEOSTopologyPreservingSimplify(shapeObj *shape, double tolerance) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSTopologyPreserveSimplify_r(handle,g1, tolerance); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS Simplify support is not available.", "msGEOSTopologyPreservingSimplify()"); return NULL; #endif } shapeObj *msGEOSConvexHull(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSConvexHull_r(handle,g1); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSConvexHull()"); return NULL; #endif } shapeObj *msGEOSBoundary(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSBoundary_r(handle,g1); return msGEOSGeometry2Shape(g2); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSBoundary()"); return NULL; #endif } pointObj *msGEOSGetCentroid(shapeObj *shape) { #ifdef USE_GEOS GEOSGeom g1, g2; GEOSCoordSeq coords; pointObj *point; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return NULL; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g1 = (GEOSGeom) shape->geometry; if(!g1) return NULL; g2 = GEOSGetCentroid_r(handle,g1); point = (pointObj *) malloc(sizeof(pointObj)); coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq_r(handle,g2); GEOSCoordSeq_getX_r(handle,coords, 0, &(point->x)); GEOSCoordSeq_getY_r(handle,coords, 0, &(point->y)); /* GEOSCoordSeq_getZ(coords, 0, &(point->z)); */ GEOSCoordSeq_destroy_r(handle,coords); return point; #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSGetCentroid()"); return NULL; #endif } shapeObj *msGEOSUnion(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2, g3; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return NULL; if(!shape1->geometry) /* if no geometry for the shape then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return NULL; if(!shape2->geometry) /* if no geometry for the shape then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return NULL; g3 = GEOSUnion_r(handle,g1, g2); return msGEOSGeometry2Shape(g3); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSUnion()"); return NULL; #endif } shapeObj *msGEOSIntersection(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2, g3; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return NULL; if(!shape1->geometry) /* if no geometry for the shape then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return NULL; if(!shape2->geometry) /* if no geometry for the shape then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return NULL; g3 = GEOSIntersection_r(handle,g1, g2); return msGEOSGeometry2Shape(g3); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSIntersection()"); return NULL; #endif } shapeObj *msGEOSDifference(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2, g3; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return NULL; if(!shape1->geometry) /* if no geometry for the shape then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return NULL; if(!shape2->geometry) /* if no geometry for the shape then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return NULL; g3 = GEOSDifference_r(handle,g1, g2); return msGEOSGeometry2Shape(g3); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSDifference()"); return NULL; #endif } shapeObj *msGEOSSymDifference(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2, g3; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return NULL; if(!shape1->geometry) /* if no geometry for the shape then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return NULL; if(!shape2->geometry) /* if no geometry for the shape then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return NULL; g3 = GEOSSymDifference_r(handle,g1, g2); return msGEOSGeometry2Shape(g3); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSSymDifference()"); return NULL; #endif } /* ** Binary predicates exposed to MapServer/MapScript */ /* ** Does shape1 contain shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSContains(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSContains_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSContains()"); return -1; #endif } /* ** Does shape1 overlap shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSOverlaps(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSOverlaps_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSOverlaps()"); return -1; #endif } /* ** Is shape1 within shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSWithin(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSWithin_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSWithin()"); return -1; #endif } /* ** Does shape1 cross shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSCrosses(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = shape2->geometry; if(!g2) return -1; result = GEOSCrosses_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSCrosses()"); return -1; #endif } /* ** Does shape1 intersect shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSIntersects(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSIntersects_r(handle,g1, g2); return ((result==2) ? -1 : result); #else if(!shape1 || !shape2) return -1; switch(shape1->type) { /* todo: deal with point shapes */ case(MS_SHAPE_LINE): switch(shape2->type) { case(MS_SHAPE_LINE): return msIntersectPolylines(shape1, shape2); case(MS_SHAPE_POLYGON): return msIntersectPolylinePolygon(shape1, shape2); } break; case(MS_SHAPE_POLYGON): switch(shape2->type) { case(MS_SHAPE_LINE): return msIntersectPolylinePolygon(shape2, shape1); case(MS_SHAPE_POLYGON): return msIntersectPolygons(shape1, shape2); } break; } return -1; #endif } /* ** Does shape1 touch shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSTouches(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSTouches_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSTouches()"); return -1; #endif } /* ** Does shape1 equal shape2, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSEquals(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSEquals_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSEquals()"); return -1; #endif } /* ** Are shape1 and shape2 disjoint, returns MS_TRUE/MS_FALSE or -1 for an error. */ int msGEOSDisjoint(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSDisjoint_r(handle,g1, g2); return ((result==2) ? -1 : result); #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSDisjoint()"); return -1; #endif } /* ** Useful misc. functions that return -1 on failure. */ double msGEOSArea(shapeObj *shape) { #if defined(USE_GEOS) && defined(GEOS_CAPI_VERSION_MAJOR) && defined(GEOS_CAPI_VERSION_MINOR) && (GEOS_CAPI_VERSION_MAJOR > 1 || GEOS_CAPI_VERSION_MINOR >= 1) GEOSGeom g; double area; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return -1; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g = (GEOSGeom) shape->geometry; if(!g) return -1; result = GEOSArea_r(handle,g, &area); return ((result==0) ? -1 : area); #elif defined(USE_GEOS) msSetError(MS_GEOSERR, "GEOS support enabled, but old version lacks GEOSArea().", "msGEOSArea()"); return -1; #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSArea()"); return -1; #endif } double msGEOSLength(shapeObj *shape) { #if defined(USE_GEOS) && defined(GEOS_CAPI_VERSION_MAJOR) && defined(GEOS_CAPI_VERSION_MINOR) && (GEOS_CAPI_VERSION_MAJOR > 1 || GEOS_CAPI_VERSION_MINOR >= 1) GEOSGeom g; double length; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape) return -1; if(!shape->geometry) /* if no geometry for the shape then build one */ shape->geometry = (GEOSGeom) msGEOSShape2Geometry(shape); g = (GEOSGeom) shape->geometry; if(!g) return -1; result = GEOSLength_r(handle,g, &length); return ((result==0) ? -1 : length); #elif defined(USE_GEOS) msSetError(MS_GEOSERR, "GEOS support enabled, but old version lacks GEOSLength().", "msGEOSLength()"); return -1; #else msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSLength()"); return -1; #endif } double msGEOSDistance(shapeObj *shape1, shapeObj *shape2) { #ifdef USE_GEOS GEOSGeom g1, g2; double distance; int result; GEOSContextHandle_t handle = msGetGeosContextHandle(); if(!shape1 || !shape2) return -1; if(!shape1->geometry) /* if no geometry for shape1 then build one */ shape1->geometry = (GEOSGeom) msGEOSShape2Geometry(shape1); g1 = (GEOSGeom) shape1->geometry; if(!g1) return -1; if(!shape2->geometry) /* if no geometry for shape2 then build one */ shape2->geometry = (GEOSGeom) msGEOSShape2Geometry(shape2); g2 = (GEOSGeom) shape2->geometry; if(!g2) return -1; result = GEOSDistance_r(handle,g1, g2, &distance); return ((result==0) ? -1 : distance); #else return msDistanceShapeToShape(shape1, shape2); /* fall back on brute force method (for MapScript) */ #endif } mapserver-7.4.3/mapgml.c000066400000000000000000002417321357574274700152100ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: shapeObj to GML output via MapServer queries. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "maperror.h" #include "mapows.h" #include "mapgml.h" #include "maptime.h" /* Use only mapgml.c if WMS or WFS is available (with minor exceptions at end)*/ #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) static int msGMLGeometryLookup(gmlGeometryListObj *geometryList, const char *type); /* ** Functions that write the feature boundary geometry (i.e. a rectObj). */ /* GML 2.1.2 */ static int gmlWriteBounds_GML2(FILE *stream, rectObj *rect, const char *srsname, const char *tab, const char *pszTopPrefix) { char *srsname_encoded; if(!stream) return(MS_FAILURE); if(!rect) return(MS_FAILURE); if(!tab) return(MS_FAILURE); msIO_fprintf(stream, "%s<%s:boundedBy>\n", tab, pszTopPrefix); if(srsname) { srsname_encoded = msEncodeHTMLEntities(srsname); msIO_fprintf(stream, "%s\t\n", tab, srsname_encoded); msFree(srsname_encoded); } else msIO_fprintf(stream, "%s\t\n", tab); msIO_fprintf(stream, "%s\t\t", tab); msIO_fprintf(stream, "%.6f,%.6f %.6f,%.6f", rect->minx, rect->miny, rect->maxx, rect->maxy ); msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s\t\n", tab); msIO_fprintf(stream, "%s\n", tab, pszTopPrefix); return MS_SUCCESS; } /* GML 3.1 or GML 3.2 (MapServer limits GML encoding to the level 0 profile) */ static int gmlWriteBounds_GML3(FILE *stream, rectObj *rect, const char *srsname, const char *tab, const char *pszTopPrefix) { char *srsname_encoded; if(!stream) return(MS_FAILURE); if(!rect) return(MS_FAILURE); if(!tab) return(MS_FAILURE); msIO_fprintf(stream, "%s<%s:boundedBy>\n", tab, pszTopPrefix); if(srsname) { srsname_encoded = msEncodeHTMLEntities(srsname); msIO_fprintf(stream, "%s\t\n", tab, srsname_encoded); msFree(srsname_encoded); } else msIO_fprintf(stream, "%s\t\n", tab); msIO_fprintf(stream, "%s\t\t%.6f %.6f\n", tab, rect->minx, rect->miny); msIO_fprintf(stream, "%s\t\t%.6f %.6f\n", tab, rect->maxx, rect->maxy); msIO_fprintf(stream, "%s\t\n", tab); msIO_fprintf(stream, "%s\n", tab, pszTopPrefix); return MS_SUCCESS; } static void gmlStartGeometryContainer(FILE *stream, const char *name, const char *namespace, const char *tab) { const char *tag_name=OWS_GML_DEFAULT_GEOMETRY_NAME; if(name) tag_name = name; if(namespace) msIO_fprintf(stream, "%s<%s:%s>\n", tab, namespace, tag_name); else msIO_fprintf(stream, "%s<%s>\n", tab, tag_name); } static void gmlEndGeometryContainer(FILE *stream, const char *name, const char *namespace, const char *tab) { const char *tag_name=OWS_GML_DEFAULT_GEOMETRY_NAME; if(name) tag_name = name; if(namespace) msIO_fprintf(stream, "%s\n", tab, namespace, tag_name); else msIO_fprintf(stream, "%s\n", tab, tag_name); } /* GML 2.1.2 */ static int gmlWriteGeometry_GML2(FILE *stream, gmlGeometryListObj *geometryList, shapeObj *shape, const char *srsname, const char *namespace, const char *tab, int nSRSDimension) { int i, j, k; int *innerlist, *outerlist=NULL, numouters; char *srsname_encoded = NULL; int geometry_aggregate_index, geometry_simple_index; char *geometry_aggregate_name = NULL, *geometry_simple_name = NULL; if(!stream) return(MS_FAILURE); if(!shape) return(MS_FAILURE); if(!tab) return(MS_FAILURE); if(!geometryList) return(MS_FAILURE); if(shape->numlines <= 0) return(MS_SUCCESS); /* empty shape, nothing to output */ if(srsname) srsname_encoded = msEncodeHTMLEntities(srsname); /* feature geometry */ switch(shape->type) { case(MS_SHAPE_POINT): geometry_simple_index = msGMLGeometryLookup(geometryList, "point"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multipoint"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; if((geometry_simple_index != -1 && shape->line[0].numpoints == 1 && shape->numlines == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->line[0].numpoints == 1 && shape->numlines == 1)) { /* write a Point(s) */ for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* Point */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%s %f,%f,%f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%s %f,%f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "%s\n", tab); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } } } else if((geometry_aggregate_index != -1) || (geometryList->numgeometries == 0)) { /* write a MultiPoint */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiPoint */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%s %f,%f,%f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%s %f,%f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s\n", tab); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; case(MS_SHAPE_LINE): geometry_simple_index = msGMLGeometryLookup(geometryList, "line"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multiline"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; if((geometry_simple_index != -1 && shape->numlines == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->numlines == 1)) { /* write a LineStrings(s) */ for(i=0; inumlines; i++) { gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* LineString */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f,%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s\n", tab); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } } else if(geometry_aggregate_index != -1 || (geometryList->numgeometries == 0)) { /* write a MultiCurve */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiLineString */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); for(j=0; jnumlines; j++) { msIO_fprintf(stream, "%s \n", tab); /* no srsname at this point */ msIO_fprintf(stream, "%s \n", tab); /* no srsname at this point */ msIO_fprintf(stream, "%s ", tab); for(i=0; iline[j].numpoints; i++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f,%f,%f ", shape->line[j].point[i].x, shape->line[j].point[i].y, shape->line[j].point[i].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f,%f ", shape->line[j].point[i].x, shape->line[j].point[i].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } msIO_fprintf(stream, "%s\n", tab); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; case(MS_SHAPE_POLYGON): /* this gets nasty, since our shapes are so flexible */ geometry_simple_index = msGMLGeometryLookup(geometryList, "polygon"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multipolygon"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; /* get a list of outter rings for this polygon */ outerlist = msGetOuterList(shape); numouters = 0; for(i=0; inumlines; i++) if(outerlist[i] == MS_TRUE) numouters++; if((geometry_simple_index != -1 && numouters == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->numlines == 1)) { /* write a Polygon(s) */ for(i=0; inumlines; i++) { if(outerlist[i] == MS_FALSE) break; /* skip non-outer rings, each outer ring is a new polygon */ /* get a list of inner rings for this polygon */ innerlist = msGetInnerList(shape, i, outerlist); gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* Polygon */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f,%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(k=0; knumlines; k++) { /* now step through all the inner rings */ if(innerlist[k] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[k].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f,%f,%f ", shape->line[k].point[j].x, shape->line[k].point[j].y, shape->line[k].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f,%f ", shape->line[k].point[j].x, shape->line[k].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s\n", tab); free(innerlist); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } free(outerlist); outerlist = NULL; } else if(geometry_aggregate_index != -1 || (geometryList->numgeometries == 0)) { /* write a MultiPolygon */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiPolygon */ if(srsname_encoded) msIO_fprintf(stream, "%s\n", tab, srsname_encoded); else msIO_fprintf(stream, "%s\n", tab); for(i=0; inumlines; i++) { /* step through the outer rings */ if(outerlist[i] == MS_TRUE) { innerlist = msGetInnerList(shape, i, outerlist); msIO_fprintf(stream, "%s\n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[i].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f,%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f,%f ", shape->line[i].point[j].x, shape->line[i].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(k=0; knumlines; k++) { /* now step through all the inner rings */ if(innerlist[k] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab); for(j=0; jline[k].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f,%f,%f ", shape->line[k].point[j].x, shape->line[k].point[j].y, shape->line[k].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f,%f ", shape->line[k].point[j].x, shape->line[k].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s\n", tab); free(innerlist); } } msIO_fprintf(stream, "%s\n", tab); free(outerlist); outerlist = NULL; gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; default: break; } /* clean-up */ msFree(srsname_encoded); msFree(outerlist); return(MS_SUCCESS); } static char* gmlCreateGeomId(OWSGMLVersion nGMLVersion, const char* pszFID, int* p_id) { char* pszGMLId; if( nGMLVersion == OWS_GML32 ) { pszGMLId = (char*) msSmallMalloc( strlen(pszFID) + 1 + strlen(" gml:id=\"\"") + 10 ); sprintf(pszGMLId, " gml:id=\"%s.%d\"", pszFID, *p_id); (*p_id) ++; } else pszGMLId = msStrdup(""); return pszGMLId; } /* GML 3.1 or GML 3.2 (MapServer limits GML encoding to the level 0 profile) */ static int gmlWriteGeometry_GML3(FILE *stream, gmlGeometryListObj *geometryList, shapeObj *shape, const char *srsname, const char *namespace, const char *tab, const char *pszFID, OWSGMLVersion nGMLVersion, int nSRSDimension) { int i, j, k, id = 1; int *innerlist, *outerlist=NULL, numouters; char *srsname_encoded = NULL; char* pszGMLId; int geometry_aggregate_index, geometry_simple_index; char *geometry_aggregate_name = NULL, *geometry_simple_name = NULL; if(!stream) return(MS_FAILURE); if(!shape) return(MS_FAILURE); if(!tab) return(MS_FAILURE); if(!geometryList) return(MS_FAILURE); if(shape->numlines <= 0) return(MS_SUCCESS); /* empty shape, nothing to output */ if(srsname) srsname_encoded = msEncodeHTMLEntities(srsname); /* feature geometry */ switch(shape->type) { case(MS_SHAPE_POINT): geometry_simple_index = msGMLGeometryLookup(geometryList, "point"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multipoint"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; if((geometry_simple_index != -1 && shape->line[0].numpoints == 1 && shape->numlines == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->line[0].numpoints == 1 && shape->numlines == 1)) { /* write a Point(s) */ for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* Point */ pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, pszGMLId, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab, pszGMLId); #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%s %f %f %f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%s %f %f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "%s \n", tab); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); msFree(pszGMLId); } } } else if((geometry_aggregate_index != -1) || (geometryList->numgeometries == 0)) { /* write a MultiPoint */ pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiPoint */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, pszGMLId, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab, pszGMLId); msFree(pszGMLId); for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { msIO_fprintf(stream, "%s \n", tab); pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); msIO_fprintf(stream, "%s \n", tab, pszGMLId); #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%s %f %f %f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%s %f %f\n", tab, shape->line[i].point[j].x, shape->line[i].point[j].y); msIO_fprintf(stream, "%s \n", tab); msFree(pszGMLId); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; case(MS_SHAPE_LINE): geometry_simple_index = msGMLGeometryLookup(geometryList, "line"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multiline"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; if((geometry_simple_index != -1 && shape->numlines == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->numlines == 1)) { /* write a LineStrings(s) */ for(i=0; inumlines; i++) { gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); /* LineString (should be Curve?) */ pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, pszGMLId, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab, pszGMLId); msFree(pszGMLId); msIO_fprintf(stream, "%s ", tab, nSRSDimension); for(j=0; jline[i].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f %f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } } else if(geometry_aggregate_index != -1 || (geometryList->numgeometries == 0)) { /* write a MultiCurve */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); /* MultiCurve */ pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, pszGMLId, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab, pszGMLId); msFree(pszGMLId); for(i=0; inumlines; i++) { msIO_fprintf(stream, "%s \n", tab); pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); msIO_fprintf(stream, "%s \n", tab, pszGMLId); /* no srsname at this point */ msFree(pszGMLId); msIO_fprintf(stream, "%s ", tab, nSRSDimension); for(j=0; jline[i].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f %f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } msIO_fprintf(stream, "%s \n", tab); gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; case(MS_SHAPE_POLYGON): /* this gets nasty, since our shapes are so flexible */ geometry_simple_index = msGMLGeometryLookup(geometryList, "polygon"); geometry_aggregate_index = msGMLGeometryLookup(geometryList, "multipolygon"); if(geometry_simple_index >= 0) geometry_simple_name = geometryList->geometries[geometry_simple_index].name; if(geometry_aggregate_index >= 0) geometry_aggregate_name = geometryList->geometries[geometry_aggregate_index].name; /* get a list of outter rings for this polygon */ outerlist = msGetOuterList(shape); numouters = 0; for(i=0; inumlines; i++) if(outerlist[i] == MS_TRUE) numouters++; if((geometry_simple_index != -1 && numouters == 1) || (geometry_simple_index != -1 && geometry_aggregate_index == -1) || (geometryList->numgeometries == 0 && shape->numlines == 1)) { /* write a Polygon(s) */ for(i=0; inumlines; i++) { if(outerlist[i] == MS_FALSE) break; /* skip non-outer rings, each outer ring is a new polygon */ /* get a list of inner rings for this polygon */ innerlist = msGetInnerList(shape, i, outerlist); gmlStartGeometryContainer(stream, geometry_simple_name, namespace, tab); pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); /* Polygon (should be Surface?) */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, pszGMLId, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab, pszGMLId); msFree(pszGMLId); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab, nSRSDimension); for(j=0; jline[i].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f %f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(k=0; knumlines; k++) { /* now step through all the inner rings */ if(innerlist[k] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab, nSRSDimension); for(j=0; jline[k].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f %f %f ", shape->line[k].point[j].x, shape->line[k].point[j].y, shape->line[k].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f %f ", shape->line[k].point[j].x, shape->line[k].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); free(innerlist); gmlEndGeometryContainer(stream, geometry_simple_name, namespace, tab); } free(outerlist); outerlist = NULL; } else if(geometry_aggregate_index != -1 || (geometryList->numgeometries == 0)) { /* write a MultiSurface */ gmlStartGeometryContainer(stream, geometry_aggregate_name, namespace, tab); pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); /* MultiSurface */ if(srsname_encoded) msIO_fprintf(stream, "%s \n", tab, pszGMLId, srsname_encoded); else msIO_fprintf(stream, "%s \n", tab, pszGMLId); msFree(pszGMLId); for(i=0; inumlines; i++) { /* step through the outer rings */ if(outerlist[i] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); /* get a list of inner rings for this polygon */ innerlist = msGetInnerList(shape, i, outerlist); pszGMLId = gmlCreateGeomId(nGMLVersion, pszFID, &id); msIO_fprintf(stream, "%s \n", tab, pszGMLId); msFree(pszGMLId); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab, nSRSDimension); for(j=0; jline[i].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f %f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y, shape->line[i].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f %f ", shape->line[i].point[j].x, shape->line[i].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); for(k=0; knumlines; k++) { /* now step through all the inner rings */ if(innerlist[k] == MS_TRUE) { msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s ", tab, nSRSDimension); for(j=0; jline[k].numpoints; j++) { #ifdef USE_POINT_Z_M if( nSRSDimension == 3 ) msIO_fprintf(stream, "%f %f %f ", shape->line[k].point[j].x, shape->line[k].point[j].y, shape->line[k].point[j].z); else /* fall-through */ #endif msIO_fprintf(stream, "%f %f ", shape->line[k].point[j].x, shape->line[k].point[j].y); } msIO_fprintf(stream, "\n"); msIO_fprintf(stream, "%s \n", tab); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); free(innerlist); msIO_fprintf(stream, "%s \n", tab); } } msIO_fprintf(stream, "%s \n", tab); free(outerlist); outerlist = NULL; gmlEndGeometryContainer(stream, geometry_aggregate_name, namespace, tab); } else { msIO_fprintf(stream, "\n"); } break; default: break; } /* clean-up */ msFree(outerlist); msFree(srsname_encoded); return(MS_SUCCESS); } /* ** Wrappers for the format specific encoding functions. */ static int gmlWriteBounds(FILE *stream, OWSGMLVersion format, rectObj *rect, const char *srsname, const char *tab, const char *pszTopPrefix) { switch(format) { case(OWS_GML2): return gmlWriteBounds_GML2(stream, rect, srsname, tab, pszTopPrefix); break; case(OWS_GML3): case(OWS_GML32): return gmlWriteBounds_GML3(stream, rect, srsname, tab, pszTopPrefix); break; default: msSetError(MS_IOERR, "Unsupported GML format.", "gmlWriteBounds()"); } return(MS_FAILURE); } static int gmlWriteGeometry(FILE *stream, gmlGeometryListObj *geometryList, OWSGMLVersion format, shapeObj *shape, const char *srsname, const char *namespace, const char *tab, const char* pszFID, int nSRSDimension) { switch(format) { case(OWS_GML2): return gmlWriteGeometry_GML2(stream, geometryList, shape, srsname, namespace, tab, nSRSDimension); break; case(OWS_GML3): case(OWS_GML32): return gmlWriteGeometry_GML3(stream, geometryList, shape, srsname, namespace, tab, pszFID, format, nSRSDimension); break; default: msSetError(MS_IOERR, "Unsupported GML format.", "gmlWriteGeometry()"); } return(MS_FAILURE); } /* ** GML specific metadata handling functions. */ int msItemInGroups(const char *name, gmlGroupListObj *groupList) { int i, j; gmlGroupObj *group; if(!groupList) return MS_FALSE; /* no groups */ for(i=0; inumgroups; i++) { group = &(groupList->groups[i]); for(j=0; jnumitems; j++) { if(strcasecmp(name, group->items[j]) == 0) return MS_TRUE; } } return MS_FALSE; } static int msGMLGeometryLookup(gmlGeometryListObj *geometryList, const char *type) { int i; if(!geometryList || !type) return -1; /* nothing to look for */ for(i=0; inumgeometries; i++) if(geometryList->geometries[i].type && (strcasecmp(geometryList->geometries[i].type, type) == 0)) return i; if( geometryList->numgeometries == 1 && geometryList->geometries[0].type == NULL ) return 0; return -1; /* not found */ } gmlGeometryListObj *msGMLGetGeometries(layerObj *layer, const char *metadata_namespaces, int bWithDefaultGeom) { int i; const char *value=NULL; char tag[64]; char **names=NULL; int numnames=0; gmlGeometryListObj *geometryList=NULL; gmlGeometryObj *geometry=NULL; /* allocate memory and initialize the item collection */ geometryList = (gmlGeometryListObj *) malloc(sizeof(gmlGeometryListObj)); MS_CHECK_ALLOC(geometryList, sizeof(gmlGeometryListObj), NULL) ; geometryList->geometries = NULL; geometryList->numgeometries = 0; if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "geometries")) != NULL) { names = msStringSplit(value, ',', &numnames); /* allocation an array of gmlGeometryObj's */ geometryList->numgeometries = numnames; geometryList->geometries = (gmlGeometryObj *) malloc(sizeof(gmlGeometryObj)*geometryList->numgeometries); if (geometryList->geometries == NULL) { msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGMLGetGeometries()", (unsigned int)(sizeof(gmlGeometryObj)*geometryList->numgeometries)); free(geometryList); return NULL; } for(i=0; inumgeometries; i++) { geometry = &(geometryList->geometries[i]); geometry->name = msStrdup(names[i]); /* initialize a few things */ geometry->type = NULL; geometry->occurmin = 0; geometry->occurmax = 1; snprintf(tag, 64, "%s_type", names[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) geometry->type = msStrdup(value); /* TODO: validate input value */ snprintf(tag, 64, "%s_occurances", names[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) { char **occur; int numoccur; occur = msStringSplit(value, ',', &numoccur); if(numoccur == 2) { /* continue (TODO: throw an error if != 2) */ geometry->occurmin = atof(occur[0]); if(strcasecmp(occur[1], "UNBOUNDED") == 0) geometry->occurmax = OWS_GML_OCCUR_UNBOUNDED; else geometry->occurmax = atof(occur[1]); } msFreeCharArray(occur,numoccur); } } msFreeCharArray(names, numnames); } else if( bWithDefaultGeom ) { geometryList->numgeometries = 1; geometryList->geometries = (gmlGeometryObj *) calloc(1, sizeof(gmlGeometryObj)); geometryList->geometries[0].name = msStrdup(OWS_GML_DEFAULT_GEOMETRY_NAME); geometryList->geometries[0].type = NULL; geometryList->geometries[0].occurmin = 0; geometryList->geometries[0].occurmax = 1; } return geometryList; } void msGMLFreeGeometries(gmlGeometryListObj *geometryList) { int i; if(!geometryList) return; for(i=0; inumgeometries; i++) { msFree(geometryList->geometries[i].name); msFree(geometryList->geometries[i].type); } free(geometryList->geometries); free(geometryList); } static void msGMLWriteItem(FILE *stream, gmlItemObj *item, const char *value, const char *namespace, const char *tab, OWSGMLVersion outputformat, const char *pszFID) { char *encoded_value = NULL, *tag_name; int add_namespace = MS_TRUE; char gmlid[256]; gmlid[0] = 0; if(!stream || !item) return; if(!item->visible) return; if(!namespace) add_namespace = MS_FALSE; if(item->alias) tag_name = item->alias; else tag_name = item->name; if(strchr(tag_name, ':') != NULL) add_namespace = MS_FALSE; if( item->type && EQUAL(item->type, "Date") ) { struct tm tm; if( msParseTime(value, &tm) == MS_TRUE ) { const char* pszStartTag = ""; const char* pszEndTag = ""; int timeresolution; timeresolution = msTimeGetResolution(value); encoded_value = (char*) msSmallMalloc(256); if( outputformat == OWS_GML32 ) { if( pszFID != NULL ) snprintf(gmlid, 256, " gml:id=\"%s.%s\"", pszFID, tag_name); pszStartTag = ""; pszEndTag = ""; } if( timeresolution == TIME_RESOLUTION_DAY ) snprintf(encoded_value, 256, "%s%04d-%02d-%02d%s", pszStartTag, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, pszEndTag); else snprintf(encoded_value, 256, "%s%04d-%02d-%02dT%02d:%02d:%02dZ%s", pszStartTag, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, pszEndTag); } } if( encoded_value == NULL ) { if(item->encode == MS_TRUE) encoded_value = msEncodeHTMLEntities(value); else encoded_value = msStrdup(value); } if(!item->template) { /* build the tag from pieces */ if(add_namespace == MS_TRUE && msIsXMLTagValid(tag_name) == MS_FALSE) msIO_fprintf(stream, "\n", tag_name); if(add_namespace == MS_TRUE) msIO_fprintf(stream, "%s<%s:%s%s>%s\n", tab, namespace, tag_name, gmlid, encoded_value, namespace, tag_name); else msIO_fprintf(stream, "%s<%s%s>%s\n", tab, tag_name, gmlid, encoded_value, tag_name); } else { char *tag = NULL; tag = msStrdup(item->template); tag = msReplaceSubstring(tag, "$value", encoded_value); if(namespace) tag = msReplaceSubstring(tag, "$namespace", namespace); msIO_fprintf(stream, "%s%s\n", tab, tag); free(tag); } free( encoded_value ); return; } gmlNamespaceListObj *msGMLGetNamespaces(webObj *web, const char *metadata_namespaces) { int i; const char *value=NULL; char tag[64]; char **prefixes=NULL; int numprefixes=0; gmlNamespaceListObj *namespaceList=NULL; gmlNamespaceObj *namespace=NULL; /* allocate the collection */ namespaceList = (gmlNamespaceListObj *) malloc(sizeof(gmlNamespaceListObj)); MS_CHECK_ALLOC(namespaceList, sizeof(gmlNamespaceListObj), NULL) ; namespaceList->namespaces = NULL; namespaceList->numnamespaces = 0; /* list of namespaces (TODO: make this automatic by parsing metadata) */ if((value = msOWSLookupMetadata(&(web->metadata), metadata_namespaces, "external_namespace_prefixes")) != NULL) { prefixes = msStringSplit(value, ',', &numprefixes); /* allocation an array of gmlNamespaceObj's */ namespaceList->numnamespaces = numprefixes; namespaceList->namespaces = (gmlNamespaceObj *) malloc(sizeof(gmlNamespaceObj)*namespaceList->numnamespaces); if (namespaceList->namespaces == NULL) { msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGMLGetNamespaces()", (unsigned int)(sizeof(gmlNamespaceObj)*namespaceList->numnamespaces)); free(namespaceList); return NULL; } for(i=0; inumnamespaces; i++) { namespace = &(namespaceList->namespaces[i]); namespace->prefix = msStrdup(prefixes[i]); /* initialize a few things */ namespace->uri = NULL; namespace->schemalocation = NULL; snprintf(tag, 64, "%s_uri", namespace->prefix); if((value = msOWSLookupMetadata(&(web->metadata), metadata_namespaces, tag)) != NULL) namespace->uri = msStrdup(value); snprintf(tag, 64, "%s_schema_location", namespace->prefix); if((value = msOWSLookupMetadata(&(web->metadata), metadata_namespaces, tag)) != NULL) namespace->schemalocation = msStrdup(value); } msFreeCharArray(prefixes, numprefixes); } return namespaceList; } void msGMLFreeNamespaces(gmlNamespaceListObj *namespaceList) { int i; if(!namespaceList) return; for(i=0; inumnamespaces; i++) { msFree(namespaceList->namespaces[i].prefix); msFree(namespaceList->namespaces[i].uri); msFree(namespaceList->namespaces[i].schemalocation); } free(namespaceList); } gmlConstantListObj *msGMLGetConstants(layerObj *layer, const char *metadata_namespaces) { int i; const char *value=NULL; char tag[64]; char **names=NULL; int numnames=0; gmlConstantListObj *constantList=NULL; gmlConstantObj *constant=NULL; /* allocate the collection */ constantList = (gmlConstantListObj *) malloc(sizeof(gmlConstantListObj)); MS_CHECK_ALLOC(constantList, sizeof(gmlConstantListObj), NULL); constantList->constants = NULL; constantList->numconstants = 0; /* list of constants (TODO: make this automatic by parsing metadata) */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "constants")) != NULL) { names = msStringSplit(value, ',', &numnames); /* allocation an array of gmlConstantObj's */ constantList->numconstants = numnames; constantList->constants = (gmlConstantObj *) malloc(sizeof(gmlConstantObj)*constantList->numconstants); if (constantList->constants == NULL) { msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGMLGetConstants()", (unsigned int)(sizeof(gmlConstantObj)*constantList->numconstants)); free(constantList); return NULL; } for(i=0; inumconstants; i++) { constant = &(constantList->constants[i]); constant->name = msStrdup(names[i]); /* initialize a few things */ constant->value = NULL; constant->type = NULL; snprintf(tag, 64, "%s_value", constant->name); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) constant->value = msStrdup(value); snprintf(tag, 64, "%s_type", constant->name); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) constant->type = msStrdup(value); } msFreeCharArray(names, numnames); } return constantList; } void msGMLFreeConstants(gmlConstantListObj *constantList) { int i; if(!constantList) return; for(i=0; inumconstants; i++) { msFree(constantList->constants[i].name); msFree(constantList->constants[i].value); msFree(constantList->constants[i].type); } free(constantList); } static void msGMLWriteConstant(FILE *stream, gmlConstantObj *constant, const char *namespace, const char *tab) { int add_namespace = MS_TRUE; if(!stream || !constant) return; if(!constant->value) return; if(!namespace) add_namespace = MS_FALSE; if(strchr(constant->name, ':') != NULL) add_namespace = MS_FALSE; if(add_namespace == MS_TRUE && msIsXMLTagValid(constant->name) == MS_FALSE) msIO_fprintf(stream, "\n", constant->name); if(add_namespace == MS_TRUE) msIO_fprintf(stream, "%s<%s:%s>%s\n", tab, namespace, constant->name, constant->value, namespace, constant->name); else msIO_fprintf(stream, "%s<%s>%s\n", tab, constant->name, constant->value, constant->name); return; } gmlGroupListObj *msGMLGetGroups(layerObj *layer, const char *metadata_namespaces) { int i; const char *value=NULL; char tag[64]; char **names=NULL; int numnames=0; gmlGroupListObj *groupList=NULL; gmlGroupObj *group=NULL; /* allocate the collection */ groupList = (gmlGroupListObj *) malloc(sizeof(gmlGroupListObj)); MS_CHECK_ALLOC(groupList, sizeof(gmlGroupListObj), NULL) ; groupList->groups = NULL; groupList->numgroups = 0; /* list of groups (TODO: make this automatic by parsing metadata) */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "groups")) != NULL && value[0] != '\0' ) { names = msStringSplit(value, ',', &numnames); /* allocation an array of gmlGroupObj's */ groupList->numgroups = numnames; groupList->groups = (gmlGroupObj *) malloc(sizeof(gmlGroupObj)*groupList->numgroups); if (groupList->groups == NULL) { msSetError(MS_MEMERR, "Out of memory allocating %u bytes.\n", "msGMLGetGroups()", (unsigned int)(sizeof(gmlGroupObj)*groupList->numgroups)); free(groupList); return NULL; } for(i=0; inumgroups; i++) { group = &(groupList->groups[i]); group->name = msStrdup(names[i]); /* initialize a few things */ group->items = NULL; group->numitems = 0; group->type = NULL; snprintf(tag, 64, "%s_group", group->name); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) group->items = msStringSplit(value, ',', &group->numitems); snprintf(tag, 64, "%s_type", group->name); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) group->type = msStrdup(value); } msFreeCharArray(names, numnames); } return groupList; } void msGMLFreeGroups(gmlGroupListObj *groupList) { int i; if(!groupList) return; for(i=0; inumgroups; i++) { msFree(groupList->groups[i].name); msFreeCharArray(groupList->groups[i].items, groupList->groups[i].numitems); msFree(groupList->groups[i].type); } msFree(groupList->groups); free(groupList); } static void msGMLWriteGroup(FILE *stream, gmlGroupObj *group, shapeObj *shape, gmlItemListObj *itemList, gmlConstantListObj *constantList, const char *namespace, const char *tab, OWSGMLVersion outputformat, const char *pszFID) { int i,j; int add_namespace = MS_TRUE; char *itemtab; gmlItemObj *item=NULL; gmlConstantObj *constant=NULL; if(!stream || !group) return; /* setup the item/constant tab */ itemtab = (char *) msSmallMalloc(sizeof(char)*strlen(tab)+3); sprintf(itemtab, "%s ", tab); if(!namespace || strchr(group->name, ':') != NULL) add_namespace = MS_FALSE; /* start the group */ if(add_namespace == MS_TRUE) msIO_fprintf(stream, "%s<%s:%s>\n", tab, namespace, group->name); else msIO_fprintf(stream, "%s<%s>\n", tab, group->name); /* now the items/constants in the group */ for(i=0; inumitems; i++) { for(j=0; jnumconstants; j++) { constant = &(constantList->constants[j]); if(strcasecmp(constant->name, group->items[i]) == 0) { msGMLWriteConstant(stream, constant, namespace, itemtab); break; } } if(j != constantList->numconstants) continue; /* found this one */ for(j=0; jnumitems; j++) { item = &(itemList->items[j]); if(strcasecmp(item->name, group->items[i]) == 0) { /* the number of items matches the number of values exactly */ msGMLWriteItem(stream, item, shape->values[j], namespace, itemtab, outputformat, pszFID); break; } } } /* end the group */ if(add_namespace == MS_TRUE) msIO_fprintf(stream, "%s\n", tab, namespace, group->name); else msIO_fprintf(stream, "%s\n", tab, group->name); msFree(itemtab); return; } #endif /* Dump GML query results for WMS GetFeatureInfo */ int msGMLWriteQuery(mapObj *map, char *filename, const char *namespaces) { #if defined(USE_WMS_SVR) int status; int i,j,k; layerObj *lp=NULL; shapeObj shape; FILE *stream=stdout; /* defaults to stdout */ char szPath[MS_MAXPATHLEN]; char *value; char *pszMapSRS = NULL; gmlGroupListObj *groupList=NULL; gmlItemListObj *itemList=NULL; gmlConstantListObj *constantList=NULL; gmlGeometryListObj *geometryList=NULL; gmlItemObj *item=NULL; gmlConstantObj *constant=NULL; msInitShape(&shape); if(filename && strlen(filename) > 0) { /* deal with the filename if present */ stream = fopen(msBuildPath(szPath, map->mappath, filename), "w"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msGMLWriteQuery()", filename); return(MS_FAILURE); } } msIO_fprintf(stream, "\n\n"); msOWSPrintValidateMetadata(stream, &(map->web.metadata), namespaces, "rootname", OWS_NOERR, "<%s ", "msGMLOutput"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "uri", OWS_NOERR, "xmlns=\"%s\"", NULL); msIO_fprintf(stream, "\n\t xmlns:gml=\"http://www.opengis.net/gml\"" ); msIO_fprintf(stream, "\n\t xmlns:xlink=\"http://www.w3.org/1999/xlink\""); msIO_fprintf(stream, "\n\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "schema", OWS_NOERR, "\n\t xsi:schemaLocation=\"%s\"", NULL); msIO_fprintf(stream, ">\n"); /* a schema *should* be required */ msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "description", OWS_NOERR, "\t%s\n", NULL); /* Look up map SRS. We need an EPSG code for GML, if not then we get null and we'll fall back on the layer's SRS */ msOWSGetEPSGProj(&(map->projection), NULL, namespaces, MS_TRUE, &pszMapSRS); /* step through the layers looking for query results */ for(i=0; inumlayers; i++) { char *pszOutputSRS = NULL; int nSRSDimension = 2; const char* geomtype; lp = (GET_LAYER(map, map->layerorder[i])); if(lp->resultcache && lp->resultcache->numresults > 0) { /* found results */ #ifdef USE_PROJ /* Determine output SRS, if map has none, then try using layer's native SRS */ if ((pszOutputSRS = pszMapSRS) == NULL) { msOWSGetEPSGProj(&(lp->projection), NULL, namespaces, MS_TRUE, &pszOutputSRS); if (pszOutputSRS == NULL) { msSetError(MS_WMSERR, "No valid EPSG code in map or layer projection for GML output", "msGMLWriteQuery()"); continue; /* No EPSG code, cannot output this layer */ } } #endif /* start this collection (layer) */ /* if no layer name provided fall back on the layer name + "_layer" */ value = (char*) msSmallMalloc(strlen(lp->name)+7); sprintf(value, "%s_layer", lp->name); msOWSPrintValidateMetadata(stream, &(lp->metadata), namespaces, "layername", OWS_NOERR, "\t<%s>\n", value); msFree(value); value = (char *) msOWSLookupMetadata(&(lp->metadata), "OM", "title"); if (value) { msOWSPrintEncodeMetadata(stream, &(lp->metadata), namespaces, "title", OWS_NOERR, "\t%s\n", value); } geomtype = msOWSLookupMetadata(&(lp->metadata), "OFG", "geomtype"); if( geomtype != NULL && (strstr(geomtype, "25d") != NULL || strstr(geomtype, "25D") != NULL) ) { #ifdef USE_POINT_Z_M nSRSDimension = 3; #else msIO_fprintf(stream, "\n", lp->name); #endif } /* populate item and group metadata structures */ itemList = msGMLGetItems(lp, namespaces); constantList = msGMLGetConstants(lp, namespaces); groupList = msGMLGetGroups(lp, namespaces); geometryList = msGMLGetGeometries(lp, namespaces, MS_FALSE); if (itemList == NULL || constantList == NULL || groupList == NULL || geometryList == NULL) { msSetError(MS_MISCERR, "Unable to populate item and group metadata structures", "msGMLWriteQuery()"); return MS_FAILURE; } for(j=0; jresultcache->numresults; j++) { status = msLayerGetShape(lp, &shape, &(lp->resultcache->results[j])); if(status != MS_SUCCESS) { msGMLFreeGroups(groupList); msGMLFreeConstants(constantList); msGMLFreeItems(itemList); msGMLFreeGeometries(geometryList); return(status); } #ifdef USE_PROJ /* project the shape into the map projection (if necessary), note that this projects the bounds as well */ if(pszOutputSRS == pszMapSRS && msProjectionsDiffer(&(lp->projection), &(map->projection))) { status = msProjectShape(&lp->projection, &map->projection, &shape); if(status != MS_SUCCESS) { msIO_fprintf(stream, "\n",msGetErrorString(",")); continue; } } #endif /* start this feature */ /* specify a feature name, if nothing provided fall back on the layer name + "_feature" */ value = (char*) msSmallMalloc(strlen(lp->name)+9); sprintf(value, "%s_feature", lp->name); msOWSPrintValidateMetadata(stream, &(lp->metadata), namespaces, "featurename", OWS_NOERR, "\t\t<%s>\n", value); msFree(value); /* Write the feature geometry and bounding box unless 'none' was requested. */ /* Default to bbox only if nothing specified and output full geometry only if explicitly requested */ if(!(geometryList && geometryList->numgeometries == 1 && strcasecmp(geometryList->geometries[0].name, "none") == 0)) { gmlWriteBounds(stream, OWS_GML2, &(shape.bounds), pszOutputSRS, "\t\t\t", "gml"); if (geometryList && geometryList->numgeometries > 0 ) gmlWriteGeometry(stream, geometryList, OWS_GML2, &(shape), pszOutputSRS, NULL, "\t\t\t", "", nSRSDimension); } /* write any item/values */ for(k=0; knumitems; k++) { item = &(itemList->items[k]); if(msItemInGroups(item->name, groupList) == MS_FALSE) msGMLWriteItem(stream, item, shape.values[k], NULL, "\t\t\t", OWS_GML2, NULL); } /* write any constants */ for(k=0; knumconstants; k++) { constant = &(constantList->constants[k]); if(msItemInGroups(constant->name, groupList) == MS_FALSE) msGMLWriteConstant(stream, constant, NULL, "\t\t\t"); } /* write any groups */ for(k=0; knumgroups; k++) msGMLWriteGroup(stream, &(groupList->groups[k]), &shape, itemList, constantList, NULL, "\t\t\t", OWS_GML2, NULL); /* end this feature */ /* specify a feature name if nothing provided */ /* fall back on the layer name + "Feature" */ value = (char*) msSmallMalloc(strlen(lp->name)+9); sprintf(value, "%s_feature", lp->name); msOWSPrintValidateMetadata(stream, &(lp->metadata), namespaces, "featurename", OWS_NOERR, "\t\t\n", value); msFree(value); msFreeShape(&shape); /* init too */ } /* end this collection (layer) */ /* if no layer name provided fall back on the layer name + "_layer" */ value = (char*) msSmallMalloc(strlen(lp->name)+7); sprintf(value, "%s_layer", lp->name); msOWSPrintValidateMetadata(stream, &(lp->metadata), namespaces, "layername", OWS_NOERR, "\t\n", value); msFree(value); msGMLFreeGroups(groupList); msGMLFreeConstants(constantList); msGMLFreeItems(itemList); msGMLFreeGeometries(geometryList); /* msLayerClose(lp); */ } if(pszOutputSRS!=pszMapSRS) { msFree(pszOutputSRS); } } /* next layer */ /* end this document */ msOWSPrintValidateMetadata(stream, &(map->web.metadata), namespaces, "rootname", OWS_NOERR, "\n", "msGMLOutput"); if(filename && strlen(filename) > 0) fclose(stream); msFree(pszMapSRS); return(MS_SUCCESS); #else /* Stub for mapscript */ msSetError(MS_MISCERR, "WMS server support not enabled", "msGMLWriteQuery()"); return MS_FAILURE; #endif } #ifdef USE_WFS_SVR void msGMLWriteWFSBounds(mapObj *map, FILE *stream, const char *tab, OWSGMLVersion outputformat, int nWFSVersion, int bUseURN) { rectObj resultBounds = {-1.0,-1.0,-1.0,-1.0}; /*add a check to see if the map projection is set to be north-east*/ int bSwapAxis = msIsAxisInvertedProj(&(map->projection)); /* Need to start with BBOX of the whole resultset */ if (msGetQueryResultBounds(map, &resultBounds) > 0) { char* srs = NULL; if (bSwapAxis) { double tmp; tmp = resultBounds.minx; resultBounds.minx = resultBounds.miny; resultBounds.miny = tmp; tmp = resultBounds.maxx; resultBounds.maxx = resultBounds.maxy; resultBounds.maxy = tmp; } if( bUseURN ) { srs = msOWSGetProjURN(&(map->projection), NULL, "FGO", MS_TRUE); if (!srs) srs = msOWSGetProjURN(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE); } else { msOWSGetEPSGProj(&(map->projection), NULL, "FGO", MS_TRUE, &srs); if (!srs) msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE, &srs); } gmlWriteBounds(stream, outputformat, &resultBounds, srs, tab, (nWFSVersion == OWS_2_0_0) ? "wfs" : "gml"); msFree(srs); } } #endif /* ** msGMLWriteWFSQuery() ** ** Similar to msGMLWriteQuery() but tuned for use with WFS */ int msGMLWriteWFSQuery(mapObj *map, FILE *stream, const char *default_namespace_prefix, OWSGMLVersion outputformat, int nWFSVersion, int bUseURN, int bGetPropertyValueRequest) { #ifdef USE_WFS_SVR int status; int i,j,k; layerObj *lp=NULL; shapeObj shape; gmlGroupListObj *groupList=NULL; gmlItemListObj *itemList=NULL; gmlConstantListObj *constantList=NULL; gmlGeometryListObj *geometryList=NULL; gmlItemObj *item=NULL; gmlConstantObj *constant=NULL; const char *namespace_prefix=NULL; int bSwapAxis; msInitShape(&shape); /*add a check to see if the map projection is set to be north-east*/ bSwapAxis = msIsAxisInvertedProj(&(map->projection)); /* Need to start with BBOX of the whole resultset */ if (!bGetPropertyValueRequest) { msGMLWriteWFSBounds(map, stream, " ", outputformat, nWFSVersion, bUseURN); } /* step through the layers looking for query results */ for(i=0; inumlayers; i++) { lp = GET_LAYER(map, map->layerorder[i]); if(lp->resultcache && lp->resultcache->numresults > 0) { /* found results */ char *layerName; const char *value; int featureIdIndex=-1; /* no feature id */ char* srs = NULL; int bOutputGMLIdOnly = MS_FALSE; int nSRSDimension = 2; const char* geomtype; /* setup namespace, a layer can override the default */ namespace_prefix = msOWSLookupMetadata(&(lp->metadata), "OFG", "namespace_prefix"); if(!namespace_prefix) namespace_prefix = default_namespace_prefix; geomtype = msOWSLookupMetadata(&(lp->metadata), "OFG", "geomtype"); if( geomtype != NULL && (strstr(geomtype, "25d") != NULL || strstr(geomtype, "25D") != NULL) ) { #ifdef USE_POINT_Z_M nSRSDimension = 3; #else msIO_fprintf(stream, "\n", lp->name); #endif } value = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid"); if(value) { /* find the featureid amongst the items for this layer */ for(j=0; jnumitems; j++) { if(strcasecmp(lp->items[j], value) == 0) { /* found it */ featureIdIndex = j; break; } } /* Produce a warning if a featureid was set but the corresponding item is not found. */ if (featureIdIndex == -1) msIO_fprintf(stream, "\n", value, lp->name); } else if( outputformat == OWS_GML32 ) msIO_fprintf(stream, "\n", lp->name); /* populate item and group metadata structures */ itemList = msGMLGetItems(lp, "G"); constantList = msGMLGetConstants(lp, "G"); groupList = msGMLGetGroups(lp, "G"); geometryList = msGMLGetGeometries(lp, "GFO", MS_FALSE); if (itemList == NULL || constantList == NULL || groupList == NULL || geometryList == NULL) { msSetError(MS_MISCERR, "Unable to populate item and group metadata structures", "msGMLWriteWFSQuery()"); return MS_FAILURE; } if( bGetPropertyValueRequest ) { const char* value = msOWSLookupMetadata(&(lp->metadata), "G", "include_items"); if( value != NULL && strcmp(value, "@gml:id") == 0 ) bOutputGMLIdOnly = MS_TRUE; } if (namespace_prefix) { layerName = (char *) msSmallMalloc(strlen(namespace_prefix)+strlen(lp->name)+2); sprintf(layerName, "%s:%s", namespace_prefix, lp->name); } else { layerName = msStrdup(lp->name); } #ifdef USE_PROJ if( bUseURN ) { srs = msOWSGetProjURN(&(map->projection), NULL, "FGO", MS_TRUE); if (!srs) srs = msOWSGetProjURN(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE); if (!srs) srs = msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FGO", MS_TRUE); } else { msOWSGetEPSGProj(&(map->projection), NULL, "FGO", MS_TRUE, &srs); if (!srs) msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "FGO", MS_TRUE, &srs); if (!srs) msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FGO", MS_TRUE, &srs); } #endif for(j=0; jresultcache->numresults; j++) { char* pszFID; if( lp->resultcache->results[j].shape ) { /* msDebug("Using cached shape %ld\n", lp->resultcache->results[j].shapeindex); */ msCopyShape(lp->resultcache->results[j].shape, &shape); } else { status = msLayerGetShape(lp, &shape, &(lp->resultcache->results[j])); if(status != MS_SUCCESS) { msGMLFreeGroups(groupList); msGMLFreeConstants(constantList); msGMLFreeItems(itemList); msGMLFreeGeometries(geometryList); msFree(layerName); return(status); } } #ifdef USE_PROJ /* project the shape into the map projection (if necessary), note that this projects the bounds as well */ if(msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&lp->projection, &map->projection, &shape); #endif if(featureIdIndex != -1) { pszFID = (char*) msSmallMalloc( strlen(lp->name) + 1 + strlen(shape.values[featureIdIndex]) + 1 ); sprintf(pszFID, "%s.%s", lp->name, shape.values[featureIdIndex]); } else pszFID = msStrdup(""); if( bOutputGMLIdOnly ) { msIO_fprintf(stream, " %s\n", pszFID); msFree(pszFID); msFreeShape(&shape); /* init too */ continue; } /* ** start this feature */ if( nWFSVersion == OWS_2_0_0 ) msIO_fprintf(stream, " \n"); else msIO_fprintf(stream, " \n"); if(msIsXMLTagValid(layerName) == MS_FALSE) msIO_fprintf(stream, "\n", layerName); if(featureIdIndex != -1) { if( !bGetPropertyValueRequest ) { if(outputformat == OWS_GML2) msIO_fprintf(stream, " <%s fid=\"%s\">\n", layerName, pszFID); else /* OWS_GML3 or OWS_GML32 */ msIO_fprintf(stream, " <%s gml:id=\"%s\">\n", layerName, pszFID); } } else { if( !bGetPropertyValueRequest ) msIO_fprintf(stream, " <%s>\n", layerName); } if (bSwapAxis) msAxisSwapShape(&shape); /* write the feature geometry and bounding box */ if(!(geometryList && geometryList->numgeometries == 1 && strcasecmp(geometryList->geometries[0].name, "none") == 0)) { if( !bGetPropertyValueRequest ) gmlWriteBounds(stream, outputformat, &(shape.bounds), srs, " ", "gml"); gmlWriteGeometry(stream, geometryList, outputformat, &(shape), srs, namespace_prefix, " ", pszFID, nSRSDimension); } /* write any item/values */ for(k=0; knumitems; k++) { item = &(itemList->items[k]); if(msItemInGroups(item->name, groupList) == MS_FALSE) msGMLWriteItem(stream, item, shape.values[k], namespace_prefix, " ", outputformat, pszFID); } /* write any constants */ for(k=0; knumconstants; k++) { constant = &(constantList->constants[k]); if(msItemInGroups(constant->name, groupList) == MS_FALSE) msGMLWriteConstant(stream, constant, namespace_prefix, " "); } /* write any groups */ for(k=0; knumgroups; k++) msGMLWriteGroup(stream, &(groupList->groups[k]), &shape, itemList, constantList, namespace_prefix, " ", outputformat, pszFID); if( !bGetPropertyValueRequest ) /* end this feature */ msIO_fprintf(stream, " \n", layerName); if( nWFSVersion == OWS_2_0_0 ) msIO_fprintf(stream, " \n"); else msIO_fprintf(stream, " \n"); msFree(pszFID); pszFID = NULL; msFreeShape(&shape); /* init too */ } msFree(srs); /* done with this layer, do a little clean-up */ msFree(layerName); msGMLFreeGroups(groupList); msGMLFreeConstants(constantList); msGMLFreeItems(itemList); msGMLFreeGeometries(geometryList); /* msLayerClose(lp); */ } } /* next layer */ return(MS_SUCCESS); #else /* Stub for mapscript */ msSetError(MS_MISCERR, "WFS server support not enabled", "msGMLWriteWFSQuery()"); return MS_FAILURE; #endif /* USE_WFS_SVR */ } #ifdef USE_LIBXML2 /** * msGML3BoundedBy() * * returns an object of BoundedBy as per GML 3 * * @param xmlNsPtr psNs the namespace object * @param minx minx * @param miny miny * @param maxx maxx * @param mayy mayy * @param psEpsg epsg code * @param dimension number of dimensions * * @return psNode xmlNodePtr of XML construct * */ xmlNodePtr msGML3BoundedBy(xmlNsPtr psNs, double minx, double miny, double maxx, double maxy, const char *psEpsg) { xmlNodePtr psNode = NULL, psSubNode = NULL; char *pszTmp = NULL; char *pszTmp2 = NULL; char *pszEpsg = NULL; size_t bufferSize = 0; psNode = xmlNewNode(psNs, BAD_CAST "boundedBy"); psSubNode = xmlNewChild(psNode, NULL, BAD_CAST "Envelope", NULL); if (psEpsg) { bufferSize = strlen(psEpsg)+1; pszEpsg = (char*) msSmallMalloc(bufferSize); snprintf(pszEpsg, bufferSize, "%s", psEpsg); msStringToLower(pszEpsg); pszTmp = msStringConcatenate(pszTmp, "urn:ogc:crs:"); pszTmp = msStringConcatenate(pszTmp, pszEpsg); xmlNewProp(psSubNode, BAD_CAST "srsName", BAD_CAST pszTmp); free(pszEpsg); free(pszTmp); pszTmp = msIntToString(2); xmlNewProp(psSubNode, BAD_CAST "srsDimension", BAD_CAST pszTmp); free(pszTmp); } pszTmp = msDoubleToString(minx, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, " "); pszTmp2 = msDoubleToString(miny, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, pszTmp2); xmlNewChild(psSubNode, NULL, BAD_CAST "lowerCorner", BAD_CAST pszTmp); free(pszTmp); free(pszTmp2); pszTmp = msDoubleToString(maxx, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, " "); pszTmp2 = msDoubleToString(maxy,MS_TRUE); pszTmp = msStringConcatenate(pszTmp, pszTmp2); xmlNewChild(psSubNode, NULL, BAD_CAST "upperCorner", BAD_CAST pszTmp); free(pszTmp); free(pszTmp2); return psNode; } /** *msGML3Point() * * returns an object of Point as per GML 3 * * @param xmlNsPtr psNs the gml namespace object * @param pszSrsName EPSG code of geometry * @param id * @param x x coordinate * @param y y coordinate * @param z z coordinate * * @return psNode xmlNodePtr of XML construct * */ xmlNodePtr msGML3Point(xmlNsPtr psNs, const char *psSrsName, const char *id, double x, double y) { xmlNodePtr psNode = NULL; char *pszTmp = NULL; int dimension = 2; char *pszSrsName = NULL; char *pszTmp2 = NULL; size_t bufferSize = 0; psNode = xmlNewNode(psNs, BAD_CAST "Point"); if (id) { xmlNewNsProp(psNode, psNs, BAD_CAST "id", BAD_CAST id); } if (psSrsName) { bufferSize = strlen(psSrsName)+1; pszSrsName = (char *) msSmallMalloc(bufferSize); snprintf(pszSrsName, bufferSize, "%s", psSrsName); msStringToLower(pszSrsName); pszTmp = msStringConcatenate(pszTmp, "urn:ogc:crs:"); pszTmp = msStringConcatenate(pszTmp, pszSrsName); xmlNewProp(psNode, BAD_CAST "srsName", BAD_CAST pszTmp); free(pszSrsName); free(pszTmp); pszTmp = msIntToString(dimension); xmlNewProp(psNode, BAD_CAST "srsDimension", BAD_CAST pszTmp); free(pszTmp); } pszTmp = msDoubleToString(x, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, " "); pszTmp2 = msDoubleToString(y, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, pszTmp2); xmlNewChild(psNode, NULL, BAD_CAST "pos", BAD_CAST pszTmp); free(pszTmp); free(pszTmp2); return psNode; } /** * msGML3TimePeriod() * * returns an object of TimePeriod as per GML 3 * * @param xmlNsPtr psNs the gml namespace object * @param pszStart start time * @param pszEnd end time * * @return psNode xmlNodePtr of XML construct * */ xmlNodePtr msGML3TimePeriod(xmlNsPtr psNs, char *pszStart, char *pszEnd) { xmlNodePtr psNode=NULL; psNode = xmlNewNode(psNs, BAD_CAST "TimePeriod"); xmlNewChild(psNode, NULL, BAD_CAST "beginPosition", BAD_CAST pszStart); if (pszEnd) xmlNewChild(psNode, NULL, BAD_CAST "endPosition", BAD_CAST pszEnd); else { xmlNewChild(psNode, NULL, BAD_CAST "endPosition", NULL); xmlNewProp(psNode, BAD_CAST "indeterminatePosition", BAD_CAST "now"); } return psNode; } /** * msGML3TimeInstant() * * returns an object of TimeInstant as per GML 3 * * @param xmlNsPtr psNs the gml namespace object * @param timeInstant time instant * * @return psNode xmlNodePtr of XML construct * */ xmlNodePtr msGML3TimeInstant(xmlNsPtr psNs, char *pszTime) { xmlNodePtr psNode=NULL; psNode = xmlNewNode(psNs, BAD_CAST "TimeInstant"); xmlNewChild(psNode, NULL, BAD_CAST "timePosition", BAD_CAST pszTime); return psNode; } #endif /* USE_LIBXML2 */ /************************************************************************/ /* The following functions are enabled in all cases, even if */ /* WMS and WFS are not available. */ /************************************************************************/ gmlItemListObj *msGMLGetItems(layerObj *layer, const char *metadata_namespaces) { int i,j; char **xmlitems=NULL; int numxmlitems=0; char **incitems=NULL; int numincitems=0; char **excitems=NULL; int numexcitems=0; char **optionalitems=NULL; int numoptionalitems=0; char **mandatoryitems=NULL; int nummandatoryitems=0; char **defaultitems=NULL; int numdefaultitems=0; const char *value=NULL; char tag[64]; gmlItemListObj *itemList=NULL; gmlItemObj *item=NULL; /* get a list of items that might be included in output */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "include_items")) != NULL) incitems = msStringSplit(value, ',', &numincitems); /* get a list of items that should be excluded in output */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "exclude_items")) != NULL) excitems = msStringSplit(value, ',', &numexcitems); /* get a list of items that should not be XML encoded */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "xml_items")) != NULL) xmlitems = msStringSplit(value, ',', &numxmlitems); /* get a list of items that should be indicated as optional in DescribeFeatureType */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "optional_items")) != NULL) optionalitems = msStringSplit(value, ',', &numoptionalitems); /* get a list of items that should be indicated as mandatory in DescribeFeatureType */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "mandatory_items")) != NULL) mandatoryitems = msStringSplit(value, ',', &nummandatoryitems); /* get a list of items that should be presented by default in GetFeature */ if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, "default_items")) != NULL) defaultitems = msStringSplit(value, ',', &numdefaultitems); /* allocate memory and iinitialize the item collection */ itemList = (gmlItemListObj *) malloc(sizeof(gmlItemListObj)); if(itemList == NULL) { msSetError(MS_MEMERR, "Error allocating a collection GML item structures.", "msGMLGetItems()"); return NULL; } itemList->numitems = layer->numitems; itemList->items = (gmlItemObj *) malloc(sizeof(gmlItemObj)*itemList->numitems); if(!itemList->items) { msSetError(MS_MEMERR, "Error allocating a collection GML item structures.", "msGMLGetItems()"); free(itemList); return NULL; } for(i=0; inumitems; i++) { item = &(itemList->items[i]); item->name = msStrdup(layer->items[i]); /* initialize the item */ item->alias = NULL; item->type = NULL; item->template = NULL; item->encode = MS_TRUE; item->visible = MS_FALSE; item->width = 0; item->precision = 0; item->outputByDefault = (numdefaultitems == 0); item->minOccurs = 0; /* check visibility, included items first... */ if(numincitems == 1 && strcasecmp("all", incitems[0]) == 0) { item->visible = MS_TRUE; } else { for(j=0; jitems[i], incitems[j]) == 0) item->visible = MS_TRUE; } } /* ...and now excluded items */ for(j=0; jitems[i], excitems[j]) == 0) item->visible = MS_FALSE; } /* check encoding */ for(j=0; jitems[i], xmlitems[j]) == 0) item->encode = MS_FALSE; } /* check optional */ if(numoptionalitems == 1 && strcasecmp("all", optionalitems[0]) == 0) { item->minOccurs = 0; } else if( numoptionalitems > 0) { item->minOccurs = 1; for(j=0; jitems[i], optionalitems[j]) == 0) item->minOccurs = 0; } } /* check mandatory */ if(nummandatoryitems == 1 && strcasecmp("all", mandatoryitems[0]) == 0) { item->minOccurs = 1; } else if( nummandatoryitems > 0) { item->minOccurs = 0; for(j=0; jitems[i], mandatoryitems[j]) == 0) item->minOccurs = 1; } } /* check default */ for(j=0; jitems[i], defaultitems[j]) == 0) item->outputByDefault = 1; } snprintf(tag, sizeof(tag), "%s_alias", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->alias = msStrdup(value); snprintf(tag, sizeof(tag), "%s_type", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->type = msStrdup(value); snprintf(tag, sizeof(tag), "%s_template", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->template = msStrdup(value); snprintf(tag, sizeof(tag), "%s_width", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->width = atoi(value); snprintf(tag, sizeof(tag), "%s_precision", layer->items[i]); if((value = msOWSLookupMetadata(&(layer->metadata), metadata_namespaces, tag)) != NULL) item->precision = atoi(value); } msFreeCharArray(incitems, numincitems); msFreeCharArray(excitems, numexcitems); msFreeCharArray(xmlitems, numxmlitems); msFreeCharArray(optionalitems, numoptionalitems); msFreeCharArray(mandatoryitems, nummandatoryitems); msFreeCharArray(defaultitems, numdefaultitems); return itemList; } void msGMLFreeItems(gmlItemListObj *itemList) { int i; if(!itemList) return; for(i=0; inumitems; i++) { msFree(itemList->items[i].name); msFree(itemList->items[i].alias); msFree(itemList->items[i].type); msFree(itemList->items[i].template); } if( itemList->items != NULL ) free(itemList->items); free(itemList); } mapserver-7.4.3/mapgml.h000066400000000000000000000040221357574274700152020ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Headers for mapgml.c. shapeObj to GML output via MapServer * queries. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPGML_H #define MAPGML_H #ifdef USE_LIBXML2 #include #include xmlNodePtr msGML3BoundedBy(xmlNsPtr psNs, double minx, double miny, double maxx, double maxy, const char *psEpsg); xmlNodePtr msGML3TimePeriod(xmlNsPtr psNs, char *pszStart, char *pszEnd); xmlNodePtr msGML3TimeInstant(xmlNsPtr psNs, char *timeInstant); xmlNodePtr msGML3Point(xmlNsPtr psNs, const char *psSrsName, const char *id, double x, double y); #endif /* USE_LIBXML2 */ #endif mapserver-7.4.3/mapgraticule.c000066400000000000000000001321601357574274700164020ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: Graticule Renderer * Author: John Novak, Novacell Technologies (jnovak@novacell.com) * ********************************************************************** * Copyright (c) 2003, John Novak, Novacell Technologies * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #include "mapserver.h" #include #include "mapproject.h" /********************************************************************************************************************** * */ typedef enum { posBottom = 1, posTop, posLeft, posRight } msGraticulePosition; typedef enum { lpDefault = 0, lpDDMMSS = 1, lpDDMM, lpDD } msLabelProcessingType; void DefineAxis( int iTickCountTarget, double *Min, double *Max, double *Inc ); static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticulePosition ePosition ); static void _FormatLabel( layerObj *pLayer, shapeObj *pShape, double dDataToFormat ); int msGraticuleLayerInitItemInfo(layerObj *layer); #define MAPGRATICULE_ARC_SUBDIVISION_DEFAULT (256) #define MAPGRATICULE_ARC_MINIMUM (16) #define MAPGRATICULE_FORMAT_STRING_DEFAULT "%5.2g" #define MAPGRATICULE_FORMAT_STRING_DDMMSS "%3d %02d %02d" #define MAPGRATICULE_FORMAT_STRING_DDMM "%3d %02d" #define MAPGRATICULE_FORMAT_STRING_DD "%3d" /********************************************************************************************************************** * */ int msGraticuleLayerOpen(layerObj *layer) { graticuleObj *pInfo = layer->grid; if( pInfo == NULL ) return MS_FAILURE; pInfo->dincrementlatitude = 15.0; pInfo->dincrementlongitude = 15.0; pInfo->dwhichlatitude = -90.0; pInfo->dwhichlongitude = -180.0; pInfo->bvertical = 1; if( layer->numclasses == 0 ) msDebug( "GRID layer has no classes, nothing will be rendered.\n" ); if( layer->numclasses > 0 && layer->class[0]->numlabels > 0 ) pInfo->blabelaxes = 1; else pInfo->blabelaxes = 0; if( pInfo->labelformat == NULL ) { pInfo->labelformat = (char *) msSmallMalloc( strlen( MAPGRATICULE_FORMAT_STRING_DEFAULT ) + 1 ); pInfo->ilabeltype = (int) lpDefault; strcpy( pInfo->labelformat, MAPGRATICULE_FORMAT_STRING_DEFAULT ); } else if( strcmp( pInfo->labelformat, "DDMMSS" ) == 0 ) { msFree(pInfo->labelformat); pInfo->labelformat = (char *) msSmallMalloc( strlen( MAPGRATICULE_FORMAT_STRING_DDMMSS ) + 1 ); pInfo->ilabeltype = (int) lpDDMMSS; strcpy( pInfo->labelformat, MAPGRATICULE_FORMAT_STRING_DDMMSS ); } else if( strcmp( pInfo->labelformat, "DDMM" ) == 0 ) { msFree(pInfo->labelformat); pInfo->labelformat = (char *) msSmallMalloc( strlen( MAPGRATICULE_FORMAT_STRING_DDMM ) + 1 ); pInfo->ilabeltype = (int) lpDDMM; strcpy( pInfo->labelformat, MAPGRATICULE_FORMAT_STRING_DDMM ); } else if( strcmp( pInfo->labelformat, "DD" ) == 0 ) { msFree(pInfo->labelformat); pInfo->labelformat = (char *) msSmallMalloc( strlen( MAPGRATICULE_FORMAT_STRING_DD ) + 1 ); pInfo->ilabeltype = (int) lpDD; strcpy( pInfo->labelformat, MAPGRATICULE_FORMAT_STRING_DD ); } return MS_SUCCESS; } /********************************************************************************************************************** * Return MS_TRUE if layer is open, MS_FALSE otherwise. */ int msGraticuleLayerIsOpen(layerObj *layer) { if(layer->grid) return MS_TRUE; return MS_FALSE; } /********************************************************************************************************************** * */ int msGraticuleLayerClose(layerObj *layer) { return MS_SUCCESS; } /********************************************************************************************************************** * */ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { graticuleObj *pInfo = layer->grid; int iAxisTickCount = 0; rectObj rectMapCoordinates; if(msCheckParentPointer(layer->map,"map") == MS_FAILURE) return MS_FAILURE; pInfo->dstartlatitude = rect.miny; pInfo->dstartlongitude = rect.minx; pInfo->dendlatitude = rect.maxy; pInfo->dendlongitude = rect.maxx; pInfo->bvertical = 1; pInfo->extent = rect; if( pInfo->minincrement > 0.0 ) { pInfo->dincrementlongitude = pInfo->minincrement; pInfo->dincrementlatitude = pInfo->minincrement; } else if( pInfo->maxincrement > 0.0 ) { pInfo->dincrementlongitude = pInfo->maxincrement; pInfo->dincrementlatitude = pInfo->maxincrement; } else { pInfo->dincrementlongitude = 0; pInfo->dincrementlatitude = 0; } if( pInfo->maxarcs > 0 ) iAxisTickCount = (int) pInfo->maxarcs; else if( pInfo->minarcs > 0 ) iAxisTickCount = (int) pInfo->minarcs; DefineAxis( iAxisTickCount, &pInfo->dstartlongitude, &pInfo->dendlongitude, &pInfo->dincrementlongitude); DefineAxis( iAxisTickCount, &pInfo->dstartlatitude, &pInfo->dendlatitude, &pInfo->dincrementlatitude); pInfo->dwhichlatitude = pInfo->dstartlatitude; pInfo->dwhichlongitude = pInfo->dstartlongitude; if( pInfo->minincrement > 0.0 && pInfo->maxincrement > 0.0 && pInfo->minincrement == pInfo->maxincrement ) { pInfo->dincrementlongitude = pInfo->minincrement; pInfo->dincrementlatitude = pInfo->minincrement; } else if( pInfo->minincrement > 0.0 ) { pInfo->dincrementlongitude = pInfo->minincrement; pInfo->dincrementlatitude = pInfo->minincrement; } else if( pInfo->maxincrement > 0.0 ) { pInfo->dincrementlongitude = pInfo->maxincrement; pInfo->dincrementlatitude = pInfo->maxincrement; } /* * If using PROJ, project rect back into map system, and generate rect corner points in native system. * These lines will be used when generating labels to get correct placement at arc/rect edge intersections. */ rectMapCoordinates = layer->map->extent; #ifdef USE_PROJ layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection)); if( layer->project && strstr(layer->map->projection.args[0], "epsg:3857") && pj_is_latlong(layer->projection.proj) ) { if( rectMapCoordinates.minx < -20037508) rectMapCoordinates.minx = -20037508; if( rectMapCoordinates.maxx > 20037508 ) rectMapCoordinates.maxx = 20037508; } #endif msFree(pInfo->pboundinglines); pInfo->pboundinglines = (lineObj *) msSmallMalloc( sizeof( lineObj ) * 4 ); msFree(pInfo->pboundingpoints); pInfo->pboundingpoints = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 8 ); { /* * top */ pInfo->pboundinglines[0].numpoints = 2; pInfo->pboundinglines[0].point = &pInfo->pboundingpoints[0]; pInfo->pboundinglines[0].point[0].x = rectMapCoordinates.minx; pInfo->pboundinglines[0].point[0].y = rectMapCoordinates.maxy; pInfo->pboundinglines[0].point[1].x = rectMapCoordinates.maxx; pInfo->pboundinglines[0].point[1].y = rectMapCoordinates.maxy; #ifdef USE_PROJ if(layer->project) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[0]); #endif /* * bottom */ pInfo->pboundinglines[1].numpoints = 2; pInfo->pboundinglines[1].point = &pInfo->pboundingpoints[2]; pInfo->pboundinglines[1].point[0].x = rectMapCoordinates.minx; pInfo->pboundinglines[1].point[0].y = rectMapCoordinates.miny; pInfo->pboundinglines[1].point[1].x = rectMapCoordinates.maxx; pInfo->pboundinglines[1].point[1].y = rectMapCoordinates.miny; #ifdef USE_PROJ if(layer->project) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[1]); #endif /* * left */ pInfo->pboundinglines[2].numpoints = 2; pInfo->pboundinglines[2].point = &pInfo->pboundingpoints[4]; pInfo->pboundinglines[2].point[0].x = rectMapCoordinates.minx; pInfo->pboundinglines[2].point[0].y = rectMapCoordinates.miny; pInfo->pboundinglines[2].point[1].x = rectMapCoordinates.minx; pInfo->pboundinglines[2].point[1].y = rectMapCoordinates.maxy; #ifdef USE_PROJ if(layer->project) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[2]); #endif /* * right */ pInfo->pboundinglines[3].numpoints = 2; pInfo->pboundinglines[3].point = &pInfo->pboundingpoints[6]; pInfo->pboundinglines[3].point[0].x = rectMapCoordinates.maxx; pInfo->pboundinglines[3].point[0].y = rectMapCoordinates.miny; pInfo->pboundinglines[3].point[1].x = rectMapCoordinates.maxx; pInfo->pboundinglines[3].point[1].y = rectMapCoordinates.maxy; #ifdef USE_PROJ if(layer->project) msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[3]); #endif } return MS_SUCCESS; } /********************************************************************************************************************** * */ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape) { graticuleObj *pInfo = layer->grid; if( pInfo->minsubdivides <= 0.0 || pInfo->maxsubdivides <= 0.0 ) pInfo->minsubdivides = pInfo->maxsubdivides = MAPGRATICULE_ARC_SUBDIVISION_DEFAULT; shape->numlines = 1; shape->type = MS_SHAPE_LINE; shape->line = (lineObj *) msSmallMalloc(sizeof( lineObj )); shape->line->numpoints = (int) pInfo->maxsubdivides; shape->line->point = NULL; /* * Subdivide and draw current arc, rendering the arc labels first */ if( pInfo->bvertical ) { int iPointIndex; double dArcDelta = (pInfo->dendlatitude - pInfo->dstartlatitude) / (double) shape->line->numpoints; double dArcPosition = pInfo->dstartlatitude + dArcDelta; double dStartY, dDeltaX; switch( pInfo->ilabelstate ) { case 0: if(!pInfo->blabelaxes) { /* Bottom */ pInfo->ilabelstate++; msFreeShape(shape); return MS_SUCCESS; } dDeltaX = (pInfo->dwhichlongitude - pInfo->pboundinglines[1].point[0].x) / (pInfo->pboundinglines[1].point[1].x - pInfo->pboundinglines[1].point[0].x); if (dDeltaX < 0) dDeltaX=dDeltaX*-1; dStartY = (pInfo->pboundinglines[1].point[1].y - pInfo->pboundinglines[1].point[0].y) * dDeltaX + pInfo->pboundinglines[1].point[0].y; shape->line->numpoints = (int) 2; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 2 ); shape->line->point[0].x = pInfo->dwhichlongitude; shape->line->point[0].y = dStartY; shape->line->point[1].x = pInfo->dwhichlongitude; shape->line->point[1].y = dStartY + dArcDelta; _FormatLabel( layer, shape, shape->line->point[0].x ); if(_AdjustLabelPosition( layer, shape, posBottom ) != MS_SUCCESS) { msFreeShape(shape); pInfo->ilabelstate++; return MS_SUCCESS; } pInfo->ilabelstate++; return MS_SUCCESS; case 1: if(!pInfo->blabelaxes) { /* Top */ pInfo->ilabelstate++; msFreeShape(shape); return MS_SUCCESS; } dDeltaX = (pInfo->dwhichlongitude - pInfo->pboundinglines[0].point[0].x) / (pInfo->pboundinglines[0].point[1].x - pInfo->pboundinglines[0].point[0].x ); if (dDeltaX < 0) dDeltaX=dDeltaX*-1; dStartY = (pInfo->pboundinglines[0].point[1].y - pInfo->pboundinglines[0].point[0].y) * dDeltaX + pInfo->pboundinglines[0].point[1].y; shape->line->numpoints = (int) 2; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 2 ); shape->line->point[0].x = pInfo->dwhichlongitude; shape->line->point[0].y = dStartY - dArcDelta; shape->line->point[1].x = pInfo->dwhichlongitude; shape->line->point[1].y = dStartY; _FormatLabel( layer, shape, shape->line->point[0].x ); if(_AdjustLabelPosition( layer, shape, posTop ) != MS_SUCCESS) { msFreeShape(shape); pInfo->ilabelstate++; return MS_SUCCESS; } pInfo->ilabelstate++; return MS_SUCCESS; case 2: shape->line->numpoints = (int) shape->line->numpoints + 1; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * shape->line->numpoints ); shape->line->point[0].x = pInfo->dwhichlongitude; shape->line->point[0].y = pInfo->dstartlatitude; for( iPointIndex = 1; iPointIndex < shape->line->numpoints; iPointIndex++ ) { shape->line->point[iPointIndex].x = pInfo->dwhichlongitude; shape->line->point[iPointIndex].y = dArcPosition; dArcPosition += dArcDelta; } pInfo->ilabelstate = 0; pInfo->dwhichlongitude += pInfo->dincrementlongitude; break; default: pInfo->ilabelstate = 0; break; } } else { /*horizontal*/ int iPointIndex; double dArcDelta = (pInfo->dendlongitude - pInfo->dstartlongitude) / (double) shape->line->numpoints; double dArcPosition = pInfo->dstartlongitude + dArcDelta; double dStartX, dDeltaY; switch( pInfo->ilabelstate ) { case 0: if(!pInfo->blabelaxes) { /* Left side */ pInfo->ilabelstate++; msFreeShape(shape); return MS_SUCCESS; } dDeltaY = (pInfo->dwhichlatitude - pInfo->pboundinglines[2].point[0].y) / (pInfo->pboundinglines[2].point[1].y - pInfo->pboundinglines[2].point[0].y ); if (dDeltaY < 0) dDeltaY= dDeltaY*-1; dStartX = (pInfo->pboundinglines[2].point[1].x - pInfo->pboundinglines[2].point[0].x) * dDeltaY + pInfo->pboundinglines[2].point[0].x; shape->line->numpoints = (int) 2; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 2 ); shape->line->point[0].x = dStartX; shape->line->point[0].y = pInfo->dwhichlatitude; shape->line->point[1].x = dStartX + dArcDelta; shape->line->point[1].y = pInfo->dwhichlatitude; _FormatLabel( layer, shape, shape->line->point[0].y ); if(_AdjustLabelPosition( layer, shape, posLeft ) != MS_SUCCESS) { msFreeShape(shape); pInfo->ilabelstate++; return MS_SUCCESS; } pInfo->ilabelstate++; return MS_SUCCESS; case 1: if(!pInfo->blabelaxes) { /* Right side */ pInfo->ilabelstate++; msFreeShape(shape); return MS_SUCCESS; } dDeltaY = (pInfo->dwhichlatitude - pInfo->pboundinglines[3].point[0].y) / (pInfo->pboundinglines[3].point[1].y - pInfo->pboundinglines[3].point[0].y ); if (dDeltaY < 0) dDeltaY= dDeltaY*-1; dStartX = (pInfo->pboundinglines[3].point[1].x - pInfo->pboundinglines[3].point[0].x) * dDeltaY + pInfo->pboundinglines[3].point[0].x; shape->line->numpoints = (int) 2; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * 2 ); shape->line->point[0].x = dStartX - dArcDelta; shape->line->point[0].y = pInfo->dwhichlatitude; shape->line->point[1].x = dStartX; shape->line->point[1].y = pInfo->dwhichlatitude; _FormatLabel( layer, shape, shape->line->point[0].y ); if(_AdjustLabelPosition( layer, shape, posRight ) != MS_SUCCESS) { msFreeShape(shape); pInfo->ilabelstate++; return MS_SUCCESS; } pInfo->ilabelstate++; return MS_SUCCESS; case 2: shape->line->numpoints = (int) shape->line->numpoints + 1; shape->line->point = (pointObj *) msSmallMalloc( sizeof( pointObj ) * shape->line->numpoints ); shape->line->point[0].x = pInfo->dstartlongitude; shape->line->point[0].y = pInfo->dwhichlatitude; for(iPointIndex = 1; iPointIndex < shape->line->numpoints; iPointIndex++) { shape->line->point[iPointIndex].x = dArcPosition; shape->line->point[iPointIndex].y = pInfo->dwhichlatitude; dArcPosition += dArcDelta; } pInfo->ilabelstate = 0; pInfo->dwhichlatitude += pInfo->dincrementlatitude; break; default: pInfo->ilabelstate = 0; break; } } /* * Increment and move to next arc */ if( pInfo->bvertical && pInfo->dwhichlongitude > pInfo->dendlongitude ) { pInfo->dwhichlatitude = pInfo->dstartlatitude; pInfo->bvertical = 0; } if (pInfo->dwhichlatitude > pInfo->dendlatitude) { /* free the lineObj and pointObj that have been erroneously allocated beforehand */ msFreeShape(shape); return MS_DONE; } return MS_SUCCESS; } /********************************************************************************************************************** * */ int msGraticuleLayerGetItems(layerObj *layer) { char **ppItemName = (char **) msSmallMalloc( sizeof( char * ) ); *ppItemName = (char *) msSmallMalloc( 64 ); /* why is this necessary? */ strcpy( *ppItemName, "Graticule" ); layer->numitems = 1; layer->items = ppItemName; return MS_SUCCESS; } /********************************************************************************************************************** * */ int msGraticuleLayerInitItemInfo(layerObj *layer) { return MS_SUCCESS; } /********************************************************************************************************************** * */ void msGraticuleLayerFreeItemInfo(layerObj *layer) { return; } /********************************************************************************************************************** * */ int msGraticuleLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { return MS_FAILURE; } /********************************************************************************************************************** * */ int msGraticuleLayerGetExtent(layerObj *layer, rectObj *extent) { graticuleObj *pInfo = layer->grid; if(pInfo) { *extent = pInfo->extent; return MS_SUCCESS; } return MS_FAILURE; } /********************************************************************************************************************** * */ int msGraticuleLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { return MS_SUCCESS; } /************************************************************************/ /* msGraticuleLayerFreeIntersectionPoints */ /* */ /* Free intersection object. */ /************************************************************************/ void msGraticuleLayerFreeIntersectionPoints( graticuleIntersectionObj *psValue) { int i=0; if (psValue) { for (i=0; inTop; i++) msFree(psValue->papszTopLabels[i]); msFree(psValue->papszTopLabels); msFree(psValue->pasTop); for (i=0; inBottom; i++) msFree(psValue->papszBottomLabels[i]); msFree(psValue->papszBottomLabels); msFree(psValue->pasBottom); for (i=0; inLeft; i++) msFree(psValue->papszLeftLabels[i]); msFree(psValue->papszLeftLabels); msFree(psValue->pasLeft); for (i=0; inRight; i++) msFree(psValue->papszRightLabels[i]); msFree(psValue->papszRightLabels); msFree(psValue->pasRight); msFree(psValue); } } /************************************************************************/ /* msGraticuleLayerInitIntersectionPoints */ /* */ /* init intersection object. */ /************************************************************************/ static void msGraticuleLayerInitIntersectionPoints( graticuleIntersectionObj *psValue) { if (psValue) { psValue->nTop = 0; psValue->pasTop = NULL; psValue->papszTopLabels = NULL; psValue->nBottom = 0; psValue->pasBottom = NULL; psValue->papszBottomLabels = NULL; psValue->nLeft = 0; psValue->pasLeft = NULL; psValue->papszLeftLabels = NULL; psValue->nRight = 0; psValue->pasRight = NULL; psValue->papszRightLabels = NULL; } } /************************************************************************/ /* msGraticuleLayerGetIntersectionPoints */ /* */ /* Utility function thar returns all intersection positions and */ /* labels (4 sides of the map) for a grid layer. */ /************************************************************************/ graticuleIntersectionObj *msGraticuleLayerGetIntersectionPoints(mapObj *map, layerObj *layer) { shapeObj shapegrid, tmpshape; rectObj searchrect; int status; pointObj oFirstPoint; pointObj oLastPoint; lineObj oLineObj; rectObj cliprect; graticuleObj *pInfo = NULL; double dfTmp; graticuleIntersectionObj *psValues = NULL; int i=0; if (layer->connectiontype != MS_GRATICULE) return NULL; pInfo = layer->grid; /*set cellsize if bnot already set*/ if (map->cellsize == 0) map->cellsize = msAdjustExtent(&(map->extent),map->width,map->height); psValues = (graticuleIntersectionObj *)msSmallMalloc(sizeof(graticuleIntersectionObj)); msGraticuleLayerInitIntersectionPoints(psValues); if(layer->transform == MS_TRUE) searchrect = map->extent; else { searchrect.minx = searchrect.miny = 0; searchrect.maxx = map->width-1; searchrect.maxy = map->height-1; } #ifdef USE_PROJ if((map->projection.numargs > 0) && (layer->projection.numargs > 0)) msProjectRect(&map->projection, &layer->projection, &searchrect); /* project the searchrect to source coords */ #endif status = msLayerOpen(layer); if(status != MS_SUCCESS) return NULL; status = msLayerWhichShapes(layer, searchrect, MS_FALSE); if(status == MS_DONE) { /* no overlap */ msLayerClose(layer); return NULL; } else if(status != MS_SUCCESS) { msLayerClose(layer); return NULL; } /* step through the target shapes */ msInitShape(&shapegrid); cliprect.minx = map->extent.minx- map->cellsize; cliprect.miny = map->extent.miny- map->cellsize; cliprect.maxx = map->extent.maxx + map->cellsize; cliprect.maxy = map->extent.maxy + map->cellsize; /* clip using the layer projection */ /* msProjectRect(&map->projection , &layer->projection, &cliprect); */ while((status = msLayerNextShape(layer, &shapegrid)) == MS_SUCCESS) { /*don't really need a class here*/ /* shapegrid.classindex = msShapeGetClass(layer, &shapegrid, map->scaledenom, NULL, 0); if((shapegrid.classindex == -1) || (layer->class[shapegrid.classindex]->status == MS_OFF)) { msFreeShape(&shapegrid); continue; } */ msInitShape(&tmpshape); msCopyShape(&shapegrid, &tmpshape); /* status = msDrawShape(map, layer, &tmpshape, image, -1); */ if(layer->project) msProjectShape(&layer->projection, &map->projection, &shapegrid); msClipPolylineRect(&shapegrid, cliprect); msTransformShapeToPixelRound(&shapegrid, map->extent, map->cellsize); if(shapegrid.numlines <= 0 || shapegrid.line[0].numpoints < 2) { /* once clipped the shape didn't need to be drawn */ msFreeShape(&shapegrid); msFreeShape(&tmpshape); continue; } if(shapegrid.numlines >= 1 && shapegrid.line[0].numpoints >=2) { /* && shapegrid.text) */ int iTmpLine = 0; int nNumPoints = 0; /*grid code seems to retunr lines that can double cross the extenst??*/ /*creating a more than one clipped shape. Take the shape that has the most points, which should be the most likley to be correct*/ if (shapegrid.numlines > 1) { for (i=0; i nNumPoints) { nNumPoints = shapegrid.line[i].numpoints; iTmpLine = i; } } } /* get the first and last point*/ oFirstPoint.x = shapegrid.line[iTmpLine].point[0].x; oFirstPoint.y = shapegrid.line[iTmpLine].point[0].y; oLineObj = shapegrid.line[iTmpLine]; oLastPoint.x = oLineObj.point[oLineObj.numpoints-1].x; oLastPoint.y = oLineObj.point[oLineObj.numpoints-1].y; if ( pInfo->bvertical) { /*vertical*/ /*SHAPES ARE DRAWN FROM BOTTOM TO TOP.*/ /*Normally lines are drawn FROM BOTTOM TO TOP but not always for some reason, so make sure that firstpoint < lastpoint in y, We are in pixel coordinates so y increases as we we go down*/ if (oFirstPoint.y < oLastPoint.y) { dfTmp = oFirstPoint.x; oFirstPoint.x = oLastPoint.x; oLastPoint.x = dfTmp; dfTmp = oFirstPoint.y; oFirstPoint.y = oLastPoint.y; oLastPoint.y = dfTmp; } /*first point should cross the BOTTOM base where y== map->height*/ if (abs ((int)oFirstPoint.y - map->height) <=1) { char *pszLabel=NULL; oFirstPoint.y = map->height; /*validate point is in map width/height*/ if (oFirstPoint.x < 0 || oFirstPoint.x > map->width) continue; /*validate point is in map width/height*/ if (oLastPoint.x < 0 || oLastPoint.x > map->width) continue; if (shapegrid.text) pszLabel = msStrdup(shapegrid.text); else { _FormatLabel(layer, &tmpshape, tmpshape.line[0].point[tmpshape.line[0].numpoints-1].x ); if (tmpshape.text) pszLabel = msStrdup(tmpshape.text); else pszLabel = msStrdup("unknown"); } /*validate that the value is not already in the array*/ if ( psValues->nBottom > 0) { /* if (psValues->pasBottom[psValues->nBottom-1].x == oFirstPoint.x) continue; */ for (i=0; inBottom; i++) { if (psValues->pasBottom[i].x == oFirstPoint.x) break; } if (i < psValues->nBottom) { msFree(pszLabel); continue; } } if (psValues->pasBottom == NULL) { psValues->pasBottom = (pointObj *)msSmallMalloc(sizeof(pointObj)); psValues->papszBottomLabels = (char **)msSmallMalloc(sizeof(char *)); psValues->nBottom = 1; } else { psValues->nBottom++; psValues->pasBottom = (pointObj *)msSmallRealloc(psValues->pasBottom, sizeof(pointObj)*psValues->nBottom); psValues->papszBottomLabels = (char **)msSmallRealloc(psValues->papszBottomLabels, sizeof(char *)*psValues->nBottom); } psValues->pasBottom[psValues->nBottom-1].x = oFirstPoint.x; psValues->pasBottom[psValues->nBottom-1].y = oFirstPoint.y; psValues->papszBottomLabels[psValues->nBottom-1] = pszLabel; } /*first point should cross the TOP base where y==0*/ if (abs((int)oLastPoint.y) <=1) { char *pszLabel=NULL; oLastPoint.y = 0; /*validate point is in map width/height*/ if (oLastPoint.x < 0 || oLastPoint.x > map->width) continue; if (shapegrid.text) pszLabel = msStrdup(shapegrid.text); else { _FormatLabel(layer, &tmpshape, tmpshape.line[0].point[tmpshape.line[0].numpoints-1].x ); if (tmpshape.text) pszLabel = msStrdup(tmpshape.text); else pszLabel = msStrdup("unknown"); } /*validate if same value is not already there*/ if ( psValues->nTop > 0) { /* if (psValues->pasTop[psValues->nTop-1].x == oLastPoint.x) continue; */ for (i=0; inTop; i++) { if (psValues->pasTop[i].x == oLastPoint.x || strcasecmp(pszLabel, psValues->papszTopLabels[i]) == 0) break; } if (i < psValues->nTop) { msFree(pszLabel); continue; } } if (psValues->pasTop == NULL) { psValues->pasTop = (pointObj *)msSmallMalloc(sizeof(pointObj)); psValues->papszTopLabels = (char **)msSmallMalloc(sizeof(char *)); psValues->nTop = 1; } else { psValues->nTop++; psValues->pasTop = (pointObj *)msSmallRealloc(psValues->pasTop, sizeof(pointObj)*psValues->nTop); psValues->papszTopLabels = (char **)msSmallRealloc(psValues->papszTopLabels, sizeof(char *)*psValues->nTop); } psValues->pasTop[psValues->nTop-1].x = oLastPoint.x; psValues->pasTop[psValues->nTop-1].y = oLastPoint.y; psValues->papszTopLabels[psValues->nTop-1] = pszLabel; } } else { /*horzontal*/ /*Normally lines are drawn from left to right but not always for some reason, so make sure that firstpoint < lastpoint in x*/ if (oFirstPoint.x > oLastPoint.x) { dfTmp = oFirstPoint.x; oFirstPoint.x = oLastPoint.x; oLastPoint.x = dfTmp; dfTmp = oFirstPoint.y; oFirstPoint.y = oLastPoint.y; oLastPoint.y = dfTmp; } /*first point should cross the LEFT base where x=0 axis*/ if (abs((int)oFirstPoint.x) <=1) { char *pszLabel=NULL; oFirstPoint.x = 0; /*validate point is in map width/height*/ if (oFirstPoint.y < 0 || oFirstPoint.y > map->height) continue; if (shapegrid.text) pszLabel = msStrdup(shapegrid.text); else { _FormatLabel(layer, &tmpshape, tmpshape.line[0].point[tmpshape.line[0].numpoints-1].y ); if (tmpshape.text) pszLabel = msStrdup(tmpshape.text); else pszLabel = msStrdup("unknown"); } /*validate that the previous value is not the same*/ if ( psValues->nLeft > 0) { /* if (psValues->pasLeft[psValues->nLeft-1].y == oFirstPoint.y) continue; */ for (i=0; inLeft; i++) { if (psValues->pasLeft[i].y == oFirstPoint.y) break; } if (i < psValues->nLeft) { msFree(pszLabel); continue; } } if (psValues->pasLeft == NULL) { psValues->pasLeft = (pointObj *)msSmallMalloc(sizeof(pointObj)); psValues->papszLeftLabels = (char **)msSmallMalloc(sizeof(char *)); psValues->nLeft = 1; } else { psValues->nLeft++; psValues->pasLeft = (pointObj *)msSmallRealloc(psValues->pasLeft, sizeof(pointObj)*psValues->nLeft); psValues->papszLeftLabels = (char **)msSmallRealloc(psValues->papszLeftLabels, sizeof(char *)*psValues->nLeft); } psValues->pasLeft[psValues->nLeft-1].x = oFirstPoint.x; psValues->pasLeft[psValues->nLeft-1].y = oFirstPoint.y; psValues->papszLeftLabels[psValues->nLeft-1] = pszLabel; /* takes ownership of allocated pszLabel */ } /*first point should cross the RIGHT base where x=map=>width axis*/ if (abs((int)oLastPoint.x - map->width) <=1) { char *pszLabel=NULL; oLastPoint.x = map->width; /*validate point is in map width/height*/ if (oLastPoint.y < 0 || oLastPoint.y > map->height) continue; if (shapegrid.text) pszLabel = msStrdup(shapegrid.text); else { _FormatLabel(layer, &tmpshape, tmpshape.line[0].point[tmpshape.line[0].numpoints-1].y ); if (tmpshape.text) pszLabel = msStrdup(tmpshape.text); else pszLabel = msStrdup("unknown"); } /*validate that the previous value is not the same*/ if ( psValues->nRight > 0) { /* if (psValues->pasRight[psValues->nRight-1].y == oLastPoint.y) continue; */ for (i=0; inRight; i++) { if (psValues->pasRight[i].y == oLastPoint.y) break; } if (i < psValues->nRight) { msFree(pszLabel); continue; } } if (psValues->pasRight == NULL) { psValues->pasRight = (pointObj *)msSmallMalloc(sizeof(pointObj)); psValues->papszRightLabels = (char **)msSmallMalloc(sizeof(char *)); psValues->nRight = 1; } else { psValues->nRight++; psValues->pasRight = (pointObj *)msSmallRealloc(psValues->pasRight, sizeof(pointObj)*psValues->nRight); psValues->papszRightLabels = (char **)msSmallRealloc(psValues->papszRightLabels, sizeof(char *)*psValues->nRight); } psValues->pasRight[psValues->nRight-1].x = oLastPoint.x; psValues->pasRight[psValues->nRight-1].y = oLastPoint.y; psValues->papszRightLabels[psValues->nRight-1] = pszLabel; } } msFreeShape(&shapegrid); msFreeShape(&tmpshape); } msInitShape(&shapegrid); } msLayerClose(layer); return psValues; } /********************************************************************************************************************** * */ int msGraticuleLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msGraticuleLayerInitItemInfo; /* should use defaults for item info functions */ layer->vtable->LayerFreeItemInfo = msGraticuleLayerFreeItemInfo; layer->vtable->LayerOpen = msGraticuleLayerOpen; layer->vtable->LayerIsOpen = msGraticuleLayerIsOpen; layer->vtable->LayerWhichShapes = msGraticuleLayerWhichShapes; layer->vtable->LayerNextShape = msGraticuleLayerNextShape; /* layer->vtable->LayerResultsGetShape, use default */ layer->vtable->LayerGetShape = msGraticuleLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerClose = msGraticuleLayerClose; layer->vtable->LayerGetItems = msGraticuleLayerGetItems; layer->vtable->LayerGetExtent = msGraticuleLayerGetExtent; layer->vtable->LayerGetAutoStyle = msGraticuleLayerGetAutoStyle; /* layer->vtable->LayerCloseConnection, use default */; layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } /********************************************************************************************************************** * */ static void _FormatLabel( layerObj *pLayer, shapeObj *pShape, double dDataToFormat ) { graticuleObj *pInfo = pLayer->grid; char cBuffer[32]; int iDegrees, iMinutes; switch( pInfo->ilabeltype ) { case lpDDMMSS: iDegrees = (int) dDataToFormat; dDataToFormat = fabs( dDataToFormat - (double) iDegrees ); iMinutes = (int) (dDataToFormat * 60.0); dDataToFormat = dDataToFormat - (((double) iMinutes) / 60.0); sprintf( cBuffer, pInfo->labelformat, iDegrees, iMinutes, (int) (dDataToFormat * 3600.0) ); break; case lpDDMM: iDegrees = (int) dDataToFormat; dDataToFormat = fabs( dDataToFormat - (double) iDegrees ); sprintf( cBuffer, pInfo->labelformat, iDegrees, (int) (dDataToFormat * 60.0) ); break; case lpDD: iDegrees = (int) dDataToFormat; sprintf( cBuffer, pInfo->labelformat, iDegrees); break; case lpDefault: default: sprintf( cBuffer, pInfo->labelformat, dDataToFormat ); } pShape->text = msStrdup( cBuffer ); } /********************************************************************************************************************** * * Move label position into display area by adjusting underlying shape line. */ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticulePosition ePosition ) { graticuleObj *pInfo = pLayer->grid; rectObj rectLabel; pointObj ptPoint; double size = -1; char *labeltxt; if( pInfo == NULL || pShape == NULL ) { msSetError(MS_MISCERR, "Assertion failed: Null shape or non-configured grid!, ", "_AdjustLabelPosition()"); return MS_FAILURE; } assert(pLayer->class[0]->numlabels >= 1); if(msCheckParentPointer(pLayer->map,"map")==MS_FAILURE) return MS_FAILURE; ptPoint = pShape->line->point[0]; #ifdef USE_PROJ if(pLayer->project) { msProjectShape( &pLayer->projection, &pLayer->map->projection, pShape ); /* Poor man detection of reprojection failure */ if( pj_is_latlong(pLayer->projection.proj) != pj_is_latlong(pLayer->map->projection.proj) ) { if( ptPoint.x == pShape->line->point[0].x && ptPoint.y == pShape->line->point[0].y ) { return MS_FAILURE; } } } #endif if(pLayer->transform) { msTransformShapeToPixelRound(pShape, pLayer->map->extent, pLayer->map->cellsize); } size = pLayer->class[0]->labels[0]->size; /* TODO someday: adjust minsize/maxsize/resolution*/ /* We only use the first label as there's no use (yet) in defining multiple lables for GRID layers, as the only label to represent is the longitude or latitude */ labeltxt = msShapeGetLabelAnnotation(pLayer, pShape, pLayer->class[0]->labels[0]); assert(labeltxt); if(msGetStringSize(pLayer->map, pLayer->class[0]->labels[0], size, labeltxt, &rectLabel) != MS_SUCCESS) { free(labeltxt); return MS_FAILURE; /* msSetError already called */ } free(labeltxt); switch( ePosition ) { case posBottom: pShape->line->point[1].y = pLayer->map->height; pShape->line->point[0].y = pLayer->map->height - (fabs(rectLabel.maxy - rectLabel.miny) * 2 + 5); break; case posTop: pShape->line->point[1].y = 0; pShape->line->point[0].y = fabs(rectLabel.maxy - rectLabel.miny) * 2 + 5; break; case posLeft: pShape->line->point[0].x = 0; pShape->line->point[1].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5; break; case posRight: pShape->line->point[1].x = pLayer->map->width; pShape->line->point[0].x = pLayer->map->width - (fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5); break; } if(pLayer->transform) msTransformPixelToShape( pShape, pLayer->map->extent, pLayer->map->cellsize ); #ifdef USE_PROJ if(pLayer->project) { /* Clamp coordinates into the validity area of the projection, in the */ /* particular case of EPSG:3857 (WebMercator) to longlat reprojection */ if( strstr(pLayer->map->projection.args[0], "epsg:3857") && pj_is_latlong(pLayer->projection.proj) ) { if( !pLayer->map->projection.gt.need_geotransform && ePosition == posLeft && pShape->line->point[0].x < -20037508) { pShape->line->point[1].x = -20037508 + (pShape->line->point[1].x - pShape->line->point[0].x); pShape->line->point[0].x = -20037508; } else if( pLayer->map->projection.gt.need_geotransform && ePosition == posLeft && pLayer->map->projection.gt.geotransform[0] + pShape->line->point[0].x * pLayer->map->projection.gt.geotransform[1] + pShape->line->point[0].y * pLayer->map->projection.gt.geotransform[2] < -20037508) { double y_tmp; double width = pShape->line->point[1].x - pShape->line->point[0].x; y_tmp = pLayer->map->projection.gt.geotransform[3] + pShape->line->point[0].x * pLayer->map->projection.gt.geotransform[4] + pShape->line->point[0].y * pLayer->map->projection.gt.geotransform[5]; pShape->line->point[0].x = pLayer->map->projection.gt.invgeotransform[0] + -20037508 * pLayer->map->projection.gt.invgeotransform[1] + y_tmp * pLayer->map->projection.gt.invgeotransform[2]; pShape->line->point[1].x = pShape->line->point[0].x + width; } if( !pLayer->map->projection.gt.need_geotransform && ePosition == posRight && pShape->line->point[1].x > 20037508) { pShape->line->point[0].x = 20037508 - (pShape->line->point[1].x - pShape->line->point[0].x); pShape->line->point[1].x = 20037508; } else if( pLayer->map->projection.gt.need_geotransform && ePosition == posRight && pLayer->map->projection.gt.geotransform[0] + pShape->line->point[1].x * pLayer->map->projection.gt.geotransform[1] + pShape->line->point[1].y * pLayer->map->projection.gt.geotransform[2] > 20037508) { double y_tmp; double width = pShape->line->point[1].x - pShape->line->point[0].x; y_tmp = pLayer->map->projection.gt.geotransform[3] + pShape->line->point[1].x * pLayer->map->projection.gt.geotransform[4] + pShape->line->point[1].y * pLayer->map->projection.gt.geotransform[5]; pShape->line->point[1].x = pLayer->map->projection.gt.invgeotransform[0] + 20037508 * pLayer->map->projection.gt.invgeotransform[1] + y_tmp * pLayer->map->projection.gt.invgeotransform[2]; pShape->line->point[0].x = pShape->line->point[1].x - width; } } msProjectShape( &pLayer->map->projection, &pLayer->projection, pShape ); } #endif switch( ePosition ) { case posBottom: case posTop: pShape->line->point[1].x = ptPoint.x; pShape->line->point[0].x = ptPoint.x; break; case posLeft: case posRight: pShape->line->point[1].y = ptPoint.y; pShape->line->point[0].y = ptPoint.y; break; } return MS_SUCCESS; } /********************************************************************************************************************** ********************************************************************************************************************** * DefineAxes - Copyright (c) 2000, Michael P.D. Bramley. * * Permission is granted to use this code without restriction as long as * this copyright notice appears in all source files. * * Minor tweaks to incrment calculations - jnovak */ void DefineAxis( int iTickCountTarget, double *Min, double *Max, double *Inc ) { /* define local variables... */ double Test_inc, /* candidate increment value */ Test_min, /* minimum scale value */ Test_max, /* maximum scale value */ Range = *Max - *Min ; /* range of data */ int i = 0 ; /* counter */ /* don't create problems -- solve them */ if( Range < 0 ) { *Inc = 0 ; return ; } /* handle special case of repeated values */ else if( Range == 0) { *Min = ceil(*Max) - 1 ; *Max = *Min + 1 ; *Inc = 1 ; return ; } /* compute candidate for increment */ Test_inc = pow( 10.0, ceil( log10( Range/10 ) ) ) ; if(*Inc > 0 && ( Test_inc < *Inc || Test_inc > *Inc )) Test_inc = *Inc; /* establish maximum scale value... */ Test_max = ( (long)(*Max / Test_inc)) * Test_inc ; if( Test_max < *Max ) Test_max += Test_inc ; /* establish minimum scale value... */ Test_min = Test_max ; do { ++i ; Test_min -= Test_inc ; } while( Test_min > *Min ) ; /* subtracting small values can screw up the scale limits, */ /* eg: if DefineAxis is called with (min,max)=(0.01, 0.1), */ /* then the calculated scale is 1.0408E17 TO 0.05 BY 0.01. */ /* the following if statment corrects for this... */ /* if(fabs(Test_min) < 1E-10) */ /* Test_min = 0 ; */ /* adjust for too few tick marks */ if(iTickCountTarget <= 0) iTickCountTarget = MAPGRATICULE_ARC_MINIMUM; while(i < iTickCountTarget) { Test_inc /= 2 ; i *= 2 ; } if(i < 6 && 0) { Test_inc /= 2 ; if((Test_min + Test_inc) <= *Min) Test_min += Test_inc ; if((Test_max - Test_inc) >= *Max) Test_max -= Test_inc ; } /* pass back axis definition to caller */ *Min = Test_min; *Max = Test_max; *Inc = Test_inc; } /********************************************************************************************************************** **********************************************************************************************************************/ mapserver-7.4.3/maphash.c000066400000000000000000000144031357574274700153450ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implement hashTableObj class. * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include "mapserver.h" #include "maphash.h" static unsigned hash(const char *key) { unsigned hashval; for(hashval=0; *key!='\0'; key++) hashval = tolower(*key) + 31 * hashval; return(hashval % MS_HASHSIZE); } hashTableObj *msCreateHashTable() { int i; hashTableObj *table; table = (hashTableObj *) msSmallMalloc(sizeof(hashTableObj)); table->items = (struct hashObj **) msSmallMalloc(sizeof(struct hashObj *)*MS_HASHSIZE); for (i=0; iitems[i] = NULL; table->numitems = 0; return table; } int initHashTable( hashTableObj *table ) { int i; table->items = (struct hashObj **) malloc(sizeof(struct hashObj *)*MS_HASHSIZE); MS_CHECK_ALLOC(table->items, sizeof(struct hashObj *)*MS_HASHSIZE, MS_FAILURE); for (i=0; iitems[i] = NULL; table->numitems = 0; return MS_SUCCESS; } void msFreeHashTable( hashTableObj *table ) { if( table != NULL ) { msFreeHashItems(table); free(table); table = NULL; } } int msHashIsEmpty( hashTableObj *table ) { if (table->numitems == 0 ) return MS_TRUE; else return MS_FALSE; } void msFreeHashItems( hashTableObj *table ) { int i; struct hashObj *tp=NULL; struct hashObj *prev_tp=NULL; if (table) { if(table->items) { for (i=0; iitems[i] != NULL) { for (tp=table->items[i]; tp!=NULL; prev_tp=tp,tp=tp->next,free(prev_tp)) { msFree(tp->key); msFree(tp->data); } } } free(table->items); table->items = NULL; } else { msSetError(MS_HASHERR, "No items allocated.", "msFreeHashItems()"); } } else { msSetError(MS_HASHERR, "Can't free NULL table", "msFreeHashItems()"); } } struct hashObj *msInsertHashTable(hashTableObj *table, const char *key, const char *value) { struct hashObj *tp; unsigned hashval; if (!table || !key || !value) { msSetError(MS_HASHERR, "Invalid hash table or key", "msInsertHashTable"); return NULL; } for (tp=table->items[hash(key)]; tp!=NULL; tp=tp->next) if(strcasecmp(key, tp->key) == 0) break; if (tp == NULL) { /* not found */ tp = (struct hashObj *) malloc(sizeof(*tp)); MS_CHECK_ALLOC(tp, sizeof(*tp), NULL); tp->key = msStrdup(key); hashval = hash(key); tp->next = table->items[hashval]; table->items[hashval] = tp; table->numitems++; } else { free(tp->data); } if ((tp->data = msStrdup(value)) == NULL) return NULL; return tp; } const char *msLookupHashTable(hashTableObj *table, const char *key) { struct hashObj *tp; if (!table || !key) { return(NULL); } for (tp=table->items[hash(key)]; tp!=NULL; tp=tp->next) if (strcasecmp(key, tp->key) == 0) return(tp->data); return NULL; } int msRemoveHashTable(hashTableObj *table, const char *key) { struct hashObj *tp; struct hashObj *prev_tp=NULL; int status = MS_FAILURE; if (!table || !key) { msSetError(MS_HASHERR, "No hash table", "msRemoveHashTable"); return MS_FAILURE; } tp=table->items[hash(key)]; if (!tp) { msSetError(MS_HASHERR, "No such hash entry", "msRemoveHashTable"); return MS_FAILURE; } prev_tp = NULL; while (tp != NULL) { if (strcasecmp(key, tp->key) == 0) { status = MS_SUCCESS; if (prev_tp) { prev_tp->next = tp->next; msFree(tp->key); msFree(tp->data); free(tp); break; } else { table->items[hash(key)] = tp->next; msFree(tp->key); msFree(tp->data); free(tp); break; } } prev_tp = tp; tp = tp->next; } if (status == MS_SUCCESS) table->numitems--; return status; } const char *msFirstKeyFromHashTable( hashTableObj *table ) { int hash_index; if (!table) { msSetError(MS_HASHERR, "No hash table", "msFirstKeyFromHashTable"); return NULL; } for (hash_index = 0; hash_index < MS_HASHSIZE; hash_index++ ) { if (table->items[hash_index] != NULL ) return table->items[hash_index]->key; } return NULL; } const char *msNextKeyFromHashTable( hashTableObj *table, const char *lastKey ) { int hash_index; struct hashObj *link; if (!table) { msSetError(MS_HASHERR, "No hash table", "msNextKeyFromHashTable"); return NULL; } if ( lastKey == NULL ) return msFirstKeyFromHashTable( table ); hash_index = hash(lastKey); for ( link = table->items[hash_index]; link != NULL && strcasecmp(lastKey,link->key) != 0; link = link->next ) {} if ( link != NULL && link->next != NULL ) return link->next->key; while ( ++hash_index < MS_HASHSIZE ) { if ( table->items[hash_index] != NULL ) return table->items[hash_index]->key; } return NULL; } mapserver-7.4.3/maphash.h000066400000000000000000000116601357574274700153540ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations for the hashTableObj and related stuff. * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPHASH__H #define MAPHASH__H #ifdef __cplusplus extern "C" { #endif #if defined(_WIN32) && !defined(__CYGWIN__) # define MS_DLL_EXPORT __declspec(dllexport) #else #define MS_DLL_EXPORT #endif #define MS_HASHSIZE 41 /* ========================================================================= * Structs * ========================================================================= */ #ifndef SWIG struct hashObj { struct hashObj *next; /* pointer to next item */ char *key; /* string key that is hashed */ char *data; /* string stored in this item */ }; #endif /*SWIG*/ typedef struct { #ifndef SWIG struct hashObj **items; /* the hash table */ #endif #ifdef SWIG %immutable; #endif /*SWIG*/ int numitems; /* number of items */ #ifdef SWIG %mutable; #endif /*SWIG*/ } hashTableObj; /* ========================================================================= * Functions * ========================================================================= */ #ifndef SWIG /* msCreateHashTable - create a hash table * ARGS: * None * RETURNS: * New hash table */ MS_DLL_EXPORT hashTableObj *msCreateHashTable( void ); /* For use in mapfile.c with hashTableObj structure members */ MS_DLL_EXPORT int initHashTable( hashTableObj *table ); /* msFreeHashTable - free allocated memory * ARGS: * table - target hash table * RETURNS: * None */ MS_DLL_EXPORT void msFreeHashTable( hashTableObj *table ); /* Free only the items for hashTableObj structure members (metadata, &c) */ MS_DLL_EXPORT void msFreeHashItems( hashTableObj *table ); /* msInsertHashTable - insert new item * ARGS: * table - the target hash table * key - key string for new item * value - data string for new item * RETURNS: * pointer to the new item or NULL * EXCEPTIONS: * raise MS_HASHERR on failure */ MS_DLL_EXPORT struct hashObj *msInsertHashTable( hashTableObj *table, const char *key, const char *value ); /* msLookupHashTable - get the value of an item by its key * ARGS: * table - the target hash table * key - key string of item * RETURNS: * string value of item */ MS_DLL_EXPORT const char *msLookupHashTable( hashTableObj *table, const char *key); /* msRemoveHashTable - remove item from table at key * ARGS: * table - target hash table * key - key string * RETURNS: * MS_SUCCESS or MS_FAILURE */ MS_DLL_EXPORT int msRemoveHashTable( hashTableObj *table, const char *key); /* msFirstKeyFromHashTable - get key of first item * ARGS: * table - target hash table * RETURNS: * first key as a string */ MS_DLL_EXPORT const char *msFirstKeyFromHashTable( hashTableObj *table ); /* msNextKeyFromHashTable - get next key * ARGS: * table - target hash table * prevkey - the previous key * RETURNS: * the key of the item of following prevkey as a string */ MS_DLL_EXPORT const char *msNextKeyFromHashTable( hashTableObj *table, const char *prevkey ); /* msHashIsEmpty - get next key * ARGS: * table - target hash table * RETURNS: * MS_TRUE if the table is empty and MS_FALSE if the table has items */ MS_DLL_EXPORT int msHashIsEmpty( hashTableObj* table ); #endif /*SWIG*/ #ifdef __cplusplus } #endif #endif /* MAPHASH__H */ mapserver-7.4.3/maphttp.c000066400000000000000000001007061357574274700154030ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: Utility functions to access files via HTTP (requires libcurl) * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2001-2003, Daniel Morissette, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ /* For now this code is enabled only when WMS/WFS client is enabled. * This should be changed to a test on the presence of libcurl which * is really what the real dependency is. */ #include "mapserver-config.h" #if defined(USE_CURL) #include "mapserver.h" #include "maphttp.h" #include "maperror.h" #include "mapthread.h" #include "mapows.h" #include #ifndef _WIN32 #include #include #endif /* * Note: This code uses libcurl to access remote files via the HTTP protocol. * Requires libcurl v 7.10 or more recent. * See http://curl.haxx.se/libcurl/c/ for the lib source code and docs. */ #include /********************************************************************** * msHTTPInit() * * This function is called to init libcurl before the first HTTP request * in this process is executed. * On further calls (when gbCurlInitialized = MS_TRUE) it simply doest nothing. * * Returns MS_SUCCESS/MS_FAILURE. * * msHTTPCleanup() will have to be called in msCleanup() when this process * exits. **********************************************************************/ static int gbCurlInitialized = MS_FALSE; int msHTTPInit() { /* curl_global_init() should only be called once (no matter how * many threads or libcurl sessions that'll be used) by every * application that uses libcurl. */ msAcquireLock(TLOCK_OWS); if (!gbCurlInitialized && curl_global_init(CURL_GLOBAL_ALL) != 0) { msReleaseLock(TLOCK_OWS); msSetError(MS_HTTPERR, "Libcurl initialization failed.", "msHTTPInit()"); return MS_FAILURE; } gbCurlInitialized = MS_TRUE; msReleaseLock(TLOCK_OWS); return MS_SUCCESS; } /********************************************************************** * msHTTPCleanup() * **********************************************************************/ void msHTTPCleanup() { msAcquireLock(TLOCK_OWS); if (gbCurlInitialized) curl_global_cleanup(); gbCurlInitialized = MS_FALSE; msReleaseLock(TLOCK_OWS); } /********************************************************************** * msHTTPInitRequestObj() * * Should be called on a new array of httpRequestObj to initialize them * for use with msHTTPExecuteRequest(), etc. * **********************************************************************/ void msHTTPInitRequestObj(httpRequestObj *pasReqInfo, int numRequests) { int i; for(i=0; idebug) { msDebug("msHTTPWriteFct(id=%d, %d bytes)\n", psReq->nLayerId, (int)(size*nmemb)); } if(psReq->nMaxBytes > 0 && (psReq->result_size + size*nmemb) > psReq->nMaxBytes) { msSetError(MS_HTTPERR, "Requested transfer larger than configured maximum %d.", "msHTTPWriteFct()", psReq->nMaxBytes ); return -1; } /* Case where we are writing to a disk file. */ if( psReq->fp != NULL ) { psReq->result_size += size*nmemb; return fwrite(buffer, size, nmemb, psReq->fp); } /* Case where we build up the result in memory */ else { if( psReq->result_data == NULL ) { psReq->result_buf_size = size*nmemb + 10000; psReq->result_data = (char *) msSmallMalloc( psReq->result_buf_size ); } else if( psReq->result_size + nmemb * size > psReq->result_buf_size ) { psReq->result_buf_size = psReq->result_size + nmemb*size + 10000; psReq->result_data = (char *) msSmallRealloc( psReq->result_data, psReq->result_buf_size ); } if( psReq->result_data == NULL ) { msSetError(MS_HTTPERR, "Unable to grow HTTP result buffer to size %d.", "msHTTPWriteFct()", psReq->result_buf_size ); psReq->result_buf_size = 0; psReq->result_size = 0; return -1; } memcpy( psReq->result_data + psReq->result_size, buffer, size*nmemb ); psReq->result_size += size*nmemb; return size*nmemb; } } /********************************************************************** * msGetCURLAuthType() * * Returns the equivalent CURL CURLAUTH_ constant given a * MS_HTTP_AUTH_TYPE, or CURLAUTH_BASIC if no match is found. **********************************************************************/ long msGetCURLAuthType(enum MS_HTTP_AUTH_TYPE authType) { switch (authType) { case MS_BASIC: return CURLAUTH_BASIC; case MS_DIGEST: return CURLAUTH_DIGEST; case MS_NTLM: return CURLAUTH_NTLM; case MS_ANY: return CURLAUTH_ANY; case MS_ANYSAFE: return CURLAUTH_ANYSAFE; default: return CURLAUTH_BASIC; } } /********************************************************************** * msHTTPAuthProxySetup() * * Common code used by msPrepareWFSLayerRequest() and * msPrepareWMSLayerRequest() to handle proxy / http auth for requests * * Return value: * MS_SUCCESS if all requests completed succesfully. * MS_FAILURE if a fatal error happened **********************************************************************/ int msHTTPAuthProxySetup(hashTableObj *mapmd, hashTableObj *lyrmd, httpRequestObj *pasReqInfo, int numRequests, mapObj *map, const char* namespaces) { const char *pszTmp; char *pszProxyHost=NULL; long nProxyPort=0; char *pszProxyUsername=NULL, *pszProxyPassword=NULL; char *pszHttpAuthUsername=NULL, *pszHttpAuthPassword=NULL; enum MS_HTTP_AUTH_TYPE eHttpAuthType = MS_BASIC; enum MS_HTTP_AUTH_TYPE eProxyAuthType = MS_BASIC; enum MS_HTTP_PROXY_TYPE eProxyType = MS_HTTP; /* ------------------------------------------------------------------ * Check for authentication and proxying metadata. If the metadata is not found * in the layer metadata, check the map-level metadata. * ------------------------------------------------------------------ */ if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_host")) != NULL) { pszProxyHost = msStrdup(pszTmp); } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_port")) != NULL) { nProxyPort = atol(pszTmp); } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_type")) != NULL) { if (strcasecmp(pszTmp, "HTTP") == 0) eProxyType = MS_HTTP; else if (strcasecmp(pszTmp, "SOCKS5") == 0) eProxyType = MS_SOCKS5; else { msSetError(MS_WMSERR, "Invalid proxy_type metadata '%s' specified", "msHTTPAuthProxySetup()", pszTmp); return MS_FAILURE; } } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_auth_type")) != NULL) { if (strcasecmp(pszTmp, "BASIC") == 0) eProxyAuthType = MS_BASIC; else if (strcasecmp(pszTmp, "DIGEST") == 0) eProxyAuthType = MS_DIGEST; else if (strcasecmp(pszTmp, "NTLM") == 0) eProxyAuthType = MS_NTLM; else if (strcasecmp(pszTmp, "ANY") == 0) eProxyAuthType = MS_ANY; else if (strcasecmp(pszTmp, "ANYSAFE") == 0) eProxyAuthType = MS_ANYSAFE; else { msSetError(MS_WMSERR, "Invalid proxy_auth_type metadata '%s' specified", "msHTTPAuthProxySetup()", pszTmp); return MS_FAILURE; } } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_username")) != NULL) { pszProxyUsername = msStrdup(pszTmp); } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "proxy_password")) != NULL) { pszProxyPassword = msDecryptStringTokens(map, pszTmp); if (pszProxyPassword == NULL) { msFree(pszProxyHost); msFree(pszProxyUsername); return(MS_FAILURE); /* An error should already have been produced */ } } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "auth_type")) != NULL) { if (strcasecmp(pszTmp, "BASIC") == 0) eHttpAuthType = MS_BASIC; else if (strcasecmp(pszTmp, "DIGEST") == 0) eHttpAuthType = MS_DIGEST; else if (strcasecmp(pszTmp, "NTLM") == 0) eHttpAuthType = MS_NTLM; else if (strcasecmp(pszTmp, "ANY") == 0) eHttpAuthType = MS_ANY; else if (strcasecmp(pszTmp, "ANYSAFE") == 0) eHttpAuthType = MS_ANYSAFE; else { msSetError(MS_WMSERR, "Invalid auth_type metadata '%s' specified", "msHTTPAuthProxySetup()", pszTmp); return MS_FAILURE; } } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "auth_username")) != NULL) { pszHttpAuthUsername = msStrdup(pszTmp); } if ((pszTmp = msOWSLookupMetadata2(lyrmd, mapmd, namespaces, "auth_password")) != NULL) { pszHttpAuthPassword = msDecryptStringTokens(map, pszTmp); if (pszHttpAuthPassword == NULL) { msFree(pszHttpAuthUsername); msFree(pszProxyHost); msFree(pszProxyUsername); msFree(pszProxyPassword); return(MS_FAILURE); /* An error should already have been produced */ } } pasReqInfo[numRequests].pszProxyAddress = pszProxyHost; pasReqInfo[numRequests].nProxyPort = nProxyPort; pasReqInfo[numRequests].eProxyType = eProxyType; pasReqInfo[numRequests].eProxyAuthType = eProxyAuthType; pasReqInfo[numRequests].pszProxyUsername = pszProxyUsername; pasReqInfo[numRequests].pszProxyPassword = pszProxyPassword; pasReqInfo[numRequests].eHttpAuthType = eHttpAuthType; pasReqInfo[numRequests].pszHttpUsername = pszHttpAuthUsername; pasReqInfo[numRequests].pszHttpPassword = pszHttpAuthPassword; return MS_SUCCESS; } /********************************************************************** * msHTTPExecuteRequests() * * Fetch a map slide via HTTP request and save to specified temp file. * * If bCheckLocalCache==MS_TRUE then if the pszOutputfile already exists * then is is not downloaded again, and status 242 is returned. * * Return value: * MS_SUCCESS if all requests completed succesfully. * MS_FAILURE if a fatal error happened * MS_DONE if some requests failed with 40x status for instance (not fatal) **********************************************************************/ int msHTTPExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, int bCheckLocalCache) { int i, nStatus = MS_SUCCESS, nTimeout, still_running=0, num_msgs=0; CURLM *multi_handle; CURLMsg *curl_msg; char debug = MS_FALSE; const char *pszCurlCABundle = NULL; if (numRequests == 0) return MS_SUCCESS; /* Nothing to do */ if (!gbCurlInitialized) msHTTPInit(); /* Establish the timeout (seconds) for how long we are going to wait * for a response. * We use the longest timeout value in the array of requests */ nTimeout = pasReqInfo[0].nTimeout; for (i=0; i nTimeout) nTimeout = pasReqInfo[i].nTimeout; if (pasReqInfo[i].debug) debug = MS_TRUE; /* For the download loop */ } if (nTimeout <= 0) nTimeout = 30; /* Check if we've got a CURL_CA_BUNDLE env. var. * If set then the value is the full path to the ca-bundle.crt file * e.g. CURL_CA_BUNDLE=/usr/local/share/curl/curl-ca-bundle.crt */ pszCurlCABundle = getenv("CURL_CA_BUNDLE"); if (debug) { msDebug("HTTP: Starting to prepare HTTP requests.\n"); if (pszCurlCABundle) msDebug("Using CURL_CA_BUNDLE=%s\n", pszCurlCABundle); } /* Alloc a curl-multi handle, and add a curl-easy handle to it for each * file to download. */ multi_handle = curl_multi_init(); if (multi_handle == NULL) { msSetError(MS_HTTPERR, "curl_multi_init() failed.", "msHTTPExecuteRequests()"); return(MS_FAILURE); } for (i=0; iversion_num/0x10000 & 0xff, psCurlVInfo->version_num/0x100 & 0xff, psCurlVInfo->version_num & 0xff ); } } if (pasReqInfo[i].pszUserAgent) { curl_easy_setopt(http_handle, CURLOPT_USERAGENT, pasReqInfo[i].pszUserAgent ); } /* Enable following redirections. Requires libcurl 7.10.1 at least */ curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1 ); curl_easy_setopt(http_handle, CURLOPT_MAXREDIRS, 10 ); /* Set timeout.*/ curl_easy_setopt(http_handle, CURLOPT_TIMEOUT, nTimeout ); /* Pass CURL_CA_BUNDLE if set */ if (pszCurlCABundle) curl_easy_setopt(http_handle, CURLOPT_CAINFO, pszCurlCABundle ); /* Set proxying settings */ if (pasReqInfo[i].pszProxyAddress != NULL && strlen(pasReqInfo[i].pszProxyAddress) > 0) { long nProxyType = CURLPROXY_HTTP; curl_easy_setopt(http_handle, CURLOPT_PROXY, pasReqInfo[i].pszProxyAddress); if (pasReqInfo[i].nProxyPort > 0 && pasReqInfo[i].nProxyPort < 65535) { curl_easy_setopt(http_handle, CURLOPT_PROXYPORT, pasReqInfo[i].nProxyPort); } switch (pasReqInfo[i].eProxyType) { case MS_HTTP: nProxyType = CURLPROXY_HTTP; break; case MS_SOCKS5: nProxyType = CURLPROXY_SOCKS5; break; } curl_easy_setopt(http_handle, CURLOPT_PROXYTYPE, nProxyType); /* If there is proxy authentication information, set it */ if (pasReqInfo[i].pszProxyUsername != NULL && pasReqInfo[i].pszProxyPassword != NULL && strlen(pasReqInfo[i].pszProxyUsername) > 0 && strlen(pasReqInfo[i].pszProxyPassword) > 0) { char szUsernamePasswd[128]; #if LIBCURL_VERSION_NUM >= 0x070a07 long nProxyAuthType = CURLAUTH_BASIC; /* CURLOPT_PROXYAUTH available only in Curl 7.10.7 and up */ nProxyAuthType = msGetCURLAuthType(pasReqInfo[i].eProxyAuthType); curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, nProxyAuthType); #else /* We log an error but don't abort processing */ msSetError(MS_HTTPERR, "CURLOPT_PROXYAUTH not supported. Requires Curl 7.10.7 and up. *_proxy_auth_type setting ignored.", "msHTTPExecuteRequests()"); #endif /* LIBCURL_VERSION_NUM */ snprintf(szUsernamePasswd, 127, "%s:%s", pasReqInfo[i].pszProxyUsername, pasReqInfo[i].pszProxyPassword); curl_easy_setopt(http_handle, CURLOPT_PROXYUSERPWD, szUsernamePasswd); } } /* Set HTTP Authentication settings */ if (pasReqInfo[i].pszHttpUsername != NULL && pasReqInfo[i].pszHttpPassword != NULL && strlen(pasReqInfo[i].pszHttpUsername) > 0 && strlen(pasReqInfo[i].pszHttpPassword) > 0) { char szUsernamePasswd[128]; long nHttpAuthType = CURLAUTH_BASIC; snprintf(szUsernamePasswd, 127, "%s:%s", pasReqInfo[i].pszHttpUsername, pasReqInfo[i].pszHttpPassword); curl_easy_setopt(http_handle, CURLOPT_USERPWD, szUsernamePasswd); nHttpAuthType = msGetCURLAuthType(pasReqInfo[i].eHttpAuthType); curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, nHttpAuthType); } /* NOSIGNAL should be set to true for timeout to work in multithread * environments on Unix, requires libcurl 7.10 or more recent. * (this force avoiding the use of sgnal handlers) */ #ifdef CURLOPT_NOSIGNAL curl_easy_setopt(http_handle, CURLOPT_NOSIGNAL, 1 ); #endif /* If we are writing file to disk, open the file now. */ if( pasReqInfo[i].pszOutputFile != NULL ) { if ( (fp = fopen(pasReqInfo[i].pszOutputFile, "wb")) == NULL) { msSetError(MS_HTTPERR, "Can't open output file %s.", "msHTTPExecuteRequests()", pasReqInfo[i].pszOutputFile); return(MS_FAILURE); } pasReqInfo[i].fp = fp; } curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, &(pasReqInfo[i])); curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, msHTTPWriteFct); /* Provide a buffer where libcurl can write human readable error msgs */ if (pasReqInfo[i].pszErrBuf == NULL) pasReqInfo[i].pszErrBuf = (char *)msSmallMalloc((CURL_ERROR_SIZE+1)* sizeof(char)); pasReqInfo[i].pszErrBuf[0] = '\0'; curl_easy_setopt(http_handle, CURLOPT_ERRORBUFFER, pasReqInfo[i].pszErrBuf); if(pasReqInfo[i].pszPostRequest != NULL ) { char szBuf[100]; struct curl_slist *headers=NULL; snprintf(szBuf, 100, "Content-Type: %s", pasReqInfo[i].pszPostContentType); headers = curl_slist_append(headers, szBuf); curl_easy_setopt(http_handle, CURLOPT_POST, 1 ); curl_easy_setopt(http_handle, CURLOPT_POSTFIELDS, pasReqInfo[i].pszPostRequest); if( debug ) { msDebug("HTTP: POST = %s", pasReqInfo[i].pszPostRequest); } curl_easy_setopt(http_handle, CURLOPT_HTTPHEADER, headers); /* curl_slist_free_all(headers); */ /* free the header list */ } /* Added by RFC-42 HTTP Cookie Forwarding */ if(pasReqInfo[i].pszHTTPCookieData != NULL) { /* Check if there's no end of line in the Cookie string */ /* This could break the HTTP Header */ int nPos; for(nPos=0; nPosmsg == CURLMSG_DONE && curl_msg->data.result != CURLE_OK) { /* Something went wrong with this transfer... report error */ for (i=0; ieasy_handle) { psReq = &(pasReqInfo[i]); break; } } if (psReq != NULL) { /* Record error code in nStatus as a negative value */ psReq->nStatus = -curl_msg->data.result; } } } if (debug) { /* Print a msDebug header for timings reported in the loop below */ msDebug("msHTTPExecuteRequests() timing summary per layer (connect_time + time_to_first_packet + download_time = total_time in seconds)\n"); } /* Check status of all requests, close files, report errors and cleanup * handles */ for (i=0; inStatus == 242) continue; /* Nothing to do here, this file was in cache already */ if (psReq->fp) fclose(psReq->fp); psReq->fp = NULL; http_handle = (CURL*)(psReq->curl_handle); if (psReq->nStatus == 0 && curl_easy_getinfo(http_handle, CURLINFO_HTTP_CODE, &lVal) == CURLE_OK) { char *pszContentType = NULL; psReq->nStatus = lVal; /* Fetch content type of response */ if (curl_easy_getinfo(http_handle, CURLINFO_CONTENT_TYPE, &pszContentType) == CURLE_OK && pszContentType != NULL) { psReq->pszContentType = msStrdup(pszContentType); } } if (!MS_HTTP_SUCCESS(psReq->nStatus)) { /* Set status to MS_DONE to indicate that transfers were */ /* completed but may not be succesfull */ nStatus = MS_DONE; if (psReq->nStatus == -(CURLE_OPERATION_TIMEOUTED)) { /* Timeout isn't a fatal error */ if (psReq->debug) msDebug("HTTP: TIMEOUT of %d seconds exceeded for %s\n", nTimeout, psReq->pszGetUrl ); msSetError(MS_HTTPERR, "HTTP: TIMEOUT of %d seconds exceeded for %s\n", "msHTTPExecuteRequests()", nTimeout, psReq->pszGetUrl); /* Rewrite error message, the curl timeout message isn't * of much use to our users. */ sprintf(psReq->pszErrBuf, "TIMEOUT of %d seconds exceeded.", nTimeout); } else if (psReq->nStatus > 0) { /* Got an HTTP Error, e.g. 404, etc. */ if (psReq->debug) msDebug("HTTP: HTTP GET request failed with status %d (%s)" " for %s\n", psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); msSetError(MS_HTTPERR, "HTTP GET request failed with status %d (%s) " "for %s", "msHTTPExecuteRequests()", psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); } else { /* Got a curl error */ errorObj *error = msGetErrorObj(); if (psReq->debug) msDebug("HTTP: request failed with curl error " "code %d (%s) for %s", -psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); if(!error || error->code == MS_NOERR) /* only set error if one hasn't already been set */ msSetError(MS_HTTPERR, "HTTP: request failed with curl error " "code %d (%s) for %s", "msHTTPExecuteRequests()", -psReq->nStatus, psReq->pszErrBuf, psReq->pszGetUrl); } } /* Report download times foreach handle, in debug mode */ if (psReq->debug) { double dConnectTime=0.0, dTotalTime=0.0, dStartTfrTime=0.0; curl_easy_getinfo(http_handle, CURLINFO_CONNECT_TIME, &dConnectTime); curl_easy_getinfo(http_handle, CURLINFO_STARTTRANSFER_TIME, &dStartTfrTime); curl_easy_getinfo(http_handle, CURLINFO_TOTAL_TIME, &dTotalTime); /* STARTTRANSFER_TIME includes CONNECT_TIME, but TOTAL_TIME * doesn't, so we need to add it. */ dTotalTime += dConnectTime; msDebug("Layer %d: %.3f + %.3f + %.3f = %.3fs\n", psReq->nLayerId, dConnectTime, dStartTfrTime-dConnectTime, dTotalTime-dStartTfrTime, dTotalTime); } /* Cleanup this handle */ curl_easy_setopt(http_handle, CURLOPT_URL, "" ); curl_multi_remove_handle(multi_handle, http_handle); curl_easy_cleanup(http_handle); psReq->curl_handle = NULL; } /* Cleanup multi handle, each handle had to be cleaned up individually */ curl_multi_cleanup(multi_handle); return nStatus; } /********************************************************************** * msHTTPGetFile() * * Wrapper to call msHTTPExecuteRequests() for a single file. **********************************************************************/ int msHTTPGetFile(const char *pszGetUrl, const char *pszOutputFile, int *pnHTTPStatus, int nTimeout, int bCheckLocalCache, int bDebug, int nMaxBytes) { httpRequestObj *pasReqInfo; /* Alloc httpRequestInfo structs through which status of each request * will be returned. * We need to alloc 2 instance of requestobj so that the last * object in the array can be set to NULL. */ pasReqInfo = (httpRequestObj*)calloc(2, sizeof(httpRequestObj)); MS_CHECK_ALLOC(pasReqInfo, 2*sizeof(httpRequestObj), MS_FAILURE); msHTTPInitRequestObj(pasReqInfo, 2); pasReqInfo[0].pszGetUrl = msStrdup(pszGetUrl); pasReqInfo[0].pszOutputFile = msStrdup(pszOutputFile); pasReqInfo[0].debug = (char)bDebug; pasReqInfo[0].nTimeout = nTimeout; pasReqInfo[0].nMaxBytes = nMaxBytes; if (msHTTPExecuteRequests(pasReqInfo, 1, bCheckLocalCache) != MS_SUCCESS) { *pnHTTPStatus = pasReqInfo[0].nStatus; if (pasReqInfo[0].debug) msDebug("HTTP request failed for %s.\n", pszGetUrl); msHTTPFreeRequestObj(pasReqInfo, 2); free(pasReqInfo); return MS_FAILURE; } *pnHTTPStatus = pasReqInfo[0].nStatus; msHTTPFreeRequestObj(pasReqInfo, 2); free(pasReqInfo); return MS_SUCCESS; } #endif /* defined(USE_WMS_LYR) || defined(USE_WMS_SVR) */ mapserver-7.4.3/maphttp.h000066400000000000000000000106261357574274700154110ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: http requests related functions * Author: MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPHTTP_H #define MAPHTTP_H #include "mapprimitive.h" #include #ifdef __cplusplus extern "C" { #endif #define MS_HTTP_SUCCESS(status) (status == 200 || status == 242) enum MS_HTTP_PROXY_TYPE { MS_HTTP, MS_SOCKS5 }; enum MS_HTTP_AUTH_TYPE { MS_BASIC, MS_DIGEST, MS_NTLM, MS_ANY, MS_ANYSAFE }; typedef struct http_request_info { int nLayerId; char *pszGetUrl; char *pszOutputFile; int nTimeout; int nMaxBytes; rectObj bbox; int width; int height; int nStatus; /* 200=success, value < 0 if request failed */ char *pszContentType; /* Content-Type of the response */ char *pszErrBuf; /* Buffer where curl can write errors */ char *pszPostRequest; /* post request content (NULL for GET) */ char *pszPostContentType;/* post request MIME type */ char *pszUserAgent; /* User-Agent, auto-generated if not set */ char *pszHTTPCookieData; /* HTTP Cookie data */ char *pszProxyAddress; /* The address (IP or hostname) of proxy svr */ long nProxyPort; /* The proxy's port */ enum MS_HTTP_PROXY_TYPE eProxyType; /* The type of proxy */ enum MS_HTTP_AUTH_TYPE eProxyAuthType; /* Auth method against proxy */ char *pszProxyUsername; /* Proxy authentication username */ char *pszProxyPassword; /* Proxy authentication password */ enum MS_HTTP_AUTH_TYPE eHttpAuthType; /* HTTP Authentication type */ char *pszHttpUsername; /* HTTP Authentication username */ char *pszHttpPassword; /* HTTP Authentication password */ /* For debugging/profiling */ int debug; /* Debug mode? MS_TRUE/MS_FALSE */ /* Private members */ void * curl_handle; /* CURLM * handle */ FILE * fp; /* FILE * used during download */ char * result_data; /* output if pszOutputFile is NULL */ int result_size; int result_buf_size; } httpRequestObj; #ifdef USE_CURL int msHTTPInit(void); void msHTTPCleanup(void); void msHTTPInitRequestObj(httpRequestObj *pasReqInfo, int numRequests); void msHTTPFreeRequestObj(httpRequestObj *pasReqInfo, int numRequests); int msHTTPExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, int bCheckLocalCache); int msHTTPGetFile(const char *pszGetUrl, const char *pszOutputFile, int *pnHTTPStatus, int nTimeout, int bCheckLocalCache, int bDebug, int nMaxBytes); int msHTTPAuthProxySetup(hashTableObj *mapmd, hashTableObj *lyrmd, httpRequestObj *pasReqInfo, int numRequests, mapObj *map, const char* namespaces); #endif /*USE_CURL*/ #ifdef __cplusplus } #endif #endif /* MAPHTTP_H */ mapserver-7.4.3/mapimageio.c000066400000000000000000001104341357574274700160350ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Low level PNG/JPEG/GIF image io native functions * Author: Thomas Bonfort (tbonfort) * ****************************************************************************** * Copyright (c) 2009 Thomas Bonfort * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include #include #include #include #include #ifdef USE_GIF #include #endif typedef struct _streamInfo { FILE *fp; bufferObj *buffer; } streamInfo; void png_write_data_to_stream(png_structp png_ptr, png_bytep data, png_size_t length) { FILE *fp = ((streamInfo*)png_get_io_ptr(png_ptr))->fp; msIO_fwrite(data,length,1,fp); } void png_write_data_to_buffer(png_structp png_ptr, png_bytep data, png_size_t length) { bufferObj *buffer = ((streamInfo*)png_get_io_ptr(png_ptr))->buffer; msBufferAppend(buffer,data,length); } void png_flush_data(png_structp png_ptr) { /* do nothing */ } typedef struct { struct jpeg_destination_mgr pub; unsigned char *data; } ms_destination_mgr; typedef struct { ms_destination_mgr mgr; FILE *stream; } ms_stream_destination_mgr; typedef struct { ms_destination_mgr mgr; bufferObj *buffer; } ms_buffer_destination_mgr; #define OUTPUT_BUF_SIZE 4096 void jpeg_init_destination (j_compress_ptr cinfo) { ms_destination_mgr *dest = (ms_destination_mgr*) cinfo->dest; /* Allocate the output buffer --- it will be released when done with image */ dest->data = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof (unsigned char)); dest->pub.next_output_byte = dest->data; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } void jpeg_stream_term_destination (j_compress_ptr cinfo) { ms_stream_destination_mgr *dest = (ms_stream_destination_mgr*) cinfo->dest; msIO_fwrite(dest->mgr.data, OUTPUT_BUF_SIZE-dest->mgr.pub.free_in_buffer, 1, dest->stream); dest->mgr.pub.next_output_byte = dest->mgr.data; dest->mgr.pub.free_in_buffer = OUTPUT_BUF_SIZE; } void jpeg_buffer_term_destination (j_compress_ptr cinfo) { ms_buffer_destination_mgr *dest = (ms_buffer_destination_mgr*) cinfo->dest; msBufferAppend(dest->buffer, dest->mgr.data, OUTPUT_BUF_SIZE-dest->mgr.pub.free_in_buffer); dest->mgr.pub.next_output_byte = dest->mgr.data; dest->mgr.pub.free_in_buffer = OUTPUT_BUF_SIZE; } int jpeg_stream_empty_output_buffer (j_compress_ptr cinfo) { ms_stream_destination_mgr *dest = (ms_stream_destination_mgr*) cinfo->dest; msIO_fwrite(dest->mgr.data, OUTPUT_BUF_SIZE, 1, dest->stream); dest->mgr.pub.next_output_byte = dest->mgr.data; dest->mgr.pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } int jpeg_buffer_empty_output_buffer (j_compress_ptr cinfo) { ms_buffer_destination_mgr *dest = (ms_buffer_destination_mgr*) cinfo->dest; msBufferAppend(dest->buffer, dest->mgr.data, OUTPUT_BUF_SIZE); dest->mgr.pub.next_output_byte = dest->mgr.data; dest->mgr.pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } static void msJPEGErrorExit(j_common_ptr cinfo) { jmp_buf* pJmpBuffer = (jmp_buf* ) cinfo->client_data; char buffer[JMSG_LENGTH_MAX]; /* Create the message */ (*cinfo->err->format_message) (cinfo, buffer); msSetError(MS_MISCERR,"libjpeg: %s","jpeg_ErrorExit()", buffer); /* Return control to the setjmp point */ longjmp(*pJmpBuffer, 1); } int saveAsJPEG(mapObj *map, rasterBufferObj *rb, streamInfo *info, outputFormatObj *format) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; int quality; const char* pszOptimized; int optimized; int arithmetic; ms_destination_mgr *dest; JSAMPLE *rowdata = NULL; unsigned int row; jmp_buf setjmp_buffer; quality = atoi(msGetOutputFormatOption( format, "QUALITY", "75")); pszOptimized = msGetOutputFormatOption( format, "OPTIMIZED", "YES"); optimized = EQUAL(pszOptimized, "YES") || EQUAL(pszOptimized, "ON") || EQUAL(pszOptimized, "TRUE"); arithmetic = EQUAL(pszOptimized, "ARITHMETIC"); if (setjmp(setjmp_buffer)) { jpeg_destroy_compress(&cinfo); free(rowdata); return MS_FAILURE; } cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = msJPEGErrorExit; cinfo.client_data = (void *) &(setjmp_buffer); jpeg_create_compress(&cinfo); if (cinfo.dest == NULL) { if(info->fp) { cinfo.dest = (struct jpeg_destination_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (ms_stream_destination_mgr)); ((ms_stream_destination_mgr*)cinfo.dest)->mgr.pub.empty_output_buffer = jpeg_stream_empty_output_buffer; ((ms_stream_destination_mgr*)cinfo.dest)->mgr.pub.term_destination = jpeg_stream_term_destination; ((ms_stream_destination_mgr*)cinfo.dest)->stream = info->fp; } else { cinfo.dest = (struct jpeg_destination_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (ms_buffer_destination_mgr)); ((ms_buffer_destination_mgr*)cinfo.dest)->mgr.pub.empty_output_buffer = jpeg_buffer_empty_output_buffer; ((ms_buffer_destination_mgr*)cinfo.dest)->mgr.pub.term_destination = jpeg_buffer_term_destination; ((ms_buffer_destination_mgr*)cinfo.dest)->buffer = info->buffer; } } dest = (ms_destination_mgr*) cinfo.dest; dest->pub.init_destination = jpeg_init_destination; cinfo.image_width = rb->width; cinfo.image_height = rb->height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); if( arithmetic ) cinfo.arith_code = TRUE; else if( optimized ) cinfo.optimize_coding = TRUE; if( arithmetic || optimized ) { /* libjpeg turbo 1.5.2 honours max_memory_to_use, but has no backing */ /* store implementation, so better not set max_memory_to_use ourselves. */ /* See https://github.com/libjpeg-turbo/libjpeg-turbo/issues/162 */ if( cinfo.mem->max_memory_to_use > 0 ) { if (map == NULL || msGetConfigOption(map, "JPEGMEM") == NULL) { /* If the user doesn't provide a value for JPEGMEM, we want to be sure */ /* that at least the image size will be used before creating the temporary file */ cinfo.mem->max_memory_to_use = MS_MAX(cinfo.mem->max_memory_to_use, cinfo.input_components * rb->width * rb->height); } } } jpeg_start_compress(&cinfo, TRUE); rowdata = (JSAMPLE*)malloc(rb->width*cinfo.input_components*sizeof(JSAMPLE)); for(row=0; rowheight; row++) { JSAMPLE *pixptr = rowdata; int col; unsigned char *r,*g,*b; r=rb->data.rgba.r+row*rb->data.rgba.row_step; g=rb->data.rgba.g+row*rb->data.rgba.row_step; b=rb->data.rgba.b+row*rb->data.rgba.row_step; for(col=0; colwidth; col++) { *(pixptr++) = *r; *(pixptr++) = *g; *(pixptr++) = *b; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } (void) jpeg_write_scanlines(&cinfo, &rowdata, 1); } /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); free(rowdata); return MS_SUCCESS; } /* * sort a given list of rgba entries so that all the opaque pixels are at the end */ int remapPaletteForPNG(rasterBufferObj *rb, rgbPixel *rgb, unsigned char *a, int *num_a) { int bot_idx, top_idx, x; int remap[256]; unsigned int maxval = rb->data.palette.scaling_maxval; assert(rb->type == MS_BUFFER_BYTE_PALETTE); /* ** remap the palette colors so that all entries with ** the maximal alpha value (i.e., fully opaque) are at the end and can ** therefore be omitted from the tRNS chunk. Note that the ordering of ** opaque entries is reversed from how they were previously arranged ** --not that this should matter to anyone. */ for (top_idx = rb->data.palette.num_entries-1, bot_idx = x = 0; x < rb->data.palette.num_entries; ++x) { if (rb->data.palette.palette[x].a == maxval) remap[x] = top_idx--; else remap[x] = bot_idx++; } /* sanity check: top and bottom indices should have just crossed paths */ if (bot_idx != top_idx + 1) { msSetError(MS_MISCERR,"quantization sanity check failed","createPNGPalette()"); return MS_FAILURE; } *num_a = bot_idx; for(x=0; xwidth*rb->height; x++) rb->data.palette.pixels[x] = remap[rb->data.palette.pixels[x]]; for (x = 0; x < rb->data.palette.num_entries; ++x) { if(maxval == 255) { a[remap[x]] = rb->data.palette.palette[x].a; rgb[remap[x]].r = rb->data.palette.palette[x].r; rgb[remap[x]].g = rb->data.palette.palette[x].g; rgb[remap[x]].b = rb->data.palette.palette[x].b; } else { /* rescale palette */ rgb[remap[x]].r = (rb->data.palette.palette[x].r * 255 + (maxval >> 1)) / maxval; rgb[remap[x]].g = (rb->data.palette.palette[x].g * 255 + (maxval >> 1)) / maxval; rgb[remap[x]].b = (rb->data.palette.palette[x].b * 255 + (maxval >> 1)) / maxval; a[remap[x]] = (rb->data.palette.palette[x].a * 255 + (maxval >> 1)) / maxval; } if(a[remap[x]] != 255) { /* un-premultiply pixels */ double da = 255.0/a[remap[x]]; rgb[remap[x]].r *= da; rgb[remap[x]].g *= da; rgb[remap[x]].b *= da; } } return MS_SUCCESS; } int savePalettePNG(rasterBufferObj *rb, streamInfo *info, int compression) { png_infop info_ptr; rgbPixel rgb[256]; unsigned char a[256]; int num_a; int row,sample_depth; png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); assert(rb->type == MS_BUFFER_BYTE_PALETTE); if (!png_ptr) return (MS_FAILURE); png_set_compression_level(png_ptr, compression); png_set_filter (png_ptr,0, PNG_FILTER_NONE); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return (MS_FAILURE); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return (MS_FAILURE); } if(info->fp) png_set_write_fn(png_ptr,info, png_write_data_to_stream, png_flush_data); else png_set_write_fn(png_ptr,info, png_write_data_to_buffer, png_flush_data); if (rb->data.palette.num_entries <= 2) sample_depth = 1; else if (rb->data.palette.num_entries <= 4) sample_depth = 2; else if (rb->data.palette.num_entries <= 16) sample_depth = 4; else sample_depth = 8; png_set_IHDR(png_ptr, info_ptr, rb->width, rb->height, sample_depth, PNG_COLOR_TYPE_PALETTE, 0, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); remapPaletteForPNG(rb,rgb,a,&num_a); png_set_PLTE(png_ptr, info_ptr, (png_colorp)(rgb),rb->data.palette.num_entries); if(num_a) png_set_tRNS(png_ptr, info_ptr, a,num_a, NULL); png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); for(row=0; rowheight; row++) { unsigned char *rowptr = &(rb->data.palette.pixels[row*rb->width]); png_write_row(png_ptr, rowptr); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return MS_SUCCESS; } int readPalette(const char *palette, rgbaPixel *entries, unsigned int *nEntries, int useAlpha) { FILE *stream = NULL; char buffer[MS_BUFFER_LENGTH]; int r,g,b,a; *nEntries = 0; stream = fopen(palette, "r"); if(!stream) { msSetError(MS_IOERR, "Error opening palette file %s.", "readPalette()", palette); return MS_FAILURE; } while(fgets(buffer, MS_BUFFER_LENGTH, stream) && *nEntries<256) { /* while there are colors to load */ if(buffer[0] == '#' || buffer[0] == '\n' || buffer[0] == '\r') continue; /* skip comments and blank lines */ if(!useAlpha) { if(3 != sscanf(buffer,"%d,%d,%d\n",&r,&g,&b)) { fclose(stream); msSetError(MS_MISCERR,"failed to parse color %d r,g,b triplet in line \"%s\" from file %s","readPalette()",*nEntries+1,buffer,palette); return MS_FAILURE; } } else { if(4 != sscanf(buffer,"%d,%d,%d,%d\n",&r,&g,&b,&a)) { fclose(stream); msSetError(MS_MISCERR,"failed to parse color %d r,g,b,a quadruplet in line \"%s\" from file %s","readPalette()",*nEntries+1,buffer,palette); return MS_FAILURE; } } if(useAlpha && a != 255) { double da = a/255.0; entries[*nEntries].r = r * da; entries[*nEntries].g = g * da; entries[*nEntries].b = b * da; entries[*nEntries].a = a; } else { entries[*nEntries].r = r; entries[*nEntries].g = g; entries[*nEntries].b = b; entries[*nEntries].a = 255; } (*nEntries)++; } fclose(stream); return MS_SUCCESS; } int saveAsPNG(mapObj *map,rasterBufferObj *rb, streamInfo *info, outputFormatObj *format) { int force_pc256 = MS_FALSE; int force_palette = MS_FALSE; int ret = MS_FAILURE; const char *force_string,*zlib_compression; int compression = -1; zlib_compression = msGetOutputFormatOption( format, "COMPRESSION", NULL); if(zlib_compression && *zlib_compression) { char *endptr; compression = strtol(zlib_compression,&endptr,10); if(*endptr || compression<-1 || compression>9) { msSetError(MS_MISCERR,"failed to parse FORMATOPTION \"COMPRESSION=%s\", expecting integer from 0 to 9.","saveAsPNG()",zlib_compression); return MS_FAILURE; } } force_string = msGetOutputFormatOption( format, "QUANTIZE_FORCE", NULL ); if( force_string && (strcasecmp(force_string,"on") == 0 || strcasecmp(force_string,"yes") == 0 || strcasecmp(force_string,"true") == 0) ) force_pc256 = MS_TRUE; force_string = msGetOutputFormatOption( format, "PALETTE_FORCE", NULL ); if( force_string && (strcasecmp(force_string,"on") == 0 || strcasecmp(force_string,"yes") == 0 || strcasecmp(force_string,"true") == 0) ) force_palette = MS_TRUE; if(force_pc256 || force_palette) { rasterBufferObj qrb; rgbaPixel palette[256], paletteGiven[256]; unsigned int numPaletteGivenEntries; memset(&qrb,0,sizeof(rasterBufferObj)); qrb.type = MS_BUFFER_BYTE_PALETTE; qrb.width = rb->width; qrb.height = rb->height; qrb.data.palette.pixels = (unsigned char*)malloc(qrb.width*qrb.height*sizeof(unsigned char)); qrb.data.palette.scaling_maxval = 255; if(force_pc256) { qrb.data.palette.palette = palette; qrb.data.palette.num_entries = atoi(msGetOutputFormatOption( format, "QUANTIZE_COLORS", "256")); ret = msQuantizeRasterBuffer(rb,&(qrb.data.palette.num_entries),qrb.data.palette.palette, NULL, 0, &qrb.data.palette.scaling_maxval); } else { int colorsWanted = atoi(msGetOutputFormatOption( format, "QUANTIZE_COLORS", "0")); const char *palettePath = msGetOutputFormatOption( format, "PALETTE", "palette.txt"); char szPath[MS_MAXPATHLEN]; if(map) { msBuildPath(szPath, map->mappath, palettePath); palettePath = szPath; } if(readPalette(palettePath,paletteGiven,&numPaletteGivenEntries,format->transparent) != MS_SUCCESS) { return MS_FAILURE; } if(numPaletteGivenEntries == 256 || colorsWanted == 0) { qrb.data.palette.palette = paletteGiven; qrb.data.palette.num_entries = numPaletteGivenEntries; ret = MS_SUCCESS; /* we have a full palette and don't want an additional quantization step */ } else { /* quantize the image, and mix our colours in the resulting palette */ qrb.data.palette.palette = palette; qrb.data.palette.num_entries = MS_MAX(colorsWanted,numPaletteGivenEntries); ret = msQuantizeRasterBuffer(rb,&(qrb.data.palette.num_entries),qrb.data.palette.palette, paletteGiven,numPaletteGivenEntries, &qrb.data.palette.scaling_maxval); } } if(ret != MS_FAILURE) { ret = msClassifyRasterBuffer(rb,&qrb); ret = savePalettePNG(&qrb,info,compression); } msFree(qrb.data.palette.pixels); return ret; } else if(rb->type == MS_BUFFER_BYTE_RGBA) { png_infop info_ptr; int color_type; int row; unsigned int *rowdata; png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (!png_ptr) return (MS_FAILURE); png_set_compression_level(png_ptr, compression); png_set_filter (png_ptr,0, PNG_FILTER_NONE); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return (MS_FAILURE); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return (MS_FAILURE); } if(info->fp) png_set_write_fn(png_ptr,info, png_write_data_to_stream, png_flush_data); else png_set_write_fn(png_ptr,info, png_write_data_to_buffer, png_flush_data); if(rb->data.rgba.a) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, rb->width, rb->height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); if(!rb->data.rgba.a && rb->data.rgba.pixel_step==4) png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); rowdata = (unsigned int*)malloc(rb->width*sizeof(unsigned int)); for(row=0; rowheight; row++) { unsigned int *pixptr = rowdata; int col; unsigned char *a,*r,*g,*b; r=rb->data.rgba.r+row*rb->data.rgba.row_step; g=rb->data.rgba.g+row*rb->data.rgba.row_step; b=rb->data.rgba.b+row*rb->data.rgba.row_step; if(rb->data.rgba.a) { a=rb->data.rgba.a+row*rb->data.rgba.row_step; for(col=0; colwidth; col++) { if(*a) { double da = *a/255.0; unsigned char *pix = (unsigned char*)pixptr; pix[0] = *r/da; pix[1] = *g/da; pix[2] = *b/da; pix[3] = *a; } else { *pixptr=0; } pixptr++; a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } else { for(col=0; colwidth; col++) { unsigned char *pix = (unsigned char*)pixptr; pix[0] = *r; pix[1] = *g; pix[2] = *b; pixptr++; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } png_write_row(png_ptr,(png_bytep)rowdata); } png_write_end(png_ptr, info_ptr); free(rowdata); png_destroy_write_struct(&png_ptr, &info_ptr); return MS_SUCCESS; } else { msSetError(MS_MISCERR,"Unknown buffer type","saveAsPNG()"); return MS_FAILURE; } } /* For platforms with incomplete ANSI defines. Fortunately, SEEK_SET is defined to be zero by the standard. */ #ifndef SEEK_SET #define SEEK_SET 0 #endif /* SEEK_SET */ int readPNG(char *path, rasterBufferObj *rb) { png_uint_32 width,height; unsigned char *a,*r,*g,*b; int bit_depth,color_type,i; unsigned char **row_pointers; png_structp png_ptr = NULL; png_infop info_ptr = NULL; FILE *stream = fopen(path,"rb"); if(!stream) return MS_FAILURE; /* could pass pointers to user-defined error handlers instead of NULLs: */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose(stream); return MS_FAILURE; /* out of memory */ } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(stream); return MS_FAILURE; /* out of memory */ } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr,&info_ptr,NULL); fclose(stream); return MS_FAILURE; } png_init_io(png_ptr,stream); png_read_info(png_ptr,info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL,NULL,NULL); rb->width = width; rb->height = height; rb->type = MS_BUFFER_BYTE_RGBA; rb->data.rgba.pixels = (unsigned char*)malloc(width*height*4*sizeof(unsigned char)); row_pointers = (unsigned char**)malloc(height*sizeof(unsigned char*)); rb->data.rgba.pixel_step=4; rb->data.rgba.row_step = width*4; b = rb->data.rgba.b = &rb->data.rgba.pixels[0]; g = rb->data.rgba.g = &rb->data.rgba.pixels[1]; r = rb->data.rgba.r = &rb->data.rgba.pixels[2]; a = rb->data.rgba.a = &rb->data.rgba.pixels[3]; for(i=0; idata.rgba.pixels[i*rb->data.rgba.row_step]); } if (color_type == PNG_COLOR_TYPE_PALETTE) /* expand palette images to RGB */ png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) /* expand low bit-depth grayscale to 8bits */ png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) /* expand transparency chunks to full alpha */ png_set_expand(png_ptr); if (bit_depth == 16) /* scale 16bits down to 8 */ png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) /* convert grayscale to rgba */ png_set_gray_to_rgb(png_ptr); png_set_bgr(png_ptr); if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE) png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); png_read_update_info(png_ptr, info_ptr); assert(png_get_rowbytes(png_ptr, info_ptr) == rb->data.rgba.row_step); png_read_image(png_ptr, row_pointers); free(row_pointers); row_pointers=NULL; png_read_end(png_ptr,NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); /*premultiply data*/ for(i=0; i> 8; *g = (*g * *a + 255) >> 8; *b = (*b * *a + 255) >> 8; } } a+=4; b+=4; g+=4; r+=4; } fclose(stream); return MS_SUCCESS; } int msSaveRasterBuffer(mapObj *map, rasterBufferObj *rb, FILE *stream, outputFormatObj *format) { if(strcasestr(format->driver,"/png")) { streamInfo info; info.fp = stream; info.buffer = NULL; return saveAsPNG(map, rb,&info,format); } else if(strcasestr(format->driver,"/jpeg")) { streamInfo info; info.fp = stream; info.buffer=NULL; return saveAsJPEG(map, rb,&info,format); } else { msSetError(MS_MISCERR,"unsupported image format\n", "msSaveRasterBuffer()"); return MS_FAILURE; } } int msSaveRasterBufferToBuffer(rasterBufferObj *data, bufferObj *buffer, outputFormatObj *format) { if(strcasestr(format->driver,"/png")) { streamInfo info; info.fp = NULL; info.buffer = buffer; return saveAsPNG(NULL, data,&info,format); } else if(strcasestr(format->driver,"/jpeg")) { streamInfo info; info.fp = NULL; info.buffer=buffer; return saveAsJPEG(NULL, data,&info,format); } else { msSetError(MS_MISCERR,"unsupported image format\n", "msSaveRasterBuffer()"); return MS_FAILURE; } } #ifdef USE_GIF #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 static char const *gif_error_msg(int code) #else static char const *gif_error_msg() #endif { static char msg[80]; #if (!defined GIFLIB_MAJOR) || (GIFLIB_MAJOR < 5) int code = GifLastError(); #endif switch (code) { case E_GIF_ERR_OPEN_FAILED: /* should not see this */ return "Failed to open given file"; case E_GIF_ERR_WRITE_FAILED: return "Write failed"; case E_GIF_ERR_HAS_SCRN_DSCR: /* should not see this */ return "Screen descriptor already passed to giflib"; case E_GIF_ERR_HAS_IMAG_DSCR: /* should not see this */ return "Image descriptor already passed to giflib"; case E_GIF_ERR_NO_COLOR_MAP: /* should not see this */ return "Neither global nor local color map set"; case E_GIF_ERR_DATA_TOO_BIG: /* should not see this */ return "Too much pixel data passed to giflib"; case E_GIF_ERR_NOT_ENOUGH_MEM: return "Out of memory"; case E_GIF_ERR_DISK_IS_FULL: return "Disk is full"; case E_GIF_ERR_CLOSE_FAILED: /* should not see this */ return "File close failed"; case E_GIF_ERR_NOT_WRITEABLE: /* should not see this */ return "File not writable"; case D_GIF_ERR_OPEN_FAILED: return "Failed to open file"; case D_GIF_ERR_READ_FAILED: return "Failed to read from file"; case D_GIF_ERR_NOT_GIF_FILE: return "File is not a GIF file"; case D_GIF_ERR_NO_SCRN_DSCR: return "No screen descriptor detected - invalid file"; case D_GIF_ERR_NO_IMAG_DSCR: return "No image descriptor detected - invalid file"; case D_GIF_ERR_NO_COLOR_MAP: return "No global or local color map found"; case D_GIF_ERR_WRONG_RECORD: return "Wrong record type detected - invalid file?"; case D_GIF_ERR_DATA_TOO_BIG: return "Data in file too big for image"; case D_GIF_ERR_NOT_ENOUGH_MEM: return "Out of memory"; case D_GIF_ERR_CLOSE_FAILED: return "Close failed"; case D_GIF_ERR_NOT_READABLE: return "File not opened for read"; case D_GIF_ERR_IMAGE_DEFECT: return "Defective image"; case D_GIF_ERR_EOF_TOO_SOON: return "Unexpected EOF - invalid file"; default: sprintf(msg, "Unknown giflib error code %d", code); return msg; } } /* not fully implemented and tested */ /* missing: set the first pointer to a,r,g,b */ int readGIF(char *path, rasterBufferObj *rb) { int i, j, codeSize, extCode, firstImageRead = MS_FALSE; unsigned char *r,*g,*b,*a; int transIdx = -1; GifFileType *image; GifPixelType *line; GifRecordType recordType; GifByteType *codeBlock, *extension; ColorMapObject *cmap; int interlacedOffsets[] = {0,4,2,1}; int interlacedJumps[] = {8,8,4,2}; #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 int errcode; #endif rb->type = MS_BUFFER_BYTE_RGBA; #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 image = DGifOpenFileName(path, &errcode); if (image == NULL) { msSetError(MS_MISCERR,"failed to load gif image: %s","readGIF()", gif_error_msg(errcode)); return MS_FAILURE; } #else image = DGifOpenFileName(path); if (image == NULL) { msSetError(MS_MISCERR,"failed to load gif image: %s","readGIF()", gif_error_msg()); return MS_FAILURE; } #endif rb->width = image->SWidth; rb->height = image->SHeight; rb->data.rgba.row_step = rb->width * 4; rb->data.rgba.pixel_step = 4; rb->data.rgba.pixels = (unsigned char*)malloc(rb->width*rb->height*4*sizeof(unsigned char)); b = rb->data.rgba.b = &rb->data.rgba.pixels[0]; g = rb->data.rgba.g = &rb->data.rgba.pixels[1]; r = rb->data.rgba.r = &rb->data.rgba.pixels[2]; a = rb->data.rgba.a = &rb->data.rgba.pixels[3]; cmap = (image->Image.ColorMap)?image->Image.ColorMap:image->SColorMap; for(i=0; iwidth*rb->height; i++) { *a = 255; *r = cmap->Colors[image->SBackGroundColor].Red; *g = cmap->Colors[image->SBackGroundColor].Green; *b = cmap->Colors[image->SBackGroundColor].Blue; a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } do { if (DGifGetRecordType(image, &recordType) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } switch (recordType) { case SCREEN_DESC_RECORD_TYPE: DGifGetScreenDesc(image); break; case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(image) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } if (!firstImageRead) { int row = image->Image.Top; int col = image->Image.Left; int width = image->Image.Width; int height = image->Image.Height; /* sanity check: */ if(col+width>rb->width || row+height>rb->height) { msSetError(MS_MISCERR,"corrupted gif image, img size exceeds screen size","readGIF()"); return MS_FAILURE; } line = (GifPixelType *) malloc(width * sizeof(GifPixelType)); if(image->Image.Interlace) { int count; for(count=0; count<4; count++) { for(i=row+interlacedOffsets[count]; idata.rgba.row_step + col * rb->data.rgba.pixel_step; a = rb->data.rgba.a + offset; r = rb->data.rgba.r + offset; g = rb->data.rgba.g + offset; b = rb->data.rgba.b + offset; if (DGifGetLine(image, line, width) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()",gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()",gif_error_msg()); #endif return MS_FAILURE; } for(j=0; jColors[pix].Red; *g = cmap->Colors[pix].Green; *b = cmap->Colors[pix].Blue; } else { *a = *r = *g = *b = 0; } a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } } } else { for (i = 0; i < height; i++) { int offset = i * rb->data.rgba.row_step + col * rb->data.rgba.pixel_step; a = rb->data.rgba.a + offset; r = rb->data.rgba.r + offset; g = rb->data.rgba.g + offset; b = rb->data.rgba.b + offset; if (DGifGetLine(image, line, width) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()",gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()",gif_error_msg()); #endif return MS_FAILURE; } for(j=0; jColors[pix].Red; *g = cmap->Colors[pix].Green; *b = cmap->Colors[pix].Blue; } else { *a = *r = *g = *b = 0; } a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } } free((char *) line); firstImageRead = MS_TRUE; } else { /* Skip all next images */ if (DGifGetCode(image, &codeSize, &codeBlock) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } while (codeBlock != NULL) { if (DGifGetCodeNext(image, &codeBlock) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } } } break; case EXTENSION_RECORD_TYPE: /* skip all extension blocks */ if (DGifGetExtension(image, &extCode, &extension) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } if(extCode == 249 && (extension[1] & 1)) transIdx = extension[4]; for (;;) { if (DGifGetExtensionNext(image, &extension) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"corrupted gif image?: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } if (extension == NULL) break; if(extension[1] & 1) transIdx = extension[4]; } break; case UNDEFINED_RECORD_TYPE: break; case TERMINATE_RECORD_TYPE: break; default: break; } } while (recordType != TERMINATE_RECORD_TYPE); #if defined GIFLIB_MAJOR && GIFLIB_MINOR && ((GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || (GIFLIB_MAJOR > 5)) if (DGifCloseFile(image, &errcode) == GIF_ERROR) { msSetError(MS_MISCERR,"failed to close gif after loading: %s","readGIF()", gif_error_msg(errcode)); return MS_FAILURE; } #else if (DGifCloseFile(image) == GIF_ERROR) { #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5 msSetError(MS_MISCERR,"failed to close gif after loading: %s","readGIF()", gif_error_msg(image->Error)); #else msSetError(MS_MISCERR,"failed to close gif after loading: %s","readGIF()", gif_error_msg()); #endif return MS_FAILURE; } #endif return MS_SUCCESS; } #endif int msLoadMSRasterBufferFromFile(char *path, rasterBufferObj *rb) { FILE *stream; unsigned char signature[8]; int ret = MS_FAILURE; stream = fopen(path,"rb"); if(!stream) { msSetError(MS_MISCERR, "unable to open file %s for reading", "msLoadMSRasterBufferFromFile()", path); return MS_FAILURE; } if(1 != fread(signature,8,1,stream)) { fclose(stream); msSetError(MS_MISCERR, "Unable to read header from image file %s", "msLoadMSRasterBufferFromFile()",path); return MS_FAILURE; } fclose(stream); if(png_sig_cmp(signature,0,8) == 0) { ret = readPNG(path,rb); } else if (!strncmp((char*)signature,"GIF",3)) { #ifdef USE_GIF ret = readGIF(path,rb); #else msSetError(MS_MISCERR,"pixmap %s seems to be GIF formatted, but this server is compiled without GIF support","readImage()",path); return MS_FAILURE; #endif } else { msSetError(MS_MISCERR,"unsupported pixmap format","readImage()"); return MS_FAILURE; } return ret; } mapserver-7.4.3/mapimagemap.c000066400000000000000000000622031357574274700162030ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implements imagemap outputformat support. * Author: Attila Csipa * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "dxfcolor.h" #include #include #ifdef _WIN32 #include #include #endif #define MYDEBUG 0 #define DEBUG_IF if (MYDEBUG > 2) /* * Client-side imagemap support was originally written by * Attila Csipa (http://prometheus.org.yu/me.php). C. Scott Ananian * (http://cscott.net) cleaned up the code somewhat and made it more flexible: * you can now customize the generated HREFs and create mouseover and * mouseout attributes. * * Use * IMAGETYPE imagemap * to select this driver. * * The following FORMATOPTIONs are available. If any are set to the empty * string the associated attribute will be suppressed. * POLYHREF the href string to use for the elements. * use a %s to interpolate the area title. * default: "javascript:Clicked('%s');" * POLYMOUSEOVER the onMouseOver string to use for the elements. * use a %s to interpolate the area title. * default: "" (ie the attribute is suppressed) * POLYMOUSEOUT the onMouseOut string to use for the elements. * use a %s to interpolate the area title. * default: "" (ie the attribute is suppressed) * SYMBOLMOUSEOVER and SYMBOLMOUSEOUT are equivalent properties for * tags representing symbols, with the same defaults. * MAPNAME the string which will be used in the name attribute * of the tag. There is no %s interpolation. * default: "map1" * SUPPRESS if "yes", then we will suppress area declarations with * no title. * default: "NO" * * For example, http://vevo.verifiedvoting.org/verifier contains this * .map file fragment: * OUTPUTFORMAT * NAME imagemap * DRIVER imagemap * FORMATOPTION "POLYHREF=/verifier/map.php?state=%s" * FORMATOPTION "SYMBOLHREF=#" * FORMATOPTION "SUPPRESS=YES" * FORMATOPTION "MAPNAME=map-48" * FORMATOPTION "POLYMOUSEOUT=return nd();" * FORMATOPTION "POLYMOUSEOVER=return overlib('%s');" * END */ /*-------------------------------------------------------------------------*/ /* A pString is a variable-length (appendable) string, stored as a triple: * character pointer, allocated length, and used length. The one wrinkle * is that we use pointers to the allocated size and character pointer, * in order to support refering to fields declared elsewhere (ie in the * 'image' data structure) for these. The 'iprintf' function appends * to a pString. */ typedef struct pString { /* these two fields are somewhere else */ char **string; int *alloc_size; /* this field is stored locally. */ int string_len; } pString; /* These are the pStrings we declare statically. One is the 'output' * imagemap/dxf file; parts of this live in another data structure and * are only referenced indirectly here. The other contains layer-specific * information for the dxf output. */ static char *layerlist=NULL; static int layersize=0; static pString imgStr, layerStr= { &layerlist, &layersize, 0 }; /* Format strings for the various bits of a client-side imagemap. */ static const char *polyHrefFmt, *polyMOverFmt, *polyMOutFmt; static const char *symbolHrefFmt, *symbolMOverFmt, *symbolMOutFmt; static const char *mapName; /* Should we suppress AREA declarations in imagemaps with no title? */ static int suppressEmpty=0; /* Prevent buffer-overrun and format-string attacks by "sanitizing" any * provided format string to fit the number of expected string arguments * (MAX) exactly. */ static const char *makeFmtSafe(const char *fmt, int MAX) { /* format string should have exactly 'MAX' %s */ char *result = msSmallMalloc(strlen(fmt)+1+3*MAX), *cp; int numstr=0, saw_percent=0; strcpy(result, fmt); for (cp=result; *cp; cp++) { if (saw_percent) { if (*cp=='%') { /* safe */ } else if (*cp=='s' && numstralloc_size) - ps->string_len; va_start(ap, fmt); #if defined(HAVE_VSNPRINTF) n = vsnprintf((*(ps->string)) + ps->string_len, remaining, fmt, ap); #else /* If vsnprintf() is not available then require a minimum * of 512 bytes of free space to prevent a buffer overflow * This is not fully bulletproof but should help, see bug 1613 */ if (remaining < 512) n = -1; else n = vsprintf((*(ps->string)) + ps->string_len, fmt, ap); #endif va_end(ap); /* if that worked, we're done! */ if (-1string_len += n; return; } else { /* double allocated string size */ *(ps->alloc_size) *= 2;/* these keeps realloc linear.*/ if (*(ps->alloc_size) < 1024) /* careful: initial size can be 0 */ *(ps->alloc_size)=1024; if (n>-1 && *(ps->alloc_size) <= (n + ps->string_len)) /* ensure at least as much as what is needed */ *(ps->alloc_size) = n+ps->string_len+1; *(ps->string) = (char *) msSmallRealloc (*(ps->string), *(ps->alloc_size)); /* if realloc doesn't work, we're screwed! */ } } while (1); /* go back and try again. */ } static int lastcolor=-1; static int matchdxfcolor(colorObj col) { int best=7; int delta=128*255; int tcolor = 0; if (lastcolor != -1) return lastcolor; while (tcolor < 256 && (ctable[tcolor].r != col.red || ctable[tcolor].g != col.green || ctable[tcolor].b != col.blue)) { if (abs( (ctable[tcolor].r - col.red) * (ctable[tcolor].r - col.red)+ (ctable[tcolor].b - col.blue) * (ctable[tcolor].b - col.blue) + (ctable[tcolor].g - col.green) * (ctable[tcolor].g - col.green) < delta) ) { best = tcolor; delta = abs( (ctable[tcolor].r - col.red) * (ctable[tcolor].r - col.red)+ (ctable[tcolor].b - col.blue) * (ctable[tcolor].b - col.blue) + (ctable[tcolor].g - col.green) * (ctable[tcolor].g - col.green) ); } tcolor++; } if (tcolor >= 256) tcolor = best; /* DEBUG_IF printf("%d/%d/%d (%d/%d - %d), %d : %d/%d/%d
\n", ctable[tcolor].r, ctable[tcolor].g, ctable[tcolor].b, tcolor, best, delta, lastcolor, col.red, col.green, col.blue); */ lastcolor = tcolor; return tcolor; } static char* lname; static int dxf; void msImageStartLayerIM(mapObj *map, layerObj *layer, imageObj *image) { DEBUG_IF printf("ImageStartLayerIM\n
"); free(lname); if (layer->name) lname = msStrdup(layer->name); else lname = msStrdup("NONE"); if (dxf == 2) { im_iprintf(&layerStr, "LAYER\n%s\n", lname); } else if (dxf) { im_iprintf(&layerStr, " 0\nLAYER\n 2\n%s\n" " 70\n 64\n 6\nCONTINUOUS\n", lname); } lastcolor = -1; } /* * Utility function to create a IM image. Returns * a pointer to an imageObj structure. */ imageObj *msImageCreateIM(int width, int height, outputFormatObj *format, char *imagepath, char *imageurl, double resolution, double defresolution) { imageObj *image=NULL; if (setvbuf(stdout, NULL, _IONBF , 0)) { printf("Whoops..."); }; DEBUG_IF printf("msImageCreateIM
\n"); if (width > 0 && height > 0) { image = (imageObj *)msSmallCalloc(1,sizeof(imageObj)); imgStr.string = &(image->img.imagemap); imgStr.alloc_size = &(image->size); image->format = format; format->refcount++; image->width = width; image->height = height; image->imagepath = NULL; image->imageurl = NULL; image->resolution = resolution; image->resolutionfactor = resolution/defresolution; if( strcasecmp("ON",msGetOutputFormatOption( format, "DXF", "OFF" )) == 0) { dxf = 1; im_iprintf(&layerStr, " 2\nLAYER\n 70\n 10\n"); } else dxf = 0; if( strcasecmp("ON",msGetOutputFormatOption( format, "SCRIPT", "OFF" )) == 0) { dxf = 2; im_iprintf(&layerStr, ""); } /* get href formation string options */ polyHrefFmt = makeFmtSafe(msGetOutputFormatOption ( format, "POLYHREF", "javascript:Clicked('%s');"), 1); polyMOverFmt = makeFmtSafe(msGetOutputFormatOption ( format, "POLYMOUSEOVER", ""), 1); polyMOutFmt = makeFmtSafe(msGetOutputFormatOption ( format, "POLYMOUSEOUT", ""), 1); symbolHrefFmt = makeFmtSafe(msGetOutputFormatOption ( format, "SYMBOLHREF", "javascript:SymbolClicked();"), 1); symbolMOverFmt = makeFmtSafe(msGetOutputFormatOption ( format, "SYMBOLMOUSEOVER", ""), 1); symbolMOutFmt = makeFmtSafe(msGetOutputFormatOption ( format, "SYMBOLMOUSEOUT", ""), 1); /* get name of client-side image map */ mapName = msGetOutputFormatOption ( format, "MAPNAME", "map1" ); /* should we suppress area declarations with no title? */ if( strcasecmp("YES",msGetOutputFormatOption( format, "SUPPRESS", "NO" )) == 0) { suppressEmpty=1; } lname = msStrdup("NONE"); *(imgStr.string) = msStrdup(""); if (*(imgStr.string)) { *(imgStr.alloc_size) = imgStr.string_len = strlen(*(imgStr.string)); } else { *(imgStr.alloc_size) = imgStr.string_len = 0; } if (imagepath) { image->imagepath = msStrdup(imagepath); } if (imageurl) { image->imageurl = msStrdup(imageurl); } return image; } else { msSetError(MS_IMGERR, "Cannot create IM image of size %d x %d.", "msImageCreateIM()", width, height ); } return image; } /* ------------------------------------------------------------------------- */ /* Draw a single marker symbol of the specified size and color */ /* ------------------------------------------------------------------------- */ void msDrawMarkerSymbolIM(mapObj *map, imageObj* img, pointObj *p, styleObj *style, double scalefactor) { symbolObj *symbol; int ox, oy; double size; DEBUG_IF printf("msDrawMarkerSymbolIM\n
"); /* skip this, we don't do text */ if(!p) return; if(style->symbol > map->symbolset.numsymbols || style->symbol < 0) return; /* no such symbol, 0 is OK */ symbol = map->symbolset.symbol[style->symbol]; ox = style->offsetx*scalefactor; oy = style->offsety*scalefactor; if(style->size == -1) { size = msSymbolGetDefaultSize( symbol ); size = MS_NINT(size*scalefactor); } else size = MS_NINT(style->size*scalefactor); size = MS_MAX(size, style->minsize*img->resolutionfactor); size = MS_MIN(size, style->maxsize*img->resolutionfactor); if(size < 1) return; /* size too small */ /* DEBUG_IF printf(".%d.%d.%d.", symbol->type, style->symbol, fc); */ if(style->symbol == 0) { /* simply draw a single pixel of the specified color */ if (dxf) { if (dxf==2) im_iprintf (&imgStr, "POINT\n%.0f %.0f\n%d\n", p->x + ox, p->y + oy, matchdxfcolor(style->color)); else im_iprintf (&imgStr, " 0\nPOINT\n 10\n%f\n 20\n%f\n 30\n0.0\n" " 62\n%6d\n 8\n%s\n", p->x + ox, p->y + oy, matchdxfcolor(style->color), lname); } else { im_iprintf (&imgStr, "\n", p->x + ox, p->y + oy); } /* point2 = &( p->line[j].point[i] ); */ /* if(point1->y == point2->y) {} */ return; } DEBUG_IF printf("A"); switch(symbol->type) { case(MS_SYMBOL_TRUETYPE): DEBUG_IF printf("T"); break; case(MS_SYMBOL_PIXMAP): DEBUG_IF printf("P"); break; case(MS_SYMBOL_VECTOR): DEBUG_IF printf("V"); { double d, offset_x, offset_y; d = size/symbol->sizey; offset_x = MS_NINT(p->x - d*.5*symbol->sizex + ox); offset_y = MS_NINT(p->y - d*.5*symbol->sizey + oy); /* For now I only render filled vector symbols in imagemap, and no */ /* dxf support available yet. */ if(symbol->filled && !dxf /* && fc >= 0 */ ) { /* char *title=(p->numvalues) ? p->values[0] : ""; */ char *title = ""; int j; im_iprintf (&imgStr, "numpoints; j++) { im_iprintf (&imgStr, "%s %d,%d", j == 0 ? "": ",", MS_NINT(d*symbol->points[j].x + offset_x), MS_NINT(d*symbol->points[j].y + offset_y) ); } im_iprintf (&imgStr, "\" />\n"); } /* end of imagemap, filled case. */ } break; default: DEBUG_IF printf("DEF"); break; } /* end switch statement */ return; } /* ------------------------------------------------------------------------- */ /* Draw a line symbol of the specified size and color */ /* ------------------------------------------------------------------------- */ void msDrawLineSymbolIM(mapObj *map, imageObj* img, shapeObj *p, styleObj *style, double scalefactor) { symbolObj *symbol; int i,j,l; char first = 1; double size; DEBUG_IF printf("msDrawLineSymbolIM
\n"); if(!p) return; if(p->numlines <= 0) return; if(style->symbol > map->symbolset.numsymbols || style->symbol < 0) return; /* no such symbol, 0 is OK */ symbol = map->symbolset.symbol[style->symbol]; if(style->size == -1) { size = msSymbolGetDefaultSize( symbol ); size = MS_NINT(size*scalefactor); } else size = MS_NINT(style->size*scalefactor); size = MS_MAX(size, style->minsize*img->resolutionfactor); size = MS_MIN(size, style->maxsize*img->resolutionfactor); if (suppressEmpty && p->numvalues==0) return;/* suppress area with empty title */ if(style->symbol == 0) { /* just draw a single width line */ for(l=0,j=0; jnumlines; j++) { if (dxf == 2) { im_iprintf (&imgStr, "LINE\n%d\n", matchdxfcolor(style->color)); } else if (dxf) { im_iprintf (&imgStr, " 0\nPOLYLINE\n 70\n 0\n 62\n%6d\n 8\n%s\n", matchdxfcolor(style->color), lname); } else { char *title; first = 1; title=(p->numvalues) ? p->values[0] : ""; im_iprintf (&imgStr, "line[j].point[p->line[j].numpoints-1] ); */ for(i=0; i < p->line[j].numpoints; i++,l++) { if (dxf == 2) { im_iprintf (&imgStr, "%.0f %.0f\n", p->line[j].point[i].x, p->line[j].point[i].y); } else if (dxf) { im_iprintf (&imgStr, " 0\nVERTEX\n 10\n%f\n 20\n%f\n 30\n%f\n", p->line[j].point[i].x, p->line[j].point[i].y, 0.0); } else { im_iprintf (&imgStr, "%s %.0f,%.0f", first ? "": ",", p->line[j].point[i].x, p->line[j].point[i].y); } first = 0; /* point2 = &( p->line[j].point[i] ); */ /* if(point1->y == point2->y) {} */ } im_iprintf (&imgStr, dxf ? (dxf == 2 ? "": " 0\nSEQEND\n") : "\" />\n"); } /* DEBUG_IF printf ("%d, ",strlen(img->img.imagemap) ); */ return; } DEBUG_IF printf("-%d-",symbol->type); return; } /* ------------------------------------------------------------------------- */ /* Draw a shade symbol of the specified size and color */ /* ------------------------------------------------------------------------- */ void msDrawShadeSymbolIM(mapObj *map, imageObj* img, shapeObj *p, styleObj *style, double scalefactor) { symbolObj *symbol; int i,j,l; char first = 1; double size; DEBUG_IF printf("msDrawShadeSymbolIM\n
"); if(!p) return; if(p->numlines <= 0) return; symbol = map->symbolset.symbol[style->symbol]; if(style->size == -1) { size = msSymbolGetDefaultSize( symbol ); size = MS_NINT(size*scalefactor); } else size = MS_NINT(style->size*scalefactor); size = MS_MAX(size, style->minsize*img->resolutionfactor); size = MS_MIN(size, style->maxsize*img->resolutionfactor); if (suppressEmpty && p->numvalues==0) return;/* suppress area with empty title */ if(style->symbol == 0) { /* simply draw a single pixel of the specified color // */ for(l=0,j=0; jnumlines; j++) { if (dxf == 2) { im_iprintf (&imgStr, "POLY\n%d\n", matchdxfcolor(style->color)); } else if (dxf) { im_iprintf (&imgStr, " 0\nPOLYLINE\n 73\n 1\n 62\n%6d\n 8\n%s\n", matchdxfcolor(style->color), lname); } else { char *title=(p->numvalues) ? p->values[0] : ""; first = 1; im_iprintf (&imgStr, "line[j].point[p->line[j].numpoints-1] ); */ for(i=0; i < p->line[j].numpoints; i++,l++) { if (dxf == 2) { im_iprintf (&imgStr, "%.0f %.0f\n", p->line[j].point[i].x, p->line[j].point[i].y); } else if (dxf) { im_iprintf (&imgStr, " 0\nVERTEX\n 10\n%f\n 20\n%f\n 30\n%f\n", p->line[j].point[i].x, p->line[j].point[i].y, 0.0); } else { im_iprintf (&imgStr, "%s %.0f,%.0f", first ? "": ",", p->line[j].point[i].x, p->line[j].point[i].y); } first = 0; /* point2 = &( p->line[j].point[i] ); */ /* if(point1->y == point2->y) {} */ } im_iprintf (&imgStr, dxf ? (dxf == 2 ? "": " 0\nSEQEND\n") : "\" />\n"); } return; } /* DEBUG_IF printf ("d"); */ DEBUG_IF printf("-%d-",symbol->type); return; } /* * Simply draws a label based on the label point and the supplied label object. */ int msDrawTextIM(mapObj *map, imageObj* img, pointObj labelPnt, char *string, labelObj *label, double scalefactor) { DEBUG_IF printf("msDrawText
\n"); if(!string) return(0); /* not errors, just don't want to do anything */ if(strlen(string) == 0) return(0); if(!dxf) return (0); if (dxf == 2) { im_iprintf (&imgStr, "TEXT\n%d\n%s\n%.0f\n%.0f\n%.0f\n" , matchdxfcolor(label->color), string, labelPnt.x, labelPnt.y, -label->angle); } else if (dxf) { im_iprintf (&imgStr, " 0\nTEXT\n 1\n%s\n 10\n%f\n 20\n%f\n 30\n0.0\n 40\n%f\n 50\n%f\n 62\n%6d\n 8\n%s\n 73\n 2\n 72\n 1\n" , string, labelPnt.x, labelPnt.y, label->size * scalefactor *100, -label->angle, matchdxfcolor(label->color), lname); } return(0); } /* * Save an image to a file named filename, if filename is NULL it goes to stdout */ int msSaveImageIM(imageObj* img, const char *filename, outputFormatObj *format ) { FILE *stream; char workbuffer[5000]; int nSize=0, size=0, iIndice=0; DEBUG_IF printf("msSaveImageIM\n
"); if(filename != NULL && strlen(filename) > 0) { stream = fopen(filename, "wb"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msSaveImage()", filename); return(MS_FAILURE); } } else { /* use stdout */ #ifdef _WIN32 /* * Change stdout mode to binary on win32 platforms */ if(_setmode( _fileno(stdout), _O_BINARY) == -1) { msSetError(MS_IOERR, "Unable to change stdout to binary mode.", "msSaveImage()"); return(MS_FAILURE); } #endif stream = stdout; } if( strcasecmp(format->driver,"imagemap") == 0 ) { DEBUG_IF printf("ALLOCD %d
\n", img->size); /* DEBUG_IF printf("F %s
\n", img->img.imagemap); */ DEBUG_IF printf("FLEN %d
\n", (int)strlen(img->img.imagemap)); if (dxf == 2) { msIO_fprintf(stream, "%s", layerlist); } else if (dxf) { msIO_fprintf(stream, " 0\nSECTION\n 2\nHEADER\n 9\n$ACADVER\n 1\nAC1009\n0\nENDSEC\n 0\nSECTION\n 2\nTABLES\n 0\nTABLE\n%s0\nENDTAB\n0\nENDSEC\n 0\nSECTION\n 2\nBLOCKS\n0\nENDSEC\n 0\nSECTION\n 2\nENTITIES\n", layerlist); } else { msIO_fprintf(stream, "\n", mapName, img->width, img->height); } nSize = sizeof(workbuffer); size = strlen(img->img.imagemap); if (size > nSize) { iIndice = 0; while ((iIndice + nSize) <= size) { snprintf(workbuffer, sizeof(workbuffer), "%s", img->img.imagemap+iIndice ); workbuffer[nSize-1] = '\0'; msIO_fwrite(workbuffer, strlen(workbuffer), 1, stream); iIndice +=nSize-1; } if (iIndice < size) { sprintf(workbuffer, "%s", img->img.imagemap+iIndice ); msIO_fprintf(stream, "%s", workbuffer); } } else msIO_fwrite(img->img.imagemap, size, 1, stream); if( strcasecmp("OFF",msGetOutputFormatOption( format, "SKIPENDTAG", "OFF" )) == 0) { if (dxf == 2) msIO_fprintf(stream, "END"); else if (dxf) msIO_fprintf(stream, "0\nENDSEC\n0\nEOF\n"); else msIO_fprintf(stream, ""); } } else { msSetError(MS_MISCERR, "Unknown output image type driver: %s.", "msSaveImage()", format->driver ); return(MS_FAILURE); } if(filename != NULL && strlen(filename) > 0) fclose(stream); return(MS_SUCCESS); } /* * Free gdImagePtr */ void msFreeImageIM(imageObj* img) { free(img->img.imagemap); } mapserver-7.4.3/mapio.c000066400000000000000000001122121357574274700150260ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementations for MapServer IO redirection capability. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2004, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include "mapserver.h" #include "mapthread.h" #ifdef _WIN32 #include #include #endif #ifdef MOD_WMS_ENABLED # include "httpd.h" # include "apr_strings.h" #endif static int is_msIO_initialized = MS_FALSE; static int is_msIO_header_enabled = MS_TRUE; typedef struct msIOContextGroup_t { msIOContext stdin_context; msIOContext stdout_context; msIOContext stderr_context; void* thread_id; struct msIOContextGroup_t *next; } msIOContextGroup; static msIOContextGroup default_contexts; static msIOContextGroup *io_context_list = NULL; static void msIO_Initialize( void ); #ifdef msIO_printf # undef msIO_printf # undef msIO_fprintf # undef msIO_fwrite # undef msIO_fread # undef msIO_vfprintf #endif /************************************************************************/ /* msIO_Cleanup() */ /************************************************************************/ void msIO_Cleanup() { if( is_msIO_initialized ) { is_msIO_initialized = MS_FALSE; while( io_context_list != NULL ) { msIOContextGroup *last = io_context_list; io_context_list = io_context_list->next; free( last ); } } } /************************************************************************/ /* msIO_GetContextGroup() */ /************************************************************************/ static msIOContextGroup *msIO_GetContextGroup() { void* nThreadId = msGetThreadId(); msIOContextGroup *prev = NULL, *group = io_context_list; if( group != NULL && group->thread_id == nThreadId ) return group; /* -------------------------------------------------------------------- */ /* Search for group for this thread */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_IOCONTEXT ); msIO_Initialize(); group = io_context_list; while( group != NULL && group->thread_id != nThreadId ) { prev = group; group = group->next; } /* -------------------------------------------------------------------- */ /* If we found it, make sure it is pushed to the front of the */ /* link for faster finding next time, and return it. */ /* -------------------------------------------------------------------- */ if( group != NULL ) { if( prev != NULL ) { prev->next = group->next; group->next = io_context_list; io_context_list = group; } msReleaseLock( TLOCK_IOCONTEXT ); return group; } /* -------------------------------------------------------------------- */ /* Create a new context group for this thread. */ /* -------------------------------------------------------------------- */ group = (msIOContextGroup *) calloc(sizeof(msIOContextGroup),1); group->stdin_context = default_contexts.stdin_context; group->stdout_context = default_contexts.stdout_context; group->stderr_context = default_contexts.stderr_context; group->thread_id = nThreadId; group->next = io_context_list; io_context_list = group; msReleaseLock( TLOCK_IOCONTEXT ); return group; } /* returns MS_TRUE if the msIO standard output hasn't been redirected */ int msIO_isStdContext() { msIOContextGroup *group = io_context_list; void* nThreadId = msGetThreadId(); if(!group || group->thread_id != nThreadId) { group = msIO_GetContextGroup(); if(!group) { return MS_FALSE; /* probably a bug */ } } if(group->stderr_context.cbData == (void*)stderr && group->stdin_context.cbData == (void*)stdin && group->stdout_context.cbData == (void*)stdout) return MS_TRUE; return MS_FALSE; } /************************************************************************/ /* msIO_getHandler() */ /************************************************************************/ msIOContext *msIO_getHandler( FILE * fp ) { void* nThreadId = msGetThreadId(); msIOContextGroup *group = io_context_list; msIO_Initialize(); if( group == NULL || group->thread_id != nThreadId ) { group = msIO_GetContextGroup(); if( group == NULL ) return NULL; } if( fp == stdin || fp == NULL || strcmp((const char *)fp,"stdin") == 0 ) return &(group->stdin_context); else if( fp == stdout || strcmp((const char *)fp,"stdout") == 0 ) return &(group->stdout_context); else if( fp == stderr || strcmp((const char *)fp,"stderr") == 0 ) return &(group->stderr_context); else return NULL; } /************************************************************************/ /* msIO_setHeaderEnabled() */ /************************************************************************/ void msIO_setHeaderEnabled(int bFlag) { is_msIO_header_enabled = bFlag; } /************************************************************************/ /* msIO_setHeader() */ /************************************************************************/ void msIO_setHeader (const char *header, const char* value, ...) { va_list args; va_start( args, value ); #ifdef MOD_WMS_ENABLED msIOContext *ioctx = msIO_getHandler (stdout); if(ioctx && !strcmp(ioctx->label,"apache")) { request_rec *r = (request_rec*) (ioctx->cbData); char *fullvalue = apr_pvsprintf(r->pool, value,args); if (strcasecmp (header, "Content-Type") == 0) { r->content_type = fullvalue; } else if (strcasecmp (header, "Status") == 0) { r->status = atoi (fullvalue); } else { apr_table_setn (r->headers_out, apr_pstrdup (r->pool, header), fullvalue ); } } else { #endif // MOD_WMS_ENABLED if( is_msIO_header_enabled ) { msIO_fprintf(stdout,"%s: ",header); msIO_vfprintf(stdout,value,args); msIO_fprintf(stdout,"\r\n"); } #ifdef MOD_WMS_ENABLED } #endif va_end( args ); } void msIO_sendHeaders () { #ifdef MOD_WMS_ENABLED msIOContext *ioctx = msIO_getHandler (stdout); if(ioctx && !strcmp(ioctx->label,"apache")) return; #endif // !MOD_WMS_ENABLED if( is_msIO_header_enabled ) { msIO_printf ("\r\n"); fflush (stdout); } } /************************************************************************/ /* msIO_installHandlers() */ /************************************************************************/ int msIO_installHandlers( msIOContext *stdin_context, msIOContext *stdout_context, msIOContext *stderr_context ) { msIOContextGroup *group; msIO_Initialize(); group = msIO_GetContextGroup(); if( stdin_context == NULL ) group->stdin_context = default_contexts.stdin_context; else if( stdin_context != &group->stdin_context ) group->stdin_context = *stdin_context; if( stdout_context == NULL ) group->stdout_context = default_contexts.stdout_context; else if( stdout_context != &group->stdout_context ) group->stdout_context = *stdout_context; if( stderr_context == NULL ) group->stderr_context = default_contexts.stderr_context; else if( stderr_context != &group->stderr_context ) group->stderr_context = *stderr_context; return MS_TRUE; } /************************************************************************/ /* msIO_contextRead() */ /************************************************************************/ int msIO_contextRead( msIOContext *context, void *data, int byteCount ) { if( context->write_channel == MS_TRUE ) return 0; else return context->readWriteFunc( context->cbData, data, byteCount ); } /************************************************************************/ /* msIO_contextWrite() */ /************************************************************************/ int msIO_contextWrite( msIOContext *context, const void *data, int byteCount ) { if( context->write_channel == MS_FALSE ) return 0; else return context->readWriteFunc( context->cbData, (void *) data, byteCount ); } /* ==================================================================== */ /* ==================================================================== */ /* Stdio-like cover functions. */ /* ==================================================================== */ /* ==================================================================== */ /************************************************************************/ /* _ms_vsprintf() */ /************************************************************************/ static int _ms_vsprintf(char **workBufPtr, const char *format, va_list ap ) { int ret_val; int workBufSize = 16000; *workBufPtr = (char*)malloc(workBufSize * sizeof(char)); if (*workBufPtr == NULL) { msSetError( MS_MEMERR, NULL, "_ms_vsprintf()"); return -1; } #if defined(HAVE_VSNPRINTF) /* This should grow a big enough buffer to hold any formatted result. */ { va_list wrk_args; #ifdef va_copy va_copy( wrk_args, ap ); #else wrk_args = ap; #endif while( (ret_val = vsnprintf( *workBufPtr, workBufSize, format, wrk_args)) >= workBufSize-1 || ret_val == -1 ) { workBufSize *= 4; *workBufPtr = (char *) realloc(*workBufPtr, workBufSize ); if (*workBufPtr == NULL) { msSetError( MS_MEMERR, NULL, "_ms_vsprintf()"); va_end( wrk_args ); return -1; } #ifdef va_copy va_end( wrk_args ); va_copy( wrk_args, ap ); #else wrk_args = ap; #endif } va_end( wrk_args ); } #else /* We do not have vsnprintf()... there is a risk of buffer overrun */ ret_val = vsprintf( *workBufPtr, format, ap ); if( ret_val < 0 || ret_val >= workBufSize ) { msSetError(MS_MISCERR, "Possible buffer overrun.", "_ms_vsprintf()"); msFree(*workBufPtr); *workBufPtr = NULL; return -1; } #endif return ret_val; } /************************************************************************/ /* msIO_printf() */ /************************************************************************/ int msIO_printf( const char *format, ... ) { va_list args; int ret; va_start( args, format ); ret = msIO_vfprintf(stdout,format,args); va_end(args); return ret; } /************************************************************************/ /* msIO_fprintf() */ /************************************************************************/ int msIO_fprintf( FILE *fp, const char *format, ... ) { va_list args; int ret; va_start( args, format ); ret = msIO_vfprintf(fp,format,args); va_end(args); return ret; } /************************************************************************/ /* msIO_vfprintf() */ /************************************************************************/ int msIO_vfprintf( FILE *fp, const char *format, va_list ap ) { va_list args_copy; int return_val; msIOContext *context; char workBuf[8000], *largerBuf = NULL; #if !defined(HAVE_VSNPRINTF) return_val = vsprintf( workBuf, format, ap); if( return_val < 0 || return_val >= sizeof(workBuf) ) { msSetError(MS_MISCERR, "Possible buffer overrun.", "msIO_vfprintf()"); return -1; } #else #ifdef va_copy va_copy( args_copy, ap ); #else args_copy = ap; #endif /* va_copy */ return_val = vsnprintf( workBuf, sizeof(workBuf), format, ap ); if (return_val == -1 || return_val >= sizeof(workBuf)-1) { return_val = _ms_vsprintf(&largerBuf, format, args_copy ); } va_end(args_copy); #endif /* HAVE_VSNPRINTF */ if (return_val < 0) return -1; context = msIO_getHandler( fp ); if( context == NULL ) return_val = fwrite( largerBuf?largerBuf:workBuf, 1, return_val, fp ); else return_val = msIO_contextWrite( context, largerBuf?largerBuf:workBuf, return_val ); msFree(largerBuf); return return_val; } /************************************************************************/ /* msIO_fwrite() */ /************************************************************************/ int msIO_fwrite( const void *data, size_t size, size_t nmemb, FILE *fp ) { msIOContext *context; if( size == 0 || nmemb == 0 ) return 0; context = msIO_getHandler( fp ); if( context == NULL ) return fwrite( data, size, nmemb, fp ); else return msIO_contextWrite( context, data, size * nmemb ) / size; } /************************************************************************/ /* msIO_fread() */ /************************************************************************/ int msIO_fread( void *data, size_t size, size_t nmemb, FILE *fp ) { msIOContext *context; if( size == 0 || nmemb == 0 ) return 0; context = msIO_getHandler( fp ); if( context == NULL ) return fread( data, size, nmemb, fp ); else return msIO_contextRead( context, data, size * nmemb ) / size; } /* ==================================================================== */ /* ==================================================================== */ /* Internal default callbacks implementing stdio reading and */ /* writing. */ /* ==================================================================== */ /* ==================================================================== */ /************************************************************************/ /* msIO_stdioRead() */ /* */ /* This is the default implementation via stdio. */ /************************************************************************/ static int msIO_stdioRead( void *cbData, void *data, int byteCount ) { return fread( data, 1, byteCount, (FILE *) cbData ); } /************************************************************************/ /* msIO_stdioWrite() */ /* */ /* This is the default implementation via stdio. */ /************************************************************************/ static int msIO_stdioWrite( void *cbData, void *data, int byteCount ) { return fwrite( data, 1, byteCount, (FILE *) cbData ); } /************************************************************************/ /* msIO_Initialize() */ /************************************************************************/ static void msIO_Initialize( void ) { if( is_msIO_initialized == MS_TRUE ) return; default_contexts.stdin_context.label = "stdio"; default_contexts.stdin_context.write_channel = MS_FALSE; default_contexts.stdin_context.readWriteFunc = msIO_stdioRead; default_contexts.stdin_context.cbData = (void *) stdin; default_contexts.stdout_context.label = "stdio"; default_contexts.stdout_context.write_channel = MS_TRUE; default_contexts.stdout_context.readWriteFunc = msIO_stdioWrite; default_contexts.stdout_context.cbData = (void *) stdout; default_contexts.stderr_context.label = "stdio"; default_contexts.stderr_context.write_channel = MS_TRUE; default_contexts.stderr_context.readWriteFunc = msIO_stdioWrite; default_contexts.stderr_context.cbData = (void *) stderr; default_contexts.next = NULL; default_contexts.thread_id = 0; is_msIO_initialized = MS_TRUE; } /* ==================================================================== */ /* ==================================================================== */ /* FastCGI output redirection functions. */ /* ==================================================================== */ /* ==================================================================== */ /************************************************************************/ /* msIO_needBinaryStdout() */ /* */ /* This function is intended to ensure that stdout is in binary */ /* mode. */ /* */ /* But don't do it we are using FastCGI. We will take care of */ /* doing it in the libfcgi library in that case for the normal */ /* cgi case, and for the fastcgi case the _setmode() call */ /* causes a crash. */ /************************************************************************/ int msIO_needBinaryStdout() { #if defined(_WIN32) && !defined(USE_FASTCGI) if(_setmode( _fileno(stdout), _O_BINARY) == -1) { msSetError(MS_IOERR, "Unable to change stdout to binary mode.", "msIO_needBinaryStdout()" ); return(MS_FAILURE); } #endif return MS_SUCCESS; } /************************************************************************/ /* msIO_needBinaryStdin() */ /* */ /* This function is intended to ensure that stdin is in binary */ /* mode. */ /* */ /* But don't do it we are using FastCGI. We will take care of */ /* doing it in the libfcgi library in that case for the normal */ /* cgi case, and for the fastcgi case the _setmode() call */ /* causes a crash. */ /************************************************************************/ int msIO_needBinaryStdin() { #if defined(_WIN32) && !defined(USE_FASTCGI) if(_setmode( _fileno(stdin), _O_BINARY) == -1) { msSetError(MS_IOERR, "Unable to change stdin to binary mode.", "msIO_needBinaryStdin()" ); return(MS_FAILURE); } #endif return MS_SUCCESS; } /* ==================================================================== */ /* memory buffer io handling functions. */ /* ==================================================================== */ /************************************************************************/ /* msIO_resetHandlers() */ /************************************************************************/ void msIO_resetHandlers() { msIOContextGroup *group = msIO_GetContextGroup(); if( group == NULL ) return; if( strcmp(group->stdin_context.label,"buffer") == 0 ) { msIOBuffer *buf = (msIOBuffer *) group->stdin_context.cbData; if( buf->data != NULL ) free( buf->data ); free( buf ); } if( strcmp(group->stdout_context.label,"buffer") == 0 ) { msIOBuffer *buf = (msIOBuffer *) group->stdout_context.cbData; if( buf->data != NULL ) free( buf->data ); free( buf ); } if( strcmp(group->stderr_context.label,"buffer") == 0 ) { msIOBuffer *buf = (msIOBuffer *) group->stderr_context.cbData; if( buf->data != NULL ) free( buf->data ); free( buf ); } msIO_installHandlers( NULL, NULL, NULL ); } /************************************************************************/ /* msIO_installStdoutToBuffer() */ /************************************************************************/ void msIO_installStdoutToBuffer() { msIOContextGroup *group = msIO_GetContextGroup(); msIOContext context; context.label = "buffer"; context.write_channel = MS_TRUE; context.readWriteFunc = msIO_bufferWrite; context.cbData = calloc(sizeof(msIOBuffer),1); msIO_installHandlers( &group->stdin_context, &context, &group->stderr_context ); } /************************************************************************/ /* msIO_pushStdoutToBufferAndGetOldContext() */ /* */ /* This function installs a temporary buffer I/O context and returns */ /* previously installed stdout handler. This previous stdout handler */ /* should later be restored with msIO_restoreOldStdoutContext(). */ /* This function can be for example used when wanting to ingest into */ /* libxml objects XML generated by msIO_fprintf() */ /************************************************************************/ msIOContext* msIO_pushStdoutToBufferAndGetOldContext() { msIOContextGroup *group = msIO_GetContextGroup(); msIOContext *old_context; /* Backup current context */ old_context = (msIOContext*) msSmallMalloc(sizeof(msIOContext)); memcpy(old_context, &group->stdout_context, sizeof(msIOContext)); msIO_installStdoutToBuffer(); return old_context; } /************************************************************************/ /* msIO_restoreOldStdoutContext() */ /************************************************************************/ void msIO_restoreOldStdoutContext(msIOContext *context_to_restore) { msIOContextGroup *group = msIO_GetContextGroup(); msIOContext *prev_context = &group->stdout_context; msIOBuffer* buffer; /* Free memory associated to our temporary context */ assert( strcmp(prev_context->label, "buffer") == 0 ); buffer = (msIOBuffer* )prev_context->cbData; msFree(buffer->data); msFree(buffer); /* Restore old context */ msIO_installHandlers( &group->stdin_context, context_to_restore, &group->stderr_context ); msFree(context_to_restore); } /************************************************************************/ /* msIO_installStdinFromBuffer() */ /************************************************************************/ void msIO_installStdinFromBuffer() { msIOContextGroup *group = msIO_GetContextGroup(); msIOContext context; context.label = "buffer"; context.write_channel = MS_FALSE; context.readWriteFunc = msIO_bufferRead; context.cbData = calloc(sizeof(msIOBuffer),1); msIO_installHandlers( &context, &group->stdout_context, &group->stderr_context ); } /************************************************************************/ /* msIO_getAndStripStdoutBufferMimeHeaders() */ /* */ /************************************************************************/ hashTableObj* msIO_getAndStripStdoutBufferMimeHeaders() { /* -------------------------------------------------------------------- */ /* Find stdout buffer. */ /* -------------------------------------------------------------------- */ msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; int start_of_mime_header, current_pos; hashTableObj* hashTable; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_getAndStripStdoutBufferMimeHeaders" ); return NULL; } buf = (msIOBuffer *) ctx->cbData; hashTable = msCreateHashTable(); /* -------------------------------------------------------------------- */ /* Loop over all headers. */ /* -------------------------------------------------------------------- */ current_pos = 0; while( MS_TRUE ) { int pos_of_column = -1; char* key, *value; start_of_mime_header = current_pos; while( current_pos < buf->data_offset ) { if( buf->data[current_pos] == '\r' ) { if( current_pos + 1 == buf->data_offset || buf->data[current_pos + 1] != '\n' ) { pos_of_column = -1; break; } break; } if( buf->data[current_pos] == ':' ) { pos_of_column = current_pos; if( current_pos + 1 == buf->data_offset || buf->data[current_pos + 1] != ' ' ) { pos_of_column = -1; break; } } current_pos++; } if( pos_of_column < 0 || current_pos == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt mime headers.", "msIO_getAndStripStdoutBufferMimeHeaders" ); msFreeHashTable(hashTable); return NULL; } key = (char*) malloc( pos_of_column - start_of_mime_header + 1 ); memcpy( key, buf->data+start_of_mime_header, pos_of_column - start_of_mime_header); key[pos_of_column - start_of_mime_header] = '\0'; value = (char*) malloc( current_pos - (pos_of_column+2) + 1 ); memcpy( value, buf->data+pos_of_column+2, current_pos - (pos_of_column+2)); value[current_pos - (pos_of_column+2)] = '\0'; msInsertHashTable( hashTable, key, value ); msFree( key ); msFree( value ); /* -------------------------------------------------------------------- */ /* Go to next line. */ /* -------------------------------------------------------------------- */ current_pos += 2; if( current_pos == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt mime headers.", "msIO_getAndStripStdoutBufferMimeHeaders" ); msFreeHashTable(hashTable); return NULL; } /* If next line is a '\r', this is the end of mime headers. */ if( buf->data[current_pos] == '\r' ) { current_pos ++; if( current_pos == buf->data_offset || buf->data[current_pos] != '\n' ) { msSetError( MS_MISCERR, "Corrupt mime headers.", "msIO_getAndStripStdoutBufferMimeHeaders" ); msFreeHashTable(hashTable); return NULL; } current_pos ++; break; } } /* -------------------------------------------------------------------- */ /* Move data to front of buffer, and reset length. */ /* -------------------------------------------------------------------- */ memmove( buf->data, buf->data+current_pos, buf->data_offset - current_pos ); buf->data[buf->data_offset - current_pos] = '\0'; buf->data_offset -= current_pos; return hashTable; } /************************************************************************/ /* msIO_stripStdoutBufferContentType() */ /* */ /* Strip off Content-Type header from buffer, and return to */ /* caller. Returned string is the callers responsibility to */ /* call msFree() on to deallocate. This function will return */ /* NULL if there is no Content-Type header. */ /************************************************************************/ char *msIO_stripStdoutBufferContentType() { /* -------------------------------------------------------------------- */ /* Find stdout buffer. */ /* -------------------------------------------------------------------- */ msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; char *content_type = NULL; int end_of_ct, start_of_data; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_stripStdoutBufferContentType" ); return NULL; } buf = (msIOBuffer *) ctx->cbData; /* -------------------------------------------------------------------- */ /* Return NULL if we don't have a Content-Type header. */ /* -------------------------------------------------------------------- */ if( buf->data_offset < 14 || strncasecmp((const char*) buf->data,"Content-Type: ",14) != 0 ) return NULL; /* -------------------------------------------------------------------- */ /* Find newline marker at end of content type argument. */ /* -------------------------------------------------------------------- */ end_of_ct = 13; while( end_of_ct+1 < buf->data_offset && buf->data[end_of_ct+1] != '\r' ) end_of_ct++; if( end_of_ct+1 == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt Content-Type header.", "msIO_stripStdoutBufferContentType" ); return NULL; } /* -------------------------------------------------------------------- */ /* Continue on to the start of data ... */ /* Go to next line and skip if empty. */ /* -------------------------------------------------------------------- */ start_of_data = end_of_ct+3; if( start_of_data < buf->data_offset && buf->data[start_of_data] == '\r' ) start_of_data +=2; if( start_of_data == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt Content-Type header.", "msIO_stripStdoutBufferContentType" ); return NULL; } /* -------------------------------------------------------------------- */ /* Copy out content type. Note we go against the coding guidelines */ /* here and use strncpy() instead of strlcpy() as the source */ /* buffer may not be NULL terminated - strlcpy() requires NULL */ /* terminated sources (see issue #4672). */ /* -------------------------------------------------------------------- */ content_type = (char *) malloc(end_of_ct-14+2); strncpy( content_type, (const char *) buf->data + 14, end_of_ct - 14 + 2); content_type[end_of_ct-14+1] = '\0'; /* -------------------------------------------------------------------- */ /* Move data to front of buffer, and reset length. */ /* -------------------------------------------------------------------- */ memmove( buf->data, buf->data+start_of_data, buf->data_offset - start_of_data ); buf->data[buf->data_offset - start_of_data] = '\0'; buf->data_offset -= start_of_data; return content_type; } /************************************************************************/ /* msIO_stripStdoutBufferContentHeaders() */ /* */ /* Strip off Content-* headers from buffer. */ /************************************************************************/ void msIO_stripStdoutBufferContentHeaders() { /* -------------------------------------------------------------------- */ /* Find stdout buffer. */ /* -------------------------------------------------------------------- */ msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; int start_of_data; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_stripStdoutBufferContentHeaders" ); return; } buf = (msIOBuffer *) ctx->cbData; /* -------------------------------------------------------------------- */ /* Exit if we don't have any content-* header. */ /* -------------------------------------------------------------------- */ if( buf->data_offset < 8 || strncasecmp((const char*) buf->data,"Content-",8) != 0 ) return; /* -------------------------------------------------------------------- */ /* Loop over all content-* headers. */ /* -------------------------------------------------------------------- */ start_of_data = 0; while( buf->data_offset > start_of_data && strncasecmp((const char*) buf->data+start_of_data,"Content-",8) == 0 ) { /* -------------------------------------------------------------------- */ /* Find newline marker at end of content-* header argument. */ /* -------------------------------------------------------------------- */ start_of_data +=7; while( start_of_data+1 < buf->data_offset && buf->data[start_of_data+1] != '\r' ) start_of_data++; if( start_of_data+1 == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt Content-* header.", "msIO_stripStdoutBufferContentHeaders" ); return; } /* -------------------------------------------------------------------- */ /* Go to next line. */ /* -------------------------------------------------------------------- */ start_of_data +=3; } /* -------------------------------------------------------------------- */ /* Continue on to the start of data ... */ /* Skip next line if empty. */ /* -------------------------------------------------------------------- */ if( start_of_data < buf->data_offset && buf->data[start_of_data] == '\r' ) start_of_data +=2; if( start_of_data == buf->data_offset ) { msSetError( MS_MISCERR, "Corrupt Content-* header.", "msIO_stripStdoutBufferContentHeaders" ); return; } /* -------------------------------------------------------------------- */ /* Move data to front of buffer, and reset length. */ /* -------------------------------------------------------------------- */ memmove( buf->data, buf->data+start_of_data, buf->data_offset - start_of_data ); buf->data[buf->data_offset - start_of_data] = '\0'; buf->data_offset -= start_of_data; return; } /************************************************************************/ /* msIO_bufferWrite() */ /************************************************************************/ int msIO_bufferWrite( void *cbData, void *data, int byteCount ) { msIOBuffer *buf = (msIOBuffer *) cbData; /* ** Grow buffer if needed (reserve one extra byte to put nul character) */ if( buf->data_offset + byteCount >= buf->data_len ) { buf->data_len = buf->data_len * 2 + byteCount + 100; if( buf->data == NULL ) buf->data = (unsigned char *) malloc(buf->data_len); else buf->data = (unsigned char *) realloc(buf->data, buf->data_len); if( buf->data == NULL ) { msSetError( MS_MEMERR, "Failed to allocate %d bytes for capture buffer.", "msIO_bufferWrite()", buf->data_len ); buf->data_len = 0; return 0; } } /* ** Copy result into buffer. */ memcpy( buf->data + buf->data_offset, data, byteCount ); buf->data_offset += byteCount; buf->data[buf->data_offset] = '\0'; return byteCount; } /************************************************************************/ /* msIO_bufferRead() */ /************************************************************************/ int msIO_bufferRead( void *cbData, void *data, int byteCount ) { /* msIOBuffer *buf = (msIOBuffer *) cbData; */ /* not implemented yet. */ return 0; } mapserver-7.4.3/mapio.h000066400000000000000000000115341357574274700150400ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Definitions for MapServer IO redirection capability. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2004, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPIO_H #define MAPIO_H /* ** We deliberately emulate stdio functions in the msIO cover functions. ** This makes it easy for folks to understand the semantics, and means we ** can just #define things to use stdio in the simplest case. */ #include #include "maphash.h" #ifdef __cplusplus extern "C" { #endif #ifndef MS_PRINT_FUNC_FORMAT #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP) #define MS_PRINT_FUNC_FORMAT( format_idx, arg_idx ) __attribute__((__format__ (__printf__, format_idx, arg_idx))) #else #define MS_PRINT_FUNC_FORMAT( format_idx, arg_idx ) #endif #endif /* stdio analogs */ int MS_DLL_EXPORT msIO_printf( const char *format, ... ) MS_PRINT_FUNC_FORMAT(1,2); int MS_DLL_EXPORT msIO_fprintf( FILE *stream, const char *format, ... ) MS_PRINT_FUNC_FORMAT(2,3); int MS_DLL_EXPORT msIO_fwrite( const void *ptr, size_t size, size_t nmemb, FILE *stream ); int MS_DLL_EXPORT msIO_fread( void *ptr, size_t size, size_t nmemb, FILE *stream ); int MS_DLL_EXPORT msIO_vfprintf( FILE *fp, const char *format, va_list ap ) MS_PRINT_FUNC_FORMAT(2,0); /* ** Definitions for the callback function and the details of the IO ** channel contexts. */ typedef int (*msIO_llReadWriteFunc)( void *cbData, void *data, int byteCount ); typedef struct msIOContext_t { const char *label; int write_channel; /* 1 for stdout/stderr, 0 for stdin */ msIO_llReadWriteFunc readWriteFunc; void *cbData; } msIOContext; int MS_DLL_EXPORT msIO_installHandlers( msIOContext *stdin_context, msIOContext *stdout_context, msIOContext *stderr_context ); msIOContext MS_DLL_EXPORT *msIO_getHandler( FILE * ); void MS_DLL_EXPORT msIO_setHeaderEnabled(int bFlag); void msIO_setHeader (const char *header, const char* value, ...) MS_PRINT_FUNC_FORMAT(2,3); void msIO_sendHeaders(void); /* ** These can be used instead of the stdio style functions if you have ** msIOContext's for the channel in question. */ int msIO_contextRead( msIOContext *context, void *data, int byteCount ); int msIO_contextWrite( msIOContext *context, const void *data, int byteCount ); /* ** For redirecting IO to a memory buffer. */ typedef struct { unsigned char *data; int data_len; /* really buffer length */ int data_offset; /* really buffer used */ } msIOBuffer; int MS_DLL_EXPORT msIO_bufferRead( void *, void *, int ); int MS_DLL_EXPORT msIO_bufferWrite( void *, void *, int ); void MS_DLL_EXPORT msIO_resetHandlers(void); void MS_DLL_EXPORT msIO_installStdoutToBuffer(void); void MS_DLL_EXPORT msIO_installStdinFromBuffer(void); void MS_DLL_EXPORT msIO_Cleanup(void); char MS_DLL_EXPORT *msIO_stripStdoutBufferContentType(void); void MS_DLL_EXPORT msIO_stripStdoutBufferContentHeaders(void); hashTableObj MS_DLL_EXPORT *msIO_getAndStripStdoutBufferMimeHeaders(void); msIOContext *msIO_pushStdoutToBufferAndGetOldContext(void); void msIO_restoreOldStdoutContext(msIOContext *context_to_restore); int MS_DLL_EXPORT msIO_isStdContext(void); /* this is just for setting normal stdout's to binary mode on windows */ int msIO_needBinaryStdout( void ); int msIO_needBinaryStdin( void ); #ifdef __cplusplus } #endif #endif /* nef MAPIO_H */ mapserver-7.4.3/mapjoin.c000066400000000000000000000601201357574274700153560ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implements MapServer joins. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #define ROW_ALLOCATION_SIZE 10 /* DBF/XBase function prototypes */ int msDBFJoinConnect(layerObj *layer, joinObj *join); int msDBFJoinPrepare(joinObj *join, shapeObj *shape); int msDBFJoinNext(joinObj *join); int msDBFJoinClose(joinObj *join); int msDBFJoinTable(layerObj *layer, joinObj *join, shapeObj *shape); /* CSV (comma delimited text file) function prototypes */ int msCSVJoinConnect(layerObj *layer, joinObj *join); int msCSVJoinPrepare(joinObj *join, shapeObj *shape); int msCSVJoinNext(joinObj *join); int msCSVJoinClose(joinObj *join); int msCSVJoinTable(layerObj *layer, joinObj *join, shapeObj *shape); /* MySQL function prototypes */ int msMySQLJoinConnect(layerObj *layer, joinObj *join); int msMySQLJoinPrepare(joinObj *join, shapeObj *shape); int msMySQLJoinNext(joinObj *join); int msMySQLJoinClose(joinObj *join); int msMySQLJoinTable(layerObj *layer, joinObj *join, shapeObj *shape); /* PostgreSQL function prototypes */ int msPOSTGRESQLJoinConnect(layerObj *layer, joinObj *join); int msPOSTGRESQLJoinPrepare(joinObj *join, shapeObj *shape); int msPOSTGRESQLJoinNext(joinObj *join); int msPOSTGRESQLJoinClose(joinObj *join); /* wrapper function for DB specific join functions */ int msJoinConnect(layerObj *layer, joinObj *join) { switch(join->connectiontype) { case(MS_DB_XBASE): return msDBFJoinConnect(layer, join); break; case(MS_DB_CSV): return msCSVJoinConnect(layer, join); break; case(MS_DB_MYSQL): return msMySQLJoinConnect(layer, join); break; case(MS_DB_POSTGRES): return msPOSTGRESQLJoinConnect(layer, join); break; default: break; } msSetError(MS_JOINERR, "Unsupported join connection type.", "msJoinConnect()"); return MS_FAILURE; } int msJoinPrepare(joinObj *join, shapeObj *shape) { switch(join->connectiontype) { case(MS_DB_XBASE): return msDBFJoinPrepare(join, shape); break; case(MS_DB_CSV): return msCSVJoinPrepare(join, shape); break; case(MS_DB_MYSQL): return msMySQLJoinPrepare(join, shape); break; case(MS_DB_POSTGRES): return msPOSTGRESQLJoinPrepare(join, shape); break; default: break; } msSetError(MS_JOINERR, "Unsupported join connection type.", "msJoinPrepare()"); return MS_FAILURE; } int msJoinNext(joinObj *join) { switch(join->connectiontype) { case(MS_DB_XBASE): return msDBFJoinNext(join); break; case(MS_DB_CSV): return msCSVJoinNext(join); break; case(MS_DB_MYSQL): return msMySQLJoinNext(join); break; case(MS_DB_POSTGRES): return msPOSTGRESQLJoinNext(join); break; default: break; } msSetError(MS_JOINERR, "Unsupported join connection type.", "msJoinNext()"); return MS_FAILURE; } int msJoinClose(joinObj *join) { switch(join->connectiontype) { case(MS_DB_XBASE): return msDBFJoinClose(join); break; case(MS_DB_CSV): return msCSVJoinClose(join); break; case(MS_DB_MYSQL): return msMySQLJoinClose(join); break; case(MS_DB_POSTGRES): return msPOSTGRESQLJoinClose(join); break; default: break; } msSetError(MS_JOINERR, "Unsupported join connection type.", "msJoinClose()"); return MS_FAILURE; } /* */ /* XBASE join functions */ /* */ typedef struct { DBFHandle hDBF; int fromindex, toindex; char *target; int nextrecord; } msDBFJoinInfo; int msDBFJoinConnect(layerObj *layer, joinObj *join) { int i; char szPath[MS_MAXPATHLEN]; msDBFJoinInfo *joininfo; if(join->joininfo) return(MS_SUCCESS); /* already open */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; /* allocate a msDBFJoinInfo struct */ joininfo = (msDBFJoinInfo *) malloc(sizeof(msDBFJoinInfo)); if(!joininfo) { msSetError(MS_MEMERR, "Error allocating XBase table info structure.", "msDBFJoinConnect()"); return(MS_FAILURE); } /* initialize any members that won't get set later on in this function */ joininfo->target = NULL; joininfo->nextrecord = 0; join->joininfo = joininfo; /* open the XBase file */ if((joininfo->hDBF = msDBFOpen( msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, join->table), "rb" )) == NULL) { if((joininfo->hDBF = msDBFOpen( msBuildPath(szPath, layer->map->mappath, join->table), "rb" )) == NULL) { msSetError(MS_IOERR, "(%s)", "msDBFJoinConnect()", join->table); return(MS_FAILURE); } } /* get "to" item index */ if((joininfo->toindex = msDBFGetItemIndex(joininfo->hDBF, join->to)) == -1) { msSetError(MS_DBFERR, "Item %s not found in table %s.", "msDBFJoinConnect()", join->to, join->table); return(MS_FAILURE); } /* get "from" item index */ for(i=0; inumitems; i++) { if(strcasecmp(layer->items[i],join->from) == 0) { /* found it */ joininfo->fromindex = i; break; } } if(i == layer->numitems) { msSetError(MS_JOINERR, "Item %s not found in layer %s.", "msDBFJoinConnect()", join->from, layer->name); return(MS_FAILURE); } /* finally store away the item names in the XBase table */ join->numitems = msDBFGetFieldCount(joininfo->hDBF); join->items = msDBFGetItems(joininfo->hDBF); if(!join->items) return(MS_FAILURE); return(MS_SUCCESS); } int msDBFJoinPrepare(joinObj *join, shapeObj *shape) { msDBFJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msDBFJoinPrepare()"); return(MS_FAILURE); } if(!shape) { msSetError(MS_JOINERR, "Shape to be joined is empty.", "msDBFJoinPrepare()"); return(MS_FAILURE); } if(!shape->values) { msSetError(MS_JOINERR, "Shape to be joined has no attributes.", "msDBFJoinPrepare()"); return(MS_FAILURE); } joininfo->nextrecord = 0; /* starting with the first record */ if(joininfo->target) free(joininfo->target); /* clear last target */ joininfo->target = msStrdup(shape->values[joininfo->fromindex]); return(MS_SUCCESS); } int msDBFJoinNext(joinObj *join) { int i, n; msDBFJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msDBFJoinNext()"); return(MS_FAILURE); } if(!joininfo->target) { msSetError(MS_JOINERR, "No target specified, run msDBFJoinPrepare() first.", "msDBFJoinNext()"); return(MS_FAILURE); } /* clear any old data */ if(join->values) { msFreeCharArray(join->values, join->numitems); join->values = NULL; } n = msDBFGetRecordCount(joininfo->hDBF); for(i=joininfo->nextrecord; itarget, msDBFReadStringAttribute(joininfo->hDBF, i, joininfo->toindex)) == 0) break; } if(i == n) { /* unable to do the join */ if((join->values = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msDBFJoinNext()"); return(MS_FAILURE); } for(i=0; inumitems; i++) join->values[i] = msStrdup("\0"); /* intialize to zero length strings */ joininfo->nextrecord = n; return(MS_DONE); } if((join->values = msDBFGetValues(joininfo->hDBF,i)) == NULL) return(MS_FAILURE); joininfo->nextrecord = i+1; /* so we know where to start looking next time through */ return(MS_SUCCESS); } int msDBFJoinClose(joinObj *join) { msDBFJoinInfo *joininfo = join->joininfo; if(!joininfo) return(MS_SUCCESS); /* already closed */ if(joininfo->hDBF) msDBFClose(joininfo->hDBF); if(joininfo->target) free(joininfo->target); free(joininfo); joininfo = NULL; return(MS_SUCCESS); } /* */ /* CSV (comma separated value) join functions */ /* */ typedef struct { int fromindex, toindex; char *target; char ***rows; int numrows; int nextrow; } msCSVJoinInfo; int msCSVJoinConnect(layerObj *layer, joinObj *join) { int i; FILE *stream; char szPath[MS_MAXPATHLEN]; msCSVJoinInfo *joininfo; char buffer[MS_BUFFER_LENGTH]; if(join->joininfo) return(MS_SUCCESS); /* already open */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; /* allocate a msCSVJoinInfo struct */ if((joininfo = (msCSVJoinInfo *) malloc(sizeof(msCSVJoinInfo))) == NULL) { msSetError(MS_MEMERR, "Error allocating CSV table info structure.", "msCSVJoinConnect()"); return(MS_FAILURE); } /* initialize any members that won't get set later on in this function */ joininfo->target = NULL; joininfo->nextrow = 0; join->joininfo = joininfo; /* open the CSV file */ if((stream = fopen( msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, join->table), "r" )) == NULL) { if((stream = fopen( msBuildPath(szPath, layer->map->mappath, join->table), "r" )) == NULL) { msSetError(MS_IOERR, "(%s)", "msCSVJoinConnect()", join->table); return(MS_FAILURE); } } /* once through to get the number of rows */ joininfo->numrows = 0; while(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) joininfo->numrows++; rewind(stream); if((joininfo->rows = (char ***) malloc(joininfo->numrows*sizeof(char **))) == NULL) { fclose(stream); msSetError(MS_MEMERR, "Error allocating rows.", "msCSVJoinConnect()"); return(MS_FAILURE); } /* load the rows */ i = 0; while(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) { msStringTrimEOL(buffer); joininfo->rows[i] = msStringSplitComplex(buffer, ",", &(join->numitems), MS_ALLOWEMPTYTOKENS); i++; } fclose(stream); /* get "from" item index */ for(i=0; inumitems; i++) { if(strcasecmp(layer->items[i],join->from) == 0) { /* found it */ joininfo->fromindex = i; break; } } if(i == layer->numitems) { msSetError(MS_JOINERR, "Item %s not found in layer %s.", "msCSVJoinConnect()", join->from, layer->name); return(MS_FAILURE); } /* get "to" index (for now the user tells us which column, 1..n) */ joininfo->toindex = atoi(join->to) - 1; if(joininfo->toindex < 0 || joininfo->toindex > join->numitems) { msSetError(MS_JOINERR, "Invalid column index %s.", "msCSVJoinConnect()", join->to); return(MS_FAILURE); } /* store away the column names (1..n) */ if((join->items = (char **) malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, "Error allocating space for join item names.", "msCSVJoinConnect()"); return(MS_FAILURE); } for(i=0; inumitems; i++) { join->items[i] = (char *) malloc(8); /* plenty of space */ sprintf(join->items[i], "%d", i+1); } return(MS_SUCCESS); } int msCSVJoinPrepare(joinObj *join, shapeObj *shape) { msCSVJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msCSVJoinPrepare()"); return(MS_FAILURE); } if(!shape) { msSetError(MS_JOINERR, "Shape to be joined is empty.", "msCSVJoinPrepare()"); return(MS_FAILURE); } if(!shape->values) { msSetError(MS_JOINERR, "Shape to be joined has no attributes.", "msCSVJoinPrepare()"); return(MS_FAILURE); } joininfo->nextrow = 0; /* starting with the first record */ if(joininfo->target) free(joininfo->target); /* clear last target */ joininfo->target = msStrdup(shape->values[joininfo->fromindex]); return(MS_SUCCESS); } int msCSVJoinNext(joinObj *join) { int i,j; msCSVJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msCSVJoinNext()"); return(MS_FAILURE); } /* clear any old data */ if(join->values) { msFreeCharArray(join->values, join->numitems); join->values = NULL; } for(i=joininfo->nextrow; inumrows; i++) { /* find a match */ if(strcmp(joininfo->target, joininfo->rows[i][joininfo->toindex]) == 0) break; } if((join->values = (char ** )malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msCSVJoinNext()"); return(MS_FAILURE); } if(i == joininfo->numrows) { /* unable to do the join */ for(j=0; jnumitems; j++) join->values[j] = msStrdup("\0"); /* intialize to zero length strings */ joininfo->nextrow = joininfo->numrows; return(MS_DONE); } for(j=0; jnumitems; j++) join->values[j] = msStrdup(joininfo->rows[i][j]); joininfo->nextrow = i+1; /* so we know where to start looking next time through */ return(MS_SUCCESS); } int msCSVJoinClose(joinObj *join) { int i; msCSVJoinInfo *joininfo = join->joininfo; if(!joininfo) return(MS_SUCCESS); /* already closed */ for(i=0; inumrows; i++) msFreeCharArray(joininfo->rows[i], join->numitems); free(joininfo->rows); if(joininfo->target) free(joininfo->target); free(joininfo); joininfo = NULL; return(MS_SUCCESS); } #ifdef USE_MYSQL #ifndef _mysql_h #include #endif char* DB_HOST = NULL; char* DB_USER = NULL; char* DB_PASSWD = NULL; char* DB_DATABASE = NULL; char* delim; #define MYDEBUG if (0) MYSQL_RES *msMySQLQuery(char *q, MYSQL *conn) { MYSQL_RES *qresult=NULL; if (mysql_query(conn,q) < 0) { mysql_close(conn); msSetError(MS_QUERYERR, "Bad mysql query (%s)", "msMySQLQuery()", q); return qresult; } if (!(qresult=mysql_store_result(conn))) { mysql_close(conn); msSetError(MS_QUERYERR, "mysql query failed (%s)", "msMySQLQuery()", q); return qresult; } return qresult; } /* */ /* mysql join functions */ /* */ typedef struct { MYSQL mysql, *conn; MYSQL_RES *qresult; MYSQL_ROW row; int rows; int fromindex; char *tocolumn; char *target; int nextrecord; } msMySQLJoinInfo; #endif int msMySQLJoinConnect(layerObj *layer, joinObj *join) { #ifndef USE_MYSQL msSetError(MS_QUERYERR, "MySQL support not available (compile with --with-mysql)", "msMySQLJoinConnect()"); return(MS_FAILURE); #else int i; char qbuf[4000]; char *conn_decrypted; msMySQLJoinInfo *joininfo; MYDEBUG if (setvbuf(stdout, NULL, _IONBF , 0)) { printf("Whoops..."); }; if(join->joininfo) return(MS_SUCCESS); /* already open */ /* allocate a msMySQLJoinInfo struct */ joininfo = (msMySQLJoinInfo *) malloc(sizeof(msMySQLJoinInfo)); if(!joininfo) { msSetError(MS_MEMERR, "Error allocating mysql table info structure.", "msMySQLJoinConnect()"); return(MS_FAILURE); } /* initialize any members that won't get set later on in this function */ joininfo->qresult = NULL; joininfo->target = NULL; joininfo->nextrecord = 0; join->joininfo = joininfo; /* open the mysql connection */ if( join->connection == NULL ) { msSetError(MS_QUERYERR, "Error parsing MYSQL JOIN: nothing specified in CONNECTION statement.", "msMySQLJoinConnect()"); return(MS_FAILURE); } conn_decrypted = msDecryptStringTokens(layer->map, join->connection); if (conn_decrypted == NULL) { msSetError(MS_QUERYERR, "Error parsing MYSQL JOIN: unable to decrypt CONNECTION statement.", "msMySQLJoinConnect()"); return(MS_FAILURE); } delim = msStrdup(":"); DB_HOST = msStrdup(strtok(conn_decrypted, delim)); DB_USER = msStrdup(strtok(NULL, delim)); DB_PASSWD = msStrdup(strtok(NULL, delim)); DB_DATABASE = msStrdup(strtok(NULL, delim)); free(conn_decrypted); if (DB_HOST == NULL || DB_USER == NULL || DB_PASSWD == NULL || DB_DATABASE == NULL) { msSetError(MS_QUERYERR, "DB param error: at least one of HOST, USER, PASSWD or DATABASE is null!", "msMySQLJoinConnect()"); return MS_FAILURE; } if (strcmp(DB_PASSWD, "none") == 0) strcpy(DB_PASSWD, ""); #if MYSQL_VERSION_ID >= 40000 mysql_init(&(joininfo->mysql)); if (!(joininfo->conn = mysql_real_connect(&(joininfo->mysql),DB_HOST,DB_USER,DB_PASSWD,NULL, 0, NULL, 0))) #else if (!(joininfo->conn = mysql_connect(&(joininfo->mysql),DB_HOST,DB_USER,DB_PASSWD))) #endif { char tmp[4000]; snprintf( tmp, sizeof(tmp), "Failed to connect to SQL server: Error: %s\nHost: %s\nUsername:%s\nPassword:%s\n", mysql_error(joininfo->conn), DB_HOST, DB_USER, DB_PASSWD); msSetError(MS_QUERYERR, "%s", "msMYSQLLayerOpen()", tmp); free(joininfo); return MS_FAILURE; } MYDEBUG printf("msMYSQLLayerOpen2 called
\n"); if (mysql_select_db(joininfo->conn,DB_DATABASE) < 0) { mysql_close(joininfo->conn); } MYDEBUG printf("msMYSQLLayerOpen3 called
\n"); if (joininfo->qresult != NULL) { /* query leftover */ MYDEBUG printf("msMYSQLLayerOpen4 called
\n"); mysql_free_result(joininfo->qresult); } MYDEBUG printf("msMYSQLLayerOpen5 called
\n"); snprintf(qbuf, sizeof(qbuf), "SELECT count(%s) FROM %s", join->to, join->table); MYDEBUG printf("%s
\n", qbuf); if ((joininfo->qresult = msMySQLQuery(qbuf, joininfo->conn))) { /* There were some rows found, write 'em out for debug */ int numrows = mysql_affected_rows(joininfo->conn); MYDEBUG printf("%d rows
\n", numrows); for(i=0; iqresult); MYDEBUG printf("(%s)
\n",row[0]); joininfo->rows = atoi(row[0]); } } else { msSetError(MS_DBFERR, "Item %s not found in table %s.", "msMySQLJoinConnect()", join->to, join->table); return(MS_FAILURE); } snprintf(qbuf, sizeof(qbuf), "EXPLAIN %s", join->table); if ((joininfo->qresult = msMySQLQuery(qbuf, joininfo->conn))) { /* There were some rows found, write 'em out for debug */ join->numitems = mysql_affected_rows(joininfo->conn); if((join->items = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msMySQLJoinConnect()"); return(MS_FAILURE); } MYDEBUG printf("%d rows
\n", join->numitems); for(i=0; inumitems; i++) { MYSQL_ROW row = mysql_fetch_row(joininfo->qresult); MYDEBUG printf("(%s)
\n",row[0]); join->items[i] = msStrdup(row[0]); } } else { msSetError(MS_DBFERR, "Item %s not found in table %s.", "msMySQLJoinConnect()", join->to, join->table); return(MS_FAILURE); } joininfo->tocolumn = msStrdup(join->to); /* get "from" item index */ for(i=0; inumitems; i++) { if(strcasecmp(layer->items[i],join->from) == 0) { /* found it */ joininfo->fromindex = i; break; } } if(i == layer->numitems) { msSetError(MS_JOINERR, "Item %s not found in layer %s.", "msMySQLJoinConnect()", join->from, layer->name); return(MS_FAILURE); } /* finally store away the item names in the XBase table */ if(!join->items) return(MS_FAILURE); return(MS_SUCCESS); #endif } int msMySQLJoinPrepare(joinObj *join, shapeObj *shape) { #ifndef USE_MYSQL msSetError(MS_QUERYERR, "MySQL support not available (compile with --with-mysql)", "msMySQLJoinPrepare()"); return(MS_FAILURE); #else msMySQLJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msMySQLJoinPrepare()"); return(MS_FAILURE); } if(!shape) { msSetError(MS_JOINERR, "Shape to be joined is empty.", "msMySQLJoinPrepare()"); return(MS_FAILURE); } if(!shape->values) { msSetError(MS_JOINERR, "Shape to be joined has no attributes.", "msMySQLJoinPrepare()"); return(MS_FAILURE); } joininfo->nextrecord = 0; /* starting with the first record */ if(joininfo->target) free(joininfo->target); /* clear last target */ joininfo->target = msStrdup(shape->values[joininfo->fromindex]); return(MS_SUCCESS); #endif } int msMySQLJoinNext(joinObj *join) { #ifndef USE_MYSQL msSetError(MS_QUERYERR, "MySQL support not available (compile with --with-mysql)", "msMySQLJoinNext()"); return(MS_FAILURE); #else int i, n; char qbuf[4000]; msMySQLJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join connection has not be created.", "msMySQLJoinNext()"); return(MS_FAILURE); } if(!joininfo->target) { msSetError(MS_JOINERR, "No target specified, run msMySQLJoinPrepare() first.", "msMySQLJoinNext()"); return(MS_FAILURE); } /* clear any old data */ if(join->values) { msFreeCharArray(join->values, join->numitems); join->values = NULL; } n = joininfo->rows; /* for(i=joininfo->nextrecord; itarget, msMySQLReadStringAttribute(joininfo->conn, i, joininfo->toindex)) == 0) break; */ /* } */ snprintf(qbuf, sizeof(qbuf), "SELECT * FROM %s WHERE %s = %s", join->table, joininfo->tocolumn, joininfo->target); MYDEBUG printf("%s
\n", qbuf); if ((joininfo->qresult = msMySQLQuery(qbuf, joininfo->conn))) { /* There were some rows found, write 'em out for debug */ int numrows = mysql_affected_rows(joininfo->conn); int numfields = mysql_field_count(joininfo->conn); MYDEBUG printf("%d rows
\n", numrows); if (numrows > 0) { MYSQL_ROW row = mysql_fetch_row(joininfo->qresult); for(i=0; i\n"); free(join->values); if((join->values = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msMySQLJoinNext()"); return(MS_FAILURE); } for(i=0; inumitems; i++) { /* join->values[i] = msStrdup("\0"); */ /* intialize to zero length strings */ join->values[i] = msStrdup(row[i]); /* intialize to zero length strings */ /* rows = atoi(row[0]); */ } } else { if((join->values = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msMySQLJoinNext()"); return(MS_FAILURE); } for(i=0; inumitems; i++) join->values[i] = msStrdup("\0"); /* intialize to zero length strings */ return(MS_DONE); } } else { msSetError(MS_QUERYERR, "Query error (%s)", "msMySQLJoinNext()", qbuf); return(MS_FAILURE); } #ifdef __NOTDEF__ if(i == n) { /* unable to do the join */ if((join->values = (char **)malloc(sizeof(char *)*join->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msMySQLJoinNext()"); return(MS_FAILURE); } for(i=0; inumitems; i++) join->values[i] = msStrdup("\0"); /* intialize to zero length strings */ joininfo->nextrecord = n; return(MS_DONE); } if((join->values = msMySQLGetValues(joininfo->conn,i)) == NULL) return(MS_FAILURE); joininfo->nextrecord = i+1; /* so we know where to start looking next time through */ #endif /* __NOTDEF__ */ return(MS_SUCCESS); #endif } int msMySQLJoinClose(joinObj *join) { #ifndef USE_MYSQL msSetError(MS_QUERYERR, "MySQL support not available (compile with --with-mysql)", "msMySQLJoinClose()"); return(MS_FAILURE); #else msMySQLJoinInfo *joininfo = join->joininfo; if(!joininfo) return(MS_SUCCESS); /* already closed */ mysql_close(joininfo->conn); if(joininfo->target) free(joininfo->target); free(joininfo); joininfo = NULL; return(MS_SUCCESS); #endif } mapserver-7.4.3/mapkml.cpp000066400000000000000000000175371357574274700155600ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Headers for mapkml.cpp Google Earth KML output * Author: David Kana and the MapServer team * ****************************************************************************** * Copyright (c) 1996-2009 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #ifdef USE_KML #include "mapkmlrenderer.h" #ifdef __cplusplus extern "C" { #endif KmlRenderer* getKmlRenderer(imageObj* img) { return (KmlRenderer*) img->img.plugin; } imageObj* msCreateImageKml(int width, int height, outputFormatObj *format, colorObj* bg) { imageObj *image = NULL; image = (imageObj*)malloc(sizeof(imageObj)); MS_CHECK_ALLOC(image, sizeof(imageObj), NULL); memset(image, 0, sizeof(imageObj)); KmlRenderer *ren = new KmlRenderer(width, height, format, bg); image->img.plugin = (void *) ren; return image; } int msSaveImageKml(imageObj *img, mapObj* map, FILE *fp, outputFormatObj *format) { KmlRenderer* renderer = getKmlRenderer(img); return renderer->saveImage(img, fp, format); } int msRenderLineKml(imageObj *img, shapeObj *p, strokeStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderLine(img, p, style); return MS_SUCCESS; } int msRenderPolygonKml(imageObj *img, shapeObj *p, colorObj *color) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderPolygon(img, p, color); return MS_SUCCESS; } int msRenderPolygonTiledKml(imageObj *img, shapeObj *p, imageObj *tile) { /*KmlRenderer* renderer = getKmlRenderer(img);*/ return MS_SUCCESS; } int msRenderLineTiledKml(imageObj *img, shapeObj *p, imageObj *tile) { return MS_SUCCESS; } int msRenderGlyphsKml(imageObj *img, pointObj *labelpnt, char *text, double angle, colorObj *clr, colorObj *olcolor, int olwidth) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderGlyphs(img, labelpnt, text, angle, clr, olcolor, olwidth); return MS_SUCCESS; } int msRenderVectorSymbolKml(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderVectorSymbol(img, x, y, symbol, style); return MS_SUCCESS; } int msRenderPixmapSymbolKml(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(img); renderer->renderPixmapSymbol(img, x, y, symbol, style); return MS_SUCCESS; } int msRenderEllipseSymbolKml(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(image); renderer->renderEllipseSymbol(image, x, y, symbol, style); return MS_SUCCESS; } int msRenderTruetypeSymbolKml(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style) { KmlRenderer* renderer = getKmlRenderer(image); renderer->renderTruetypeSymbol(image, x, y, symbol, style); return MS_SUCCESS; } int msRenderTileKml(imageObj *img, imageObj *tile, double x, double y) { return MS_SUCCESS; } int msGetRasterBufferKml(imageObj *img,rasterBufferObj *rb) { return MS_FAILURE; //not supported for kml } int msGetTruetypeTextBBoxKml(rendererVTableObj *r,char** fonts, int numfonts, double size, char *string, rectObj *rect, double **advances, int bAdjustBaseline) { rect->minx=0.0; rect->maxx=0.0; rect->miny=0.0; rect->maxy=0.0; if (advances) { int numglyphs = msGetNumGlyphs(string); *advances = (double*) msSmallMalloc(numglyphs * sizeof (double)); for(int i=0; istartNewLayer(img, layer); } int msCloseNewLayerKml(imageObj *img, mapObj *map, layerObj *layer) { KmlRenderer* renderer = getKmlRenderer(img); return renderer->closeNewLayer(img, layer); } int msFreeImageKml(imageObj *image) { KmlRenderer* renderer = getKmlRenderer(image); if (renderer) { delete renderer; } image->img.plugin=NULL; return MS_SUCCESS; } int msFreeSymbolKml(symbolObj *symbol) { return MS_SUCCESS; } int msStartShapeKml(imageObj *img, shapeObj *shape) { KmlRenderer* renderer = getKmlRenderer(img); renderer->startShape(img, shape); return MS_SUCCESS; } int msEndShapeKml(imageObj *img, shapeObj *shape) { KmlRenderer* renderer = getKmlRenderer(img); renderer->endShape(img, shape); return MS_SUCCESS; } int msMergeRasterBufferKml(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { KmlRenderer* renderer = getKmlRenderer(dest); return renderer->mergeRasterBuffer(dest,overlay); } #ifdef __cplusplus } #endif #endif /*USE_KML*/ int aggInitializeRasterBuffer(rasterBufferObj *rb, int width, int height, int mode); int msPopulateRendererVTableKML( rendererVTableObj *renderer ) { #ifdef USE_KML renderer->supports_pixel_buffer = 0; renderer->supports_clipping = 0; renderer->use_imagecache = 0; renderer->default_transform_mode = MS_TRANSFORM_NONE; renderer->startLayer = msStartNewLayerKml; renderer->endLayer = msCloseNewLayerKml; renderer->renderLine=&msRenderLineKml; renderer->createImage=&msCreateImageKml; renderer->saveImage=&msSaveImageKml; renderer->renderPolygon=&msRenderPolygonKml; renderer->renderText=&msRenderGlyphsKml; renderer->renderEllipseSymbol = &msRenderEllipseSymbolKml; renderer->renderVectorSymbol = &msRenderVectorSymbolKml; renderer->renderPixmapSymbol = &msRenderPixmapSymbolKml; renderer->mergeRasterBuffer = &msMergeRasterBufferKml; renderer->loadImageFromFile = msLoadMSRasterBufferFromFile; renderer->initializeRasterBuffer = aggInitializeRasterBuffer; renderer->renderTile = &msRenderTileKml; renderer->renderPolygonTiled = &msRenderPolygonTiledKml; renderer->renderLineTiled = NULL; renderer->freeSymbol = &msFreeSymbolKml; renderer->freeImage=&msFreeImageKml; renderer->mergeRasterBuffer = msMergeRasterBufferKml; renderer->compositeRasterBuffer = NULL; renderer->startShape=&msStartShapeKml; renderer->endShape=&msEndShapeKml; return MS_SUCCESS; #else msSetError(MS_MISCERR, "KML Driver requested but is not built in", "msPopulateRendererVTableKML()"); return MS_FAILURE; #endif } mapserver-7.4.3/mapkmlrenderer.cpp000066400000000000000000001236311357574274700173000ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Google Earth KML output * Author: David Kana and the MapServer team * ****************************************************************************** * Copyright (c) 1996-2009 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver-config.h" #ifdef USE_KML #include "mapserver.h" #include "maperror.h" #include "mapkmlrenderer.h" #include "mapio.h" #include "mapows.h" #if defined(USE_OGR) # include "cpl_conv.h" # include "cpl_vsi.h" #endif #define KML_MAXFEATURES_TODRAW 1000 KmlRenderer::KmlRenderer(int width, int height, outputFormatObj *format, colorObj* color/*=NULL*/) : Width(width), Height(height), MapCellsize(1.0), XmlDoc(NULL), LayerNode(NULL), GroundOverlayNode(NULL), PlacemarkNode(NULL), GeomNode(NULL), Items(NULL), NumItems(0), FirstLayer(MS_TRUE), map(NULL), currentLayer(NULL), mElevationFromAttribute( false ), mElevationAttributeIndex( -1 ), mCurrentElevationValue(0.0) { /*private variables*/ pszLayerDescMetadata = NULL; papszLayerIncludeItems = NULL; nIncludeItems=0; papszLayerExcludeItems = NULL; nExcludeItems=0; pszLayerNameAttributeMetadata = NULL; /*metadata to use for a name for each feature*/ LineStyle = NULL; numLineStyle = 0; xmlNodePtr styleNode; xmlNodePtr listStyleNode; /* Create document.*/ XmlDoc = xmlNewDoc(BAD_CAST "1.0"); xmlNodePtr rootNode = xmlNewNode(NULL, BAD_CAST "kml"); /* Name spaces*/ xmlSetNs(rootNode, xmlNewNs(rootNode, BAD_CAST "http://www.opengis.net/kml/2.2", NULL)); xmlDocSetRootElement(XmlDoc, rootNode); DocNode = xmlNewChild(rootNode, NULL, BAD_CAST "Document", NULL); styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST "LayerFolder_check"); listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL); xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "check"); styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST "LayerFolder_checkHideChildren"); listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL); xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "checkHideChildren"); styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST "LayerFolder_checkOffOnly"); listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL); xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "checkOffOnly"); styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST "LayerFolder_radioFolder"); listStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "ListStyle", NULL); xmlNewChild(listStyleNode, NULL, BAD_CAST "listItemType", BAD_CAST "radioFolder"); StyleHashTable = msCreateHashTable(); } KmlRenderer::~KmlRenderer() { if (XmlDoc) xmlFreeDoc(XmlDoc); if (StyleHashTable) msFreeHashTable(StyleHashTable); if(LineStyle) msFree(LineStyle); xmlCleanupParser(); } imageObj* KmlRenderer::createImage(int, int, outputFormatObj*, colorObj*) { return NULL; } int KmlRenderer::saveImage(imageObj *, FILE *fp, outputFormatObj *format) { /* -------------------------------------------------------------------- */ /* Write out the document. */ /* -------------------------------------------------------------------- */ int bufSize = 0; xmlChar *buf = NULL; msIOContext *context = NULL; int chunkSize = 4096; #if defined(CPL_ZIP_API_OFFERED) int bZip = MS_FALSE; #endif if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; xmlDocDumpFormatMemoryEnc(XmlDoc, &buf, &bufSize, "UTF-8", 1); #if defined(USE_OGR) if (format && format->driver && strcasecmp(format->driver, "kmz") == 0) { #if defined(CPL_ZIP_API_OFFERED) bZip = MS_TRUE; #else msSetError( MS_MISCERR, "kmz format support unavailable, perhaps you need to upgrade to GDAL/OGR 1.8?", "KmlRenderer::saveImage()"); xmlFree(buf); return MS_FAILURE; #endif } #if defined(CPL_ZIP_API_OFFERED) if (bZip) { VSILFILE *fpZip; int bytes_read; char buffer[1024]; char *zip_filename =NULL; void *hZip=NULL; zip_filename = msTmpFile(NULL, NULL, "/vsimem/kmlzip/", "kmz" ); hZip = CPLCreateZip( zip_filename, NULL ); CPLCreateFileInZip( hZip, "mapserver.kml", NULL ); for (int i=0; i bufSize) size = bufSize - i; CPLWriteFileInZip( hZip, buf+i, size); } CPLCloseFileInZip( hZip ); CPLCloseZip( hZip ); context = msIO_getHandler(fp); fpZip = VSIFOpenL( zip_filename, "r" ); while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fpZip )) > 0 ) { if (context) msIO_contextWrite(context, buffer, bytes_read); else msIO_fwrite( buffer, 1, bytes_read, fp ); } VSIFCloseL( fpZip ); msFree( zip_filename); xmlFree(buf); return(MS_SUCCESS); } #endif #endif context = msIO_getHandler(fp); for (int i=0; i bufSize) size = bufSize - i; if (context) msIO_contextWrite(context, buf+i, size); else msIO_fwrite(buf+i, 1, size, fp); } xmlFree(buf); return(MS_SUCCESS); } /************************************************************************/ /* processLayer */ /* */ /* Set parameters that make sense to a kml output. */ /************************************************************************/ void KmlRenderer::processLayer(layerObj *layer, outputFormatObj *format) { int i; const char *asRaster = NULL; int nMaxFeatures = -1; const char *pszTmp; char szTmp[10]; if (!layer) return; /*turn of labelcache*/ layer->labelcache = MS_OFF; /*if there are labels we want the coordinates to be the center of the element.*/ for(i=0; inumclasses; i++) if(layer->_class[i]->numlabels > 0) layer->_class[i]->labels[0]->position = MS_XY; /*we do not want to draw multiple styles. the new rendering architecture does not allow to know if we are dealing with a multi-style. So here we remove all styles beside the first one*/ for(i=0; inumclasses; i++) { while (layer->_class[i]->numstyles > 1) msDeleteStyle(layer->_class[i], layer->_class[i]->numstyles-1); } /*if layer has a metadata KML_OUTPUTASRASTER set to true, add a processing directive to use an agg driver*/ asRaster = msLookupHashTable(&layer->metadata, "kml_outputasraster"); if (!asRaster) asRaster = msLookupHashTable(&(layer->map->web.metadata), "kml_outputasraster"); if (asRaster && (strcasecmp(asRaster, "true") == 0 || strcasecmp(asRaster, "yes") == 0)) msLayerAddProcessing(layer, "RENDERER=png24"); /*set a maxfeaturestodraw, if not already set*/ pszTmp = msLookupHashTable(&layer->metadata, "maxfeaturestodraw"); if (pszTmp) nMaxFeatures = atoi(pszTmp); else { pszTmp = msLookupHashTable(&layer->map->web.metadata, "maxfeaturestodraw"); if (pszTmp) nMaxFeatures = atoi(pszTmp); } if (nMaxFeatures < 0 && format) nMaxFeatures = atoi(msGetOutputFormatOption( format, "maxfeaturestodraw", "-1")); if (nMaxFeatures < 0 && format) { snprintf(szTmp, sizeof(szTmp), "%d", KML_MAXFEATURES_TODRAW); msSetOutputFormatOption( format, "maxfeaturestodraw", szTmp); } } /************************************************************************/ /* getLayerName */ /* */ /* Internal utility function to build name used fo rthe layer. */ /************************************************************************/ char* KmlRenderer::getLayerName(layerObj *layer) { char stmp[20]; const char *name=NULL;; if (!layer) return NULL; name = msLookupHashTable(&layer->metadata, "ows_name"); if (name && strlen(name) > 0) return msStrdup(name); if (layer->name && strlen(layer->name) > 0) return msStrdup(layer->name); sprintf(stmp, "Layer%d",layer->index); return msStrdup(stmp); } const char* KmlRenderer::getAliasName(layerObj *lp, char *pszItemName, const char *namespaces) { const char *pszAlias = NULL; if (lp && pszItemName && strlen(pszItemName) > 0) { char szTmp[256]; snprintf(szTmp, sizeof(szTmp), "%s_alias", pszItemName); pszAlias = msOWSLookupMetadata(&(lp->metadata), namespaces, szTmp); } return pszAlias; } int KmlRenderer::startNewLayer(imageObj *img, layerObj *layer) { char *layerName=NULL; const char *value=NULL; LayerNode = xmlNewNode(NULL, BAD_CAST "Folder"); layerName = getLayerName(layer); xmlNewChild(LayerNode, NULL, BAD_CAST "name", BAD_CAST layerName); msFree(layerName); const char *layerVisibility = layer->status != MS_OFF ? "1" : "0"; xmlNewChild(LayerNode, NULL, BAD_CAST "visibility", BAD_CAST layerVisibility); const char *layerDsiplayFolder = msLookupHashTable(&(layer->metadata), "kml_folder_display"); if (layerDsiplayFolder == NULL) layerDsiplayFolder = msLookupHashTable(&(layer->map->web.metadata), "kml_folder_display"); if (!layerDsiplayFolder || strlen(layerDsiplayFolder)<=0) { xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_check"); } else { if (strcasecmp(layerDsiplayFolder, "checkHideChildren") == 0) xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_checkHideChildren"); else if (strcasecmp(layerDsiplayFolder, "checkOffOnly") == 0) xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_checkOffOnly"); else if (strcasecmp(layerDsiplayFolder, "radioFolder") == 0) xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_radioFolder"); else xmlNewChild(LayerNode, NULL, BAD_CAST "styleUrl", BAD_CAST "#LayerFolder_check"); } /*Init few things on the first layer*/ if (FirstLayer) { FirstLayer = MS_FALSE; map = layer->map; if (layer->map->mappath) snprintf(MapPath, sizeof(MapPath), "%s", layer->map->mappath); /*First rendered layer - check mapfile projection*/ checkProjection(layer->map); /*check for image path and image url*/ if (layer->map->debug && (layer->map->web.imageurl == NULL || layer->map->web.imagepath == NULL)) msDebug("KmlRenderer::startNewLayer: imagepath and imageurl should be set in the web object\n"); /*map rect for ground overlay*/ MapExtent = layer->map->extent; MapCellsize = layer->map->cellsize; BgColor = layer->map->imagecolor; xmlNewChild(DocNode, NULL, BAD_CAST "name", BAD_CAST layer->map->name); aggFormat = msSelectOutputFormat( layer->map, "png24"); aggFormat->transparent = MS_TRUE; } currentLayer = layer; if (!msLayerIsOpen(layer)) { if (msLayerOpen(layer) != MS_SUCCESS) { msSetError(MS_MISCERR, "msLayerOpen failed", "KmlRenderer::startNewLayer" ); return MS_FAILURE; } } /*pre process the layer to set things that make sense for kml output*/ if (img) processLayer(layer, img->format); else processLayer(layer, NULL); if (msLookupHashTable(&layer->metadata, "kml_description")) pszLayerDescMetadata = msLookupHashTable(&layer->metadata, "kml_description"); else if (msLookupHashTable(&layer->metadata, "ows_description")) pszLayerDescMetadata = msLookupHashTable(&layer->metadata, "ows_description"); value=msLookupHashTable(&layer->metadata, "kml_include_items"); if (!value) value=msLookupHashTable(&layer->metadata, "ows_include_items"); if (value) papszLayerIncludeItems = msStringSplit(value, ',', &nIncludeItems); value=msLookupHashTable(&layer->metadata, "kml_exclude_items"); if (!value) value=msLookupHashTable(&layer->metadata, "ows_exclude_items"); if (value) papszLayerExcludeItems = msStringSplit(value, ',', &nExcludeItems); if (msLookupHashTable(&layer->metadata, "kml_name_item")) pszLayerNameAttributeMetadata = msLookupHashTable(&layer->metadata, "kml_name_item"); /*get all attributes*/ if(msLayerWhichItems(layer, MS_TRUE, NULL) != MS_SUCCESS) { return MS_FAILURE; } NumItems = layer->numitems; if (NumItems) { Items = (char **)msSmallCalloc(NumItems, sizeof(char *)); for (int i=0; iitems[i]); } const char* elevationAttribute = msLookupHashTable(&layer->metadata, "kml_elevation_attribute"); if( elevationAttribute ) { mElevationFromAttribute = true; for( int i = 0; i < layer->numitems; ++i ) { if( strcasecmp( layer->items[i], elevationAttribute ) == 0 ) { mElevationAttributeIndex = i; } } } setupRenderingParams(&layer->metadata); return MS_SUCCESS; } int KmlRenderer::closeNewLayer(imageObj *img, layerObj *layer) { flushPlacemark(); xmlAddChild(DocNode, LayerNode); if(Items) { msFreeCharArray(Items, NumItems); Items = NULL; NumItems = 0; } if (pszLayerDescMetadata) pszLayerDescMetadata = NULL; if (pszLayerNameAttributeMetadata) pszLayerNameAttributeMetadata = NULL; if (papszLayerIncludeItems && nIncludeItems>0) msFreeCharArray(papszLayerIncludeItems, nIncludeItems); papszLayerIncludeItems=NULL; if (papszLayerExcludeItems && nExcludeItems>0) msFreeCharArray(papszLayerExcludeItems, nExcludeItems); papszLayerExcludeItems=NULL; return MS_SUCCESS; } int KmlRenderer::mergeRasterBuffer(imageObj *image, rasterBufferObj *rb) { assert(rb && rb->type == MS_BUFFER_BYTE_RGBA); char *tmpFileName = NULL; char *tmpUrl = NULL; FILE *tmpFile = NULL; tmpFileName = msTmpFile(NULL, MapPath, image->imagepath, "png"); tmpFile = fopen(tmpFileName,"wb"); if (tmpFile) { if (!aggFormat->vtable) msInitializeRendererVTable(aggFormat); msSaveRasterBuffer(map,rb,tmpFile,aggFormat); tmpUrl = msStrdup( image->imageurl); tmpUrl = msStringConcatenate(tmpUrl, (char *)(msGetBasename(tmpFileName))); tmpUrl = msStringConcatenate(tmpUrl, ".png"); createGroundOverlayNode(LayerNode, tmpUrl, currentLayer); msFree(tmpFileName); msFree(tmpUrl); fclose(tmpFile); return MS_SUCCESS; } else { msSetError(MS_IOERR,"Failed to create file for kml overlay","KmlRenderer::mergeRasterBuffer()"); return MS_FAILURE; } } void KmlRenderer::setupRenderingParams(hashTableObj *layerMetadata) { AltitudeMode = 0; Extrude = 0; Tessellate = 0; const char *altitudeModeVal = msLookupHashTable(layerMetadata, "kml_altitudeMode"); if (altitudeModeVal) { if(strcasecmp(altitudeModeVal, "absolute") == 0) AltitudeMode = absolute; else if(strcasecmp(altitudeModeVal, "relativeToGround") == 0) AltitudeMode = relativeToGround; else if(strcasecmp(altitudeModeVal, "clampToGround") == 0) AltitudeMode = clampToGround; } const char *extrudeVal = msLookupHashTable(layerMetadata, "kml_extrude"); if (altitudeModeVal) { Extrude = atoi(extrudeVal); } const char *tessellateVal = msLookupHashTable(layerMetadata, "kml_tessellate"); if (tessellateVal) { Tessellate = atoi(tessellateVal); } } int KmlRenderer::checkProjection(mapObj *map) { projectionObj *projection= &map->projection; #ifdef USE_PROJ if (projection && projection->numargs > 0 && pj_is_latlong(projection->proj)) { return MS_SUCCESS; } else { char epsg_string[100]; rectObj sRect; projectionObj out; /* for layer the do not have any projection set, set them with the current map projection*/ if (projection && projection->numargs > 0) { layerObj *lp = NULL; int i =0; char *pszMapProjectString = msGetProjectionString(projection); if (pszMapProjectString) { for(i=0; inumlayers; i++) { lp = GET_LAYER(map, i); if (lp->projection.numargs == 0 && lp->transform == MS_TRUE) { msFreeProjection(&lp->projection); msLoadProjectionString(&lp->projection, pszMapProjectString); } } msFree(pszMapProjectString); } } strcpy(epsg_string, "epsg:4326" ); msInitProjection(&out); msLoadProjectionString(&out, epsg_string); sRect = map->extent; msProjectRect(projection, &out, &sRect); msFreeProjection(projection); msLoadProjectionString(projection, epsg_string); /*change also units and extents*/ map->extent = sRect; map->units = MS_DD; if (map->debug) msDebug("KmlRenderer::checkProjection: Mapfile projection set to epsg:4326\n"); return MS_SUCCESS; } #else msSetError(MS_MISCERR, "Projection support not enabled", "KmlRenderer::checkProjection" ); return MS_FAILURE; #endif } xmlNodePtr KmlRenderer::createPlacemarkNode(xmlNodePtr parentNode, char *styleUrl) { xmlNodePtr placemarkNode = xmlNewChild(parentNode, NULL, BAD_CAST "Placemark", NULL); /*always add a name. It will be replaced by a text value if available*/ char tmpid[100]; char *stmp=NULL, *layerName=NULL; if (CurrentShapeName && strlen(CurrentShapeName)>0) { xmlNewChild(placemarkNode, NULL, BAD_CAST "name", BAD_CAST CurrentShapeName); } else { sprintf(tmpid, ".%d", CurrentShapeIndex); layerName = getLayerName(currentLayer); stmp = msStringConcatenate(stmp, layerName); stmp = msStringConcatenate(stmp, tmpid); xmlNewChild(placemarkNode, NULL, BAD_CAST "name", BAD_CAST stmp); } msFree(layerName); msFree(stmp); if (styleUrl) xmlNewChild(placemarkNode, NULL, BAD_CAST "styleUrl", BAD_CAST styleUrl); return placemarkNode; } void KmlRenderer::renderLine(imageObj*, shapeObj *p, strokeStyleObj *style) { if (p->numlines == 0) return; if (PlacemarkNode == NULL) PlacemarkNode = createPlacemarkNode(LayerNode, NULL); if (!PlacemarkNode) return; addLineStyleToList(style); SymbologyFlag[Line] = 1; /*p->index > CurrentDrawnShapeIndexneed to be reviewd. Added since the hight level code caches shapes when rendering lines*/ if (CurrentDrawnShapeIndex == -1 || p->index > CurrentDrawnShapeIndex) { xmlNodePtr geomNode = getGeomParentNode("LineString"); addAddRenderingSpecifications(geomNode); addCoordsNode(geomNode, p->line[0].point, p->line[0].numpoints); /* more than one line => MultiGeometry*/ if (p->numlines > 1) { geomNode = getGeomParentNode("LineString"); // returns MultiGeom Node for (int i=1; inumlines; i++) { xmlNodePtr lineStringNode = xmlNewChild(geomNode, NULL, BAD_CAST "LineString", NULL); addAddRenderingSpecifications(lineStringNode); addCoordsNode(lineStringNode, p->line[i].point, p->line[i].numpoints); } } CurrentDrawnShapeIndex = p->index; } } void KmlRenderer::renderPolygon(imageObj*, shapeObj *p, colorObj *color) { if (PlacemarkNode == NULL) PlacemarkNode = createPlacemarkNode(LayerNode, NULL); if (!PlacemarkNode) return; memcpy(&PolygonColor, color, sizeof(colorObj)); SymbologyFlag[Polygon] = 1; if (p->index != CurrentDrawnShapeIndex) { xmlNodePtr geomParentNode = getGeomParentNode("Polygon"); for (int i=0; inumlines; i++) { xmlNodePtr bdryNode = NULL; if (i==0) /* __TODO__ check ring order*/ bdryNode = xmlNewChild(geomParentNode, NULL, BAD_CAST "outerBoundaryIs", NULL); else bdryNode = xmlNewChild(geomParentNode, NULL, BAD_CAST "innerBoundaryIs", NULL); xmlNodePtr ringNode = xmlNewChild(bdryNode, NULL, BAD_CAST "LinearRing", NULL); addAddRenderingSpecifications(ringNode); addCoordsNode(ringNode, p->line[i].point, p->line[i].numpoints); } CurrentDrawnShapeIndex = p->index; } } void KmlRenderer::addCoordsNode(xmlNodePtr parentNode, pointObj *pts, int numPts) { char lineBuf[128]; xmlNodePtr coordsNode = xmlNewChild(parentNode, NULL, BAD_CAST "coordinates", NULL); xmlNodeAddContent(coordsNode, BAD_CAST "\n"); for (int i=0; ichildren; node; node = node->next) { if (node->type != XML_ELEMENT_NODE) continue; if (strcmp((char *)node->name, "name") == 0) { xmlNodeSetContent(node, BAD_CAST text); break; } } /*xmlNewChild(PlacemarkNode, NULL, BAD_CAST "name", BAD_CAST text);*/ xmlNodePtr geomNode = getGeomParentNode("Point"); addAddRenderingSpecifications(geomNode); pointObj pt; pt.x = labelpnt->x; pt.y = labelpnt->y; addCoordsNode(geomNode, &pt, 1); } void KmlRenderer::addAddRenderingSpecifications(xmlNodePtr node) { /* 0 0 clampToGround */ if (Extrude) xmlNewChild(node, NULL, BAD_CAST "extrude", BAD_CAST "1"); if (Tessellate) xmlNewChild(node, NULL, BAD_CAST "tessellate", BAD_CAST "1"); if (AltitudeMode == absolute) xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "absolute"); else if (AltitudeMode == relativeToGround) xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "relativeToGround"); else if (AltitudeMode == clampToGround) xmlNewChild(node, NULL, BAD_CAST "altitudeMode", BAD_CAST "clampToGround"); } imageObj *agg2CreateImage(int width, int height, outputFormatObj *format, colorObj * bg); int KmlRenderer::createIconImage(char *fileName, symbolObj *symbol, symbolStyleObj *symstyle) { pointObj p; int status; imageObj *tmpImg = NULL; tmpImg = agg2CreateImage((int)(symbol->sizex*symstyle->scale), (int)(symbol->sizey*symstyle->scale), aggFormat, NULL); tmpImg->format = aggFormat; if (!aggFormat->vtable) msInitializeRendererVTable(aggFormat); p.x = symbol->sizex * symstyle->scale / 2; p.y = symbol->sizey *symstyle->scale / 2; #ifdef USE_POINT_Z_M p.z = 0.0; #endif status = msDrawMarkerSymbol(map,tmpImg, &p, symstyle->style, 1); if( status != MS_SUCCESS ) return status; return msSaveImage(map, tmpImg, fileName); } void KmlRenderer::renderSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { if (PlacemarkNode == NULL) PlacemarkNode = createPlacemarkNode(LayerNode, NULL); if (!PlacemarkNode) return; snprintf(SymbolUrl, sizeof(SymbolUrl), "%s", lookupSymbolUrl(img, symbol, style)); SymbologyFlag[Symbol] = 1; xmlNodePtr geomNode = getGeomParentNode("Point"); addAddRenderingSpecifications(geomNode); pointObj pt; pt.x = x; pt.y = y; addCoordsNode(geomNode, &pt, 1); } void KmlRenderer::renderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { renderSymbol(img, x, y, symbol, style); } void KmlRenderer::renderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { renderSymbol(img, x, y, symbol, style); } void KmlRenderer::renderEllipseSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { renderSymbol(img, x, y, symbol, style); } void KmlRenderer::renderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { renderSymbol(img, x, y, symbol, style); } xmlNodePtr KmlRenderer::createGroundOverlayNode(xmlNodePtr parentNode, char *imageHref, layerObj *layer) { /* GroundOverlay.kml 7fffffff 1 http://www.google.com/intl/en/images/logo.gif onInterval 86400 0.75 37.83234 37.832122 -122.373033 -122.373724 45 */ char layerHexColor[32]; xmlNodePtr groundOverlayNode = xmlNewChild(parentNode, NULL, BAD_CAST "GroundOverlay", NULL); char *layerName = getLayerName(layer); xmlNewChild(groundOverlayNode, NULL, BAD_CAST "name", BAD_CAST layerName); if (layer->compositer && layer->compositer->opacity > 0 && layer->compositer->opacity < 100) { sprintf(layerHexColor, "%02xffffff", (unsigned int)MS_NINT(layer->compositer->opacity*2.55)); xmlNewChild(groundOverlayNode, NULL, BAD_CAST "color", BAD_CAST layerHexColor); } else xmlNewChild(groundOverlayNode, NULL, BAD_CAST "color", BAD_CAST "ffffffff"); char stmp[20]; sprintf(stmp, "%d",layer->index); xmlNewChild(groundOverlayNode, NULL, BAD_CAST "drawOrder", BAD_CAST stmp); if (imageHref) { xmlNodePtr iconNode = xmlNewChild(groundOverlayNode, NULL, BAD_CAST "Icon", NULL); xmlNewChild(iconNode, NULL, BAD_CAST "href", BAD_CAST imageHref); } char crdStr[64]; rectObj mapextent; if (map->gt.need_geotransform == MS_TRUE) mapextent = currentLayer->map->saved_extent; else mapextent = currentLayer->map->extent; xmlNodePtr latLonBoxNode = xmlNewChild(groundOverlayNode, NULL, BAD_CAST "LatLonBox", NULL); sprintf(crdStr, "%.8f", mapextent.maxy); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "north", BAD_CAST crdStr); sprintf(crdStr, "%.8f", mapextent.miny); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "south", BAD_CAST crdStr); sprintf(crdStr, "%.8f", mapextent.minx); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "west", BAD_CAST crdStr); sprintf(crdStr, "%.8f", mapextent.maxx); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "east", BAD_CAST crdStr); xmlNewChild(latLonBoxNode, NULL, BAD_CAST "rotation", BAD_CAST "0.0"); return groundOverlayNode; } void KmlRenderer::startShape(imageObj *, shapeObj *shape) { if (PlacemarkNode) flushPlacemark(); CurrentShapeIndex=-1; CurrentDrawnShapeIndex = -1; CurrentShapeName=NULL; /*should be done at endshape but the plugin architecture does not call endshape yet*/ if(LineStyle) { msFree(LineStyle); LineStyle = NULL; numLineStyle = 0; } CurrentShapeIndex = shape->index; if (pszLayerNameAttributeMetadata) { for (int i=0; inumitems; i++) { if (strcasecmp(currentLayer->items[i], pszLayerNameAttributeMetadata) == 0 && shape->values[i]) { CurrentShapeName = msStrdup(shape->values[i]); break; } } } PlacemarkNode = NULL; GeomNode = NULL; DescriptionNode = createDescriptionNode(shape); if( mElevationFromAttribute && shape->numvalues > mElevationAttributeIndex && mElevationAttributeIndex >= 0 && shape->values[mElevationAttributeIndex]) { mCurrentElevationValue = atof( shape->values[mElevationAttributeIndex] ); } memset(SymbologyFlag, 0, NumSymbologyFlag); } void KmlRenderer::endShape(imageObj*, shapeObj*) { CurrentShapeIndex = -1; if (CurrentShapeName) msFree(CurrentShapeName); CurrentShapeName = NULL; } xmlNodePtr KmlRenderer::getGeomParentNode(const char *geomName) { /*we do not need a multi-geometry for point layers*/ if (currentLayer->type != MS_LAYER_POINT && currentLayer->type != MS_LAYER_ANNOTATION && GeomNode) { /*placemark geometry already defined, we need multigeometry node*/ xmlNodePtr multiGeomNode = xmlNewNode(NULL, BAD_CAST "MultiGeometry"); xmlAddChild(multiGeomNode, GeomNode); GeomNode = multiGeomNode; xmlNodePtr geomNode = xmlNewChild(multiGeomNode, NULL, BAD_CAST geomName, NULL); return geomNode; } else { GeomNode = xmlNewNode(NULL, BAD_CAST geomName); return GeomNode; } } const char* KmlRenderer::lookupSymbolUrl(imageObj *img, symbolObj *symbol, symbolStyleObj *symstyle) { char symbolHexColor[32]; /* */ sprintf(symbolHexColor,"%02x%02x%02x%02x", symstyle->style->color.alpha, symstyle->style->color.blue, symstyle->style->color.green, symstyle->style->color.red); snprintf(SymbolName, sizeof(SymbolName), "symbol_%s_%.1f_%s", symbol->name, symstyle->scale, symbolHexColor); const char *symbolUrl = msLookupHashTable(StyleHashTable, SymbolName); if (!symbolUrl) { char iconFileName[MS_MAXPATHLEN]; char iconUrl[MS_MAXPATHLEN]; if (img->imagepath) { char *tmpFileName = msTmpFile(NULL, MapPath, img->imagepath, "png"); snprintf(iconFileName, sizeof(iconFileName), "%s", tmpFileName); msFree(tmpFileName); } else { sprintf(iconFileName, "symbol_%s_%.1f.%s", symbol->name, symstyle->scale, "png"); } if (createIconImage(iconFileName, symbol, symstyle) != MS_SUCCESS) { msSetError(MS_IOERR, "Error creating icon file '%s'", "KmlRenderer::lookupSymbolStyle()", iconFileName); return NULL; } if (img->imageurl) sprintf(iconUrl, "%s%s.%s", img->imageurl, msGetBasename(iconFileName), "png"); else snprintf(iconUrl, sizeof(iconUrl), "%s", iconFileName); hashObj *hash = msInsertHashTable(StyleHashTable, SymbolName, iconUrl); symbolUrl = hash->data; } return symbolUrl; } const char* KmlRenderer::lookupPlacemarkStyle() { char lineHexColor[32]; char polygonHexColor[32]; char labelHexColor[32]; char *styleName=NULL; styleName = msStringConcatenate(styleName, "style"); if (SymbologyFlag[Line]) { /* ffffffff normal 1 */ for (int i=0; icompositer && currentLayer->compositer->opacity > 0 && currentLayer->compositer->opacity < 100 && LineStyle[i].color->alpha == 255) LineStyle[i].color->alpha = MS_NINT(currentLayer->compositer->opacity*2.55); sprintf(lineHexColor,"%02x%02x%02x%02x", LineStyle[i].color->alpha, LineStyle[0].color->blue, LineStyle[i].color->green, LineStyle[i].color->red); char lineStyleName[32]; sprintf(lineStyleName, "_line_%s_w%.1f", lineHexColor, LineStyle[i].width); styleName = msStringConcatenate(styleName, lineStyleName); } } if (SymbologyFlag[Polygon]) { /* ffffffff normal 1 1 */ if (currentLayer && currentLayer->compositer && currentLayer->compositer->opacity > 0 && currentLayer->compositer->opacity < 100 && PolygonColor.alpha == 255) PolygonColor.alpha = MS_NINT(currentLayer->compositer->opacity*2.55); sprintf(polygonHexColor,"%02x%02x%02x%02x", PolygonColor.alpha, PolygonColor.blue, PolygonColor.green, PolygonColor.red); char polygonStyleName[64]; sprintf(polygonStyleName, "_polygon_%s", polygonHexColor); styleName = msStringConcatenate(styleName, polygonStyleName); } if (SymbologyFlag[Label]) { /* ffffffff normal 1 */ if (currentLayer && currentLayer->compositer && currentLayer->compositer->opacity > 0 && currentLayer->compositer->opacity < 100 && LabelColor.alpha == 255) LabelColor.alpha = MS_NINT(currentLayer->compositer->opacity*2.55); sprintf(labelHexColor,"%02x%02x%02x%02x", LabelColor.alpha, LabelColor.blue, LabelColor.green, LabelColor.red); // __TODO__ add label scale char labelStyleName[64]; sprintf(labelStyleName, "_label_%s", labelHexColor); styleName = msStringConcatenate(styleName, labelStyleName); } if (SymbologyFlag[Symbol]) { /* */ /* __TODO__ add label scale */ styleName = msStringConcatenate(styleName, "_"); styleName = msStringConcatenate(styleName, SymbolName); } const char *styleUrl = msLookupHashTable(StyleHashTable, styleName); if (!styleUrl) { char *styleValue=NULL; styleValue = msStringConcatenate(styleValue, "#"); styleValue = msStringConcatenate(styleValue, styleName); hashObj *hash = msInsertHashTable(StyleHashTable, styleName, styleValue); styleUrl = hash->data; msFree(styleValue); /* Insert new Style node into Document node*/ xmlNodePtr styleNode = xmlNewChild(DocNode, NULL, BAD_CAST "Style", NULL); xmlNewProp(styleNode, BAD_CAST "id", BAD_CAST styleName); if (SymbologyFlag[Polygon]) { xmlNodePtr polyStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "PolyStyle", NULL); xmlNewChild(polyStyleNode, NULL, BAD_CAST "color", BAD_CAST polygonHexColor); } if (SymbologyFlag[Line]) { for (int i=0; ialpha, LineStyle[i].color->blue, LineStyle[i].color->green, LineStyle[i].color->red); xmlNewChild(lineStyleNode, NULL, BAD_CAST "color", BAD_CAST lineHexColor); char width[16]; sprintf(width, "%.1f", LineStyle[i].width); xmlNewChild(lineStyleNode, NULL, BAD_CAST "width", BAD_CAST width); } } if (SymbologyFlag[Symbol]) { xmlNodePtr iconStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "IconStyle", NULL); xmlNodePtr iconNode = xmlNewChild(iconStyleNode, NULL, BAD_CAST "Icon", NULL); xmlNewChild(iconNode, NULL, BAD_CAST "href", BAD_CAST SymbolUrl); /*char scale[16]; sprintf(scale, "%.1f", style->scale); xmlNewChild(iconStyleNode, NULL, BAD_CAST "scale", BAD_CAST scale);*/ } else { const char *value=msLookupHashTable(¤tLayer->metadata, "kml_default_symbol_href"); if (value && strlen(value) > 0) { xmlNodePtr iconStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "IconStyle", NULL); xmlNodePtr iconNode = xmlNewChild(iconStyleNode, NULL, BAD_CAST "Icon", NULL); xmlNewChild(iconNode, NULL, BAD_CAST "href", BAD_CAST value); } } if (SymbologyFlag[Label]) { xmlNodePtr labelStyleNode = xmlNewChild(styleNode, NULL, BAD_CAST "LabelStyle", NULL); xmlNewChild(labelStyleNode, NULL, BAD_CAST "color", BAD_CAST labelHexColor); /*char scale[16]; sprintf(scale, "%.1f", style->scale); xmlNewChild(iconStyleNode, NULL, BAD_CAST "scale", BAD_CAST scale);*/ } } if (styleName) msFree(styleName); return styleUrl; } void KmlRenderer::flushPlacemark() { if (PlacemarkNode) { const char *styleUrl = lookupPlacemarkStyle(); xmlNewChild(PlacemarkNode, NULL, BAD_CAST "styleUrl", BAD_CAST styleUrl); if (DescriptionNode) xmlAddChild(PlacemarkNode, DescriptionNode); if (GeomNode) xmlAddChild(PlacemarkNode, GeomNode); } } xmlNodePtr KmlRenderer::createDescriptionNode(shapeObj *shape) { /* */ /*description nodes for vector layers: - if kml_description is set, use it - if not, dump the attributes */ if (pszLayerDescMetadata) { char *pszTmp=NULL; char *pszTmpDesc = NULL; size_t bufferSize = 0; pszTmpDesc = msStrdup(pszLayerDescMetadata); for (int i=0; inumitems; i++) { bufferSize = strlen(currentLayer->items[i]) + 3; pszTmp = (char *)msSmallMalloc(bufferSize); snprintf(pszTmp, bufferSize, "%%%s%%",currentLayer->items[i]); if (strcasestr(pszTmpDesc, pszTmp)) pszTmpDesc = msCaseReplaceSubstring(pszTmpDesc, pszTmp, shape->values[i]); msFree(pszTmp); } xmlNodePtr descriptionNode = xmlNewNode(NULL, BAD_CAST "description"); xmlNodeAddContent(descriptionNode, BAD_CAST pszTmpDesc); msFree(pszTmpDesc); return descriptionNode; } else if ((papszLayerIncludeItems && nIncludeItems > 0) || (papszLayerExcludeItems && nExcludeItems > 0)) { /* -------------------------------------------------------------------- */ /* preffered way is to use the ExtendedData tag (#3728) */ /* http://code.google.com/apis/kml/documentation/extendeddata.html */ /* -------------------------------------------------------------------- */ xmlNodePtr extendedDataNode = xmlNewNode(NULL, BAD_CAST "ExtendedData"); xmlNodePtr dataNode = NULL; const char*pszAlias=NULL; int bIncludeAll = MS_FALSE; if(papszLayerIncludeItems && nIncludeItems == 1 && strcasecmp(papszLayerIncludeItems[0], "all") == 0) bIncludeAll = MS_TRUE; for (int i=0; inumitems; i++) { int j=0,k=0; /*TODO optimize to calculate this only once per layer*/ for (j=0; jitems[i], papszLayerIncludeItems[j]) == 0) break; } if (j 0) { for (k=0; kitems[i], papszLayerExcludeItems[k]) == 0) break; } } if (nExcludeItems == 0 || k == nExcludeItems) { dataNode = xmlNewNode(NULL, BAD_CAST "Data"); xmlNewProp(dataNode, BAD_CAST "name", BAD_CAST currentLayer->items[i]); pszAlias = getAliasName(currentLayer, currentLayer->items[i], "GO"); if (pszAlias) xmlNewChild(dataNode, NULL, BAD_CAST "displayName", BAD_CAST pszAlias); else xmlNewChild(dataNode, NULL, BAD_CAST "displayName", BAD_CAST currentLayer->items[i]); if (shape->values[i] && strlen(shape->values[i])) xmlNewChild(dataNode, NULL, BAD_CAST "value", BAD_CAST shape->values[i]); else xmlNewChild(dataNode, NULL, BAD_CAST "value", NULL); xmlAddChild(extendedDataNode, dataNode); } } } return extendedDataNode; } return NULL; } void KmlRenderer::addLineStyleToList(strokeStyleObj *style) { /*actually this is not necessary. kml only uses the last LineStyle so we should not bother keeping them all*/ int i =0; for (i=0; iwidth == LineStyle[i].width && LineStyle[i].color->alpha == style->color->alpha && LineStyle[i].color->red == style->color->red && LineStyle[i].color->green == style->color->green && LineStyle[i].color->blue == style->color->blue) break; } if (i == numLineStyle) { numLineStyle++; if (LineStyle == NULL) LineStyle = (strokeStyleObj *)msSmallMalloc(sizeof(strokeStyleObj)); else LineStyle = (strokeStyleObj *)msSmallRealloc(LineStyle, sizeof(strokeStyleObj)*numLineStyle); memcpy(&LineStyle[numLineStyle-1], style, sizeof(strokeStyleObj)); } } #endif mapserver-7.4.3/mapkmlrenderer.h000066400000000000000000000142301357574274700167370ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Headers for mapkmlrenderer.cpp Google Earth KML output * Author: David Kana and the MapServer team * ****************************************************************************** * Copyright (c) 1996-2009 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #ifndef MAPKMLRENDERER_H #define MAPKMLRENDERER_H #include "mapserver-config.h" #if defined(USE_KML) #include "mapserver.h" #include "maplibxml2.h" class KmlRenderer { private: const char *pszLayerDescMetadata; /*if the kml_description is set*/ char **papszLayerIncludeItems; int nIncludeItems; char **papszLayerExcludeItems; int nExcludeItems; const char *pszLayerNameAttributeMetadata; protected: // map properties int Width, Height; rectObj MapExtent; double MapCellsize; colorObj BgColor; char MapPath[MS_MAXPATHLEN]; // xml nodes pointers xmlDocPtr XmlDoc; xmlNodePtr DocNode; xmlNodePtr LayerNode; xmlNodePtr GroundOverlayNode; xmlNodePtr PlacemarkNode; xmlNodePtr GeomNode; xmlNodePtr DescriptionNode; int CurrentShapeIndex; int CurrentDrawnShapeIndex; char *CurrentShapeName; char **Items; int NumItems; int DumpAttributes; // placemark symbology hashTableObj *StyleHashTable; colorObj LabelColor; strokeStyleObj *LineStyle; int numLineStyle; colorObj PolygonColor; char SymbolName[128]; char SymbolUrl[128]; enum { NumSymbologyFlag = 4}; char SymbologyFlag[NumSymbologyFlag]; enum symbFlagsEnum { Label, Line, Polygon, Symbol }; int FirstLayer; mapObj *map; layerObj *currentLayer; int AltitudeMode; int Tessellate; int Extrude; enum altitudeModeEnum { undefined, clampToGround, relativeToGround, absolute }; /**True if elevation is taken from a feature attribute*/ bool mElevationFromAttribute; /**Attribute index of elevation (or -1 if elevation is not attribute driven*/ int mElevationAttributeIndex; double mCurrentElevationValue; outputFormatObj *aggFormat; protected: imageObj* createInternalImage(); xmlNodePtr createPlacemarkNode(xmlNodePtr parentNode, char *styleUrl); xmlNodePtr createGroundOverlayNode(xmlNodePtr parentNode, char *imageHref, layerObj *layer); xmlNodePtr createDescriptionNode(shapeObj *shape); const char* lookupSymbolUrl(imageObj *img, symbolObj *symbol, symbolStyleObj *style); void addCoordsNode(xmlNodePtr parentNode, pointObj *pts, int numPts); void setupRenderingParams(hashTableObj *layerMetadata); void addAddRenderingSpecifications(xmlNodePtr node); int checkProjection(mapObj *map); int createIconImage(char *fileName, symbolObj *symbol, symbolStyleObj *style); void renderSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); ////////////////////////////////////////////////////////////////////////////// void renderLineVector(imageObj *img, shapeObj *p, strokeStyleObj *style); void renderPolygonVector(imageObj *img, shapeObj *p, colorObj *color); void renderGlyphsVector(imageObj *img, double x, double y, labelStyleObj *style, char *text); const char* lookupPlacemarkStyle(); void flushPlacemark(); xmlNodePtr getGeomParentNode(const char *geomName); char* getLayerName(layerObj *layer); void processLayer(layerObj *layer, outputFormatObj *format); void addLineStyleToList(strokeStyleObj *style); const char *getAliasName(layerObj *lp, char *pszItemName, const char *namespaces); public: KmlRenderer(int width, int height, outputFormatObj *format, colorObj* color = NULL); virtual ~KmlRenderer(); imageObj* createImage(int width, int height, outputFormatObj *format, colorObj* bg); int saveImage(imageObj *img, FILE *fp, outputFormatObj *format); int startNewLayer(imageObj *img, layerObj *layer); int closeNewLayer(imageObj *img, layerObj *layer); void startShape(imageObj *img, shapeObj *shape); void endShape(imageObj *img, shapeObj *shape); void renderLine(imageObj *img, shapeObj *p, strokeStyleObj *style); void renderPolygon(imageObj *img, shapeObj *p, colorObj *color); void renderGlyphs(imageObj *img, pointObj *labelpnt, char *text, double angle, colorObj *clr, colorObj *olcolor, int olwidth); // Symbols void renderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void renderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void renderEllipseSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); void renderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); int getTruetypeTextBBox(imageObj *img,char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances); int mergeRasterBuffer(imageObj *image, rasterBufferObj *rb); }; #endif /* USE_KML */ #endif mapserver-7.4.3/maplabel.c000066400000000000000000001143531357574274700155060ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Labeling Implementation. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* ** maplabel.c: Routines to enable text drawing, BITMAP or TRUETYPE. */ #include #include "mapserver.h" #include "fontcache.h" void initTextPath(textPathObj *ts) { memset(ts,0,sizeof(*ts)); } int WARN_UNUSED msLayoutTextSymbol(mapObj *map, textSymbolObj *ts, textPathObj *tgret); #if defined(USE_EXTENDED_DEBUG) && 0 static void msDebugTextPath(textSymbolObj *ts) { int i; msDebug("text: %s\n",ts->annotext); if(ts->textpath) { for(i=0;itextpath->numglyphs; i++) { glyphObj *g = &ts->textpath->glyphs[i]; msDebug("glyph %d: pos: %f %f\n",g->glyph->key.codepoint,g->pnt.x,g->pnt.y); } } else { msDebug("no glyphs\n"); } msDebug("\n=========================================\n"); } #endif int msComputeTextPath(mapObj *map, textSymbolObj *ts) { textPathObj *tgret = msSmallMalloc(sizeof(textPathObj)); assert(ts->annotext && *ts->annotext); initTextPath(tgret); ts->textpath = tgret; tgret->absolute = 0; tgret->glyph_size = ts->label->size * ts->scalefactor; tgret->glyph_size = MS_MAX(tgret->glyph_size, ts->label->minsize * ts->resolutionfactor); tgret->glyph_size = MS_NINT(MS_MIN(tgret->glyph_size, ts->label->maxsize * ts->resolutionfactor)); tgret->line_height = ceil(tgret->glyph_size * 1.33); return msLayoutTextSymbol(map,ts,tgret); } void initTextSymbol(textSymbolObj *ts) { memset(ts,0,sizeof(*ts)); } void freeTextPath(textPathObj *tp) { free(tp->glyphs); if(tp->bounds.poly) { free(tp->bounds.poly->point); free(tp->bounds.poly); } } void freeTextSymbol(textSymbolObj *ts) { if(ts->textpath) { freeTextPath(ts->textpath); free(ts->textpath); } if(ts->label->numstyles) { if(ts->style_bounds) { int i; for(i=0;ilabel->numstyles; i++) { if(ts->style_bounds[i]) { if(ts->style_bounds[i]->poly) { free(ts->style_bounds[i]->poly->point); free(ts->style_bounds[i]->poly); } free(ts->style_bounds[i]); } } free(ts->style_bounds); } } free(ts->annotext); if(freeLabel(ts->label) == MS_SUCCESS) { free(ts->label); } } void msCopyTextPath(textPathObj *dst, textPathObj *src) { int i; *dst = *src; if(src->bounds.poly) { dst->bounds.poly = msSmallMalloc(sizeof(lineObj)); dst->bounds.poly->numpoints = src->bounds.poly->numpoints; dst->bounds.poly->point = msSmallMalloc(src->bounds.poly->numpoints * sizeof(pointObj)); for(i=0; ibounds.poly->numpoints; i++) { dst->bounds.poly->point[i] = src->bounds.poly->point[i]; } } else { dst->bounds.poly = NULL; } if(dst->numglyphs > 0) { dst->glyphs = msSmallMalloc(dst->numglyphs * sizeof(glyphObj)); for(i=0; inumglyphs; i++) dst->glyphs[i] = src->glyphs[i]; } } void msCopyTextSymbol(textSymbolObj *dst, textSymbolObj *src) { *dst = *src; MS_REFCNT_INCR(src->label); dst->annotext = msStrdup(src->annotext); if(dst->textpath) { dst->textpath = msSmallMalloc(sizeof(textPathObj)); msCopyTextPath(dst->textpath,src->textpath); } } static int labelNeedsDeepCopy(labelObj *label) { int i; if(label->numbindings > 0) return MS_TRUE; for(i=0; inumstyles; i++) { if(label->styles[i]->numbindings>0) { return MS_TRUE; } } return MS_FALSE; } void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char *string, double scalefactor, double resolutionfactor, label_cache_mode cache) { if(cache == duplicate_always) { ts->label = msSmallMalloc(sizeof(labelObj)); initLabel(ts->label); msCopyLabel(ts->label,l); } else if(cache == duplicate_never) { ts->label = l; MS_REFCNT_INCR(l); } else if(cache == duplicate_if_needed && labelNeedsDeepCopy(l)) { ts->label = msSmallMalloc(sizeof(labelObj)); initLabel(ts->label); msCopyLabel(ts->label,l); } else { ts->label = l; MS_REFCNT_INCR(l); } ts->resolutionfactor = resolutionfactor; ts->scalefactor = scalefactor; ts->annotext = string; /* we take the ownership of the annotation text */ ts->rotation = l->angle * MS_DEG_TO_RAD; } int msAddLabelGroup(mapObj *map, imageObj *image, layerObj* layer, int classindex, shapeObj *shape, pointObj *point, double featuresize) { int l,s, priority; labelCacheSlotObj *cacheslot; labelCacheMemberObj *cachePtr=NULL; layerObj *layerPtr=NULL; classObj *classPtr=NULL; int numtextsymbols = 0; textSymbolObj **textsymbols, *ts; int layerindex = layer->index; // We cannot use GET_LAYER here because in drawQuery the drawing may happen // on a temp layer only. layerPtr = layer; classPtr = layer->class[classindex]; if(classPtr->numlabels == 0) return MS_SUCCESS; /* not an error just nothing to do */ /* check that the label intersects the layer mask */ if(layerPtr->mask) { int maskLayerIdx = msGetLayerIndex(map,layerPtr->mask); layerObj *maskLayer = GET_LAYER(map,maskLayerIdx); unsigned char *alphapixptr; if(maskLayer->maskimage && MS_IMAGE_RENDERER(maskLayer->maskimage)->supports_pixel_buffer) { rasterBufferObj rb; int x,y; memset(&rb,0,sizeof(rasterBufferObj)); if(UNLIKELY(MS_FAILURE == MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,&rb))) { return MS_FAILURE; } x = MS_NINT(point->x); y = MS_NINT(point->y); /* Using label repeatdistance, we might have a point with x/y below 0. See #4764 */ if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { assert(rb.type == MS_BUFFER_BYTE_RGBA); alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ return MS_SUCCESS; } } else { return MS_SUCCESS; /* label point does not intersect image extent, we cannot know if it intersects mask, so we discard it (#5237)*/ } } else { msSetError(MS_MISCERR, "Layer (%s) references references a mask layer, but the selected renderer does not support them", "msAddLabelGroup()", layerPtr->name); return (MS_FAILURE); } } textsymbols = msSmallMalloc(classPtr->numlabels * sizeof(textSymbolObj*)); for(l=0; lnumlabels; l++) { labelObj *lbl = classPtr->labels[l]; char *annotext; if(msGetLabelStatus(map,layerPtr,shape,lbl) == MS_OFF) { continue; } annotext = msShapeGetLabelAnnotation(layerPtr,shape,lbl); if(!annotext) { for(s=0;snumstyles;s++) { if(lbl->styles[s]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) break; /* we have a "symbol only label, so we shouldn't skip this label */ } if(s == lbl->numstyles) { continue; /* no anno text, and no label symbols */ } } ts = msSmallMalloc(sizeof(textSymbolObj)); initTextSymbol(ts); msPopulateTextSymbolForLabelAndString(ts,lbl,annotext,layerPtr->scalefactor,image->resolutionfactor, 1); if(annotext && *annotext && lbl->autominfeaturesize && featuresize > 0) { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,ts))) { freeTextSymbol(ts); free(ts); return MS_FAILURE; } if(featuresize < (ts->textpath->bounds.bbox.maxx - ts->textpath->bounds.bbox.minx)) { /* feature is too big to be drawn, skip it */ freeTextSymbol(ts); free(ts); continue; } } textsymbols[numtextsymbols] = ts; numtextsymbols++; } if(numtextsymbols == 0) { free(textsymbols); return MS_SUCCESS; } /* Validate label priority value and get ref on label cache for it */ priority = classPtr->labels[0]->priority; /* take priority from the first label */ if (priority < 1) priority = 1; else if (priority > MS_MAX_LABEL_PRIORITY) priority = MS_MAX_LABEL_PRIORITY; cacheslot = &(map->labelcache.slots[priority-1]); if(cacheslot->numlabels == cacheslot->cachesize) { /* just add it to the end */ cacheslot->labels = (labelCacheMemberObj *) realloc(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->cachesize += MS_LABELCACHEINCREMENT; } cachePtr = &(cacheslot->labels[cacheslot->numlabels]); cachePtr->layerindex = layerindex; /* so we can get back to this *raw* data if necessary */ cachePtr->classindex = classindex; cachePtr->point = *point; /* the actual label point */ cachePtr->leaderline = NULL; cachePtr->leaderbbox = NULL; cachePtr->markerid = -1; cachePtr->status = MS_FALSE; if(layerPtr->type == MS_LAYER_POINT && classPtr->numstyles > 0) { /* cache the marker placement, it's already on the map */ /* TO DO: at the moment only checks the bottom style, perhaps should check all of them */ /* #2347: after RFC-24 classPtr->styles could be NULL so we check it */ double w, h; if(msGetMarkerSize(map, classPtr->styles[0], &w, &h, layerPtr->scalefactor) != MS_SUCCESS) return(MS_FAILURE); if(cacheslot->nummarkers == cacheslot->markercachesize) { /* just add it to the end */ cacheslot->markers = (markerCacheMemberObj *) realloc(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->markercachesize+=MS_LABELCACHEINCREMENT; } cacheslot->markers[cacheslot->nummarkers].bounds.minx = (point->x - .5 * w); cacheslot->markers[cacheslot->nummarkers].bounds.miny = (point->y - .5 * h); cacheslot->markers[cacheslot->nummarkers].bounds.maxx = cacheslot->markers[cacheslot->nummarkers].bounds.minx + (w-1); cacheslot->markers[cacheslot->nummarkers].bounds.maxy = cacheslot->markers[cacheslot->nummarkers].bounds.miny + (h-1); cacheslot->markers[cacheslot->nummarkers].id = cacheslot->numlabels; cachePtr->markerid = cacheslot->nummarkers; cacheslot->nummarkers++; } cachePtr->textsymbols = textsymbols; cachePtr->numtextsymbols = numtextsymbols; cacheslot->numlabels++; return(MS_SUCCESS); } int msAddLabel(mapObj *map, imageObj *image, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize, textSymbolObj *ts) { int i; labelCacheSlotObj *cacheslot; labelCacheMemberObj *cachePtr=NULL; char *annotext = NULL; layerObj *layerPtr; classObj *classPtr; layerPtr=GET_LAYER(map,layerindex); assert(layerPtr); assert(classindex < layerPtr->numclasses); classPtr = layerPtr->class[classindex]; assert(label); if(ts) annotext = ts->annotext; else if(shape) annotext = msShapeGetLabelAnnotation(layerPtr,shape,label); if(!annotext) { /* check if we have a labelpnt style */ for(i=0; inumstyles; i++) { if(label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) break; } if(i==label->numstyles) { /* label has no text or marker symbols */ if(ts) { freeTextSymbol(ts); free(ts); } return MS_SUCCESS; } } if(classPtr->leader) { if(ts && ts->textpath && ts->textpath->absolute) { msSetError(MS_MISCERR, "LEADERs are not supported on ANGLE FOLLOW labels", "msAddLabel()"); return MS_FAILURE; } } /* check that the label intersects the layer mask */ if (layerPtr->mask) { int maskLayerIdx = msGetLayerIndex(map, layerPtr->mask); layerObj *maskLayer = GET_LAYER(map, maskLayerIdx); unsigned char *alphapixptr; if (maskLayer->maskimage && MS_IMAGE_RENDERER(maskLayer->maskimage)->supports_pixel_buffer) { rasterBufferObj rb; memset(&rb, 0, sizeof (rasterBufferObj)); if(UNLIKELY(MS_FAILURE == MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage, &rb))) { return MS_FAILURE; } assert(rb.type == MS_BUFFER_BYTE_RGBA); if (point) { int x = MS_NINT(point->x); int y = MS_NINT(point->y); /* Using label repeatdistance, we might have a point with x/y below 0. See #4764 */ if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { alphapixptr = rb.data.rgba.a+rb.data.rgba.row_step*y + rb.data.rgba.pixel_step*x; if(!*alphapixptr) { /* label point does not intersect mask */ if(ts) { freeTextSymbol(ts); free(ts); } return MS_SUCCESS; } } else { return MS_SUCCESS; /* label point does not intersect image extent, we cannot know if it intersects mask, so we discard it (#5237)*/ } } else if (ts && ts->textpath) { int i = 0; for (i = 0; i < ts->textpath->numglyphs; i++) { int x = MS_NINT(ts->textpath->glyphs[i].pnt.x); int y = MS_NINT(ts->textpath->glyphs[i].pnt.y); if (x >= 0 && x < rb.width && y >= 0 && y < rb.height) { alphapixptr = rb.data.rgba.a + rb.data.rgba.row_step * y + rb.data.rgba.pixel_step*x; if (!*alphapixptr) { freeTextSymbol(ts); free(ts); return MS_SUCCESS; } } else { freeTextSymbol(ts); free(ts); return MS_SUCCESS; /* label point does not intersect image extent, we cannot know if it intersects mask, so we discard it (#5237)*/ } } } } else { msSetError(MS_MISCERR, "Layer (%s) references references a mask layer, but the selected renderer does not support them", "msAddLabel()", layerPtr->name); return (MS_FAILURE); } } if(!ts) { ts = msSmallMalloc(sizeof(textSymbolObj)); initTextSymbol(ts); msPopulateTextSymbolForLabelAndString(ts,label,annotext,layerPtr->scalefactor,image->resolutionfactor, 1); } if(annotext && label->autominfeaturesize && featuresize > 0) { if(!ts->textpath) { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,ts))) return MS_FAILURE; } if(featuresize > (ts->textpath->bounds.bbox.maxx - ts->textpath->bounds.bbox.minx)) { /* feature is too big to be drawn, skip it */ freeTextSymbol(ts); free(ts); return MS_SUCCESS; } } /* Validate label priority value and get ref on label cache for it */ if (label->priority < 1) label->priority = 1; else if (label->priority > MS_MAX_LABEL_PRIORITY) label->priority = MS_MAX_LABEL_PRIORITY; cacheslot = &(map->labelcache.slots[label->priority-1]); if(cacheslot->numlabels == cacheslot->cachesize) { /* just add it to the end */ cacheslot->labels = (labelCacheMemberObj *) realloc(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->labels, sizeof(labelCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->cachesize += MS_LABELCACHEINCREMENT; } cachePtr = &(cacheslot->labels[cacheslot->numlabels]); cachePtr->layerindex = layerindex; /* so we can get back to this *raw* data if necessary */ cachePtr->classindex = classindex; #ifdef include_deprecated if(shape) { cachePtr->shapetype = shape->type; } else { cachePtr->shapetype = MS_SHAPE_POINT; } #endif cachePtr->leaderline = NULL; cachePtr->leaderbbox = NULL; /* Store the label point or the label path (Bug #1620) */ if ( point ) { cachePtr->point = *point; /* the actual label point */ } else { assert(ts && ts->textpath && ts->textpath->absolute && ts->textpath->numglyphs>0); /* Use the middle point of the labelpath for mindistance calculations */ cachePtr->point = ts->textpath->glyphs[ts->textpath->numglyphs/2].pnt; } /* copy the label */ cachePtr->numtextsymbols = 1; cachePtr->textsymbols = (textSymbolObj **) msSmallMalloc(sizeof(textSymbolObj*)); cachePtr->textsymbols[0] = ts; cachePtr->markerid = -1; cachePtr->status = MS_FALSE; if(layerPtr->type == MS_LAYER_POINT && classPtr->numstyles > 0) { /* cache the marker placement, it's already on the map */ double w, h; if(cacheslot->nummarkers == cacheslot->markercachesize) { /* just add it to the end */ cacheslot->markers = (markerCacheMemberObj *) realloc(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT)); MS_CHECK_ALLOC(cacheslot->markers, sizeof(markerCacheMemberObj)*(cacheslot->cachesize+MS_LABELCACHEINCREMENT), MS_FAILURE); cacheslot->markercachesize+=MS_LABELCACHEINCREMENT; } i = cacheslot->nummarkers; /* TO DO: at the moment only checks the bottom style, perhaps should check all of them */ /* #2347: after RFC-24 classPtr->styles could be NULL so we check it */ if(classPtr->styles != NULL) { if(msGetMarkerSize(map, classPtr->styles[0], &w, &h, layerPtr->scalefactor) != MS_SUCCESS) return(MS_FAILURE); cacheslot->markers[cacheslot->nummarkers].bounds.minx = (point->x - .5 * w); cacheslot->markers[cacheslot->nummarkers].bounds.miny = (point->y - .5 * h); cacheslot->markers[cacheslot->nummarkers].bounds.maxx = cacheslot->markers[cacheslot->nummarkers].bounds.minx + (w-1); cacheslot->markers[cacheslot->nummarkers].bounds.maxy = cacheslot->markers[cacheslot->nummarkers].bounds.miny + (h-1); cacheslot->markers[i].id = cacheslot->numlabels; cachePtr->markerid = i; cacheslot->nummarkers++; } } cacheslot->numlabels++; return(MS_SUCCESS); } /* ** Is a label completely in the image, reserving a gutter (in pixels) inside ** image for no labels (effectively making image larger. The gutter can be ** negative in cases where a label has a buffer around it. */ static int labelInImage(int width, int height, lineObj *lpoly, rectObj *bounds, int gutter) { int j; /* do a bbox test first */ if(bounds->minx >= gutter && bounds->miny >= gutter && bounds->maxx < width-gutter && bounds->maxy < height-gutter) { return MS_TRUE; } if(lpoly) { for(j=1; jnumpoints; j++) { if(lpoly->point[j].x < gutter) return(MS_FALSE); if(lpoly->point[j].x >= width-gutter) return(MS_FALSE); if(lpoly->point[j].y < gutter) return(MS_FALSE); if(lpoly->point[j].y >= height-gutter) return(MS_FALSE); } } else { /* if no poly, then return false as the boundong box intersected */ return MS_FALSE; } return(MS_TRUE); } void insertRenderedLabelMember(mapObj *map, labelCacheMemberObj *cachePtr) { if(map->labelcache.num_rendered_members == map->labelcache.num_allocated_rendered_members) { if(map->labelcache.num_rendered_members == 0) { map->labelcache.num_allocated_rendered_members = 50; } else { map->labelcache.num_allocated_rendered_members *= 2; } map->labelcache.rendered_text_symbols = msSmallRealloc(map->labelcache.rendered_text_symbols, map->labelcache.num_allocated_rendered_members * sizeof(labelCacheMemberObj*)); } map->labelcache.rendered_text_symbols[map->labelcache.num_rendered_members++] = cachePtr; } static inline int testSegmentLabelBBoxIntersection(const rectObj *leaderbbox, const pointObj *lp1, const pointObj *lp2, const label_bounds *test) { if(msRectOverlap(leaderbbox, &test->bbox)) { if(test->poly) { int pp; for(pp=1; pppoly->numpoints; pp++) { if(msIntersectSegments( &(test->poly->point[pp-1]), &(test->poly->point[pp]), lp1,lp2) == MS_TRUE) { return(MS_FALSE); } } } else { pointObj tp1,tp2; tp1.x = test->bbox.minx; tp1.y = test->bbox.miny; tp2.x = test->bbox.minx; tp2.y = test->bbox.maxy; if(msIntersectSegments(lp1,lp2,&tp1,&tp2)) return MS_FALSE; tp2.x = test->bbox.maxx; tp2.y = test->bbox.miny; if(msIntersectSegments(lp1,lp2,&tp1,&tp2)) return MS_FALSE; tp1.x = test->bbox.maxx; tp1.y = test->bbox.maxy; tp2.x = test->bbox.minx; tp2.y = test->bbox.maxy; if(msIntersectSegments(lp1,lp2,&tp1,&tp2)) return MS_FALSE; tp2.x = test->bbox.maxx; tp2.y = test->bbox.miny; if(msIntersectSegments(lp1,lp2,&tp1,&tp2)) return MS_FALSE; } } return MS_TRUE; } int msTestLabelCacheLeaderCollision(mapObj *map, pointObj *lp1, pointObj *lp2) { int p; rectObj leaderbbox; leaderbbox.minx = MS_MIN(lp1->x,lp2->x); leaderbbox.maxx = MS_MAX(lp1->x,lp2->x); leaderbbox.miny = MS_MIN(lp1->y,lp2->y); leaderbbox.maxy = MS_MAX(lp1->y,lp2->y); for(p=0; plabelcache.num_rendered_members; p++) { labelCacheMemberObj *curCachePtr= map->labelcache.rendered_text_symbols[p]; if(msRectOverlap(&leaderbbox, &(curCachePtr->bbox))) { /* leaderbbox interesects with the curCachePtr's global bbox */ int t; for(t=0; tnumtextsymbols; t++) { int s; textSymbolObj *ts = curCachePtr->textsymbols[t]; /* check for intersect with textpath */ if(ts->textpath && testSegmentLabelBBoxIntersection(&leaderbbox, lp1, lp2, &ts->textpath->bounds) == MS_FALSE) { return MS_FALSE; } /* check for intersect with label's labelpnt styles */ if(ts->style_bounds) { for(s=0; slabel->numstyles; s++) { if(ts->label->styles[s]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { if(testSegmentLabelBBoxIntersection(&leaderbbox, lp1,lp2, ts->style_bounds[s]) == MS_FALSE) { return MS_FALSE; } } } } } if(curCachePtr->leaderbbox) { if(msIntersectSegments(lp1,lp2,&(curCachePtr->leaderline->point[0]), &(curCachePtr->leaderline->point[1])) == MS_TRUE) { return MS_FALSE; } } } } return MS_TRUE; } /* msTestLabelCacheCollisions() ** ** Compares label bounds (in *bounds) against labels already drawn and markers from cache and ** returns MS_FALSE if it collides with another label, or collides with a marker. ** ** This function is used by the various msDrawLabelCacheXX() implementations. int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, label_bounds *bounds, int current_priority, int current_label); */ int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, label_bounds *lb, int current_priority, int current_label) { labelCacheObj *labelcache = &(map->labelcache); int i, p, ll; /* * Check against image bounds first */ if(!cachePtr->textsymbols[0]->label->partials) { if(labelInImage(map->width, map->height, lb->poly, &lb->bbox, labelcache->gutter) == MS_FALSE) { return MS_FALSE; } } /* Compare against all rendered markers from this priority level and higher. ** Labels can overlap their own marker and markers from lower priority levels */ for (p=current_priority; p < MS_MAX_LABEL_PRIORITY; p++) { labelCacheSlotObj *markerslot; markerslot = &(labelcache->slots[p]); for ( ll = 0; ll < markerslot->nummarkers; ll++ ) { if ( !(p == current_priority && current_label == markerslot->markers[ll].id ) ) { /* labels can overlap their own marker */ if ( intersectLabelPolygons(NULL, &markerslot->markers[ll].bounds, lb->poly, &lb->bbox ) == MS_TRUE ) { return MS_FALSE; } } } } for(p=0; pnum_rendered_members; p++) { labelCacheMemberObj *curCachePtr= labelcache->rendered_text_symbols[p]; if(msRectOverlap(&curCachePtr->bbox,&lb->bbox)) { for(i=0; inumtextsymbols; i++) { int j; textSymbolObj *ts = curCachePtr->textsymbols[i]; if(ts->textpath && intersectLabelPolygons(ts->textpath->bounds.poly, &ts->textpath->bounds.bbox, lb->poly, &lb->bbox) == MS_TRUE ) { return MS_FALSE; } if(ts->style_bounds) { for(j=0;jlabel->numstyles;j++) { if(ts->style_bounds[j] && ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { if(intersectLabelPolygons(ts->style_bounds[j]->poly, &ts->style_bounds[j]->bbox, lb->poly, &lb->bbox)) { return MS_FALSE; } } } } } } if(curCachePtr->leaderline) { if(testSegmentLabelBBoxIntersection(curCachePtr->leaderbbox, &curCachePtr->leaderline->point[0], &curCachePtr->leaderline->point[1], lb) == MS_FALSE) { return MS_FALSE; } } } return MS_TRUE; } /* utility function to get the rect of a string outside of a rendering loop, i.e. without going through textpath layouts */ int msGetStringSize(mapObj *map, labelObj *label, int size, char *string, rectObj *r) { textSymbolObj ts; double lsize = label->size; initTextSymbol(&ts); label->size = size; msPopulateTextSymbolForLabelAndString(&ts,label,msStrdup(string),1,1,0); if(UNLIKELY(MS_FAILURE == msGetTextSymbolSize(map,&ts,r))) return MS_FAILURE; label->size = lsize; freeTextSymbol(&ts); return MS_SUCCESS; } int msInitFontSet(fontSetObj *fontset) { fontset->filename = NULL; /* fontset->fonts = NULL; */ initHashTable(&(fontset->fonts)); fontset->numfonts = 0; fontset->map = NULL; return( 0 ); } int msFreeFontSet(fontSetObj *fontset) { if (fontset->filename) free(fontset->filename); fontset->filename = NULL; if (&(fontset->fonts)) msFreeHashItems(&(fontset->fonts)); /* fontset->fonts = NULL; */ fontset->numfonts = 0; return( 0 ); } int msLoadFontSet(fontSetObj *fontset, mapObj *map) { FILE *stream; char buffer[MS_BUFFER_LENGTH]; char alias[64], file1[MS_PATH_LENGTH], file2[MS_PATH_LENGTH]; char *path; char szPath[MS_MAXPATHLEN]; int i; int bFullPath = 0; if(fontset->numfonts != 0) /* already initialized */ return(0); if(!fontset->filename) return(0); fontset->map = (mapObj *)map; path = msGetPath(fontset->filename); /* fontset->fonts = msCreateHashTable(); // create font hash */ /* if(!fontset->fonts) { */ /* msSetError(MS_HASHERR, "Error initializing font hash.", "msLoadFontSet()"); */ /* return(-1); */ /* } */ stream = fopen( msBuildPath(szPath, fontset->map->mappath, fontset->filename), "r"); if(!stream) { msSetError(MS_IOERR, "Error opening fontset %s.", "msLoadFontset()", fontset->filename); return(-1); } i = 0; while(fgets(buffer, MS_BUFFER_LENGTH, stream)) { /* while there's something to load */ if(buffer[0] == '#' || buffer[0] == '\n' || buffer[0] == '\r' || buffer[0] == ' ') continue; /* skip comments and blank lines */ sscanf(buffer,"%s %s", alias, file1); if (!(*file1) || !(*alias) || (strlen(file1) <= 0)) continue; bFullPath = 0; #if defined(_WIN32) && !defined(__CYGWIN__) if (file1[0] == '\\' || (strlen(file1) > 1 && (file1[1] == ':'))) bFullPath = 1; #else if(file1[0] == '/') bFullPath = 1; #endif if(bFullPath) { /* already full path */ msInsertHashTable(&(fontset->fonts), alias, file1); } else { snprintf(file2, sizeof(file2), "%s%s", path, file1); /* msInsertHashTable(fontset->fonts, alias, file2); */ /* ** msBuildPath is use here, but if we have to save the fontset file ** the msBuildPath must be done everywhere the fonts are used and ** removed here. */ msInsertHashTable(&(fontset->fonts), alias, msBuildPath(szPath, fontset->map->mappath, file2)); } i++; } fontset->numfonts = i; fclose(stream); /* close the file */ free(path); return(0); } int msGetTextSymbolSize(mapObj *map, textSymbolObj *ts, rectObj *r) { if(!ts->textpath) { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,ts))) return MS_FAILURE; } *r = ts->textpath->bounds.bbox; return MS_SUCCESS; } /* ** Note: All these routines assume a reference point at the LL corner of the text. GD's ** bitmapped fonts use UL and this is compensated for. Note the rect is relative to the ** LL corner of the text to be rendered, this is first line for TrueType fonts. */ #define MARKER_SLOP 2 pointObj get_metrics(pointObj *p, int position, textPathObj *tp, int ox, int oy, double rotation, int buffer, label_bounds *bounds) { pointObj q; double x1=0, y1=0, x2=0, y2=0; double sin_a,cos_a; double w, h, x, y; w = tp->bounds.bbox.maxx - tp->bounds.bbox.minx; h = tp->bounds.bbox.maxy - tp->bounds.bbox.miny; switch(position) { case MS_UL: x1 = -w - ox; y1 = -oy; break; case MS_UC: x1 = -(w/2.0); y1 = -oy - MARKER_SLOP; break; case MS_UR: x1 = ox; y1 = -oy; break; case MS_CL: x1 = -w - ox - MARKER_SLOP; if(oy > 0 && tp->numlines == 1) y1 = oy; else y1 = (h/2.0); break; case MS_CC: x1 = -(w/2.0) + ox; y1 = (h/2.0) + oy; break; case MS_CR: x1 = ox + MARKER_SLOP; if(oy > 0 && tp->numlines == 1) y1 = oy; else y1 = (h/2.0); break; case MS_LL: x1 = -w - ox; y1 = h + oy; break; case MS_LC: x1 = -(w/2.0); y1 = h + oy + MARKER_SLOP; break; case MS_LR: x1 = ox; y1 = h + oy; break; } if(rotation) { sin_a = sin(rotation); cos_a = cos(rotation); x = x1 - tp->bounds.bbox.minx; y = tp->bounds.bbox.maxy - y1; q.x = p->x + (x * cos_a - (y) * sin_a); q.y = p->y - (x * sin_a + (y) * cos_a); if(bounds) { x2 = x1 - buffer; /* ll */ y2 = y1 + buffer; bounds->poly->point[0].x = p->x + (x2 * cos_a - (-y2) * sin_a); bounds->poly->point[0].y = p->y - (x2 * sin_a + (-y2) * cos_a); x2 = x1 - buffer; /* ul */ y2 = y1 - h - buffer; bounds->poly->point[1].x = p->x + (x2 * cos_a - (-y2) * sin_a); bounds->poly->point[1].y = p->y - (x2 * sin_a + (-y2) * cos_a); x2 = x1 + w + buffer; /* ur */ y2 = y1 - h - buffer; bounds->poly->point[2].x = p->x + (x2 * cos_a - (-y2) * sin_a); bounds->poly->point[2].y = p->y - (x2 * sin_a + (-y2) * cos_a); x2 = x1 + w + buffer; /* lr */ y2 = y1 + buffer; bounds->poly->point[3].x = p->x + (x2 * cos_a - (-y2) * sin_a); bounds->poly->point[3].y = p->y - (x2 * sin_a + (-y2) * cos_a); bounds->poly->point[4].x = bounds->poly->point[0].x; bounds->poly->point[4].y = bounds->poly->point[0].y; fastComputeBounds(bounds->poly,&bounds->bbox); } } else { q.x = p->x + x1 - tp->bounds.bbox.minx; q.y = p->y + y1 ; if(bounds) { /* no rotation, we only need to return a bbox */ bounds->poly = NULL; bounds->bbox.minx = q.x - buffer; bounds->bbox.maxy = q.y + buffer + tp->bounds.bbox.maxy; bounds->bbox.maxx = q.x + w + buffer; bounds->bbox.miny = bounds->bbox.maxy - h - buffer*2; } } return(q); } int intersectTextSymbol(textSymbolObj *ts, label_bounds *lb) { if(ts->textpath && ts->textpath->absolute) { if(intersectLabelPolygons(lb->poly,&lb->bbox,ts->textpath->bounds.poly,&ts->textpath->bounds.bbox)) return MS_TRUE; } if(ts->style_bounds) { int s; for(s=0; slabel->numstyles; s++) { if(ts->style_bounds[s] && ts->label->styles[s]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT && intersectLabelPolygons(lb->poly,&lb->bbox,ts->style_bounds[s]->poly, &ts->style_bounds[s]->bbox)) return MS_TRUE; } } return MS_FALSE; } /* ** Variation on msIntersectPolygons. Label polygons aren't like shapefile polygons. They ** have no holes, and often do have overlapping parts (i.e. road symbols). */ int intersectLabelPolygons(lineObj *l1, rectObj *r1, lineObj *l2, rectObj *r2) { int v1,v2; pointObj *point; lineObj *p1,*p2,sp1,sp2; pointObj pnts1[5],pnts2[5]; /* STEP 0: check bounding boxes */ if(!msRectOverlap(r1,r2)) { /* from alans@wunderground.com */ return(MS_FALSE); } if(!l1 && !l2) return MS_TRUE; if(!l1) { p1 = &sp1; p1->numpoints = 5; p1->point = pnts1; pnts1[0].x = pnts1[1].x = pnts1[4].x = r1->minx; pnts1[2].x = pnts1[3].x = r1->maxx; pnts1[0].y = pnts1[3].y = pnts1[4].y = r1->miny; pnts1[1].y = pnts1[2].y = r1->maxy; } else { p1 = l1; } if(!l2) { p2 = &sp2; p2->numpoints = 5; p2->point = pnts2; pnts2[0].x = pnts2[1].x = pnts2[4].x = r2->minx; pnts2[2].x = pnts2[3].x = r2->maxx; pnts2[0].y = pnts2[3].y = pnts2[4].y = r2->miny; pnts2[1].y = pnts2[2].y = r2->maxy; } else { p2 = l2; } /* STEP 1: look for intersecting line segments */ for(v1=1; v1numpoints; v1++) for(v2=1; v2numpoints; v2++) if(msIntersectSegments(&(p1->point[v1-1]), &(p1->point[v1]), &(p2->point[v2-1]), &(p2->point[v2])) == MS_TRUE) { return(MS_TRUE); } /* STEP 2: polygon one completely contains two (only need to check one point from each part) */ point = &(p2->point[0]); if(msPointInPolygon(point, p1) == MS_TRUE) /* ok, the point is in a polygon */ return(MS_TRUE); /* STEP 3: polygon two completely contains one (only need to check one point from each part) */ point = &(p1->point[0]); if(msPointInPolygon(point, p2) == MS_TRUE) /* ok, the point is in a polygon */ return(MS_TRUE); return(MS_FALSE); } /* For MapScript, exactly the same the msInsertStyle */ int msInsertLabelStyle(labelObj *label, styleObj *style, int nStyleIndex) { int i; if (!style) { msSetError(MS_CHILDERR, "Can't insert a NULL Style", "msInsertLabelStyle()"); return -1; } /* Ensure there is room for a new style */ if (msGrowLabelStyles(label) == NULL) { return -1; } /* Catch attempt to insert past end of styles array */ else if (nStyleIndex >= label->numstyles) { msSetError(MS_CHILDERR, "Cannot insert style beyond index %d", "insertLabelStyle()", label->numstyles-1); return -1; } else if (nStyleIndex < 0) { /* Insert at the end by default */ label->styles[label->numstyles]=style; MS_REFCNT_INCR(style); label->numstyles++; return label->numstyles-1; } else if (nStyleIndex >= 0 && nStyleIndex < label->numstyles) { /* Move styles existing at the specified nStyleIndex or greater */ /* to a higher nStyleIndex */ for (i=label->numstyles-1; i>=nStyleIndex; i--) { label->styles[i+1] = label->styles[i]; } label->styles[nStyleIndex]=style; MS_REFCNT_INCR(style); label->numstyles++; return nStyleIndex; } else { msSetError(MS_CHILDERR, "Invalid nStyleIndex", "insertLabelStyle()"); return -1; } } /** * Move the style up inside the array of styles. */ int msMoveLabelStyleUp(labelObj *label, int nStyleIndex) { styleObj *psTmpStyle = NULL; if (label && nStyleIndex < label->numstyles && nStyleIndex >0) { psTmpStyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(psTmpStyle); msCopyStyle(psTmpStyle, label->styles[nStyleIndex]); msCopyStyle(label->styles[nStyleIndex], label->styles[nStyleIndex-1]); msCopyStyle(label->styles[nStyleIndex-1], psTmpStyle); return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLabelStyleUp()", nStyleIndex); return (MS_FAILURE); } /** * Move the style down inside the array of styles. */ int msMoveLabelStyleDown(labelObj *label, int nStyleIndex) { styleObj *psTmpStyle = NULL; if (label && nStyleIndex < label->numstyles-1 && nStyleIndex >=0) { psTmpStyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(psTmpStyle); msCopyStyle(psTmpStyle, label->styles[nStyleIndex]); msCopyStyle(label->styles[nStyleIndex], label->styles[nStyleIndex+1]); msCopyStyle(label->styles[nStyleIndex+1], psTmpStyle); return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLabelStyleDown()", nStyleIndex); return (MS_FAILURE); } /** * Delete the style identified by the index and shift * styles that follows the deleted style. */ int msDeleteLabelStyle(labelObj *label, int nStyleIndex) { int i = 0; if (label && nStyleIndex < label->numstyles && nStyleIndex >=0) { if (freeStyle(label->styles[nStyleIndex]) == MS_SUCCESS) msFree(label->styles[nStyleIndex]); for (i=nStyleIndex; i< label->numstyles-1; i++) { label->styles[i] = label->styles[i+1]; } label->styles[label->numstyles-1] = NULL; label->numstyles--; return(MS_SUCCESS); } msSetError(MS_CHILDERR, "Invalid index: %d", "msDeleteLabelStyle()", nStyleIndex); return (MS_FAILURE); } styleObj *msRemoveLabelStyle(labelObj *label, int nStyleIndex) { int i; styleObj *style; if (nStyleIndex < 0 || nStyleIndex >= label->numstyles) { msSetError(MS_CHILDERR, "Cannot remove style, invalid nStyleIndex %d", "removeLabelStyle()", nStyleIndex); return NULL; } else { style=label->styles[nStyleIndex]; for (i=nStyleIndex; inumstyles-1; i++) { label->styles[i]=label->styles[i+1]; } label->styles[label->numstyles-1]=NULL; label->numstyles--; MS_REFCNT_DECR(style); return style; } } mapserver-7.4.3/maplayer.c000066400000000000000000002205401357574274700155370ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of most layerObj functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "maptime.h" #include "mapogcfilter.h" #include "mapthread.h" #include "mapfile.h" #include "mapparser.h" #include static int populateVirtualTable(layerVTableObj *vtable); /* ** Iteminfo is a layer parameter that holds information necessary to retrieve an individual item for ** a particular source. It is an array built from a list of items. The type of iteminfo will vary by ** source. For shapefiles and OGR it is simply an array of integers where each value is an index for ** the item. For SDE it's a ESRI specific type that contains index and column type information. Two ** helper functions below initialize and free that structure member which is used locally by layer ** specific functions. */ int msLayerInitItemInfo(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerInitItemInfo(layer); } void msLayerFreeItemInfo(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return; } layer->vtable->LayerFreeItemInfo(layer); /* * Layer expressions with attribute binding hold a numeric index pointing * to an iteminfo (node->tokenval.bindval.index). If iteminfo changes, * an expression may be no longer valid. (#5161) */ msLayerFreeExpressions(layer); } int msLayerRestoreFromScaletokens(layerObj *layer) { if(!layer->scaletokens || !layer->orig_st) { return MS_SUCCESS; } if(layer->orig_st->data) { msFree(layer->data); layer->data = layer->orig_st->data; } if(layer->orig_st->tileindex) { msFree(layer->tileindex); layer->tileindex = layer->orig_st->tileindex; } if(layer->orig_st->tileitem) { msFree(layer->tileitem); layer->tileitem = layer->orig_st->tileitem; } if(layer->orig_st->filter) { msLoadExpressionString(&(layer->filter),layer->orig_st->filter); msFree(layer->orig_st->filter); } if(layer->orig_st->filteritem) { msFree(layer->filteritem); layer->filteritem = layer->orig_st->filteritem; } if(layer->orig_st->n_processing) { int i; for(i=0;iorig_st->n_processing;i++) { msFree(layer->processing[layer->orig_st->processing_idx[i]]); layer->processing[layer->orig_st->processing_idx[i]] = layer->orig_st->processing[i]; } msFree(layer->orig_st->processing); msFree(layer->orig_st->processing_idx); } msFree(layer->orig_st); layer->orig_st = NULL; return MS_SUCCESS; } #define check_st_alloc(l) if(!l->orig_st) l->orig_st=msSmallCalloc(1,sizeof(originalScaleTokenStrings)); int msLayerApplyScaletokens(layerObj *layer, double scale) { int i,p; if(!layer->scaletokens) { return MS_SUCCESS; } msLayerRestoreFromScaletokens(layer); for(i=0;inumscaletokens;i++) { scaleTokenObj *st = &layer->scaletokens[i]; scaleTokenEntryObj *ste = NULL; if(scale<=0) { ste = &(st->tokens[0]); /* no scale defined, use first entry */ } else { int tokenindex=0; while(tokenindexn_entries) { ste = &(st->tokens[tokenindex]); if(scale < ste->maxscale && scale >= ste->minscale) break; /* current token is the correct one */ tokenindex++; ste = NULL; } } assert(ste); if(layer->data && strstr(layer->data,st->name)) { if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->data (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } check_st_alloc(layer); layer->orig_st->data = layer->data; layer->data = msStrdup(layer->data); layer->data = msReplaceSubstring(layer->data,st->name,ste->value); } if(layer->tileindex && strstr(layer->tileindex,st->name)) { if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->tileindex (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } check_st_alloc(layer); layer->orig_st->tileindex = layer->tileindex; layer->tileindex = msStrdup(layer->tileindex); layer->tileindex = msReplaceSubstring(layer->tileindex,st->name,ste->value); } if(layer->tileitem && strstr(layer->tileitem,st->name)) { if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->tileitem (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } check_st_alloc(layer); layer->orig_st->tileitem = layer->tileitem; layer->tileitem = msStrdup(layer->tileitem); layer->tileitem = msReplaceSubstring(layer->tileitem,st->name,ste->value); } if(layer->filteritem && strstr(layer->filteritem,st->name)) { if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->filteritem (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } check_st_alloc(layer); layer->orig_st->filteritem = layer->filteritem; layer->filteritem = msStrdup(layer->filteritem); layer->filteritem = msReplaceSubstring(layer->filteritem,st->name,ste->value); } if(layer->filter.string && strstr(layer->filter.string,st->name)) { char *tmpval; if(layer->debug >= MS_DEBUGLEVEL_DEBUG) { msDebug("replacing scaletoken (%s) with (%s) in layer->filter (%s) for scale=%f\n", st->name,ste->value,layer->name,scale); } check_st_alloc(layer); layer->orig_st->filter = msStrdup(layer->filter.string); tmpval = msStrdup(layer->filter.string); tmpval = msReplaceSubstring(tmpval,st->name,ste->value); if(msLoadExpressionString(&(layer->filter),tmpval) == -1) return(MS_FAILURE); /* msLoadExpressionString() cleans up previously allocated expression */ msFree(tmpval); } for(p=0;pnumprocessing;p++) { if(strstr(layer->processing[p],st->name)) { check_st_alloc(layer); layer->orig_st->n_processing++; layer->orig_st->processing = msSmallRealloc(layer->orig_st->processing, layer->orig_st->n_processing * sizeof(char*)); layer->orig_st->processing_idx = msSmallRealloc(layer->orig_st->processing_idx, layer->orig_st->n_processing * sizeof(int)); layer->orig_st->processing[layer->orig_st->n_processing-1] = layer->processing[p]; layer->orig_st->processing_idx[layer->orig_st->n_processing-1] = p; layer->processing[p] = msStrdup(layer->processing[p]); layer->processing[p] = msReplaceSubstring(layer->processing[p],st->name,ste->value); } } } return MS_SUCCESS; } /* ** Does exactly what it implies, readies a layer for processing. */ int msLayerOpen(layerObj *layer) { int rv; /* RFC-86 Scale dependant token replacements*/ rv = msLayerApplyScaletokens(layer,(layer->map)?layer->map->scaledenom:-1); if (rv != MS_SUCCESS) return rv; /* RFC-69 clustering support */ if (layer->cluster.region) return msClusterLayerOpen(layer); if(layer->features && layer->connectiontype != MS_GRATICULE ) layer->connectiontype = MS_INLINE; if(layer->tileindex && layer->connectiontype == MS_SHAPEFILE) layer->connectiontype = MS_TILED_SHAPEFILE; if(layer->type == MS_LAYER_RASTER && layer->connectiontype != MS_WMS && layer->connectiontype != MS_KERNELDENSITY) layer->connectiontype = MS_RASTER; if ( ! layer->vtable) { rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerOpen(layer); } /* ** Returns MS_TRUE if layer has been opened using msLayerOpen(), MS_FALSE otherwise */ int msLayerIsOpen(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerIsOpen(layer); } /* ** Returns MS_TRUE is a layer supports the common expression/filter syntax (RFC 64) and MS_FALSE otherwise. */ int msLayerSupportsCommonFilters(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerSupportsCommonFilters(layer); } int msLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) { if (!layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerTranslateFilter(layer, filter, filteritem); } /* ** Performs a spatial, and optionally an attribute based feature search. The function basically ** prepares things so that candidate features can be accessed by query or drawing functions. For ** OGR and shapefiles this sets an internal bit vector that indicates whether a particular feature ** is to processed. For SDE it executes an SQL statement on the SDE server. Once run the msLayerNextShape ** function should be called to actually access the shapes. ** ** Note that for shapefiles we apply any maxfeatures constraint at this point. That may be the only ** connection type where this is feasible. */ int msLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { if(!msLayerSupportsCommonFilters(layer)) msLayerTranslateFilter(layer, &layer->filter, layer->filteritem); if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerWhichShapes(layer, rect, isQuery); } /* ** Called after msWhichShapes has been called to actually retrieve shapes within a given area ** and matching a vendor specific filter (i.e. layer FILTER attribute). ** ** Shapefiles: NULL shapes (shapes with attributes but NO vertices are skipped) */ int msLayerNextShape(layerObj *layer, shapeObj *shape) { int rv, filter_passed; if ( ! layer->vtable) { rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } #ifdef USE_V8_MAPSCRIPT /* we need to force the GetItems for the geomtransform attributes */ if(!layer->items && layer->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION && strstr(layer->_geomtransform.string, "javascript")) msLayerGetItems(layer); #endif /* At the end of switch case (default -> break; -> return MS_FAILURE), * was following TODO ITEM: * * TO DO! This is where dynamic joins will happen. Joined attributes will be * tagged on to the main attributes with the naming scheme [join name].[item name]. * We need to leverage the iteminfo (I think) at this point */ /* RFC 91: MapServer-based filtering is done at a more general level. */ do { rv = layer->vtable->LayerNextShape(layer, shape); if(rv != MS_SUCCESS) return rv; filter_passed = MS_TRUE; /* By default accept ANY shape */ /* attributes need to be iconv'd to UTF-8 before any filter logic is applied */ if(layer->encoding) { rv = msLayerEncodeShapeAttributes(layer,shape); if(rv != MS_SUCCESS) return rv; } // if(layer->numitems > 0 && layer->iteminfo) { filter_passed = msEvalExpression(layer, shape, &(layer->filter), layer->filteritemindex); // } if(!filter_passed) msFreeShape(shape); } while(!filter_passed); /* RFC89 Apply Layer GeomTransform */ if(layer->_geomtransform.type != MS_GEOMTRANSFORM_NONE && rv == MS_SUCCESS) { rv = msGeomTransformShape(layer->map, layer, shape); if(rv != MS_SUCCESS) return rv; } return rv; } /* ** Used to retrieve a shape from a result set by index. Result sets are created by the various ** msQueryBy...() functions. The index is assigned by the data source. */ /* int msLayerResultsGetShape(layerObj *layer, shapeObj *shape, int tile, long record) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerResultsGetShape(layer, shape, tile, record); } */ /* ** Used to retrieve a shape by index. All data sources must be capable of random access using ** a record number(s) of some sort. */ int msLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { int rv; if( ! layer->vtable) { rv = msInitializeVirtualTable(layer); if(rv != MS_SUCCESS) return rv; } /* ** TODO: This is where dynamic joins could happen. Joined attributes would be ** tagged on to the main attributes with the naming scheme [join name].[item name]. */ rv = layer->vtable->LayerGetShape(layer, shape, record); if(rv != MS_SUCCESS) return rv; /* RFC89 Apply Layer GeomTransform */ if(layer->_geomtransform.type != MS_GEOMTRANSFORM_NONE && rv == MS_SUCCESS) { rv = msGeomTransformShape(layer->map, layer, shape); if(rv != MS_SUCCESS) return rv; } if(layer->encoding) { rv = msLayerEncodeShapeAttributes(layer,shape); if(rv != MS_SUCCESS) return rv; } return rv; } /* ** Returns the number of shapes that match the potential filter and extent. * rectProjection is the projection in which rect is expressed, or can be NULL if * rect should be considered in the layer projection. * This should be equivalent to calling msLayerWhichShapes() and counting the * number of shapes returned by msLayerNextShape(), honouring layer->maxfeatures * limitation if layer->maxfeatures>=0, and honouring layer->startindex if * layer->startindex >= 1 and paging is enabled. * Returns -1 in case of failure. */ int msLayerGetShapeCount(layerObj *layer, rectObj rect, projectionObj *rectProjection) { int rv; if( ! layer->vtable) { rv = msInitializeVirtualTable(layer); if(rv != MS_SUCCESS) return -1; } return layer->vtable->LayerGetShapeCount(layer, rect, rectProjection); } /* ** Closes resources used by a particular layer. */ void msLayerClose(layerObj *layer) { /* no need for items once the layer is closed */ msLayerFreeItemInfo(layer); if(layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } /* clear out items used as part of expressions (bug #2702) -- what about the layer filter? */ msLayerFreeExpressions(layer); if (layer->vtable) { layer->vtable->LayerClose(layer); } msLayerRestoreFromScaletokens(layer); } /* ** Clear out items used as part of expressions. */ void msLayerFreeExpressions(layerObj *layer) { int i,j,k; msFreeExpressionTokens(&(layer->filter)); msFreeExpressionTokens(&(layer->cluster.group)); msFreeExpressionTokens(&(layer->cluster.filter)); for(i=0; inumclasses; i++) { msFreeExpressionTokens(&(layer->class[i]->expression)); msFreeExpressionTokens(&(layer->class[i]->text)); for(j=0; jclass[i]->numstyles; j++) msFreeExpressionTokens(&(layer->class[i]->styles[j]->_geomtransform)); for(k=0; kclass[i]->numlabels; k++) { msFreeExpressionTokens(&(layer->class[i]->labels[k]->expression)); msFreeExpressionTokens(&(layer->class[i]->labels[k]->text)); } } } /* ** Retrieves a list of attributes available for this layer. Most sources also set the iteminfo array ** at this point. This function is used when processing query results to expose attributes to query ** templates. At that point all attributes are fair game. */ int msLayerGetItems(layerObj *layer) { const char *itemNames; /* clean up any previously allocated instances */ msLayerFreeItemInfo(layer); if(layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } /* At the end of switch case (default -> break; -> return MS_FAILURE), * was following TODO ITEM: */ /* TO DO! Need to add any joined itemd on to the core layer items, one long list! */ itemNames = msLayerGetProcessingKey( layer, "ITEMS" ); if (itemNames) { layer->items = msStringSplit(itemNames, ',', &layer->numitems); /* populate the iteminfo array */ return (msLayerInitItemInfo(layer)); } else return layer->vtable->LayerGetItems(layer); } /* ** Returns extent of spatial coverage for a layer. ** ** If layer->extent is set then this value is used, otherwise the ** driver-specific implementation is called (this can be expensive). ** ** If layer is not already opened then it is opened and closed (so this ** function can be called on both opened or closed layers). ** ** Returns MS_SUCCESS/MS_FAILURE. */ int msLayerGetExtent(layerObj *layer, rectObj *extent) { int need_to_close = MS_FALSE, status = MS_SUCCESS; if (MS_VALID_EXTENT(layer->extent)) { *extent = layer->extent; return MS_SUCCESS; } if (!msLayerIsOpen(layer)) { if (msLayerOpen(layer) != MS_SUCCESS) return MS_FAILURE; need_to_close = MS_TRUE; } if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) { if (need_to_close) msLayerClose(layer); return rv; } } status = layer->vtable->LayerGetExtent(layer, extent); if (need_to_close) msLayerClose(layer); return(status); } int msLayerGetItemIndex(layerObj *layer, char *item) { int i; for(i=0; inumitems; i++) { if(strcasecmp(layer->items[i], item) == 0) return(i); } return -1; /* item not found */ } static int string2list(char **list, int *listsize, char *string) { int i; for(i=0; i<(*listsize); i++) { if(strcasecmp(list[i], string) == 0) { /* printf("string2list (duplicate): %s %d\n", string, i); */ return(i); } } list[i] = msStrdup(string); (*listsize)++; /* printf("string2list: %s %d\n", string, i); */ return(i); } extern int msyylex(void); extern int msyylex_destroy(void); extern int msyystate; extern char *msyystring; /* string to tokenize */ extern double msyynumber; /* token containers */ extern char *msyystring_buffer; const char *msExpressionTokenToString(int token) { switch(token) { case '(': return "("; case ')': return ")"; case ',': return ","; case '+': return "+"; case '-': return "-"; case '/': return "/"; case '*': return "*"; case '%': return "%"; case MS_TOKEN_LOGICAL_AND: return " and "; case MS_TOKEN_LOGICAL_OR: return " or "; case MS_TOKEN_LOGICAL_NOT: return " not "; case MS_TOKEN_COMPARISON_EQ: return " = "; case MS_TOKEN_COMPARISON_NE: return " != "; case MS_TOKEN_COMPARISON_GT: return " > "; case MS_TOKEN_COMPARISON_GE: return " >= "; case MS_TOKEN_COMPARISON_LT: return " < "; case MS_TOKEN_COMPARISON_LE: return " <= "; case MS_TOKEN_COMPARISON_IEQ: return ""; case MS_TOKEN_COMPARISON_RE: return " ~ "; case MS_TOKEN_COMPARISON_IRE: return " ~* "; case MS_TOKEN_COMPARISON_IN: return " in "; case MS_TOKEN_COMPARISON_LIKE: return " like "; case MS_TOKEN_COMPARISON_INTERSECTS: return "intersects"; case MS_TOKEN_COMPARISON_DISJOINT: return "disjoint"; case MS_TOKEN_COMPARISON_TOUCHES: return "touches"; case MS_TOKEN_COMPARISON_OVERLAPS: return "overlaps"; case MS_TOKEN_COMPARISON_CROSSES: return "crosses"; case MS_TOKEN_COMPARISON_WITHIN: return "within"; case MS_TOKEN_COMPARISON_CONTAINS: return "contains"; case MS_TOKEN_COMPARISON_EQUALS: return "equals"; case MS_TOKEN_COMPARISON_BEYOND: return "beyond"; case MS_TOKEN_COMPARISON_DWITHIN: return "dwithin"; case MS_TOKEN_FUNCTION_LENGTH: return "length"; case MS_TOKEN_FUNCTION_TOSTRING: return "tostring"; case MS_TOKEN_FUNCTION_COMMIFY: return "commify"; case MS_TOKEN_FUNCTION_AREA: return "area"; case MS_TOKEN_FUNCTION_ROUND: return "round"; case MS_TOKEN_FUNCTION_BUFFER: return "buffer"; case MS_TOKEN_FUNCTION_DIFFERENCE: return "difference"; case MS_TOKEN_FUNCTION_SIMPLIFY: return "simplify"; // case MS_TOKEN_FUNCTION_SIMPLIFYPT: case MS_TOKEN_FUNCTION_GENERALIZE: return "generalize"; default: return NULL; } } int msTokenizeExpression(expressionObj *expression, char **list, int *listsize) { tokenListNodeObjPtr node; int token; /* TODO: make sure the constants can't somehow reference invalid expression types */ /* if(expression->type != MS_EXPRESSION && expression->type != MS_GEOMTRANSFORM_EXPRESSION) return MS_SUCCESS; */ msAcquireLock(TLOCK_PARSER); msyystate = MS_TOKENIZE_EXPRESSION; msyystring = expression->string; /* the thing we're tokenizing */ while((token = msyylex()) != 0) { /* keep processing tokens until the end of the string (\0) */ if((node = (tokenListNodeObjPtr) malloc(sizeof(tokenListNodeObj))) == NULL) { msSetError(MS_MEMERR, NULL, "msTokenizeExpression()"); goto parse_error; } node->tokensrc = NULL; node->tailifhead = NULL; node->next = NULL; switch(token) { case MS_TOKEN_LITERAL_BOOLEAN: case MS_TOKEN_LITERAL_NUMBER: node->token = token; node->tokenval.dblval = msyynumber; break; case MS_TOKEN_LITERAL_STRING: node->token = token; node->tokenval.strval = msStrdup(msyystring_buffer); break; case MS_TOKEN_LITERAL_TIME: node->tokensrc = msStrdup(msyystring_buffer); node->token = token; msTimeInit(&(node->tokenval.tmval)); if(msParseTime(msyystring_buffer, &(node->tokenval.tmval)) != MS_TRUE) { msSetError(MS_PARSEERR, "Parsing time value failed.", "msTokenizeExpression()"); free(node); goto parse_error; } break; case MS_TOKEN_BINDING_DOUBLE: /* we've encountered an attribute (binding) reference */ case MS_TOKEN_BINDING_INTEGER: case MS_TOKEN_BINDING_STRING: case MS_TOKEN_BINDING_TIME: node->token = token; /* binding type */ node->tokenval.bindval.item = msStrdup(msyystring_buffer); if(list) node->tokenval.bindval.index = string2list(list, listsize, msyystring_buffer); break; case MS_TOKEN_BINDING_SHAPE: node->token = token; break; case MS_TOKEN_BINDING_MAP_CELLSIZE: node->token = token; break; case MS_TOKEN_BINDING_DATA_CELLSIZE: node->token = token; break; case MS_TOKEN_FUNCTION_FROMTEXT: /* we want to process a shape from WKT once and not for every feature being evaluated */ if((token = msyylex()) != 40) { /* ( */ msSetError(MS_PARSEERR, "Parsing fromText function failed.", "msTokenizeExpression()"); free(node); goto parse_error; } if((token = msyylex()) != MS_TOKEN_LITERAL_STRING) { msSetError(MS_PARSEERR, "Parsing fromText function failed.", "msTokenizeExpression()"); free(node); goto parse_error; } node->token = MS_TOKEN_LITERAL_SHAPE; node->tokenval.shpval = msShapeFromWKT(msyystring_buffer); if(!node->tokenval.shpval) { msSetError(MS_PARSEERR, "Parsing fromText function failed, WKT processing failed.", "msTokenizeExpression()"); free(node); goto parse_error; } /* todo: perhaps process optional args (e.g. projection) */ if((token = msyylex()) != 41) { /* ) */ msSetError(MS_PARSEERR, "Parsing fromText function failed.", "msTokenizeExpression()"); msFreeShape(node->tokenval.shpval); free(node->tokenval.shpval); free(node); goto parse_error; } break; default: node->token = token; /* for everything else */ break; } /* add node to token list */ if(expression->tokens == NULL) { expression->tokens = node; } else { if(expression->tokens->tailifhead != NULL) /* this should never be NULL, but just in case */ expression->tokens->tailifhead->next = node; /* put the node at the end of the list */ } /* repoint the head of the list to the end - our new element this causes a loop if we are at the head, be careful not to walk in a loop */ expression->tokens->tailifhead = node; } expression->curtoken = expression->tokens; /* point at the first token */ msReleaseLock(TLOCK_PARSER); return MS_SUCCESS; parse_error: msReleaseLock(TLOCK_PARSER); return MS_FAILURE; } /* ** This function builds a list of items necessary to draw or query a particular layer by ** examining the contents of the various xxxxitem parameters and expressions. That list is ** then used to set the iteminfo variable. */ int msLayerWhichItems(layerObj *layer, int get_all, const char *metadata) { int i, j, k, l, rv; int nt=0; if (!layer->vtable) { rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } /* Cleanup any previous item selection */ msLayerFreeItemInfo(layer); if(layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } /* ** need a count of potential items/attributes needed */ /* layer level counts */ layer->classitemindex = -1; layer->filteritemindex = -1; layer->styleitemindex = -1; layer->labelitemindex = -1; layer->utfitemindex = -1; if(layer->classitem) nt++; if(layer->filteritem) nt++; if(layer->styleitem && (strcasecmp(layer->styleitem, "AUTO") != 0) && (strncasecmp(layer->styleitem, "javascript://", 13) != 0)) nt++; if(layer->filter.type == MS_EXPRESSION) nt += msCountChars(layer->filter.string, '['); if(layer->cluster.group.type == MS_EXPRESSION) nt += msCountChars(layer->cluster.group.string, '['); if(layer->cluster.filter.type == MS_EXPRESSION) nt += msCountChars(layer->cluster.filter.string, '['); if(layer->labelitem) nt++; if(layer->utfitem) nt++; if(layer->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) msTokenizeExpression(&layer->_geomtransform, layer->items, &(layer->numitems)); /* class level counts */ for(i=0; inumclasses; i++) { for(j=0; jclass[i]->numstyles; j++) { if(layer->class[i]->styles[j]->rangeitem) nt++; nt += layer->class[i]->styles[j]->numbindings; if(layer->class[i]->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) nt += msCountChars(layer->class[i]->styles[j]->_geomtransform.string, '['); } if(layer->class[i]->expression.type == MS_EXPRESSION) nt += msCountChars(layer->class[i]->expression.string, '['); for(l=0; lclass[i]->numlabels; l++) { nt += layer->class[i]->labels[l]->numbindings; for(j=0; jclass[i]->labels[l]->numstyles; j++) { if(layer->class[i]->labels[l]->styles[j]->rangeitem) nt++; nt += layer->class[i]->labels[l]->styles[j]->numbindings; if(layer->class[i]->labels[l]->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) nt += msCountChars(layer->class[i]->labels[l]->styles[j]->_geomtransform.string, '['); } if(layer->class[i]->labels[l]->expression.type == MS_EXPRESSION) nt += msCountChars(layer->class[i]->labels[l]->expression.string, '['); if(layer->class[i]->labels[l]->text.type == MS_EXPRESSION || (layer->class[i]->labels[l]->text.string && strchr(layer->class[i]->labels[l]->text.string,'[') != NULL && strchr(layer->class[i]->labels[l]->text.string,']') != NULL)) nt += msCountChars(layer->class[i]->labels[l]->text.string, '['); } if(layer->class[i]->text.type == MS_EXPRESSION || (layer->class[i]->text.string && strchr(layer->class[i]->text.string,'[') != NULL && strchr(layer->class[i]->text.string,']') != NULL)) nt += msCountChars(layer->class[i]->text.string, '['); } /* utfgrid count */ if(layer->utfdata.type == MS_EXPRESSION || (layer->utfdata.string && strchr(layer->utfdata.string,'[') != NULL && strchr(layer->utfdata.string,']') != NULL)) nt += msCountChars(layer->utfdata.string, '['); /* ** allocate space for the item list (worse case size) */ /* always retrieve all items in some cases */ if(layer->connectiontype == MS_INLINE || get_all == MS_TRUE || (layer->map->outputformat && layer->map->outputformat->renderer == MS_RENDER_WITH_KML)) { rv = msLayerGetItems(layer); if(nt > 0) /* need to realloc the array to accept the possible new items*/ layer->items = (char **)msSmallRealloc(layer->items, sizeof(char *)*(layer->numitems + nt)); } else { rv = layer->vtable->LayerCreateItems(layer, nt); } if(rv != MS_SUCCESS) return rv; /* ** build layer item list, compute item indexes for explicity item references (e.g. classitem) or item bindings */ /* layer items */ if(layer->classitem) layer->classitemindex = string2list(layer->items, &(layer->numitems), layer->classitem); if(layer->filteritem) layer->filteritemindex = string2list(layer->items, &(layer->numitems), layer->filteritem); if(layer->styleitem && (strcasecmp(layer->styleitem, "AUTO") != 0) && (strncasecmp(layer->styleitem, "javascript://",13) != 0)) layer->styleitemindex = string2list(layer->items, &(layer->numitems), layer->styleitem); if(layer->labelitem) layer->labelitemindex = string2list(layer->items, &(layer->numitems), layer->labelitem); if(layer->utfitem) layer->utfitemindex = string2list(layer->items, &(layer->numitems), layer->utfitem); /* layer classes */ for(i=0; inumclasses; i++) { if(layer->class[i]->expression.type == MS_EXPRESSION) /* class expression */ msTokenizeExpression(&(layer->class[i]->expression), layer->items, &(layer->numitems)); /* class styles (items, bindings, geomtransform) */ for(j=0; jclass[i]->numstyles; j++) { if(layer->class[i]->styles[j]->rangeitem) layer->class[i]->styles[j]->rangeitemindex = string2list(layer->items, &(layer->numitems), layer->class[i]->styles[j]->rangeitem); for(k=0; kclass[i]->styles[j]->bindings[k].item) layer->class[i]->styles[j]->bindings[k].index = string2list(layer->items, &(layer->numitems), layer->class[i]->styles[j]->bindings[k].item); } if(layer->class[i]->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) msTokenizeExpression(&(layer->class[i]->styles[j]->_geomtransform), layer->items, &(layer->numitems)); } /* class labels and label styles (items, bindings, geomtransform) */ for(l=0; lclass[i]->numlabels; l++) { for(j=0; jclass[i]->labels[l]->numstyles; j++) { if(layer->class[i]->labels[l]->styles[j]->rangeitem) layer->class[i]->labels[l]->styles[j]->rangeitemindex = string2list(layer->items, &(layer->numitems), layer->class[i]->labels[l]->styles[j]->rangeitem); for(k=0; kclass[i]->labels[l]->styles[j]->bindings[k].item) layer->class[i]->labels[l]->styles[j]->bindings[k].index = string2list(layer->items, &(layer->numitems), layer->class[i]->labels[l]->styles[j]->bindings[k].item); if(layer->class[i]->labels[l]->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_EXPRESSION) msTokenizeExpression(&(layer->class[i]->labels[l]->styles[j]->_geomtransform), layer->items, &(layer->numitems)); } } for(k=0; kclass[i]->labels[l]->bindings[k].item) layer->class[i]->labels[l]->bindings[k].index = string2list(layer->items, &(layer->numitems), layer->class[i]->labels[l]->bindings[k].item); } /* label expression */ if(layer->class[i]->labels[l]->expression.type == MS_EXPRESSION) msTokenizeExpression(&(layer->class[i]->labels[l]->expression), layer->items, &(layer->numitems)); /* label text */ if(layer->class[i]->labels[l]->text.type == MS_EXPRESSION || (layer->class[i]->labels[l]->text.string && strchr(layer->class[i]->labels[l]->text.string,'[') != NULL && strchr(layer->class[i]->labels[l]->text.string,']') != NULL)) msTokenizeExpression(&(layer->class[i]->labels[l]->text), layer->items, &(layer->numitems)); } /* class text */ if(layer->class[i]->text.type == MS_EXPRESSION || (layer->class[i]->text.string && strchr(layer->class[i]->text.string,'[') != NULL && strchr(layer->class[i]->text.string,']') != NULL)) msTokenizeExpression(&(layer->class[i]->text), layer->items, &(layer->numitems)); } /* layer filter */ if(layer->filter.type == MS_EXPRESSION) msTokenizeExpression(&(layer->filter), layer->items, &(layer->numitems)); /* cluster expressions */ if(layer->cluster.group.type == MS_EXPRESSION) msTokenizeExpression(&(layer->cluster.group), layer->items, &(layer->numitems)); if(layer->cluster.filter.type == MS_EXPRESSION) msTokenizeExpression(&(layer->cluster.filter), layer->items, &(layer->numitems)); /* utfdata */ if(layer->utfdata.type == MS_EXPRESSION || (layer->utfdata.string && strchr(layer->utfdata.string,'[') != NULL && strchr(layer->utfdata.string,']') != NULL)) { msTokenizeExpression(&(layer->utfdata), layer->items, &(layer->numitems)); } if(metadata) { char **tokens; int n = 0; int j; int bFound = 0; tokens = msStringSplit(metadata, ',', &n); if(tokens) { for(i=0; inumitems; j++) { if(strcmp(tokens[i], layer->items[j]) == 0) { bFound = 1; break; } } if(!bFound) { layer->numitems++; layer->items = (char **)msSmallRealloc(layer->items, sizeof(char *)*(layer->numitems)); layer->items[layer->numitems-1] = msStrdup(tokens[i]); } } msFreeCharArray(tokens, n); } } /* populate the iteminfo array */ if(layer->numitems == 0) return(MS_SUCCESS); return(msLayerInitItemInfo(layer)); } /* ** A helper function to set the items to be retrieved with a particular shape. Unused at the moment but will be used ** from within MapScript. Should not need modification. */ int msLayerSetItems(layerObj *layer, char **items, int numitems) { int i; /* Cleanup any previous item selection */ msLayerFreeItemInfo(layer); if(layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } /* now allocate and set the layer item parameters */ layer->items = (char **)malloc(sizeof(char *)*numitems); MS_CHECK_ALLOC(layer->items, sizeof(char *)*numitems, MS_FAILURE); for(i=0; iitems[i] = msStrdup(items[i]); layer->numitems = numitems; /* populate the iteminfo array */ return(msLayerInitItemInfo(layer)); return(MS_SUCCESS); } /* ** Fills a classObj with style info from the specified shape. This is used ** with STYLEITEM AUTO when rendering shapes. ** For optimal results, this should be called immediately after ** GetNextShape() or GetShape() so that the shape doesn't have to be read ** twice. ** */ int msLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerGetAutoStyle(map, layer, c, shape); } /* ** Fills a classObj with style info from the specified attribute. This is used ** with STYLEITEM "attribute" when rendering shapes. ** */ int msLayerGetFeatureStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { char* stylestring = NULL; if (layer->styleitem && layer->styleitemindex >=0) { stylestring = msStrdup(shape->values[layer->styleitemindex]); } else if (strncasecmp(layer->styleitem,"javascript://",13) == 0) { #ifdef USE_V8_MAPSCRIPT char *filename = layer->styleitem+13; if (!map->v8context) { msV8CreateContext(map); if (!map->v8context) { msSetError(MS_V8ERR, "Unable to create v8 context.", "msLayerGetFeatureStyle()"); return MS_FAILURE; } } if (*filename == '\0') { msSetError(MS_V8ERR, "Invalid javascript filename: \"%s\".", "msLayerGetFeatureStyle()", layer->styleitem); return MS_FAILURE; } stylestring = msV8GetFeatureStyle(map, filename, layer, shape); #else msSetError(MS_V8ERR, "V8 Javascript support is not available.", "msLayerGetFeatureStyle()"); return MS_FAILURE; #endif } else { /* unknown styleitem */ return MS_FAILURE; } /* try to find out the current style format */ if (!stylestring) return MS_FAILURE; if (strncasecmp(stylestring,"style",5) == 0) { resetClassStyle(c); c->layer = layer; if (msMaybeAllocateClassStyle(c, 0)) { free(stylestring); return(MS_FAILURE); } msUpdateStyleFromString(c->styles[0], stylestring, MS_FALSE); if(c->styles[0]->symbolname) { if((c->styles[0]->symbol = msGetSymbolIndex(&(map->symbolset), c->styles[0]->symbolname, MS_TRUE)) == -1) { msSetError(MS_MISCERR, "Undefined symbol \"%s\" in class of layer %s.", "msLayerGetFeatureStyle()", c->styles[0]->symbolname, layer->name); free(stylestring); return MS_FAILURE; } } } else if (strncasecmp(stylestring,"class",5) == 0) { if (strcasestr(stylestring, " style ") != NULL) { /* reset style if stylestring contains style definitions */ resetClassStyle(c); c->layer = layer; } msUpdateClassFromString(c, stylestring, MS_FALSE); } else if (strncasecmp(stylestring,"pen",3) == 0 || strncasecmp(stylestring,"brush",5) == 0 || strncasecmp(stylestring,"symbol",6) == 0 || strncasecmp(stylestring,"label",5) == 0) { msOGRUpdateStyleFromString(map, layer, c, stylestring); } else { resetClassStyle(c); } free(stylestring); return MS_SUCCESS; } /* Returns the number of inline feature of a layer */ int msLayerGetNumFeatures(layerObj *layer) { int need_to_close = MS_FALSE, result = -1; if (!msLayerIsOpen(layer)) { if (msLayerOpen(layer) != MS_SUCCESS) return result; need_to_close = MS_TRUE; } if (!layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return result; } result = layer->vtable->LayerGetNumFeatures(layer); if (need_to_close) msLayerClose(layer); return(result); } void msLayerSetProcessingKey( layerObj *layer, const char *key, const char *value) { int len = strlen(key); int i; char *directive = NULL; if( value != NULL ) { directive = (char *) msSmallMalloc(strlen(key)+strlen(value)+2); sprintf( directive, "%s=%s", key, value ); } for( i = 0; i < layer->numprocessing; i++ ) { if( strncasecmp( key, layer->processing[i], len ) == 0 && layer->processing[i][len] == '=' ) { free( layer->processing[i] ); /* ** Either replace the existing entry with a new one or ** clear the entry. */ if( directive != NULL ) layer->processing[i] = directive; else { layer->processing[i] = layer->processing[layer->numprocessing-1]; layer->processing[layer->numprocessing-1] = NULL; layer->numprocessing--; } return; } } /* otherwise add the directive at the end. */ if( directive != NULL ) { msLayerAddProcessing( layer, directive ); free( directive ); } } void msLayerSubstituteProcessing( layerObj *layer, const char *from, const char *to ) { int i; for( i = 0; i < layer->numprocessing; i++ ) { layer->processing[i] = msCaseReplaceSubstring(layer->processing[i], from, to); } } void msLayerAddProcessing( layerObj *layer, const char *directive ) { layer->numprocessing++; if( layer->numprocessing == 1 ) layer->processing = (char **) msSmallMalloc(2*sizeof(char *)); else layer->processing = (char **) msSmallRealloc(layer->processing, sizeof(char*) * (layer->numprocessing+1) ); layer->processing[layer->numprocessing-1] = msStrdup(directive); layer->processing[layer->numprocessing] = NULL; } char *msLayerGetProcessing( layerObj *layer, int proc_index) { if (proc_index < 0 || proc_index >= layer->numprocessing) { msSetError(MS_CHILDERR, "Invalid processing index.", "msLayerGetProcessing()"); return NULL; } else { return layer->processing[proc_index]; } } char *msLayerGetProcessingKey( layerObj *layer, const char *key ) { int i, len = strlen(key); for( i = 0; i < layer->numprocessing; i++ ) { if( strncasecmp(layer->processing[i],key,len) == 0 && layer->processing[i][len] == '=' ) return layer->processing[i] + len + 1; } return NULL; } /************************************************************************/ /* msLayerGetMaxFeaturesToDraw */ /* */ /* Check to see if maxfeaturestodraw is set as a metadata or an */ /* output format option. Used for vector layers to limit the */ /* number of fatures rendered. */ /************************************************************************/ int msLayerGetMaxFeaturesToDraw(layerObj *layer, outputFormatObj *format) { int nMaxFeatures = -1; const char *pszTmp = NULL; if (layer) { nMaxFeatures = layer->maxfeatures; pszTmp = msLookupHashTable(&layer->metadata, "maxfeaturestodraw"); if (pszTmp) nMaxFeatures = atoi(pszTmp); else { pszTmp = msLookupHashTable(&layer->map->web.metadata, "maxfeaturestodraw"); if (pszTmp) nMaxFeatures = atoi(pszTmp); } } if(format) { if (nMaxFeatures < 0) nMaxFeatures = atoi(msGetOutputFormatOption( format, "maxfeaturestodraw", "-1")); } return nMaxFeatures; } int msLayerClearProcessing( layerObj *layer ) { if (layer->numprocessing > 0) { msFreeCharArray( layer->processing, layer->numprocessing ); layer->processing = NULL; layer->numprocessing = 0; } return layer->numprocessing; } int makeTimeFilter(layerObj *lp, const char *timestring, const char *timefield, const int addtimebacktics) { char **atimes, **tokens = NULL; int numtimes,i, ntmp = 0; char *pszBuffer = NULL; int bOnlyExistingFilter = 0; if (!lp || !timestring || !timefield) return MS_FALSE; /* parse the time string. We support dicrete times (eg 2004-09-21), */ /* multiple times (2004-09-21, 2004-09-22, ...) */ /* and range(s) (2004-09-21/2004-09-25, 2004-09-27/2004-09-29) */ if (strstr(timestring, ",") == NULL && strstr(timestring, "/") == NULL) { /* discrete time */ /* if(lp->filteritem) free(lp->filteritem); lp->filteritem = msStrdup(timefield); if (&lp->filter) msFreeExpression(&lp->filter); */ if (&lp->filter) { /* if the filter is set and it's a sting type, concatenate it with the time. If not just free it */ if (lp->filter.string && lp->filter.type == MS_STRING) { pszBuffer = msStringConcatenate(pszBuffer, "(("); pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") and "); } else { msFreeExpression(&lp->filter); } } pszBuffer = msStringConcatenate(pszBuffer, "("); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "["); pszBuffer = msStringConcatenate(pszBuffer, (char *)timefield); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "]"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); pszBuffer = msStringConcatenate(pszBuffer, " = "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, (char *)timestring); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, ")"); /* if there was a filter, It was concatenate with an And ans should be closed*/ if(&lp->filter && lp->filter.string && lp->filter.type == MS_STRING) { pszBuffer = msStringConcatenate(pszBuffer, ")"); } msLoadExpressionString(&lp->filter, pszBuffer); if (pszBuffer) msFree(pszBuffer); return MS_TRUE; } atimes = msStringSplit(timestring, ',', &numtimes); if (atimes == NULL || numtimes < 1) { msFreeCharArray(atimes,numtimes); return MS_FALSE; } if (&lp->filter && lp->filter.string && lp->filter.type == MS_STRING) { pszBuffer = msStringConcatenate(pszBuffer, "(("); pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") and "); /*this flag is used to indicate that the buffer contains only the existing filter. It is set to 0 when time filter parts are added to the buffer */ bOnlyExistingFilter = 1; } else msFreeExpression(&lp->filter); /* check to see if we have ranges by parsing the first entry */ tokens = msStringSplit(atimes[0], '/', &ntmp); if (ntmp == 2) { /* ranges */ msFreeCharArray(tokens, ntmp); for (i=0; i 0 && bOnlyExistingFilter == 0) pszBuffer = msStringConcatenate(pszBuffer, " OR "); else pszBuffer = msStringConcatenate(pszBuffer, "("); bOnlyExistingFilter = 0; pszBuffer = msStringConcatenate(pszBuffer, "("); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "["); pszBuffer = msStringConcatenate(pszBuffer, (char *)timefield); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "]"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); pszBuffer = msStringConcatenate(pszBuffer, " >= "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, tokens[0]); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, " AND "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "["); pszBuffer = msStringConcatenate(pszBuffer, (char *)timefield); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "]"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); pszBuffer = msStringConcatenate(pszBuffer, " <= "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, tokens[1]); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, ")"); } msFreeCharArray(tokens, ntmp); } if (pszBuffer && strlen(pszBuffer) > 0 && bOnlyExistingFilter == 0) pszBuffer = msStringConcatenate(pszBuffer, ")"); } else if (ntmp == 1) { /* multiple times */ msFreeCharArray(tokens, ntmp); pszBuffer = msStringConcatenate(pszBuffer, "("); for (i=0; i 0) pszBuffer = msStringConcatenate(pszBuffer, " OR "); pszBuffer = msStringConcatenate(pszBuffer, "("); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "["); pszBuffer = msStringConcatenate(pszBuffer, (char *)timefield); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "]"); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); pszBuffer = msStringConcatenate(pszBuffer, " = "); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, atimes[i]); if (addtimebacktics) pszBuffer = msStringConcatenate(pszBuffer, "`"); else pszBuffer = msStringConcatenate(pszBuffer, "'"); pszBuffer = msStringConcatenate(pszBuffer, ")"); } pszBuffer = msStringConcatenate(pszBuffer, ")"); } else { msFreeCharArray(tokens, ntmp); msFreeCharArray(atimes, numtimes); msFree(pszBuffer); return MS_FALSE; } msFreeCharArray(atimes, numtimes); /* load the string to the filter */ if (pszBuffer && strlen(pszBuffer) > 0) { if(&lp->filter && lp->filter.string && lp->filter.type == MS_STRING) pszBuffer = msStringConcatenate(pszBuffer, ")"); /* if(lp->filteritem) free(lp->filteritem); lp->filteritem = msStrdup(timefield); */ msLoadExpressionString(&lp->filter, pszBuffer); } msFree(pszBuffer); return MS_TRUE; } /** set the filter parameter for a time filter **/ int msLayerSetTimeFilter(layerObj *lp, const char *timestring, const char *timefield) { if ( ! lp->vtable) { int rv = msInitializeVirtualTable(lp); if (rv != MS_SUCCESS) return rv; } return lp->vtable->LayerSetTimeFilter(lp, timestring, timefield); } int msLayerMakeBackticsTimeFilter(layerObj *lp, const char *timestring, const char *timefield) { return makeTimeFilter(lp, timestring, timefield, MS_TRUE); } int msLayerMakePlainTimeFilter(layerObj *lp, const char *timestring, const char *timefield) { return makeTimeFilter(lp, timestring, timefield, MS_FALSE); } /* * Dummies / default actions for layers */ int LayerDefaultInitItemInfo(layerObj *layer) { return MS_SUCCESS; } void LayerDefaultFreeItemInfo(layerObj *layer) { return; } int LayerDefaultOpen(layerObj *layer) { return MS_FAILURE; } int LayerDefaultIsOpen(layerObj *layer) { return MS_FALSE; } int LayerDefaultWhichShapes(layerObj *layer, rectObj rect, int isQuery) { return MS_SUCCESS; } int LayerDefaultNextShape(layerObj *layer, shapeObj *shape) { return MS_FAILURE; } int LayerDefaultGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { return MS_FAILURE; } int LayerDefaultGetShapeCount(layerObj *layer, rectObj rect, projectionObj *rectProjection) { int status; shapeObj shape, searchshape; int nShapeCount = 0; rectObj searchrect = rect; msInitShape(&searchshape); msRectToPolygon(searchrect, &searchshape); #ifdef USE_PROJ if( rectProjection != NULL ) { if(layer->project && msProjectionsDiffer(&(layer->projection), rectProjection)) msProjectRect(rectProjection, &(layer->projection), &searchrect); /* project the searchrect to source coords */ else layer->project = MS_FALSE; } #endif status = msLayerWhichShapes(layer, searchrect, MS_TRUE) ; if( status == MS_FAILURE ) { msFreeShape(&searchshape); return -1; } else if( status == MS_DONE ) { msFreeShape(&searchshape); return 0; } msInitShape(&shape); while((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) { if( rectProjection != NULL ) { #ifdef USE_PROJ if(layer->project && msProjectionsDiffer(&(layer->projection), rectProjection)) msProjectShape(&(layer->projection), rectProjection, &shape); else layer->project = MS_FALSE; #endif if(msRectContained(&shape.bounds, &rect) == MS_TRUE) { /* if the whole shape is in, don't intersect */ status = MS_TRUE; } else { switch(shape.type) { /* make sure shape actually intersects the qrect (ADD FUNCTIONS SPECIFIC TO RECTOBJ) */ case MS_SHAPE_POINT: status = msIntersectMultipointPolygon(&shape, &searchshape); break; case MS_SHAPE_LINE: status = msIntersectPolylinePolygon(&shape, &searchshape); break; case MS_SHAPE_POLYGON: status = msIntersectPolygons(&shape, &searchshape); break; default: break; } } } else status = MS_TRUE; if( status == MS_TRUE ) nShapeCount++ ; msFreeShape(&shape); if(layer->maxfeatures > 0 && layer->maxfeatures == nShapeCount) break; } msFreeShape(&searchshape); return nShapeCount; } int LayerDefaultClose(layerObj *layer) { return MS_SUCCESS; } int LayerDefaultGetItems(layerObj *layer) { return MS_SUCCESS; /* returning no items is legit */ } int msLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { #ifdef USE_OGR return FLTLayerApplyCondSQLFilterToLayer(psNode, map, iLayerIndex); #else return MS_FAILURE; #endif } int msLayerSupportsPaging(layerObj *layer) { if (layer && ((layer->connectiontype == MS_ORACLESPATIAL) || (layer->connectiontype == MS_POSTGIS)) ) return MS_TRUE; return MS_FALSE; } int msLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); /* * msLayerSupportsSorting() * * Returns MS_TRUE if the layer supports sorting/ordering. */ int msLayerSupportsSorting(layerObj *layer) { if (layer && ( (layer->connectiontype == MS_OGR) || (layer->connectiontype == MS_POSTGIS) || (layer->connectiontype == MS_ORACLESPATIAL) || ((layer->connectiontype == MS_PLUGIN) && (strstr(layer->plugin_library,"msplugin_oracle") != NULL)) || ((layer->connectiontype == MS_PLUGIN) && (strstr(layer->plugin_library,"msplugin_mssql2008") != NULL)) ) ) return MS_TRUE; return MS_FALSE; } /* * msLayerSetSort() * * Copy the sortBy clause passed as an argument into the layer sortBy member. */ void msLayerSetSort(layerObj *layer, const sortByClause* sortBy) { int i; for(i=0;isortBy.nProperties;i++) msFree(layer->sortBy.properties[i].item); msFree(layer->sortBy.properties); layer->sortBy.nProperties = sortBy->nProperties; layer->sortBy.properties = (sortByProperties*) msSmallMalloc(sortBy->nProperties * sizeof(sortByProperties)); for(i=0;isortBy.nProperties;i++) { layer->sortBy.properties[i].item = msStrdup(sortBy->properties[i].item); layer->sortBy.properties[i].sortOrder = sortBy->properties[i].sortOrder; } } /* * msLayerBuildSQLOrderBy() * * Returns the content of a SQL ORDER BY clause from the sortBy member of * the layer. The string does not contain the "ORDER BY" keywords itself. */ char* msLayerBuildSQLOrderBy(layerObj *layer) { char* strOrderBy = NULL; if( layer->sortBy.nProperties > 0 ) { int i; for(i=0;isortBy.nProperties;i++) { char* escaped = msLayerEscapePropertyName(layer, layer->sortBy.properties[i].item); if( i > 0 ) strOrderBy = msStringConcatenate(strOrderBy, ", "); strOrderBy = msStringConcatenate(strOrderBy, escaped); if( layer->sortBy.properties[i].sortOrder == SORT_DESC ) strOrderBy = msStringConcatenate(strOrderBy, " DESC"); msFree(escaped); } } return strOrderBy; } int msLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { #ifdef USE_OGR return FLTLayerApplyPlainFilterToLayer(psNode, map, iLayerIndex); #else return MS_FAILURE; #endif } int msLayerGetPaging(layerObj *layer) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) { msSetError(MS_MISCERR, "Unable to initialize virtual table", "msLayerGetPaging()"); return MS_FAILURE; } } return layer->vtable->LayerGetPaging(layer); } void msLayerEnablePaging(layerObj *layer, int value) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) { msSetError(MS_MISCERR, "Unable to initialize virtual table", "msLayerEnablePaging()"); return; } } return layer->vtable->LayerEnablePaging(layer, value); } int LayerDefaultGetExtent(layerObj *layer, rectObj *extent) { return MS_FAILURE; } int LayerDefaultGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj *shape) { msSetError(MS_MISCERR, "'STYLEITEM AUTO' not supported for this data source.", "msLayerGetAutoStyle()"); return MS_FAILURE; } int LayerDefaultCloseConnection(layerObj *layer) { return MS_SUCCESS; } int LayerDefaultCreateItems(layerObj *layer, const int nt) { if (nt > 0) { layer->items = (char **)calloc(nt, sizeof(char *)); /* should be more than enough space */ MS_CHECK_ALLOC(layer->items, sizeof(char *), MS_FAILURE); layer->numitems = 0; } return MS_SUCCESS; } int LayerDefaultGetNumFeatures(layerObj *layer) { rectObj extent; int status; int result; shapeObj shape; /* calculate layer extent */ if (!MS_VALID_EXTENT(layer->extent)) { if (msLayerGetExtent(layer, &extent) != MS_SUCCESS) { msSetError(MS_MISCERR, "Unable to get layer extent", "LayerDefaultGetNumFeatures()"); return -1; } } else extent = layer->extent; /* Cleanup any previous item selection */ msLayerFreeItemInfo(layer); if (layer->items) { msFreeCharArray(layer->items, layer->numitems); layer->items = NULL; layer->numitems = 0; } status = msLayerWhichShapes(layer, extent, MS_FALSE); if (status == MS_DONE) { /* no overlap */ return 0; } else if (status != MS_SUCCESS) { return -1; } result = 0; while ((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) { ++result; } return result; } int LayerDefaultAutoProjection(layerObj *layer, projectionObj* projection) { msSetError(MS_MISCERR, "This data driver does not implement AUTO projection support", "LayerDefaultAutoProjection()"); return MS_FAILURE; } int LayerDefaultSupportsCommonFilters(layerObj *layer) { return MS_FALSE; } int LayerDefaultTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) { if(!filter->string) return MS_SUCCESS; /* nothing to do, not an error */ msSetError(MS_MISCERR, "This data driver does not implement filter translation support", "LayerDefaultTranslateFilter()"); return MS_FAILURE; } int msLayerDefaultGetPaging(layerObj *layer) { return MS_FALSE; } void msLayerDefaultEnablePaging(layerObj *layer, int value) { return; } /************************************************************************/ /* LayerDefaultEscapeSQLParam */ /* */ /* Default function used to escape strings and avoid sql */ /* injection. Specific drivers should redefine if an escaping */ /* function is available in the driver. */ /************************************************************************/ char *LayerDefaultEscapeSQLParam(layerObj *layer, const char* pszString) { char *pszEscapedStr=NULL; if (pszString) { int nSrcLen; char c; int i=0, j=0; nSrcLen = (int)strlen(pszString); pszEscapedStr = (char*) msSmallMalloc( 2 * nSrcLen + 1); for(i = 0, j = 0; i < nSrcLen; i++) { c = pszString[i]; if (c == '\'') { pszEscapedStr[j++] = '\''; pszEscapedStr[j++] = '\''; } else if (c == '\\') { pszEscapedStr[j++] = '\\'; pszEscapedStr[j++] = '\\'; } else pszEscapedStr[j++] = c; } pszEscapedStr[j] = 0; } return pszEscapedStr; } /************************************************************************/ /* LayerDefaultEscapePropertyName */ /* */ /* Return the property name in a properly escaped and quoted form. */ /************************************************************************/ char *LayerDefaultEscapePropertyName(layerObj *layer, const char* pszString) { char* pszEscapedStr=NULL; int i, j = 0; if (layer && pszString && strlen(pszString) > 0) { int nLength = strlen(pszString); pszEscapedStr = (char*) msSmallMalloc( 1 + 2 * nLength + 1 + 1); pszEscapedStr[j++] = '"'; for (i=0; iconnectiontype = connectiontype; /* For internal types, library_str is ignored */ if (connectiontype == MS_PLUGIN) { int rv; msFree(layer->plugin_library); msFree(layer->plugin_library_original); layer->plugin_library_original = msStrdup(library_str); rv = msBuildPluginLibraryPath(&layer->plugin_library, layer->plugin_library_original, layer->map); if (rv != MS_SUCCESS) { return rv; } } return msInitializeVirtualTable(layer) ; } static int populateVirtualTable(layerVTableObj *vtable) { assert(vtable != NULL); vtable->LayerSupportsCommonFilters = LayerDefaultSupportsCommonFilters; vtable->LayerTranslateFilter = LayerDefaultTranslateFilter; vtable->LayerInitItemInfo = LayerDefaultInitItemInfo; vtable->LayerFreeItemInfo = LayerDefaultFreeItemInfo; vtable->LayerOpen = LayerDefaultOpen; vtable->LayerIsOpen = LayerDefaultIsOpen; vtable->LayerWhichShapes = LayerDefaultWhichShapes; vtable->LayerNextShape = LayerDefaultNextShape; /* vtable->LayerResultsGetShape = LayerDefaultResultsGetShape; */ vtable->LayerGetShape = LayerDefaultGetShape; vtable->LayerGetShapeCount = LayerDefaultGetShapeCount; vtable->LayerClose = LayerDefaultClose; vtable->LayerGetItems = LayerDefaultGetItems; vtable->LayerGetExtent = LayerDefaultGetExtent; vtable->LayerGetAutoStyle = LayerDefaultGetAutoStyle; vtable->LayerCloseConnection = LayerDefaultCloseConnection; vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter; vtable->LayerApplyFilterToLayer = msLayerApplyPlainFilterToLayer; vtable->LayerCreateItems = LayerDefaultCreateItems; vtable->LayerGetNumFeatures = LayerDefaultGetNumFeatures; vtable->LayerGetAutoProjection = LayerDefaultAutoProjection; vtable->LayerEscapeSQLParam = LayerDefaultEscapeSQLParam; vtable->LayerEscapePropertyName = LayerDefaultEscapePropertyName; vtable->LayerEnablePaging = msLayerDefaultEnablePaging; vtable->LayerGetPaging = msLayerDefaultGetPaging; return MS_SUCCESS; } static int createVirtualTable(layerVTableObj **vtable) { *vtable = malloc(sizeof(**vtable)); MS_CHECK_ALLOC(*vtable, sizeof(**vtable), MS_FAILURE); return populateVirtualTable(*vtable); } static int destroyVirtualTable(layerVTableObj **vtable) { memset(*vtable, 0, sizeof(**vtable)); msFree(*vtable); *vtable = NULL; return MS_SUCCESS; } int msInitializeVirtualTable(layerObj *layer) { if (layer->vtable) { destroyVirtualTable(&layer->vtable); } createVirtualTable(&layer->vtable); if(layer->features && layer->connectiontype != MS_GRATICULE ) layer->connectiontype = MS_INLINE; if(layer->tileindex && layer->connectiontype == MS_SHAPEFILE) layer->connectiontype = MS_TILED_SHAPEFILE; if(layer->type == MS_LAYER_RASTER && layer->connectiontype != MS_WMS && layer->connectiontype != MS_KERNELDENSITY) layer->connectiontype = MS_RASTER; switch(layer->connectiontype) { case(MS_INLINE): return(msINLINELayerInitializeVirtualTable(layer)); break; case(MS_SHAPEFILE): return(msSHPLayerInitializeVirtualTable(layer)); break; case(MS_TILED_SHAPEFILE): return(msTiledSHPLayerInitializeVirtualTable(layer)); break; case(MS_OGR): return(msOGRLayerInitializeVirtualTable(layer)); break; case(MS_POSTGIS): return(msPostGISLayerInitializeVirtualTable(layer)); break; case(MS_WMS): /* WMS should be treated as a raster layer */ return(msRASTERLayerInitializeVirtualTable(layer)); break; case(MS_KERNELDENSITY): /* KERNELDENSITY should be treated as a raster layer */ return(msRASTERLayerInitializeVirtualTable(layer)); break; case(MS_ORACLESPATIAL): return(msOracleSpatialLayerInitializeVirtualTable(layer)); break; case(MS_WFS): return(msWFSLayerInitializeVirtualTable(layer)); break; case(MS_GRATICULE): return(msGraticuleLayerInitializeVirtualTable(layer)); break; case(MS_RASTER): return(msRASTERLayerInitializeVirtualTable(layer)); break; case(MS_PLUGIN): return(msPluginLayerInitializeVirtualTable(layer)); break; case(MS_UNION): return(msUnionLayerInitializeVirtualTable(layer)); break; case(MS_UVRASTER): return(msUVRASTERLayerInitializeVirtualTable(layer)); break; case(MS_CONTOUR): return(msContourLayerInitializeVirtualTable(layer)); break; default: msSetError(MS_MISCERR, "Unknown connectiontype, it was %d", "msInitializeVirtualTable()", layer->connectiontype); return MS_FAILURE; break; } /* not reached */ return MS_FAILURE; } /* * INLINE: Virtual table functions */ typedef struct { rectObj searchrect; int is_relative; /* relative coordinates? */ } msINLINELayerInfo; int msINLINELayerIsOpen(layerObj *layer) { if (layer->layerinfo) return(MS_TRUE); else return(MS_FALSE); } msINLINELayerInfo *msINLINECreateLayerInfo(void) { msINLINELayerInfo *layerinfo = msSmallMalloc(sizeof(msINLINELayerInfo)); layerinfo->searchrect.minx = -1.0; layerinfo->searchrect.miny = -1.0; layerinfo->searchrect.maxx = -1.0; layerinfo->searchrect.maxy = -1.0; layerinfo->is_relative = MS_FALSE; return layerinfo; } int msINLINELayerOpen(layerObj *layer) { msINLINELayerInfo *layerinfo; if (layer->layerinfo) { if (layer->debug) { msDebug("msINLINELayerOpen: Layer is already open!\n"); } return MS_SUCCESS; /* already open */ } /* ** Initialize the layerinfo **/ layerinfo = msINLINECreateLayerInfo(); layer->currentfeature = layer->features; /* point to the begining of the feature list */ layer->layerinfo = (void*)layerinfo; return(MS_SUCCESS); } int msINLINELayerClose(layerObj *layer) { if (layer->layerinfo) { free(layer->layerinfo); layer->layerinfo = NULL; } return MS_SUCCESS; } int msINLINELayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msINLINELayerInfo *layerinfo = NULL; layerinfo = (msINLINELayerInfo*) layer->layerinfo; layerinfo->searchrect = rect; layerinfo->is_relative = (layer->transform != MS_FALSE && layer->transform != MS_TRUE); return MS_SUCCESS; } /* Author: Cristoph Spoerri and Sean Gillies */ int msINLINELayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { int i=0; featureListNodeObjPtr current; int shapeindex = record->shapeindex; /* only index necessary */ current = layer->features; while (current!=NULL && i!=shapeindex) { i++; current = current->next; } if (current == NULL) { msSetError(MS_SHPERR, "No inline feature with this index.", "msINLINELayerGetShape()"); return MS_FAILURE; } if (msCopyShape(&(current->shape), shape) != MS_SUCCESS) { msSetError(MS_SHPERR, "Cannot retrieve inline shape. There some problem with the shape", "msINLINELayerGetShape()"); return MS_FAILURE; } /* check for the expected size of the values array */ if (layer->numitems > shape->numvalues) { shape->values = (char **)msSmallRealloc(shape->values, sizeof(char *)*(layer->numitems)); for (i = shape->numvalues; i < layer->numitems; i++) shape->values[i] = msStrdup(""); } msComputeBounds(shape); return MS_SUCCESS; } int msINLINELayerNextShape(layerObj *layer, shapeObj *shape) { msINLINELayerInfo *layerinfo = NULL; shapeObj * s; layerinfo = (msINLINELayerInfo*) layer->layerinfo; while (1) { if( ! (layer->currentfeature)) { /* out of features */ return(MS_DONE); } s = &(layer->currentfeature->shape); layer->currentfeature = layer->currentfeature->next; msComputeBounds(s); if (layerinfo->is_relative || msRectOverlap(&s->bounds, &layerinfo->searchrect)) { msCopyShape(s, shape); /* check for the expected size of the values array */ if (layer->numitems > shape->numvalues) { int i; shape->values = (char **)msSmallRealloc(shape->values, sizeof(char *)*(layer->numitems)); for (i = shape->numvalues; i < layer->numitems; i++) shape->values[i] = msStrdup(""); shape->numvalues = layer->numitems; } break; } } return(MS_SUCCESS); } int msINLINELayerGetNumFeatures(layerObj *layer) { int i = 0; featureListNodeObjPtr current; current = layer->features; while (current != NULL) { i++; current = current->next; } return i; } /* Returns an escaped string */ char *msLayerEscapeSQLParam(layerObj *layer, const char*pszString) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return ""; } return layer->vtable->LayerEscapeSQLParam(layer, pszString); } char *msLayerEscapePropertyName(layerObj *layer, const char*pszString) { if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return ""; } return layer->vtable->LayerEscapePropertyName(layer, pszString); } int msINLINELayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); /* layer->vtable->LayerInitItemInfo, use default */ /* layer->vtable->LayerFreeItemInfo, use default */ layer->vtable->LayerOpen = msINLINELayerOpen; layer->vtable->LayerIsOpen = msINLINELayerIsOpen; layer->vtable->LayerWhichShapes = msINLINELayerWhichShapes; layer->vtable->LayerNextShape = msINLINELayerNextShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerGetShape = msINLINELayerGetShape; layer->vtable->LayerClose = msINLINELayerClose; /* layer->vtable->LayerGetItems, use default */ /* * Original code contained following * TODO: need to compute extents */ /* layer->vtable->LayerGetExtent, use default */ /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerCloseConnection, use default */ layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCreateItems, use default */ layer->vtable->LayerGetNumFeatures = msINLINELayerGetNumFeatures; /*layer->vtable->LayerEscapeSQLParam, use default*/ /*layer->vtable->LayerEscapePropertyName, use default*/ /* layer->vtable->LayerEnablePaging, use default */ /* layer->vtable->LayerGetPaging, use default */ return MS_SUCCESS; } mapserver-7.4.3/maplegend.c000066400000000000000000001075051357574274700156660ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Legend generation. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #define PSF .8 #define VMARGIN 5 /* margin at top and bottom of legend graphic */ #define HMARGIN 5 /* margin at left and right of legend graphic */ static int msDrawGradientSymbol(rendererVTableObj* renderer, imageObj* image_draw, double x_center, double y_center, int width, int height, styleObj* style) { int i, j; unsigned char *r,*g,*b,*a; symbolObj symbol; rasterBufferObj* rb; symbolStyleObj symbolStyle; int ret; initSymbol(&symbol); rb = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); symbol.pixmap_buffer = rb; rb->type = MS_BUFFER_BYTE_RGBA; rb->width = width; rb->height = height; rb->data.rgba.row_step = rb->width * 4; rb->data.rgba.pixel_step = 4; rb->data.rgba.pixels = (unsigned char*)malloc( rb->width*rb->height*4*sizeof(unsigned char)); b = rb->data.rgba.b = &rb->data.rgba.pixels[0]; g = rb->data.rgba.g = &rb->data.rgba.pixels[1]; r = rb->data.rgba.r = &rb->data.rgba.pixels[2]; a = rb->data.rgba.a = &rb->data.rgba.pixels[3]; for( j = 0; j < rb->height; j++ ) { for( i = 0; i < rb->width; i++ ) { msValueToRange(style, style->minvalue + (double)i / rb->width * (style->maxvalue - style->minvalue), MS_COLORSPACE_RGB); b[4*(j * rb->width + i)] = style->color.blue; g[4*(j * rb->width + i)] = style->color.green; r[4*(j * rb->width + i)] = style->color.red; a[4*(j * rb->width + i)] = style->color.alpha; } } INIT_SYMBOL_STYLE(symbolStyle); ret = renderer->renderPixmapSymbol(image_draw, x_center, y_center, &symbol, &symbolStyle); msFreeSymbol(&symbol); return ret; } /* * generic function for drawing a legend icon. (added for bug #2348) * renderer specific drawing functions shouldn't be called directly, but through * this function */ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass, int width, int height, imageObj *image, int dstX, int dstY, int scale_independant, class_hittest *hittest) { int i, type, hasmarkersymbol, ret=MS_SUCCESS; double offset; double polygon_contraction = 0.5; /* used to account for the width of a polygon's outline */ shapeObj box, zigzag; lineObj box_line,zigzag_line; pointObj box_point[5], zigzag_point[4]; pointObj marker; char szPath[MS_MAXPATHLEN]; styleObj outline_style; imageObj *image_draw = image; rendererVTableObj *renderer; outputFormatObj *transFormat = NULL, *altFormat=NULL; const char *alternativeFormatString = NULL; if(!MS_RENDERER_PLUGIN(image->format)) { msSetError(MS_MISCERR,"unsupported image format","msDrawLegendIcon()"); return MS_FAILURE; } alternativeFormatString = msLayerGetProcessingKey(lp, "RENDERER"); if (MS_RENDERER_PLUGIN(image_draw->format) && alternativeFormatString!=NULL && (altFormat= msSelectOutputFormat(map, alternativeFormatString))) { msInitializeRendererVTable(altFormat); image_draw = msImageCreate(image->width, image->height, altFormat, image->imagepath, image->imageurl, map->resolution, map->defresolution, &map->imagecolor); image_draw->map = map; renderer = MS_IMAGE_RENDERER(image_draw); } else { renderer = MS_IMAGE_RENDERER(image_draw); if (lp->compositer && renderer->compositeRasterBuffer) { image_draw = msImageCreate(image->width, image->height, image->format, image->imagepath, image->imageurl, map->resolution, map->defresolution, NULL); if (!image_draw) { msSetError(MS_MISCERR, "Unable to initialize temporary transparent image.", "msDrawLegendIcon()"); return (MS_FAILURE); } image_draw->map = map; } } if(renderer->supports_clipping && MS_VALID_COLOR(map->legend.outlinecolor)) { /* keep GD specific code here for now as it supports clipping */ rectObj clip; clip.maxx = dstX + width - 1; clip.maxy = dstY + height -1; clip.minx = dstX; clip.miny = dstY; renderer->setClip(image_draw,clip); } /* if the class has a keyimage, treat it as a point layer * (the keyimage will be treated there) */ if(theclass->keyimage != NULL) { type = MS_LAYER_POINT; } else { /* some polygon layers may be better drawn using zigzag if there is no fill */ type = lp->type; if(type == MS_LAYER_POLYGON) { type = MS_LAYER_LINE; for(i=0; inumstyles; i++) { if(MS_VALID_COLOR(theclass->styles[i]->color)) { /* there is a fill */ type = MS_LAYER_POLYGON; } if(MS_VALID_COLOR(theclass->styles[i]->outlinecolor)) { /* there is an outline */ polygon_contraction = MS_MAX(polygon_contraction, theclass->styles[i]->width / 2.0); } } } } /* initialize the box used for polygons and for outlines */ msInitShape(&box); box.line = &box_line; box.numlines = 1; box.line[0].point = box_point; box.line[0].numpoints = 5; box.type = MS_SHAPE_POLYGON; box.line[0].point[0].x = dstX + polygon_contraction; box.line[0].point[0].y = dstY + polygon_contraction; box.line[0].point[1].x = dstX + width - polygon_contraction; box.line[0].point[1].y = dstY + polygon_contraction; box.line[0].point[2].x = dstX + width - polygon_contraction; box.line[0].point[2].y = dstY + height - polygon_contraction; box.line[0].point[3].x = dstX + polygon_contraction; box.line[0].point[3].y = dstY + height - polygon_contraction; box.line[0].point[4].x = box.line[0].point[0].x; box.line[0].point[4].y = box.line[0].point[0].y; /* ** now draw the appropriate color/symbol/size combination */ switch(type) { case MS_LAYER_POINT: marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); if(theclass->keyimage != NULL) { int symbolNum; styleObj imgStyle; symbolObj *symbol=NULL; symbolNum = msAddImageSymbol(&(map->symbolset), msBuildPath(szPath, map->mappath, theclass->keyimage)); if(symbolNum == -1) { msSetError(MS_IMGERR, "Failed to open legend key image", "msCreateLegendIcon()"); return(MS_FAILURE); } symbol = map->symbolset.symbol[symbolNum]; initStyle(&imgStyle); /*set size so that symbol will be scaled properly #3296*/ if (width/symbol->sizex < height/symbol->sizey) imgStyle.size = symbol->sizey*(width/symbol->sizex); else imgStyle.size = symbol->sizey*(height/symbol->sizey); if (imgStyle.size > imgStyle.maxsize) imgStyle.maxsize = imgStyle.size; imgStyle.symbol = symbolNum; ret = msDrawMarkerSymbol(map ,image_draw,&marker,&imgStyle, 1.0); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; /* TO DO: we may want to handle this differently depending on the relative size of the keyimage */ } else { for(i=0; inumstyles; i++) { if(!scale_independant && map->scaledenom > 0) { styleObj *lp = theclass->styles[i]; if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(hittest && hittest->stylehits[i].status == 0) continue; ret = msDrawMarkerSymbol(map, image_draw, &marker, theclass->styles[i], lp->scalefactor * image->resolutionfactor); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } } break; case MS_LAYER_LINE: offset = 1; /* To set the offset, we only check the size/width parameter of the first style */ if (theclass->numstyles > 0) { if (theclass->styles[0]->symbol > 0 && theclass->styles[0]->symbol < map->symbolset.numsymbols && map->symbolset.symbol[theclass->styles[0]->symbol]->type != MS_SYMBOL_SIMPLE) offset = theclass->styles[0]->size/2; else offset = theclass->styles[0]->width/2; } msInitShape(&zigzag); zigzag.line = &zigzag_line; zigzag.numlines = 1; zigzag.line[0].point = zigzag_point; zigzag.line[0].numpoints = 4; zigzag.type = MS_SHAPE_LINE; zigzag.line[0].point[0].x = dstX + offset; zigzag.line[0].point[0].y = dstY + height - offset; zigzag.line[0].point[1].x = dstX + MS_NINT(width / 3.0) - 1; zigzag.line[0].point[1].y = dstY + offset; zigzag.line[0].point[2].x = dstX + MS_NINT(2.0 * width / 3.0) - 1; zigzag.line[0].point[2].y = dstY + height - offset; zigzag.line[0].point[3].x = dstX + width - offset; zigzag.line[0].point[3].y = dstY + offset; for(i=0; inumstyles; i++) { if(!scale_independant && map->scaledenom > 0) { styleObj *lp = theclass->styles[i]; if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(hittest && hittest->stylehits[i].status == 0) continue; if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { if (theclass->styles[i]->outlinewidth > 0) { /* Swap the style contents to render the outline first, * and then restore the style to render the interior of the line */ msOutlineRenderingPrepareStyle(theclass->styles[i], map, lp, image); ret = msDrawLineSymbol(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); msOutlineRenderingRestoreStyle(theclass->styles[i], map, lp, image); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } ret = msDrawLineSymbol(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } else { if (theclass->styles[i]->outlinewidth > 0) { /* Swap the style contents to render the outline first, * and then restore the style to render the interior of the line */ msOutlineRenderingPrepareStyle(theclass->styles[i], map, lp, image); ret = msDrawTransformedShape(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); msOutlineRenderingRestoreStyle(theclass->styles[i], map, lp, image); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } ret = msDrawTransformedShape(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } } break; case MS_LAYER_CIRCLE: case MS_LAYER_RASTER: case MS_LAYER_CHART: case MS_LAYER_POLYGON: for(i=0; inumstyles; i++) { if(!scale_independant && map->scaledenom > 0) { styleObj *lp = theclass->styles[i]; if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(hittest && hittest->stylehits[i].status == 0) continue; if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT || theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) { if (MS_VALID_COLOR(theclass->styles[i]->mincolor)) { ret = msDrawGradientSymbol(renderer, image_draw, dstX + width / 2., dstY + height / 2.0, width - 2 * polygon_contraction, height - 2 * polygon_contraction, theclass->styles[i]); } else { ret = msDrawShadeSymbol(map, image_draw, &box, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor); } if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } else { ret = msDrawTransformedShape(map, image_draw, &box, theclass->styles[i], lp->scalefactor); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } } break; default: return MS_FAILURE; break; } /* end symbol drawing */ /* handle label styles */ for(i=0; inumlabels; i++) { labelObj *l = theclass->labels[i]; if(!scale_independant && map->scaledenom > 0) { if(msScaleInBounds(map->scaledenom, l->minscaledenom, l->maxscaledenom)) { int j; for(j=0; jnumstyles; j++) { styleObj *s = l->styles[j]; marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); if(s->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { ret = msDrawMarkerSymbol(map, image_draw, &marker, s, lp->scalefactor); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } } } } } /* handle "pure" text layers, i.e. layers with no symbology */ hasmarkersymbol = 0; if(theclass->numstyles == 0) { for(i=0; inumlabels; i++) { labelObj *l = theclass->labels[i]; if(!scale_independant && map->scaledenom > 0) { if(msScaleInBounds(map->scaledenom, l->minscaledenom, l->maxscaledenom)) { int j; for(j=0; jnumstyles; j++) { styleObj *s = l->styles[j]; if(s->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) { hasmarkersymbol = 1; } } } } } } else { hasmarkersymbol = 1; } if(!hasmarkersymbol && theclass->numlabels>0) { textSymbolObj ts; pointObj textstartpt; marker.x = dstX + MS_NINT(width / 2.0); marker.y = dstY + MS_NINT(height / 2.0); initTextSymbol(&ts); msPopulateTextSymbolForLabelAndString(&ts,theclass->labels[0],msStrdup("Az"),lp->scalefactor*image_draw->resolutionfactor,image_draw->resolutionfactor, duplicate_always); ts.label->size = height - 1; ts.rotation = 0; ret = msComputeTextPath(map,&ts); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; textstartpt = get_metrics(&marker,MS_CC,ts.textpath,0,0,0,0,NULL); ret = msDrawTextSymbol(map,image_draw, textstartpt, &ts); freeTextSymbol(&ts); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; } /* handle an outline if necessary */ if(MS_VALID_COLOR(map->legend.outlinecolor)) { initStyle(&outline_style); outline_style.color = map->legend.outlinecolor; ret = msDrawLineSymbol(map, image_draw, &box, &outline_style, image_draw->resolutionfactor); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; /* reset clipping rectangle */ if(renderer->supports_clipping) renderer->resetClip(image_draw); } if (altFormat) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); rendererVTableObj *altrenderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); ret = altrenderer->getRasterBufferHandle(image_draw,&rb); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; ret = renderer->mergeRasterBuffer(image,&rb,((lp->compositer)?lp->compositer->opacity*0.01:1.0),0,0,0,0,rb.width,rb.height); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; /* * hack to work around bug #3834: if we have use an alternate renderer, the symbolset may contain * symbols that reference it. We want to remove those references before the altFormat is destroyed * to avoid a segfault and/or a leak, and so the the main renderer doesn't pick the cache up thinking * it's for him. */ for(i=0; isymbolset.numsymbols; i++) { if (map->symbolset.symbol[i]!=NULL) { symbolObj *s = map->symbolset.symbol[i]; if(s->renderer == altrenderer) { altrenderer->freeSymbol(s); s->renderer = NULL; } } } } else if(image != image_draw) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image_draw); rasterBufferObj rb; memset(&rb,0,sizeof(rasterBufferObj)); ret = renderer->getRasterBufferHandle(image_draw,&rb); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; ret = renderer->mergeRasterBuffer(image,&rb,((lp->compositer)?lp->compositer->opacity*0.01:1.0),0,0,0,0,rb.width,rb.height); if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup; /* deref and possibly free temporary transparent output format. */ msApplyOutputFormat( &transFormat, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } legend_icon_cleanup: if(image != image_draw) { msFreeImage(image_draw); } return ret; } imageObj *msCreateLegendIcon(mapObj* map, layerObj* lp, classObj* class, int width, int height, int scale_independant) { imageObj *image; outputFormatObj *format = NULL; int i = 0; rendererVTableObj *renderer = MS_MAP_RENDERER(map); if( !renderer ) { msSetError(MS_MISCERR, "invalid map outputformat", "msCreateLegendIcon()"); return(NULL); } /* ensure we have an image format representing the options for the legend */ msApplyOutputFormat(&format, map->outputformat, map->legend.transparent, map->legend.interlace, MS_NOOVERRIDE); image = msImageCreate(width,height,format,map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &(map->legend.imagecolor)); /* drop this reference to output format */ msApplyOutputFormat( &format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); if(image == NULL) { msSetError(MS_IMGERR, "Unable to initialize image.","msCreateLegendIcon()"); return(NULL); } image->map = map; /* Call drawLegendIcon with destination (0, 0) */ /* Return an empty image if lp==NULL || class=NULL */ /* (If class is NULL draw the legend for all classes. Modifications done */ /* Fev 2004 by AY) */ if (lp) { if (class) { if(UNLIKELY(MS_FAILURE == msDrawLegendIcon(map, lp, class, width, height, image, 0, 0, scale_independant, NULL))) { msFreeImage(image); return NULL; } } else { for (i=0; inumclasses; i++) { if(UNLIKELY(MS_FAILURE == msDrawLegendIcon(map, lp, lp->class[i], width, height, image, 0, 0, scale_independant, NULL))) { msFreeImage(image); return NULL; } } } } return image; } /* * Calculates the optimal size for the legend. If the optional layerObj * argument is given, the legend size will be calculated for only that * layer. Otherwise, the legend size is calculated for all layers that * are not MS_OFF or of MS_LAYER_QUERY type. * * Returns one of: * MS_SUCCESS * MS_FAILURE */ int msLegendCalcSize(mapObj *map, int scale_independent, int *size_x, int *size_y, int *layer_index, int num_layers, map_hittest *hittest, double resolutionfactor) { int i, j; int status, maxwidth=0, nLegendItems=0; char *text; layerObj *lp; rectObj rect; int current_layers=0; /* reset sizes */ *size_x = 0; *size_y = 0; /* enable scale-dependent calculations */ if(!scale_independent) { map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); status = msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) return MS_FAILURE; } /* * step through all map classes, and for each one that will be displayed * calculate the label size */ if (layer_index != NULL && num_layers >0) current_layers = num_layers; else current_layers = map->numlayers; for(i=0; i< current_layers; i++) { int layerindex; if (layer_index != NULL && num_layers > 0) layerindex = layer_index[i]; else layerindex = map->layerorder[i]; lp = (GET_LAYER(map, layerindex)); if((lp->status == MS_OFF && (layer_index == NULL || num_layers <= 0)) || (lp->type == MS_LAYER_QUERY)) /* skip it */ continue; if(hittest && hittest->layerhits[layerindex].status == 0) continue; if(!scale_independent && map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } for(j=lp->numclasses-1; j>=0; j--) { textSymbolObj ts; text = lp->class[j]->title?lp->class[j]->title:lp->class[j]->name; /* point to the right legend text, title takes precedence */ if(!text) continue; /* skip it */ /* skip the class if the classgroup is defined */ if(lp->classgroup && (lp->class[j]->group == NULL || strcasecmp(lp->class[j]->group, lp->classgroup) != 0)) continue; /* verify class scale */ if(!scale_independent && map->scaledenom > 0) { if((lp->class[j]->maxscaledenom > 0) && (map->scaledenom > lp->class[j]->maxscaledenom)) continue; if((lp->class[j]->minscaledenom > 0) && (map->scaledenom <= lp->class[j]->minscaledenom)) continue; } if(hittest && hittest->layerhits[layerindex].classhits[j].status == 0) continue; if(*text) { initTextSymbol(&ts); msPopulateTextSymbolForLabelAndString(&ts,&map->legend.label,msStrdup(text),resolutionfactor,resolutionfactor, 0); if(UNLIKELY(MS_FAILURE == msGetTextSymbolSize(map,&ts,&rect))) { freeTextSymbol(&ts); return MS_FAILURE; } freeTextSymbol(&ts); maxwidth = MS_MAX(maxwidth, MS_NINT(rect.maxx - rect.minx)); *size_y += MS_MAX(MS_NINT(rect.maxy - rect.miny), map->legend.keysizey); } else { *size_y += map->legend.keysizey; } nLegendItems++; } } /* Calculate the size of the legend: */ /* - account for the Y keyspacing */ *size_y += (2*VMARGIN) + ((nLegendItems-1) * map->legend.keyspacingy); /* - determine the legend width */ *size_x = (2*HMARGIN) + maxwidth + map->legend.keyspacingx + map->legend.keysizex; if(*size_y <=0 || *size_x <=0) return MS_FAILURE; return MS_SUCCESS; } /* ** Creates a GD image of a legend for a specific map. msDrawLegend() ** respects the current scale, and classes without a name are not ** added to the legend. ** ** scale_independent is used for WMS GetLegendGraphic. It should be set to ** MS_FALSE in most cases. If it is set to MS_TRUE then the layers' minscale ** and maxscale are ignored and layers that are currently out of scale still ** show up in the legend. */ imageObj *msDrawLegend(mapObj *map, int scale_independent, map_hittest *hittest) { int i,j,ret=MS_SUCCESS; /* loop counters */ pointObj pnt; int size_x, size_y=0; layerObj *lp; rectObj rect; imageObj *image = NULL; outputFormatObj *format = NULL; char *text; struct legend_struct { int height; textSymbolObj ts; int layerindex, classindex; struct legend_struct* pred; }; typedef struct legend_struct legendlabel; legendlabel *head=NULL,*cur=NULL; if(!MS_RENDERER_PLUGIN(map->outputformat)) { msSetError(MS_MISCERR,"unsupported output format","msDrawLegend()"); return NULL; } if(msValidateContexts(map) != MS_SUCCESS) return NULL; /* make sure there are no recursive REQUIRES or LABELREQUIRES expressions */ if(msLegendCalcSize(map, scale_independent, &size_x, &size_y, NULL, 0, hittest, map->resolution/map->defresolution) != MS_SUCCESS) return NULL; /* * step through all map classes, and for each one that will be displayed * keep a reference to its label size and text */ for(i=0; inumlayers; i++) { lp = (GET_LAYER(map, map->layerorder[i])); if((lp->status == MS_OFF) || (lp->type == MS_LAYER_QUERY)) /* skip it */ continue; if(hittest && hittest->layerhits[map->layerorder[i]].status == 0) continue; if(!scale_independent && map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if(!scale_independent && lp->maxscaledenom <=0 && lp->minscaledenom <=0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } /* set the scale factor so that scale dependant symbols are drawn in the legend with their default size */ if(lp->sizeunits != MS_PIXELS) { map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); lp->scalefactor = (msInchesPerUnit(lp->sizeunits,0)/msInchesPerUnit(map->units,0)) / map->cellsize; } for(j=lp->numclasses-1; j>=0; j--) { text = lp->class[j]->title?lp->class[j]->title:lp->class[j]->name; /* point to the right legend text, title takes precedence */ if(!text) continue; /* skip it */ /* skip the class if the classgroup is defined */ if(lp->classgroup && (lp->class[j]->group == NULL || strcasecmp(lp->class[j]->group, lp->classgroup) != 0)) continue; if(!scale_independent && map->scaledenom > 0) { /* verify class scale here */ if((lp->class[j]->maxscaledenom > 0) && (map->scaledenom > lp->class[j]->maxscaledenom)) continue; if((lp->class[j]->minscaledenom > 0) && (map->scaledenom <= lp->class[j]->minscaledenom)) continue; } if(hittest && hittest->layerhits[map->layerorder[i]].classhits[j].status == 0) { continue; } cur = (legendlabel*) msSmallMalloc(sizeof(legendlabel)); initTextSymbol(&cur->ts); if(*text) { msPopulateTextSymbolForLabelAndString(&cur->ts,&map->legend.label,msStrdup(text),map->resolution/map->defresolution,map->resolution/map->defresolution, 0); if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,&cur->ts))) { ret = MS_FAILURE; goto cleanup; } if(UNLIKELY(MS_FAILURE == msGetTextSymbolSize(map,&cur->ts,&rect))) { ret = MS_FAILURE; goto cleanup; } cur->height = MS_MAX(MS_NINT(rect.maxy - rect.miny), map->legend.keysizey); } else { cur->height = map->legend.keysizey; } cur->classindex = j; cur->layerindex = map->layerorder[i]; cur->pred = head; head = cur; } } /* ensure we have an image format representing the options for the legend. */ msApplyOutputFormat(&format, map->outputformat, map->legend.transparent, map->legend.interlace, MS_NOOVERRIDE); /* initialize the legend image */ image = msImageCreate(size_x, size_y, format, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->legend.imagecolor); if(!image) { msSetError(MS_MISCERR, "Unable to initialize image.", "msDrawLegend()"); return NULL; } image->map = map; /* image = renderer->createImage(size_x,size_y,format,&(map->legend.imagecolor)); */ /* drop this reference to output format */ msApplyOutputFormat(&format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE); pnt.y = VMARGIN; pnt.x = HMARGIN + map->legend.keysizex + map->legend.keyspacingx; while(cur) { /* cur initially points on the last legend item, i.e. the one that should be at the top */ class_hittest *ch = NULL; /* set the scale factor so that scale dependant symbols are drawn in the legend with their default size */ if(map->layers[cur->layerindex]->sizeunits != MS_PIXELS) { map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); map->layers[cur->layerindex]->scalefactor = (msInchesPerUnit(map->layers[cur->layerindex]->sizeunits,0)/msInchesPerUnit(map->units,0)) / map->cellsize; } if(hittest) { ch = &hittest->layerhits[cur->layerindex].classhits[cur->classindex]; } ret = msDrawLegendIcon(map, map->layers[cur->layerindex], map->layers[cur->layerindex]->class[cur->classindex], map->legend.keysizex, map->legend.keysizey, image, HMARGIN, (int) pnt.y, scale_independent, ch); if(UNLIKELY(ret != MS_SUCCESS)) goto cleanup; pnt.y += cur->height; if(cur->ts.annotext) { pointObj textPnt = pnt; textPnt.y -= cur->ts.textpath->bounds.bbox.maxy; textPnt.y += map->legend.label.offsety; textPnt.x += map->legend.label.offsetx; ret = msDrawTextSymbol(map,image,textPnt,&cur->ts); if(UNLIKELY(ret == MS_FAILURE)) goto cleanup; freeTextSymbol(&cur->ts); } pnt.y += map->legend.keyspacingy; /* bump y for next label */ /* clean up */ head = cur; cur = cur->pred; free(head); } /* next legend */ cleanup: while(cur) { freeTextSymbol(&cur->ts); head = cur; cur = cur->pred; free(head); } if(UNLIKELY(ret != MS_SUCCESS)) { if(image) msFreeImage(image); return NULL; } return(image); } /* TODO */ int msEmbedLegend(mapObj *map, imageObj *img) { int s,l; pointObj point; imageObj *image = NULL; symbolObj *legendSymbol; char* imageType = NULL; rendererVTableObj *renderer; s = msGetSymbolIndex(&(map->symbolset), "legend", MS_FALSE); if(s != -1) msRemoveSymbol(&(map->symbolset), s); /* solves some caching issues in AGG with long-running processes */ if(msGrowSymbolSet(&map->symbolset) == NULL) return -1; s = map->symbolset.numsymbols; legendSymbol = map->symbolset.symbol[s]; map->symbolset.numsymbols++; initSymbol(legendSymbol); if(!MS_RENDERER_PLUGIN(map->outputformat) || !MS_MAP_RENDERER(map)->supports_pixel_buffer) { imageType = msStrdup(map->imagetype); /* save format */ if MS_DRIVER_CAIRO(map->outputformat) map->outputformat = msSelectOutputFormat( map, "cairopng" ); else map->outputformat = msSelectOutputFormat( map, "png" ); msInitializeRendererVTable(map->outputformat); } renderer = MS_MAP_RENDERER(map); /* render the legend. */ image = msDrawLegend(map, MS_FALSE, NULL); if( image == NULL ) { msFree(imageType); return MS_FAILURE; } if (imageType) { map->outputformat = msSelectOutputFormat( map, imageType ); /* restore format */ msFree(imageType); } /* copy renderered legend image into symbol */ legendSymbol->pixmap_buffer = calloc(1,sizeof(rasterBufferObj)); MS_CHECK_ALLOC(legendSymbol->pixmap_buffer, sizeof(rasterBufferObj), MS_FAILURE); if(MS_SUCCESS != renderer->getRasterBufferCopy(image,legendSymbol->pixmap_buffer)) return MS_FAILURE; legendSymbol->renderer = renderer; msFreeImage( image ); if(!legendSymbol->pixmap_buffer) return(MS_FAILURE); /* something went wrong creating scalebar */ legendSymbol->type = MS_SYMBOL_PIXMAP; /* intialize a few things */ legendSymbol->name = msStrdup("legend"); legendSymbol->sizex = legendSymbol->pixmap_buffer->width; legendSymbol->sizey = legendSymbol->pixmap_buffer->height; /* I'm not too sure this test is sufficient ... NFW. */ /* if(map->legend.transparent == MS_ON) */ /* gdImageColorTransparent(legendSymbol->img_deprecated, 0); */ switch(map->legend.position) { case(MS_LL): point.x = MS_NINT(legendSymbol->sizex/2.0); point.y = map->height - MS_NINT(legendSymbol->sizey/2.0); break; case(MS_LR): point.x = map->width - MS_NINT(legendSymbol->sizex/2.0); point.y = map->height - MS_NINT(legendSymbol->sizey/2.0); break; case(MS_LC): point.x = MS_NINT(map->width/2.0); point.y = map->height - MS_NINT(legendSymbol->sizey/2.0); break; case(MS_UR): point.x = map->width - MS_NINT(legendSymbol->sizex/2.0); point.y = MS_NINT(legendSymbol->sizey/2.0); break; case(MS_UL): point.x = MS_NINT(legendSymbol->sizex/2.0); point.y = MS_NINT(legendSymbol->sizey/2.0); break; case(MS_UC): point.x = MS_NINT(map->width/2.0); point.y = MS_NINT(legendSymbol->sizey/2.0); break; } l = msGetLayerIndex(map, "__embed__legend"); if(l == -1) { if(msGrowMapLayers(map) == NULL) return(-1); l = map->numlayers; map->numlayers++; if(initLayer((GET_LAYER(map, l)), map) == -1) return(-1); GET_LAYER(map, l)->name = msStrdup("__embed__legend"); GET_LAYER(map, l)->type = MS_LAYER_POINT; if(msGrowLayerClasses( GET_LAYER(map, l) ) == NULL) return(-1); if(initClass(GET_LAYER(map, l)->class[0]) == -1) return(-1); GET_LAYER(map, l)->numclasses = 1; /* so we make sure to free it */ /* update the layer order list with the layer's index. */ map->layerorder[l] = l; } GET_LAYER(map, l)->status = MS_ON; if(map->legend.postlabelcache) { /* add it directly to the image */ if(UNLIKELY(msMaybeAllocateClassStyle(GET_LAYER(map, l)->class[0], 0)==MS_FAILURE)) return MS_FAILURE; GET_LAYER(map, l)->class[0]->styles[0]->symbol = s; if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, img, &point, GET_LAYER(map, l)->class[0]->styles[0], 1.0))) return MS_FAILURE; } else { if(!GET_LAYER(map, l)->class[0]->labels) { if(msGrowClassLabels(GET_LAYER(map, l)->class[0]) == NULL) return MS_FAILURE; initLabel(GET_LAYER(map, l)->class[0]->labels[0]); GET_LAYER(map, l)->class[0]->numlabels = 1; GET_LAYER(map, l)->class[0]->labels[0]->force = MS_TRUE; GET_LAYER(map, l)->class[0]->labels[0]->size = MS_MEDIUM; /* must set a size to have a valid label definition */ GET_LAYER(map, l)->class[0]->labels[0]->priority = MS_MAX_LABEL_PRIORITY; } if(GET_LAYER(map, l)->class[0]->labels[0]->numstyles == 0) { if(msGrowLabelStyles(GET_LAYER(map,l)->class[0]->labels[0]) == NULL) return(MS_FAILURE); GET_LAYER(map,l)->class[0]->labels[0]->numstyles = 1; initStyle(GET_LAYER(map,l)->class[0]->labels[0]->styles[0]); GET_LAYER(map,l)->class[0]->labels[0]->styles[0]->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOINT; } GET_LAYER(map,l)->class[0]->labels[0]->styles[0]->symbol = s; if(UNLIKELY(MS_FAILURE == msAddLabel(map, img, GET_LAYER(map, l)->class[0]->labels[0], l, 0, NULL, &point, -1, NULL))) return MS_FAILURE; } /* Mark layer as deleted so that it doesn't interfere with html legends or with saving maps */ GET_LAYER(map, l)->status = MS_DELETE; return MS_SUCCESS; } mapserver-7.4.3/maplexer.c000066400000000000000000006112701357574274700155460ustar00rootroot00000000000000#line 2 "/home/even/mapserver/mapserver/maplexer.c" #line 4 "/home/even/mapserver/mapserver/maplexer.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define yy_create_buffer msyy_create_buffer #define yy_delete_buffer msyy_delete_buffer #define yy_flex_debug msyy_flex_debug #define yy_init_buffer msyy_init_buffer #define yy_flush_buffer msyy_flush_buffer #define yy_load_buffer_state msyy_load_buffer_state #define yy_switch_to_buffer msyy_switch_to_buffer #define yyin msyyin #define yyleng msyyleng #define yylex msyylex #define yylineno msyylineno #define yyout msyyout #define yyrestart msyyrestart #define yytext msyytext #define yywrap msyywrap #define yyalloc msyyalloc #define yyrealloc msyyrealloc #define yyfree msyyfree #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_SUBMINOR_VERSION 0 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE msyyrestart(msyyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif extern yy_size_t msyyleng; extern FILE *msyyin, *msyyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) #define YY_LINENO_REWIND_TO(ptr) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up msyytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up msyytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via msyyrestart()), so that the user can continue scanning by * just pointing msyyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when msyytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ yy_size_t msyyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow msyywrap()'s to do buffer switches * instead of setting up a fresh msyyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void msyyrestart (FILE *input_file ); void msyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE msyy_create_buffer (FILE *file,int size ); void msyy_delete_buffer (YY_BUFFER_STATE b ); void msyy_flush_buffer (YY_BUFFER_STATE b ); void msyypush_buffer_state (YY_BUFFER_STATE new_buffer ); void msyypop_buffer_state (void ); static void msyyensure_buffer_stack (void ); static void msyy_load_buffer_state (void ); static void msyy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER msyy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE msyy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE msyy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE msyy_scan_bytes (yyconst char *bytes,yy_size_t len ); void *msyyalloc (yy_size_t ); void *msyyrealloc (void *,yy_size_t ); void msyyfree (void * ); #define yy_new_buffer msyy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ msyyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ msyy_create_buffer(msyyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ msyyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ msyy_create_buffer(msyyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *msyyin = (FILE *) 0, *msyyout = (FILE *) 0; typedef int yy_state_type; extern int msyylineno; int msyylineno = 1; extern char *msyytext; #ifdef yytext_ptr #undef yytext_ptr #endif #define yytext_ptr msyytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); #if defined(__GNUC__) && __GNUC__ >= 3 __attribute__((__noreturn__)) #endif static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up msyytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ msyyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 351 #define YY_END_OF_BUFFER 352 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[2024] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 349, 1, 347, 340, 2, 349, 349, 333, 346, 333, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 349, 349, 349, 348, 348, 8, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 1, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 350, 1, 1, 11, 345, 350, 345, 350, 334, 334, 15, 12, 14, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 348, 18, 348, 351, 1, 351, 351, 343, 341, 341, 342, 5, 7, 6, 1, 2, 0, 338, 333, 333, 346, 333, 346, 0, 3, 346, 2, 333, 0, 346, 346, 346, 346, 346, 346, 346, 346, 251, 346, 346, 346, 255, 346, 256, 346, 346, 261, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 274, 346, 346, 277, 346, 278, 346, 346, 346, 346, 346, 346, 346, 346, 346, 289, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 229, 346, 346, 315, 316, 346, 317, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 0, 326, 0, 339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 346, 346, 255, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 289, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 13, 0, 10, 0, 334, 334, 334, 0, 334, 0, 17, 19, 12, 16, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 16, 14, 21, 0, 17, 0, 15, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 335, 20, 0, 344, 0, 343, 341, 341, 342, 5, 4, 333, 0, 0, 346, 333, 0, 337, 346, 337, 2, 2, 2, 333, 0, 0, 333, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 257, 346, 346, 346, 346, 346, 346, 346, 346, 346, 83, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 98, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 139, 140, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 287, 288, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 309, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 241, 322, 346, 243, 323, 346, 61, 0, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 324, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 287, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 0, 0, 0, 0, 0, 334, 334, 0, 0, 334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 336, 336, 2, 2, 2, 0, 333, 346, 346, 346, 346, 346, 246, 346, 346, 346, 346, 346, 346, 346, 250, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 76, 346, 346, 346, 346, 80, 346, 346, 346, 346, 346, 346, 346, 346, 346, 265, 346, 346, 346, 93, 346, 346, 346, 97, 346, 346, 346, 100, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 118, 346, 346, 346, 346, 346, 346, 346, 346, 346, 275, 346, 276, 346, 143, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 174, 346, 285, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 212, 346, 346, 346, 346, 346, 346, 346, 224, 346, 311, 346, 346, 346, 346, 313, 235, 346, 346, 346, 346, 346, 346, 346, 346, 346, 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 346, 346, 76, 346, 93, 346, 346, 346, 346, 346, 346, 346, 212, 346, 346, 313, 331, 0, 334, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 332, 2, 54, 346, 56, 346, 346, 247, 346, 346, 248, 346, 346, 346, 346, 346, 346, 253, 346, 65, 346, 69, 346, 346, 346, 346, 346, 346, 346, 78, 346, 346, 346, 346, 263, 81, 346, 84, 346, 346, 264, 346, 346, 346, 346, 346, 346, 95, 346, 346, 267, 346, 346, 103, 268, 346, 346, 105, 346, 346, 114, 346, 346, 191, 346, 346, 346, 346, 346, 122, 273, 346, 132, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 282, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 283, 346, 259, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 296, 346, 346, 346, 346, 346, 346, 346, 346, 300, 346, 346, 346, 346, 346, 346, 346, 346, 302, 303, 205, 346, 346, 346, 346, 346, 346, 307, 346, 346, 215, 346, 221, 346, 346, 346, 346, 228, 346, 346, 346, 346, 318, 236, 346, 346, 346, 346, 346, 346, 242, 56, 65, 0, 0, 0, 122, 132, 0, 0, 0, 0, 0, 0, 215, 0, 236, 346, 69, 346, 346, 346, 346, 346, 346, 346, 346, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 28, 0, 26, 0, 0, 0, 0, 27, 0, 0, 0, 0, 346, 346, 346, 346, 346, 346, 249, 346, 63, 252, 346, 254, 346, 346, 346, 346, 346, 72, 346, 73, 346, 346, 346, 346, 346, 346, 79, 346, 346, 346, 346, 86, 346, 89, 90, 266, 346, 92, 346, 346, 346, 346, 104, 270, 346, 346, 346, 346, 346, 346, 271, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 131, 133, 134, 346, 346, 141, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 279, 346, 280, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 286, 175, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 295, 294, 299, 190, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 301, 346, 200, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 305, 306, 346, 308, 214, 346, 217, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 240, 321, 0, 86, 0, 0, 134, 0, 0, 0, 0, 0, 0, 346, 217, 346, 46, 31, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 43, 0, 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 68, 346, 346, 346, 346, 320, 346, 346, 260, 346, 262, 346, 346, 346, 88, 346, 94, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 113, 346, 346, 346, 346, 346, 120, 346, 346, 346, 346, 346, 346, 346, 346, 346, 136, 346, 346, 144, 346, 346, 346, 346, 346, 346, 346, 346, 153, 346, 346, 346, 346, 346, 159, 346, 346, 346, 346, 346, 346, 346, 170, 346, 346, 346, 346, 346, 176, 346, 177, 346, 346, 346, 346, 346, 189, 346, 346, 297, 346, 298, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 227, 346, 346, 346, 346, 346, 237, 238, 346, 346, 0, 0, 0, 0, 0, 0, 0, 0, 0, 346, 346, 25, 0, 42, 0, 0, 47, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 40, 0, 0, 327, 346, 346, 346, 346, 346, 60, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 82, 346, 346, 346, 346, 346, 346, 101, 346, 346, 346, 346, 346, 112, 346, 346, 346, 346, 119, 346, 346, 346, 346, 346, 346, 346, 346, 346, 137, 346, 346, 346, 346, 346, 346, 346, 346, 149, 346, 346, 156, 157, 158, 346, 346, 346, 346, 346, 346, 166, 346, 346, 173, 284, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 188, 346, 346, 192, 346, 346, 194, 346, 346, 346, 198, 346, 346, 346, 346, 202, 346, 207, 346, 346, 304, 346, 346, 346, 346, 346, 346, 346, 222, 111, 346, 226, 346, 346, 346, 312, 314, 319, 346, 0, 0, 0, 0, 198, 0, 0, 207, 0, 222, 44, 0, 39, 30, 48, 0, 0, 0, 41, 33, 0, 24, 0, 0, 346, 346, 57, 346, 59, 346, 64, 346, 66, 346, 346, 71, 346, 346, 52, 346, 346, 87, 346, 346, 346, 102, 346, 109, 110, 346, 107, 346, 116, 117, 346, 346, 346, 346, 346, 125, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 152, 346, 346, 346, 346, 346, 346, 346, 346, 346, 169, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 53, 199, 346, 346, 346, 346, 346, 346, 346, 211, 213, 216, 346, 220, 346, 225, 230, 234, 346, 346, 0, 0, 107, 0, 199, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 346, 245, 346, 346, 67, 51, 70, 74, 346, 346, 85, 91, 346, 346, 106, 346, 115, 346, 121, 272, 123, 346, 346, 346, 346, 346, 346, 142, 145, 346, 346, 346, 346, 346, 346, 346, 346, 160, 346, 346, 346, 346, 346, 346, 346, 346, 346, 290, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 258, 346, 195, 196, 346, 201, 346, 203, 206, 208, 346, 210, 346, 346, 346, 346, 239, 0, 106, 196, 203, 0, 32, 35, 38, 37, 34, 0, 0, 55, 346, 346, 346, 77, 346, 346, 346, 346, 346, 124, 346, 346, 346, 346, 346, 146, 147, 151, 148, 346, 346, 346, 155, 161, 346, 168, 165, 346, 346, 172, 346, 291, 346, 346, 346, 346, 346, 346, 346, 346, 346, 186, 346, 293, 310, 346, 197, 346, 209, 218, 346, 346, 346, 233, 0, 233, 0, 0, 346, 62, 346, 346, 96, 346, 108, 346, 346, 346, 346, 135, 346, 346, 346, 154, 346, 346, 171, 346, 346, 178, 179, 180, 346, 182, 346, 346, 346, 346, 346, 346, 346, 346, 346, 232, 0, 0, 0, 346, 346, 204, 99, 269, 126, 128, 130, 346, 346, 150, 346, 167, 281, 292, 346, 346, 346, 346, 187, 346, 346, 346, 346, 346, 204, 0, 0, 346, 75, 346, 346, 346, 346, 164, 346, 183, 184, 346, 193, 162, 346, 346, 231, 0, 328, 58, 346, 346, 138, 163, 346, 346, 346, 223, 329, 346, 346, 346, 346, 219, 346, 346, 346, 346, 127, 129, 346, 346, 346, 185, 346, 346, 181, 0 } ; static yyconst YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 1, 1, 9, 10, 11, 12, 13, 14, 1, 15, 16, 17, 18, 18, 19, 18, 18, 18, 18, 18, 18, 18, 20, 1, 21, 22, 23, 1, 1, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 1, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 85, 1, 1, 1, 86, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 87, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst YY_CHAR yy_meta[89] = { 0, 1, 1, 2, 1, 3, 1, 4, 1, 1, 5, 1, 1, 6, 1, 7, 8, 8, 8, 8, 3, 1, 7, 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 9, 10, 7, 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_uint16_t yy_base[2051] = { 0, 0, 0, 86, 172, 260, 0, 348, 0, 89, 93, 97, 99, 98, 102, 1126, 4850, 115, 4850, 4850, 0, 1088, 115, 119, 436, 151, 127, 430, 499, 162, 428, 504, 511, 173, 424, 54, 114, 560, 561, 428, 612, 620, 80, 444, 667, 622, 676, 449, 725, 0, 1002, 965, 892, 4850, 4850, 4850, 98, 116, 126, 145, 173, 456, 195, 183, 182, 442, 564, 437, 442, 453, 528, 179, 797, 562, 502, 786, 576, 669, 676, 509, 501, 719, 516, 791, 559, 514, 793, 801, 580, 843, 860, 791, 613, 4850, 254, 549, 944, 913, 919, 866, 595, 704, 754, 892, 646, 881, 723, 721, 849, 794, 554, 870, 834, 565, 641, 861, 838, 855, 628, 877, 874, 670, 688, 909, 137, 762, 822, 4850, 4850, 723, 824, 784, 0, 726, 809, 927, 0, 4850, 766, 772, 0, 769, 763, 920, 931, 0, 934, 950, 752, 4850, 993, 1081, 952, 969, 863, 989, 867, 955, 879, 917, 920, 979, 0, 949, 985, 977, 997, 992, 0, 975, 981, 0, 1005, 993, 995, 998, 1071, 1009, 996, 999, 1062, 1075, 1070, 1071, 1069, 1072, 1075, 1090, 1091, 1073, 1093, 1083, 1095, 1129, 1092, 1089, 1129, 1087, 1132, 0, 1152, 1121, 0, 1129, 0, 1152, 1152, 1180, 1136, 1132, 1183, 1177, 1149, 1156, 1170, 1176, 1196, 1178, 1204, 1192, 1193, 1189, 1193, 1227, 1223, 1211, 1234, 1243, 1213, 1200, 1229, 1221, 1233, 1259, 1236, 1235, 1257, 1250, 1253, 1269, 1270, 1286, 1262, 1298, 1262, 0, 0, 1283, 0, 1289, 1278, 1289, 1305, 1308, 1292, 1308, 1295, 1298, 1317, 666, 4850, 607, 591, 585, 1313, 1320, 1316, 1304, 1327, 1331, 1327, 1319, 1321, 1335, 1338, 1344, 1321, 1329, 1357, 1351, 1359, 617, 1367, 4850, 1363, 1365, 1368, 1360, 1353, 1373, 1378, 1377, 1366, 1372, 1383, 1375, 1392, 1413, 1369, 1404, 1401, 1389, 1406, 1398, 1414, 0, 1403, 1422, 1410, 1407, 1423, 1419, 1418, 1435, 1413, 1440, 1430, 1431, 1436, 1433, 1425, 1443, 4850, 615, 4850, 558, 1464, 1485, 1489, 1497, 1500, 1506, 4850, 4850, 4850, 4850, 1464, 1477, 1466, 1497, 1493, 1489, 1504, 1499, 1488, 1499, 1494, 1499, 1501, 4850, 1507, 1495, 1504, 1496, 4850, 1500, 4850, 1519, 1505, 1515, 1514, 1511, 1510, 1517, 1524, 530, 1551, 1552, 1548, 4850, 501, 199, 4850, 4850, 542, 4850, 445, 0, 4850, 4850, 4850, 0, 4850, 1571, 1577, 559, 749, 760, 434, 1556, 1630, 1561, 177, 1718, 1806, 1590, 1597, 938, 954, 1564, 1566, 1579, 1579, 1589, 1585, 1592, 1600, 1601, 1619, 1619, 1610, 1630, 1618, 1619, 1622, 1638, 1623, 1624, 1629, 1629, 1705, 0, 1645, 1626, 1709, 1626, 1633, 1641, 1646, 1632, 1638, 0, 1640, 1638, 1708, 1698, 1700, 1701, 1710, 1711, 1704, 1706, 1725, 1716, 0, 1718, 1718, 1713, 1730, 1714, 1733, 1733, 1730, 1733, 1793, 1738, 1766, 1793, 1786, 1786, 1793, 1799, 1794, 1805, 1804, 1800, 1808, 1810, 1796, 1814, 1815, 0, 0, 1810, 1811, 1871, 1814, 1823, 1820, 1821, 1925, 1822, 1828, 1844, 1857, 1854, 1871, 1868, 1863, 0, 237, 1881, 1882, 1907, 1869, 1869, 1877, 1896, 1897, 1917, 1921, 1939, 1927, 1923, 1936, 1924, 1936, 1929, 1946, 1943, 1952, 1951, 1938, 1946, 1964, 1967, 1973, 1981, 1984, 1973, 1984, 1988, 1982, 1995, 1977, 1986, 0, 1997, 1989, 1986, 1984, 2000, 1981, 1995, 2003, 1995, 2009, 2006, 2008, 2003, 2017, 2013, 2025, 2023, 0, 0, 2027, 0, 0, 2032, 4850, 2038, 2032, 2035, 2050, 2049, 2053, 2054, 2055, 4850, 2051, 2044, 2058, 2049, 2054, 2062, 2056, 2055, 2050, 4850, 196, 4850, 2052, 2057, 2059, 2074, 2075, 2075, 2063, 2065, 2081, 2088, 2100, 2099, 2104, 2105, 2093, 2101, 2097, 2112, 2106, 2112, 2118, 2118, 2122, 2109, 2121, 2108, 189, 764, 181, 1186, 956, 1052, 2137, 2139, 1106, 1165, 2128, 2122, 2132, 2132, 2127, 2131, 2152, 2151, 2142, 2162, 2145, 2146, 2153, 2162, 2150, 2166, 2171, 2167, 2170, 4850, 2159, 2165, 2164, 2167, 2163, 2181, 2180, 2181, 2179, 2170, 2175, 2199, 462, 610, 1222, 4850, 0, 2179, 2254, 0, 1280, 1583, 2210, 2210, 2221, 2207, 2228, 153, 2223, 2215, 2234, 2225, 2247, 2230, 2248, 0, 2254, 2269, 2250, 2244, 2244, 2248, 2261, 2259, 2264, 2256, 2256, 2266, 2254, 2286, 2287, 0, 2280, 2304, 2284, 2306, 2293, 2316, 2310, 2320, 2305, 0, 2323, 2324, 2315, 2312, 2327, 2328, 2333, 0, 2315, 2316, 2328, 2319, 2327, 2336, 2340, 2326, 2342, 2343, 2328, 2326, 2342, 2335, 2335, 0, 2353, 2357, 2374, 2358, 2360, 2368, 2371, 2369, 2383, 0, 2377, 2389, 2388, 0, 2376, 2380, 2387, 2392, 2393, 2386, 2400, 2384, 2429, 2403, 2400, 2389, 2407, 2394, 2394, 2395, 2398, 2405, 2424, 2429, 2430, 2431, 2443, 2446, 2447, 2444, 2436, 2447, 2445, 0, 2449, 0, 2458, 2463, 2440, 2452, 2450, 2461, 2450, 2461, 2465, 2470, 2472, 2466, 2481, 2485, 2475, 2478, 2490, 2480, 2500, 2492, 2506, 2509, 2490, 2511, 2512, 2500, 2504, 2500, 2520, 2513, 2511, 2504, 2525, 2525, 2529, 2518, 2529, 2523, 2524, 2516, 2527, 2522, 2523, 2551, 2542, 2553, 2557, 0, 2553, 0, 2554, 2556, 2557, 2563, 2558, 0, 2565, 2561, 2580, 2562, 2564, 2580, 2580, 2571, 2583, 0, 2587, 2575, 2590, 2582, 2592, 2586, 2581, 2587, 2597, 2581, 2600, 2607, 2615, 4850, 2616, 2605, 2612, 2615, 2617, 0, 2622, 0, 2633, 2621, 2631, 2629, 2637, 2631, 2624, 0, 2630, 2634, 0, 4850, 1670, 1777, 4850, 2633, 2643, 2644, 2653, 2637, 2652, 2643, 2651, 2648, 2656, 2643, 2644, 2650, 2677, 2663, 2663, 2663, 2668, 2681, 2692, 2685, 2678, 2682, 2693, 4850, 2684, 2694, 2706, 1866, 2689, 4850, 0, 0, 2688, 0, 2707, 2697, 0, 2692, 2706, 0, 2715, 2703, 2715, 2703, 2704, 2720, 0, 2720, 2735, 2721, 2712, 2734, 2729, 2742, 2752, 2737, 2758, 2759, 0, 2750, 2744, 2746, 2746, 0, 0, 2757, 0, 2748, 2749, 0, 2752, 2767, 2754, 2754, 2773, 2763, 0, 2762, 2765, 0, 2781, 2765, 0, 0, 2769, 2783, 2804, 2773, 2800, 0, 2804, 2810, 0, 2794, 2809, 2785, 2825, 2822, 2841, 0, 2815, 0, 2812, 2827, 2832, 2819, 2821, 2837, 2819, 2826, 2845, 2834, 2846, 2853, 2863, 2868, 2846, 2871, 2866, 2878, 2870, 2883, 2867, 0, 2862, 2885, 2865, 2872, 2891, 2878, 2874, 2881, 2895, 2875, 2900, 2892, 2902, 0, 2891, 0, 2905, 2897, 2891, 2892, 2901, 2901, 2923, 2915, 2910, 2930, 2933, 2917, 2927, 2925, 2929, 2932, 2929, 2934, 2935, 2942, 2945, 2952, 2946, 2937, 2954, 2958, 2949, 2949, 2963, 2955, 2961, 2953, 2956, 2957, 0, 0, 2988, 2963, 2968, 2977, 2991, 2992, 2989, 0, 3001, 2988, 3001, 2999, 0, 3011, 3012, 3005, 2997, 0, 3015, 3014, 3010, 2993, 0, 0, 3006, 3024, 3011, 3031, 3014, 3017, 0, 4850, 4850, 3017, 3020, 3049, 4850, 4850, 3041, 3050, 3041, 3050, 3037, 3057, 4850, 3049, 4850, 3061, 0, 3052, 3070, 3052, 3069, 3074, 3058, 3067, 3079, 3077, 3064, 3082, 3082, 3087, 3075, 3085, 3086, 3078, 4850, 3095, 3097, 3106, 3113, 3096, 3113, 3109, 4850, 3119, 4850, 3112, 3119, 3121, 3126, 4850, 3118, 1871, 3131, 3130, 3120, 3117, 3130, 3125, 3121, 3130, 0, 3137, 0, 0, 3124, 0, 3131, 3130, 3135, 3153, 3143, 0, 3147, 0, 3137, 3146, 3149, 3162, 3157, 3163, 0, 3174, 3168, 3164, 3180, 0, 3185, 0, 3182, 0, 3172, 0, 3178, 3193, 3175, 3192, 0, 0, 3183, 3184, 3200, 3181, 3178, 3186, 0, 3200, 3194, 3210, 3211, 3211, 3209, 3212, 3215, 3199, 3225, 3216, 3218, 3243, 3234, 0, 0, 3234, 3225, 3236, 3232, 3234, 3235, 3235, 3236, 3235, 3254, 3253, 3243, 3251, 3259, 3261, 3250, 3247, 0, 3248, 0, 3257, 3255, 3258, 3258, 3259, 3257, 3276, 3281, 3281, 3295, 3297, 3286, 3283, 3294, 3306, 0, 0, 3308, 150, 3289, 3296, 3311, 3311, 3293, 3308, 3307, 3302, 0, 0, 0, 0, 3317, 3311, 3311, 3308, 3323, 3327, 3310, 3316, 3316, 3324, 3339, 3321, 0, 3328, 0, 3321, 3346, 3350, 3342, 3362, 3359, 3350, 3363, 3366, 3374, 0, 0, 3367, 0, 0, 3357, 3359, 3359, 3360, 3378, 3378, 3365, 3373, 3373, 3388, 3378, 3375, 3391, 3384, 3393, 3381, 0, 0, 3387, 4850, 3388, 3379, 4850, 3385, 3411, 3403, 3404, 3424, 3425, 3402, 0, 3410, 4850, 4850, 3406, 3423, 3419, 3434, 3426, 3427, 4850, 3441, 3420, 3433, 3430, 3442, 3431, 4850, 3434, 3445, 3433, 3439, 3435, 4850, 3457, 3458, 88, 3444, 3455, 3464, 3445, 3462, 3455, 3464, 3483, 3474, 3487, 0, 3479, 3479, 3480, 3492, 0, 3482, 3496, 0, 3492, 0, 3499, 3498, 3493, 0, 3489, 0, 3495, 3498, 3501, 3498, 3503, 3512, 3497, 3517, 3505, 3510, 0, 3518, 3523, 3515, 3523, 3524, 0, 3527, 3536, 3547, 3533, 3549, 3531, 3547, 3545, 3548, 0, 3550, 3556, 0, 3557, 3567, 3548, 3561, 3553, 3553, 3562, 3570, 0, 3567, 3565, 3570, 3578, 3575, 0, 3574, 3583, 3566, 3579, 3571, 3570, 3586, 0, 3589, 3591, 3604, 3608, 3604, 0, 3610, 0, 3601, 3623, 3609, 3647, 3608, 0, 3627, 3624, 0, 3618, 0, 3614, 3631, 3612, 3629, 3630, 3622, 3625, 3637, 3642, 3646, 3643, 3634, 3656, 3656, 3661, 3667, 3675, 3670, 3677, 3667, 3668, 3684, 3687, 3689, 3687, 3693, 3686, 0, 3697, 3683, 3684, 3698, 3699, 0, 0, 3689, 3699, 3699, 3700, 3697, 3705, 3699, 3719, 3715, 3709, 3710, 3745, 3731, 4850, 3718, 4850, 3726, 3721, 4850, 3733, 3730, 3742, 4850, 3749, 3745, 3737, 3732, 3752, 3755, 4850, 3760, 3757, 4850, 3754, 3751, 3751, 3759, 3761, 0, 3757, 3758, 3756, 3771, 3783, 3793, 3794, 3787, 3798, 3804, 3789, 0, 3796, 3798, 3808, 3794, 3797, 3812, 0, 3803, 3814, 3812, 3810, 3818, 0, 3823, 3820, 3807, 3813, 0, 3814, 3813, 3824, 3822, 3823, 3818, 3819, 3818, 3828, 3839, 3834, 3835, 3850, 3847, 3867, 3850, 3865, 3873, 3871, 3854, 3877, 0, 0, 0, 3853, 3866, 3863, 3878, 3862, 3877, 3882, 3865, 3887, 0, 0, 3876, 3889, 3879, 3893, 3882, 3889, 3881, 3899, 3886, 3913, 3887, 3917, 0, 3916, 3908, 0, 3916, 3922, 0, 3921, 3921, 3924, 0, 3925, 3935, 3921, 3924, 0, 3929, 0, 3931, 3942, 0, 3936, 3923, 3942, 3932, 3939, 3954, 3936, 3943, 0, 3936, 0, 3956, 3949, 3958, 0, 0, 0, 3955, 3955, 3969, 3980, 3973, 4850, 3984, 3980, 4850, 3991, 0, 4850, 3994, 4850, 4850, 4850, 3972, 3979, 3984, 4850, 3986, 4002, 4850, 3992, 3993, 3992, 3994, 0, 4005, 0, 3997, 0, 3995, 0, 4007, 3995, 0, 4000, 3999, 0, 3998, 4009, 0, 4011, 4016, 4026, 0, 4020, 0, 0, 4037, 0, 4031, 0, 0, 4031, 4044, 4033, 4048, 4056, 0, 4055, 4056, 4051, 4048, 4061, 4059, 4060, 4063, 4062, 4048, 4069, 0, 4055, 4067, 4064, 4054, 4070, 4073, 4074, 4060, 4084, 0, 4081, 4078, 4074, 4091, 4094, 4104, 4092, 4101, 4110, 4102, 4116, 4108, 4097, 4108, 4103, 4098, 4113, 4122, 4123, 4117, 4127, 4125, 4119, 4133, 0, 0, 4120, 4116, 4123, 4125, 4127, 4127, 4142, 0, 0, 0, 4136, 0, 4148, 0, 4135, 0, 4148, 4156, 4151, 4156, 4850, 4161, 4850, 4162, 4163, 4176, 4177, 4164, 4164, 4165, 4850, 4174, 4169, 4169, 0, 4187, 4190, 0, 0, 0, 4172, 4180, 4186, 0, 0, 4181, 4182, 0, 4179, 0, 4191, 0, 0, 0, 4184, 4208, 4209, 4193, 4217, 4200, 0, 0, 4224, 4213, 4225, 4222, 4235, 4223, 4234, 4234, 0, 4238, 4225, 4237, 4234, 4233, 4244, 4245, 4239, 4227, 0, 4244, 4239, 4236, 4256, 4247, 4244, 4242, 4243, 4254, 4266, 4270, 4254, 4260, 0, 4285, 0, 0, 4271, 0, 4293, 0, 0, 0, 4277, 0, 4291, 4278, 4285, 4298, 0, 4291, 4850, 4850, 4850, 4285, 4850, 4850, 4850, 4850, 4850, 4287, 4299, 0, 4292, 4289, 4285, 0, 4297, 4299, 4296, 4290, 4299, 0, 4308, 4309, 4318, 4304, 4314, 0, 0, 0, 0, 4320, 4320, 4337, 0, 0, 4338, 0, 0, 4333, 4348, 0, 4351, 0, 4356, 4340, 4351, 4340, 4354, 4344, 4354, 4358, 4359, 0, 4354, 0, 0, 4367, 0, 4357, 0, 4368, 4354, 4366, 4351, 0, 4362, 4850, 4386, 4354, 4369, 0, 4366, 4371, 0, 4373, 0, 4371, 4392, 4399, 4390, 0, 4401, 4407, 4405, 0, 4393, 4407, 0, 4402, 4410, 0, 0, 0, 4405, 0, 4398, 4399, 4415, 4418, 4423, 4429, 4428, 4429, 4416, 0, 4423, 4413, 4442, 4423, 4438, 0, 0, 0, 4440, 4442, 0, 4422, 4445, 0, 4453, 0, 0, 0, 4444, 4461, 4467, 4468, 0, 4471, 4475, 4467, 4464, 4464, 4850, 4479, 64, 4467, 0, 4481, 4482, 4486, 4487, 0, 4472, 0, 0, 4491, 0, 0, 4480, 4482, 0, 56, 4850, 0, 4484, 4485, 0, 0, 4486, 4486, 4489, 0, 4850, 4490, 4491, 4505, 4498, 0, 4506, 4507, 4518, 4513, 0, 0, 4519, 4517, 4526, 0, 4524, 4524, 0, 4850, 4596, 4606, 4616, 4626, 4636, 4646, 4650, 4658, 4668, 4678, 4681, 4691, 4701, 4711, 4721, 4731, 4741, 4751, 4761, 4771, 4779, 4789, 4799, 4809, 4819, 4829, 4839 } ; static yyconst flex_int16_t yy_def[2051] = { 0, 2023, 1, 2024, 2024, 2023, 5, 2023, 7, 2025, 2025, 2026, 2026, 2027, 2027, 2023, 2023, 2023, 2023, 2023, 2028, 2029, 2023, 2030, 2031, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2032, 2033, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2034, 2023, 2031, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 37, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 46, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2036, 2023, 2023, 2023, 2023, 2023, 2037, 2038, 2039, 2023, 2023, 2023, 2040, 2023, 2023, 2023, 2028, 2029, 2029, 2023, 2023, 2030, 2030, 2030, 2041, 2023, 2042, 2043, 2023, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2032, 2023, 2033, 2033, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2044, 2023, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2045, 2023, 2046, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2035, 2035, 2023, 2036, 2047, 2023, 2023, 2037, 2023, 2038, 2039, 2023, 2023, 2023, 2040, 2023, 2023, 2023, 2023, 2030, 2030, 2041, 2023, 2042, 2030, 2048, 2043, 2049, 2023, 2023, 2023, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2044, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2045, 2045, 2046, 2046, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2035, 2047, 2047, 2023, 2023, 2030, 2050, 2049, 646, 2023, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2035, 2023, 2050, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2035, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2035, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2035, 2035, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2023, 2035, 2035, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2035, 2035, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2035, 2035, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2035, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2023, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 2030, 0, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023 } ; static yyconst flex_uint16_t yy_nxt[4939] = { 0, 16, 17, 18, 17, 17, 16, 19, 20, 16, 19, 21, 16, 16, 16, 22, 23, 24, 25, 25, 16, 16, 16, 16, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 49, 49, 50, 16, 16, 16, 16, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 49, 49, 51, 16, 16, 16, 16, 16, 52, 16, 53, 54, 129, 195, 129, 129, 129, 130, 129, 129, 131, 130, 137, 55, 131, 133, 137, 133, 134, 2004, 134, 56, 138, 57, 58, 59, 138, 1994, 139, 60, 139, 139, 61, 62, 195, 225, 63, 64, 65, 66, 67, 68, 143, 69, 144, 144, 264, 70, 146, 146, 55, 1497, 56, 196, 57, 58, 59, 197, 147, 135, 60, 135, 265, 61, 62, 266, 225, 63, 64, 65, 66, 67, 68, 154, 69, 155, 1417, 264, 152, 54, 144, 144, 156, 900, 196, 54, 53, 54, 197, 147, 153, 388, 139, 265, 139, 139, 266, 170, 371, 55, 171, 172, 372, 267, 154, 645, 155, 56, 189, 57, 58, 59, 190, 156, 173, 60, 191, 174, 61, 62, 268, 153, 63, 64, 65, 66, 67, 68, 170, 69, 271, 171, 172, 70, 267, 272, 55, 273, 56, 189, 57, 58, 59, 190, 601, 173, 60, 191, 174, 61, 62, 268, 599, 63, 64, 65, 66, 67, 68, 571, 69, 271, 641, 762, 372, 54, 272, 139, 273, 139, 139, 54, 16, 17, 53, 71, 17, 16, 19, 16, 16, 19, 21, 16, 16, 16, 22, 23, 72, 25, 25, 16, 16, 16, 16, 73, 74, 75, 76, 77, 78, 79, 80, 81, 49, 82, 83, 84, 85, 86, 87, 49, 88, 89, 90, 91, 49, 92, 49, 49, 49, 16, 16, 16, 16, 16, 73, 74, 75, 76, 77, 78, 79, 80, 81, 49, 82, 83, 84, 85, 86, 87, 49, 88, 89, 90, 91, 49, 92, 49, 49, 49, 51, 54, 16, 16, 16, 16, 16, 54, 93, 94, 53, 95, 94, 96, 97, 93, 98, 99, 93, 93, 93, 93, 100, 101, 93, 102, 102, 93, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 93, 113, 114, 93, 115, 93, 116, 117, 93, 93, 118, 119, 120, 121, 93, 122, 93, 93, 93, 123, 93, 93, 93, 124, 106, 107, 108, 109, 110, 111, 112, 93, 113, 114, 93, 115, 93, 116, 117, 93, 93, 118, 119, 120, 121, 93, 122, 93, 93, 93, 93, 125, 93, 126, 93, 93, 93, 127, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 149, 148, 389, 210, 151, 157, 375, 148, 148, 158, 148, 192, 193, 159, 175, 176, 177, 211, 194, 226, 178, 274, 160, 227, 251, 161, 179, 228, 252, 278, 279, 269, 280, 229, 210, 270, 157, 148, 148, 148, 158, 148, 192, 193, 159, 175, 176, 177, 211, 194, 226, 178, 274, 160, 227, 251, 161, 179, 228, 252, 278, 279, 269, 280, 229, 641, 270, 372, 148, 148, 148, 148, 148, 148, 148, 148, 162, 285, 163, 180, 190, 164, 165, 181, 185, 166, 185, 182, 167, 303, 186, 168, 169, 183, 187, 298, 184, 282, 282, 197, 375, 295, 139, 188, 139, 139, 372, 162, 285, 163, 180, 190, 164, 165, 181, 185, 166, 185, 182, 167, 303, 186, 168, 169, 183, 187, 298, 184, 642, 642, 197, 283, 295, 369, 188, 198, 205, 199, 301, 200, 206, 275, 302, 201, 207, 344, 202, 276, 154, 203, 284, 288, 204, 350, 171, 289, 208, 156, 277, 312, 209, 601, 326, 228, 327, 327, 198, 205, 199, 301, 200, 206, 275, 302, 201, 207, 344, 202, 276, 154, 203, 284, 288, 204, 350, 171, 289, 208, 156, 277, 312, 209, 212, 213, 228, 219, 255, 239, 256, 220, 214, 240, 215, 221, 216, 241, 222, 217, 218, 223, 333, 242, 224, 641, 243, 893, 351, 358, 599, 334, 571, 244, 550, 212, 213, 262, 219, 255, 239, 256, 220, 214, 240, 215, 221, 216, 241, 222, 217, 218, 223, 262, 242, 224, 230, 243, 231, 351, 358, 232, 233, 180, 244, 245, 234, 181, 290, 291, 235, 293, 363, 236, 246, 237, 247, 294, 238, 292, 248, 260, 249, 364, 250, 328, 328, 230, 139, 231, 139, 139, 232, 233, 180, 329, 245, 234, 181, 290, 291, 235, 293, 363, 236, 246, 237, 247, 294, 238, 292, 248, 338, 249, 364, 250, 253, 254, 296, 297, 255, 378, 256, 336, 257, 194, 329, 337, 339, 258, 387, 387, 389, 330, 859, 327, 327, 139, 142, 139, 139, 387, 387, 338, 142, 331, 382, 253, 254, 296, 297, 255, 378, 256, 336, 257, 194, 375, 337, 339, 258, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 2023, 148, 162, 331, 163, 299, 599, 148, 148, 300, 148, 286, 304, 145, 287, 308, 342, 168, 321, 145, 305, 375, 215, 309, 145, 373, 145, 306, 307, 310, 343, 379, 311, 162, 356, 163, 299, 148, 148, 148, 300, 148, 286, 304, 145, 287, 308, 342, 168, 321, 145, 305, 348, 215, 309, 145, 322, 145, 306, 307, 310, 343, 379, 311, 313, 314, 355, 349, 148, 148, 148, 148, 148, 148, 148, 148, 315, 340, 317, 352, 341, 316, 318, 348, 345, 399, 356, 322, 319, 353, 357, 320, 346, 335, 354, 313, 314, 355, 349, 359, 404, 347, 361, 360, 332, 362, 325, 315, 340, 317, 352, 341, 316, 318, 407, 345, 399, 356, 324, 319, 353, 357, 320, 346, 380, 354, 366, 380, 383, 383, 359, 404, 347, 361, 360, 367, 362, 152, 384, 144, 144, 368, 146, 146, 408, 407, 398, 398, 410, 153, 409, 369, 147, 323, 385, 386, 322, 366, 387, 387, 395, 395, 398, 398, 603, 603, 367, 263, 380, 384, 396, 405, 368, 397, 397, 408, 413, 398, 398, 410, 153, 409, 406, 147, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 411, 414, 391, 396, 405, 388, 388, 400, 388, 413, 415, 401, 421, 416, 412, 406, 422, 425, 402, 418, 419, 420, 423, 426, 403, 427, 424, 430, 431, 432, 433, 411, 414, 417, 434, 388, 388, 388, 400, 388, 262, 415, 401, 421, 416, 412, 260, 422, 425, 402, 418, 419, 420, 423, 426, 403, 427, 424, 430, 431, 432, 433, 603, 603, 417, 434, 388, 388, 388, 388, 388, 388, 388, 388, 392, 392, 388, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 428, 435, 394, 436, 142, 392, 392, 437, 392, 438, 439, 443, 440, 441, 429, 444, 442, 445, 446, 447, 450, 451, 452, 453, 458, 459, 462, 448, 607, 607, 2023, 428, 435, 449, 436, 392, 392, 392, 437, 392, 438, 439, 443, 440, 441, 429, 444, 442, 445, 446, 447, 450, 451, 452, 453, 458, 459, 462, 448, 454, 455, 463, 470, 471, 449, 456, 392, 392, 392, 392, 392, 392, 392, 392, 460, 482, 457, 464, 483, 465, 467, 461, 488, 476, 466, 468, 469, 607, 607, 2023, 454, 455, 463, 470, 471, 472, 456, 473, 474, 477, 859, 489, 490, 475, 491, 460, 482, 457, 464, 483, 465, 467, 461, 488, 476, 466, 468, 469, 486, 478, 479, 480, 487, 484, 492, 493, 472, 481, 473, 474, 477, 485, 489, 490, 475, 491, 494, 495, 497, 496, 498, 499, 601, 505, 642, 642, 2023, 514, 515, 486, 478, 479, 480, 487, 484, 492, 493, 516, 481, 503, 517, 518, 485, 500, 522, 504, 501, 494, 495, 497, 496, 498, 499, 502, 505, 506, 508, 509, 514, 515, 507, 2023, 510, 523, 526, 524, 511, 512, 516, 513, 503, 517, 518, 527, 500, 522, 504, 501, 528, 519, 520, 534, 649, 649, 502, 538, 506, 508, 509, 525, 529, 507, 521, 510, 523, 526, 524, 511, 512, 539, 513, 530, 540, 541, 527, 531, 535, 532, 542, 528, 519, 520, 534, 533, 536, 543, 538, 544, 545, 546, 525, 529, 547, 521, 548, 549, 537, 551, 552, 553, 539, 554, 530, 540, 541, 555, 531, 535, 532, 542, 556, 558, 559, 560, 533, 536, 543, 561, 544, 545, 546, 562, 564, 547, 565, 548, 549, 537, 551, 552, 553, 566, 554, 557, 563, 567, 555, 568, 569, 282, 282, 556, 558, 559, 560, 405, 572, 401, 561, 573, 575, 574, 562, 564, 402, 565, 576, 428, 431, 433, 403, 578, 566, 577, 557, 563, 567, 449, 568, 569, 580, 583, 439, 283, 579, 441, 405, 572, 401, 2023, 573, 575, 574, 584, 468, 402, 585, 576, 428, 431, 433, 403, 578, 581, 577, 478, 485, 586, 449, 456, 587, 580, 583, 439, 588, 579, 441, 496, 589, 590, 582, 504, 512, 592, 584, 468, 593, 585, 524, 591, 594, 595, 534, 596, 581, 531, 478, 485, 586, 597, 456, 587, 530, 533, 2023, 588, 328, 328, 496, 589, 590, 582, 504, 512, 592, 324, 329, 593, 2023, 524, 591, 594, 595, 534, 596, 330, 531, 327, 327, 608, 597, 328, 328, 530, 533, 602, 602, 331, 609, 603, 603, 329, 604, 604, 606, 606, 324, 329, 607, 607, 610, 613, 605, 611, 612, 616, 617, 614, 618, 619, 608, 620, 621, 622, 624, 625, 626, 627, 331, 609, 615, 628, 329, 629, 623, 630, 631, 632, 634, 633, 635, 610, 613, 605, 611, 612, 616, 617, 614, 618, 619, 636, 620, 621, 622, 624, 625, 626, 627, 637, 638, 615, 628, 639, 629, 623, 630, 631, 632, 634, 633, 635, 643, 383, 383, 385, 385, 644, 650, 642, 642, 651, 636, 384, 369, 649, 649, 369, 369, 2023, 637, 638, 395, 395, 639, 648, 648, 2023, 652, 649, 649, 653, 396, 643, 2023, 654, 2023, 655, 644, 650, 656, 657, 651, 658, 384, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 652, 659, 391, 653, 396, 388, 388, 654, 388, 655, 660, 661, 656, 657, 662, 658, 663, 664, 665, 666, 667, 668, 669, 670, 674, 675, 678, 679, 680, 681, 682, 683, 659, 684, 685, 388, 388, 388, 2023, 388, 2023, 660, 661, 861, 861, 662, 2023, 663, 664, 665, 666, 667, 668, 669, 670, 674, 675, 678, 679, 680, 681, 682, 683, 2023, 684, 685, 388, 388, 388, 388, 388, 388, 388, 388, 392, 392, 388, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 676, 671, 394, 686, 2023, 392, 392, 687, 392, 672, 688, 689, 690, 692, 693, 673, 694, 677, 695, 697, 691, 698, 699, 700, 701, 702, 703, 704, 696, 705, 706, 676, 671, 709, 686, 392, 392, 392, 687, 392, 672, 688, 689, 690, 692, 693, 673, 694, 677, 695, 697, 691, 698, 699, 700, 701, 702, 703, 704, 696, 705, 706, 861, 861, 709, 2023, 392, 392, 392, 392, 392, 392, 392, 392, 140, 140, 710, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 711, 712, 713, 707, 2023, 140, 140, 708, 140, 714, 715, 717, 718, 719, 720, 721, 722, 647, 723, 710, 716, 724, 725, 726, 727, 739, 740, 742, 743, 754, 741, 711, 712, 713, 707, 140, 140, 140, 708, 140, 714, 715, 717, 718, 719, 720, 721, 722, 647, 723, 755, 716, 724, 725, 726, 727, 739, 740, 742, 743, 754, 741, 2023, 756, 757, 2023, 140, 140, 140, 140, 140, 140, 140, 140, 728, 729, 758, 730, 759, 731, 732, 755, 733, 760, 761, 734, 763, 764, 735, 767, 2023, 768, 736, 737, 756, 757, 738, 369, 1124, 769, 2023, 770, 369, 1328, 771, 728, 729, 758, 730, 759, 731, 732, 772, 733, 760, 761, 734, 763, 764, 735, 767, 765, 768, 736, 737, 766, 773, 738, 744, 745, 769, 746, 770, 747, 748, 771, 749, 774, 777, 750, 779, 780, 775, 772, 782, 783, 751, 752, 781, 778, 753, 784, 765, 785, 786, 787, 766, 773, 788, 744, 745, 789, 746, 790, 747, 748, 776, 749, 774, 777, 750, 779, 780, 775, 791, 782, 783, 751, 752, 781, 778, 753, 784, 792, 785, 786, 787, 793, 794, 788, 795, 797, 789, 798, 790, 799, 800, 776, 801, 802, 803, 804, 796, 805, 806, 791, 807, 808, 809, 810, 811, 812, 813, 814, 792, 815, 820, 2023, 793, 794, 816, 795, 797, 818, 798, 817, 799, 800, 819, 801, 802, 803, 804, 796, 805, 806, 821, 807, 808, 809, 810, 811, 812, 813, 814, 823, 815, 820, 822, 824, 825, 816, 826, 827, 818, 828, 817, 829, 830, 819, 831, 832, 833, 834, 835, 836, 837, 821, 838, 839, 840, 841, 842, 843, 844, 672, 823, 845, 676, 822, 824, 825, 846, 826, 827, 691, 828, 847, 829, 830, 848, 831, 832, 833, 834, 835, 836, 837, 707, 838, 839, 840, 841, 842, 843, 844, 672, 849, 845, 676, 715, 851, 741, 846, 852, 765, 691, 853, 847, 771, 850, 848, 854, 777, 795, 855, 856, 857, 858, 707, 817, 862, 860, 860, 604, 604, 861, 861, 849, 863, 864, 715, 851, 741, 605, 852, 765, 865, 853, 866, 771, 850, 867, 854, 777, 795, 855, 856, 857, 858, 868, 817, 862, 869, 870, 871, 872, 873, 874, 875, 863, 864, 876, 877, 878, 605, 879, 880, 865, 881, 866, 882, 883, 867, 884, 885, 886, 887, 888, 889, 894, 868, 890, 891, 869, 870, 871, 872, 873, 874, 875, 369, 892, 876, 877, 878, 369, 879, 880, 2023, 881, 2023, 882, 883, 2023, 884, 885, 886, 887, 888, 889, 894, 2023, 890, 891, 2023, 895, 896, 897, 898, 369, 899, 901, 892, 140, 140, 902, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 903, 904, 905, 906, 2023, 140, 140, 907, 140, 895, 896, 897, 898, 908, 899, 901, 911, 912, 913, 902, 914, 915, 917, 918, 909, 919, 920, 922, 921, 923, 916, 903, 904, 905, 906, 140, 140, 140, 907, 140, 2023, 2023, 2023, 910, 908, 924, 925, 911, 912, 913, 926, 914, 915, 917, 918, 909, 919, 920, 922, 921, 923, 916, 927, 928, 929, 930, 140, 140, 140, 140, 140, 140, 140, 140, 910, 931, 924, 925, 932, 933, 934, 926, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 927, 928, 929, 930, 946, 947, 948, 949, 950, 951, 952, 953, 954, 931, 955, 956, 932, 933, 934, 957, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 958, 961, 962, 963, 946, 947, 948, 949, 950, 951, 952, 953, 954, 959, 955, 956, 964, 965, 966, 957, 960, 967, 968, 970, 971, 972, 973, 974, 975, 969, 976, 958, 961, 962, 963, 977, 978, 2023, 982, 983, 984, 985, 986, 987, 959, 988, 989, 964, 965, 966, 990, 960, 967, 968, 970, 971, 972, 973, 974, 975, 969, 976, 979, 991, 992, 993, 977, 978, 980, 982, 983, 984, 985, 986, 987, 994, 988, 989, 995, 996, 981, 990, 999, 1000, 1001, 997, 1002, 1003, 1004, 1005, 1008, 1009, 1010, 979, 991, 992, 993, 998, 1006, 980, 1011, 1012, 1007, 1013, 1014, 1015, 994, 1016, 1017, 995, 996, 981, 1018, 999, 1000, 1001, 997, 1002, 1003, 1004, 1005, 1008, 1009, 1010, 1019, 1020, 1021, 1022, 998, 1006, 1023, 1011, 1012, 1007, 1013, 1014, 1015, 1024, 1016, 1017, 1026, 1027, 1025, 1018, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1019, 1020, 1021, 1022, 1039, 1040, 1023, 1041, 1042, 1043, 1044, 1045, 1046, 1024, 1047, 1048, 1026, 1027, 1025, 1049, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1050, 1051, 1052, 1057, 1039, 1040, 1055, 1041, 1042, 1043, 1044, 1045, 1046, 1053, 1047, 1048, 1056, 1054, 1058, 1049, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1050, 1051, 1052, 1057, 1070, 1071, 1055, 1072, 1073, 1074, 1075, 1076, 1077, 1053, 1078, 1079, 1056, 1054, 1058, 1080, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1081, 1082, 1083, 1084, 1070, 1071, 1085, 1072, 1073, 1074, 1075, 1076, 1077, 1086, 1078, 1079, 1087, 1088, 1089, 1080, 1090, 1091, 959, 1092, 1006, 1093, 1094, 1095, 1096, 1097, 1098, 1081, 1082, 1083, 1084, 1099, 1100, 1085, 1101, 1102, 1103, 1104, 1105, 1106, 1086, 1107, 1108, 1087, 1088, 1089, 1109, 1090, 1091, 959, 1092, 1006, 1093, 1094, 1095, 1096, 1097, 1098, 1110, 1111, 1112, 1113, 1099, 1100, 1114, 1101, 1102, 1103, 1104, 1105, 1106, 1115, 1107, 1108, 1116, 1117, 1118, 1109, 1119, 1120, 1121, 1122, 2023, 1125, 1126, 1123, 1127, 1128, 1129, 1110, 1111, 1112, 1113, 1130, 1131, 1114, 369, 1132, 1133, 1134, 1135, 1136, 1115, 1137, 1140, 1116, 1117, 1118, 1141, 1119, 1120, 1121, 1122, 369, 1125, 1126, 1123, 1127, 1128, 1129, 1138, 1142, 1139, 1143, 1130, 1131, 1144, 1145, 1132, 1133, 1134, 1135, 1136, 1146, 1137, 1140, 1147, 1148, 1149, 1141, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1138, 1142, 1139, 1143, 1161, 1162, 1144, 1145, 1163, 1164, 1165, 1166, 1167, 1146, 1168, 1169, 1147, 1148, 1149, 1176, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1177, 1178, 1181, 1170, 1161, 1162, 1182, 1183, 1163, 1164, 1165, 1166, 1167, 1171, 1168, 1169, 1172, 1173, 1179, 1176, 1174, 1175, 1184, 1185, 2023, 1191, 1192, 1193, 1180, 1194, 1195, 1177, 1178, 1181, 1170, 1196, 1197, 1182, 1183, 1198, 1186, 1199, 1200, 1187, 1171, 1201, 1188, 1172, 1173, 1179, 1189, 1174, 1175, 1184, 1185, 1190, 1191, 1192, 1193, 1180, 1194, 1195, 1202, 1203, 1204, 1205, 1196, 1197, 1206, 1207, 1198, 1186, 1199, 1200, 1187, 1208, 1201, 1188, 1209, 1210, 1211, 1189, 1212, 1213, 1214, 1215, 1190, 1216, 1217, 1218, 1219, 1220, 1221, 1202, 1203, 1204, 1205, 1222, 1223, 1206, 1207, 1224, 1225, 1226, 1227, 1228, 1208, 1229, 1230, 1209, 1210, 1211, 1231, 1212, 1213, 1214, 1215, 1232, 1216, 1217, 1218, 1219, 1220, 1221, 1233, 1234, 1235, 1236, 1222, 1223, 1237, 1238, 1224, 1225, 1226, 1227, 1228, 1239, 1229, 1230, 1240, 1241, 1242, 1231, 1243, 1244, 1245, 1246, 1232, 1249, 1247, 1250, 1251, 1252, 1255, 1233, 1234, 1235, 1236, 1248, 1253, 1237, 1238, 1256, 1257, 1258, 1259, 1254, 1239, 1260, 1261, 1240, 1241, 1242, 1262, 1243, 1244, 1245, 1246, 1266, 1249, 1247, 1250, 1251, 1252, 1255, 1263, 1267, 1264, 1268, 1248, 1253, 1269, 1270, 1256, 1257, 1258, 1259, 1254, 1271, 1260, 1261, 1272, 1273, 1265, 1262, 1274, 1275, 1276, 1277, 1266, 1280, 1281, 1284, 1285, 1278, 1282, 1263, 1267, 1264, 1268, 1279, 1286, 1269, 1270, 1287, 1283, 1288, 1289, 1290, 1271, 1291, 1292, 1272, 1273, 1265, 1293, 1274, 1275, 1276, 1277, 1296, 1280, 1281, 1284, 1285, 1278, 1282, 1294, 1297, 1298, 1299, 1279, 1286, 1300, 1301, 1287, 1283, 1288, 1289, 1290, 1302, 1291, 1292, 1138, 1295, 1139, 1293, 1157, 1170, 1180, 1303, 1296, 1243, 1188, 1304, 1305, 1306, 1307, 1294, 1297, 1298, 1299, 1190, 1308, 1300, 1301, 1309, 1310, 1311, 1312, 1313, 1302, 1314, 1315, 1138, 1295, 1139, 1316, 1157, 1170, 1180, 1303, 1317, 1243, 1188, 1304, 1305, 1306, 1307, 1318, 1319, 1320, 1321, 1190, 1308, 1322, 1323, 1309, 1310, 1311, 1312, 1313, 1324, 1314, 1315, 1325, 1326, 1327, 1316, 1329, 1330, 1331, 1332, 1317, 1333, 1334, 1335, 1336, 1337, 1338, 1318, 1319, 1320, 1321, 1339, 1340, 1322, 1323, 1341, 1342, 1343, 1344, 1345, 1324, 369, 369, 1325, 1326, 1327, 1346, 1329, 1330, 1331, 1332, 1347, 1333, 1334, 1335, 1336, 1337, 1338, 1348, 1349, 1350, 1351, 1339, 1340, 1352, 1353, 1341, 1342, 1343, 1344, 1345, 1354, 1355, 1356, 1357, 1358, 1359, 1346, 1360, 1361, 1362, 1363, 1347, 1364, 1365, 1366, 1367, 1368, 1369, 1348, 1349, 1350, 1351, 1370, 1371, 1352, 1353, 1372, 1373, 1374, 1375, 1376, 1354, 1355, 1356, 1357, 1358, 1359, 1377, 1360, 1361, 1362, 1363, 1378, 1364, 1365, 1366, 1367, 1368, 1369, 1379, 1382, 1383, 1384, 1370, 1371, 1380, 1385, 1372, 1373, 1374, 1375, 1376, 1386, 1381, 1387, 1388, 1389, 1390, 1377, 1391, 1392, 1393, 1394, 1378, 1395, 1396, 1397, 1398, 1399, 1400, 1379, 1382, 1383, 1384, 1401, 1402, 1380, 1385, 1403, 1404, 1405, 1406, 1407, 1386, 1381, 1387, 1388, 1389, 1390, 1408, 1391, 1392, 1393, 1394, 1409, 1395, 1396, 1397, 1398, 1399, 1400, 1410, 1411, 1412, 1413, 1401, 1402, 1414, 1415, 1403, 1404, 1405, 1406, 1407, 1416, 1418, 1419, 1420, 1421, 1422, 1408, 1423, 1424, 1425, 1426, 1409, 1427, 1428, 1429, 1430, 1431, 1432, 1410, 1411, 1412, 1413, 1433, 1434, 1414, 1415, 1435, 1436, 1437, 1438, 1439, 1416, 1418, 1419, 1420, 1421, 1422, 1440, 1423, 1424, 1425, 1426, 1441, 1427, 1428, 1429, 1430, 1431, 1432, 1442, 1443, 1444, 1445, 1433, 1434, 1446, 1447, 1435, 1436, 1437, 1438, 1439, 1449, 1450, 1451, 1452, 1453, 1454, 1440, 1455, 1456, 1457, 1448, 1441, 1458, 1459, 1460, 1461, 1462, 1463, 1442, 1443, 1444, 1445, 1464, 1465, 1446, 1447, 1466, 1467, 1468, 1469, 1470, 1449, 1450, 1451, 1452, 1453, 1454, 1471, 1455, 1456, 1457, 1448, 1472, 1458, 1459, 1460, 1461, 1462, 1463, 1473, 1474, 1475, 1476, 1464, 1465, 1477, 1478, 1466, 1467, 1468, 1469, 1470, 1479, 1480, 1481, 1482, 1483, 1484, 1471, 1485, 1486, 1487, 1488, 1472, 1489, 1490, 1491, 1492, 1493, 1494, 1473, 1474, 1475, 1476, 1498, 1495, 1477, 1478, 1496, 1499, 1500, 1501, 1502, 1479, 1480, 1481, 1482, 1483, 1484, 1503, 1485, 1486, 1487, 1488, 1504, 1489, 1490, 1491, 1492, 1493, 1494, 369, 369, 1505, 1506, 1498, 1495, 1507, 1508, 1496, 1499, 1500, 1501, 1502, 1509, 1510, 1511, 1512, 1513, 1514, 1503, 1515, 1516, 1517, 1518, 1504, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1505, 1506, 1527, 1528, 1507, 1508, 1529, 1530, 1531, 1532, 1533, 1509, 1510, 1511, 1512, 1513, 1514, 1534, 1515, 1516, 1517, 1518, 1535, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1536, 1537, 1527, 1528, 1538, 1539, 1529, 1530, 1531, 1532, 1533, 1540, 1541, 1542, 1543, 1544, 1545, 1534, 1546, 1547, 1548, 1549, 1535, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1536, 1537, 1558, 1559, 1538, 1539, 1560, 1561, 1562, 1563, 1564, 1540, 1541, 1542, 1543, 1544, 1545, 1565, 1546, 1547, 1548, 1549, 1566, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1567, 1568, 1558, 1559, 1569, 1572, 1560, 1561, 1562, 1563, 1564, 1570, 1575, 1571, 1573, 1581, 1582, 1565, 1583, 2023, 1584, 1585, 1566, 2023, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1567, 1568, 1593, 1574, 1569, 1572, 1576, 1577, 1594, 1595, 1596, 1570, 1575, 1571, 1573, 1581, 1582, 1578, 1583, 1579, 1584, 1585, 1597, 1580, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1598, 1599, 1593, 1574, 1600, 1601, 1576, 1577, 1594, 1595, 1596, 1602, 1603, 1604, 1605, 1606, 1607, 1578, 1608, 1579, 1609, 1610, 1597, 1580, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1598, 1599, 1618, 1619, 1600, 1601, 1620, 1621, 1622, 1623, 1624, 1602, 1603, 1604, 1605, 1606, 1607, 1625, 1608, 1626, 1609, 1610, 1627, 1628, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1629, 1630, 1618, 1619, 1631, 1632, 1620, 1621, 1622, 1623, 1624, 1576, 1577, 1633, 1634, 1635, 1636, 1625, 1637, 1626, 1638, 1639, 1627, 1628, 1579, 1640, 1641, 1644, 1580, 1642, 1645, 1629, 1630, 1643, 1646, 1631, 1632, 1647, 1648, 1649, 1650, 1651, 1576, 1577, 1633, 1634, 1635, 1636, 1652, 1637, 369, 1638, 1639, 369, 1653, 1579, 1640, 1641, 1644, 1580, 1642, 1645, 1654, 1655, 1643, 1646, 1656, 1657, 1647, 1648, 1649, 1650, 1651, 1658, 1659, 1660, 1661, 1662, 1663, 1652, 1664, 1665, 1666, 1667, 1668, 1653, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1654, 1655, 1676, 1677, 1656, 1657, 1678, 1679, 1680, 1681, 1682, 1658, 1659, 1660, 1661, 1662, 1663, 1683, 1664, 1665, 1666, 1667, 1668, 1684, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1685, 1686, 1676, 1677, 1687, 1688, 1678, 1679, 1680, 1681, 1682, 1689, 1690, 1691, 1692, 1693, 1694, 1683, 1695, 1696, 1697, 1698, 1699, 1684, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1685, 1686, 1707, 1708, 1687, 1688, 1709, 1710, 1711, 1712, 1713, 1689, 1690, 1691, 1692, 1693, 1694, 1716, 1695, 1696, 1697, 1698, 1699, 1714, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1715, 1719, 1707, 1708, 1717, 1720, 1709, 1710, 1711, 1712, 1713, 1721, 1722, 1723, 1724, 1725, 1726, 1716, 1727, 1728, 1718, 1729, 1730, 1714, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1715, 1719, 1738, 1739, 1717, 1720, 1740, 1741, 1742, 1743, 1744, 1721, 1722, 1723, 1724, 1725, 1726, 1745, 1727, 1728, 1718, 1729, 1730, 1746, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1747, 1748, 1738, 1739, 1749, 1750, 1740, 1741, 1742, 1743, 1744, 1751, 1752, 1753, 1754, 1755, 1756, 1745, 1757, 1758, 1759, 1760, 1761, 1746, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1747, 1748, 1769, 1770, 1749, 1750, 369, 369, 1771, 1772, 1773, 1751, 1752, 1753, 1754, 1755, 1756, 1774, 1757, 1758, 1759, 1760, 1761, 1775, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1776, 1777, 1769, 1770, 1778, 1779, 1780, 1781, 1771, 1772, 1773, 1782, 1783, 1784, 1785, 1786, 1787, 1774, 1788, 1789, 1790, 1791, 1792, 1775, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1776, 1777, 1800, 1801, 1778, 1779, 1780, 1781, 1802, 1803, 1804, 1782, 1783, 1784, 1785, 1786, 1787, 1805, 1788, 1789, 1790, 1791, 1792, 1806, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1807, 1808, 1800, 1801, 1809, 1810, 1811, 1812, 1802, 1803, 1804, 1813, 1814, 1815, 1816, 1817, 1818, 1805, 1819, 1820, 1821, 1822, 1823, 1806, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1807, 1808, 1831, 1832, 1809, 1810, 1811, 1812, 1833, 1834, 1835, 1813, 1814, 1815, 1816, 1817, 1818, 1836, 1819, 1820, 1821, 1822, 1823, 1837, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1838, 1839, 1831, 1832, 1840, 1841, 1842, 1843, 1833, 1834, 1835, 1844, 1845, 1846, 1847, 1848, 1849, 1836, 1850, 1851, 1852, 1853, 1854, 1837, 1855, 1856, 1857, 1858, 369, 1859, 1860, 1838, 1839, 369, 1861, 1840, 1841, 1842, 1843, 1862, 1863, 1864, 1844, 1845, 1846, 1847, 1848, 1849, 1865, 1850, 1851, 1852, 1853, 1854, 1866, 1855, 1856, 1857, 1858, 1867, 1859, 1860, 1868, 1869, 1870, 1861, 1871, 1872, 1873, 1874, 1862, 1863, 1864, 1875, 1876, 1877, 1878, 1879, 1880, 1865, 1881, 1882, 1883, 1884, 1885, 1866, 1886, 1887, 1888, 1889, 1867, 1890, 1891, 1868, 1869, 1870, 1892, 1871, 1872, 1873, 1874, 1893, 1894, 1895, 1875, 1876, 1877, 1878, 1879, 1880, 1896, 1881, 1882, 1883, 1884, 1885, 1897, 1886, 1887, 1888, 1889, 1898, 1890, 1891, 1899, 1900, 1901, 1892, 1902, 1903, 1906, 1904, 1893, 1894, 1895, 1907, 1908, 1910, 1909, 1911, 1912, 1896, 1913, 1914, 1915, 1916, 369, 1897, 1905, 1917, 1918, 1919, 1898, 1920, 1921, 1899, 1900, 1901, 369, 1902, 1903, 1906, 1904, 1922, 1923, 1924, 1907, 1908, 1910, 1909, 1911, 1912, 1925, 1913, 1914, 1915, 1916, 1926, 1927, 1905, 1917, 1918, 1919, 1928, 1920, 1921, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1922, 1923, 1924, 1937, 1938, 1939, 1940, 1941, 1942, 1925, 1943, 1944, 1945, 1946, 1926, 1927, 1948, 1949, 1950, 369, 1928, 1951, 1952, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1947, 1953, 1954, 1937, 1938, 1939, 1940, 1941, 1942, 1955, 1943, 1944, 1945, 1946, 1956, 1957, 1948, 1949, 1950, 1958, 369, 1951, 1952, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1947, 1953, 1954, 1967, 1968, 1969, 1970, 1971, 1972, 1955, 1973, 1974, 1977, 1975, 1956, 1957, 369, 1978, 1979, 1958, 1980, 1976, 1981, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1982, 1983, 1984, 1967, 1968, 1969, 1970, 1971, 1972, 1985, 1973, 1974, 1977, 1975, 369, 1986, 1987, 1978, 1979, 1988, 1980, 1976, 1981, 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1997, 1982, 1983, 1984, 1998, 1999, 2000, 2001, 2002, 2003, 1985, 2005, 2006, 2007, 2008, 2009, 1986, 1987, 2010, 2011, 1988, 369, 2012, 2013, 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1997, 2014, 2015, 2016, 1998, 1999, 2000, 2001, 2002, 2003, 2017, 2005, 2006, 2007, 2008, 2009, 2018, 2019, 2010, 2011, 2020, 2021, 2012, 2013, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2014, 2015, 2016, 2023, 2023, 2023, 2023, 2023, 2023, 2017, 2023, 2023, 2023, 2023, 2023, 2018, 2019, 2023, 2023, 2020, 2021, 2023, 2023, 2022, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 140, 2023, 140, 140, 140, 140, 140, 140, 140, 140, 141, 2023, 141, 141, 141, 141, 141, 141, 141, 141, 145, 145, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 261, 2023, 261, 261, 261, 261, 261, 261, 261, 261, 281, 2023, 281, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 377, 377, 377, 2023, 2023, 377, 377, 377, 2023, 377, 381, 2023, 381, 381, 381, 2023, 381, 381, 381, 381, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 570, 2023, 2023, 2023, 570, 570, 2023, 570, 598, 598, 598, 2023, 598, 598, 598, 598, 598, 598, 600, 600, 600, 600, 2023, 600, 600, 600, 600, 600, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 646, 2023, 646, 646, 646, 646, 646, 646, 646, 646, 140, 2023, 140, 140, 140, 140, 140, 140, 140, 140, 15, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023 } ; static yyconst flex_int16_t yy_chk[4939] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 9, 35, 9, 9, 10, 9, 10, 10, 9, 10, 13, 3, 10, 11, 14, 12, 11, 1993, 12, 3, 13, 3, 3, 3, 14, 1976, 17, 3, 17, 17, 3, 3, 35, 42, 3, 3, 3, 3, 3, 3, 22, 3, 22, 22, 56, 3, 23, 23, 3, 1330, 3, 36, 3, 3, 3, 36, 23, 11, 3, 12, 57, 3, 3, 58, 42, 3, 3, 3, 3, 3, 3, 26, 3, 26, 1231, 56, 25, 3, 25, 25, 26, 655, 36, 3, 4, 4, 36, 23, 25, 392, 71, 57, 71, 71, 58, 29, 124, 4, 29, 29, 124, 59, 26, 392, 26, 4, 33, 4, 4, 4, 33, 26, 29, 4, 33, 29, 4, 4, 60, 25, 4, 4, 4, 4, 4, 4, 29, 4, 62, 29, 29, 4, 59, 63, 4, 64, 4, 33, 4, 4, 4, 33, 600, 29, 4, 33, 29, 4, 4, 60, 598, 4, 4, 4, 4, 4, 4, 570, 4, 62, 371, 490, 371, 4, 63, 94, 64, 94, 94, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 388, 39, 24, 27, 376, 24, 24, 27, 24, 34, 34, 27, 30, 30, 30, 39, 34, 43, 30, 65, 27, 43, 47, 27, 30, 43, 47, 67, 68, 61, 69, 43, 39, 61, 27, 24, 24, 24, 27, 24, 34, 34, 27, 30, 30, 30, 39, 34, 43, 30, 65, 27, 43, 47, 27, 30, 43, 47, 67, 68, 61, 69, 43, 640, 61, 640, 24, 24, 24, 24, 24, 24, 24, 24, 28, 74, 28, 31, 80, 28, 28, 31, 79, 28, 32, 31, 28, 85, 32, 28, 28, 31, 32, 82, 31, 70, 70, 82, 374, 79, 95, 32, 95, 95, 370, 28, 74, 28, 31, 80, 28, 28, 31, 79, 28, 32, 31, 28, 85, 32, 28, 28, 31, 32, 82, 31, 385, 385, 82, 70, 79, 365, 32, 37, 38, 37, 84, 37, 38, 66, 84, 37, 38, 110, 37, 66, 73, 37, 73, 76, 37, 113, 76, 76, 38, 73, 66, 88, 38, 325, 100, 88, 100, 100, 37, 38, 37, 84, 37, 38, 66, 84, 37, 38, 110, 37, 66, 73, 37, 73, 76, 37, 113, 76, 76, 38, 73, 66, 88, 38, 40, 40, 88, 41, 92, 45, 92, 41, 40, 45, 40, 41, 40, 45, 41, 40, 40, 41, 104, 45, 41, 641, 45, 641, 114, 118, 323, 104, 281, 45, 263, 40, 40, 262, 41, 92, 45, 92, 41, 40, 45, 40, 41, 40, 45, 41, 40, 40, 41, 261, 45, 41, 44, 45, 44, 114, 118, 44, 44, 78, 45, 46, 44, 78, 77, 77, 44, 78, 121, 44, 46, 44, 46, 78, 44, 77, 46, 259, 46, 122, 46, 101, 101, 44, 129, 44, 129, 129, 44, 44, 78, 101, 46, 44, 78, 77, 77, 44, 78, 121, 44, 46, 44, 46, 78, 44, 77, 46, 107, 46, 122, 46, 48, 48, 81, 81, 48, 133, 48, 106, 48, 81, 101, 106, 107, 48, 386, 386, 148, 102, 599, 102, 102, 139, 142, 139, 139, 387, 387, 107, 141, 102, 138, 48, 48, 81, 81, 48, 133, 48, 106, 48, 81, 131, 106, 107, 48, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 75, 102, 75, 83, 599, 72, 72, 83, 72, 75, 86, 83, 75, 87, 109, 75, 91, 83, 86, 130, 86, 87, 91, 126, 91, 86, 86, 87, 109, 134, 87, 75, 125, 75, 83, 72, 72, 72, 83, 72, 75, 86, 83, 75, 87, 109, 75, 91, 83, 86, 112, 86, 87, 91, 116, 91, 86, 86, 87, 109, 134, 87, 89, 89, 116, 112, 72, 72, 72, 72, 72, 72, 72, 72, 89, 108, 90, 115, 108, 89, 90, 112, 111, 154, 117, 116, 90, 115, 117, 90, 111, 105, 115, 89, 89, 116, 112, 119, 156, 111, 120, 119, 103, 120, 99, 89, 108, 90, 115, 108, 89, 90, 158, 111, 154, 117, 98, 90, 115, 117, 90, 111, 135, 115, 123, 135, 143, 143, 119, 156, 111, 120, 119, 123, 120, 144, 143, 144, 144, 123, 146, 146, 159, 158, 397, 397, 160, 144, 159, 123, 146, 97, 147, 147, 96, 123, 147, 147, 152, 152, 398, 398, 602, 602, 123, 52, 135, 143, 152, 157, 123, 153, 153, 159, 163, 153, 153, 160, 144, 159, 157, 146, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 161, 164, 150, 152, 157, 150, 150, 155, 150, 163, 165, 155, 169, 166, 161, 157, 170, 173, 155, 167, 167, 167, 172, 174, 155, 175, 172, 177, 177, 178, 179, 161, 164, 166, 179, 150, 150, 150, 155, 150, 51, 165, 155, 169, 166, 161, 50, 170, 173, 155, 167, 167, 167, 172, 174, 155, 175, 172, 177, 177, 178, 179, 603, 603, 166, 179, 150, 150, 150, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 176, 180, 151, 181, 21, 151, 151, 181, 151, 182, 183, 184, 183, 183, 176, 185, 183, 186, 187, 188, 189, 190, 191, 192, 194, 195, 197, 188, 606, 606, 15, 176, 180, 188, 181, 151, 151, 151, 181, 151, 182, 183, 184, 183, 183, 176, 185, 183, 186, 187, 188, 189, 190, 191, 192, 194, 195, 197, 188, 193, 193, 198, 201, 203, 188, 193, 151, 151, 151, 151, 151, 151, 151, 151, 196, 208, 193, 198, 209, 198, 200, 196, 212, 206, 198, 200, 200, 607, 607, 0, 193, 193, 198, 201, 203, 205, 193, 205, 205, 206, 601, 213, 214, 205, 215, 196, 208, 193, 198, 209, 198, 200, 196, 212, 206, 198, 200, 200, 211, 207, 207, 207, 211, 210, 216, 217, 205, 207, 205, 205, 206, 210, 213, 214, 205, 215, 218, 219, 220, 219, 221, 222, 601, 225, 642, 642, 0, 228, 229, 211, 207, 207, 207, 211, 210, 216, 217, 230, 207, 224, 231, 232, 210, 223, 234, 224, 223, 218, 219, 220, 219, 221, 222, 223, 225, 226, 227, 227, 228, 229, 226, 0, 227, 235, 237, 236, 227, 227, 230, 227, 224, 231, 232, 238, 223, 234, 224, 223, 239, 233, 233, 242, 648, 648, 223, 244, 226, 227, 227, 236, 240, 226, 233, 227, 235, 237, 236, 227, 227, 247, 227, 240, 249, 250, 238, 241, 243, 241, 251, 239, 233, 233, 242, 241, 243, 252, 244, 253, 254, 255, 236, 240, 256, 233, 257, 258, 243, 264, 265, 266, 247, 267, 240, 249, 250, 268, 241, 243, 241, 251, 269, 270, 271, 272, 241, 243, 252, 273, 253, 254, 255, 274, 275, 256, 276, 257, 258, 243, 264, 265, 266, 277, 267, 269, 274, 278, 268, 279, 280, 282, 282, 269, 270, 271, 272, 285, 286, 284, 273, 287, 288, 287, 274, 275, 284, 276, 289, 290, 291, 292, 284, 293, 277, 292, 269, 274, 278, 295, 279, 280, 296, 298, 294, 282, 294, 294, 285, 286, 284, 0, 287, 288, 287, 299, 300, 284, 301, 289, 290, 291, 292, 284, 293, 297, 292, 302, 303, 304, 295, 297, 306, 296, 298, 294, 307, 294, 294, 308, 309, 310, 297, 311, 312, 313, 299, 300, 314, 301, 315, 310, 316, 317, 319, 320, 297, 318, 302, 303, 304, 321, 297, 306, 317, 318, 0, 307, 326, 326, 308, 309, 310, 297, 311, 312, 313, 336, 326, 314, 0, 315, 310, 316, 317, 319, 320, 327, 318, 327, 327, 337, 321, 328, 328, 317, 318, 329, 329, 327, 338, 329, 329, 328, 330, 330, 331, 331, 336, 326, 331, 331, 339, 341, 330, 340, 340, 343, 344, 342, 345, 346, 337, 347, 348, 350, 351, 352, 353, 355, 327, 338, 342, 357, 328, 358, 350, 359, 360, 361, 362, 361, 363, 339, 341, 330, 340, 340, 343, 344, 342, 345, 346, 364, 347, 348, 350, 351, 352, 353, 355, 366, 367, 342, 357, 368, 358, 350, 359, 360, 361, 362, 361, 363, 389, 383, 383, 384, 384, 391, 399, 384, 384, 400, 364, 383, 368, 649, 649, 366, 367, 0, 366, 367, 395, 395, 368, 396, 396, 0, 401, 396, 396, 402, 395, 389, 0, 403, 0, 404, 391, 399, 405, 406, 400, 407, 383, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 401, 408, 390, 402, 395, 390, 390, 403, 390, 404, 409, 410, 405, 406, 411, 407, 412, 413, 414, 415, 416, 417, 418, 419, 422, 423, 425, 426, 427, 428, 429, 430, 408, 432, 433, 390, 390, 390, 0, 390, 0, 409, 410, 860, 860, 411, 0, 412, 413, 414, 415, 416, 417, 418, 419, 422, 423, 425, 426, 427, 428, 429, 430, 0, 432, 433, 390, 390, 390, 390, 390, 390, 390, 390, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 424, 420, 393, 434, 0, 393, 393, 435, 393, 420, 436, 437, 438, 439, 440, 420, 441, 424, 442, 443, 438, 445, 446, 447, 448, 449, 450, 451, 442, 452, 453, 424, 420, 455, 434, 393, 393, 393, 435, 393, 420, 436, 437, 438, 439, 440, 420, 441, 424, 442, 443, 438, 445, 446, 447, 448, 449, 450, 451, 442, 452, 453, 861, 861, 455, 0, 393, 393, 393, 393, 393, 393, 393, 393, 394, 394, 456, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 457, 458, 459, 454, 0, 394, 394, 454, 394, 460, 461, 462, 463, 464, 465, 466, 467, 394, 468, 456, 461, 469, 470, 473, 474, 476, 477, 478, 479, 481, 477, 457, 458, 459, 454, 394, 394, 394, 454, 394, 460, 461, 462, 463, 464, 465, 466, 467, 394, 468, 482, 461, 469, 470, 473, 474, 476, 477, 478, 479, 481, 477, 0, 483, 484, 0, 394, 394, 394, 394, 394, 394, 394, 394, 475, 475, 485, 475, 486, 475, 475, 482, 475, 487, 488, 475, 491, 492, 475, 494, 0, 495, 475, 475, 483, 484, 475, 891, 891, 496, 0, 497, 1123, 1123, 498, 475, 475, 485, 475, 486, 475, 475, 498, 475, 487, 488, 475, 491, 492, 475, 494, 493, 495, 475, 475, 493, 499, 475, 480, 480, 496, 480, 497, 480, 480, 498, 480, 500, 502, 480, 503, 504, 501, 498, 505, 506, 480, 480, 504, 502, 480, 507, 493, 508, 509, 510, 493, 499, 511, 480, 480, 512, 480, 513, 480, 480, 501, 480, 500, 502, 480, 503, 504, 501, 514, 505, 506, 480, 480, 504, 502, 480, 507, 515, 508, 509, 510, 516, 517, 511, 518, 519, 512, 520, 513, 521, 522, 501, 523, 524, 525, 527, 518, 528, 529, 514, 530, 531, 532, 533, 534, 535, 536, 537, 515, 538, 541, 0, 516, 517, 539, 518, 519, 540, 520, 539, 521, 522, 540, 523, 524, 525, 527, 518, 528, 529, 542, 530, 531, 532, 533, 534, 535, 536, 537, 543, 538, 541, 542, 546, 549, 539, 551, 552, 540, 553, 539, 554, 555, 540, 556, 557, 558, 560, 561, 562, 563, 542, 564, 565, 566, 567, 568, 572, 573, 574, 543, 575, 576, 542, 546, 549, 577, 551, 552, 578, 553, 579, 554, 555, 580, 556, 557, 558, 560, 561, 562, 563, 581, 564, 565, 566, 567, 568, 572, 573, 574, 582, 575, 576, 583, 584, 585, 577, 586, 587, 578, 588, 579, 589, 583, 580, 590, 591, 592, 593, 594, 595, 596, 581, 597, 608, 605, 605, 604, 604, 605, 605, 582, 609, 610, 583, 584, 585, 604, 586, 587, 611, 588, 612, 589, 583, 613, 590, 591, 592, 593, 594, 595, 596, 614, 597, 608, 615, 616, 617, 618, 619, 620, 621, 609, 610, 622, 623, 624, 604, 625, 626, 611, 628, 612, 629, 630, 613, 631, 632, 633, 634, 635, 636, 645, 614, 637, 638, 615, 616, 617, 618, 619, 620, 621, 637, 639, 622, 623, 624, 638, 625, 626, 0, 628, 0, 629, 630, 0, 631, 632, 633, 634, 635, 636, 645, 0, 637, 638, 0, 650, 651, 652, 653, 639, 654, 656, 639, 646, 646, 657, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 658, 659, 660, 661, 0, 646, 646, 662, 646, 650, 651, 652, 653, 664, 654, 656, 666, 667, 668, 657, 669, 670, 671, 672, 665, 673, 674, 675, 674, 676, 670, 658, 659, 660, 661, 646, 646, 646, 662, 646, 0, 0, 0, 665, 664, 677, 678, 666, 667, 668, 680, 669, 670, 671, 672, 665, 673, 674, 675, 674, 676, 670, 681, 682, 683, 684, 646, 646, 646, 646, 646, 646, 646, 646, 665, 685, 677, 678, 686, 687, 688, 680, 690, 691, 692, 693, 694, 695, 696, 698, 699, 700, 701, 681, 682, 683, 684, 702, 703, 704, 705, 706, 707, 708, 709, 710, 685, 711, 712, 686, 687, 688, 714, 690, 691, 692, 693, 694, 695, 696, 698, 699, 700, 701, 715, 717, 718, 719, 702, 703, 704, 705, 706, 707, 708, 709, 710, 716, 711, 712, 720, 721, 722, 714, 716, 724, 725, 726, 728, 729, 730, 731, 732, 725, 733, 715, 717, 718, 719, 734, 735, 0, 737, 738, 739, 740, 741, 742, 716, 743, 744, 720, 721, 722, 745, 716, 724, 725, 726, 728, 729, 730, 731, 732, 725, 733, 736, 746, 747, 748, 734, 735, 736, 737, 738, 739, 740, 741, 742, 749, 743, 744, 750, 751, 736, 745, 752, 753, 754, 751, 755, 756, 758, 760, 762, 763, 764, 736, 746, 747, 748, 751, 761, 736, 765, 766, 761, 767, 768, 769, 749, 770, 771, 750, 751, 736, 772, 752, 753, 754, 751, 755, 756, 758, 760, 762, 763, 764, 773, 774, 775, 776, 751, 761, 777, 765, 766, 761, 767, 768, 769, 778, 770, 771, 779, 780, 778, 772, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 773, 774, 775, 776, 792, 793, 777, 794, 795, 796, 797, 798, 799, 778, 800, 801, 779, 780, 778, 802, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 803, 804, 805, 810, 792, 793, 808, 794, 795, 796, 797, 798, 799, 806, 800, 801, 808, 806, 811, 802, 812, 813, 814, 816, 817, 818, 819, 820, 821, 822, 823, 803, 804, 805, 810, 824, 826, 808, 827, 828, 829, 830, 831, 832, 806, 833, 834, 808, 806, 811, 835, 812, 813, 814, 816, 817, 818, 819, 820, 821, 822, 823, 836, 837, 838, 840, 824, 826, 841, 827, 828, 829, 830, 831, 832, 842, 833, 834, 843, 844, 846, 835, 848, 849, 850, 851, 852, 853, 854, 856, 857, 863, 864, 836, 837, 838, 840, 865, 866, 841, 867, 868, 869, 870, 871, 872, 842, 873, 874, 843, 844, 846, 875, 848, 849, 850, 851, 852, 853, 854, 856, 857, 863, 864, 876, 877, 878, 879, 865, 866, 880, 867, 868, 869, 870, 871, 872, 881, 873, 874, 882, 883, 884, 875, 885, 886, 888, 889, 0, 892, 896, 890, 898, 899, 901, 876, 877, 878, 879, 902, 904, 880, 892, 905, 906, 907, 908, 909, 881, 911, 913, 882, 883, 884, 914, 885, 886, 888, 889, 890, 892, 896, 890, 898, 899, 901, 912, 915, 912, 916, 902, 904, 916, 917, 905, 906, 907, 908, 909, 918, 911, 913, 919, 920, 921, 914, 923, 924, 925, 926, 929, 931, 932, 932, 934, 935, 936, 912, 915, 912, 916, 937, 938, 916, 917, 939, 941, 942, 944, 945, 918, 948, 949, 919, 920, 921, 951, 923, 924, 925, 926, 929, 931, 932, 932, 934, 935, 936, 952, 954, 957, 950, 937, 938, 958, 959, 939, 941, 942, 944, 945, 950, 948, 949, 950, 950, 955, 951, 950, 950, 960, 961, 0, 964, 966, 967, 955, 968, 969, 952, 954, 957, 950, 970, 971, 958, 959, 972, 962, 973, 974, 962, 950, 975, 962, 950, 950, 955, 962, 950, 950, 960, 961, 962, 964, 966, 967, 955, 968, 969, 976, 977, 978, 979, 970, 971, 980, 981, 972, 962, 973, 974, 962, 982, 975, 962, 983, 984, 985, 962, 986, 988, 989, 990, 962, 991, 992, 993, 994, 995, 996, 976, 977, 978, 979, 997, 998, 980, 981, 999, 1000, 1002, 1004, 1005, 982, 1006, 1007, 983, 984, 985, 1008, 986, 988, 989, 990, 1009, 991, 992, 993, 994, 995, 996, 1010, 1011, 1012, 1013, 997, 998, 1014, 1015, 999, 1000, 1002, 1004, 1005, 1016, 1006, 1007, 1017, 1018, 1019, 1008, 1020, 1021, 1022, 1023, 1009, 1025, 1024, 1026, 1027, 1028, 1030, 1010, 1011, 1012, 1013, 1024, 1029, 1014, 1015, 1031, 1032, 1033, 1034, 1029, 1016, 1035, 1036, 1017, 1018, 1019, 1037, 1020, 1021, 1022, 1023, 1041, 1025, 1024, 1026, 1027, 1028, 1030, 1040, 1042, 1040, 1043, 1024, 1029, 1044, 1045, 1031, 1032, 1033, 1034, 1029, 1046, 1035, 1036, 1048, 1049, 1040, 1037, 1050, 1051, 1053, 1054, 1041, 1056, 1058, 1060, 1061, 1055, 1059, 1040, 1042, 1040, 1043, 1055, 1064, 1044, 1045, 1065, 1059, 1066, 1067, 1068, 1046, 1069, 1073, 1048, 1049, 1040, 1074, 1050, 1051, 1053, 1054, 1078, 1056, 1058, 1060, 1061, 1055, 1059, 1075, 1079, 1080, 1081, 1055, 1064, 1082, 1083, 1065, 1059, 1066, 1067, 1068, 1085, 1069, 1073, 1087, 1075, 1087, 1074, 1089, 1090, 1091, 1093, 1078, 1094, 1092, 1095, 1096, 1097, 1098, 1075, 1079, 1080, 1081, 1092, 1099, 1082, 1083, 1100, 1101, 1102, 1103, 1104, 1085, 1105, 1107, 1087, 1075, 1087, 1108, 1089, 1090, 1091, 1093, 1109, 1094, 1092, 1095, 1096, 1097, 1098, 1110, 1111, 1112, 1113, 1092, 1099, 1115, 1117, 1100, 1101, 1102, 1103, 1104, 1118, 1105, 1107, 1119, 1120, 1122, 1108, 1124, 1125, 1126, 1127, 1109, 1128, 1129, 1130, 1131, 1133, 1136, 1110, 1111, 1112, 1113, 1138, 1139, 1115, 1117, 1140, 1141, 1142, 1144, 1146, 1118, 1125, 1124, 1119, 1120, 1122, 1147, 1124, 1125, 1126, 1127, 1148, 1128, 1129, 1130, 1131, 1133, 1136, 1149, 1150, 1151, 1153, 1138, 1139, 1154, 1155, 1140, 1141, 1142, 1144, 1146, 1156, 1158, 1160, 1162, 1164, 1165, 1147, 1166, 1167, 1170, 1171, 1148, 1172, 1173, 1174, 1175, 1177, 1178, 1149, 1150, 1151, 1153, 1179, 1180, 1154, 1155, 1181, 1182, 1183, 1184, 1185, 1156, 1158, 1160, 1162, 1164, 1165, 1186, 1166, 1167, 1170, 1171, 1187, 1172, 1173, 1174, 1175, 1177, 1178, 1188, 1190, 1193, 1194, 1179, 1180, 1189, 1195, 1181, 1182, 1183, 1184, 1185, 1196, 1189, 1197, 1198, 1199, 1200, 1186, 1201, 1202, 1203, 1204, 1187, 1205, 1206, 1207, 1208, 1209, 1211, 1188, 1190, 1193, 1194, 1213, 1214, 1189, 1195, 1215, 1216, 1217, 1218, 1219, 1196, 1189, 1197, 1198, 1199, 1200, 1220, 1201, 1202, 1203, 1204, 1221, 1205, 1206, 1207, 1208, 1209, 1211, 1222, 1223, 1224, 1225, 1213, 1214, 1226, 1227, 1215, 1216, 1217, 1218, 1219, 1230, 1232, 1233, 1234, 1235, 1236, 1220, 1237, 1238, 1239, 1244, 1221, 1245, 1246, 1247, 1248, 1249, 1250, 1222, 1223, 1224, 1225, 1251, 1252, 1226, 1227, 1253, 1254, 1255, 1257, 1259, 1230, 1232, 1233, 1234, 1235, 1236, 1260, 1237, 1238, 1239, 1244, 1261, 1245, 1246, 1247, 1248, 1249, 1250, 1262, 1263, 1264, 1265, 1251, 1252, 1266, 1267, 1253, 1254, 1255, 1257, 1259, 1268, 1271, 1274, 1275, 1276, 1277, 1260, 1278, 1279, 1280, 1267, 1261, 1281, 1282, 1283, 1284, 1285, 1286, 1262, 1263, 1264, 1265, 1287, 1288, 1266, 1267, 1289, 1292, 1294, 1295, 1297, 1268, 1271, 1274, 1275, 1276, 1277, 1298, 1278, 1279, 1280, 1267, 1299, 1281, 1282, 1283, 1284, 1285, 1286, 1300, 1301, 1302, 1303, 1287, 1288, 1305, 1308, 1289, 1292, 1294, 1295, 1297, 1309, 1310, 1311, 1312, 1313, 1315, 1298, 1316, 1317, 1318, 1319, 1299, 1320, 1322, 1323, 1324, 1325, 1326, 1300, 1301, 1302, 1303, 1331, 1328, 1305, 1308, 1329, 1332, 1333, 1334, 1335, 1309, 1310, 1311, 1312, 1313, 1315, 1336, 1316, 1317, 1318, 1319, 1337, 1320, 1322, 1323, 1324, 1325, 1326, 1328, 1329, 1338, 1339, 1331, 1328, 1340, 1342, 1329, 1332, 1333, 1334, 1335, 1343, 1344, 1345, 1347, 1348, 1350, 1336, 1352, 1353, 1354, 1356, 1337, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1338, 1339, 1366, 1367, 1340, 1342, 1369, 1370, 1371, 1372, 1373, 1343, 1344, 1345, 1347, 1348, 1350, 1375, 1352, 1353, 1354, 1356, 1376, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1377, 1378, 1366, 1367, 1379, 1380, 1369, 1370, 1371, 1372, 1373, 1381, 1382, 1383, 1385, 1386, 1388, 1375, 1389, 1390, 1391, 1392, 1376, 1393, 1394, 1395, 1397, 1398, 1399, 1400, 1401, 1377, 1378, 1403, 1404, 1379, 1380, 1405, 1406, 1407, 1408, 1409, 1381, 1382, 1383, 1385, 1386, 1388, 1411, 1389, 1390, 1391, 1392, 1412, 1393, 1394, 1395, 1397, 1398, 1399, 1400, 1401, 1413, 1414, 1403, 1404, 1415, 1419, 1405, 1406, 1407, 1408, 1409, 1417, 1421, 1417, 1420, 1423, 1425, 1411, 1426, 0, 1428, 1430, 1412, 0, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1413, 1414, 1438, 1420, 1415, 1419, 1422, 1422, 1439, 1440, 1441, 1417, 1421, 1417, 1420, 1423, 1425, 1422, 1426, 1422, 1428, 1430, 1442, 1422, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1443, 1444, 1438, 1420, 1445, 1446, 1422, 1422, 1439, 1440, 1441, 1447, 1448, 1449, 1450, 1451, 1452, 1422, 1452, 1422, 1453, 1454, 1442, 1422, 1455, 1456, 1458, 1459, 1460, 1461, 1462, 1443, 1444, 1465, 1466, 1445, 1446, 1467, 1468, 1469, 1470, 1471, 1447, 1448, 1449, 1450, 1451, 1452, 1472, 1452, 1473, 1453, 1454, 1474, 1475, 1455, 1456, 1458, 1459, 1460, 1461, 1462, 1477, 1479, 1465, 1466, 1481, 1482, 1467, 1468, 1469, 1470, 1471, 1476, 1476, 1484, 1485, 1486, 1488, 1472, 1489, 1473, 1490, 1491, 1474, 1475, 1476, 1492, 1493, 1498, 1476, 1495, 1499, 1477, 1479, 1496, 1500, 1481, 1482, 1501, 1502, 1504, 1505, 1506, 1476, 1476, 1484, 1485, 1486, 1488, 1507, 1489, 1496, 1490, 1491, 1495, 1508, 1476, 1492, 1493, 1498, 1476, 1495, 1499, 1509, 1510, 1496, 1500, 1511, 1512, 1501, 1502, 1504, 1505, 1506, 1513, 1514, 1516, 1517, 1518, 1519, 1507, 1520, 1521, 1523, 1524, 1525, 1508, 1526, 1527, 1529, 1530, 1531, 1532, 1534, 1509, 1510, 1535, 1536, 1511, 1512, 1537, 1538, 1539, 1540, 1541, 1513, 1514, 1516, 1517, 1518, 1519, 1542, 1520, 1521, 1523, 1524, 1525, 1543, 1526, 1527, 1529, 1530, 1531, 1532, 1534, 1544, 1545, 1535, 1536, 1546, 1547, 1537, 1538, 1539, 1540, 1541, 1548, 1549, 1550, 1551, 1552, 1553, 1542, 1554, 1558, 1559, 1560, 1561, 1543, 1562, 1563, 1564, 1565, 1566, 1569, 1570, 1544, 1545, 1571, 1572, 1546, 1547, 1573, 1574, 1575, 1576, 1577, 1548, 1549, 1550, 1551, 1552, 1553, 1579, 1554, 1558, 1559, 1560, 1561, 1578, 1562, 1563, 1564, 1565, 1566, 1569, 1570, 1578, 1582, 1571, 1572, 1580, 1583, 1573, 1574, 1575, 1576, 1577, 1585, 1586, 1588, 1589, 1590, 1592, 1579, 1593, 1594, 1580, 1595, 1597, 1578, 1599, 1600, 1602, 1603, 1604, 1605, 1606, 1578, 1582, 1607, 1608, 1580, 1583, 1609, 1611, 1613, 1614, 1615, 1585, 1586, 1588, 1589, 1590, 1592, 1619, 1593, 1594, 1580, 1595, 1597, 1620, 1599, 1600, 1602, 1603, 1604, 1605, 1606, 1621, 1622, 1607, 1608, 1623, 1625, 1609, 1611, 1613, 1614, 1615, 1626, 1628, 1631, 1635, 1636, 1637, 1619, 1639, 1640, 1642, 1643, 1644, 1620, 1645, 1647, 1649, 1651, 1653, 1654, 1656, 1621, 1622, 1657, 1659, 1623, 1625, 1642, 1643, 1660, 1662, 1663, 1626, 1628, 1631, 1635, 1636, 1637, 1664, 1639, 1640, 1642, 1643, 1644, 1666, 1645, 1647, 1649, 1651, 1653, 1654, 1656, 1669, 1671, 1657, 1659, 1674, 1675, 1676, 1677, 1660, 1662, 1663, 1678, 1680, 1681, 1682, 1683, 1684, 1664, 1685, 1686, 1687, 1688, 1689, 1666, 1690, 1692, 1693, 1694, 1695, 1696, 1697, 1669, 1671, 1698, 1699, 1674, 1675, 1676, 1677, 1700, 1702, 1703, 1678, 1680, 1681, 1682, 1683, 1684, 1704, 1685, 1686, 1687, 1688, 1689, 1705, 1690, 1692, 1693, 1694, 1695, 1696, 1697, 1706, 1707, 1698, 1699, 1708, 1709, 1710, 1711, 1700, 1702, 1703, 1712, 1713, 1714, 1715, 1716, 1717, 1704, 1718, 1719, 1720, 1721, 1722, 1705, 1723, 1724, 1725, 1728, 1729, 1730, 1731, 1706, 1707, 1732, 1733, 1708, 1709, 1710, 1711, 1734, 1738, 1740, 1712, 1713, 1714, 1715, 1716, 1717, 1742, 1718, 1719, 1720, 1721, 1722, 1744, 1723, 1724, 1725, 1728, 1729, 1730, 1731, 1745, 1746, 1732, 1733, 1747, 1749, 1751, 1752, 1734, 1738, 1740, 1753, 1754, 1755, 1756, 1757, 1759, 1742, 1760, 1761, 1763, 1764, 1768, 1744, 1769, 1770, 1773, 1774, 1760, 1776, 1778, 1745, 1746, 1759, 1782, 1747, 1749, 1751, 1752, 1783, 1784, 1785, 1753, 1754, 1755, 1756, 1757, 1759, 1786, 1760, 1761, 1763, 1764, 1768, 1787, 1769, 1770, 1773, 1774, 1790, 1776, 1778, 1791, 1792, 1793, 1782, 1794, 1795, 1796, 1797, 1783, 1784, 1785, 1799, 1800, 1801, 1802, 1803, 1804, 1786, 1805, 1806, 1807, 1809, 1810, 1787, 1811, 1812, 1813, 1814, 1790, 1815, 1816, 1791, 1792, 1793, 1817, 1794, 1795, 1796, 1797, 1818, 1819, 1820, 1799, 1800, 1801, 1802, 1803, 1804, 1821, 1805, 1806, 1807, 1809, 1810, 1823, 1811, 1812, 1813, 1814, 1826, 1815, 1816, 1828, 1832, 1834, 1817, 1835, 1836, 1839, 1837, 1818, 1819, 1820, 1843, 1849, 1852, 1850, 1853, 1854, 1821, 1856, 1857, 1858, 1859, 1849, 1823, 1837, 1860, 1862, 1863, 1826, 1864, 1865, 1828, 1832, 1834, 1850, 1835, 1836, 1839, 1837, 1866, 1871, 1872, 1843, 1849, 1852, 1850, 1853, 1854, 1873, 1856, 1857, 1858, 1859, 1876, 1879, 1837, 1860, 1862, 1863, 1880, 1864, 1865, 1882, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1866, 1871, 1872, 1891, 1892, 1894, 1897, 1899, 1901, 1873, 1902, 1903, 1904, 1906, 1876, 1879, 1909, 1910, 1912, 1909, 1880, 1913, 1915, 1882, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1908, 1917, 1918, 1891, 1892, 1894, 1897, 1899, 1901, 1919, 1902, 1903, 1904, 1906, 1920, 1922, 1909, 1910, 1912, 1923, 1908, 1913, 1915, 1924, 1926, 1927, 1929, 1930, 1934, 1936, 1937, 1908, 1917, 1918, 1938, 1939, 1940, 1941, 1942, 1943, 1919, 1944, 1946, 1949, 1947, 1920, 1922, 1947, 1950, 1954, 1923, 1955, 1948, 1957, 1924, 1926, 1927, 1929, 1930, 1934, 1936, 1937, 1958, 1960, 1964, 1938, 1939, 1940, 1941, 1942, 1943, 1965, 1944, 1946, 1949, 1947, 1948, 1966, 1967, 1950, 1954, 1969, 1955, 1948, 1957, 1970, 1971, 1972, 1973, 1975, 1977, 1979, 1980, 1958, 1960, 1964, 1981, 1982, 1984, 1987, 1990, 1991, 1965, 1996, 1997, 2000, 2001, 2002, 1966, 1967, 2005, 2006, 1969, 1975, 2007, 2008, 1970, 1971, 1972, 1973, 1975, 1977, 1979, 1980, 2010, 2011, 2012, 1981, 1982, 1984, 1987, 1990, 1991, 2013, 1996, 1997, 2000, 2001, 2002, 2016, 2017, 2005, 2006, 2018, 2020, 2007, 2008, 2021, 0, 0, 0, 0, 0, 0, 0, 2010, 2011, 2012, 0, 0, 0, 0, 0, 0, 2013, 0, 0, 0, 0, 0, 2016, 2017, 0, 0, 2018, 2020, 0, 0, 2021, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2025, 2025, 2025, 2025, 2025, 2025, 2025, 2025, 2025, 2025, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2027, 2028, 0, 2028, 2028, 2028, 2028, 2028, 2028, 2028, 2028, 2029, 0, 2029, 2029, 2029, 2029, 2029, 2029, 2029, 2029, 2030, 2030, 2031, 2031, 2031, 2031, 2031, 2031, 2031, 2031, 2031, 2031, 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2032, 2033, 0, 2033, 2033, 2033, 2033, 2033, 2033, 2033, 2033, 2034, 0, 2034, 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2035, 2036, 2036, 2036, 2036, 2036, 2036, 2036, 2036, 2036, 2036, 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2038, 2038, 2038, 2038, 2038, 2038, 2038, 2038, 2038, 2038, 2039, 2039, 2039, 0, 0, 2039, 2039, 2039, 0, 2039, 2040, 0, 2040, 2040, 2040, 0, 2040, 2040, 2040, 2040, 2041, 2041, 2041, 2041, 2041, 2041, 2041, 2041, 2041, 2041, 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2042, 2043, 2043, 2043, 2043, 2043, 2043, 2043, 2043, 2043, 2043, 2044, 0, 0, 0, 2044, 2044, 0, 2044, 2045, 2045, 2045, 0, 2045, 2045, 2045, 2045, 2045, 2045, 2046, 2046, 2046, 2046, 0, 2046, 2046, 2046, 2046, 2046, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2049, 0, 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2049, 2050, 0, 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2050, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int msyy_flex_debug; int msyy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *msyytext; #line 1 "maplexer.l" #line 4 "maplexer.l" /* ** READ ME FIRST! ** ** When this file is altered, it is necessary to do "make lexer". Due to ** problems detailed in #2310 the lexer is no longer automatically rebuilt ** when maplexer.l is altered. */ #define YY_NO_INPUT /* C declarations */ #include #include #include #include #include #include "mapserver.h" #include "maperror.h" #include "mapfile.h" #include "maptime.h" #include "mapsymbol.h" #include "mapparser.h" #include "mapprimitive.h" /* msyylineno is required for flex 2.5.4 and older, but is already defined by * flex 2.5.31 (bug 975). * Unfortunately there is no clean way to differenciate the two versions, * so we use the symbol YY_CURRENT_BUFFER_LVALUE to base our test since it * was not present in 2.5.4 and is present in 2.5.31. Hopefully that won't * put us in trouble with other versions. If that happens then we can * switch to using autoconf to detect the version. */ #ifndef YY_CURRENT_BUFFER_LVALUE int msyylineno = 1; #endif #define YY_NO_INPUT int msyysource=MS_STRING_TOKENS; double msyynumber; int msyystate=MS_TOKENIZE_DEFAULT; char *msyystring=NULL; char *msyybasepath=NULL; char *msyystring_buffer_ptr; int msyystring_buffer_size = 0; int msyystring_size; char msyystring_begin; char *msyystring_buffer = NULL; int msyystring_icase = MS_FALSE; int msyystring_return_state; int msyystring_begin_state; int msyystring_size_tmp; int msyyreturncomments = 0; #define MS_LEXER_STRING_REALLOC(string, string_size, max_size, string_ptr) \ if (string_size >= max_size) { \ msyystring_size_tmp = max_size; \ max_size = ((max_size*2) > string_size) ? max_size*2 : string_size+1; \ string = (char *) msSmallRealloc(string, sizeof(char *) * max_size); \ string_ptr = string; \ string_ptr += msyystring_size_tmp; \ } #define MS_LEXER_RETURN_TOKEN(token) \ MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), \ msyystring_buffer_size, msyystring_buffer_ptr); \ strcpy(msyystring_buffer, msyytext); \ return(token); #define MAX_INCLUDE_DEPTH 5 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_lineno[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; char path[MS_MAXPATHLEN]; #line 2332 "/home/even/mapserver/mapserver/maplexer.c" #define INITIAL 0 #define URL_VARIABLE 1 #define URL_STRING 2 #define EXPRESSION_STRING 3 #define INCLUDE 4 #define MSSTRING 5 #define MULTILINE_COMMENT 6 #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int msyylex_destroy (void ); int msyyget_debug (void ); void msyyset_debug (int debug_flag ); YY_EXTRA_TYPE msyyget_extra (void ); void msyyset_extra (YY_EXTRA_TYPE user_defined ); FILE *msyyget_in (void ); void msyyset_in (FILE * _in_str ); FILE *msyyget_out (void ); void msyyset_out (FILE * _out_str ); yy_size_t msyyget_leng (void ); char *msyyget_text (void ); int msyyget_lineno (void ); void msyyset_lineno (int _line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int msyywrap (void ); #else extern int msyywrap (void ); #endif #endif #ifndef YY_NO_UNPUT static void yyunput (int c,char *buf_ptr ); #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( msyytext, msyyleng, 1, msyyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( msyyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( msyyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, msyyin))==0 && ferror(msyyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(msyyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int msyylex (void); #define YY_DECL int msyylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after msyytext and msyyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! msyyin ) msyyin = stdin; if ( ! msyyout ) msyyout = stdout; if ( ! YY_CURRENT_BUFFER ) { msyyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = msyy_create_buffer(msyyin,YY_BUF_SIZE ); } msyy_load_buffer_state( ); } { #line 91 "maplexer.l" if (msyystring_buffer == NULL) { msyystring_buffer_size = 256; msyystring_buffer = (char*) msSmallMalloc(sizeof(char) * msyystring_buffer_size); } msyystring_buffer[0] = '\0'; switch(msyystate) { case(MS_TOKENIZE_DEFAULT): break; case(MS_TOKENIZE_FILE): BEGIN(INITIAL); msyystring_begin_state = INITIAL; msyysource=MS_FILE_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyystring=NULL; msyyreturncomments=0; include_stack_ptr=0; return(0); break; case(MS_TOKENIZE_STRING): BEGIN(INITIAL); msyystring_begin_state = INITIAL; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_STRING_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyin=NULL; msyyreturncomments=0; include_stack_ptr=0; return(0); break; case(MS_TOKENIZE_URL_VARIABLE): BEGIN(URL_VARIABLE); msyystring_begin_state = URL_VARIABLE; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_URL_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyreturncomments=0; (void) yyunput; /* just to avoid warning about it being unrefed */ break; case(MS_TOKENIZE_URL_STRING): BEGIN(URL_STRING); msyystring_begin_state = URL_STRING; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_URL_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyin=NULL; msyyreturncomments=0; return(0); break; case(MS_TOKENIZE_EXPRESSION): BEGIN(EXPRESSION_STRING); msyystring_begin_state = EXPRESSION_STRING; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyystate=MS_TOKENIZE_DEFAULT; msyyreturncomments=0; break; case(99): BEGIN(INITIAL); /* may not need this one */ msyystring_begin_state = INITIAL; msyy_delete_buffer(YY_CURRENT_BUFFER); msyystate=MS_TOKENIZE_DEFAULT; msyystring=NULL; msyyreturncomments=0; return(0); break; default: break; } #line 2624 "/home/even/mapserver/mapserver/maplexer.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of msyytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 2024 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_current_state != 2023 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_find_action: yy_act = yy_accept[yy_current_state]; YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 166 "maplexer.l" ; YY_BREAK case 2: YY_RULE_SETUP #line 168 "maplexer.l" { if (msyyreturncomments) return(MS_COMMENT); } YY_BREAK case 3: YY_RULE_SETUP #line 170 "maplexer.l" { BEGIN(MULTILINE_COMMENT); } YY_BREAK case 4: YY_RULE_SETUP #line 171 "maplexer.l" { BEGIN(INITIAL); } YY_BREAK case 5: YY_RULE_SETUP #line 172 "maplexer.l" ; YY_BREAK case 6: YY_RULE_SETUP #line 173 "maplexer.l" ; YY_BREAK case 7: /* rule 7 can match eol */ YY_RULE_SETUP #line 174 "maplexer.l" { msyylineno++; } YY_BREAK case 8: YY_RULE_SETUP #line 176 "maplexer.l" ; YY_BREAK case 9: YY_RULE_SETUP #line 178 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_OR); } YY_BREAK case 10: YY_RULE_SETUP #line 179 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_AND); } YY_BREAK case 11: YY_RULE_SETUP #line 180 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_NOT); } YY_BREAK case 12: YY_RULE_SETUP #line 181 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_EQ); } YY_BREAK case 13: YY_RULE_SETUP #line 182 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_NE); } YY_BREAK case 14: YY_RULE_SETUP #line 183 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_GT); } YY_BREAK case 15: YY_RULE_SETUP #line 184 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_LT); } YY_BREAK case 16: YY_RULE_SETUP #line 185 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_GE); } YY_BREAK case 17: YY_RULE_SETUP #line 186 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_LE); } YY_BREAK case 18: YY_RULE_SETUP #line 187 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_RE); } YY_BREAK case 19: YY_RULE_SETUP #line 189 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IEQ); } YY_BREAK case 20: YY_RULE_SETUP #line 190 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IRE); } YY_BREAK case 21: YY_RULE_SETUP #line 192 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IN); /* was IN */ } YY_BREAK case 22: YY_RULE_SETUP #line 194 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_AREA); } YY_BREAK case 23: YY_RULE_SETUP #line 195 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_LENGTH); } YY_BREAK case 24: YY_RULE_SETUP #line 196 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_TOSTRING); } YY_BREAK case 25: YY_RULE_SETUP #line 197 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_COMMIFY); } YY_BREAK case 26: YY_RULE_SETUP #line 198 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_ROUND); } YY_BREAK case 27: YY_RULE_SETUP #line 199 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_UPPER); } YY_BREAK case 28: YY_RULE_SETUP #line 200 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_LOWER); } YY_BREAK case 29: YY_RULE_SETUP #line 201 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_INITCAP); } YY_BREAK case 30: YY_RULE_SETUP #line 202 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_FIRSTCAP); } YY_BREAK case 31: YY_RULE_SETUP #line 204 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_BUFFER); } YY_BREAK case 32: YY_RULE_SETUP #line 205 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_DIFFERENCE); } YY_BREAK case 33: YY_RULE_SETUP #line 206 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SIMPLIFY); } YY_BREAK case 34: YY_RULE_SETUP #line 207 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SIMPLIFYPT); } YY_BREAK case 35: YY_RULE_SETUP #line 208 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_GENERALIZE); } YY_BREAK case 36: YY_RULE_SETUP #line 209 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SMOOTHSIA); } YY_BREAK case 37: YY_RULE_SETUP #line 210 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_JAVASCRIPT); } YY_BREAK case 38: YY_RULE_SETUP #line 212 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_INTERSECTS); } YY_BREAK case 39: YY_RULE_SETUP #line 213 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_DISJOINT); } YY_BREAK case 40: YY_RULE_SETUP #line 214 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_TOUCHES); } YY_BREAK case 41: YY_RULE_SETUP #line 215 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_OVERLAPS); } YY_BREAK case 42: YY_RULE_SETUP #line 216 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_CROSSES); } YY_BREAK case 43: YY_RULE_SETUP #line 217 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_WITHIN); } YY_BREAK case 44: YY_RULE_SETUP #line 218 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_CONTAINS); } YY_BREAK case 45: YY_RULE_SETUP #line 219 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_EQUALS); } YY_BREAK case 46: YY_RULE_SETUP #line 220 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_BEYOND); } YY_BREAK case 47: YY_RULE_SETUP #line 221 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_DWITHIN); } YY_BREAK case 48: YY_RULE_SETUP #line 223 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_FROMTEXT); } YY_BREAK case 49: YY_RULE_SETUP #line 225 "maplexer.l" { msyynumber=MS_TRUE; return(MS_TOKEN_LITERAL_BOOLEAN); } YY_BREAK case 50: YY_RULE_SETUP #line 226 "maplexer.l" { msyynumber=MS_FALSE; return(MS_TOKEN_LITERAL_BOOLEAN); } YY_BREAK case 51: YY_RULE_SETUP #line 228 "maplexer.l" { MS_LEXER_RETURN_TOKEN(COLORRANGE); } YY_BREAK case 52: YY_RULE_SETUP #line 229 "maplexer.l" { MS_LEXER_RETURN_TOKEN(DATARANGE); } YY_BREAK case 53: YY_RULE_SETUP #line 230 "maplexer.l" { MS_LEXER_RETURN_TOKEN(RANGEITEM); } YY_BREAK case 54: YY_RULE_SETUP #line 232 "maplexer.l" { MS_LEXER_RETURN_TOKEN(ALIGN); } YY_BREAK case 55: YY_RULE_SETUP #line 233 "maplexer.l" { MS_LEXER_RETURN_TOKEN(ANCHORPOINT); } YY_BREAK case 56: YY_RULE_SETUP #line 234 "maplexer.l" { MS_LEXER_RETURN_TOKEN(ANGLE); } YY_BREAK case 57: YY_RULE_SETUP #line 235 "maplexer.l" { MS_LEXER_RETURN_TOKEN(ANTIALIAS); } YY_BREAK case 58: YY_RULE_SETUP #line 236 "maplexer.l" { MS_LEXER_RETURN_TOKEN(BACKGROUNDCOLOR); } YY_BREAK case 59: YY_RULE_SETUP #line 237 "maplexer.l" { MS_LEXER_RETURN_TOKEN(BANDSITEM); } YY_BREAK case 60: YY_RULE_SETUP #line 238 "maplexer.l" { MS_LEXER_RETURN_TOKEN(BINDVALS); } YY_BREAK case 61: YY_RULE_SETUP #line 239 "maplexer.l" { MS_LEXER_RETURN_TOKEN(BOM); } YY_BREAK case 62: YY_RULE_SETUP #line 240 "maplexer.l" { MS_LEXER_RETURN_TOKEN(BROWSEFORMAT); } YY_BREAK case 63: YY_RULE_SETUP #line 241 "maplexer.l" { MS_LEXER_RETURN_TOKEN(BUFFER); } YY_BREAK case 64: YY_RULE_SETUP #line 242 "maplexer.l" { MS_LEXER_RETURN_TOKEN(CHARACTER); } YY_BREAK case 65: YY_RULE_SETUP #line 243 "maplexer.l" { MS_LEXER_RETURN_TOKEN(CLASS); } YY_BREAK case 66: YY_RULE_SETUP #line 244 "maplexer.l" { MS_LEXER_RETURN_TOKEN(CLASSITEM); } YY_BREAK case 67: YY_RULE_SETUP #line 245 "maplexer.l" { MS_LEXER_RETURN_TOKEN(CLASSGROUP); } YY_BREAK case 68: YY_RULE_SETUP #line 246 "maplexer.l" { MS_LEXER_RETURN_TOKEN(CLUSTER); } YY_BREAK case 69: YY_RULE_SETUP #line 247 "maplexer.l" { MS_LEXER_RETURN_TOKEN(COLOR); } YY_BREAK case 70: YY_RULE_SETUP #line 248 "maplexer.l" { MS_LEXER_RETURN_TOKEN(COMPFILTER); } YY_BREAK case 71: YY_RULE_SETUP #line 249 "maplexer.l" { MS_LEXER_RETURN_TOKEN(COMPOSITE); } YY_BREAK case 72: YY_RULE_SETUP #line 250 "maplexer.l" { MS_LEXER_RETURN_TOKEN(COMPOP); } YY_BREAK case 73: YY_RULE_SETUP #line 251 "maplexer.l" { MS_LEXER_RETURN_TOKEN(CONFIG); } YY_BREAK case 74: YY_RULE_SETUP #line 252 "maplexer.l" { MS_LEXER_RETURN_TOKEN(CONNECTION); } YY_BREAK case 75: YY_RULE_SETUP #line 253 "maplexer.l" { MS_LEXER_RETURN_TOKEN(CONNECTIONTYPE); } YY_BREAK case 76: YY_RULE_SETUP #line 254 "maplexer.l" { MS_LEXER_RETURN_TOKEN(DATA); } YY_BREAK case 77: YY_RULE_SETUP #line 255 "maplexer.l" { MS_LEXER_RETURN_TOKEN(DATAPATTERN); } YY_BREAK case 78: YY_RULE_SETUP #line 256 "maplexer.l" { MS_LEXER_RETURN_TOKEN(DEBUG); } YY_BREAK case 79: YY_RULE_SETUP #line 257 "maplexer.l" { MS_LEXER_RETURN_TOKEN(DRIVER); } YY_BREAK case 80: YY_RULE_SETUP #line 258 "maplexer.l" { MS_LEXER_RETURN_TOKEN(DUMP); } YY_BREAK case 81: YY_RULE_SETUP #line 259 "maplexer.l" { MS_LEXER_RETURN_TOKEN(EMPTY); } YY_BREAK case 82: YY_RULE_SETUP #line 260 "maplexer.l" { MS_LEXER_RETURN_TOKEN(ENCODING); } YY_BREAK case 83: YY_RULE_SETUP #line 261 "maplexer.l" { MS_LEXER_RETURN_TOKEN(END); } YY_BREAK case 84: YY_RULE_SETUP #line 262 "maplexer.l" { MS_LEXER_RETURN_TOKEN(ERROR); } YY_BREAK case 85: YY_RULE_SETUP #line 263 "maplexer.l" { MS_LEXER_RETURN_TOKEN(EXPRESSION); } YY_BREAK case 86: YY_RULE_SETUP #line 264 "maplexer.l" { MS_LEXER_RETURN_TOKEN(EXTENT); } YY_BREAK case 87: YY_RULE_SETUP #line 265 "maplexer.l" { MS_LEXER_RETURN_TOKEN(EXTENSION); } YY_BREAK case 88: YY_RULE_SETUP #line 266 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FEATURE); } YY_BREAK case 89: YY_RULE_SETUP #line 267 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FILLED); } YY_BREAK case 90: YY_RULE_SETUP #line 268 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FILTER); } YY_BREAK case 91: YY_RULE_SETUP #line 269 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FILTERITEM); } YY_BREAK case 92: YY_RULE_SETUP #line 270 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FOOTER); } YY_BREAK case 93: YY_RULE_SETUP #line 271 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FONT); } YY_BREAK case 94: YY_RULE_SETUP #line 272 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FONTSET); } YY_BREAK case 95: YY_RULE_SETUP #line 273 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FORCE); } YY_BREAK case 96: YY_RULE_SETUP #line 274 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FORMATOPTION); } YY_BREAK case 97: YY_RULE_SETUP #line 275 "maplexer.l" { MS_LEXER_RETURN_TOKEN(FROM); } YY_BREAK case 98: YY_RULE_SETUP #line 276 "maplexer.l" { MS_LEXER_RETURN_TOKEN(GAP); } YY_BREAK case 99: YY_RULE_SETUP #line 277 "maplexer.l" { MS_LEXER_RETURN_TOKEN(GEOMTRANSFORM); } YY_BREAK case 100: YY_RULE_SETUP #line 278 "maplexer.l" { MS_LEXER_RETURN_TOKEN(GRID); } YY_BREAK case 101: YY_RULE_SETUP #line 279 "maplexer.l" { MS_LEXER_RETURN_TOKEN(GRIDSTEP); } YY_BREAK case 102: YY_RULE_SETUP #line 280 "maplexer.l" { MS_LEXER_RETURN_TOKEN(GRATICULE); } YY_BREAK case 103: YY_RULE_SETUP #line 281 "maplexer.l" { MS_LEXER_RETURN_TOKEN(GROUP); } YY_BREAK case 104: YY_RULE_SETUP #line 282 "maplexer.l" { MS_LEXER_RETURN_TOKEN(HEADER); } YY_BREAK case 105: YY_RULE_SETUP #line 283 "maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGE); } YY_BREAK case 106: YY_RULE_SETUP #line 284 "maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGECOLOR); } YY_BREAK case 107: YY_RULE_SETUP #line 285 "maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGETYPE); } YY_BREAK case 108: YY_RULE_SETUP #line 286 "maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGEQUALITY); } YY_BREAK case 109: YY_RULE_SETUP #line 287 "maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGEMODE); } YY_BREAK case 110: YY_RULE_SETUP #line 288 "maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGEPATH); } YY_BREAK case 111: YY_RULE_SETUP #line 289 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TEMPPATH); } YY_BREAK case 112: YY_RULE_SETUP #line 290 "maplexer.l" { MS_LEXER_RETURN_TOKEN(IMAGEURL); } YY_BREAK case 113: YY_RULE_SETUP #line 291 "maplexer.l" { BEGIN(INCLUDE); } YY_BREAK case 114: YY_RULE_SETUP #line 292 "maplexer.l" { MS_LEXER_RETURN_TOKEN(INDEX); } YY_BREAK case 115: YY_RULE_SETUP #line 293 "maplexer.l" { MS_LEXER_RETURN_TOKEN(INITIALGAP); } YY_BREAK case 116: YY_RULE_SETUP #line 294 "maplexer.l" { MS_LEXER_RETURN_TOKEN(INTERLACE); } YY_BREAK case 117: YY_RULE_SETUP #line 295 "maplexer.l" { MS_LEXER_RETURN_TOKEN(INTERVALS); } YY_BREAK case 118: YY_RULE_SETUP #line 296 "maplexer.l" { MS_LEXER_RETURN_TOKEN(JOIN); } YY_BREAK case 119: YY_RULE_SETUP #line 297 "maplexer.l" { MS_LEXER_RETURN_TOKEN(KEYIMAGE); } YY_BREAK case 120: YY_RULE_SETUP #line 298 "maplexer.l" { MS_LEXER_RETURN_TOKEN(KEYSIZE); } YY_BREAK case 121: YY_RULE_SETUP #line 299 "maplexer.l" { MS_LEXER_RETURN_TOKEN(KEYSPACING); } YY_BREAK case 122: YY_RULE_SETUP #line 300 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABEL); } YY_BREAK case 123: YY_RULE_SETUP #line 301 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELCACHE); } YY_BREAK case 124: YY_RULE_SETUP #line 302 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELFORMAT); } YY_BREAK case 125: YY_RULE_SETUP #line 303 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELITEM); } YY_BREAK case 126: YY_RULE_SETUP #line 304 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELMAXSCALE); } YY_BREAK case 127: YY_RULE_SETUP #line 305 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELMAXSCALEDENOM); } YY_BREAK case 128: YY_RULE_SETUP #line 306 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELMINSCALE); } YY_BREAK case 129: YY_RULE_SETUP #line 307 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELMINSCALEDENOM); } YY_BREAK case 130: YY_RULE_SETUP #line 308 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LABELREQUIRES); } YY_BREAK case 131: YY_RULE_SETUP #line 309 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LATLON); } YY_BREAK case 132: YY_RULE_SETUP #line 310 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LAYER); } YY_BREAK case 133: YY_RULE_SETUP #line 311 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LEADER); } YY_BREAK case 134: YY_RULE_SETUP #line 312 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LEGEND); } YY_BREAK case 135: YY_RULE_SETUP #line 313 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LEGENDFORMAT); } YY_BREAK case 136: YY_RULE_SETUP #line 314 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LINECAP); } YY_BREAK case 137: YY_RULE_SETUP #line 315 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LINEJOIN); } YY_BREAK case 138: YY_RULE_SETUP #line 316 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LINEJOINMAXSIZE); } YY_BREAK case 139: YY_RULE_SETUP #line 317 "maplexer.l" { MS_LEXER_RETURN_TOKEN(LOG); } YY_BREAK case 140: YY_RULE_SETUP #line 318 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAP); } YY_BREAK case 141: YY_RULE_SETUP #line 319 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MARKER); } YY_BREAK case 142: YY_RULE_SETUP #line 320 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MARKERSIZE); } YY_BREAK case 143: YY_RULE_SETUP #line 321 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MASK); } YY_BREAK case 144: YY_RULE_SETUP #line 322 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXARCS); } YY_BREAK case 145: YY_RULE_SETUP #line 323 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXBOXSIZE); } YY_BREAK case 146: YY_RULE_SETUP #line 324 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXDISTANCE); } YY_BREAK case 147: YY_RULE_SETUP #line 325 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXFEATURES); } YY_BREAK case 148: YY_RULE_SETUP #line 326 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXINTERVAL); } YY_BREAK case 149: YY_RULE_SETUP #line 327 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXSCALE); } YY_BREAK case 150: YY_RULE_SETUP #line 328 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXSCALEDENOM); } YY_BREAK case 151: YY_RULE_SETUP #line 329 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXGEOWIDTH); } YY_BREAK case 152: YY_RULE_SETUP #line 330 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXLENGTH); } YY_BREAK case 153: YY_RULE_SETUP #line 331 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXSIZE); } YY_BREAK case 154: YY_RULE_SETUP #line 332 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXSUBDIVIDE); } YY_BREAK case 155: YY_RULE_SETUP #line 333 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXTEMPLATE); } YY_BREAK case 156: YY_RULE_SETUP #line 334 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXWIDTH); } YY_BREAK case 157: YY_RULE_SETUP #line 335 "maplexer.l" { MS_LEXER_RETURN_TOKEN(METADATA); } YY_BREAK case 158: YY_RULE_SETUP #line 336 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MIMETYPE); } YY_BREAK case 159: YY_RULE_SETUP #line 337 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINARCS); } YY_BREAK case 160: YY_RULE_SETUP #line 338 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINBOXSIZE); } YY_BREAK case 161: YY_RULE_SETUP #line 339 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINDISTANCE); } YY_BREAK case 162: YY_RULE_SETUP #line 340 "maplexer.l" { MS_LEXER_RETURN_TOKEN(REPEATDISTANCE); } YY_BREAK case 163: YY_RULE_SETUP #line 341 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MAXOVERLAPANGLE); } YY_BREAK case 164: YY_RULE_SETUP #line 342 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINFEATURESIZE); } YY_BREAK case 165: YY_RULE_SETUP #line 343 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MININTERVAL); } YY_BREAK case 166: YY_RULE_SETUP #line 344 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINSCALE); } YY_BREAK case 167: YY_RULE_SETUP #line 345 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINSCALEDENOM); } YY_BREAK case 168: YY_RULE_SETUP #line 346 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINGEOWIDTH); } YY_BREAK case 169: YY_RULE_SETUP #line 347 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINLENGTH); } YY_BREAK case 170: YY_RULE_SETUP #line 348 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINSIZE); } YY_BREAK case 171: YY_RULE_SETUP #line 349 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINSUBDIVIDE); } YY_BREAK case 172: YY_RULE_SETUP #line 350 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINTEMPLATE); } YY_BREAK case 173: YY_RULE_SETUP #line 351 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MINWIDTH); } YY_BREAK case 174: YY_RULE_SETUP #line 352 "maplexer.l" { MS_LEXER_RETURN_TOKEN(NAME); } YY_BREAK case 175: YY_RULE_SETUP #line 353 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OFFSET); } YY_BREAK case 176: YY_RULE_SETUP #line 354 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OFFSITE); } YY_BREAK case 177: YY_RULE_SETUP #line 355 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OPACITY); } YY_BREAK case 178: YY_RULE_SETUP #line 356 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OUTLINECOLOR); } YY_BREAK case 179: YY_RULE_SETUP #line 357 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OUTLINEWIDTH); } YY_BREAK case 180: YY_RULE_SETUP #line 358 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OUTPUTFORMAT); } YY_BREAK case 181: YY_RULE_SETUP #line 359 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYBACKGROUNDCOLOR); } YY_BREAK case 182: YY_RULE_SETUP #line 360 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYCOLOR); } YY_BREAK case 183: YY_RULE_SETUP #line 361 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYMAXSIZE); } YY_BREAK case 184: YY_RULE_SETUP #line 362 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYMINSIZE); } YY_BREAK case 185: YY_RULE_SETUP #line 363 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYOUTLINECOLOR); } YY_BREAK case 186: YY_RULE_SETUP #line 364 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYSIZE); } YY_BREAK case 187: YY_RULE_SETUP #line 365 "maplexer.l" { MS_LEXER_RETURN_TOKEN(OVERLAYSYMBOL); } YY_BREAK case 188: YY_RULE_SETUP #line 366 "maplexer.l" { MS_LEXER_RETURN_TOKEN(PARTIALS); } YY_BREAK case 189: YY_RULE_SETUP #line 367 "maplexer.l" { MS_LEXER_RETURN_TOKEN(PATTERN); } YY_BREAK case 190: YY_RULE_SETUP #line 368 "maplexer.l" { MS_LEXER_RETURN_TOKEN(POINTS); } YY_BREAK case 191: YY_RULE_SETUP #line 369 "maplexer.l" { MS_LEXER_RETURN_TOKEN(ITEMS); } YY_BREAK case 192: YY_RULE_SETUP #line 370 "maplexer.l" { MS_LEXER_RETURN_TOKEN(POSITION); } YY_BREAK case 193: YY_RULE_SETUP #line 371 "maplexer.l" { MS_LEXER_RETURN_TOKEN(POSTLABELCACHE); } YY_BREAK case 194: YY_RULE_SETUP #line 372 "maplexer.l" { MS_LEXER_RETURN_TOKEN(PRIORITY); } YY_BREAK case 195: YY_RULE_SETUP #line 373 "maplexer.l" { MS_LEXER_RETURN_TOKEN(PROCESSING); } YY_BREAK case 196: YY_RULE_SETUP #line 374 "maplexer.l" { MS_LEXER_RETURN_TOKEN(PROJECTION); } YY_BREAK case 197: YY_RULE_SETUP #line 375 "maplexer.l" { MS_LEXER_RETURN_TOKEN(QUERYFORMAT); } YY_BREAK case 198: YY_RULE_SETUP #line 376 "maplexer.l" { MS_LEXER_RETURN_TOKEN(QUERYMAP); } YY_BREAK case 199: YY_RULE_SETUP #line 377 "maplexer.l" { MS_LEXER_RETURN_TOKEN(REFERENCE); } YY_BREAK case 200: YY_RULE_SETUP #line 378 "maplexer.l" { MS_LEXER_RETURN_TOKEN(REGION); } YY_BREAK case 201: YY_RULE_SETUP #line 379 "maplexer.l" { MS_LEXER_RETURN_TOKEN(RELATIVETO); } YY_BREAK case 202: YY_RULE_SETUP #line 380 "maplexer.l" { MS_LEXER_RETURN_TOKEN(REQUIRES); } YY_BREAK case 203: YY_RULE_SETUP #line 381 "maplexer.l" { MS_LEXER_RETURN_TOKEN(RESOLUTION); } YY_BREAK case 204: YY_RULE_SETUP #line 382 "maplexer.l" { MS_LEXER_RETURN_TOKEN(DEFRESOLUTION); } YY_BREAK case 205: YY_RULE_SETUP #line 383 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SCALE); } YY_BREAK case 206: YY_RULE_SETUP #line 384 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SCALEDENOM); } YY_BREAK case 207: YY_RULE_SETUP #line 385 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SCALEBAR); } YY_BREAK case 208: YY_RULE_SETUP #line 386 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SCALETOKEN); } YY_BREAK case 209: YY_RULE_SETUP #line 387 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SHADOWCOLOR); } YY_BREAK case 210: YY_RULE_SETUP #line 388 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SHADOWSIZE); } YY_BREAK case 211: YY_RULE_SETUP #line 389 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SHAPEPATH); } YY_BREAK case 212: YY_RULE_SETUP #line 390 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SIZE); } YY_BREAK case 213: YY_RULE_SETUP #line 391 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SIZEUNITS); } YY_BREAK case 214: YY_RULE_SETUP #line 392 "maplexer.l" { MS_LEXER_RETURN_TOKEN(STATUS); } YY_BREAK case 215: YY_RULE_SETUP #line 393 "maplexer.l" { MS_LEXER_RETURN_TOKEN(STYLE); } YY_BREAK case 216: YY_RULE_SETUP #line 394 "maplexer.l" { MS_LEXER_RETURN_TOKEN(STYLEITEM); } YY_BREAK case 217: YY_RULE_SETUP #line 395 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SYMBOL); } YY_BREAK case 218: YY_RULE_SETUP #line 396 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SYMBOLSCALE); } YY_BREAK case 219: YY_RULE_SETUP #line 397 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SYMBOLSCALEDENOM); } YY_BREAK case 220: YY_RULE_SETUP #line 398 "maplexer.l" { MS_LEXER_RETURN_TOKEN(SYMBOLSET); } YY_BREAK case 221: YY_RULE_SETUP #line 399 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TABLE); } YY_BREAK case 222: YY_RULE_SETUP #line 400 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TEMPLATE); } YY_BREAK case 223: YY_RULE_SETUP #line 401 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TEMPLATEPATTERN); } YY_BREAK case 224: YY_RULE_SETUP #line 402 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TEXT); } YY_BREAK case 225: YY_RULE_SETUP #line 403 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TILEINDEX); } YY_BREAK case 226: YY_RULE_SETUP #line 404 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TILEITEM); } YY_BREAK case 227: YY_RULE_SETUP #line 405 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TILESRS); } YY_BREAK case 228: YY_RULE_SETUP #line 406 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TITLE); } YY_BREAK case 229: YY_RULE_SETUP #line 407 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TO); } YY_BREAK case 230: YY_RULE_SETUP #line 408 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TOLERANCE); } YY_BREAK case 231: YY_RULE_SETUP #line 409 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TOLERANCEUNITS); } YY_BREAK case 232: YY_RULE_SETUP #line 410 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TRANSPARENCY); } YY_BREAK case 233: YY_RULE_SETUP #line 411 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TRANSPARENT); } YY_BREAK case 234: YY_RULE_SETUP #line 412 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TRANSFORM); } YY_BREAK case 235: YY_RULE_SETUP #line 413 "maplexer.l" { MS_LEXER_RETURN_TOKEN(TYPE); } YY_BREAK case 236: YY_RULE_SETUP #line 414 "maplexer.l" { MS_LEXER_RETURN_TOKEN(UNITS); } YY_BREAK case 237: YY_RULE_SETUP #line 415 "maplexer.l" { MS_LEXER_RETURN_TOKEN(UTFDATA); } YY_BREAK case 238: YY_RULE_SETUP #line 416 "maplexer.l" { MS_LEXER_RETURN_TOKEN(UTFITEM); } YY_BREAK case 239: YY_RULE_SETUP #line 417 "maplexer.l" { MS_LEXER_RETURN_TOKEN(VALIDATION); } YY_BREAK case 240: YY_RULE_SETUP #line 418 "maplexer.l" { MS_LEXER_RETURN_TOKEN(VALUES); } YY_BREAK case 241: YY_RULE_SETUP #line 419 "maplexer.l" { MS_LEXER_RETURN_TOKEN(WEB); } YY_BREAK case 242: YY_RULE_SETUP #line 420 "maplexer.l" { MS_LEXER_RETURN_TOKEN(WIDTH); } YY_BREAK case 243: YY_RULE_SETUP #line 421 "maplexer.l" { MS_LEXER_RETURN_TOKEN(WKT); } YY_BREAK case 244: YY_RULE_SETUP #line 422 "maplexer.l" { MS_LEXER_RETURN_TOKEN(WRAP); } YY_BREAK case 245: YY_RULE_SETUP #line 424 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_ANNOTATION); } YY_BREAK case 246: YY_RULE_SETUP #line 425 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_AUTO); } YY_BREAK case 247: YY_RULE_SETUP #line 426 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_AUTO2); } YY_BREAK case 248: YY_RULE_SETUP #line 427 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_BEVEL); } YY_BREAK case 249: YY_RULE_SETUP #line 428 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_BITMAP); } YY_BREAK case 250: YY_RULE_SETUP #line 429 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_BUTT); } YY_BREAK case 251: YY_RULE_SETUP #line 430 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CC); } YY_BREAK case 252: YY_RULE_SETUP #line 431 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ALIGN_CENTER); } YY_BREAK case 253: YY_RULE_SETUP #line 432 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_CHART); } YY_BREAK case 254: YY_RULE_SETUP #line 433 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_CIRCLE); } YY_BREAK case 255: YY_RULE_SETUP #line 434 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CL); } YY_BREAK case 256: YY_RULE_SETUP #line 435 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CR); } YY_BREAK case 257: YY_RULE_SETUP #line 436 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DB_CSV); } YY_BREAK case 258: YY_RULE_SETUP #line 437 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DB_POSTGRES); } YY_BREAK case 259: YY_RULE_SETUP #line 438 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DB_MYSQL); } YY_BREAK case 260: YY_RULE_SETUP #line 439 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DEFAULT); } YY_BREAK case 261: YY_RULE_SETUP #line 440 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_DD); } YY_BREAK case 262: YY_RULE_SETUP #line 441 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_ELLIPSE); } YY_BREAK case 263: YY_RULE_SETUP #line 442 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_EMBED); } YY_BREAK case 264: YY_RULE_SETUP #line 443 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_FALSE); } YY_BREAK case 265: YY_RULE_SETUP #line 444 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_FEET); } YY_BREAK case 266: YY_RULE_SETUP #line 445 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_FOLLOW); } YY_BREAK case 267: YY_RULE_SETUP #line 446 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_GIANT); } YY_BREAK case 268: YY_RULE_SETUP #line 447 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_HATCH); } YY_BREAK case 269: YY_RULE_SETUP #line 448 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_KERNELDENSITY); } YY_BREAK case 270: YY_RULE_SETUP #line 449 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_HILITE); } YY_BREAK case 271: YY_RULE_SETUP #line 450 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_INCHES); } YY_BREAK case 272: YY_RULE_SETUP #line 451 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_KILOMETERS); } YY_BREAK case 273: YY_RULE_SETUP #line 452 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LARGE); } YY_BREAK case 274: YY_RULE_SETUP #line 453 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LC); } YY_BREAK case 275: YY_RULE_SETUP #line 454 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ALIGN_LEFT); } YY_BREAK case 276: YY_RULE_SETUP #line 455 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_LINE); } YY_BREAK case 277: YY_RULE_SETUP #line 456 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LL); } YY_BREAK case 278: YY_RULE_SETUP #line 457 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LR); } YY_BREAK case 279: YY_RULE_SETUP #line 458 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_MEDIUM); } YY_BREAK case 280: YY_RULE_SETUP #line 459 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_METERS); } YY_BREAK case 281: YY_RULE_SETUP #line 460 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_NAUTICALMILES); } YY_BREAK case 282: YY_RULE_SETUP #line 461 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_MILES); } YY_BREAK case 283: YY_RULE_SETUP #line 462 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_MITER); } YY_BREAK case 284: YY_RULE_SETUP #line 463 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_MULTIPLE); } YY_BREAK case 285: YY_RULE_SETUP #line 464 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_NONE); } YY_BREAK case 286: YY_RULE_SETUP #line 465 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_NORMAL); } YY_BREAK case 287: YY_RULE_SETUP #line 466 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_OFF); } YY_BREAK case 288: YY_RULE_SETUP #line 467 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_OGR); } YY_BREAK case 289: YY_RULE_SETUP #line 468 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ON); } YY_BREAK case 290: YY_RULE_SETUP #line 469 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_JOIN_ONE_TO_ONE); } YY_BREAK case 291: YY_RULE_SETUP #line 470 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_JOIN_ONE_TO_MANY); } YY_BREAK case 292: YY_RULE_SETUP #line 471 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ORACLESPATIAL); } YY_BREAK case 293: YY_RULE_SETUP #line 472 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_PERCENTAGES); } YY_BREAK case 294: YY_RULE_SETUP #line 473 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_PIXMAP); } YY_BREAK case 295: YY_RULE_SETUP #line 474 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_PIXELS); } YY_BREAK case 296: YY_RULE_SETUP #line 475 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_POINT); } YY_BREAK case 297: YY_RULE_SETUP #line 476 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_POLYGON); } YY_BREAK case 298: YY_RULE_SETUP #line 477 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_POSTGIS); } YY_BREAK case 299: YY_RULE_SETUP #line 478 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_PLUGIN); } YY_BREAK case 300: YY_RULE_SETUP #line 479 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_QUERY); } YY_BREAK case 301: YY_RULE_SETUP #line 480 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_LAYER_RASTER); } YY_BREAK case 302: YY_RULE_SETUP #line 481 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_ALIGN_RIGHT); } YY_BREAK case 303: YY_RULE_SETUP #line 482 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_ROUND); } YY_BREAK case 304: YY_RULE_SETUP #line 483 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SELECTED); } YY_BREAK case 305: YY_RULE_SETUP #line 484 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_SIMPLE); } YY_BREAK case 306: YY_RULE_SETUP #line 485 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SINGLE); } YY_BREAK case 307: YY_RULE_SETUP #line 486 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SMALL); } YY_BREAK case 308: YY_RULE_SETUP #line 487 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_SQUARE); } YY_BREAK case 309: YY_RULE_SETUP #line 488 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_SVG); } YY_BREAK case 310: YY_RULE_SETUP #line 489 "maplexer.l" { MS_LEXER_RETURN_TOKEN(POLAROFFSET); } YY_BREAK case 311: YY_RULE_SETUP #line 490 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TINY); } YY_BREAK case 312: YY_RULE_SETUP #line 491 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CJC_TRIANGLE); } YY_BREAK case 313: YY_RULE_SETUP #line 492 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TRUE); } YY_BREAK case 314: YY_RULE_SETUP #line 493 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_TRUETYPE); } YY_BREAK case 315: YY_RULE_SETUP #line 494 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UC); } YY_BREAK case 316: YY_RULE_SETUP #line 495 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UL); } YY_BREAK case 317: YY_RULE_SETUP #line 496 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UR); } YY_BREAK case 318: YY_RULE_SETUP #line 497 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UNION); } YY_BREAK case 319: YY_RULE_SETUP #line 498 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_UVRASTER); } YY_BREAK case 320: YY_RULE_SETUP #line 499 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_CONTOUR); } YY_BREAK case 321: YY_RULE_SETUP #line 500 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_VECTOR); } YY_BREAK case 322: YY_RULE_SETUP #line 501 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_WFS); } YY_BREAK case 323: YY_RULE_SETUP #line 502 "maplexer.l" { MS_LEXER_RETURN_TOKEN(MS_WMS); } YY_BREAK case 324: YY_RULE_SETUP #line 504 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); return(MS_STRING); } YY_BREAK case 325: YY_RULE_SETUP #line 512 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_NUMBER); } YY_BREAK case 326: /* rule 326 can match eol */ YY_RULE_SETUP #line 522 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); return(MS_BINDING); } YY_BREAK case 327: YY_RULE_SETUP #line 531 "maplexer.l" { /* attribute binding - shape (fixed value) */ return(MS_TOKEN_BINDING_SHAPE); } YY_BREAK case 328: YY_RULE_SETUP #line 535 "maplexer.l" { /* attribute binding - map cellsize */ return(MS_TOKEN_BINDING_MAP_CELLSIZE); } YY_BREAK case 329: YY_RULE_SETUP #line 539 "maplexer.l" { /* attribute binding - data cellsize */ return(MS_TOKEN_BINDING_DATA_CELLSIZE); } YY_BREAK case 330: /* rule 330 can match eol */ YY_RULE_SETUP #line 543 "maplexer.l" { /* attribute binding - numeric (no quotes) */ msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_DOUBLE); } YY_BREAK case 331: /* rule 331 can match eol */ YY_RULE_SETUP #line 552 "maplexer.l" { /* attribute binding - string (single or double quotes) */ msyytext+=2; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_STRING); } YY_BREAK case 332: /* rule 332 can match eol */ YY_RULE_SETUP #line 561 "maplexer.l" { /* attribute binding - time */ msyytext+=2; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_TIME); } YY_BREAK case 333: YY_RULE_SETUP #line 571 "maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_NUMBER); } YY_BREAK case 334: YY_RULE_SETUP #line 579 "maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_TOKEN_LITERAL_NUMBER); } YY_BREAK case 335: /* rule 335 can match eol */ YY_RULE_SETUP #line 587 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_LITERAL_TIME); } YY_BREAK case 336: /* rule 336 can match eol */ YY_RULE_SETUP #line 596 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_IREGEX); } YY_BREAK case 337: /* rule 337 can match eol */ YY_RULE_SETUP #line 605 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_REGEX); } YY_BREAK case 338: YY_RULE_SETUP #line 614 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_EXPRESSION); } YY_BREAK case 339: YY_RULE_SETUP #line 623 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_LIST); } YY_BREAK case 340: YY_RULE_SETUP #line 632 "maplexer.l" { msyystring_return_state = MS_STRING; msyystring_begin = msyytext[0]; msyystring_size = 0; msyystring_buffer_ptr = msyystring_buffer; BEGIN(MSSTRING); } YY_BREAK case 341: YY_RULE_SETUP #line 640 "maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); if (msyystring_begin == msyytext[0]) { BEGIN(msyystring_begin_state); *msyystring_buffer_ptr = '\0'; if (msyystring_return_state == MS_STRING) { if (msyystring_icase && strlen(msyytext)==2) { msyystring_icase = MS_FALSE; // reset return MS_ISTRING; } else return MS_STRING; } return msyystring_return_state; } else { ++msyystring_size; *msyystring_buffer_ptr++ = *msyytext; if (strlen(msyytext)==2) { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; *msyystring_buffer_ptr++ = msyytext[1]; } } } YY_BREAK case 342: YY_RULE_SETUP #line 670 "maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; if (strlen(msyytext) == 2) *msyystring_buffer_ptr++ = msyytext[1]; else *msyystring_buffer_ptr++ = msyytext[0]; } YY_BREAK case 343: /* rule 343 can match eol */ YY_RULE_SETUP #line 681 "maplexer.l" { char *yptr = msyytext; while ( *yptr ) { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; *msyystring_buffer_ptr++ = *yptr++; } } YY_BREAK case 344: /* rule 344 can match eol */ YY_RULE_SETUP #line 691 "maplexer.l" { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; if(include_stack_ptr >= MAX_INCLUDE_DEPTH) { msSetError(MS_IOERR, "Includes nested to deeply.", "msyylex()"); return(-1); } include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; /* save state */ include_lineno[include_stack_ptr] = msyylineno; include_stack_ptr++; msyyin = fopen(msBuildPath(path, msyybasepath, msyytext), "r"); if(!msyyin) { msSetError(MS_IOERR, "Error opening included file \"%s\".", "msyylex()", msyytext); msyyin = YY_CURRENT_BUFFER->yy_input_file; return(-1); } msyy_switch_to_buffer( msyy_create_buffer(msyyin, YY_BUF_SIZE) ); msyylineno = 1; BEGIN(INITIAL); } YY_BREAK case 345: YY_RULE_SETUP #line 717 "maplexer.l" { msyystring_return_state = MS_TOKEN_LITERAL_STRING; msyystring_begin = msyytext[0]; msyystring_size = 0; msyystring_buffer_ptr = msyystring_buffer; BEGIN(MSSTRING); } YY_BREAK case 346: YY_RULE_SETUP #line 725 "maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_STRING); } YY_BREAK case 347: /* rule 347 can match eol */ YY_RULE_SETUP #line 732 "maplexer.l" { msyylineno++; } YY_BREAK case YY_STATE_EOF(INITIAL): #line 734 "maplexer.l" { if( --include_stack_ptr < 0 ) return(EOF); /* end of main file */ else { fclose(YY_CURRENT_BUFFER->yy_input_file); msyy_delete_buffer( YY_CURRENT_BUFFER ); msyy_switch_to_buffer(include_stack[include_stack_ptr]); msyylineno = include_lineno[include_stack_ptr]; } } YY_BREAK case 348: /* rule 348 can match eol */ YY_RULE_SETUP #line 745 "maplexer.l" { return(0); } YY_BREAK case 349: YY_RULE_SETUP #line 749 "maplexer.l" { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(0); } YY_BREAK case 350: YY_RULE_SETUP #line 755 "maplexer.l" { return(msyytext[0]); } YY_BREAK case 351: YY_RULE_SETUP #line 756 "maplexer.l" ECHO; YY_BREAK #line 4652 "/home/even/mapserver/mapserver/maplexer.c" case YY_STATE_EOF(URL_VARIABLE): case YY_STATE_EOF(URL_STRING): case YY_STATE_EOF(EXPRESSION_STRING): case YY_STATE_EOF(INCLUDE): case YY_STATE_EOF(MSSTRING): case YY_STATE_EOF(MULTILINE_COMMENT): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed msyyin at a new source and called * msyylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = msyyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( msyywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * msyytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of user's declarations */ } /* end of msyylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); yy_size_t number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { yy_size_t new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ msyyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; msyyrestart(msyyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) msyyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { yy_state_type yy_current_state; char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 88); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 2024 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { int yy_is_jam; char *yy_cp = (yy_c_buf_p); YY_CHAR yy_c = 88; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 2024 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 2023); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT static void yyunput (int c, char * yy_bp ) { char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up msyytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ yy_size_t number_to_move = (yy_n_chars) + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ msyyrestart(msyyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( msyywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve msyytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void msyyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ msyyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = msyy_create_buffer(msyyin,YY_BUF_SIZE ); } msyy_init_buffer(YY_CURRENT_BUFFER,input_file ); msyy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void msyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * msyypop_buffer_state(); * msyypush_buffer_state(new_buffer); */ msyyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; msyy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (msyywrap()) processing, but the only time this flag * is looked at is after msyywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void msyy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; msyyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE msyy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) msyyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in msyy_create_buffer()" ); b->yy_buf_size = (yy_size_t)size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) msyyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in msyy_create_buffer()" ); b->yy_is_our_buffer = 1; msyy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with msyy_create_buffer() * */ void msyy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) msyyfree((void *) b->yy_ch_buf ); msyyfree((void *) b ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a msyyrestart() or at EOF. */ static void msyy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; msyy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then msyy_init_buffer was _probably_ * called from msyyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void msyy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) msyy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void msyypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; msyyensure_buffer_stack(); /* This block is copied from msyy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from msyy_switch_to_buffer. */ msyy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void msyypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; msyy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { msyy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void msyyensure_buffer_stack (void) { yy_size_t num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ (yy_buffer_stack) = (struct yy_buffer_state**)msyyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in msyyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)msyyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in msyyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE msyy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) msyyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in msyy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; msyy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to msyylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * msyy_scan_bytes() instead. */ YY_BUFFER_STATE msyy_scan_string (yyconst char * yystr ) { return msyy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to msyylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE msyy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) msyyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in msyy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = msyy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in msyy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up msyytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ msyytext[msyyleng] = (yy_hold_char); \ (yy_c_buf_p) = msyytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ msyyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int msyyget_lineno (void) { return msyylineno; } /** Get the input stream. * */ FILE *msyyget_in (void) { return msyyin; } /** Get the output stream. * */ FILE *msyyget_out (void) { return msyyout; } /** Get the length of the current token. * */ yy_size_t msyyget_leng (void) { return msyyleng; } /** Get the current token. * */ char *msyyget_text (void) { return msyytext; } /** Set the current line number. * @param _line_number line number * */ void msyyset_lineno (int _line_number ) { msyylineno = _line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param _in_str A readable stream. * * @see msyy_switch_to_buffer */ void msyyset_in (FILE * _in_str ) { msyyin = _in_str ; } void msyyset_out (FILE * _out_str ) { msyyout = _out_str ; } int msyyget_debug (void) { return msyy_flex_debug; } void msyyset_debug (int _bdebug ) { msyy_flex_debug = _bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from msyylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT msyyin = stdin; msyyout = stdout; #else msyyin = (FILE *) 0; msyyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * msyylex_init() */ return 0; } /* msyylex_destroy is for both reentrant and non-reentrant scanners. */ int msyylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ msyy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; msyypop_buffer_state(); } /* Destroy the stack itself. */ msyyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * msyylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *msyyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *msyyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void msyyfree (void * ptr ) { free( (char *) ptr ); /* see msyyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 756 "maplexer.l" /* ** Any extra C functions */ int msyywrap() /* override */ { return(1); } int msyyerror(char *s) { msSetError(MS_PARSEERR, "%s", "msyyparse()", s); return(0); } mapserver-7.4.3/maplexer.l000066400000000000000000001360321357574274700155550ustar00rootroot00000000000000%option never-interactive %{ /* ** READ ME FIRST! ** ** When this file is altered, it is necessary to do "make lexer". Due to ** problems detailed in #2310 the lexer is no longer automatically rebuilt ** when maplexer.l is altered. */ #define YY_NO_INPUT /* C declarations */ #include #include #include #include #include #include "mapserver.h" #include "maperror.h" #include "mapfile.h" #include "maptime.h" #include "mapsymbol.h" #include "mapparser.h" #include "mapprimitive.h" /* msyylineno is required for flex 2.5.4 and older, but is already defined by * flex 2.5.31 (bug 975). * Unfortunately there is no clean way to differenciate the two versions, * so we use the symbol YY_CURRENT_BUFFER_LVALUE to base our test since it * was not present in 2.5.4 and is present in 2.5.31. Hopefully that won't * put us in trouble with other versions. If that happens then we can * switch to using autoconf to detect the version. */ #ifndef YY_CURRENT_BUFFER_LVALUE int msyylineno = 1; #endif #define YY_NO_INPUT int msyysource=MS_STRING_TOKENS; double msyynumber; int msyystate=MS_TOKENIZE_DEFAULT; char *msyystring=NULL; char *msyybasepath=NULL; char *msyystring_buffer_ptr; int msyystring_buffer_size = 0; int msyystring_size; char msyystring_begin; char *msyystring_buffer = NULL; int msyystring_icase = MS_FALSE; int msyystring_return_state; int msyystring_begin_state; int msyystring_size_tmp; int msyyreturncomments = 0; #define MS_LEXER_STRING_REALLOC(string, string_size, max_size, string_ptr) \ if (string_size >= max_size) { \ msyystring_size_tmp = max_size; \ max_size = ((max_size*2) > string_size) ? max_size*2 : string_size+1; \ string = (char *) msSmallRealloc(string, sizeof(char *) * max_size); \ string_ptr = string; \ string_ptr += msyystring_size_tmp; \ } #define MS_LEXER_RETURN_TOKEN(token) \ MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), \ msyystring_buffer_size, msyystring_buffer_ptr); \ strcpy(msyystring_buffer, msyytext); \ return(token); #define MAX_INCLUDE_DEPTH 5 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_lineno[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; char path[MS_MAXPATHLEN]; %} %s URL_VARIABLE %s URL_STRING %s EXPRESSION_STRING %s INCLUDE %s MSSTRING %s MULTILINE_COMMENT %% if (msyystring_buffer == NULL) { msyystring_buffer_size = 256; msyystring_buffer = (char*) msSmallMalloc(sizeof(char) * msyystring_buffer_size); } msyystring_buffer[0] = '\0'; switch(msyystate) { case(MS_TOKENIZE_DEFAULT): break; case(MS_TOKENIZE_FILE): BEGIN(INITIAL); msyystring_begin_state = INITIAL; msyysource=MS_FILE_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyystring=NULL; msyyreturncomments=0; include_stack_ptr=0; return(0); break; case(MS_TOKENIZE_STRING): BEGIN(INITIAL); msyystring_begin_state = INITIAL; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_STRING_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyin=NULL; msyyreturncomments=0; include_stack_ptr=0; return(0); break; case(MS_TOKENIZE_URL_VARIABLE): BEGIN(URL_VARIABLE); msyystring_begin_state = URL_VARIABLE; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_URL_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyreturncomments=0; (void) yyunput; /* just to avoid warning about it being unrefed */ break; case(MS_TOKENIZE_URL_STRING): BEGIN(URL_STRING); msyystring_begin_state = URL_STRING; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyysource=MS_URL_TOKENS; msyystate=MS_TOKENIZE_DEFAULT; msyyin=NULL; msyyreturncomments=0; return(0); break; case(MS_TOKENIZE_EXPRESSION): BEGIN(EXPRESSION_STRING); msyystring_begin_state = EXPRESSION_STRING; msyy_delete_buffer(YY_CURRENT_BUFFER); msyy_scan_string(msyystring); msyystate=MS_TOKENIZE_DEFAULT; msyyreturncomments=0; break; case(99): BEGIN(INITIAL); /* may not need this one */ msyystring_begin_state = INITIAL; msyy_delete_buffer(YY_CURRENT_BUFFER); msyystate=MS_TOKENIZE_DEFAULT; msyystring=NULL; msyyreturncomments=0; return(0); break; default: break; } [ \t\r]+ ; (\/\/|#).* { if (msyyreturncomments) return(MS_COMMENT); } \/\* { BEGIN(MULTILINE_COMMENT); } \*\/ { BEGIN(INITIAL); } [^*\n]+ ; \* ; \n { msyylineno++; } _|\. ; or|\|\| { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_OR); } and|&& { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_AND); } not|! { MS_LEXER_RETURN_TOKEN(MS_TOKEN_LOGICAL_NOT); } eq|=|== { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_EQ); } ne|!= { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_NE); } gt|> { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_GT); } lt|< { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_LT); } ge|>= { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_GE); } le|<= { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_LE); } ~ { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_RE); } =\* { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IEQ); } ~\* { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IRE); } in { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_IN); /* was IN */ } area { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_AREA); } length { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_LENGTH); } tostring { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_TOSTRING); } commify { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_COMMIFY); } round { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_ROUND); } upper { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_UPPER); } lower { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_LOWER); } initcap { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_INITCAP); } firstcap { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_FIRSTCAP); } buffer { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_BUFFER); } difference { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_DIFFERENCE); } simplify { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SIMPLIFY); } simplifypt { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SIMPLIFYPT); } generalize { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_GENERALIZE); } smoothsia { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_SMOOTHSIA); } javascript { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_JAVASCRIPT); } intersects { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_INTERSECTS); } disjoint { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_DISJOINT); } touches { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_TOUCHES); } overlaps { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_OVERLAPS); } crosses { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_CROSSES); } within { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_WITHIN); } contains { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_CONTAINS); } equals { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_EQUALS); } beyond { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_BEYOND); } dwithin { MS_LEXER_RETURN_TOKEN(MS_TOKEN_COMPARISON_DWITHIN); } fromtext { MS_LEXER_RETURN_TOKEN(MS_TOKEN_FUNCTION_FROMTEXT); } true { msyynumber=MS_TRUE; return(MS_TOKEN_LITERAL_BOOLEAN); } false { msyynumber=MS_FALSE; return(MS_TOKEN_LITERAL_BOOLEAN); } colorrange { MS_LEXER_RETURN_TOKEN(COLORRANGE); } datarange { MS_LEXER_RETURN_TOKEN(DATARANGE); } rangeitem { MS_LEXER_RETURN_TOKEN(RANGEITEM); } align { MS_LEXER_RETURN_TOKEN(ALIGN); } anchorpoint { MS_LEXER_RETURN_TOKEN(ANCHORPOINT); } angle { MS_LEXER_RETURN_TOKEN(ANGLE); } antialias { MS_LEXER_RETURN_TOKEN(ANTIALIAS); } backgroundcolor { MS_LEXER_RETURN_TOKEN(BACKGROUNDCOLOR); } bandsitem { MS_LEXER_RETURN_TOKEN(BANDSITEM); } bindvals { MS_LEXER_RETURN_TOKEN(BINDVALS); } \xEF\xBB\xBF { MS_LEXER_RETURN_TOKEN(BOM); } browseformat { MS_LEXER_RETURN_TOKEN(BROWSEFORMAT); } buffer { MS_LEXER_RETURN_TOKEN(BUFFER); } character { MS_LEXER_RETURN_TOKEN(CHARACTER); } class { MS_LEXER_RETURN_TOKEN(CLASS); } classitem { MS_LEXER_RETURN_TOKEN(CLASSITEM); } classgroup { MS_LEXER_RETURN_TOKEN(CLASSGROUP); } cluster { MS_LEXER_RETURN_TOKEN(CLUSTER); } color { MS_LEXER_RETURN_TOKEN(COLOR); } compfilter { MS_LEXER_RETURN_TOKEN(COMPFILTER); } composite { MS_LEXER_RETURN_TOKEN(COMPOSITE); } compop { MS_LEXER_RETURN_TOKEN(COMPOP); } config { MS_LEXER_RETURN_TOKEN(CONFIG); } connection { MS_LEXER_RETURN_TOKEN(CONNECTION); } connectiontype { MS_LEXER_RETURN_TOKEN(CONNECTIONTYPE); } data { MS_LEXER_RETURN_TOKEN(DATA); } datapattern { MS_LEXER_RETURN_TOKEN(DATAPATTERN); } debug { MS_LEXER_RETURN_TOKEN(DEBUG); } driver { MS_LEXER_RETURN_TOKEN(DRIVER); } dump { MS_LEXER_RETURN_TOKEN(DUMP); } empty { MS_LEXER_RETURN_TOKEN(EMPTY); } encoding { MS_LEXER_RETURN_TOKEN(ENCODING); } end { MS_LEXER_RETURN_TOKEN(END); } error { MS_LEXER_RETURN_TOKEN(ERROR); } expression { MS_LEXER_RETURN_TOKEN(EXPRESSION); } extent { MS_LEXER_RETURN_TOKEN(EXTENT); } extension { MS_LEXER_RETURN_TOKEN(EXTENSION); } feature { MS_LEXER_RETURN_TOKEN(FEATURE); } filled { MS_LEXER_RETURN_TOKEN(FILLED); } filter { MS_LEXER_RETURN_TOKEN(FILTER); } filteritem { MS_LEXER_RETURN_TOKEN(FILTERITEM); } footer { MS_LEXER_RETURN_TOKEN(FOOTER); } font { MS_LEXER_RETURN_TOKEN(FONT); } fontset { MS_LEXER_RETURN_TOKEN(FONTSET); } force { MS_LEXER_RETURN_TOKEN(FORCE); } formatoption { MS_LEXER_RETURN_TOKEN(FORMATOPTION); } from { MS_LEXER_RETURN_TOKEN(FROM); } gap { MS_LEXER_RETURN_TOKEN(GAP); } geomtransform { MS_LEXER_RETURN_TOKEN(GEOMTRANSFORM); } grid { MS_LEXER_RETURN_TOKEN(GRID); } gridstep { MS_LEXER_RETURN_TOKEN(GRIDSTEP); } graticule { MS_LEXER_RETURN_TOKEN(GRATICULE); } group { MS_LEXER_RETURN_TOKEN(GROUP); } header { MS_LEXER_RETURN_TOKEN(HEADER); } image { MS_LEXER_RETURN_TOKEN(IMAGE); } imagecolor { MS_LEXER_RETURN_TOKEN(IMAGECOLOR); } imagetype { MS_LEXER_RETURN_TOKEN(IMAGETYPE); } imagequality { MS_LEXER_RETURN_TOKEN(IMAGEQUALITY); } imagemode { MS_LEXER_RETURN_TOKEN(IMAGEMODE); } imagepath { MS_LEXER_RETURN_TOKEN(IMAGEPATH); } temppath { MS_LEXER_RETURN_TOKEN(TEMPPATH); } imageurl { MS_LEXER_RETURN_TOKEN(IMAGEURL); } include { BEGIN(INCLUDE); } index { MS_LEXER_RETURN_TOKEN(INDEX); } initialgap { MS_LEXER_RETURN_TOKEN(INITIALGAP); } interlace { MS_LEXER_RETURN_TOKEN(INTERLACE); } intervals { MS_LEXER_RETURN_TOKEN(INTERVALS); } join { MS_LEXER_RETURN_TOKEN(JOIN); } keyimage { MS_LEXER_RETURN_TOKEN(KEYIMAGE); } keysize { MS_LEXER_RETURN_TOKEN(KEYSIZE); } keyspacing { MS_LEXER_RETURN_TOKEN(KEYSPACING); } label { MS_LEXER_RETURN_TOKEN(LABEL); } labelcache { MS_LEXER_RETURN_TOKEN(LABELCACHE); } labelformat { MS_LEXER_RETURN_TOKEN(LABELFORMAT); } labelitem { MS_LEXER_RETURN_TOKEN(LABELITEM); } labelmaxscale { MS_LEXER_RETURN_TOKEN(LABELMAXSCALE); } labelmaxscaledenom { MS_LEXER_RETURN_TOKEN(LABELMAXSCALEDENOM); } labelminscale { MS_LEXER_RETURN_TOKEN(LABELMINSCALE); } labelminscaledenom { MS_LEXER_RETURN_TOKEN(LABELMINSCALEDENOM); } labelrequires { MS_LEXER_RETURN_TOKEN(LABELREQUIRES); } latlon { MS_LEXER_RETURN_TOKEN(LATLON); } layer { MS_LEXER_RETURN_TOKEN(LAYER); } leader { MS_LEXER_RETURN_TOKEN(LEADER); } legend { MS_LEXER_RETURN_TOKEN(LEGEND); } legendformat { MS_LEXER_RETURN_TOKEN(LEGENDFORMAT); } linecap { MS_LEXER_RETURN_TOKEN(LINECAP); } linejoin { MS_LEXER_RETURN_TOKEN(LINEJOIN); } linejoinmaxsize { MS_LEXER_RETURN_TOKEN(LINEJOINMAXSIZE); } log { MS_LEXER_RETURN_TOKEN(LOG); } map { MS_LEXER_RETURN_TOKEN(MAP); } marker { MS_LEXER_RETURN_TOKEN(MARKER); } markersize { MS_LEXER_RETURN_TOKEN(MARKERSIZE); } mask { MS_LEXER_RETURN_TOKEN(MASK); } maxarcs { MS_LEXER_RETURN_TOKEN(MAXARCS); } maxboxsize { MS_LEXER_RETURN_TOKEN(MAXBOXSIZE); } maxdistance { MS_LEXER_RETURN_TOKEN(MAXDISTANCE); } maxfeatures { MS_LEXER_RETURN_TOKEN(MAXFEATURES); } maxinterval { MS_LEXER_RETURN_TOKEN(MAXINTERVAL); } maxscale { MS_LEXER_RETURN_TOKEN(MAXSCALE); } maxscaledenom { MS_LEXER_RETURN_TOKEN(MAXSCALEDENOM); } maxgeowidth { MS_LEXER_RETURN_TOKEN(MAXGEOWIDTH); } maxlength { MS_LEXER_RETURN_TOKEN(MAXLENGTH); } maxsize { MS_LEXER_RETURN_TOKEN(MAXSIZE); } maxsubdivide { MS_LEXER_RETURN_TOKEN(MAXSUBDIVIDE); } maxtemplate { MS_LEXER_RETURN_TOKEN(MAXTEMPLATE); } maxwidth { MS_LEXER_RETURN_TOKEN(MAXWIDTH); } metadata { MS_LEXER_RETURN_TOKEN(METADATA); } mimetype { MS_LEXER_RETURN_TOKEN(MIMETYPE); } minarcs { MS_LEXER_RETURN_TOKEN(MINARCS); } minboxsize { MS_LEXER_RETURN_TOKEN(MINBOXSIZE); } mindistance { MS_LEXER_RETURN_TOKEN(MINDISTANCE); } repeatdistance { MS_LEXER_RETURN_TOKEN(REPEATDISTANCE); } maxoverlapangle { MS_LEXER_RETURN_TOKEN(MAXOVERLAPANGLE); } minfeaturesize { MS_LEXER_RETURN_TOKEN(MINFEATURESIZE); } mininterval { MS_LEXER_RETURN_TOKEN(MININTERVAL); } minscale { MS_LEXER_RETURN_TOKEN(MINSCALE); } minscaledenom { MS_LEXER_RETURN_TOKEN(MINSCALEDENOM); } mingeowidth { MS_LEXER_RETURN_TOKEN(MINGEOWIDTH); } minlength { MS_LEXER_RETURN_TOKEN(MINLENGTH); } minsize { MS_LEXER_RETURN_TOKEN(MINSIZE); } minsubdivide { MS_LEXER_RETURN_TOKEN(MINSUBDIVIDE); } mintemplate { MS_LEXER_RETURN_TOKEN(MINTEMPLATE); } minwidth { MS_LEXER_RETURN_TOKEN(MINWIDTH); } name { MS_LEXER_RETURN_TOKEN(NAME); } offset { MS_LEXER_RETURN_TOKEN(OFFSET); } offsite { MS_LEXER_RETURN_TOKEN(OFFSITE); } opacity { MS_LEXER_RETURN_TOKEN(OPACITY); } outlinecolor { MS_LEXER_RETURN_TOKEN(OUTLINECOLOR); } outlinewidth { MS_LEXER_RETURN_TOKEN(OUTLINEWIDTH); } outputformat { MS_LEXER_RETURN_TOKEN(OUTPUTFORMAT); } overlaybackgroundcolor { MS_LEXER_RETURN_TOKEN(OVERLAYBACKGROUNDCOLOR); } overlaycolor { MS_LEXER_RETURN_TOKEN(OVERLAYCOLOR); } overlaymaxsize { MS_LEXER_RETURN_TOKEN(OVERLAYMAXSIZE); } overlayminsize { MS_LEXER_RETURN_TOKEN(OVERLAYMINSIZE); } overlayoutlinecolor { MS_LEXER_RETURN_TOKEN(OVERLAYOUTLINECOLOR); } overlaysize { MS_LEXER_RETURN_TOKEN(OVERLAYSIZE); } overlaysymbol { MS_LEXER_RETURN_TOKEN(OVERLAYSYMBOL); } partials { MS_LEXER_RETURN_TOKEN(PARTIALS); } pattern { MS_LEXER_RETURN_TOKEN(PATTERN); } points { MS_LEXER_RETURN_TOKEN(POINTS); } items { MS_LEXER_RETURN_TOKEN(ITEMS); } position { MS_LEXER_RETURN_TOKEN(POSITION); } postlabelcache { MS_LEXER_RETURN_TOKEN(POSTLABELCACHE); } priority { MS_LEXER_RETURN_TOKEN(PRIORITY); } processing { MS_LEXER_RETURN_TOKEN(PROCESSING); } projection { MS_LEXER_RETURN_TOKEN(PROJECTION); } queryformat { MS_LEXER_RETURN_TOKEN(QUERYFORMAT); } querymap { MS_LEXER_RETURN_TOKEN(QUERYMAP); } reference { MS_LEXER_RETURN_TOKEN(REFERENCE); } region { MS_LEXER_RETURN_TOKEN(REGION); } relativeto { MS_LEXER_RETURN_TOKEN(RELATIVETO); } requires { MS_LEXER_RETURN_TOKEN(REQUIRES); } resolution { MS_LEXER_RETURN_TOKEN(RESOLUTION); } defresolution { MS_LEXER_RETURN_TOKEN(DEFRESOLUTION); } scale { MS_LEXER_RETURN_TOKEN(SCALE); } scaledenom { MS_LEXER_RETURN_TOKEN(SCALEDENOM); } scalebar { MS_LEXER_RETURN_TOKEN(SCALEBAR); } scaletoken { MS_LEXER_RETURN_TOKEN(SCALETOKEN); } shadowcolor { MS_LEXER_RETURN_TOKEN(SHADOWCOLOR); } shadowsize { MS_LEXER_RETURN_TOKEN(SHADOWSIZE); } shapepath { MS_LEXER_RETURN_TOKEN(SHAPEPATH); } size { MS_LEXER_RETURN_TOKEN(SIZE); } sizeunits { MS_LEXER_RETURN_TOKEN(SIZEUNITS); } status { MS_LEXER_RETURN_TOKEN(STATUS); } style { MS_LEXER_RETURN_TOKEN(STYLE); } styleitem { MS_LEXER_RETURN_TOKEN(STYLEITEM); } symbol { MS_LEXER_RETURN_TOKEN(SYMBOL); } symbolscale { MS_LEXER_RETURN_TOKEN(SYMBOLSCALE); } symbolscaledenom { MS_LEXER_RETURN_TOKEN(SYMBOLSCALEDENOM); } symbolset { MS_LEXER_RETURN_TOKEN(SYMBOLSET); } table { MS_LEXER_RETURN_TOKEN(TABLE); } template { MS_LEXER_RETURN_TOKEN(TEMPLATE); } templatepattern { MS_LEXER_RETURN_TOKEN(TEMPLATEPATTERN); } text { MS_LEXER_RETURN_TOKEN(TEXT); } tileindex { MS_LEXER_RETURN_TOKEN(TILEINDEX); } tileitem { MS_LEXER_RETURN_TOKEN(TILEITEM); } tilesrs { MS_LEXER_RETURN_TOKEN(TILESRS); } title { MS_LEXER_RETURN_TOKEN(TITLE); } to { MS_LEXER_RETURN_TOKEN(TO); } tolerance { MS_LEXER_RETURN_TOKEN(TOLERANCE); } toleranceunits { MS_LEXER_RETURN_TOKEN(TOLERANCEUNITS); } transparency { MS_LEXER_RETURN_TOKEN(TRANSPARENCY); } transparent { MS_LEXER_RETURN_TOKEN(TRANSPARENT); } transform { MS_LEXER_RETURN_TOKEN(TRANSFORM); } type { MS_LEXER_RETURN_TOKEN(TYPE); } units { MS_LEXER_RETURN_TOKEN(UNITS); } utfdata { MS_LEXER_RETURN_TOKEN(UTFDATA); } utfitem { MS_LEXER_RETURN_TOKEN(UTFITEM); } validation { MS_LEXER_RETURN_TOKEN(VALIDATION); } values { MS_LEXER_RETURN_TOKEN(VALUES); } web { MS_LEXER_RETURN_TOKEN(WEB); } width { MS_LEXER_RETURN_TOKEN(WIDTH); } wkt { MS_LEXER_RETURN_TOKEN(WKT); } wrap { MS_LEXER_RETURN_TOKEN(WRAP); } annotation { MS_LEXER_RETURN_TOKEN(MS_LAYER_ANNOTATION); } auto { MS_LEXER_RETURN_TOKEN(MS_AUTO); } auto2 { MS_LEXER_RETURN_TOKEN(MS_AUTO2); } bevel { MS_LEXER_RETURN_TOKEN(MS_CJC_BEVEL); } bitmap { MS_LEXER_RETURN_TOKEN(MS_BITMAP); } butt { MS_LEXER_RETURN_TOKEN(MS_CJC_BUTT); } cc { MS_LEXER_RETURN_TOKEN(MS_CC); } center { MS_LEXER_RETURN_TOKEN(MS_ALIGN_CENTER); } chart { MS_LEXER_RETURN_TOKEN(MS_LAYER_CHART); } circle { MS_LEXER_RETURN_TOKEN(MS_LAYER_CIRCLE); } cl { MS_LEXER_RETURN_TOKEN(MS_CL); } cr { MS_LEXER_RETURN_TOKEN(MS_CR); } csv { MS_LEXER_RETURN_TOKEN(MS_DB_CSV); } postgresql { MS_LEXER_RETURN_TOKEN(MS_DB_POSTGRES); } mysql { MS_LEXER_RETURN_TOKEN(MS_DB_MYSQL); } default { MS_LEXER_RETURN_TOKEN(MS_DEFAULT); } dd { MS_LEXER_RETURN_TOKEN(MS_DD); } ellipse { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_ELLIPSE); } embed { MS_LEXER_RETURN_TOKEN(MS_EMBED); } false { MS_LEXER_RETURN_TOKEN(MS_FALSE); } feet { MS_LEXER_RETURN_TOKEN(MS_FEET); } follow { MS_LEXER_RETURN_TOKEN(MS_FOLLOW); } giant { MS_LEXER_RETURN_TOKEN(MS_GIANT); } hatch { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_HATCH); } kerneldensity { MS_LEXER_RETURN_TOKEN(MS_KERNELDENSITY); } hilite { MS_LEXER_RETURN_TOKEN(MS_HILITE); } inches { MS_LEXER_RETURN_TOKEN(MS_INCHES); } kilometers { MS_LEXER_RETURN_TOKEN(MS_KILOMETERS); } large { MS_LEXER_RETURN_TOKEN(MS_LARGE); } lc { MS_LEXER_RETURN_TOKEN(MS_LC); } left { MS_LEXER_RETURN_TOKEN(MS_ALIGN_LEFT); } line { MS_LEXER_RETURN_TOKEN(MS_LAYER_LINE); } ll { MS_LEXER_RETURN_TOKEN(MS_LL); } lr { MS_LEXER_RETURN_TOKEN(MS_LR); } medium { MS_LEXER_RETURN_TOKEN(MS_MEDIUM); } meters { MS_LEXER_RETURN_TOKEN(MS_METERS); } nauticalmiles { MS_LEXER_RETURN_TOKEN(MS_NAUTICALMILES); } miles { MS_LEXER_RETURN_TOKEN(MS_MILES); } miter { MS_LEXER_RETURN_TOKEN(MS_CJC_MITER); } multiple { MS_LEXER_RETURN_TOKEN(MS_MULTIPLE); } none { MS_LEXER_RETURN_TOKEN(MS_CJC_NONE); } normal { MS_LEXER_RETURN_TOKEN(MS_NORMAL); } off { MS_LEXER_RETURN_TOKEN(MS_OFF); } ogr { MS_LEXER_RETURN_TOKEN(MS_OGR); } on { MS_LEXER_RETURN_TOKEN(MS_ON); } one-to-one { MS_LEXER_RETURN_TOKEN(MS_JOIN_ONE_TO_ONE); } one-to-many { MS_LEXER_RETURN_TOKEN(MS_JOIN_ONE_TO_MANY); } oraclespatial { MS_LEXER_RETURN_TOKEN(MS_ORACLESPATIAL); } percentages { MS_LEXER_RETURN_TOKEN(MS_PERCENTAGES); } pixmap { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_PIXMAP); } pixels { MS_LEXER_RETURN_TOKEN(MS_PIXELS); } point { MS_LEXER_RETURN_TOKEN(MS_LAYER_POINT); } polygon { MS_LEXER_RETURN_TOKEN(MS_LAYER_POLYGON); } postgis { MS_LEXER_RETURN_TOKEN(MS_POSTGIS); } plugin { MS_LEXER_RETURN_TOKEN(MS_PLUGIN); } query { MS_LEXER_RETURN_TOKEN(MS_LAYER_QUERY); } raster { MS_LEXER_RETURN_TOKEN(MS_LAYER_RASTER); } right { MS_LEXER_RETURN_TOKEN(MS_ALIGN_RIGHT); } round { MS_LEXER_RETURN_TOKEN(MS_CJC_ROUND); } selected { MS_LEXER_RETURN_TOKEN(MS_SELECTED); } simple { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_SIMPLE); } single { MS_LEXER_RETURN_TOKEN(MS_SINGLE); } small { MS_LEXER_RETURN_TOKEN(MS_SMALL); } square { MS_LEXER_RETURN_TOKEN(MS_CJC_SQUARE); } svg { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_SVG); } polaroffset { MS_LEXER_RETURN_TOKEN(POLAROFFSET); } tiny { MS_LEXER_RETURN_TOKEN(MS_TINY); } triangle { MS_LEXER_RETURN_TOKEN(MS_CJC_TRIANGLE); } true { MS_LEXER_RETURN_TOKEN(MS_TRUE); } truetype { MS_LEXER_RETURN_TOKEN(MS_TRUETYPE); } uc { MS_LEXER_RETURN_TOKEN(MS_UC); } ul { MS_LEXER_RETURN_TOKEN(MS_UL); } ur { MS_LEXER_RETURN_TOKEN(MS_UR); } union { MS_LEXER_RETURN_TOKEN(MS_UNION); } uvraster { MS_LEXER_RETURN_TOKEN(MS_UVRASTER); } contour { MS_LEXER_RETURN_TOKEN(MS_CONTOUR); } vector { MS_LEXER_RETURN_TOKEN(MS_SYMBOL_VECTOR); } wfs { MS_LEXER_RETURN_TOKEN(MS_WFS); } wms { MS_LEXER_RETURN_TOKEN(MS_WMS); } \[[a-z/\.][a-z0-9/:\.\-\=_ ]*\] { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); return(MS_STRING); } \[[0-9]*\] { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_NUMBER); } \[[^\]]*\] { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); return(MS_BINDING); } \[shape\] { /* attribute binding - shape (fixed value) */ return(MS_TOKEN_BINDING_SHAPE); } \[map_cellsize\] { /* attribute binding - map cellsize */ return(MS_TOKEN_BINDING_MAP_CELLSIZE); } \[data_cellsize\] { /* attribute binding - data cellsize */ return(MS_TOKEN_BINDING_DATA_CELLSIZE); } \[[^\]]*\] { /* attribute binding - numeric (no quotes) */ msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_DOUBLE); } \"\[[^\"]*\]\"|\'\[[^\']*\]\' { /* attribute binding - string (single or double quotes) */ msyytext+=2; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_STRING); } \`\[[^\`]*\]\` { /* attribute binding - time */ msyytext+=2; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_BINDING_TIME); } -?[0-9]+|-?[0-9]+\.[0-9]*|-?\.[0-9]*|-?[0-9]+[eE][+-]?[0-9]+|-?[0-9]+\.[0-9]*[eE][+-]?[0-9]+|-?\.[0-9]*[eE][+-]?[0-9]+ { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_NUMBER); } -?[0-9]+|-?[0-9]+\.[0-9]*|-?\.[0-9]*|-?[0-9]+[eE][+-]?[0-9]+|-?[0-9]+\.[0-9]*[eE][+-]?[0-9]+|-?\.[0-9]*[eE][+-]?[0-9]+ { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer,msyytext); msyynumber = atof(msyytext); return(MS_TOKEN_LITERAL_NUMBER); } \`[^\`]*\` { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_TOKEN_LITERAL_TIME); } \/[^*]{1}[^\/]*\/i { msyytext++; msyytext[strlen(msyytext)-2] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_IREGEX); } \/[^*]{1}[^\/]*\/ { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_REGEX); } \(.*\) { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_EXPRESSION); } \{.*\} { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_LIST); } \'|\" { msyystring_return_state = MS_STRING; msyystring_begin = msyytext[0]; msyystring_size = 0; msyystring_buffer_ptr = msyystring_buffer; BEGIN(MSSTRING); } \'|\"|\"i|\'i { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); if (msyystring_begin == msyytext[0]) { BEGIN(msyystring_begin_state); *msyystring_buffer_ptr = '\0'; if (msyystring_return_state == MS_STRING) { if (msyystring_icase && strlen(msyytext)==2) { msyystring_icase = MS_FALSE; // reset return MS_ISTRING; } else return MS_STRING; } return msyystring_return_state; } else { ++msyystring_size; *msyystring_buffer_ptr++ = *msyytext; if (strlen(msyytext)==2) { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; *msyystring_buffer_ptr++ = msyytext[1]; } } } \\\'|\\\"|\\\\|\\ { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; if (strlen(msyytext) == 2) *msyystring_buffer_ptr++ = msyytext[1]; else *msyystring_buffer_ptr++ = msyytext[0]; } [^\\\'\\\"]+ { char *yptr = msyytext; while ( *yptr ) { MS_LEXER_STRING_REALLOC(msyystring_buffer, msyystring_size, msyystring_buffer_size, msyystring_buffer_ptr); ++msyystring_size; *msyystring_buffer_ptr++ = *yptr++; } } \"[^\"]*\"|\'[^\']*\' { msyytext++; msyytext[strlen(msyytext)-1] = '\0'; if(include_stack_ptr >= MAX_INCLUDE_DEPTH) { msSetError(MS_IOERR, "Includes nested to deeply.", "msyylex()"); return(-1); } include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; /* save state */ include_lineno[include_stack_ptr] = msyylineno; include_stack_ptr++; msyyin = fopen(msBuildPath(path, msyybasepath, msyytext), "r"); if(!msyyin) { msSetError(MS_IOERR, "Error opening included file \"%s\".", "msyylex()", msyytext); msyyin = YY_CURRENT_BUFFER->yy_input_file; return(-1); } msyy_switch_to_buffer( msyy_create_buffer(msyyin, YY_BUF_SIZE) ); msyylineno = 1; BEGIN(INITIAL); } \'|\" { msyystring_return_state = MS_TOKEN_LITERAL_STRING; msyystring_begin = msyytext[0]; msyystring_size = 0; msyystring_buffer_ptr = msyystring_buffer; BEGIN(MSSTRING); } [a-z/\.][a-z0-9/\._\-\=]* { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(MS_STRING); } \n { msyylineno++; } <> { if( --include_stack_ptr < 0 ) return(EOF); /* end of main file */ else { fclose(YY_CURRENT_BUFFER->yy_input_file); msyy_delete_buffer( YY_CURRENT_BUFFER ); msyy_switch_to_buffer(include_stack[include_stack_ptr]); msyylineno = include_lineno[include_stack_ptr]; } } [\r|\n|\0] { return(0); } . { MS_LEXER_STRING_REALLOC(msyystring_buffer, strlen(msyytext), msyystring_buffer_size, msyystring_buffer_ptr); strcpy(msyystring_buffer, msyytext); return(0); } . { return(msyytext[0]); } %% /* ** Any extra C functions */ int msyywrap() /* override */ { return(1); } int msyyerror(char *s) { msSetError(MS_PARSEERR, "%s", "msyyparse()", s); return(0); } mapserver-7.4.3/maplibxml2.c000066400000000000000000000074471357574274700160050ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: libxml2 convenience wrapper functions * Author: Tom Kralidis (tomkralidis@gmail.com) * ****************************************************************************** * Copyright (c) 2007, Tom Kralidis * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #ifdef USE_LIBXML2 #include #include #include #include /** * msLibXml2GenerateList() * * Convenience function to produce a series of XML elements from a delimited list * * @param xmlNodePtr psParent the encompassing node * @param xmlNsPtr psNs the namespace object * @param const char *elname the list member element name * @param const char *values the list member element values * @param char delim the delimiter * */ void msLibXml2GenerateList(xmlNodePtr psParent, xmlNsPtr psNs, const char *elname, const char *values, char delim) { char **tokens = NULL; int n = 0; int i = 0; tokens = msStringSplit(values, delim, &n); for (i=0; inodesetval)) { xmlXPathFreeObject(result); return NULL; } return result; } /** * msLibXml2GetXPathTree * * Convenience function to fetch an XPath and children * * @param xmlDocPtr doc the XML doc pointer * @param xmlXPathObjectPtr the xpath object * * @return result string * */ char *msLibXml2GetXPathTree(xmlDocPtr doc, xmlXPathObjectPtr xpath) { xmlBufferPtr xbuf; char *result = NULL; xbuf = xmlBufferCreate(); if (xpath) { if (xmlNodeDump(xbuf, doc, xpath->nodesetval->nodeTab[0], 0, 0) == -1) { return NULL; } result = msStrdup((char *)xbuf->content); } xmlBufferFree(xbuf); return result; } #endif /* defined(USE_LIBXML2) */ mapserver-7.4.3/maplibxml2.h000066400000000000000000000040641357574274700160020ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: libxml2 convenience wrapper functions include file * Author: Tom Kralidis (tomkralidis@gmail.com) * ****************************************************************************** * Copyright (c) 2007, Tom Kralidis * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPLIBXML2_H #define MAPLIBXML2_H #ifdef USE_LIBXML2 #include #include #include #include #include #include xmlXPathObjectPtr msLibXml2GetXPath(xmlDocPtr doc, xmlXPathContextPtr context, xmlChar *xpath); void msLibXml2GenerateList(xmlNodePtr psParent, xmlNsPtr psNs, const char *elname, const char *values, char delim); char *msLibXml2GetXPathTree(xmlDocPtr doc, xmlXPathObjectPtr xpath); #endif /* defined(USE_LIBXML2) */ #endif /* MAPLIBXML2_H */ mapserver-7.4.3/mapmetadata.c000066400000000000000000001146371357574274700162140ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: Metadata implementation * Author: Tom Kralidis (tomkralidis@gmail.com) * ********************************************************************** * Copyright (c) 2017, Tom Kralidis * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #include "mapserver.h" #include "mapows.h" #include "mapowscommon.h" #include "maplibxml2.h" /************************************************************************/ /* _msMetadataGetCharacterString */ /* */ /* Create a gmd:name/gmd:CharacterString element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetCharacterString(xmlNsPtr namespace, const char *name, const char *value, xmlNsPtr* ppsNsGco) { xmlNodePtr psNode = NULL; if( *ppsNsGco == NULL ) *ppsNsGco = xmlNewNs(NULL, BAD_CAST "http://www.isotc211.org/2005/gmd", BAD_CAST "gco"); psNode = xmlNewNode(namespace, BAD_CAST name); if (!value) xmlNewNsProp(psNode, *ppsNsGco, BAD_CAST "nilReason", BAD_CAST "missing"); else xmlNewChild(psNode, *ppsNsGco, BAD_CAST "CharacterString", BAD_CAST value); return psNode; } /************************************************************************/ /* _msMetadataGetURL */ /* */ /* Create a gmd:name/gmd:URL element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetURL(xmlNsPtr namespace, const char *name, const char *value, xmlNsPtr* ppsNsGco) { xmlNodePtr psNode = NULL; if( *ppsNsGco == NULL ) *ppsNsGco = xmlNewNs(NULL, BAD_CAST "http://www.isotc211.org/2005/gmd", BAD_CAST "gco"); psNode = xmlNewNode(namespace, BAD_CAST name); if (!value) xmlNewNsProp(psNode, *ppsNsGco, BAD_CAST "nilReason", BAD_CAST "missing"); else xmlNewChild(psNode, namespace, BAD_CAST "URL", BAD_CAST value); return psNode; } /************************************************************************/ /* _msMetadataGetOnline */ /* */ /* Create a gmd:onLine element pattern */ /************************************************************************/ static char* _stringConcatenateAndEncodeHTML(char* str, const char* appendStr) { char* pszTmp = msEncodeHTMLEntities(appendStr); str = msStringConcatenate(str, pszTmp); msFree(pszTmp); return str; } static xmlNodePtr _msMetadataGetOnline(xmlNsPtr namespace, layerObj *layer, const char *service, const char *format, const char *desc, const char *url_in, xmlNsPtr* ppsNsGco) { int status; char *url = NULL; char buffer[32]; char *epsg_str; const char *link_protocol = "unknown protocol"; xmlNodePtr psNode = NULL; xmlNodePtr psORNode = NULL; rectObj rect; psNode = xmlNewNode(namespace, BAD_CAST "onLine"); psORNode = xmlNewChild(psNode, namespace, BAD_CAST "CI_OnlineResource", NULL); url = msStrdup(url_in); if (strcasecmp(service, "M") == 0) { url = _stringConcatenateAndEncodeHTML(url, "service=WMS&version=1.3.0&request=GetMap&width=500&height=300&styles=&layers="); url = _stringConcatenateAndEncodeHTML(url, layer->name); url = _stringConcatenateAndEncodeHTML(url, "&format="); url = _stringConcatenateAndEncodeHTML(url, format); url = _stringConcatenateAndEncodeHTML(url, "&crs="); { char* epsg_str = NULL; msOWSGetEPSGProj(&(layer->projection), &(layer->metadata), "MFCSGO", MS_TRUE, &epsg_str); url = _stringConcatenateAndEncodeHTML(url, epsg_str); msFree(epsg_str); } link_protocol = "WWW:DOWNLOAD-1.0-http-get-map"; status = msLayerGetExtent(layer, &rect); if (status == 0) { url = _stringConcatenateAndEncodeHTML(url, "&bbox="); sprintf(buffer, "%f", rect.miny); url = msStringConcatenate(url, buffer); url = msStringConcatenate(url, ","); sprintf(buffer, "%f", rect.minx); url = msStringConcatenate(url, buffer); url = msStringConcatenate(url, ","); sprintf(buffer, "%f", rect.maxy); url = msStringConcatenate(url, buffer); url = msStringConcatenate(url, ","); sprintf(buffer, "%f", rect.maxx); url = msStringConcatenate(url, buffer); } } else if (strcasecmp(service, "F") == 0) { link_protocol = "WWW:DOWNLOAD-1.0-http--download"; url = _stringConcatenateAndEncodeHTML(url, "service=WFS&version=1.1.0&request=GetFeature&typename="); url = _stringConcatenateAndEncodeHTML(url, layer->name); url = _stringConcatenateAndEncodeHTML(url, "&outputformat="); url = _stringConcatenateAndEncodeHTML(url, format); } else if (strcasecmp(service, "C") == 0) { link_protocol = "WWW:DOWNLOAD-1.0-http--download"; url = _stringConcatenateAndEncodeHTML(url, "service=WCS&version=2.0.1&request=GetCoverage&coverageid="); url = _stringConcatenateAndEncodeHTML(url, layer->name); url = _stringConcatenateAndEncodeHTML(url, "&format="); url = _stringConcatenateAndEncodeHTML(url, format); } xmlAddChild(psORNode, _msMetadataGetURL(namespace, "linkage", url, ppsNsGco)); msFree(url); xmlAddChild(psORNode, _msMetadataGetCharacterString(namespace, "protocol", link_protocol, ppsNsGco)); xmlAddChild(psORNode, _msMetadataGetCharacterString(namespace, "name", layer->name, ppsNsGco)); xmlAddChild(psORNode, _msMetadataGetCharacterString(namespace, "description", desc, ppsNsGco)); return psNode; } /************************************************************************/ /* _msMetadataGetInteger */ /* */ /* Create a gmd:name/gmd:Integer element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetInteger(xmlNsPtr namespace, const char *name, int value, xmlNsPtr* ppsNsGco) { char buffer[8]; xmlNodePtr psNode = NULL; sprintf(buffer, "%d", value); if( *ppsNsGco == NULL ) *ppsNsGco = xmlNewNs(NULL, BAD_CAST "http://www.isotc211.org/2005/gmd", BAD_CAST "gco"); psNode = xmlNewNode(namespace, BAD_CAST name); if (!value) xmlNewNsProp(psNode, *ppsNsGco, BAD_CAST "nilReason", BAD_CAST "missing"); else xmlNewChild(psNode, *ppsNsGco, BAD_CAST "Integer", BAD_CAST buffer); return psNode; } /************************************************************************/ /* _msMetadataGetDecimal */ /* */ /* Create a gmd:name/gmd:Decimal element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetDecimal(xmlNsPtr namespace, const char *name, double value, xmlNsPtr* ppsNsGco) { char buffer[32]; xmlNodePtr psNode = NULL; sprintf(buffer, "%f", value); if( *ppsNsGco == NULL ) *ppsNsGco = xmlNewNs(NULL, BAD_CAST "http://www.isotc211.org/2005/gmd", BAD_CAST "gco"); psNode = xmlNewNode(namespace, BAD_CAST name); if (!value) xmlNewNsProp(psNode, *ppsNsGco, BAD_CAST "nilReason", BAD_CAST "missing"); else xmlNewChild(psNode, *ppsNsGco, BAD_CAST "Decimal", BAD_CAST buffer); return psNode; } /************************************************************************/ /* _msMetadataGetCodeList */ /* */ /* Create a gmd:name/gmd:* code list element pattern */ /************************************************************************/ xmlNodePtr _msMetadataGetCodeList(xmlNsPtr namespace, char *parent_element, char *name, char *value) { char *codelist = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psCodeNode = NULL; codelist = msStrdup("http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#"); codelist = msStringConcatenate(codelist, name); psNode = xmlNewNode(namespace, BAD_CAST parent_element); psCodeNode = xmlNewChild(psNode, namespace, BAD_CAST name, BAD_CAST value); xmlNewProp(psCodeNode, BAD_CAST "codeSpace", BAD_CAST "ISOTC211/19115"); xmlNewProp(psCodeNode, BAD_CAST "codeList", BAD_CAST codelist); xmlNewProp(psCodeNode, BAD_CAST "codeListValue", BAD_CAST value); msFree(codelist); return psNode; } /************************************************************************/ /* _msMetadataGetDate */ /* */ /* Create a gmd:date or gmd:dateStamp element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetDate(xmlNsPtr namespace, const char *parent_element, const char *date_type, const char *value, xmlNsPtr* ppsNsGco) { xmlNodePtr psNode = NULL; xmlNodePtr psNode2 = NULL; if( *ppsNsGco == NULL ) *ppsNsGco = xmlNewNs(NULL, BAD_CAST "http://www.isotc211.org/2005/gmd", BAD_CAST "gco"); psNode = xmlNewNode(namespace, BAD_CAST parent_element); if (date_type == NULL) { /* it's a gmd:dateStamp */ xmlNewChild(psNode, *ppsNsGco, BAD_CAST "Date", BAD_CAST value); return psNode; } psNode2 = xmlNewChild(psNode, namespace, BAD_CAST "date", NULL); xmlNewChild(psNode2, *ppsNsGco, BAD_CAST "Date", BAD_CAST value); xmlAddChild(psNode, _msMetadataGetCodeList(namespace, "dateType", "CI_DateTypeCode", date_type)); return psNode; } /************************************************************************/ /* _msMetadataGetGMLTimePeriod */ /* */ /* Create a gml:TimePeriod element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetGMLTimePeriod(char **temporal) { xmlNsPtr psNsGml = NULL; xmlNodePtr psNode = NULL; psNsGml = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"); psNode = xmlNewNode(psNsGml, BAD_CAST "TimePeriod"); xmlNewNsProp(psNode, psNsGml, BAD_CAST "id", BAD_CAST "T001"); xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"); xmlSetNs(psNode, psNsGml); xmlNewChild(psNode, psNsGml, BAD_CAST "beginPosition", BAD_CAST temporal[0]); xmlNewChild(psNode, psNsGml, BAD_CAST "endPosition", BAD_CAST temporal[1]); return psNode; } /************************************************************************/ /* _msMetadataGetExtent */ /* */ /* Create a gmd:extent element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetExtent(xmlNsPtr namespace, layerObj *layer, xmlNsPtr *ppsNsGco) { int n; int status; char *value = NULL; char **temporal = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psEXNode = NULL; xmlNodePtr psGNode = NULL; xmlNodePtr psGNode2 = NULL; xmlNodePtr psTNode = NULL; xmlNodePtr psTNode2 = NULL; xmlNodePtr psENode = NULL; rectObj rect; psNode = xmlNewNode(namespace, BAD_CAST "extent"); psEXNode = xmlNewChild(psNode, namespace, BAD_CAST "EX_Extent", NULL); /* scan for geospatial extent */ status = msLayerGetExtent(layer, &rect); if (status == 0) { /* always project to lat long */ msOWSProjectToWGS84(&layer->projection, &rect); psGNode = xmlNewChild(psEXNode, namespace, BAD_CAST "geographicElement", NULL); psGNode2 = xmlNewChild(psGNode, namespace, BAD_CAST "EX_GeographicBoundingBox", NULL); xmlAddChild(psGNode2, _msMetadataGetDecimal(namespace, "westBoundLongitude", rect.minx, ppsNsGco)); xmlAddChild(psGNode2, _msMetadataGetDecimal(namespace, "eastBoundLongitude", rect.maxx, ppsNsGco)); xmlAddChild(psGNode2, _msMetadataGetDecimal(namespace, "southBoundLatitude", rect.miny, ppsNsGco)); xmlAddChild(psGNode2, _msMetadataGetDecimal(namespace, "northBoundLatitude", rect.maxy, ppsNsGco)); } /* scan for temporal extent */ value = (char *)msOWSLookupMetadata(&(layer->metadata), "MO", "timeextent"); if (value) { /* WMS */ temporal = msStringSplit(value, '/', &n); } else { /* WCS */ value = (char *)msOWSLookupMetadata(&(layer->metadata), "CO", "timeposition"); if (value) { /* split extent */ temporal = msStringSplit(value, ',', &n); } } if (!value) { /* SOS */ value = (char *)msOWSLookupMetadata(&(layer->metadata), "SO", "offering_timeextent"); if (value) temporal = msStringSplit(value, '/', &n); } if (value) { if (temporal && n > 0) { psTNode = xmlNewChild(psEXNode, namespace, BAD_CAST "temporalElement", NULL); psTNode2 = xmlNewChild(psTNode, namespace, BAD_CAST "EX_TemporalExtent", NULL); psENode = xmlNewChild(psTNode2, namespace, BAD_CAST "extent", NULL); xmlAddChild(psENode, _msMetadataGetGMLTimePeriod(temporal)); msFreeCharArray(temporal, n); } } return psNode; } /************************************************************************/ /* _msMetadataGetReferenceSystemInfo */ /* */ /* Create a gmd:referenceSystemInfo element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetReferenceSystemInfo(xmlNsPtr namespace, layerObj *layer, xmlNsPtr* ppsNsGco) { char *epsg_str = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psRSNode = NULL; xmlNodePtr psRSINode = NULL; xmlNodePtr psRSINode2 = NULL; psNode = xmlNewNode(namespace, BAD_CAST "referenceSystemInfo"); psRSNode = xmlNewChild(psNode, namespace, BAD_CAST "MD_ReferenceSystem", NULL); psRSINode = xmlNewChild(psRSNode, namespace, BAD_CAST "referenceSystemIdentifier", NULL); psRSINode2 = xmlNewChild(psRSINode, namespace, BAD_CAST "RS_Identifier", NULL); msOWSGetEPSGProj(&(layer->projection), &(layer->metadata), "MFCSGO", MS_TRUE, &epsg_str); xmlAddChild(psRSINode2, _msMetadataGetCharacterString(namespace, "code", epsg_str, ppsNsGco)); xmlAddChild(psRSINode2, _msMetadataGetCharacterString(namespace, "codeSpace", "http://www.epsg-registry.org", ppsNsGco)); xmlAddChild(psRSINode2, _msMetadataGetCharacterString(namespace, "version", "6.14", ppsNsGco)); msFree(epsg_str); return psNode; } /************************************************************************/ /* _msMetadataGetContact */ /* */ /* Create a gmd:contact element pattern */ /************************************************************************/ xmlNodePtr _msMetadataGetContact(xmlNsPtr namespace, char *contact_element, mapObj *map, xmlNsPtr* ppsNsGco) { char *value = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psCNode = NULL; xmlNodePtr psCINode = NULL; xmlNodePtr psCINode2 = NULL; xmlNodePtr psPhoneNode = NULL; xmlNodePtr psCIPhoneNode = NULL; xmlNodePtr psAddressNode = NULL; xmlNodePtr psCIAddressNode = NULL; xmlNodePtr psORNode = NULL; xmlNodePtr psORNode2 = NULL; psNode = xmlNewNode(namespace, BAD_CAST contact_element); psCNode = xmlNewChild(psNode, namespace, BAD_CAST "CI_ResponsibleParty", NULL); xmlNewProp(psCNode, BAD_CAST "id", BAD_CAST contact_element); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "contactperson"); if (value) xmlAddChild(psCNode, _msMetadataGetCharacterString(namespace, "individualName", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "contactorganization"); if (value) xmlAddChild(psCNode, _msMetadataGetCharacterString(namespace, "organisationName", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "contactposition"); if (value) xmlAddChild(psCNode, _msMetadataGetCharacterString(namespace, "positionName", value, ppsNsGco)); psCINode = xmlNewChild(psCNode, namespace, BAD_CAST "contactInfo", NULL); psCINode2 = xmlNewChild(psCINode, namespace, BAD_CAST "CI_Contact", NULL); psPhoneNode = xmlNewChild(psCINode2, namespace, BAD_CAST "phone", NULL); psCIPhoneNode = xmlNewChild(psPhoneNode, namespace, BAD_CAST "CI_Telephone", NULL); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "contactvoicetelephone"); if (value) xmlAddChild(psCIPhoneNode, _msMetadataGetCharacterString(namespace, "voice", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "contactfacsimiletelephone"); if (value) xmlAddChild(psCIPhoneNode, _msMetadataGetCharacterString(namespace, "facsimile", value, ppsNsGco)); psAddressNode = xmlNewChild(psCINode2, namespace, BAD_CAST "address", NULL); psCIAddressNode = xmlNewChild(psAddressNode, namespace, BAD_CAST "CI_Address", NULL); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "address"); if (value) xmlAddChild(psCIAddressNode, _msMetadataGetCharacterString(namespace, "deliveryPoint", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "city"); if (value) xmlAddChild(psCIAddressNode, _msMetadataGetCharacterString(namespace, "city", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "stateorprovince"); if (value) xmlAddChild(psCIAddressNode, _msMetadataGetCharacterString(namespace, "administrativeArea", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "postcode"); if (value) xmlAddChild(psCIAddressNode, _msMetadataGetCharacterString(namespace, "postalCode", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "country"); if (value) xmlAddChild(psCIAddressNode, _msMetadataGetCharacterString(namespace, "country", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "contactelectronicmailaddress"); if (value) xmlAddChild(psCIAddressNode, _msMetadataGetCharacterString(namespace, "electronicMailAddress", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(map->web.metadata), "MCFO", "onlineresource"); if (value) { psORNode = xmlNewChild(psCINode2, namespace, BAD_CAST "onlineResource", NULL); psORNode2 = xmlNewChild(psORNode, namespace, BAD_CAST "CI_OnlineResource", NULL); xmlAddChild(psORNode2, _msMetadataGetURL(namespace, "linkage", value, ppsNsGco)); } xmlAddChild(psCNode, _msMetadataGetCodeList(namespace, "role", "CI_RoleCode", "pointOfContact")); return psNode; } /************************************************************************/ /* _msMetadataGetIdentificationInfo */ /* */ /* Create a gmd:identificationInfo element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetIdentificationInfo(xmlNsPtr namespace, mapObj *map, layerObj *layer, xmlNsPtr *ppsNsGco) { int i = 0; int n; char *value; char **tokens = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psDINode = NULL; xmlNodePtr psCNode = NULL; xmlNodePtr psCINode = NULL; xmlNodePtr psDNode = NULL; xmlNodePtr psKWNode = NULL; xmlNodePtr psMDKNode = NULL; psNode = xmlNewNode(namespace, BAD_CAST "identificationInfo"); psDINode = xmlNewChild(psNode, namespace, BAD_CAST "MD_DataIdentification", NULL); xmlNewProp(psDINode, BAD_CAST "id", BAD_CAST layer->name); psCNode = xmlNewChild(psDINode, namespace, BAD_CAST "citation", NULL); psCINode = xmlNewChild(psCNode, namespace, BAD_CAST "CI_Citation", NULL); value = (char *)msOWSLookupMetadata(&(layer->metadata), "MCFGO", "title"); if (!value) value = (char *)msOWSLookupMetadata(&(layer->metadata), "S", "offering_name"); xmlAddChild(psCINode, _msMetadataGetCharacterString(namespace, "title", value, ppsNsGco)); psDNode = xmlNewChild(psCINode, namespace, BAD_CAST "date", NULL); xmlAddChild(psDNode, _msMetadataGetDate(namespace, "CI_Date", "publication", "2011", ppsNsGco)); value = (char *)msOWSLookupMetadata(&(layer->metadata), "MCFGO", "abstract"); if (!value) value = (char *)msOWSLookupMetadata(&(layer->metadata), "S", "offering_description"); xmlAddChild(psDINode, _msMetadataGetCharacterString(namespace, "abstract", value, ppsNsGco)); value = (char *)msOWSLookupMetadata(&(layer->metadata), "MCFSGO", "keywordlist"); if (value) { psKWNode = xmlNewChild(psDINode, namespace, BAD_CAST "descriptiveKeywords", NULL); psMDKNode = xmlNewChild(psKWNode, namespace, BAD_CAST "MD_Keywords", NULL); tokens = msStringSplit(value, ',', &n); if (tokens && n > 0) { for (i=0; itype == MS_LAYER_RASTER) { psSRNode = xmlNewChild(psNode, namespace, BAD_CAST "MD_GridSpatialRepresentation", NULL); xmlAddChild(psSRNode, _msMetadataGetInteger(namespace, "numberOfDimensions", 2, ppsNsGco)); xmlAddChild(psSRNode, _msMetadataGetCodeList(namespace, "cellGeometry", "MD_CellGeometryCode", "area")); } else { psSRNode = xmlNewChild(psNode, namespace, BAD_CAST "MD_VectorSpatialRepresentation", NULL); xmlAddChild(psSRNode, _msMetadataGetCodeList(namespace, "topologyLevel", "MD_TopologyLevelCode", "geometryOnly")); psGONode = xmlNewChild(psSRNode, namespace, BAD_CAST "geometricObjects", NULL); psGONode2 = xmlNewChild(psGONode, namespace, BAD_CAST "MD_GeometricObjects", NULL); if (layer->type == MS_LAYER_POINT) value = "point"; else if (layer->type == MS_LAYER_LINE) value = "curve"; else if (layer->type == MS_LAYER_POLYGON) value = "surface"; else value = "complex"; xmlAddChild(psGONode2, _msMetadataGetCodeList(namespace, "geometricObjectType", "MD_GeometricObjectTypeCode", value)); // TODO: find way to get feature count in a fast way /* xmlAddChild(psGONode2, _msMetadataGetInteger(namespace, "geometricObjectCount", msLayerGetNumFeatures(layer))); */ } return psNode; } /************************************************************************/ /* _msMetadataGetDistributionInfo */ /* */ /* Create a gmd:identificationInfo element pattern */ /************************************************************************/ static xmlNodePtr _msMetadataGetDistributionInfo(xmlNsPtr namespace, mapObj *map, layerObj *layer, cgiRequestObj *cgi_request, xmlNsPtr* ppsNsGco) { char *url = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psMDNode = NULL; xmlNodePtr psTONode = NULL; xmlNodePtr psDTONode = NULL; xmlNodePtr psDNode = NULL; xmlNodePtr psDNode2 = NULL; psNode = xmlNewNode(namespace, BAD_CAST "distributionInfo"); psMDNode = xmlNewChild(psNode, namespace, BAD_CAST "MD_Distribution", NULL); { char* pszTmp = msOWSGetOnlineResource(map, "MFCSGO", "onlineresource", cgi_request); url = msEncodeHTMLEntities(pszTmp); msFree(pszTmp); } /* gmd:distributor */ psDNode = xmlNewChild(psMDNode, namespace, BAD_CAST "distributor", NULL); psDNode2 = xmlNewChild(psDNode, namespace, BAD_CAST "MD_Distributor", NULL); xmlAddChild(psDNode2, _msMetadataGetContact(namespace, "distributorContact", map, ppsNsGco)); /* gmd:transferOptions */ psTONode = xmlNewChild(psMDNode, namespace, BAD_CAST "transferOptions", NULL); psDTONode = xmlNewChild(psTONode, namespace, BAD_CAST "MD_DigitalTransferOptions", NULL); xmlAddChild(psDTONode, _msMetadataGetCharacterString(namespace, "unitsOfDistribution", "KB", ppsNsGco)); /* links */ /* WMS */ xmlAddChild(psDTONode, _msMetadataGetOnline(namespace, layer, "M", "image/png", "PNG Format", url, ppsNsGco)); xmlAddChild(psDTONode, _msMetadataGetOnline(namespace, layer, "M", "image/jpeg", "JPEG Format", url, ppsNsGco)); /* WCS */ if (layer->type == MS_LAYER_RASTER) { xmlAddChild(psDTONode, _msMetadataGetOnline(namespace, layer, "C", "image/tiff", "GeoTIFF Format", url, ppsNsGco)); } /* WFS */ else { xmlAddChild(psDTONode, _msMetadataGetOnline(namespace, layer, "F", "GML2", "GML2 Format", url, ppsNsGco)); xmlAddChild(psDTONode, _msMetadataGetOnline(namespace, layer, "F", "GML3", "GML3 Format", url, ppsNsGco)); } msFree(url); return psNode; } /************************************************************************/ /* msMetadataGetExceptionReport */ /* */ /* Generate an OWS Common Exception Report */ /************************************************************************/ static xmlNodePtr msMetadataGetExceptionReport(mapObj *map, char *code, char *locator, char *message, xmlNsPtr* ppsNsOws) { char *schemas_location = NULL; xmlNodePtr psRootNode = NULL; schemas_location = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); *ppsNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); psRootNode = msOWSCommonExceptionReport(*ppsNsOws, OWS_1_1_0, schemas_location, "1.1.0", msOWSGetLanguage(map, "exception"), code, locator, message); msFree(schemas_location); xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); return psRootNode; } /************************************************************************/ /* msMetadataGetLayerMetadata */ /* */ /* Generate an ISO 19139:2007 representation of layer metadata */ /************************************************************************/ static xmlNodePtr msMetadataGetLayerMetadata(mapObj *map, metadataParamsObj *paramsObj, cgiRequestObj *cgi_request, owsRequestObj *ows_request, xmlNsPtr* ppsNsOws, xmlNsPtr* ppsNsXsi, xmlNsPtr* ppsNsGmd, xmlNsPtr* ppsNsGco) { int i; int layer_found = MS_FALSE; xmlNodePtr psRootNode = NULL; layerObj *layer = NULL; /* Check that layer requested exists in mapfile */ for (i=0; inumlayers; i++) { if(strcasecmp(GET_LAYER(map, i)->name, paramsObj->pszLayer) == 0) { layer_found = MS_TRUE; layer = GET_LAYER(map, i); break; } } if (layer_found == MS_FALSE) { psRootNode = msMetadataGetExceptionReport(map, "InvalidParameterValue", "layer", "Layer not found", ppsNsOws); } /* Check that outputschema is valid */ else if (paramsObj->pszOutputSchema && strcasecmp(paramsObj->pszOutputSchema, "http://www.isotc211.org/2005/gmd") != 0) { psRootNode = msMetadataGetExceptionReport(map, "InvalidParameterValue", "outputschema", "OUTPUTSCHEMA must be \"http://www.isotc211.org/2005/gmd\"", ppsNsOws); } else { *ppsNsXsi = xmlNewNs(NULL, BAD_CAST "http://www.w3.org/2001/XMLSchema-instance", BAD_CAST "xsi"); *ppsNsGmd = xmlNewNs(NULL, BAD_CAST "http://www.isotc211.org/2005/gmd", BAD_CAST "gmd"); /* root element */ psRootNode = xmlNewNode(NULL, BAD_CAST "MD_Metadata"); xmlNewNs(psRootNode, BAD_CAST "http://www.isotc211.org/2005/gmd", BAD_CAST "gmd"); xmlNewNs(psRootNode, BAD_CAST "http://www.isotc211.org/2005/gco", BAD_CAST "gco"); xmlNewNs(psRootNode, BAD_CAST "http://www.w3.org/2001/XMLSchema-instance", BAD_CAST "xsi"); xmlSetNs(psRootNode, *ppsNsGmd); xmlNewNsProp(psRootNode, *ppsNsXsi, BAD_CAST "schemaLocation", BAD_CAST "http://www.isotc211.org/2005/gmd http://www.isotc211.org/2005/gmd/gmd.xsd"); /* gmd:identifier */ xmlAddChild(psRootNode, _msMetadataGetCharacterString(*ppsNsGmd, "fileIdentifier", layer->name, ppsNsGco)); /* gmd:language */ xmlAddChild(psRootNode, _msMetadataGetCharacterString(*ppsNsGmd, "language", (char *)msOWSGetLanguage(map, "exception"), ppsNsGco)); /* gmd:hierarchyLevel */ xmlAddChild(psRootNode, _msMetadataGetCodeList(*ppsNsGmd, "hierarchyLevel", "MD_ScopeCode", "dataset")); /* gmd:contact */ xmlAddChild(psRootNode, _msMetadataGetContact(*ppsNsGmd, "contact", map, ppsNsGco)); /* gmd:dateStamp */ /* TODO: nil for now, find way to derive this automagically */ xmlAddChild(psRootNode, _msMetadataGetCharacterString(*ppsNsGmd, "dateStamp", NULL, ppsNsGco)); /* gmd:metadataStandardName */ xmlAddChild(psRootNode, _msMetadataGetCharacterString(*ppsNsGmd, "metadataStandardName", "ISO 19115:2003 - Geographic information - Metadata", ppsNsGco)); /* gmd:metadataStandardVersion */ xmlAddChild(psRootNode, _msMetadataGetCharacterString(*ppsNsGmd, "metadataStandardVersion", "ISO 19115:2003", ppsNsGco)); /* gmd:spatialRepresentationInfo */ xmlAddChild(psRootNode, _msMetadataGetSpatialRepresentationInfo(*ppsNsGmd, layer, ppsNsGco)); /* gmd:referenceSystemInfo */ xmlAddChild(psRootNode, _msMetadataGetReferenceSystemInfo(*ppsNsGmd, layer, ppsNsGco)); /* gmd:identificationInfo */ xmlAddChild(psRootNode, _msMetadataGetIdentificationInfo(*ppsNsGmd, map, layer, ppsNsGco)); /* gmd:distributionInfo */ xmlAddChild(psRootNode, _msMetadataGetDistributionInfo(*ppsNsGmd, map, layer, cgi_request, ppsNsGco)); } return psRootNode; } /************************************************************************/ /* msMetadataDispatch */ /* */ /* Entry point for metadata requests. */ /* */ /* - If this is a valid request then it is processed and MS_SUCCESS */ /* is returned on success, or MS_FAILURE on failure. */ /* */ /* - If this does not appear to be a valid WFS request then MS_DONE */ /* is returned and MapServer is expected to process this as a regular */ /* MapServer request. */ /************************************************************************/ int msMetadataDispatch(mapObj *map, cgiRequestObj *cgi_request, owsRequestObj *ows_request) { int i; int status = MS_SUCCESS; xmlNodePtr psRootNode = NULL; xmlDocPtr xml_document; metadataParamsObj *paramsObj; layerObj *layer = NULL; xmlNsPtr psNsOws = NULL; xmlNsPtr psNsXsi = NULL; xmlNsPtr psNsGmd = NULL; xmlNsPtr psNsGco = NULL; /* Populate the Params object based on the request */ paramsObj = msMetadataCreateParamsObj(); xml_document = xmlNewDoc(BAD_CAST "1.0"); if (msMetadataParseRequest(map, cgi_request, ows_request, paramsObj) == MS_FAILURE) { psRootNode = msMetadataGetExceptionReport(map, "InvalidRequest", "layer", "Request parsing failed", &psNsOws); status = MS_FAILURE; } /* if layer= is not specified, */ if (paramsObj->pszLayer==NULL || strlen(paramsObj->pszLayer)<=0) { psRootNode = msMetadataGetExceptionReport(map, "MissingParameterValue", "layer", "Missing layer parameter", &psNsOws); status = MS_FAILURE; } if (status == MS_SUCCESS) { /* Start dispatching request */ /* Check that layer requested exists in mapfile */ for (i=0; inumlayers; i++) { if(strcasecmp(GET_LAYER(map, i)->name, paramsObj->pszLayer) == 0) { layer = GET_LAYER(map, i); break; } } if (layer != NULL && msOWSLookupMetadata(&(layer->metadata), "MFCO", "metadataurl_href")) { msIO_setHeader("Status", "301 Moved Permanently"); msIO_setHeader("Location", "%s", msOWSLookupMetadata(&(layer->metadata), "MFCO", "metadataurl_href")); msIO_sendHeaders(); } else { psRootNode = msMetadataGetLayerMetadata(map, paramsObj, cgi_request, ows_request, &psNsOws, &psNsXsi, &psNsGmd, &psNsGco); } } if (psRootNode != NULL) { xmlChar *xml_buffer = NULL; int buffersize = 0; xmlDocSetRootElement(xml_document, psRootNode); msIO_setHeader("Content-type", "text/xml"); msIO_sendHeaders(); xmlDocDumpFormatMemory(xml_document, &xml_buffer, &buffersize, 1); msIO_printf("%s", (char *) xml_buffer); xmlFree(xml_buffer); } xmlFreeDoc(xml_document); if( psNsOws ) xmlFreeNs(psNsOws); if( psNsXsi ) xmlFreeNs(psNsXsi); if( psNsGmd ) xmlFreeNs(psNsGmd); if( psNsGco ) xmlFreeNs(psNsGco); msMetadataFreeParamsObj(paramsObj); return status; } /************************************************************************/ /* msMetadataCreateParamsObj */ /* */ /* Create a parameter object, initialize it. */ /* The caller should free the object using msMetadataFreeParamsObj. */ /************************************************************************/ metadataParamsObj *msMetadataCreateParamsObj() { metadataParamsObj *paramsObj = (metadataParamsObj *)calloc(1, sizeof(metadataParamsObj)); MS_CHECK_ALLOC(paramsObj, sizeof(metadataParamsObj), NULL); paramsObj->pszLayer = NULL; paramsObj->pszOutputSchema = NULL; return paramsObj; } /************************************************************************/ /* msMetadataFreeParmsObj */ /* */ /* Free params object. */ /************************************************************************/ void msMetadataFreeParamsObj(metadataParamsObj *metadataparams) { if (metadataparams) { free(metadataparams->pszRequest); free(metadataparams->pszLayer); free(metadataparams->pszOutputSchema); free(metadataparams); } } /************************************************************************/ /* msMetadataParseRequest */ /* */ /* Parse request into the params object. */ /************************************************************************/ int msMetadataParseRequest(mapObj *map, cgiRequestObj *request, owsRequestObj *ows_request, metadataParamsObj *metadataparams) { int i = 0; if (!request || !metadataparams) return MS_FAILURE; if (request->NumParams > 0) { for(i=0; iNumParams; i++) { if (request->ParamNames[i] && request->ParamValues[i]) { if (strcasecmp(request->ParamNames[i], "LAYER") == 0) metadataparams->pszLayer = msStrdup(request->ParamValues[i]); if (strcasecmp(request->ParamNames[i], "OUTPUTSCHEMA") == 0) metadataparams->pszOutputSchema = msStrdup(request->ParamValues[i]); } } } return MS_SUCCESS; } /************************************************************************/ /* msMetadataSetGetMetadataURL */ /* */ /* Parse request into the params object. */ /************************************************************************/ void msMetadataSetGetMetadataURL(layerObj *lp, const char *url) { char *pszMetadataURL=NULL; pszMetadataURL = msStrdup(url); msDecodeHTMLEntities(pszMetadataURL); pszMetadataURL = msStringConcatenate(pszMetadataURL, "request=GetMetadata&layer="); pszMetadataURL = msStringConcatenate(pszMetadataURL, lp->name); msInsertHashTable(&(lp->metadata), "ows_metadataurl_href", pszMetadataURL); msInsertHashTable(&(lp->metadata), "ows_metadataurl_type", "TC211"); msInsertHashTable(&(lp->metadata), "ows_metadataurl_format", "text/xml"); msInsertHashTable(&(lp->metadata), "ows_metadatalink_href", pszMetadataURL); msInsertHashTable(&(lp->metadata), "ows_metadatalink_type", "TC211"); msInsertHashTable(&(lp->metadata), "ows_metadatalink_format", "text/xml"); msFree(pszMetadataURL); } mapserver-7.4.3/mapmssql2008.c000066400000000000000000003461471357574274700161100ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MS SQL Server Layer Connector * Author: Richard Hillman - based on PostGIS and SpatialDB connectors * Tamas Szekeres - maintenance * ****************************************************************************** * Copyright (c) 2007 IS Consulting (www.mapdotnet.com) * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** * * Revision 1.0 2007/7/1 * Created. * */ #define _CRT_SECURE_NO_WARNINGS 1 /* $Id$ */ #include #include "mapserver.h" #include "maptime.h" #include "mapows.h" #ifdef USE_MSSQL2008 #include #include #include #include #include #include /* tolower() */ /* SqlGeometry/SqlGeography serialization format Simple Point (SerializationProps & IsSinglePoint) [SRID][0x01][SerializationProps][Point][z][m] Simple Line Segment (SerializationProps & IsSingleLineSegment) [SRID][0x01][SerializationProps][Point1][Point2][z1][z2][m1][m2] Complex Geometries [SRID][VersionAttribute][SerializationProps][NumPoints][Point1]..[PointN][z1]..[zN][m1]..[mN] [NumFigures][Figure]..[Figure][NumShapes][Shape]..[Shape] Complex Geometries (FigureAttribute == Curve) [SRID][VersionAttribute][SerializationProps][NumPoints][Point1]..[PointN][z1]..[zN][m1]..[mN] [NumFigures][Figure]..[Figure][NumShapes][Shape]..[Shape][NumSegments][SegmentType]..[SegmentType] VersionAttribute (1 byte) 0x01 = Katmai (MSSQL2008+) 0x02 = Denali (MSSQL2012+) SRID Spatial Reference Id (4 bytes) SerializationProps (bitmask) 1 byte 0x01 = HasZValues 0x02 = HasMValues 0x04 = IsValid 0x08 = IsSinglePoint 0x10 = IsSingleLineSegment 0x20 = IsLargerThanAHemisphere Point (2-4)x8 bytes, size depends on SerializationProps & HasZValues & HasMValues [x][y] - SqlGeometry [latitude][longitude] - SqlGeography Figure [FigureAttribute][PointOffset] FigureAttribute - Katmai (1 byte) 0x00 = Interior Ring 0x01 = Stroke 0x02 = Exterior Ring FigureAttribute - Denali (1 byte) 0x00 = None 0x01 = Line 0x02 = Arc 0x03 = Curve Shape [ParentFigureOffset][FigureOffset][ShapeType] ShapeType (1 byte) 0x00 = Unknown 0x01 = Point 0x02 = LineString 0x03 = Polygon 0x04 = MultiPoint 0x05 = MultiLineString 0x06 = MultiPolygon 0x07 = GeometryCollection -- Denali 0x08 = CircularString 0x09 = CompoundCurve 0x0A = CurvePolygon 0x0B = FullGlobe SegmentType (1 byte) 0x00 = Line 0x01 = Arc 0x02 = FirstLine 0x03 = FirstArc */ /* Native geometry parser macros */ /* parser error codes */ #define NOERROR 0 #define NOT_ENOUGH_DATA 1 #define CORRUPT_DATA 2 #define UNSUPPORTED_GEOMETRY_TYPE 3 /* geometry format to transfer geometry column */ #define MSSQLGEOMETRY_NATIVE 0 #define MSSQLGEOMETRY_WKB 1 #define MSSQLGEOMETRY_WKT 2 /* geometry column types */ #define MSSQLCOLTYPE_GEOMETRY 0 #define MSSQLCOLTYPE_GEOGRAPHY 1 #define MSSQLCOLTYPE_BINARY 2 #define MSSQLCOLTYPE_TEXT 3 #define SP_NONE 0 #define SP_HASZVALUES 1 #define SP_HASMVALUES 2 #define SP_ISVALID 4 #define SP_ISSINGLEPOINT 8 #define SP_ISSINGLELINESEGMENT 0x10 #define SP_ISLARGERTHANAHEMISPHERE 0x20 #define ST_UNKNOWN 0 #define ST_POINT 1 #define ST_LINESTRING 2 #define ST_POLYGON 3 #define ST_MULTIPOINT 4 #define ST_MULTILINESTRING 5 #define ST_MULTIPOLYGON 6 #define ST_GEOMETRYCOLLECTION 7 #define ST_CIRCULARSTRING 8 #define ST_COMPOUNDCURVE 9 #define ST_CURVEPOLYGON 10 #define ST_FULLGLOBE 11 #define SMT_LINE 0 #define SMT_ARC 1 #define SMT_FIRSTLINE 2 #define SMT_FIRSTARC 3 #define ReadInt32(nPos) (*((unsigned int*)(gpi->pszData + (nPos)))) #define ReadByte(nPos) (gpi->pszData[nPos]) #define ReadDouble(nPos) (*((double*)(gpi->pszData + (nPos)))) #define ParentOffset(iShape) (ReadInt32(gpi->nShapePos + (iShape) * 9 )) #define FigureOffset(iShape) (ReadInt32(gpi->nShapePos + (iShape) * 9 + 4)) #define ShapeType(iShape) (ReadByte(gpi->nShapePos + (iShape) * 9 + 8)) #define SegmentType(iSegment) (ReadByte(gpi->nSegmentPos + (iSegment))) #define NextFigureOffset(iShape) (iShape + 1 < gpi->nNumShapes? FigureOffset((iShape) +1) : gpi->nNumFigures) #define FigureAttribute(iFigure) (ReadByte(gpi->nFigurePos + (iFigure) * 5)) #define PointOffset(iFigure) (ReadInt32(gpi->nFigurePos + (iFigure) * 5 + 1)) #define NextPointOffset(iFigure) (iFigure + 1 < gpi->nNumFigures? PointOffset((iFigure) +1) : gpi->nNumPoints) #define ReadX(iPoint) (ReadDouble(gpi->nPointPos + 16 * (iPoint))) #define ReadY(iPoint) (ReadDouble(gpi->nPointPos + 16 * (iPoint) + 8)) #define ReadZ(iPoint) (ReadDouble(gpi->nPointPos + 16 * gpi->nNumPoints + 8 * (iPoint))) #define ReadM(iPoint) (ReadDouble(gpi->nPointPos + 24 * gpi->nNumPoints + 8 * (iPoint))) #define FP_EPSILON 1e-12 #define SEGMENT_ANGLE 5.0 #define SEGMENT_MINPOINTS 10 /* Native geometry parser struct */ typedef struct msGeometryParserInfo_t { unsigned char* pszData; int nLen; /* version */ char chVersion; /* serialization properties */ char chProps; /* point array */ int nPointSize; int nPointPos; int nNumPoints; int nNumPointsRead; /* figure array */ int nFigurePos; int nNumFigures; /* shape array */ int nShapePos; int nNumShapes; int nSRSId; /* segment array */ int nSegmentPos; int nNumSegments; /* geometry or geography */ int nColType; /* bounds */ double minx; double miny; double maxx; double maxy; } msGeometryParserInfo; /* Structure for connection to an ODBC database (Microsoft preferred way to connect to SQL Server 2005 from c/c++) */ typedef struct msODBCconn_t { SQLHENV henv; /* ODBC HENV */ SQLHDBC hdbc; /* ODBC HDBC */ SQLHSTMT hstmt; /* ODBC HSTMNT */ char errorMessage[1024]; /* Last error message if any */ } msODBCconn; typedef struct ms_MSSQL2008_layer_info_t { char *sql; /* sql query to send to DB */ long row_num; /* what row is the NEXT to be read (for random access) */ char *geom_column; /* name of the actual geometry column parsed from the LAYER's DATA field */ char *geom_column_type; /* the type of the geometry column */ char *geom_table; /* the table name or sub-select decalred in the LAYER's DATA field */ char *urid_name; /* name of user-specified unique identifier or OID */ char *user_srid; /* zero length = calculate, non-zero means using this value! */ char *index_name; /* hopefully this isn't necessary - but if the optimizer ain't cuttin' it... */ char *sort_spec; /* the sort by specification which should be applied to the generated select statement */ int mssqlversion_major; /* the sql server major version number */ SQLSMALLINT *itemtypes; /* storing the sql field types for further reference */ msODBCconn * conn; /* Connection to db */ msGeometryParserInfo gpi; /* struct for the geometry parser */ int geometry_format; /* Geometry format to be retrieved from the database */ tokenListNodeObjPtr current_node; /* filter expression translation */ } msMSSQL2008LayerInfo; #define SQL_COLUMN_NAME_MAX_LENGTH 128 #define SQL_TABLE_NAME_MAX_LENGTH 128 #define DATA_ERROR_MESSAGE \ "%s" \ "Error with MSSQL2008 data variable. You specified '%s'.
\n" \ "Standard ways of specifiying are :
\n(1) 'geometry_column from geometry_table'
\n(2) 'geometry_column from (<sub query>) as foo using unique <column name> using SRID=<srid#>'

\n\n" \ "Make sure you utilize the 'using unique <column name>' and 'using with <index name>' clauses in.\n\n

" \ "For more help, please see http://www.mapdotnet.com \n\n

" \ "mapmssql2008.c - version of 2007/7/1.\n" /* Native geometry parser code */ void ReadPoint(msGeometryParserInfo* gpi, pointObj* p, int iPoint) { if (gpi->nColType == MSSQLCOLTYPE_GEOGRAPHY) { p->x = ReadY(iPoint); p->y = ReadX(iPoint); } else { p->x = ReadX(iPoint); p->y = ReadY(iPoint); } /* calculate bounds */ if (gpi->nNumPointsRead++ == 0) { gpi->minx = gpi->maxx = p->x; gpi->miny = gpi->maxy = p->y; } else { if (gpi->minx > p->x) gpi->minx = p->x; else if (gpi->maxx < p->x) gpi->maxx = p->x; if (gpi->miny > p->y) gpi->miny = p->y; else if (gpi->maxy < p->y) gpi->maxy = p->y; } #ifdef USE_POINT_Z_M if ((gpi->chProps & SP_HASZVALUES) && (gpi->chProps & SP_HASMVALUES)) { p->z = ReadZ(iPoint); p->m = ReadM(iPoint); } else if (gpi->chProps & SP_HASZVALUES) { p->z = ReadZ(iPoint); p->m = 0.0; } else if (gpi->chProps & SP_HASMVALUES) { p->z = 0.0; p->m = ReadZ(iPoint); } else { p->z = 0.0; p->m = 0.0; } #endif } int StrokeArcToLine(msGeometryParserInfo* gpi, lineObj* line, int index) { if (index > 1) { double x, y, x1, y1, x2, y2, x3, y3, dxa, dya, sxa, sya, dxb, dyb; double d, sxb, syb, ox, oy, a1, a3, sa, da, a, radius; int numpoints; #ifdef USE_POINT_Z_M double z; z = line->point[index].z; /* must be equal for arc segments */ #endif /* first point */ x1 = line->point[index - 2].x; y1 = line->point[index - 2].y; /* second point */ x2 = line->point[index - 1].x; y2 = line->point[index - 1].y; /* third point */ x3 = line->point[index].x; y3 = line->point[index].y; sxa = (x1 + x2); sya = (y1 + y2); dxa = x2 - x1; dya = y2 - y1; sxb = (x2 + x3); syb = (y2 + y3); dxb = x3 - x2; dyb = y3 - y2; d = (dxa * dyb - dya * dxb) * 2; if (fabs(d) < FP_EPSILON) { /* points are colinear, nothing to do here */ return index; } /* calculating the center of circle */ ox = ((sya - syb) * dya * dyb + sxa * dyb * dxa - sxb * dya * dxb) / d; oy = ((sxb - sxa) * dxa * dxb + syb * dyb * dxa - sya * dya * dxb) / d; radius = sqrt((x1 - ox) * (x1 - ox) + (y1 - oy) * (y1 - oy)); /* calculating the angle to be used */ a1 = atan2(y1 - oy, x1 - ox); a3 = atan2(y3 - oy, x3 - ox); if (d > 0) { /* draw counterclockwise */ if (a3 > a1) /* Wrapping past 180? */ sa = a3 - a1; else sa = a3 - a1 + 2.0 * M_PI ; } else { if (a3 > a1) /* Wrapping past 180? */ sa = a3 - a1 + 2.0 * M_PI; else sa = a3 - a1; } numpoints = (int)floor(fabs(sa) * 180 / SEGMENT_ANGLE / M_PI); if (numpoints < SEGMENT_MINPOINTS) numpoints = SEGMENT_MINPOINTS; da = sa / numpoints; /* extend the point array */ line->numpoints += numpoints - 2; line->point = msSmallRealloc(line->point, sizeof(pointObj) * line->numpoints); --index; a = a1 + da; while (numpoints > 1) { line->point[index].x = x = ox + radius * cos(a); line->point[index].y = y = oy + radius * sin(a); #ifdef USE_POINT_Z_M line->point[index].z = z; #endif /* calculate bounds */ if (gpi->minx > x) gpi->minx = x; else if (gpi->maxx < x) gpi->maxx = x; if (gpi->miny > y) gpi->miny = y; else if (gpi->maxy < y) gpi->maxy = y; a += da; ++index; --numpoints; } /* set last point */ line->point[index].x = x3; line->point[index].y = y3; #ifdef USE_POINT_Z_M line->point[index].z = z; #endif } return index; } int ParseSqlGeometry(msMSSQL2008LayerInfo* layerinfo, shapeObj *shape) { msGeometryParserInfo* gpi = &layerinfo->gpi; gpi->nNumPointsRead = 0; if (gpi->nLen < 10) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } /* store the SRS id for further use */ gpi->nSRSId = ReadInt32(0); gpi->chVersion = ReadByte(4); if (gpi->chVersion > 2) { msDebug("ParseSqlGeometry CORRUPT_DATA\n"); return CORRUPT_DATA; } gpi->chProps = ReadByte(5); gpi->nPointSize = 16; if ( gpi->chProps & SP_HASMVALUES ) gpi->nPointSize += 8; if ( gpi->chProps & SP_HASZVALUES ) gpi->nPointSize += 8; if ( gpi->chProps & SP_ISSINGLEPOINT ) { // single point geometry gpi->nNumPoints = 1; if (gpi->nLen < 6 + gpi->nPointSize) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) msSmallMalloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) msSmallMalloc(sizeof(pointObj)); shape->line[0].numpoints = 1; gpi->nPointPos = 6; ReadPoint(gpi, &shape->line[0].point[0], 0); } else if ( gpi->chProps & SP_ISSINGLELINESEGMENT ) { // single line segment with 2 points gpi->nNumPoints = 2; if (gpi->nLen < 6 + 2 * gpi->nPointSize) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } shape->type = MS_SHAPE_LINE; shape->line = (lineObj *) msSmallMalloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) msSmallMalloc(sizeof(pointObj) * 2); shape->line[0].numpoints = 2; gpi->nPointPos = 6; ReadPoint(gpi, &shape->line[0].point[0], 0); ReadPoint(gpi, &shape->line[0].point[1], 1); } else { int iShape, iFigure, iSegment; // complex geometries gpi->nNumPoints = ReadInt32(6); if ( gpi->nNumPoints <= 0 ) { return NOERROR; } // position of the point array gpi->nPointPos = 10; // position of the figures gpi->nFigurePos = gpi->nPointPos + gpi->nPointSize * gpi->nNumPoints + 4; if (gpi->nLen < gpi->nFigurePos) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } gpi->nNumFigures = ReadInt32(gpi->nFigurePos - 4); if ( gpi->nNumFigures <= 0 ) { return NOERROR; } // position of the shapes gpi->nShapePos = gpi->nFigurePos + 5 * gpi->nNumFigures + 4; if (gpi->nLen < gpi->nShapePos) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } gpi->nNumShapes = ReadInt32(gpi->nShapePos - 4); if (gpi->nLen < gpi->nShapePos + 9 * gpi->nNumShapes) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } if ( gpi->nNumShapes <= 0 ) { return NOERROR; } // pick up the root shape if ( ParentOffset(0) != 0xFFFFFFFF) { msDebug("ParseSqlGeometry CORRUPT_DATA\n"); return CORRUPT_DATA; } // determine the shape type for (iShape = 0; iShape < gpi->nNumShapes; iShape++) { unsigned char shapeType = ShapeType(iShape); if (shapeType == ST_POINT || shapeType == ST_MULTIPOINT) { shape->type = MS_SHAPE_POINT; break; } else if (shapeType == ST_LINESTRING || shapeType == ST_MULTILINESTRING || shapeType == ST_CIRCULARSTRING || shapeType == ST_COMPOUNDCURVE) { shape->type = MS_SHAPE_LINE; break; } else if (shapeType == ST_POLYGON || shapeType == ST_MULTIPOLYGON || shapeType == ST_CURVEPOLYGON) { shape->type = MS_SHAPE_POLYGON; break; } } shape->line = (lineObj *) msSmallMalloc(sizeof(lineObj) * gpi->nNumFigures); shape->numlines = gpi->nNumFigures; gpi->nNumSegments = 0; // read figures for (iFigure = 0; iFigure < gpi->nNumFigures; iFigure++) { int iPoint, iNextPoint, i; iPoint = PointOffset(iFigure); iNextPoint = NextPointOffset(iFigure); shape->line[iFigure].point = (pointObj *) msSmallMalloc(sizeof(pointObj)*(iNextPoint - iPoint)); shape->line[iFigure].numpoints = iNextPoint - iPoint; i = 0; if (gpi->chVersion == 0x02 && FigureAttribute(iFigure) >= 0x02) { int nPointPrepared = 0; lineObj* line = &shape->line[iFigure]; if (FigureAttribute(iFigure) == 0x03) { if (gpi->nNumSegments == 0) { /* position of the segment types */ gpi->nSegmentPos = gpi->nShapePos + 9 * gpi->nNumShapes + 4; gpi->nNumSegments = ReadInt32(gpi->nSegmentPos - 4); if (gpi->nLen < gpi->nSegmentPos + gpi->nNumSegments) { msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n"); return NOT_ENOUGH_DATA; } iSegment = 0; } while (iPoint < iNextPoint && iSegment < gpi->nNumSegments) { ReadPoint(gpi, &line->point[i], iPoint); ++iPoint; ++nPointPrepared; if (nPointPrepared == 2 && (SegmentType(iSegment) == SMT_FIRSTLINE || SegmentType(iSegment) == SMT_LINE)) { ++iSegment; nPointPrepared = 1; } else if (nPointPrepared == 3 && (SegmentType(iSegment) == SMT_FIRSTARC || SegmentType(iSegment) == SMT_ARC)) { i = StrokeArcToLine(gpi, line, i); ++iSegment; nPointPrepared = 1; } ++i; } } else { while (iPoint < iNextPoint) { ReadPoint(gpi, &line->point[i], iPoint); ++iPoint; ++nPointPrepared; if (nPointPrepared == 3) { i = StrokeArcToLine(gpi, line, i); nPointPrepared = 1; } ++i; } } } else { while (iPoint < iNextPoint) { ReadPoint(gpi, &shape->line[iFigure].point[i], iPoint); ++iPoint; ++i; } } } } /* set bounds */ shape->bounds.minx = gpi->minx; shape->bounds.miny = gpi->miny; shape->bounds.maxx = gpi->maxx; shape->bounds.maxy = gpi->maxy; return NOERROR; } /* MS SQL driver code*/ msMSSQL2008LayerInfo *getMSSQL2008LayerInfo(const layerObj *layer) { return layer->layerinfo; } void setMSSQL2008LayerInfo(layerObj *layer, msMSSQL2008LayerInfo *MSSQL2008layerinfo) { layer->layerinfo = (void*) MSSQL2008layerinfo; } void handleSQLError(layerObj *layer) { SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH]; SQLLEN NativeError; SQLSMALLINT i, MsgLen; SQLRETURN rc; msMSSQL2008LayerInfo *layerinfo = getMSSQL2008LayerInfo(layer); if (layerinfo == NULL) return; // Get the status records. i = 1; while ((rc = SQLGetDiagRec(SQL_HANDLE_STMT, layerinfo->conn->hstmt, i, SqlState, &NativeError, Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) { if(layer->debug) { msDebug("SQLError: %s\n", Msg); } i++; } } /* remove white space */ /* dont send in empty strings or strings with just " " in them! */ static char* removeWhite(char *str) { int initial; char *orig, *loc; initial = strspn(str, " "); if(initial) { memmove(str, str + initial, strlen(str) - initial + 1); } /* now final */ if(strlen(str) == 0) { return str; } if(str[strlen(str) - 1] == ' ') { /* have to remove from end */ orig = str; loc = &str[strlen(str) - 1]; while((*loc = ' ') && (loc >orig)) { *loc = 0; loc--; } } return str; } /* TODO Take a look at glibc's strcasestr */ static char *strstrIgnoreCase(const char *haystack, const char *needle) { char *hay_lower; char *needle_lower; int len_hay,len_need; int t; char *loc; int match = -1; len_hay = strlen(haystack); len_need = strlen(needle); hay_lower = (char*) msSmallMalloc(len_hay + 1); needle_lower =(char*) msSmallMalloc(len_need + 1); for(t = 0; t < len_hay; t++) { hay_lower[t] = (char)tolower(haystack[t]); } hay_lower[t] = 0; for(t = 0; t < len_need; t++) { needle_lower[t] = (char)tolower(needle[t]); } needle_lower[t] = 0; loc = strstr(hay_lower, needle_lower); if(loc) { match = loc - hay_lower; } msFree(hay_lower); msFree(needle_lower); return (char *) (match < 0 ? NULL : haystack + match); } static int msMSSQL2008LayerParseData(layerObj *layer, char **geom_column_name, char **geom_column_type, char **table_name, char **urid_name, char **user_srid, char **index_name, char **sort_spec, int debug); /* Close connection and handles */ static void msMSSQL2008CloseConnection(void *conn_handle) { msODBCconn * conn = (msODBCconn *) conn_handle; if (!conn) { return; } if (conn->hstmt) { SQLFreeHandle(SQL_HANDLE_STMT, conn->hstmt); } if (conn->hdbc) { SQLDisconnect(conn->hdbc); SQLFreeHandle(SQL_HANDLE_DBC, conn->hdbc); } if (conn->henv) { SQLFreeHandle(SQL_HANDLE_ENV, conn->henv); } msFree(conn); } /* Set the error string for the connection */ static void setConnError(msODBCconn *conn) { SQLSMALLINT len; SQLGetDiagField(SQL_HANDLE_DBC, conn->hdbc, 1, SQL_DIAG_MESSAGE_TEXT, (SQLPOINTER) conn->errorMessage, sizeof(conn->errorMessage), &len); conn->errorMessage[len] = 0; } /* Connect to db */ static msODBCconn * mssql2008Connect(const char * connString) { SQLCHAR outConnString[1024]; SQLSMALLINT outConnStringLen; SQLRETURN rc; msODBCconn * conn = msSmallMalloc(sizeof(msODBCconn)); memset(conn, 0, sizeof(*conn)); SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &conn->henv); SQLSetEnvAttr(conn->henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0); SQLAllocHandle(SQL_HANDLE_DBC, conn->henv, &conn->hdbc); if (strcasestr(connString, "DRIVER=") == 0) { SQLCHAR fullConnString[1024]; snprintf((char*)fullConnString, sizeof(fullConnString), "DRIVER={SQL Server};%s", connString); rc = SQLDriverConnect(conn->hdbc, NULL, fullConnString, SQL_NTS, outConnString, 1024, &outConnStringLen, SQL_DRIVER_NOPROMPT); } else { rc = SQLDriverConnect(conn->hdbc, NULL, connString, SQL_NTS, outConnString, 1024, &outConnStringLen, SQL_DRIVER_NOPROMPT); } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { setConnError(conn); return conn; } SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &conn->hstmt); return conn; } /* Set the error string for the statement execution */ static void setStmntError(msODBCconn *conn) { SQLSMALLINT len; SQLGetDiagField(SQL_HANDLE_STMT, conn->hstmt, 1, SQL_DIAG_MESSAGE_TEXT, (SQLPOINTER) conn->errorMessage, sizeof(conn->errorMessage), &len); conn->errorMessage[len] = 0; } /* Execute SQL against connection. Set error string if failed */ static int executeSQL(msODBCconn *conn, const char * sql) { SQLRETURN rc; SQLCloseCursor(conn->hstmt); rc = SQLExecDirect(conn->hstmt, (SQLCHAR *) sql, SQL_NTS); if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { return 1; } else { setStmntError(conn); return 0; } } /* Get columns name from query results */ static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLength, layerObj *layer, char pass_field_def, SQLSMALLINT *itemType) { SQLRETURN rc; SQLCHAR columnName[SQL_COLUMN_NAME_MAX_LENGTH + 1]; SQLSMALLINT columnNameLen; SQLSMALLINT dataType; SQLULEN columnSize; SQLSMALLINT decimalDigits; SQLSMALLINT nullable; msMSSQL2008LayerInfo *layerinfo = getMSSQL2008LayerInfo(layer); rc = SQLDescribeCol( conn->hstmt, (SQLUSMALLINT)index, columnName, SQL_COLUMN_NAME_MAX_LENGTH, &columnNameLen, &dataType, &columnSize, &decimalDigits, &nullable); if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { if (bufferLength < SQL_COLUMN_NAME_MAX_LENGTH + 1) strlcpy(buffer, (const char *)columnName, bufferLength); else strlcpy(buffer, (const char *)columnName, SQL_COLUMN_NAME_MAX_LENGTH + 1); *itemType = dataType; if (pass_field_def) { char md_item_name[256]; char gml_width[32], gml_precision[32]; const char *gml_type = NULL; gml_width[0] = '\0'; gml_precision[0] = '\0'; switch( dataType ) { case SQL_INTEGER: case SQL_SMALLINT: case SQL_TINYINT: gml_type = "Integer"; break; case SQL_BIGINT: gml_type = "Long"; break; case SQL_REAL: case SQL_FLOAT: case SQL_DOUBLE: case SQL_DECIMAL: case SQL_NUMERIC: gml_type = "Real"; if( decimalDigits > 0 ) sprintf( gml_precision, "%d", decimalDigits ); break; case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: gml_type = "Date"; break; case SQL_BIT: gml_type = "Boolean"; break; default: gml_type = "Character"; break; } if( columnSize > 0 ) sprintf( gml_width, "%d", columnSize ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", buffer ); if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", buffer ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",buffer ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_nillable",buffer ); if( nullable > 0 ) msInsertHashTable(&(layer->metadata), md_item_name, "true" ); } return 1; } else { setStmntError(conn); return 0; } } /* open up a connection to the MS SQL 2008 database using the connection string in layer->connection */ /* ie. "driver=;server=;database=;integrated security=?;user id=;password=" */ int msMSSQL2008LayerOpen(layerObj *layer) { msMSSQL2008LayerInfo *layerinfo; char *index, *maskeddata; int i, count; char *conn_decrypted = NULL; if(layer->debug) { msDebug("msMSSQL2008LayerOpen called datastatement: %s\n", layer->data); } if(getMSSQL2008LayerInfo(layer)) { if(layer->debug) { msDebug("msMSSQL2008LayerOpen :: layer is already open!!\n"); } return MS_SUCCESS; /* already open */ } if(!layer->data) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerOpen()", "", "Error parsing MSSQL2008 data variable: nothing specified in DATA statement.

\n\nMore Help:

\n\n"); return MS_FAILURE; } if(!layer->connection) { msSetError( MS_QUERYERR, "MSSQL connection parameter not specified.", "msMSSQL2008LayerOpen()"); return MS_FAILURE; } /* have to setup a connection to the database */ layerinfo = (msMSSQL2008LayerInfo*) msSmallMalloc(sizeof(msMSSQL2008LayerInfo)); layerinfo->sql = NULL; /* calc later */ layerinfo->row_num = 0; layerinfo->geom_column = NULL; layerinfo->geom_column_type = NULL; layerinfo->geom_table = NULL; layerinfo->urid_name = NULL; layerinfo->user_srid = NULL; layerinfo->index_name = NULL; layerinfo->sort_spec = NULL; layerinfo->conn = NULL; layerinfo->itemtypes = NULL; layerinfo->mssqlversion_major = 0; layerinfo->conn = (msODBCconn *) msConnPoolRequest(layer); if(!layerinfo->conn) { if(layer->debug) { msDebug("MSMSSQL2008LayerOpen -- shared connection not available.\n"); } /* Decrypt any encrypted token in connection and attempt to connect */ conn_decrypted = msDecryptStringTokens(layer->map, layer->connection); if (conn_decrypted == NULL) { return(MS_FAILURE); /* An error should already have been produced */ } layerinfo->conn = mssql2008Connect(conn_decrypted); msFree(conn_decrypted); conn_decrypted = NULL; if(!layerinfo->conn || layerinfo->conn->errorMessage[0]) { char *errMess = "Out of memory"; msDebug("FAILURE!!!"); maskeddata = (char *)msSmallMalloc(strlen(layer->connection) + 1); strcpy(maskeddata, layer->connection); index = strstr(maskeddata, "password="); if(index != NULL) { index = (char *)(index + 9); count = (int)(strstr(index, " ") - index); for(i = 0; i < count; i++) { strlcpy(index, "*", (int)1); index++; } } if (layerinfo->conn) { errMess = layerinfo->conn->errorMessage; } msSetError(MS_QUERYERR, "Couldnt make connection to MS SQL Server 2008 with connect string '%s'.\n
\n" "Error reported was '%s'.\n
\n\n" "This error occured when trying to make a connection to the specified SQL server. \n" "
\nMost commonly this is caused by
\n" "(1) incorrect connection string
\n" "(2) you didn't specify a 'user id=...' in your connection string
\n" "(3) SQL server isnt running
\n" "(4) TCPIP not enabled for SQL Client or server
\n\n", "msMSSQL2008LayerOpen()", maskeddata, errMess); msFree(maskeddata); msMSSQL2008CloseConnection(layerinfo->conn); msFree(layerinfo); return MS_FAILURE; } msConnPoolRegister(layer, layerinfo->conn, msMSSQL2008CloseConnection); } setMSSQL2008LayerInfo(layer, layerinfo); if (msMSSQL2008LayerParseData(layer, &layerinfo->geom_column, &layerinfo->geom_column_type, &layerinfo->geom_table, &layerinfo->urid_name, &layerinfo->user_srid, &layerinfo->index_name, &layerinfo->sort_spec, layer->debug) != MS_SUCCESS) { msSetError( MS_QUERYERR, "Could not parse the layer data", "msMSSQL2008LayerOpen()"); return MS_FAILURE; } /* identify the geometry transfer type */ if (msLayerGetProcessingKey( layer, "MSSQL_READ_WKB" ) != NULL) layerinfo->geometry_format = MSSQLGEOMETRY_WKB; else { layerinfo->geometry_format = MSSQLGEOMETRY_NATIVE; if (strcasecmp(layerinfo->geom_column_type, "geography") == 0) layerinfo->gpi.nColType = MSSQLCOLTYPE_GEOGRAPHY; else layerinfo->gpi.nColType = MSSQLCOLTYPE_GEOMETRY; } return MS_SUCCESS; } /* Return MS_TRUE if layer is open, MS_FALSE otherwise. */ int msMSSQL2008LayerIsOpen(layerObj *layer) { return getMSSQL2008LayerInfo(layer) ? MS_TRUE : MS_FALSE; } /* Free the itemindexes array in a layer. */ void msMSSQL2008LayerFreeItemInfo(layerObj *layer) { if(layer->debug) { msDebug("msMSSQL2008LayerFreeItemInfo called\n"); } if(layer->iteminfo) { msFree(layer->iteminfo); } layer->iteminfo = NULL; } /* allocate the iteminfo index array - same order as the item list */ int msMSSQL2008LayerInitItemInfo(layerObj *layer) { int i; int *itemindexes ; if (layer->debug) { msDebug("msMSSQL2008LayerInitItemInfo called\n"); } if(layer->numitems == 0) { return MS_SUCCESS; } msFree(layer->iteminfo); layer->iteminfo = (int *) msSmallMalloc(sizeof(int) * layer->numitems); itemindexes = (int*)layer->iteminfo; for(i = 0; i < layer->numitems; i++) { itemindexes[i] = i; /* last one is always the geometry one - the rest are non-geom */ } return MS_SUCCESS; } static int getMSSQLMajorVersion(layerObj* layer) { msMSSQL2008LayerInfo *layerinfo = getMSSQL2008LayerInfo(layer); if (layerinfo == NULL) return 0; if (layerinfo->mssqlversion_major == 0) { char* mssqlversion_major = msLayerGetProcessingKey(layer, "MSSQL_VERSION_MAJOR"); if (mssqlversion_major != NULL) { layerinfo->mssqlversion_major = atoi(mssqlversion_major); } else { /* need to query from database */ if (executeSQL(layerinfo->conn, "SELECT SERVERPROPERTY('ProductVersion')")) { SQLRETURN rc = SQLFetch(layerinfo->conn->hstmt); if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { /* process results */ char result_data[256]; SQLLEN retLen = 0; rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_CHAR, result_data, sizeof(result_data), &retLen); if (rc != SQL_ERROR) { result_data[retLen] = 0; layerinfo->mssqlversion_major = atoi(result_data); } } } } } return layerinfo->mssqlversion_major; } /* Get the layer extent as specified in the mapfile or a largest area */ /* covering all features */ int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent) { msMSSQL2008LayerInfo *layerinfo; char *query = 0; char result_data[256]; SQLLEN retLen; SQLRETURN rc; if(layer->debug) { msDebug("msMSSQL2008LayerGetExtent called\n"); } if (!(layer->extent.minx == -1.0 && layer->extent.miny == -1.0 && layer->extent.maxx == -1.0 && layer->extent.maxy == -1.0)) { /* extent was already set */ extent->minx = layer->extent.minx; extent->miny = layer->extent.miny; extent->maxx = layer->extent.maxx; extent->maxy = layer->extent.maxy; } layerinfo = getMSSQL2008LayerInfo(layer); if (!layerinfo) { msSetError(MS_QUERYERR, "GetExtent called with layerinfo = NULL", "msMSSQL2008LayerGetExtent()"); return MS_FAILURE; } /* set up statement */ if (getMSSQLMajorVersion(layer) >= 11) { if (strcasecmp(layerinfo->geom_column_type, "geography") == 0) { query = msStringConcatenate(query, "WITH extent(extentcol) AS (SELECT geometry::EnvelopeAggregate(geometry::STGeomFromWKB("); query = msStringConcatenate(query, layerinfo->geom_column); query = msStringConcatenate(query, ".STAsBinary(), "); query = msStringConcatenate(query, layerinfo->geom_column); query = msStringConcatenate(query, ".STSrid)"); } else { query = msStringConcatenate(query, "WITH extent(extentcol) AS (SELECT geometry::EnvelopeAggregate("); query = msStringConcatenate(query, layerinfo->geom_column); } query = msStringConcatenate(query, ") AS extentcol FROM "); query = msStringConcatenate(query, layerinfo->geom_table); query = msStringConcatenate(query, ") SELECT extentcol.STPointN(1).STX, extentcol.STPointN(1).STY, extentcol.STPointN(3).STX, extentcol.STPointN(3).STY FROM extent"); } else { if (strcasecmp(layerinfo->geom_column_type, "geography") == 0) { query = msStringConcatenate(query, "WITH ENVELOPE as (SELECT geometry::STGeomFromWKB("); query = msStringConcatenate(query, layerinfo->geom_column); query = msStringConcatenate(query, ".STAsBinary(), "); query = msStringConcatenate(query, layerinfo->geom_column); query = msStringConcatenate(query, ".STSrid)"); } else { query = msStringConcatenate(query, "WITH ENVELOPE as (SELECT "); query = msStringConcatenate(query, layerinfo->geom_column); } query = msStringConcatenate(query, ".STEnvelope() as envelope from "); query = msStringConcatenate(query, layerinfo->geom_table); query = msStringConcatenate(query, "), CORNERS as (SELECT envelope.STPointN(1) as point from ENVELOPE UNION ALL select envelope.STPointN(3) from ENVELOPE) SELECT MIN(point.STX), MIN(point.STY), MAX(point.STX), MAX(point.STY) FROM CORNERS"); } if (!executeSQL(layerinfo->conn, query)) { msFree(query); return MS_FAILURE; } msFree(query); /* process results */ rc = SQLFetch(layerinfo->conn->hstmt); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { if (layer->debug) { msDebug("msMSSQL2008LayerGetExtent: No results found.\n"); } return MS_FAILURE; } rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_CHAR, result_data, sizeof(result_data), &retLen); if (rc == SQL_ERROR) { msSetError(MS_QUERYERR, "Failed to get MinX value", "msMSSQL2008LayerGetExtent()"); return MS_FAILURE; } result_data[retLen] = 0; extent->minx = atof(result_data); rc = SQLGetData(layerinfo->conn->hstmt, 2, SQL_C_CHAR, result_data, sizeof(result_data), &retLen); if (rc == SQL_ERROR) { msSetError(MS_QUERYERR, "Failed to get MinY value", "msMSSQL2008LayerGetExtent()"); return MS_FAILURE; } result_data[retLen] = 0; extent->miny = atof(result_data); rc = SQLGetData(layerinfo->conn->hstmt, 3, SQL_C_CHAR, result_data, sizeof(result_data), &retLen); if (rc == SQL_ERROR) { msSetError(MS_QUERYERR, "Failed to get MaxX value", "msMSSQL2008LayerGetExtent()"); return MS_FAILURE; } result_data[retLen] = 0; extent->maxx = atof(result_data); rc = SQLGetData(layerinfo->conn->hstmt, 4, SQL_C_CHAR, result_data, sizeof(result_data), &retLen); if (rc == SQL_ERROR) { msSetError(MS_QUERYERR, "Failed to get MaxY value", "msMSSQL2008LayerGetExtent()"); return MS_FAILURE; } result_data[retLen] = 0; extent->maxy = atof(result_data); return MS_SUCCESS; } /* Get the layer feature count */ int msMSSQL2008LayerGetNumFeatures(layerObj *layer) { msMSSQL2008LayerInfo *layerinfo; char *query = 0; char result_data[256]; SQLLEN retLen; SQLRETURN rc; if (layer->debug) { msDebug("msMSSQL2008LayerGetNumFeatures called\n"); } layerinfo = getMSSQL2008LayerInfo(layer); if (!layerinfo) { msSetError(MS_QUERYERR, "GetNumFeatures called with layerinfo = NULL", "msMSSQL2008LayerGetNumFeatures()"); return -1; } /* set up statement */ query = msStringConcatenate(query, "SELECT count(*) FROM "); query = msStringConcatenate(query, layerinfo->geom_table); /* adding attribute filter */ if (layer->filter.native_string) { query = msStringConcatenate(query, " WHERE ("); query = msStringConcatenate(query, layer->filter.native_string); query = msStringConcatenate(query, ")"); } else if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { query = msStringConcatenate(query, " WHERE ("); query = msStringConcatenate(query, msLayerGetProcessingKey(layer, "NATIVE_FILTER")); query = msStringConcatenate(query, ")"); } if (!executeSQL(layerinfo->conn, query)) { msFree(query); return -1; } msFree(query); rc = SQLFetch(layerinfo->conn->hstmt); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { if (layer->debug) { msDebug("msMSSQL2008LayerGetNumFeatures: No results found.\n"); } return -1; } rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_CHAR, result_data, sizeof(result_data), &retLen); if (rc == SQL_ERROR) { msSetError(MS_QUERYERR, "Failed to get feature count", "msMSSQL2008LayerGetNumFeatures()"); return -1; } result_data[retLen] = 0; return atoi(result_data); } /* Prepare and execute the SQL statement for this layer */ static int prepare_database(layerObj *layer, rectObj rect, char **query_string) { msMSSQL2008LayerInfo *layerinfo; char *query = 0; char *data_source = 0; char *f_table_name = 0; char *geom_table = 0; /* "Geometry::STGeomFromText('POLYGON(())',)" + terminator = 40 chars Plus 10 formatted doubles (15 digits of precision, a decimal point, a space/comma delimiter each = 17 chars each) Plus SRID + comma - if SRID is a long...we'll be safe with 10 chars */ char box3d[40 + 10 * 22 + 11]; int t; char *pos_from, *pos_ftab, *pos_space, *pos_paren; rectObj extent; int hasFilter = MS_FALSE; layerinfo = getMSSQL2008LayerInfo(layer); /* Extract the proper f_table_name from the geom_table string. * We are expecting the geom_table to be either a single word * or a sub-select clause that possibly includes a join -- * * (select column[,column[,...]] from ftab[ natural join table2]) as foo * * We are expecting whitespace or a ')' after the ftab name. * */ geom_table = msStrdup(layerinfo->geom_table); pos_from = strstrIgnoreCase(geom_table, " from "); if(!pos_from) { f_table_name = (char *) msSmallMalloc(strlen(geom_table) + 1); strcpy(f_table_name, geom_table); } else { /* geom_table is a sub-select clause */ pos_ftab = pos_from + 6; /* This should be the start of the ftab name */ pos_space = strstr(pos_ftab, " "); /* First space */ /* TODO strrchr is POSIX and C99, rindex is neither */ #if defined(_WIN32) && !defined(__CYGWIN__) pos_paren = strrchr(pos_ftab, ')'); #else pos_paren = rindex(pos_ftab, ')'); #endif if(!pos_space || !pos_paren) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "prepare_database()", geom_table, "Error parsing MSSQL2008 data variable: Something is wrong with your subselect statement.

\n\nMore Help:

\n\n"); return MS_FAILURE; } if (pos_paren < pos_space) { /* closing parenthesis preceeds any space */ f_table_name = (char *) msSmallMalloc(pos_paren - pos_ftab + 1); strlcpy(f_table_name, pos_ftab, pos_paren - pos_ftab + 1); } else { f_table_name = (char *) msSmallMalloc(pos_space - pos_ftab + 1); strlcpy(f_table_name, pos_ftab, pos_space - pos_ftab + 1); } } if (rect.minx == rect.maxx || rect.miny == rect.maxy) { /* create point shape for rectangles with zero area */ sprintf(box3d, "%s::STGeomFromText('POINT(%.15g %.15g)',%s)", /* %s.STSrid)", */ layerinfo->geom_column_type, rect.minx, rect.miny, layerinfo->user_srid); } else { sprintf(box3d, "%s::STGeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%s)", /* %s.STSrid)", */ layerinfo->geom_column_type, rect.minx, rect.miny, rect.maxx, rect.miny, rect.maxx, rect.maxy, rect.minx, rect.maxy, rect.minx, rect.miny, layerinfo->user_srid ); } /* substitute token '!BOX!' in geom_table with the box3d - do an unlimited # of subs */ /* to not undo the work here, we need to make sure that data_source is malloc'd here */ if (!strstr(geom_table, "!BOX!")) { data_source = (char *)msSmallMalloc(strlen(geom_table) + 1); strcpy(data_source, geom_table); } else { char* result = NULL; while (strstr(geom_table, "!BOX!")) { /* need to do a substition */ char *start, *end; char *oldresult = result; start = strstr(geom_table, "!BOX!"); end = start + 5; result = (char *)msSmallMalloc((start - geom_table) + strlen(box3d) + strlen(end) + 1); strlcpy(result, geom_table, start - geom_table + 1); strcpy(result + (start - geom_table), box3d); strcat(result, end); geom_table = result; msFree(oldresult); } /* if we're here, this will be a malloc'd string, so no need to copy it */ data_source = (char *)geom_table; } /* start creating the query */ query = msStringConcatenate(query, "SELECT "); /* adding items to the select list */ for (t = 0; t < layer->numitems; t++) { #ifdef USE_ICONV query = msStringConcatenate(query, "convert(nvarchar(max), ["); query = msStringConcatenate(query, layer->items[t]); query = msStringConcatenate(query, "]),"); #else query = msStringConcatenate(query, "convert(varchar(max), ["); query = msStringConcatenate(query, layer->items[t]); query = msStringConcatenate(query, "]),"); #endif } /* adding geometry column */ query = msStringConcatenate(query, "["); query = msStringConcatenate(query, layerinfo->geom_column); if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) query = msStringConcatenate(query, "],"); else query = msStringConcatenate(query, "].STAsBinary(),"); /* adding id column */ query = msStringConcatenate(query, "convert(varchar(36), ["); query = msStringConcatenate(query, layerinfo->urid_name); query = msStringConcatenate(query, "]) FROM "); /* adding the source */ query = msStringConcatenate(query, data_source); msFree(data_source); msFree(f_table_name); /* use the index hint if provided */ if (layerinfo->index_name) { query = msStringConcatenate(query, " WITH (INDEX("); query = msStringConcatenate(query, layerinfo->index_name); query = msStringConcatenate(query, "))"); } /* adding attribute filter */ if (layer->filter.native_string) { query = msStringConcatenate(query, " WHERE ("); query = msStringConcatenate(query, layer->filter.native_string); query = msStringConcatenate(query, ")"); hasFilter = MS_TRUE; } else if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { query = msStringConcatenate(query, " WHERE ("); query = msStringConcatenate(query, msLayerGetProcessingKey(layer, "NATIVE_FILTER")); query = msStringConcatenate(query, ")"); hasFilter = MS_TRUE; } /* adding spatial filter */ if (hasFilter == MS_FALSE) query = msStringConcatenate(query, " WHERE "); else query = msStringConcatenate(query, " AND "); query = msStringConcatenate(query, layerinfo->geom_column); query = msStringConcatenate(query, ".STIntersects("); query = msStringConcatenate(query, box3d); query = msStringConcatenate(query, ") = 1 "); if (layerinfo->sort_spec) { query = msStringConcatenate(query, layerinfo->sort_spec); } /* Add extra sort by */ if( layer->sortBy.nProperties > 0 ) { char* pszTmp = msLayerBuildSQLOrderBy(layer); if (layerinfo->sort_spec) query = msStringConcatenate(query, ", "); else query = msStringConcatenate(query, " ORDER BY "); query = msStringConcatenate(query, pszTmp); msFree(pszTmp); } if (layer->debug) { msDebug("query:%s\n", query); } if (executeSQL(layerinfo->conn, query)) { char pass_field_def = 0; int t; const char *value; *query_string = query; /* collect result information */ if ((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value, "auto") == 0) pass_field_def = 1; msFree(layerinfo->itemtypes); layerinfo->itemtypes = msSmallMalloc(sizeof(SQLSMALLINT) * (layer->numitems + 1)); for (t = 0; t < layer->numitems; t++) { char colBuff[256]; SQLSMALLINT itemType; columnName(layerinfo->conn, t + 1, colBuff, sizeof(colBuff), layer, pass_field_def, &itemType); layerinfo->itemtypes[t] = itemType; } return MS_SUCCESS; } else { msSetError(MS_QUERYERR, "Error executing MSSQL2008 SQL statement: %s\n-%s\n", "msMSSQL2008LayerGetShape()", query, layerinfo->conn->errorMessage); msFree(query); return MS_FAILURE; } } /* Execute SQL query for this layer */ int msMSSQL2008LayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msMSSQL2008LayerInfo *layerinfo = 0; char *query_str = 0; int set_up_result; if(layer->debug) { msDebug("msMSSQL2008LayerWhichShapes called\n"); } layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { /* layer not opened yet */ msSetError(MS_QUERYERR, "msMSSQL2008LayerWhichShapes called on unopened layer (layerinfo = NULL)", "msMSSQL2008LayerWhichShapes()"); return MS_FAILURE; } if(!layer->data) { msSetError(MS_QUERYERR, "Missing DATA clause in MSSQL2008 Layer definition. DATA statement must contain 'geometry_column from table_name' or 'geometry_column from (sub-query) as foo'.", "msMSSQL2008LayerWhichShapes()"); return MS_FAILURE; } set_up_result = prepare_database(layer, rect, &query_str); if(set_up_result != MS_SUCCESS) { msFree(query_str); return set_up_result; /* relay error */ } msFree(layerinfo->sql); layerinfo->sql = query_str; layerinfo->row_num = 0; return MS_SUCCESS; } /* Close the MSSQL2008 record set and connection */ int msMSSQL2008LayerClose(layerObj *layer) { msMSSQL2008LayerInfo *layerinfo; layerinfo = getMSSQL2008LayerInfo(layer); if(layer->debug) { char *data = ""; if (layer->data) { data = layer->data; } msDebug("msMSSQL2008LayerClose datastatement: %s\n", data); } if(layer->debug && !layerinfo) { msDebug("msMSSQL2008LayerClose -- layerinfo is NULL\n"); } if(layerinfo) { msConnPoolRelease(layer, layerinfo->conn); layerinfo->conn = NULL; if(layerinfo->user_srid) { msFree(layerinfo->user_srid); layerinfo->user_srid = NULL; } if(layerinfo->urid_name) { msFree(layerinfo->urid_name); layerinfo->urid_name = NULL; } if(layerinfo->index_name) { msFree(layerinfo->index_name); layerinfo->index_name = NULL; } if(layerinfo->sort_spec) { msFree(layerinfo->sort_spec); layerinfo->sort_spec = NULL; } if(layerinfo->sql) { msFree(layerinfo->sql); layerinfo->sql = NULL; } if(layerinfo->geom_column) { msFree(layerinfo->geom_column); layerinfo->geom_column = NULL; } if(layerinfo->geom_column_type) { msFree(layerinfo->geom_column_type); layerinfo->geom_column_type = NULL; } if(layerinfo->geom_table) { msFree(layerinfo->geom_table); layerinfo->geom_table = NULL; } if(layerinfo->itemtypes) { msFree(layerinfo->itemtypes); layerinfo->itemtypes = NULL; } setMSSQL2008LayerInfo(layer, NULL); msFree(layerinfo); } return MS_SUCCESS; } /* ******************************************************* */ /* wkb is assumed to be 2d (force_2d) */ /* and wkb is a GEOMETRYCOLLECTION (force_collection) */ /* and wkb is in the endian of this computer (asbinary(...,'[XN]DR')) */ /* each of the sub-geom inside the collection are point,linestring, or polygon */ /* */ /* also, int is 32bits long */ /* double is 64bits long */ /* ******************************************************* */ /* convert the wkb into points */ /* points -> pass through */ /* lines-> constituent points */ /* polys-> treat ring like line and pull out the consituent points */ static int force_to_points(char *wkb, shapeObj *shape) { /* we're going to make a 'line' for each entity (point, line or ring) in the geom collection */ int offset = 0; int pt_offset; int ngeoms; int t, u, v; int type, nrings, npoints; lineObj line = {0, NULL}; shape->type = MS_SHAPE_NULL; /* nothing in it */ memcpy(&ngeoms, &wkb[5], 4); offset = 9; /* were the first geometry is */ for(t=0; t < ngeoms; t++) { memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ if(type == 1) { /* Point */ shape->type = MS_SHAPE_POINT; line.numpoints = 1; line.point = (pointObj *) msSmallMalloc(sizeof(pointObj)); memcpy(&line.point[0].x, &wkb[offset + 5], 8); memcpy(&line.point[0].y, &wkb[offset + 5 + 8], 8); offset += 5 + 16; msAddLine(shape, &line); msFree(line.point); } else if(type == 2) { /* Linestring */ shape->type = MS_SHAPE_POINT; memcpy(&line.numpoints, &wkb[offset+5], 4); /* num points */ line.point = (pointObj *) msSmallMalloc(sizeof(pointObj) * line.numpoints); for(u = 0; u < line.numpoints; u++) { memcpy( &line.point[u].x, &wkb[offset+9 + (16 * u)], 8); memcpy( &line.point[u].y, &wkb[offset+9 + (16 * u)+8], 8); } offset += 9 + 16 * line.numpoints; /* length of object */ msAddLine(shape, &line); msFree(line.point); } else if(type == 3) { /* Polygon */ shape->type = MS_SHAPE_POINT; memcpy(&nrings, &wkb[offset+5],4); /* num rings */ /* add a line for each polygon ring */ pt_offset = 0; offset += 9; /* now points at 1st linear ring */ for(u = 0; u < nrings; u++) { /* for each ring, make a line */ memcpy(&npoints, &wkb[offset], 4); /* num points */ line.numpoints = npoints; line.point = (pointObj *) msSmallMalloc(sizeof(pointObj)* npoints); /* point struct */ for(v = 0; v < npoints; v++) { memcpy(&line.point[v].x, &wkb[offset + 4 + (16 * v)], 8); memcpy(&line.point[v].y, &wkb[offset + 4 + (16 * v) + 8], 8); } /* make offset point to next linear ring */ msAddLine(shape, &line); msFree(line.point); offset += 4 + 16 *npoints; } } } return MS_SUCCESS; } /* convert the wkb into lines */ /* points-> remove */ /* lines -> pass through */ /* polys -> treat rings as lines */ static int force_to_lines(char *wkb, shapeObj *shape) { int offset = 0; int pt_offset; int ngeoms; int t, u, v; int type, nrings, npoints; lineObj line = {0, NULL}; shape->type = MS_SHAPE_NULL; /* nothing in it */ memcpy(&ngeoms, &wkb[5], 4); offset = 9; /* were the first geometry is */ for(t=0; t < ngeoms; t++) { memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ /* cannot do anything with a point */ if(type == 2) { /* Linestring */ shape->type = MS_SHAPE_LINE; memcpy(&line.numpoints, &wkb[offset + 5], 4); line.point = (pointObj*) msSmallMalloc(sizeof(pointObj) * line.numpoints ); for(u=0; u < line.numpoints; u++) { memcpy(&line.point[u].x, &wkb[offset + 9 + (16 * u)], 8); memcpy(&line.point[u].y, &wkb[offset + 9 + (16 * u)+8], 8); } offset += 9 + 16 * line.numpoints; /* length of object */ msAddLine(shape, &line); msFree(line.point); } else if(type == 3) { /* polygon */ shape->type = MS_SHAPE_LINE; memcpy(&nrings, &wkb[offset + 5], 4); /* num rings */ /* add a line for each polygon ring */ pt_offset = 0; offset += 9; /* now points at 1st linear ring */ for(u = 0; u < nrings; u++) { /* for each ring, make a line */ memcpy(&npoints, &wkb[offset], 4); line.numpoints = npoints; line.point = (pointObj*) msSmallMalloc(sizeof(pointObj) * npoints); /* point struct */ for(v = 0; v < npoints; v++) { memcpy(&line.point[v].x, &wkb[offset + 4 + (16 * v)], 8); memcpy(&line.point[v].y, &wkb[offset + 4 + (16 * v) + 8], 8); } /* make offset point to next linear ring */ msAddLine(shape, &line); msFree(line.point); offset += 4 + 16 * npoints; } } } return MS_SUCCESS; } /* point -> reject */ /* line -> reject */ /* polygon -> lines of linear rings */ static int force_to_polygons(char *wkb, shapeObj *shape) { int offset = 0; int pt_offset; int ngeoms; int t, u, v; int type, nrings, npoints; lineObj line = {0, NULL}; shape->type = MS_SHAPE_NULL; /* nothing in it */ memcpy(&ngeoms, &wkb[5], 4); offset = 9; /* were the first geometry is */ for(t = 0; t < ngeoms; t++) { memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ if(type == 3) { /* polygon */ shape->type = MS_SHAPE_POLYGON; memcpy(&nrings, &wkb[offset + 5], 4); /* num rings */ /* add a line for each polygon ring */ pt_offset = 0; offset += 9; /* now points at 1st linear ring */ for(u=0; u < nrings; u++) { /* for each ring, make a line */ memcpy(&npoints, &wkb[offset], 4); /* num points */ line.numpoints = npoints; line.point = (pointObj*) msSmallMalloc(sizeof(pointObj) * npoints); for(v=0; v < npoints; v++) { memcpy(&line.point[v].x, &wkb[offset + 4 + (16 * v)], 8); memcpy(&line.point[v].y, &wkb[offset + 4 + (16 * v) + 8], 8); } /* make offset point to next linear ring */ msAddLine(shape, &line); msFree(line.point); offset += 4 + 16 * npoints; } } } return MS_SUCCESS; } /* if there is any polygon in wkb, return force_polygon */ /* if there is any line in wkb, return force_line */ /* otherwise return force_point */ static int dont_force(char *wkb, shapeObj *shape) { int offset =0; int ngeoms; int type, t; int best_type; best_type = MS_SHAPE_NULL; /* nothing in it */ memcpy(&ngeoms, &wkb[5], 4); offset = 9; /* were the first geometry is */ for(t = 0; t < ngeoms; t++) { memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ if(type == 3) { best_type = MS_SHAPE_POLYGON; } else if(type ==2 && best_type != MS_SHAPE_POLYGON) { best_type = MS_SHAPE_LINE; } else if(type == 1 && best_type == MS_SHAPE_NULL) { best_type = MS_SHAPE_POINT; } } if(best_type == MS_SHAPE_POINT) { return force_to_points(wkb, shape); } if(best_type == MS_SHAPE_LINE) { return force_to_lines(wkb, shape); } if(best_type == MS_SHAPE_POLYGON) { return force_to_polygons(wkb, shape); } return MS_FAILURE; /* unknown type */ } /* ******************************************************* */ /* wkb assumed to be same endian as this machine. */ /* Should be in little endian (default if created by Microsoft platforms) */ /* ******************************************************* */ /* convert the wkb into points */ /* points -> pass through */ /* lines-> constituent points */ /* polys-> treat ring like line and pull out the consituent points */ static int force_to_shapeType(char *wkb, shapeObj *shape, int msShapeType) { int offset = 0; int ngeoms = 1; int u, v; int type, nrings, npoints; lineObj line = {0, NULL}; shape->type = MS_SHAPE_NULL; /* nothing in it */ do { ngeoms--; memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ if (type == 1) { /* Point */ shape->type = msShapeType; line.numpoints = 1; line.point = (pointObj *) msSmallMalloc(sizeof(pointObj)); memcpy(&line.point[0].x, &wkb[offset + 5], 8); memcpy(&line.point[0].y, &wkb[offset + 5 + 8], 8); offset += 5 + 16; if (msShapeType == MS_SHAPE_POINT) { msAddLine(shape, &line); } msFree(line.point); } else if(type == 2) { /* Linestring */ shape->type = msShapeType; memcpy(&line.numpoints, &wkb[offset+5], 4); /* num points */ line.point = (pointObj *) msSmallMalloc(sizeof(pointObj) * line.numpoints); for(u = 0; u < line.numpoints; u++) { memcpy( &line.point[u].x, &wkb[offset+9 + (16 * u)], 8); memcpy( &line.point[u].y, &wkb[offset+9 + (16 * u)+8], 8); } offset += 9 + 16 * line.numpoints; /* length of object */ if ((msShapeType == MS_SHAPE_POINT) || (msShapeType == MS_SHAPE_LINE)) { msAddLine(shape, &line); } msFree(line.point); } else if(type == 3) { /* Polygon */ shape->type = msShapeType; memcpy(&nrings, &wkb[offset+5],4); /* num rings */ /* add a line for each polygon ring */ offset += 9; /* now points at 1st linear ring */ for(u = 0; u < nrings; u++) { /* for each ring, make a line */ memcpy(&npoints, &wkb[offset], 4); /* num points */ line.numpoints = npoints; line.point = (pointObj *) msSmallMalloc(sizeof(pointObj)* npoints); /* point struct */ for(v = 0; v < npoints; v++) { memcpy(&line.point[v].x, &wkb[offset + 4 + (16 * v)], 8); memcpy(&line.point[v].y, &wkb[offset + 4 + (16 * v) + 8], 8); } /* make offset point to next linear ring */ msAddLine(shape, &line); msFree(line.point); offset += 4 + 16 *npoints; } } else if(type >= 4 && type <= 7) { int cnt = 0; offset += 5; memcpy(&cnt, &wkb[offset], 4); offset += 4; /* were the first geometry is */ ngeoms += cnt; } } while (ngeoms > 0); return MS_SUCCESS; } ///* if there is any polygon in wkb, return force_polygon */ ///* if there is any line in wkb, return force_line */ ///* otherwise return force_point */ //static int dont_force(char *wkb, shapeObj *shape) //{ // int offset =0; // int ngeoms = 1; // int type; // int best_type; // int u; // int nrings, npoints; // // best_type = MS_SHAPE_NULL; /* nothing in it */ // // do // { // ngeoms--; // // memcpy(&type, &wkb[offset + 1], 4); /* type of this geometry */ // // if(type == 3) { // best_type = MS_SHAPE_POLYGON; // } else if(type ==2 && best_type != MS_SHAPE_POLYGON) { // best_type = MS_SHAPE_LINE; // } else if(type == 1 && best_type == MS_SHAPE_NULL) { // best_type = MS_SHAPE_POINT; // } // // if (type == 1) // { // /* Point */ // offset += 5 + 16; // } // else if(type == 2) // { // int numPoints; // // memcpy(&numPoints, &wkb[offset+5], 4); /* num points */ // /* Linestring */ // offset += 9 + 16 * numPoints; /* length of object */ // } // else if(type == 3) // { // /* Polygon */ // memcpy(&nrings, &wkb[offset+5],4); /* num rings */ // offset += 9; /* now points at 1st linear ring */ // for(u = 0; u < nrings; u++) { // /* for each ring, make a line */ // memcpy(&npoints, &wkb[offset], 4); /* num points */ // offset += 4 + 16 *npoints; // } // } // else if(type >= 4 && type <= 7) // { // int cnt = 0; // // offset += 5; // // memcpy(&cnt, &wkb[offset], 4); // offset += 4; /* were the first geometry is */ // // ngeoms += cnt; // } // } // while (ngeoms > 0); // // return force_to_shapeType(wkb, shape, best_type); //} // /* find the bounds of the shape */ static void find_bounds(shapeObj *shape) { int t, u; int first_one = 1; for(t = 0; t < shape->numlines; t++) { for(u = 0; u < shape->line[t].numpoints; u++) { if(first_one) { shape->bounds.minx = shape->line[t].point[u].x; shape->bounds.maxx = shape->line[t].point[u].x; shape->bounds.miny = shape->line[t].point[u].y; shape->bounds.maxy = shape->line[t].point[u].y; first_one = 0; } else { if(shape->line[t].point[u].x < shape->bounds.minx) { shape->bounds.minx = shape->line[t].point[u].x; } if(shape->line[t].point[u].x > shape->bounds.maxx) { shape->bounds.maxx = shape->line[t].point[u].x; } if(shape->line[t].point[u].y < shape->bounds.miny) { shape->bounds.miny = shape->line[t].point[u].y; } if(shape->line[t].point[u].y > shape->bounds.maxy) { shape->bounds.maxy = shape->line[t].point[u].y; } } } } } /* Used by NextShape() to access a shape in the query set */ int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *record) { msMSSQL2008LayerInfo *layerinfo; int result; SQLLEN needLen = 0; SQLLEN retLen = 0; char dummyBuffer[1]; char *wkbBuffer; char *valueBuffer; char oidBuffer[ 16 ]; /* assuming the OID will always be a long this should be enough */ long record_oid; int t; /* for coercing single types into geometry collections */ char *wkbTemp; int geomType; layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { msSetError(MS_QUERYERR, "GetShape called with layerinfo = NULL", "msMSSQL2008LayerGetShape()"); return MS_FAILURE; } if(!layerinfo->conn) { msSetError(MS_QUERYERR, "NextShape called on MSSQL2008 layer with no connection to DB.", "msMSSQL2008LayerGetShape()"); return MS_FAILURE; } shape->type = MS_SHAPE_NULL; while(shape->type == MS_SHAPE_NULL) { /* SQLRETURN rc = SQLFetchScroll(layerinfo->conn->hstmt, SQL_FETCH_ABSOLUTE, (SQLLEN) (*record) + 1); */ /* We only do forward fetches. the parameter 'record' is ignored, but is incremented */ SQLRETURN rc = SQLFetch(layerinfo->conn->hstmt); /* Any error assume out of recordset bounds */ if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { handleSQLError(layer); return MS_DONE; } /* retreive an item */ { /* have to retrieve shape attributes */ shape->values = (char **) msSmallMalloc(sizeof(char *) * layer->numitems); shape->numvalues = layer->numitems; for(t=0; t < layer->numitems; t++) { /* figure out how big the buffer needs to be */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(t + 1), SQL_C_BINARY, dummyBuffer, 0, &needLen); if (rc == SQL_ERROR) handleSQLError(layer); if (needLen > 0) { /* allocate the buffer - this will be a null-terminated string so alloc for the null too */ valueBuffer = (char*) msSmallMalloc( needLen + 2 ); if ( valueBuffer == NULL ) { msSetError( MS_QUERYERR, "Could not allocate value buffer.", "msMSSQL2008LayerGetShapeRandom()" ); return MS_FAILURE; } /* Now grab the data */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(t + 1), SQL_C_BINARY, valueBuffer, needLen, &retLen); if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) handleSQLError(layer); /* Terminate the buffer */ valueBuffer[retLen] = 0; /* null terminate it */ /* Pop the value into the shape's value array */ #ifdef USE_ICONV valueBuffer[retLen + 1] = 0; shape->values[t] = msConvertWideStringToUTF8((wchar_t*)valueBuffer, "UCS-2LE"); msFree(valueBuffer); #else shape->values[t] = valueBuffer; #endif } else /* Copy empty sting for NULL values */ shape->values[t] = msStrdup(""); } /* Get shape geometry */ { /* Set up to request the size of the buffer needed */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(layer->numitems + 1), SQL_C_BINARY, dummyBuffer, 0, &needLen); if (rc == SQL_ERROR) handleSQLError(layer); /* allow space for coercion to geometry collection if needed*/ wkbTemp = (char*)msSmallMalloc(needLen+9); /* write data above space allocated for geometry collection coercion */ wkbBuffer = wkbTemp + 9; if ( wkbBuffer == NULL ) { msSetError( MS_QUERYERR, "Could not allocate value buffer.", "msMSSQL2008LayerGetShapeRandom()" ); return MS_FAILURE; } /* Grab the WKB */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(layer->numitems + 1), SQL_C_BINARY, wkbBuffer, needLen, &retLen); if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) handleSQLError(layer); if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) { layerinfo->gpi.pszData = (unsigned char*)wkbBuffer; layerinfo->gpi.nLen = retLen; if (!ParseSqlGeometry(layerinfo, shape)) { switch(layer->type) { case MS_LAYER_POINT: shape->type = MS_SHAPE_POINT; break; case MS_LAYER_LINE: shape->type = MS_SHAPE_LINE; break; case MS_LAYER_POLYGON: shape->type = MS_SHAPE_POLYGON; break; } } } else { memcpy(&geomType, wkbBuffer + 1, 4); /* is this a single type? */ if (geomType < 4) { /* copy byte order marker (although we don't check it) */ wkbTemp[0] = wkbBuffer[0]; wkbBuffer = wkbTemp; /* indicate type is geometry collection (although geomType + 3 would also work) */ wkbBuffer[1] = (char)7; wkbBuffer[2] = (char)0; wkbBuffer[3] = (char)0; wkbBuffer[4] = (char)0; /* indicate 1 shape */ wkbBuffer[5] = (char)1; wkbBuffer[6] = (char)0; wkbBuffer[7] = (char)0; wkbBuffer[8] = (char)0; } switch(layer->type) { case MS_LAYER_POINT: result = force_to_points(wkbBuffer, shape); break; case MS_LAYER_LINE: result = force_to_lines(wkbBuffer, shape); break; case MS_LAYER_POLYGON: result = force_to_polygons(wkbBuffer, shape); break; case MS_LAYER_QUERY: case MS_LAYER_CHART: result = dont_force(wkbBuffer, shape); break; case MS_LAYER_RASTER: msDebug( "Ignoring MS_LAYER_RASTER in mapMSSQL2008.c\n" ); break; case MS_LAYER_CIRCLE: msDebug( "Ignoring MS_LAYER_CIRCLE in mapMSSQL2008.c\n" ); break; default: msDebug( "Unsupported layer type in msMSSQL2008LayerNextShape()!" ); break; } find_bounds(shape); } //free(wkbBuffer); msFree(wkbTemp); } /* Next get unique id for row - since the OID shouldn't be larger than a long we'll assume billions as a limit */ rc = SQLGetData(layerinfo->conn->hstmt, (SQLUSMALLINT)(layer->numitems + 2), SQL_C_BINARY, oidBuffer, sizeof(oidBuffer) - 1, &retLen); if (rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) handleSQLError(layer); if (retLen < sizeof(oidBuffer)) { oidBuffer[retLen] = 0; record_oid = strtol(oidBuffer, NULL, 10); shape->index = record_oid; } else { /* non integer fid column, use single pass */ shape->index = -1; } shape->resultindex = (*record); (*record)++; /* move to next shape */ if(shape->type != MS_SHAPE_NULL) { return MS_SUCCESS; } else { msDebug("msMSSQL2008LayerGetShapeRandom bad shape: %d\n", *record); } /* if (layer->type == MS_LAYER_POINT) {return MS_DONE;} */ } } msFreeShape(shape); return MS_FAILURE; } /* find the next shape with the appropriate shape type (convert it if necessary) */ /* also, load in the attribute data */ /* MS_DONE => no more data */ int msMSSQL2008LayerNextShape(layerObj *layer, shapeObj *shape) { int result; msMSSQL2008LayerInfo *layerinfo; layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { msSetError(MS_QUERYERR, "NextShape called with layerinfo = NULL", "msMSSQL2008LayerNextShape()"); return MS_FAILURE; } result = msMSSQL2008LayerGetShapeRandom(layer, shape, &(layerinfo->row_num)); /* getshaperandom will increment the row_num */ /* layerinfo->row_num ++; */ return result; } /* Execute a query on the DB based on the query result. */ int msMSSQL2008LayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { char *query_str; char *columns_wanted = 0; msMSSQL2008LayerInfo *layerinfo; int t; char buffer[32000] = ""; long shapeindex = record->shapeindex; long resultindex = record->resultindex; if(layer->debug) { msDebug("msMSSQL2008LayerGetShape called for shapeindex = %i\n", shapeindex); } layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { /* Layer not open */ msSetError(MS_QUERYERR, "msMSSQL2008LayerGetShape called on unopened layer (layerinfo = NULL)", "msMSSQL2008LayerGetShape()"); return MS_FAILURE; } if (resultindex >= 0 && layerinfo->sql) { /* trying to provide the result from the current resultset (single-pass query) */ if( resultindex < layerinfo->row_num) { /* re-issue the query */ if (!executeSQL(layerinfo->conn, layerinfo->sql)) { msSetError(MS_QUERYERR, "Error executing MSSQL2008 SQL statement: %s\n-%s\n", "msMSSQL2008LayerGetShape()", layerinfo->sql, layerinfo->conn->errorMessage); return MS_FAILURE; } layerinfo->row_num = 0; } while( layerinfo->row_num < resultindex ) { /* move forward until we reach the desired index */ if (msMSSQL2008LayerGetShapeRandom(layer, shape, &(layerinfo->row_num)) != MS_SUCCESS) return MS_FAILURE; } return msMSSQL2008LayerGetShapeRandom(layer, shape, &(layerinfo->row_num)); } /* non single-pass case, fetch the record from the database */ if(layer->numitems == 0) { if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) snprintf(buffer, sizeof(buffer), "%s, convert(varchar(36), %s)", layerinfo->geom_column, layerinfo->urid_name); else snprintf(buffer, sizeof(buffer), "%s.STAsBinary(), convert(varchar(36), %s)", layerinfo->geom_column, layerinfo->urid_name); columns_wanted = msStrdup(buffer); } else { for(t = 0; t < layer->numitems; t++) { snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(varchar(max), %s),", layer->items[t]); } if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE) snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%s, convert(varchar(36), %s)", layerinfo->geom_column, layerinfo->urid_name); else snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%s.STAsBinary(), convert(varchar(36), %s)", layerinfo->geom_column, layerinfo->urid_name); columns_wanted = msStrdup(buffer); } /* index_name is ignored here since the hint should be for the spatial index, not the PK index */ snprintf(buffer, sizeof(buffer), "select %s from %s where %s = %d", columns_wanted, layerinfo->geom_table, layerinfo->urid_name, shapeindex); query_str = msStrdup(buffer); if(layer->debug) { msDebug("msMSSQL2008LayerGetShape: %s \n", query_str); } msFree(columns_wanted); if (!executeSQL(layerinfo->conn, query_str)) { msSetError(MS_QUERYERR, "Error executing MSSQL2008 SQL statement: %s\n-%s\n", "msMSSQL2008LayerGetShape()", query_str, layerinfo->conn->errorMessage); msFree(query_str); return MS_FAILURE; } /* we don't preserve the query string in this case (cannot be re-used) */ msFree(query_str); layerinfo->row_num = 0; return msMSSQL2008LayerGetShapeRandom(layer, shape, &(layerinfo->row_num)); } /* Query the DB for info about the requested table */ int msMSSQL2008LayerGetItems(layerObj *layer) { msMSSQL2008LayerInfo *layerinfo; char *sql = NULL; int t, sqlSize; char found_geom = 0; int item_num; SQLSMALLINT cols = 0; const char *value; /* * Pass the field definitions through to the layer metadata in the * "gml_[item]_{type,width,precision}" set of metadata items for * defining fields. */ char pass_field_def = 0; if(layer->debug) { msDebug("in msMSSQL2008LayerGetItems (find column names)\n"); } layerinfo = getMSSQL2008LayerInfo(layer); if(!layerinfo) { /* layer not opened yet */ msSetError(MS_QUERYERR, "msMSSQL2008LayerGetItems called on unopened layer", "msMSSQL2008LayerGetItems()"); return MS_FAILURE; } if(!layerinfo->conn) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetItems called on MSSQL2008 layer with no connection to DB.", "msMSSQL2008LayerGetItems()"); return MS_FAILURE; } sqlSize = strlen(layerinfo->geom_table) + 30; sql = msSmallMalloc(sizeof(char *) * sqlSize); snprintf(sql, sqlSize, "SELECT top 0 * FROM %s", layerinfo->geom_table); if (!executeSQL(layerinfo->conn, sql)) { msFree(sql); return MS_FAILURE; } msFree(sql); SQLNumResultCols (layerinfo->conn->hstmt, &cols); layer->numitems = cols - 1; /* dont include the geometry column */ layer->items = msSmallMalloc(sizeof(char *) * (layer->numitems + 1)); /* +1 in case there is a problem finding goeometry column */ layerinfo->itemtypes = msSmallMalloc(sizeof(SQLSMALLINT) * (layer->numitems + 1)); /* it will return an error if there is no geometry column found, */ /* so this isnt a problem */ found_geom = 0; /* havent found the geom field */ item_num = 0; /* consider populating the field definitions in metadata */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) pass_field_def = 1; for(t = 0; t < cols; t++) { char colBuff[256]; SQLSMALLINT itemType; columnName(layerinfo->conn, t + 1, colBuff, sizeof(colBuff), layer, pass_field_def, &itemType); if(strcmp(colBuff, layerinfo->geom_column) != 0) { /* this isnt the geometry column */ layer->items[item_num] = (char *) msSmallMalloc(strlen(colBuff) + 1); strcpy(layer->items[item_num], colBuff); layerinfo->itemtypes[item_num] = itemType; item_num++; } else { found_geom = 1; } } if(!found_geom) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetItems: tried to find the geometry column in the results from the database, but couldnt find it. Is it miss-capitialized? '%s'", "msMSSQL2008LayerGetItems()", layerinfo->geom_column); return MS_FAILURE; } return msMSSQL2008LayerInitItemInfo(layer); } /* Get primary key column of table */ int msMSSQL2008LayerRetrievePK(layerObj *layer, char **urid_name, char* table_name, int debug) { char sql[1024]; msMSSQL2008LayerInfo *layerinfo = 0; SQLRETURN rc; snprintf(sql, sizeof(sql), "SELECT convert(varchar(50), sys.columns.name) AS ColumnName, sys.indexes.name " "FROM sys.columns INNER JOIN " " sys.indexes INNER JOIN " " sys.tables ON sys.indexes.object_id = sys.tables.object_id INNER JOIN " " sys.index_columns ON sys.indexes.object_id = sys.index_columns.object_id AND sys.indexes.index_id = sys.index_columns.index_id ON " " sys.columns.object_id = sys.index_columns.object_id AND sys.columns.column_id = sys.index_columns.column_id " "WHERE (sys.indexes.is_primary_key = 1) AND (sys.tables.name = N'%s') ", table_name); if (debug) { msDebug("msMSSQL2008LayerRetrievePK: query = %s\n", sql); } layerinfo = (msMSSQL2008LayerInfo *) layer->layerinfo; if(layerinfo->conn == NULL) { msSetError(MS_QUERYERR, "Layer does not have a MSSQL2008 connection.", "msMSSQL2008LayerRetrievePK()"); return(MS_FAILURE); } /* error somewhere above here in this method */ if(!executeSQL(layerinfo->conn, sql)) { char *tmp1; char *tmp2 = NULL; tmp1 = "Error executing MSSQL2008 statement (msMSSQL2008LayerRetrievePK():"; tmp2 = (char *)msSmallMalloc(sizeof(char)*(strlen(tmp1) + strlen(sql) + 1)); strcpy(tmp2, tmp1); strcat(tmp2, sql); msSetError(MS_QUERYERR, tmp2, "msMSSQL2008LayerRetrievePK()"); msFree(tmp2); return(MS_FAILURE); } rc = SQLFetch(layerinfo->conn->hstmt); if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { if(debug) { msDebug("msMSSQL2008LayerRetrievePK: No results found.\n"); } return MS_FAILURE; } { char buff[100]; SQLLEN retLen; rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_BINARY, buff, sizeof(buff), &retLen); rc = SQLFetch(layerinfo->conn->hstmt); if(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) { if(debug) { msDebug("msMSSQL2008LayerRetrievePK: Multiple primary key columns are not supported in MapServer\n"); } return MS_FAILURE; } buff[retLen] = 0; *urid_name = msStrdup(buff); } return MS_SUCCESS; } /* Function to parse the Mapserver DATA parameter for geometry * column name, table name and name of a column to serve as a * unique record id */ static int msMSSQL2008LayerParseData(layerObj *layer, char **geom_column_name, char **geom_column_type, char **table_name, char **urid_name, char **user_srid, char **index_name, char **sort_spec, int debug) { char *pos_opt, *pos_scn, *tmp, *pos_srid, *pos_urid, *pos_geomtype, *pos_geomtype2, *pos_indexHint, *data, *pos_order; int slength; data = msStrdup(layer->data); /* replace tabs with spaces */ msReplaceChar(data, '\t', ' '); /* given a string of the from 'geom from ctivalues' or 'geom from () as foo' * return geom_column_name as 'geom' * and table name as 'ctivalues' or 'geom from () as foo' */ /* First look for the optional ' using unique ID' string */ pos_urid = strstrIgnoreCase(data, " using unique "); if(pos_urid) { /* CHANGE - protect the trailing edge for thing like 'using unique ftab_id using srid=33' */ tmp = strstr(pos_urid + 14, " "); if(!tmp) { tmp = pos_urid + strlen(pos_urid); } *urid_name = (char *) msSmallMalloc((tmp - (pos_urid + 14)) + 1); strlcpy(*urid_name, pos_urid + 14, (tmp - (pos_urid + 14)) + 1); } /* Find the srid */ pos_srid = strstrIgnoreCase(data, " using SRID="); if(!pos_srid) { *user_srid = (char *) msSmallMalloc(2); (*user_srid)[0] = '0'; (*user_srid)[1] = 0; } else { slength = strspn(pos_srid + 12, "-0123456789"); if(!slength) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable: You specified 'using SRID=#' but didn't have any numbers!

\n\nMore Help:

\n\n", data); msFree(data); return MS_FAILURE; } else { *user_srid = (char *) msSmallMalloc(slength + 1); strlcpy(*user_srid, pos_srid + 12, slength+1); } } pos_indexHint = strstrIgnoreCase(data, " using index "); if(pos_indexHint) { /* CHANGE - protect the trailing edge for thing like 'using unique ftab_id using srid=33' */ tmp = strstr(pos_indexHint + 13, " "); if(!tmp) { tmp = pos_indexHint + strlen(pos_indexHint); } *index_name = (char *) msSmallMalloc((tmp - (pos_indexHint + 13)) + 1); strlcpy(*index_name, pos_indexHint + 13, tmp - (pos_indexHint + 13)+1); } /* this is a little hack so the rest of the code works. If the ' using SRID=' comes before */ /* the ' using unique ', then make sure pos_opt points to where the ' using SRID' starts! */ pos_opt = pos_urid; if ( !pos_opt || ( pos_srid && pos_srid < pos_opt ) ) pos_opt = pos_srid; if ( !pos_opt || ( pos_indexHint && pos_indexHint < pos_opt ) ) pos_opt = pos_indexHint; if ( !pos_opt ) pos_opt = data + strlen(data); /* Scan for the table or sub-select clause */ pos_scn = strstrIgnoreCase(data, " from "); if(!pos_scn) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable. Must contain 'geometry_column from table_name' or 'geom from (subselect) as foo' (couldn't find ' from '). More help:

\n\n", data); msFree(data); return MS_FAILURE; } /* Scanning the geometry column type */ pos_geomtype = data; while (pos_geomtype < pos_scn && *pos_geomtype != '(' && *pos_geomtype != 0) ++pos_geomtype; if(*pos_geomtype == '(') { pos_geomtype2 = pos_geomtype; while (pos_geomtype2 < pos_scn && *pos_geomtype2 != ')' && *pos_geomtype2 != 0) ++pos_geomtype2; if (*pos_geomtype2 != ')' || pos_geomtype2 == pos_geomtype) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable. Invalid syntax near geometry column type.", data); msFree(data); return MS_FAILURE; } *geom_column_name = (char *) msSmallMalloc((pos_geomtype - data) + 1); strlcpy(*geom_column_name, data, pos_geomtype - data + 1); *geom_column_type = (char *) msSmallMalloc(pos_geomtype2 - pos_geomtype); strlcpy(*geom_column_type, pos_geomtype + 1, pos_geomtype2 - pos_geomtype); } else { /* Copy the geometry column name */ *geom_column_name = (char *) msSmallMalloc((pos_scn - data) + 1); strlcpy(*geom_column_name, data, pos_scn - data + 1); *geom_column_type = msStrdup("geometry"); } /* Copy out the table name or sub-select clause */ *table_name = (char *) msSmallMalloc((pos_opt - (pos_scn + 6)) + 1); strlcpy(*table_name, pos_scn + 6, pos_opt - (pos_scn + 6) + 1); if(strlen(*table_name) < 1 || strlen(*geom_column_name) < 1) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable. Must contain 'geometry_column from table_name' or 'geom from (subselect) as foo' (couldnt find a geometry_column or table/subselect). More help:

\n\n", data); msFree(data); return MS_FAILURE; } if( !pos_urid ) { if( msMSSQL2008LayerRetrievePK(layer, urid_name, *table_name, debug) != MS_SUCCESS ) { msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "No primary key defined for table, or primary key contains more that one column\n\n", *table_name); msFree(data); return MS_FAILURE; } } /* Find the order by */ pos_order = strstrIgnoreCase(pos_opt, " order by "); if (pos_order) { *sort_spec = msStrdup(pos_order); } if(debug) { msDebug("msMSSQL2008LayerParseData: unique column = %s, srid='%s', geom_column_name = %s, table_name=%s\n", *urid_name, *user_srid, *geom_column_name, *table_name); } msFree(data); return MS_SUCCESS; } char *msMSSQL2008LayerEscapePropertyName(layerObj *layer, const char* pszString) { char* pszEscapedStr=NULL; int i, j = 0; if (pszString && strlen(pszString) > 0) { int nLength = strlen(pszString); pszEscapedStr = (char*) msSmallMalloc( 1 + nLength + 1 + 1); pszEscapedStr[j++] = '['; for (i=0; ilayerinfo; if (!layerinfo->current_node) { msSetError(MS_MISCERR, "Unecpected end of expression", "msMSSQL2008LayerTranslateFilter()"); return 0; } switch(layerinfo->current_node->token) { case '(': filter->native_string = msStringConcatenate(filter->native_string, "("); /* process subexpression */ layerinfo->current_node = layerinfo->current_node->next; while (layerinfo->current_node != NULL) { if (!process_node(layer, filter)) return 0; if (!layerinfo->current_node) break; if (layerinfo->current_node->token == ')') break; layerinfo->current_node = layerinfo->current_node->next; } break; case ')': filter->native_string = msStringConcatenate(filter->native_string, ")"); break; /* argument separator */ case ',': break; /* literal tokens */ case MS_TOKEN_LITERAL_BOOLEAN: if(layerinfo->current_node->tokenval.dblval == MS_TRUE) filter->native_string = msStringConcatenate(filter->native_string, "1"); else filter->native_string = msStringConcatenate(filter->native_string, "0"); break; case MS_TOKEN_LITERAL_NUMBER: strtmpl = "%lf"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16); sprintf(snippet, strtmpl, layerinfo->current_node->tokenval.dblval); filter->native_string = msStringConcatenate(filter->native_string, snippet); msFree(snippet); break; case MS_TOKEN_LITERAL_STRING: strtmpl = "'%s'"; stresc = msMSSQL2008LayerEscapeSQLParam(layer, layerinfo->current_node->tokenval.strval); snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); sprintf(snippet, strtmpl, stresc); filter->native_string = msStringConcatenate(filter->native_string, snippet); msFree(snippet); msFree(stresc); break; case MS_TOKEN_LITERAL_TIME: { int resolution = msTimeGetResolution(layerinfo->current_node->tokensrc); snippet = (char *) msSmallMalloc(128); switch(resolution) { case TIME_RESOLUTION_YEAR: sprintf(snippet, "'%d'", (layerinfo->current_node->tokenval.tmval.tm_year+1900)); break; case TIME_RESOLUTION_MONTH: sprintf(snippet, "'%d-%02d-01'", (layerinfo->current_node->tokenval.tmval.tm_year+1900), (layerinfo->current_node->tokenval.tmval.tm_mon+1)); break; case TIME_RESOLUTION_DAY: sprintf(snippet, "'%d-%02d-%02d'", (layerinfo->current_node->tokenval.tmval.tm_year+1900), (layerinfo->current_node->tokenval.tmval.tm_mon+1), layerinfo->current_node->tokenval.tmval.tm_mday); break; case TIME_RESOLUTION_HOUR: sprintf(snippet, "'%d-%02d-%02d %02d:00'", (layerinfo->current_node->tokenval.tmval.tm_year+1900), (layerinfo->current_node->tokenval.tmval.tm_mon+1), layerinfo->current_node->tokenval.tmval.tm_mday, layerinfo->current_node->tokenval.tmval.tm_hour); break; case TIME_RESOLUTION_MINUTE: sprintf(snippet, "%d-%02d-%02d %02d:%02d'", (layerinfo->current_node->tokenval.tmval.tm_year+1900), (layerinfo->current_node->tokenval.tmval.tm_mon+1), layerinfo->current_node->tokenval.tmval.tm_mday, layerinfo->current_node->tokenval.tmval.tm_hour, layerinfo->current_node->tokenval.tmval.tm_min); break; case TIME_RESOLUTION_SECOND: sprintf(snippet, "'%d-%02d-%02d %02d:%02d:%02d'", (layerinfo->current_node->tokenval.tmval.tm_year+1900), (layerinfo->current_node->tokenval.tmval.tm_mon+1), layerinfo->current_node->tokenval.tmval.tm_mday, layerinfo->current_node->tokenval.tmval.tm_hour, layerinfo->current_node->tokenval.tmval.tm_min, layerinfo->current_node->tokenval.tmval.tm_sec); break; } filter->native_string = msStringConcatenate(filter->native_string, snippet); msFree(snippet); } break; case MS_TOKEN_LITERAL_SHAPE: if (strcasecmp(layerinfo->geom_column_type, "geography") == 0) filter->native_string = msStringConcatenate(filter->native_string, "geography::STGeomFromText('"); else filter->native_string = msStringConcatenate(filter->native_string, "geometry::STGeomFromText('"); filter->native_string = msStringConcatenate(filter->native_string, msShapeToWKT(layerinfo->current_node->tokenval.shpval)); filter->native_string = msStringConcatenate(filter->native_string, "'"); if(layerinfo->user_srid && strcmp(layerinfo->user_srid, "") != 0) { filter->native_string = msStringConcatenate(filter->native_string, ", "); filter->native_string = msStringConcatenate(filter->native_string, layerinfo->user_srid); } filter->native_string = msStringConcatenate(filter->native_string, ")"); break; case MS_TOKEN_BINDING_TIME: case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: case MS_TOKEN_BINDING_STRING: if(layerinfo->current_node->next->token == MS_TOKEN_COMPARISON_IRE) strtmpl = "LOWER(%s)"; else strtmpl = "%s"; stresc = msMSSQL2008LayerEscapePropertyName(layer, layerinfo->current_node->tokenval.bindval.item); snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); sprintf(snippet, strtmpl, stresc); filter->native_string = msStringConcatenate(filter->native_string, snippet); msFree(snippet); msFree(stresc); break; case MS_TOKEN_BINDING_SHAPE: filter->native_string = msStringConcatenate(filter->native_string, layerinfo->geom_column); break; case MS_TOKEN_BINDING_MAP_CELLSIZE: strtmpl = "%lf"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16); sprintf(snippet, strtmpl, layer->map->cellsize); filter->native_string = msStringConcatenate(filter->native_string, snippet); msFree(snippet); break; /* comparisons */ case MS_TOKEN_COMPARISON_IN: filter->native_string = msStringConcatenate(filter->native_string, " IN "); break; case MS_TOKEN_COMPARISON_RE: case MS_TOKEN_COMPARISON_IRE: case MS_TOKEN_COMPARISON_LIKE: { /* process regexp */ size_t i = 0, j = 0; char c; char c_next; int bCaseInsensitive = (layerinfo->current_node->token == MS_TOKEN_COMPARISON_IRE); int nEscapeLen = 0; if (bCaseInsensitive) filter->native_string = msStringConcatenate(filter->native_string, " LIKE LOWER("); else filter->native_string = msStringConcatenate(filter->native_string, " LIKE "); layerinfo->current_node = layerinfo->current_node->next; if (layerinfo->current_node->token != MS_TOKEN_LITERAL_STRING) return 0; strtmpl = msStrdup(layerinfo->current_node->tokenval.strval); if (strtmpl[0] == '/') { stresc = strtmpl + 1; strtmpl[strlen(strtmpl) - 1] = '\0'; } else if (strtmpl[0] == '^') stresc = strtmpl + 1; else stresc = strtmpl; while (*stresc) { c = stresc[i]; if (c == '%' || c == '_' || c == '[' || c == ']' || c == '^') { nEscapeLen++; } stresc++; } snippet = (char *)msSmallMalloc(strlen(strtmpl) + nEscapeLen + 3); snippet[j++] = '\''; while (i < strlen(strtmpl)) { c = strtmpl[i]; c_next = strtmpl[i+1]; if (i == 0 && c == '^') { i++; continue; } if( c == '$' && c_next == 0 && strtmpl[0] == '^' ) break; if (c == '\\') { i++; c = c_next; } if (c == '%' || c == '_' || c == '[' || c == ']' || c == '^') { snippet[j++] = '\\'; } if (c == '.' && c_next == '*') { i++; c = '%'; } else if (c == '.') c = '_'; snippet[j++] = c; i++; } snippet[j++] = '\''; snippet[j] = '\0'; filter->native_string = msStringConcatenate(filter->native_string, snippet); msFree(strtmpl); msFree(snippet); if (bCaseInsensitive) filter->native_string = msStringConcatenate(filter->native_string, ")"); if (nEscapeLen > 0) filter->native_string = msStringConcatenate(filter->native_string, " ESCAPE '\\'"); } break; case MS_TOKEN_COMPARISON_EQ: filter->native_string = msStringConcatenate(filter->native_string, " = "); break; case MS_TOKEN_COMPARISON_NE: filter->native_string = msStringConcatenate(filter->native_string, " != "); break; case MS_TOKEN_COMPARISON_GT: filter->native_string = msStringConcatenate(filter->native_string, " > "); break; case MS_TOKEN_COMPARISON_GE: filter->native_string = msStringConcatenate(filter->native_string, " >= "); break; case MS_TOKEN_COMPARISON_LT: filter->native_string = msStringConcatenate(filter->native_string, " < "); break; case MS_TOKEN_COMPARISON_LE: filter->native_string = msStringConcatenate(filter->native_string, " <= "); break; /* logical ops */ case MS_TOKEN_LOGICAL_AND: filter->native_string = msStringConcatenate(filter->native_string, " AND "); break; case MS_TOKEN_LOGICAL_OR: filter->native_string = msStringConcatenate(filter->native_string, " OR "); break; case MS_TOKEN_LOGICAL_NOT: filter->native_string = msStringConcatenate(filter->native_string, " NOT "); break; /* spatial comparison tokens */ case MS_TOKEN_COMPARISON_INTERSECTS: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STIntersects("); if (!process_node(layer, filter)) return 0; break; case MS_TOKEN_COMPARISON_DISJOINT: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STDisjoint("); if (!process_node(layer, filter)) return 0; break; case MS_TOKEN_COMPARISON_TOUCHES: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STTouches("); if (!process_node(layer, filter)) return 0; break; case MS_TOKEN_COMPARISON_OVERLAPS: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STOverlaps("); if (!process_node(layer, filter)) return 0; break; case MS_TOKEN_COMPARISON_CROSSES: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STCrosses("); if (!process_node(layer, filter)) return 0; break; case MS_TOKEN_COMPARISON_WITHIN: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STWithin("); if (!process_node(layer, filter)) return 0; break; case MS_TOKEN_COMPARISON_CONTAINS: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STContains("); if (!process_node(layer, filter)) return 0; break; case MS_TOKEN_COMPARISON_EQUALS: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STEquals("); if (!process_node(layer, filter)) return 0; break; case MS_TOKEN_COMPARISON_BEYOND: msSetError(MS_MISCERR, "Beyond operator is unsupported.", "msMSSQL2008LayerTranslateFilter()"); return 0; case MS_TOKEN_COMPARISON_DWITHIN: msSetError(MS_MISCERR, "DWithin operator is unsupported.", "msMSSQL2008LayerTranslateFilter()"); return 0; /* spatial functions */ case MS_TOKEN_FUNCTION_AREA: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STArea()"); break; case MS_TOKEN_FUNCTION_BUFFER: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STBuffer("); if (!process_node(layer, filter)) return 0; filter->native_string = msStringConcatenate(filter->native_string, ")"); break; case MS_TOKEN_FUNCTION_DIFFERENCE: if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (!process_node(layer, filter)) return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; if (layerinfo->current_node->next) layerinfo->current_node = layerinfo->current_node->next; else return 0; filter->native_string = msStringConcatenate(filter->native_string, ".STDifference("); if (!process_node(layer, filter)) return 0; filter->native_string = msStringConcatenate(filter->native_string, ")"); break; case MS_TOKEN_FUNCTION_FROMTEXT: if (strcasecmp(layerinfo->geom_column_type, "geography") == 0) filter->native_string = msStringConcatenate(filter->native_string, "geography::STGeomFromText"); else filter->native_string = msStringConcatenate(filter->native_string, "geometry::STGeomFromText"); break; case MS_TOKEN_FUNCTION_LENGTH: filter->native_string = msStringConcatenate(filter->native_string, "len"); break; case MS_TOKEN_FUNCTION_ROUND: filter->native_string = msStringConcatenate(filter->native_string, "round"); break; case MS_TOKEN_FUNCTION_TOSTRING: break; case MS_TOKEN_FUNCTION_COMMIFY: break; case MS_TOKEN_FUNCTION_SIMPLIFY: filter->native_string = msStringConcatenate(filter->native_string, ".Reduce"); break; case MS_TOKEN_FUNCTION_SIMPLIFYPT: break; case MS_TOKEN_FUNCTION_GENERALIZE: filter->native_string = msStringConcatenate(filter->native_string, ".Reduce"); break; default: msSetError(MS_MISCERR, "Translation to native SQL failed.","msMSSQL2008LayerTranslateFilter()"); if (layer->debug) { msDebug("Token not caught, exiting: Token is %i\n", layerinfo->current_node->token); } return 0; } return 1; } /* Translate filter expression to native msssql filter */ int msMSSQL2008LayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) { char *snippet = NULL; char *strtmpl = NULL; char *stresc = NULL; msMSSQL2008LayerInfo *layerinfo = (msMSSQL2008LayerInfo *) layer->layerinfo; if(!filter->string) return MS_SUCCESS; msFree(filter->native_string); filter->native_string = NULL; if(filter->type == MS_STRING && filter->string && filteritem) { /* item/value pair */ stresc = msMSSQL2008LayerEscapePropertyName(layer, filteritem); if(filter->flags & MS_EXP_INSENSITIVE) { filter->native_string = msStringConcatenate(filter->native_string, "upper("); filter->native_string = msStringConcatenate(filter->native_string, stresc); filter->native_string = msStringConcatenate(filter->native_string, ") = upper("); } else { filter->native_string = msStringConcatenate(filter->native_string, stresc); filter->native_string = msStringConcatenate(filter->native_string, " = "); } msFree(stresc); strtmpl = "'%s'"; /* don't have a type for the righthand literal so assume it's a string and we quote */ snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(filter->string)); sprintf(snippet, strtmpl, filter->string); // TODO: escape filter->string filter->native_string = msStringConcatenate(filter->native_string, snippet); free(snippet); if(filter->flags & MS_EXP_INSENSITIVE) filter->native_string = msStringConcatenate(filter->native_string, ")"); } else if(filter->type == MS_REGEX && filter->string && filteritem) { /* item/regex pair */ /* NOTE: regex is not supported by MSSQL natively. We should install it in CLR UDF according to https://msdn.microsoft.com/en-us/magazine/cc163473.aspx*/ filter->native_string = msStringConcatenate(filter->native_string, "dbo.RegexMatch("); if(filter->flags & MS_EXP_INSENSITIVE) { filter->native_string = msStringConcatenate(filter->native_string, "'(?i)"); } filter->native_string = msStrdup(filteritem); filter->native_string = msStringConcatenate(filter->native_string, ", "); strtmpl = "'%s'"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(filter->string)); sprintf(snippet, strtmpl, filter->string); // TODO: escape filter->string filter->native_string = msStringConcatenate(filter->native_string, snippet); filter->native_string = msStringConcatenate(filter->native_string, "')"); free(snippet); } else if(filter->type == MS_EXPRESSION) { if(layer->debug >= 2) msDebug("msMSSQL2008LayerTranslateFilter. String: %s.\n", filter->string); if(!filter->tokens) { if(layer->debug >= 2) msDebug("msMSSQL2008LayerTranslateFilter. There are tokens to process... \n"); return MS_SUCCESS; } /* start processing nodes */ layerinfo->current_node = filter->tokens; while (layerinfo->current_node != NULL) { if (!process_node(layer, filter)) { msFree(filter->native_string); filter->native_string = 0; return MS_FAILURE; } if (!layerinfo->current_node) break; layerinfo->current_node = layerinfo->current_node->next; } } return MS_SUCCESS; } #else /* prototypes if MSSQL2008 isnt supposed to be compiled */ int msMSSQL2008LayerOpen(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerOpen called but unimplemented! (mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerOpen()"); return MS_FAILURE; } int msMSSQL2008LayerIsOpen(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008IsLayerOpen called but unimplemented! (mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerIsOpen()"); return MS_FALSE; } void msMSSQL2008LayerFreeItemInfo(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerFreeItemInfo called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerFreeItemInfo()"); } int msMSSQL2008LayerInitItemInfo(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerInitItemInfo called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerInitItemInfo()"); return MS_FAILURE; } int msMSSQL2008LayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msSetError(MS_QUERYERR, "msMSSQL2008LayerWhichShapes called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerWhichShapes()"); return MS_FAILURE; } int msMSSQL2008LayerClose(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerClose called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerClose()"); return MS_FAILURE; } int msMSSQL2008LayerNextShape(layerObj *layer, shapeObj *shape) { msSetError(MS_QUERYERR, "msMSSQL2008LayerNextShape called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerNextShape()"); return MS_FAILURE; } int msMSSQL2008LayerGetShape(layerObj *layer, shapeObj *shape, long record) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetShape called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetShape()"); return MS_FAILURE; } int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetExtent called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetExtent()"); return MS_FAILURE; } int msMSSQL2008LayerGetNumFeatures(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetNumFeatures called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetNumFeatures()"); return -1; } int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *record) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetShapeRandom called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetShapeRandom()"); return MS_FAILURE; } int msMSSQL2008LayerGetItems(layerObj *layer) { msSetError(MS_QUERYERR, "msMSSQL2008LayerGetItems called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerGetItems()"); return MS_FAILURE; } int msMSSQL2008LayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) { msSetError(MS_QUERYERR, "msMSSQL2008LayerTranslateFilter called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerTranslateFilter()"); return MS_FAILURE; } char *msMSSQL2008LayerEscapeSQLParam(layerObj *layer, const char *pszString) { msSetError(MS_QUERYERR, "msMSSQL2008EscapeSQLParam called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerEscapeSQLParam()"); return NULL; } char *msMSSQL2008LayerEscapePropertyName(layerObj *layer, const char *pszString) { msSetError(MS_QUERYERR, "msMSSQL2008LayerEscapePropertyName called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerEscapePropertyName()"); return NULL; } /* end above's #ifdef USE_MSSQL2008 */ #endif #ifdef USE_MSSQL2008_PLUGIN MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) { assert(layer != NULL); assert(vtable != NULL); vtable->LayerTranslateFilter = msMSSQL2008LayerTranslateFilter; vtable->LayerEscapeSQLParam = msMSSQL2008LayerEscapeSQLParam; vtable->LayerEscapePropertyName = msMSSQL2008LayerEscapePropertyName; vtable->LayerInitItemInfo = msMSSQL2008LayerInitItemInfo; vtable->LayerFreeItemInfo = msMSSQL2008LayerFreeItemInfo; vtable->LayerOpen = msMSSQL2008LayerOpen; vtable->LayerIsOpen = msMSSQL2008LayerIsOpen; vtable->LayerWhichShapes = msMSSQL2008LayerWhichShapes; vtable->LayerNextShape = msMSSQL2008LayerNextShape; vtable->LayerGetShape = msMSSQL2008LayerGetShape; vtable->LayerClose = msMSSQL2008LayerClose; vtable->LayerGetItems = msMSSQL2008LayerGetItems; vtable->LayerGetExtent = msMSSQL2008LayerGetExtent; vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; /* vtable->LayerGetAutoStyle, not supported for this layer */ vtable->LayerCloseConnection = msMSSQL2008LayerClose; vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* vtable->LayerCreateItems, use default */ vtable->LayerGetNumFeatures = msMSSQL2008LayerGetNumFeatures; /* layer->vtable->LayerGetAutoProjection, use defaut*/ return MS_SUCCESS; } #endif int msMSSQL2008LayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerTranslateFilter = msMSSQL2008LayerTranslateFilter; layer->vtable->LayerEscapeSQLParam = msMSSQL2008LayerEscapeSQLParam; layer->vtable->LayerEscapePropertyName = msMSSQL2008LayerEscapePropertyName; layer->vtable->LayerInitItemInfo = msMSSQL2008LayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msMSSQL2008LayerFreeItemInfo; layer->vtable->LayerOpen = msMSSQL2008LayerOpen; layer->vtable->LayerIsOpen = msMSSQL2008LayerIsOpen; layer->vtable->LayerWhichShapes = msMSSQL2008LayerWhichShapes; layer->vtable->LayerNextShape = msMSSQL2008LayerNextShape; layer->vtable->LayerGetShape = msMSSQL2008LayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerClose = msMSSQL2008LayerClose; layer->vtable->LayerGetItems = msMSSQL2008LayerGetItems; layer->vtable->LayerGetExtent = msMSSQL2008LayerGetExtent; layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; /* layer->vtable->LayerGetAutoStyle, not supported for this layer */ layer->vtable->LayerCloseConnection = msMSSQL2008LayerClose; layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerCreateItems, use default */ layer->vtable->LayerGetNumFeatures = msMSSQL2008LayerGetNumFeatures; return MS_SUCCESS; } mapserver-7.4.3/mapmvt.c000066400000000000000000000475471357574274700152470ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapBox Vector Tile rendering. * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2015 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "maptile.h" #ifdef USE_PBF #include "vector_tile.pb-c.h" #include "mapows.h" #include "uthash.h" #include #define MOVETO 1 #define LINETO 2 #define CLOSEPATH 7 #define FEATURES_INCREMENT_SIZE 5 enum MS_RING_DIRECTION { MS_DIRECTION_INVALID_RING, MS_DIRECTION_CLOCKWISE, MS_DIRECTION_COUNTERCLOCKWISE }; typedef struct { char *value; unsigned int index; UT_hash_handle hh; } value_lookup; typedef struct { value_lookup *cache; } value_lookup_table; #define COMMAND(id, count) (((id) & 0x7) | ((count) << 3)) #define PARAMETER(n) (((n) << 1) ^ ((n) >> 31)) static double getTriangleHeight(lineObj *ring) { int i; double s=0, b=0; if(ring->numpoints != 4) return -1; /* not a triangle */ for(i=0; inumpoints-1; i++) { s += (ring->point[i].x*ring->point[i+1].y - ring->point[i+1].x*ring->point[i].y); b = MS_MAX(b, msDistancePointToPoint(&ring->point[i], &ring->point[i+1])); } return (MS_ABS(s/b)); } static enum MS_RING_DIRECTION mvtGetRingDirection(lineObj *ring) { int i, sum=0; if(ring->numpoints < 4) return MS_DIRECTION_INVALID_RING; /* step throught the edges */ for(i=0; inumpoints-1; i++) { sum += ring->point[i].x * ring->point[i+1].y - ring->point[i+1].x * ring->point[i].y; } return sum > 0 ? MS_DIRECTION_CLOCKWISE : sum < 0 ? MS_DIRECTION_COUNTERCLOCKWISE : MS_DIRECTION_INVALID_RING; } static void mvtReverseRingDirection(lineObj *ring) { pointObj temp; int start=1, end=ring->numpoints-2; /* first and last points are the same so skip 'em */ while (start < end) { temp.x = ring->point[start].x; temp.y = ring->point[start].y; ring->point[start].x = ring->point[end].x; ring->point[start].y = ring->point[end].y; ring->point[end].x = temp.x; ring->point[end].y = temp.y; start++; end--; } } static void mvtReorderRings(shapeObj *shape, int *outers) { int i, j; int t1; lineObj t2; for(i=0; i<(shape->numlines-1); i++) { for(j=0; j<(shape->numlines-i-1); j++) { if(outers[j] < outers[j+1]) { /* swap */ t1 = outers[j]; outers[j] = outers[j+1]; outers[j+1] = t1; t2 = shape->line[j]; shape->line[j] = shape->line[j+1]; shape->line[j+1] = t2; } } } } static int mvtTransformShape(shapeObj *shape, rectObj *extent, int layer_type, int mvt_layer_extent) { double scale_x,scale_y; int i,j,outj; int *outers=NULL, ring_direction; scale_x = (double)mvt_layer_extent/(extent->maxx - extent->minx); scale_y = (double)mvt_layer_extent/(extent->maxy - extent->miny); if(layer_type == MS_LAYER_POLYGON) { outers = msGetOuterList(shape); /* compute before we muck with the shape */ if(outers[0] == 0) /* first ring must be an outer */ mvtReorderRings(shape, outers); } for(i=0;inumlines;i++) { for(j=0,outj=0;jline[i].numpoints;j++) { shape->line[i].point[outj].x = (int)((shape->line[i].point[j].x - extent->minx)*scale_x); shape->line[i].point[outj].y = mvt_layer_extent - (int)((shape->line[i].point[j].y - extent->miny)*scale_y); if(!outj || shape->line[i].point[outj].x != shape->line[i].point[outj-1].x || shape->line[i].point[outj].y != shape->line[i].point[outj-1].y) outj++; /* add the point to the shape only if it's the first one or if it's different than the previous one */ } shape->line[i].numpoints = outj; if(layer_type == MS_LAYER_POLYGON) { if(shape->line[i].numpoints == 4 && getTriangleHeight(&shape->line[i]) < 1) { shape->line[i].numpoints = 0; /* so it's not considered anymore */ continue; /* next ring */ } ring_direction = mvtGetRingDirection(&shape->line[i]); if(ring_direction == MS_DIRECTION_INVALID_RING) shape->line[i].numpoints = 0; /* so it's not considered anymore */ else if((outers[i] && ring_direction != MS_DIRECTION_CLOCKWISE) || (!outers[i] && ring_direction != MS_DIRECTION_COUNTERCLOCKWISE)) mvtReverseRingDirection(&shape->line[i]); } } msComputeBounds(shape); /* TODO: might need to limit this to just valid parts... */ msFree(outers); return (shape->numlines == 0)?MS_FAILURE:MS_SUCCESS; /* sucess if at least one line */ } static int mvtClipShape(shapeObj *shape, int layer_type, int buffer, int mvt_layer_extent) { rectObj tile_rect; tile_rect.minx = tile_rect.miny=-buffer*16; tile_rect.maxx = tile_rect.maxy=mvt_layer_extent + buffer*16; if(layer_type == MS_LAYER_POLYGON) { msClipPolygonRect(shape, tile_rect); } else if(layer_type == MS_LAYER_LINE) { msClipPolylineRect(shape, tile_rect); } /* success if at least one line and not a degenerate bounding box */ if(shape->numlines > 0 && (layer_type == MS_LAYER_POINT || (shape->bounds.minx != shape->bounds.maxx || shape->bounds.miny != shape->bounds.maxy))) return MS_SUCCESS; else return MS_FAILURE; } static void freeMvtFeature( VectorTile__Tile__Feature *mvt_feature ) { if(mvt_feature->tags) msFree(mvt_feature->tags); if(mvt_feature->geometry) msFree(mvt_feature->geometry); } static void freeMvtValue( VectorTile__Tile__Value *mvt_value ) { if(mvt_value->string_value) msFree(mvt_value->string_value); } static void freeMvtLayer( VectorTile__Tile__Layer *mvt_layer ) { int i; if(mvt_layer->keys) { for(i=0;in_keys; i++) { msFree(mvt_layer->keys[i]); } msFree(mvt_layer->keys); } if(mvt_layer->values) { for(i=0;in_values; i++) { freeMvtValue(mvt_layer->values[i]); msFree(mvt_layer->values[i]); } msFree(mvt_layer->values); } if(mvt_layer->features) { for(i=0;in_features; i++) { freeMvtFeature(mvt_layer->features[i]); msFree(mvt_layer->features[i]); } msFree(mvt_layer->features); } } int mvtWriteShape( layerObj *layer, shapeObj *shape, VectorTile__Tile__Layer *mvt_layer, gmlItemListObj *item_list, value_lookup_table *value_lookup_cache, rectObj *unbuffered_bbox, int buffer) { VectorTile__Tile__Feature *mvt_feature; int i,j,iout; value_lookup *value; long int n_geometry; /* could consider an intersection test here */ if(mvtTransformShape(shape, unbuffered_bbox, layer->type, mvt_layer->extent) != MS_SUCCESS) { return MS_SUCCESS; /* degenerate shape */ } if(mvtClipShape(shape, layer->type, buffer, mvt_layer->extent) != MS_SUCCESS) { return MS_SUCCESS; /* no features left after clipping */ } n_geometry = 0; if(layer->type == MS_LAYER_POINT) { for(i=0;inumlines;i++) n_geometry += shape->line[i].numpoints * 2; if(n_geometry) n_geometry++; /* one MOVETO */ } else if(layer->type == MS_LAYER_LINE) { for(i=0;inumlines;i++) if(shape->line[i].numpoints >= 2) n_geometry += 2 + shape->line[i].numpoints * 2; /* one MOVETO, one LINETO */ } else { /* MS_LAYER_POLYGON */ for(i=0;inumlines;i++) if(shape->line[i].numpoints >= 4) n_geometry += 3 + (shape->line[i].numpoints-1) * 2; /* one MOVETO, one LINETO, one CLOSEPATH (don't consider last duplicate point) */ } if(n_geometry == 0) return MS_SUCCESS; mvt_layer->features[mvt_layer->n_features++] = msSmallMalloc(sizeof(VectorTile__Tile__Feature)); mvt_feature = mvt_layer->features[mvt_layer->n_features-1]; vector_tile__tile__feature__init(mvt_feature); mvt_feature->n_tags = mvt_layer->n_keys * 2; mvt_feature->tags = msSmallMalloc(mvt_feature->n_tags * sizeof(uint32_t)); mvt_feature->id = shape->index; mvt_feature->has_id = 1; if(layer->type == MS_LAYER_POLYGON) mvt_feature->type = VECTOR_TILE__TILE__GEOM_TYPE__POLYGON; else if(layer->type == MS_LAYER_LINE) mvt_feature->type = VECTOR_TILE__TILE__GEOM_TYPE__LINESTRING; else mvt_feature->type = VECTOR_TILE__TILE__GEOM_TYPE__POINT; mvt_feature->has_type = 1; /* output values */ for( i = 0, iout = 0; i < item_list->numitems; i++ ) { gmlItemObj *item = item_list->items + i; if( !item->visible ) continue; UT_HASH_FIND_STR(value_lookup_cache->cache, shape->values[i], value); if(!value) { VectorTile__Tile__Value *mvt_value; value = msSmallMalloc(sizeof(value_lookup)); value->value = msStrdup(shape->values[i]); value->index = mvt_layer->n_values; mvt_layer->values = msSmallRealloc(mvt_layer->values,(++mvt_layer->n_values)*sizeof(VectorTile__Tile__Value*)); mvt_layer->values[mvt_layer->n_values-1] = msSmallMalloc(sizeof(VectorTile__Tile__Value)); mvt_value = mvt_layer->values[mvt_layer->n_values-1]; vector_tile__tile__value__init(mvt_value); if( item->type && EQUAL(item->type,"Integer")) { mvt_value->int_value = atoi(value->value); mvt_value->has_int_value = 1; } else if( item->type && EQUAL(item->type,"Long")) { /* signed */ mvt_value->sint_value = atol(value->value); mvt_value->has_sint_value = 1; } else if( item->type && EQUAL(item->type,"Real")) { mvt_value->float_value = atof(value->value); mvt_value->has_float_value = 1; } else if( item->type && EQUAL(item->type,"Boolean") ) { if(EQUAL(value->value,"0") || EQUAL(value->value,"false")) mvt_value->bool_value = 0; else mvt_value->bool_value = 1; mvt_value->has_bool_value = 1; } else { mvt_value->string_value = msStrdup(value->value); } UT_HASH_ADD_KEYPTR(hh,value_lookup_cache->cache,value->value, strlen(value->value), value); } mvt_feature->tags[iout*2] = iout; mvt_feature->tags[iout*2+1] = value->index; iout++; } /* output geom */ mvt_feature->n_geometry = n_geometry; mvt_feature->geometry = msSmallMalloc(mvt_feature->n_geometry * sizeof(uint32_t)); if(layer->type == MS_LAYER_POINT) { int idx=0, lastx=0, lasty=0; mvt_feature->geometry[idx++] = COMMAND(MOVETO, mvt_feature->n_geometry-1); for(i=0;inumlines;i++) { for(j=0;jline[i].numpoints;j++) { mvt_feature->geometry[idx++] = PARAMETER(MS_NINT(shape->line[i].point[j].x)-lastx); mvt_feature->geometry[idx++] = PARAMETER(MS_NINT(shape->line[i].point[j].y)-lasty); lastx = MS_NINT(shape->line[i].point[j].x); lasty = MS_NINT(shape->line[i].point[j].y); } } } else { /* MS_LAYER_LINE or MS_LAYER_POLYGON */ int numpoints; int idx=0, lastx=0, lasty=0; for(i=0;inumlines;i++) { if((layer->type == MS_LAYER_LINE && !(shape->line[i].numpoints >= 2)) || (layer->type == MS_LAYER_POLYGON && !(shape->line[i].numpoints >= 4))) { continue; /* skip malformed parts */ } numpoints = (layer->type == MS_LAYER_LINE)?shape->line[i].numpoints:(shape->line[i].numpoints-1); /* don't consider last point for polygons */ for(j=0;jgeometry[idx++] = COMMAND(MOVETO, 1); } else if(j==1) { mvt_feature->geometry[idx++] = COMMAND(LINETO, numpoints-1); } mvt_feature->geometry[idx++] = PARAMETER(MS_NINT(shape->line[i].point[j].x)-lastx); mvt_feature->geometry[idx++] = PARAMETER(MS_NINT(shape->line[i].point[j].y)-lasty); lastx = MS_NINT(shape->line[i].point[j].x); lasty = MS_NINT(shape->line[i].point[j].y); } if(layer->type == MS_LAYER_POLYGON) { mvt_feature->geometry[idx++] = COMMAND(CLOSEPATH, 1); } } } return MS_SUCCESS; } static void freeMvtTile( VectorTile__Tile *mvt_tile ) { int iLayer; for(iLayer=0;iLayern_layers;iLayer++) { freeMvtLayer(mvt_tile->layers[iLayer]); msFree(mvt_tile->layers[iLayer]); } msFree(mvt_tile->layers); } int msMVTWriteTile( mapObj *map, int sendheaders ) { int iLayer,retcode=MS_SUCCESS; unsigned len; void *buf; const char *mvt_extent = msGetOutputFormatOption(map->outputformat, "EXTENT", "4096"); const char *mvt_buffer = msGetOutputFormatOption(map->outputformat, "EDGE_BUFFER", "10"); int buffer = MS_ABS(atoi(mvt_buffer)); VectorTile__Tile mvt_tile = VECTOR_TILE__TILE__INIT; mvt_tile.layers = msSmallCalloc(map->numlayers, sizeof(VectorTile__Tile__Layer*)); /* make sure we have a scale and cellsize computed */ map->cellsize = MS_CELLSIZE(map->extent.minx, map->extent.maxx, map->width); msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom); /* expand the map->extent so it goes from pixel center (MapServer) to pixel edge (OWS) */ map->extent.minx -= map->cellsize * 0.5; map->extent.maxx += map->cellsize * 0.5; map->extent.miny -= map->cellsize * 0.5; map->extent.maxy += map->cellsize * 0.5; for( iLayer = 0; iLayer < map->numlayers; iLayer++ ) { int status=MS_SUCCESS; layerObj *layer = GET_LAYER(map, iLayer); int i; shapeObj shape; gmlItemListObj *item_list = NULL; VectorTile__Tile__Layer *mvt_layer; value_lookup_table value_lookup_cache = {NULL}; value_lookup *cur_value_lookup, *tmp_value_lookup; rectObj rect; int features_size = 0; if(!msLayerIsVisible(map, layer)) continue; if(layer->type != MS_LAYER_POINT && layer->type != MS_LAYER_POLYGON && layer->type != MS_LAYER_LINE) continue; status = msLayerOpen(layer); if(status != MS_SUCCESS) { retcode = status; goto layer_cleanup; } status = msLayerWhichItems(layer, MS_TRUE, NULL); /* we want all items - behaves like a query in that sense */ if(status != MS_SUCCESS) { retcode = status; goto layer_cleanup; } /* -------------------------------------------------------------------- */ /* Will we need to reproject? */ /* -------------------------------------------------------------------- */ layer->project = msProjectionsDiffer(&(layer->projection), &(map->projection)); rect = map->extent; if(layer->project) msProjectRect(&(map->projection), &(layer->projection), &rect); status = msLayerWhichShapes(layer, rect, MS_TRUE); if(status == MS_DONE) { /* no overlap - that's ok */ retcode = MS_SUCCESS; goto layer_cleanup; } else if(status != MS_SUCCESS) { retcode = status; goto layer_cleanup; } mvt_tile.layers[mvt_tile.n_layers++] = msSmallMalloc(sizeof(VectorTile__Tile__Layer)); mvt_layer = mvt_tile.layers[mvt_tile.n_layers-1]; vector_tile__tile__layer__init(mvt_layer); mvt_layer->version = 2; mvt_layer->name = layer->name; mvt_layer->extent = MS_ABS(atoi(mvt_extent)); mvt_layer->has_extent = 1; /* -------------------------------------------------------------------- */ /* Create appropriate attributes on this layer. */ /* -------------------------------------------------------------------- */ item_list = msGMLGetItems( layer, "G" ); assert( item_list->numitems == layer->numitems ); mvt_layer->keys = msSmallMalloc(layer->numitems * sizeof(char*)); for( i = 0; i < layer->numitems; i++ ) { gmlItemObj *item = item_list->items + i; if( !item->visible ) continue; if( item->alias ) mvt_layer->keys[mvt_layer->n_keys++] = msStrdup(item->alias); else mvt_layer->keys[mvt_layer->n_keys++] = msStrdup(item->name); } /* -------------------------------------------------------------------- */ /* Setup joins if needed. This is likely untested. */ /* -------------------------------------------------------------------- */ if(layer->numjoins > 0) { int j; for(j=0; jnumjoins; j++) { status = msJoinConnect(layer, &(layer->joins[j])); if(status != MS_SUCCESS) { retcode = status; goto layer_cleanup; } } } mvt_layer->features = msSmallCalloc(FEATURES_INCREMENT_SIZE, sizeof(VectorTile__Tile__Feature*)); features_size = FEATURES_INCREMENT_SIZE; msInitShape(&shape); while((status = msLayerNextShape(layer, &shape)) == MS_SUCCESS) { if(layer->numclasses > 0) { shape.classindex = msShapeGetClass(layer, map, &shape, NULL, -1); /* Perform classification, and some annotation related magic. */ if(shape.classindex < 0) goto feature_cleanup; /* no matching CLASS found, skip this feature */ } /* ** prepare any necessary JOINs here (one-to-one only) */ if( layer->numjoins > 0) { int j; for(j=0; j < layer->numjoins; j++) { if(layer->joins[j].type == MS_JOIN_ONE_TO_ONE) { msJoinPrepare(&(layer->joins[j]), &shape); msJoinNext(&(layer->joins[j])); /* fetch the first row */ } } } if(mvt_layer->n_features == features_size) { /* need to allocate more space */ features_size += FEATURES_INCREMENT_SIZE; mvt_layer->features = msSmallRealloc(mvt_layer->features, sizeof(VectorTile__Tile__Feature*)*(features_size)); } if( layer->project ) { status = msProjectShape(&layer->projection, &layer->map->projection, &shape); } if( status == MS_SUCCESS ) { status = mvtWriteShape( layer, &shape, mvt_layer, item_list, &value_lookup_cache, &map->extent, buffer ); } feature_cleanup: msFreeShape(&shape); if(retcode != MS_SUCCESS) goto layer_cleanup; } /* next shape */ layer_cleanup: msLayerClose(layer); msGMLFreeItems(item_list); UT_HASH_ITER(hh, value_lookup_cache.cache, cur_value_lookup, tmp_value_lookup) { msFree(cur_value_lookup->value); UT_HASH_DEL(value_lookup_cache.cache,cur_value_lookup); msFree(cur_value_lookup); } if(retcode != MS_SUCCESS) goto cleanup; } /* next layer */ len = vector_tile__tile__get_packed_size(&mvt_tile); // This is the calculated packing length buf = msSmallMalloc(len); // Allocate memory vector_tile__tile__pack(&mvt_tile, buf); if( sendheaders ) { msIO_fprintf( stdout, "Content-Length: %d\r\n" "Content-Type: application/x-protobuf\r\n\r\n", len); } msIO_fwrite(buf,len,1,stdout); msFree(buf); cleanup: freeMvtTile(&mvt_tile); return retcode; } int msPopulateRendererVTableMVT(rendererVTableObj * renderer) { return MS_SUCCESS; } #else int msPopulateRendererVTableMVT(rendererVTableObj * renderer) { msSetError(MS_MISCERR, "Vector Tile Driver requested but support is not compiled in", "msPopulateRendererVTableMVT()"); return MS_FAILURE; } int msMVTWriteTile( mapObj *map, int sendheaders ) { msSetError(MS_MISCERR, "Vector Tile support is not available.", "msMVTWriteTile()"); return MS_FAILURE; } #endif mapserver-7.4.3/mapobject.c000066400000000000000000000636231357574274700157000ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Functions for operating on a mapObj that don't belong in a * more specific file such as mapfile.c, or mapdraw.c. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2004, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "mapows.h" #ifdef USE_GDAL # include "gdal.h" # include "cpl_conv.h" #endif void freeWeb(webObj *web); void freeScalebar(scalebarObj *scalebar); void freeReferenceMap(referenceMapObj *ref); void freeLegend(legendObj *legend); /************************************************************************/ /* msNewMapObj() */ /* */ /* Create a new initialized map object. */ /************************************************************************/ mapObj *msNewMapObj() { mapObj *map; /* create an empty map, no layers etc... */ map = (mapObj *)calloc(sizeof(mapObj),1); if(!map) { msSetError(MS_MEMERR, NULL, "msCreateMap()"); return NULL; } if( initMap( map ) == -1 ) return NULL; if( msPostMapParseOutputFormatSetup( map ) == MS_FAILURE ) return NULL; return map; } /************************************************************************/ /* msFreeMap() */ /************************************************************************/ void msFreeMap(mapObj *map) { int i; if(!map) return; /* printf("msFreeMap(): maybe freeing map at %p count=%d.\n",map, map->refcount); */ if(MS_REFCNT_DECR_IS_NOT_ZERO(map)) { return; } if(map->debug >= MS_DEBUGLEVEL_VV) msDebug("msFreeMap(): freeing map at %p.\n",map); msCloseConnections(map); msFree(map->name); msFree(map->shapepath); msFree(map->mappath); msFreeProjection(&(map->projection)); msFreeProjection(&(map->latlon)); msFreeLabelCache(&(map->labelcache)); msFree(map->imagetype); msFreeFontSet(&(map->fontset)); msFreeSymbolSet(&map->symbolset); /* free symbols */ msFree(map->symbolset.filename); freeWeb(&(map->web)); freeScalebar(&(map->scalebar)); freeReferenceMap(&(map->reference)); freeLegend(&(map->legend)); for(i=0; imaxlayers; i++) { if(GET_LAYER(map, i) != NULL) { GET_LAYER(map, i)->map = NULL; if(freeLayer((GET_LAYER(map, i))) == MS_SUCCESS) free(GET_LAYER(map, i)); } } msFree(map->layers); if(map->layerorder) free(map->layerorder); msFree(map->templatepattern); msFree(map->datapattern); msFreeHashItems(&(map->configoptions)); if(map->outputformat && map->outputformat->refcount > 0 && --map->outputformat->refcount < 1) msFreeOutputFormat(map->outputformat); for(i=0; inumoutputformats; i++ ) { if(map->outputformatlist[i]->refcount > 0 && --map->outputformatlist[i]->refcount < 1) msFreeOutputFormat(map->outputformatlist[i]); } if(map->outputformatlist != NULL) msFree(map->outputformatlist); msFreeQuery(&(map->query)); #ifdef USE_V8_MAPSCRIPT if (map->v8context) msV8FreeContext(map); #endif msFree(map); } /************************************************************************/ /* msGetConfigOption() */ /************************************************************************/ const char *msGetConfigOption( mapObj *map, const char *key) { return msLookupHashTable( &(map->configoptions), key ); } /************************************************************************/ /* msSetConfigOption() */ /************************************************************************/ int msSetConfigOption( mapObj *map, const char *key, const char *value) { /* We have special "early" handling of this so that it will be */ /* in effect when the projection blocks are parsed and pj_init is called. */ if( strcasecmp(key,"PROJ_LIB") == 0 ) { /* value may be relative to map path */ msSetPROJ_LIB( value, map->mappath ); } /* Same for MS_ERRORFILE, we want it to kick in as early as possible * to catch parsing errors. * Value can be relative to mapfile, unless it's already absolute */ if( strcasecmp(key,"MS_ERRORFILE") == 0 ) { if (msSetErrorFile( value, map->mappath ) != MS_SUCCESS) return MS_FAILURE; } if( msLookupHashTable( &(map->configoptions), key ) != NULL ) msRemoveHashTable( &(map->configoptions), key ); msInsertHashTable( &(map->configoptions), key, value ); return MS_SUCCESS; } /************************************************************************/ /* msTestConfigOption() */ /************************************************************************/ int msTestConfigOption( mapObj *map, const char *key, int default_result ) { const char *result = msGetConfigOption( map, key ); if( result == NULL ) return default_result; if( strcasecmp(result,"YES") == 0 || strcasecmp(result,"ON") == 0 || strcasecmp(result,"TRUE") == 0 ) return MS_TRUE; else return MS_FALSE; } /************************************************************************/ /* msApplyMapConfigOptions() */ /************************************************************************/ void msApplyMapConfigOptions( mapObj *map ) { const char *key; for( key = msFirstKeyFromHashTable( &(map->configoptions) ); key != NULL; key = msNextKeyFromHashTable( &(map->configoptions), key ) ) { const char *value = msLookupHashTable( &(map->configoptions), key ); if( strcasecmp(key,"PROJ_LIB") == 0 ) { msSetPROJ_LIB( value, map->mappath ); } else if( strcasecmp(key,"MS_ERRORFILE") == 0 ) { msSetErrorFile( value, map->mappath ); } else { #if defined(USE_GDAL) && GDAL_RELEASE_DATE > 20030601 CPLSetConfigOption( key, value ); #endif } } } /************************************************************************/ /* msMapIgnoreMissingData() */ /************************************************************************/ int msMapIgnoreMissingData( mapObj *map ) { const char *result = msGetConfigOption( map, "ON_MISSING_DATA" ); const int default_result = #ifndef IGNORE_MISSING_DATA MS_MISSING_DATA_FAIL; #else MS_MISSING_DATA_LOG; #endif if( result == NULL ) return default_result; if( strcasecmp(result,"FAIL") == 0 ) return MS_MISSING_DATA_FAIL; else if( strcasecmp(result,"LOG") == 0 ) return MS_MISSING_DATA_LOG; else if( strcasecmp(result,"IGNORE") == 0 ) return MS_MISSING_DATA_IGNORE; return default_result; } /************************************************************************/ /* msMapSetExtent() */ /************************************************************************/ int msMapSetExtent( mapObj *map, double minx, double miny, double maxx, double maxy) { map->extent.minx = minx; map->extent.miny = miny; map->extent.maxx = maxx; map->extent.maxy = maxy; if (!MS_VALID_EXTENT(map->extent)) { msSetError(MS_MISCERR, "Given map extent is invalid. Check that it " \ "is in the form: minx, miny, maxx, maxy", "setExtent()"); return MS_FAILURE; } map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); /* if the map size is also set, recompute scale, ignore errors? */ if( map->width != -1 || map->height != -1 ) msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &(map->scaledenom)); return msMapComputeGeotransform( map ); } /************************************************************************/ /* msMapOffsetExtent() */ /************************************************************************/ int msMapOffsetExtent( mapObj *map, double x, double y) { return msMapSetExtent( map, map->extent.minx + x, map->extent.miny + y, map->extent.maxx + x, map->extent.maxy + y); } /************************************************************************/ /* msMapScaleExtent() */ /************************************************************************/ int msMapScaleExtent( mapObj *map, double zoomfactor, double minscaledenom, double maxscaledenom) { double geo_width, geo_height, center_x, center_y, md; if (zoomfactor <= 0.0) { msSetError(MS_MISCERR, "The given zoomfactor is invalid", "msMapScaleExtent()"); } geo_width = map->extent.maxx - map->extent.minx; geo_height = map->extent.maxy - map->extent.miny; center_x = map->extent.minx + geo_width * 0.5; center_y = map->extent.miny + geo_height * 0.5; geo_width *= zoomfactor; if (minscaledenom > 0 || maxscaledenom > 0) { /* ensure we are within the valid scale domain */ md = (map->width-1)/(map->resolution * msInchesPerUnit(map->units, center_y)); if (minscaledenom > 0 && geo_width < minscaledenom * md) geo_width = minscaledenom * md; if (maxscaledenom > 0 && geo_width > maxscaledenom * md) geo_width = maxscaledenom * md; } geo_width *= 0.5; geo_height = geo_width * map->height / map->width; return msMapSetExtent( map, center_x - geo_width, center_y - geo_height, center_x + geo_width, center_y + geo_height); } /************************************************************************/ /* msMapSetCenter() */ /************************************************************************/ int msMapSetCenter( mapObj *map, pointObj *center) { return msMapOffsetExtent(map, center->x - (map->extent.minx + map->extent.maxx) * 0.5, center->y - (map->extent.miny + map->extent.maxy) * 0.5); } /************************************************************************/ /* msMapSetRotation() */ /************************************************************************/ int msMapSetRotation( mapObj *map, double rotation_angle ) { map->gt.rotation_angle = rotation_angle; if( map->gt.rotation_angle != 0.0 ) map->gt.need_geotransform = MS_TRUE; else map->gt.need_geotransform = MS_FALSE; return msMapComputeGeotransform( map ); } /************************************************************************/ /* msMapSetSize() */ /************************************************************************/ int msMapSetSize( mapObj *map, int width, int height ) { map->width = width; map->height = height; return msMapComputeGeotransform( map ); /* like SetRotation -- sean */ } /************************************************************************/ /* msMapComputeGeotransform() */ /************************************************************************/ extern int InvGeoTransform( double *gt_in, double *gt_out ); int msMapComputeGeotransform( mapObj * map ) { double rot_angle; double geo_width, geo_height, center_x, center_y; map->saved_extent = map->extent; /* Do we have all required parameters? */ if( map->extent.minx == map->extent.maxx || map->width == 0 || map->height == 0 ) return MS_FAILURE; rot_angle = map->gt.rotation_angle * MS_PI / 180.0; geo_width = map->extent.maxx - map->extent.minx; geo_height = map->extent.maxy - map->extent.miny; center_x = map->extent.minx + geo_width*0.5; center_y = map->extent.miny + geo_height*0.5; /* ** Per bug 1916 we have to adjust for the fact that map extents ** are based on the center of the edge pixels, not the outer ** edges as is expected in a geotransform. */ map->gt.geotransform[1] = cos(rot_angle) * geo_width / (map->width-1); map->gt.geotransform[2] = sin(rot_angle) * geo_height / (map->height-1); map->gt.geotransform[0] = center_x - (map->width * 0.5) * map->gt.geotransform[1] - (map->height * 0.5) * map->gt.geotransform[2]; map->gt.geotransform[4] = sin(rot_angle) * geo_width / (map->width-1); map->gt.geotransform[5] = - cos(rot_angle) * geo_height / (map->height-1); map->gt.geotransform[3] = center_y - (map->width * 0.5) * map->gt.geotransform[4] - (map->height * 0.5) * map->gt.geotransform[5]; if( InvGeoTransform( map->gt.geotransform, map->gt.invgeotransform ) ) return MS_SUCCESS; else return MS_FAILURE; } /************************************************************************/ /* msMapPixelToGeoref() */ /************************************************************************/ void msMapPixelToGeoref( mapObj *map, double *x, double *y ) { msSetError(MS_MISCERR, NULL, "msMapPixelToGeoref() not yet implemented"); } /************************************************************************/ /* msMapGeorefToPixel() */ /************************************************************************/ void msMapGeorefToPixel( mapObj *map, double *x, double *y ) { msSetError(MS_MISCERR, NULL, "msMapGeorefToPixel() not yet implemented"); } /************************************************************************/ /* msMapSetFakedExtent() */ /************************************************************************/ int msMapSetFakedExtent( mapObj *map ) { int i; /* -------------------------------------------------------------------- */ /* Remember the original map extents so we can restore them */ /* later. */ /* -------------------------------------------------------------------- */ map->saved_extent = map->extent; /* -------------------------------------------------------------------- */ /* Set extents such that the bottom left corner is 0,0 and the */ /* top right is width,height. Note this is upside down from */ /* the normal sense of pixel/line coordiantes, but we do this */ /* so that the normal "extent" concept of coordinates */ /* increasing to the right, and up is maintained (like in */ /* georeferenced coordinate systems). */ /* -------------------------------------------------------------------- */ map->extent.minx = 0; map->extent.maxx = map->width; map->extent.miny = 0; map->extent.maxy = map->height; map->cellsize = 1.0; /* -------------------------------------------------------------------- */ /* When we copy the geotransform into the projection object we */ /* have to flip it to account for the preceeding upside-down */ /* coordinate system. */ /* -------------------------------------------------------------------- */ map->projection.gt = map->gt; map->projection.gt.geotransform[0] += map->height * map->gt.geotransform[2]; map->projection.gt.geotransform[3] += map->height * map->gt.geotransform[5]; map->projection.gt.geotransform[2] *= -1; map->projection.gt.geotransform[5] *= -1; for(i=0; inumlayers; i++) GET_LAYER(map, i)->project = MS_TRUE; return InvGeoTransform( map->projection.gt.geotransform, map->projection.gt.invgeotransform ); } /************************************************************************/ /* msMapRestoreRealExtent() */ /************************************************************************/ int msMapRestoreRealExtent( mapObj *map ) { map->projection.gt.need_geotransform = MS_FALSE; map->extent = map->saved_extent; map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); return MS_SUCCESS; } /************************************************************************/ /* msInsertLayer() */ /************************************************************************/ /* Returns the index at which the layer was inserted */ int msInsertLayer(mapObj *map, layerObj *layer, int nIndex) { if (!layer) { msSetError(MS_CHILDERR, "Can't insert a NULL Layer", "msInsertLayer()"); return -1; } /* Ensure there is room for a new layer */ if (map->numlayers == map->maxlayers) { if (msGrowMapLayers(map) == NULL) return -1; } /* msGrowMapLayers allocates the new layer which we don't need to do since we have 1 that we are inserting not sure if it is possible for this to be non null otherwise, but better to check since this function replaces the value */ if (map->layers[map->numlayers]!=NULL) free(map->layers[map->numlayers]); /* Catch attempt to insert past end of layers array */ if (nIndex >= map->numlayers) { msSetError(MS_CHILDERR, "Cannot insert layer beyond index %d", "msInsertLayer()", map->numlayers-1); return -1; } else if (nIndex < 0) { /* Insert at the end by default */ map->layerorder[map->numlayers] = map->numlayers; GET_LAYER(map, map->numlayers) = layer; GET_LAYER(map, map->numlayers)->index = map->numlayers; GET_LAYER(map, map->numlayers)->map = map; MS_REFCNT_INCR(layer); map->numlayers++; return map->numlayers-1; } else if (nIndex >= 0 && nIndex < map->numlayers) { /* Move existing layers at the specified nIndex or greater */ /* to an index one higher */ int i; for (i=map->numlayers; i>nIndex; i--) { GET_LAYER(map, i)=GET_LAYER(map, i-1); GET_LAYER(map, i)->index = i; } /* assign new layer to specified index */ GET_LAYER(map, nIndex)=layer; GET_LAYER(map, nIndex)->index = nIndex; GET_LAYER(map, nIndex)->map = map; /* adjust layers drawing order */ for (i=map->numlayers; i>nIndex; i--) { map->layerorder[i] = map->layerorder[i-1]; if (map->layerorder[i] >= nIndex) map->layerorder[i]++; } for (i=0; ilayerorder[i] >= nIndex) map->layerorder[i]++; } map->layerorder[nIndex] = nIndex; /* increment number of layers and return */ MS_REFCNT_INCR(layer); map->numlayers++; return nIndex; } else { msSetError(MS_CHILDERR, "Invalid index", "msInsertLayer()"); return -1; } } /************************************************************************/ /* msRemoveLayer() */ /************************************************************************/ layerObj *msRemoveLayer(mapObj *map, int nIndex) { int i; int order_index; layerObj *layer; if (nIndex < 0 || nIndex >= map->numlayers) { msSetError(MS_CHILDERR, "Cannot remove Layer, invalid index %d", "msRemoveLayer()", nIndex); return NULL; } else { layer=GET_LAYER(map, nIndex); /* msCopyLayer(layer, (GET_LAYER(map, nIndex))); */ /* Iteratively copy the higher index layers down one index */ for (i=nIndex; inumlayers-1; i++) { /* freeLayer((GET_LAYER(map, i))); */ /* initLayer((GET_LAYER(map, i)), map); */ /* msCopyLayer(GET_LAYER(map, i), GET_LAYER(map, i+1)); */ GET_LAYER(map, i)=GET_LAYER(map, i+1); GET_LAYER(map, i)->index = i; } /* Free the extra layer at the end */ /* freeLayer((GET_LAYER(map, map->numlayers-1))); */ GET_LAYER(map, map->numlayers-1)=NULL; /* Adjust drawing order */ order_index = 0; for (i=0; inumlayers; i++) { if (map->layerorder[i] > nIndex) map->layerorder[i]--; if (map->layerorder[i] == nIndex) { order_index = i; break; } } for (i=order_index; inumlayers-1; i++) { map->layerorder[i] = map->layerorder[i+1]; if (map->layerorder[i] > nIndex) map->layerorder[i]--; } /* decrement number of layers and return copy of removed layer */ map->numlayers--; layer->map=NULL; MS_REFCNT_DECR(layer); return layer; } } /* ** Move the layer's order for drawing purpose. Moving it up here ** will have the effect of drawing the layer earlier. */ int msMoveLayerUp(mapObj *map, int nLayerIndex) { int iCurrentIndex = -1; int i = 0; if (map && nLayerIndex < map->numlayers && nLayerIndex >=0) { for (i=0; inumlayers; i++) { if ( map->layerorder[i] == nLayerIndex) { iCurrentIndex = i; break; } } if (iCurrentIndex >=0) { /* we do not need to promote if it is the first one. */ if (iCurrentIndex == 0) return MS_FAILURE; map->layerorder[iCurrentIndex] = map->layerorder[iCurrentIndex-1]; map->layerorder[iCurrentIndex-1] = nLayerIndex; return MS_SUCCESS; } } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLayerUp()", nLayerIndex); return MS_FAILURE; } /* ** Move the layer's order for drawing purpose. Moving it down here ** will have the effect of drawing the layer later. */ int msMoveLayerDown(mapObj *map, int nLayerIndex) { int iCurrentIndex = -1; int i = 0; if (map && nLayerIndex < map->numlayers && nLayerIndex >=0) { for (i=0; inumlayers; i++) { if ( map->layerorder[i] == nLayerIndex) { iCurrentIndex = i; break; } } if (iCurrentIndex >=0) { /* we do not need to demote if it is the last one. */ if (iCurrentIndex == map->numlayers-1) return MS_FAILURE; map->layerorder[iCurrentIndex] = map->layerorder[iCurrentIndex+1]; map->layerorder[iCurrentIndex+1] = nLayerIndex; return MS_SUCCESS; } } msSetError(MS_CHILDERR, "Invalid index: %d", "msMoveLayerDown()", nLayerIndex); return MS_FAILURE; } /* ** Set the array used for the drawing order. The array passed must contain ** all the layer's index ordered by the drawing priority. ** Ex : for 3 layers in the map file, if ** panIndexes[0] = 2 ** panIndexes[1] = 0 ** panIndexes[2] = 1 ** will set the darwing order to layer 2, layer 0, ** and then layer 1. ** ** Note : It is assumed that the index panIndexes has the same number of ** of elements as the number of layers in the map. ** Return TRUE on success else FALSE. */ int msSetLayersdrawingOrder(mapObj *self, int *panIndexes) { int nElements = 0; int i, j = 0; int bFound = 0; if (self && panIndexes) { nElements = self->numlayers; for (i=0; ilayerorder[i] = panIndexes[i]; } return 1; } return 0; } /* ========================================================================= msMapLoadOWSParameters Function to support mapscript mapObj::loadOWSParameters ========================================================================= */ int msMapLoadOWSParameters(mapObj *map, cgiRequestObj *request, const char *wmtver) { #ifdef USE_WMS_SVR int version; char *wms_exception_format = NULL; const char *wms_request= NULL; int result, i = 0; owsRequestObj ows_request; ows_request.numlayers = 0; ows_request.enabled_layers = NULL; version = msOWSParseVersionString(wmtver); for(i=0; iNumParams; i++) { if (strcasecmp(request->ParamNames[i], "EXCEPTIONS") == 0) wms_exception_format = request->ParamValues[i]; else if (strcasecmp(request->ParamNames[i], "REQUEST") == 0) wms_request = request->ParamValues[i]; } msOWSRequestLayersEnabled(map, "M", wms_request, &ows_request); result = msWMSLoadGetMapParams(map, version, request->ParamNames, request->ParamValues, request->NumParams, wms_exception_format, wms_request, &ows_request); if (ows_request.numlayers > 0) msFree(ows_request.enabled_layers); return result; #else msSetError(MS_WMSERR, "WMS server support is not available.", "msMapLoadOWSParameters()"); return MS_FAILURE; #endif } mapserver-7.4.3/mapogcfilter.c000066400000000000000000004177611357574274700164160ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Filter Encoding implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #define _GNU_SOURCE #include "mapserver-config.h" #ifdef USE_OGR #include "cpl_minixml.h" #include "cpl_string.h" #endif #include "mapogcfilter.h" #include "mapserver.h" #include "mapowscommon.h" #include "maptime.h" #include "mapows.h" #include #if 0 static int FLTHasUniqueTopLevelDuringFilter(FilterEncodingNode *psFilterNode); #endif #if !(defined(_WIN32) && !defined(__CYGWIN__)) static inline void IGUR_double(double ignored) { (void)ignored; } /* Ignore GCC Unused Result */ #endif int FLTIsNumeric(const char *pszValue) { if (pszValue != NULL && *pszValue != '\0' && !isspace(*pszValue)) { /*the regex seems to have a problem on windows when mapserver is built using PHP regex*/ #if defined(_WIN32) && !defined(__CYGWIN__) int i = 0, nLength=0, bString=0; nLength = strlen(pszValue); for (i=0; iconnectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_PLUGIN) { pszFinalExpression = msStrdup("("); pszFinalExpression = msStringConcatenate(pszFinalExpression, pszExpression); pszFinalExpression = msStringConcatenate(pszFinalExpression, ")"); } else if (lp->connectiontype == MS_OGR) { pszFinalExpression = msStrdup(pszExpression); if (lp->filter.type != MS_EXPRESSION) { bConcatWhere = 1; } else { if (lp->filter.string && EQUALN(lp->filter.string,"WHERE ",6)) { bHasAWhere = 1; bConcatWhere =1; } } } else pszFinalExpression = msStrdup(pszExpression); if (bConcatWhere) pszBuffer = msStringConcatenate(pszBuffer, "WHERE "); /* if the filter is set and it's an expression type, concatenate it with this filter. If not just free it */ if (lp->filter.string && lp->filter.type == MS_EXPRESSION) { pszBuffer = msStringConcatenate(pszBuffer, "(("); if (bHasAWhere) pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string+6); else pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") and "); } else if (lp->filter.string) msFreeExpression(&lp->filter); pszBuffer = msStringConcatenate(pszBuffer, pszFinalExpression); if(lp->filter.string && lp->filter.type == MS_EXPRESSION) pszBuffer = msStringConcatenate(pszBuffer, ")"); /*assuming that expression was properly escaped escapedTextString = msStringEscape(pszBuffer); msLoadExpressionString(&lp->filter, (char*)CPLSPrintf("%s", escapedTextString)); msFree(escapedTextString); */ msLoadExpressionString(&lp->filter, pszBuffer); msFree(pszFinalExpression); if (pszBuffer) msFree(pszBuffer); return MS_TRUE; } return MS_FALSE; } char *FLTGetExpressionForValuesRanges(layerObj *lp, const char *item, const char *value, int forcecharcter) { int bIscharacter, bSqlLayer=MS_FALSE; char *pszExpression = NULL, *pszEscapedStr=NULL, *pszTmpExpression=NULL; char **paszElements = NULL, **papszRangeElements=NULL; int numelements,i,nrangeelements; /* TODO: remove the bSqlLayer checks since we want to write MapServer expressions only. */ /* double minval, maxval; */ if (lp && item && value) { if (strstr(value, "/") == NULL) { /*value(s)*/ paszElements = msStringSplit (value, ',', &numelements); if (paszElements && numelements > 0) { if (forcecharcter) bIscharacter = MS_TRUE; else bIscharacter= !FLTIsNumeric(paszElements[0]); pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); for (i=0; i 0) { pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); for (i=0; i 0) { pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); if (nrangeelements == 2 || nrangeelements == 3) { /* minval = atof(papszRangeElements[0]); maxval = atof(papszRangeElements[1]); */ if (bSqlLayer) pszTmpExpression = msStringConcatenate(pszTmpExpression, item); else { pszTmpExpression = msStringConcatenate(pszTmpExpression, "["); pszTmpExpression = msStringConcatenate(pszTmpExpression, item); pszTmpExpression = msStringConcatenate(pszTmpExpression, "]"); } pszTmpExpression = msStringConcatenate(pszTmpExpression, " >= "); pszEscapedStr = msLayerEscapeSQLParam(lp, papszRangeElements[0]); pszTmpExpression = msStringConcatenate(pszTmpExpression, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr=NULL; pszTmpExpression = msStringConcatenate(pszTmpExpression, " AND "); if (bSqlLayer) pszTmpExpression = msStringConcatenate(pszTmpExpression, item); else { pszTmpExpression = msStringConcatenate(pszTmpExpression, "["); pszTmpExpression = msStringConcatenate(pszTmpExpression, item); pszTmpExpression = msStringConcatenate(pszTmpExpression, "]"); } pszTmpExpression = msStringConcatenate(pszTmpExpression, " <= "); pszEscapedStr = msLayerEscapeSQLParam(lp, papszRangeElements[1]); pszTmpExpression = msStringConcatenate(pszTmpExpression, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr=NULL; pszTmpExpression = msStringConcatenate(pszTmpExpression, ")"); } else if (nrangeelements == 1) { pszTmpExpression = msStringConcatenate(pszTmpExpression, "("); if (bSqlLayer) pszTmpExpression = msStringConcatenate(pszTmpExpression, item); else { pszTmpExpression = msStringConcatenate(pszTmpExpression, "["); pszTmpExpression = msStringConcatenate(pszTmpExpression, item); pszTmpExpression = msStringConcatenate(pszTmpExpression, "]"); } pszTmpExpression = msStringConcatenate(pszTmpExpression, " = "); pszEscapedStr = msLayerEscapeSQLParam(lp, papszRangeElements[0]); pszTmpExpression = msStringConcatenate(pszTmpExpression, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr=NULL; pszTmpExpression = msStringConcatenate(pszTmpExpression, ")"); } if (pszExpression != NULL) pszExpression = msStringConcatenate(pszExpression, " OR "); pszExpression = msStringConcatenate(pszExpression, pszTmpExpression); msFree(pszTmpExpression); pszTmpExpression = NULL; } msFreeCharArray(papszRangeElements, nrangeelements); } pszExpression = msStringConcatenate(pszExpression, ")"); } msFreeCharArray(paszElements, numelements); } } msFree(pszTmpExpression); return pszExpression; } #ifdef USE_OGR int FLTogrConvertGeometry(OGRGeometryH hGeometry, shapeObj *psShape, OGRwkbGeometryType nType) { return msOGRGeometryToShape(hGeometry, psShape, nType); } static int FLTShapeFromGMLTree(CPLXMLNode *psTree, shapeObj *psShape , char **ppszSRS) { const char *pszSRS = NULL; if (psTree && psShape) { CPLXMLNode *psNext = psTree->psNext; OGRGeometryH hGeometry = NULL; psTree->psNext = NULL; hGeometry = OGR_G_CreateFromGMLTree(psTree ); psTree->psNext = psNext; if (hGeometry) { OGRwkbGeometryType nType; nType = OGR_G_GetGeometryType(hGeometry); if (nType == wkbPolygon25D || nType == wkbMultiPolygon25D) nType = wkbPolygon; else if (nType == wkbLineString25D || nType == wkbMultiLineString25D) nType = wkbLineString; else if (nType == wkbPoint25D || nType == wkbMultiPoint25D) nType = wkbPoint; FLTogrConvertGeometry(hGeometry, psShape, nType); OGR_G_DestroyGeometry(hGeometry); pszSRS = CPLGetXMLValue(psTree, "srsName", NULL); if (ppszSRS && pszSRS) *ppszSRS = msStrdup(pszSRS); return MS_TRUE; } } return MS_FALSE; } int FLTGetGeosOperator(char *pszValue) { if (!pszValue) return -1; if (strcasecmp(pszValue, "Equals") == 0) return MS_GEOS_EQUALS; else if (strcasecmp(pszValue, "Intersect") == 0 || strcasecmp(pszValue, "Intersects") == 0) return MS_GEOS_INTERSECTS; else if (strcasecmp(pszValue, "Disjoint") == 0) return MS_GEOS_DISJOINT; else if (strcasecmp(pszValue, "Touches") == 0) return MS_GEOS_TOUCHES; else if (strcasecmp(pszValue, "Crosses") == 0) return MS_GEOS_CROSSES; else if (strcasecmp(pszValue, "Within") == 0) return MS_GEOS_WITHIN; else if (strcasecmp(pszValue, "Contains") == 0) return MS_GEOS_CONTAINS; else if (strcasecmp(pszValue, "Overlaps") == 0) return MS_GEOS_OVERLAPS; else if (strcasecmp(pszValue, "Beyond") == 0) return MS_GEOS_BEYOND; else if (strcasecmp(pszValue, "DWithin") == 0) return MS_GEOS_DWITHIN; return -1; } int FLTIsGeosNode(char *pszValue) { if (FLTGetGeosOperator(pszValue) == -1) return MS_FALSE; return MS_TRUE; } /************************************************************************/ /* FLTIsSimpleFilterNoSpatial */ /* */ /* Filter encoding with only attribute queries */ /************************************************************************/ int FLTIsSimpleFilterNoSpatial(FilterEncodingNode *psNode) { if (FLTIsSimpleFilter(psNode) && FLTNumberOfFilterType(psNode, "BBOX") == 0) return MS_TRUE; return MS_FALSE; } /************************************************************************/ /* FLTApplySimpleSQLFilter() */ /************************************************************************/ int FLTApplySimpleSQLFilter(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { layerObj *lp = NULL; char *szExpression = NULL; rectObj sQueryRect = map->extent; const char *szEPSG = NULL; projectionObj sProjTmp; char *pszBuffer = NULL; int bConcatWhere = 0; int bHasAWhere =0; char *pszTmp = NULL, *pszTmp2 = NULL; char *tmpfilename = NULL; const char* pszTimeField = NULL; const char* pszTimeValue = NULL; lp = (GET_LAYER(map, iLayerIndex)); /* if there is a bbox use it */ szEPSG = FLTGetBBOX(psNode, &sQueryRect); if(szEPSG && map->projection.numargs > 0) { msInitProjection(&sProjTmp); /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ if (msLoadProjectionString(&sProjTmp, szEPSG) == 0) { msProjectRect(&sProjTmp, &map->projection, &sQueryRect); } msFreeProjection(&sProjTmp); } if( lp->connectiontype == MS_OGR ) { pszTimeValue = FLTGetDuring(psNode, &pszTimeField); } /* make sure that the layer can be queried*/ if (!lp->template) lp->template = msStrdup("ttt.html"); /* if there is no class, create at least one, so that query by rect would work */ if (lp->numclasses == 0) { if (msGrowLayerClasses(lp) == NULL) return MS_FAILURE; initClass(lp->class[0]); } bConcatWhere = 0; bHasAWhere = 0; if (lp->connectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_PLUGIN) { szExpression = FLTGetSQLExpression(psNode, lp); if (szExpression) { pszTmp = msStrdup("("); pszTmp = msStringConcatenate(pszTmp, szExpression); pszTmp = msStringConcatenate(pszTmp, ")"); msFree(szExpression); szExpression = pszTmp; } } /* concatenates the WHERE clause for OGR layers. This only applies if the expression was empty or not of an expression string. If there is an sql type expression, it is assumed to have the WHERE clause. If it is an expression and does not have a WHERE it is assumed to be a mapserver type expression*/ else if (lp->connectiontype == MS_OGR) { if (lp->filter.type != MS_EXPRESSION) { szExpression = FLTGetSQLExpression(psNode, lp); bConcatWhere = 1; } else { if (lp->filter.string && EQUALN(lp->filter.string,"WHERE ",6)) { szExpression = FLTGetSQLExpression(psNode, lp); bHasAWhere = 1; bConcatWhere =1; } else { szExpression = FLTGetCommonExpression(psNode, lp); } } } else { szExpression = FLTGetCommonExpression(psNode, lp); } if (szExpression) { if (bConcatWhere) pszBuffer = msStringConcatenate(pszBuffer, "WHERE "); /* if the filter is set and it's an expression type, concatenate it with this filter. If not just free it */ if (lp->filter.string && lp->filter.type == MS_EXPRESSION) { pszBuffer = msStringConcatenate(pszBuffer, "(("); if (bHasAWhere) pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string+6); else pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") and "); } else if (lp->filter.string) msFreeExpression(&lp->filter); pszBuffer = msStringConcatenate(pszBuffer, szExpression); if(lp->filter.string && lp->filter.type == MS_EXPRESSION) pszBuffer = msStringConcatenate(pszBuffer, ")"); msLoadExpressionString(&lp->filter, pszBuffer); free(szExpression); } if (pszTimeField && pszTimeValue) msLayerSetTimeFilter(lp, pszTimeValue, pszTimeField); if (pszBuffer) free(pszBuffer); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = lp->index; map->query.rect = sQueryRect; if(map->debug == MS_DEBUGLEVEL_VVV) { tmpfilename = msTmpFile(map, map->mappath, NULL, "_filter.map"); if (tmpfilename == NULL) { tmpfilename = msTmpFile(map, NULL, NULL, "_filter.map" ); } if (tmpfilename) { msSaveMap(map,tmpfilename); msDebug("FLTApplySimpleSQLFilter(): Map file after Filter was applied %s\n", tmpfilename); msFree(tmpfilename); } } /*for oracle connection, if we have a simple filter with no spatial constraints we should set the connection function to NONE to have a better performance (#2725)*/ if (lp->connectiontype == MS_ORACLESPATIAL && FLTIsSimpleFilterNoSpatial(psNode)) { if (strcasestr(lp->data, "USING") == 0) lp->data = msStringConcatenate(lp->data, " USING NONE"); else if (strcasestr(lp->data, "NONE") == 0) { /*if one of the functions is used, just replace it with NONE*/ if (strcasestr(lp->data, "FILTER")) lp->data = msCaseReplaceSubstring(lp->data, "FILTER", "NONE"); else if (strcasestr(lp->data, "GEOMRELATE")) lp->data = msCaseReplaceSubstring(lp->data, "GEOMRELATE", "NONE"); else if (strcasestr(lp->data, "RELATE")) lp->data = msCaseReplaceSubstring(lp->data, "RELATE", "NONE"); else if (strcasestr(lp->data, "VERSION")) { /*should add NONE just before the VERSION. Cases are: DATA "ORA_GEOMETRY FROM data USING VERSION 10g DATA "ORA_GEOMETRY FROM data USING UNIQUE FID VERSION 10g" */ pszTmp = (char *)strcasestr(lp->data, "VERSION"); pszTmp2 = msStringConcatenate(pszTmp2, " NONE "); pszTmp2 = msStringConcatenate(pszTmp2, pszTmp); lp->data = msCaseReplaceSubstring(lp->data, pszTmp, pszTmp2); msFree(pszTmp2); } else if (strcasestr(lp->data, "SRID")) { lp->data = msStringConcatenate(lp->data, " NONE"); } } } return msQueryByRect(map); /* return MS_SUCCESS; */ } /************************************************************************/ /* FLTSplitFilters */ /* */ /* Split filters separated by parentheses into an array of strings. */ /************************************************************************/ char** FLTSplitFilters(const char* pszStr, int* pnTokens) { const char* pszTokenBegin; char** papszRet = NULL; int nTokens = 0; char chStringQuote = '\0'; int nXMLIndent = 0; int bInBracket = FALSE; if( *pszStr != '(' ) { *pnTokens = 0; return NULL; } pszStr ++; pszTokenBegin = pszStr; while( *pszStr != '\0' ) { /* Ignore any character until end of quoted string */ if( chStringQuote != '\0' ) { if( *pszStr == chStringQuote ) chStringQuote = 0; } /* Detect begin of quoted string only for an XML attribute, i.e. between < and > */ else if( bInBracket && (*pszStr == '\'' || *pszStr == '"') ) { chStringQuote = *pszStr; } /* Begin of XML element */ else if( *pszStr == '<' ) { bInBracket = TRUE; if( pszStr[1] == '/' ) nXMLIndent --; else if( pszStr[1] != '!' ) nXMLIndent ++; } /* case */ else if (*pszStr == '/' && pszStr[1] == '>' ) { bInBracket = FALSE; nXMLIndent --; pszStr ++; } /* End of XML element */ else if( *pszStr == '>' ) { bInBracket = FALSE; } /* Only detect and of filter when XML indentation goes back to zero */ else if( nXMLIndent == 0 && *pszStr == ')' ) { papszRet = (char**) msSmallRealloc(papszRet, sizeof(char*) * (nTokens + 1)); papszRet[nTokens] = msStrdup(pszTokenBegin); papszRet[nTokens][pszStr - pszTokenBegin] = '\0'; nTokens ++; if( pszStr[1] != '(' ) { break; } pszStr ++; pszTokenBegin = pszStr + 1; } pszStr ++; } *pnTokens = nTokens; return papszRet; } /************************************************************************/ /* FLTIsSimpleFilter */ /* */ /* Filter encoding with only attribute queries and only one bbox. */ /************************************************************************/ int FLTIsSimpleFilter(FilterEncodingNode *psNode) { if (FLTValidForBBoxFilter(psNode)) { if (FLTNumberOfFilterType(psNode, "DWithin") == 0 && FLTNumberOfFilterType(psNode, "Intersect") == 0 && FLTNumberOfFilterType(psNode, "Intersects") == 0 && FLTNumberOfFilterType(psNode, "Equals") == 0 && FLTNumberOfFilterType(psNode, "Disjoint") == 0 && FLTNumberOfFilterType(psNode, "Touches") == 0 && FLTNumberOfFilterType(psNode, "Crosses") == 0 && FLTNumberOfFilterType(psNode, "Within") == 0 && FLTNumberOfFilterType(psNode, "Contains") == 0 && FLTNumberOfFilterType(psNode, "Overlaps") == 0 && FLTNumberOfFilterType(psNode, "Beyond") == 0) return TRUE; } return FALSE; } /************************************************************************/ /* FLTApplyFilterToLayer */ /* */ /* Use the filter encoding node to create mapserver expressions */ /* and apply it to the layer. */ /************************************************************************/ int FLTApplyFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { layerObj *layer = GET_LAYER(map, iLayerIndex); if ( ! layer->vtable) { int rv = msInitializeVirtualTable(layer); if (rv != MS_SUCCESS) return rv; } return layer->vtable->LayerApplyFilterToLayer(psNode, map, iLayerIndex); } /************************************************************************/ /* FLTLayerApplyCondSQLFilterToLayer */ /* */ /* Helper function for layer virtual table architecture */ /************************************************************************/ int FLTLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { return FLTLayerApplyPlainFilterToLayer(psNode, map, iLayerIndex); } /************************************************************************/ /* FLTGetTopBBOX */ /* */ /* Return the "top" BBOX if there's a unique one. */ /************************************************************************/ static int FLTGetTopBBOXInternal(FilterEncodingNode *psNode, FilterEncodingNode** ppsTopBBOX, int *pnCount) { if (psNode->pszValue && strcasecmp(psNode->pszValue, "BBOX") == 0) { (*pnCount) ++; if( *pnCount == 1 ) { *ppsTopBBOX = psNode; return TRUE; } *ppsTopBBOX = NULL; return FALSE; } else if (psNode->pszValue && strcasecmp(psNode->pszValue, "AND") == 0) { return FLTGetTopBBOXInternal(psNode->psLeftNode, ppsTopBBOX, pnCount) && FLTGetTopBBOXInternal(psNode->psRightNode, ppsTopBBOX, pnCount); } else { return TRUE; } } static FilterEncodingNode* FLTGetTopBBOX(FilterEncodingNode *psNode) { int nCount = 0; FilterEncodingNode* psTopBBOX = NULL; FLTGetTopBBOXInternal(psNode, &psTopBBOX, &nCount); return psTopBBOX; } /************************************************************************/ /* FLTLayerApplyPlainFilterToLayer */ /* */ /* Helper function for layer virtual table architecture */ /************************************************************************/ int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex) { char *pszExpression =NULL; int status =MS_FALSE; layerObj* lp = GET_LAYER(map, iLayerIndex); pszExpression = FLTGetCommonExpression(psNode, lp); if (pszExpression) { const char* pszUseDefaultExtent; FilterEncodingNode* psTopBBOX; rectObj rect = map->extent; pszUseDefaultExtent = msOWSLookupMetadata(&(lp->metadata), "F", "use_default_extent_for_getfeature"); if( pszUseDefaultExtent && !CSLTestBoolean(pszUseDefaultExtent) && lp->connectiontype == MS_OGR ) { const rectObj rectInvalid = MS_INIT_INVALID_RECT; rect = rectInvalid; } psTopBBOX = FLTGetTopBBOX(psNode); if( psTopBBOX ) { int can_remove_expression = MS_TRUE; const char* pszEPSG = FLTGetBBOX(psNode, &rect); if(pszEPSG && map->projection.numargs > 0) { projectionObj sProjTmp; msInitProjection(&sProjTmp); /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ if (msLoadProjectionString(&sProjTmp, pszEPSG) == 0) { rectObj oldRect = rect; msProjectRect(&sProjTmp, &map->projection, &rect); /* If reprojection is involved, do not remove the expression */ if( rect.minx != oldRect.minx || rect.miny != oldRect.miny || rect.maxx != oldRect.maxx || rect.maxy != oldRect.maxy ) { can_remove_expression = MS_FALSE; } } msFreeProjection(&sProjTmp); } /* Small optimization: if the query is just a BBOX, then do a */ /* msQueryByRect() */ if( psTopBBOX == psNode && can_remove_expression ) { msFree(pszExpression); pszExpression = NULL; } } if(map->debug == MS_DEBUGLEVEL_VVV) { if( pszExpression ) msDebug("FLTLayerApplyPlainFilterToLayer(): %s, rect=%.15g,%.15g,%.15g,%.15g\n", pszExpression, rect.minx, rect.miny, rect.maxx, rect.maxy); else msDebug("FLTLayerApplyPlainFilterToLayer(): rect=%.15g,%.15g,%.15g,%.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy); } status = FLTApplyFilterToLayerCommonExpressionWithRect(map, iLayerIndex, pszExpression, rect); msFree(pszExpression); } return status; } /************************************************************************/ /* FilterNode *FLTPaserFilterEncoding(char *szXMLString) */ /* */ /* Parses an Filter Encoding XML string and creates a */ /* FilterEncodingNodes corresponding to the string. */ /* Returns a pointer to the first node or NULL if */ /* unsuccessfull. */ /* Calling function should use FreeFilterEncodingNode function */ /* to free memeory. */ /************************************************************************/ FilterEncodingNode *FLTParseFilterEncoding(const char *szXMLString) { CPLXMLNode *psRoot = NULL, *psChild=NULL, *psFilter=NULL; FilterEncodingNode *psFilterNode = NULL; if (szXMLString == NULL || strlen(szXMLString) <= 0 || (strstr(szXMLString, "Filter") == NULL)) return NULL; psRoot = CPLParseXMLString(szXMLString); if( psRoot == NULL) return NULL; /* strip namespaces. We srtip all name spaces (#1350)*/ CPLStripXMLNamespace(psRoot, NULL, 1); /* -------------------------------------------------------------------- */ /* get the root element (Filter). */ /* -------------------------------------------------------------------- */ psFilter = CPLGetXMLNode(psRoot, "=Filter"); if (!psFilter) { CPLDestroyXMLNode( psRoot ); return NULL; } psChild = psFilter->psChild; while (psChild) { if (FLTIsSupportedFilterType(psChild)) { psFilterNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psFilterNode, psChild); break; } else psChild = psChild->psNext; } CPLDestroyXMLNode( psRoot ); /* -------------------------------------------------------------------- */ /* validate the node tree to make sure that all the nodes are valid.*/ /* -------------------------------------------------------------------- */ if (!FLTValidFilterNode(psFilterNode)) { FLTFreeFilterEncodingNode(psFilterNode); return NULL; } return psFilterNode; } /************************************************************************/ /* int FLTValidFilterNode(FilterEncodingNode *psFilterNode) */ /* */ /* Validate that all the nodes are filled properly. We could */ /* have parts of the nodes that are correct and part which */ /* could be incorrect if the filter string sent is corrupted */ /* (eg missing a value :) */ /************************************************************************/ int FLTValidFilterNode(FilterEncodingNode *psFilterNode) { int bReturn = 0; if (!psFilterNode) return 0; if (psFilterNode->eType == FILTER_NODE_TYPE_UNDEFINED) return 0; if (psFilterNode->psLeftNode) { bReturn = FLTValidFilterNode(psFilterNode->psLeftNode); if (bReturn == 0) return 0; else if (psFilterNode->psRightNode) return FLTValidFilterNode(psFilterNode->psRightNode); } return 1; } /************************************************************************/ /* FLTIsGeometryFilterNodeType */ /************************************************************************/ static int FLTIsGeometryFilterNodeType(int eType) { return (eType == FILTER_NODE_TYPE_GEOMETRY_POINT || eType == FILTER_NODE_TYPE_GEOMETRY_LINE || eType == FILTER_NODE_TYPE_GEOMETRY_POLYGON); } /************************************************************************/ /* FLTFreeFilterEncodingNode */ /* */ /* recursive freeing of Filter Encoding nodes. */ /************************************************************************/ void FLTFreeFilterEncodingNode(FilterEncodingNode *psFilterNode) { if (psFilterNode) { if (psFilterNode->psLeftNode) { FLTFreeFilterEncodingNode(psFilterNode->psLeftNode); psFilterNode->psLeftNode = NULL; } if (psFilterNode->psRightNode) { FLTFreeFilterEncodingNode(psFilterNode->psRightNode); psFilterNode->psRightNode = NULL; } if (psFilterNode->pszSRS) free( psFilterNode->pszSRS); if( psFilterNode->pOther ) { if (psFilterNode->pszValue != NULL && strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) { FEPropertyIsLike* propIsLike = (FEPropertyIsLike *)psFilterNode->pOther; if( propIsLike->pszWildCard ) free( propIsLike->pszWildCard ); if( propIsLike->pszSingleChar ) free( propIsLike->pszSingleChar ); if( propIsLike->pszEscapeChar ) free( propIsLike->pszEscapeChar ); } else if (FLTIsGeometryFilterNodeType(psFilterNode->eType)) { msFreeShape((shapeObj *)(psFilterNode->pOther)); } /* else */ /* TODO free pOther special fields */ free( psFilterNode->pOther ); } /* Cannot free pszValue before, 'cause we are testing it above */ if( psFilterNode->pszValue ) free( psFilterNode->pszValue ); free(psFilterNode); } } /************************************************************************/ /* FLTCreateFilterEncodingNode */ /* */ /* return a FilterEncoding node. */ /************************************************************************/ FilterEncodingNode *FLTCreateFilterEncodingNode(void) { FilterEncodingNode *psFilterNode = NULL; psFilterNode = (FilterEncodingNode *)malloc(sizeof (FilterEncodingNode)); psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; psFilterNode->pszValue = NULL; psFilterNode->pOther = NULL; psFilterNode->pszSRS = NULL; psFilterNode->psLeftNode = NULL; psFilterNode->psRightNode = NULL; return psFilterNode; } FilterEncodingNode *FLTCreateBinaryCompFilterEncodingNode(void) { FilterEncodingNode *psFilterNode = NULL; psFilterNode = FLTCreateFilterEncodingNode(); /* used to store case sensitivity flag. Default is 0 meaning the comparing is case sensititive */ psFilterNode->pOther = (int *)malloc(sizeof(int)); (*(int *)(psFilterNode->pOther)) = 0; return psFilterNode; } /************************************************************************/ /* FLTFindGeometryNode */ /* */ /************************************************************************/ static CPLXMLNode* FLTFindGeometryNode(CPLXMLNode* psXMLNode, int* pbPoint, int* pbLine, int* pbPolygon) { CPLXMLNode *psGMLElement = NULL; psGMLElement = CPLGetXMLNode(psXMLNode, "Point"); if (!psGMLElement) psGMLElement = CPLGetXMLNode(psXMLNode, "PointType"); if (psGMLElement) *pbPoint =1; else { psGMLElement= CPLGetXMLNode(psXMLNode, "Polygon"); if (psGMLElement) *pbPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiPolygon"))) *pbPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "Surface"))) *pbPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiSurface"))) *pbPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "Box"))) *pbPolygon = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "LineString"))) *pbLine = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiLineString"))) *pbLine = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "Curve"))) *pbLine = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiCurve"))) *pbLine = 1; else if ((psGMLElement= CPLGetXMLNode(psXMLNode, "MultiPoint"))) *pbPoint = 1; } return psGMLElement; } /************************************************************************/ /* FLTGetPropertyName */ /************************************************************************/ static const char* FLTGetPropertyName(CPLXMLNode* psXMLNode) { const char* pszPropertyName; pszPropertyName = CPLGetXMLValue(psXMLNode, "PropertyName", NULL); if( pszPropertyName == NULL ) /* FE 2.0 ? */ pszPropertyName = CPLGetXMLValue(psXMLNode, "ValueReference", NULL); return pszPropertyName; } /************************************************************************/ /* FLTGetFirstChildNode */ /************************************************************************/ static CPLXMLNode* FLTGetFirstChildNode(CPLXMLNode* psXMLNode) { if( psXMLNode == NULL ) return NULL; psXMLNode = psXMLNode->psChild; while( psXMLNode != NULL ) { if( psXMLNode->eType == CXT_Element ) return psXMLNode; psXMLNode = psXMLNode->psNext; } return NULL; } /************************************************************************/ /* FLTGetNextSibblingNode */ /************************************************************************/ static CPLXMLNode* FLTGetNextSibblingNode(CPLXMLNode* psXMLNode) { if( psXMLNode == NULL ) return NULL; psXMLNode = psXMLNode->psNext; while( psXMLNode != NULL ) { if( psXMLNode->eType == CXT_Element ) return psXMLNode; psXMLNode = psXMLNode->psNext; } return NULL; } /************************************************************************/ /* FLTInsertElementInNode */ /* */ /* Utility function to parse an XML node and transfer the */ /* contents into the Filter Encoding node structure. */ /************************************************************************/ void FLTInsertElementInNode(FilterEncodingNode *psFilterNode, CPLXMLNode *psXMLNode) { int nStrLength = 0; char *pszTmp = NULL; FilterEncodingNode *psCurFilNode= NULL; CPLXMLNode *psCurXMLNode = NULL; CPLXMLNode *psTmpNode = NULL; CPLXMLNode *psFeatureIdNode = NULL; const char *pszFeatureId=NULL; char *pszFeatureIdList=NULL; if (psFilterNode && psXMLNode && psXMLNode->pszValue) { psFilterNode->pszValue = msStrdup(psXMLNode->pszValue); psFilterNode->psLeftNode = NULL; psFilterNode->psRightNode = NULL; /* -------------------------------------------------------------------- */ /* Logical filter. AND, OR and NOT are supported. Example of */ /* filer using logical filters : */ /* */ /* */ /* */ /* Person/Age */ /* 50 */ /* */ /* */ /* Person/Address/City */ /* Toronto */ /* */ /* */ /* */ /* -------------------------------------------------------------------- */ if (FLTIsLogicalFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_LOGICAL; if (strcasecmp(psFilterNode->pszValue, "AND") == 0 || strcasecmp(psFilterNode->pszValue, "OR") == 0) { CPLXMLNode* psFirstNode = FLTGetFirstChildNode(psXMLNode); CPLXMLNode* psSecondNode = FLTGetNextSibblingNode(psFirstNode); if (psFirstNode && psSecondNode) { /*2 operators */ CPLXMLNode* psNextNode = FLTGetNextSibblingNode(psSecondNode); if (psNextNode == NULL) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psFilterNode->psLeftNode, psFirstNode); psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psFilterNode->psRightNode, psSecondNode); } else { psCurXMLNode = psFirstNode; psCurFilNode = psFilterNode; while(psCurXMLNode) { psNextNode = FLTGetNextSibblingNode(psCurXMLNode); if (FLTGetNextSibblingNode(psNextNode)) { psCurFilNode->psLeftNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psCurFilNode->psLeftNode, psCurXMLNode); psCurFilNode->psRightNode = FLTCreateFilterEncodingNode(); psCurFilNode->psRightNode->eType = FILTER_NODE_TYPE_LOGICAL; psCurFilNode->psRightNode->pszValue = msStrdup(psFilterNode->pszValue); psCurFilNode = psCurFilNode->psRightNode; psCurXMLNode = psNextNode; } else { /*last 2 operators*/ psCurFilNode->psLeftNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psCurFilNode->psLeftNode, psCurXMLNode); psCurFilNode->psRightNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psCurFilNode->psRightNode, psNextNode); break; } } } } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } else if (strcasecmp(psFilterNode->pszValue, "NOT") == 0) { CPLXMLNode* psFirstNode = FLTGetFirstChildNode(psXMLNode); if (psFirstNode) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); FLTInsertElementInNode(psFilterNode->psLeftNode, psFirstNode); } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; }/* end if is logical */ /* -------------------------------------------------------------------- */ /* Spatial Filter. */ /* BBOX : */ /* */ /* */ /* Geometry */ /* */ /* 13.0983,31.5899 35.5472,42.8143*/ /* */ /* */ /* */ /* */ /* DWithin */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Geometry */ /* */ /* 13.0983,31.5899 */ /* */ /* 10 */ /* */ /* */ /* */ /* Intersect */ /* */ /* type="ogc:BinarySpatialOpType" substitutionGroup="ogc:spatialOps"/>*/ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* -------------------------------------------------------------------- */ else if (FLTIsSpatialFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_SPATIAL; if (strcasecmp(psXMLNode->pszValue, "BBOX") == 0) { char *pszSRS = NULL; const char* pszPropertyName = NULL; CPLXMLNode *psBox = NULL, *psEnvelope=NULL; rectObj sBox; int bCoordinatesValid = 0; pszPropertyName = FLTGetPropertyName(psXMLNode); psBox = CPLGetXMLNode(psXMLNode, "Box"); if (!psBox) psBox = CPLGetXMLNode(psXMLNode, "BoxType"); /*FE 1.0 used box FE1.1 uses envelop*/ if (psBox) bCoordinatesValid = FLTParseGMLBox(psBox, &sBox, &pszSRS); else if ((psEnvelope = CPLGetXMLNode(psXMLNode, "Envelope"))) bCoordinatesValid = FLTParseGMLEnvelope(psEnvelope, &sBox, &pszSRS); if (bCoordinatesValid) { /*set the srs if available*/ if (pszSRS) psFilterNode->pszSRS = pszSRS; psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; /* PropertyName is optional since FE 1.1.0, in which case */ /* the BBOX must apply to all geometry fields. As we support */ /* currently only one geometry field, this doesn't make much */ /* difference to further processing. */ if( pszPropertyName != NULL ) { psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); } /* coordinates */ psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_BBOX; psFilterNode->psRightNode->pOther = (rectObj *)msSmallMalloc(sizeof(rectObj)); ((rectObj *)psFilterNode->psRightNode->pOther)->minx = sBox.minx; ((rectObj *)psFilterNode->psRightNode->pOther)->miny = sBox.miny; ((rectObj *)psFilterNode->psRightNode->pOther)->maxx = sBox.maxx; ((rectObj *)psFilterNode->psRightNode->pOther)->maxy = sBox.maxy; } else { msFree(pszSRS); psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } } else if (strcasecmp(psXMLNode->pszValue, "DWithin") == 0 || strcasecmp(psXMLNode->pszValue, "Beyond") == 0) { shapeObj *psShape = NULL; int bPoint = 0, bLine = 0, bPolygon = 0; const char *pszUnits = NULL; const char* pszDistance = NULL; const char* pszPropertyName; char *pszSRS = NULL; CPLXMLNode *psGMLElement = NULL, *psDistance=NULL; pszPropertyName = FLTGetPropertyName(psXMLNode); psGMLElement = FLTFindGeometryNode(psXMLNode, &bPoint, &bLine, &bPolygon); psDistance = CPLGetXMLNode(psXMLNode, "Distance"); if( psDistance != NULL ) pszDistance = CPLGetXMLValue(psDistance, NULL, NULL ); if (pszPropertyName != NULL && psGMLElement && psDistance != NULL ) { pszUnits = CPLGetXMLValue(psDistance, "units", NULL); if( pszUnits == NULL ) /* FE 2.0 */ pszUnits = CPLGetXMLValue(psDistance, "uom", NULL); psShape = (shapeObj *)msSmallMalloc(sizeof(shapeObj)); msInitShape(psShape); if (FLTShapeFromGMLTree(psGMLElement, psShape, &pszSRS)) { /*set the srs if available*/ if (pszSRS) psFilterNode->pszSRS = pszSRS; psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); if (bPoint) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_POINT; else if (bLine) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_LINE; else if (bPolygon) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_POLYGON; psFilterNode->psRightNode->pOther = (shapeObj *)psShape; /*the value will be distance;units*/ psFilterNode->psRightNode->pszValue = msStrdup(pszDistance); if (pszUnits) { psFilterNode->psRightNode->pszValue= msStringConcatenate(psFilterNode->psRightNode->pszValue, ";"); psFilterNode->psRightNode->pszValue= msStringConcatenate(psFilterNode->psRightNode->pszValue, pszUnits); } } else { free(psShape); msFree(pszSRS); psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } else if (strcasecmp(psXMLNode->pszValue, "Intersect") == 0 || strcasecmp(psXMLNode->pszValue, "Intersects") == 0 || strcasecmp(psXMLNode->pszValue, "Equals") == 0 || strcasecmp(psXMLNode->pszValue, "Disjoint") == 0 || strcasecmp(psXMLNode->pszValue, "Touches") == 0 || strcasecmp(psXMLNode->pszValue, "Crosses") == 0 || strcasecmp(psXMLNode->pszValue, "Within") == 0 || strcasecmp(psXMLNode->pszValue, "Contains") == 0 || strcasecmp(psXMLNode->pszValue, "Overlaps") == 0) { shapeObj *psShape = NULL; int bLine = 0, bPolygon = 0, bPoint=0; char *pszSRS = NULL; const char* pszPropertyName; CPLXMLNode *psGMLElement = NULL; pszPropertyName = FLTGetPropertyName(psXMLNode); psGMLElement = FLTFindGeometryNode(psXMLNode, &bPoint, &bLine, &bPolygon); if (pszPropertyName != NULL && psGMLElement) { psShape = (shapeObj *)msSmallMalloc(sizeof(shapeObj)); msInitShape(psShape); if (FLTShapeFromGMLTree(psGMLElement, psShape, &pszSRS)) { /*set the srs if available*/ if (pszSRS) psFilterNode->pszSRS = pszSRS; psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); if (bPoint) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_POINT; else if (bLine) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_LINE; else if (bPolygon) psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_GEOMETRY_POLYGON; psFilterNode->psRightNode->pOther = (shapeObj *)psShape; } else { free(psShape); msFree(pszSRS); psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } }/* end of is spatial */ /* -------------------------------------------------------------------- */ /* Comparison Filter */ /* -------------------------------------------------------------------- */ else if (FLTIsComparisonFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_COMPARISON; /* -------------------------------------------------------------------- */ /* binary comaparison types. Example : */ /* */ /* */ /* */ /* SomeProperty */ /* 100 */ /* */ /* */ /* -------------------------------------------------------------------- */ if (FLTIsBinaryComparisonFilterType(psXMLNode->pszValue)) { const char* pszPropertyName = FLTGetPropertyName(psXMLNode); if (pszPropertyName != NULL ) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); psTmpNode = CPLSearchXMLNode(psXMLNode, "Literal"); if (psTmpNode) { const char* pszLiteral = CPLGetXMLValue(psTmpNode, NULL, NULL); psFilterNode->psRightNode = FLTCreateBinaryCompFilterEncodingNode(); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; if (pszLiteral != NULL) { const char* pszMatchCase; psFilterNode->psRightNode->pszValue = msStrdup(pszLiteral); pszMatchCase = CPLGetXMLValue(psXMLNode, "matchCase", NULL); /*check if the matchCase attribute is set*/ if( pszMatchCase != NULL && strcasecmp( pszMatchCase, "false") == 0) { (*(int *)psFilterNode->psRightNode->pOther) = 1; } } /* special case where the user puts an empty value */ /* for the Literal so it can end up as an empty */ /* string query in the expression */ else psFilterNode->psRightNode->pszValue = NULL; } } if (psFilterNode->psLeftNode == NULL || psFilterNode->psRightNode == NULL) psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } /* -------------------------------------------------------------------- */ /* PropertyIsBetween filter : extract property name and boudary */ /* values. The boundary values are stored in the right */ /* node. The values are separated by a semi-column (;) */ /* Eg of Filter : */ /* */ /* DEPTH */ /* 400 */ /* 800 */ /* */ /* */ /* Or */ /* */ /* DEPTH */ /* 400 */ /* 800 */ /* */ /* -------------------------------------------------------------------- */ else if (strcasecmp(psXMLNode->pszValue, "PropertyIsBetween") == 0) { const char* pszPropertyName = FLTGetPropertyName(psXMLNode); CPLXMLNode* psLowerBoundary = CPLGetXMLNode(psXMLNode, "LowerBoundary"); CPLXMLNode* psUpperBoundary = CPLGetXMLNode(psXMLNode, "UpperBoundary"); const char* pszLowerNode = NULL; const char* pszUpperNode = NULL; if( psLowerBoundary != NULL ) { /* check if the is there */ if (CPLGetXMLNode(psLowerBoundary, "Literal") != NULL) pszLowerNode = CPLGetXMLValue(psLowerBoundary, "Literal", NULL); else pszLowerNode = CPLGetXMLValue(psLowerBoundary, NULL, NULL); } if( psUpperBoundary != NULL ) { if (CPLGetXMLNode(psUpperBoundary, "Literal") != NULL) pszUpperNode = CPLGetXMLValue(psUpperBoundary, "Literal", NULL); else pszUpperNode = CPLGetXMLValue(psUpperBoundary, NULL, NULL); } if (pszPropertyName != NULL && pszLowerNode != NULL && pszUpperNode != NULL) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_BOUNDARY; /* adding a ; between bounary values */ nStrLength = strlen(pszLowerNode) + strlen(pszUpperNode) + 2; psFilterNode->psRightNode->pszValue = (char *)malloc(sizeof(char)*(nStrLength)); strcpy( psFilterNode->psRightNode->pszValue, pszLowerNode); strlcat(psFilterNode->psRightNode->pszValue, ";", nStrLength); strlcat(psFilterNode->psRightNode->pszValue, pszUpperNode, nStrLength); } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; }/* end of PropertyIsBetween */ /* -------------------------------------------------------------------- */ /* PropertyIsLike */ /* */ /* */ /* */ /* LAST_NAME */ /* JOHN* */ /* */ /* */ /* -------------------------------------------------------------------- */ else if (strcasecmp(psXMLNode->pszValue, "PropertyIsLike") == 0) { const char* pszPropertyName = FLTGetPropertyName(psXMLNode); const char* pszLiteral = CPLGetXMLValue(psXMLNode, "Literal", NULL); const char* pszWildCard = CPLGetXMLValue(psXMLNode, "wildCard", NULL); const char* pszSingleChar = CPLGetXMLValue(psXMLNode, "singleChar", NULL); const char* pszEscapeChar = CPLGetXMLValue(psXMLNode, "escape", NULL); if( pszEscapeChar == NULL ) pszEscapeChar = CPLGetXMLValue(psXMLNode, "escapeChar", NULL); if (pszPropertyName != NULL && pszLiteral != NULL && pszWildCard != NULL && pszSingleChar != NULL && pszEscapeChar != NULL) { FEPropertyIsLike* propIsLike; propIsLike = (FEPropertyIsLike *)malloc(sizeof(FEPropertyIsLike)); psFilterNode->pOther = propIsLike; propIsLike->bCaseInsensitive = 0; propIsLike->pszWildCard = msStrdup(pszWildCard); propIsLike->pszSingleChar = msStrdup(pszSingleChar); propIsLike->pszEscapeChar = msStrdup(pszEscapeChar); pszTmp = (char *)CPLGetXMLValue(psXMLNode, "matchCase", NULL); if (pszTmp && strcasecmp(pszTmp, "false") == 0) { propIsLike->bCaseInsensitive =1; } /* -------------------------------------------------------------------- */ /* Create left and right node for the attribute and the value. */ /* -------------------------------------------------------------------- */ psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); psFilterNode->psRightNode->pszValue = msStrdup(pszLiteral); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } else if (strcasecmp(psXMLNode->pszValue, "PropertyIsNull") == 0) { const char* pszPropertyName = FLTGetPropertyName(psXMLNode); if( pszPropertyName != NULL ) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } else if (strcasecmp(psXMLNode->pszValue, "PropertyIsNil") == 0) { const char* pszPropertyName = FLTGetPropertyName(psXMLNode); if( pszPropertyName != NULL ) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } } /* -------------------------------------------------------------------- */ /* FeatureId Filter */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Note that for FES1.1.0 the featureid has been depricated in */ /* favor of GmlObjectId */ /* */ /* */ /* And in FES 2.0, in favor of */ /* -------------------------------------------------------------------- */ else if (FLTIsFeatureIdFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_FEATUREID; pszFeatureId = CPLGetXMLValue(psXMLNode, "fid", NULL); /*for FE 1.1.0 GmlObjectId */ if (pszFeatureId == NULL) pszFeatureId = CPLGetXMLValue(psXMLNode, "id", NULL); /*for FE 2.0 ResourceId */ if (pszFeatureId == NULL) pszFeatureId = CPLGetXMLValue(psXMLNode, "rid", NULL); pszFeatureIdList = NULL; psFeatureIdNode = psXMLNode; while (psFeatureIdNode) { pszFeatureId = CPLGetXMLValue(psFeatureIdNode, "fid", NULL); if (!pszFeatureId) pszFeatureId = CPLGetXMLValue(psFeatureIdNode, "id", NULL); if (!pszFeatureId) pszFeatureId = CPLGetXMLValue(psFeatureIdNode, "rid", NULL); if (pszFeatureId) { if (pszFeatureIdList) pszFeatureIdList = msStringConcatenate(pszFeatureIdList, ","); pszFeatureIdList = msStringConcatenate(pszFeatureIdList, pszFeatureId); } psFeatureIdNode = psFeatureIdNode->psNext; } if (pszFeatureIdList) { msFree(psFilterNode->pszValue); psFilterNode->pszValue = msStrdup(pszFeatureIdList); msFree(pszFeatureIdList); } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } /* -------------------------------------------------------------------- */ /* Temporal Filter. */ /* gml:TimeInstant 2005-05-17T00:00:00Z 2005-05-23T00:00:00Z */ /* -------------------------------------------------------------------- */ else if (FLTIsTemporalFilterType(psXMLNode->pszValue)) { psFilterNode->eType = FILTER_NODE_TYPE_TEMPORAL; if (strcasecmp(psXMLNode->pszValue, "During") == 0) { const char* pszPropertyName = NULL; const char* pszBeginTime; const char* pszEndTime; pszPropertyName = FLTGetPropertyName(psXMLNode); pszBeginTime = CPLGetXMLValue(psXMLNode, "TimePeriod.begin.TimeInstant.timePosition", NULL); if( pszBeginTime == NULL ) pszBeginTime = CPLGetXMLValue(psXMLNode, "TimePeriod.beginPosition", NULL); pszEndTime = CPLGetXMLValue(psXMLNode, "TimePeriod.end.TimeInstant.timePosition", NULL); if( pszEndTime == NULL ) pszEndTime = CPLGetXMLValue(psXMLNode, "TimePeriod.endPosition", NULL); if (pszPropertyName && pszBeginTime && pszEndTime && strchr(pszBeginTime, '\'') == NULL && strchr(pszBeginTime, '\\') == NULL && strchr(pszEndTime, '\'') == NULL && strchr(pszEndTime, '\\') == NULL && msTimeGetResolution(pszBeginTime) >= 0 && msTimeGetResolution(pszEndTime) >= 0) { psFilterNode->psLeftNode = FLTCreateFilterEncodingNode(); psFilterNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psFilterNode->psLeftNode->pszValue = msStrdup(pszPropertyName); psFilterNode->psRightNode = FLTCreateFilterEncodingNode(); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_TIME_PERIOD; psFilterNode->psRightNode->pszValue = msSmallMalloc( strlen(pszBeginTime) + strlen(pszEndTime) + 2 ); sprintf(psFilterNode->psRightNode->pszValue, "%s/%s", pszBeginTime, pszEndTime); } else psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } else { psFilterNode->eType = FILTER_NODE_TYPE_UNDEFINED; } }/* end of is temporal */ } } /************************************************************************/ /* int FLTIsLogicalFilterType((char *pszValue) */ /* */ /* return TRUE if the value of the node is of logical filter */ /* encoding type. */ /************************************************************************/ int FLTIsLogicalFilterType(const char *pszValue) { if (pszValue) { if (strcasecmp(pszValue, "AND") == 0 || strcasecmp(pszValue, "OR") == 0 || strcasecmp(pszValue, "NOT") == 0) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsBinaryComparisonFilterType(char *pszValue) */ /* */ /* Binary comparison filter type. */ /************************************************************************/ int FLTIsBinaryComparisonFilterType(const char *pszValue) { if (pszValue) { if (strcasecmp(pszValue, "PropertyIsEqualTo") == 0 || strcasecmp(pszValue, "PropertyIsNotEqualTo") == 0 || strcasecmp(pszValue, "PropertyIsLessThan") == 0 || strcasecmp(pszValue, "PropertyIsGreaterThan") == 0 || strcasecmp(pszValue, "PropertyIsLessThanOrEqualTo") == 0 || strcasecmp(pszValue, "PropertyIsGreaterThanOrEqualTo") == 0) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsComparisonFilterType(char *pszValue) */ /* */ /* return TRUE if the value of the node is of comparison filter */ /* encoding type. */ /************************************************************************/ int FLTIsComparisonFilterType(const char *pszValue) { if (pszValue) { if (FLTIsBinaryComparisonFilterType(pszValue) || strcasecmp(pszValue, "PropertyIsLike") == 0 || strcasecmp(pszValue, "PropertyIsBetween") == 0 || strcasecmp(pszValue, "PropertyIsNull") == 0 || strcasecmp(pszValue, "PropertyIsNil") == 0) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsFeatureIdFilterType(char *pszValue) */ /* */ /* return TRUE if the value of the node is of featureid filter */ /* encoding type. */ /************************************************************************/ int FLTIsFeatureIdFilterType(const char *pszValue) { if (pszValue && (strcasecmp(pszValue, "FeatureId") == 0 || strcasecmp(pszValue, "GmlObjectId") == 0 || strcasecmp(pszValue, "ResourceId") == 0)) return MS_TRUE; return MS_FALSE; } /************************************************************************/ /* int FLTIsSpatialFilterType(char *pszValue) */ /* */ /* return TRUE if the value of the node is of spatial filter */ /* encoding type. */ /************************************************************************/ int FLTIsSpatialFilterType(const char *pszValue) { if (pszValue) { if ( strcasecmp(pszValue, "BBOX") == 0 || strcasecmp(pszValue, "DWithin") == 0 || strcasecmp(pszValue, "Intersect") == 0 || strcasecmp(pszValue, "Intersects") == 0 || strcasecmp(pszValue, "Equals") == 0 || strcasecmp(pszValue, "Disjoint") == 0 || strcasecmp(pszValue, "Touches") == 0 || strcasecmp(pszValue, "Crosses") == 0 || strcasecmp(pszValue, "Within") == 0 || strcasecmp(pszValue, "Contains") == 0 || strcasecmp(pszValue, "Overlaps") == 0 || strcasecmp(pszValue, "Beyond") == 0) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsTemportalFilterType(char *pszValue) */ /* */ /* return TRUE if the value of the node is of temporal filter */ /* encoding type. */ /************************************************************************/ int FLTIsTemporalFilterType(const char *pszValue) { if (pszValue) { if ( strcasecmp(pszValue, "During") == 0 ) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* int FLTIsSupportedFilterType(CPLXMLNode *psXMLNode) */ /* */ /* Verfify if the value of the node is one of the supported */ /* filter type. */ /************************************************************************/ int FLTIsSupportedFilterType(CPLXMLNode *psXMLNode) { if (psXMLNode) { if (FLTIsLogicalFilterType(psXMLNode->pszValue) || FLTIsSpatialFilterType(psXMLNode->pszValue) || FLTIsComparisonFilterType(psXMLNode->pszValue) || FLTIsFeatureIdFilterType(psXMLNode->pszValue) || FLTIsTemporalFilterType(psXMLNode->pszValue)) return MS_TRUE; } return MS_FALSE; } /************************************************************************/ /* FLTNumberOfFilterType */ /* */ /* Loop trhough the nodes and return the number of nodes of */ /* specified value. */ /************************************************************************/ int FLTNumberOfFilterType(FilterEncodingNode *psFilterNode, const char *szType) { int nCount = 0; int nLeftNode=0 , nRightNode = 0; if (!psFilterNode || !szType || !psFilterNode->pszValue) return 0; if (strcasecmp(psFilterNode->pszValue, (char*)szType) == 0) nCount++; if (psFilterNode->psLeftNode) nLeftNode = FLTNumberOfFilterType(psFilterNode->psLeftNode, szType); nCount += nLeftNode; if (psFilterNode->psRightNode) nRightNode = FLTNumberOfFilterType(psFilterNode->psRightNode, szType); nCount += nRightNode; return nCount; } /************************************************************************/ /* FLTValidForBBoxFilter */ /* */ /* Validate if there is only one BBOX filter node. Here is waht */ /* is supported (is valid) : */ /* - one node which is a BBOX */ /* - a logical AND with a valid BBOX */ /* */ /* eg 1: */ /* */ /* Geometry */ /* */ /* 13.0983,31.5899 35.5472,42.8143*/ /* */ /* */ /* */ /* */ /* eg 2 : */ /* */ /* */ /* Geometry */ /* */ /* 13.0983,31.5899 35.5472,42.8143*/ /* */ /* */ /* */ /* SomeProperty */ /* 100 */ /* */ /* */ /* */ /* */ /************************************************************************/ int FLTValidForBBoxFilter(FilterEncodingNode *psFilterNode) { int nCount = 0; if (!psFilterNode || !psFilterNode->pszValue) return 1; nCount = FLTNumberOfFilterType(psFilterNode, "BBOX"); if (nCount > 1) return 0; else if (nCount == 0) return 1; /* nCount ==1 */ if (strcasecmp(psFilterNode->pszValue, "BBOX") == 0) return 1; if (strcasecmp(psFilterNode->pszValue, "AND") == 0) { return FLTValidForBBoxFilter(psFilterNode->psLeftNode) && FLTValidForBBoxFilter(psFilterNode->psRightNode); } return 0; } #if 0 static int FLTHasUniqueTopLevelDuringFilter(FilterEncodingNode *psFilterNode) { int nCount = 0; if (!psFilterNode || !psFilterNode->pszValue) return 1; nCount = FLTNumberOfFilterType(psFilterNode, "During"); if (nCount > 1) return 0; else if (nCount == 0) return 1; /* nCount ==1 */ if (strcasecmp(psFilterNode->pszValue, "During") == 0) return 1; if (strcasecmp(psFilterNode->pszValue, "AND") == 0) { return FLTHasUniqueTopLevelDuringFilter(psFilterNode->psLeftNode) && FLTHasUniqueTopLevelDuringFilter(psFilterNode->psRightNode); } return 0; } #endif int FLTIsLineFilter(FilterEncodingNode *psFilterNode) { if (!psFilterNode || !psFilterNode->pszValue) return 0; if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL && psFilterNode->psRightNode && psFilterNode->psRightNode->eType == FILTER_NODE_TYPE_GEOMETRY_LINE) return 1; return 0; } int FLTIsPolygonFilter(FilterEncodingNode *psFilterNode) { if (!psFilterNode || !psFilterNode->pszValue) return 0; if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL && psFilterNode->psRightNode && psFilterNode->psRightNode->eType == FILTER_NODE_TYPE_GEOMETRY_POLYGON) return 1; return 0; } int FLTIsPointFilter(FilterEncodingNode *psFilterNode) { if (!psFilterNode || !psFilterNode->pszValue) return 0; if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL && psFilterNode->psRightNode && psFilterNode->psRightNode->eType == FILTER_NODE_TYPE_GEOMETRY_POINT) return 1; return 0; } int FLTIsBBoxFilter(FilterEncodingNode *psFilterNode) { if (!psFilterNode || !psFilterNode->pszValue) return 0; if (strcasecmp(psFilterNode->pszValue, "BBOX") == 0) return 1; return 0; } shapeObj *FLTGetShape(FilterEncodingNode *psFilterNode, double *pdfDistance, int *pnUnit) { char **tokens = NULL; int nTokens = 0; FilterEncodingNode *psNode = psFilterNode; char *szUnitStr = NULL; char *szUnit = NULL; if (psNode) { if (psNode->eType == FILTER_NODE_TYPE_SPATIAL && psNode->psRightNode) psNode = psNode->psRightNode; if (FLTIsGeometryFilterNodeType(psNode->eType)) { if (psNode->pszValue && pdfDistance) { /* sytnax expected is "distance;unit" or just "distance" if unit is there syntax is "URI#unit" (eg http://..../#m) or just "unit" */ tokens = msStringSplit(psNode->pszValue,';', &nTokens); if (tokens && nTokens >= 1) { *pdfDistance = atof(tokens[0]); if (nTokens == 2 && pnUnit) { szUnitStr = msStrdup(tokens[1]); msFreeCharArray(tokens, nTokens); nTokens = 0; tokens = msStringSplit(szUnitStr,'#', &nTokens); msFree(szUnitStr); if (tokens && nTokens >= 1) { if (nTokens ==1) szUnit = tokens[0]; else szUnit = tokens[1]; if (strcasecmp(szUnit,"m") == 0 || strcasecmp(szUnit,"meters") == 0 ) *pnUnit = MS_METERS; else if (strcasecmp(szUnit,"km") == 0 || strcasecmp(szUnit,"kilometers") == 0) *pnUnit = MS_KILOMETERS; else if (strcasecmp(szUnit,"NM") == 0 || strcasecmp(szUnit,"nauticalmiles") == 0) *pnUnit = MS_NAUTICALMILES; else if (strcasecmp(szUnit,"mi") == 0 || strcasecmp(szUnit,"miles") == 0) *pnUnit = MS_MILES; else if (strcasecmp(szUnit,"in") == 0 || strcasecmp(szUnit,"inches") == 0) *pnUnit = MS_INCHES; else if (strcasecmp(szUnit,"ft") == 0 || strcasecmp(szUnit,"feet") == 0) *pnUnit = MS_FEET; else if (strcasecmp(szUnit,"deg") == 0 || strcasecmp(szUnit,"dd") == 0) *pnUnit = MS_DD; else if (strcasecmp(szUnit,"px") == 0) *pnUnit = MS_PIXELS; } } } msFreeCharArray(tokens, nTokens); } return (shapeObj *)psNode->pOther; } } return NULL; } /************************************************************************/ /* FLTGetBBOX */ /* */ /* Loop through the nodes are return the coordinates of the */ /* first bbox node found. The retrun value is the epsg code of */ /* the bbox. */ /************************************************************************/ const char *FLTGetBBOX(FilterEncodingNode *psFilterNode, rectObj *psRect) { const char *pszReturn = NULL; if (!psFilterNode || !psRect) return NULL; if (psFilterNode->pszValue && strcasecmp(psFilterNode->pszValue, "BBOX") == 0) { if (psFilterNode->psRightNode && psFilterNode->psRightNode->pOther) { rectObj* pRect= (rectObj *)psFilterNode->psRightNode->pOther; psRect->minx = pRect->minx; psRect->miny = pRect->miny; psRect->maxx = pRect->maxx; psRect->maxy = pRect->maxy; return psFilterNode->pszSRS; } } else { pszReturn = FLTGetBBOX(psFilterNode->psLeftNode, psRect); if (pszReturn) return pszReturn; else return FLTGetBBOX(psFilterNode->psRightNode, psRect); } return pszReturn; } const char* FLTGetDuring(FilterEncodingNode *psFilterNode, const char** ppszTimeField) { const char *pszReturn = NULL; if (!psFilterNode || !ppszTimeField) return NULL; if (psFilterNode->pszValue && strcasecmp(psFilterNode->pszValue, "During") == 0) { *ppszTimeField = psFilterNode->psLeftNode->pszValue; return psFilterNode->psRightNode->pszValue; } else { pszReturn = FLTGetDuring(psFilterNode->psLeftNode, ppszTimeField); if (pszReturn) return pszReturn; else return FLTGetDuring(psFilterNode->psRightNode, ppszTimeField); } return pszReturn; } /************************************************************************/ /* FLTGetSQLExpression */ /* */ /* Build SQL expressions from the mapserver nodes. */ /************************************************************************/ char *FLTGetSQLExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszExpression = NULL; const char *pszAttribute = NULL; char szTmp[256]; char **tokens = NULL; int nTokens = 0, i=0, bString=0; if (psFilterNode == NULL || lp == NULL) return NULL; if (psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON) { if ( psFilterNode->psLeftNode && psFilterNode->psRightNode) { if (FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) { pszExpression = FLTGetBinaryComparisonSQLExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0) { pszExpression = FLTGetIsBetweenComparisonSQLExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) { pszExpression = FLTGetIsLikeComparisonSQLExpression(psFilterNode, lp); } } } else if (psFilterNode->eType == FILTER_NODE_TYPE_LOGICAL) { if (strcasecmp(psFilterNode->pszValue, "AND") == 0 || strcasecmp(psFilterNode->pszValue, "OR") == 0) { pszExpression = FLTGetLogicalComparisonSQLExpresssion(psFilterNode, lp); } else if (strcasecmp(psFilterNode->pszValue, "NOT") == 0) { pszExpression = FLTGetLogicalComparisonSQLExpresssion(psFilterNode, lp); } } else if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL) { /* TODO */ } else if (psFilterNode->eType == FILTER_NODE_TYPE_FEATUREID) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) if (psFilterNode->pszValue) { pszAttribute = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid"); if (pszAttribute) { tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens); bString = 0; if (tokens && nTokens > 0) { for (i=0; iconnectiontype == MS_OGR || lp->connectiontype == MS_POSTGIS ) snprintf(szTmp, sizeof(szTmp), "(CAST(%s AS CHARACTER(255)) = '%s')" , pszAttribute, pszEscapedStr); else snprintf(szTmp, sizeof(szTmp), "(%s = '%s')" , pszAttribute, pszEscapedStr); } else snprintf(szTmp, sizeof(szTmp), "(%s = %s)" , pszAttribute, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr=NULL; if (pszExpression != NULL) pszExpression = msStringConcatenate(pszExpression, " OR "); else /*opening and closing brackets*/ pszExpression = msStringConcatenate(pszExpression, "("); pszExpression = msStringConcatenate(pszExpression, szTmp); } msFreeCharArray(tokens, nTokens); } } /*opening and closing brackets*/ if (pszExpression) pszExpression = msStringConcatenate(pszExpression, ")"); } #else msSetError(MS_MISCERR, "OWS support is not available.", "FLTGetSQLExpression()"); return(MS_FAILURE); #endif } else if ( lp->connectiontype != MS_OGR && psFilterNode->eType == FILTER_NODE_TYPE_TEMPORAL ) pszExpression = FLTGetTimeExpression(psFilterNode, lp); return pszExpression; } /************************************************************************/ /* FLTGetLogicalComparisonSQLExpresssion */ /* */ /* Return the expression for logical comparison expression. */ /************************************************************************/ char *FLTGetLogicalComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszBuffer = NULL; char *pszTmp = NULL; int nTmp = 0; if (lp == NULL) return NULL; /* ==================================================================== */ /* special case for BBOX node. */ /* ==================================================================== */ if (psFilterNode->psLeftNode && psFilterNode->psRightNode && ((strcasecmp(psFilterNode->psLeftNode->pszValue, "BBOX") == 0) || (strcasecmp(psFilterNode->psRightNode->pszValue, "BBOX") == 0))) { if (strcasecmp(psFilterNode->psLeftNode->pszValue, "BBOX") != 0) pszTmp = FLTGetSQLExpression(psFilterNode->psLeftNode, lp); else pszTmp = FLTGetSQLExpression(psFilterNode->psRightNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + 1)); sprintf(pszBuffer, "%s", pszTmp); } /* ==================================================================== */ /* special case for temporal filter node (OGR layer only) */ /* ==================================================================== */ else if (lp->connectiontype == MS_OGR && psFilterNode->psLeftNode && psFilterNode->psRightNode && (psFilterNode->psLeftNode->eType == FILTER_NODE_TYPE_TEMPORAL || psFilterNode->psRightNode->eType == FILTER_NODE_TYPE_TEMPORAL) ) { if (psFilterNode->psLeftNode->eType != FILTER_NODE_TYPE_TEMPORAL) pszTmp = FLTGetSQLExpression(psFilterNode->psLeftNode, lp); else pszTmp = FLTGetSQLExpression(psFilterNode->psRightNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + 1)); sprintf(pszBuffer, "%s", pszTmp); } /* -------------------------------------------------------------------- */ /* OR and AND */ /* -------------------------------------------------------------------- */ else if (psFilterNode->psLeftNode && psFilterNode->psRightNode) { pszTmp = FLTGetSQLExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + strlen(psFilterNode->pszValue) + 5)); pszBuffer[0] = '\0'; strcat(pszBuffer, " ("); strcat(pszBuffer, pszTmp); strcat(pszBuffer, " "); strcat(pszBuffer, psFilterNode->pszValue); strcat(pszBuffer, " "); free( pszTmp ); nTmp = strlen(pszBuffer); pszTmp = FLTGetSQLExpression(psFilterNode->psRightNode, lp); if (!pszTmp) { free(pszBuffer); return NULL; } pszBuffer = (char *)realloc(pszBuffer, sizeof(char) * (strlen(pszTmp) + nTmp +3)); strcat(pszBuffer, pszTmp); strcat(pszBuffer, ") "); } /* -------------------------------------------------------------------- */ /* NOT */ /* -------------------------------------------------------------------- */ else if (psFilterNode->psLeftNode && strcasecmp(psFilterNode->pszValue, "NOT") == 0) { pszTmp = FLTGetSQLExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; pszBuffer = (char *)malloc(sizeof(char) * (strlen(pszTmp) + 9)); pszBuffer[0] = '\0'; strcat(pszBuffer, " (NOT "); strcat(pszBuffer, pszTmp); strcat(pszBuffer, ") "); } else return NULL; /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ if( pszTmp != NULL ) free( pszTmp ); return pszBuffer; } /************************************************************************/ /* FLTGetBinaryComparisonSQLExpresssion */ /* */ /* Return the expression for a binary comparison filter node. */ /************************************************************************/ char *FLTGetBinaryComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { const size_t bufferSize = 1024; char szBuffer[1024]; int bString=0; char szTmp[256]; char* pszEscapedStr = NULL; szBuffer[0] = '\0'; if (!psFilterNode || ! FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) return NULL; /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (psFilterNode->psRightNode->pszValue) { const char* pszOFGType; snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue); pszOFGType = msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp); if (pszOFGType!= NULL && strcasecmp(pszOFGType, "Character") == 0) bString = 1; else if (FLTIsNumeric(psFilterNode->psRightNode->pszValue) == MS_FALSE) bString = 1; } /* specical case to be able to have empty strings in the expression. */ if (psFilterNode->psRightNode->pszValue == NULL) bString = 1; /*opening bracket*/ strlcat(szBuffer, " (", bufferSize); pszEscapedStr = msLayerEscapePropertyName(lp, psFilterNode->psLeftNode->pszValue); /* attribute */ /*case insensitive set ? */ if (bString && strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0 && psFilterNode->psRightNode->pOther && (*(int *)psFilterNode->psRightNode->pOther) == 1) { snprintf(szTmp, sizeof(szTmp), "lower(%s) ", pszEscapedStr); strlcat(szBuffer, szTmp, bufferSize); } else strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr = NULL; /* logical operator */ if (strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0) strlcat(szBuffer, "=", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsNotEqualTo") == 0) strlcat(szBuffer, "<>", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThan") == 0) strlcat(szBuffer, "<", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThan") == 0) strlcat(szBuffer, ">", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThanOrEqualTo") == 0) strlcat(szBuffer, "<=", bufferSize); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThanOrEqualTo") == 0) strlcat(szBuffer, ">=", bufferSize); strlcat(szBuffer, " ", bufferSize); /* value */ if (bString && psFilterNode->psRightNode->pszValue && strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0 && psFilterNode->psRightNode->pOther && (*(int *)psFilterNode->psRightNode->pOther) == 1) { char* pszEscapedStr; pszEscapedStr = msLayerEscapeSQLParam(lp, psFilterNode->psRightNode->pszValue); snprintf(szTmp, sizeof(szTmp), "lower('%s') ", pszEscapedStr); msFree(pszEscapedStr); strlcat(szBuffer, szTmp, bufferSize); } else { if (bString) strlcat(szBuffer, "'", bufferSize); if (psFilterNode->psRightNode->pszValue) { if (bString) { char* pszEscapedStr; pszEscapedStr = msLayerEscapeSQLParam(lp, psFilterNode->psRightNode->pszValue); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr=NULL; } else strlcat(szBuffer, psFilterNode->psRightNode->pszValue, bufferSize); } if (bString) strlcat(szBuffer, "'", bufferSize); } /*closing bracket*/ strlcat(szBuffer, ") ", bufferSize); return msStrdup(szBuffer); } /************************************************************************/ /* FLTGetIsBetweenComparisonSQLExpresssion */ /* */ /* Build an SQL expresssion for IsBteween Filter. */ /************************************************************************/ char *FLTGetIsBetweenComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { const size_t bufferSize = 1024; char szBuffer[1024]; char **aszBounds = NULL; int nBounds = 0; int bString=0; char szTmp[256]; char* pszEscapedStr; szBuffer[0] = '\0'; if (!psFilterNode || !(strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0)) return NULL; if (!psFilterNode->psLeftNode || !psFilterNode->psRightNode ) return NULL; /* -------------------------------------------------------------------- */ /* Get the bounds value which are stored like boundmin;boundmax */ /* -------------------------------------------------------------------- */ aszBounds = msStringSplit(psFilterNode->psRightNode->pszValue, ';', &nBounds); if (nBounds != 2) { msFreeCharArray(aszBounds, nBounds); return NULL; } /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (aszBounds[0]) { const char* pszOFGType; snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue); pszOFGType = msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp); if (pszOFGType!= NULL && strcasecmp(pszOFGType, "Character") == 0) bString = 1; else if (FLTIsNumeric(aszBounds[0]) == MS_FALSE) bString = 1; } if (!bString) { if (aszBounds[1]) { if (FLTIsNumeric(aszBounds[1]) == MS_FALSE) bString = 1; } } /* -------------------------------------------------------------------- */ /* build expresssion. */ /* -------------------------------------------------------------------- */ /*opening paranthesis */ strlcat(szBuffer, " (", bufferSize); /* attribute */ pszEscapedStr = msLayerEscapePropertyName(lp, psFilterNode->psLeftNode->pszValue); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr = NULL; /*between*/ strlcat(szBuffer, " BETWEEN ", bufferSize); /*bound 1*/ if (bString) strlcat(szBuffer,"'", bufferSize); pszEscapedStr = msLayerEscapeSQLParam( lp, aszBounds[0]); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr=NULL; if (bString) strlcat(szBuffer,"'", bufferSize); strlcat(szBuffer, " AND ", bufferSize); /*bound 2*/ if (bString) strlcat(szBuffer, "'", bufferSize); pszEscapedStr = msLayerEscapeSQLParam( lp, aszBounds[1]); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr=NULL; if (bString) strlcat(szBuffer,"'", bufferSize); /*closing paranthesis*/ strlcat(szBuffer, ")", bufferSize); msFreeCharArray(aszBounds, nBounds); return msStrdup(szBuffer); } /************************************************************************/ /* FLTGetIsLikeComparisonSQLExpression */ /* */ /* Build an sql expression for IsLike filter. */ /************************************************************************/ char *FLTGetIsLikeComparisonSQLExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { const size_t bufferSize = 1024; char szBuffer[1024]; char *pszValue = NULL; const char *pszWild = NULL; const char *pszSingle = NULL; const char *pszEscape = NULL; char szTmp[4]; int nLength=0, i=0, j=0; int bCaseInsensitive = 0; char *pszEscapedStr = NULL; FEPropertyIsLike* propIsLike; if (!psFilterNode || !psFilterNode->pOther || !psFilterNode->psLeftNode || !psFilterNode->psRightNode || !psFilterNode->psRightNode->pszValue) return NULL; propIsLike = (FEPropertyIsLike *)psFilterNode->pOther; pszWild = propIsLike->pszWildCard; pszSingle = propIsLike->pszSingleChar; pszEscape = propIsLike->pszEscapeChar; bCaseInsensitive = propIsLike->bCaseInsensitive; if (!pszWild || strlen(pszWild) == 0 || !pszSingle || strlen(pszSingle) == 0 || !pszEscape || strlen(pszEscape) == 0) return NULL; if (pszEscape[0] == '\'') { /* This might be valid, but the risk of SQL injection is too high */ /* and the below code is not ready for that */ /* Someone who does this has clearly suspect intentions ! */ msSetError(MS_MISCERR, "Single quote character is not allowed as an escaping character.", "FLTGetIsLikeComparisonSQLExpression()"); return NULL; } szBuffer[0] = '\0'; /*opening bracket*/ strlcat(szBuffer, " (", bufferSize); /* attribute name */ pszEscapedStr = msLayerEscapePropertyName(lp, psFilterNode->psLeftNode->pszValue); strlcat(szBuffer, pszEscapedStr, bufferSize); msFree(pszEscapedStr); pszEscapedStr = NULL; if (lp->connectiontype == MS_POSTGIS) { if (bCaseInsensitive == 1) strlcat(szBuffer, "::text ilike '", bufferSize); else strlcat(szBuffer, "::text like '", bufferSize); } else strlcat(szBuffer, " like '", bufferSize); pszValue = psFilterNode->psRightNode->pszValue; nLength = strlen(pszValue); pszEscapedStr = (char*) msSmallMalloc( 3 * nLength + 1); for (i=0, j=0; iconnectiontype != MS_OGR) { if (lp->connectiontype == MS_POSTGIS && pszEscape[0] == '\\') strlcat(szBuffer, " escape E'", bufferSize); else strlcat(szBuffer, " escape '", bufferSize); szTmp[0] = pszEscape[0]; if (pszEscape[0] == '\\') { szTmp[1] = '\\'; szTmp[2] = '\''; szTmp[3] = '\0'; } else { szTmp[1] = '\''; szTmp[2] = '\0'; } strlcat(szBuffer, szTmp, bufferSize); } strlcat(szBuffer, ") ", bufferSize); return msStrdup(szBuffer); } /************************************************************************/ /* FLTHasSpatialFilter */ /* */ /* Utility function to see if a spatial filter is included in */ /* the node. */ /************************************************************************/ int FLTHasSpatialFilter(FilterEncodingNode *psNode) { int bResult = MS_FALSE; if (!psNode) return MS_FALSE; if (psNode->eType == FILTER_NODE_TYPE_LOGICAL) { if (psNode->psLeftNode) bResult = FLTHasSpatialFilter(psNode->psLeftNode); if (bResult) return MS_TRUE; if (psNode->psRightNode) bResult = FLTHasSpatialFilter(psNode->psRightNode); if (bResult) return MS_TRUE; } else if (FLTIsBBoxFilter(psNode) || FLTIsPointFilter(psNode) || FLTIsLineFilter(psNode) || FLTIsPolygonFilter(psNode)) return MS_TRUE; return MS_FALSE; } /************************************************************************/ /* FLTCreateFeatureIdFilterEncoding */ /* */ /* Utility function to create a filter node of FeatureId type. */ /************************************************************************/ FilterEncodingNode *FLTCreateFeatureIdFilterEncoding(const char *pszString) { FilterEncodingNode *psFilterNode = NULL; if (pszString) { psFilterNode = FLTCreateFilterEncodingNode(); psFilterNode->eType = FILTER_NODE_TYPE_FEATUREID; psFilterNode->pszValue = msStrdup(pszString); return psFilterNode; } return NULL; } /************************************************************************/ /* FLTParseGMLBox */ /* */ /* Parse gml box. Used for FE 1.0 */ /************************************************************************/ int FLTParseGMLBox(CPLXMLNode *psBox, rectObj *psBbox, char **ppszSRS) { int bCoordinatesValid = 0; CPLXMLNode *psCoordinates = NULL; CPLXMLNode *psCoord1 = NULL, *psCoord2 = NULL; char **papszCoords=NULL, **papszMin=NULL, **papszMax = NULL; int nCoords = 0, nCoordsMin = 0, nCoordsMax = 0; const char *pszTmpCoord = NULL; const char *pszSRS = NULL; const char *pszTS = NULL; const char *pszCS = NULL; double minx = 0.0, miny = 0.0, maxx = 0.0, maxy = 0.0; if (psBox) { pszSRS = CPLGetXMLValue(psBox, "srsName", NULL); if (ppszSRS && pszSRS) *ppszSRS = msStrdup(pszSRS); psCoordinates = CPLGetXMLNode(psBox, "coordinates"); pszTS = CPLGetXMLValue(psCoordinates, "ts", NULL); if( pszTS == NULL ) pszTS = " "; pszCS = CPLGetXMLValue(psCoordinates, "cs", NULL); if( pszCS == NULL ) pszCS = ","; pszTmpCoord = CPLGetXMLValue(psCoordinates, NULL, NULL); if (pszTmpCoord) { papszCoords = msStringSplit(pszTmpCoord, pszTS[0], &nCoords); if (papszCoords && nCoords == 2) { papszMin = msStringSplit(papszCoords[0], pszCS[0], &nCoordsMin); if (papszMin && nCoordsMin == 2) { papszMax = msStringSplit(papszCoords[1], pszCS[0], &nCoordsMax); } if (papszMax && nCoordsMax == 2) { bCoordinatesValid =1; minx = atof(papszMin[0]); miny = atof(papszMin[1]); maxx = atof(papszMax[0]); maxy = atof(papszMax[1]); } msFreeCharArray(papszMin, nCoordsMin); msFreeCharArray(papszMax, nCoordsMax); } msFreeCharArray(papszCoords, nCoords); } else { psCoord1 = CPLGetXMLNode(psBox, "coord"); psCoord2 = FLTGetNextSibblingNode(psCoord1); if (psCoord1 && psCoord2 && strcmp(psCoord2->pszValue, "coord") == 0) { const char* pszX = CPLGetXMLValue(psCoord1, "X", NULL); const char* pszY = CPLGetXMLValue(psCoord1, "Y", NULL); if (pszX && pszY) { minx = atof(pszX); miny = atof(pszY); pszX = CPLGetXMLValue(psCoord2, "X", NULL); pszY = CPLGetXMLValue(psCoord2, "Y", NULL); if (pszX && pszY) { maxx = atof(pszX); maxy = atof(pszY); bCoordinatesValid = 1; } } } } } if (bCoordinatesValid) { psBbox->minx = minx; psBbox->miny = miny; psBbox->maxx = maxx; psBbox->maxy = maxy; } return bCoordinatesValid; } /************************************************************************/ /* FLTParseGMLEnvelope */ /* */ /* Utility function to parse a gml:Envelope (used for SOS and FE1.1)*/ /************************************************************************/ int FLTParseGMLEnvelope(CPLXMLNode *psRoot, rectObj *psBbox, char **ppszSRS) { CPLXMLNode *psUpperCorner=NULL, *psLowerCorner=NULL; const char *pszLowerCorner=NULL, *pszUpperCorner=NULL; int bValid = 0; char **tokens; int n; if (psRoot && psBbox && psRoot->eType == CXT_Element && EQUAL(psRoot->pszValue,"Envelope")) { /*Get the srs if available*/ if (ppszSRS) { const char* pszSRS = CPLGetXMLValue(psRoot, "srsName", NULL); if( pszSRS != NULL ) *ppszSRS = msStrdup(pszSRS); } psLowerCorner = CPLSearchXMLNode(psRoot, "lowerCorner"); psUpperCorner = CPLSearchXMLNode(psRoot, "upperCorner"); if (psLowerCorner && psUpperCorner) { pszLowerCorner = CPLGetXMLValue(psLowerCorner, NULL, NULL); pszUpperCorner = CPLGetXMLValue(psUpperCorner, NULL, NULL); if (pszLowerCorner && pszUpperCorner) { tokens = msStringSplit(pszLowerCorner, ' ', &n); if (tokens && n >= 2) { psBbox->minx = atof(tokens[0]); psBbox->miny = atof(tokens[1]); msFreeCharArray(tokens, n); tokens = msStringSplit(pszUpperCorner, ' ', &n); if (tokens && n >= 2) { psBbox->maxx = atof(tokens[0]); psBbox->maxy = atof(tokens[1]); bValid = 1; } } msFreeCharArray(tokens, n); } } } return bValid; } /************************************************************************/ /* FLTNeedSRSSwapping */ /************************************************************************/ static int FLTNeedSRSSwapping( const char* pszSRS ) { int bNeedSwapping = MS_FALSE; projectionObj sProjTmp; msInitProjection(&sProjTmp); if (msLoadProjectionStringEPSG(&sProjTmp, pszSRS) == 0) { bNeedSwapping = msIsAxisInvertedProj(&sProjTmp); } msFreeProjection(&sProjTmp); return bNeedSwapping; } /************************************************************************/ /* FLTDoAxisSwappingIfNecessary */ /* */ /* Explore all geometries and BBOX to do axis swapping when the */ /* SRS requires it. If no explicit SRS is attached to the geometry */ /* the bDefaultSRSNeedsAxisSwapping is taken into account. The */ /* caller will have to determine its value from a more general */ /* context. */ /************************************************************************/ void FLTDoAxisSwappingIfNecessary(FilterEncodingNode *psFilterNode, int bDefaultSRSNeedsAxisSwapping) { if( psFilterNode == NULL ) return; if( psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL && psFilterNode->psRightNode->eType == FILTER_NODE_TYPE_BBOX ) { rectObj* rect = (rectObj *)psFilterNode->psRightNode->pOther; const char* pszSRS = psFilterNode->pszSRS; if( (pszSRS != NULL && FLTNeedSRSSwapping(pszSRS)) || (pszSRS == NULL && bDefaultSRSNeedsAxisSwapping) ) { double tmp; tmp = rect->minx; rect->minx = rect->miny; rect->miny = tmp; tmp = rect->maxx; rect->maxx = rect->maxy; rect->maxy = tmp; } } else if( psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL && FLTIsGeometryFilterNodeType(psFilterNode->psRightNode->eType) ) { shapeObj* shape = (shapeObj *)(psFilterNode->psRightNode->pOther); const char* pszSRS = psFilterNode->pszSRS; if( (pszSRS != NULL && FLTNeedSRSSwapping(pszSRS)) || (pszSRS == NULL && bDefaultSRSNeedsAxisSwapping) ) { msAxisSwapShape(shape); } } else { FLTDoAxisSwappingIfNecessary(psFilterNode->psLeftNode, bDefaultSRSNeedsAxisSwapping); FLTDoAxisSwappingIfNecessary(psFilterNode->psRightNode, bDefaultSRSNeedsAxisSwapping); } } static void FLTReplacePropertyName(FilterEncodingNode *psFilterNode, const char *pszOldName, const char *pszNewName) { if (psFilterNode && pszOldName && pszNewName) { if (psFilterNode->eType == FILTER_NODE_TYPE_PROPERTYNAME) { if (psFilterNode->pszValue && strcasecmp(psFilterNode->pszValue, pszOldName) == 0) { msFree(psFilterNode->pszValue); psFilterNode->pszValue = msStrdup(pszNewName); } } if (psFilterNode->psLeftNode) FLTReplacePropertyName(psFilterNode->psLeftNode, pszOldName, pszNewName); if (psFilterNode->psRightNode) FLTReplacePropertyName(psFilterNode->psRightNode, pszOldName, pszNewName); } } static int FLTIsGMLDefaultProperty(const char* pszName) { return (strcmp(pszName, "gml:name") == 0 || strcmp(pszName, "gml:description") == 0 || strcmp(pszName, "gml:descriptionReference") == 0 || strcmp(pszName, "gml:identifier") == 0 || strcmp(pszName, "gml:boundedBy") == 0 || strcmp(pszName, "@gml:id") == 0); } static void FLTStripNameSpacesFromPropertyName(FilterEncodingNode *psFilterNode) { char **tokens=NULL; int n=0; if (psFilterNode) { if (psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON && psFilterNode->psLeftNode != NULL && psFilterNode->psLeftNode->eType == FILTER_NODE_TYPE_PROPERTYNAME && FLTIsGMLDefaultProperty(psFilterNode->psLeftNode->pszValue) ) { return; } if (psFilterNode->eType == FILTER_NODE_TYPE_PROPERTYNAME) { if (psFilterNode->pszValue && strstr(psFilterNode->pszValue, ":")) { tokens = msStringSplit(psFilterNode->pszValue, ':', &n); if (tokens && n==2) { msFree(psFilterNode->pszValue); psFilterNode->pszValue = msStrdup(tokens[1]); } msFreeCharArray(tokens, n); } } if (psFilterNode->psLeftNode) FLTStripNameSpacesFromPropertyName(psFilterNode->psLeftNode); if (psFilterNode->psRightNode) FLTStripNameSpacesFromPropertyName(psFilterNode->psRightNode); } } static void FLTRemoveGroupName(FilterEncodingNode *psFilterNode, gmlGroupListObj* groupList) { int i; if (psFilterNode) { if (psFilterNode->eType == FILTER_NODE_TYPE_PROPERTYNAME) { if( psFilterNode->pszValue != NULL ) { const char* pszPropertyName = psFilterNode->pszValue; const char* pszSlash = strchr(pszPropertyName, '/'); if( pszSlash != NULL ) { const char* pszColon = strchr(pszPropertyName, ':'); if( pszColon != NULL && pszColon < pszSlash ) pszPropertyName = pszColon + 1; for(i=0;inumgroups;i++) { const char* pszGroupName = groupList->groups[i].name; size_t nGroupNameLen = strlen(pszGroupName); if(strncasecmp(pszPropertyName, pszGroupName, nGroupNameLen) == 0 && pszPropertyName[nGroupNameLen] == '/') { char* pszTmp; pszPropertyName = pszPropertyName + nGroupNameLen + 1; pszColon = strchr(pszPropertyName, ':'); if( pszColon != NULL ) pszPropertyName = pszColon + 1; pszTmp = msStrdup(pszPropertyName); msFree(psFilterNode->pszValue); psFilterNode->pszValue = pszTmp; break; } } } } } if (psFilterNode->psLeftNode) FLTRemoveGroupName(psFilterNode->psLeftNode, groupList); if (psFilterNode->psRightNode) FLTRemoveGroupName(psFilterNode->psRightNode, groupList); } } /************************************************************************/ /* FLTPreParseFilterForAliasAndGroup */ /* */ /* Utility function to replace aliased' and grouped attributes */ /* with their internal name. */ /************************************************************************/ void FLTPreParseFilterForAliasAndGroup(FilterEncodingNode *psFilterNode, mapObj *map, int i, const char *namespaces) { layerObj *lp=NULL; char szTmp[256]; const char *pszFullName = NULL; int layerWasOpened = MS_FALSE; #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) if (psFilterNode && map && i>=0 && inumlayers) { /*strip name spaces before hand*/ FLTStripNameSpacesFromPropertyName(psFilterNode); lp = GET_LAYER(map, i); layerWasOpened = msLayerIsOpen(lp); if (msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) { /* Remove group names from property names if using groupname/itemname syntax */ gmlGroupListObj* groupList = msGMLGetGroups(lp, namespaces); if( groupList && groupList->numgroups > 0 ) FLTRemoveGroupName(psFilterNode, groupList); msGMLFreeGroups(groupList); for(i=0; inumitems; i++) { if (!lp->items[i] || strlen(lp->items[i]) <= 0) continue; snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[i]); pszFullName = msOWSLookupMetadata(&(lp->metadata), namespaces, szTmp); if (pszFullName) { FLTReplacePropertyName(psFilterNode, pszFullName, lp->items[i]); } } if (!layerWasOpened) /* do not close the layer if it has been opened somewhere else (paging?) */ msLayerClose(lp); } } #else msSetError(MS_MISCERR, "OWS support is not available.", "FLTPreParseFilterForAlias()"); #endif } /************************************************************************/ /* FLTCheckFeatureIdFilters */ /* */ /* Check that FeatureId filters match features in the active */ /* layer. */ /************************************************************************/ int FLTCheckFeatureIdFilters(FilterEncodingNode *psFilterNode, mapObj *map, int i) { int status = MS_SUCCESS; if (psFilterNode->eType == FILTER_NODE_TYPE_FEATUREID) { char** tokens; int nTokens = 0; layerObj* lp; int j; lp = GET_LAYER(map, i); tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens); for (j=0; jname) || strncasecmp(pszId, lp->name, strlen(lp->name)) != 0 ) { msSetError(MS_MISCERR, "Feature id %s not consistent with feature type name %s.", "FLTPreParseFilterForAlias()", pszId, lp->name); status = MS_FAILURE; break; } } } msFreeCharArray(tokens, nTokens); } if (psFilterNode->psLeftNode) { status = FLTCheckFeatureIdFilters(psFilterNode->psLeftNode, map, i); if( status == MS_SUCCESS ) { if (psFilterNode->psRightNode) status = FLTCheckFeatureIdFilters(psFilterNode->psRightNode, map, i); } } return status; } /************************************************************************/ /* FLTCheckInvalidOperand */ /* */ /* Check that the operand of a comparison operator is valid */ /* Currently only detects use of boundedBy in a binary comparison */ /************************************************************************/ int FLTCheckInvalidOperand(FilterEncodingNode *psFilterNode) { int status = MS_SUCCESS; if (psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON && psFilterNode->psLeftNode != NULL && psFilterNode->psLeftNode->eType == FILTER_NODE_TYPE_PROPERTYNAME) { if( strcmp(psFilterNode->psLeftNode->pszValue, "gml:boundedBy") == 0 && strcmp(psFilterNode->pszValue, "PropertyIsNull") != 0 && strcmp(psFilterNode->pszValue, "PropertyIsNil") != 0 ) { msSetError(MS_MISCERR, "Operand '%s' is invalid in comparison.", "FLTCheckInvalidOperand()", psFilterNode->psLeftNode->pszValue); return MS_FAILURE; } } if (psFilterNode->psLeftNode) { status = FLTCheckInvalidOperand(psFilterNode->psLeftNode); if( status == MS_SUCCESS ) { if (psFilterNode->psRightNode) status = FLTCheckInvalidOperand(psFilterNode->psRightNode); } } return status; } /************************************************************************/ /* FLTProcessPropertyIsNull */ /* */ /* HACK for PropertyIsNull processing. PostGIS & Spatialite only */ /* for now. */ /************************************************************************/ int FLTProcessPropertyIsNull(FilterEncodingNode *psFilterNode, mapObj *map, int i) { int status = MS_SUCCESS; if (psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON && psFilterNode->psLeftNode != NULL && psFilterNode->psLeftNode->eType == FILTER_NODE_TYPE_PROPERTYNAME && strcmp(psFilterNode->pszValue, "PropertyIsNull") == 0 && !FLTIsGMLDefaultProperty(psFilterNode->psLeftNode->pszValue) ) { layerObj* lp; int layerWasOpened; lp = GET_LAYER(map, i); layerWasOpened = msLayerIsOpen(lp); /* Horrible HACK to compensate for the lack of null testing in MapServer */ if( (lp->connectiontype == MS_POSTGIS || (lp->connectiontype == MS_OGR && msOGRIsSpatialite(lp))) && strcmp(psFilterNode->pszValue, "PropertyIsNull") == 0 ) { msFree(psFilterNode->pszValue); psFilterNode->pszValue = msStrdup("PropertyIsEqualTo"); psFilterNode->psRightNode = FLTCreateBinaryCompFilterEncodingNode(); psFilterNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; psFilterNode->psRightNode->pszValue = msStrdup("_MAPSERVER_NULL_"); } if (!layerWasOpened) /* do not close the layer if it has been opened somewhere else (paging?) */ msLayerClose(lp); } if (psFilterNode->psLeftNode) { status = FLTProcessPropertyIsNull(psFilterNode->psLeftNode, map, i); if( status == MS_SUCCESS ) { if (psFilterNode->psRightNode) status = FLTProcessPropertyIsNull(psFilterNode->psRightNode, map, i); } } return status; } /************************************************************************/ /* FLTCheckInvalidProperty */ /* */ /* Check that property names are known */ /************************************************************************/ int FLTCheckInvalidProperty(FilterEncodingNode *psFilterNode, mapObj *map, int i) { int status = MS_SUCCESS; if (psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON && psFilterNode->psLeftNode != NULL && psFilterNode->psLeftNode->eType == FILTER_NODE_TYPE_PROPERTYNAME) { layerObj* lp; int layerWasOpened; int bFound = MS_FALSE; if ((strcmp(psFilterNode->pszValue, "PropertyIsNull") == 0 || strcmp(psFilterNode->pszValue, "PropertyIsNil") == 0) && FLTIsGMLDefaultProperty(psFilterNode->psLeftNode->pszValue) ) { return MS_SUCCESS; } lp = GET_LAYER(map, i); layerWasOpened = msLayerIsOpen(lp); if ((layerWasOpened || msLayerOpen(lp) == MS_SUCCESS) && msLayerGetItems(lp) == MS_SUCCESS) { int i; gmlItemListObj* items = msGMLGetItems(lp, "G"); for(i=0; inumitems; i++) { if (!items->items[i].name || strlen(items->items[i].name) <= 0 || !items->items[i].visible) continue; if (strcasecmp(items->items[i].name, psFilterNode->psLeftNode->pszValue) == 0) { bFound = MS_TRUE; break; } } msGMLFreeItems(items); } if (!layerWasOpened) /* do not close the layer if it has been opened somewhere else (paging?) */ msLayerClose(lp); if( !bFound ) { msSetError(MS_MISCERR, "Property '%s' is unknown.", "FLTCheckInvalidProperty()", psFilterNode->psLeftNode->pszValue); return MS_FAILURE; } } if (psFilterNode->psLeftNode) { status = FLTCheckInvalidProperty(psFilterNode->psLeftNode, map, i); if( status == MS_SUCCESS ) { if (psFilterNode->psRightNode) status = FLTCheckInvalidProperty(psFilterNode->psRightNode, map, i); } } return status; } /************************************************************************/ /* FLTSimplify */ /* */ /* Simplify the expression by removing parts that evaluate to */ /* constants. */ /* The passed psFilterNode is potentially consumed by the function */ /* and replaced by the returned value. */ /* If the function returns NULL, *pnEvaluation = MS_FALSE means */ /* that the filter evaluates to FALSE, or MS_TRUE that it */ /* evaluates to TRUE */ /************************************************************************/ FilterEncodingNode* FLTSimplify(FilterEncodingNode *psFilterNode, int* pnEvaluation) { *pnEvaluation = -1; /* There are no nullable or nillable property in WFS currently */ /* except gml:name or gml:description that are null */ if( psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON && (strcmp(psFilterNode->pszValue, "PropertyIsNull") == 0 || strcmp(psFilterNode->pszValue, "PropertyIsNil") == 0 ) && psFilterNode->psLeftNode != NULL && psFilterNode->psLeftNode->eType == FILTER_NODE_TYPE_PROPERTYNAME ) { if( strcmp(psFilterNode->pszValue, "PropertyIsNull") == 0 && FLTIsGMLDefaultProperty(psFilterNode->psLeftNode->pszValue) && strcmp(psFilterNode->psLeftNode->pszValue, "@gml:id") != 0 && strcmp(psFilterNode->psLeftNode->pszValue, "gml:boundedBy") != 0) *pnEvaluation = MS_TRUE; else *pnEvaluation = MS_FALSE; FLTFreeFilterEncodingNode(psFilterNode); return NULL; } if( psFilterNode->eType == FILTER_NODE_TYPE_LOGICAL && strcasecmp(psFilterNode->pszValue, "NOT") == 0 && psFilterNode->psLeftNode != NULL ) { int nEvaluation; psFilterNode->psLeftNode = FLTSimplify(psFilterNode->psLeftNode, &nEvaluation); if( psFilterNode->psLeftNode == NULL ) { *pnEvaluation = 1 - nEvaluation; FLTFreeFilterEncodingNode(psFilterNode); return NULL; } } if( psFilterNode->eType == FILTER_NODE_TYPE_LOGICAL && (strcasecmp(psFilterNode->pszValue, "AND") == 0 || strcasecmp(psFilterNode->pszValue, "OR") == 0) && psFilterNode->psLeftNode != NULL && psFilterNode->psRightNode != NULL ) { FilterEncodingNode* psOtherNode; int nEvaluation; int nExpectedValForFastExit; psFilterNode->psLeftNode = FLTSimplify(psFilterNode->psLeftNode, &nEvaluation); if( strcasecmp(psFilterNode->pszValue, "AND") == 0 ) nExpectedValForFastExit = MS_FALSE; else nExpectedValForFastExit = MS_TRUE; if( psFilterNode->psLeftNode == NULL ) { if( nEvaluation == nExpectedValForFastExit ) { *pnEvaluation = nEvaluation; FLTFreeFilterEncodingNode(psFilterNode); return NULL; } psOtherNode = psFilterNode->psRightNode; psFilterNode->psRightNode = NULL; FLTFreeFilterEncodingNode(psFilterNode); return FLTSimplify(psOtherNode, pnEvaluation); } psFilterNode->psRightNode = FLTSimplify(psFilterNode->psRightNode, &nEvaluation); if( psFilterNode->psRightNode == NULL ) { if( nEvaluation == nExpectedValForFastExit ) { *pnEvaluation = nEvaluation; FLTFreeFilterEncodingNode(psFilterNode); return NULL; } psOtherNode = psFilterNode->psLeftNode; psFilterNode->psLeftNode = NULL; FLTFreeFilterEncodingNode(psFilterNode); return FLTSimplify(psOtherNode, pnEvaluation); } } return psFilterNode; } #ifdef USE_LIBXML2 xmlNodePtr FLTGetCapabilities(xmlNsPtr psNsParent, xmlNsPtr psNsOgc, int bTemporal) { xmlNodePtr psRootNode = NULL, psNode = NULL, psSubNode = NULL, psSubSubNode = NULL; psRootNode = xmlNewNode(psNsParent, BAD_CAST "Filter_Capabilities"); psNode = xmlNewChild(psRootNode, psNsOgc, BAD_CAST "Spatial_Capabilities", NULL); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "GeometryOperands", NULL); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "GeometryOperand", BAD_CAST "gml:Point"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "GeometryOperand", BAD_CAST "gml:LineString"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "GeometryOperand", BAD_CAST "gml:Polygon"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "GeometryOperand", BAD_CAST "gml:Envelope"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "SpatialOperators", NULL); #ifdef USE_GEOS psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Equals"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Disjoint"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Touches"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Within"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Overlaps"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Crosses"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Intersects"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Contains"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "DWithin"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "Beyond"); #endif psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "SpatialOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "BBOX"); if (bTemporal) { psNode = xmlNewChild(psRootNode, psNsOgc, BAD_CAST "Temporal_Capabilities", NULL); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "TemporalOperands", NULL); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "TemporalOperand", BAD_CAST "gml:TimePeriod"); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "TemporalOperand", BAD_CAST "gml:TimeInstant"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "TemporalOperators", NULL); psSubSubNode = xmlNewChild(psSubNode, psNsOgc, BAD_CAST "TemporalOperator", NULL); xmlNewProp(psSubSubNode, BAD_CAST "name", BAD_CAST "TM_Equals"); } psNode = xmlNewChild(psRootNode, psNsOgc, BAD_CAST "Scalar_Capabilities", NULL); xmlNewChild(psNode, psNsOgc, BAD_CAST "LogicalOperators", NULL); psNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperators", NULL); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "LessThan"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "GreaterThan"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "LessThanEqualTo"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "GreaterThanEqualTo"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "EqualTo"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "NotEqualTo"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "Like"); psSubNode = xmlNewChild(psNode, psNsOgc, BAD_CAST "ComparisonOperator", BAD_CAST "Between"); psNode = xmlNewChild(psRootNode, psNsOgc, BAD_CAST "Id_Capabilities", NULL); xmlNewChild(psNode, psNsOgc, BAD_CAST "EID", NULL); xmlNewChild(psNode, psNsOgc, BAD_CAST "FID", NULL); return psRootNode; } #endif #endif mapserver-7.4.3/mapogcfilter.h000066400000000000000000000161061357574274700164070ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Filter Encoding implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #ifndef MAPOGCFILTER_H #define MAPOGCFILTER_H #include "mapserver.h" /*dont need ogr for these functikons*/ MS_DLL_EXPORT int FLTIsNumeric(const char *pszValue); MS_DLL_EXPORT int FLTApplyExpressionToLayer(layerObj *lp, const char *pszExpression); MS_DLL_EXPORT char *FLTGetExpressionForValuesRanges(layerObj *lp, const char *item, const char *value, int forcecharcter); #ifdef USE_OGR /* There is a dependency to OGR for the MiniXML parser */ #include "cpl_minixml.h" #ifdef USE_LIBXML2 #include #include #endif typedef struct { char *pszWildCard; char *pszSingleChar; char *pszEscapeChar; int bCaseInsensitive; } FEPropertyIsLike; /* -------------------------------------------------------------------- */ /* prototypes. */ /* -------------------------------------------------------------------- */ MS_DLL_EXPORT FilterEncodingNode *FLTParseFilterEncoding(const char *szXMLString); MS_DLL_EXPORT FilterEncodingNode *FLTCreateFilterEncodingNode(void); MS_DLL_EXPORT char** FLTSplitFilters(const char* pszStr, int* pnTokens); MS_DLL_EXPORT int FLTApplyFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT int FLTLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT void FLTFreeFilterEncodingNode(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTValidFilterNode(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTValidForBBoxFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTNumberOfFilterType(FilterEncodingNode *psFilterNode, const char *szType); MS_DLL_EXPORT int FLTIsBBoxFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTIsPointFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTIsLineFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTIsPolygonFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTValidForPropertyIsLikeFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT int FLTIsOnlyPropertyIsLike(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT void FLTInsertElementInNode(FilterEncodingNode *psFilterNode, CPLXMLNode *psXMLNode); MS_DLL_EXPORT int FLTIsLogicalFilterType(const char *pszValue); MS_DLL_EXPORT int FLTIsBinaryComparisonFilterType(const char *pszValue); MS_DLL_EXPORT int FLTIsComparisonFilterType(const char *pszValue); MS_DLL_EXPORT int FLTIsFeatureIdFilterType(const char *pszValue); MS_DLL_EXPORT int FLTIsSpatialFilterType(const char *pszValue); MS_DLL_EXPORT int FLTIsTemporalFilterType(const char *pszValue); MS_DLL_EXPORT int FLTIsSupportedFilterType(CPLXMLNode *psXMLNode); MS_DLL_EXPORT const char *FLTGetBBOX(FilterEncodingNode *psFilterNode, rectObj *psRect); const char* FLTGetDuring(FilterEncodingNode *psFilterNode, const char** ppszTimeField); MS_DLL_EXPORT shapeObj *FLTGetShape(FilterEncodingNode *psFilterNode, double *pdfDistance, int *pnUnit); MS_DLL_EXPORT int FLTHasSpatialFilter(FilterEncodingNode *psFilterNode); /*SQL expressions related functions.*/ MS_DLL_EXPORT int FLTApplySimpleSQLFilter(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT char *FLTGetSQLExpression(FilterEncodingNode *psFilterNode,layerObj *lp); MS_DLL_EXPORT char *FLTGetBinaryComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetIsBetweenComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetIsLikeComparisonSQLExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetLogicalComparisonSQLExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT int FLTIsSimpleFilter(FilterEncodingNode *psFilterNode); MS_DLL_EXPORT FilterEncodingNode *FLTCreateFeatureIdFilterEncoding(const char *pszString); MS_DLL_EXPORT int FLTParseGMLEnvelope(CPLXMLNode *psRoot, rectObj *psBbox, char **ppszSRS); MS_DLL_EXPORT int FLTParseGMLBox(CPLXMLNode *psBox, rectObj *psBbox, char **ppszSRS); /*common-expressions*/ MS_DLL_EXPORT char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT char *FLTGetCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp); char* FLTGetTimeExpression(FilterEncodingNode *psFilterNode, layerObj *lp); MS_DLL_EXPORT int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, const char *pszExpression); #ifdef USE_LIBXML2 MS_DLL_EXPORT xmlNodePtr FLTGetCapabilities(xmlNsPtr psNsParent, xmlNsPtr psNsOgc, int bTemporal); #endif void FLTDoAxisSwappingIfNecessary(FilterEncodingNode *psFilterNode, int bDefaultSRSNeedsAxisSwapping); void FLTPreParseFilterForAliasAndGroup(FilterEncodingNode *psFilterNode, mapObj *map, int i, const char *namespaces); int FLTCheckFeatureIdFilters(FilterEncodingNode *psFilterNode, mapObj *map, int i); int FLTCheckInvalidOperand(FilterEncodingNode *psFilterNode); int FLTCheckInvalidProperty(FilterEncodingNode *psFilterNode, mapObj *map, int i); FilterEncodingNode* FLTSimplify(FilterEncodingNode *psFilterNode, int* pnEvaluation); int FLTApplyFilterToLayerCommonExpressionWithRect(mapObj *map, int iLayerIndex, const char *pszExpression, rectObj rect); int FLTProcessPropertyIsNull(FilterEncodingNode *psFilterNode, mapObj *map, int i); #endif #endif mapserver-7.4.3/mapogcfiltercommon.c000066400000000000000000000663451357574274700176250ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Filter Encoding implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #ifdef USE_OGR #include "cpl_minixml.h" #endif #include "mapogcfilter.h" #include "mapserver.h" #include "mapows.h" #include "mapowscommon.h" #ifdef USE_OGR char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode) { const size_t bufferSize = 1024; char szBuffer[1024]; char szTmp[512]; char *pszValue = NULL; const char *pszWild = NULL; const char *pszSingle = NULL; const char *pszEscape = NULL; int bCaseInsensitive = 0; FEPropertyIsLike* propIsLike; int nLength=0, i=0, iTmp=0; /* From http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04 */ /* also add double quote because we are within a string */ const char* pszRegexSpecialCharsAndDoubleQuote = "\\^${[().*+?|\""; if (!psFilterNode || !psFilterNode->pOther || !psFilterNode->psLeftNode || !psFilterNode->psRightNode || !psFilterNode->psRightNode->pszValue) return NULL; propIsLike = (FEPropertyIsLike *)psFilterNode->pOther; pszWild = propIsLike->pszWildCard; pszSingle = propIsLike->pszSingleChar; pszEscape = propIsLike->pszEscapeChar; bCaseInsensitive = propIsLike->bCaseInsensitive; if (!pszWild || strlen(pszWild) == 0 || !pszSingle || strlen(pszSingle) == 0 || !pszEscape || strlen(pszEscape) == 0) return NULL; /* -------------------------------------------------------------------- */ /* Use operand with regular expressions. */ /* -------------------------------------------------------------------- */ szBuffer[0] = '\0'; sprintf(szTmp, "%s", "(\"["); szTmp[4] = '\0'; strlcat(szBuffer, szTmp, bufferSize); /* attribute */ strlcat(szBuffer, psFilterNode->psLeftNode->pszValue, bufferSize); szBuffer[strlen(szBuffer)] = '\0'; /* #3521 */ if (bCaseInsensitive == 1) sprintf(szTmp, "%s", "]\" ~* \""); else sprintf(szTmp, "%s", "]\" ~ \""); szTmp[7] = '\0'; strlcat(szBuffer, szTmp, bufferSize); szBuffer[strlen(szBuffer)] = '\0'; pszValue = psFilterNode->psRightNode->pszValue; nLength = strlen(pszValue); /* The 4 factor is in case of \. See below */ if( 1 + 4 * nLength + 1 + 1 + 1 >= sizeof(szTmp) ) return NULL; iTmp =0; if (nLength > 0) { szTmp[iTmp]= '^'; iTmp++; } for (i=0; i 0) { szTmp[iTmp]= '$'; iTmp++; } szTmp[iTmp] = '"'; szTmp[++iTmp] = '\0'; #if 0 msDebug("like: %s\n", pszValue); msDebug("regexp (with \\ escaping for MapServer use): %s\n", szTmp); #endif strlcat(szBuffer, szTmp, bufferSize); strlcat(szBuffer, ")", bufferSize); return msStrdup(szBuffer); } char *FLTGetIsBetweenComparisonCommonExpresssion(FilterEncodingNode *psFilterNode, layerObj *lp) { const size_t bufferSize = 1024; char szBuffer[1024]; char **aszBounds = NULL; int nBounds = 0; int bString=0; int bDateTime = 0; char *pszExpression=NULL, *pszTmpEscaped; if (!psFilterNode || !(strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0)) return NULL; if (psFilterNode->psLeftNode == NULL || psFilterNode->psRightNode == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* Get the bounds value which are stored like boundmin;boundmax */ /* -------------------------------------------------------------------- */ aszBounds = msStringSplit(psFilterNode->psRightNode->pszValue, ';', &nBounds); if (nBounds != 2) { msFreeCharArray(aszBounds, nBounds); return NULL; } /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; if (aszBounds[0]) { const char* pszType; snprintf(szBuffer, bufferSize, "%s_type", psFilterNode->psLeftNode->pszValue); pszType = msOWSLookupMetadata(&(lp->metadata), "OFG", szBuffer); if (pszType != NULL && (strcasecmp(pszType, "Character") == 0)) bString = 1; else if (pszType != NULL && (strcasecmp(pszType, "Date") == 0)) bDateTime = 1; else if (FLTIsNumeric(aszBounds[0]) == MS_FALSE) bString = 1; } if (!bString && !bDateTime) { if (aszBounds[1]) { if (FLTIsNumeric(aszBounds[1]) == MS_FALSE) bString = 1; } } /* -------------------------------------------------------------------- */ /* build expresssion. */ /* -------------------------------------------------------------------- */ /* attribute */ if (bString) sprintf(szBuffer, "%s", "(\"["); else sprintf(szBuffer, "%s", "(["); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, psFilterNode->psLeftNode->pszValue); if (bString) sprintf(szBuffer, "%s", "]\" "); else sprintf(szBuffer, "%s", "] "); pszExpression = msStringConcatenate(pszExpression, szBuffer); sprintf(szBuffer, "%s", " >= "); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) { pszExpression = msStringConcatenate(pszExpression, "\""); } else if (bDateTime) { pszExpression = msStringConcatenate(pszExpression, "`"); } pszTmpEscaped = msStringEscape(aszBounds[0]); snprintf(szBuffer, bufferSize, "%s", pszTmpEscaped); if(pszTmpEscaped != aszBounds[0] ) msFree(pszTmpEscaped); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) { pszExpression = msStringConcatenate(pszExpression, "\""); } else if (bDateTime) { pszExpression = msStringConcatenate(pszExpression, "`"); } sprintf(szBuffer, "%s", " AND "); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) sprintf(szBuffer, "%s", " \"["); else sprintf(szBuffer, "%s", " ["); pszExpression = msStringConcatenate(pszExpression, szBuffer); /* attribute */ pszExpression = msStringConcatenate(pszExpression, psFilterNode->psLeftNode->pszValue); if (bString) sprintf(szBuffer, "%s", "]\" "); else sprintf(szBuffer, "%s", "] "); pszExpression = msStringConcatenate(pszExpression, szBuffer); sprintf(szBuffer, "%s", " <= "); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) { pszExpression = msStringConcatenate(pszExpression, "\""); } else if (bDateTime) { pszExpression = msStringConcatenate(pszExpression, "`"); } pszTmpEscaped = msStringEscape(aszBounds[1]); snprintf(szBuffer, bufferSize, "%s", pszTmpEscaped); if (pszTmpEscaped != aszBounds[1]) msFree(pszTmpEscaped); pszExpression = msStringConcatenate(pszExpression, szBuffer); if (bString) { pszExpression = msStringConcatenate(pszExpression, "\""); } else if (bDateTime) { pszExpression = msStringConcatenate(pszExpression, "`"); } sprintf(szBuffer, "%s", ")"); pszExpression = msStringConcatenate(pszExpression, szBuffer); msFreeCharArray(aszBounds, nBounds); return pszExpression; } char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char szTmp[1024]; char *pszExpression = NULL, *pszTmpEscaped; int bString; int bDateTime; if (psFilterNode == NULL) return NULL; /* -------------------------------------------------------------------- */ /* check if the value is a numeric value or alphanumeric. If it */ /* is alphanumeric, add quotes around attribute and values. */ /* -------------------------------------------------------------------- */ bString = 0; bDateTime = 0; if (psFilterNode->psRightNode->pszValue) { const char* pszType; snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue); pszType = msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp); if (pszType!= NULL && (strcasecmp(pszType, "Character") == 0)) bString = 1; else if (pszType!= NULL && (strcasecmp(pszType, "Date") == 0)) bDateTime = 1; else if (FLTIsNumeric(psFilterNode->psRightNode->pszValue) == MS_FALSE) bString = 1; } /* specical case to be able to have empty strings in the expression. */ /* propertyislike is always treated as string */ if (psFilterNode->psRightNode->pszValue == NULL || strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) bString = 1; /* attribute */ if (bString) sprintf(szTmp, "%s", "(\"["); else sprintf(szTmp, "%s","(["); pszExpression = msStringConcatenate(pszExpression, szTmp); pszExpression = msStringConcatenate(pszExpression, psFilterNode->psLeftNode->pszValue); if (bString) sprintf(szTmp, "%s","]\" "); else sprintf(szTmp, "%s", "] "); pszExpression = msStringConcatenate(pszExpression, szTmp); if (strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0) { /* case insensitive set ? */ if (psFilterNode->psRightNode->pOther && (*(int *)psFilterNode->psRightNode->pOther) == 1) sprintf(szTmp, "%s", "=*"); else sprintf(szTmp, "%s", "="); } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsNotEqualTo") == 0) sprintf(szTmp, "%s", "!="); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThan") == 0) sprintf(szTmp, "%s", "<"); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThan") == 0) sprintf(szTmp, "%s", ">"); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThanOrEqualTo") == 0) sprintf(szTmp, "%s", "<="); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThanOrEqualTo") == 0) sprintf(szTmp, "%s", ">="); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) sprintf(szTmp, "%s", "~"); pszExpression = msStringConcatenate(pszExpression, szTmp); pszExpression = msStringConcatenate(pszExpression, " "); /* value */ if (bString) { sprintf(szTmp, "%s", "\""); pszExpression = msStringConcatenate(pszExpression, szTmp); } else if (bDateTime) { sprintf(szTmp, "%s", "`"); pszExpression = msStringConcatenate(pszExpression, szTmp); } if (psFilterNode->psRightNode->pszValue) { pszTmpEscaped = msStringEscape(psFilterNode->psRightNode->pszValue); pszExpression = msStringConcatenate(pszExpression, pszTmpEscaped); if(pszTmpEscaped != psFilterNode->psRightNode->pszValue ) msFree(pszTmpEscaped); } if (bString) { sprintf(szTmp, "%s", "\""); pszExpression = msStringConcatenate(pszExpression, szTmp); } else if (bDateTime) { sprintf(szTmp, "%s", "`"); pszExpression = msStringConcatenate(pszExpression, szTmp); } sprintf(szTmp, "%s", ")"); pszExpression = msStringConcatenate(pszExpression, szTmp); return pszExpression; } char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszExpression = NULL; char *pszTmp = NULL; if (!psFilterNode || !FLTIsLogicalFilterType(psFilterNode->pszValue)) return NULL; /* -------------------------------------------------------------------- */ /* OR and AND */ /* -------------------------------------------------------------------- */ if (psFilterNode->psLeftNode && psFilterNode->psRightNode) { pszTmp = FLTGetCommonExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; pszExpression = msStringConcatenate(pszExpression, "("); pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); pszExpression = msStringConcatenate(pszExpression, " "); pszExpression = msStringConcatenate(pszExpression, psFilterNode->pszValue); pszExpression = msStringConcatenate(pszExpression, " "); pszTmp = FLTGetCommonExpression(psFilterNode->psRightNode, lp); if (!pszTmp) { msFree(pszExpression); return NULL; } pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); pszExpression = msStringConcatenate(pszExpression, ")"); } /* -------------------------------------------------------------------- */ /* NOT */ /* -------------------------------------------------------------------- */ else if (psFilterNode->psLeftNode && strcasecmp(psFilterNode->pszValue, "NOT") == 0) { pszTmp = FLTGetCommonExpression(psFilterNode->psLeftNode, lp); if (!pszTmp) return NULL; pszExpression = msStringConcatenate(pszExpression, "(NOT "); pszExpression = msStringConcatenate(pszExpression, pszTmp); msFree(pszTmp); pszExpression = msStringConcatenate(pszExpression, ")"); } return pszExpression; } char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerObj *lp) { char *pszExpression = NULL; shapeObj *psQueryShape = NULL; double dfDistance = -1; int nUnit = -1, nLayerUnit = -1; char *pszWktText = NULL; char szBuffer[256]; char *pszTmp=NULL; projectionObj sProjTmp; rectObj sQueryRect; shapeObj *psTmpShape=NULL; int bBBoxQuery = 0; int bAlreadyReprojected = 0; if (psNode == NULL || lp == NULL) return NULL; if (psNode->eType != FILTER_NODE_TYPE_SPATIAL) return NULL; /* get the shape */ if (FLTIsBBoxFilter(psNode)) { char szPolygon[512]; FLTGetBBOX(psNode, &sQueryRect); snprintf(szPolygon, sizeof(szPolygon), "POLYGON((%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f,%.18f %.18f))", sQueryRect.minx, sQueryRect.miny, sQueryRect.minx, sQueryRect.maxy, sQueryRect.maxx, sQueryRect.maxy, sQueryRect.maxx, sQueryRect.miny, sQueryRect.minx, sQueryRect.miny); psTmpShape = msShapeFromWKT(szPolygon); /* ** This is a horrible hack to deal with world-extent requests and ** reprojection. msProjectRect() detects if reprojection from longlat to ** projected SRS, and in that case it transforms the bbox to -1e-15,-1e-15,1e15,1e15 ** to ensure that all features are returned. ** ** Make wfs_200_cite_filter_bbox_world.xml and wfs_200_cite_postgis_bbox_world.xml pass */ if (fabs(sQueryRect.minx - -180.0) < 1e-5 && fabs(sQueryRect.miny - -90.0) < 1e-5 && fabs(sQueryRect.maxx - 180.0) < 1e-5 && fabs(sQueryRect.maxy - 90.0) < 1e-5) { if (lp->projection.numargs > 0) { if (psNode->pszSRS) msInitProjection(&sProjTmp); if (psNode->pszSRS) { /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) { msProjectRect(&sProjTmp, &lp->projection, &sQueryRect); } } else if (lp->map->projection.numargs > 0) msProjectRect(&lp->map->projection, &lp->projection, &sQueryRect); if (psNode->pszSRS) msFreeProjection(&sProjTmp); } if (sQueryRect.minx <= -1e14) { msFreeShape(psTmpShape); msFree(psTmpShape); psTmpShape = (shapeObj*) msSmallMalloc(sizeof(shapeObj)); msInitShape(psTmpShape); msRectToPolygon(sQueryRect, psTmpShape); bAlreadyReprojected = 1; } } bBBoxQuery = 1; } else { /* other geos type operations */ /* project shape to layer projection. If the proj is not part of the filter query, assume that the cooredinates are in the map projection */ psQueryShape = FLTGetShape(psNode, &dfDistance, &nUnit); if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0 ) && dfDistance > 0) { nLayerUnit = lp->units; if(nLayerUnit == -1) nLayerUnit = GetMapserverUnitUsingProj(&lp->projection); if(nLayerUnit == -1) nLayerUnit = lp->map->units; if(nLayerUnit == -1) nLayerUnit = GetMapserverUnitUsingProj(&lp->map->projection); if (nUnit >= 0 && nUnit != nLayerUnit) dfDistance *= msInchesPerUnit(nUnit,0)/msInchesPerUnit(nLayerUnit,0); /* target is layer units */ } psTmpShape = psQueryShape; } if (psTmpShape) { /* ** target is layer projection */ if (!bAlreadyReprojected && lp->projection.numargs > 0) { if (psNode->pszSRS) msInitProjection(&sProjTmp); if (psNode->pszSRS) { /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */ if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) { msProjectShape(&sProjTmp, &lp->projection, psTmpShape); } } else if (lp->map->projection.numargs > 0) msProjectShape(&lp->map->projection, &lp->projection, psTmpShape); if (psNode->pszSRS) msFreeProjection(&sProjTmp); } /* function name */ if (bBBoxQuery) { sprintf(szBuffer, "%s", "intersects"); } else { if (strncasecmp(psNode->pszValue, "intersect", 9) == 0) sprintf(szBuffer, "%s", "intersects"); else { pszTmp = msStrdup(psNode->pszValue); msStringToLower(pszTmp); sprintf(szBuffer, "%s", pszTmp); msFree(pszTmp); } } pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, "("); /* geometry binding */ sprintf(szBuffer, "%s", "[shape]"); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, ","); /* filter geometry */ pszWktText = msGEOSShapeToWKT(psTmpShape); sprintf(szBuffer, "%s", "fromText('"); pszExpression = msStringConcatenate(pszExpression, szBuffer); pszExpression = msStringConcatenate(pszExpression, pszWktText); sprintf(szBuffer, "%s", "')"); pszExpression = msStringConcatenate(pszExpression, szBuffer); msGEOSFreeWKT(pszWktText); /* (optional) beyond/dwithin distance, always 0.0 since we apply the distance as a buffer earlier */ if ((strcasecmp(psNode->pszValue, "DWithin") == 0 || strcasecmp(psNode->pszValue, "Beyond") == 0)) { // pszExpression = msStringConcatenate(pszExpression, ",0.0"); sprintf(szBuffer, ",%g", dfDistance); pszExpression = msStringConcatenate(pszExpression, szBuffer); } /* terminate the function */ pszExpression = msStringConcatenate(pszExpression, ") = TRUE"); } /* ** Cleanup */ if (bBBoxQuery) { msFreeShape(psTmpShape); msFree(psTmpShape); } return pszExpression; } char *FLTGetFeatureIdCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszExpression = NULL; int nTokens = 0, i=0, bString=0; char **tokens = NULL; const char *pszAttribute=NULL; #if defined(USE_WMS_SVR) || defined(USE_WFS_SVR) || defined(USE_WCS_SVR) || defined(USE_SOS_SVR) if (psFilterNode->pszValue) { pszAttribute = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid"); if (pszAttribute) { tokens = msStringSplit(psFilterNode->pszValue,',', &nTokens); if (tokens && nTokens > 0) { for (i=0; ieType != FILTER_NODE_TYPE_TEMPORAL) return NULL; pszTimeValue = FLTGetDuring(psFilterNode, &pszTimeField); if (pszTimeField && pszTimeValue) { expressionObj old_filter; msInitExpression(&old_filter); msCopyExpression(&old_filter, &lp->filter); /* save existing filter */ msFreeExpression(&lp->filter); if (msLayerSetTimeFilter(lp, pszTimeValue, pszTimeField) == MS_TRUE) { pszExpression = msStrdup(lp->filter.string); } msCopyExpression(&lp->filter, &old_filter); /* restore old filter */ msFreeExpression(&old_filter); } return pszExpression; } char *FLTGetCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp) { char *pszExpression = NULL; if (!psFilterNode) return NULL; if (psFilterNode->eType == FILTER_NODE_TYPE_COMPARISON) { if ( psFilterNode->psLeftNode && psFilterNode->psRightNode) { if (FLTIsBinaryComparisonFilterType(psFilterNode->pszValue)) pszExpression = FLTGetBinaryComparisonCommonExpression(psFilterNode, lp); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0) pszExpression = FLTGetIsLikeComparisonCommonExpression(psFilterNode); else if (strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0) pszExpression = FLTGetIsBetweenComparisonCommonExpresssion(psFilterNode, lp); } } else if (psFilterNode->eType == FILTER_NODE_TYPE_LOGICAL) { pszExpression = FLTGetLogicalComparisonCommonExpression(psFilterNode, lp); } else if (psFilterNode->eType == FILTER_NODE_TYPE_SPATIAL) { pszExpression = FLTGetSpatialComparisonCommonExpression(psFilterNode, lp); } else if (psFilterNode->eType == FILTER_NODE_TYPE_FEATUREID) { pszExpression = FLTGetFeatureIdCommonExpression(psFilterNode, lp); } else if (psFilterNode->eType == FILTER_NODE_TYPE_TEMPORAL) { pszExpression = FLTGetTimeExpression(psFilterNode, lp); } return pszExpression; } int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, const char *pszExpression) { return FLTApplyFilterToLayerCommonExpressionWithRect(map, iLayerIndex, pszExpression, map->extent); } /* rect must be in map->projection */ int FLTApplyFilterToLayerCommonExpressionWithRect(mapObj *map, int iLayerIndex, const char *pszExpression, rectObj rect) { int retval; int save_startindex; int save_maxfeatures; int save_only_cache_result_count; int save_cache_shapes; int save_max_cached_shape_count; int save_max_cached_shape_ram_amount; save_startindex = map->query.startindex; save_maxfeatures = map->query.maxfeatures; save_only_cache_result_count = map->query.only_cache_result_count; save_cache_shapes = map->query.cache_shapes; save_max_cached_shape_count = map->query.max_cached_shape_count; save_max_cached_shape_ram_amount = map->query.max_cached_shape_ram_amount; msInitQuery(&(map->query)); map->query.startindex = save_startindex; map->query.maxfeatures = save_maxfeatures; map->query.only_cache_result_count = save_only_cache_result_count; map->query.cache_shapes = save_cache_shapes; map->query.max_cached_shape_count = save_max_cached_shape_count; map->query.max_cached_shape_ram_amount = save_max_cached_shape_ram_amount; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = iLayerIndex; map->query.rect = rect; if( pszExpression ) { map->query.type = MS_QUERY_BY_FILTER; msInitExpression(&map->query.filter); map->query.filter.string = msStrdup(pszExpression); map->query.filter.type = MS_EXPRESSION; /* a logical expression */ retval = msQueryByFilter(map); } else { map->query.type = MS_QUERY_BY_RECT; retval = msQueryByRect(map); } return retval; } #endif mapserver-7.4.3/mapogcsld.c000066400000000000000000006321741357574274700157100ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC SLD implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #include "mapogcsld.h" #include "mapogcfilter.h" #include "mapserver.h" #include "mapows.h" #ifdef USE_OGR #include "cpl_string.h" #endif #if defined(USE_OGR) && defined(USE_CURL) static inline void IGUR_sizet(size_t ignored) { (void)ignored; } /* Ignore GCC Unused Result */ #endif #define SLD_LINE_SYMBOL_NAME "sld_line_symbol" #define SLD_LINE_SYMBOL_DASH_NAME "sld_line_symbol_dash" #define SLD_MARK_SYMBOL_SQUARE "sld_mark_symbol_square" #define SLD_MARK_SYMBOL_SQUARE_FILLED "sld_mark_symbol_square_filled" #define SLD_MARK_SYMBOL_CIRCLE "sld_mark_symbol_circle" #define SLD_MARK_SYMBOL_CIRCLE_FILLED "sld_mark_symbol_circle_filled" #define SLD_MARK_SYMBOL_TRIANGLE "sld_mark_symbol_triangle" #define SLD_MARK_SYMBOL_TRIANGLE_FILLED "sld_mark_symbol_triangle_filled" #define SLD_MARK_SYMBOL_STAR "sld_mark_symbol_star" #define SLD_MARK_SYMBOL_STAR_FILLED "sld_mark_symbol_star_filled" #define SLD_MARK_SYMBOL_CROSS "sld_mark_symbol_cross" #define SLD_MARK_SYMBOL_CROSS_FILLED "sld_mark_symbol_cross_filled" #define SLD_MARK_SYMBOL_X "sld_mark_symbol_x" #define SLD_MARK_SYMBOL_X_FILLED "sld_mark_symbol_x_filled" /************************************************************************/ /* msSLDApplySLDURL */ /* */ /* Use the SLD document given through a URL and apply the SLD */ /* on the map. Layer name and Named Layer's name parameter are */ /* used to do the match. */ /************************************************************************/ int msSLDApplySLDURL(mapObj *map, const char *szURL, int iLayer, const char *pszStyleLayerName, char **ppszLayerNames) { #ifdef USE_OGR /* needed for libcurl function msHTTPGetFile in maphttp.c */ #if defined(USE_CURL) char *pszSLDTmpFile = NULL; int status = 0; char *pszSLDbuf=NULL; FILE *fp = NULL; int nStatus = MS_FAILURE; if (map && szURL) { pszSLDTmpFile = msTmpFile(map, map->mappath, NULL, "sld.xml"); if (pszSLDTmpFile == NULL) { pszSLDTmpFile = msTmpFile(map, NULL, NULL, "sld.xml" ); } if (pszSLDTmpFile == NULL) { msSetError(MS_WMSERR, "Could not determine temporary file %s. Please make sure that the temporary path is set. The temporary path can be defined for example by setting TEMPPATH in the map file. Please check the MapServer documentation on temporary path settings.", "msSLDApplySLDURL()", pszSLDTmpFile); } else { int nMaxRemoteSLDBytes; const char *pszMaxRemoteSLDBytes = msOWSLookupMetadata(&(map->web.metadata), "MO", "remote_sld_max_bytes"); if(!pszMaxRemoteSLDBytes) { nMaxRemoteSLDBytes = 1024*1024; /* 1 megaByte */ } else { nMaxRemoteSLDBytes = atoi(pszMaxRemoteSLDBytes); } if (msHTTPGetFile(szURL, pszSLDTmpFile, &status,-1, 0, 0, nMaxRemoteSLDBytes) == MS_SUCCESS) { if ((fp = fopen(pszSLDTmpFile, "rb")) != NULL) { int nBufsize=0; fseek(fp, 0, SEEK_END); nBufsize = ftell(fp); if(nBufsize > 0) { rewind(fp); pszSLDbuf = (char*)malloc((nBufsize+1)*sizeof(char)); IGUR_sizet(fread(pszSLDbuf, 1, nBufsize, fp)); pszSLDbuf[nBufsize] = '\0'; } else { msSetError(MS_WMSERR, "Could not open SLD %s as it appears empty", "msSLDApplySLDURL", szURL); } fclose(fp); unlink(pszSLDTmpFile); } } else { unlink(pszSLDTmpFile); msSetError(MS_WMSERR, "Could not open SLD %s and save it in a temporary file. Please make sure that the sld url is valid and that the temporary path is set. The temporary path can be defined for example by setting TEMPPATH in the map file. Please check the MapServer documentation on temporary path settings.", "msSLDApplySLDURL", szURL); } msFree(pszSLDTmpFile); if (pszSLDbuf) nStatus = msSLDApplySLD(map, pszSLDbuf, iLayer, pszStyleLayerName, ppszLayerNames); } } msFree(pszSLDbuf); return nStatus; #else msSetError(MS_MISCERR, "WMS/WFS client support is not enabled .", "msSLDApplySLDURL()"); return(MS_FAILURE); #endif #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msSLDApplySLDURL()"); return(MS_FAILURE); #endif /* USE_OGR */ } /************************************************************************/ /* msSLDApplySLD */ /* */ /* Parses the SLD into array of layers. Go through the map and */ /* compare the SLD layers and the map layers using the name. If */ /* they have the same name, copy the classes asscoaited with */ /* the SLD layers onto the map layers. */ /************************************************************************/ int msSLDApplySLD(mapObj *map, const char *psSLDXML, int iLayer, const char *pszStyleLayerName, char **ppszLayerNames) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) #ifdef USE_OGR int nLayers = 0; layerObj *pasLayers = NULL; int i, j, k, z, iClass; int bUseSpecificLayer = 0; const char *pszTmp = NULL; int nStatus = MS_SUCCESS; /*const char *pszSLDNotSupported = NULL;*/ char *tmpfilename = NULL; const char *pszFullName = NULL; char szTmp[512]; char *pszTmp1=NULL; char *pszTmp2 = NULL; char *pszBuffer = NULL; layerObj *lp = NULL; pasLayers = msSLDParseSLD(map, psSLDXML, &nLayers); if( pasLayers == NULL ) { errorObj* psError = msGetErrorObj(); if( psError && psError->code != MS_NOERR ) return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* If the same layer is given more that once, we need to */ /* duplicate it. */ /* -------------------------------------------------------------------- */ if (pasLayers && nLayers>0) { int l,m; for (m=0; mvtable) msInitializeVirtualTable(psTmpLayer); /*make the name unique*/ snprintf(tmpId, sizeof(tmpId), "%lx_%x_%d",(long)time(NULL),(int)getpid(), map->numlayers); if (psTmpLayer->name) msFree(psTmpLayer->name); psTmpLayer->name = msStrdup(tmpId); msFree(pasLayers[l].name); pasLayers[l].name = msStrdup(tmpId); msInsertLayer(map, psTmpLayer, -1); MS_REFCNT_DECR(psTmpLayer); } } } for (i=0; inumlayers; i++) { if (iLayer >=0 && iLayer< map->numlayers) { i = iLayer; bUseSpecificLayer = 1; } /* compare layer name to wms_name as well */ pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "MO", "name"); for (j=0; jname, pasLayers[j].name) == 0 || (pszTmp && strcasecmp(pszTmp, pasLayers[j].name) == 0))|| (GET_LAYER(map, i)->group && strcasecmp(GET_LAYER(map, i)->group, pasLayers[j].name) == 0))) || (bUseSpecificLayer && pszStyleLayerName && pasLayers[j].name && strcasecmp(pasLayers[j].name, pszStyleLayerName) == 0)) { #ifdef notdef /*this is a test code if we decide to flag some layers as not supporting SLD*/ pszSLDNotSupported = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "M", "SLD_NOT_SUPPORTED"); if (pszSLDNotSupported) { msSetError(MS_WMSERR, "Layer %s does not support SLD", "msSLDApplySLD", pasLayers[j].name); nsStatus = MS_FAILURE; goto sld_cleanup; } #endif if ( pasLayers[j].numclasses > 0) { GET_LAYER(map, i)->type = pasLayers[j].type; for(k=0; knumclasses; k++) { if (GET_LAYER(map, i)->class[k] != NULL) { GET_LAYER(map, i)->class[k]->layer=NULL; if (freeClass(GET_LAYER(map, i)->class[k]) == MS_SUCCESS ) { msFree(GET_LAYER(map, i)->class[k]); GET_LAYER(map, i)->class[k] = NULL; } } } GET_LAYER(map, i)->numclasses = 0; /*unset the classgroup on the layer if it was set. This allows the layer to render with all the classes defined in the SLD*/ msFree(GET_LAYER(map, i)->classgroup); GET_LAYER(map, i)->classgroup = NULL; iClass = 0; for (k=0; k < pasLayers[j].numclasses; k++) { if (msGrowLayerClasses(GET_LAYER(map, i)) == NULL) return MS_FAILURE; initClass(GET_LAYER(map, i)->class[iClass]); msCopyClass(GET_LAYER(map, i)->class[iClass], pasLayers[j].class[k], NULL); GET_LAYER(map, i)->class[iClass]->layer = GET_LAYER(map, i); GET_LAYER(map, i)->numclasses++; /*aliases may have been used as part of the sld text symbolizer for label element. Try to process it if that is the case #3114*/ if (msLayerOpen(GET_LAYER(map, i)) == MS_SUCCESS && msLayerGetItems(GET_LAYER(map, i)) == MS_SUCCESS) { if (GET_LAYER(map, i)->class[iClass]->text.string) { for(z=0; znumitems; z++) { if (!GET_LAYER(map, i)->items[z] || strlen(GET_LAYER(map, i)->items[z]) <= 0) continue; snprintf(szTmp, sizeof(szTmp), "%s_alias", GET_LAYER(map, i)->items[z]); pszFullName = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "G", szTmp); pszTmp1 = msStrdup( GET_LAYER(map, i)->class[iClass]->text.string); if (pszFullName != NULL && (strstr(pszTmp1, pszFullName) != NULL)) { char *tmpstr1= NULL; tmpstr1 = msReplaceSubstring(pszTmp1, pszFullName, GET_LAYER(map, i)->items[z]); pszTmp2 = (char *)malloc(sizeof(char)*(strlen(tmpstr1)+3)); sprintf(pszTmp2,"(%s)",tmpstr1); msLoadExpressionString(&(GET_LAYER(map, i)->class[iClass]->text), pszTmp2); msFree(pszTmp2); } msFree(pszTmp1); } } } iClass++; } } else { /*this is probably an SLD that uses Named styles*/ if (pasLayers[j].classgroup) { for (k=0; knumclasses; k++) { if (GET_LAYER(map, i)->class[k]->group && strcasecmp(GET_LAYER(map, i)->class[k]->group, pasLayers[j].classgroup) == 0) break; } if (k < GET_LAYER(map, i)->numclasses) { msFree( GET_LAYER(map, i)->classgroup); GET_LAYER(map, i)->classgroup = msStrdup(pasLayers[j].classgroup); } else { /* TODO we throw an exception ?*/ } } } if (pasLayers[j].labelitem) { if (GET_LAYER(map, i)->labelitem) free(GET_LAYER(map, i)->labelitem); GET_LAYER(map, i)->labelitem = msStrdup(pasLayers[j].labelitem); } if (pasLayers[j].classitem) { if (GET_LAYER(map, i)->classitem) free(GET_LAYER(map, i)->classitem); GET_LAYER(map, i)->classitem = msStrdup(pasLayers[j].classitem); } /* opacity for sld raster */ if (GET_LAYER(map, i)->type == MS_LAYER_RASTER && pasLayers[j].compositer && pasLayers[j].compositer->opacity != 100) msSetLayerOpacity(GET_LAYER(map, i), pasLayers[j].compositer->opacity); /* mark as auto-generate SLD */ if (GET_LAYER(map, i)->connectiontype == MS_WMS) msInsertHashTable(&(GET_LAYER(map, i)->metadata), "wms_sld_body", "auto" ); lp = GET_LAYER(map, i); /* The SLD might have a FeatureTypeConstraint */ if( pasLayers[j].filter.type == MS_EXPRESSION ) { if( lp->filter.string && lp->filter.type == MS_EXPRESSION ) { pszBuffer = msStringConcatenate(NULL, "(("); pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string); pszBuffer = msStringConcatenate(pszBuffer, ") AND ("); pszBuffer = msStringConcatenate(pszBuffer, pasLayers[j].filter.string); pszBuffer = msStringConcatenate(pszBuffer, "))"); msFreeExpression(&lp->filter); msInitExpression(&lp->filter); lp->filter.string = pszBuffer; lp->filter.type = MS_EXPRESSION; pszBuffer = NULL; } else { msFreeExpression(&lp->filter); msInitExpression(&lp->filter); lp->filter.string = msStrdup(pasLayers[j].filter.string); lp->filter.type = MS_EXPRESSION; } } /*in some cases it would make sense to concatenate all the class expressions and use it to set the filter on the layer. This could increase performace. Will do it for db types layers #2840*/ if (lp->filter.string == NULL || (lp->filter.string && lp->filter.type == MS_STRING && !lp->filteritem)) { if (lp->connectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_PLUGIN) { if (lp->numclasses > 0) { /* check first that all classes have an expression type. That is the only way we can concatenate them and set the filter expression */ for (k=0; knumclasses; k++) { if (lp->class[k]->expression.type != MS_EXPRESSION) break; } if (k == lp->numclasses) { for (k=0; knumclasses; k++) { if (pszBuffer == NULL) snprintf(szTmp, sizeof(szTmp), "%s", "(("); /* we a building a string expression, explicitly set type below */ else snprintf(szTmp, sizeof(szTmp), "%s", " OR "); pszBuffer = msStringConcatenate(pszBuffer, szTmp); pszBuffer = msStringConcatenate(pszBuffer, lp->class[k]->expression.string); } snprintf(szTmp, sizeof(szTmp), "%s", "))"); pszBuffer =msStringConcatenate(pszBuffer, szTmp); msFreeExpression(&lp->filter); msInitExpression(&lp->filter); lp->filter.string = msStrdup(pszBuffer); lp->filter.type = MS_EXPRESSION; msFree(pszBuffer); pszBuffer = NULL; } } } } break; } } if (bUseSpecificLayer) break; } /* -------------------------------------------------------------------- */ /* if needed return a comma separated list of the layers found */ /* in the sld. */ /* -------------------------------------------------------------------- */ if (ppszLayerNames) { char *pszTmp = NULL; for (i=0; idebug == MS_DEBUGLEVEL_VVV) { tmpfilename = msTmpFile(map, map->mappath, NULL, "_sld.map"); if (tmpfilename == NULL) { tmpfilename = msTmpFile(map, NULL, NULL, "_sld.map" ); } if (tmpfilename) { msSaveMap(map,tmpfilename); msDebug("msApplySLD(): Map file after SLD was applied %s", tmpfilename); msFree(tmpfilename); } } return nStatus; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msSLDApplySLD()"); return(MS_FAILURE); #endif /* USE_OGR */ #else msSetError(MS_MISCERR, "OWS support is not available.", "msSLDApplySLD()"); return(MS_FAILURE); #endif } #ifdef USE_OGR /************************************************************************/ /* msSLDParseSLD */ /* */ /* Parse the sld document into layers : for each named layer */ /* there is one mapserver layer created with approproate */ /* classes and styles. */ /* Returns an array of mapserver layers. The pnLayres if */ /* provided will indicate the size of the returned array. */ /************************************************************************/ layerObj *msSLDParseSLD(mapObj *map, const char *psSLDXML, int *pnLayers) { CPLXMLNode *psRoot = NULL; CPLXMLNode *psSLD, *psNamedLayer, *psChild, *psName; layerObj *pasLayers = NULL; int iLayer = 0; int nLayers = 0; if (map == NULL || psSLDXML == NULL || strlen(psSLDXML) <= 0 || (strstr(psSLDXML, "StyledLayerDescriptor") == NULL)) { msSetError(MS_WMSERR, "Invalid SLD document", ""); return NULL; } psRoot = CPLParseXMLString(psSLDXML); if( psRoot == NULL) { msSetError(MS_WMSERR, "Invalid SLD document : %s", "", psSLDXML); return NULL; } /* strip namespaces ogc and sld and gml */ CPLStripXMLNamespace(psRoot, "ogc", 1); CPLStripXMLNamespace(psRoot, "sld", 1); CPLStripXMLNamespace(psRoot, "gml", 1); CPLStripXMLNamespace(psRoot, "se", 1); /* -------------------------------------------------------------------- */ /* get the root element (Filter). */ /* -------------------------------------------------------------------- */ psChild = psRoot; psSLD = NULL; while( psChild != NULL ) { if (psChild->eType == CXT_Element && EQUAL(psChild->pszValue,"StyledLayerDescriptor")) { psSLD = psChild; break; } else psChild = psChild->psNext; } if (!psSLD) { msSetError(MS_WMSERR, "Invalid SLD document : %s", "", psSLDXML); return NULL; } /* -------------------------------------------------------------------- */ /* Parse the named layers. */ /* -------------------------------------------------------------------- */ psNamedLayer = CPLGetXMLNode(psSLD, "NamedLayer"); while (psNamedLayer) { if (!psNamedLayer->pszValue || strcasecmp(psNamedLayer->pszValue, "NamedLayer") != 0) { psNamedLayer = psNamedLayer->psNext; continue; } psNamedLayer = psNamedLayer->psNext; nLayers++; } if (nLayers > 0) pasLayers = (layerObj *)malloc(sizeof(layerObj)*nLayers); else return NULL; psNamedLayer = CPLGetXMLNode(psSLD, "NamedLayer"); if (psNamedLayer) { iLayer = 0; while (psNamedLayer) { if (!psNamedLayer->pszValue || strcasecmp(psNamedLayer->pszValue, "NamedLayer") != 0) { psNamedLayer = psNamedLayer->psNext; continue; } psName = CPLGetXMLNode(psNamedLayer, "Name"); initLayer(&pasLayers[iLayer], map); if (psName && psName->psChild && psName->psChild->pszValue) pasLayers[iLayer].name = msStrdup(psName->psChild->pszValue); if( msSLDParseNamedLayer(psNamedLayer, &pasLayers[iLayer]) != MS_SUCCESS ) { int i; for (i=0; i<=iLayer; i++) freeLayer(&pasLayers[i]); msFree(pasLayers); nLayers = 0; pasLayers = NULL; break; } psNamedLayer = psNamedLayer->psNext; iLayer++; } } if (pnLayers) *pnLayers = nLayers; if (psRoot) CPLDestroyXMLNode(psRoot); return pasLayers; } double _msSLDParseSizeParameter(CPLXMLNode *psSize) { double dSize = 0; CPLXMLNode *psLiteral = NULL; if (psSize) { psLiteral = CPLGetXMLNode(psSize, "Literal"); if (psLiteral && psLiteral->psChild && psLiteral->psChild->pszValue) dSize = atof(psLiteral->psChild->pszValue); else if (psSize->psChild && psSize->psChild->pszValue) dSize = atof(psSize->psChild->pszValue); } return dSize; } /************************************************************************/ /* _SLDApplyRuleValues */ /* */ /* Utility function to set the scale, title/name for the */ /* classes created by a Rule. */ /************************************************************************/ void _SLDApplyRuleValues(CPLXMLNode *psRule, layerObj *psLayer, int nNewClasses) { int i=0; CPLXMLNode *psMinScale=NULL, *psMaxScale=NULL; CPLXMLNode *psName=NULL, *psTitle=NULL; double dfMinScale=0, dfMaxScale=0; char *pszName=NULL, *pszTitle=NULL; if (psRule && psLayer && nNewClasses > 0) { /* -------------------------------------------------------------------- */ /* parse minscale and maxscale. */ /* -------------------------------------------------------------------- */ psMinScale = CPLGetXMLNode(psRule, "MinScaleDenominator"); if (psMinScale && psMinScale->psChild && psMinScale->psChild->pszValue) dfMinScale = atof(psMinScale->psChild->pszValue); psMaxScale = CPLGetXMLNode(psRule, "MaxScaleDenominator"); if (psMaxScale && psMaxScale->psChild && psMaxScale->psChild->pszValue) dfMaxScale = atof(psMaxScale->psChild->pszValue); /* -------------------------------------------------------------------- */ /* parse name and title. */ /* -------------------------------------------------------------------- */ psName = CPLGetXMLNode(psRule, "Name"); if (psName && psName->psChild && psName->psChild->pszValue) pszName = psName->psChild->pszValue; psTitle = CPLGetXMLNode(psRule, "Title"); if (psTitle && psTitle->psChild && psTitle->psChild->pszValue) pszTitle = psTitle->psChild->pszValue; /* -------------------------------------------------------------------- */ /* set the scale to all the classes created by the rule. */ /* -------------------------------------------------------------------- */ if (dfMinScale > 0 || dfMaxScale > 0) { for (i=0; i 0) psLayer->class[psLayer->numclasses-1-i]->minscaledenom = dfMinScale; if (dfMaxScale) psLayer->class[psLayer->numclasses-1-i]->maxscaledenom = dfMaxScale; } } /* -------------------------------------------------------------------- */ /* set name and title to the classes created by the rule. */ /* -------------------------------------------------------------------- */ for (i=0; iclass[psLayer->numclasses-1-i]->name) { if (pszName) psLayer->class[psLayer->numclasses-1-i]->name = msStrdup(pszName); else if (pszTitle) psLayer->class[psLayer->numclasses-1-i]->name = msStrdup(pszTitle); else psLayer->class[psLayer->numclasses-1-i]->name = msStrdup("Unknown"); } } if (pszTitle) { for (i=0; iclass[psLayer->numclasses-1-i]->title = msStrdup(pszTitle); } } } } /************************************************************************/ /* msSLDGetCommonExpressionFromFilter */ /* */ /* Get a commomn expression valid from the filter valid for the */ /* temporary layer. */ /************************************************************************/ static char* msSLDGetCommonExpressionFromFilter(CPLXMLNode* psFilter, layerObj *psLayer) { char *pszExpression = NULL; CPLXMLNode *psTmpNextNode = NULL; CPLXMLNode *psTmpNode = NULL; FilterEncodingNode *psNode = NULL; char *pszTmpFilter = NULL; layerObj *psCurrentLayer = NULL; const char *pszWmsName=NULL; const char *key=NULL; /* clone the tree and set the next node to null */ /* so we only have the Filter node */ psTmpNode = CPLCloneXMLTree(psFilter); psTmpNextNode = psTmpNode->psNext; psTmpNode->psNext = NULL; pszTmpFilter = CPLSerializeXMLTree(psTmpNode); psTmpNode->psNext = psTmpNextNode; CPLDestroyXMLNode(psTmpNode); if (pszTmpFilter) { psNode = FLTParseFilterEncoding(pszTmpFilter); CPLFree(pszTmpFilter); } if (psNode) { int j; /*preparse the filter for possible gml aliases set on the layer's metada: "gml_NA3DESC_alias" "alias_name" and filter could be alias_name #3079*/ for (j=0; jmap->numlayers; j++) { psCurrentLayer = GET_LAYER(psLayer->map, j); pszWmsName = msOWSLookupMetadata(&(psCurrentLayer->metadata), "MO", "name"); if ((psCurrentLayer->name && psLayer->name && strcasecmp(psCurrentLayer->name, psLayer->name) == 0) || (psCurrentLayer->group && psLayer->name && strcasecmp(psCurrentLayer->group, psLayer->name) == 0) || (psLayer->name && pszWmsName && strcasecmp(pszWmsName, psLayer->name) == 0)) break; } if (j < psLayer->map->numlayers) { /*make sure that the tmp layer has all the metadata that the orinal layer has, allowing to do parsing for such things as gml_attribute_type #3052*/ while (1) { key = msNextKeyFromHashTable(&psCurrentLayer->metadata, key); if (!key) break; else msInsertHashTable(&psLayer->metadata, key, msLookupHashTable(&psCurrentLayer->metadata, key)); } FLTPreParseFilterForAliasAndGroup(psNode, psLayer->map, j, "G"); } pszExpression = FLTGetCommonExpression(psNode, psLayer); FLTFreeFilterEncodingNode(psNode); } return pszExpression; } /************************************************************************/ /* msSLDParseNamedLayer */ /* */ /* Parse NamedLayer root. */ /************************************************************************/ int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *psLayer) { CPLXMLNode *psFeatureTypeStyle, *psRule, *psUserStyle; CPLXMLNode *psSLDName = NULL, *psNamedStyle=NULL; CPLXMLNode *psElseFilter = NULL, *psFilter=NULL; CPLXMLNode *psLayerFeatureConstraints = NULL; int nNewClasses=0, nClassBeforeFilter=0, nClassAfterFilter=0; int nClassAfterRule=0, nClassBeforeRule=0; if (!psRoot || !psLayer) return MS_FAILURE; psUserStyle = CPLGetXMLNode(psRoot, "UserStyle"); if (psUserStyle) { psFeatureTypeStyle = CPLGetXMLNode(psUserStyle, "FeatureTypeStyle"); if (psFeatureTypeStyle) { while (psFeatureTypeStyle && psFeatureTypeStyle->pszValue && strcasecmp(psFeatureTypeStyle->pszValue, "FeatureTypeStyle") == 0) { if (!psFeatureTypeStyle->pszValue || strcasecmp(psFeatureTypeStyle->pszValue, "FeatureTypeStyle") != 0) { psFeatureTypeStyle = psFeatureTypeStyle->psNext; continue; } /* -------------------------------------------------------------------- */ /* Parse rules with no Else filter. */ /* -------------------------------------------------------------------- */ psRule = CPLGetXMLNode(psFeatureTypeStyle, "Rule"); while (psRule) { if (!psRule->pszValue || strcasecmp(psRule->pszValue, "Rule") != 0) { psRule = psRule->psNext; continue; } /* used for scale setting */ nClassBeforeRule = psLayer->numclasses; psElseFilter = CPLGetXMLNode(psRule, "ElseFilter"); nClassBeforeFilter = psLayer->numclasses; if (psElseFilter == NULL) msSLDParseRule(psRule, psLayer); nClassAfterFilter = psLayer->numclasses; /* -------------------------------------------------------------------- */ /* Parse the filter and apply it to the latest class created by */ /* the rule. */ /* NOTE : Spatial Filter is not supported. */ /* -------------------------------------------------------------------- */ psFilter = CPLGetXMLNode(psRule, "Filter"); if (psFilter && psFilter->psChild && psFilter->psChild->pszValue) { char* pszExpression = msSLDGetCommonExpressionFromFilter(psFilter, psLayer); if (pszExpression) { int i; nNewClasses = nClassAfterFilter - nClassBeforeFilter; for (i=0; i class[psLayer->numclasses-1-i]-> expression); msFreeExpression(exp); msInitExpression(exp); exp->string = msStrdup(pszExpression); exp->type = MS_EXPRESSION; } msFree(pszExpression); pszExpression = NULL; } } nClassAfterRule = psLayer->numclasses; nNewClasses = nClassAfterRule - nClassBeforeRule; /* apply scale and title to newly created classes */ _SLDApplyRuleValues(psRule, psLayer, nNewClasses); /* TODO : parse legendgraphic */ psRule = psRule->psNext; } /* -------------------------------------------------------------------- */ /* First parse rules with the else filter. These rules will */ /* create the classes that are placed at the end of class */ /* list. (See how classes are applied to layers in function */ /* msSLDApplySLD). */ /* -------------------------------------------------------------------- */ psRule = CPLGetXMLNode(psFeatureTypeStyle, "Rule"); while (psRule) { if (!psRule->pszValue || strcasecmp(psRule->pszValue, "Rule") != 0) { psRule = psRule->psNext; continue; } psElseFilter = CPLGetXMLNode(psRule, "ElseFilter"); if (psElseFilter) { msSLDParseRule(psRule, psLayer); _SLDApplyRuleValues(psRule, psLayer, 1); } psRule = psRule->psNext; } psFeatureTypeStyle = psFeatureTypeStyle->psNext; } } } /* check for Named styles*/ else { psNamedStyle = CPLGetXMLNode(psRoot, "NamedStyle"); if (psNamedStyle) { psSLDName = CPLGetXMLNode(psNamedStyle, "Name"); if (psSLDName && psSLDName->psChild && psSLDName->psChild->pszValue) { msFree(psLayer->classgroup); psLayer->classgroup = msStrdup(psSLDName->psChild->pszValue); } } } /* Deal with LayerFeatureConstraints */ psLayerFeatureConstraints = CPLGetXMLNode(psRoot, "LayerFeatureConstraints"); if( psLayerFeatureConstraints != NULL ) { CPLXMLNode* psIter = psLayerFeatureConstraints->psChild; CPLXMLNode* psFeatureTypeConstraint = NULL; for(; psIter != NULL; psIter = psIter->psNext ) { if( psIter->eType == CXT_Element && strcmp(psIter->pszValue, "FeatureTypeConstraint") == 0 ) { if( psFeatureTypeConstraint == NULL ) { psFeatureTypeConstraint = psIter; } else { msSetError(MS_WMSERR, "Only one single FeatureTypeConstraint element " "per LayerFeatureConstraints is supported", ""); return MS_FAILURE; } } } if( psFeatureTypeConstraint != NULL ) { if( CPLGetXMLNode(psFeatureTypeConstraint, "FeatureTypeName") != NULL ) { msSetError(MS_WMSERR, "FeatureTypeName element is not " "supported in FeatureTypeConstraint", ""); return MS_FAILURE; } if( CPLGetXMLNode(psFeatureTypeConstraint, "Extent") != NULL ) { msSetError(MS_WMSERR, "Extent element is not " "supported in FeatureTypeConstraint", ""); return MS_FAILURE; } psFilter = CPLGetXMLNode(psFeatureTypeConstraint, "Filter"); if (psFilter && psFilter->psChild && psFilter->psChild->pszValue) { char* pszExpression = msSLDGetCommonExpressionFromFilter(psFilter, psLayer); if (pszExpression) { msFreeExpression(&psLayer->filter); msInitExpression(&psLayer->filter); psLayer->filter.string = pszExpression; psLayer->filter.type = MS_EXPRESSION; } } } } return MS_SUCCESS; } /************************************************************************/ /* void msSLDParseRule(CPLXMLNode *psRoot, layerObj *psLayer) */ /* */ /* Parse a Rule node into classes for a spcific layer. */ /************************************************************************/ int msSLDParseRule(CPLXMLNode *psRoot, layerObj *psLayer) { CPLXMLNode *psLineSymbolizer = NULL; CPLXMLNode *psPolygonSymbolizer = NULL; CPLXMLNode *psPointSymbolizer = NULL; CPLXMLNode *psTextSymbolizer = NULL; CPLXMLNode *psRasterSymbolizer = NULL; int bSymbolizer = 0; int bNewClass=0, nSymbolizer=0; if (!psRoot || !psLayer) return MS_FAILURE; /* TODO : parse name of the rule */ /* -------------------------------------------------------------------- */ /* The SLD specs assumes here that a certain FeatureType can only have*/ /* rules for only one type of symbolizer. */ /* -------------------------------------------------------------------- */ /* ==================================================================== */ /* For each rule a new class is created. If there are more than */ /* one symbolizer of the same type, a style is added in the */ /* same class. */ /* ==================================================================== */ nSymbolizer =0; /* line symbolizer */ psLineSymbolizer = CPLGetXMLNode(psRoot, "LineSymbolizer"); while (psLineSymbolizer) { if (!psLineSymbolizer->pszValue || strcasecmp(psLineSymbolizer->pszValue, "LineSymbolizer") != 0) { psLineSymbolizer = psLineSymbolizer->psNext; continue; } bSymbolizer = 1; if (nSymbolizer == 0) bNewClass = 1; else bNewClass = 0; msSLDParseLineSymbolizer(psLineSymbolizer, psLayer, bNewClass); psLineSymbolizer = psLineSymbolizer->psNext; psLayer->type = MS_LAYER_LINE; nSymbolizer++; } /* Polygon symbolizer */ psPolygonSymbolizer = CPLGetXMLNode(psRoot, "PolygonSymbolizer"); while (psPolygonSymbolizer) { if (!psPolygonSymbolizer->pszValue || strcasecmp(psPolygonSymbolizer->pszValue, "PolygonSymbolizer") != 0) { psPolygonSymbolizer = psPolygonSymbolizer->psNext; continue; } bSymbolizer = 1; if (nSymbolizer == 0) bNewClass = 1; else bNewClass = 0; msSLDParsePolygonSymbolizer(psPolygonSymbolizer, psLayer, bNewClass); psPolygonSymbolizer = psPolygonSymbolizer->psNext; psLayer->type = MS_LAYER_POLYGON; nSymbolizer++; } /* Point Symbolizer */ psPointSymbolizer = CPLGetXMLNode(psRoot, "PointSymbolizer"); while (psPointSymbolizer) { if (!psPointSymbolizer->pszValue || strcasecmp(psPointSymbolizer->pszValue, "PointSymbolizer") != 0) { psPointSymbolizer = psPointSymbolizer->psNext; continue; } bSymbolizer = 1; if (nSymbolizer == 0) bNewClass = 1; else bNewClass = 0; msSLDParsePointSymbolizer(psPointSymbolizer, psLayer, bNewClass); psPointSymbolizer = psPointSymbolizer->psNext; psLayer->type = MS_LAYER_POINT; nSymbolizer++; } /* Text symbolizer */ /* ==================================================================== */ /* For text symbolizer, here is how it is translated into */ /* mapserver classes : */ /* - If there are other symbolizers(line, polygon, symbol), */ /* the label object created will be created in the same class */ /* (the last class) as the symbolizer. This allows o have for */ /* example of point layer with labels. */ /* - If there are no other symbolizers, a new clas will be */ /* created ocontain the label object. */ /* ==================================================================== */ psTextSymbolizer = CPLGetXMLNode(psRoot, "TextSymbolizer"); while (psTextSymbolizer && psTextSymbolizer->pszValue && strcasecmp(psTextSymbolizer->pszValue, "TextSymbolizer") == 0) { if (!psTextSymbolizer->pszValue || strcasecmp(psTextSymbolizer->pszValue, "TextSymbolizer") != 0) { psTextSymbolizer = psTextSymbolizer->psNext; continue; } if (nSymbolizer == 0) psLayer->type = MS_LAYER_POINT; msSLDParseTextSymbolizer(psTextSymbolizer, psLayer, bSymbolizer); psTextSymbolizer = psTextSymbolizer->psNext; } /* Raster symbolizer */ psRasterSymbolizer = CPLGetXMLNode(psRoot, "RasterSymbolizer"); while (psRasterSymbolizer && psRasterSymbolizer->pszValue && strcasecmp(psRasterSymbolizer->pszValue, "RasterSymbolizer") == 0) { if (!psRasterSymbolizer->pszValue || strcasecmp(psRasterSymbolizer->pszValue, "RasterSymbolizer") != 0) { psRasterSymbolizer = psRasterSymbolizer->psNext; continue; } msSLDParseRasterSymbolizer(psRasterSymbolizer, psLayer); psRasterSymbolizer = psRasterSymbolizer->psNext; psLayer->type = MS_LAYER_RASTER; } return MS_SUCCESS; } /************************************************************************/ /* void msSLDParseLineSymbolizer(CPLXMLNode *psRoot, layerObj */ /* *psLayer) */ /* */ /* Parses the LineSymbolizer rule and creates a class in the */ /* layer. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Example of a rule : */ /* ... */ /* */ /* */ /* */ /* center-line */ /* */ /* */ /* #0000ff */ /* 5.0 */ /* 10.0 5 5 10*/ /* */ /* */ /* */ /* ... */ /************************************************************************/ int msSLDParseLineSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass) { int nClassId = 0; CPLXMLNode *psStroke=NULL, *psOffset=NULL; int iStyle = 0; if (!psRoot || !psLayer) return MS_FAILURE; psStroke = CPLGetXMLNode(psRoot, "Stroke"); if (psStroke) { if (bNewClass || psLayer->numclasses <= 0) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; } else nClassId = psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); msSLDParseStroke(psStroke, psLayer->class[nClassId]->styles[iStyle], psLayer->map, 0); /*parse PerpendicularOffset SLD 1.1.10*/ psOffset = CPLGetXMLNode(psRoot, "PerpendicularOffset"); if (psOffset && psOffset->psChild && psOffset->psChild->pszValue) { psLayer->class[nClassId]->styles[iStyle]->offsetx = atoi(psOffset->psChild->pszValue); psLayer->class[nClassId]->styles[iStyle]->offsety = MS_STYLE_SINGLE_SIDED_OFFSET; } } return MS_SUCCESS; } /************************************************************************/ /* void msSLDParseStroke(CPLXMLNode *psStroke, styleObj */ /* *psStyle, int iColorParam) */ /* */ /* Parse Stroke content into a style object. */ /* The iColorParm is used to indicate which color object to use */ /* : */ /* 0 : for color */ /* 1 : outlinecolor */ /************************************************************************/ int msSLDParseStroke(CPLXMLNode *psStroke, styleObj *psStyle, mapObj *map, int iColorParam) { CPLXMLNode *psCssParam = NULL, *psGraphicFill=NULL; char *psStrkName = NULL; char *psColor = NULL; int nLength = 0; char *pszDashValue = NULL; if (!psStroke || !psStyle) return MS_FAILURE; /* parse css parameters */ psCssParam = CPLGetXMLNode(psStroke, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psStroke, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { psStrkName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (psStrkName) { if (strcasecmp(psStrkName, "stroke") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psColor = psCssParam->psChild->psNext->pszValue; if (psColor) { nLength = strlen(psColor); /* expecting hexadecimal ex : #aaaaff */ if (nLength == 7 && psColor[0] == '#') { if (iColorParam == 0) { psStyle->color.red = msHexToInt(psColor+1); psStyle->color.green = msHexToInt(psColor+3); psStyle->color.blue= msHexToInt(psColor+5); } else if (iColorParam == 1) { psStyle->outlinecolor.red = msHexToInt(psColor+1); psStyle->outlinecolor.green = msHexToInt(psColor+3); psStyle->outlinecolor.blue= msHexToInt(psColor+5); } else if (iColorParam == 2) { psStyle->backgroundcolor.red = msHexToInt(psColor+1); psStyle->backgroundcolor.green = msHexToInt(psColor+3); psStyle->backgroundcolor.blue= msHexToInt(psColor+5); } } } } else if (strcasecmp(psStrkName, "stroke-width") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) { psStyle->width = atof(psCssParam->psChild->psNext->pszValue); } } else if (strcasecmp(psStrkName, "stroke-dasharray") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) { int nDash = 0, i; char **aszValues = NULL; int nMaxDash; if(pszDashValue) free(pszDashValue); /* free previous if multiple stroke-dasharray attributes were found */ pszDashValue = msStrdup(psCssParam->psChild->psNext->pszValue); aszValues = msStringSplit(pszDashValue, ' ', &nDash); if (nDash > 0) { nMaxDash = nDash; if (nDash > MS_MAXPATTERNLENGTH) nMaxDash = MS_MAXPATTERNLENGTH; psStyle->patternlength = nMaxDash; for (i=0; ipattern[i] = atof(aszValues[i]); psStyle->linecap = MS_CJC_BUTT; } msFreeCharArray(aszValues, nDash); } } else if (strcasecmp(psStrkName, "stroke-opacity") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) { if (iColorParam == 0) { psStyle->color.alpha = (int)(atof(psCssParam->psChild->psNext->pszValue)*255); } else { psStyle->outlinecolor.alpha = (int)(atof(psCssParam->psChild->psNext->pszValue)*255); } } } } psCssParam = psCssParam->psNext; } /* parse graphic fill or stroke */ /* graphic fill and graphic stroke pare parsed the same way : */ /* TODO : It seems inconsistent to me since the only diffrence */ /* between them seems to be fill (fill) or not fill (stroke). And */ /* then again the fill parameter can be used inside both elements. */ psGraphicFill = CPLGetXMLNode(psStroke, "GraphicFill"); if (psGraphicFill) msSLDParseGraphicFillOrStroke(psGraphicFill, pszDashValue, psStyle, map); psGraphicFill = CPLGetXMLNode(psStroke, "GraphicStroke"); if (psGraphicFill) msSLDParseGraphicFillOrStroke(psGraphicFill, pszDashValue, psStyle, map); if (pszDashValue) free(pszDashValue); return MS_SUCCESS; } /************************************************************************/ /* void msSLDParsePolygonSymbolizer(CPLXMLNode *psRoot, */ /* layerObj *psLayer) */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Here, the CssParameter names are fill instead of stroke and */ /* fill-opacity instead of stroke-opacity. None of the other CssParameters*/ /* in Stroke are available for filling and the default value for the fill color in this context is 50% gray (value #808080).*/ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* The default if neither an ExternalGraphic nor a Mark is specified is to use the default*/ /* mark of a square with a 50%-gray fill and a black outline, with a size of 6 pixels.*/ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* The WellKnownName element gives the well-known name of the shape of the mark.*/ /* Allowed values include at least square, circle, triangle, star, cross,*/ /* and x, though map servers may draw a different symbol instead if they don't have a*/ /* shape for all of these. The default WellKnownName is square. Renderings of these*/ /* marks may be made solid or hollow depending on Fill and Stroke elements.*/ /* */ /************************************************************************/ int msSLDParsePolygonSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass) { CPLXMLNode *psFill, *psStroke; int nClassId=0, iStyle=0; CPLXMLNode *psDisplacement=NULL, *psDisplacementX=NULL, *psDisplacementY=NULL; int nOffsetX=-1, nOffsetY=-1; if (!psRoot || !psLayer) return MS_FAILURE; /*parse displacement for SLD 1.1.0*/ psDisplacement = CPLGetXMLNode(psRoot, "Displacement"); if (psDisplacement) { psDisplacementX = CPLGetXMLNode(psDisplacement, "DisplacementX"); psDisplacementY = CPLGetXMLNode(psDisplacement, "DisplacementY"); /* psCssParam->psChild->psNext->pszValue) */ if (psDisplacementX && psDisplacementX->psChild && psDisplacementX->psChild->pszValue && psDisplacementY && psDisplacementY->psChild && psDisplacementY->psChild->pszValue) { nOffsetX = atoi(psDisplacementX->psChild->pszValue); nOffsetY = atoi(psDisplacementY->psChild->pszValue); } } psFill = CPLGetXMLNode(psRoot, "Fill"); if (psFill) { if (bNewClass || psLayer->numclasses <= 0) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; } else nClassId = psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); msSLDParsePolygonFill(psFill, psLayer->class[nClassId]->styles[iStyle], psLayer->map); if (nOffsetX > 0 && nOffsetY > 0) { psLayer->class[nClassId]->styles[iStyle]->offsetx = nOffsetX; psLayer->class[nClassId]->styles[iStyle]->offsety = nOffsetY; } } /* stroke wich corresponds to the outilne in mapserver */ /* is drawn after the fill */ psStroke = CPLGetXMLNode(psRoot, "Stroke"); if (psStroke) { /* -------------------------------------------------------------------- */ /* there was a fill so add a style to the last class created */ /* by the fill */ /* -------------------------------------------------------------------- */ if (psFill && psLayer->numclasses > 0) { nClassId =psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); } else { if (bNewClass || psLayer->numclasses <= 0) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; } else nClassId = psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); } msSLDParseStroke(psStroke, psLayer->class[nClassId]->styles[iStyle], psLayer->map, 1); if (nOffsetX > 0 && nOffsetY > 0) { psLayer->class[nClassId]->styles[iStyle]->offsetx = nOffsetX; psLayer->class[nClassId]->styles[iStyle]->offsety = nOffsetY; } } return MS_SUCCESS; } /************************************************************************/ /* void msSLDParsePolygonFill(CPLXMLNode *psFill, styleObj *psStyle, */ /* mapObj *map) */ /* */ /* Parse the Fill node for a polygon into a style. */ /************************************************************************/ int msSLDParsePolygonFill(CPLXMLNode *psFill, styleObj *psStyle, mapObj *map) { CPLXMLNode *psCssParam, *psGraphicFill; char *psColor=NULL, *psFillName=NULL; int nLength = 0; if (!psFill || !psStyle || !map) return MS_FAILURE; /* sets the default fill color defined in the spec #808080 */ psStyle->color.red = 128; psStyle->color.green = 128; psStyle->color.blue = 128; psCssParam = CPLGetXMLNode(psFill, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psFill, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { psFillName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (psFillName) { if (strcasecmp(psFillName, "fill") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psColor = psCssParam->psChild->psNext->pszValue; if (psColor) { nLength = strlen(psColor); /* expecting hexadecimal ex : #aaaaff */ if (nLength == 7 && psColor[0] == '#') { psStyle->color.red = msHexToInt(psColor+1); psStyle->color.green = msHexToInt(psColor+3); psStyle->color.blue= msHexToInt(psColor+5); } } } else if (strcasecmp(psFillName, "fill-opacity") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) { psStyle->color.alpha = (int)(atof(psCssParam->psChild->psNext->pszValue)*255); } } } psCssParam = psCssParam->psNext; } /* graphic fill and graphic stroke pare parsed the same way : */ /* TODO : It seems inconsistent to me since the only diffrence */ /* between them seems to be fill (fill) or not fill (stroke). And */ /* then again the fill parameter can be used inside both elements. */ psGraphicFill = CPLGetXMLNode(psFill, "GraphicFill"); if (psGraphicFill) msSLDParseGraphicFillOrStroke(psGraphicFill, NULL, psStyle, map); psGraphicFill = CPLGetXMLNode(psFill, "GraphicStroke"); if (psGraphicFill) msSLDParseGraphicFillOrStroke(psGraphicFill, NULL, psStyle, map); return MS_SUCCESS; } /************************************************************************/ /* msSLDParseGraphicFillOrStroke */ /* */ /* Parse the GraphicFill Or GraphicStroke node : look for a */ /* Marker symbol and set the style for that symbol. */ /************************************************************************/ int msSLDParseGraphicFillOrStroke(CPLXMLNode *psRoot, char *pszDashValue, styleObj *psStyle, mapObj *map) { CPLXMLNode *psCssParam, *psGraphic, *psExternalGraphic, *psMark, *psSize, *psGap, *psInitialGap; CPLXMLNode *psWellKnownName, *psStroke, *psFill; CPLXMLNode *psDisplacement=NULL, *psDisplacementX=NULL, *psDisplacementY=NULL; CPLXMLNode *psOpacity=NULL, *psRotation=NULL; char *psName=NULL, *psValue = NULL; int nLength = 0; char *pszSymbolName = NULL; int bFilled = 0; CPLXMLNode *psPropertyName=NULL; char szTmp[256]; if (!psRoot || !psStyle || !map) return MS_FAILURE; /* ==================================================================== */ /* This a definition taken from the specification (11.3.2) : */ /* Graphics can either be referenced from an external URL in a common format (such as*/ /* GIF or SVG) or may be derived from a Mark. Multiple external URLs and marks may be*/ /* referenced with the semantic that they all provide the equivalent graphic in different*/ /* formats. */ /* */ /* For this reason, we only need to support one Mark and one */ /* ExtrnalGraphic ???? */ /* ==================================================================== */ psGraphic = CPLGetXMLNode(psRoot, "Graphic"); if (psGraphic) { /* extract symbol size */ psSize = CPLGetXMLNode(psGraphic, "Size"); if (psSize) psStyle->size = _msSLDParseSizeParameter(psSize); else { /*do not set a default for external symbols #2305*/ psExternalGraphic = CPLGetXMLNode(psGraphic, "ExternalGraphic"); if (!psExternalGraphic) psStyle->size = 6; /* default value */ } /*SLD 1.1.0 extract opacity, rotation, displacement*/ psOpacity = CPLGetXMLNode(psGraphic, "Opacity"); if (psOpacity && psOpacity->psChild && psOpacity->psChild->pszValue) psStyle->opacity = (int)(atof(psOpacity->psChild->pszValue) * 100); psRotation = CPLGetXMLNode(psGraphic, "Rotation"); if (psRotation) { psPropertyName = CPLGetXMLNode(psRotation, "PropertyName"); if (psPropertyName) { snprintf(szTmp, sizeof(szTmp), "%s", CPLGetXMLValue(psPropertyName, NULL, NULL)); psStyle->bindings[MS_STYLE_BINDING_ANGLE].item = msStrdup(szTmp); psStyle->numbindings++; } else { if (psRotation->psChild && psRotation->psChild->pszValue) psStyle->angle = atof(psRotation->psChild->pszValue); } } psDisplacement = CPLGetXMLNode(psGraphic, "Displacement"); if (psDisplacement) { psDisplacementX = CPLGetXMLNode(psDisplacement, "DisplacementX"); psDisplacementY = CPLGetXMLNode(psDisplacement, "DisplacementY"); /* psCssParam->psChild->psNext->pszValue) */ if (psDisplacementX && psDisplacementX->psChild && psDisplacementX->psChild->pszValue && psDisplacementY && psDisplacementY->psChild && psDisplacementY->psChild->pszValue) { psStyle->offsetx = atoi(psDisplacementX->psChild->pszValue); psStyle->offsety = atoi(psDisplacementY->psChild->pszValue); } } /* extract symbol */ psMark = CPLGetXMLNode(psGraphic, "Mark"); if (psMark) { pszSymbolName = NULL; psWellKnownName = CPLGetXMLNode(psMark, "WellKnownName"); if (psWellKnownName && psWellKnownName->psChild && psWellKnownName->psChild->pszValue) pszSymbolName = msStrdup(psWellKnownName->psChild->pszValue); /* default symbol is square */ if (!pszSymbolName || !*pszSymbolName || (strcasecmp(pszSymbolName, "square") != 0 && strcasecmp(pszSymbolName, "circle") != 0 && strcasecmp(pszSymbolName, "triangle") != 0 && strcasecmp(pszSymbolName, "star") != 0 && strcasecmp(pszSymbolName, "cross") != 0 && strcasecmp(pszSymbolName, "x") != 0)) { if (!pszSymbolName || !*pszSymbolName || msGetSymbolIndex(&map->symbolset, pszSymbolName, MS_FALSE) < 0) { msFree(pszSymbolName); pszSymbolName = msStrdup("square"); } } /* check if the symbol should be filled or not */ psFill = CPLGetXMLNode(psMark, "Fill"); psStroke = CPLGetXMLNode(psMark, "Stroke"); if (psFill || psStroke) { if (psFill) bFilled = 1; else bFilled = 0; if (psFill) { psCssParam = CPLGetXMLNode(psFill, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psFill, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { psName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (psName && strcasecmp(psName, "fill") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { nLength = strlen(psValue); if (nLength == 7 && psValue[0] == '#') { msSLDSetColorObject(psValue, &psStyle->color); } } } else if (psName && strcasecmp(psName, "fill-opacity") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { psStyle->color.alpha = (int)(atof(psValue)*255); } } psCssParam = psCssParam->psNext; } } if (psStroke) { psCssParam = CPLGetXMLNode(psStroke, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psStroke, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { psName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (psName && strcasecmp(psName, "stroke") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { nLength = strlen(psValue); if (nLength == 7 && psValue[0] == '#') { msSLDSetColorObject(psValue, &psStyle->outlinecolor); } } } else if (psName && strcasecmp(psName, "stroke-opacity") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { psStyle->outlinecolor.alpha = (int)(atof(psValue)*255); } } else if (psName && strcasecmp(psName, "stroke-width") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) psValue = psCssParam->psChild->psNext->pszValue; if (psValue) { psStyle->width = atof(psValue); } } psCssParam = psCssParam->psNext; } } } /* set the default color if color is not not already set */ if ((psStyle->color.red < 0 || psStyle->color.green == -1 || psStyle->color.blue == -1) && (psStyle->outlinecolor.red == -1 || psStyle->outlinecolor.green == -1 || psStyle->outlinecolor.blue == -1)) { psStyle->color.red = 128; psStyle->color.green = 128; psStyle->color.blue = 128; } /* Get the corresponding symbol id */ psStyle->symbol = msSLDGetMarkSymbol(map, pszSymbolName, bFilled); if (psStyle->symbol > 0 && psStyle->symbol < map->symbolset.numsymbols) psStyle->symbolname = msStrdup(map->symbolset.symbol[psStyle->symbol]->name); } else { psExternalGraphic = CPLGetXMLNode(psGraphic, "ExternalGraphic"); if (psExternalGraphic) msSLDParseExternalGraphic(psExternalGraphic, psStyle, map); } msFree(pszSymbolName); } psGap = CPLGetXMLNode(psRoot, "Gap"); if (psGap && psGap->psChild && psGap->psChild->pszValue) { psStyle->gap = atof(psGap->psChild->pszValue); } psInitialGap = CPLGetXMLNode(psRoot, "InitialGap"); if (psInitialGap && psInitialGap->psChild && psInitialGap->psChild->pszValue) { psStyle->initialgap = atof(psInitialGap->psChild->pszValue); } return MS_SUCCESS; } /************************************************************************/ /* msSLDGetMarkSymbol */ /* */ /* Get a Mark symbol using the name. Mark symbols can be */ /* square, circle, triangle, star, cross, x. */ /* If the symbol does not exsist add it to the symbol list. */ /************************************************************************/ int msSLDGetMarkSymbol(mapObj *map, char *pszSymbolName, int bFilled) { int nSymbolId = 0; symbolObj *psSymbol = NULL; if (!map || !pszSymbolName) return 0; if (strcasecmp(pszSymbolName, "square") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_SQUARE_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_SQUARE, MS_FALSE); } else if (strcasecmp(pszSymbolName, "circle") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_CIRCLE_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_CIRCLE, MS_FALSE); } else if (strcasecmp(pszSymbolName, "triangle") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_TRIANGLE_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_TRIANGLE, MS_FALSE); } else if (strcasecmp(pszSymbolName, "star") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_STAR_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_STAR, MS_FALSE); } else if (strcasecmp(pszSymbolName, "cross") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_CROSS_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_CROSS, MS_FALSE); } else if (strcasecmp(pszSymbolName, "x") == 0) { if (bFilled) nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_X_FILLED, MS_FALSE); else nSymbolId = msGetSymbolIndex(&map->symbolset, SLD_MARK_SYMBOL_X, MS_FALSE); } else { nSymbolId = msGetSymbolIndex(&map->symbolset, pszSymbolName, MS_FALSE); } if (nSymbolId <= 0) { if( (psSymbol = msGrowSymbolSet(&(map->symbolset))) == NULL) return 0; /* returns 0 for no symbol */ nSymbolId = map->symbolset.numsymbols; map->symbolset.numsymbols++; initSymbol(psSymbol); psSymbol->inmapfile = MS_TRUE; psSymbol->sizex = 1; psSymbol->sizey = 1; if (strcasecmp(pszSymbolName, "square") == 0) { if (bFilled) psSymbol->name = msStrdup(SLD_MARK_SYMBOL_SQUARE_FILLED); else psSymbol->name = msStrdup(SLD_MARK_SYMBOL_SQUARE); psSymbol->type = MS_SYMBOL_VECTOR; if (bFilled) psSymbol->filled = MS_TRUE; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; } else if (strcasecmp(pszSymbolName, "circle") == 0) { if (bFilled) psSymbol->name = msStrdup(SLD_MARK_SYMBOL_CIRCLE_FILLED); else psSymbol->name = msStrdup(SLD_MARK_SYMBOL_CIRCLE); psSymbol->type = MS_SYMBOL_ELLIPSE; if (bFilled) psSymbol->filled = MS_TRUE; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->sizex = 1; psSymbol->sizey = 1; psSymbol->numpoints++; } else if (strcasecmp(pszSymbolName, "triangle") == 0) { if (bFilled) psSymbol->name = msStrdup(SLD_MARK_SYMBOL_TRIANGLE_FILLED); else psSymbol->name = msStrdup(SLD_MARK_SYMBOL_TRIANGLE); psSymbol->type = MS_SYMBOL_VECTOR; if (bFilled) psSymbol->filled = MS_TRUE; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; } else if (strcasecmp(pszSymbolName, "star") == 0) { if (bFilled) psSymbol->name = msStrdup(SLD_MARK_SYMBOL_STAR_FILLED); else psSymbol->name = msStrdup(SLD_MARK_SYMBOL_STAR); psSymbol->type = MS_SYMBOL_VECTOR; if (bFilled) psSymbol->filled = MS_TRUE; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 0.375; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.35; psSymbol->points[psSymbol->numpoints].y = 0.375; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.65; psSymbol->points[psSymbol->numpoints].y = 0.375; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 0.375; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.75; psSymbol->points[psSymbol->numpoints].y = 0.625; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.875; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 0.75; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.125; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.25; psSymbol->points[psSymbol->numpoints].y = 0.625; psSymbol->numpoints++; } /* cross is like plus (+) since there is also X symbol ?? */ else if (strcasecmp(pszSymbolName, "cross") == 0) { /* NEVER FILL CROSS */ /* if (bFilled) */ /* psSymbol->name = msStrdup(SLD_MARK_SYMBOL_CROSS_FILLED); */ /* else */ psSymbol->name = msStrdup(SLD_MARK_SYMBOL_CROSS); psSymbol->type = MS_SYMBOL_VECTOR; /* if (bFilled) */ /* psSymbol->filled = MS_TRUE; */ psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0.5; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = -99; psSymbol->points[psSymbol->numpoints].y = -99; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 0.5; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 0.5; psSymbol->numpoints++; } else if (strcasecmp(pszSymbolName, "x") == 0) { /* NEVER FILL X */ /* if (bFilled) */ /* psSymbol->name = msStrdup(SLD_MARK_SYMBOL_X_FILLED); */ /* else */ psSymbol->name = msStrdup(SLD_MARK_SYMBOL_X); psSymbol->type = MS_SYMBOL_VECTOR; /* if (bFilled) */ /* psSymbol->filled = MS_TRUE; */ psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = -99; psSymbol->points[psSymbol->numpoints].y = -99; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 0; psSymbol->points[psSymbol->numpoints].y = 1; psSymbol->numpoints++; psSymbol->points[psSymbol->numpoints].x = 1; psSymbol->points[psSymbol->numpoints].y = 0; psSymbol->numpoints++; } } return nSymbolId; } static const unsigned char PNGsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; /* 89 50 4E 47 0D 0A 1A 0A hex */ /************************************************************************/ /* msSLDGetGraphicSymbol */ /* */ /* Create a symbol entry for an inmap pixmap symbol. Returns */ /* the symbol id. */ /************************************************************************/ int msSLDGetGraphicSymbol(mapObj *map, char *pszFileName, char* extGraphicName, int nGap) { int nSymbolId = 0; symbolObj *psSymbol = NULL; if (map && pszFileName) { if( (psSymbol = msGrowSymbolSet(&(map->symbolset))) == NULL) return 0; /* returns 0 for no symbol */ nSymbolId = map->symbolset.numsymbols; map->symbolset.numsymbols++; initSymbol(psSymbol); psSymbol->inmapfile = MS_TRUE; psSymbol->type = MS_SYMBOL_PIXMAP; psSymbol->name = msStrdup(extGraphicName); psSymbol->imagepath = msStrdup(pszFileName); psSymbol->full_pixmap_path = msStrdup(pszFileName); } return nSymbolId; } /************************************************************************/ /* msSLDParsePointSymbolizer */ /* */ /* Parse point symbolizer. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /************************************************************************/ int msSLDParsePointSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass) { int nClassId = 0; int iStyle = 0; if (!psRoot || !psLayer) return MS_FAILURE; if (bNewClass || psLayer->numclasses <= 0) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; } else nClassId = psLayer->numclasses-1; iStyle = psLayer->class[nClassId]->numstyles; msMaybeAllocateClassStyle(psLayer->class[nClassId], iStyle); msSLDParseGraphicFillOrStroke(psRoot, NULL, psLayer->class[nClassId]->styles[iStyle], psLayer->map); return MS_SUCCESS; } /************************************************************************/ /* msSLDParseExternalGraphic */ /* */ /* Parse extrenal graphic node : download the symbol referneced */ /* by the URL and create a PIXMAP inmap symbol. Only GIF and */ /* PNG are supported. */ /************************************************************************/ int msSLDParseExternalGraphic(CPLXMLNode *psExternalGraphic, styleObj *psStyle, mapObj *map) { char *pszFormat = NULL; CPLXMLNode *psURL=NULL, *psFormat=NULL, *psTmp=NULL; char *pszURL=NULL; if (!psExternalGraphic || !psStyle || !map) return MS_FAILURE; psFormat = CPLGetXMLNode(psExternalGraphic, "Format"); if (psFormat && psFormat->psChild && psFormat->psChild->pszValue) pszFormat = psFormat->psChild->pszValue; /* supports GIF and PNG and SVG */ if (pszFormat && (strcasecmp(pszFormat, "GIF") == 0 || strcasecmp(pszFormat, "image/gif") == 0 || strcasecmp(pszFormat, "PNG") == 0 || strcasecmp(pszFormat, "image/png") == 0 || strcasecmp(pszFormat, "image/svg+xml") == 0)) { /* */ psURL = CPLGetXMLNode(psExternalGraphic, "OnlineResource"); if (psURL && psURL->psChild) { psTmp = psURL->psChild; while (psTmp != NULL && psTmp->pszValue && strcasecmp(psTmp->pszValue, "xlink:href") != 0) { psTmp = psTmp->psNext; } if (psTmp && psTmp->psChild) { pszURL = (char*)psTmp->psChild->pszValue; /* validate the ExternalGraphic parameter */ if(msValidateParameter(pszURL, msLookupHashTable(&(map->web.validation), "sld_external_graphic"), NULL, NULL, NULL) != MS_SUCCESS) { msSetError(MS_WEBERR, "SLD ExternalGraphic OnlineResource value fails to validate against sld_external_graphic VALIDATION", "mapserv()"); return MS_FAILURE; } /*external symbols using http will be automaticallly downloaded. The file should be saved in a temporary directory (msAddImageSymbol) #2305*/ psStyle->symbol = msGetSymbolIndex(&map->symbolset, pszURL, MS_TRUE); if (psStyle->symbol > 0 && psStyle->symbol < map->symbolset.numsymbols) psStyle->symbolname = msStrdup(map->symbolset.symbol[psStyle->symbol]->name); /* set the color parameter if not set. Does not make sense */ /* for pixmap but mapserver needs it. */ if (psStyle->color.red == -1 || psStyle->color.green || psStyle->color.blue) { psStyle->color.red = 0; psStyle->color.green = 0; psStyle->color.blue = 0; } } } } return MS_SUCCESS; } /************************************************************************/ /* msSLDParseTextSymbolizer */ /* */ /* Parse text symbolizer. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* Four types of CssParameter are allowed, font-family, font-style,*/ /* fontweight,and font-size. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* The coordinates are given as two floating-point numbers in */ /* the AnchorPointX and AnchorPointY elements each with values */ /* between 0.0 and 1.0 inclusive. The bounding box of the label */ /* to be rendered is considered to be in a coorindate space */ /* from 0.0 (lowerleft corner) to 1.0 (upper-right corner), and */ /* the anchor position is specified as a point in this */ /* space. The default point is X=0, Y=0.5, which is at the */ /* middle height of the lefthand side of the label. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /************************************************************************/ int msSLDParseTextSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bOtherSymboliser) { int nStyleId=0, nClassId=0; if (!psRoot || !psLayer) return MS_FAILURE; if (!bOtherSymboliser) { if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; initClass(psLayer->class[psLayer->numclasses]); nClassId = psLayer->numclasses; psLayer->numclasses++; msMaybeAllocateClassStyle(psLayer->class[nClassId], 0); nStyleId = 0; } else { nClassId = psLayer->numclasses - 1; if (nClassId >= 0)/* should always be true */ nStyleId = psLayer->class[nClassId]->numstyles -1; } if (nStyleId >= 0 && nClassId >= 0) /* should always be true */ msSLDParseTextParams(psRoot, psLayer, psLayer->class[nClassId]); return MS_SUCCESS; } /************************************************************************/ /* msSLDParseRasterSymbolizer */ /* */ /* Supports the ColorMap parameter in a Raster Symbolizer. In */ /* the ColorMap, only color and quantity are used here. */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* SLD 1.1 */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /* */ /************************************************************************/ int msSLDParseRasterSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer) { CPLXMLNode *psColorMap = NULL, *psColorEntry = NULL, *psOpacity=NULL; char *pszColor=NULL, *pszQuantity=NULL; char *pszPreviousColor=NULL, *pszPreviousQuality=NULL; colorObj sColor; char szExpression[100]; int nClassId = 0; double dfOpacity = 1.0; char *pszLabel = NULL, *pszPreviousLabel = NULL; char *pch = NULL, *pchPrevious=NULL; CPLXMLNode *psNode=NULL, *psCategorize=NULL; char *pszTmp = NULL; int nValues=0, nThresholds=0; int i,nMaxValues= 100, nMaxThreshold=100; if (!psRoot || !psLayer) return MS_FAILURE; psOpacity = CPLGetXMLNode(psRoot, "Opacity"); if (psOpacity) { if (psOpacity->psChild && psOpacity->psChild->pszValue) dfOpacity = atof(psOpacity->psChild->pszValue); /* values in sld goes from 0.0 (for transparent) to 1.0 (for full opacity); */ if (dfOpacity >=0.0 && dfOpacity <=1.0) msSetLayerOpacity(psLayer,(int)(dfOpacity * 100)); else { msSetError(MS_WMSERR, "Invalid opacity value. Values should be between 0.0 and 1.0", "msSLDParseRasterSymbolizer()"); return MS_FAILURE; } } psColorMap = CPLGetXMLNode(psRoot, "ColorMap"); if (psColorMap) { psColorEntry = CPLGetXMLNode(psColorMap, "ColorMapEntry"); if (psColorEntry) { /*SLD 1.0*/ while (psColorEntry && psColorEntry->pszValue && strcasecmp(psColorEntry->pszValue, "ColorMapEntry") == 0) { pszColor = (char *)CPLGetXMLValue(psColorEntry, "color", NULL); pszQuantity = (char *)CPLGetXMLValue(psColorEntry, "quantity", NULL); pszLabel = (char *)CPLGetXMLValue(psColorEntry, "label", NULL); if (pszColor && pszQuantity) { if (pszPreviousColor && pszPreviousQuality) { if (strlen(pszPreviousColor) == 7 && pszPreviousColor[0] == '#' && strlen(pszColor) == 7 && pszColor[0] == '#') { sColor.red = msHexToInt(pszPreviousColor+1); sColor.green= msHexToInt(pszPreviousColor+3); sColor.blue = msHexToInt(pszPreviousColor+5); /* pszQuantity and pszPreviousQuality may be integer or float */ pchPrevious=strchr(pszPreviousQuality,'.'); pch=strchr(pszQuantity,'.'); if (pchPrevious==NULL && pch==NULL) { snprintf(szExpression, sizeof(szExpression), "([pixel] >= %d AND [pixel] < %d)", atoi(pszPreviousQuality), atoi(pszQuantity)); } else if (pchPrevious != NULL && pch==NULL) { snprintf(szExpression, sizeof(szExpression), "([pixel] >= %f AND [pixel] < %d)", atof(pszPreviousQuality), atoi(pszQuantity)); } else if (pchPrevious == NULL && pch != NULL) { snprintf(szExpression, sizeof(szExpression), "([pixel] >= %d AND [pixel] < %f)", atoi(pszPreviousQuality), atof(pszQuantity)); } else { snprintf(szExpression, sizeof(szExpression), "([pixel] >= %f AND [pixel] < %f)", atof(pszPreviousQuality), atof(pszQuantity)); } if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; else { initClass(psLayer->class[psLayer->numclasses]); psLayer->numclasses++; nClassId = psLayer->numclasses-1; /*set the class name using the label. If label not defined set it with the quantity*/ if (pszPreviousLabel) psLayer->class[nClassId]->name = msStrdup(pszPreviousLabel); else psLayer->class[nClassId]->name = msStrdup(pszPreviousQuality); msMaybeAllocateClassStyle(psLayer->class[nClassId], 0); psLayer->class[nClassId]->styles[0]->color.red = sColor.red; psLayer->class[nClassId]->styles[0]->color.green = sColor.green; psLayer->class[nClassId]->styles[0]->color.blue = sColor.blue; if (psLayer->classitem && strcasecmp(psLayer->classitem, "[pixel]") != 0) free(psLayer->classitem); psLayer->classitem = msStrdup("[pixel]"); msLoadExpressionString(&psLayer->class[nClassId]->expression, szExpression); } } else { msSetError(MS_WMSERR, "Invalid ColorMap Entry.", "msSLDParseRasterSymbolizer()"); return MS_FAILURE; } } pszPreviousColor = pszColor; pszPreviousQuality = pszQuantity; pszPreviousLabel = pszLabel; } psColorEntry = psColorEntry->psNext; } /* do the last Color Map Entry */ if (pszColor && pszQuantity) { if (strlen(pszColor) == 7 && pszColor[0] == '#') { sColor.red = msHexToInt(pszColor+1); sColor.green= msHexToInt(pszColor+3); sColor.blue = msHexToInt(pszColor+5); /* pszQuantity may be integer or float */ pch=strchr(pszQuantity,'.'); if (pch==NULL) { snprintf(szExpression, sizeof(szExpression), "([pixel] = %d)", atoi(pszQuantity)); } else { snprintf(szExpression, sizeof(szExpression), "([pixel] = %f)", atof(pszQuantity)); } if (msGrowLayerClasses(psLayer) == NULL) return MS_FAILURE; else { initClass(psLayer->class[psLayer->numclasses]); psLayer->numclasses++; nClassId = psLayer->numclasses-1; msMaybeAllocateClassStyle(psLayer->class[nClassId], 0); if (pszLabel) psLayer->class[nClassId]->name = msStrdup(pszLabel); else psLayer->class[nClassId]->name = msStrdup(pszQuantity); psLayer->class[nClassId]->numstyles = 1; psLayer->class[nClassId]->styles[0]->color.red = sColor.red; psLayer->class[nClassId]->styles[0]->color.green = sColor.green; psLayer->class[nClassId]->styles[0]->color.blue = sColor.blue; if (psLayer->classitem && strcasecmp(psLayer->classitem, "[pixel]") != 0) free(psLayer->classitem); psLayer->classitem = msStrdup("[pixel]"); msLoadExpressionString(&psLayer->class[nClassId]->expression, szExpression); } } } } else if ((psCategorize = CPLGetXMLNode(psColorMap, "Categorize"))) { char** papszValues = (char **)malloc(sizeof(char*)*nMaxValues); char** papszThresholds = (char **)malloc(sizeof(char*)*nMaxThreshold); psNode = CPLGetXMLNode(psCategorize, "Value"); while (psNode && psNode->pszValue && psNode->psChild && psNode->psChild->pszValue) { if (strcasecmp(psNode->pszValue, "Value") == 0) { papszValues[nValues] = psNode->psChild->pszValue; nValues++; if (nValues == nMaxValues) { nMaxValues +=100; papszValues = (char **)realloc(papszValues, sizeof(char*)*nMaxValues); } } else if (strcasecmp(psNode->pszValue, "Threshold") == 0) { papszThresholds[nThresholds] = psNode->psChild->pszValue; nThresholds++; if (nValues == nMaxThreshold) { nMaxThreshold += 100; papszThresholds = (char **)realloc(papszThresholds, sizeof(char*)*nMaxThreshold); } } psNode = psNode->psNext; } if (nThresholds > 0 && nValues == nThresholds+1) { /*free existing classes*/ for(i=0; inumclasses; i++) { if (psLayer->class[i] != NULL) { psLayer->class[i]->layer=NULL; if ( freeClass(psLayer->class[i]) == MS_SUCCESS ) { msFree(psLayer->class[i]); psLayer->class[i]=NULL; } } } psLayer->numclasses=0; for (i=0; i= %f AND [pixel] < %f)", atof(papszThresholds[i-1]), atof(papszThresholds[i])); else snprintf(szExpression, sizeof(szExpression), "([pixel] >= %d AND [pixel] < %d)", atoi(papszThresholds[i-1]), atoi(papszThresholds[i])); } else { if (strchr(papszThresholds[i-1],'.')) snprintf(szExpression, sizeof(szExpression), "([pixel] >= %f)", atof(papszThresholds[i-1])); else snprintf(szExpression, sizeof(szExpression), "([pixel] >= %d)", atoi(papszThresholds[i-1])); } if (msGrowLayerClasses(psLayer)) { initClass(psLayer->class[psLayer->numclasses]); psLayer->numclasses++; nClassId = psLayer->numclasses-1; msMaybeAllocateClassStyle(psLayer->class[nClassId], 0); psLayer->class[nClassId]->numstyles = 1; psLayer->class[nClassId]->styles[0]->color.red = sColor.red; psLayer->class[nClassId]->styles[0]->color.green = sColor.green; psLayer->class[nClassId]->styles[0]->color.blue = sColor.blue; if (psLayer->classitem && strcasecmp(psLayer->classitem, "[pixel]") != 0) free(psLayer->classitem); psLayer->classitem = msStrdup("[pixel]"); msLoadExpressionString(&psLayer->class[nClassId]->expression, szExpression); } } } } free(papszValues); free(papszThresholds); } else { msSetError(MS_WMSERR, "Invalid SLD document. msSLDParseRaster", ""); return MS_FAILURE; } } return MS_SUCCESS; } /************************************************************************/ /* msSLDParseTextParams */ /* */ /* Parse text paramaters like font, placement and color. */ /************************************************************************/ int msSLDParseTextParams(CPLXMLNode *psRoot, layerObj *psLayer, classObj *psClass) { char szFontName[100]; double dfFontSize = 10; CPLXMLNode *psLabel=NULL, *psFont=NULL; CPLXMLNode *psCssParam = NULL; char *pszName=NULL, *pszFontFamily=NULL, *pszFontStyle=NULL; char *pszFontWeight=NULL; CPLXMLNode *psLabelPlacement=NULL, *psPointPlacement=NULL, *psLinePlacement=NULL; CPLXMLNode *psFill = NULL, *psPropertyName=NULL, *psHalo=NULL, *psHaloRadius=NULL, *psHaloFill=NULL; int nLength = 0; char *pszColor = NULL; /* char *pszItem = NULL; */ CPLXMLNode *psTmpNode = NULL; char *pszClassText = NULL; char szTmp[100]; labelObj *psLabelObj = NULL; szFontName[0]='\0'; if (!psRoot || !psClass || !psLayer) return MS_FAILURE; if(psClass->numlabels == 0) { if(msGrowClassLabels(psClass) == NULL) return(MS_FAILURE); initLabel(psClass->labels[0]); psClass->numlabels++; } psLabelObj = psClass->labels[0]; /*set the angle by default to auto. the angle can be modified Label Placement #2806*/ psLabelObj->anglemode = MS_AUTO; /* label */ /* support literal expression and propertyname - - Bug 1857 */ psLabel = CPLGetXMLNode(psRoot, "Label"); if (psLabel ) { psTmpNode = psLabel->psChild; psPropertyName = CPLGetXMLNode(psLabel, "PropertyName"); if (psPropertyName) { while (psTmpNode) { /* open bracket to get valid expression */ if (pszClassText == NULL) pszClassText = msStringConcatenate(pszClassText, "("); if (psTmpNode->eType == CXT_Text && psTmpNode->pszValue) { pszClassText = msStringConcatenate(pszClassText, psTmpNode->pszValue); } else if (psTmpNode->eType == CXT_Element && strcasecmp(psTmpNode->pszValue,"PropertyName") ==0 && CPLGetXMLValue(psTmpNode, NULL, NULL)) { snprintf(szTmp, sizeof(szTmp), "\"[%s]\"", CPLGetXMLValue(psTmpNode, NULL, NULL)); pszClassText = msStringConcatenate(pszClassText, szTmp); } psTmpNode = psTmpNode->psNext; } /* close bracket to get valid expression */ if (pszClassText != NULL) pszClassText = msStringConcatenate(pszClassText, ")"); } else { /* supports - */ if (psLabel->psChild && psLabel->psChild->pszValue) { pszClassText = msStringConcatenate(pszClassText, "(\"["); pszClassText = msStringConcatenate(pszClassText, psLabel->psChild->pszValue); pszClassText = msStringConcatenate(pszClassText, "]\")"); } } if (pszClassText) { /* pszItem) */ msLoadExpressionString(&psClass->text, pszClassText); free(pszClassText); /* font */ psFont = CPLGetXMLNode(psRoot, "Font"); if (psFont) { psCssParam = CPLGetXMLNode(psFont, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psFont, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { pszName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (pszName) { if (strcasecmp(pszName, "font-family") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszFontFamily = psCssParam->psChild->psNext->pszValue; } /* normal, italic, oblique */ else if (strcasecmp(pszName, "font-style") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszFontStyle = psCssParam->psChild->psNext->pszValue; } /* normal or bold */ else if (strcasecmp(pszName, "font-weight") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszFontWeight = psCssParam->psChild->psNext->pszValue; } /* default is 10 pix */ else if (strcasecmp(pszName, "font-size") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) dfFontSize = atof(psCssParam->psChild->psNext->pszValue); if (dfFontSize <=0.0) dfFontSize = 10.0; } } psCssParam = psCssParam->psNext; } } /* -------------------------------------------------------------------- */ /* parse the label placement. */ /* -------------------------------------------------------------------- */ psLabelPlacement = CPLGetXMLNode(psRoot, "LabelPlacement"); if (psLabelPlacement) { psPointPlacement = CPLGetXMLNode(psLabelPlacement, "PointPlacement"); psLinePlacement = CPLGetXMLNode(psLabelPlacement, "LinePlacement"); if (psPointPlacement) ParseTextPointPlacement(psPointPlacement, psClass); if (psLinePlacement) ParseTextLinePlacement(psLinePlacement, psClass); } /* -------------------------------------------------------------------- */ /* build the font name using the font font-family, font-style */ /* and font-weight. The name building uses a - between these */ /* parameters and the resulting name is compared to the list of */ /* available fonts. If the name exists, it will be used else we */ /* go to the bitmap fonts. */ /* -------------------------------------------------------------------- */ if (pszFontFamily) { snprintf(szFontName, sizeof(szFontName), "%s", pszFontFamily); if (pszFontWeight && strcasecmp(pszFontWeight, "normal") != 0) { strlcat(szFontName, "-", sizeof(szFontName)); strlcat(szFontName, pszFontWeight, sizeof(szFontName)); } if (pszFontStyle && strcasecmp(pszFontStyle, "normal") != 0) { strlcat(szFontName, "-", sizeof(szFontName)); strlcat(szFontName, pszFontStyle, sizeof(szFontName)); } if ((msLookupHashTable(&(psLayer->map->fontset.fonts), szFontName) !=NULL)) { psLabelObj->font = msStrdup(szFontName); } } psLabelObj->size = dfFontSize; /* -------------------------------------------------------------------- */ /* parse the halo parameter. */ /* -------------------------------------------------------------------- */ psHalo = CPLGetXMLNode(psRoot, "Halo"); if (psHalo) { psHaloRadius = CPLGetXMLNode(psHalo, "Radius"); if (psHaloRadius && psHaloRadius->psChild && psHaloRadius->psChild->pszValue) psLabelObj->outlinewidth = atoi(psHaloRadius->psChild->pszValue); psHaloFill = CPLGetXMLNode(psHalo, "Fill"); if (psHaloFill) { psCssParam = CPLGetXMLNode(psHaloFill, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psHaloFill, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { pszName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (pszName) { if (strcasecmp(pszName, "fill") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszColor = psCssParam->psChild->psNext->pszValue; if (pszColor) { nLength = strlen(pszColor); /* expecting hexadecimal ex : #aaaaff */ if (nLength == 7 && pszColor[0] == '#') { psLabelObj->outlinecolor.red = msHexToInt(pszColor+1); psLabelObj->outlinecolor.green = msHexToInt(pszColor+3); psLabelObj->outlinecolor.blue = msHexToInt(pszColor+5); } } } } psCssParam = psCssParam->psNext; } } } /* -------------------------------------------------------------------- */ /* Parse the color */ /* -------------------------------------------------------------------- */ psFill = CPLGetXMLNode(psRoot, "Fill"); if (psFill) { psCssParam = CPLGetXMLNode(psFill, "CssParameter"); /*sld 1.1 used SvgParameter*/ if (psCssParam == NULL) psCssParam = CPLGetXMLNode(psFill, "SvgParameter"); while (psCssParam && psCssParam->pszValue && (strcasecmp(psCssParam->pszValue, "CssParameter") == 0 || strcasecmp(psCssParam->pszValue, "SvgParameter") == 0)) { pszName = (char*)CPLGetXMLValue(psCssParam, "name", NULL); if (pszName) { if (strcasecmp(pszName, "fill") == 0) { if(psCssParam->psChild && psCssParam->psChild->psNext && psCssParam->psChild->psNext->pszValue) pszColor = psCssParam->psChild->psNext->pszValue; if (pszColor) { nLength = strlen(pszColor); /* expecting hexadecimal ex : #aaaaff */ if (nLength == 7 && pszColor[0] == '#') { psLabelObj->color.red = msHexToInt(pszColor+1); psLabelObj->color.green = msHexToInt(pszColor+3); psLabelObj->color.blue = msHexToInt(pszColor+5); } } } } psCssParam = psCssParam->psNext; } } }/* labelitem */ } return MS_SUCCESS; } /************************************************************************/ /* ParseTextPointPlacement */ /* */ /* point placement node for the text symbolizer. */ /************************************************************************/ int ParseTextPointPlacement(CPLXMLNode *psRoot, classObj *psClass) { CPLXMLNode *psAnchor, *psAnchorX, *psAnchorY; double dfAnchorX=0, dfAnchorY=0; CPLXMLNode *psDisplacement, *psDisplacementX, *psDisplacementY; CPLXMLNode *psRotation=NULL, *psPropertyName=NULL; char szTmp[100]; labelObj *psLabelObj = NULL; if (!psRoot || !psClass) return MS_FAILURE; if(psClass->numlabels == 0) { if(msGrowClassLabels(psClass) == NULL) return(MS_FAILURE); initLabel(psClass->labels[0]); psClass->numlabels++; } psLabelObj = psClass->labels[0]; /* init the label with the default position */ psLabelObj->position = MS_CL; /* -------------------------------------------------------------------- */ /* parse anchor point. see function msSLDParseTextSymbolizer */ /* for documentation. */ /* -------------------------------------------------------------------- */ psAnchor = CPLGetXMLNode(psRoot, "AnchorPoint"); if (psAnchor) { psAnchorX = CPLGetXMLNode(psAnchor, "AnchorPointX"); psAnchorY = CPLGetXMLNode(psAnchor, "AnchorPointY"); /* psCssParam->psChild->psNext->pszValue) */ if (psAnchorX && psAnchorX->psChild && psAnchorX->psChild->pszValue && psAnchorY && psAnchorY->psChild && psAnchorY->psChild->pszValue) { dfAnchorX = atof(psAnchorX->psChild->pszValue); dfAnchorY = atof(psAnchorY->psChild->pszValue); if ((dfAnchorX == 0 || dfAnchorX == 0.5 || dfAnchorX == 1) && (dfAnchorY == 0 || dfAnchorY == 0.5 || dfAnchorY == 1)) { if (dfAnchorX == 0 && dfAnchorY == 0) psLabelObj->position = MS_LL; if (dfAnchorX == 0 && dfAnchorY == 0.5) psLabelObj->position = MS_CL; if (dfAnchorX == 0 && dfAnchorY == 1) psLabelObj->position = MS_UL; if (dfAnchorX == 0.5 && dfAnchorY == 0) psLabelObj->position = MS_LC; if (dfAnchorX == 0.5 && dfAnchorY == 0.5) psLabelObj->position = MS_CC; if (dfAnchorX == 0.5 && dfAnchorY == 1) psLabelObj->position = MS_UC; if (dfAnchorX == 1 && dfAnchorY == 0) psLabelObj->position = MS_LR; if (dfAnchorX == 1 && dfAnchorY == 0.5) psLabelObj->position = MS_CR; if (dfAnchorX == 1 && dfAnchorY == 1) psLabelObj->position = MS_UR; } } } /* -------------------------------------------------------------------- */ /* Parse displacement */ /* -------------------------------------------------------------------- */ psDisplacement = CPLGetXMLNode(psRoot, "Displacement"); if (psDisplacement) { psDisplacementX = CPLGetXMLNode(psDisplacement, "DisplacementX"); psDisplacementY = CPLGetXMLNode(psDisplacement, "DisplacementY"); /* psCssParam->psChild->psNext->pszValue) */ if (psDisplacementX && psDisplacementX->psChild && psDisplacementX->psChild->pszValue && psDisplacementY && psDisplacementY->psChild && psDisplacementY->psChild->pszValue) { psLabelObj->offsetx = atoi(psDisplacementX->psChild->pszValue); psLabelObj->offsety = atoi(psDisplacementY->psChild->pszValue); } } /* -------------------------------------------------------------------- */ /* parse rotation. */ /* -------------------------------------------------------------------- */ psRotation = CPLGetXMLNode(psRoot, "Rotation"); if (psRotation) { psPropertyName = CPLGetXMLNode(psRotation, "PropertyName"); if (psPropertyName) { snprintf(szTmp, sizeof(szTmp), "%s", CPLGetXMLValue(psPropertyName, NULL, NULL)); psLabelObj->bindings[MS_LABEL_BINDING_ANGLE].item = msStrdup(szTmp); psLabelObj->numbindings++; } else { if (psRotation->psChild && psRotation->psChild->pszValue) psLabelObj->angle = atof(psRotation->psChild->pszValue); } } return MS_SUCCESS; } /************************************************************************/ /* ParseTextLinePlacement */ /* */ /* Lineplacement node fro the text symbolizer. */ /************************************************************************/ int ParseTextLinePlacement(CPLXMLNode *psRoot, classObj *psClass) { CPLXMLNode *psOffset = NULL, *psAligned=NULL; labelObj *psLabelObj = NULL; if (!psRoot || !psClass) return MS_FAILURE; if(psClass->numlabels == 0) { if(msGrowClassLabels(psClass) == NULL) return(MS_FAILURE); initLabel(psClass->labels[0]); psClass->numlabels++; } psLabelObj = psClass->labels[0]; /*if there is a line placement, we will assume that the best setting for mapserver would be for the text to follow the line #2806*/ psLabelObj->anglemode = MS_FOLLOW; /*sld 1.1.0 has a parameter IsAligned. default value is true*/ psAligned = CPLGetXMLNode(psRoot, "IsAligned"); if (psAligned && psAligned->psChild && psAligned->psChild->pszValue && strcasecmp(psAligned->psChild->pszValue, "false") == 0) { psLabelObj->anglemode = MS_NONE; } psOffset = CPLGetXMLNode(psRoot, "PerpendicularOffset"); if (psOffset && psOffset->psChild && psOffset->psChild->pszValue) { psLabelObj->offsetx = atoi(psOffset->psChild->pszValue); psLabelObj->offsety = MS_LABEL_PERPENDICULAR_OFFSET; /*if there is a PerpendicularOffset, we will assume that the best setting for mapserver would be to use angle=0 and the the offset #2806*/ /* since sld 1.1.0 introduces the IsAligned parameter, only set the angles if the parameter is not set*/ if (!psAligned) { psLabelObj->anglemode = MS_NONE; psLabelObj->offsety = psLabelObj->offsetx; } } return MS_SUCCESS; } /************************************************************************/ /* void msSLDSetColorObject(char *psHexColor, colorObj */ /* *psColor) */ /* */ /* Utility function to exctract rgb values from an hexadecimal */ /* color string (format is : #aaff08) and set it in the color */ /* object. */ /************************************************************************/ int msSLDSetColorObject(char *psHexColor, colorObj *psColor) { if (psHexColor && psColor && strlen(psHexColor)== 7 && psHexColor[0] == '#') { psColor->red = msHexToInt(psHexColor+1); psColor->green = msHexToInt(psHexColor+3); psColor->blue= msHexToInt(psHexColor+5); } return MS_SUCCESS; } #endif /* -------------------------------------------------------------------- */ /* client sld support functions */ /* -------------------------------------------------------------------- */ /************************************************************************/ /* msSLDGenerateSLD(mapObj *map, int iLayer) */ /* */ /* Return an SLD document for all layers that are on or */ /* default. The second argument should be set to -1 to genarte */ /* on all layers. Or set to the layer index to generate an SLD */ /* for a specific layer. */ /* */ /* The caller should free the returned string. */ /************************************************************************/ char *msSLDGenerateSLD(mapObj *map, int iLayer, const char *pszVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) #ifdef USE_OGR char szTmp[500]; int i = 0; char *pszTmp = NULL; char *pszSLD = NULL; char *schemalocation = NULL; int sld_version = OWS_VERSION_NOTSET; sld_version = msOWSParseVersionString(pszVersion); if (sld_version == OWS_VERSION_NOTSET || (sld_version!= OWS_1_0_0 && sld_version!= OWS_1_1_0)) sld_version = OWS_1_0_0; if (map) { schemalocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); if (sld_version == OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "\n",schemalocation ); else snprintf(szTmp, sizeof(szTmp), "\n", schemalocation); free(schemalocation); pszSLD = msStringConcatenate(pszSLD, szTmp); if (iLayer < 0 || iLayer > map->numlayers -1) { for (i=0; inumlayers; i++) { pszTmp = msSLDGenerateSLDLayer(GET_LAYER(map, i), sld_version); if (pszTmp) { pszSLD= msStringConcatenate(pszSLD, pszTmp); free(pszTmp); } } } else { pszTmp = msSLDGenerateSLDLayer(GET_LAYER(map, iLayer), sld_version); if (pszTmp) { pszSLD = msStringConcatenate(pszSLD, pszTmp); free(pszTmp); } } snprintf(szTmp, sizeof(szTmp), "%s", "\n"); pszSLD = msStringConcatenate(pszSLD, szTmp); } return pszSLD; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msSLDGenerateSLD()"); return NULL; #endif /* USE_OGR */ #else msSetError(MS_MISCERR, "OWS support is not available.", "msSLDGenerateSLDLayer()"); return NULL; #endif } /************************************************************************/ /* msSLDGetGraphicSLD */ /* */ /* Get an SLD for a style containg a symbol (Mark or external). */ /************************************************************************/ char *msSLDGetGraphicSLD(styleObj *psStyle, layerObj *psLayer, int bNeedMarkSybol, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char *pszSLD = NULL; int nSymbol = -1; symbolObj *psSymbol = NULL; char szTmp[512]; char szFormat[4]; int i = 0, nLength = 0; int bFillColor = 0, bColorAvailable=0; int bGenerateDefaultSymbol = 0; char *pszSymbolName= NULL; char sNameSpace[10]; char sCssParam[30]; sCssParam[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sCssParam, "se:SvgParameter"); else strcpy(sCssParam, "CssParameter"); sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); if (psStyle && psLayer && psLayer->map) { nSymbol = -1; if (psStyle->symbol > 0) nSymbol = psStyle->symbol; else if (psStyle->symbolname) nSymbol = msGetSymbolIndex(&psLayer->map->symbolset, psStyle->symbolname, MS_FALSE); bGenerateDefaultSymbol = 0; if (bNeedMarkSybol && (nSymbol <=0 || nSymbol >= psLayer->map->symbolset.numsymbols)) bGenerateDefaultSymbol = 1; if (nSymbol > 0 && nSymbol < psLayer->map->symbolset.numsymbols) { psSymbol = psLayer->map->symbolset.symbol[nSymbol]; if (psSymbol->type == MS_SYMBOL_VECTOR || psSymbol->type == MS_SYMBOL_ELLIPSE) { /* Mark symbol */ if (psSymbol->name) { if (strcasecmp(psSymbol->name, "square") == 0 || strcasecmp(psSymbol->name, "circle") == 0 || strcasecmp(psSymbol->name, "triangle") == 0 || strcasecmp(psSymbol->name, "star") == 0 || strcasecmp(psSymbol->name, "cross") == 0 || strcasecmp(psSymbol->name, "x") == 0) pszSymbolName = msStrdup(psSymbol->name); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_square", 22) == 0) pszSymbolName = msStrdup("square"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_triangle", 24) == 0) pszSymbolName = msStrdup("triangle"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_circle", 22) == 0) pszSymbolName = msStrdup("circle"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_star", 20) == 0) pszSymbolName = msStrdup("star"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_cross", 21) == 0) pszSymbolName = msStrdup("cross"); else if (strncasecmp(psSymbol->name, "sld_mark_symbol_x", 17) == 0) pszSymbolName = msStrdup("X"); if (pszSymbolName) { colorObj sTmpColor; snprintf(szTmp, sizeof(szTmp), "<%sGraphic>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sMark>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sWellKnownName>%s\n", sNameSpace, pszSymbolName, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psStyle->color.red != -1 && psStyle->color.green != -1 && psStyle->color.blue != -1) { sTmpColor.red = psStyle->color.red; sTmpColor.green = psStyle->color.green; sTmpColor.blue = psStyle->color.blue; bFillColor =1; } else if (psStyle->outlinecolor.red != -1 && psStyle->outlinecolor.green != -1 && psStyle->outlinecolor.blue != -1) { sTmpColor.red = psStyle->outlinecolor.red; sTmpColor.green = psStyle->outlinecolor.green; sTmpColor.blue = psStyle->outlinecolor.blue; bFillColor = 0; } else { sTmpColor.red = 128; sTmpColor.green = 128; sTmpColor.blue = 128; bFillColor =1; } if (psLayer->type == MS_LAYER_POINT) { if (psSymbol->filled || bFillColor) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%02x%02x%02x\n", sCssParam,sTmpColor.red, sTmpColor.green, sTmpColor.blue, sCssParam); } else { snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke\">#%02x%02x%02x\n", sCssParam, sTmpColor.red, sTmpColor.green, sTmpColor.blue, sCssParam); } } else { if (bFillColor) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%02x%02x%02x\n", sCssParam, sTmpColor.red, sTmpColor.green, sTmpColor.blue, sCssParam); } else { snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke\">#%02x%02x%02x\n", sCssParam, sTmpColor.red, sTmpColor.green, sTmpColor.blue, sCssParam); } } pszSLD = msStringConcatenate(pszSLD, szTmp); if ((psLayer->type == MS_LAYER_POINT && psSymbol->filled) || bFillColor) snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); else snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psStyle->size > 0) { snprintf(szTmp, sizeof(szTmp), "<%sSize>%g\n", sNameSpace, psStyle->size, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (pszSymbolName) free(pszSymbolName); } } else bGenerateDefaultSymbol =1; } else if (psSymbol->type == MS_SYMBOL_PIXMAP || psSymbol->type == MS_SYMBOL_SVG) { if (psSymbol->name) { const char *pszURL = msLookupHashTable(&(psLayer->metadata), "WMS_SLD_SYMBOL_URL"); if (!pszURL) pszURL = msLookupHashTable(&(psLayer->map->web.metadata), "WMS_SLD_SYMBOL_URL"); if (pszURL) { snprintf(szTmp, sizeof(szTmp), "<%sGraphic>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sExternalGraphic>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sOnlineResource xmlns:xlink=\"http://www.w3.org/1999/xlink\" xlink:type=\"simple\" xlink:href=\"%s%s\"/>\n", sNameSpace, pszURL,psSymbol->imagepath); pszSLD = msStringConcatenate(pszSLD, szTmp); /* TODO : extract format from symbol */ szFormat[0] = '\0'; nLength = strlen(psSymbol->imagepath); if (nLength > 3) { for (i=0; i<=2; i++) szFormat[2-i] = psSymbol->imagepath[nLength-1-i]; szFormat[3] = '\0'; } if (strlen(szFormat) > 0 && ((strcasecmp (szFormat, "GIF") == 0) || (strcasecmp (szFormat, "PNG") == 0))) { if (strcasecmp (szFormat, "GIF") == 0) snprintf(szTmp, sizeof(szTmp), "<%sFormat>image/gif\n", sNameSpace, sNameSpace); else snprintf(szTmp, sizeof(szTmp), "<%sFormat>image/png\n", sNameSpace, sNameSpace); } else snprintf(szTmp, sizeof(szTmp), "<%sFormat>%s\n", sNameSpace, (psSymbol->type ==MS_SYMBOL_SVG)?"image/svg+xml":"image/gif",sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psStyle->size > 0) snprintf(szTmp, sizeof(szTmp), "<%sSize>%g\n", sNameSpace, psStyle->size, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } } } } if (bGenerateDefaultSymbol) { /* genrate a default square symbol */ snprintf(szTmp, sizeof(szTmp), "<%sGraphic>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sMark>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sWellKnownName>%s\n", sNameSpace, "square", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); bColorAvailable = 0; if (psStyle->color.red != -1 && psStyle->color.green != -1 && psStyle->color.blue != -1) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%02x%02x%02x\n", sCssParam, psStyle->color.red, psStyle->color.green, psStyle->color.blue, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); bColorAvailable = 1; } if (psStyle->outlinecolor.red != -1 && psStyle->outlinecolor.green != -1 && psStyle->outlinecolor.blue != -1) { snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"Stroke\">#%02x%02x%02x\n", sCssParam, psStyle->outlinecolor.red, psStyle->outlinecolor.green, psStyle->outlinecolor.blue, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); bColorAvailable = 1; } if (!bColorAvailable) { /* default color */ snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">%s\n", sCssParam, "#808080", sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psStyle->size > 0) snprintf(szTmp, sizeof(szTmp), "<%sSize>%g\n", sNameSpace, psStyle->size, sNameSpace); else snprintf(szTmp, sizeof(szTmp), "<%sSize>%d\n", sNameSpace,1,sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } } return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGenerateLineSLD */ /* */ /* Generate SLD for a Line layer. */ /************************************************************************/ char *msSLDGenerateLineSLD(styleObj *psStyle, layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char *pszSLD = NULL; char szTmp[100]; char szHexColor[7]; int nSymbol = -1; int i = 0; double dfSize = 1.0; char *pszDashArray = NULL; char *pszGraphicSLD = NULL; char sCssParam[30]; char sNameSpace[10]; if ( msCheckParentPointer(psLayer->map,"map")==MS_FAILURE ) return NULL; sCssParam[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy( sCssParam, "se:SvgParameter"); else strcpy( sCssParam, "CssParameter"); sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); snprintf(szTmp, sizeof(szTmp), "<%sLineSymbolizer>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszGraphicSLD = msSLDGetGraphicSLD(psStyle, psLayer, 0, nVersion); if (pszGraphicSLD) { snprintf(szTmp, sizeof(szTmp), "<%sGraphicStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszSLD = msStringConcatenate(pszSLD, pszGraphicSLD); if(nVersion >= OWS_1_1_0) { if(psStyle->gap > 0) { snprintf(szTmp, sizeof(szTmp), "<%sGap>%.2f\n", sNameSpace,psStyle->gap,sNameSpace); } if(psStyle->initialgap > 0) { snprintf(szTmp, sizeof(szTmp), "<%sInitialGap>%.2f\n", sNameSpace,psStyle->initialgap,sNameSpace); } } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); free(pszGraphicSLD); pszGraphicSLD = NULL; } if (psStyle->color.red != -1 && psStyle->color.green != -1 && psStyle->color.blue != -1) sprintf(szHexColor,"%02x%02x%02x",psStyle->color.red, psStyle->color.green,psStyle->color.blue); else sprintf(szHexColor,"%02x%02x%02x",psStyle->outlinecolor.red, psStyle->outlinecolor.green,psStyle->outlinecolor.blue); snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke\">#%s\n", sCssParam, szHexColor, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); if(psStyle->color.alpha != 255 && psStyle->color.alpha!=-1) { snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke-opacity\">%.2f\n", sCssParam, (float)psStyle->color.alpha/255.0, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } nSymbol = -1; if (psStyle->symbol >= 0) nSymbol = psStyle->symbol; else if (psStyle->symbolname) nSymbol = msGetSymbolIndex(&psLayer->map->symbolset, psStyle->symbolname, MS_FALSE); if (nSymbol <0) dfSize = 1.0; else { if (psStyle->size > 0) dfSize = psStyle->size; else if (psStyle->width > 0) dfSize = psStyle->width; else dfSize = 1; } snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke-width\">%.2f\n", sCssParam, dfSize, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); /* -------------------------------------------------------------------- */ /* dash array */ /* -------------------------------------------------------------------- */ if (psStyle->patternlength > 0) { for (i=0; ipatternlength; i++) { snprintf(szTmp, sizeof(szTmp), "%.2f ", psStyle->pattern[i]); pszDashArray = msStringConcatenate(pszDashArray, szTmp); } snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke-dasharray\">%s\n", sCssParam, pszDashArray, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); msFree(pszDashArray); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGeneratePolygonSLD */ /* */ /* Generate SLD for a Polygon layer. */ /************************************************************************/ char *msSLDGeneratePolygonSLD(styleObj *psStyle, layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char szTmp[100]; char *pszSLD = NULL; char szHexColor[7]; char *pszGraphicSLD = NULL; double dfSize; char sCssParam[30]; char sNameSpace[10]; sCssParam[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sCssParam, "se:SvgParameter"); else strcpy(sCssParam, "CssParameter"); sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); snprintf(szTmp, sizeof(szTmp), "<%sPolygonSymbolizer>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* fill */ if (psStyle->color.red != -1 && psStyle->color.green != -1 && psStyle->color.blue != -1) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszGraphicSLD = msSLDGetGraphicSLD(psStyle, psLayer, 0, nVersion); if (pszGraphicSLD) { snprintf(szTmp, sizeof(szTmp), "<%sGraphicFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszSLD = msStringConcatenate(pszSLD, pszGraphicSLD); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); free(pszGraphicSLD); pszGraphicSLD = NULL; } sprintf(szHexColor,"%02x%02x%02x",psStyle->color.red, psStyle->color.green,psStyle->color.blue); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%s\n", sCssParam, szHexColor, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); if(psStyle->color.alpha != 255 && psStyle->color.alpha!=-1) { snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill-opacity\">%.2f\n", sCssParam, (float)psStyle->color.alpha/255, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } /* stroke */ if (psStyle->outlinecolor.red != -1 && psStyle->outlinecolor.green != -1 && psStyle->outlinecolor.blue != -1) { snprintf(szTmp, sizeof(szTmp), "<%sStroke>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* If there is a symbol to be used for sroke, the color in the */ /* style sholud be set to -1. Else It won't apply here. */ if (psStyle->color.red == -1 && psStyle->color.green == -1 && psStyle->color.blue == -1) { pszGraphicSLD = msSLDGetGraphicSLD(psStyle, psLayer, 0, nVersion); if (pszGraphicSLD) { snprintf(szTmp, sizeof(szTmp), "<%sGraphicFill>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszSLD = msStringConcatenate(pszSLD, pszGraphicSLD); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); free(pszGraphicSLD); pszGraphicSLD = NULL; } } sprintf(szHexColor,"%02x%02x%02x",psStyle->outlinecolor.red, psStyle->outlinecolor.green, psStyle->outlinecolor.blue); snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke\">#%s\n", sCssParam, szHexColor, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); dfSize = 1.0; if (psStyle->size > 0) dfSize = psStyle->size; else if (psStyle->width > 0) dfSize = psStyle->width; snprintf(szTmp, sizeof(szTmp), "<%s name=\"stroke-width\">%.2f\n", sCssParam,dfSize,sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGeneratePointSLD */ /* */ /* Generate SLD for a Point layer. */ /************************************************************************/ char *msSLDGeneratePointSLD(styleObj *psStyle, layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char *pszSLD = NULL; char *pszGraphicSLD = NULL; char szTmp[100]; char sNameSpace[10]; sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); snprintf(szTmp, sizeof(szTmp), "<%sPointSymbolizer>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); pszGraphicSLD = msSLDGetGraphicSLD(psStyle, psLayer, 1, nVersion); if (pszGraphicSLD) { pszSLD = msStringConcatenate(pszSLD, pszGraphicSLD); free(pszGraphicSLD); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGenerateTextSLD */ /* */ /* Generate a TextSymboliser SLD xml based on the class's label */ /* object. */ /************************************************************************/ char *msSLDGenerateTextSLD(classObj *psClass, layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) char *pszSLD = NULL; char szTmp[100]; char **aszFontsParts = NULL; int nFontParts = 0; char szHexColor[7]; int nColorRed=-1, nColorGreen=-1, nColorBlue=-1; double dfAnchorX = 0.5, dfAnchorY = 0.5; int i = 0; char sCssParam[30]; char sNameSpace[10]; labelObj *psLabelObj = NULL; sCssParam[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sCssParam, "se:SvgParameter"); else strcpy(sCssParam, "CssParameter"); sNameSpace[0] = '\0'; if (nVersion > OWS_1_0_0) strcpy(sNameSpace, "se:"); if (psClass && psLayer && psLayer->labelitem && strlen(psLayer->labelitem) > 0 && psClass->numlabels > 0) { psLabelObj = psClass->labels[0]; snprintf(szTmp, sizeof(szTmp), "<%sTextSymbolizer>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sLabel>%s\n", sNameSpace, psLayer->labelitem, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* -------------------------------------------------------------------- */ /* only true type fonts are exported. Font name should be */ /* something like arial-bold-italic. There are 3 parts to the */ /* name font-family, font-style (italic, oblique, nomal), */ /* font-weight (bold, normal). These 3 elements are separated */ /* with -. */ /* -------------------------------------------------------------------- */ if (psLabelObj->font) { aszFontsParts = msStringSplit(psLabelObj->font, '-', &nFontParts); if (nFontParts > 0) { snprintf(szTmp, sizeof(szTmp), "<%sFont>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* assuming first one is font-family */ snprintf(szTmp, sizeof(szTmp), "<%s name=\"font-family\">%s\n", sCssParam, aszFontsParts[0], sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); for (i=1; i%s\n", sCssParam, aszFontsParts[i], sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } else if (strcasecmp(aszFontsParts[i], "bold") == 0) { snprintf(szTmp, sizeof(szTmp), "<%s name=\"font-weight\">%s\n", sCssParam, aszFontsParts[i], sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } } /* size */ if (psLabelObj->size > 0) { snprintf(szTmp, sizeof(szTmp), "<%s name=\"font-size\">%d\n", sCssParam, psLabelObj->size, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } msFreeCharArray(aszFontsParts, nFontParts); } /* label placement */ snprintf(szTmp, sizeof(szTmp), "<%sLabelPlacement>\n<%sPointPlacement>\n", sNameSpace, sNameSpace ); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sAnchorPoint>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psLabelObj->position == MS_LL) { dfAnchorX =0; dfAnchorY = 0; } else if (psLabelObj->position == MS_CL) { dfAnchorX =0; dfAnchorY = 0.5; } else if (psLabelObj->position == MS_UL) { dfAnchorX =0; dfAnchorY = 1; } else if (psLabelObj->position == MS_LC) { dfAnchorX =0.5; dfAnchorY = 0; } else if (psLabelObj->position == MS_CC) { dfAnchorX =0.5; dfAnchorY = 0.5; } else if (psLabelObj->position == MS_UC) { dfAnchorX =0.5; dfAnchorY = 1; } else if (psLabelObj->position == MS_LR) { dfAnchorX =1; dfAnchorY = 0; } else if (psLabelObj->position == MS_CR) { dfAnchorX =1; dfAnchorY = 0.5; } else if (psLabelObj->position == MS_UR) { dfAnchorX =1; dfAnchorY = 1; } snprintf(szTmp, sizeof(szTmp), "<%sAnchorPointX>%.1f\n", sNameSpace, dfAnchorX, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "<%sAnchorPointY>%.1f\n", sNameSpace, dfAnchorY, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* displacement */ if (psLabelObj->offsetx > 0 || psLabelObj->offsety > 0) { snprintf(szTmp, sizeof(szTmp), "<%sDisplacement>\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); if (psLabelObj->offsetx > 0) { snprintf(szTmp, sizeof(szTmp), "<%sDisplacementX>%d\n", sNameSpace, psLabelObj->offsetx, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } if (psLabelObj->offsety > 0) { snprintf(szTmp, sizeof(szTmp), "<%sDisplacementY>%d\n", sNameSpace, psLabelObj->offsety, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } /* rotation */ if (psLabelObj->angle > 0) { snprintf(szTmp, sizeof(szTmp), "<%sRotation>%.2f\n", sNameSpace, psLabelObj->angle, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } /* TODO : support Halo parameter => shadow */ snprintf(szTmp, sizeof(szTmp), "\n\n", sNameSpace, sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); /* color */ if (psLabelObj->color.red != -1 && psLabelObj->color.green != -1 && psLabelObj->color.blue != -1) { nColorRed = psLabelObj->color.red; nColorGreen = psLabelObj->color.green; nColorBlue = psLabelObj->color.blue; } else if (psLabelObj->outlinecolor.red != -1 && psLabelObj->outlinecolor.green != -1 && psLabelObj->outlinecolor.blue != -1) { nColorRed = psLabelObj->outlinecolor.red; nColorGreen = psLabelObj->outlinecolor.green; nColorBlue = psLabelObj->outlinecolor.blue; } if (nColorRed >= 0 && nColorGreen >= 0 && nColorBlue >=0) { snprintf(szTmp, sizeof(szTmp), "<%sFill>\n", sNameSpace ); pszSLD = msStringConcatenate(pszSLD, szTmp); sprintf(szHexColor,"%02hhx%02hhx%02hhx",nColorRed, nColorGreen, nColorBlue); snprintf(szTmp, sizeof(szTmp), "<%s name=\"fill\">#%s\n", sCssParam, szHexColor, sCssParam); pszSLD = msStringConcatenate(pszSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "\n", sNameSpace); pszSLD = msStringConcatenate(pszSLD, szTmp); } return pszSLD; #else return NULL; #endif } /************************************************************************/ /* msSLDGenerateSLDLayer */ /* */ /* Genrate an SLD XML string based on the layer's classes. */ /************************************************************************/ char *msSLDGenerateSLDLayer(layerObj *psLayer, int nVersion) { #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) #ifdef USE_OGR char szTmp[100]; char *pszTmpName = NULL; int i, j; styleObj *psStyle = NULL; char *pszFilter = NULL; char *pszFinalSLD = NULL; char *pszSLD = NULL; const char *pszTmp = NULL; double dfMinScale =-1, dfMaxScale = -1; const char *pszWfsFilter= NULL; char *pszEncoded = NULL, *pszWfsFilterEncoded=NULL; if (psLayer && (psLayer->status == MS_ON || psLayer->status == MS_DEFAULT) && (psLayer->type == MS_LAYER_POINT || psLayer->type == MS_LAYER_LINE || psLayer->type == MS_LAYER_POLYGON )) { snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); pszTmp = msOWSLookupMetadata(&(psLayer->metadata), "MO", "name"); if (pszTmp) { pszEncoded = msEncodeHTMLEntities(pszTmp); if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", pszEncoded); else snprintf(szTmp, sizeof(szTmp), "%s\n", pszEncoded); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); msFree(pszEncoded); } else if (psLayer->name) { pszEncoded = msEncodeHTMLEntities(psLayer->name); pszTmpName = (char *)malloc(sizeof(char)*(strlen(pszEncoded)+100)); if (nVersion > OWS_1_0_0) sprintf(pszTmpName, "%s\n", pszEncoded); else sprintf(pszTmpName, "%s\n", pszEncoded); msFree(pszEncoded); pszFinalSLD = msStringConcatenate(pszFinalSLD, pszTmpName); msFree(pszTmpName); pszTmpName=NULL; } else { if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", "NamedLayer"); else snprintf(szTmp, sizeof(szTmp), "%s\n", "NamedLayer"); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", ""); else snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); pszWfsFilter = msLookupHashTable(&(psLayer->metadata), "wfs_filter"); if (pszWfsFilter) pszWfsFilterEncoded = msEncodeHTMLEntities(pszWfsFilter); if (psLayer->numclasses > 0) { for (i=0; inumclasses; i++) { if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", ""); else snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); /* if class has a name, use it as the RULE name */ if (psLayer->class[i]->name) { pszEncoded = msEncodeHTMLEntities(psLayer->class[i]->name); pszTmpName = (char *)malloc(sizeof(char)*(strlen(pszEncoded)+100)); if (nVersion > OWS_1_0_0) sprintf(pszTmpName, "%s\n", pszEncoded); else sprintf(pszTmpName, "%s\n", pszEncoded); msFree(pszEncoded); pszFinalSLD = msStringConcatenate(pszFinalSLD, pszTmpName); msFree(pszTmpName); pszTmpName=NULL; } /* -------------------------------------------------------------------- */ /* get the Filter if there is a class expression. */ /* -------------------------------------------------------------------- */ pszFilter = msSLDGetFilter(psLayer->class[i] , pszWfsFilter);/* pszWfsFilterEncoded); */ if (pszFilter) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszFilter); free(pszFilter); } /* -------------------------------------------------------------------- */ /* generate the min/max scale. */ /* -------------------------------------------------------------------- */ dfMinScale = -1.0; if (psLayer->class[i]->minscaledenom > 0) dfMinScale = psLayer->class[i]->minscaledenom; else if (psLayer->minscaledenom > 0) dfMinScale = psLayer->minscaledenom; else if (psLayer->map && psLayer->map->web.minscaledenom > 0) dfMinScale = psLayer->map->web.minscaledenom; if (dfMinScale > 0) { if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%f\n", dfMinScale); else snprintf(szTmp, sizeof(szTmp), "%f\n", dfMinScale); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } dfMaxScale = -1.0; if (psLayer->class[i]->maxscaledenom > 0) dfMaxScale = psLayer->class[i]->maxscaledenom; else if (psLayer->maxscaledenom > 0) dfMaxScale = psLayer->maxscaledenom; else if (psLayer->map && psLayer->map->web.maxscaledenom > 0) dfMaxScale = psLayer->map->web.maxscaledenom; if (dfMaxScale > 0) { if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%f\n", dfMaxScale); else snprintf(szTmp, sizeof(szTmp), "%f\n", dfMaxScale); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } /* -------------------------------------------------------------------- */ /* Line symbolizer. */ /* */ /* Right now only generates a stroke element containing css */ /* parameters. */ /* Lines using symbols TODO (specially for dash lines) */ /* -------------------------------------------------------------------- */ if (psLayer->type == MS_LAYER_LINE) { for (j=0; jclass[i]->numstyles; j++) { psStyle = psLayer->class[i]->styles[j]; pszSLD = msSLDGenerateLineSLD(psStyle, psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } } } else if (psLayer->type == MS_LAYER_POLYGON) { for (j=0; jclass[i]->numstyles; j++) { psStyle = psLayer->class[i]->styles[j]; pszSLD = msSLDGeneratePolygonSLD(psStyle, psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } } } else if (psLayer->type == MS_LAYER_POINT) { for (j=0; jclass[i]->numstyles; j++) { psStyle = psLayer->class[i]->styles[j]; pszSLD = msSLDGeneratePointSLD(psStyle, psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } } } /* label if it exists */ pszSLD = msSLDGenerateTextSLD(psLayer->class[i], psLayer, nVersion); if (pszSLD) { pszFinalSLD = msStringConcatenate(pszFinalSLD, pszSLD); free(pszSLD); } if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", ""); else snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } } if (pszWfsFilterEncoded) msFree(pszWfsFilterEncoded); if (nVersion > OWS_1_0_0) snprintf(szTmp, sizeof(szTmp), "%s\n", ""); else snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); snprintf(szTmp, sizeof(szTmp), "%s\n", ""); pszFinalSLD = msStringConcatenate(pszFinalSLD, szTmp); } return pszFinalSLD; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msSLDGenerateSLDLayer()"); return NULL; #endif /* USE_OGR */ #else msSetError(MS_MISCERR, "OWS support is not available.", "msSLDGenerateSLDLayer()"); return NULL; #endif } #ifdef USE_OGR char *msSLDGetComparisonValue(char *pszExpression) { char *pszValue = NULL; if (!pszExpression) return NULL; if (strstr(pszExpression, "<=") || strstr(pszExpression, " le ")) pszValue = msStrdup("PropertyIsLessThanOrEqualTo"); else if (strstr(pszExpression, "=~")) pszValue = msStrdup("PropertyIsLike"); else if (strstr(pszExpression, "~*")) pszValue = msStrdup("PropertyIsLike"); else if (strstr(pszExpression, ">=") || strstr(pszExpression, " ge ")) pszValue = msStrdup("PropertyIsGreaterThanOrEqualTo"); else if (strstr(pszExpression, "!=") || strstr(pszExpression, " ne ")) pszValue = msStrdup("PropertyIsNotEqualTo"); else if (strstr(pszExpression, "=") || strstr(pszExpression, " eq ")) pszValue = msStrdup("PropertyIsEqualTo"); else if (strstr(pszExpression, "<") || strstr(pszExpression, " lt ")) pszValue = msStrdup("PropertyIsLessThan"); else if (strstr(pszExpression, ">") || strstr(pszExpression, " gt ")) pszValue = msStrdup("PropertyIsGreaterThan"); return pszValue; } char *msSLDGetLogicalOperator(char *pszExpression) { if (!pszExpression) return NULL; /* TODO for NOT */ if(strstr(pszExpression, " AND ") || strstr(pszExpression, "AND(")) return msStrdup("And"); if(strstr(pszExpression, " OR ") || strstr(pszExpression, "OR(")) return msStrdup("Or"); if(strstr(pszExpression, "NOT ") || strstr(pszExpression, "NOT(")) return msStrdup("Not"); return NULL; } char *msSLDGetRightExpressionOfOperator(char *pszExpression) { char *pszAnd = NULL, *pszOr = NULL, *pszNot=NULL; pszAnd = strstr(pszExpression, " AND "); if (!pszAnd) pszAnd = strstr(pszExpression, " and "); if (pszAnd) return msStrdup(pszAnd+4); else { pszOr = strstr(pszExpression, " OR "); if (!pszOr) pszOr = strstr(pszExpression, " or "); if (pszOr) return msStrdup(pszOr+3); else { pszNot = strstr(pszExpression, "NOT "); if (!pszNot) pszNot = strstr(pszExpression, "not "); if (!pszNot) pszNot = strstr(pszExpression, "NOT("); if (!pszNot) pszNot = strstr(pszExpression, "not("); if (pszNot) return msStrdup(pszNot+4); } } return NULL; } char *msSLDGetLeftExpressionOfOperator(char *pszExpression) { char *pszReturn = NULL; int nLength = 0, i =0, iReturn=0; if (!pszExpression || (nLength = strlen(pszExpression)) <=0) return NULL; pszReturn = (char *)malloc(sizeof(char)*(nLength+1)); pszReturn[0] = '\0'; if (strstr(pszExpression, " AND ") || strstr(pszExpression, " and ")) { for (i=0; i 1) { pszAttributeName = msStrdup(aszValues[0]); pszAttributeValue = msStrdup(aszValues[1]); } else { nLength = strlen(pszExpression); pszAttributeName = (char *)malloc(sizeof(char)*(nLength+1)); iValue = 0; for (i=0; i 2 && strcasecmp(pszComparionValue, "PropertyIsLike") == 0) { int len = strlen(pszFinalAttributeValue); msStringTrimBlanks(pszFinalAttributeValue); if (pszFinalAttributeValue[0] == '/' && (pszFinalAttributeValue[len-1] == '/' || (pszFinalAttributeValue[len-1] == 'i' && pszFinalAttributeValue[len-2] == '/'))) { if (pszFinalAttributeValue[len-1] == '/') pszFinalAttributeValue[len-1] = '\0'; else pszFinalAttributeValue[len-2] = '\0'; memmove(pszFinalAttributeValue, pszFinalAttributeValue + ((pszFinalAttributeValue[1] == '^') ? 2 : 1), len-1); /*replace wild card string .* with * */ pszFinalAttributeValue = msReplaceSubstring(pszFinalAttributeValue, ".*", "*"); } } msFree(pszAttributeName); msFree(pszAttributeValue); return pszFinalAttributeValue; } } char *msSLDGetAttributeName(char *pszExpression, char *pszComparionValue) { return msSLDGetAttributeNameOrValue(pszExpression, pszComparionValue, 1); } char *msSLDGetAttributeValue(char *pszExpression, char *pszComparionValue) { return msSLDGetAttributeNameOrValue(pszExpression, pszComparionValue, 0); } /************************************************************************/ /* BuildExpressionTree */ /* */ /* Build a filter expression node based on mapserver's class */ /* expression. This is limited to simple expressions like : */ /* A = B, A < B, A <= B, A > B, A >= B, A != B */ /* It also handles one level of logical expressions : */ /* A AND B */ /* A OR B */ /* NOT A */ /************************************************************************/ FilterEncodingNode *BuildExpressionTree(char *pszExpression, FilterEncodingNode *psNode) { int nLength = 0; int nOperators=0; char *pszComparionValue=NULL, *pszAttibuteName=NULL; char *pszAttibuteValue=NULL; char *pszLeftExpression=NULL, *pszRightExpression=NULL, *pszOperator=NULL; if (!pszExpression || (nLength = strlen(pszExpression)) <=0) return NULL; /* -------------------------------------------------------------------- */ /* First we check how many logical operators are there : */ /* - if none : It means It is a comparision operator (like =, */ /* >, >= .... We get the comparison value as well as the */ /* attribute and the attribut's value and assign it to the node */ /* passed in argument. */ /* - if there is one operator, we assign the operator to the */ /* node and adds the expressions into the left and right nodes. */ /* -------------------------------------------------------------------- */ nOperators = msSLDNumberOfLogicalOperators(pszExpression); if (nOperators == 0) { if (!psNode) psNode = FLTCreateFilterEncodingNode(); pszComparionValue = msSLDGetComparisonValue(pszExpression); pszAttibuteName = msSLDGetAttributeName(pszExpression, pszComparionValue); pszAttibuteValue = msSLDGetAttributeValue(pszExpression, pszComparionValue); if (pszComparionValue && pszAttibuteName && pszAttibuteValue) { psNode->eType = FILTER_NODE_TYPE_COMPARISON; psNode->pszValue = msStrdup(pszComparionValue); psNode->psLeftNode = FLTCreateFilterEncodingNode(); psNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psNode->psLeftNode->pszValue = msStrdup(pszAttibuteName); psNode->psRightNode = FLTCreateFilterEncodingNode(); psNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; psNode->psRightNode->pszValue = msStrdup(pszAttibuteValue); if (strcasecmp(pszComparionValue, "PropertyIsLike") == 0) { psNode->pOther = (FEPropertyIsLike *)malloc(sizeof(FEPropertyIsLike)); ((FEPropertyIsLike *)psNode->pOther)->bCaseInsensitive = 0; ((FEPropertyIsLike *)psNode->pOther)->pszWildCard = msStrdup("*"); ((FEPropertyIsLike *)psNode->pOther)->pszSingleChar = msStrdup("#"); ((FEPropertyIsLike *)psNode->pOther)->pszEscapeChar = msStrdup("!"); } free(pszComparionValue); free(pszAttibuteName); free(pszAttibuteValue); } return psNode; } else if (nOperators == 1) { pszOperator = msSLDGetLogicalOperator(pszExpression); if (pszOperator) { if (!psNode) psNode = FLTCreateFilterEncodingNode(); psNode->eType = FILTER_NODE_TYPE_LOGICAL; psNode->pszValue = msStrdup(pszOperator); free(pszOperator); pszLeftExpression = msSLDGetLeftExpressionOfOperator(pszExpression); pszRightExpression = msSLDGetRightExpressionOfOperator(pszExpression); if (pszLeftExpression || pszRightExpression) { if (pszLeftExpression) { pszComparionValue = msSLDGetComparisonValue(pszLeftExpression); pszAttibuteName = msSLDGetAttributeName(pszLeftExpression, pszComparionValue); pszAttibuteValue = msSLDGetAttributeValue(pszLeftExpression, pszComparionValue); if (pszComparionValue && pszAttibuteName && pszAttibuteValue) { psNode->psLeftNode = FLTCreateFilterEncodingNode(); psNode->psLeftNode->eType = FILTER_NODE_TYPE_COMPARISON; psNode->psLeftNode->pszValue = msStrdup(pszComparionValue); psNode->psLeftNode->psLeftNode = FLTCreateFilterEncodingNode(); psNode->psLeftNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psNode->psLeftNode->psLeftNode->pszValue = msStrdup(pszAttibuteName); psNode->psLeftNode->psRightNode = FLTCreateFilterEncodingNode(); psNode->psLeftNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; psNode->psLeftNode->psRightNode->pszValue = msStrdup(pszAttibuteValue); free(pszComparionValue); free(pszAttibuteName); free(pszAttibuteValue); } } if (pszRightExpression) { pszComparionValue = msSLDGetComparisonValue(pszRightExpression); pszAttibuteName = msSLDGetAttributeName(pszRightExpression, pszComparionValue); pszAttibuteValue = msSLDGetAttributeValue(pszRightExpression, pszComparionValue); if (pszComparionValue && pszAttibuteName && pszAttibuteValue) { psNode->psRightNode = FLTCreateFilterEncodingNode(); psNode->psRightNode->eType = FILTER_NODE_TYPE_COMPARISON; psNode->psRightNode->pszValue = msStrdup(pszComparionValue); psNode->psRightNode->psLeftNode = FLTCreateFilterEncodingNode(); psNode->psRightNode->psLeftNode->eType = FILTER_NODE_TYPE_PROPERTYNAME; psNode->psRightNode->psLeftNode->pszValue = msStrdup(pszAttibuteName); psNode->psRightNode->psRightNode = FLTCreateFilterEncodingNode(); psNode->psRightNode->psRightNode->eType = FILTER_NODE_TYPE_LITERAL; psNode->psRightNode->psRightNode->pszValue = msStrdup(pszAttibuteValue); free(pszComparionValue); free(pszAttibuteName); free(pszAttibuteValue); } } } } return psNode; } else { return NULL; } } char *msSLDBuildFilterEncoding(FilterEncodingNode *psNode) { char *pszTmp = NULL; char szTmp[200]; char *pszExpression = NULL; if (!psNode) return NULL; if (psNode->eType == FILTER_NODE_TYPE_COMPARISON && psNode->pszValue && psNode->psLeftNode && psNode->psLeftNode->pszValue && psNode->psRightNode && psNode->psRightNode->pszValue) { snprintf(szTmp, sizeof(szTmp), "%s%s", psNode->pszValue, psNode->psLeftNode->pszValue, psNode->psRightNode->pszValue, psNode->pszValue); pszExpression = msStrdup(szTmp); } else if (psNode->eType == FILTER_NODE_TYPE_LOGICAL && psNode->pszValue && ((psNode->psLeftNode && psNode->psLeftNode->pszValue) || (psNode->psRightNode && psNode->psRightNode->pszValue))) { snprintf(szTmp, sizeof(szTmp), "", psNode->pszValue); pszExpression = msStringConcatenate(pszExpression, szTmp); if (psNode->psLeftNode) { pszTmp = msSLDBuildFilterEncoding(psNode->psLeftNode); if (pszTmp) { pszExpression = msStringConcatenate(pszExpression, pszTmp); free(pszTmp); } } if (psNode->psRightNode) { pszTmp = msSLDBuildFilterEncoding(psNode->psRightNode); if (pszTmp) { pszExpression = msStringConcatenate(pszExpression, pszTmp); free(pszTmp); } } snprintf(szTmp, sizeof(szTmp), "", psNode->pszValue); pszExpression = msStringConcatenate(pszExpression, szTmp); } return pszExpression; } char *msSLDParseLogicalExpression(char *pszExpression, const char *pszWfsFilter) { FilterEncodingNode *psNode = NULL; char *pszFLTExpression = NULL; char *pszTmp = NULL; if (!pszExpression || strlen(pszExpression) <=0) return NULL; /* psNode = BuildExpressionTree(pszExpression, NULL); */ psNode = BuildExpressionTree(pszExpression, NULL); if (psNode) { pszFLTExpression = msSLDBuildFilterEncoding(psNode); if (pszFLTExpression) { pszTmp = msStringConcatenate(pszTmp, ""); if (pszWfsFilter) { pszTmp = msStringConcatenate(pszTmp, ""); pszTmp = msStringConcatenate(pszTmp, (char *)pszWfsFilter); } pszTmp = msStringConcatenate(pszTmp, pszFLTExpression); if (pszWfsFilter) pszTmp = msStringConcatenate(pszTmp, ""); pszTmp = msStringConcatenate(pszTmp, "\n"); free(pszFLTExpression); pszFLTExpression = pszTmp; } } return pszFLTExpression; } /************************************************************************/ /* char *msSLDParseExpression(char *pszExpression) */ /* */ /* Return an OGC filter for a mapserver locgical expression. */ /* TODO : move function to mapogcfilter.c */ /************************************************************************/ char *msSLDParseExpression(char *pszExpression) { int nElements = 0; char **aszElements = NULL; char szBuffer[500]; char szFinalAtt[40]; char szFinalValue[40]; char szAttribute[40]; char szValue[40]; int i=0, nLength=0, iAtt=0, iVal=0; int bStartCopy=0, bSinglequote=0, bDoublequote=0; char *pszFilter = NULL; if (!pszExpression) return NULL; nLength = strlen(pszExpression); aszElements = msStringSplit(pszExpression, ' ', &nElements); szFinalAtt[0] = '\0'; szFinalValue[0] = '\0'; for (i=0; i 0 && i < nElements-1) { snprintf(szAttribute, sizeof(szAttribute), "%s", aszElements[i-1]); snprintf(szValue, sizeof(szValue), "%s", aszElements[i+1]); /* parse attribute */ nLength = strlen(szAttribute); if (nLength > 0) { iAtt = 0; for (i=0; i 0) { if (szValue[0] == '\'') bSinglequote = 1; else if (szValue[0] == '\"') bDoublequote = 1; else snprintf(szFinalValue, sizeof(szFinalValue), "%s", szValue); iVal = 0; if (bSinglequote || bDoublequote) { for (i=1; i 0 && strlen(szFinalValue) >0) { snprintf(szBuffer, sizeof(szBuffer), "%s%s", szFinalAtt, szFinalValue); msFree(pszFilter); /*FIXME: we are possibly discarding a previously set pszFilter */ pszFilter = msStrdup(szBuffer); } } } msFreeCharArray(aszElements, nElements); return pszFilter; } /************************************************************************/ /* msSLDConvertRegexExpToOgcIsLike */ /* */ /* Convert mapserver regex expression to ogc is like propoery */ /* exprssion. */ /* */ /* Review bug 1644 for details. Here are the current rules: */ /* */ /* The filter encoding property like is more limited compared */ /* to regular expressiosn that can be built in mapserver. I */ /* think we should define what is possible to convert properly */ /* and do those, and also identify potential problems. Example : */ /* - any time there is a .* in the expression it will be */ /* converted to * */ /* - any other character plus all the metacharcters . ^ $ * + */ /* ? { [ ] \ | ( ) would be outputed as is. (In case of */ /* mapserver, when we read the the ogc filter expression, we */ /* convert the wild card chracter to .*, and we convert the */ /* single chracter to . and the escpae character to \ all */ /* other are outputed as is) */ /* - the ogc tag would look like */ /* */ /* - type of potential problem : */ /* * if an expression is like /T (star)/ it will be */ /* converted to T* which is not correct. */ /* */ /************************************************************************/ char *msSLDConvertRegexExpToOgcIsLike(char *pszRegex) { char szBuffer[1024]; int iBuffer = 0, i=0; int nLength = 0; if (!pszRegex || strlen(pszRegex) == 0) return NULL; szBuffer[0] = '\0'; nLength = strlen(pszRegex); while (i < nLength) { if (pszRegex[i] != '.') { szBuffer[iBuffer++] = pszRegex[i]; i++; } else { if (iexpression.string) { /* string expression */ if (psClass->expression.type == MS_STRING) { if (psClass->layer && psClass->layer->classitem) { if (pszWfsFilter) snprintf(szBuffer, sizeof(szBuffer), "%s%s%s\n", pszWfsFilter, psClass->layer->classitem, psClass->expression.string); else snprintf(szBuffer, sizeof(szBuffer), "%s%s\n", psClass->layer->classitem, psClass->expression.string); pszFilter = msStrdup(szBuffer); } } else if (psClass->expression.type == MS_EXPRESSION) { pszFilter = msSLDParseLogicalExpression(psClass->expression.string, pszWfsFilter); } else if (psClass->expression.type == MS_REGEX) { if (psClass->layer && psClass->layer->classitem && psClass->expression.string) { pszOgcFilter = msSLDConvertRegexExpToOgcIsLike(psClass->expression.string); if (pszWfsFilter) snprintf(szBuffer, sizeof(szBuffer), "%s%s%s\n", pszWfsFilter, psClass->layer->classitem, pszOgcFilter); else snprintf(szBuffer, sizeof(szBuffer), "%s%s\n", psClass->layer->classitem, pszOgcFilter); free(pszOgcFilter); pszFilter = msStrdup(szBuffer); } } } else if (pszWfsFilter) { snprintf(szBuffer, sizeof(szBuffer), "%s\n", pszWfsFilter); pszFilter = msStrdup(szBuffer); } return pszFilter; } #endif mapserver-7.4.3/mapogcsld.h000066400000000000000000000110061357574274700156760ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC SLD implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2003, Y. Assefa, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #include "mapserver.h" MS_DLL_EXPORT char *msSLDGenerateSLD(mapObj *map, int iLayer, const char *pszVersion); MS_DLL_EXPORT int msSLDApplySLDURL(mapObj *map, const char *szURL, int iLayer, const char *pszStyleLayerName, char **ppszLayerNames); MS_DLL_EXPORT int msSLDApplySLD(mapObj *map, const char *psSLDXML, int iLayer, const char *pszStyleLayerName, char **ppszLayerNames); #ifdef USE_OGR /* There is a dependency to OGR for the MiniXML parser */ #include "cpl_minixml.h" /* -------------------------------------------------------------------- */ /* prototypes. */ /* -------------------------------------------------------------------- */ layerObj *msSLDParseSLD(mapObj *map, const char *psSLDXML, int *pnLayers); int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *layer); int msSLDParseRule(CPLXMLNode *psRoot, layerObj *psLayer); int msSLDParseStroke(CPLXMLNode *psStroke, styleObj *psStyle, mapObj *map, int iColorParam); int msSLDParsePolygonFill(CPLXMLNode *psFill, styleObj *psStyle, mapObj *map); int msSLDParseLineSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass); int msSLDParsePolygonSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass); int msSLDParsePointSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bNewClass); int msSLDParseTextSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer, int bOtherSymboliser); int msSLDParseRasterSymbolizer(CPLXMLNode *psRoot, layerObj *psLayer); int msSLDParseGraphicFillOrStroke(CPLXMLNode *psGraphicFill, char *pszDashValue, styleObj *psStyle, mapObj *map); int msSLDParseExternalGraphic(CPLXMLNode *psExternalGraphic, styleObj *psStyle, mapObj *map); int msSLDGetLineSymbol(mapObj *map); int msSLDGetDashLineSymbol(mapObj *map, char *pszDashArray); int msSLDGetMarkSymbol(mapObj *map, char *pszSymbolName, int bFilled); int msSLDGetGraphicSymbol(mapObj *map, char *pszFileName, char *extGraphicName, int nGap); int msSLDSetColorObject(char *psHexColor, colorObj *psColor); int msSLDParseTextParams(CPLXMLNode *psRoot, layerObj *psLayer, classObj *psClass); int ParseTextPointPlacement(CPLXMLNode *psRoot, classObj *psClass); int ParseTextLinePlacement(CPLXMLNode *psRoot, classObj *psClass); char *msSLDGenerateSLDLayer(layerObj *psLayer, int nVersion); char *msSLDGetFilter(classObj *psClass, const char *pszWfsFilter); char *msSLDGenerateLineSLD(styleObj *psStyle, layerObj *psLayer, int nVersion); char *msSLDGeneratePolygonSLD(styleObj *psStyle, layerObj *psLayer, int nVersion); char *msSLDGeneratePointSLD(styleObj *psStyle, layerObj *psLayer, int nVersion); char *msSLDGenerateTextSLD(classObj *psClass, layerObj *psLayer, int nVersion); FilterEncodingNode *BuildExpressionTree(char *pszExpression, FilterEncodingNode *psNode); #endif mapserver-7.4.3/mapogcsos.c000066400000000000000000003713311357574274700157250ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC SOS implementation * Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2006, Y. Assefa, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #define _GNU_SOURCE #include "mapserver.h" #include "mapows.h" #if defined(USE_SOS_SVR) && defined(USE_LIBXML2) #include "maperror.h" #include "mapthread.h" #include "mapows.h" #include "maptime.h" #include "mapgml.h" #include "mapogcfilter.h" #include "mapowscommon.h" #include "maplibxml2.h" #include "libxml/parser.h" #include "libxml/tree.h" #include "libxml/xpath.h" #include "libxml/xpathInternals.h" const char *pszSOSVersion = "1.0.0"; const char *pszSOSNamespaceUri = "http://www.opengis.net/sos/1.0"; const char *pszSOSNamespacePrefix = "sos"; const char *pszOMNamespaceUri = "http://www.opengis.net/om/1.0"; const char *pszOMNamespacePrefix = "om"; const char *pszSOSDescribeSensorMimeType = "text/xml; subtype=\"sensorML/1.0.0\""; const char *pszSOSGetObservationMimeType = "text/xml; subtype=\"om/1.0.0\""; typedef struct { char *pszProcedure; xmlNodePtr psResultNode; } SOSProcedureNode; int msSOSParseRequest(mapObj *map, cgiRequestObj *request, sosParamsObj *sosparams); void msSOSFreeParamsObj(sosParamsObj *sosparams); /* ** msSOSException() ** ** Report current MapServer error in XML exception format. ** Wrapper function around msOWSCommonExceptionReport. Merely ** passes SOS specific info. ** */ static int msSOSException(mapObj *map, char *locator, char *exceptionCode) { int size = 0; char *errorString = NULL; char *schemasLocation = NULL; xmlDocPtr psDoc = NULL; xmlNodePtr psRootNode = NULL; xmlNsPtr psNsOws = NULL; xmlChar *buffer = NULL; psNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); errorString = msGetErrorString("\n"); schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_1_0, schemasLocation, pszSOSVersion, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorString); xmlDocSetRootElement(psDoc, psRootNode); xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); msIO_setHeader("Content-Type","text/xml; charset=UTF-8"); msIO_sendHeaders(); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, ("UTF-8"), 1); msIO_printf("%s", buffer); /*free buffer and the document */ free(errorString); free(schemasLocation); xmlFree(buffer); xmlFreeDoc(psDoc); xmlFreeNs(psNsOws); /* ** The typical pattern is to call msSOSException() right after ** msSetError(). In order to prevent mapserv.c from re-reporting this ** error at a higher level, we mark it as reported here. #3571 */ { errorObj *err = msGetErrorObj(); if( err != NULL && err->code != MS_NOERR ) err->isreported = MS_TRUE; } return MS_FAILURE; } static int _IsInList(char **papsProcedures, int nDistinctProcedures, char *pszProcedure) { int i = 0; if (papsProcedures && nDistinctProcedures > 0 && pszProcedure) { for (i=0; ieType == FILTER_NODE_TYPE_PROPERTYNAME) { for (i=0; inumitems; i++) { if (strcasecmp(lp->items[i], psFilterNode->pszValue) == 0) { bFound = 1; break; } } if (!bFound) return MS_FALSE; } if (psFilterNode->psLeftNode && psFilterNode->eType != FILTER_NODE_TYPE_SPATIAL) { if (msSOSValidateFilter(psFilterNode->psLeftNode, lp) == MS_FALSE) return MS_FALSE; } if (psFilterNode->psRightNode && psFilterNode->eType != FILTER_NODE_TYPE_SPATIAL) { if (msSOSValidateFilter(psFilterNode->psRightNode, lp) == MS_FALSE) return MS_FALSE; } } return MS_TRUE; } /************************************************************************/ /* msSOSAddMetadataChildNode */ /* */ /* Utility function to add a metadata node. */ /************************************************************************/ void msSOSAddMetadataChildNode(xmlNodePtr psParent, const char *psNodeName, xmlNsPtr psNs, hashTableObj *metadata, const char *psNamespaces, const char *psMetadataName, const char *psDefaultValue) { xmlNodePtr psNode = NULL; char *psValue = NULL; if (psParent && psNodeName) { psValue = msOWSGetEncodeMetadata(metadata, psNamespaces, psMetadataName, psDefaultValue); if (psValue) { psNode = xmlNewChild(psParent, NULL, BAD_CAST psNodeName, BAD_CAST psValue); if (psNs) xmlSetNs(psNode, psNs); free(psValue); } } } /************************************************************************/ /* msSOSGetFirstLayerForOffering */ /* */ /* return the first layer for the offering. */ /************************************************************************/ layerObj *msSOSGetFirstLayerForOffering(mapObj *map, const char *pszOffering, const char *pszProperty) { layerObj *lp = NULL; const char *pszTmp = NULL; int i = 0; if (pszOffering && map) { for (i=0; inumlayers; i++) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"); if (pszTmp && (strcasecmp(pszTmp, pszOffering) == 0)) { if (pszProperty) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "observedproperty_id"); if (pszTmp && (strcasecmp(pszTmp, pszProperty) == 0)) { lp = (GET_LAYER(map, i)); break; } } else { lp = (GET_LAYER(map, i)); break; } } } } return lp; } xmlNodePtr msSOSAddTimeNode(xmlNsPtr psNs, xmlNsPtr psNsGml, char *pszStart, char *pszEnd) { xmlNodePtr psNode=NULL; char *timeel= NULL; if (strcmp((char *)psNs->prefix,"sos") == 0) timeel = "time"; if (strcmp((char *)psNs->prefix,"om") == 0) timeel = "samplingTime"; else timeel = "time"; psNode = xmlNewNode(psNs, BAD_CAST timeel); xmlAddChild(psNode, msGML3TimePeriod(psNsGml, pszStart, pszEnd)); return psNode; } void msSOSAddPropertyNode(xmlNsPtr psNsSwe, xmlNsPtr psNsXLink, xmlNodePtr psParent, layerObj *lp, xmlNsPtr psNsGml, char *pszCompositePhenomenonId) { const char *pszValue = NULL; char *pszTmpVal = NULL, *pszFullName = NULL; xmlNodePtr psCompNode, psNode; int i, j=0; char szTmp[256]; const char *pszComponentBase = "urn:ogc:def:property:"; if (psParent && lp) { psNode = xmlNewChild(psParent, NULL, BAD_CAST "observedProperty", NULL); psCompNode = xmlNewChild(psNode, psNsSwe, BAD_CAST "CompositePhenomenon", NULL); pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id"); pszTmpVal = msStrdup(pszValue); if (pszCompositePhenomenonId != NULL) { /* unique value needs to be constructed */ pszTmpVal = msStringConcatenate(pszTmpVal, "_"); pszTmpVal = msStringConcatenate(pszTmpVal, pszCompositePhenomenonId); } if (pszTmpVal) { /*should always be true */ xmlNewNsProp(psCompNode, psNsGml, BAD_CAST "id", BAD_CAST pszTmpVal); msFree(pszTmpVal); } pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_name"); if (pszValue) psNode = xmlNewTextChild(psCompNode, psNsGml, BAD_CAST "name", BAD_CAST pszValue); /* add components */ /*assuming that the layer is opened and msLayerGetItems called*/ for(i=0; inumitems; i++) { pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_authority"); if (pszValue) pszTmpVal = msStrdup(pszValue); else pszTmpVal = msStrdup("OGC-SWE"); pszFullName = msStrdup(pszComponentBase); pszFullName = msStringConcatenate(pszFullName, pszTmpVal); free(pszTmpVal); pszFullName = msStringConcatenate(pszFullName, ":"); pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_version"); if (pszValue) pszTmpVal = msStrdup(pszValue); else pszTmpVal = msStrdup("1"); pszFullName = msStringConcatenate(pszFullName, pszTmpVal); free(pszTmpVal); pszFullName = msStringConcatenate(pszFullName, ":"); snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[i]); pszValue = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (pszValue) pszTmpVal = msStrdup(pszValue); else pszTmpVal = msStrdup(lp->items[i]); pszFullName = msStringConcatenate(pszFullName, pszTmpVal); psNode = xmlNewChild(psCompNode, psNsSwe, BAD_CAST "component", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszFullName); free(pszFullName); free(pszTmpVal); j++; } pszTmpVal = msIntToString(j); xmlNewNsProp(psCompNode, NULL, BAD_CAST "dimension", BAD_CAST pszTmpVal); free(pszTmpVal); } } /************************************************************************/ /* msSOSAddGeometryNode */ /* */ /* Outout gml 2 gemptry nodes based on a shape. All logic comes */ /* from gmlWriteGeometry_GML2. Should be merged at one point if */ /* possible. */ /************************************************************************/ void msSOSAddGeometryNode(xmlNsPtr psNsGml, xmlNsPtr psNsMs, xmlNodePtr psParent, mapObj *map, layerObj *lp, shapeObj *psShape, const char *pszEpsg_in) { char *pszTmp = NULL; int i,j = 0; xmlNodePtr psPointNode, psNode, psLineNode, psPolygonNode; int *panOuterList = NULL, *panInnerList = NULL; const char *pszEpsg = pszEpsg_in; char *pszEpsg_buf = NULL; if (psParent && psShape) { if (msProjectionsDiffer(&map->projection, &lp->projection) == MS_TRUE) { msProjectShape(&lp->projection, &map->projection, psShape); msOWSGetEPSGProj(&(map->projection), &(lp->metadata), "SO", MS_TRUE, &pszEpsg_buf); pszEpsg = pszEpsg_buf; } switch(psShape->type) { case(MS_SHAPE_POINT): psNode = xmlNewChild(psParent, NULL, BAD_CAST "msGeometry", NULL); xmlSetNs(psNode, psNsMs); if (psShape->line[0].numpoints > 1) { psPointNode = xmlNewChild(psNode, NULL, BAD_CAST "MultiPoint", NULL); xmlSetNs(psPointNode, psNsGml); if (pszEpsg) xmlNewProp(psPointNode, BAD_CAST "srsName", BAD_CAST pszEpsg); } else psPointNode= psNode; /*add all points */ for(i=0; iline[0].numpoints; i++) { psNode = xmlAddChild(psPointNode, msGML3Point(psNsGml, pszEpsg, NULL, psShape->line[0].point[i].x, psShape->line[0].point[i].y)); } break; case(MS_SHAPE_LINE): psNode = xmlNewChild(psParent, NULL, BAD_CAST "msGeometry", NULL); xmlSetNs(psNode,xmlNewNs(psNode, NULL, NULL)); if (psShape->numlines > 1) { psLineNode = xmlNewChild(psNode, NULL, BAD_CAST "MultiLineString", NULL); xmlSetNs(psLineNode,xmlNewNs(psLineNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); if (pszEpsg) xmlNewProp(psLineNode, BAD_CAST "srsName", BAD_CAST pszEpsg); } else psLineNode= psNode; for(i=0; inumlines; i++) { if (psShape->numlines > 1) { psNode = xmlNewChild(psLineNode, NULL, BAD_CAST "lineStringMember", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); psNode = xmlNewChild(psNode, NULL, BAD_CAST "LineString", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } else { psNode = xmlNewChild(psLineNode, NULL, BAD_CAST "LineString", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } if (pszEpsg) xmlNewProp(psNode, BAD_CAST "srsName", BAD_CAST pszEpsg); pszTmp = NULL; for(j=0; jline[i].numpoints; j++) { char *doubleTmp = msDoubleToString(psShape->line[i].point[j].x, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, doubleTmp); pszTmp = msStringConcatenate(pszTmp, ","); free(doubleTmp); doubleTmp = msDoubleToString(psShape->line[i].point[j].y, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, doubleTmp); pszTmp = msStringConcatenate(pszTmp, ","); free(doubleTmp); } psNode = xmlNewChild(psNode, NULL, BAD_CAST "coordinates", BAD_CAST pszTmp); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); free(pszTmp); } break; case(MS_SHAPE_POLYGON): psNode = xmlNewChild(psParent, NULL, BAD_CAST "msGeometry", NULL); xmlSetNs(psNode,xmlNewNs(psNode, NULL, NULL)); if (psShape->numlines > 1) { psPolygonNode = xmlNewChild(psNode, NULL, BAD_CAST "MultiPolygon", NULL); xmlSetNs(psPolygonNode, xmlNewNs(psPolygonNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); if (pszEpsg) xmlNewProp(psPolygonNode, BAD_CAST "srsName", BAD_CAST pszEpsg); } else psPolygonNode= psNode; panOuterList = msGetOuterList(psShape); for(i=0; inumlines; i++) { if(panOuterList[i] != MS_TRUE) continue; panInnerList = msGetInnerList(psShape, i, panOuterList); if (psShape->numlines > 1) { psNode = xmlNewChild(psPolygonNode, NULL, BAD_CAST "polygonMember", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); psNode = xmlNewChild(psNode, NULL, BAD_CAST "Polygon", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } else { psNode = xmlNewChild(psPolygonNode, NULL, BAD_CAST "Polygon", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } if (pszEpsg) xmlNewProp(psNode, BAD_CAST "srsName", BAD_CAST pszEpsg); psNode = xmlNewChild(psNode, NULL, BAD_CAST "outerBoundaryIs", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); psNode = xmlNewChild(psNode, NULL, BAD_CAST "LinearRing", NULL); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); pszTmp = NULL; for(j=0; jline[i].numpoints; j++) { char *doubleTmp; doubleTmp = msDoubleToString(psShape->line[i].point[j].x, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, doubleTmp); pszTmp = msStringConcatenate(pszTmp, ","); free(doubleTmp); doubleTmp = msDoubleToString(psShape->line[i].point[j].y, MS_TRUE); pszTmp = msStringConcatenate(pszTmp, doubleTmp); pszTmp = msStringConcatenate(pszTmp, " "); free(doubleTmp); } psNode = xmlNewChild(psNode, NULL, BAD_CAST "coordinates", BAD_CAST pszTmp); xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); free(pszTmp); if (panInnerList) free(panInnerList); } if (panOuterList) free(panOuterList); break; default: break; } } msFree(pszEpsg_buf); } /************************************************************************/ /* void msSOSAddDataBlockDefinition(xmlNodePtr psParent, */ /* layerObj *lp) */ /* */ /* Add a databalock used for GetObservation request. */ /************************************************************************/ void msSOSAddDataBlockDefinition(xmlNsPtr psNsSwe, xmlNodePtr psParent, layerObj *lp) { xmlNodePtr psNode, psRecordNode, psCompNode, psSubNode, psEncNode; const char *pszDefinition = NULL, *pszUom=NULL, *pszValue=NULL, *pszName=NULL; char szTmp[100]; int i=0; char *pszTokenValue = NULL; char *pszBlockValue = NULL; const char *pszBlockSep=NULL, *pszTokenSep=NULL; if (psParent) { psNode = xmlNewChild(psParent, NULL, BAD_CAST "DataBlockDefinition", NULL); xmlSetNs(psNode, psNsSwe); /* -------------------------------------------------------------------- */ /* Add components. */ /* -------------------------------------------------------------------- */ psCompNode = xmlNewChild(psNode, NULL, BAD_CAST "components", NULL); psEncNode = xmlNewChild(psNode, NULL, BAD_CAST "encoding", NULL); psRecordNode = xmlNewChild(psCompNode, NULL, BAD_CAST "DataRecord", NULL); /*always add a time field if timeitem is defined*/ if (msOWSLookupMetadata(&(lp->metadata), "SO", "timeitem")) { psNode = xmlNewChild(psRecordNode, NULL, BAD_CAST "field", NULL); xmlNewNsProp(psNode, NULL, BAD_CAST "name", BAD_CAST "time"); psNode = xmlNewChild(psNode, NULL, BAD_CAST "Time", NULL); xmlNewNsProp(psNode, NULL, BAD_CAST "definition", BAD_CAST "urn:ogc:phenomenon:time:iso8601"); } /*add all other fields*/ /*assuming that the layer is open */ for(i=0; inumitems; i++) { snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[i]); pszValue = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (pszValue) { psNode = xmlNewChild(psRecordNode, NULL, BAD_CAST "field", NULL); /* check if there is an alias/full name used */ snprintf(szTmp, sizeof(szTmp), "%s_alias", lp->items[i]); pszName = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (!pszName) pszName = lp->items[i]; xmlNewNsProp(psNode, NULL, BAD_CAST "name", BAD_CAST pszName); psNode = xmlNewChild(psNode, NULL, BAD_CAST "Quantity", NULL); /* get definition and uom */ snprintf(szTmp, sizeof(szTmp), "%s_definition", lp->items[i]); pszDefinition = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (pszDefinition == NULL) pszDefinition = "urn:ogc:object:definition"; xmlNewNsProp(psNode, NULL, BAD_CAST "definition", BAD_CAST pszDefinition); snprintf(szTmp, sizeof(szTmp), "%s_uom", lp->items[i]); pszUom = msOWSLookupMetadata(&(lp->metadata), "S", szTmp); if (pszUom == NULL) pszUom = "urn:ogc:object:uom"; psNode = xmlNewChild(psNode, NULL, BAD_CAST "uom", NULL); xmlNewNsProp(psNode, NULL, BAD_CAST "code", BAD_CAST pszUom); } } /* -------------------------------------------------------------------- */ /* Add encoding block. */ /* -------------------------------------------------------------------- */ pszBlockSep = msOWSLookupMetadata(&(lp->map->web.metadata), "S", "encoding_blockSeparator"); pszTokenSep = msOWSLookupMetadata(&(lp->map->web.metadata), "S", "encoding_tokenSeparator"); psSubNode = xmlNewChild(psEncNode, NULL, BAD_CAST "TextBlock", NULL); if (pszTokenSep) pszTokenValue = msStringConcatenate(pszTokenValue, (char *)pszTokenSep); else pszTokenValue = msStringConcatenate(pszTokenValue, ","); xmlNewNsProp(psSubNode, NULL, BAD_CAST "tokenSeparator", BAD_CAST pszTokenValue); if (pszBlockSep) pszBlockValue = msStringConcatenate(pszBlockValue, (char *)pszBlockSep); else pszBlockValue = msStringConcatenate(pszBlockValue, "\n"); xmlNewNsProp(psSubNode, NULL, BAD_CAST "blockSeparator", BAD_CAST pszBlockValue); xmlNewNsProp(psSubNode, NULL, BAD_CAST "decimalSeparator", BAD_CAST "."); msFree(pszTokenValue); msFree(pszBlockValue); } } /************************************************************************/ /* msSOSAddMemberNode */ /* */ /* Add a memeber node corresponding to a feature. */ /* Assuming that the layer is opened and msLayerGetItems is */ /* called on it. */ /************************************************************************/ void msSOSAddMemberNode(xmlNsPtr psNsGml, xmlNsPtr psNsOm, xmlNsPtr psNsSwe, xmlNsPtr psNsXLink, xmlNsPtr psNsMs, xmlNodePtr psParent, mapObj *map, layerObj *lp, int iFeatureId, const char *script_url, const char *opLayerName) { xmlNodePtr psObsNode, psNode, psLayerNode = NULL; const char *pszValue = NULL; char *pszEpsg = NULL; int status,i,j; shapeObj sShape; char szTmp[256]; layerObj *lpfirst = NULL; const char *pszTimeField = NULL; char *pszTmp = NULL; char *pszOid = NULL; char *pszTime = NULL; char *pszValueShape = NULL; const char *pszFeatureId = NULL; if (psParent) { msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lp->resultcache->results[iFeatureId])); if(status != MS_SUCCESS) { xmlFreeNs(psNsOm); return; } psNode = xmlNewChild(psParent, NULL, BAD_CAST "member", NULL); psObsNode = xmlNewChild(psNode, NULL, BAD_CAST "Observation", BAD_CAST pszValue); pszFeatureId = msOWSLookupMetadata(&(lp->metadata), "OSG", "featureid"); if(pszFeatureId && msLayerGetItems(lp) == MS_SUCCESS) { /* find the featureid amongst the items for this layer */ for(j=0; jnumitems; j++) { if(strcasecmp(lp->items[j], pszFeatureId) == 0) { /* found it */ break; } } if (jnumitems) { pszOid = msStringConcatenate(pszOid, "o_"); pszOid = msStringConcatenate(pszOid, sShape.values[j]); xmlNewNsProp(psObsNode, psNsGml, BAD_CAST "id", BAD_CAST pszOid); } } /* order of elements is time, location, procedure, observedproperty featureofinterest, result */ /* time*/ pszTimeField = msOWSLookupMetadata(&(lp->metadata), "SO", "timeitem"); if (pszTimeField && sShape.values) { for(i=0; inumitems; i++) { if (strcasecmp(lp->items[i], pszTimeField) == 0) { if (sShape.values[i] && strlen(sShape.values[i]) > 0) { pszTime = msStringConcatenate(pszTime, sShape.values[i]); psNode = xmlNewChild(psObsNode, psNsOm, BAD_CAST "samplingTime", NULL); xmlAddChild(psNode, msGML3TimeInstant(psNsGml, pszTime)); msFree(pszTime); } break; } } } /*TODO add location*/ /*procedure*/ /* if a procedure_item is defined, we should extract the value for the attributes. If not dump what is found in the procedure metadata bug 2054*/ if ((pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item"))) { lpfirst = msSOSGetFirstLayerForOffering(map, msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"), msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id")); if (lp != lpfirst) status = msLayerOpen(lpfirst); if (status == MS_SUCCESS && msLayerGetItems(lpfirst) == MS_SUCCESS) { for(i=0; inumitems; i++) { if (strcasecmp(lpfirst->items[i], pszValue) == 0) { break; } } if (i < lpfirst->numitems) { snprintf(szTmp, sizeof(szTmp), "%s", "urn:ogc:def:procedure:"); pszTmp = msStringConcatenate(pszTmp, szTmp); pszValueShape = msEncodeHTMLEntities(sShape.values[i]); pszTmp = msStringConcatenate(pszTmp, pszValueShape); psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "procedure", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp = NULL; msFree(pszValueShape); } /*else should we generate a warning !*/ if (lp != lpfirst) msLayerClose(lpfirst); } } else if ((pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "procedure"))) { if (! msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item")) xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_procedure_item\" missing for sos:procedure. If you have more than 1 procedures, sos:procedure will output them incorrectly.")); snprintf(szTmp, sizeof(szTmp), "%s", "urn:ogc:def:procedure:"); pszTmp = msStringConcatenate(pszTmp, szTmp); pszTmp = msStringConcatenate(pszTmp, (char *)pszValue); psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "procedure", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp = NULL; } /*observed property*/ pszValue = msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id"); if (pszValue) msSOSAddPropertyNode(psNsSwe, psNsXLink, psObsNode, lp, psNsGml, pszOid); msFree(pszOid); pszOid = NULL; /*TODO add featureofinterest*/ pszTmp = msStringConcatenate(pszTmp, (char *) script_url); pszTmp = msStringConcatenate(pszTmp, "service=WFS&version=1.1.0&request=DescribeFeatureType&typename="); pszTmp = msStringConcatenate(pszTmp, (char *) opLayerName); psNode = xmlNewChild(psObsNode, psNsOm, BAD_CAST "featureOfInterest", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp=NULL; /* add result : gml:featureMember of all selected elements */ psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "result", NULL); /*TODO should we add soemwhere the units of the value : 29.00 */ #ifdef USE_PROJ if(msProjectionsDiffer(&(lp->projection), &(map->projection))) msProjectShape(&lp->projection, &lp->projection, &sShape); #endif psNode = xmlNewChild(psNode, psNsGml, BAD_CAST "featureMember", NULL); /* xmlSetNs(psNode,xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); */ /*TODO : add namespaces like wfs " ms and a url to mapserve ? */ psLayerNode = xmlNewChild(psNode, psNsMs, BAD_CAST lp->name, NULL); /* fetch gml:id */ pszFeatureId = msOWSLookupMetadata(&(lp->metadata), "OSG", "featureid"); if(pszFeatureId && msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) xmlSetNs(psLayerNode,psNsMs); /*bbox*/ #ifdef USE_PROJ msOWSGetEPSGProj(&(map->projection), &(lp->metadata), "SO", MS_TRUE, &pszEpsg); if (!pszEpsg) msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "SO", MS_TRUE, &pszEpsg); if (msProjectionsDiffer(&map->projection, &lp->projection) == MS_TRUE) msProjectRect(&lp->projection, &map->projection, &sShape.bounds); #endif psNode = xmlAddChild(psLayerNode, msGML3BoundedBy(psNsGml, sShape.bounds.minx, sShape.bounds.miny, sShape.bounds.maxx, sShape.bounds.maxy, pszEpsg)); /*geometry*/ msSOSAddGeometryNode(psNsGml, psNsMs, psLayerNode, map, lp, &sShape, pszEpsg); msFree(pszEpsg); /*attributes */ /* TODO only output attributes where there is a sos_%s_alias (to be discussed)*/ /* the first layer is the one that has to have all the metadata defined */ lpfirst = msSOSGetFirstLayerForOffering(map, msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"), msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id")); if (lpfirst && msLayerOpen(lpfirst) == MS_SUCCESS && msLayerGetItems(lpfirst) == MS_SUCCESS) { for(i=0; inumitems; i++) { snprintf(szTmp, sizeof(szTmp), "%s_alias", lpfirst->items[i]); pszValue = msOWSLookupMetadata(&(lpfirst->metadata), "S", szTmp); if (pszValue) { for (j=0; jnumitems; j++) { if (strcasecmp(lpfirst->items[i], lpfirst->items[j]) == 0) { /*if there is an alias used, use it to output the parameter name : eg "sos_AMMON_DIS_alias" "Amonia" */ snprintf(szTmp, sizeof(szTmp), "%s_alias", lpfirst->items[i]); pszValue = msOWSLookupMetadata(&(lpfirst->metadata), "S", szTmp); pszValueShape = msEncodeHTMLEntities(sShape.values[j]); if (pszValue) { pszTmp = msEncodeHTMLEntities(pszValue); psNode = xmlNewChild(psLayerNode, psNsMs, BAD_CAST pszValue, BAD_CAST pszValueShape); free(pszTmp); } else { pszTmp = msEncodeHTMLEntities(lpfirst->items[i]); psNode = xmlNewChild(psLayerNode, psNsMs, BAD_CAST lpfirst->items[i], BAD_CAST pszValueShape); free(pszTmp); } free(pszValueShape); xmlSetNs(psNode,psNsMs); break; } } } } if (lp->index != lpfirst->index) msLayerClose(lpfirst); } msFreeShape(&sShape); } } /************************************************************************/ /* msSOSReturnMemberResult */ /* */ /* Add a result string to the result node (used for */ /* GetObservation using "observation" as the response output. */ /* Assuming here that the layer is already opened. */ /************************************************************************/ char* msSOSReturnMemberResult(layerObj *lp, int iFeatureId, char **ppszProcedure) { char *pszFinalValue = NULL; shapeObj sShape; int i, j, status; layerObj *lpfirst; const char *pszTimeField = NULL, *pszValue=NULL, *pszProcedureField=NULL; char *pszValueShape = NULL; char szTmp[100]; const char *pszSep=NULL; msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lp->resultcache->results[iFeatureId])); if(status != MS_SUCCESS) return NULL; pszTimeField = msOWSLookupMetadata(&(lp->metadata), "SO", "timeitem"); if (pszTimeField && sShape.values) { for(i=0; inumitems; i++) { if (strcasecmp(lp->items[i], pszTimeField) == 0) { pszFinalValue = msStringConcatenate(pszFinalValue, sShape.values[i]); break; } } } if (ppszProcedure) { pszProcedureField = msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item"); for(i=0; inumitems; i++) { if (strcasecmp(lp->items[i], pszProcedureField) == 0) { (*ppszProcedure) = msStrdup( sShape.values[i]); break; } } } /* the first layer is the one that has to have all the metadata defined */ lpfirst = msSOSGetFirstLayerForOffering(lp->map, msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"), msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id")); if (lp == lpfirst || (lpfirst && msLayerOpen(lpfirst) == MS_SUCCESS && msLayerGetItems(lpfirst) == MS_SUCCESS)) { pszSep = msOWSLookupMetadata(&(lp->map->web.metadata), "S", "encoding_tokenSeparator"); for(i=0; inumitems; i++) { snprintf(szTmp, sizeof(szTmp), "%s_alias", lpfirst->items[i]); pszValue = msOWSLookupMetadata(&(lpfirst->metadata), "S", szTmp); if (pszValue) { for (j=0; jnumitems; j++) { if (strcasecmp(lpfirst->items[i], lpfirst->items[j]) == 0) { pszValueShape = msEncodeHTMLEntities(sShape.values[j]); if (pszFinalValue) { if (pszSep) pszFinalValue = msStringConcatenate(pszFinalValue, (char *)pszSep); else pszFinalValue = msStringConcatenate(pszFinalValue, ","); } pszFinalValue = msStringConcatenate(pszFinalValue, pszValueShape); msFree(pszValueShape); } } } } } msFreeShape(&sShape); return pszFinalValue; } /************************************************************************/ /* msSOSAddMemberNodeObservation */ /* */ /* Add a member node used for getObservation request using */ /* Observation as the result format. */ /************************************************************************/ xmlNodePtr msSOSAddMemberNodeObservation(xmlNsPtr psNsGml, xmlNsPtr psNsSos, xmlNsPtr psNsOm, xmlNsPtr psNsSwe, xmlNsPtr psNsXLink, xmlNodePtr psParent, mapObj *map, layerObj *lp, const char *pszProcedure) { char *pszTmp = NULL; xmlNodePtr psNode=NULL, psObsNode=NULL, psMemberNode=NULL; layerObj *lpfirst; const char *value = NULL; /*always featch the first layer that has the same offering id and observered propery. This allows to only define all the attributes and components on the first layer if the user wants to present several mapserver layers as the same offering.*/ lpfirst = msSOSGetFirstLayerForOffering(map, msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"), msOWSLookupMetadata(&(lp->metadata), "S", "observedproperty_id")); if (psParent) { psMemberNode = xmlNewChild(psParent, NULL, BAD_CAST "member", NULL); psObsNode = xmlNewChild(psMemberNode, NULL, BAD_CAST "Observation", NULL); /*time*/ /* ??TODO : sampling time is a manadatory element but uses a non mandatory metadata sos_offering_timeextent */ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_timeextent"); if (value) { char **tokens; int n; char *pszEndTime = NULL; tokens = msStringSplit(value, '/', &n); if (tokens==NULL || (n != 1 && n!=2)) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_timeextent.", "msSOSGetObservation()"); msSOSException(map, "sos_offering_timeextent", "InvalidParameterValue"); return NULL; } if (n == 2) /* end time is empty. It is going to be set as "now*/ pszEndTime = tokens[1]; psNode = xmlAddChild(psObsNode, msSOSAddTimeNode(psNsOm, psNsGml, tokens[0], pszEndTime)); msFreeCharArray(tokens, n); } /* procedure */ if (pszProcedure) { /*this should always be true since procedure is a manadtory element*/ if (! msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item") && msOWSLookupMetadata(&(lp->metadata), "S", "procedure")) xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_procedure_item\" missing for sos:procedure. If you have more than 1 procedures, sos:procedure will output them incorrectly.")); pszTmp = msStringConcatenate(pszTmp, "urn:ogc:def:procedure:"); pszTmp = msStringConcatenate(pszTmp, (char *)pszProcedure); psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "procedure", NULL); /* xmlNewNsProp(psNode, xmlNewNs(NULL, BAD_CAST "http://www.w3.org/1999/xlink", BAD_CAST "xlink"), BAD_CAST "href", BAD_CAST pszTmp); */ xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp = NULL; } /*observed propery and components*/ if (lp != lpfirst && msLayerOpen(lpfirst) == MS_SUCCESS && msLayerGetItems(lpfirst) == MS_SUCCESS) { msSOSAddPropertyNode(psNsSwe, psNsXLink, psObsNode, lpfirst, psNsGml, NULL); msLayerClose(lpfirst); } else msSOSAddPropertyNode(psNsSwe, psNsXLink, psObsNode, lpfirst, psNsGml, NULL); /* result definition*/ psNode = xmlNewChild(psObsNode, NULL, BAD_CAST "resultDefinition", NULL); msSOSAddDataBlockDefinition(psNsSwe, psNode, lpfirst); } return psObsNode; } /************************************************************************/ /* msSOSParseTimeGML */ /* */ /* Utility function to convert a gml time value to a */ /* string. Supported gml times are : */ /* */ /* - */ /* 2005-09-01T11:54:32 */ /* 2005-09-02T14:54:32 */ /* */ /* This will be converted to startime/endtime */ /* */ /* - */ /* 2003-02-13T12:28-08:00*/ /* */ /* This will retunr the timevalue as a string. */ /* */ /* The caller of the function should free the return value. */ /************************************************************************/ char *msSOSParseTimeGML(char *pszGmlTime) { char *pszReturn = NULL, *pszBegin = NULL, *pszEnd = NULL; CPLXMLNode *psRoot=NULL, *psChild=NULL; CPLXMLNode *psTime=NULL, *psBegin=NULL, *psEnd=NULL; struct tm tm_struct; if (pszGmlTime) { psRoot = CPLParseXMLString(pszGmlTime); if(!psRoot) return NULL; CPLStripXMLNamespace(psRoot, "gml", 1); if (psRoot->eType == CXT_Element && (EQUAL(psRoot->pszValue,"TimePeriod") || EQUAL(psRoot->pszValue,"TimeInstant"))) { if (EQUAL(psRoot->pszValue,"TimeInstant")) { psChild = psRoot->psChild; if (psChild && EQUAL(psChild->pszValue,"timePosition")) { psTime = psChild->psNext; if (psTime && psTime->pszValue && psTime->eType == CXT_Text) { if (msParseTime(psTime->pszValue, &tm_struct) == MS_TRUE) pszReturn = msStrdup(psTime->pszValue); } } } else { psBegin = psRoot->psChild; if (psBegin) psEnd = psBegin->psNext; if (psBegin && EQUAL(psBegin->pszValue, "beginPosition") && psEnd && EQUAL(psEnd->pszValue, "endPosition")) { if (psBegin->psChild && psBegin->psChild->pszValue && psBegin->psChild->eType == CXT_Text) pszBegin = msStrdup( psBegin->psChild->pszValue); if (psEnd->psChild && psEnd->psChild->pszValue && psEnd->psChild->eType == CXT_Text) pszEnd = msStrdup(psEnd->psChild->pszValue); if (pszBegin && pszEnd) { if (msParseTime(pszBegin, &tm_struct) == MS_TRUE && msParseTime(pszEnd, &tm_struct) == MS_TRUE) { pszReturn = msStrdup(pszBegin); pszReturn = msStringConcatenate(pszReturn, "/"); pszReturn = msStringConcatenate(pszReturn, pszEnd); } } msFree(pszBegin); msFree(pszEnd); } } } } CPLDestroyXMLNode(psRoot); return pszReturn; } /************************************************************************/ /* msSOSGetCapabilities */ /* */ /* getCapabilities request handler. */ /************************************************************************/ int msSOSGetCapabilities(mapObj *map, sosParamsObj *sosparams, cgiRequestObj *req, owsRequestObj *ows_request) { xmlDocPtr psDoc = NULL; /* document pointer */ xmlNodePtr psRootNode, psMainNode, psNode; xmlNodePtr psOfferingNode; char *schemalocation = NULL; char *xsi_schemaLocation = NULL; char *script_url=NULL; const char *updatesequence=NULL; int i,j,k; layerObj *lp = NULL, *lpTmp = NULL; const char *value = NULL; char *pszTmp = NULL; char *pszProcedure = NULL; char szTmp[256]; /* array of offering */ char **papsOfferings = NULL; int nOfferings =0, nCurrentOff = -1; int nProperties = 0; char **papszProperties = NULL; int iItemPosition = -1; shapeObj sShape; int status; /* for each layer it indicates the indice to be used in papsOfferings (to associate it with the offering) */ int *panOfferingLayers = NULL; char **papsProcedures = NULL; int nDistinctProcedures =0; xmlNsPtr psNsGml = NULL; xmlNsPtr psNsSos = NULL; xmlNsPtr psNsOws = NULL; xmlNsPtr psNsOgc = NULL; xmlNsPtr psNsXLink = NULL; xmlNsPtr psNsSwe = NULL; xmlChar *buffer = NULL; int size = 0; msIOContext *context = NULL; int ows_version = OWS_1_1_0; int sosSupportedVersions[] = {OWS_1_0_0}; int sosNumSupportedVersions = 1; /* acceptversions: do OWS Common style of version negotiation */ if (sosparams->pszAcceptVersions) { char **tokens; int i, j, k=-1; tokens = msStringSplit(sosparams->pszAcceptVersions, ',', &j); for (i=0; ipszAcceptVersions, pszSOSVersion); return msSOSException(map, "acceptversions", "VersionNegotiationFailed"); } } /* updateSequence */ updatesequence = msOWSLookupMetadata(&(map->web.metadata), "SO", "updatesequence"); if (sosparams->pszUpdateSequence != NULL) { i = msOWSNegotiateUpdateSequence(sosparams->pszUpdateSequence, updatesequence); if (i == 0) { /* current */ msSetError(MS_SOSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msSOSGetCapabilities()", sosparams->pszUpdateSequence, updatesequence); return msSOSException(map, "updatesequence", "CurrentUpdateSequence"); } if (i > 0) { /* invalid */ msSetError(MS_SOSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msSOSGetCapabilities()", sosparams->pszUpdateSequence, updatesequence); return msSOSException(map, "updatesequence", "InvalidUpdateSequence"); } } psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "Capabilities"); xmlDocSetRootElement(psDoc, psRootNode); psNsGml = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"); psNsSos = xmlNewNs(NULL, BAD_CAST pszSOSNamespaceUri, BAD_CAST pszSOSNamespacePrefix); psNsOgc = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX); psNsSwe = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/swe/1.0.1", BAD_CAST "swe"); /* name spaces */ xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/om/1.0", BAD_CAST "om")); psNsOws = xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows"); xmlSetNs(psRootNode, psNsOws ); xmlSetNs(psRootNode,xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/swe/1.0.1", BAD_CAST "swe")); psNsXLink = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); xmlSetNs(psRootNode, psNsXLink ); xmlSetNs(psRootNode,xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST pszSOSNamespaceUri, BAD_CAST pszSOSNamespacePrefix)); /*version fixed for now*/ xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST pszSOSVersion); value = msOWSLookupMetadata(&(map->web.metadata), "SO", "updatesequence"); if (value) xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST value); /*schema fixed*/ schemalocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) ); xsi_schemaLocation = msStrdup(pszSOSNamespaceUri); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/sos/"); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *)pszSOSVersion); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/sosGetCapabilities.xsd"); xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation); xmlAddChild(psRootNode, xmlNewComment(BAD_CAST msGetVersion())); /*service identification*/ xmlAddChild(psRootNode, msOWSCommonServiceIdentification(psNsOws, map, "SOS", pszSOSVersion, "SO", NULL)); /*service provider*/ xmlAddChild(psRootNode, msOWSCommonServiceProvider(psNsOws, psNsXLink, map, "SO", NULL)); /*operation metadata */ if ((script_url=msOWSGetOnlineResource(map, "SO", "onlineresource", req)) == NULL) return msSOSException(map, "NoApplicableCode", "NoApplicableCode"); psMainNode = xmlAddChild(psRootNode, msOWSCommonOperationsMetadata(psNsOws)); psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetCapabilities", OWS_METHOD_GETPOST, (char *) script_url)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "service", "SOS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "version", (char *)pszSOSVersion)); if (msOWSRequestIsEnabled(map, NULL, "S", "DescribeSensor", MS_TRUE)) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"DescribeSensor", OWS_METHOD_GETPOST, (char *) script_url)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "service", "SOS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "version", (char *)pszSOSVersion)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "sensorid", "urn:ogc:object:procedure")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "outputFormat", (char *)pszSOSDescribeSensorMimeType)); } if (msOWSRequestIsEnabled(map, NULL, "S", "DescribeObservationType", MS_TRUE)) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"DescribeObservationType", OWS_METHOD_GETPOST, (char *) script_url)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "service", "SOS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "version", (char *)pszSOSVersion)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "observedproperty", "urn:ogc:object:observedproperty")); } if (msOWSRequestIsEnabled(map, NULL, "S", "GetObservation", MS_TRUE)) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetObservation", OWS_METHOD_GETPOST, (char *) script_url)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "service", "SOS")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "version", (char *)pszSOSVersion)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "offering", "urn:ogc:object:offering")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "observedproperty", "urn:ogc:object:observedproperty")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "eventtime", "sos:time")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "procedure", "urn:ogc:object:sensor")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "featureofinterest", "gml:location")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "result", "ogc:Filter")); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "responseFormat", (char *)pszSOSGetObservationMimeType)); xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Parameter", "resultModel", "Observation,Measurement")); } value = msOWSLookupMetadata(&(map->web.metadata), "SO", "maxfeatures"); if (value) { psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,"Constraint", "DefaultMaxFeatures", (char *)value)); } /* */ xmlAddChild(psRootNode, FLTGetCapabilities(psNsSos, psNsOgc, MS_TRUE)); /*Offerings */ psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Contents", NULL); psMainNode = xmlNewChild(psNode, NULL, BAD_CAST "ObservationOfferingList", NULL); /*go through the layers and check for metadata sos_offering_id. One or more layers could have the same offering id. In that case they are adverized as the same offering. The first layer that has*/ if (map->numlayers) { papsOfferings = (char **)malloc(sizeof(char *)*map->numlayers); panOfferingLayers = (int *)malloc(sizeof(int)*map->numlayers); for (i=0; inumlayers; i++) panOfferingLayers[i] = -1; for (i=0; inumlayers; i++) { lp = (GET_LAYER(map, i)); if (lp->status == MS_DELETE) continue; value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_id"); if (value && (msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers))) { nCurrentOff = -1; for (j=0; j= 0) /* existing offering */ panOfferingLayers[i] = nCurrentOff; else { /*new offering */ papsOfferings[nOfferings] = msStrdup(value); panOfferingLayers[i] = nOfferings; nOfferings++; } } } if (nOfferings > 0) { for (i=0; inumlayers; j++) { if (panOfferingLayers[j] == i) /*first layer of the offering */ break; } lp = (GET_LAYER(map, j)); /*description*/ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_description"); if (value) psNode = xmlNewChild(psOfferingNode, psNsGml, BAD_CAST "description", BAD_CAST value); else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_offering_description\" missing for gml:description")); /*name*/ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_name"); if (value) psNode = xmlNewChild(psOfferingNode, psNsGml, BAD_CAST "name", BAD_CAST value); else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_offering_name\" missing for gml:name")); /* srsName */ value = msOWSLookupMetadata(&(map->web.metadata), "SO", "srs"); if (value) msLibXml2GenerateList(psOfferingNode, psNsGml, "srsName", value, ' '); else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Required metadata \"sos_srs\" missing for gml:srsName")); /*bounding box */ /*TODO : if sos_offering_extent does not exist compute extents Check also what happen if epsg not present */ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_extent"); if (value) { char **tokens,*pszLayerEPSG; int n; tokens = msStringSplit(value, ',', &n); if (tokens==NULL || n != 4) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_extent.", "msSOSGetCapabilities()"); return msSOSException(map, "sos_offering_extent", "InvalidParameterValue"); } msOWSGetEPSGProj(&(lp->projection),&(lp->metadata), "SO", MS_TRUE,&pszLayerEPSG); if (pszLayerEPSG) { psNode = xmlAddChild(psOfferingNode, msGML3BoundedBy(psNsGml, atof(tokens[0]), atof(tokens[1]), atof(tokens[2]), atof(tokens[3]), pszLayerEPSG)); msFree(pszLayerEPSG); } msFreeCharArray(tokens, n); } /* intended application */ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_intendedapplication"); if (value) psNode = xmlNewChild(psOfferingNode, psNsSos, BAD_CAST "intendedApplication", BAD_CAST value); else xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"sos_offering_intendedapplication\" missing for sos:intendedApplication")); /*time*/ value = msOWSLookupMetadata(&(lp->metadata), "S", "offering_timeextent"); if (value) { char **tokens; int n; char *pszEndTime = NULL; tokens = msStringSplit(value, '/', &n); if (tokens==NULL || (n != 1 && n!=2)) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_timeextent.", "msSOSGetCapabilities()"); return msSOSException(map, "sos_offering_timeextent", "InvalidParameterValue"); } if (n == 2) /* end time is empty. It is going to be set as "now*/ pszEndTime = tokens[1]; psNode = xmlAddChild(psOfferingNode, msSOSAddTimeNode(psNsSos, psNsGml, tokens[0], pszEndTime)); msFreeCharArray(tokens, n); } /*procedure : output all procedure links for the offering */ for (j=0; jnumlayers; j++) { if (panOfferingLayers[j] == i) { value = msOWSLookupMetadata(&(GET_LAYER(map, j)->metadata), "S", "procedure"); if (value && strlen(value) > 0) { /*value could be a list of procedure*/ char **tokens; int n = 0; tokens = msStringSplit(value, ' ', &n); for (k=0; kmetadata), "S", "procedure_item"))) { /* if a procedure_item is used, it means that the procedure (or sensor) need to be extracted from the data. Thus we need to query the layer and get the values from each feature */ lpTmp = GET_LAYER(map,j); if (lpTmp->template == NULL) lpTmp->template = msStrdup("ttt"); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = j; map->query.rect = map->extent; msQueryByRect(map); /*check if the attribute specified in the procedure_item is available on the layer*/ iItemPosition = -1; if (msLayerGetItems(lpTmp) == MS_SUCCESS && lpTmp->resultcache && lpTmp->resultcache->numresults > 0) { for(k=0; knumitems; k++) { if (strcasecmp(lpTmp->items[k], value) == 0) { iItemPosition = k; break; } } if (iItemPosition == -1) { msSetError(MS_SOSERR, "procedure_item %s could not be found on the layer %s", "msSOSGetCapabilities()", value, lpTmp->name); return msSOSException(map, "mapserv", "NoApplicableCode"); } /*for each selected feature, grab the value of the prodedire_item*/ /* do not duplicate sensor ids if they are the same */ /*keep list of distinct procedures*/ papsProcedures = (char **)malloc(sizeof(char *) * lpTmp->resultcache->numresults); nDistinctProcedures = 0; for(k=0; kresultcache->numresults; k++) papsProcedures[k] = NULL; for(k=0; kresultcache->numresults; k++) { msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lpTmp->resultcache->results[k])); if(status != MS_SUCCESS) continue; if (sShape.values[iItemPosition]) { pszProcedure = msStringConcatenate(pszProcedure, sShape.values[iItemPosition]); if (!_IsInList(papsProcedures, nDistinctProcedures, pszProcedure)) { papsProcedures[nDistinctProcedures] = msStrdup(pszProcedure); nDistinctProcedures++; snprintf(szTmp, sizeof(szTmp), "%s", "urn:ogc:def:procedure:"); pszTmp = msStringConcatenate(pszTmp, szTmp); pszTmp = msStringConcatenate(pszTmp, pszProcedure); psNode = xmlNewChild(psOfferingNode, NULL, BAD_CAST "procedure", NULL); xmlNewNsProp(psNode, xmlNewNs(NULL, BAD_CAST "http://www.w3.org/1999/xlink", BAD_CAST "xlink"), BAD_CAST "href", BAD_CAST pszTmp); msFree(pszTmp); pszTmp = NULL; } msFree(pszProcedure); pszProcedure = NULL; } } for(k=0; kresultcache->numresults; k++) if (papsProcedures[k] != NULL) msFree(papsProcedures[k]); msFree(papsProcedures); } else { msSetError(MS_SOSERR, "Invalid procedure %s", "msSOSGetCapabilities()", value); return msSOSException(map, "procedure", "InvalidParameterValue"); } } else { msSetError(MS_SOSERR, "Mandatory metadata procedure_item could not be found on the layer %s", "msSOSGetCapabilities()", GET_LAYER(map,j)->name); return msSOSException(map, "mapserv", "NoApplicableCode"); } } } /*observed property */ /* observed property are equivalent to layers. We can group sevaral layers using the same sos_observedproperty_id. The components are the attributes. Components are exposed using the metadata sos_%s_aliasl */ nProperties = 0; papszProperties = (char **)malloc(sizeof(char *)*map->numlayers); for (j=0; jnumlayers; j++) { if (panOfferingLayers[j] == i) { if ((value = msOWSLookupMetadata(&(GET_LAYER(map, j)->metadata), "S", "observedproperty_id"))) { for (k=0; k 0) { for (i=0; iweb.metadata), "SO", "encoding", OWS_NOERR, "\n", "ISO-8859-1"); */ /*xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1);*/ /* xmlDocDump crashs withe the prebuild windows binaries distibutes at the libxml site???. It works with locally build binaries*/ context = msIO_getHandler(stdout); xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, ("UTF-8"), 1); msIO_contextWrite(context, buffer, size); xmlFree(buffer); /*free buffer and the document */ /*xmlFree(buffer);*/ xmlFreeDoc(psDoc); xmlFreeNs(psNsGml); xmlFreeNs(psNsSos); xmlFreeNs(psNsOgc); xmlFreeNs(psNsSwe); free(xsi_schemaLocation); free(schemalocation); msFree(script_url); /* *Free the global variables that may *have been allocated by the parser. */ xmlCleanupParser(); return(MS_SUCCESS); /* nSize = sizeof(workbuffer); nSize = nSize-1;*/ /* the last character for the '\0' */ /* if (size > nSize) { iIndice = 0; while ((iIndice + nSize) <= size) { snprintf(workbuffer, (sizeof(workbuffer)-1), "%s", buffer+iIndice ); workbuffer[sizeof(workbuffer)-1] = '\0'; msIO_printf("%s", workbuffer); iIndice +=nSize; } if (iIndice < size) { sprintf(workbuffer, "%s", buffer+iIndice ); msIO_printf("%s", workbuffer); } } else { msIO_printf("%s", buffer); } */ } /************************************************************************/ /* msSOSGetObservation */ /* */ /* GetObservation request handler */ /************************************************************************/ int msSOSGetObservation(mapObj *map, sosParamsObj *sosparams, cgiRequestObj *req, owsRequestObj *ows_request) { char *schemalocation = NULL; char *xsi_schemaLocation = NULL; const char *pszTmp = NULL, *pszTmp2 = NULL; const char *user_namespace_uri = "http://mapserver.gis.umn.edu/mapserver"; const char *user_namespace_prefix = "ms"; char *script_url=NULL; int i, j, k, bLayerFound = 0; layerObj *lp = NULL, *lpfirst = NULL; const char *pszTimeExtent=NULL, *pszTimeField=NULL, *pszValue=NULL; FilterEncodingNode *psFilterNode = NULL; rectObj sBbox; xmlDocPtr psDoc = NULL; xmlNodePtr psRootNode, psNode; char **tokens=NULL, **tokens1; int n=0, n1=0; xmlNsPtr psNsGml = NULL; xmlNsPtr psNsOm = NULL; xmlNsPtr psNsSwe = NULL; xmlNsPtr psNsXLink = NULL; xmlNsPtr psNsSos = NULL; xmlNsPtr psNsMs = NULL; const char *opLayerName = NULL; char *pszBuffer = NULL; const char *pszProcedureItem = NULL; int bSpatialDB = 0; xmlChar *buffer = NULL; int size = 0; msIOContext *context = NULL; xmlNodePtr psObservationNode = NULL, psResultNode=NULL; const char *pszProcedure = NULL; const char *pszBlockSep=NULL; int nDiffrentProc = 0; SOSProcedureNode *paDiffrentProc = NULL; int iItemPosition, status; shapeObj sShape; char* pszEscapedStr = NULL; sBbox = map->extent; /* establish local namespace */ pszTmp = msOWSLookupMetadata(&(map->web.metadata), "SFO", "namespace_uri"); if(pszTmp) user_namespace_uri = pszTmp; pszTmp = msOWSLookupMetadata(&(map->web.metadata), "SFO", "namespace_prefix"); if(pszTmp) user_namespace_prefix = pszTmp; /* validates mandatory request elements */ if (!sosparams->pszOffering) { msSetError(MS_SOSERR, "Missing OFFERING parameter.", "msSOSGetObservation()"); return msSOSException(map, "offering", "MissingParameterValue"); } if (!sosparams->pszObservedProperty) { msSetError(MS_SOSERR, "Missing OBSERVEDPROPERTY parameter.", "msSOSGetObservation()"); return msSOSException(map, "observedproperty", "MissingParameterValue"); } if (!sosparams->pszResponseFormat) { msSetError(MS_SOSERR, "Missing RESPONSEFORMAT parameter.", "msSOSGetObservation()"); return msSOSException(map, "responseformat", "MissingParameterValue"); } if (strcasecmp(sosparams->pszResponseFormat, pszSOSGetObservationMimeType) != 0) { msSetError(MS_SOSERR, "Invalid RESPONSEFORMAT parameter %s. Allowable values are: %s", "msSOSGetObservation()", sosparams->pszResponseFormat, pszSOSGetObservationMimeType); return msSOSException(map, "responseformat", "InvalidParameterValue"); } if (sosparams->pszResponseMode && strcasecmp(sosparams->pszResponseMode, "inline") != 0) { msSetError(MS_SOSERR, "Invalid RESPONSEMODE parameter %s. Allowable values are: \"inline\"", "msSOSGetObservation()", sosparams->pszResponseMode); return msSOSException(map, "responsemode", "InvalidParameterValue"); } /*validate if offering exists*/ for (i=0; inumlayers; i++) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"); if (pszTmp && (strcasecmp(pszTmp, sosparams->pszOffering) == 0) && (msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers))) break; } if (i==map->numlayers) { msSetError(MS_SOSERR, "Offering %s not found. A layer might be disabled for \ this request. Check sos/ows_enable_request settings.", "msSOSGetObservation()", sosparams->pszOffering); return msSOSException(map, "offering", "InvalidParameterValue"); } /*validate if observed property exist*/ /* Allow more the 1 oberved property comma separated (specs is unclear on it). If we do it, we need to see if other parameters like result (filter encoding) should be given for each property too) */ bLayerFound = 0; tokens = msStringSplit(sosparams->pszObservedProperty, ',', &n); for (i=0; inumlayers; i++) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"); pszTmp2 = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "observedproperty_id"); GET_LAYER(map, i)->status = MS_OFF; if (pszTmp && pszTmp2) { if (strcasecmp(pszTmp, sosparams->pszOffering) == 0) { if (tokens && n > 0) { for (j=0; jstatus = MS_ON; /* opLayerName = msStrdup(GET_LAYER(map, i)->name); */ opLayerName = GET_LAYER(map, i)->name; /* Force setting a template to enable query. */ if (!GET_LAYER(map, i)->template) GET_LAYER(map, i)->template = msStrdup("ttt.html"); bLayerFound = 1; break; } } } } } } if (tokens && n > 0) msFreeCharArray(tokens, n); if (bLayerFound == 0) { msSetError(MS_SOSERR, "ObservedProperty %s not found.", "msSOSGetObservation()", sosparams->pszObservedProperty); return msSOSException(map, "observedproperty", "InvalidParameterValue"); } /* apply procedure : could be a comma separated list. set status to on those layers that have the sos_procedure metadata equals to this parameter. Note that the layer should already have it's status at ON by the offering,observedproperty filter done above */ if (sosparams->pszProcedure) { bLayerFound = 0; tokens = msStringSplit(sosparams->pszProcedure, ',', &n); if (tokens && n > 0) { for (i=0; inumlayers; i++) { if(GET_LAYER(map, i)->status == MS_ON) { pszValue = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "procedure"); if (pszValue) { /* the procedure metadata can be a list "sensor1 sensor2..."*/ tokens1 = msStringSplit(pszValue, ' ', &n1); for (j=0; jstatus = MS_OFF; if (tokens1) msFreeCharArray(tokens1, n1); if (bLayerFound == 0) { msSetError(MS_SOSERR, "Procedure %s not found.", "msSOSGetObservation()", sosparams->pszProcedure); msFreeCharArray(tokens, n); return msSOSException(map, "procedure", "InvalidParameterValue"); } } /* if there is a procedure_item defined on the layer, we will */ /* use it to set the filter parameter of the layer */ if ((GET_LAYER(map, i)->status == MS_ON) && (pszProcedureItem = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "procedure_item"))) { lp = GET_LAYER(map, i); /* HACK BEGIN */ if (msOWSLookupMetadata(&(GET_LAYER(map,i)->metadata), "S", "procedure") == NULL) { /* if sos_procedure_item is used, and sos_procedure is not, it means that */ /* the procedure or sensor) need to be extracted from the data. Thus we */ /* need to query the layer and get the values from each feature */ if (lp->template == NULL) lp->template = msStrdup("ttt"); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = i; map->query.rect = map->extent; msQueryByRect(map); /*check if the attribute specified in the procedure_item is available */ /*on the layer*/ iItemPosition = -1; if (msLayerGetItems(lp) == MS_SUCCESS && lp->resultcache && lp->resultcache->numresults > 0) { for(k=0; knumitems; k++) { if (strcasecmp(lp->items[k], pszProcedureItem) == 0) { iItemPosition = k; break; } } if (iItemPosition == -1) { msSetError(MS_SOSERR, "sos_procedure_item %s could not be found on the layer %s", "msSOSGetCapabilities()", pszProcedureItem, lp->name); return msSOSException(map, "mapserv", "NoApplicableCode"); } /*for each selected feature, grab the value of the procedure_item*/ bLayerFound = 0; for(k=0; kresultcache->numresults; k++) { msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lp->resultcache->results[k])); if(status != MS_SUCCESS) continue; if (sShape.values[iItemPosition]) { tokens = msStringSplit(sosparams->pszProcedure, ',', &n); for (j=0; jpszProcedure); return msSOSException(map, "procedure", "InvalidParameterValue"); } } } /* HACK END */ pszBuffer = NULL; if (&lp->filter) { if (lp->filter.string && strlen(lp->filter.string) > 0) msFreeExpression(&lp->filter); } /*The filter should reflect the underlying db*/ /*for ogr add a where clause */ bSpatialDB = 0; if (lp->connectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_OGR) bSpatialDB = 1; if (bSpatialDB) { if (lp->connectiontype != MS_OGR) pszBuffer = msStringConcatenate(pszBuffer, "("); else pszBuffer = msStringConcatenate(pszBuffer, "WHERE "); } else pszBuffer = msStringConcatenate(pszBuffer, "("); for (j=0; j 0) pszBuffer = msStringConcatenate(pszBuffer, " OR "); pszBuffer = msStringConcatenate(pszBuffer, "("); if (!bSpatialDB) { pszBuffer = msStringConcatenate(pszBuffer, "'["); pszBuffer = msStringConcatenate(pszBuffer, (char *)pszProcedureItem); } else { pszEscapedStr = msLayerEscapePropertyName(lp, (char *)pszProcedureItem); pszBuffer = msStringConcatenate(pszBuffer, pszEscapedStr); msFree(pszEscapedStr); pszEscapedStr = NULL; } if (!bSpatialDB) pszBuffer = msStringConcatenate(pszBuffer, "]'"); pszBuffer = msStringConcatenate(pszBuffer, " = '"); pszEscapedStr = msLayerEscapeSQLParam(lp, tokens[j]); pszBuffer = msStringConcatenate(pszBuffer, pszEscapedStr); msFree(pszEscapedStr); pszBuffer = msStringConcatenate(pszBuffer, "')"); } if (!bSpatialDB || lp->connectiontype != MS_OGR) pszBuffer = msStringConcatenate(pszBuffer, ")"); msLoadExpressionString(&lp->filter, pszBuffer); if (pszBuffer) msFree(pszBuffer); } } } msFreeCharArray(tokens, n); } } /* -------------------------------------------------------------------- */ /* supports 2 types of gml:Time : TimePeriod and TimeInstant : */ /* - */ /* 2005-09-01T11:54:32 */ /* 2005-09-02T14:54:32 */ /* */ /* */ /* - */ /* 2003-02-13T12:28-08:00*/ /* */ /* */ /* The user can specify mutilple times separated by commas. */ /* */ /* The gml will be parsed and trasformed into a sting tah */ /* looks like timestart/timeend,... */ /* -------------------------------------------------------------------- */ /*apply time filter if available */ if (sosparams->pszEventTime) { char **apszTimes = NULL; int numtimes = 0; char *pszTimeString = NULL, *pszTmp = NULL; /* Because SOS has specific TemporalOperator which extends FES 1.1, the time filter */ /* passed is different than what mapogcfilter (per 1.0.0) supports. */ /* */ /* Because, in XML POST mode, we traverse directly to gml:TimePeriod|gml:TimeInstant */ /* this is passed directly to mapogcfilter. */ /* for GET requests, we strip the parent element before passing */ pszTmp = msStrdup(sosparams->pszEventTime); pszTmp = msCaseReplaceSubstring(pszTmp, "", ""); pszTmp = msCaseReplaceSubstring(pszTmp, "", ""); pszTmp = msCaseReplaceSubstring(pszTmp, "", ""); pszTmp = msCaseReplaceSubstring(pszTmp, "", ""); apszTimes = msStringSplit (pszTmp, ',', &numtimes); msFree(pszTmp); if (numtimes >=1) { for (i=0; ipszEventTime); return msSOSException(map, "eventtime", "InvalidParameterValue"); } for (i=0; inumlayers; i++) { if (GET_LAYER(map, i)->status == MS_ON) { /* the sos_offering_timeextent should be used for time validation*/ /*TODO : too documented ?*/ lpfirst = msSOSGetFirstLayerForOffering(map, msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"), NULL); if (lpfirst) pszTimeExtent = msOWSLookupMetadata(&lpfirst->metadata, "S", "offering_timeextent"); pszTimeField = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "SO", "timeitem"); if (pszTimeField) { /*validate only if time extent is set.*/ if (pszTimeExtent) { if (msValidateTimeValue(pszTimeString, pszTimeExtent) == MS_TRUE) msLayerSetTimeFilter((GET_LAYER(map, i)), pszTimeString, pszTimeField); else { /*we should turn the layer off since the eventTime is not in the time extent*/ GET_LAYER(map, i)->status = MS_OFF; } } else msLayerSetTimeFilter((GET_LAYER(map, i)), pszTimeString, pszTimeField); } } } if (pszTimeString) msFree(pszTimeString); } /*bbox*/ /* this is a gml feature -66 43 -62 45 */ if (sosparams->pszFeatureOfInterest) { int bValid = 0; CPLXMLNode *psRoot=NULL; char *pszSRS = NULL; psRoot = CPLParseXMLString(sosparams->pszFeatureOfInterest); if(!psRoot) { msSetError(MS_SOSERR, "Invalid gml:Envelope value given for featureOfInterest.", "msSOSGetObservation()"); return msSOSException(map, "featureofinterest", "InvalidParameterValue"); } CPLStripXMLNamespace(psRoot, "gml", 1); bValid = FLTParseGMLEnvelope(psRoot, &sBbox, &pszSRS); /* TODO we should reproject the bbox to the map projection if there is an srs defined */ if (!bValid) { msSetError(MS_SOSERR, "Invalid gml:Envelope value given for featureOfInterest %s.", "msSOSGetObservation()", sosparams->pszEventTime); return msSOSException(map, "featureofinterest", "InvalidParameterValue"); } map->extent.minx = sBbox.minx; map->extent.miny = sBbox.miny; map->extent.maxx = sBbox.maxx; map->extent.maxy = sBbox.maxy; CPLDestroyXMLNode(psRoot); msFree(pszSRS); } if (sosparams->pszSrsName) { /* validate against MAP.WEB.METADATA.sos_srs */ int iUnits = -1; char **tokens = NULL; const char *pszSRSList = NULL; int n = 0; int bFound = 0; int k; char srsbuffer[100]; projectionObj po; pszSRSList = msOWSLookupMetadata(&(map->web.metadata), "SO", "srs"); if (pszSRSList) { tokens = msStringSplit(pszSRSList, ' ', &n); if (tokens && n > 0) { for (k=0; kpszSrsName, tokens[k]) == 0) { /* match */ bFound = 1; /* project MAP.EXTENT to this SRS */ msInitProjection(&po); snprintf(srsbuffer, sizeof(srsbuffer), "+init=epsg:%.20s", sosparams->pszSrsName+strlen("EPSG:")); if (msLoadProjectionString(&po, srsbuffer) != 0) { msSetError(MS_SOSERR, "Could not set output projection to \"%s\"", "msSOSGetObservation()", sosparams->pszSrsName); return msSOSException(map, "mapserv", "NoApplicableCode"); } if (msProjectionsDiffer(&map->projection, &po) == MS_TRUE) { msProjectRect(&map->projection, &po, &map->extent); sBbox = map->extent; } /* set map->projection to this SRS */ if (msLoadProjectionString(&(map->projection), srsbuffer) != 0) { msSetError(MS_SOSERR, "Could not set output projection to \"%s\"", "msSOSGetObservation()", sosparams->pszSrsName); return msSOSException(map, "mapserv", "NoApplicableCode"); } iUnits = GetMapserverUnitUsingProj(&(map->projection)); if (iUnits != -1) map->units = iUnits; msFreeProjection(&po); break; } } msFreeCharArray(tokens, n); } if (bFound == 0) { msSetError(MS_SOSERR, "srsName value \"%s\" unsupported / invalid", "msSOSGetObservation()", sosparams->pszSrsName); return msSOSException(map, "srsName", "InvalidParameterValue"); } } else { msSetError(MS_SOSERR, "MAP.WEB.METADATA.sos_srs not set", "msSOSGetObservation()"); return msSOSException(map, "mapserv", "NoApplicableCode"); } } /* apply filter */ if (sosparams->pszResult) { psFilterNode = FLTParseFilterEncoding(sosparams->pszResult); if (!psFilterNode) { msSetError(MS_SOSERR, "Invalid or Unsupported RESULT in GetObservation: %s", "msSOSGetObservation()", sosparams->pszResult); return msSOSException(map, "result", "InvalidParameterValue"); } /* apply the filter to all layers that are on */ for (i=0; inumlayers; i++) { lp = GET_LAYER(map, i); if (lp->status == MS_ON) { /* preparse parser so that alias for fields can be used */ FLTPreParseFilterForAliasAndGroup(psFilterNode, map, i, "S"); /* validate that the property names used are valid (there is a corresponding layer attribute) */ if (msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) { if (msSOSValidateFilter(psFilterNode, lp)== MS_FALSE) { msSetError(MS_SOSERR, "Invalid component name in RESULT statement", "msSOSGetObservation()"); return msSOSException(map, "result", "InvalidParameterValue"); } msLayerClose(lp); } FLTApplyFilterToLayer(psFilterNode, map, i); } } FLTFreeFilterEncodingNode(psFilterNode); } /* this is just a fall back if bbox is enetered. The bbox parameter is not supported by the sos specs */ if (sosparams->pszBBox && !sosparams->pszFeatureOfInterest) { char **tokens; int n; tokens = msStringSplit(sosparams->pszBBox, ',', &n); if (tokens==NULL || n != 4) { msSetError(MS_SOSERR, "Wrong number of arguments for bounding box.", "msSOSGetObservation()"); return msSOSException(map, "bbox", "InvalidParameterValue"); } sBbox.minx = atof(tokens[0]); sBbox.miny = atof(tokens[1]); sBbox.maxx = atof(tokens[2]); sBbox.maxy = atof(tokens[3]); msFreeCharArray(tokens, n); } /* do the query if the filter encoding (pszResult) is not part of the request. If pszResult is available, the query on the layers will be done when the filter is parsed*/ if (!sosparams->pszResult) { map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = -1; map->query.rect = sBbox; msQueryByRect(map); } /*get the first layers of the offering*/ for (i=0; inumlayers; i++) { pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "offering_id"); if (pszTmp && (strcasecmp(pszTmp, sosparams->pszOffering) == 0)) { lp = (GET_LAYER(map, i)); break; } } /* build xml return tree*/ psNsSos = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/sos/1.0", BAD_CAST "sos"); psNsGml = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"); psNsOm = xmlNewNs(NULL, BAD_CAST pszOMNamespaceUri, BAD_CAST pszOMNamespacePrefix); psNsSwe = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/swe/1.0.1", BAD_CAST "swe"); psNsXLink = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX); psNsMs = xmlNewNs(NULL, BAD_CAST user_namespace_uri, BAD_CAST user_namespace_prefix); psDoc = xmlNewDoc(BAD_CAST "1.0"); psRootNode = xmlNewNode(NULL, BAD_CAST "ObservationCollection"); xmlDocSetRootElement(psDoc, psRootNode); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/swe/1.0.1", BAD_CAST "swe")); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST pszSOSNamespaceUri, BAD_CAST pszSOSNamespacePrefix)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST user_namespace_uri, BAD_CAST user_namespace_prefix)); xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/om/1.0", BAD_CAST "om")); xmlNewNsProp(psRootNode, psNsGml, BAD_CAST "id", BAD_CAST sosparams->pszOffering); schemalocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map)); if ((script_url=msOWSGetOnlineResource(map, "SO", "onlineresource", req)) == NULL) return msSOSException(map, "NoApplicableCode", "NoApplicableCode"); xsi_schemaLocation = msStrdup("http://www.opengis.net/om/1.0 "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/om/1.0.0/om.xsd "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *) user_namespace_uri); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *) script_url); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "service=WFS&version=1.1.0&request=DescribeFeatureType&typename="); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *) opLayerName); xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation); /* description */ pszTmp = msOWSLookupMetadata(&(lp->metadata), "S", "offering_description"); if (pszTmp) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "description", BAD_CAST pszTmp); xmlSetNs(psNode, xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } /* name */ pszTmp = msOWSLookupMetadata(&(lp->metadata), "S", "offering_name"); if (pszTmp) { psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "name", BAD_CAST pszTmp); xmlSetNs(psNode, xmlNewNs(psNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml")); } /* extent */ pszTmp = msOWSLookupMetadata(&(lp->metadata), "S", "offering_extent"); if (pszTmp) { char **tokens; char *pszMapEpsg; int n; rectObj envelope; msOWSGetEPSGProj(&(map->projection), &(lp->metadata), "SO", MS_TRUE, &pszMapEpsg); tokens = msStringSplit(pszTmp, ',', &n); if (tokens==NULL || n != 4) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_extent.", "msSOSGetCapabilities()"); msFree(script_url); return msSOSException(map, "sos_offering_extent", "InvalidParameterValue"); } envelope.minx = atof(tokens[0]); envelope.miny = atof(tokens[1]); envelope.maxx = atof(tokens[2]); envelope.maxy = atof(tokens[3]); if (map && msProjectionsDiffer(&map->projection, &lp->projection) == MS_TRUE) { if (msProjectRect(&lp->projection, &map->projection, &envelope) == MS_FAILURE) { msSetError(MS_SOSERR, "Coordinates transformation failed. Raised in msProjectRect() of file %s line %d", "msSOSGetCapabilities()", __FILE__, __LINE__); msFree(script_url); return msSOSException(map, "sos_offering_extent", "InvalidParameterValue"); } } psNode = xmlAddChild(psRootNode, msGML3BoundedBy(psNsGml, envelope.minx, envelope.miny, envelope.maxx, envelope.maxy, pszMapEpsg)); msFreeCharArray(tokens, n); msFree(pszMapEpsg); } /* time pszTmp = msOWSLookupMetadata(&(lp->metadata), "S","offering_timeextent"); if (pszTmp) { char **tokens; int n; char *pszEndTime = NULL; tokens = msStringSplit(pszTmp, '/', &n); if (tokens==NULL || (n != 1 && n!=2)) { msSetError(MS_SOSERR, "Wrong number of arguments for sos_offering_timeextent.", "msSOSGetCapabilities()"); return msSOSException(map, "sos_offering_timeextent", "InvalidParameterValue"); } */ /* if (n == 2) */ /* end time is empty. It is going to be set as "now" */ /* pszEndTime = tokens[1]; psNode = xmlAddChild(psRootNode, msSOSAddTimeNode(xmlNewNs(NULL, BAD_CAST pszOMNamespaceUri, BAD_CAST pszOMNamespacePrefix), tokens[0], pszEndTime)); psNode = xmlAddChild(psRootNode, msSOSAddTimeNode(psNsOm, psNsGml, tokens[0], pszEndTime)); msFreeCharArray(tokens, n); } */ if (sosparams->pszResultModel && strcasecmp(sosparams->pszResultModel, "om:Measurement") != 0 && strcasecmp(sosparams->pszResultModel, "om:Observation") != 0) { msSetError(MS_SOSERR, "resultModel should be om:Measurement or om:Observation", "msSOSGetObservation()"); free(xsi_schemaLocation); free(schemalocation); msFree(script_url); xmlFreeNs(psNsSos); xmlFreeNs(psNsGml); xmlFreeNs(psNsOm); xmlFreeNs(psNsSwe); xmlFreeNs(psNsXLink); xmlFreeNs(psNsMs); xmlFreeDoc(psDoc); return msSOSException(map, "resultModel", "InvalidParameterValue"); } else { /* output result members */ for (i=0; inumlayers; i++) { if (GET_LAYER(map, i)->resultcache && GET_LAYER(map, i)->resultcache->numresults > 0) { msLayerGetItems((GET_LAYER(map, i))); pszTmp = msOWSLookupMetadata(&(map->web.metadata), "SO", "maxfeatures"); if (pszTmp != NULL) n1 = atoi(pszTmp); else n1 = 0; if (sosparams->pszResultModel == NULL || strcasecmp(sosparams->pszResultModel, "om:Measurement") == 0) { for(j=0; jresultcache->numresults; j++) { msSOSAddMemberNode(psNsGml, psNsOm, psNsSwe, psNsXLink, psNsMs, psRootNode, map, (GET_LAYER(map, i)), j, script_url, opLayerName); if (j == n1-1) break; } } else { /*assuming here that pszResultModel = observation */ /*layer does not define a procedure_item: this means one procedure per layer defined using sos_procedure)*/ if (msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "procedure_item") == NULL) { pszProcedure = msOWSLookupMetadata(&(lp->metadata), "S", "procedure"); psObservationNode = msSOSAddMemberNodeObservation(psNsGml, psNsSos, psNsOm, psNsSwe, psNsXLink, psRootNode, map, (GET_LAYER(map, i)), pszProcedure); /*add a result node*/ psResultNode = xmlNewChild(psObservationNode, NULL, BAD_CAST "result", NULL); for(j=0; jresultcache->numresults; j++) { /*add a block separator*/ if (j > 0) { pszBlockSep = msOWSLookupMetadata(&(map->web.metadata), "S", "encoding_blockSeparator"); if (pszBlockSep) xmlNodeAddContent(psResultNode, BAD_CAST pszBlockSep); else xmlNodeAddContent(psResultNode, BAD_CAST "\n"); } { char* pszResult = msSOSReturnMemberResult((GET_LAYER(map, i)), j, NULL); if (pszResult) { xmlNodeAddContent(psResultNode, BAD_CAST pszResult); msFree(pszResult); } } } } /*this is the case where procedure_item is used. Needs more management since the same data on a layer contains different procedures (procedures are one of the fields of the record)*/ else { for(j=0; jresultcache->numresults; j++) { char* pszProcedureValue = NULL; char* pszResult = msSOSReturnMemberResult((GET_LAYER(map, i)), j, &pszProcedureValue); if (!pszProcedureValue || !pszResult) { msFree(pszProcedureValue); msFree(pszResult); continue; } for (k=0; kweb.metadata), "S", "encoding_blockSeparator"); if (pszBlockSep) xmlNodeAddContent(paDiffrentProc[k].psResultNode, BAD_CAST pszBlockSep); else xmlNodeAddContent(paDiffrentProc[k].psResultNode, BAD_CAST "\n"); xmlNodeAddContent(paDiffrentProc[k].psResultNode, BAD_CAST pszResult); break; } } if (k == nDiffrentProc) { /*a new procedure*/ nDiffrentProc++; if (paDiffrentProc == NULL) paDiffrentProc = (SOSProcedureNode *)malloc(sizeof(SOSProcedureNode)); else paDiffrentProc = (SOSProcedureNode *)realloc(paDiffrentProc, sizeof(SOSProcedureNode) *nDiffrentProc); paDiffrentProc[nDiffrentProc-1].pszProcedure = msStrdup(pszProcedureValue); psObservationNode = msSOSAddMemberNodeObservation(psNsGml, psNsSos, psNsOm, psNsSwe, psNsXLink, psRootNode, map, (GET_LAYER(map, i)), pszProcedureValue); paDiffrentProc[nDiffrentProc-1].psResultNode = xmlNewChild(psObservationNode, NULL, BAD_CAST "result", NULL); xmlNodeAddContent(paDiffrentProc[nDiffrentProc-1].psResultNode, BAD_CAST pszResult); } msFree(pszProcedureValue); msFree(pszResult); } if (paDiffrentProc) { for (k=0; kpszOutputFormat) { msSetError(MS_SOSERR, "Missing mandatory parameter outputFormat.", "msSOSDescribeSensor()"); return msSOSException(map, "outputformat", "MissingParameterValue"); } if (strcasecmp(sosparams->pszOutputFormat, pszSOSDescribeSensorMimeType) != 0) { msSetError(MS_SOSERR, "Invalid outputformat parameter %s. Allowable values are: %s", "msSOSDescribeSensor()", sosparams->pszOutputFormat, pszSOSDescribeSensorMimeType); return msSOSException(map, "outputformat", "InvalidParameterValue"); } if (!sosparams->pszProcedure) { msSetError(MS_SOSERR, "Missing mandatory parameter procedure", "msSOSDescribeSensor()"); return msSOSException(map, "procedure", "MissingParameterValue"); } for (i=0; inumlayers; i++) { lp = GET_LAYER(map, i); pszId = msOWSLookupMetadata(&(lp->metadata), "S", "procedure"); if (pszId && strlen(pszId) > 0) { /*procedure could be a list*/ char **tokens = NULL; int n=0; int bFound = 0; tokens = msStringSplit(pszId, ' ', &n); for (k=0; k 0) { pszProcedureURI = msStrdup("urn:ogc:def:procedure:"); pszProcedureURI = msStringConcatenate(pszProcedureURI, tokens[k]); if ( (pszProcedureURI && strcasecmp(pszProcedureURI, sosparams->pszProcedure) == 0) && (msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers)) ) { bFound = 1; pszProcedureId = msStrdup(tokens[k]); msFree(pszProcedureURI); break; } msFree(pszProcedureURI); } } msFreeCharArray(tokens, n); if (bFound) { pszUrl = msOWSLookupMetadata(&(lp->metadata), "S", "describesensor_url"); if (pszUrl) { pszTmp = msStrdup(pszUrl); /* %procedure% is the hardcoded variable name to use within sos_describesensor_url */ tmpstr = (char *)malloc(sizeof(char)*strlen("procedure") + 3); sprintf(tmpstr,"%%%s%%", "procedure"); if (strcasestr(pszUrl, tmpstr) != NULL) pszTmp = msCaseReplaceSubstring(pszTmp, tmpstr, pszProcedureId); msFree(tmpstr); pszEncodedUrl = msEncodeHTMLEntities(pszTmp); msIO_printf("Location: %s\n\n", pszEncodedUrl); msFree(pszTmp); msFree(pszEncodedUrl); msFree(pszProcedureId); return(MS_SUCCESS); } else { msSetError(MS_SOSERR, "Missing mandatory metadata sos_describesensor_url on layer %s", "msSOSDescribeSensor()", lp->name); return msSOSException(map, "sos_describesensor_url", "MissingParameterValue"); } } } else if ((pszId = msOWSLookupMetadata(&(lp->metadata), "S", "procedure_item"))) { iItemPosition = -1; if (msLayerOpen(lp) == MS_SUCCESS && msLayerGetItems(lp) == MS_SUCCESS) { for(j=0; jnumitems; j++) { if (strcasecmp(lp->items[j], pszId) == 0) { iItemPosition = j; break; } } msLayerClose(lp); } if (iItemPosition >=0) { if (lp->template == NULL) lp->template = msStrdup("ttt"); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.layer = i; map->query.rect = map->extent; msQueryByRect(map); msLayerGetItems(lp); if (lp->resultcache && lp->resultcache->numresults > 0) { for(j=0; jresultcache->numresults; j++) { msInitShape(&sShape); status = msLayerGetShape(lp, &sShape, &(lp->resultcache->results[j])); if(status != MS_SUCCESS) continue; if (sShape.values[iItemPosition]) { pszProcedureURI = msStrdup("urn:ogc:def:procedure:"); pszProcedureURI = msStringConcatenate(pszProcedureURI, sShape.values[iItemPosition]); if (strcasecmp(pszProcedureURI, sosparams->pszProcedure) == 0) { pszUrl = msOWSLookupMetadata(&(lp->metadata), "S", "describesensor_url"); pszProcedureId = msStrdup(sShape.values[iItemPosition]); if (pszUrl) { pszTmp = msStrdup(pszUrl); /* %procedure% is the hardcoded variable names to use within sos_describesensor_url */ tmpstr = (char *)malloc(sizeof(char)*strlen("procedure") + 3); sprintf(tmpstr,"%%%s%%", "procedure"); if (strcasestr(pszUrl, tmpstr) != NULL) pszTmp = msCaseReplaceSubstring(pszTmp, tmpstr, pszProcedureId); msFree(tmpstr); pszEncodedUrl = msEncodeHTMLEntities(pszTmp); msIO_printf("Location: %s\n\n", pszEncodedUrl); msFree(pszTmp); return(MS_SUCCESS); } else { msSetError(MS_SOSERR, "Missing mandatory metadata sos_describesensor_url on layer %s", "msSOSDescribeSensor()", lp->name); return msSOSException(map, "mapserv", "NoApplicableCode"); } } } } } } } } msSetError(MS_SOSERR, "procedure %s not found.", "msSOSDescribeSensor()", sosparams->pszProcedure); return msSOSException(map, "procedure", "InvalidParameterValue"); } /************************************************************************/ /* msSOSDescribeObservationType */ /* */ /* DescribeObserrvationType request handler */ /************************************************************************/ int msSOSDescribeObservationType(mapObj *map, sosParamsObj *sosparams, cgiRequestObj *req, owsRequestObj *ows_request) { int i, j, n = 0, bLayerFound = 0; char **tokens = NULL; char *script_url=NULL; const char *pszTmp = NULL; char *pszTmp2=NULL; const char *opLayerName = NULL; if (!sosparams->pszObservedProperty) { msSetError(MS_SOSERR, "Missing mandatory parameter observedproperty", "msSOSDescribeObservationType()"); return msSOSException(map, "observedproperty", "MissingParameterValue"); } tokens = msStringSplit(sosparams->pszObservedProperty, ',', &n); for (i=0; inumlayers; i++) { if (!msIntegerInArray(GET_LAYER(map, i)->index, ows_request->enabled_layers, ows_request->numlayers)) continue; pszTmp = msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "S", "observedproperty_id"); if (pszTmp) { if (strcasecmp(pszTmp, sosparams->pszObservedProperty) == 0) { if (tokens && n > 0) { for (j=0; jname; bLayerFound = 1; break; } } } } } } if (tokens && n > 0) msFreeCharArray(tokens, n); if (bLayerFound == 0) { msSetError(MS_SOSERR, "ObservedProperty %s not found.", "msSOSGetObservation()", sosparams->pszObservedProperty); return msSOSException(map, "observedproperty", "InvalidParameterValue"); } if ((script_url=msOWSGetOnlineResource(map, "SO", "onlineresource", req)) == NULL) return msSOSException(map, "NoApplicableCode", "NoApplicableCode"); pszTmp2 = msStringConcatenate(pszTmp2, (char *) script_url); pszTmp2 = msStringConcatenate(pszTmp2, "service=WFS&version=1.1.0&request=DescribeFeatureType&typename="); pszTmp2 = msStringConcatenate(pszTmp2, (char *) opLayerName); msIO_printf("Location: %s\n\n", pszTmp2); msFree(pszTmp2); msFree(script_url); return(MS_SUCCESS); } #endif /* defined(USE_WCS_SVR) && defined(USE_LIBXML2) */ /* ** msSOSDispatch() is the entry point for SOS requests. ** - If this is a valid request then it is processed and MS_SUCCESS is returned ** on success, or MS_FAILURE on failure. */ int msSOSDispatch(mapObj *map, cgiRequestObj *req, owsRequestObj *ows_request) { #if defined(USE_SOS_SVR) && defined(USE_LIBXML2) int returnvalue = MS_DONE; sosParamsObj *paramsObj = (sosParamsObj *)calloc(1, sizeof(sosParamsObj)); if (msSOSParseRequest(map, req, paramsObj) == MS_FAILURE) { msSOSFreeParamsObj(paramsObj); free(paramsObj); return MS_FAILURE; } /* SERVICE must be specified and be SOS */ if (paramsObj->pszService && strcasecmp(paramsObj->pszService, "SOS") == 0) { /* this is an SOS request */ if (!paramsObj->pszRequest) { msSetError(MS_SOSERR, "Missing REQUEST Parameter", "msSOSDispatch()"); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "request", "MissingParameterValue"); } msOWSRequestLayersEnabled(map, "S", paramsObj->pszRequest, ows_request); if (ows_request->numlayers == 0) { msSetError(MS_SOSERR, "SOS request not enabled. Check sos/ows_enable_request settings.", "msSOSDispatch()"); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "request", "InvalidParameterValue"); } if (strcasecmp(paramsObj->pszRequest, "GetCapabilities") == 0) { returnvalue = msSOSGetCapabilities(map, paramsObj, req, ows_request); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } else if (strcasecmp(paramsObj->pszRequest, "DescribeSensor") == 0 || strcasecmp(paramsObj->pszRequest, "GetObservation") == 0 || strcasecmp(paramsObj->pszRequest, "DescribeObservationType") == 0 ) { /* check version */ if (!paramsObj->pszVersion) { msSetError(MS_SOSERR, "Missing VERSION parameter", "msSOSDispatch()"); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "version", "MissingParameterValue"); } if (msOWSParseVersionString(paramsObj->pszVersion) != OWS_1_0_0) { msSetError(MS_SOSERR, "VERSION %s not supported. Supported versions are: %s.", "msSOSDispatch()", paramsObj->pszVersion, pszSOSVersion); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "version", "InvalidParameterValue"); } if (strcasecmp(paramsObj->pszRequest, "DescribeSensor") == 0) returnvalue = msSOSDescribeSensor(map, paramsObj, ows_request); else if (strcasecmp(paramsObj->pszRequest, "GetObservation") == 0) returnvalue = msSOSGetObservation(map, paramsObj, req, ows_request); else if (strcasecmp(paramsObj->pszRequest, "DescribeObservationType") == 0) returnvalue = msSOSDescribeObservationType(map, paramsObj, req, ows_request); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return returnvalue; } else { msSetError(MS_SOSERR, "Invalid REQUEST parameter: %s", "msSOSDispatch()", paramsObj->pszRequest); msSOSFreeParamsObj(paramsObj); free(paramsObj); paramsObj = NULL; return msSOSException(map, "request", "InvalidParameterValue"); } } else { msSOSFreeParamsObj(paramsObj); free(paramsObj); return MS_DONE; /* Not an SOS request */ } #else msSetError(MS_SOSERR, "SOS support is not available.", "msSOSDispatch()"); return(MS_FAILURE); #endif } #if defined(USE_SOS_SVR) && defined(USE_LIBXML2) int msSOSParseRequest(mapObj *map, cgiRequestObj *request, sosParamsObj *sosparams) { int i; xmlDocPtr doc; xmlXPathContextPtr context; xmlNodeSetPtr nodeset; xmlXPathObjectPtr psXPathTmp; char *pszTmp = NULL; if (request->NumParams) { /* this is a GET request */ for(i=0; iNumParams; i++) { if (strcasecmp(request->ParamNames[i], "SERVICE") == 0) sosparams->pszService = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "VERSION") == 0) sosparams->pszVersion = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "ACCEPTVERSIONS") == 0) sosparams->pszAcceptVersions = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "REQUEST") == 0) sosparams->pszRequest = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "UPDATESEQUENCE") == 0) sosparams->pszUpdateSequence = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "SENSORID") == 0) sosparams->pszSensorId = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "PROCEDURE") == 0) sosparams->pszProcedure = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "OUTPUTFORMAT") == 0) sosparams->pszOutputFormat = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "OFFERING") == 0) sosparams->pszOffering = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "OBSERVEDPROPERTY") == 0) sosparams->pszObservedProperty = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "EVENTTIME") == 0) sosparams->pszEventTime = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESULT") == 0) sosparams->pszResult = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESULTMODEL") == 0) sosparams->pszResultModel = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESPONSEFORMAT") == 0) sosparams->pszResponseFormat = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "RESPONSEMODE") == 0) sosparams->pszResponseMode = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "BBOX") == 0) sosparams->pszBBox = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "SRSNAME") == 0) sosparams->pszSrsName = msStrdup(request->ParamValues[i]); else if (strcasecmp(request->ParamNames[i], "FEATUREOFINTEREST") == 0) sosparams->pszFeatureOfInterest = msStrdup(request->ParamValues[i]); } } if (request->postrequest) { /* this a POST request */ /* load document */ doc = xmlParseDoc((xmlChar *)request->postrequest); if (doc == NULL ) { msSetError(MS_SOSERR, "Invalid POST request. XML is not well-formed", "msSOSParseRequest()"); return msSOSException(map, "request", "InvalidRequest"); } /* load context */ context = xmlXPathNewContext(doc); if (context == NULL) { msSetError(MS_SOSERR, "Could not create context (xmlXPathNewContext)", "msSOSParseRequest()"); return msSOSException(map, "request", "NoApplicableCode"); } /* register namespaces */ if(xmlXPathRegisterNs(context, (xmlChar *)"sos", (xmlChar *)"http://www.opengis.net/sos/1.0") != 0 || xmlXPathRegisterNs(context, (xmlChar *)"ows", (xmlChar *)"http://www.opengis.net/ows/1.1") != 0 || xmlXPathRegisterNs(context, (xmlChar *)"ogc", (xmlChar *)"http://www.opengis.net/ogc") != 0 || xmlXPathRegisterNs(context, (xmlChar *)"gml", (xmlChar *)"http://www.opengis.net/gml") != 0) { msSetError(MS_SOSERR, "Could not register namespaces (xmlXPathRegisterNs)", "msSOSParseRequest()"); return msSOSException(map, "request", "NoApplicableCode"); } /* check for service */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/*/@service"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszService = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for updateSequence*/ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/*/@updateSequence"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszUpdateSequence = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for version */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/*/ows:AcceptVersions/ows:Version|/*/@version"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszVersion = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for request */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetCapabilities"); if (psXPathTmp) sosparams->pszRequest = msStrdup("GetCapabilities"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeSensor"); if (psXPathTmp) sosparams->pszRequest = msStrdup("DescribeSensor"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation"); if (psXPathTmp) sosparams->pszRequest = msStrdup("GetObservation"); psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeObservationType"); if (psXPathTmp) sosparams->pszRequest = msStrdup("DescribeObservationType"); xmlXPathFreeObject(psXPathTmp); /* check for outputformat */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeSensor/@outputFormat"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszOutputFormat = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for Procedure */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:DescribeSensor/sos:procedure"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszProcedure = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for offering */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:offering"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszOffering = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for observedproperty */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:observedProperty"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszObservedProperty = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for procedure */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:procedure"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszProcedure = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for responseFormat */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:responseFormat"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszResponseFormat = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for resultModel */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:resultModel"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszResultModel = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for responseMode */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:responseMode"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszResponseMode = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for srsName */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/@srsName"); if (psXPathTmp) { nodeset = psXPathTmp->nodesetval; sosparams->pszSrsName = (char *)xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); } xmlXPathFreeObject(psXPathTmp); /* check for result (chunk of XML) */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:result/child::*"); if (psXPathTmp) { sosparams->pszResult = msLibXml2GetXPathTree(doc, psXPathTmp); pszTmp = msStringConcatenate(pszTmp, ""); pszTmp = msStringConcatenate(pszTmp, sosparams->pszResult); pszTmp = msStringConcatenate(pszTmp, ""); msFree(sosparams->pszResult); sosparams->pszResult = msStrdup(pszTmp); msFree(pszTmp); } xmlXPathFreeObject(psXPathTmp); /* check for featureOfInterest (chunk of XML) */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:featureOfInterest/ogc:BBOX/gml:Envelope"); if (psXPathTmp) { sosparams->pszFeatureOfInterest = (char *)msLibXml2GetXPathTree(doc, psXPathTmp); } xmlXPathFreeObject(psXPathTmp); /* check for eventTime (chunk of XML) */ psXPathTmp = msLibXml2GetXPath(doc, context, (xmlChar *)"/sos:GetObservation/sos:eventTime/*/gml:TimeInstant|/sos:GetObservation/sos:eventTime/*/gml:TimePeriod"); if (psXPathTmp) { sosparams->pszEventTime = (char *)msLibXml2GetXPathTree(doc, psXPathTmp); } xmlXPathFreeObject(psXPathTmp); xmlXPathFreeContext(context); xmlFreeDoc(doc); xmlCleanupParser(); } return MS_SUCCESS; } void msSOSFreeParamsObj(sosParamsObj *sosparams) { if (sosparams) { if (sosparams->pszService) free(sosparams->pszService); if (sosparams->pszVersion) free(sosparams->pszVersion); if (sosparams->pszAcceptVersions) free(sosparams->pszAcceptVersions); if (sosparams->pszUpdateSequence) free(sosparams->pszUpdateSequence); if (sosparams->pszRequest) free(sosparams->pszRequest); if (sosparams->pszOutputFormat) free(sosparams->pszOutputFormat); if (sosparams->pszSensorId) free(sosparams->pszSensorId); if (sosparams->pszProcedure) free(sosparams->pszProcedure); if (sosparams->pszOffering) free(sosparams->pszOffering); if (sosparams->pszObservedProperty) free(sosparams->pszObservedProperty); if (sosparams->pszEventTime) free(sosparams->pszEventTime); if (sosparams->pszResult) free(sosparams->pszResult); if (sosparams->pszResponseFormat) free(sosparams->pszResponseFormat); if (sosparams->pszResultModel) free(sosparams->pszResultModel); if (sosparams->pszResponseMode) free(sosparams->pszResponseMode); if (sosparams->pszSrsName) free(sosparams->pszSrsName); if (sosparams->pszFeatureOfInterest) free(sosparams->pszFeatureOfInterest); } } #endif /* defined(USE_SOS_SVR) && defined(USE_LIBXML2) */ mapserver-7.4.3/mapogl.cpp000066400000000000000000000211431357574274700155420ustar00rootroot00000000000000/****************************************************************************** * $id: mapogl.cpp 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #ifdef USE_OGL #include #include #include "mapoglrenderer.h" #include "mapoglcontext.h" imageObj* createImageObjOgl(OglRenderer* renderer) { if (!renderer->isValid()) return NULL; imageObj* pNewImage = (imageObj*)calloc(1, sizeof(imageObj)); if (!pNewImage) return pNewImage; pNewImage->img.plugin = (void *) renderer; return pNewImage; } OglRenderer* getOglRenderer(imageObj* img) { return (OglRenderer*) img->img.plugin; } int msSaveImageOgl(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { rasterBufferObj data; OglRenderer* renderer = getOglRenderer(img); renderer->readRasterBuffer(&data); return msSaveRasterBuffer(NULL,&data,fp,img->format ); } int msDrawLineOgl(imageObj *img, shapeObj *p, strokeStyleObj *style) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPolyline(p, style->color, style->width, style->patternlength, style->pattern); return MS_SUCCESS; } int msDrawPolygonOgl(imageObj *img, shapeObj *p, colorObj *color) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPolygon(p, color, NULL, 0); return MS_SUCCESS; } //void msFreeTileOgl(imageObj *tile) //{ // delete (OglCache*)tile; //} int msDrawLineTiledOgl(imageObj *img, shapeObj *p, imageObj *tile) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPolylineTile(p, getOglRenderer(tile)->getTexture()); return MS_SUCCESS; } int msDrawPolygonTiledOgl(imageObj *img, shapeObj *p, imageObj *tile) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPolygon(p, NULL, NULL, 0.0, getOglRenderer(tile)->getTexture()); return MS_SUCCESS; } int msRenderPixmapOgl(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { OglRenderer* renderer = getOglRenderer(img); renderer->renderPixmap(symbol, x, y, style->rotation, style->scale); return MS_SUCCESS; } int msRenderVectorSymbolOgl (imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { OglRenderer* renderer = getOglRenderer(img); renderer->renderVectorSymbol(x, y, symbol, style->scale, style->rotation, style->color, style->outlinecolor, style->outlinewidth); return MS_SUCCESS; } int msRenderTruetypeSymbolOgl(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { OglRenderer* renderer = getOglRenderer(img); double size = style->scale*72.0; renderer->renderGlyphs(0, 0, style->color, style->outlinecolor, size, symbol->font, symbol->character, style->rotation, NULL, 0, 0); return MS_SUCCESS; } int msRenderTileOgl(imageObj *img, imageObj *tile, double x, double y) { OglRenderer* renderer = getOglRenderer(img); renderer->renderTile(getOglRenderer(tile)->getTexture(), x, y, 0.0); return MS_SUCCESS; } int msGetTruetypeTextBBoxOgl(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances, int bAdjustBaseline) { if (OglRenderer::getStringBBox(fonts[0], size, string, rect, advances)) { return MS_SUCCESS; } else { return MS_FAILURE; } } int msRenderGlyphsOgl(imageObj *img, double x, double y, labelStyleObj *style, char *text) { OglRenderer* renderer = getOglRenderer(img); renderer->renderGlyphs(x, y, style->color, style->outlinecolor, style->size, style->fonts[0], text, style->rotation, NULL, 0.0, 0.0); return MS_SUCCESS; } int msMergeRasterBufferOgl(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { OglRenderer* renderer = getOglRenderer(dest); renderer->drawRasterBuffer(overlay, opacity, srcX, srcY, dstX, dstY, width, height); return MS_SUCCESS; } imageObj* msImageCreateOgl(int width, int height, outputFormatObj *format, colorObj* bg) { imageObj *pNewImage = NULL; if (format->imagemode != MS_IMAGEMODE_RGB && format->imagemode != MS_IMAGEMODE_RGBA) { msSetError( MS_OGLERR, "OpenGL driver only supports RGB or RGBA pixel models.", "msImageCreateOGL()"); return NULL; } return createImageObjOgl(new OglRenderer(width, height, bg)); } int msRenderEllipseOgl(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style) { OglRenderer* renderer = getOglRenderer(image); renderer->renderEllipse(x, y, style->rotation, symbol->sizex, symbol->sizey, style->color, style->outlinecolor, style->outlinewidth); return MS_SUCCESS; } int msFreeImageOgl(imageObj *img) { OglRenderer* renderer = getOglRenderer(img); if (renderer) { delete renderer; } img->img.plugin=NULL; return MS_SUCCESS; } int msStartLayerOgl(imageObj *img, mapObj *map, layerObj *layer) { getOglRenderer(img)->setTransparency((double)layer->opacity/100); return MS_SUCCESS; } int msEndLayerOgl(imageObj *img, mapObj *map, layerObj *layer) { getOglRenderer(img)->setTransparency(1.0); return MS_SUCCESS; } int msFreeSymbolOgl(symbolObj *s) { return MS_SUCCESS; } int msGetRasterBufferCopyOgl(imageObj *img, rasterBufferObj *rb) { getOglRenderer(img)->readRasterBuffer(rb); return MS_SUCCESS; } int msGetRasterBufferHandleOgl(imageObj *img, rasterBufferObj * rb) { getOglRenderer(img)->readRasterBuffer(rb); return MS_SUCCESS; } int msInitializeRasterBufferOgl(rasterBufferObj *rb, int width, int height, int mode) { OglRenderer::initializeRasterBuffer(rb, width, height, mode==MS_IMAGEMODE_RGBA); return MS_SUCCESS; } #endif /* USE_OGL */ int msPopulateRendererVTableOGL(rendererVTableObj *renderer) { #ifdef USE_OGL renderer->supports_transparent_layers = 1; renderer->supports_pixel_buffer = 1; renderer->supports_clipping = 0; renderer->use_imagecache = 0; renderer->supports_bitmap_fonts = 0; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; renderer->startLayer = msStartLayerOgl; renderer->endLayer = msEndLayerOgl; renderer->createImage=&msImageCreateOgl; renderer->saveImage=&msSaveImageOgl; renderer->renderLine=&msDrawLineOgl; renderer->renderPolygon=&msDrawPolygonOgl; renderer->renderGlyphs=&msRenderGlyphsOgl; renderer->renderEllipseSymbol = &msRenderEllipseOgl; renderer->renderVectorSymbol = &msRenderVectorSymbolOgl; renderer->renderPixmapSymbol = &msRenderPixmapOgl; renderer->renderTruetypeSymbol = &msRenderTruetypeSymbolOgl; renderer->renderTile = &msRenderTileOgl; renderer->renderPolygonTiled = &msDrawPolygonTiledOgl; renderer->renderLineTiled = &msDrawLineTiledOgl; renderer->getTruetypeTextBBox = &msGetTruetypeTextBBoxOgl; renderer->getRasterBufferHandle = msGetRasterBufferHandleOgl; renderer->getRasterBufferCopy = msGetRasterBufferCopyOgl; renderer->initializeRasterBuffer = msInitializeRasterBufferOgl; renderer->mergeRasterBuffer = msMergeRasterBufferOgl; renderer->loadImageFromFile = msLoadMSRasterBufferFromFile; renderer->freeSymbol = &msFreeSymbolOgl; renderer->freeImage=&msFreeImageOgl; return MS_SUCCESS; #else msSetError(MS_MISCERR,"OGL driver requested but it is not compiled in this release", "msPopulateRendererVTableOGL()"); return MS_FAILURE; #endif } mapserver-7.4.3/mapoglcontext.cpp000066400000000000000000000353171357574274700171570ustar00rootroot00000000000000/****************************************************************************** * $id: mapoglcontext.cpp 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifdef USE_OGL #include "mapserver.h" #include "maperror.h" #include "mapoglcontext.h" #define _T(x) __TEXT(x) ms_uint32 OglContext::MAX_MULTISAMPLE_SAMPLES = 16; ms_uint32 OglContext::MAX_ANISOTROPY = 0; ms_uint32 OglContext::MAX_TEXTURE_SIZE = 0; ms_uint32 OglContext::MIN_TEXTURE_SIZE = 0; OglContext* OglContext::current = NULL; OglContext::OglContext(ms_uint32 width, ms_uint32 height) : valid(false) { if (!window && !initWindow()) return; if (!sharingContext && !initSharingContext()) return; if (!(this->width = getTextureSize(GL_TEXTURE_WIDTH, width))) return; if (!(this->height = getTextureSize(GL_TEXTURE_HEIGHT, height))) return; if (!createPBuffer(this->width, this->height)) return; if (!makeCurrent()) return; valid = true; } ms_uint32 OglContext::getTextureSize(GLuint dimension, ms_uint32 value) { glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, value, value, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); GLint check = 0; glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, dimension, &check); if (glGetError() != GL_NO_ERROR) { msSetError(MS_OGLERR, "glGetTexLevelParameteriv failed. glError: %d", "OglContext::getTextureSize()", glGetError()); } if (check == 0) { return MS_MAX(MS_MIN(NextPowerOf2(value), OglContext::MAX_TEXTURE_SIZE), OglContext::MIN_TEXTURE_SIZE); } else { msSetError(MS_OGLERR, "Unable to create opengl texture of map size", "OglContext::getTextureSize()"); return value; } } GLuint OglContext::NextPowerOf2(GLuint in) { in -= 1; in |= in >> 16; in |= in >> 8; in |= in >> 4; in |= in >> 2; in |= in >> 1; return in + 1; } #if defined(_WIN32) && !defined(__CYGWIN__) HDC OglContext::window = NULL; HGLRC OglContext::sharingContext = NULL; LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return(1L); } OglContext::~OglContext() { //TODO } bool OglContext::makeCurrent() { if (current != this) { current = this; if (!wglMakeContextCurrentARB(hPBufferDC, hPBufferDC, hPBufferRC)) { msSetError(MS_OGLERR, "Can't Activate The GL Rendering pbuffer.", "OglContext::makeCurrent()"); return FALSE; } } return true; } bool OglContext::initWindow() { int windowPixelFormat; WNDCLASS wc; DWORD dwExStyle; DWORD dwStyle; RECT WindowRect; HMODULE hInstance = NULL; HWND hWnd = NULL; WindowRect.left=(long)0; WindowRect.right=(long)0; WindowRect.top=(long)0; WindowRect.bottom=(long)0; hInstance = GetModuleHandle(NULL); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.lpfnWndProc = (WNDPROC) WndProc; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = _T("OpenGL"); if (!RegisterClass(&wc)) { msSetError(MS_OGLERR, "Failed To Register The Window Class.", "OglContext::initWindow()"); return FALSE; } dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; dwStyle=WS_OVERLAPPEDWINDOW; AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); if (!(hWnd=CreateWindowEx( dwExStyle, _T("OpenGL"), _T("temp"), dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top, NULL, NULL, hInstance, NULL))) { msSetError(MS_OGLERR, "Window Creation Error.", "OglContext::initWindow()"); return FALSE; } static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 24, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 8, // Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; if (!(window=GetDC(hWnd))) { msSetError(MS_OGLERR, "Can't Create A GL Device Context.. Last Error: %d", "OglContext::initWindow()", GetLastError()); return FALSE; } if (!(windowPixelFormat=ChoosePixelFormat(window,&pfd))) { msSetError(MS_OGLERR, "Can't Find A Suitable windowPixelFormat. Last Error: %d", "OglContext::initWindow()", GetLastError()); return FALSE; } if(!SetPixelFormat(window,windowPixelFormat,&pfd)) { msSetError(MS_OGLERR, "Can't Set The windowPixelFormat. Last Error: %d", "OglContext::initWindow()", GetLastError()); return FALSE; } return TRUE; } bool OglContext::initSharingContext() { if (!(sharingContext=wglCreateContext(window))) { msSetError(MS_OGLERR, "Can't Create A GL Rendering Context.", "OglContext::createContext()"); return FALSE; } if(!wglMakeCurrent(window,sharingContext)) { msSetError(MS_OGLERR, "Can't Activate The GL Rendering Context.", "OglContext::createContext()"); return FALSE; } if (!(wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"))) { msSetError(MS_OGLERR, "unable to retreive wglChoosePixelFormatARB method.", "OglContext::createContext()"); return FALSE; } if (!(wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB"))) { msSetError(MS_OGLERR, "unable to retreive wglCreatePbufferARB method.", "OglContext::createContext()"); return FALSE; } if (!(wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB"))) { msSetError(MS_OGLERR, "unable to retreive wglGetPbufferDCARB method.", "OglContext::createContext()"); return FALSE; } if (!(wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB"))) { msSetError(MS_OGLERR, "unable to retreive wglReleasePbufferDCARB method.", "OglContext::createContext()"); return FALSE; } if (!(wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)wglGetProcAddress("wglMakeContextCurrentARB"))) { msSetError(MS_OGLERR, "unable to retreive wglMakeContextCurrentARB method.", "OglContext::createContext()"); return FALSE; } glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*) &MAX_ANISOTROPY); glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&MAX_TEXTURE_SIZE); MIN_TEXTURE_SIZE = 8; return TRUE; } bool OglContext::createPBuffer(ms_uint32 width, ms_uint32 height) { HPBUFFERARB hPBuffer = NULL; hPBufferDC = NULL; hPBufferRC = NULL; int pixelFormat; int valid = false; UINT numFormats = 0; float fAttributes[] = {0,0}; int samples = MAX_MULTISAMPLE_SAMPLES; while ((!valid || numFormats == 0) && samples >= 0) { int iAttributes[] = { WGL_SAMPLES_ARB,samples, WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE, WGL_SUPPORT_OPENGL_ARB,GL_TRUE, WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, WGL_COLOR_BITS_ARB,24, WGL_ALPHA_BITS_ARB,8, WGL_DEPTH_BITS_ARB,16, WGL_STENCIL_BITS_ARB,0, WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, 0,0 }; valid = wglChoosePixelFormatARB(window,iAttributes,fAttributes,1,&pixelFormat,&numFormats); if (!valid || numFormats == 0) samples -= 2; } if(numFormats == 0) { msSetError(MS_OGLERR, "P-buffer Error: Unable to find an acceptable pixel format.", "OglContext::createPBuffer()"); return FALSE; } if (!(hPBuffer = wglCreatePbufferARB(window, pixelFormat, width, height, 0))) { msSetError(MS_OGLERR, "P-buffer Error: Unable to create P-buffer. glError: %d", "OglContext::createPBuffer()", glGetError()); return FALSE; } if (!(hPBufferDC = wglGetPbufferDCARB(hPBuffer))) { msSetError(MS_OGLERR, "P-buffer Error: Unable to get P-buffer DC. glError: %d", "OglContext::createPBuffer()", glGetError()); return FALSE; } if (!(hPBufferRC = wglCreateContext(hPBufferDC))) { msSetError(MS_OGLERR, "P-buffer Error: Unable to get P-buffer DC. glError: %d", "OglContext::createPBuffer()", glGetError()); return FALSE; } if (wglShareLists(sharingContext,hPBufferRC) == FALSE) { msSetError(MS_OGLERR, "P-buffer Error: Unable to share display lists. glError: %d", "OglContext::createPBuffer()", glGetError()); return FALSE; } return TRUE; } PFNWGLCHOOSEPIXELFORMATARBPROC OglContext::wglChoosePixelFormatARB = NULL; PFNWGLCREATEPBUFFERARBPROC OglContext::wglCreatePbufferARB = NULL; PFNWGLGETPBUFFERDCARBPROC OglContext::wglGetPbufferDCARB = NULL; PFNWGLRELEASEPBUFFERDCARBPROC OglContext::wglReleasePbufferDCARB = NULL; PFNWGLMAKECONTEXTCURRENTARBPROC OglContext::wglMakeContextCurrentARB = NULL; #else /* UNIX */ Display* OglContext::window = NULL; GLXContext OglContext::sharingContext = NULL; GLXFBConfig* OglContext::configs = NULL; OglContext::~OglContext() { //TODO } bool OglContext::makeCurrent() { if (current != this) { current = this; if (!glXMakeCurrent(window, pbuffer, sharingContext)) { msSetError(MS_OGLERR, "glXMakeCurrent failed. glError: %d", "OglContext::makeCurrent()", glGetError()); return false; } } return true; } bool OglContext::initSharingContext() { int fb_attributes[] = { GLX_SAMPLES_ARB, MAX_MULTISAMPLE_SAMPLES, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, 0, GLX_SAMPLE_BUFFERS_ARB, 1, 0 }; int num_configs = 0; while (num_configs == 0 && fb_attributes[1] >= 0) { configs = glXChooseFBConfig(window, DefaultScreen(window), fb_attributes, &num_configs); fb_attributes[1] -= 2; } if (configs == NULL || num_configs == 0) { msSetError(MS_OGLERR, "glXChooseFBConfig could not find any configs. Likely your video card or drivers are not supported. glError: %d", "OglContext::init()", glGetError()); return false; } sharingContext = glXCreateNewContext(window, *configs, GLX_RGBA_TYPE, NULL, 1); if (sharingContext == NULL) { msSetError(MS_OGLERR, "glXCreateNewContext failed. glError: %d", "OglContext::initSharingContext()", glGetError()); return false; } return true; } bool OglContext::createPBuffer(ms_uint32 width, ms_uint32 height) { int maxHeight, maxWidth; glXGetFBConfigAttrib(window, *configs, GLX_MAX_PBUFFER_WIDTH, &maxWidth); glXGetFBConfigAttrib(window, *configs, GLX_MAX_PBUFFER_HEIGHT, &maxHeight); ms_uint32 uMaxHeight = maxHeight, uMaxWidth = maxWidth; this->width = MS_MIN(width, uMaxWidth); this->height = MS_MIN(height, uMaxHeight); int iPbufferAttributes[] = { GLX_PBUFFER_WIDTH, this->width, GLX_PBUFFER_HEIGHT, this->height, GLX_LARGEST_PBUFFER, false, 0, 0 }; pbuffer = glXCreatePbuffer(window, *configs, iPbufferAttributes); if (pbuffer == 0) { msSetError(MS_OGLERR, "glXCreatePbuffer failed. glError: %d", "OglContext::init()", glGetError()); return false; } return true; } bool OglContext::initWindow() { const char* const display_name = getenv("DISPLAY"); if (!display_name) { msSetError(MS_OGLERR, "DISPLAY environment variable not set", "OglContext::init()"); return false; } window = XOpenDisplay(display_name); if (!window) { msSetError(MS_OGLERR, "XOpenDisplay() failed.", "OglContext::init()"); return false; } const int fb_attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, 0, GLX_SAMPLE_BUFFERS_ARB, 1, 0 }; int num_configs = 0; GLXFBConfig* tempConfigs = glXChooseFBConfig(window, DefaultScreen(window), fb_attributes, &num_configs); if (tempConfigs == NULL || num_configs == 0) { msSetError(MS_OGLERR, "glXChooseFBConfig could not find any configs. Likely your video card or drivers are not supported.", "OglContext::initWindow()"); return false; } GLXContext tempContext = glXCreateNewContext(window, *tempConfigs, GLX_RGBA_TYPE, NULL, 1); if (tempContext == NULL) { msSetError(MS_OGLERR, "glXCreateNewContext failed.", "OglContext::initWindow()"); return false; } int iPbufferAttributes[] = {0, 0}; GLXPbuffer tempBuffer = glXCreatePbuffer(window, *tempConfigs, iPbufferAttributes); if (tempBuffer == 0) { msSetError(MS_OGLERR, "glXCreatePbuffer failed.", "OglContext::initWindow()"); return false; } if (!glXMakeCurrent(window, tempBuffer, tempContext)) { msSetError(MS_OGLERR, "glXMakeCurrent failed.", "OglContext::initWindow()"); return false; } glGetIntegerv(GL_MAX_SAMPLES_EXT, (GLint*)&MAX_MULTISAMPLE_SAMPLES); glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*) &MAX_ANISOTROPY); glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&MAX_TEXTURE_SIZE); MIN_TEXTURE_SIZE = 8; return true; } #endif /* UNIX */ #endif /* USE_OGL */ mapserver-7.4.3/mapoglcontext.h000066400000000000000000000070151357574274700166160ustar00rootroot00000000000000/****************************************************************************** * $id: mapoglcontext.h 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPOGLCONTEXT_H_ #define MAPOGLCONTEXT_H_ #ifdef USE_OGL #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #include "opengl/glext.h" #include "opengl/wglext.h" typedef HDC OGL_WINDOW; typedef HGLRC OGL_CONTEXT; typedef HGLRC OGL_PBUFFER; #define CALLBACK __stdcall #else #include #include #include typedef Display* OGL_WINDOW; typedef GLXContext OGL_CONTEXT; typedef GLXPbuffer OGL_PBUFFER; #define CALLBACK #endif class OglRenderer; class OglContext { private: static OglContext* current; static bool initWindow(); static bool initSharingContext(); static ms_uint32 getTextureSize(GLuint dimension, ms_uint32 value); static GLuint NextPowerOf2(GLuint in); #if defined(_WIN32) && !defined(__CYGWIN__) static HDC window; static HGLRC sharingContext; HDC hPBufferDC; HGLRC hPBufferRC; #else static Display* window; static GLXContext sharingContext; static GLXFBConfig* configs; GLXPbuffer pbuffer; #endif public: static ms_uint32 MAX_MULTISAMPLE_SAMPLES; static ms_uint32 MAX_ANISOTROPY; static ms_uint32 MAX_TEXTURE_SIZE; static ms_uint32 MIN_TEXTURE_SIZE; OglContext(ms_uint32 width, ms_uint32 height); ~OglContext(); int getHeight() const { return height; } int getWidth() const { return width; } bool isValid() const { return valid; } bool makeCurrent(); void bindPBufferToTexture(); private: bool createPBuffer(ms_uint32 width, ms_uint32 height); ms_uint32 width; ms_uint32 height; bool valid; int windowPixelFormat; #if defined(_WIN32) && !defined(__CYGWIN__) static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB; static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB; static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB; static PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB; #endif }; #endif /* USE_OGL */ #endif /* MAPOGLCONTEXT_H_ */ mapserver-7.4.3/mapoglrenderer.cpp000066400000000000000000000565671357574274700173130ustar00rootroot00000000000000/****************************************************************************** * $id: mapoglrenderer.cpp 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifdef USE_OGL #include #include #include "mapserver.h" #include "maperror.h" #include "mapoglrenderer.h" using namespace std; double OglRenderer::SIZE_RES = 100.0 / 72.0; ms_uint32 OglRenderer::OUTLINE_WIDTH = 2; ms_uint32 OglRenderer::FONT_SIZE = 20; ms_uint32 OglRenderer::FONT_RES = 200; double OglRenderer::OGL_PI = 3.14159265; ms_uint32 OglRenderer::SHAPE_CIRCLE_RES = 10; double OglRenderer::SHAPE_CIRCLE_RADIUS = 10.0; OglRenderer::fontCache_t OglRenderer::fontCache = OglRenderer::fontCache_t(); OglRenderer::dashCache_t OglRenderer::dashCache = OglRenderer::dashCache_t(); std::vector OglRenderer::shapes = std::vector(); GLvoid CALLBACK beginCallback(GLenum which); GLvoid CALLBACK errorCallback(GLenum errorCode); GLvoid CALLBACK endCallback(void); GLvoid CALLBACK combineDataCallback(GLdouble coords[3], GLdouble* vertex_data[4], GLfloat weight[4], void** dataOut, void* polygon_data); GLvoid CALLBACK vertexCallback(GLdouble *vertex); OglRenderer::OglRenderer(ms_uint32 width, ms_uint32 height, colorObj* color) : width(width), height(height), texture(NULL), transparency(1.0), valid(false) { context = new OglContext(width, height); if (!context->isValid()) return; if (!context->makeCurrent()) return; int viewPort[4]; glGetIntegerv(GL_VIEWPORT ,viewPort); viewportX = viewPort[0]; viewportY = viewPort[1]; viewportWidth = viewPort[2]; viewportHeight = viewPort[3]; glPushMatrix(); // set read/write context to pbuffer glEnable(GL_MULTISAMPLE_ARB); glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glDisable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // draw & read the front buffer of pbuffer glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); if (!(tess = gluNewTess())) { msSetError(MS_OGLERR, "P-buffer Error: Unable to create tessalotor", "OglRenderer"); return; } gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK*)(void)) vertexCallback); gluTessCallback(tess, GLU_TESS_BEGIN, (void(CALLBACK*)(void)) beginCallback); gluTessCallback(tess, GLU_TESS_END, (void(CALLBACK*)(void)) endCallback); gluTessCallback(tess, GLU_TESS_ERROR, (void(CALLBACK*)(void)) errorCallback); gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (void(CALLBACK*)(void)) combineDataCallback); if (color) { glClearColor((double) color->red / 255, (double) color->green / 255, (double) color->blue / 255, (double)color->alpha / 100); } else { glClearColor(0.0, 0.0, 0.0, 0.0); } glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, width, 0.0, height, -3.0, 3.0); createShapes(); valid = true; } OglRenderer::~OglRenderer() { makeCurrent(); glViewport(viewportX, viewportY, viewportWidth, viewportHeight); glPopMatrix(); delete context; } OglCachePtr OglRenderer::getTexture() { if (!texture) { makeCurrent(); texture = new OglCache(); texture->texture = createTexture(0,0);//TEXTURE_BORDER/2, TEXTURE_BORDER/2); texture->width = this->width; texture->height = this->height; } return texture; } GLuint OglRenderer::createTexture(ms_uint32 offsetX, ms_uint32 offsetY) { GLuint texture = 0; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST); if (OglContext::MAX_ANISOTROPY != 0) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, OglContext::MAX_ANISOTROPY); } glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, offsetX, offsetY, context->getWidth(), context->getHeight(), 0); glBindTexture(GL_TEXTURE_2D,0); return texture; } bool OglRenderer::getStringBBox(char *font, double size, char *string, rectObj *rect, double** advances) { FTFont* face = getFTFont(font, size); if (!face) { msSetError(MS_OGLERR, "Failed to load font (%s).", "OglRenderer::getStringBBox()", font); return false; } float llx =0.0f, lly=0.0f, llz=0.0f, urx=0.0f, ury=0.0f, urz=0.0f; glPushAttrib( GL_ALL_ATTRIB_BITS ); FTBBox boundingBox = face->BBox(string); glPopAttrib(); rect->minx = boundingBox.Lower().X(); rect->maxx = boundingBox.Upper().X(); rect->miny = -boundingBox.Upper().Y(); rect->maxy = -boundingBox.Lower().Y(); if (advances) { int length = strlen(string); *advances = new double[length]; for (int i = 0; i < length; ++i) { (*advances)[i] = face->Advance(&string[i], 1); } } return true; } void OglRenderer::initializeRasterBuffer(rasterBufferObj * rb, int width, int height, bool useAlpha) { unsigned char* buffer = new unsigned char[4 * width * height]; rb->data.rgba.pixels = buffer; rb->data.rgba.r = &buffer[2]; rb->data.rgba.g = &buffer[1]; rb->data.rgba.b = &buffer[0]; if (useAlpha) rb->data.rgba.a = &buffer[3]; rb->type =MS_BUFFER_BYTE_RGBA; rb->data.rgba.row_step = 4*width; rb->data.rgba.pixel_step = 4; rb->width = width; rb->height = height; } void OglRenderer::readRasterBuffer(rasterBufferObj * rb) { makeCurrent(); unsigned char* buffer = new unsigned char[4 * width * height]; glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, buffer); rb->type =MS_BUFFER_BYTE_RGBA; rb->data.rgba.pixels = buffer; rb->data.rgba.row_step = 4*width; rb->data.rgba.pixel_step = 4; rb->width = width; rb->height = height; rb->data.rgba.r = &buffer[2]; rb->data.rgba.g = &buffer[1]; rb->data.rgba.b = &buffer[0]; rb->data.rgba.a = NULL; } void OglRenderer::drawRasterBuffer(rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { // todo to support all alpha and srcx/y this needs to be done by creating a texture makeCurrent(); glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, overlay->data.rgba.pixels); } void OglRenderer::setTransparency(double transparency) { this->transparency = transparency; } void OglRenderer::setColor(colorObj *color) { if (color && MS_VALID_COLOR(*color)) { glColor4d((double) color->red / 255, (double) color->green / 255, (double) color->blue / 255, transparency); } else { glColor4d(0.0, 0.0, 0.0, 1.0); } } void OglRenderer::drawVectorLineStrip(symbolObj *symbol, double width) { glPushMatrix(); glLineWidth(width); glBegin(GL_LINE_STRIP); for (int i = 0; i < symbol->numpoints; i++) { if (symbol->points[i].x < 0 && symbol->points[i].y < 0) { glEnd(); glBegin(GL_LINE_STRIP); } else { glVertex2d(symbol->points[i].x, symbol->points[i].y); } } glEnd(); glPopMatrix(); } double OglRenderer::drawTriangles(pointObj* p1, pointObj* p2, double width, double tilelength, double textureStart) { double dx = p1->x - p2->x; double dy = p1->y - p2->y; double dist = sqrt(dx * dx + dy * dy); double theta; if (dx != 0) theta = atan(dy / dx); else theta = (dy > 0 ? 1 : -1) * OGL_PI / 2; double xw = sin(theta) * width / 2; double yw = cos(theta) * width / 2; double textureEnd = dist / tilelength; glTexCoord2d(textureStart, 1); glVertex2d(p1->x + xw, p1->y - yw); // Bottom Left Of The Texture and Quad glTexCoord2d(textureStart, 0); glVertex2d(p1->x - xw, p1->y + yw); // Bottom Right Of The Texture and Quad glTexCoord2d(textureStart + textureEnd, 1); glVertex2d(p2->x + xw, p2->y - yw); // Top Right Of The Texture and Quad glTexCoord2d(textureStart + textureEnd, 0); glVertex2d(p2->x - xw, p2->y + yw); // Top Left Of The Texture and Quad return dist; } double OglRenderer::drawQuad(pointObj* p1, pointObj* p2, double width, double tilelength, double textureStart) { double dx = p1->x - p2->x; double dy = p1->y - p2->y; double dist = sqrt(dx * dx + dy * dy); double theta; if (dx) theta = atan(dy / dx); else theta = (dy > 0 ? 1 : -1) * OGL_PI / 2; glPushMatrix(); glTranslated(p1->x, p1->y, 0); glRotated((p1->x < p2->x ? 0 : 180) + theta * (180 / OGL_PI), 0, 0, 1); glTranslated(-p1->x, -p1->y, 0); glBegin(GL_QUADS); glTexCoord2d(textureStart, 1); glVertex2d(p1->x, p1->y - width / 2); // Bottom Left Of The Texture and Quad glTexCoord2d(textureStart + (dist / tilelength), 1); glVertex2d(p1->x + dist, p1->y - width / 2); // Bottom Right Of The Texture and Quad glTexCoord2d(textureStart + (dist / tilelength), 0); glVertex2d(p1->x + dist, p1->y + width / 2); // Top Right Of The Texture and Quad glTexCoord2d(textureStart, 0); glVertex2d(p1->x, p1->y + width / 2); // Top Left Of The Texture and Quad glEnd(); glPopMatrix(); return dist; } void OglRenderer::renderTile(const OglCachePtr& tile, double x, double y, double angle) { makeCurrent(); glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); glBindTexture(GL_TEXTURE_2D, tile->texture); glPushMatrix(); glTranslated(x, y, 0); if (angle) { glRotated(angle, 0, 0, 1); } glTranslated(-x, -y, 0); glBegin(GL_QUADS); glTexCoord2d(0, 1); glVertex2d( x-(tile->width/2), y+(tile->height/2)); // Bottom Left Of The Texture and Quad glTexCoord2d(1, 1); glVertex2d( x+(tile->width/2), y+(tile->height/2)); // Bottom Right Of The Texture and Quad glTexCoord2d(1, 0); glVertex2d( x+(tile->width/2), y-(tile->height/2)); // Top Right Of The Texture and Quad glTexCoord2d(0, 0); glVertex2d( x-(tile->width/2), y-(tile->height/2)); // Top Left Of The Texture and Quad glEnd(); glPopMatrix(); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); } void OglRenderer::renderPolylineTile(shapeObj *shape, const OglCachePtr& tile) { makeCurrent(); glBindTexture(GL_TEXTURE_2D, tile->texture); // Select Our Texture glBegin(GL_TRIANGLE_STRIP); double place = 0.0; for (int i = 0; i < shape->numlines; i++) { for (int j = 0; j < shape->line[i].numpoints - 1; j++) { double dist = drawTriangles(&shape->line[i].point[j], &shape->line[i].point[j + 1], tile->height, tile->width, place / tile->width); place = (place + dist); while (place >= tile->width) place -= tile->width; } } glEnd(); glBindTexture(GL_TEXTURE_2D, 0); } void OglRenderer::renderVectorSymbol(double x, double y, symbolObj *symbol, double scale, double angle, colorObj *c, colorObj *oc, double ow) { makeCurrent(); glPushMatrix(); glTranslated(x, y, 0); glRotated(angle, 0, 0, 1); glScaled(scale, scale, 0); glTranslated(-symbol->sizex/2, -symbol->sizey/2, 0.0); if (oc != NULL && MS_VALID_COLOR(*oc) && ow > 0) { setColor(oc); drawVectorLineStrip(symbol, ow); } if (c != NULL && MS_VALID_COLOR(*c) && ow > 0) { setColor(c); drawVectorLineStrip(symbol, ow); } glPopMatrix(); } void OglRenderer::renderPolyline(shapeObj *p, colorObj *c, double width, int patternlength, double* pattern, int lineCap, int joinStyle, colorObj *outlinecolor, double outlinewidth) { makeCurrent(); if (outlinecolor) { glEnable(GL_DEPTH_TEST); glPushMatrix(); glTranslated(0, 0, 1); } setColor(c); if (patternlength > 0) { if (p->renderer_cache == NULL) { loadLine(p, width, patternlength, pattern); } /* FIXME */ if (p->renderer_cache == NULL) return; OglCache* cache = (OglCache*) p->renderer_cache; GLuint texture = cache->texture; if (cache->patternDistance > 0) { glBindTexture(GL_TEXTURE_2D, texture); double place = 0; glBegin(GL_TRIANGLE_STRIP); for (int j = 0; j < p->numlines; j++) { for (int i = 0; i < p->line[j].numpoints - 1; i++) { double dist = drawTriangles(&p->line[j].point[i], &p->line[j].point[i + 1], width, cache->patternDistance, place / cache->patternDistance); place = (place + dist); while (place >= cache->patternDistance) place -= cache->patternDistance; // better than mod, no rounding } } glEnd(); glBindTexture(GL_TEXTURE_2D, 0); } } else { float widthRange[2]; glGetFloatv(GL_LINE_WIDTH_RANGE, widthRange); bool quads = !(width >= widthRange[0] && width <= widthRange[1]); double circleScale = width / SHAPE_CIRCLE_RADIUS / 2; glLineWidth(width); if (quads || (width > 1.0 && (lineCap == MS_CJC_ROUND || joinStyle == MS_CJC_ROUND))) { for (int j = 0; j < p->numlines; j++) { for (int i = 0; i < p->line[j].numpoints; i++) { if (i != p->line[j].numpoints - 1) { if (quads) { drawQuad(&p->line[j].point[i], &p->line[j].point[i + 1], width); } else { glBegin(GL_LINES); glVertex2f(p->line[j].point[i].x, p->line[j].point[i].y); glVertex2f(p->line[j].point[i + 1].x,p->line[j].point[i + 1].y); glEnd(); } } if ((lineCap == MS_CJC_ROUND && (i == 0 || i == p->line[j].numpoints - 1)) || (joinStyle == MS_CJC_ROUND && (i > 0 && i < p->line[j].numpoints - 1))) { glPushMatrix(); glTranslated(p->line[j].point[i].x, p->line[j].point[i].y, 0); glScaled(circleScale, circleScale, 0); glCallList(shapes[circle]); glPopMatrix(); } } } } else { for (int j = 0; j < p->numlines; j++) { glBegin(GL_LINE_STRIP); for (int i = 0; i < p->line[j].numpoints; i++) { glVertex2f(p->line[j].point[i].x, p->line[j].point[i].y); } glEnd(); } } } if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor)) { glPopMatrix(); double owidth = MS_MAX(width + OUTLINE_WIDTH, outlinewidth); glPushMatrix(); glTranslated(0, 0, -1); renderPolyline(p, outlinecolor, owidth, patternlength, pattern, lineCap, joinStyle); glPopMatrix(); glDisable(GL_DEPTH_TEST); } } void OglRenderer::renderPolygon(shapeObj *p, colorObj *color, colorObj *outlinecolor, double outlinewidth, const OglCachePtr& tile, int lineCap, int joinStyle) { /* OpenGL cannot draw complex polygons so we need to use a Tessallator to draw the polygon using a GL_TRIANGLE_FAN ISSUE: There's a problem here. It would seem that changing the dimensions or bounding box area breaks the code. Reports need for a combine callback. */ makeCurrent(); std::vector pointers; double texWidth = 0; double texHeight = 0; if (tile) { glBindTexture(GL_TEXTURE_2D, tile->texture); // Select Our Texture texWidth = tile->width; texHeight = tile->height; } setColor(color); gluTessBeginPolygon(tess, NULL ); for (int j = 0; j < p->numlines; j++) { gluTessBeginContour(tess); for (int i = 0; i < p->line[j].numpoints; i++) { // create temp array and place GLdouble* dbls = new GLdouble[5]; pointers.push_back(dbls); dbls[0] = p->line[j].point[i].x; dbls[1] = p->line[j].point[i].y; dbls[2] = 0.0; dbls[3] = texWidth; dbls[4] = texHeight; gluTessVertex(tess, dbls, dbls); } gluTessEndContour(tess); } gluTessEndPolygon(tess); // destroy temp arrays for (std::vector::iterator iter = pointers.begin(); iter != pointers.end(); iter++) { delete[] *iter; } glBindTexture(GL_TEXTURE_2D, 0); // Select Our Texture if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor) && outlinewidth > 0) { renderPolyline(p, outlinecolor, outlinewidth, 0, NULL, lineCap, joinStyle); } } void OglRenderer::renderGlyphs(double x, double y, colorObj *color, colorObj *outlinecolor, double size, const char* font, char *thechars, double angle, colorObj *shadowcolor, double shdx, double shdy) { makeCurrent(); FTFont* face = getFTFont(font, size); if (!face) { msSetError(MS_OGLERR, "Failed to load font (%s).", "OglRenderer::renderGlyphs()", font); return; } glPushAttrib(GL_ALL_ATTRIB_BITS); glPushMatrix(); glTranslated(floor(x), floor(y), 0); glScaled(1.0, -1.0, 1); glRotated(angle * (180 / OGL_PI), 0, 0, 1); if (outlinecolor && MS_VALID_COLOR(*outlinecolor)) { setColor(outlinecolor); for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (i || j) { glPushMatrix(); glTranslated(i, j, 0); face->Render(thechars); glPopMatrix(); } } } } if (color != NULL && MS_VALID_COLOR(*color)) { setColor(color); face->Render(thechars); } glPopMatrix(); glPopAttrib(); } void OglRenderer::renderPixmap(symbolObj *symbol, double x, double y, double angle, double scale) { makeCurrent(); float zoomX, zoomY; glGetFloatv(GL_ZOOM_X, &zoomX); glGetFloatv(GL_ZOOM_Y, &zoomY); GLubyte* imgdata = symbol->pixmap_buffer->data.rgba.pixels; glPixelZoom(zoomX*scale, zoomY*scale); glRasterPos2d(x-symbol->pixmap_buffer->width/2, y-symbol->pixmap_buffer->height/2); glDrawPixels(symbol->pixmap_buffer->width, symbol->pixmap_buffer->height, GL_BGRA, GL_UNSIGNED_BYTE, imgdata); glPixelZoom(zoomX, zoomY); } void OglRenderer::renderEllipse(double x, double y, double angle, double width, double height, colorObj *color, colorObj *outlinecolor, double outlinewidth = 1.0) { makeCurrent(); if (outlinecolor && MS_VALID_COLOR(*outlinecolor)) { glEnable(GL_DEPTH_TEST); glPushMatrix(); glTranslated(0, 0, 1); } setColor(color); glPushMatrix(); if (angle) { glRotated(angle, 0, 0, 1); } glTranslated(x, y, 0); glScaled(width / SHAPE_CIRCLE_RADIUS / 2, height / SHAPE_CIRCLE_RADIUS / 2, 1); glCallList(shapes[circle]); glPopMatrix(); if (outlinecolor != NULL && MS_VALID_COLOR(*outlinecolor)) { glPopMatrix(); glPushMatrix(); glTranslated(0, 0, -1); renderEllipse(x, y, angle, width + outlinewidth, height, outlinecolor, NULL, 0); glPopMatrix(); glDisable(GL_DEPTH_TEST); } } bool OglRenderer::loadLine(shapeObj* shape, double width, int patternlength, double* pattern) { /* OglCache* cache = (OglCache*) shape->renderer_cache; if (cache->patternDistance == 0) { for (int i = 0; i < patternlength; i++) { cache->patternDistance += pattern[i]; } } GLubyte imgdata[TEX_SIZE * TEX_SIZE * 4]; int pow2length = min(max(NextPowerOf2(cache->patternDistance), MIN_TEX_SIZE), TEX_SIZE); int pow2width = min(max(NextPowerOf2(width), MIN_TEX_SIZE), TEX_SIZE); double lengthScale = (double) pow2length / cache->patternDistance; glColor3d(0, 0, 0); double place = 0; double xRadii = width / 2 * lengthScale; double yRadii = pow2width / 2; for (int i = 0; i < patternlength; i++) { double next = pattern[i] * lengthScale; if (i % 2 == 0) { glPushMatrix(); glTranslated(place + xRadii, yRadii, 0); glScaled(xRadii / SHAPE_CIRCLE_RADIUS, yRadii / SHAPE_CIRCLE_RADIUS, 0); glCallList(shapes[circle]); glPopMatrix(); glBegin(GL_QUADS); glVertex2d(place + pow2width / 2, 0); glVertex2d(place + next - pow2width / 2, 0); glVertex2d(place + next - pow2width / 2, pow2width); glVertex2d(place + pow2width / 2, pow2width); glEnd(); glPushMatrix(); glTranslated(place + next - xRadii, yRadii, 0); glScaled(xRadii / SHAPE_CIRCLE_RADIUS, yRadii / SHAPE_CIRCLE_RADIUS, 0); glCallList(shapes[circle]); glPopMatrix(); } place += next; } glReadPixels(0, 0, pow2length, pow2width, GL_RGBA, GL_UNSIGNED_BYTE, imgdata); //createTexture(pow2length, pow2width, GL_ALPHA, imgdata);*/ return true; } FTFont* OglRenderer::getFTFont(const char* font, double size) { FTFont** face = &fontCache[font][size]; if (*face == NULL && ifstream(font)) { *face = new FTGLTextureFont( font ); if (*face) { (*face)->UseDisplayList(true); (*face)->FaceSize(size*SIZE_RES); } } return *face; } GLvoid CALLBACK beginCallback(GLenum which) { glBegin(which); } GLvoid CALLBACK errorCallback(GLenum errorCode) { const GLubyte *estring; estring = gluErrorString(errorCode); fprintf(stderr, "Tessellation Error: %d %s\n", errorCode, estring); exit(0); } GLvoid CALLBACK endCallback(void) { glEnd(); } GLvoid CALLBACK combineDataCallback(GLdouble coords[3], GLdouble* vertex_data[4], GLfloat weight[4], void** dataOut, void* polygon_data) { GLdouble *vertex; vertex = (GLdouble *) malloc(5 * sizeof(GLdouble)); vertex[0] = coords[0]; vertex[1] = coords[1]; vertex[2] = coords[2]; vertex[3] = vertex_data[0][3]; vertex[4] = vertex_data[0][4]; *dataOut = vertex; } GLvoid CALLBACK vertexCallback(GLdouble *vertex) { if (vertex[3] > 0) glTexCoord2d(vertex[0]/vertex[3], vertex[1]/vertex[4]); glVertex3dv(vertex); } void OglRenderer::createShapes() { double da = MS_MIN(OGL_PI / 2, OGL_PI / SHAPE_CIRCLE_RES); GLuint circle = glGenLists(1); glNewList(circle, GL_COMPILE); glBegin(GL_TRIANGLE_FAN); glVertex2d(0, 0); for (double a = 0.0; a <= 2 * OGL_PI; a += da) { glVertex2d(0 + cos(a) * SHAPE_CIRCLE_RADIUS, 0 + sin(a) * SHAPE_CIRCLE_RADIUS); } glVertex2d(0 + SHAPE_CIRCLE_RADIUS, 0); glEnd(); glEndList(); shapes.push_back(circle); } void OglRenderer::makeCurrent() { context->makeCurrent(); } #endif mapserver-7.4.3/mapoglrenderer.h000066400000000000000000000122641357574274700167420ustar00rootroot00000000000000/****************************************************************************** * $id: mapoglrenderer.h 7725 2011-04-09 15:56:58Z toby $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef OGL_H #define OGL_H #ifdef USE_OGL #include "mapoglcontext.h" #include "mapserver.h" #include #include #include #include #include class OglCache { public: ~OglCache() { glDeleteTextures(1, &texture); } GLuint texture; ms_uint32 width; ms_uint32 height; ms_uint32 patternDistance; }; typedef OglCache* OglCachePtr; class OglRenderer { public: OglRenderer(ms_uint32 width, ms_uint32 height, colorObj* color = NULL); virtual ~OglRenderer(); void renderPolyline(shapeObj *p, colorObj *c, double width, int patternlength, double* pattern, int lineCap = MS_CJC_ROUND, int joinStyle = MS_CJC_ROUND, colorObj *outlinecolor = NULL, double outlinewidth = 0); void renderPolygon(shapeObj*, colorObj *color, colorObj *outlinecolor, double outlinewidth, const OglCachePtr& tile = OglCachePtr(), int lineCap=MS_CJC_ROUND, int joinStyle=MS_CJC_ROUND); void renderGlyphs(double x, double y, colorObj *color, colorObj *outlinecolor, double size, const char* font, char *thechars, double angle, colorObj *shadowcolor, double shdx, double shdy); void renderPixmap(symbolObj *symbol, double x, double y, double angle, double scale); void renderEllipse(double x, double y, double angle, double w, double h, colorObj *color, colorObj *outlinecolor, double outlinewidth); void renderVectorSymbol(double x, double y, symbolObj *symbol, double scale, double angle, colorObj *c, colorObj *oc, double ow); void renderTile(const OglCachePtr& tile, double x, double y, double angle); void renderPolylineTile(shapeObj *p, const OglCachePtr& tile); static bool getStringBBox(char *font, double size, char *string, rectObj *rect, double** advances); void setTransparency(double transparency); void readRasterBuffer(rasterBufferObj * rb); void drawRasterBuffer(rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height); static void initializeRasterBuffer(rasterBufferObj * rb, int width, int height, bool useAlpha); OglCachePtr getTexture(); int getWidth() const { return width; } int getHeight() const { return height; } bool isValid() const { return valid && context->isValid(); } protected: OglCachePtr texture; ms_uint32 width; ms_uint32 height; double transparency; bool valid; GLint viewportX; GLint viewportY; GLsizei viewportWidth; GLsizei viewportHeight; typedef std::map > fontCache_t; typedef std::map > dashCache_t; static FTFont* getFTFont(const char* font, double size); bool loadLine(shapeObj* shape, double width, int patternlength, double *pattern); double drawQuad(pointObj *p1, pointObj *p2, double width, double tilelength = 0.0, double textureStart = 0.0); double drawTriangles(pointObj *p1, pointObj *p2, double width, double tilelength = 0.0, double textureStart = 0.0); void drawVectorLineStrip(symbolObj *symbol, double width); void drawFan(pointObj* center, pointObj* from, pointObj* to, int resolution); void createShapes(); GLuint createTexture(ms_uint32 x, ms_uint32 y); void makeCurrent(); void setColor(colorObj *color); GLUtesselator *tess; enum shapes_t { circle = 0}; OglContext* context; static dashCache_t dashCache; static fontCache_t fontCache; static std::vector shapes; static std::vector testSymbols; static ms_uint32 OUTLINE_WIDTH; static ms_uint32 FONT_SIZE; static ms_uint32 FONT_RES; static double OGL_PI; static ms_uint32 SHAPE_CIRCLE_RES; static double SHAPE_CIRCLE_RADIUS; static double SIZE_RES; }; #endif /* USE_OGL */ #endif mapserver-7.4.3/mapogr.cpp000066400000000000000000006372231357574274700155640ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGR Link * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * Frank Warmerdam (warmerdam@pobox.com) * ********************************************************************** * Copyright (c) 2000-2005, Daniel Morissette, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include #include "mapserver.h" #include "mapproject.h" #include "mapthread.h" #include "mapows.h" #include #include #if defined(USE_OGR) || defined(USE_GDAL) # include "gdal_version.h" # include "cpl_conv.h" # include "cpl_string.h" # include "ogr_srs_api.h" #endif #define ACQUIRE_OGR_LOCK msAcquireLock( TLOCK_OGR ) #define RELEASE_OGR_LOCK msReleaseLock( TLOCK_OGR ) #ifdef USE_OGR // GDAL 1.x API #include "ogr_api.h" typedef struct ms_ogr_file_info_t { char *pszFname; char *pszLayerDef; int nLayerIndex; OGRDataSourceH hDS; OGRLayerH hLayer; OGRFeatureH hLastFeature; int nTileId; /* applies on the tiles themselves. */ projectionObj sTileProj; /* applies on the tiles themselves. */ struct ms_ogr_file_info_t *poCurTile; /* exists on tile index, -> tiles */ bool rect_is_defined; rectObj rect; /* set by TranslateMsExpression (possibly) and WhichShapes */ int last_record_index_read; const char* dialect; /* NULL, Spatialite or PostgreSQL */ char *pszSelect; char *pszSpatialFilterTableName; char *pszSpatialFilterGeometryColumn; char *pszMainTableName; char *pszRowId; int bIsOKForSQLCompose; bool bHasSpatialIndex; // used only for spatialite for now char* pszTablePrefix; // prefix to qualify field names. used only for spatialite & gpkg for now when a join is done for spatial filtering. int bPaging; char* pszWHERE; } msOGRFileInfo; static int msOGRLayerIsOpen(layerObj *layer); static int msOGRLayerInitItemInfo(layerObj *layer); static int msOGRLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape); static void msOGRCloseConnection( void *conn_handle ); /* ================================================================== * Geometry conversion functions * ================================================================== */ /********************************************************************** * ogrPointsAddPoint() * * NOTE: This function assumes the line->point array already has been * allocated large enough for the point to be added, but that numpoints * does not include this new point. **********************************************************************/ static void ogrPointsAddPoint(lineObj *line, double dX, double dY, #ifdef USE_POINT_Z_M double dZ, #endif int lineindex, rectObj *bounds) { /* Keep track of shape bounds */ if (line->numpoints == 0 && lineindex == 0) { bounds->minx = bounds->maxx = dX; bounds->miny = bounds->maxy = dY; } else { if (dX < bounds->minx) bounds->minx = dX; if (dX > bounds->maxx) bounds->maxx = dX; if (dY < bounds->miny) bounds->miny = dY; if (dY > bounds->maxy) bounds->maxy = dY; } line->point[line->numpoints].x = dX; line->point[line->numpoints].y = dY; #ifdef USE_POINT_Z_M line->point[line->numpoints].z = dZ; line->point[line->numpoints].m = 0.0; #endif line->numpoints++; } /********************************************************************** * ogrGeomPoints() **********************************************************************/ static int ogrGeomPoints(OGRGeometryH hGeom, shapeObj *outshp) { int i; int numpoints; if (hGeom == NULL) return 0; OGRwkbGeometryType eGType = wkbFlatten( OGR_G_GetGeometryType( hGeom ) ); /* -------------------------------------------------------------------- */ /* Container types result in recursive invocation on each */ /* subobject to add a set of points to the current list. */ /* -------------------------------------------------------------------- */ switch( eGType ) { case wkbGeometryCollection: case wkbMultiLineString: case wkbMultiPolygon: case wkbPolygon: { /* Treat it as GeometryCollection */ for (int iGeom=0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ ) { if( ogrGeomPoints( OGR_G_GetGeometryRef( hGeom, iGeom ), outshp ) == -1 ) return -1; } return 0; } break; case wkbPoint: case wkbMultiPoint: case wkbLineString: case wkbLinearRing: /* We will handle these directly */ break; default: /* There shouldn't be any more cases should there? */ msSetError(MS_OGRERR, "OGRGeometry type `%s' not supported yet.", "ogrGeomPoints()", OGR_G_GetGeometryName( hGeom ) ); return(-1); } /* ------------------------------------------------------------------ * Count total number of points * ------------------------------------------------------------------ */ if ( eGType == wkbPoint ) { numpoints = 1; } else if ( eGType == wkbLineString || eGType == wkbLinearRing ) { numpoints = OGR_G_GetPointCount( hGeom ); } else if ( eGType == wkbMultiPoint ) { numpoints = OGR_G_GetGeometryCount( hGeom ); } else { msSetError(MS_OGRERR, "OGRGeometry type `%s' not supported yet.", "ogrGeomPoints()", OGR_G_GetGeometryName( hGeom ) ); return(-1); } /* ------------------------------------------------------------------ * Do we need to allocate a line object to contain all our points? * ------------------------------------------------------------------ */ if( outshp->numlines == 0 ) { lineObj newline; newline.numpoints = 0; newline.point = NULL; msAddLine(outshp, &newline); } /* ------------------------------------------------------------------ * Extend the point array for the new of points to add from the * current geometry. * ------------------------------------------------------------------ */ lineObj *line = outshp->line + outshp->numlines-1; if( line->point == NULL ) line->point = (pointObj *) malloc(sizeof(pointObj) * numpoints); else line->point = (pointObj *) realloc(line->point,sizeof(pointObj) * (numpoints+line->numpoints)); if(!line->point) { msSetError(MS_MEMERR, "Unable to allocate temporary point cache.", "ogrGeomPoints()"); return(-1); } /* ------------------------------------------------------------------ * alloc buffer and filter/transform points * ------------------------------------------------------------------ */ if( eGType == wkbPoint ) { ogrPointsAddPoint(line, OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0), #ifdef USE_POINT_Z_M OGR_G_GetZ(hGeom, 0), #endif outshp->numlines-1, &(outshp->bounds)); } else if( eGType == wkbLineString || eGType == wkbLinearRing ) { for(i=0; inumlines-1, &(outshp->bounds)); } else if( eGType == wkbMultiPoint ) { for(i=0; inumlines-1, &(outshp->bounds)); } } outshp->type = MS_SHAPE_POINT; return(0); } /********************************************************************** * ogrGeomLine() * * Recursively convert any OGRGeometry into a shapeObj. Each part becomes * a line in the overall shapeObj. **********************************************************************/ static int ogrGeomLine(OGRGeometryH hGeom, shapeObj *outshp, int bCloseRings) { if (hGeom == NULL) return 0; /* ------------------------------------------------------------------ * Use recursive calls for complex geometries * ------------------------------------------------------------------ */ OGRwkbGeometryType eGType = wkbFlatten( OGR_G_GetGeometryType( hGeom ) ); if ( eGType == wkbPolygon || eGType == wkbGeometryCollection || eGType == wkbMultiLineString || eGType == wkbMultiPolygon ) { if (eGType == wkbPolygon && outshp->type == MS_SHAPE_NULL) outshp->type = MS_SHAPE_POLYGON; /* Treat it as GeometryCollection */ for (int iGeom=0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ ) { if( ogrGeomLine( OGR_G_GetGeometryRef( hGeom, iGeom ), outshp, bCloseRings ) == -1 ) return -1; } } /* ------------------------------------------------------------------ * OGRPoint and OGRMultiPoint * ------------------------------------------------------------------ */ else if ( eGType == wkbPoint || eGType == wkbMultiPoint ) { /* Hummmm a point when we're drawing lines/polygons... just drop it! */ } /* ------------------------------------------------------------------ * OGRLinearRing/OGRLineString ... both are of type wkbLineString * ------------------------------------------------------------------ */ else if ( eGType == wkbLineString ) { int j, numpoints; lineObj line= {0,NULL}; double dX, dY; if ((numpoints = OGR_G_GetPointCount( hGeom )) < 2) return 0; if (outshp->type == MS_SHAPE_NULL) outshp->type = MS_SHAPE_LINE; line.numpoints = 0; line.point = (pointObj *)malloc(sizeof(pointObj)*(numpoints+1)); if(!line.point) { msSetError(MS_MEMERR, "Unable to allocate temporary point cache.", "ogrGeomLine"); return(-1); } #if GDAL_VERSION_NUM >= 1900 OGR_G_GetPoints(hGeom, &(line.point[0].x), sizeof(pointObj), &(line.point[0].y), sizeof(pointObj), #ifdef USE_POINT_Z_M &(line.point[0].z), sizeof(pointObj)); #else NULL, 0); #endif #endif for(j=0; jnumlines == 0) { outshp->bounds.minx = outshp->bounds.maxx = dX; outshp->bounds.miny = outshp->bounds.maxy = dY; } else { if (dX < outshp->bounds.minx) outshp->bounds.minx = dX; if (dX > outshp->bounds.maxx) outshp->bounds.maxx = dX; if (dY < outshp->bounds.miny) outshp->bounds.miny = dY; if (dY > outshp->bounds.maxy) outshp->bounds.maxy = dY; } } line.numpoints = numpoints; if (bCloseRings && ( line.point[line.numpoints-1].x != line.point[0].x || line.point[line.numpoints-1].y != line.point[0].y ) ) { line.point[line.numpoints].x = line.point[0].x; line.point[line.numpoints].y = line.point[0].y; #ifdef USE_POINT_Z_M line.point[line.numpoints].z = line.point[0].z; #endif line.numpoints++; } msAddLineDirectly(outshp, &line); } else { msSetError(MS_OGRERR, "OGRGeometry type `%s' not supported.", "ogrGeomLine()", OGR_G_GetGeometryName( hGeom ) ); return(-1); } return(0); } /********************************************************************** * ogrGetLinearGeometry() * * Fetch geometry from OGR feature. If using GDAL 2.0 or later, the geometry * might be of curve type, so linearize it. **********************************************************************/ static OGRGeometryH ogrGetLinearGeometry(OGRFeatureH hFeature) { #if GDAL_VERSION_MAJOR >= 2 /* Convert in place and reassign to the feature */ OGRGeometryH hGeom = OGR_F_StealGeometry(hFeature); if( hGeom != NULL ) { hGeom = OGR_G_ForceTo(hGeom, OGR_GT_GetLinear(OGR_G_GetGeometryType(hGeom)), NULL); OGR_F_SetGeometryDirectly(hFeature, hGeom); } return hGeom; #else return OGR_F_GetGeometryRef( hFeature ); #endif } /********************************************************************** * ogrConvertGeometry() * * Convert OGR geometry into a shape object doing the best possible * job to match OGR Geometry type and layer type. * * If layer type is incompatible with geometry, then shape is returned with * shape->type = MS_SHAPE_NULL **********************************************************************/ static int ogrConvertGeometry(OGRGeometryH hGeom, shapeObj *outshp, enum MS_LAYER_TYPE layertype) { /* ------------------------------------------------------------------ * Process geometry according to layer type * ------------------------------------------------------------------ */ int nStatus = MS_SUCCESS; if (hGeom == NULL) { // Empty geometry... this is not an error... we'll just skip it return MS_SUCCESS; } switch(layertype) { /* ------------------------------------------------------------------ * POINT layer - Any geometry can be converted to point/multipoint * ------------------------------------------------------------------ */ case MS_LAYER_POINT: if(ogrGeomPoints(hGeom, outshp) == -1) { nStatus = MS_FAILURE; // Error message already produced. } break; /* ------------------------------------------------------------------ * LINE layer * ------------------------------------------------------------------ */ case MS_LAYER_LINE: if(ogrGeomLine(hGeom, outshp, MS_FALSE) == -1) { nStatus = MS_FAILURE; // Error message already produced. } if (outshp->type != MS_SHAPE_LINE && outshp->type != MS_SHAPE_POLYGON) outshp->type = MS_SHAPE_NULL; // Incompatible type for this layer break; /* ------------------------------------------------------------------ * POLYGON layer * ------------------------------------------------------------------ */ case MS_LAYER_POLYGON: if(ogrGeomLine(hGeom, outshp, MS_TRUE) == -1) { nStatus = MS_FAILURE; // Error message already produced. } if (outshp->type != MS_SHAPE_POLYGON) outshp->type = MS_SHAPE_NULL; // Incompatible type for this layer break; /* ------------------------------------------------------------------ * Chart or Query layers - return real feature type * ------------------------------------------------------------------ */ case MS_LAYER_CHART: case MS_LAYER_QUERY: switch( OGR_G_GetGeometryType( hGeom ) ) { case wkbPoint: case wkbPoint25D: case wkbMultiPoint: case wkbMultiPoint25D: if(ogrGeomPoints(hGeom, outshp) == -1) { nStatus = MS_FAILURE; // Error message already produced. } break; default: // Handle any non-point types as lines/polygons ... ogrGeomLine() // will decide the shape type if(ogrGeomLine(hGeom, outshp, MS_FALSE) == -1) { nStatus = MS_FAILURE; // Error message already produced. } } break; default: msSetError(MS_MISCERR, "Unknown or unsupported layer type.", "msOGRLayerNextShape()"); nStatus = MS_FAILURE; } /* switch layertype */ return nStatus; } /********************************************************************** * msOGRGeometryToShape() * * Utility function to convert from OGR geometry to a mapserver shape * object. **********************************************************************/ int msOGRGeometryToShape(OGRGeometryH hGeometry, shapeObj *psShape, OGRwkbGeometryType nType) { if (hGeometry && psShape && nType > 0) { if (nType == wkbPoint || nType == wkbMultiPoint ) return ogrConvertGeometry(hGeometry, psShape, MS_LAYER_POINT); else if (nType == wkbLineString || nType == wkbMultiLineString) return ogrConvertGeometry(hGeometry, psShape, MS_LAYER_LINE); else if (nType == wkbPolygon || nType == wkbMultiPolygon) return ogrConvertGeometry(hGeometry, psShape, MS_LAYER_POLYGON); else return MS_FAILURE; } else return MS_FAILURE; } /* ================================================================== * Attributes handling functions * ================================================================== */ // Special field index codes for handling text string and angle coming from // OGR style strings. #define MSOGR_FID_INDEX -99 #define MSOGR_LABELNUMITEMS 21 #define MSOGR_LABELFONTNAMENAME "OGR:LabelFont" #define MSOGR_LABELFONTNAMEINDEX -100 #define MSOGR_LABELSIZENAME "OGR:LabelSize" #define MSOGR_LABELSIZEINDEX -101 #define MSOGR_LABELTEXTNAME "OGR:LabelText" #define MSOGR_LABELTEXTINDEX -102 #define MSOGR_LABELANGLENAME "OGR:LabelAngle" #define MSOGR_LABELANGLEINDEX -103 #define MSOGR_LABELFCOLORNAME "OGR:LabelFColor" #define MSOGR_LABELFCOLORINDEX -104 #define MSOGR_LABELBCOLORNAME "OGR:LabelBColor" #define MSOGR_LABELBCOLORINDEX -105 #define MSOGR_LABELPLACEMENTNAME "OGR:LabelPlacement" #define MSOGR_LABELPLACEMENTINDEX -106 #define MSOGR_LABELANCHORNAME "OGR:LabelAnchor" #define MSOGR_LABELANCHORINDEX -107 #define MSOGR_LABELDXNAME "OGR:LabelDx" #define MSOGR_LABELDXINDEX -108 #define MSOGR_LABELDYNAME "OGR:LabelDy" #define MSOGR_LABELDYINDEX -109 #define MSOGR_LABELPERPNAME "OGR:LabelPerp" #define MSOGR_LABELPERPINDEX -110 #define MSOGR_LABELBOLDNAME "OGR:LabelBold" #define MSOGR_LABELBOLDINDEX -111 #define MSOGR_LABELITALICNAME "OGR:LabelItalic" #define MSOGR_LABELITALICINDEX -112 #define MSOGR_LABELUNDERLINENAME "OGR:LabelUnderline" #define MSOGR_LABELUNDERLINEINDEX -113 #define MSOGR_LABELPRIORITYNAME "OGR:LabelPriority" #define MSOGR_LABELPRIORITYINDEX -114 #define MSOGR_LABELSTRIKEOUTNAME "OGR:LabelStrikeout" #define MSOGR_LABELSTRIKEOUTINDEX -115 #define MSOGR_LABELSTRETCHNAME "OGR:LabelStretch" #define MSOGR_LABELSTRETCHINDEX -116 #define MSOGR_LABELADJHORNAME "OGR:LabelAdjHor" #define MSOGR_LABELADJHORINDEX -117 #define MSOGR_LABELADJVERTNAME "OGR:LabelAdjVert" #define MSOGR_LABELADJVERTINDEX -118 #define MSOGR_LABELHCOLORNAME "OGR:LabelHColor" #define MSOGR_LABELHCOLORINDEX -119 #define MSOGR_LABELOCOLORNAME "OGR:LabelOColor" #define MSOGR_LABELOCOLORINDEX -120 // Special codes for the OGR style parameters #define MSOGR_LABELPARAMNAME "OGR:LabelParam" #define MSOGR_LABELPARAMNAMELEN 14 #define MSOGR_LABELPARAMINDEX -500 #define MSOGR_BRUSHPARAMNAME "OGR:BrushParam" #define MSOGR_BRUSHPARAMNAMELEN 14 #define MSOGR_BRUSHPARAMINDEX -600 #define MSOGR_PENPARAMNAME "OGR:PenParam" #define MSOGR_PENPARAMNAMELEN 12 #define MSOGR_PENPARAMINDEX -700 #define MSOGR_SYMBOLPARAMNAME "OGR:SymbolParam" #define MSOGR_SYMBOLPARAMNAMELEN 15 #define MSOGR_SYMBOLPARAMINDEX -800 /********************************************************************** * msOGRGetValues() * * Load selected item (i.e. field) values into a char array * * Some special attribute names are used to return some OGRFeature params * like for instance stuff encoded in the OGRStyleString. * For now the following pseudo-attribute names are supported: * "OGR:TextString" OGRFeatureStyle's text string if present * "OGR:TextAngle" OGRFeatureStyle's text angle, or 0 if not set **********************************************************************/ static char **msOGRGetValues(layerObj *layer, OGRFeatureH hFeature) { char **values; const char *pszValue = NULL; int i; if(layer->numitems == 0) return(NULL); if(!layer->iteminfo) // Should not happen... but just in case! if (msOGRLayerInitItemInfo(layer) != MS_SUCCESS) return NULL; if((values = (char **)malloc(sizeof(char *)*layer->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msOGRGetValues()"); return(NULL); } OGRStyleMgrH hStyleMgr = NULL; OGRStyleToolH hLabelStyle = NULL; OGRStyleToolH hPenStyle = NULL; OGRStyleToolH hBrushStyle = NULL; OGRStyleToolH hSymbolStyle = NULL; int *itemindexes = (int*)layer->iteminfo; for(i=0; inumitems; i++) { if (itemindexes[i] >= 0) { // Extract regular attributes values[i] = msStrdup(OGR_F_GetFieldAsString( hFeature, itemindexes[i])); } else if (itemindexes[i] == MSOGR_FID_INDEX ) { values[i] = msStrdup(CPLSPrintf(CPL_FRMT_GIB, (GIntBig) OGR_F_GetFID(hFeature))); } else { // Handle special OGR attributes coming from StyleString if (!hStyleMgr) { hStyleMgr = OGR_SM_Create(NULL); OGR_SM_InitFromFeature(hStyleMgr, hFeature); int numParts = OGR_SM_GetPartCount(hStyleMgr, NULL); for(int i=0; imap) OGR_ST_SetUnit(hStylePart, OGRSTUPixel, layer->map->cellsize*layer->map->resolution/layer->map->defresolution*72.0*39.37); } } int bDefault; if (itemindexes[i] == MSOGR_LABELTEXTINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelTextString, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELTEXTNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELANGLEINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelAngle, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELANGLENAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELSIZEINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelSize, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELSIZENAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELFCOLORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelFColor, &bDefault)) == NULL)) values[i] = msStrdup("#000000"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELFCOLORNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELFONTNAMEINDEX ) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelFontName, &bDefault)) == NULL)) values[i] = msStrdup("Arial"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELFONTNAMENAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELBCOLORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelBColor, &bDefault)) == NULL)) values[i] = msStrdup("#000000"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELBCOLORNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELPLACEMENTINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelPlacement, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELPLACEMENTNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELANCHORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelAnchor, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELANCHORNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELDXINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelDx, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELDXNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELDYINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelDy, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELDYNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELPERPINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelPerp, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELPERPNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELBOLDINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelBold, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELBOLDNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELITALICINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelItalic, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELITALICNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELUNDERLINEINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelUnderline, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELUNDERLINENAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELPRIORITYINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelPriority, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELPRIORITYNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELSTRIKEOUTINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelStrikeout, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELSTRIKEOUTNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELSTRETCHINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelStretch, &bDefault)) == NULL)) values[i] = msStrdup("0"); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELSTRETCHNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELADJHORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelAdjHor, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELADJHORNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELADJVERTINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelAdjVert, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELADJVERTNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] == MSOGR_LABELHCOLORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelHColor, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELHCOLORNAME " = \"%s\"\n", values[i]); } #if GDAL_VERSION_NUM >= 1600 else if (itemindexes[i] == MSOGR_LABELOCOLORINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelOColor, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELOCOLORNAME " = \"%s\"\n", values[i]); } #endif /* GDAL_VERSION_NUM >= 1600 */ else if (itemindexes[i] >= MSOGR_LABELPARAMINDEX) { if (hLabelStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hLabelStyle, itemindexes[i] - MSOGR_LABELPARAMINDEX, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_LABELPARAMNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] >= MSOGR_BRUSHPARAMINDEX) { if (hBrushStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hBrushStyle, itemindexes[i] - MSOGR_BRUSHPARAMINDEX, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_BRUSHPARAMNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] >= MSOGR_PENPARAMINDEX) { if (hPenStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hPenStyle, itemindexes[i] - MSOGR_PENPARAMINDEX, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_PENPARAMNAME " = \"%s\"\n", values[i]); } else if (itemindexes[i] >= MSOGR_SYMBOLPARAMINDEX) { if (hSymbolStyle == NULL || ((pszValue = OGR_ST_GetParamStr(hSymbolStyle, itemindexes[i] - MSOGR_SYMBOLPARAMINDEX, &bDefault)) == NULL)) values[i] = msStrdup(""); else values[i] = msStrdup(pszValue); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug(MSOGR_SYMBOLPARAMNAME " = \"%s\"\n", values[i]); } else { msFreeCharArray(values,i); OGR_SM_Destroy(hStyleMgr); OGR_ST_Destroy(hLabelStyle); OGR_ST_Destroy(hPenStyle); OGR_ST_Destroy(hBrushStyle); OGR_ST_Destroy(hSymbolStyle); msSetError(MS_OGRERR,"Invalid field index!?!","msOGRGetValues()"); return(NULL); } } } OGR_SM_Destroy(hStyleMgr); OGR_ST_Destroy(hLabelStyle); OGR_ST_Destroy(hPenStyle); OGR_ST_Destroy(hBrushStyle); OGR_ST_Destroy(hSymbolStyle); return(values); } #endif /* USE_OGR */ #if defined(USE_OGR) || defined(USE_GDAL) /********************************************************************** * msOGRSpatialRef2ProjectionObj() * * Init a MapServer projectionObj using an OGRSpatialRef * Works only with PROJECTION AUTO * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ static int msOGRSpatialRef2ProjectionObj(OGRSpatialReferenceH hSRS, projectionObj *proj, int debug_flag ) { #ifdef USE_PROJ // First flush the "auto" name from the projargs[]... msFreeProjection( proj ); if (hSRS == NULL || OSRIsLocal( hSRS ) ) { // Dataset had no set projection or is NonEarth (LOCAL_CS)... // Nothing else to do. Leave proj empty and no reprojection will happen! return MS_SUCCESS; } // Export OGR SRS to a PROJ4 string char *pszProj = NULL; if (OSRExportToProj4( hSRS, &pszProj ) != OGRERR_NONE || pszProj == NULL || strlen(pszProj) == 0) { msSetError(MS_OGRERR, "Conversion from OGR SRS to PROJ4 failed.", "msOGRSpatialRef2ProjectionObj()"); CPLFree(pszProj); return(MS_FAILURE); } if( debug_flag ) msDebug( "AUTO = %s\n", pszProj ); if( msLoadProjectionString( proj, pszProj ) != 0 ) return MS_FAILURE; CPLFree(pszProj); #endif return MS_SUCCESS; } #endif // defined(USE_OGR) || defined(USE_GDAL) /********************************************************************** * msOGCWKT2ProjectionObj() * * Init a MapServer projectionObj using an OGC WKT definition. * Works only with PROJECTION AUTO * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGCWKT2ProjectionObj( const char *pszWKT, projectionObj *proj, int debug_flag ) { #if defined(USE_OGR) || defined(USE_GDAL) OGRSpatialReferenceH hSRS; char *pszAltWKT = (char *) pszWKT; OGRErr eErr; int ms_result; hSRS = OSRNewSpatialReference( NULL ); if( !EQUALN(pszWKT,"GEOGCS",6) && !EQUALN(pszWKT,"PROJCS",6) && !EQUALN(pszWKT,"LOCAL_CS",8) ) eErr = OSRSetFromUserInput( hSRS, pszWKT ); else eErr = OSRImportFromWkt( hSRS, &pszAltWKT ); if( eErr != OGRERR_NONE ) { OSRDestroySpatialReference( hSRS ); msSetError(MS_OGRERR, "Ingestion of WKT string '%s' failed.", "msOGCWKT2ProjectionObj()", pszWKT ); return MS_FAILURE; } ms_result = msOGRSpatialRef2ProjectionObj( hSRS, proj, debug_flag ); OSRDestroySpatialReference( hSRS ); return ms_result; #else msSetError(MS_OGRERR, "Not implemented since neither OGR nor GDAL is enabled.", "msOGCWKT2ProjectionObj()"); return MS_FAILURE; #endif } /********************************************************************** * msOGRFileOpen() * * Open an OGR connection, and initialize a msOGRFileInfo. **********************************************************************/ #ifdef USE_OGR static int bOGRDriversRegistered = MS_FALSE; #endif void msOGRInitialize(void) { #ifdef USE_OGR /* ------------------------------------------------------------------ * Register OGR Drivers, only once per execution * ------------------------------------------------------------------ */ if (!bOGRDriversRegistered) { ACQUIRE_OGR_LOCK; OGRRegisterAll(); CPLPushErrorHandler( CPLQuietErrorHandler ); /* ------------------------------------------------------------------ * Pass config option GML_FIELDTYPES=ALWAYS_STRING to OGR so that all * GML attributes are returned as strings to MapServer. This is most efficient * and prevents problems with autodetection of some attribute types. * ------------------------------------------------------------------ */ CPLSetConfigOption("GML_FIELDTYPES","ALWAYS_STRING"); bOGRDriversRegistered = MS_TRUE; RELEASE_OGR_LOCK; } #endif /* USE_OGR */ } /* ================================================================== * The following functions closely relate to the API called from * maplayer.c, but are intended to be used for the tileindex or direct * layer access. * ================================================================== */ #ifdef USE_OGR static void msOGRFileOpenSpatialite( layerObj *layer, const char *pszLayerDef, msOGRFileInfo *psInfo ); /********************************************************************** * msOGRFileOpen() * * Open an OGR connection, and initialize a msOGRFileInfo. **********************************************************************/ static msOGRFileInfo * msOGRFileOpen(layerObj *layer, const char *connection ) { char *conn_decrypted = NULL; msOGRInitialize(); /* ------------------------------------------------------------------ * Make sure any encrypted token in the connection string are decrypted * ------------------------------------------------------------------ */ if (connection) { conn_decrypted = msDecryptStringTokens(layer->map, connection); if (conn_decrypted == NULL) return NULL; /* An error should already have been reported */ } /* ------------------------------------------------------------------ * Parse connection string into dataset name, and layer name. * ------------------------------------------------------------------ */ char *pszDSName = NULL, *pszLayerDef = NULL; if( conn_decrypted == NULL ) { /* we don't have anything */ } else if( layer->data != NULL ) { pszDSName = CPLStrdup(conn_decrypted); pszLayerDef = CPLStrdup(layer->data); } else { char **papszTokens = NULL; papszTokens = CSLTokenizeStringComplex( conn_decrypted, ",", TRUE, FALSE ); if( CSLCount(papszTokens) > 0 ) pszDSName = CPLStrdup( papszTokens[0] ); if( CSLCount(papszTokens) > 1 ) pszLayerDef = CPLStrdup( papszTokens[1] ); CSLDestroy(papszTokens); } /* Get rid of decrypted connection string. We'll use the original (not * decrypted) string for debug and error messages in the rest of the code. */ msFree(conn_decrypted); conn_decrypted = NULL; if( pszDSName == NULL ) { msSetError(MS_OGRERR, "Error parsing OGR connection information in layer `%s'", "msOGRFileOpen()", layer->name?layer->name:"(null)" ); return NULL; } if( pszLayerDef == NULL ) pszLayerDef = CPLStrdup("0"); /* -------------------------------------------------------------------- */ /* Can we get an existing connection for this layer? */ /* -------------------------------------------------------------------- */ OGRDataSourceH hDS; hDS = (OGRDataSourceH) msConnPoolRequest( layer ); /* -------------------------------------------------------------------- */ /* If not, open now, and register this connection with the */ /* pool. */ /* -------------------------------------------------------------------- */ if( hDS == NULL ) { char szPath[MS_MAXPATHLEN] = ""; const char *pszDSSelectedName = pszDSName; if( layer->debug ) msDebug("msOGRFileOpen(%s)...\n", connection); CPLErrorReset(); if (msTryBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, pszDSName) != NULL || msTryBuildPath(szPath, layer->map->mappath, pszDSName) != NULL) { /* Use relative path */ pszDSSelectedName = szPath; } if( layer->debug ) msDebug("OGROPen(%s)\n", pszDSSelectedName); ACQUIRE_OGR_LOCK; hDS = OGROpen( pszDSSelectedName, MS_FALSE, NULL ); RELEASE_OGR_LOCK; if( hDS == NULL ) { msSetError(MS_OGRERR, "Open failed for OGR connection in layer `%s'. " "File not found or unsupported format. Check server logs.", "msOGRFileOpen()", layer->name?layer->name:"(null)" ); if( strlen(CPLGetLastErrorMsg()) == 0 ) msDebug("Open failed for OGR connection in layer `%s'.\n%s\n", layer->name?layer->name:"(null)", CPLGetLastErrorMsg() ); CPLFree( pszDSName ); CPLFree( pszLayerDef ); return NULL; } msConnPoolRegister( layer, hDS, msOGRCloseConnection ); } CPLFree( pszDSName ); pszDSName = NULL; /* ------------------------------------------------------------------ * Find the layer selected. * ------------------------------------------------------------------ */ int nLayerIndex = 0; OGRLayerH hLayer = NULL; int iLayer; if( EQUALN(pszLayerDef,"SELECT ",7) ) { ACQUIRE_OGR_LOCK; hLayer = OGR_DS_ExecuteSQL( hDS, pszLayerDef, NULL, NULL ); if( hLayer == NULL ) { msSetError(MS_OGRERR, "ExecuteSQL() failed. Check server logs.", "msOGRFileOpen()"); if( strlen(CPLGetLastErrorMsg()) == 0 ) msDebug("ExecuteSQL(%s) failed.\n%s\n", pszLayerDef, CPLGetLastErrorMsg() ); RELEASE_OGR_LOCK; msConnPoolRelease( layer, hDS ); CPLFree( pszLayerDef ); return NULL; } RELEASE_OGR_LOCK; nLayerIndex = -1; } for( iLayer = 0; hLayer == NULL && iLayer < OGR_DS_GetLayerCount(hDS); iLayer++ ) { hLayer = OGR_DS_GetLayer( hDS, iLayer ); if( hLayer != NULL #if GDAL_VERSION_NUM >= 1800 && EQUAL(OGR_L_GetName(hLayer),pszLayerDef) ) #else && EQUAL(OGR_FD_GetName( OGR_L_GetLayerDefn(hLayer) ),pszLayerDef) ) #endif { nLayerIndex = iLayer; break; } else hLayer = NULL; } if( hLayer == NULL && (atoi(pszLayerDef) > 0 || EQUAL(pszLayerDef,"0")) ) { nLayerIndex = atoi(pszLayerDef); if( nLayerIndex < OGR_DS_GetLayerCount(hDS) ) hLayer = OGR_DS_GetLayer( hDS, nLayerIndex ); } if (hLayer == NULL) { msSetError(MS_OGRERR, "GetLayer(%s) failed for OGR connection. Check logs.", "msOGRFileOpen()", pszLayerDef); msDebug("GetLayer(%s) failed for OGR connection `%s'.\n", pszLayerDef, connection ); CPLFree( pszLayerDef ); msConnPoolRelease( layer, hDS ); return NULL; } /* ------------------------------------------------------------------ * OK... open succeded... alloc and fill msOGRFileInfo inside layer obj * ------------------------------------------------------------------ */ msOGRFileInfo *psInfo =(msOGRFileInfo*)CPLCalloc(1,sizeof(msOGRFileInfo)); psInfo->pszFname = CPLStrdup(OGR_DS_GetName( hDS )); psInfo->pszLayerDef = pszLayerDef; psInfo->nLayerIndex = nLayerIndex; psInfo->hDS = hDS; psInfo->hLayer = hLayer; psInfo->nTileId = 0; msInitProjection(&(psInfo->sTileProj)); psInfo->poCurTile = NULL; psInfo->rect_is_defined = false; psInfo->rect.minx = psInfo->rect.maxx = 0; psInfo->rect.miny = psInfo->rect.maxy = 0; psInfo->last_record_index_read = -1; psInfo->dialect = NULL; psInfo->pszSelect = NULL; psInfo->pszSpatialFilterTableName = NULL; psInfo->pszSpatialFilterGeometryColumn = NULL; psInfo->pszMainTableName = NULL; psInfo->pszRowId = NULL; psInfo->bIsOKForSQLCompose = true; psInfo->bPaging = false; psInfo->bHasSpatialIndex = false; psInfo->pszTablePrefix = NULL; psInfo->pszWHERE = NULL; // GDAL 1.x API OGRSFDriverH dr = OGR_DS_GetDriver(hDS); const char *name = OGR_Dr_GetName(dr); if (strcmp(name, "SQLite") == 0) { bool have_spatialite = false; CPLPushErrorHandler(CPLQuietErrorHandler); // test for Spatialite support in driver const char *test_spatialite = "SELECT spatialite_version()"; OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_spatialite, NULL, NULL); if (l) { OGR_DS_ReleaseResultSet(hDS, l); have_spatialite = true; } // test for Spatialite enabled db if (have_spatialite) { have_spatialite = false; const char *test_sql = "select 1 from sqlite_master where name = 'geometry_columns' and sql LIKE '%spatial_index_enabled%'"; OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_sql, NULL, NULL); if (l) { if (OGR_L_GetFeatureCount(l, TRUE) == 1) have_spatialite = true; OGR_DS_ReleaseResultSet(hDS, l); } } CPLPopErrorHandler(); CPLErrorReset(); if (have_spatialite) psInfo->dialect = "Spatialite"; else msDebug("msOGRFileOpen: Native SQL not available, no Spatialite support and/or not a Spatialite enabled db\n"); } else if (strcmp(name, "PostgreSQL") == 0) { psInfo->dialect = "PostgreSQL"; // todo: PostgreSQL not yet tested } else if (strcmp(name, "GPKG") == 0 && nLayerIndex >= 0 && atoi(GDALVersionInfo("VERSION_NUM")) >= 2000000) { bool has_rtree = false; const char* test_rtree = CPLSPrintf("SELECT 1 FROM sqlite_master WHERE name = 'rtree_%s_%s'", OGR_L_GetName(hLayer), OGR_L_GetGeometryColumn(hLayer)); OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_rtree, NULL, NULL); if( l ) { if( OGR_L_GetFeatureCount(l, TRUE) == 1 ) { has_rtree = true; } OGR_DS_ReleaseResultSet(hDS, l); } if( has_rtree ) { bool have_gpkg_spatialite = false; CPLPushErrorHandler(CPLQuietErrorHandler); // test for Spatialite >= 4.3 support in driver const char *test_spatialite = "SELECT spatialite_version()"; l = OGR_DS_ExecuteSQL(hDS, test_spatialite, NULL, NULL); if (l) { OGRFeatureH hFeat = OGR_L_GetNextFeature(l); if( hFeat ) { const char* pszVersion = OGR_F_GetFieldAsString(hFeat, 0); have_gpkg_spatialite = atof(pszVersion) >= 4.3; OGR_F_Destroy(hFeat); } OGR_DS_ReleaseResultSet(hDS, l); } CPLPopErrorHandler(); CPLErrorReset(); if( have_gpkg_spatialite ) { psInfo->pszMainTableName = msStrdup( OGR_L_GetName(hLayer) ); psInfo->pszTablePrefix = msStrdup( psInfo->pszMainTableName ); psInfo->pszSpatialFilterTableName = msStrdup( OGR_L_GetName(hLayer) ); psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_L_GetGeometryColumn(hLayer) ); psInfo->dialect = "GPKG"; psInfo->bPaging = true; psInfo->bHasSpatialIndex = true; } else msDebug("msOGRFileOpen: Spatialite support in GPKG not enabled\n"); } else { msDebug("msOGRFileOpen: RTree index not available\n"); } } if( psInfo->dialect != NULL && EQUAL(psInfo->dialect, "Spatialite") ) msOGRFileOpenSpatialite(layer, pszLayerDef, psInfo); return psInfo; } /************************************************************************/ /* msOGRFileOpenSpatialite() */ /************************************************************************/ static void msOGRFileOpenSpatialite( layerObj *layer, const char* pszLayerDef, msOGRFileInfo *psInfo ) { // In the case of a SQLite DB, check that we can identify the // underlying table if( psInfo->nLayerIndex == -1 ) { psInfo->bIsOKForSQLCompose = false; const char* from = strstr( psInfo->pszLayerDef, " from "); if( from == NULL ) from = strstr( psInfo->pszLayerDef, " FROM "); if( from ) { const char* pszBeginningOfTable = from + strlen(" FROM "); const char* pszIter = pszBeginningOfTable; while( *pszIter && *pszIter != ' ' ) pszIter ++; if( strchr(pszIter, ',') == NULL && strstr(pszIter, " where ") == NULL && strstr(pszIter, " WHERE ") == NULL && strstr(pszIter, " join ") == NULL && strstr(pszIter, " JOIN ") == NULL && strstr(pszIter, " order by ") == NULL && strstr(pszIter, " ORDER BY ") == NULL) { psInfo->bIsOKForSQLCompose = true; psInfo->pszMainTableName = msStrdup(pszBeginningOfTable); psInfo->pszMainTableName[pszIter - pszBeginningOfTable] = '\0'; psInfo->pszSpatialFilterTableName = msStrdup(psInfo->pszMainTableName); psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_L_GetGeometryColumn(psInfo->hLayer) ); char* pszRequest = NULL; pszRequest = msStringConcatenate(pszRequest, "SELECT name FROM sqlite_master WHERE type = 'table' AND name = lower('"); pszRequest = msStringConcatenate(pszRequest, psInfo->pszMainTableName); pszRequest = msStringConcatenate(pszRequest, "')"); OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); msFree(pszRequest); if( hLayer ) { OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); psInfo->bIsOKForSQLCompose = (hFeature != NULL); if( hFeature ) { msFree(psInfo->pszMainTableName); msFree(psInfo->pszSpatialFilterTableName); psInfo->pszMainTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0) ); psInfo->pszSpatialFilterTableName = msStrdup( psInfo->pszMainTableName ); OGR_F_Destroy(hFeature); } OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); } if( psInfo->bIsOKForSQLCompose ) { psInfo->pszSelect = msStrdup(psInfo->pszLayerDef); } else { // Test if it is a spatial view pszRequest = msStringConcatenate(NULL, "SELECT f_table_name, f_geometry_column, view_rowid FROM views_geometry_columns WHERE view_name = lower('"); pszRequest = msStringConcatenate(pszRequest, psInfo->pszMainTableName); pszRequest = msStringConcatenate(pszRequest, "')"); CPLPushErrorHandler(CPLQuietErrorHandler); OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); CPLPopErrorHandler(); msFree(pszRequest); if( hLayer ) { OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); psInfo->bIsOKForSQLCompose = (hFeature != NULL); if( hFeature ) { psInfo->pszSelect = msStrdup(psInfo->pszLayerDef); msFree(psInfo->pszSpatialFilterTableName); psInfo->pszSpatialFilterTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0 ) ); CPLFree( psInfo->pszSpatialFilterGeometryColumn ); psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_F_GetFieldAsString( hFeature, 1 ) ); psInfo->pszRowId = msStrdup( OGR_F_GetFieldAsString( hFeature, 2 ) ); OGR_F_Destroy(hFeature); } OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); } } } } } else { psInfo->bIsOKForSQLCompose = false; char* pszRequest = NULL; pszRequest = msStringConcatenate(pszRequest, "SELECT * FROM sqlite_master WHERE type = 'table' AND name = lower('"); pszRequest = msStringConcatenate(pszRequest, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); pszRequest = msStringConcatenate(pszRequest, "')"); OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); msFree(pszRequest); if( hLayer ) { OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); psInfo->bIsOKForSQLCompose = (hFeature != NULL); if( hFeature ) OGR_F_Destroy(hFeature); OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); } if( psInfo->bIsOKForSQLCompose ) { psInfo->pszMainTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); psInfo->pszSpatialFilterTableName = msStrdup(psInfo->pszMainTableName); psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_L_GetGeometryColumn(psInfo->hLayer) ); } else { // Test if it is a spatial view pszRequest = msStringConcatenate(NULL, "SELECT f_table_name, f_geometry_column, view_rowid FROM views_geometry_columns WHERE view_name = lower('"); pszRequest = msStringConcatenate(pszRequest, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); pszRequest = msStringConcatenate(pszRequest, "')"); CPLPushErrorHandler(CPLQuietErrorHandler); OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); CPLPopErrorHandler(); msFree(pszRequest); if( hLayer ) { OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); psInfo->bIsOKForSQLCompose = (hFeature != NULL); if( hFeature ) { psInfo->pszMainTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); psInfo->pszSpatialFilterTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0 ) ); psInfo->pszSpatialFilterGeometryColumn = msStrdup( OGR_F_GetFieldAsString( hFeature, 1 ) ); psInfo->pszRowId = msStrdup( OGR_F_GetFieldAsString( hFeature, 2 ) ); OGR_F_Destroy(hFeature); } OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); } } } // in the case we cannot handle the native string, go back to the client // side evaluation by unsetting it. if( !psInfo->bIsOKForSQLCompose && psInfo->dialect != NULL ) { if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("msOGRFileOpen(): Falling back to MapServer only evaluation\n"); } psInfo->dialect = NULL; } // Check if spatial index has been disabled (testing purposes) if (msLayerGetProcessingKey(layer, "USE_SPATIAL_INDEX") != NULL && !CSLTestBoolean(msLayerGetProcessingKey(layer, "USE_SPATIAL_INDEX")) ) { if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("msOGRFileOpen(): Layer %s has spatial index disabled by processing option\n", pszLayerDef); } } // Test if spatial index is available else if( psInfo->dialect != NULL ) { char* pszRequest = NULL; pszRequest = msStringConcatenate(pszRequest, "SELECT * FROM sqlite_master WHERE type = 'table' AND name = 'idx_"); pszRequest = msStringConcatenate(pszRequest, psInfo->pszSpatialFilterTableName); pszRequest = msStringConcatenate(pszRequest, "_"); pszRequest = msStringConcatenate(pszRequest, OGR_L_GetGeometryColumn(psInfo->hLayer)); pszRequest = msStringConcatenate(pszRequest, "'"); psInfo->bHasSpatialIndex = false; //msDebug("msOGRFileOpen(): %s", pszRequest); OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); if( hLayer ) { OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); if( hFeature ) { psInfo->bHasSpatialIndex = true; OGR_F_Destroy(hFeature); } OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); } msFree(pszRequest); pszRequest = NULL; if( !psInfo->bHasSpatialIndex ) { if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("msOGRFileOpen(): Layer %s has no spatial index table\n", pszLayerDef); } } else { pszRequest = msStringConcatenate(pszRequest, "SELECT * FROM geometry_columns WHERE f_table_name = lower('"); pszRequest = msStringConcatenate(pszRequest, psInfo->pszSpatialFilterTableName); pszRequest = msStringConcatenate(pszRequest, "') AND f_geometry_column = lower('"); pszRequest = msStringConcatenate(pszRequest, psInfo->pszSpatialFilterGeometryColumn); pszRequest = msStringConcatenate(pszRequest, "') AND spatial_index_enabled = 1"); psInfo->bHasSpatialIndex = false; OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL ); if( hLayer ) { OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer); if( hFeature ) { psInfo->bHasSpatialIndex = true; OGR_F_Destroy(hFeature); } OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer ); } msFree(pszRequest); pszRequest = NULL; if( !psInfo->bHasSpatialIndex ) { if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("msOGRFileOpen(): Layer %s has spatial index disabled\n", pszLayerDef); } } else { if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("msOGRFileOpen(): Layer %s has spatial index enabled\n", pszLayerDef); } psInfo->pszTablePrefix = msStrdup( psInfo->pszMainTableName ); } } } psInfo->bPaging = (psInfo->dialect != NULL); } /************************************************************************/ /* msOGRCloseConnection() */ /* */ /* Callback for thread pool to actually release an OGR */ /* connection. */ /************************************************************************/ static void msOGRCloseConnection( void *conn_handle ) { OGRDataSourceH hDS = (OGRDataSourceH) conn_handle; ACQUIRE_OGR_LOCK; OGR_DS_Destroy( hDS ); RELEASE_OGR_LOCK; } /********************************************************************** * msOGRFileClose() **********************************************************************/ static int msOGRFileClose(layerObj *layer, msOGRFileInfo *psInfo ) { if (!psInfo) return MS_SUCCESS; if( layer->debug ) msDebug("msOGRFileClose(%s,%d).\n", psInfo->pszFname, psInfo->nLayerIndex); CPLFree(psInfo->pszFname); CPLFree(psInfo->pszLayerDef); ACQUIRE_OGR_LOCK; if (psInfo->hLastFeature) OGR_F_Destroy( psInfo->hLastFeature ); /* If nLayerIndex == -1 then the layer is an SQL result ... free it */ if( psInfo->nLayerIndex == -1 ) OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer ); // Release (potentially close) the datasource connection. // Make sure we aren't holding the lock when the callback may need it. RELEASE_OGR_LOCK; msConnPoolRelease( layer, psInfo->hDS ); // Free current tile if there is one. if( psInfo->poCurTile != NULL ) msOGRFileClose( layer, psInfo->poCurTile ); msFreeProjection(&(psInfo->sTileProj)); msFree(psInfo->pszSelect); msFree(psInfo->pszSpatialFilterTableName); msFree(psInfo->pszSpatialFilterGeometryColumn); msFree(psInfo->pszMainTableName); msFree(psInfo->pszRowId); msFree(psInfo->pszTablePrefix); msFree(psInfo->pszWHERE); CPLFree(psInfo); return MS_SUCCESS; } #endif /* USE_OGR */ /************************************************************************/ /* msOGREscapeSQLParam */ /************************************************************************/ static char *msOGREscapeSQLParam(layerObj *layer, const char *pszString) { #ifdef USE_OGR char* pszEscapedStr =NULL; if(layer && pszString) { char* pszEscapedOGRStr = CPLEscapeString(pszString, strlen(pszString), CPLES_SQL ); pszEscapedStr = msStrdup(pszEscapedOGRStr); CPLFree(pszEscapedOGRStr); } return pszEscapedStr; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGREscapeSQLParam()"); return NULL; #endif /* USE_OGR */ } #ifdef USE_OGR // http://www.sqlite.org/lang_expr.html // http://www.gaia-gis.it/gaia-sins/spatialite-sql-4.3.0.html static char* msOGRGetQuotedItem(layerObj* layer, const char* pszItem ) { msOGRFileInfo *psInfo = (msOGRFileInfo *)layer->layerinfo; char* ret = NULL; char* escapedItem = msLayerEscapePropertyName(layer, pszItem); if( psInfo->pszTablePrefix) { char* escapedTable = msLayerEscapePropertyName(layer, psInfo->pszTablePrefix); ret = msStringConcatenate(ret, "\""); ret = msStringConcatenate(ret, escapedTable); ret = msStringConcatenate(ret, "\".\""); ret = msStringConcatenate(ret, escapedItem); ret = msStringConcatenate(ret, "\""); msFree(escapedTable); } else { ret = msStringConcatenate(ret, "\""); ret = msStringConcatenate(ret, escapedItem); ret = msStringConcatenate(ret, "\""); } msFree(escapedItem); return ret; } static char *msOGRGetToken(layerObj* layer, tokenListNodeObjPtr *node) { msOGRFileInfo *info = (msOGRFileInfo *)layer->layerinfo; tokenListNodeObjPtr n = *node; if (!n) return NULL; char *out = NULL; size_t nOutSize; switch(n->token) { case MS_TOKEN_LOGICAL_AND: out = msStrdup(" AND "); break; case MS_TOKEN_LOGICAL_OR: out = msStrdup(" OR "); break; case MS_TOKEN_LOGICAL_NOT: out = msStrdup(" NOT "); break; case MS_TOKEN_LITERAL_NUMBER: nOutSize = 80; out = (char *)msSmallMalloc(nOutSize); snprintf(out, nOutSize, "%lf", n->tokenval.dblval); break; case MS_TOKEN_LITERAL_STRING: { char *stresc = msOGREscapeSQLParam(layer, n->tokenval.strval); nOutSize = strlen(stresc)+3; out = (char *)msSmallMalloc(nOutSize); snprintf(out, nOutSize, "'%s'", stresc); msFree(stresc); break; } case MS_TOKEN_LITERAL_TIME: // seems to require METADATA gml_types => auto nOutSize = 80; out = (char *)msSmallMalloc(nOutSize); #if 0 // FIXME? or perhaps just remove me. tm_zone is not supported on Windows, and not used anywhere else in the code base if (n->tokenval.tmval.tm_zone) snprintf(out, nOutSize, "'%d-%02d-%02dT%02d:%02d:%02d%s'", n->tokenval.tmval.tm_year+1900, n->tokenval.tmval.tm_mon+1, n->tokenval.tmval.tm_mday, n->tokenval.tmval.tm_hour, n->tokenval.tmval.tm_min, n->tokenval.tmval.tm_sec, n->tokenval.tmval.tm_zone); else #endif snprintf(out, nOutSize, "'%d-%02d-%02dT%02d:%02d:%02d'", n->tokenval.tmval.tm_year+1900, n->tokenval.tmval.tm_mon+1, n->tokenval.tmval.tm_mday, n->tokenval.tmval.tm_hour, n->tokenval.tmval.tm_min, n->tokenval.tmval.tm_sec); break; case MS_TOKEN_LITERAL_SHAPE: { // assumed to be in right srs after FLTGetSpatialComparisonCommonExpression char *wkt = msShapeToWKT(n->tokenval.shpval); char *stresc = msOGRGetQuotedItem(layer, OGR_L_GetGeometryColumn(info->hLayer)); // which geom field?? nOutSize = strlen(wkt)+strlen(stresc)+35; out = (char *)msSmallMalloc(nOutSize); snprintf(out, nOutSize, "ST_GeomFromText('%s',ST_SRID(%s))", wkt, stresc); msFree(wkt); msFree(stresc); break; } case MS_TOKEN_LITERAL_BOOLEAN: out = msStrdup(n->tokenval.dblval == 0 ? "FALSE" : "TRUE"); break; case MS_TOKEN_COMPARISON_EQ: if(n->next != NULL && n->next->token == MS_TOKEN_LITERAL_STRING && strcmp(n->next->tokenval.strval, "_MAPSERVER_NULL_") == 0 ) { out = msStrdup(" IS NULL"); n = n->next; break; } out = msStrdup(" = "); break; case MS_TOKEN_COMPARISON_NE: out = msStrdup(" != "); break; case MS_TOKEN_COMPARISON_GT: out = msStrdup(" > "); break; case MS_TOKEN_COMPARISON_LT: out = msStrdup(" < "); break; case MS_TOKEN_COMPARISON_LE: out = msStrdup(" <= "); break; case MS_TOKEN_COMPARISON_GE: out = msStrdup(" >= "); break; case MS_TOKEN_COMPARISON_IEQ: out = msStrdup(" = "); break; case MS_TOKEN_COMPARISON_IN: out = msStrdup(" IN "); break; // the origin may be mapfile (complex regexes, layer->map.query.filter.string == NULL, regex may have //) or // OGC Filter (simple patterns only, layer->map.query.filter.string != NULL) case MS_TOKEN_COMPARISON_RE: case MS_TOKEN_COMPARISON_IRE: case MS_TOKEN_COMPARISON_LIKE: { int case_sensitive = n->token == MS_TOKEN_COMPARISON_RE || n->token == MS_TOKEN_COMPARISON_LIKE; // in PostgreSQL and OGR: LIKE (case sensitive) and ILIKE (case insensitive) // in SQLite: LIKE (case insensitive) and GLOB (case sensitive) const char *op = case_sensitive ? "LIKE" : "ILIKE"; char wild_any = '%'; char wild_one = '_'; if (EQUAL(info->dialect, "Spatialite") || EQUAL(info->dialect, "GPKG")) { if (case_sensitive) { op = "GLOB"; wild_any = '*'; wild_one = '?'; } else { op = "LIKE"; } } n = n->next; if (n->token != MS_TOKEN_LITERAL_STRING) return NULL; char *regex = msStrdup(n->tokenval.strval); int complex_regex = *n->tokenval.strval == '/'; // could be non-complex but that is soo corner case // PostgreSQL has POSIX regexes, SQLite does not by default, OGR does not if (complex_regex) { if (!EQUAL(info->dialect, "PostgreSQL")) { msFree(regex); return NULL; } // remove // regex++; regex[strlen(regex) - 1] = '\0'; if (case_sensitive) op = "~"; else op = "~*"; } char *re = (char *) msSmallMalloc(strlen(regex)+3); size_t i = 0, j = 0; re[j++] = '\''; while (i < strlen(regex)) { char c = regex[i]; char c_next = regex[i+1]; if (c == '.' && c_next == '*') { i++; c = wild_any; } else if (c == '.') c = wild_one; else if (i == 0 && c == '^') { i++; continue; } else if( c == '$' && c_next == 0 ) { break; } re[j++] = c; i++; } re[j++] = '\''; re[j] = '\0'; nOutSize = 1 + strlen(op)+ 1 + strlen(re) + 1; out = (char *)msSmallMalloc(nOutSize); snprintf(out, nOutSize, " %s %s", op, re); msFree(re); msFree(regex); break; } case MS_TOKEN_COMPARISON_INTERSECTS: out = msStrdup("ST_Intersects"); break; case MS_TOKEN_COMPARISON_DISJOINT: out = msStrdup("ST_Disjoint"); break; case MS_TOKEN_COMPARISON_TOUCHES: out = msStrdup("ST_Touches"); break; case MS_TOKEN_COMPARISON_OVERLAPS: out = msStrdup("ST_Overlaps"); break; case MS_TOKEN_COMPARISON_CROSSES: out = msStrdup("ST_Crosses"); break; case MS_TOKEN_COMPARISON_WITHIN: out = msStrdup("ST_Within"); break; case MS_TOKEN_COMPARISON_DWITHIN: out = msStrdup("ST_Distance"); break; case MS_TOKEN_COMPARISON_BEYOND: out = msStrdup("ST_Distance"); break; case MS_TOKEN_COMPARISON_CONTAINS: out = msStrdup("ST_Contains"); break; case MS_TOKEN_COMPARISON_EQUALS: out = msStrdup("ST_Equals"); break; case MS_TOKEN_FUNCTION_LENGTH: out = msStrdup("ST_Length"); break; case MS_TOKEN_FUNCTION_AREA: out = msStrdup("ST_Area"); break; case MS_TOKEN_BINDING_DOUBLE: { char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); nOutSize = strlen(stresc)+ + 30; out = (char *)msSmallMalloc(nOutSize); char md_item_name[256]; snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", n->tokenval.bindval.item ); const char* type = msLookupHashTable(&(layer->metadata), md_item_name); // Do not cast if the variable is of the appropriate type as it can // prevent using database indexes, such as for SQlite if( type != NULL && (EQUAL(type, "Integer") || EQUAL(type, "Long") || EQUAL(type, "Real")) ) { snprintf(out, nOutSize, "%s", stresc); } else { const char *SQLtype = "float(16)"; if (EQUAL(info->dialect, "Spatialite") || EQUAL(info->dialect, "GPKG")) SQLtype = "REAL"; else if (EQUAL(info->dialect, "PostgreSQL")) SQLtype = "double precision"; snprintf(out, nOutSize, "CAST(%s AS %s)", stresc, SQLtype); } msFree(stresc); break; } case MS_TOKEN_BINDING_INTEGER: { char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); nOutSize = strlen(stresc)+ 20; out = (char *)msSmallMalloc(nOutSize); char md_item_name[256]; snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", n->tokenval.bindval.item ); const char* type = msLookupHashTable(&(layer->metadata), md_item_name); // Do not cast if the variable is of the appropriate type as it can // prevent using database indexes, such as for SQlite if( type != NULL && (EQUAL(type, "Integer") || EQUAL(type, "Long") || EQUAL(type, "Real")) ) { snprintf(out, nOutSize, "%s", stresc); } else { snprintf(out, nOutSize, "CAST(%s AS integer)", stresc); } msFree(stresc); break; } case MS_TOKEN_BINDING_STRING: { char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); nOutSize = strlen(stresc) + 30; out = (char *)msSmallMalloc(nOutSize); char md_item_name[256]; snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", n->tokenval.bindval.item ); const char* type = msLookupHashTable(&(layer->metadata), md_item_name); // Do not cast if the variable is of the appropriate type as it can // prevent using database indexes, such as for SQlite if( type != NULL && EQUAL(type, "Character") ) { snprintf(out, nOutSize, "%s", stresc); } else { snprintf(out, nOutSize, "CAST(%s AS text)", stresc); } msFree(stresc); break; } case MS_TOKEN_BINDING_TIME: { // won't get here unless col is parsed as time and they are not char *stresc = msOGRGetQuotedItem(layer, n->tokenval.bindval.item); nOutSize = strlen(stresc)+ 10; out = (char *)msSmallMalloc(nOutSize); snprintf(out, nOutSize, "%s", stresc); msFree(stresc); break; } case MS_TOKEN_BINDING_SHAPE: { char *stresc = msOGRGetQuotedItem(layer, OGR_L_GetGeometryColumn(info->hLayer)); // which geom field?? nOutSize = strlen(stresc)+ 10; out = (char *)msSmallMalloc(nOutSize); snprintf(out, nOutSize, "%s", stresc); msFree(stresc); break; } // unhandled below until default case MS_TOKEN_FUNCTION_TOSTRING: case MS_TOKEN_FUNCTION_COMMIFY: case MS_TOKEN_FUNCTION_ROUND: case MS_TOKEN_FUNCTION_FROMTEXT: case MS_TOKEN_FUNCTION_BUFFER: case MS_TOKEN_FUNCTION_DIFFERENCE: case MS_TOKEN_FUNCTION_SIMPLIFY: case MS_TOKEN_FUNCTION_SIMPLIFYPT: case MS_TOKEN_FUNCTION_GENERALIZE: case MS_TOKEN_FUNCTION_SMOOTHSIA: case MS_TOKEN_FUNCTION_JAVASCRIPT: case MS_TOKEN_FUNCTION_UPPER: case MS_TOKEN_FUNCTION_LOWER: case MS_TOKEN_FUNCTION_INITCAP: case MS_TOKEN_FUNCTION_FIRSTCAP: case MS_TOKEN_BINDING_MAP_CELLSIZE: case MS_TOKEN_BINDING_DATA_CELLSIZE: case MS_PARSE_TYPE_BOOLEAN: case MS_PARSE_TYPE_STRING: case MS_PARSE_TYPE_SHAPE: break; default: if (n->token < 128) { char c = n->token; out = (char *)msSmallMalloc(2); sprintf(out, "%c", c); } break; } n = n->next; *node = n; return out; } /* * msOGRLayerBuildSQLOrderBy() * * Returns the content of a SQL ORDER BY clause from the sortBy member of * the layer. The string does not contain the "ORDER BY" keywords itself. */ static char* msOGRLayerBuildSQLOrderBy(layerObj *layer, msOGRFileInfo *psInfo) { char* strOrderBy = NULL; if( layer->sortBy.nProperties > 0 ) { int i; for(i=0;isortBy.nProperties;i++) { if( i > 0 ) strOrderBy = msStringConcatenate(strOrderBy, ", "); char* escapedItem = msLayerEscapePropertyName(layer, layer->sortBy.properties[i].item); if( psInfo->pszTablePrefix) { char* escapedTable = msLayerEscapePropertyName(layer, psInfo->pszTablePrefix); strOrderBy = msStringConcatenate(strOrderBy, "\""); strOrderBy = msStringConcatenate(strOrderBy, escapedTable); strOrderBy = msStringConcatenate(strOrderBy, "\".\""); strOrderBy = msStringConcatenate(strOrderBy, escapedItem); strOrderBy = msStringConcatenate(strOrderBy, "\""); msFree(escapedTable); } else { #if GDAL_VERSION_MAJOR < 2 // Old GDAL don't like quoted identifiers in ORDER BY strOrderBy = msStringConcatenate(strOrderBy, layer->sortBy.properties[i].item); #else strOrderBy = msStringConcatenate(strOrderBy, "\""); strOrderBy = msStringConcatenate(strOrderBy, escapedItem); strOrderBy = msStringConcatenate(strOrderBy, "\""); #endif } msFree(escapedItem); if( layer->sortBy.properties[i].sortOrder == SORT_DESC ) strOrderBy = msStringConcatenate(strOrderBy, " DESC"); } } return strOrderBy; } /********************************************************************** * msOGRFileWhichShapes() * * Init OGR layer structs ready for calls to msOGRFileNextShape(). * * Returns MS_SUCCESS/MS_FAILURE, or MS_DONE if no shape matching the * layer's FILTER overlaps the selected region. **********************************************************************/ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *psInfo) { // rect is from BBOX parameter in query (In lieu of a FEATUREID or FILTER) or mapfile somehow if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileWhichShapes()"); return(MS_FAILURE); } char *select = (psInfo->pszSelect) ? msStrdup(psInfo->pszSelect) : NULL; const rectObj rectInvalid = MS_INIT_INVALID_RECT; bool bIsValidRect = memcmp(&rect, &rectInvalid, sizeof(rect)) != 0; // we'll go strictly two possible ways: // 1) GetLayer + SetFilter // 2) ExecuteSQL (psInfo->hLayer is an SQL result OR sortBy was requested OR have native_string // and start from the second if ( psInfo->bIsOKForSQLCompose && (psInfo->nLayerIndex == -1 || layer->sortBy.nProperties > 0 || layer->filter.native_string || (psInfo->bPaging && layer->maxfeatures > 0)) ) { const bool bHasGeometry = OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone; if( psInfo->nLayerIndex == -1 && select == NULL ) { select = msStrdup(psInfo->pszLayerDef); /* If nLayerIndex == -1 then the layer is an SQL result ... free it */ OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer ); psInfo->hLayer = NULL; } else if( select == NULL ) { const char* pszGeometryColumn; int i; select = msStringConcatenate(select, "SELECT "); for(i = 0; i < layer->numitems; i++) { if( i > 0 ) select = msStringConcatenate(select, ", "); char* escaped = msOGRGetQuotedItem(layer, layer->items[i]); select = msStringConcatenate(select, escaped); msFree(escaped); if( psInfo->pszTablePrefix ) { select = msStringConcatenate(select, " AS \""); escaped = msLayerEscapePropertyName(layer, layer->items[i]); select = msStringConcatenate(select, escaped); msFree(escaped); select = msStringConcatenate(select, "\""); } } if( layer->numitems > 0 ) select = msStringConcatenate(select, ", "); pszGeometryColumn = OGR_L_GetGeometryColumn(psInfo->hLayer); if( pszGeometryColumn != NULL && pszGeometryColumn[0] != '\0' ) { char* escaped = msOGRGetQuotedItem(layer, pszGeometryColumn); select = msStringConcatenate(select, escaped); msFree(escaped); if( psInfo->pszTablePrefix ) { select = msStringConcatenate(select, " AS \""); escaped = msLayerEscapePropertyName(layer, pszGeometryColumn); select = msStringConcatenate(select, escaped); msFree(escaped); select = msStringConcatenate(select, "\""); } } else { /* Add ", *" so that we still have an hope to get the geometry */ if( psInfo->pszTablePrefix ) { select = msStringConcatenate(select, "\""); char* escaped = msLayerEscapePropertyName(layer, psInfo->pszTablePrefix); select = msStringConcatenate(select, escaped); msFree(escaped); select = msStringConcatenate(select, "\"."); } select = msStringConcatenate(select, "*"); } select = msStringConcatenate(select, " FROM "); if( psInfo->nLayerIndex == -1 ) { select = msStringConcatenate(select, "("); select = msStringConcatenate(select, psInfo->pszLayerDef); select = msStringConcatenate(select, ") MSSUBSELECT"); } else { select = msStringConcatenate(select, "\""); char* escaped = msLayerEscapePropertyName(layer, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer))); select = msStringConcatenate(select, escaped); msFree(escaped); select = msStringConcatenate(select, "\""); } } char *filter = NULL; if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { filter = msStringConcatenate(filter, "("); filter = msStringConcatenate(filter, msLayerGetProcessingKey(layer, "NATIVE_FILTER")); filter = msStringConcatenate(filter, ")"); } /* ------------------------------------------------------------------ * Set Spatial filter... this may result in no features being returned * if layer does not overlap current view. * * __TODO__ We should return MS_DONE if no shape overlaps the selected * region and matches the layer's FILTER expression, but there is currently * no _efficient_ way to do that with OGR. * ------------------------------------------------------------------ */ if (psInfo->rect_is_defined) { rect.minx = MAX(psInfo->rect.minx, rect.minx); rect.miny = MAX(psInfo->rect.miny, rect.miny); rect.maxx = MIN(psInfo->rect.maxx, rect.maxx); rect.maxy = MIN(psInfo->rect.maxy, rect.maxy); bIsValidRect = true; } psInfo->rect = rect; bool bSpatialiteOrGPKGAddOrderByFID = false; if( psInfo->dialect && psInfo->pszMainTableName != NULL && ( (EQUAL(psInfo->dialect, "Spatialite") && psInfo->bHasSpatialIndex) || EQUAL(psInfo->dialect, "GPKG") ) && bIsValidRect ) { select = msStringConcatenate(select, " JOIN "); char szSpatialIndexName[256]; snprintf( szSpatialIndexName, sizeof(szSpatialIndexName), "%s_%s_%s", EQUAL(psInfo->dialect, "Spatialite") ? "idx" : "rtree", psInfo->pszSpatialFilterTableName, psInfo->pszSpatialFilterGeometryColumn ); char* pszEscapedSpatialIndexName = msLayerEscapePropertyName( layer, szSpatialIndexName); select = msStringConcatenate(select, "\""); select = msStringConcatenate(select, pszEscapedSpatialIndexName); msFree(pszEscapedSpatialIndexName); select = msStringConcatenate(select, "\" ms_spat_idx ON \""); char* pszEscapedMainTableName = msLayerEscapePropertyName( layer, psInfo->pszMainTableName); select = msStringConcatenate(select, pszEscapedMainTableName); msFree(pszEscapedMainTableName); select = msStringConcatenate(select, "\"."); if( psInfo->pszRowId ) { char* pszEscapedRowId = msLayerEscapePropertyName( layer, psInfo->pszRowId); select = msStringConcatenate(select, "\""); select = msStringConcatenate(select, pszEscapedRowId); select = msStringConcatenate(select, "\""); msFree(pszEscapedRowId); } else select = msStringConcatenate(select, "ROWID"); if( EQUAL(psInfo->dialect, "Spatialite") ) select = msStringConcatenate(select, " = ms_spat_idx.pkid AND "); else select = msStringConcatenate(select, " = ms_spat_idx.id AND "); char szCond[256]; if( EQUAL(psInfo->dialect, "Spatialite") ) { snprintf(szCond, sizeof(szCond), "ms_spat_idx.xmin <= %.15g AND ms_spat_idx.xmax >= %.15g AND " "ms_spat_idx.ymin <= %.15g AND ms_spat_idx.ymax >= %.15g", rect.maxx, rect.minx, rect.maxy, rect.miny); } else { snprintf(szCond, sizeof(szCond), "ms_spat_idx.minx <= %.15g AND ms_spat_idx.maxx >= %.15g AND " "ms_spat_idx.miny <= %.15g AND ms_spat_idx.maxy >= %.15g", rect.maxx, rect.minx, rect.maxy, rect.miny); } select = msStringConcatenate(select, szCond); bSpatialiteOrGPKGAddOrderByFID = true; } const char *sql = layer->filter.native_string; if (psInfo->dialect && sql && *sql != '\0' && (EQUAL(psInfo->dialect, "Spatialite") || EQUAL(psInfo->dialect, "GPKG") || EQUAL(psInfo->dialect, "PostgreSQL")) ) { if (filter) filter = msStringConcatenate(filter, " AND "); filter = msStringConcatenate(filter, "("); filter = msStringConcatenate(filter, sql); filter = msStringConcatenate(filter, ")"); } else if( psInfo->pszWHERE ) { if (filter) filter = msStringConcatenate(filter, " AND "); filter = msStringConcatenate(filter, "("); filter = msStringConcatenate(filter, psInfo->pszWHERE); filter = msStringConcatenate(filter, ")"); } bool bOffsetAlreadyAdded = false; // use spatial index if (psInfo->dialect && bIsValidRect ) { if (EQUAL(psInfo->dialect, "PostgreSQL")) { if (filter) filter = msStringConcatenate(filter, " AND"); const char *col = OGR_L_GetGeometryColumn(psInfo->hLayer); // which geom field?? filter = msStringConcatenate(filter, " (\""); char* escaped = msLayerEscapePropertyName(layer, col); filter = msStringConcatenate(filter, escaped); msFree(escaped); filter = msStringConcatenate(filter, "\" && ST_MakeEnvelope("); char *points = (char *)msSmallMalloc(30*2*5); snprintf(points, 30*4, "%lf,%lf,%lf,%lf", rect.minx, rect.miny, rect.maxx, rect.maxy); filter = msStringConcatenate(filter, points); msFree(points); filter = msStringConcatenate(filter, "))"); } else if( psInfo->dialect && EQUAL(psInfo->dialect, "Spatialite") && psInfo->pszMainTableName != NULL && !psInfo->bHasSpatialIndex ) { if (filter) filter = msStringConcatenate(filter, " AND"); const char *col = OGR_L_GetGeometryColumn(psInfo->hLayer); // which geom field?? filter = msStringConcatenate(filter, " MbrIntersects(\""); char* escaped = msLayerEscapePropertyName(layer, col); filter = msStringConcatenate(filter, escaped); msFree(escaped); filter = msStringConcatenate(filter, "\", BuildMbr("); char *points = (char *)msSmallMalloc(30*2*5); snprintf(points, 30*4, "%lf,%lf,%lf,%lf", rect.minx, rect.miny, rect.maxx, rect.maxy); filter = msStringConcatenate(filter, points); msFree(points); filter = msStringConcatenate(filter, "))"); } } /* get sortBy */ char *sort = NULL; if( layer->sortBy.nProperties > 0) { char *strOrderBy = msOGRLayerBuildSQLOrderBy(layer, psInfo); if (strOrderBy) { if( psInfo->nLayerIndex == -1 ) { if( strcasestr(psInfo->pszLayerDef, " ORDER BY ") == NULL ) sort = msStringConcatenate(sort, " ORDER BY "); else sort = msStringConcatenate(sort, ", "); } else { sort = msStringConcatenate(sort, " ORDER BY "); } sort = msStringConcatenate(sort, strOrderBy); msFree(strOrderBy); } } if( bSpatialiteOrGPKGAddOrderByFID ) { if( sort == NULL ) sort = msStringConcatenate(NULL, " ORDER BY "); else sort = msStringConcatenate(sort, ", "); char* pszEscapedMainTableName = msLayerEscapePropertyName( layer, psInfo->pszMainTableName); sort = msStringConcatenate(sort, "\""); sort = msStringConcatenate(sort, pszEscapedMainTableName); sort = msStringConcatenate(sort, "\"."); msFree(pszEscapedMainTableName); if( psInfo->pszRowId ) { char* pszEscapedRowId = msLayerEscapePropertyName( layer, psInfo->pszRowId); sort = msStringConcatenate(sort, "\""); sort = msStringConcatenate(sort, pszEscapedRowId); sort = msStringConcatenate(sort, "\""); msFree(pszEscapedRowId); } else sort = msStringConcatenate(sort, "ROWID"); } // compose SQL if (filter) { select = msStringConcatenate(select, " WHERE "); select = msStringConcatenate(select, filter); msFree(filter); } if (sort) { select = msStringConcatenate(select, " "); select = msStringConcatenate(select, sort); msFree(sort); } if ( psInfo->bPaging && layer->maxfeatures >= 0 ) { char szLimit[50]; snprintf(szLimit, sizeof(szLimit), " LIMIT %d", layer->maxfeatures); select = msStringConcatenate(select, szLimit); } if ( !bOffsetAlreadyAdded && psInfo->bPaging && layer->startindex > 0 ) { char szOffset[50]; snprintf(szOffset, sizeof(szOffset), " OFFSET %d", layer->startindex-1); select = msStringConcatenate(select, szOffset); } if( layer->debug ) msDebug("msOGRFileWhichShapes: SQL = %s.\n", select); ACQUIRE_OGR_LOCK; if( psInfo->nLayerIndex == -1 && psInfo->hLayer != NULL ) { OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer ); } OGRGeometryH hGeom = NULL; if( psInfo->dialect == NULL && bHasGeometry && bIsValidRect ) { if (rect.minx == rect.maxx && rect.miny == rect.maxy) { hGeom = OGR_G_CreateGeometry( wkbPoint ); OGR_G_SetPoint_2D( hGeom, 0, rect.minx, rect.miny ); } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) { hGeom = OGR_G_CreateGeometry( wkbLineString ); OGR_G_AddPoint_2D( hGeom, rect.minx, rect.miny ); OGR_G_AddPoint_2D( hGeom, rect.maxx, rect.maxy ); } else { hGeom = OGR_G_CreateGeometry( wkbPolygon ); OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing ); OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny); OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy); OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy); OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); OGR_G_AddGeometryDirectly( hGeom, hRing ); } if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy ); } } psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, select, hGeom, NULL ); psInfo->nLayerIndex = -1; if( hGeom != NULL ) OGR_G_DestroyGeometry(hGeom); if( psInfo->hLayer == NULL ) { RELEASE_OGR_LOCK; msSetError(MS_OGRERR, "ExecuteSQL() failed. Check logs.", "msOGRFileWhichShapes()"); msDebug("ExecuteSQL(%s) failed.\n%s\n", select, CPLGetLastErrorMsg()); msFree(select); return MS_FAILURE; } // Update itemindexes / layer->iteminfo msOGRLayerInitItemInfo(layer); } else { // case of 1) GetLayer + SetFilter char *pszOGRFilter = NULL; if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { pszOGRFilter = msStringConcatenate(pszOGRFilter, "("); pszOGRFilter = msStringConcatenate(pszOGRFilter, msLayerGetProcessingKey(layer, "NATIVE_FILTER")); pszOGRFilter = msStringConcatenate(pszOGRFilter, ")"); } if( psInfo->pszWHERE ) { if( pszOGRFilter ) { pszOGRFilter = msStringConcatenate(pszOGRFilter, " AND ("); pszOGRFilter = msStringConcatenate(pszOGRFilter, psInfo->pszWHERE); pszOGRFilter = msStringConcatenate(pszOGRFilter, ")"); } else { pszOGRFilter = msStringConcatenate(pszOGRFilter, psInfo->pszWHERE); } } ACQUIRE_OGR_LOCK; if( OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone && bIsValidRect ) { if (rect.minx == rect.maxx && rect.miny == rect.maxy) { OGRGeometryH hSpatialFilterPoint = OGR_G_CreateGeometry( wkbPoint ); OGR_G_SetPoint_2D( hSpatialFilterPoint, 0, rect.minx, rect.miny ); OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPoint ); OGR_G_DestroyGeometry( hSpatialFilterPoint ); } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) { OGRGeometryH hSpatialFilterLine = OGR_G_CreateGeometry( wkbLineString ); OGR_G_AddPoint_2D( hSpatialFilterLine, rect.minx, rect.miny ); OGR_G_AddPoint_2D( hSpatialFilterLine, rect.maxx, rect.maxy ); OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterLine ); OGR_G_DestroyGeometry( hSpatialFilterLine ); } else { OGRGeometryH hSpatialFilterPolygon = OGR_G_CreateGeometry( wkbPolygon ); OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing ); OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny); OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy); OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy); OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny); OGR_G_AddGeometryDirectly( hSpatialFilterPolygon, hRing ); OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPolygon ); OGR_G_DestroyGeometry( hSpatialFilterPolygon ); } if (layer->debug >= MS_DEBUGLEVEL_VVV) { msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n", rect.minx, rect.miny, rect.maxx, rect.maxy ); } } psInfo->rect = rect; /* ------------------------------------------------------------------ * Apply an attribute filter if we have one prefixed with a WHERE * keyword in the filter string. Otherwise, ensure the attribute * filter is clear. * ------------------------------------------------------------------ */ if( pszOGRFilter != NULL ) { if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("msOGRFileWhichShapes: Setting attribute filter to %s\n", pszOGRFilter ); CPLErrorReset(); if( OGR_L_SetAttributeFilter( psInfo->hLayer, pszOGRFilter ) != OGRERR_NONE ) { msSetError(MS_OGRERR, "SetAttributeFilter() failed on layer %s. Check logs.", "msOGRFileWhichShapes()", layer->name?layer->name:"(null)"); msDebug("SetAttributeFilter(%s) failed on layer %s.\n%s\n", pszOGRFilter, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() ); RELEASE_OGR_LOCK; msFree(pszOGRFilter); msFree(select); return MS_FAILURE; } msFree(pszOGRFilter); } else OGR_L_SetAttributeFilter( psInfo->hLayer, NULL ); } msFree(select); /* ------------------------------------------------------------------ * Reset current feature pointer * ------------------------------------------------------------------ */ OGR_L_ResetReading( psInfo->hLayer ); psInfo->last_record_index_read = -1; RELEASE_OGR_LOCK; return MS_SUCCESS; } /********************************************************************** * msOGRPassThroughFieldDefinitions() * * Pass the field definitions through to the layer metadata in the * "gml_[item]_{type,width,precision}" set of metadata items for * defining fields. **********************************************************************/ static void msOGRPassThroughFieldDefinitions( layerObj *layer, msOGRFileInfo *psInfo ) { OGRFeatureDefnH hDefn = OGR_L_GetLayerDefn( psInfo->hLayer ); int numitems, i; numitems = OGR_FD_GetFieldCount( hDefn ); for(i=0; i 0 ) sprintf( gml_width, "%d", OGR_Fld_GetWidth( hField) ); break; #if GDAL_VERSION_MAJOR >= 2 case OFTInteger64: gml_type = "Long"; if( OGR_Fld_GetWidth( hField) > 0 ) sprintf( gml_width, "%d", OGR_Fld_GetWidth( hField) ); break; #endif case OFTReal: gml_type = "Real"; if( OGR_Fld_GetWidth( hField) > 0 ) sprintf( gml_width, "%d", OGR_Fld_GetWidth( hField) ); if( OGR_Fld_GetPrecision( hField ) > 0 ) sprintf( gml_precision, "%d", OGR_Fld_GetPrecision( hField) ); break; case OFTString: gml_type = "Character"; if( OGR_Fld_GetWidth( hField) > 0 ) sprintf( gml_width, "%d", OGR_Fld_GetWidth( hField) ); break; case OFTDate: case OFTTime: case OFTDateTime: gml_type = "Date"; break; default: gml_type = "Character"; break; } snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", item ); if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } /* Should we try to address style items, or other special items? */ } /********************************************************************** * msOGRFileGetItems() * * Returns a list of field names in a NULL terminated list of strings. **********************************************************************/ static char **msOGRFileGetItems(layerObj *layer, msOGRFileInfo *psInfo ) { OGRFeatureDefnH hDefn; int i, numitems,totalnumitems; int numStyleItems = MSOGR_LABELNUMITEMS; char **items; const char *getShapeStyleItems, *value; if((hDefn = OGR_L_GetLayerDefn( psInfo->hLayer )) == NULL) { msSetError(MS_OGRERR, "OGR Connection for layer `%s' contains no field definition.", "msOGRFileGetItems()", layer->name?layer->name:"(null)" ); return NULL; } totalnumitems = numitems = OGR_FD_GetFieldCount( hDefn ); getShapeStyleItems = msLayerGetProcessingKey( layer, "GETSHAPE_STYLE_ITEMS" ); if (getShapeStyleItems && EQUAL(getShapeStyleItems, "all")) totalnumitems += numStyleItems; if((items = (char**)malloc(sizeof(char *)*(totalnumitems+1))) == NULL) { msSetError(MS_MEMERR, NULL, "msOGRFileGetItems()"); return NULL; } for(i=0; imetadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) msOGRPassThroughFieldDefinitions( layer, psInfo ); return items; } /********************************************************************** * msOGRFileNextShape() * * Returns shape sequentially from OGR data source. * msOGRLayerWhichShape() must have been called first. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ static int msOGRFileNextShape(layerObj *layer, shapeObj *shape, msOGRFileInfo *psInfo ) { OGRFeatureH hFeature = NULL; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileNextShape()"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Read until we find a feature that matches attribute filter and * whose geometry is compatible with current layer type. * ------------------------------------------------------------------ */ msFreeShape(shape); shape->type = MS_SHAPE_NULL; ACQUIRE_OGR_LOCK; while (shape->type == MS_SHAPE_NULL) { if( hFeature ) OGR_F_Destroy( hFeature ); if( (hFeature = OGR_L_GetNextFeature( psInfo->hLayer )) == NULL ) { psInfo->last_record_index_read = -1; if( CPLGetLastErrorType() == CE_Failure ) { msSetError(MS_OGRERR, "OGR GetNextFeature() error'd. Check logs.", "msOGRFileNextShape()"); msDebug("msOGRFileNextShape(): %s\n", CPLGetLastErrorMsg() ); RELEASE_OGR_LOCK; return MS_FAILURE; } else { RELEASE_OGR_LOCK; if (layer->debug >= MS_DEBUGLEVEL_VV) msDebug("msOGRFileNextShape: Returning MS_DONE (no more shapes)\n" ); return MS_DONE; // No more features to read } } psInfo->last_record_index_read++; if(layer->numitems > 0) { shape->values = msOGRGetValues(layer, hFeature); shape->numvalues = layer->numitems; if(!shape->values) { OGR_F_Destroy( hFeature ); RELEASE_OGR_LOCK; return(MS_FAILURE); } } // Feature matched filter expression... process geometry // shape->type will be set if geom is compatible with layer type if (ogrConvertGeometry(ogrGetLinearGeometry( hFeature ), shape, layer->type) == MS_SUCCESS) { if (shape->type != MS_SHAPE_NULL) break; // Shape is ready to be returned! if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("msOGRFileNextShape: Rejecting feature (shapeid = " CPL_FRMT_GIB ", tileid=%d) of incompatible type for this layer (feature wkbType %d, layer type %d)\n", (GIntBig)OGR_F_GetFID( hFeature ), psInfo->nTileId, OGR_F_GetGeometryRef( hFeature )==NULL ? wkbFlatten(wkbUnknown):wkbFlatten( OGR_G_GetGeometryType( OGR_F_GetGeometryRef( hFeature ) ) ), layer->type); } else { msFreeShape(shape); OGR_F_Destroy( hFeature ); RELEASE_OGR_LOCK; return MS_FAILURE; // Error message already produced. } // Feature rejected... free shape to clear attributes values. msFreeShape(shape); shape->type = MS_SHAPE_NULL; } shape->index = (int)OGR_F_GetFID( hFeature ); // FIXME? GetFID() is a 64bit integer in GDAL 2.0 shape->resultindex = psInfo->last_record_index_read; shape->tileindex = psInfo->nTileId; if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("msOGRFileNextShape: Returning shape=%ld, tile=%d\n", shape->index, shape->tileindex ); // Keep ref. to last feature read in case we need style info. if (psInfo->hLastFeature) OGR_F_Destroy( psInfo->hLastFeature ); psInfo->hLastFeature = hFeature; RELEASE_OGR_LOCK; return MS_SUCCESS; } /********************************************************************** * msOGRFileGetShape() * * Returns shape from OGR data source by id. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ static int msOGRFileGetShape(layerObj *layer, shapeObj *shape, long record, msOGRFileInfo *psInfo, int record_is_fid ) { OGRFeatureH hFeature; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileNextShape()"); return(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* Clear previously loaded shape. */ /* -------------------------------------------------------------------- */ msFreeShape(shape); shape->type = MS_SHAPE_NULL; /* -------------------------------------------------------------------- */ /* Support reading feature by fid. */ /* -------------------------------------------------------------------- */ if( record_is_fid ) { ACQUIRE_OGR_LOCK; if( (hFeature = OGR_L_GetFeature( psInfo->hLayer, record )) == NULL ) { RELEASE_OGR_LOCK; return MS_FAILURE; } } /* -------------------------------------------------------------------- */ /* Support reading shape by offset within the current */ /* resultset. */ /* -------------------------------------------------------------------- */ else { ACQUIRE_OGR_LOCK; if( record <= psInfo->last_record_index_read || psInfo->last_record_index_read == -1 ) { OGR_L_ResetReading( psInfo->hLayer ); psInfo->last_record_index_read = -1; } hFeature = NULL; while( psInfo->last_record_index_read < record ) { if( hFeature != NULL ) { OGR_F_Destroy( hFeature ); hFeature = NULL; } if( (hFeature = OGR_L_GetNextFeature( psInfo->hLayer )) == NULL ) { RELEASE_OGR_LOCK; return MS_FAILURE; } psInfo->last_record_index_read++; } } /* ------------------------------------------------------------------ * Handle shape geometry... * ------------------------------------------------------------------ */ // shape->type will be set if geom is compatible with layer type if (ogrConvertGeometry(ogrGetLinearGeometry( hFeature ), shape, layer->type) != MS_SUCCESS) { RELEASE_OGR_LOCK; return MS_FAILURE; // Error message already produced. } if (shape->type == MS_SHAPE_NULL) { msSetError(MS_OGRERR, "Requested feature is incompatible with layer type", "msOGRLayerGetShape()"); RELEASE_OGR_LOCK; return MS_FAILURE; } /* ------------------------------------------------------------------ * Process shape attributes * ------------------------------------------------------------------ */ if(layer->numitems > 0) { shape->values = msOGRGetValues(layer, hFeature); shape->numvalues = layer->numitems; if(!shape->values) { RELEASE_OGR_LOCK; return(MS_FAILURE); } } if (record_is_fid) { shape->index = record; shape->resultindex = -1; } else { shape->index = (int)OGR_F_GetFID( hFeature ); // FIXME? GetFID() is a 64bit integer in GDAL 2.0 shape->resultindex = record; } shape->tileindex = psInfo->nTileId; // Keep ref. to last feature read in case we need style info. if (psInfo->hLastFeature) OGR_F_Destroy( psInfo->hLastFeature ); psInfo->hLastFeature = hFeature; RELEASE_OGR_LOCK; return MS_SUCCESS; } /************************************************************************/ /* msOGRFileReadTile() */ /* */ /* Advance to the next tile (or if targetTile is not -1 advance */ /* to that tile), causing the tile to become the poCurTile in */ /* the tileindexes psInfo structure. Returns MS_DONE if there */ /* are no more available tiles. */ /* */ /* Newly loaded tiles are automatically "WhichShaped" based on */ /* the current rectangle. */ /************************************************************************/ int msOGRFileReadTile( layerObj *layer, msOGRFileInfo *psInfo, int targetTile = -1 ) { int nFeatureId; /* -------------------------------------------------------------------- */ /* Close old tile if one is open. */ /* -------------------------------------------------------------------- */ if( psInfo->poCurTile != NULL ) { msOGRFileClose( layer, psInfo->poCurTile ); psInfo->poCurTile = NULL; } /* -------------------------------------------------------------------- */ /* If -2 is passed, then seek reset reading of the tileindex. */ /* We want to start from the beginning even if this file is */ /* shared between layers or renders. */ /* -------------------------------------------------------------------- */ ACQUIRE_OGR_LOCK; if( targetTile == -2 ) { OGR_L_ResetReading( psInfo->hLayer ); } /* -------------------------------------------------------------------- */ /* Get the name (connection string really) of the next tile. */ /* -------------------------------------------------------------------- */ OGRFeatureH hFeature; char *connection = NULL; msOGRFileInfo *psTileInfo = NULL; int status; #ifndef IGNORE_MISSING_DATA NextFile: #endif if( targetTile < 0 ) hFeature = OGR_L_GetNextFeature( psInfo->hLayer ); else hFeature = OGR_L_GetFeature( psInfo->hLayer, targetTile ); if( hFeature == NULL ) { RELEASE_OGR_LOCK; if( targetTile == -1 ) return MS_DONE; else return MS_FAILURE; } connection = msStrdup( OGR_F_GetFieldAsString( hFeature, layer->tileitemindex )); char* pszSRS = NULL; if( layer->tilesrs != NULL ) { int idx = OGR_F_GetFieldIndex( hFeature, layer->tilesrs); if( idx >= 0 ) { pszSRS = msStrdup( OGR_F_GetFieldAsString( hFeature, idx )); } } nFeatureId = (int)OGR_F_GetFID( hFeature ); // FIXME? GetFID() is a 64bit integer in GDAL 2.0 OGR_F_Destroy( hFeature ); RELEASE_OGR_LOCK; /* -------------------------------------------------------------------- */ /* Open the new tile file. */ /* -------------------------------------------------------------------- */ psTileInfo = msOGRFileOpen( layer, connection ); free( connection ); #ifndef IGNORE_MISSING_DATA if( psTileInfo == NULL && targetTile == -1 ) goto NextFile; #endif if( psTileInfo == NULL ) { msFree(pszSRS); return MS_FAILURE; } if( pszSRS != NULL ) { if( msOGCWKT2ProjectionObj( pszSRS, &(psInfo->sTileProj), layer->debug ) != MS_SUCCESS ) { msFree(pszSRS); return MS_FAILURE; } msFree(pszSRS); } psTileInfo->nTileId = nFeatureId; /* -------------------------------------------------------------------- */ /* Initialize the spatial query on this file. */ /* -------------------------------------------------------------------- */ if( psInfo->rect.minx != 0 || psInfo->rect.maxx != 0 ) { rectObj rect = psInfo->rect; #ifdef USE_PROJ if( layer->tileindex != NULL && psInfo->sTileProj.numargs > 0 ) { msProjectRect(&(layer->projection), &(psInfo->sTileProj), &rect); } #endif status = msOGRFileWhichShapes( layer, rect, psTileInfo ); if( status != MS_SUCCESS ) return status; } psInfo->poCurTile = psTileInfo; /* -------------------------------------------------------------------- */ /* Update the iteminfo in case this layer has a different field */ /* list. */ /* -------------------------------------------------------------------- */ msOGRLayerInitItemInfo( layer ); return MS_SUCCESS; } /************************************************************************/ /* msExprNode */ /************************************************************************/ class msExprNode { public: std::vector m_aoChildren; int m_nToken; std::string m_osVal; double m_dfVal; struct tm m_tmVal; msExprNode() : m_nToken(0), m_dfVal(0.0) {} ~msExprNode(); }; msExprNode::~msExprNode() { for(size_t i=0;i aoStackOp, aoStackVal; while( node != NULL ) { if( node->token == '(' ) { msExprNode* subExpr = BuildExprTree(node->next, &node, nParenthesisLevel + 1); if( subExpr == NULL ) { goto fail; } aoStackVal.push_back(subExpr); continue; } else if( node->token == ')' ) { if( nParenthesisLevel > 0 ) { break; } goto fail; } else if( node->token == '+' || node->token == '-' || node->token == '*' || node->token == '/' || node->token == '%' || node->token == MS_TOKEN_LOGICAL_NOT || node->token == MS_TOKEN_LOGICAL_AND || node->token == MS_TOKEN_LOGICAL_OR || node->token == MS_TOKEN_COMPARISON_GE || node->token == MS_TOKEN_COMPARISON_GT || node->token == MS_TOKEN_COMPARISON_LE || node->token == MS_TOKEN_COMPARISON_LT || node->token == MS_TOKEN_COMPARISON_EQ || node->token == MS_TOKEN_COMPARISON_IEQ || node->token == MS_TOKEN_COMPARISON_LIKE || node->token == MS_TOKEN_COMPARISON_NE || node->token == MS_TOKEN_COMPARISON_RE || node->token == MS_TOKEN_COMPARISON_IRE || node->token == MS_TOKEN_COMPARISON_IN ) { while( !aoStackOp.empty() && exprGetPriority(node->token) <= exprGetPriority(aoStackOp.back()->m_nToken)) { msExprNode* val1 = NULL; msExprNode* val2 = NULL; msExprNode* newNode = NULL; if (aoStackOp.back()->m_nToken != MS_TOKEN_LOGICAL_NOT) { if( aoStackVal.empty() ) goto fail; val2 = aoStackVal.back(); aoStackVal.pop_back(); } if( aoStackVal.empty() ) goto fail; val1 = aoStackVal.back(); aoStackVal.pop_back(); newNode = new msExprNode; newNode->m_nToken = aoStackOp.back()->m_nToken; newNode->m_aoChildren.push_back(val1); if( val2 ) newNode->m_aoChildren.push_back(val2); aoStackVal.push_back(newNode); delete aoStackOp.back(); aoStackOp.pop_back(); } msExprNode* newNode = new msExprNode; newNode->m_nToken = node->token; aoStackOp.push_back(newNode); } else if( node->token == ',' ) { } else if( node->token == MS_TOKEN_COMPARISON_INTERSECTS || node->token == MS_TOKEN_COMPARISON_DISJOINT || node->token == MS_TOKEN_COMPARISON_TOUCHES || node->token == MS_TOKEN_COMPARISON_OVERLAPS || node->token == MS_TOKEN_COMPARISON_CROSSES || node->token == MS_TOKEN_COMPARISON_DWITHIN || node->token == MS_TOKEN_COMPARISON_BEYOND || node->token == MS_TOKEN_COMPARISON_WITHIN || node->token == MS_TOKEN_COMPARISON_CONTAINS || node->token == MS_TOKEN_COMPARISON_EQUALS || node->token == MS_TOKEN_FUNCTION_LENGTH || node->token == MS_TOKEN_FUNCTION_TOSTRING || node->token == MS_TOKEN_FUNCTION_COMMIFY || node->token == MS_TOKEN_FUNCTION_AREA || node->token == MS_TOKEN_FUNCTION_ROUND || node->token == MS_TOKEN_FUNCTION_FROMTEXT || node->token == MS_TOKEN_FUNCTION_BUFFER || node->token == MS_TOKEN_FUNCTION_DIFFERENCE || node->token == MS_TOKEN_FUNCTION_SIMPLIFY || node->token == MS_TOKEN_FUNCTION_SIMPLIFYPT || node->token == MS_TOKEN_FUNCTION_GENERALIZE || node->token == MS_TOKEN_FUNCTION_SMOOTHSIA || node->token == MS_TOKEN_FUNCTION_JAVASCRIPT || node->token == MS_TOKEN_FUNCTION_UPPER || node->token == MS_TOKEN_FUNCTION_LOWER || node->token == MS_TOKEN_FUNCTION_INITCAP || node->token == MS_TOKEN_FUNCTION_FIRSTCAP ) { if( node->next && node->next->token == '(' ) { int node_token = node->token; msExprNode* subExpr = BuildExprTree(node->next->next, &node, nParenthesisLevel + 1); if( subExpr == NULL ) { goto fail; } msExprNode* newNode = new msExprNode; newNode->m_nToken = node_token; if( subExpr->m_nToken == 0 ) { newNode->m_aoChildren = subExpr->m_aoChildren; subExpr->m_aoChildren.clear(); delete subExpr; } else { newNode->m_aoChildren.push_back(subExpr); } aoStackVal.push_back(newNode); continue; } else goto fail; } else if( node->token == MS_TOKEN_LITERAL_NUMBER || node->token == MS_TOKEN_LITERAL_BOOLEAN ) { msExprNode* newNode = new msExprNode; newNode->m_nToken = node->token; newNode->m_dfVal = node->tokenval.dblval; aoStackVal.push_back(newNode); } else if( node->token == MS_TOKEN_LITERAL_STRING ) { msExprNode* newNode = new msExprNode; newNode->m_nToken = node->token; newNode->m_osVal = node->tokenval.strval; aoStackVal.push_back(newNode); } else if( node->token == MS_TOKEN_LITERAL_TIME ) { msExprNode* newNode = new msExprNode; newNode->m_nToken = node->token; newNode->m_tmVal = node->tokenval.tmval; aoStackVal.push_back(newNode); } else if( node->token == MS_TOKEN_LITERAL_SHAPE ) { msExprNode* newNode = new msExprNode; newNode->m_nToken = node->token; char *wkt = msShapeToWKT(node->tokenval.shpval); newNode->m_osVal = wkt; msFree(wkt); aoStackVal.push_back(newNode); } else if( node->token == MS_TOKEN_BINDING_DOUBLE || node->token == MS_TOKEN_BINDING_INTEGER || node->token == MS_TOKEN_BINDING_STRING || node->token == MS_TOKEN_BINDING_TIME ) { msExprNode* newNode = new msExprNode; newNode->m_nToken = node->token; newNode->m_osVal = node->tokenval.bindval.item; aoStackVal.push_back(newNode); } else { msExprNode* newNode = new msExprNode; newNode->m_nToken = node->token; aoStackVal.push_back(newNode); } node = node->next; } while( !aoStackOp.empty() ) { msExprNode* val1 = NULL; msExprNode* val2 = NULL; msExprNode* newNode = NULL; if (aoStackOp.back()->m_nToken != MS_TOKEN_LOGICAL_NOT) { if( aoStackVal.empty() ) goto fail; val2 = aoStackVal.back(); aoStackVal.pop_back(); } if( aoStackVal.empty() ) goto fail; val1 = aoStackVal.back(); aoStackVal.pop_back(); newNode = new msExprNode; newNode->m_nToken = aoStackOp.back()->m_nToken; newNode->m_aoChildren.push_back(val1); if( val2 ) newNode->m_aoChildren.push_back(val2); aoStackVal.push_back(newNode); delete aoStackOp.back(); aoStackOp.pop_back(); } if( aoStackVal.size() == 1 ) poRet = aoStackVal.back(); else if( aoStackVal.size() > 1 ) { poRet = new msExprNode; poRet->m_aoChildren = aoStackVal; } if( pNodeNext ) *pNodeNext = node ? node->next : NULL; return poRet; fail: for( size_t i=0; im_nToken == MS_TOKEN_COMPARISON_EQ && expr->m_aoChildren.size() == 2 && expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_BOOLEAN && expr->m_aoChildren[1]->m_dfVal == 1.0 ) { return msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[0], pSpatialFilterNode); } if( (expr->m_nToken == MS_TOKEN_COMPARISON_INTERSECTS || expr->m_nToken == MS_TOKEN_COMPARISON_CONTAINS ) && expr->m_aoChildren.size() == 2 && expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_SHAPE ) { if( info->rect_is_defined ) { // Several intersects... *pSpatialFilterNode = NULL; info->rect_is_defined = MS_FALSE; return MS_FALSE; } OGRGeometryH hSpatialFilter = NULL; char* wkt = const_cast(expr->m_aoChildren[1]->m_osVal.c_str()); OGRErr e = OGR_G_CreateFromWkt(&wkt, NULL, &hSpatialFilter); if (e == OGRERR_NONE) { OGREnvelope env; OGR_G_GetEnvelope(hSpatialFilter, &env); info->rect.minx = env.MinX; info->rect.miny = env.MinY; info->rect.maxx = env.MaxX; info->rect.maxy = env.MaxY; info->rect_is_defined = true; *pSpatialFilterNode = expr; OGR_G_DestroyGeometry(hSpatialFilter); return MS_TRUE; } return MS_FALSE; } if( expr->m_nToken == MS_TOKEN_LOGICAL_AND && expr->m_aoChildren.size() == 2 ) { return msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[0], pSpatialFilterNode) && msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[1], pSpatialFilterNode); } return MS_TRUE; } /********************************************************************** * msOGRTranslatePartialMSExpressionToOGRSQL() * * Tries to partially translate a mapserver expression to SQL **********************************************************************/ static std::string msOGRGetTokenText(int nToken) { switch( nToken ) { case '*': case '+': case '-': case '/': case '%': return std::string(1, static_cast(nToken)); case MS_TOKEN_COMPARISON_GE: return ">="; case MS_TOKEN_COMPARISON_GT: return ">"; case MS_TOKEN_COMPARISON_LE: return "<="; case MS_TOKEN_COMPARISON_LT: return "<"; case MS_TOKEN_COMPARISON_EQ: return "="; case MS_TOKEN_COMPARISON_NE: return "!="; case MS_TOKEN_COMPARISON_LIKE: return "LIKE"; default: return std::string(); } } static std::string msOGRTranslatePartialInternal(layerObj* layer, const msExprNode* expr, const msExprNode* spatialFilterNode, bool& bPartialFilter) { switch( expr->m_nToken ) { case MS_TOKEN_LOGICAL_NOT: { std::string osTmp(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); if( osTmp.empty() ) return std::string(); return "(NOT " + osTmp + ")"; } case MS_TOKEN_LOGICAL_AND: { // We can deal with partially translated children std::string osTmp1(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); std::string osTmp2(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter )); if( !osTmp1.empty() && !osTmp2.empty() ) { return "(" + osTmp1 + " AND " + osTmp2 + ")"; } else if( !osTmp1.empty() ) return osTmp1; else return osTmp2; } case MS_TOKEN_LOGICAL_OR: { // We can NOT deal with partially translated children std::string osTmp1(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); std::string osTmp2(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter )); if( !osTmp1.empty() && !osTmp2.empty() ) { return "(" + osTmp1 + " OR " + osTmp2 + ")"; } else return std::string(); } case '*': case '+': case '-': case '/': case '%': case MS_TOKEN_COMPARISON_GE: case MS_TOKEN_COMPARISON_GT: case MS_TOKEN_COMPARISON_LE: case MS_TOKEN_COMPARISON_LT: case MS_TOKEN_COMPARISON_EQ: case MS_TOKEN_COMPARISON_NE: { std::string osTmp1(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); std::string osTmp2(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter )); if( !osTmp1.empty() && !osTmp2.empty() ) { if( expr->m_nToken == MS_TOKEN_COMPARISON_EQ && osTmp2 == "'_MAPSERVER_NULL_'" ) { return "(" + osTmp1 + " IS NULL )"; } if( expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_STRING ) { char md_item_name[256]; snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", expr->m_aoChildren[0]->m_osVal.c_str() ); const char* type = msLookupHashTable(&(layer->metadata), md_item_name); // Cast if needed (or unsure) if( type == NULL || !EQUAL(type, "Character") ) { osTmp1 = "CAST(" + osTmp1 + " AS CHARACTER(4096))"; } } return "(" + osTmp1 + " " + msOGRGetTokenText(expr->m_nToken) + " " + osTmp2 + ")"; } else return std::string(); } case MS_TOKEN_COMPARISON_RE: { std::string osTmp1(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); if( expr->m_aoChildren[1]->m_nToken != MS_TOKEN_LITERAL_STRING ) { return std::string(); } std::string osRE("'"); const size_t nSize = expr->m_aoChildren[1]->m_osVal.size(); bool bHasUsedEscape = false; for( size_t i=0; im_aoChildren[1]->m_osVal[i] == '^' ) continue; if( i == nSize-1 && expr->m_aoChildren[1]->m_osVal[i] == '$' ) break; if( expr->m_aoChildren[1]->m_osVal[i] == '.' ) { if( i+1m_aoChildren[1]->m_osVal[i+1] == '*' ) { osRE += "%"; i++; } else { osRE += "_"; } } else if( expr->m_aoChildren[1]->m_osVal[i] == '\\' && i+1m_aoChildren[1]->m_osVal[i+1]; i++; } else if( expr->m_aoChildren[1]->m_osVal[i] == 'X' || expr->m_aoChildren[1]->m_osVal[i] == '%' || expr->m_aoChildren[1]->m_osVal[i] == '_' ) { bHasUsedEscape = true; osRE += 'X'; osRE += expr->m_aoChildren[1]->m_osVal[i]; } else { osRE += expr->m_aoChildren[1]->m_osVal[i]; } } osRE += "'"; char md_item_name[256]; snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", expr->m_aoChildren[0]->m_osVal.c_str() ); const char* type = msLookupHashTable(&(layer->metadata), md_item_name); // Cast if needed (or unsure) if( type == NULL || !EQUAL(type, "Character") ) { osTmp1 = "CAST(" + osTmp1 + " AS CHARACTER(4096))"; } std::string osRet( "(" + osTmp1 + " LIKE " + osRE ); if( bHasUsedEscape ) osRet += " ESCAPE 'X'"; osRet += ")"; return osRet; } case MS_TOKEN_COMPARISON_IN: { std::string osTmp1(msOGRTranslatePartialInternal( layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter )); std::string osRet = "(" + osTmp1 + " IN ("; for( size_t i=0; i< expr->m_aoChildren[1]->m_aoChildren.size(); ++i ) { if( i > 0 ) osRet += ", "; osRet += msOGRTranslatePartialInternal( layer, expr->m_aoChildren[1]->m_aoChildren[i], spatialFilterNode, bPartialFilter ); } osRet += ")"; return osRet; } case MS_TOKEN_LITERAL_NUMBER: case MS_TOKEN_LITERAL_BOOLEAN: { return std::string(CPLSPrintf("%.18g", expr->m_dfVal)); } case MS_TOKEN_LITERAL_STRING: { char *stresc = msOGREscapeSQLParam(layer, expr->m_osVal.c_str()); std::string osRet("'" + std::string(stresc) + "'"); msFree(stresc); return osRet; } case MS_TOKEN_LITERAL_TIME: { #ifdef notdef // Breaks tests in msautotest/wxs/wfs_time_ogr.map return std::string(CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'", expr->m_tmVal.tm_year+1900, expr->m_tmVal.tm_mon+1, expr->m_tmVal.tm_mday, expr->m_tmVal.tm_hour, expr->m_tmVal.tm_min, expr->m_tmVal.tm_sec)); #endif return std::string(); } case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: case MS_TOKEN_BINDING_STRING: case MS_TOKEN_BINDING_TIME: { char* pszTmp = msOGRGetQuotedItem(layer, expr->m_osVal.c_str()); std::string osRet(pszTmp); msFree(pszTmp); return osRet; } case MS_TOKEN_COMPARISON_INTERSECTS: { if( expr != spatialFilterNode ) bPartialFilter = true; return std::string(); } default: { bPartialFilter = true; return std::string(); } } } #endif /* def USE_OGR */ /* ================================================================== * Here comes the REAL stuff... the functions below are called by maplayer.c * ================================================================== */ /********************************************************************** * msOGRTranslateMsExpressionToOGRSQL() * * Tries to translate a mapserver expression to OGR or driver native SQL **********************************************************************/ static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer, expressionObj* psFilter, char *filteritem) { #ifdef USE_OGR msOGRFileInfo *info = (msOGRFileInfo *)layer->layerinfo; msFree(layer->filter.native_string); layer->filter.native_string = NULL; msFree(info->pszWHERE); info->pszWHERE = NULL; // reasons to not produce native string: not simple layer, or an explicit deny char *do_this = msLayerGetProcessingKey(layer, "NATIVE_SQL"); // default is YES if (do_this && strcmp(do_this, "NO") == 0) { return MS_SUCCESS; } tokenListNodeObjPtr node = psFilter->tokens; msExprNode* expr = BuildExprTree(node, NULL, 0); info->rect_is_defined = MS_FALSE; const msExprNode* spatialFilterNode = NULL; if( expr ) msOGRExtractTopSpatialFilter( info, expr, &spatialFilterNode ); // more reasons to not produce native string: not a recognized driver if (!info->dialect) { // in which case we might still want to try to get a partial WHERE clause if( filteritem == NULL && expr ) { bool bPartialFilter = false; std::string osSQL( msOGRTranslatePartialInternal(layer, expr, spatialFilterNode, bPartialFilter) ); if( !osSQL.empty() ) { info->pszWHERE = msStrdup(osSQL.c_str()); if( bPartialFilter ) { msDebug("Full filter has only been partially " "translated to OGR filter %s\n", info->pszWHERE); } } else if( bPartialFilter ) { msDebug("Filter could not be translated to OGR filter\n"); } } delete expr; return MS_SUCCESS; } char *sql = NULL; // node may be NULL if layer->filter.string != NULL and filteritem != NULL // this is simple filter but string is regex if (node == NULL && filteritem != NULL && layer->filter.string != NULL) { sql = msStringConcatenate(sql, "\""); sql = msStringConcatenate(sql, filteritem); sql = msStringConcatenate(sql, "\""); if (EQUAL(info->dialect, "PostgreSQL") ) { sql = msStringConcatenate(sql, " ~ "); } else { sql = msStringConcatenate(sql, " LIKE "); } sql = msStringConcatenate(sql, "'"); sql = msStringConcatenate(sql, layer->filter.string); sql = msStringConcatenate(sql, "'"); } while (node != NULL) { if (node->next && node->next->token == MS_TOKEN_COMPARISON_IEQ) { char *left = msOGRGetToken(layer, &node); node = node->next; // skip = char *right = msOGRGetToken(layer, &node); sql = msStringConcatenate(sql, "upper("); sql = msStringConcatenate(sql, left); sql = msStringConcatenate(sql, ")"); sql = msStringConcatenate(sql, "="); sql = msStringConcatenate(sql, "upper("); sql = msStringConcatenate(sql, right); sql = msStringConcatenate(sql, ")"); int ok = left && right; msFree(left); msFree(right); if (!ok) { goto fail; } continue; } switch(node->token) { case MS_TOKEN_COMPARISON_INTERSECTS: case MS_TOKEN_COMPARISON_DISJOINT: case MS_TOKEN_COMPARISON_TOUCHES: case MS_TOKEN_COMPARISON_OVERLAPS: case MS_TOKEN_COMPARISON_CROSSES: case MS_TOKEN_COMPARISON_DWITHIN: case MS_TOKEN_COMPARISON_BEYOND: case MS_TOKEN_COMPARISON_WITHIN: case MS_TOKEN_COMPARISON_CONTAINS: case MS_TOKEN_COMPARISON_EQUALS:{ int token = node->token; char *fct = msOGRGetToken(layer, &node); node = node->next; // skip ( char *a1 = msOGRGetToken(layer, &node); node = node->next; // skip , char *a2 = msOGRGetToken(layer, &node); char *a3 = NULL; if (token == MS_TOKEN_COMPARISON_DWITHIN || token == MS_TOKEN_COMPARISON_BEYOND) { node = node->next; // skip , a3 = msOGRGetToken(layer, &node); } node = node->next; // skip ) char *eq = msOGRGetToken(layer, &node); char *rval = msOGRGetToken(layer, &node); if (strcmp(eq, " != ") == 0 || strcmp(rval, "FALSE") == 0) { sql = msStringConcatenate(sql, "NOT "); } // FIXME: case rval is more complex sql = msStringConcatenate(sql, fct); sql = msStringConcatenate(sql, "("); sql = msStringConcatenate(sql, a1); sql = msStringConcatenate(sql, ","); sql = msStringConcatenate(sql, a2); if (token == MS_TOKEN_COMPARISON_DWITHIN || token == MS_TOKEN_COMPARISON_BEYOND) { sql = msStringConcatenate(sql, ")"); if (token == MS_TOKEN_COMPARISON_DWITHIN) sql = msStringConcatenate(sql, "<="); else sql = msStringConcatenate(sql, ">"); sql = msStringConcatenate(sql, a3); } else { sql = msStringConcatenate(sql, ")"); } int ok = fct && a1 && a2 && eq && rval; if (token == MS_TOKEN_COMPARISON_DWITHIN) { ok = ok && a3; } msFree(fct); msFree(a1); msFree(a2); msFree(a3); msFree(eq); msFree(rval); if (!ok) { goto fail; } break; } default: { char *token = msOGRGetToken(layer, &node); if (!token) { goto fail; } sql = msStringConcatenate(sql, token); msFree(token); } } } layer->filter.native_string = sql; delete expr; return MS_SUCCESS; fail: // error producing native string msDebug("Note: Error parsing token list, could produce only: %s. Trying in partial mode\n", sql); msFree(sql); // in which case we might still want to try to get a partial WHERE clause if( expr ) { bool bPartialFilter = false; std::string osSQL( msOGRTranslatePartialInternal(layer, expr, spatialFilterNode, bPartialFilter) ); if( !osSQL.empty() ) { info->pszWHERE = msStrdup(osSQL.c_str()); if( bPartialFilter ) { msDebug("Full filter has only been partially " "translated to OGR filter %s\n", info->pszWHERE); } } else if( bPartialFilter ) { msDebug("Filter could not be translated to OGR filter\n"); } } delete expr; return MS_SUCCESS; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRTranslateMsExpressionToOGRSQL()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerOpen() * * Open OGR data source for the specified map layer. * * If pszOverrideConnection != NULL then this value is used as the connection * string instead of lp->connection. This is used for instance to open * a WFS layer, in this case lp->connection is the WFS url, but we want * OGR to open the local file on disk that was previously downloaded. * * An OGR connection string is: [,] * is file format specific * (optional) is the OGR layer index * default is 0, the first layer. * * One can use the "ogrinfo" program to find out the layer indices in a dataset * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGRLayerOpen(layerObj *layer, const char *pszOverrideConnection) { #ifdef USE_OGR msOGRFileInfo *psInfo; if (layer->layerinfo != NULL) { return MS_SUCCESS; // Nothing to do... layer is already opened } /* -------------------------------------------------------------------- */ /* If this is not a tiled layer, just directly open the target. */ /* -------------------------------------------------------------------- */ if( layer->tileindex == NULL ) { psInfo = msOGRFileOpen( layer, (pszOverrideConnection ? pszOverrideConnection: layer->connection) ); layer->layerinfo = psInfo; layer->tileitemindex = -1; if( layer->layerinfo == NULL ) return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Otherwise we open the tile index, identify the tile item */ /* index and try to select the first file matching our query */ /* region. */ /* -------------------------------------------------------------------- */ else { // Open tile index psInfo = msOGRFileOpen( layer, layer->tileindex ); layer->layerinfo = psInfo; if( layer->layerinfo == NULL ) return MS_FAILURE; // Identify TILEITEM OGRFeatureDefnH hDefn = OGR_L_GetLayerDefn( psInfo->hLayer ); layer->tileitemindex = OGR_FD_GetFieldIndex(hDefn, layer->tileitem); if( layer->tileitemindex < 0 ) { msSetError(MS_OGRERR, "Can't identify TILEITEM %s field in TILEINDEX `%s'.", "msOGRLayerOpen()", layer->tileitem, layer->tileindex ); msOGRFileClose( layer, psInfo ); layer->layerinfo = NULL; return MS_FAILURE; } // Identify TILESRS if( layer->tilesrs != NULL && OGR_FD_GetFieldIndex(hDefn, layer->tilesrs) < 0 ) { msSetError(MS_OGRERR, "Can't identify TILESRS %s field in TILEINDEX `%s'.", "msOGRLayerOpen()", layer->tilesrs, layer->tileindex ); msOGRFileClose( layer, psInfo ); layer->layerinfo = NULL; return MS_FAILURE; } if( layer->tilesrs != NULL && layer->projection.numargs == 0 ) { msSetError(MS_OGRERR, "A layer with TILESRS set in TILEINDEX `%s' must have a " "projection set on itself.", "msOGRLayerOpen()", layer->tileindex ); msOGRFileClose( layer, psInfo ); layer->layerinfo = NULL; return MS_FAILURE; } } /* ------------------------------------------------------------------ * If projection was "auto" then set proj to the dataset's projection. * For a tile index, it is assume the tile index has the projection. * ------------------------------------------------------------------ */ #ifdef USE_PROJ if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { ACQUIRE_OGR_LOCK; OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( psInfo->hLayer ); if (msOGRSpatialRef2ProjectionObj(hSRS, &(layer->projection), layer->debug ) != MS_SUCCESS) { errorObj *ms_error = msGetErrorObj(); RELEASE_OGR_LOCK; msSetError(MS_OGRERR, "%s " "PROJECTION AUTO cannot be used for this " "OGR connection (in layer `%s').", "msOGRLayerOpen()", ms_error->message, layer->name?layer->name:"(null)" ); msOGRFileClose( layer, psInfo ); layer->layerinfo = NULL; return(MS_FAILURE); } RELEASE_OGR_LOCK; } #endif return MS_SUCCESS; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerOpen()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerOpenVT() * * Overloaded version of msOGRLayerOpen for virtual table architecture **********************************************************************/ static int msOGRLayerOpenVT(layerObj *layer) { return msOGRLayerOpen(layer, NULL); } /********************************************************************** * msOGRLayerClose() **********************************************************************/ int msOGRLayerClose(layerObj *layer) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; if (psInfo) { if( layer->debug ) msDebug("msOGRLayerClose(%s).\n", layer->connection); msOGRFileClose( layer, psInfo ); layer->layerinfo = NULL; } return MS_SUCCESS; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerClose()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerIsOpen() **********************************************************************/ static int msOGRLayerIsOpen(layerObj *layer) { #ifdef USE_OGR if (layer->layerinfo) return MS_TRUE; return MS_FALSE; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerIsOpen()"); return(MS_FALSE); #endif /* USE_OGR */ } int msOGRIsSpatialite(layerObj* layer) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; if (psInfo && psInfo->dialect && EQUAL(psInfo->dialect, "Spatialite") ) { // reasons to not produce native string: not simple layer, or an explicit deny char *do_this = msLayerGetProcessingKey(layer, "NATIVE_SQL"); // default is YES if (do_this && strcmp(do_this, "NO") == 0) { return MS_FALSE; } return MS_TRUE; } return MS_FALSE; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRIsSpatialite()"); return(MS_FALSE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerWhichShapes() * * Init OGR layer structs ready for calls to msOGRLayerNextShape(). * * Returns MS_SUCCESS/MS_FAILURE, or MS_DONE if no shape matching the * layer's FILTER overlaps the selected region. **********************************************************************/ int msOGRLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; int status; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerWhichShapes()"); return(MS_FAILURE); } status = msOGRFileWhichShapes( layer, rect, psInfo ); if( status != MS_SUCCESS || layer->tileindex == NULL ) return status; // If we are using a tile index, we need to advance to the first // tile matching the spatial query, and load it. return msOGRFileReadTile( layer, psInfo ); #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerWhichShapes()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerGetItems() * * Load item (i.e. field) names in a char array. If we are working * with a tiled layer, ensure a tile is loaded and use it for the items. * It is implicitly assumed that the schemas will match on all tiles. **********************************************************************/ int msOGRLayerGetItems(layerObj *layer) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetItems()"); return(MS_FAILURE); } if( layer->tileindex != NULL ) { if( psInfo->poCurTile == NULL && msOGRFileReadTile( layer, psInfo ) != MS_SUCCESS ) return MS_FAILURE; psInfo = psInfo->poCurTile; } layer->numitems = 0; layer->items = msOGRFileGetItems(layer, psInfo); if( layer->items == NULL ) return MS_FAILURE; while( layer->items[layer->numitems] != NULL ) layer->numitems++; return msOGRLayerInitItemInfo(layer); #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetItems()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerInitItemInfo() * * Init the itemindexes array after items[] has been reset in a layer. **********************************************************************/ static int msOGRLayerInitItemInfo(layerObj *layer) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; int i; OGRFeatureDefnH hDefn; if (layer->numitems == 0) return MS_SUCCESS; if( layer->tileindex != NULL ) { if( psInfo->poCurTile == NULL && msOGRFileReadTile( layer, psInfo, -2 ) != MS_SUCCESS ) return MS_FAILURE; psInfo = psInfo->poCurTile; } if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerInitItemInfo()"); return(MS_FAILURE); } if((hDefn = OGR_L_GetLayerDefn( psInfo->hLayer )) == NULL) { msSetError(MS_OGRERR, "Layer contains no fields.", "msOGRLayerInitItemInfo()"); return(MS_FAILURE); } if (layer->iteminfo) free(layer->iteminfo); if((layer->iteminfo = (int *)malloc(sizeof(int)*layer->numitems))== NULL) { msSetError(MS_MEMERR, NULL, "msOGRLayerInitItemInfo()"); return(MS_FAILURE); } int *itemindexes = (int*)layer->iteminfo; for(i=0; inumitems; i++) { // Special case for handling text string and angle coming from // OGR style strings. We use special attribute snames. if (EQUAL(layer->items[i], MSOGR_LABELFONTNAMENAME)) itemindexes[i] = MSOGR_LABELFONTNAMEINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELSIZENAME)) itemindexes[i] = MSOGR_LABELSIZEINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELTEXTNAME)) itemindexes[i] = MSOGR_LABELTEXTINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELANGLENAME)) itemindexes[i] = MSOGR_LABELANGLEINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELFCOLORNAME)) itemindexes[i] = MSOGR_LABELFCOLORINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELBCOLORNAME)) itemindexes[i] = MSOGR_LABELBCOLORINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELPLACEMENTNAME)) itemindexes[i] = MSOGR_LABELPLACEMENTINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELANCHORNAME)) itemindexes[i] = MSOGR_LABELANCHORINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELDXNAME)) itemindexes[i] = MSOGR_LABELDXINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELDYNAME)) itemindexes[i] = MSOGR_LABELDYINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELPERPNAME)) itemindexes[i] = MSOGR_LABELPERPINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELBOLDNAME)) itemindexes[i] = MSOGR_LABELBOLDINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELITALICNAME)) itemindexes[i] = MSOGR_LABELITALICINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELUNDERLINENAME)) itemindexes[i] = MSOGR_LABELUNDERLINEINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELPRIORITYNAME)) itemindexes[i] = MSOGR_LABELPRIORITYINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELSTRIKEOUTNAME)) itemindexes[i] = MSOGR_LABELSTRIKEOUTINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELSTRETCHNAME)) itemindexes[i] = MSOGR_LABELSTRETCHINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELADJHORNAME)) itemindexes[i] = MSOGR_LABELADJHORINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELADJVERTNAME)) itemindexes[i] = MSOGR_LABELADJVERTINDEX; else if (EQUAL(layer->items[i], MSOGR_LABELHCOLORNAME)) itemindexes[i] = MSOGR_LABELHCOLORINDEX; #if GDAL_VERSION_NUM >= 1600 else if (EQUAL(layer->items[i], MSOGR_LABELOCOLORNAME)) itemindexes[i] = MSOGR_LABELOCOLORINDEX; #endif /* GDAL_VERSION_NUM >= 1600 */ else if (EQUALN(layer->items[i], MSOGR_LABELPARAMNAME, MSOGR_LABELPARAMNAMELEN)) itemindexes[i] = MSOGR_LABELPARAMINDEX + atoi(layer->items[i] + MSOGR_LABELPARAMNAMELEN); else if (EQUALN(layer->items[i], MSOGR_BRUSHPARAMNAME, MSOGR_BRUSHPARAMNAMELEN)) itemindexes[i] = MSOGR_BRUSHPARAMINDEX + atoi(layer->items[i] + MSOGR_BRUSHPARAMNAMELEN); else if (EQUALN(layer->items[i], MSOGR_PENPARAMNAME, MSOGR_PENPARAMNAMELEN)) itemindexes[i] = MSOGR_PENPARAMINDEX + atoi(layer->items[i] + MSOGR_PENPARAMNAMELEN); else if (EQUALN(layer->items[i], MSOGR_SYMBOLPARAMNAME, MSOGR_SYMBOLPARAMNAMELEN)) itemindexes[i] = MSOGR_SYMBOLPARAMINDEX + atoi(layer->items[i] + MSOGR_SYMBOLPARAMNAMELEN); else { itemindexes[i] = OGR_FD_GetFieldIndex( hDefn, layer->items[i] ); if( itemindexes[i] == -1 ) { if( EQUAL( layer->items[i], OGR_L_GetFIDColumn( psInfo->hLayer ) ) ) { itemindexes[i] = MSOGR_FID_INDEX; } } } if(itemindexes[i] == -1) { msSetError(MS_OGRERR, "Invalid Field name: %s in layer `%s'", "msOGRLayerInitItemInfo()", layer->items[i], layer->name ? layer->name : "(null)"); return(MS_FAILURE); } } return(MS_SUCCESS); #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerInitItemInfo()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerFreeItemInfo() * * Free the itemindexes array in a layer. **********************************************************************/ void msOGRLayerFreeItemInfo(layerObj *layer) { #ifdef USE_OGR if (layer->iteminfo) free(layer->iteminfo); layer->iteminfo = NULL; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerFreeItemInfo()"); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerNextShape() * * Returns shape sequentially from OGR data source. * msOGRLayerWhichShape() must have been called first. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGRLayerNextShape(layerObj *layer, shapeObj *shape) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; int status; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerNextShape()"); return(MS_FAILURE); } if( layer->tileindex == NULL ) return msOGRFileNextShape( layer, shape, psInfo ); // Do we need to load the first tile? if( psInfo->poCurTile == NULL ) { status = msOGRFileReadTile( layer, psInfo ); if( status != MS_SUCCESS ) return status; } do { // Try getting a shape from this tile. status = msOGRFileNextShape( layer, shape, psInfo->poCurTile ); if( status != MS_DONE ) { #ifdef USE_PROJ if( psInfo->sTileProj.numargs > 0 ) { msProjectShape(&(psInfo->sTileProj), &(layer->projection), shape); } #endif return status; } // try next tile. status = msOGRFileReadTile( layer, psInfo ); if( status != MS_SUCCESS ) return status; } while( status == MS_SUCCESS ); return status; //make compiler happy. this is never reached however #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerNextShape()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerGetShape() * * Returns shape from OGR data source by fid. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGRLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; long shapeindex = record->shapeindex; int tileindex = record->tileindex; int resultindex = record->resultindex; int record_is_fid = TRUE; /* set the resultindex as shapeindex if available */ if (resultindex >= 0) { record_is_fid = FALSE; shapeindex = resultindex; } if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetShape()"); return(MS_FAILURE); } if( layer->tileindex == NULL ) return msOGRFileGetShape(layer, shape, shapeindex, psInfo, record_is_fid ); else { if( psInfo->poCurTile == NULL || psInfo->poCurTile->nTileId != tileindex ) { if( msOGRFileReadTile( layer, psInfo, tileindex ) != MS_SUCCESS ) return MS_FAILURE; } int status = msOGRFileGetShape(layer, shape, shapeindex, psInfo->poCurTile, record_is_fid ); #ifdef USE_PROJ if( status == MS_SUCCESS && psInfo->sTileProj.numargs > 0 ) { msProjectShape(&(psInfo->sTileProj), &(layer->projection), shape); } #endif return status; } #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetShape()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerGetExtent() * * Returns the layer extents. * * Returns MS_SUCCESS/MS_FAILURE **********************************************************************/ int msOGRLayerGetExtent(layerObj *layer, rectObj *extent) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; OGREnvelope oExtent; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetExtent()"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Call OGR's GetExtent()... note that for some formats this will * result in a scan of the whole layer and can be an expensive call. * * For tile indexes layers we assume it is sufficient to get the * extents of the tile index. * ------------------------------------------------------------------ */ ACQUIRE_OGR_LOCK; if (OGR_L_GetExtent( psInfo->hLayer, &oExtent, TRUE) != OGRERR_NONE) { RELEASE_OGR_LOCK; msSetError(MS_MISCERR, "Unable to get extents for this layer.", "msOGRLayerGetExtent()"); return(MS_FAILURE); } RELEASE_OGR_LOCK; extent->minx = oExtent.MinX; extent->miny = oExtent.MinY; extent->maxx = oExtent.MaxX; extent->maxy = oExtent.MaxY; return MS_SUCCESS; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetExtent()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRLayerGetNumFeatures() * * Returns the layer feature count. * * Returns the number of features on success, -1 on error **********************************************************************/ int msOGRLayerGetNumFeatures(layerObj *layer) { #ifdef USE_OGR msOGRFileInfo *psInfo = (msOGRFileInfo*)layer->layerinfo; int result; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetNumFeatures()"); return -1; } /* ------------------------------------------------------------------ * Call OGR's GetFeatureCount()... note that for some formats this will * result in a scan of the whole layer and can be an expensive call. * ------------------------------------------------------------------ */ ACQUIRE_OGR_LOCK; result = (int)OGR_L_GetFeatureCount(psInfo->hLayer, TRUE); RELEASE_OGR_LOCK; return result; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetNumFeatures()"); return -1; #endif /* USE_OGR */ } /********************************************************************** * msOGRGetSymbolId() * * Returns a MapServer symbol number matching one of the symbols from * the OGR symbol id string. If not found then try to locate the * default symbol name, and if not found return 0. **********************************************************************/ #ifdef USE_OGR static int msOGRGetSymbolId(symbolSetObj *symbolset, const char *pszSymbolId, const char *pszDefaultSymbol, int try_addimage_if_notfound) { // Symbol name mapping: // First look for the native symbol name, then the ogr-... // generic name, and in last resort try pszDefaultSymbol if // provided by user. char **params; int numparams; int nSymbol = -1; if (pszSymbolId && pszSymbolId[0] != '\0') { #if GDAL_VERSION_NUM >= 1800 /* Use comma as the separator */ params = msStringSplit(pszSymbolId, ',', &numparams); #else params = msStringSplit(pszSymbolId, '.', &numparams); #endif if (params != NULL) { for(int j=0; jnPriority < sssb->nPriority ) return -1; else if( sssa->nPriority > sssb->nPriority ) return 1; else if( sssa->nApparitionIndex < sssb->nApparitionIndex ) return -1; else return 1; } static int msOGRUpdateStyle(OGRStyleMgrH hStyleMgr, mapObj *map, layerObj *layer, classObj *c) { GBool bIsBrush=MS_FALSE; int numParts = OGR_SM_GetPartCount(hStyleMgr, NULL); int nPriority; int bIsPenBrushOnly = msOGRUpdateStyleCheckPenBrushOnly(hStyleMgr); StyleSortStruct* pasSortStruct = (StyleSortStruct*) msSmallMalloc(sizeof(StyleSortStruct) * numParts); int iSortStruct = 0; int iBaseStyleIndex = c->numstyles; int i; /* ------------------------------------------------------------------ * Handle each part * ------------------------------------------------------------------ */ for(i=0; icellsize*map->resolution/map->defresolution*72.0*39.37); if (eStylePartType == OGRSTCLabel) { int ret = msOGRUpdateStyleParseLabel(map, layer, c, hStylePart); if( ret != MS_SUCCESS ) { OGR_ST_Destroy(hStylePart); msFree(pasSortStruct); return ret; } } else if (eStylePartType == OGRSTCPen) { styleObj* s; int nIndex; if( bIsPenBrushOnly ) { /* Historic behaviour when there is a PEN and BRUSH only */ if (bIsBrush || layer->type == MS_LAYER_POLYGON) // This is a multipart symbology, so pen defn goes in the // overlaysymbol params nIndex = 1; else nIndex = 0; } else nIndex = c->numstyles; if (msMaybeAllocateClassStyle(c, nIndex)) { OGR_ST_Destroy(hStylePart); msFree(pasSortStruct); return(MS_FAILURE); } s = c->styles[nIndex]; msOGRUpdateStyleParsePen(map, layer, s, hStylePart, bIsBrush, &nPriority); } else if (eStylePartType == OGRSTCBrush) { styleObj* s; int nIndex = ( bIsPenBrushOnly ) ? 0 : c->numstyles; /* We need 1 style */ if (msMaybeAllocateClassStyle(c, nIndex)) { OGR_ST_Destroy(hStylePart); msFree(pasSortStruct); return(MS_FAILURE); } s = c->styles[nIndex]; msOGRUpdateStyleParseBrush(map, layer, s, hStylePart, &bIsBrush, &nPriority); } else if (eStylePartType == OGRSTCSymbol) { styleObj* s; /* We need 1 style */ int nIndex = c->numstyles; if (msMaybeAllocateClassStyle(c, nIndex)) { OGR_ST_Destroy(hStylePart); msFree(pasSortStruct); return(MS_FAILURE); } s = c->styles[nIndex]; msOGRUpdateStyleParseSymbol(map, layer, s, hStylePart, &nPriority); } /* Memorize the explicit priority and apparition order of the parsed tool/style */ if( !bIsPenBrushOnly && (eStylePartType == OGRSTCPen || eStylePartType == OGRSTCBrush || eStylePartType == OGRSTCSymbol) ) { pasSortStruct[iSortStruct].nPriority = nPriority; pasSortStruct[iSortStruct].nApparitionIndex = iSortStruct; iSortStruct++; } OGR_ST_Destroy(hStylePart); } if( iSortStruct > 1 && !bIsPenBrushOnly ) { /* Compute style order based on their explicit priority and apparition order */ qsort(pasSortStruct, iSortStruct, sizeof(StyleSortStruct), msOGRUpdateStyleSortFct); /* Now reorder styles in c->styles */ styleObj** ppsStyleTmp = (styleObj**)msSmallMalloc( iSortStruct * sizeof(styleObj*) ); memcpy( ppsStyleTmp, c->styles + iBaseStyleIndex, iSortStruct * sizeof(styleObj*) ); for( i = 0; i < iSortStruct; i++) { c->styles[iBaseStyleIndex + i] = ppsStyleTmp[pasSortStruct[i].nApparitionIndex]; } msFree(ppsStyleTmp); } msFree(pasSortStruct); return MS_SUCCESS; } static int msOGRUpdateStyleParseLabel(mapObj *map, layerObj *layer, classObj *c, OGRStyleToolH hLabelStyle) { GBool bIsNull; int r=0,g=0,b=0,t=0; // Enclose the text string inside quotes to make sure it is seen // as a string by the parser inside loadExpression(). (bug185) /* See bug 3481 about the isalnum hack */ const char *labelTextString = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelTextString, &bIsNull); if (c->numlabels == 0) { /* allocate a new label object */ if(msGrowClassLabels(c) == NULL) return MS_FAILURE; c->numlabels++; initLabel(c->labels[0]); } msFreeExpression(&c->labels[0]->text); c->labels[0]->text.type = MS_STRING; c->labels[0]->text.string = msStrdup(labelTextString); c->labels[0]->angle = OGR_ST_GetParamDbl(hLabelStyle, OGRSTLabelAngle, &bIsNull); c->labels[0]->size = OGR_ST_GetParamDbl(hLabelStyle, OGRSTLabelSize, &bIsNull); if( c->labels[0]->size < 1 ) /* no point dropping to zero size */ c->labels[0]->size = 1; // OGR default is anchor point = LL, so label is at UR of anchor c->labels[0]->position = MS_UR; int nPosition = OGR_ST_GetParamNum(hLabelStyle, OGRSTLabelAnchor, &bIsNull); if( !bIsNull ) { switch( nPosition ) { case 1: c->labels[0]->position = MS_UR; break; case 2: c->labels[0]->position = MS_UC; break; case 3: c->labels[0]->position = MS_UL; break; case 4: c->labels[0]->position = MS_CR; break; case 5: c->labels[0]->position = MS_CC; break; case 6: c->labels[0]->position = MS_CL; break; case 7: c->labels[0]->position = MS_LR; break; case 8: c->labels[0]->position = MS_LC; break; case 9: c->labels[0]->position = MS_LL; break; case 10: c->labels[0]->position = MS_UR; break; /*approximate*/ case 11: c->labels[0]->position = MS_UC; break; case 12: c->labels[0]->position = MS_UL; break; default: break; } } const char *pszColor = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelFColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hLabelStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->labels[0]->color, r, g, b, t); } pszColor = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelHColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hLabelStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->labels[0]->shadowcolor, r, g, b, t); } #if GDAL_VERSION_NUM >= 1600 pszColor = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelOColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hLabelStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(c->labels[0]->outlinecolor, r, g, b, t); } #endif /* GDAL_VERSION_NUM >= 1600 */ const char *pszBold = OGR_ST_GetParamNum(hLabelStyle, OGRSTLabelBold, &bIsNull) ? "-bold" : ""; const char *pszItalic = OGR_ST_GetParamNum(hLabelStyle, OGRSTLabelItalic, &bIsNull) ? "-italic" : ""; const char *pszFontName = OGR_ST_GetParamStr(hLabelStyle, OGRSTLabelFontName, &bIsNull); /* replace spaces with hyphens to allow mapping to a valid hashtable entry*/ char* pszFontNameEscaped = NULL; if (pszFontName != NULL) { pszFontNameEscaped = msStrdup(pszFontName); msReplaceChar(pszFontNameEscaped, ' ', '-'); } const char *pszName = CPLSPrintf("%s%s%s", pszFontNameEscaped, pszBold, pszItalic); bool bFont = true; if (pszFontNameEscaped != NULL && !bIsNull && pszFontNameEscaped[0] != '\0') { if (msLookupHashTable(&(map->fontset.fonts), (char*)pszName) != NULL) { c->labels[0]->font = msStrdup(pszName); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** Using '%s' TTF font **\n", pszName); } else if ( (strcmp(pszFontNameEscaped,pszName) != 0) && msLookupHashTable(&(map->fontset.fonts), (char*)pszFontNameEscaped) != NULL) { c->labels[0]->font = msStrdup(pszFontNameEscaped); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** Using '%s' TTF font **\n", pszFontNameEscaped); } else if (msLookupHashTable(&(map->fontset.fonts),"default") != NULL) { c->labels[0]->font = msStrdup("default"); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** Using 'default' TTF font **\n"); } else bFont = false; } msFree(pszFontNameEscaped); if (!bFont) { c->labels[0]->size = MS_MEDIUM; } return MS_SUCCESS; } static int msOGRUpdateStyleParsePen(mapObj *map, layerObj *layer, styleObj *s, OGRStyleToolH hPenStyle, int bIsBrush, int* pbPriority) { GBool bIsNull; int r=0,g=0,b=0,t=0; const char *pszPenName, *pszPattern, *pszCap, *pszJoin; colorObj oPenColor; int nPenSymbol = 0; int nPenSize = 1; t =-1; double pattern[MS_MAXPATTERNLENGTH]; int patternlength = 0; int linecap = MS_CJC_DEFAULT_CAPS; int linejoin = MS_CJC_DEFAULT_JOINS; double offsetx = 0.0; double offsety = 0.0; // Make sure pen is always initialized MS_INIT_COLOR(oPenColor, -1, -1, -1,255); pszPenName = OGR_ST_GetParamStr(hPenStyle, OGRSTPenId, &bIsNull); if (bIsNull) pszPenName = NULL; // Check for Pen Pattern "ogr-pen-1": the invisible pen // If that's what we have then set pen color to -1 if (pszPenName && strstr(pszPenName, "ogr-pen-1") != NULL) { MS_INIT_COLOR(oPenColor, -1, -1, -1,255); } else { const char *pszColor = OGR_ST_GetParamStr(hPenStyle, OGRSTPenColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hPenStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(oPenColor, r, g, b, t); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** PEN COLOR = %d %d %d **\n", r,g,b); } nPenSize = OGR_ST_GetParamNum(hPenStyle, OGRSTPenWidth, &bIsNull); if (bIsNull) nPenSize = 1; if (pszPenName!=NULL) { // Try to match pen name in symbol file nPenSymbol = msOGRGetSymbolId(&(map->symbolset), pszPenName, NULL, MS_FALSE); } } if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** PEN COLOR = %d %d %d **\n", oPenColor.red,oPenColor.green,oPenColor.blue); pszPattern = OGR_ST_GetParamStr(hPenStyle, OGRSTPenPattern, &bIsNull); if (bIsNull) pszPattern = NULL; if( pszPattern != NULL ) { char** papszTokens = CSLTokenizeStringComplex(pszPattern, " ", FALSE, FALSE); int nTokenCount = CSLCount(papszTokens); int bValidFormat = TRUE; if( nTokenCount >= 2 && nTokenCount <= MS_MAXPATTERNLENGTH) { for(int i=0;i 2 && strcmp(papszTokens[i] + strlen(papszTokens[i]) - 2, "px") == 0 ) { pattern[patternlength++] = CPLAtof(papszTokens[i]); } else { bValidFormat = FALSE; patternlength = 0; break; } } } else bValidFormat = FALSE; if( !bValidFormat && layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Invalid/unhandled pen pattern format = %s\n", pszPattern); CSLDestroy(papszTokens); } pszCap = OGR_ST_GetParamStr(hPenStyle, OGRSTPenCap, &bIsNull); if (bIsNull) pszCap = NULL; if( pszCap != NULL ) { /* Note: the default in OGR Feature style is BUTT, but the MapServer */ /* default is ROUND. Currently use MapServer default. */ if( strcmp(pszCap, "b") == 0 ) /* BUTT */ linecap = MS_CJC_BUTT; else if( strcmp(pszCap, "r") == 0 ) /* ROUND */ linecap = MS_CJC_ROUND; else if( strcmp(pszCap, "p") == 0 ) /* PROJECTING */ linecap = MS_CJC_SQUARE; else if( layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Invalid/unhandled pen cap = %s\n", pszCap); } pszJoin = OGR_ST_GetParamStr(hPenStyle, OGRSTPenJoin, &bIsNull); if (bIsNull) pszJoin = NULL; if( pszJoin != NULL ) { /* Note: the default in OGR Feature style is MITER, but the MapServer */ /* default is NONE. Currently use MapServer default. */ if( strcmp(pszJoin, "m") == 0 ) /* MITTER */ linejoin = MS_CJC_MITER; else if( strcmp(pszJoin, "r") == 0 ) /* ROUND */ linejoin = MS_CJC_ROUND; else if( strcmp(pszJoin, "b") == 0 ) /* BEVEL */ linejoin = MS_CJC_BEVEL; else if( layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("Invalid/unhandled pen join = %s\n", pszJoin); } offsetx = OGR_ST_GetParamDbl(hPenStyle, OGRSTPenPerOffset, &bIsNull); if( bIsNull ) offsetx = 0; if( offsetx != 0.0 ) { /* OGR feature style and MapServer conventions related to offset */ /* sign are the same : negative values for left of line, positive for */ /* right of line */ offsety = MS_STYLE_SINGLE_SIDED_OFFSET; } if (bIsBrush || layer->type == MS_LAYER_POLYGON) { // This is a multipart symbology, so pen defn goes in the // overlaysymbol params s->outlinecolor = oPenColor; } else { // Single part symbology s->color = oPenColor; } s->symbol = nPenSymbol; s->size = nPenSize; s->width = nPenSize; s->linecap = linecap; s->linejoin = linejoin; s->offsetx = offsetx; s->offsety = offsety; s->patternlength = patternlength; if( patternlength > 0 ) memcpy(s->pattern, pattern, sizeof(double) * patternlength); int nPriority = OGR_ST_GetParamNum(hPenStyle, OGRSTPenPriority, &bIsNull); if( !bIsNull ) *pbPriority = nPriority; return MS_SUCCESS; } static int msOGRUpdateStyleParseBrush(mapObj *map, layerObj *layer, styleObj *s, OGRStyleToolH hBrushStyle, int* pbIsBrush, int* pbPriority) { GBool bIsNull; int r=0,g=0,b=0,t=0; const char *pszBrushName = OGR_ST_GetParamStr(hBrushStyle, OGRSTBrushId, &bIsNull); if (bIsNull) pszBrushName = NULL; // Check for Brush Pattern "ogr-brush-1": the invisible fill // If that's what we have then set fill color to -1 if (pszBrushName && strstr(pszBrushName, "ogr-brush-1") != NULL) { MS_INIT_COLOR(s->color, -1, -1, -1, 255); } else { *pbIsBrush = TRUE; const char *pszColor = OGR_ST_GetParamStr(hBrushStyle, OGRSTBrushFColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hBrushStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(s->color, r, g, b, t); if (layer->debug >= MS_DEBUGLEVEL_VVV) msDebug("** BRUSH COLOR = %d %d %d **\n", r,g,b); } pszColor = OGR_ST_GetParamStr(hBrushStyle, OGRSTBrushBColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hBrushStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(s->backgroundcolor, r, g, b, t); } // Symbol name mapping: // First look for the native symbol name, then the ogr-... // generic name. // If none provided or found then use 0: solid fill const char *pszName = OGR_ST_GetParamStr(hBrushStyle, OGRSTBrushId, &bIsNull); s->symbol = msOGRGetSymbolId(&(map->symbolset), pszName, NULL, MS_FALSE); double angle = OGR_ST_GetParamDbl(hBrushStyle, OGRSTBrushAngle, &bIsNull); if( !bIsNull ) s->angle = angle; double size = OGR_ST_GetParamDbl(hBrushStyle, OGRSTBrushSize, &bIsNull); if( !bIsNull ) s->size = size; double spacingx = OGR_ST_GetParamDbl(hBrushStyle, OGRSTBrushDx, &bIsNull); if( !bIsNull ) { double spacingy = OGR_ST_GetParamDbl(hBrushStyle, OGRSTBrushDy, &bIsNull); if( !bIsNull ) { if( spacingx == spacingy ) s->gap = spacingx; else if( layer->debug >= MS_DEBUGLEVEL_VVV ) msDebug("Ignoring brush dx and dy since they don't have the same value\n"); } } } int nPriority = OGR_ST_GetParamNum(hBrushStyle, OGRSTBrushPriority, &bIsNull); if( !bIsNull ) *pbPriority = nPriority; return MS_SUCCESS; } static int msOGRUpdateStyleParseSymbol(mapObj *map, layerObj *layer, styleObj *s, OGRStyleToolH hSymbolStyle, int* pbPriority) { GBool bIsNull; int r=0,g=0,b=0,t=0; const char *pszColor = OGR_ST_GetParamStr(hSymbolStyle, OGRSTSymbolColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hSymbolStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(s->color, r, g, b, t); } #if GDAL_VERSION_NUM >= 1600 pszColor = OGR_ST_GetParamStr(hSymbolStyle, OGRSTSymbolOColor, &bIsNull); if (!bIsNull && OGR_ST_GetRGBFromString(hSymbolStyle, pszColor, &r, &g, &b, &t)) { MS_INIT_COLOR(s->outlinecolor, r, g, b, t); } #endif /* GDAL_VERSION_NUM >= 1600 */ s->angle = OGR_ST_GetParamNum(hSymbolStyle, OGRSTSymbolAngle, &bIsNull); double dfTmp = OGR_ST_GetParamNum(hSymbolStyle, OGRSTSymbolSize, &bIsNull); if (!bIsNull) s->size = dfTmp; // Symbol name mapping: // First look for the native symbol name, then the ogr-... // generic name, and in last resort try "default-marker" if // provided by user. const char *pszName = OGR_ST_GetParamStr(hSymbolStyle, OGRSTSymbolId, &bIsNull); if (bIsNull) pszName = NULL; int try_addimage_if_notfound = MS_FALSE; #ifdef USE_CURL if (pszName && strncasecmp(pszName, "http", 4) == 0) try_addimage_if_notfound =MS_TRUE; #endif if (!s->symbolname) s->symbol = msOGRGetSymbolId(&(map->symbolset), pszName, "default-marker", try_addimage_if_notfound); int nPriority = OGR_ST_GetParamNum(hSymbolStyle, OGRSTSymbolPriority, &bIsNull); if( !bIsNull ) *pbPriority = nPriority; return MS_SUCCESS; } #endif /* USE_OGR */ /********************************************************************** * msOGRLayerGetAutoStyle() * * Fills a classObj with style info from the specified shape. * For optimal results, this should be called immediately after * GetNextShape() or GetShape() so that the shape doesn't have to be read * twice. * * The returned classObj is a ref. to a static structure valid only until * the next call and that shouldn't be freed by the caller. **********************************************************************/ static int msOGRLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { #ifdef USE_OGR msOGRFileInfo *psInfo =(msOGRFileInfo*)layer->layerinfo; if (psInfo == NULL || psInfo->hLayer == NULL) { msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRLayerGetAutoStyle()"); return(MS_FAILURE); } if( layer->tileindex != NULL ) { if( (psInfo->poCurTile == NULL || shape->tileindex != psInfo->poCurTile->nTileId) && msOGRFileReadTile( layer, psInfo ) != MS_SUCCESS ) return MS_FAILURE; psInfo = psInfo->poCurTile; } /* ------------------------------------------------------------------ * Read shape or reuse ref. to last shape read. * ------------------------------------------------------------------ */ ACQUIRE_OGR_LOCK; if (psInfo->hLastFeature == NULL || psInfo->last_record_index_read != shape->resultindex) { RELEASE_OGR_LOCK; msSetError(MS_MISCERR, "Assertion failed: AutoStyle not requested on loaded shape.", "msOGRLayerGetAutoStyle()"); return(MS_FAILURE); } /* ------------------------------------------------------------------ * Reset style info in the class to defaults * the only members we don't touch are name, expression, and join/query stuff * ------------------------------------------------------------------ */ resetClassStyle(c); if (msMaybeAllocateClassStyle(c, 0)) { RELEASE_OGR_LOCK; return(MS_FAILURE); } // __TODO__ label cache incompatible with styleitem feature. layer->labelcache = MS_OFF; int nRetVal = MS_SUCCESS; if (psInfo->hLastFeature) { OGRStyleMgrH hStyleMgr = OGR_SM_Create(NULL); OGR_SM_InitFromFeature(hStyleMgr, psInfo->hLastFeature); nRetVal = msOGRUpdateStyle(hStyleMgr, map, layer, c); OGR_SM_Destroy(hStyleMgr); } RELEASE_OGR_LOCK; return nRetVal; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetAutoStyle()"); return(MS_FAILURE); #endif /* USE_OGR */ } /********************************************************************** * msOGRUpdateStyleFromString() * * Fills a classObj with style info from the specified style string. * For optimal results, this should be called immediately after * GetNextShape() or GetShape() so that the shape doesn't have to be read * twice. * * The returned classObj is a ref. to a static structure valid only until * the next call and that shouldn't be freed by the caller. **********************************************************************/ int msOGRUpdateStyleFromString(mapObj *map, layerObj *layer, classObj *c, const char *stylestring) { #ifdef USE_OGR /* ------------------------------------------------------------------ * Reset style info in the class to defaults * the only members we don't touch are name, expression, and join/query stuff * ------------------------------------------------------------------ */ resetClassStyle(c); if (msMaybeAllocateClassStyle(c, 0)) { return(MS_FAILURE); } // __TODO__ label cache incompatible with styleitem feature. layer->labelcache = MS_OFF; int nRetVal = MS_SUCCESS; ACQUIRE_OGR_LOCK; OGRStyleMgrH hStyleMgr = OGR_SM_Create(NULL); OGR_SM_InitStyleString(hStyleMgr, stylestring); nRetVal = msOGRUpdateStyle(hStyleMgr, map, layer, c); OGR_SM_Destroy(hStyleMgr); RELEASE_OGR_LOCK; return nRetVal; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGRLayerGetAutoStyle()"); return(MS_FAILURE); #endif /* USE_OGR */ } /************************************************************************/ /* msOGRLCleanup() */ /************************************************************************/ void msOGRCleanup( void ) { #if defined(USE_OGR) ACQUIRE_OGR_LOCK; if( bOGRDriversRegistered == MS_TRUE ) { CPLPopErrorHandler(); bOGRDriversRegistered = MS_FALSE; } RELEASE_OGR_LOCK; #endif } /************************************************************************/ /* msOGREscapeSQLParam */ /************************************************************************/ char *msOGREscapePropertyName(layerObj *layer, const char *pszString) { #ifdef USE_OGR char* pszEscapedStr =NULL; if(layer && pszString && strlen(pszString) > 0) { pszEscapedStr = (char*) msSmallMalloc( strlen(pszString) * 2 + 1 ); int j = 0; for( int i = 0; pszString[i] != '\0'; ++i ) { if( pszString[i] == '"' ) { pszEscapedStr[j++] = '"'; pszEscapedStr[j++] = '"'; } else pszEscapedStr[j++] = pszString[i]; } pszEscapedStr[j] = 0; } return pszEscapedStr; #else /* ------------------------------------------------------------------ * OGR Support not included... * ------------------------------------------------------------------ */ msSetError(MS_MISCERR, "OGR support is not available.", "msOGREscapePropertyName()"); return NULL; #endif /* USE_OGR */ } static int msOGRLayerSupportsCommonFilters(layerObj *layer) { return MS_FALSE; } static void msOGREnablePaging(layerObj *layer, int value) { #ifdef USE_OGR msOGRFileInfo *layerinfo = NULL; if (layer->debug) { msDebug("msOGREnablePaging(%d) called.\n", value); } if(!msOGRLayerIsOpen(layer)) msOGRLayerOpenVT(layer); assert( layer->layerinfo != NULL); layerinfo = (msOGRFileInfo *)layer->layerinfo; layerinfo->bPaging = value; #else msSetError( MS_MISCERR, "OGR support is not available.", "msOGREnablePaging()"); #endif return; } static int msOGRGetPaging(layerObj *layer) { #ifdef USE_OGR msOGRFileInfo *layerinfo = NULL; if (layer->debug) { msDebug("msOGRGetPaging called.\n"); } if(!msOGRLayerIsOpen(layer)) msOGRLayerOpenVT(layer); assert( layer->layerinfo != NULL); layerinfo = (msOGRFileInfo *)layer->layerinfo; return layerinfo->bPaging; #else msSetError( MS_MISCERR, "OGR support is not available.", "msOGREnablePaging()"); return MS_FAILURE; #endif } /************************************************************************/ /* msOGRLayerInitializeVirtualTable() */ /************************************************************************/ int msOGRLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerTranslateFilter = msOGRTranslateMsExpressionToOGRSQL; layer->vtable->LayerSupportsCommonFilters = msOGRLayerSupportsCommonFilters; layer->vtable->LayerInitItemInfo = msOGRLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msOGRLayerFreeItemInfo; layer->vtable->LayerOpen = msOGRLayerOpenVT; layer->vtable->LayerIsOpen = msOGRLayerIsOpen; layer->vtable->LayerWhichShapes = msOGRLayerWhichShapes; layer->vtable->LayerNextShape = msOGRLayerNextShape; layer->vtable->LayerGetShape = msOGRLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerClose = msOGRLayerClose; layer->vtable->LayerGetItems = msOGRLayerGetItems; layer->vtable->LayerGetExtent = msOGRLayerGetExtent; layer->vtable->LayerGetAutoStyle = msOGRLayerGetAutoStyle; /* layer->vtable->LayerCloseConnection, use default */ layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerCreateItems, use default */ layer->vtable->LayerGetNumFeatures = msOGRLayerGetNumFeatures; /* layer->vtable->LayerGetAutoProjection, use defaut*/ layer->vtable->LayerEscapeSQLParam = msOGREscapeSQLParam; layer->vtable->LayerEscapePropertyName = msOGREscapePropertyName; layer->vtable->LayerEnablePaging = msOGREnablePaging; layer->vtable->LayerGetPaging = msOGRGetPaging; return MS_SUCCESS; } /************************************************************************/ /* msOGRShapeFromWKT() */ /************************************************************************/ shapeObj *msOGRShapeFromWKT(const char *string) { #ifdef USE_OGR OGRGeometryH hGeom = NULL; shapeObj *shape=NULL; if(!string) return NULL; if( OGR_G_CreateFromWkt( (char **)&string, NULL, &hGeom ) != OGRERR_NONE ) { msSetError(MS_OGRERR, "Failed to parse WKT string.", "msOGRShapeFromWKT()" ); return NULL; } /* Initialize a corresponding shapeObj */ shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); /* translate WKT into an OGRGeometry. */ if( msOGRGeometryToShape( hGeom, shape, wkbFlatten(OGR_G_GetGeometryType(hGeom)) ) == MS_FAILURE ) { free( shape ); return NULL; } OGR_G_DestroyGeometry( hGeom ); return shape; #else msSetError(MS_OGRERR, "OGR support is not available.","msOGRShapeFromWKT()"); return NULL; #endif } /************************************************************************/ /* msOGRShapeToWKT() */ /************************************************************************/ char *msOGRShapeToWKT(shapeObj *shape) { #ifdef USE_OGR OGRGeometryH hGeom = NULL; int i; char *wkt = NULL; if(!shape) return NULL; if( shape->type == MS_SHAPE_POINT && shape->numlines == 1 && shape->line[0].numpoints == 1 ) { hGeom = OGR_G_CreateGeometry( wkbPoint ); OGR_G_SetPoint_2D( hGeom, 0, shape->line[0].point[0].x, shape->line[0].point[0].y ); } else if( shape->type == MS_SHAPE_POINT && shape->numlines == 1 && shape->line[0].numpoints > 1 ) { hGeom = OGR_G_CreateGeometry( wkbMultiPoint ); for( i = 0; i < shape->line[0].numpoints; i++ ) { OGRGeometryH hPoint; hPoint = OGR_G_CreateGeometry( wkbPoint ); OGR_G_SetPoint_2D( hPoint, 0, shape->line[0].point[i].x, shape->line[0].point[i].y ); OGR_G_AddGeometryDirectly( hGeom, hPoint ); } } else if( shape->type == MS_SHAPE_LINE && shape->numlines == 1 ) { hGeom = OGR_G_CreateGeometry( wkbLineString ); for( i = 0; i < shape->line[0].numpoints; i++ ) { OGR_G_AddPoint_2D( hGeom, shape->line[0].point[i].x, shape->line[0].point[i].y ); } } else if( shape->type == MS_SHAPE_LINE && shape->numlines > 1 ) { OGRGeometryH hMultiLine = OGR_G_CreateGeometry( wkbMultiLineString ); int iLine; for( iLine = 0; iLine < shape->numlines; iLine++ ) { hGeom = OGR_G_CreateGeometry( wkbLineString ); for( i = 0; i < shape->line[iLine].numpoints; i++ ) { OGR_G_AddPoint_2D( hGeom, shape->line[iLine].point[i].x, shape->line[iLine].point[i].y ); } OGR_G_AddGeometryDirectly( hMultiLine, hGeom ); } hGeom = hMultiLine; } else if( shape->type == MS_SHAPE_POLYGON ) { int iLine; /* actually, it is pretty hard to be sure rings 1+ are interior */ hGeom = OGR_G_CreateGeometry( wkbPolygon ); for( iLine = 0; iLine < shape->numlines; iLine++ ) { OGRGeometryH hRing; hRing = OGR_G_CreateGeometry( wkbLinearRing ); for( i = 0; i < shape->line[iLine].numpoints; i++ ) { OGR_G_AddPoint_2D( hRing, shape->line[iLine].point[i].x, shape->line[iLine].point[i].y ); } OGR_G_AddGeometryDirectly( hGeom, hRing ); } } else { msSetError(MS_OGRERR, "OGR support is not available.", "msOGRShapeToWKT()"); } if( hGeom != NULL ) { char *pszOGRWkt; OGR_G_ExportToWkt( hGeom, &pszOGRWkt ); wkt = msStrdup( pszOGRWkt ); CPLFree( pszOGRWkt ); } return wkt; #else msSetError(MS_OGRERR, "OGR support is not available.", "msOGRShapeToWKT()"); return NULL; #endif } mapserver-7.4.3/mapogroutput.c000066400000000000000000001407641357574274700165040ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: OGR Output (for WFS) * Author: Frank Warmerdam (warmerdam@pobox.com) * ********************************************************************** * Copyright (c) 2010, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include #include "mapserver.h" #include "mapproject.h" #include "mapthread.h" #include "mapows.h" #if defined(USE_OGR) # define __USE_LARGEFILE64 1 # include "ogr_api.h" # include "ogr_srs_api.h" # include "cpl_conv.h" # include "cpl_vsi.h" # include "cpl_string.h" #endif #ifdef USE_OGR /************************************************************************/ /* msInitDefaultOGROutputFormat() */ /************************************************************************/ int msInitDefaultOGROutputFormat( outputFormatObj *format ) { OGRSFDriverH hDriver; msOGRInitialize(); /* -------------------------------------------------------------------- */ /* check that this driver exists. Note visiting drivers should */ /* be pretty threadsafe so don't bother acquiring the GDAL */ /* lock. */ /* -------------------------------------------------------------------- */ hDriver = OGRGetDriverByName( format->driver+4 ); if( hDriver == NULL ) { msSetError( MS_MISCERR, "No OGR driver named `%s' available.", "msInitDefaultOGROutputFormat()", format->driver+4 ); return MS_FAILURE; } if( !OGR_Dr_TestCapability( hDriver, ODrCCreateDataSource ) ) { msSetError( MS_MISCERR, "OGR `%s' driver does not support output.", "msInitDefaultOGROutputFormat()", format->driver+4 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Initialize the object. */ /* -------------------------------------------------------------------- */ format->imagemode = MS_IMAGEMODE_FEATURE; format->renderer = MS_RENDER_WITH_OGR; /* perhaps we should eventually hardcode mimetypes and extensions for some formats? */ return MS_SUCCESS; } /************************************************************************/ /* msCSLConcatenate() */ /************************************************************************/ static char** msCSLConcatenate( char** papszResult, char** papszToBeAdded ) { char** papszIter = papszToBeAdded; while( papszIter && *papszIter ) { papszResult = CSLAddString(papszResult, *papszIter); papszIter ++; } return papszResult; } /************************************************************************/ /* msOGRRecursiveFileList() */ /* */ /* Collect a list of all files under the named directory, */ /* including those in subdirectories. */ /************************************************************************/ char **msOGRRecursiveFileList( const char *path ) { char **file_list; char **result_list = NULL; int i, count, change; file_list = CPLReadDir( path ); count = CSLCount(file_list); /* -------------------------------------------------------------------- */ /* Sort the file list so we always get them back in the same */ /* order - it makes autotests more stable. */ /* -------------------------------------------------------------------- */ do { change = 0; for( i = 0; i < count-1; i++ ) { if( strcasecmp(file_list[i],file_list[i+1]) > 0 ) { char *temp = file_list[i]; file_list[i] = file_list[i+1]; file_list[i+1] = temp; change = 1; } } } while( change ); /* -------------------------------------------------------------------- */ /* collect names we want and process subdirectories. */ /* -------------------------------------------------------------------- */ for( i = 0; i < count; i++ ) { char full_filename[MS_MAXPATHLEN]; VSIStatBufL sStatBuf; if( EQUAL(file_list[i],".") || EQUAL(file_list[i],"..") ) continue; strlcpy( full_filename, CPLFormFilename( path, file_list[i], NULL ), sizeof(full_filename) ); VSIStatL( full_filename, &sStatBuf ); if( VSI_ISREG( sStatBuf.st_mode ) ) { result_list = CSLAddString( result_list, full_filename ); } else if( VSI_ISDIR( sStatBuf.st_mode ) ) { char **subfiles = msOGRRecursiveFileList( full_filename ); result_list = msCSLConcatenate( result_list, subfiles ); CSLDestroy( subfiles ); } } CSLDestroy( file_list ); return result_list; } /************************************************************************/ /* msOGRCleanupDS() */ /************************************************************************/ static void msOGRCleanupDS( const char *datasource_name ) { char **file_list; char path[MS_MAXPATHLEN]; int i; VSIStatBufL sStatBuf; if( VSIStatL( datasource_name, &sStatBuf ) != 0 ) return; if( VSI_ISDIR( sStatBuf.st_mode ) ) strlcpy( path, datasource_name, sizeof(path) ); else strlcpy( path, CPLGetPath( datasource_name ), sizeof(path) ); file_list = CPLReadDir( path ); for( i = 0; file_list != NULL && file_list[i] != NULL; i++ ) { char full_filename[MS_MAXPATHLEN]; VSIStatBufL sStatBuf; if( EQUAL(file_list[i],".") || EQUAL(file_list[i],"..") ) continue; strlcpy( full_filename, CPLFormFilename( path, file_list[i], NULL ), sizeof(full_filename) ); VSIStatL( full_filename, &sStatBuf ); if( VSI_ISREG( sStatBuf.st_mode ) ) { VSIUnlink( full_filename ); } else if( VSI_ISDIR( sStatBuf.st_mode ) ) { msOGRCleanupDS( full_filename ); } } CSLDestroy( file_list ); VSIRmdir( path ); } /************************************************************************/ /* msOGRSetPoints() */ /************************************************************************/ static void msOGRSetPoints( OGRGeometryH hGeom, lineObj *line, int bWant2DOutput) { int i; if( bWant2DOutput ) { for( i = 0; i < line->numpoints; i++ ) { OGR_G_SetPoint_2D( hGeom, i, line->point[i].x, line->point[i].y ); } } else { for( i = 0; i < line->numpoints; i++ ) { OGR_G_SetPoint( hGeom, i, line->point[i].x, line->point[i].y, #ifdef USE_POINT_Z_M line->point[i].z #else 0.0 #endif ); } } } /************************************************************************/ /* msOGRWriteShape() */ /************************************************************************/ static int msOGRWriteShape( layerObj *map_layer, OGRLayerH hOGRLayer, shapeObj *shape, gmlItemListObj *item_list, int nFirstOGRFieldIndex, const char *pszFeatureid ) { OGRGeometryH hGeom = NULL; OGRFeatureH hFeat; OGRErr eErr; int i, out_field; OGRwkbGeometryType eLayerGType, eFlattenLayerGType; OGRFeatureDefnH hLayerDefn; int bWant2DOutput; hLayerDefn = OGR_L_GetLayerDefn( hOGRLayer ); eLayerGType = OGR_FD_GetGeomType(hLayerDefn); eFlattenLayerGType = wkbFlatten(eLayerGType); bWant2DOutput = (eLayerGType == eFlattenLayerGType); /* -------------------------------------------------------------------- */ /* Transform point geometry. */ /* -------------------------------------------------------------------- */ if( shape->type == MS_SHAPE_POINT ) { OGRGeometryH hMP = NULL; int j; if( shape->numlines < 1 ) { msSetError(MS_MISCERR, "Failed on odd point geometry.", "msOGRWriteShape()"); return MS_FAILURE; } if( shape->numlines == 1 && shape->line[0].numpoints > 1 ) { hGeom = OGR_G_CreateGeometry( wkbMultiPoint ); for( j = 0; j < shape->line[0].numpoints; j++ ) { OGRGeometryH hPoint = OGR_G_CreateGeometry( wkbPoint ); if( bWant2DOutput ) { OGR_G_SetPoint_2D( hPoint, 0, shape->line[0].point[j].x, shape->line[0].point[j].y ); } else { OGR_G_SetPoint( hPoint, 0, shape->line[0].point[j].x, shape->line[0].point[j].y, #ifdef USE_POINT_Z_M shape->line[0].point[j].z #else 0.0 #endif ); } OGR_G_AddGeometryDirectly( hGeom, hPoint ); } } else { if( shape->numlines > 1 ) hMP = OGR_G_CreateGeometry( wkbMultiPoint ); for( j = 0; j < shape->numlines; j++ ) { if( shape->line[j].numpoints != 1 ) { msSetError(MS_MISCERR, "Failed on odd point geometry.", "msOGRWriteShape()"); return MS_FAILURE; } hGeom = OGR_G_CreateGeometry( wkbPoint ); if( bWant2DOutput ) { OGR_G_SetPoint_2D( hGeom, 0, shape->line[j].point[0].x, shape->line[j].point[0].y ); } else { OGR_G_SetPoint( hGeom, 0, shape->line[j].point[0].x, shape->line[j].point[0].y, #ifdef USE_POINT_Z_M shape->line[j].point[0].z #else 0.0 #endif ); } if( hMP != NULL ) { OGR_G_AddGeometryDirectly( hMP, hGeom ); } } if( hMP != NULL ) hGeom = hMP; } } /* -------------------------------------------------------------------- */ /* Transform line geometry. */ /* -------------------------------------------------------------------- */ else if( shape->type == MS_SHAPE_LINE ) { OGRGeometryH hML = NULL; int j; if( shape->numlines < 1 || shape->line[0].numpoints < 2 ) { msSetError(MS_MISCERR, "Failed on odd line geometry.", "msOGRWriteShape()"); return MS_FAILURE; } if( shape->numlines > 1 ) hML = OGR_G_CreateGeometry( wkbMultiLineString ); for( j = 0; j < shape->numlines; j++ ) { hGeom = OGR_G_CreateGeometry( wkbLineString ); msOGRSetPoints( hGeom, &(shape->line[j]), bWant2DOutput); if( hML != NULL ) { OGR_G_AddGeometryDirectly( hML, hGeom ); hGeom = hML; } } } /* -------------------------------------------------------------------- */ /* Transform polygon geometry. */ /* -------------------------------------------------------------------- */ else if( shape->type == MS_SHAPE_POLYGON ) { int iRing, iOuter; int *outer_flags; OGRGeometryH hMP; if( shape->numlines < 1 ) { msSetError(MS_MISCERR, "Failed on odd polygon geometry.", "msOGRWriteShape()"); return MS_FAILURE; } outer_flags = msGetOuterList( shape ); hMP = OGR_G_CreateGeometry( wkbMultiPolygon ); for( iOuter = 0; iOuter < shape->numlines; iOuter++ ) { int *inner_flags; OGRGeometryH hRing; if( !outer_flags[iOuter] ) continue; hGeom = OGR_G_CreateGeometry( wkbPolygon ); /* handle outer ring */ hRing = OGR_G_CreateGeometry( wkbLinearRing ); msOGRSetPoints( hRing, &(shape->line[iOuter]), bWant2DOutput); OGR_G_AddGeometryDirectly( hGeom, hRing ); /* handle inner rings (holes) */ inner_flags = msGetInnerList( shape, iOuter, outer_flags ); for( iRing = 0; iRing < shape->numlines; iRing++ ) { if( !inner_flags[iRing] ) continue; hRing = OGR_G_CreateGeometry( wkbLinearRing ); msOGRSetPoints( hRing, &(shape->line[iRing]), bWant2DOutput); OGR_G_AddGeometryDirectly( hGeom, hRing ); } free(inner_flags); OGR_G_AddGeometryDirectly( hMP, hGeom ); } free(outer_flags); if( OGR_G_GetGeometryCount( hMP ) == 1 ) { hGeom = OGR_G_Clone( OGR_G_GetGeometryRef( hMP, 0 ) ); OGR_G_DestroyGeometry( hMP ); } else { hGeom = hMP; } } /* -------------------------------------------------------------------- */ /* Consider trying to force the geometry to a new type if it */ /* doesn't match the layer. */ /* -------------------------------------------------------------------- */ #if defined(GDAL_VERSION_NUM) && (GDAL_VERSION_NUM >= 1800) if( hGeom != NULL ) { OGRwkbGeometryType eFlattenFeatureGType = wkbFlatten(OGR_G_GetGeometryType( hGeom )); if( eFlattenFeatureGType != eFlattenLayerGType ) { if( eFlattenLayerGType == wkbPolygon ) hGeom = OGR_G_ForceToPolygon( hGeom ); else if( eFlattenLayerGType == wkbMultiPolygon ) hGeom = OGR_G_ForceToMultiPolygon( hGeom ); else if( eFlattenLayerGType == wkbMultiPoint ) hGeom = OGR_G_ForceToMultiPoint( hGeom ); else if( eFlattenLayerGType == wkbMultiLineString ) hGeom = OGR_G_ForceToMultiLineString( hGeom ); } } #endif /* GDAL/OGR 1.8 or later */ /* -------------------------------------------------------------------- */ /* Consider flattening the geometry to 2D if we want 2D */ /* output. */ /* Note: this shouldn't be called in recent OGR versions where */ /* OGR_G_SetPoint_2D is properly honoured. */ /* -------------------------------------------------------------------- */ if( bWant2DOutput && hGeom != NULL ) { OGRwkbGeometryType eFeatureGType = OGR_G_GetGeometryType( hGeom ); if( eFeatureGType != wkbFlatten(eFeatureGType) ) OGR_G_FlattenTo2D( hGeom ); } /* -------------------------------------------------------------------- */ /* Create the feature, and attach the geometry. */ /* -------------------------------------------------------------------- */ hFeat = OGR_F_Create( hLayerDefn ); OGR_F_SetGeometryDirectly( hFeat, hGeom ); /* -------------------------------------------------------------------- */ /* Set attributes. */ /* -------------------------------------------------------------------- */ out_field = nFirstOGRFieldIndex; for( i = 0; i < item_list->numitems; i++ ) { gmlItemObj *item = item_list->items + i; if(pszFeatureid && !strcmp(pszFeatureid, item->name)) { char *endptr; long feature_id = strtol(shape->values[i],&endptr,10); if(endptr && *endptr==0) { /* only set the featureid if it is numeric */ OGR_F_SetFID(hFeat, feature_id); } } if( !item->visible ) continue; /* Avoid setting empty strings for numeric fields, so that OGR */ /* doesn't take them as 0. (#4633) */ if( shape->values[i][0] == '\0' ) { OGRFieldDefnH hFieldDefn = OGR_FD_GetFieldDefn(hLayerDefn, out_field); OGRFieldType eFieldType = OGR_Fld_GetType(hFieldDefn); if( eFieldType == OFTInteger || eFieldType == OFTReal #if GDAL_VERSION_MAJOR >= 2 || eFieldType == OFTInteger64 #endif ) { out_field++; continue; } } OGR_F_SetFieldString( hFeat, out_field++, shape->values[i] ); } /* -------------------------------------------------------------------- */ /* Write out and cleanup. */ /* -------------------------------------------------------------------- */ eErr = OGR_L_CreateFeature( hOGRLayer, hFeat ); OGR_F_Destroy( hFeat ); if( eErr != OGRERR_NONE ) { msSetError( MS_OGRERR, "Attempt to write feature failed (code=%d):\n%s", "msOGRWriteShape()", (int) eErr, CPLGetLastErrorMsg() ); } if( eErr == OGRERR_NONE ) return MS_SUCCESS; else return MS_FAILURE; } #if defined(GDAL_COMPUTE_VERSION) #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,0,0) /************************************************************************/ /* msOGRStdoutWriteFunction() */ /************************************************************************/ /* Used by /vsistdout/ */ static size_t msOGRStdoutWriteFunction(const void* ptr, size_t size, size_t nmemb, FILE* stream) { msIOContext *ioctx = (msIOContext*) stream; return msIO_contextWrite(ioctx, ptr, size * nmemb ) / size; } #endif #endif /************************************************************************/ /* msOGROutputGetAdditonalFiles() */ /* */ /* Collect additional files specified in */ /* wfs/ows_additional_files_in_output of WEB.METADATA and LAYER.METADATA */ /************************************************************************/ /* Result to be freed with CSLDestroy() */ static char** msOGROutputGetAdditonalFiles( mapObj *map ) { int i; hashTableObj* hSetAdditionalFiles; char** papszFiles = NULL; hSetAdditionalFiles = msCreateHashTable(); for( i = -1; i < map->numlayers; i++ ) { const char* value; if( i < 0 ) { value = msOWSLookupMetadata(&(map->web.metadata), "FO", "additional_files_in_output"); } else { layerObj *layer = GET_LAYER(map, i); if( !layer->resultcache || layer->resultcache->numresults == 0 ) continue; value = msOWSLookupMetadata(&(layer->metadata), "FO", "additional_files_in_output"); } if( value != NULL ) { char** papszList = CSLTokenizeString2( value, ",", CSLT_HONOURSTRINGS ); char** papszListIter = papszList; while( papszListIter && *papszListIter ) { const char* file = *papszListIter; VSIStatBufL sStat; if( strncmp(file, "http://", strlen("http://")) == 0 || strncmp(file, "https://", strlen("https://")) == 0 ) { /* Remote file ? We will use /vsicurl_streaming/ to read it */ if( msLookupHashTable(hSetAdditionalFiles, file) == NULL ) { msInsertHashTable(hSetAdditionalFiles, file, "YES"); papszFiles = CSLAddString(papszFiles, CPLSPrintf("/vsicurl_streaming/%s", file)); } } else { int nLen = (int)strlen(file); char filename[MS_MAXPATHLEN]; if( CPLIsFilenameRelative(file) ) { if( !map->shapepath ) msTryBuildPath(filename, map->mappath, file); else msTryBuildPath3(filename, map->mappath, map->shapepath, file); } else strlcpy(filename, file, MS_MAXPATHLEN); if( nLen > 2 && ( strcmp(file + nLen - 1, "/") == 0 || strcmp(file + nLen - 2, "/*") == 0 ) ) { *strrchr(filename, '/') = '\0'; } else if( nLen > 2 && ( strcmp(file + nLen - 1, "\\") == 0 || strcmp(file + nLen - 2, "\\*") == 0 ) ) { *strrchr(filename, '\\') = '\0'; } if( msLookupHashTable(hSetAdditionalFiles, filename) == NULL ) { msInsertHashTable(hSetAdditionalFiles, filename, "YES"); if( VSIStatL( filename, &sStat ) == 0 ) { if( VSI_ISDIR( sStat.st_mode ) ) { char** papszDirContent = msOGRRecursiveFileList(filename); papszFiles = msCSLConcatenate(papszFiles, papszDirContent); CSLDestroy(papszDirContent); } else { papszFiles = CSLAddString(papszFiles, filename); } } else { msDebug("File %s does not exist.\n", filename); } } } papszListIter ++; } CSLDestroy(papszList); } } msFreeHashTable(hSetAdditionalFiles); return papszFiles; } #endif /* def USE_OGR */ /************************************************************************/ /* msOGRWriteFromQuery() */ /************************************************************************/ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders ) { #ifndef USE_OGR msSetError(MS_OGRERR, "OGR support is not available.", "msOGRWriteFromQuery()"); return MS_FAILURE; #else /* -------------------------------------------------------------------- */ /* Variable declarations. */ /* -------------------------------------------------------------------- */ OGRSFDriverH hDriver; OGRDataSourceH hDS; const char *storage; const char *fo_filename; const char *form; char datasource_name[MS_MAXPATHLEN]; char base_dir[MS_MAXPATHLEN]; char *request_dir = NULL; char **ds_options = NULL; char **layer_options = NULL; char **file_list = NULL; int iLayer, i; int bDataSourceNameIsRequestDir = FALSE; int bUseFeatureId = MS_FALSE; /* -------------------------------------------------------------------- */ /* Fetch the output format driver. */ /* -------------------------------------------------------------------- */ msOGRInitialize(); hDriver = OGRGetDriverByName( format->driver+4 ); if( hDriver == NULL ) { msSetError( MS_MISCERR, "No OGR driver named `%s' available.", "msOGRWriteFromQuery()", format->driver+4 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Capture datasource and layer creation options. */ /* -------------------------------------------------------------------- */ for( i=0; i < format->numformatoptions; i++ ) { if( strncasecmp(format->formatoptions[i],"LCO:",4) == 0 ) layer_options = CSLAddString( layer_options, format->formatoptions[i] + 4 ); if( strncasecmp(format->formatoptions[i],"DSCO:",5) == 0 ) ds_options = CSLAddString( ds_options, format->formatoptions[i] + 5 ); } if(!strcasecmp("true",msGetOutputFormatOption(format,"USE_FEATUREID","false"))) { bUseFeatureId = MS_TRUE; } /* ==================================================================== */ /* Determine the output datasource name to use. */ /* ==================================================================== */ storage = msGetOutputFormatOption( format, "STORAGE", "filesystem" ); if( EQUAL(storage,"stream") && !msIO_isStdContext() ) { #if defined(GDAL_COMPUTE_VERSION) #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,0,0) msIOContext *ioctx = msIO_getHandler (stdout); if( ioctx != NULL ) VSIStdoutSetRedirection( msOGRStdoutWriteFunction, (FILE*)ioctx ); else #endif #endif /* bug #4858, streaming output won't work if standard output has been * redirected, we switch to memory output in this case */ storage = "memory"; } /* -------------------------------------------------------------------- */ /* Where are we putting stuff? */ /* -------------------------------------------------------------------- */ if( EQUAL(storage,"filesystem") ) { base_dir[0] = '\0' ; } else if( EQUAL(storage,"memory") ) { strcpy( base_dir, "/vsimem/ogr_out/" ); } else if( EQUAL(storage,"stream") ) { /* handled later */ } else { msSetError( MS_MISCERR, "STORAGE=%s value not supported.", "msOGRWriteFromQuery()", storage ); CSLDestroy(layer_options); CSLDestroy(ds_options); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Create a subdirectory to handle this request. */ /* -------------------------------------------------------------------- */ if( !EQUAL(storage,"stream") ) { const char* dir_to_create; if (strlen(base_dir) > 0) request_dir = msTmpFile(map, NULL, base_dir, "" ); else request_dir = msTmpFile(map, NULL, NULL, "" ); if( request_dir[strlen(request_dir)-1] == '.' ) request_dir[strlen(request_dir)-1] = '\0'; dir_to_create = request_dir; /* Workaround issue in GDAL versions released at this time : * GDAL issue fixed per https://trac.osgeo.org/gdal/ticket/6991 */ if( EQUAL(storage,"memory") && EQUAL(format->driver+4, "ESRI Shapefile") ) { dir_to_create = base_dir; } if( VSIMkdir( dir_to_create, 0777 ) != 0 ) { msSetError( MS_MISCERR, "Attempt to create directory '%s' failed.", "msOGRWriteFromQuery()", dir_to_create ); msFree(request_dir); CSLDestroy(layer_options); CSLDestroy(ds_options); return MS_FAILURE; } } /* else handled later */ /* -------------------------------------------------------------------- */ /* Setup the full datasource name. */ /* -------------------------------------------------------------------- */ #if !defined(CPL_ZIP_API_OFFERED) form = msGetOutputFormatOption( format, "FORM", "multipart" ); #else form = msGetOutputFormatOption( format, "FORM", "zip" ); #endif if( EQUAL(form,"zip") ) fo_filename = msGetOutputFormatOption( format, "FILENAME", "result.zip" ); else fo_filename = msGetOutputFormatOption( format, "FILENAME", "result.dat" ); /* Validate that the filename does not contain any directory */ /* information, which might lead to removal of unwanted files. (#4086) */ if( strchr(fo_filename, '/') != NULL || strchr(fo_filename, ':') != NULL || strchr(fo_filename, '\\') != NULL ) { msSetError( MS_MISCERR, "Invalid value for FILENAME option. " "It must not contain any directory information.", "msOGRWriteFromQuery()" ); msFree(request_dir); CSLDestroy(layer_options); CSLDestroy(ds_options); return MS_FAILURE; } if( !EQUAL(storage,"stream") ) { msBuildPath( datasource_name, request_dir, fo_filename ); if( EQUAL(form,"zip") ) { /* if generating a zip file, remove the zip extension for the internal */ /* filename */ if( EQUAL(CPLGetExtension(datasource_name), "zip") ) { *strrchr(datasource_name, '.') = '\0'; } /* and add .dat extension if user didn't provide another extension */ if( EQUAL(CPLGetExtension(datasource_name), "") ) { strcat(datasource_name, ".dat"); } } /* Shapefile and MapInfo driver only properly work with multiple layers */ /* if the output dataset name is a directory */ if( EQUAL(format->driver+4, "ESRI Shapefile") || EQUAL(format->driver+4, "MapInfo File") ) { bDataSourceNameIsRequestDir = TRUE; strcpy(datasource_name, request_dir); } } else strcpy( datasource_name, "/vsistdout/" ); msFree( request_dir ); request_dir = NULL; /* -------------------------------------------------------------------- */ /* Emit content type headers for stream output now. */ /* -------------------------------------------------------------------- */ if( EQUAL(storage,"stream") ) { if( sendheaders && format->mimetype ) { msIO_setHeader("Content-Type","%s",format->mimetype); msIO_sendHeaders(); } else msIO_fprintf( stdout, "%c", 10 ); } /* ==================================================================== */ /* Create the datasource. */ /* ==================================================================== */ hDS = OGR_Dr_CreateDataSource( hDriver, datasource_name, ds_options ); CSLDestroy( ds_options ); if( hDS == NULL ) { msOGRCleanupDS( datasource_name ); msSetError( MS_MISCERR, "OGR CreateDataSource failed for '%s' with driver '%s'.", "msOGRWriteFromQuery()", datasource_name, format->driver+4 ); CSLDestroy(layer_options); return MS_FAILURE; } /* ==================================================================== */ /* Process each layer with a resultset. */ /* ==================================================================== */ for( iLayer = 0; iLayer < map->numlayers; iLayer++ ) { int status; layerObj *layer = GET_LAYER(map, iLayer); shapeObj resultshape; OGRLayerH hOGRLayer; OGRwkbGeometryType eGeomType; OGRSpatialReferenceH srs = NULL; gmlItemListObj *item_list = NULL; const char *value; char *pszWKT; int nFirstOGRFieldIndex = -1; const char *pszFeatureid = NULL; if( !layer->resultcache ) continue; /* -------------------------------------------------------------------- */ /* Will we need to reproject? */ /* -------------------------------------------------------------------- */ if(layer->transform == MS_TRUE) layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection)); /* -------------------------------------------------------------------- */ /* Establish the geometry type to use for the created layer. */ /* First we consult the wfs_geomtype field and fallback to */ /* deriving something from the type of the mapserver layer. */ /* -------------------------------------------------------------------- */ value = msOWSLookupMetadata(&(layer->metadata), "FOG", "geomtype"); if( value == NULL ) { if( layer->type == MS_LAYER_POINT ) value = "Point"; else if( layer->type == MS_LAYER_LINE ) value = "LineString"; else if( layer->type == MS_LAYER_POLYGON ) value = "Polygon"; else value = "Geometry"; } if(bUseFeatureId) pszFeatureid = msOWSLookupMetadata(&(layer->metadata), "FOG", "featureid"); if( strcasecmp(value,"Point") == 0 ) eGeomType = wkbPoint; else if( strcasecmp(value,"LineString") == 0 ) eGeomType = wkbLineString; else if( strcasecmp(value,"Polygon") == 0 ) eGeomType = wkbPolygon; else if( strcasecmp(value,"MultiPoint") == 0 ) eGeomType = wkbMultiPoint; else if( strcasecmp(value,"MultiLineString") == 0 ) eGeomType = wkbMultiLineString; else if( strcasecmp(value,"MultiPolygon") == 0 ) eGeomType = wkbMultiPolygon; else if( strcasecmp(value,"GeometryCollection") == 0 ) eGeomType = wkbGeometryCollection; else if( strcasecmp(value,"Point25D") == 0 ) eGeomType = wkbPoint25D; else if( strcasecmp(value,"LineString25D") == 0 ) eGeomType = wkbLineString25D; else if( strcasecmp(value,"Polygon25D") == 0 ) eGeomType = wkbPolygon25D; else if( strcasecmp(value,"MultiPoint25D") == 0 ) eGeomType = wkbMultiPoint25D; else if( strcasecmp(value,"MultiLineString25D") == 0 ) eGeomType = wkbMultiLineString25D; else if( strcasecmp(value,"MultiPolygon25D") == 0 ) eGeomType = wkbMultiPolygon25D; else if( strcasecmp(value,"GeometryCollection25D") == 0 ) eGeomType = wkbGeometryCollection25D; else if( strcasecmp(value,"Unknown") == 0 || strcasecmp(value,"Geometry") == 0 ) eGeomType = wkbUnknown; else if( strcasecmp(value,"None") == 0 ) eGeomType = wkbNone; else eGeomType = wkbUnknown; /* -------------------------------------------------------------------- */ /* Create a spatial reference. */ /* -------------------------------------------------------------------- */ pszWKT = msProjectionObj2OGCWKT( &(map->projection) ); if( pszWKT != NULL ) { srs = OSRNewSpatialReference( pszWKT ); msFree( pszWKT ); } /* -------------------------------------------------------------------- */ /* Create the corresponding OGR Layer. */ /* -------------------------------------------------------------------- */ hOGRLayer = OGR_DS_CreateLayer( hDS, layer->name, srs, eGeomType, layer_options ); if( hOGRLayer == NULL ) { OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); msSetError( MS_MISCERR, "OGR OGR_DS_CreateLayer failed for layer '%s' with driver '%s'.", "msOGRWriteFromQuery()", layer->name, format->driver+4 ); CSLDestroy(layer_options); return MS_FAILURE; } if( srs != NULL ) OSRRelease( srs ); /* -------------------------------------------------------------------- */ /* Create appropriate attributes on this layer. */ /* -------------------------------------------------------------------- */ item_list = msGMLGetItems( layer, "G" ); assert( item_list->numitems == layer->numitems ); for( i = 0; i < layer->numitems; i++ ) { OGRFieldDefnH hFldDefn; OGRErr eErr; const char *name; gmlItemObj *item = item_list->items + i; OGRFieldType eType; if( !item->visible ) continue; if( item->alias ) name = item->alias; else name = item->name; if( item->type == NULL ) eType = OFTString; else if( EQUAL(item->type,"Integer") ) eType = OFTInteger; else if( EQUAL(item->type,"Long") ) #if GDAL_VERSION_MAJOR >= 2 eType = OFTInteger64; #else eType = OFTReal; #endif else if( EQUAL(item->type,"Real") ) eType = OFTReal; else if( EQUAL(item->type,"Character") ) eType = OFTString; else if( EQUAL(item->type,"Date") ) eType = OFTDateTime; else if( EQUAL(item->type,"Boolean") ) eType = OFTInteger; else eType = OFTString; hFldDefn = OGR_Fld_Create( name, eType ); if( item->width != 0 ) OGR_Fld_SetWidth( hFldDefn, item->width ); if( item->precision != 0 ) OGR_Fld_SetPrecision( hFldDefn, item->precision ); eErr = OGR_L_CreateField( hOGRLayer, hFldDefn, TRUE ); OGR_Fld_Destroy( hFldDefn ); if( eErr != OGRERR_NONE ) { msSetError( MS_OGRERR, "Failed to create field '%s' in output feature schema:\n%s", "msOGRWriteFromQuery()", layer->items[i], CPLGetLastErrorMsg() ); OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); msGMLFreeItems(item_list); CSLDestroy(layer_options); return MS_FAILURE; } /* The index of the first field we create is not necessarily 0 */ if( nFirstOGRFieldIndex < 0 ) nFirstOGRFieldIndex = OGR_FD_GetFieldCount( OGR_L_GetLayerDefn( hOGRLayer ) ) - 1; } /* -------------------------------------------------------------------- */ /* Setup joins if needed. This is likely untested. */ /* -------------------------------------------------------------------- */ if(layer->numjoins > 0) { int j; for(j=0; jnumjoins; j++) { status = msJoinConnect(layer, &(layer->joins[j])); if(status != MS_SUCCESS) { OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); msGMLFreeItems(item_list); CSLDestroy(layer_options); return status; } } } msInitShape( &resultshape ); /* -------------------------------------------------------------------- */ /* Loop over all the shapes in the resultcache. */ /* -------------------------------------------------------------------- */ for(i=0; i < layer->resultcache->numresults; i++) { msFreeShape(&resultshape); /* init too */ /* ** Read the shape. */ if( layer->resultcache->results[i].shape ) { /* msDebug("Using cached shape %ld\n", layer->resultcache->results[i].shapeindex); */ msCopyShape(layer->resultcache->results[i].shape, &resultshape); } else { status = msLayerGetShape(layer, &resultshape, &(layer->resultcache->results[i])); if(status != MS_SUCCESS) { OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); msGMLFreeItems(item_list); msFreeShape(&resultshape); CSLDestroy(layer_options); return status; } } /* ** Perform classification, and some annotation related magic. */ resultshape.classindex = msShapeGetClass(layer, map, &resultshape, NULL, -1); if( resultshape.classindex >= 0 && (layer->class[resultshape.classindex]->text.string || layer->labelitem) && layer->class[resultshape.classindex]->numlabels > 0 && layer->class[resultshape.classindex]->labels[0]->size != -1 ) { resultshape.text = msShapeGetLabelAnnotation(layer,&resultshape,layer->class[resultshape.classindex]->labels[0]); } /* ** prepare any necessary JOINs here (one-to-one only) */ if( layer->numjoins > 0) { int j; for(j=0; j < layer->numjoins; j++) { if(layer->joins[j].type == MS_JOIN_ONE_TO_ONE) { msJoinPrepare(&(layer->joins[j]), &resultshape); msJoinNext(&(layer->joins[j])); /* fetch the first row */ } } } if( layer->project ) { status = msProjectShape(&layer->projection, &layer->map->projection, &resultshape); } /* ** Write out the feature to OGR. */ if( status == MS_SUCCESS ) status = msOGRWriteShape( layer, hOGRLayer, &resultshape, item_list, nFirstOGRFieldIndex, pszFeatureid ); if(status != MS_SUCCESS) { OGR_DS_Destroy( hDS ); msOGRCleanupDS( datasource_name ); msGMLFreeItems(item_list); msFreeShape(&resultshape); CSLDestroy(layer_options); return status; } } msGMLFreeItems(item_list); msFreeShape(&resultshape); /* init too */ } /* -------------------------------------------------------------------- */ /* Close the datasource. */ /* -------------------------------------------------------------------- */ OGR_DS_Destroy( hDS ); CSLDestroy( layer_options ); /* -------------------------------------------------------------------- */ /* Get list of resulting files. */ /* -------------------------------------------------------------------- */ if( EQUAL(form,"simple") ) { file_list = CSLAddString( NULL, datasource_name ); } else { char datasource_path[MS_MAXPATHLEN]; if( bDataSourceNameIsRequestDir ) file_list = msOGRRecursiveFileList( datasource_name ); else { strncpy( datasource_path, CPLGetPath( datasource_name ), MS_MAXPATHLEN-1 ); file_list = msOGRRecursiveFileList( datasource_path ); } } /* -------------------------------------------------------------------- */ /* If our "storage" is stream then the output has already been */ /* sent back to the client and we don't need to copy it now. */ /* -------------------------------------------------------------------- */ if( EQUAL(storage,"stream") ) { /* already done */ } /* -------------------------------------------------------------------- */ /* Handle case of simple file written to stdout. */ /* -------------------------------------------------------------------- */ else if( EQUAL(form,"simple") ) { char buffer[1024]; int bytes_read; FILE *fp; const char *jsonp; jsonp = msGetOutputFormatOption( format, "JSONP", NULL ); if( sendheaders ) { if( !jsonp ) msIO_setHeader("Content-Disposition","attachment; filename=%s", CPLGetFilename( file_list[0] ) ); if( format->mimetype ) msIO_setHeader("Content-Type","%s",format->mimetype); msIO_sendHeaders(); } else msIO_fprintf( stdout, "%c", 10 ); fp = VSIFOpenL( file_list[0], "r" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open result file '%s'.", "msOGRWriteFromQuery()", file_list[0] ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } if( jsonp != NULL ) msIO_fprintf( stdout, "%s(", jsonp ); while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fp )) > 0 ) msIO_fwrite( buffer, 1, bytes_read, stdout ); VSIFCloseL( fp ); if (jsonp != NULL) msIO_fprintf( stdout, ");\n" ); } /* -------------------------------------------------------------------- */ /* Handle the case of a multi-part result. */ /* -------------------------------------------------------------------- */ else if( EQUAL(form,"multipart") ) { char **papszAdditionalFiles; static const char *boundary = "xxOGRBoundaryxx"; msIO_setHeader("Content-Type","multipart/mixed; boundary=%s",boundary); msIO_sendHeaders(); msIO_fprintf(stdout,"--%s\r\n",boundary ); papszAdditionalFiles = msOGROutputGetAdditonalFiles(map); file_list = msCSLConcatenate(file_list, papszAdditionalFiles); CSLDestroy(papszAdditionalFiles); for( i = 0; file_list != NULL && file_list[i] != NULL; i++ ) { FILE *fp; int bytes_read; char buffer[1024]; if( sendheaders ) msIO_fprintf( stdout, "Content-Disposition: attachment; filename=%s\r\n" "Content-Type: application/binary\r\n" "Content-Transfer-Encoding: binary\r\n\r\n", CPLGetFilename( file_list[i] )); fp = VSIFOpenL( file_list[i], "r" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open result file '%s'.", "msOGRWriteFromQuery()", file_list[0] ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fp )) > 0 ) msIO_fwrite( buffer, 1, bytes_read, stdout ); VSIFCloseL( fp ); if (file_list[i+1] == NULL) msIO_fprintf( stdout, "\r\n--%s--\r\n", boundary ); else msIO_fprintf( stdout, "\r\n--%s\r\n", boundary ); } } /* -------------------------------------------------------------------- */ /* Handle the case of a zip file result. */ /* -------------------------------------------------------------------- */ else if( EQUAL(form,"zip") ) { #if !defined(CPL_ZIP_API_OFFERED) msSetError( MS_MISCERR, "FORM=zip selected, but CPL ZIP support unavailable, perhaps you need to upgrade to GDAL/OGR 1.8?", "msOGRWriteFromQuery()"); msOGRCleanupDS( datasource_name ); return MS_FAILURE; #else FILE *fp; char *zip_filename = msTmpFile(map, NULL, "/vsimem/ogrzip/", "zip" ); void *hZip; int bytes_read; char buffer[1024]; char **papszAdditionalFiles; hZip = CPLCreateZip( zip_filename, NULL ); papszAdditionalFiles = msOGROutputGetAdditonalFiles(map); file_list = msCSLConcatenate(file_list, papszAdditionalFiles); CSLDestroy(papszAdditionalFiles); for( i = 0; file_list != NULL && file_list[i] != NULL; i++ ) { CPLCreateFileInZip( hZip, CPLGetFilename(file_list[i]), NULL ); fp = VSIFOpenL( file_list[i], "r" ); if( fp == NULL ) { CPLCloseZip( hZip ); msSetError( MS_MISCERR, "Failed to open result file '%s'.", "msOGRWriteFromQuery()", file_list[0] ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fp )) > 0 ) { CPLWriteFileInZip( hZip, buffer, bytes_read ); } VSIFCloseL( fp ); CPLCloseFileInZip( hZip ); } CPLCloseZip( hZip ); if( sendheaders ) { const char* zip_filename = fo_filename; /* Make sure the filename is ended by .zip */ if( !EQUAL(CPLGetExtension(zip_filename), "zip") && !EQUAL(CPLGetExtension(zip_filename), "kmz") ) zip_filename = CPLFormFilename(NULL, fo_filename, "zip"); msIO_setHeader("Content-Disposition","attachment; filename=%s",zip_filename); msIO_setHeader("Content-Type","application/zip"); msIO_sendHeaders(); } fp = VSIFOpenL( zip_filename, "r" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open zip file '%s'.", "msOGRWriteFromQuery()", file_list[0] ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } while( (bytes_read = VSIFReadL( buffer, 1, sizeof(buffer), fp )) > 0 ) msIO_fwrite( buffer, 1, bytes_read, stdout ); VSIFCloseL( fp ); msFree( zip_filename ); #endif /* defined(CPL_ZIP_API_OFFERED) */ } /* -------------------------------------------------------------------- */ /* Handle illegal form value. */ /* -------------------------------------------------------------------- */ else { msSetError( MS_MISCERR, "Unsupported FORM=%s value.", "msOGRWriteFromQuery()", form ); msOGRCleanupDS( datasource_name ); return MS_FAILURE; } msOGRCleanupDS( datasource_name ); CSLDestroy( file_list ); return MS_SUCCESS; #endif /* def USE_OGR */ } /************************************************************************/ /* msPopulateRenderVTableOGR() */ /************************************************************************/ int msPopulateRendererVTableOGR( rendererVTableObj *renderer ) { #ifdef USE_OGR /* we aren't really a normal renderer so we leave everything default */ return MS_SUCCESS; #else msSetError(MS_OGRERR, "OGR Driver requested but is not built in", "msPopulateRendererVTableOGR()"); return MS_FAILURE; #endif } mapserver-7.4.3/maporaclespatial.c000066400000000000000000004532661357574274700172630ustar00rootroot00000000000000/****************************************************************************** * Project: MapServer * Purpose: Native access to Oracle Spatial (SDO) data. * Author: Fernando Simon (fsimon@univali.br) * Rodrigo Becke Cabral * Adriana Gomes Alves * * Notes: Developed under several funding agreements: * * 1) n.45/00 between CTTMAR/UNIVALI (www.cttmar.univali.br) * and CEPSUL/IBAMA (www.ibama.gov.br) * * 2) CNPq (www.cnpq.br) under process 401263.03-7 * * 3) FUNCITEC (www.funcitec.rct-sc.br) under process FCTP1523-031 * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "maptime.h" #include "mapows.h" #include #if defined(USE_ORACLESPATIAL) || defined(USE_ORACLE_PLUGIN) #include #include #define ARRAY_SIZE 1024 #define QUERY_SIZE 1 #define TEXT_SIZE 4000 /* ticket #2260 */ #define TYPE_OWNER "MDSYS" #define SDO_GEOMETRY TYPE_OWNER".SDO_GEOMETRY" #define SDO_ORDINATE_ARRAY TYPE_OWNER".SDO_ORDINATE_ARRAY" #define SDO_GEOMETRY_LEN strlen( SDO_GEOMETRY ) #define FUNCTION_FILTER 1 #define FUNCTION_RELATE 2 #define FUNCTION_GEOMRELATE 3 #define FUNCTION_NONE 4 #define VERSION_8i 1 #define VERSION_9i 2 #define VERSION_10g 3 #define TOLERANCE 0.001 #define NULLERRCODE 1405 #define TABLE_NAME_SIZE 2000 typedef struct { OCINumber x; OCINumber y; OCINumber z; } SDOPointObj; typedef struct { OCINumber gtype; OCINumber srid; SDOPointObj point; OCIArray *elem_info; OCIArray *ordinates; } SDOGeometryObj; typedef struct { OCIInd _atomic; OCIInd x; OCIInd y; OCIInd z; } SDOPointInd; typedef struct { OCIInd _atomic; OCIInd gtype; OCIInd srid; SDOPointInd point; OCIInd elem_info; OCIInd ordinates; } SDOGeometryInd; typedef text item_text[TEXT_SIZE]; typedef item_text item_text_array[ARRAY_SIZE]; typedef item_text item_text_array_query[QUERY_SIZE]; typedef ub2 query_dtype[ARRAY_SIZE]; typedef struct { /*Oracle handlers (global to connection)*/ OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; int last_oci_status; text last_oci_error[2048]; /* This references counter is to avoid the cache freed if there are other layers that could use it */ int ref_count; } msOracleSpatialHandler; typedef struct { /* Oracle data handlers (global to connection) */ OCIDescribe *dschp; OCIType *tdo; } msOracleSpatialDataHandler; typedef struct { OCIStmt *stmthp; /* fetch data buffer */ ub4 rows_count; /* total number of rows (so far) within cursor */ ub4 row_num; /* current row index within cursor results */ ub4 rows_fetched; /* total number of rows fetched into our buffer */ ub4 row; /* current row index within our buffer */ item_text_array *items; /* items buffer */ item_text_array_query *items_query; /* items buffer */ SDOGeometryObj *obj[ARRAY_SIZE]; /* spatial object buffer */ SDOGeometryInd *ind[ARRAY_SIZE]; /* object indicator (null) buffer */ int uniqueidindex; /*allows to keep whic attribute id index is used as unique id*/ } msOracleSpatialStatement; typedef struct { /* oracle handlers */ msOracleSpatialHandler *orahandlers; /* oracle data handlers */ msOracleSpatialDataHandler *oradatahandlers; msOracleSpatialStatement *orastmt; /* Following items are setup by WhichShapes * used by NextShape, ResultGetShape * disposed by CloseLayer (if set) */ msOracleSpatialStatement *orastmt2; /* Driver handling of pagination, enabled by default */ int paging; } msOracleSpatialLayerInfo; static OCIType *ordinates_tdo = NULL; static OCIArray *ordinates; /* local prototypes */ static int TRY( msOracleSpatialHandler *hand, sword status ); static int ERROR( char *routine, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ); static void msSplitLogin( char *connection, mapObj *map, char **username, char **password, char **dblink ); static int msSplitData( char *data, char **geometry_column_name, char **table_name, char **unique, char **srid, char **indexfield, int *function, int * version); static void msOCICloseConnection( void *layerinfo ); static msOracleSpatialHandler *msOCISetHandlers( char *username, char *password, char *dblink ); static int msOCISetDataHandlers( msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ); static void msOCICloseDataHandlers ( msOracleSpatialDataHandler *dthand ); static void msOCICloseHandlers( msOracleSpatialHandler *hand ); static void msOCIClearLayerInfo( msOracleSpatialLayerInfo *layerinfo ); static int msOCIOpenStatement( msOracleSpatialHandler *hand, msOracleSpatialStatement *sthand ); static void msOCIFinishStatement( msOracleSpatialStatement *sthand ); static int msOCIGet2DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIGet3DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIGet4DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ); static int msOCIConvertCircle( pointObj *pt ); static void osFilteritem(layerObj *layer, int function, char *query_str, size_t size, int mode); static void osAggrGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name); static void osConvexHullGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name); static void osGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *index_column_name, char *srid, rectObj rect); static void osNoGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *index_column_name, char *srid, rectObj rect); static double osCalculateArcRadius(pointObj *pnt); static void osCalculateArc(pointObj *pnt, int data3d, int data4d, double area, double radius, double npoints, int side, lineObj arcline, shapeObj *shape); static void osGenerateArc(shapeObj *shape, lineObj arcline, lineObj points, int i, int n, int data3d, int data4d); static void osShapeBounds ( shapeObj *shp ); static void osCloneShape(shapeObj *shape, shapeObj *newshape, int data3d, int data4d); static void osPointCluster(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int interpretation, int data3d, int data4d); static void osPoint(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osClosedPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int elem_type, int data3d, int data4d); static void osRectangle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osCircle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d); static void osArcPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj arcpoints,int elem_type,int data3d, int data4d); static int osGetOrdinates(msOracleSpatialDataHandler *dthand, msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, SDOGeometryInd *ind); static int osCheck2DGtype(int pIntGtype); static int osCheck3DGtype(int pIntGtype); static int osCheck4DGtype(int pIntGtype); /****************************************************************************** * Local Helper Functions * ******************************************************************************/ /* if an error ocurred call msSetError, sets last_oci_status to MS_FAILURE and return 0; * otherwise returns 1 */ static int TRY( msOracleSpatialHandler *hand, sword status ) { sb4 errcode = 0; if (hand->last_oci_status == MS_FAILURE) return 0; /* error from previous call */ switch (status) { case OCI_SUCCESS_WITH_INFO: case OCI_ERROR: OCIErrorGet((dvoid *)hand->errhp, (ub4)1, (text *)NULL, &errcode, hand->last_oci_error, (ub4)sizeof(hand->last_oci_error), OCI_HTYPE_ERROR ); if (errcode == NULLERRCODE) { hand->last_oci_error[0] = (text)'\0'; return 1; } hand->last_oci_error[sizeof(hand->last_oci_error)-1] = 0; /* terminate string!? */ break; case OCI_NEED_DATA: strlcpy( (char *)hand->last_oci_error, "OCI_NEED_DATA", sizeof(hand->last_oci_error)); break; case OCI_INVALID_HANDLE: strlcpy( (char *)hand->last_oci_error, "OCI_INVALID_HANDLE", sizeof(hand->last_oci_error)); break; case OCI_STILL_EXECUTING: ((char*)hand->last_oci_error)[sizeof(hand->last_oci_error)-1] = 0; break; case OCI_CONTINUE: strlcpy( (char *)hand->last_oci_error, "OCI_CONTINUE", sizeof(hand->last_oci_error)); break; default: return 1; /* no error */ } /* if I got here, there was an error */ hand->last_oci_status = MS_FAILURE; return 0; /* error! */ } OCIType *get_tdo(char *typename, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ) { OCIParam *paramp = NULL; OCIRef *type_ref = NULL; OCIType *tdoe = NULL; int success = 0; success = TRY( hand, OCIDescribeAny(hand->svchp, hand->errhp, (text *)typename, (ub4)strlen((char *)typename), OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TYPE, dthand->dschp)) &&TRY( hand, OCIAttrGet((dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (dvoid *)¶mp, (ub4 *)0, (ub4)OCI_ATTR_PARAM, hand->errhp)) &&TRY( hand, OCIAttrGet((dvoid *)paramp, (ub4)OCI_DTYPE_PARAM, (dvoid *)&type_ref, (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, hand->errhp)) &&TRY( hand, OCIObjectPin(hand->envhp, hand->errhp, type_ref, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&tdoe)); if (success) return tdoe; /* if failure, return NULL*/ return NULL; } /* check last_oci_status for MS_FAILURE (set by TRY()) if an error ocurred return 1; * otherwise, returns 0 */ static int ERROR( char *routine, msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand ) { if (hand->last_oci_status == MS_FAILURE) { /* there was an error */ msSetError( MS_ORACLESPATIALERR, "OracleSpatial server returned an error, check logs for more details", routine ); msDebug("OracleSpatial server returned an error in funtion (%s): %s.\n", routine, (char*)hand->last_oci_error ); /* reset error flag */ hand->last_oci_status = MS_SUCCESS; return 1; /* error processed */ } else return 0; /* no error */ } /* break layer->connection (username/password@dblink) into username, password and dblink */ static void msSplitLogin( char *connection, mapObj *map, char **username, char **password, char **dblink ) { char *src, *tgt, *conn_decrypted; size_t buffer_size = 0; /* bad 'connection' */ if (connection == NULL) return; buffer_size = strlen(connection)+1; *username = (char*)malloc(buffer_size); *password = (char*)malloc(buffer_size); *dblink = (char*)malloc(buffer_size); /* clearup */ **username = **password = **dblink = 0; /* Decrypt any encrypted token */ conn_decrypted = msDecryptStringTokens(map, connection); if (conn_decrypted == NULL) return; /* ok, split connection */ for( tgt=*username, src=conn_decrypted; *src; src++, tgt++ ) if (*src=='/' || *src=='@') break; else *tgt = *src; *tgt = 0; if (*src == '/') { for( tgt=*password, ++src; *src; src++, tgt++ ) if (*src == '@') break; else *tgt = *src; *tgt = 0; } if (*src == '@') { strlcpy( *dblink, ++src, buffer_size); } msFree(conn_decrypted); } /* break layer->data into geometry_column_name, table_name and srid */ static int msSplitData( char *data, char **geometry_column_name, char **table_name, char **unique, char **srid, char **indexfield, int *function, int *version ) { char *tok_from = "from"; char *tok_using = "using"; char *tok_unique = "unique"; char *tok_srid = "srid"; char *tok_indexfield="indexfield"; char *tok_version = "version"; char data_version[4] = ""; char tok_function[11] = ""; int parenthesis, i; char *src = data, *tgt; int table_name_size = TABLE_NAME_SIZE; size_t buffer_size = 0; /* bad 'data' */ if (data == NULL) return 0; buffer_size = strlen(data)+1; *geometry_column_name = (char*)malloc(buffer_size); *unique = (char*)malloc(buffer_size); *srid = (char*)malloc(buffer_size); *indexfield=(char*)malloc(buffer_size); /* clearup */ **geometry_column_name = **table_name = 0; /* parsing 'geometry_column_name' */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=*geometry_column_name; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; /* parsing 'from' */ for( ; *src && isspace( *src ); src++ ) ; /* skip blanks */ for( ; *src && *tok_from && tolower(*src)==*tok_from; src++, tok_from++ ); if (*tok_from != '\0') return 0; /* parsing 'table_name' or '(SELECT stmt)' */ i = 0; for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=*table_name, parenthesis=0; *src; src++, tgt++, ++i ) { if (*src == '(') parenthesis++; else if (*src == ')') parenthesis--; else if (parenthesis==0 && isspace( *src )) break; /* stop on spaces */ /* double the size of the table_name array if necessary */ if (i == table_name_size) { size_t tgt_offset = tgt - *table_name; table_name_size *= 2; *table_name = (char *) realloc(*table_name,sizeof(char *) * table_name_size); tgt = *table_name + tgt_offset; } *tgt = *src; } *tgt = 0; strlcpy( *unique, "", buffer_size); strlcpy( *srid, "NULL", buffer_size); strlcpy( *indexfield, "", buffer_size); *function = -1; *version = -1; /* parsing 'unique' */ for( ; *src && isspace( *src ); src++ ) ; /* skip blanks */ if (*src != '\0') { /* parse 'using' */ for( ; *src && *tok_using && tolower(*src)==*tok_using; src++, tok_using++ ); if (*tok_using != '\0') return 0; /* parsing 'unique' */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( ; *src && *tok_unique && tolower(*src)==*tok_unique; src++, tok_unique++ ); if (*tok_unique == '\0') { for( ; *src && isspace( *src ); src++ ); /* skip blanks */ if (*src == '\0') return 0; for( tgt=*unique; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; if (*tok_unique != '\0') return 0; } /* parsing 'srid' */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( ; *src && *tok_srid && tolower(*src)==*tok_srid; src++, tok_srid++ ); if (*tok_srid == '\0') { for( ; *src && isspace( *src ); src++ ); /* skip blanks */ if (*src == '\0') return 0; for( tgt=*srid; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; if (*tok_srid != '\0') return 0; } /* parsing 'indexfield' */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( ; *src && *tok_indexfield && tolower(*src)==*tok_indexfield; src++, tok_indexfield++ ); if (*tok_indexfield == '\0') { for( ; *src && isspace( *src ); src++ ); /* skip blanks */ if (*src == '\0') return 0; for( tgt=*indexfield; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; if (*tok_indexfield != '\0') return 0; } /*parsing function/version */ for( ; *src && isspace( *src ); src++ ); if (*src != '\0') { for( tgt=tok_function; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; } /*Upcase conversion for the FUNCTION/VERSION token*/ for (i=0; tok_function[i] != '\0'; i++) tok_function[i] = toupper(tok_function[i]); if (strcmp(tok_function, "VERSION")) { if (!strcmp(tok_function, "FILTER") || !strcmp(tok_function, "")) *function = FUNCTION_FILTER; else if(!strcmp(tok_function, "RELATE")) *function = FUNCTION_RELATE; else if (!strcmp(tok_function,"GEOMRELATE")) *function = FUNCTION_GEOMRELATE; else if (!strcmp(tok_function,"NONE")) *function = FUNCTION_NONE; else { *function = -1; return 0; } /*parsing VERSION token when user defined one function*/ for( ; *src && isspace( *src ); src++ ); for( ; *src && *tok_version && tolower(*src)==*tok_version; src++, tok_version++ ); } else { for(tgt = "VERSION"; *tgt && *tok_version && toupper(*tgt)==toupper(*tok_version); tgt++, tok_version++ ); *function = FUNCTION_FILTER; } /*parsing version*/ if (*tok_version == '\0') { for( ; *src && isspace( *src ); src++ ); /* skip blanks */ for( tgt=data_version; *src; src++, tgt++ ) if (isspace( *src )) break; else *tgt = *src; *tgt = 0; for (i=0; data_version[i] != '\0'; i++) data_version[i] = tolower(data_version[i]); if (!strcmp(data_version, "8i")) *version = VERSION_8i; else if(!strcmp(data_version, "9i")) *version = VERSION_9i; else if (!strcmp(data_version, "10g")) *version = VERSION_10g; else return 0; } } /* finish parsing */ for( ; *src && isspace( *src ); src++ ); /* skip blanks */ return (*src == '\0'); } /****************************************************************************** * OCI Helper Functions * ******************************************************************************/ /* create statement handle from database connection */ static int msOCIOpenStatement( msOracleSpatialHandler *hand, msOracleSpatialStatement *sthand) { int success = 0; char * cmd = ""; /* allocate stmthp */ success = TRY( hand, OCIHandleAlloc( (dvoid *)hand->envhp, (dvoid **)&sthand->stmthp, (ub4)OCI_HTYPE_STMT, (size_t)0, (dvoid **)0 ) ); sthand->rows_count = 0; sthand->row_num = 0; sthand->rows_fetched = 0; sthand->row = 0; sthand->items = NULL; sthand->items_query = NULL; /* setting environment values to enable time parsing */ cmd = "alter session set NLS_DATE_FORMAT='yyyy-mm-dd hh24:mi:ss'"; success = TRY(hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (const OraText*)cmd, (ub4) strlen(cmd), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); success = TRY(hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT ) ); cmd = "alter session set NLS_TIMESTAMP_TZ_FORMAT='yyyy-mm-dd hh24:mi:ss'"; success = TRY(hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (const OraText*)cmd, (ub4) strlen(cmd), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); success = TRY(hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT ) ); cmd = "alter session set NLS_TIMESTAMP_FORMAT = 'yyyy-mm-dd hh24:mi:ss'"; success = TRY(hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (const OraText*)cmd, (ub4) strlen(cmd), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); success = TRY(hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT ) ); cmd = "alter session set time_zone = 'GMT'"; success = TRY(hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (const OraText*)cmd, (ub4) strlen(cmd), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); success = TRY(hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT ) ); /* fprintf(stderr, "Creating statement handle at %p\n", sthand->stmthp); */ return success; } /* create statement handle from database connection */ static void msOCIFinishStatement( msOracleSpatialStatement *sthand ) { if(sthand != NULL) { /* fprintf(stderr, "Freeing statement handle at %p\n", sthand->stmthp); */ if (sthand->stmthp != NULL) OCIHandleFree( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT ); if (sthand->items != NULL) free( sthand->items ); if (sthand->items_query != NULL) free( sthand->items_query ); memset(sthand, 0, sizeof( msOracleSpatialStatement ) ); free(sthand); } } static int msOCISetDataHandlers(msOracleSpatialHandler *hand, msOracleSpatialDataHandler *dthand) { int success = 0; OCIParam *paramp = NULL; OCIRef *type_ref = NULL; success = TRY( hand, /* allocate dschp */ OCIHandleAlloc( hand->envhp, (dvoid **)&dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (size_t)0, (dvoid **)0 ) ) && TRY( hand, /* describe SDO_GEOMETRY in svchp (dschp) */ OCIDescribeAny( hand->svchp, hand->errhp, (text *)SDO_GEOMETRY, (ub4)SDO_GEOMETRY_LEN, OCI_OTYPE_NAME, (ub1)1, (ub1)OCI_PTYPE_TYPE, dthand->dschp ) ) && TRY( hand, /* get param for SDO_GEOMETRY */ OCIAttrGet( (dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE, (dvoid *)¶mp, (ub4 *)0, (ub4)OCI_ATTR_PARAM, hand->errhp ) ) && TRY( hand, /* get type_ref for SDO_GEOMETRY */ OCIAttrGet( (dvoid *)paramp, (ub4)OCI_DTYPE_PARAM, (dvoid *)&type_ref, (ub4 *)0, (ub4)OCI_ATTR_REF_TDO, hand->errhp ) ) && TRY( hand, /* get TDO for SDO_GEOMETRY */ OCIObjectPin( hand->envhp, hand->errhp, type_ref, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&dthand->tdo ) ); return success; } /* connect to database */ static msOracleSpatialHandler *msOCISetHandlers( char *username, char *password, char *dblink ) { int success; msOracleSpatialHandler *hand = NULL; hand = (msOracleSpatialHandler *) malloc( sizeof(msOracleSpatialHandler)); if (hand == NULL) { msSetError(MS_MEMERR, NULL, "msOCISetHandlers()"); return NULL; } memset( hand, 0, sizeof(msOracleSpatialHandler) ); hand->ref_count = 1; hand->last_oci_status = MS_SUCCESS; hand->last_oci_error[0] = (text)'\0'; success = TRY( hand, /* allocate envhp */ #ifdef USE_THREAD OCIEnvCreate( &hand->envhp, OCI_OBJECT|OCI_THREADED, (dvoid *)0, 0, 0, 0, (size_t) 0, (dvoid **)0 ) ) #else OCIEnvCreate( &hand->envhp, OCI_OBJECT, (dvoid *)0, 0, 0, 0, (size_t) 0, (dvoid **)0 ) ) #endif && TRY( hand, /* allocate errhp */ OCIHandleAlloc( (dvoid *)hand->envhp, (dvoid **)&hand->errhp, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0 ) ) && TRY( hand, /* logon */ OCILogon( hand->envhp, hand->errhp, &hand->svchp, (text *)username, strlen(username), (text *)password, strlen(password), (text *)dblink, strlen(dblink) ) ); if ( !success ) { msDebug( "Cannot create OCI Handlers. " "Connection failure." "Error: %s." "msOracleSpatialLayerOpen()\n", hand->last_oci_error); msSetError( MS_ORACLESPATIALERR, "Cannot create OCI Handlers. " "Connection failure. Check your logs and the connection string. ", "msOracleSpatialLayerOpen()"); msOCICloseHandlers(hand); return NULL; } return hand; } /* disconnect from database */ static void msOCICloseHandlers( msOracleSpatialHandler *hand ) { if (hand->svchp != NULL) OCILogoff( hand->svchp, hand->errhp ); if (hand->errhp != NULL) OCIHandleFree( (dvoid *)hand->errhp, (ub4)OCI_HTYPE_ERROR ); if (hand->envhp != NULL) OCIHandleFree( (dvoid *)hand->envhp, (ub4)OCI_HTYPE_ENV ); if (hand != NULL) memset( hand, 0, sizeof (msOracleSpatialHandler)); free(hand); } static void msOCICloseDataHandlers( msOracleSpatialDataHandler *dthand ) { if (dthand->dschp != NULL) OCIHandleFree( (dvoid *)dthand->dschp, (ub4)OCI_HTYPE_DESCRIBE ); if (dthand != NULL) memset( dthand, 0, sizeof (msOracleSpatialDataHandler)); free(dthand); } static void msOCIClearLayerInfo( msOracleSpatialLayerInfo *layerinfo ) { if (layerinfo != NULL) { memset( layerinfo, 0, sizeof( msOracleSpatialLayerInfo ) ); free(layerinfo); } } /*function that creates the correct sql for geoditical srid for version 9i*/ static void osGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *index_column_name, char *srid, rectObj rect) { char *filter_field=index_column_name[0]=='\0' ? geom_column_name : index_column_name; switch (function) { case FUNCTION_FILTER: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates ), :srid)," "'querytype=window') = 'TRUE'", filter_field); break; } case FUNCTION_RELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_RELATE( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates ), :srid)," "'mask=anyinteract querytype=window') = 'TRUE'", filter_field); break; } case FUNCTION_GEOMRELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_GEOM.RELATE( %s, 'anyinteract', SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates), :srid)," "%f) = 'TRUE' AND %s IS NOT NULL", index_column_name, TOLERANCE, geom_column_name ); break; } case FUNCTION_NONE: { break; } default: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, SDO_CS.VIEWPORT_TRANSFORM(MDSYS.SDO_GEOMETRY(" "2003, 0, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates), :srid)," "'querytype=window') = 'TRUE'", filter_field ); } } } /*function that generate the correct sql for no geoditic srid's*/ static void osNoGeodeticData(int function, int version, char *query_str, size_t size, char *geom_column_name, char *index_column_name, char *srid, rectObj rect) { char *filter_field= index_column_name[0]=='\0' ? geom_column_name : index_column_name; switch (function) { case FUNCTION_FILTER: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," /* "MDSYS.SDO_ORDINATE_ARRAY(%.9g,%.9g,%.9g,%.9g)" */ ":ordinates" " ),'querytype=window') = 'TRUE'", filter_field); break; } case FUNCTION_RELATE: { if (version == VERSION_10g) { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_ANYINTERACT( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)) = 'TRUE'", filter_field); } else { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_RELATE( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "'mask=anyinteract querytype=window') = 'TRUE'", geom_column_name); } break; } case FUNCTION_GEOMRELATE: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_GEOM.RELATE( %s, 'anyinteract', MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "%f) = 'TRUE' AND %s IS NOT NULL", index_column_name, TOLERANCE, geom_column_name ); break; } case FUNCTION_NONE: { break; } default: { snprintf( query_str + strlen(query_str), size-strlen(query_str), "SDO_FILTER( %s, MDSYS.SDO_GEOMETRY(" "2003, :srid, NULL," "MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3)," ":ordinates)," "'querytype=window') = 'TRUE'", filter_field); } } } /* get ordinates from SDO buffer */ static int msOCIGet2DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=2, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ); if (success) { pt[n].x = x; pt[n].y = y; } } return success ? n : 0; } static int msOCIGet3DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; #ifdef USE_POINT_Z_M double z; boolean numnull; #endif /* USE_POINT_Z_M */ OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=3, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ) #ifdef USE_POINT_Z_M && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) #endif /* USE_POINT_Z_M */ ; #ifdef USE_POINT_Z_M if (success) { success = TRY(hand, OCINumberIsZero( hand->errhp, oci_number, (boolean *)&numnull)); if (success) { success = TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&z ) ); } else { hand->last_oci_status = MS_SUCCESS; strlcpy( (char *)hand->last_oci_error, "Retrieve z value, but NULL value for z. Setting z to 0.", sizeof(hand->last_oci_error)); z = 0; success = 1; } } #endif /* USE_POINT_Z_M */ if (success) { pt[n].x = x; pt[n].y = y; #ifdef USE_POINT_Z_M pt[n].z = z; #endif /* USE_POINT_Z_M */ } } return success ? n : 0; } static int msOCIGet4DOrdinates( msOracleSpatialHandler *hand, SDOGeometryObj *obj, int s, int e, pointObj *pt ) { double x, y; int i, n, success = 1; boolean exists; #ifdef USE_POINT_Z_M double z; boolean numnull; #endif /* USE_POINT_Z_M */ OCINumber *oci_number; for( i=s, n=0; i < e && success; i+=4, n++ ) { success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&y ) ) #ifdef USE_POINT_Z_M && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, (sb4)i+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) #endif /* USE_POINT_Z_M */ ; #ifdef USE_POINT_Z_M if (success) { success = TRY(hand, OCINumberIsZero( hand->errhp, oci_number, (boolean *)&numnull)); if (success) { success = TRY( hand, OCINumberToReal( hand->errhp, oci_number, (uword)sizeof(double), (dvoid *)&z ) ); } else { hand->last_oci_status = MS_SUCCESS; strlcpy( (char *)hand->last_oci_error, "Retrieve z value, but NULL value for z. Setting z to 0.", sizeof(hand->last_oci_error)); z = 0; success = 1; } } #endif /* USE_POINT_Z_M */ if (success) { pt[n].x = x; pt[n].y = y; #ifdef USE_POINT_Z_M pt[n].z = z; #endif /* USE_POINT_Z_M */ } } return success ? n : 0; } /* convert three-point circle to two-point rectangular bounds */ static int msOCIConvertCircle( pointObj *pt ) { pointObj ptaux; double dXa, dXb; double ma, mb; double cx, cy, r; int success; dXa = pt[1].x - pt[0].x; success = (fabs( dXa ) > 1e-8); if (!success) { /* switch points 1 & 2 */ ptaux = pt[1]; pt[1] = pt[2]; pt[2] = ptaux; dXa = pt[1].x - pt[0].x; success = (fabs( dXa ) > 1e-8); } if (success) { dXb = pt[2].x - pt[1].x; success = (fabs( dXb ) > 1e-8); if (!success) { /* insert point 2 before point 0 */ ptaux = pt[2]; pt[2] = pt[1]; pt[1] = pt[0]; pt[0] = ptaux; dXb = dXa; /* segment A has become B */ dXa = pt[1].x - pt[0].x; /* recalculate new segment A */ success = (fabs( dXa ) > 1e-8); } } if (success) { ma = (pt[1].y - pt[0].y)/dXa; mb = (pt[2].y - pt[1].y)/dXb; success = (fabs( mb - ma ) > 1e-8); } if (!success) return 0; /* calculate center and radius */ cx = (ma*mb*(pt[0].y - pt[2].y) + mb*(pt[0].x + pt[1].x) - ma*(pt[1].x + pt[2].x))/(2*(mb - ma)); cy = (fabs( ma ) > 1e-8) ? ((pt[0].y + pt[1].y)/2 - (cx - (pt[0].x + pt[1].x)/2)/ma) : ((pt[1].y + pt[2].y)/2 - (cx - (pt[1].x + pt[2].x)/2)/mb); r = sqrt( pow( pt[0].x - cx, 2 ) + pow( pt[0].y - cy, 2 ) ); /* update pt buffer with rectangular bounds */ pt[0].x = cx - r; pt[0].y = cy - r; pt[1].x = cx + r; pt[1].y = cy + r; return 1; } /*function that creates the correct sql for filter and filteritem*/ static void osFilteritem(layerObj *layer, int function, char *query_str, size_t size, int mode) { char *native_filter; if (layer->filter.native_string != NULL) { if (mode == 1) strlcat( query_str, " WHERE ", size); else strlcat( query_str, " AND ", size); /* if (layer->filteritem != NULL) { snprintf (query_str + strlen(query_str), size-strlen(query_str), " %s = ", layer->filteritem); */ /* snprintf (query_str + strlen(query_str), " %s = ", layer->filteritem); */ /* } */ snprintf (query_str + strlen(query_str), size-strlen(query_str), " %s ", layer->filter.native_string); /* snprintf(buffer, n, "gfdg %s %s %s", layer->filter.native_string, (layer->filteritem != NULL ? layer->filteritem : ""), ); */ if (function != FUNCTION_NONE) snprintf (query_str + strlen(query_str), size-strlen(query_str), " AND "); } else { if (function != FUNCTION_NONE) strlcat( query_str, " WHERE ", size); } /* Handle a native filter set as a PROCESSING option (#5001). */ if ( msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL ) { if ((function == FUNCTION_NONE)&&(layer->filter.native_string == NULL)) { strlcat( query_str, " WHERE ", size); } if ((function == FUNCTION_NONE)&&(layer->filter.native_string != NULL)) { strlcat( query_str, " AND ", size); } native_filter = msLayerGetProcessingKey(layer, "NATIVE_FILTER"); snprintf(query_str + strlen(query_str) , size-strlen(query_str), " %s ", native_filter); if (function != FUNCTION_NONE) { strlcat( query_str, " AND ", size); } } } static void osAggrGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name) { char query_str2[6000]; int i = 0; snprintf( query_str2, sizeof(query_str2), "(SELECT"); for( i = 0; i < layer->numitems; ++i ) snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s,", layer->items[i] ); snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s FROM %s", geom_column_name, table_name); osFilteritem(layer, FUNCTION_NONE, query_str2, sizeof(query_str2), 1); snprintf( query_str, size, "SELECT SDO_AGGR_MBR(%s) AS GEOM from %s)", geom_column_name, query_str2); if (layer->debug) msDebug("osAggrGetExtent was called: %s.\n", query_str); } static void osConvexHullGetExtent(layerObj *layer, char *query_str, size_t size, char *geom_column_name, char *table_name) { char query_str2[6000]; int i = 0; snprintf( query_str2, sizeof(query_str2), "(SELECT"); for( i = 0; i < layer->numitems; ++i ) snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s,", layer->items[i] ); snprintf( query_str2 + strlen(query_str2), sizeof(query_str2)-strlen(query_str2), " %s FROM %s", geom_column_name, table_name); osFilteritem(layer, FUNCTION_NONE, query_str2, sizeof(query_str2), 1); snprintf( query_str, size, "SELECT SDO_GEOM.SDO_CONVEXHULL(%s, %f) AS GEOM from %s)", geom_column_name, TOLERANCE, query_str2); } static double osCalculateArcRadius(pointObj *pnt) { double rc; double r1, r2, r3; r1 = sqrt( pow(pnt[0].x-pnt[1].x,2) + pow(pnt[0].y-pnt[1].y,2) ); r2 = sqrt( pow(pnt[1].x-pnt[2].x,2) + pow(pnt[1].y-pnt[2].y,2) ); r3 = sqrt( pow(pnt[2].x-pnt[0].x,2) + pow(pnt[2].y-pnt[0].y,2) ); rc = ( r1+r2+r3 )/2; return ( ( r1*r2*r3 )/( 4*sqrt( rc * (rc-r1) * (rc-r2) * (rc-r3) ) ) ); } static void osCalculateArc(pointObj *pnt, int data3d, int data4d, double area, double radius, double npoints, int side, lineObj arcline, shapeObj *shape) { double length, ctrl, angle; double divbas, plusbas, cosbas, sinbas = 0; #ifdef USE_POINT_Z_M double zrange = 0; #endif /* USE_POINT_Z_M */ int i = 0; if ( npoints > 0 ) { length = sqrt(((pnt[1].x-pnt[0].x)*(pnt[1].x-pnt[0].x))+((pnt[1].y-pnt[0].y)*(pnt[1].y-pnt[0].y))); ctrl = length/(2*radius); #ifdef USE_POINT_Z_M if (data3d||data4d) { zrange = labs(pnt[0].z-pnt[1].z)/npoints; if ((pnt[0].z > pnt[1].z) && side == 1) zrange *= -1; else if ((pnt[0].z < pnt[1].z) && side == 1) zrange = zrange; else if ((pnt[0].z > pnt[1].z) && side != 1) zrange *= -1; else if ((pnt[0].z < pnt[1].z) && side != 1) zrange = zrange; } #endif /* USE_POINT_Z_M */ if( ctrl <= 1 ) { divbas = 2 * asin(ctrl); plusbas = divbas/(npoints); cosbas = (pnt[0].x-pnt[3].x)/radius; sinbas = (pnt[0].y-pnt[3].y)/radius; angle = plusbas; arcline.point = (pointObj *)malloc(sizeof(pointObj)*(npoints+1)); arcline.point[0].x = pnt[0].x; arcline.point[0].y = pnt[0].y; #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[0].z = pnt[0].z; #endif /* USE_POINT_Z_M */ for (i = 1; i <= npoints; i++) { if( side == 1) { arcline.point[i].x = pnt[3].x + radius * ((cosbas*cos(angle))-(sinbas*sin(angle))); arcline.point[i].y = pnt[3].y + radius * ((sinbas*cos(angle))+(cosbas*sin(angle))); #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z + (zrange*i); #endif /* USE_POINT_Z_M */ } else { if ( side == -1) { arcline.point[i].x = pnt[3].x + radius * ((cosbas*cos(angle))+(sinbas*sin(angle))); arcline.point[i].y = pnt[3].y + radius * ((sinbas*cos(angle))-(cosbas*sin(angle))); #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z + (zrange*i); #endif /* USE_POINT_Z_M */ } else { arcline.point[i].x = pnt[0].x; arcline.point[i].y = pnt[0].y; #ifdef USE_POINT_Z_M if (data3d||data4d) arcline.point[i].z = pnt[0].z; #endif /* USE_POINT_Z_M */ } } angle += plusbas; } arcline.numpoints = npoints+1; msAddLine( shape, &arcline ); free (arcline.point); } } else { arcline.point = (pointObj *)malloc(sizeof(pointObj)*(2)); arcline.point[0].x = pnt[0].x; arcline.point[0].y = pnt[0].y; arcline.point[1].x = pnt[1].x; arcline.point[1].y = pnt[1].y; #ifdef USE_POINT_Z_M if(data3d||data4d) { arcline.point[0].z = pnt[0].z; arcline.point[1].z = pnt[1].z; } #endif /* USE_POINT_Z_M */ arcline.numpoints = 2; msAddLine( shape, &arcline ); free (arcline.point); } } /* Part of this function was based on Terralib function TeGenerateArc * found in TeGeometryAlgorith.cpp (www.terralib.org). * Part of this function was based on Dr. Ialo (Univali/Cttmar) functions. */ static void osGenerateArc(shapeObj *shape, lineObj arcline, lineObj points, int i, int n, int data3d, int data4d) { double mult, plus1, plus2, plus3, bpoint; double cx, cy; double radius, side, area, npoints; double dist1 = 0; double dist2 = 0; pointObj point5[4]; mult = ( points.point[i+1].x - points.point[i].x ) * ( points.point[i+2].y - points.point[i].y ) - ( points.point[i+1].y - points.point[i].y ) * ( points.point[i+2].x - points.point[i].x ); if (mult) { /*point5 = (pointObj *)malloc(sizeof(pointObj)*(4));*/ plus1 = points.point[i].x * points.point[i].x + points.point[i].y * points.point[i].y; plus2 = points.point[i+1].x * points.point[i+1].x + points.point[i+1].y * points.point[i+1].y; plus3 = points.point[i+2].x * points.point[i+2].x + points.point[i+2].y * points.point[i+2].y; bpoint = plus1 * ( points.point[i+1].y - points.point[i+2].y ) + plus2 * ( points.point[i+2].y - points.point[i].y ) + plus3 * ( points.point[i].y - points.point[i+1].y ); cx = bpoint / (2.0 * mult); bpoint = plus1 * ( points.point[i+2].x - points.point[i+1].x ) + plus2 * ( points.point[i].x - points.point[i+2].x ) + plus3 * ( points.point[i+1].x - points.point[i].x ); cy = bpoint / (2.0 * mult); dist1 = (points.point[i+1].x - points.point[i].x) * (cy - points.point[i].y); dist2 = (points.point[i+1].y - points.point[i].y) * (cx - points.point[i].x); side = 0; if((dist1-dist2) > 0) side = 1; else { if((dist1-dist2) < 0) side = -1; } point5[0] = points.point[i]; point5[1] = points.point[i+1]; point5[2] = points.point[i+2]; point5[3].x = cx; point5[3].y = cy; radius = osCalculateArcRadius(point5); area = ((points.point[i].x + points.point[i+1].x) * (points.point[i+1].y - points.point[i].y)) + ((points.point[i+1].x + points.point[i+2].x) * (points.point[i+2].y - points.point[i+1].y)); npoints = labs(area/radius); point5[0] = points.point[i]; point5[1] = points.point[i+1]; osCalculateArc(point5, data3d, data4d, area, radius, (npoints>1000)?1000:npoints, side, arcline, shape); point5[0] = points.point[i+1]; point5[1] = points.point[i+2]; osCalculateArc(point5, data3d, data4d, area, radius, (npoints>1000)?1000:npoints, side, arcline, shape); } else { arcline.point = (pointObj *)malloc(sizeof(pointObj)*(2)); arcline.point[0].x = points.point[i].x; arcline.point[0].y = points.point[i].y; arcline.point[1].x = points.point[i+2].x; arcline.point[1].y = points.point[i+2].y; #ifdef USE_POINT_Z_M if (data3d||data4d) { arcline.point[0].z = points.point[i].z; arcline.point[1].z = points.point[i+2].z; } #endif /* USE_POINT_Z_M */ arcline.numpoints = 2; msAddLine( shape, &arcline ); free (arcline.point); } } static void osShapeBounds ( shapeObj *shp ) { int i, f; if ( (shp->numlines > 0) && (shp->line[0].numpoints > 0) ) { shp->bounds.minx = shp->line[0].point[0].x; shp->bounds.maxx = shp->line[0].point[0].x; shp->bounds.miny = shp->line[0].point[0].y; shp->bounds.maxy = shp->line[0].point[0].y; } for ( i = 0 ; i < shp->numlines; i++) { for( f = 0; f < shp->line[i].numpoints; f++) { if (shp->line[i].point[f].x < shp->bounds.minx) shp->bounds.minx = shp->line[i].point[f].x; if (shp->line[i].point[f].x > shp->bounds.maxx) shp->bounds.maxx = shp->line[i].point[f].x; if (shp->line[i].point[f].y < shp->bounds.miny) shp->bounds.miny = shp->line[i].point[f].y; if (shp->line[i].point[f].y > shp->bounds.maxy) shp->bounds.maxy = shp->line[i].point[f].y; } } } static void osCloneShape(shapeObj *shape, shapeObj *newshape, int data3d, int data4d) { int max_points = 0; int i,f,g; lineObj shapeline = {0, NULL}; for (i = 0; i < shape->numlines; i++) max_points += shape->line[i].numpoints; if (max_points > 0) shapeline.point = (pointObj *)malloc( sizeof(pointObj)*max_points ); g = 0; for ( i = 0 ; i < shape->numlines; i++) { for( f = 0; f < shape->line[i].numpoints && g <= max_points; f++, g++) { shapeline.point[g].x = shape->line[i].point[f].x; shapeline.point[g].y = shape->line[i].point[f].y; #ifdef USE_POINT_Z_M if (data3d||data4d) shapeline.point[g].z = shape->line[i].point[f].z; #endif /* USE_POINT_Z_M */ } } if (g) { shapeline.numpoints = g; newshape->type = shape->type; /* jimk: 2009/09/23 Fixes compound linestrings being converted to polygons */ msAddLine( newshape, &shapeline ); } } static void osPointCluster(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int interpretation, int data3d, int data4d) { int n; n = (end - start)/2; /* n = interpretation; */ /* if (n == interpretation) { */ points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n == interpretation && n>0) { shape->type = MS_SHAPE_POINT; points.numpoints = n; msAddLine( shape, &points ); } free( points.point ); /* } */ } static void osPoint(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 1) { shape->type = MS_SHAPE_POINT; points.numpoints = 1; points.point = pnt; msAddLine( shape, &points ); } } static void osClosedPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, int elem_type, int data3d, int data4d) { int n; n = (end - start)/2; points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n > 0) { shape->type = (elem_type==21) ? MS_SHAPE_LINE : MS_SHAPE_POLYGON; points.numpoints = n; msAddLine( shape, &points ); } free( points.point ); } static void osRectangle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 2) { shape->type = MS_SHAPE_POLYGON; points.numpoints = 5; points.point = pnt; /* point5 [0] & [1] contains the lower-left and upper-right points of the rectangle */ pnt[2] = pnt[1]; pnt[1].x = pnt[0].x; pnt[3].x = pnt[2].x; pnt[3].y = pnt[0].y; pnt[4] = pnt[0]; #ifdef USE_POINT_Z_M if (data3d||data4d) { pnt[1].z = pnt[0].z; pnt[3].z = pnt[2].z; } #endif /* USE_POINT_Z_M */ msAddLine( shape, &points ); } } static void osCircle(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj points, pointObj *pnt, int data3d, int data4d) { int n; if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ else n = msOCIGet2DOrdinates( hand, obj, start, end, pnt ); /* n must be < 5 */ if (n == 3) { if (msOCIConvertCircle( pnt )) { shape->type = MS_SHAPE_POINT; points.numpoints = 2; points.point = pnt; msAddLine( shape, &points ); } else { strlcpy( (char *)hand->last_oci_error, "Points in circle object are colinear", sizeof(hand->last_oci_error)); hand->last_oci_status = MS_FAILURE; } } } static void osArcPolygon(msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, int start, int end, lineObj arcpoints, int elem_type, int data3d, int data4d) { int n, i; lineObj points = {0, NULL}; n = (end - start)/2; points.point = (pointObj *)malloc( sizeof(pointObj)*n ); if (data3d) n = msOCIGet3DOrdinates( hand, obj, start, end, points.point ); else if (data4d) n = msOCIGet4DOrdinates( hand, obj, start, end, points.point ); else n = msOCIGet2DOrdinates( hand, obj, start, end, points.point ); if (n > 2) { shape->type = (elem_type==32) ? MS_SHAPE_POLYGON : MS_SHAPE_LINE; points.numpoints = n; for (i = 0; i < n-2; i = i+2) osGenerateArc(shape, arcpoints, points, i, n, data3d, data4d); } free (points.point); } static int osCheck2DGtype(int pIntGtype) { if (pIntGtype > 2000 && pIntGtype < 2008) { if (pIntGtype != 2004) return MS_TRUE; } return MS_FALSE; } static int osCheck3DGtype(int pIntGtype) { if (pIntGtype > 3000 && pIntGtype < 3308) { if (pIntGtype > 3007) pIntGtype-= 300; if (pIntGtype <= 3007 && pIntGtype != 3004) return MS_TRUE; } /* * Future version, untested * return (pIntGtype & 2208 && (pIntGtype & 3000 || pIntGtype & 3296) && pIntGtype & 3); */ return MS_FALSE; } static int osCheck4DGtype(int pIntGtype) { if (pIntGtype > 4000 && pIntGtype < 4408) { if (pIntGtype > 4007) pIntGtype-= 400; if (pIntGtype <= 4007 && pIntGtype != 4004) return MS_TRUE; } return MS_FALSE; } static int osGetOrdinates(msOracleSpatialDataHandler *dthand, msOracleSpatialHandler *hand, shapeObj *shape, SDOGeometryObj *obj, SDOGeometryInd *ind) { int gtype, elem_type, compound_type; float compound_lenght, compound_count; ub4 etype; ub4 interpretation; int nelems, nords, data3d, data4d; int elem, ord_start, ord_end; boolean exists; OCINumber *oci_number; double x, y; #ifdef USE_POINT_Z_M double z; #endif /* USE_POINT_Z_M */ int success; lineObj points = {0, NULL}; pointObj point5[5]; /* for quick access */ shapeObj newshape; /* for compound polygons */ /*stat the variables for compound polygons*/ compound_lenght = 0; compound_type = 0; compound_count = -1; data3d = 0; data4d = 0; if (ind->_atomic != OCI_IND_NULL) { /* not a null object */ nelems = nords = 0; success = TRY( hand, OCICollSize( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, &nelems ) ) && TRY( hand, OCICollSize( hand->envhp, hand->errhp, (OCIColl *)obj->ordinates, &nords ) ) && TRY( hand, OCINumberToInt( hand->errhp, &(obj->gtype), (uword)sizeof(int), OCI_NUMBER_SIGNED, (dvoid *)>ype ) ); /*&& (nords%2==0 && nelems%3==0);*/ /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ if (success && osCheck2DGtype(gtype)) { success = (nords%2==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ } else if (success && osCheck3DGtype(gtype)) { success = (nords%3==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ data3d = 1; } else if (success && osCheck4DGtype(gtype)) { success = (nords%4==0 && nelems%3==0)?1:0; /* check %2==0 for 2D geometries; and %3==0 for element info triplets */ data4d = 1; } if (success) { /* reading SDO_POINT from SDO_GEOMETRY for a 2D/3D point geometry */ if ((gtype==2001 || gtype==3001 || gtype==4001 ) && ind->point._atomic == OCI_IND_NOTNULL && ind->point.x == OCI_IND_NOTNULL && ind->point.y == OCI_IND_NOTNULL) { success = TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.x), (uword)sizeof(double), (dvoid *)&x ) ) && TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.y), (uword)sizeof(double), (dvoid *)&y ) ); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; shape->type = MS_SHAPE_POINT; points.numpoints = 1; points.point = point5; point5[0].x = x; point5[0].y = y; #ifdef USE_POINT_Z_M if (data3d || data4d) { if (ind->point.z == OCI_IND_NOTNULL) { success = TRY( hand, OCINumberToReal( hand->errhp, &(obj->point.z), (uword)sizeof(double), (dvoid *)&z )); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; else point5[0].z = z; } else point5[0].z = z; } #endif /* USE_POINT_Z_M */ msAddLine( shape, &points ); return MS_SUCCESS; } /* if SDO_POINT not fetched, proceed reading elements (element info/ordinates) */ success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info,(sb4)0, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_SIGNED, (dvoid *)&ord_end ) ); elem = 0; ord_end--; /* shifts offset from 1..n to 0..n-1 */ do { ord_start = ord_end; if (elem+3 >= nelems) { /* processing last element */ ord_end = nords; success = 1; } else { /* get start ordinate position for next element which is ord_end for this element */ success = TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+3, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_SIGNED, (dvoid *)&ord_end ) ); ord_end--; /* shifts offset from 1..n to 0..n-1 */ } success = (success && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+1, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_UNSIGNED, (dvoid *)&etype ) ) && TRY( hand, OCICollGetElem( hand->envhp, hand->errhp, (OCIColl *)obj->elem_info, (sb4)elem+2, (boolean *)&exists, (dvoid *)&oci_number, (dvoid **)0 ) ) && TRY( hand, OCINumberToInt( hand->errhp, oci_number, (uword)sizeof(ub4), OCI_NUMBER_UNSIGNED, (dvoid *)&interpretation ) )); if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; if ( etype == 1005 || etype == 2005 || etype == 4 ) { compound_type = 1; compound_lenght = interpretation; compound_count = 0; msInitShape(&newshape); } elem_type = (etype == 1 && interpretation > 1) ? 10 : ((etype%10)*10 + interpretation); /* msDebug("osGetOrdinates shape->index = %ld\telem_type = %d\n",shape->index, elem_type); */ switch (elem_type) { case 10: /* point cluster with 'interpretation'-points */ osPointCluster (hand, shape, obj, ord_start, ord_end, points, interpretation, data3d, data4d); break; case 11: /* point type */ osPoint(hand, shape, obj, ord_start, ord_end, points, point5, data3d, data4d); break; case 21: /* line string whose vertices are connected by straight line segments */ if (compound_type) osClosedPolygon(hand, &newshape, obj, ord_start, (compound_count= compound_lenght) { osCloneShape(&newshape, shape, data3d, data4d); msFreeShape(&newshape); } if (ERROR( "osGetOrdinates()", hand, dthand )) return MS_FAILURE; /* prepare for next cycle */ ord_start = ord_end; elem += 3; if (compound_type) compound_count++; } while (elem < nelems); /* end of element loop */ } /* end of gtype big-if */ } /* end of not-null-object if */ if (compound_type){ if (gtype == 2003 || gtype == 2007) shape->type = MS_SHAPE_POLYGON; msFreeShape(&newshape); } return MS_SUCCESS; } static void msOCICloseConnection( void *hand ) { msOCICloseHandlers( (msOracleSpatialHandler *)hand ); } /* opens a layer by connecting to db with username/password@database stored in layer->connection */ int msOracleSpatialLayerOpen( layerObj *layer ) { char *username = NULL, *password = NULL, *dblink = NULL; msOracleSpatialLayerInfo *layerinfo = NULL; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialStatement *sthand = NULL, *sthand2 = NULL; msOracleSpatialHandler *hand = NULL; if (layer->debug >=2) msDebug("msOracleSpatialLayerOpen called with: %s (Layer pointer %p)\n",layer->data, layer); if (layer->layerinfo != NULL) /* Skip if layer is already open */ return MS_SUCCESS; if (layer->data == NULL) { msDebug( "Error parsing OracleSpatial DATA variable. Must be:" "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'." "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE.\n"); msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. More info in server logs", "msOracleSpatialLayerOpen()"); return MS_FAILURE; } layerinfo = (msOracleSpatialLayerInfo *)malloc(sizeof(msOracleSpatialLayerInfo)); dthand = (msOracleSpatialDataHandler *)malloc(sizeof(msOracleSpatialDataHandler)); sthand = (msOracleSpatialStatement *)malloc(sizeof(msOracleSpatialStatement)); sthand2 = (msOracleSpatialStatement *)malloc(sizeof(msOracleSpatialStatement)); if ((dthand == NULL) || (layerinfo == NULL)) { msSetError(MS_MEMERR, NULL, "msOracleSpatialLayerOpen()"); return MS_FAILURE; } memset( dthand, 0, sizeof(msOracleSpatialDataHandler) ); memset( sthand, 0, sizeof(msOracleSpatialStatement) ); memset( sthand2, 0, sizeof(msOracleSpatialStatement) ); memset( layerinfo, 0, sizeof(msOracleSpatialLayerInfo) ); layerinfo->paging = MS_TRUE; msSplitLogin( layer->connection, layer->map, &username, &password, &dblink ); hand = (msOracleSpatialHandler *) msConnPoolRequest( layer ); if( hand == NULL ) { hand = msOCISetHandlers( username, password, dblink ); if (hand == NULL) { msOCICloseDataHandlers( dthand ); msOCIFinishStatement( sthand ); msOCIFinishStatement( sthand2 ); msOCIClearLayerInfo( layerinfo ); if (username) free(username); if (password) free(password); if (dblink) free(dblink); return MS_FAILURE; } if ( layer->debug >=2) msDebug("msOracleSpatialLayerOpen. Shared connection not available. Creating one.\n"); msConnPoolRegister( layer, hand, msOCICloseConnection ); } else { hand->ref_count++; hand->last_oci_status = MS_SUCCESS; hand->last_oci_error[0] = (text)'\0'; } if (!(msOCISetDataHandlers(hand, dthand) & msOCIOpenStatement(hand, sthand) & msOCIOpenStatement(hand, sthand2))) { msSetError( MS_ORACLESPATIALERR, "Cannot create OCI LayerInfo. " "Connection failure.", "msOracleSpatialLayerOpen()"); if (layer->debug>=2) msDebug("msOracleSpatialLayerOpen. Cannot create OCI LayerInfo. Connection failure.\n"); msOCICloseDataHandlers ( dthand ); msOCICloseHandlers( hand ); msOCIClearLayerInfo( layerinfo ); } layerinfo->orahandlers = hand; layerinfo->oradatahandlers = dthand; layerinfo->orastmt = sthand; layerinfo->orastmt2 = sthand2; layer->layerinfo = layerinfo; if (username) free(username); if (password) free(password); if (dblink) free(dblink); return layer->layerinfo != NULL ? MS_SUCCESS : MS_FAILURE; } /* return MS_TRUE if layer is open, MS_FALSE otherwise.*/ int msOracleSpatialLayerIsOpen(layerObj *layer) { if (layer->layerinfo != NULL) return MS_TRUE; return MS_FALSE; } /* closes the layer, disconnecting from db if connected. layer->layerinfo is freed */ int msOracleSpatialLayerClose( layerObj *layer ) { msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; /*int lIntSuccessFree = 0;*/ if (layer->debug>=2) msDebug("msOracleSpatialLayerClose was called. Layer: %p, Layer name: %s\n", layer, layer->name); if (layerinfo != NULL) { /* * Some errors with the OCIObjectFree with query function * If uncomment draw mode will work but no query modes * Need to investigate the error cause */ /*lIntSuccessFree = TRY (layerinfo->orahandlers, OCIObjectFree(layerinfo->orahandlers->envhp, layerinfo->orahandlers->errhp, (dvoid *)layerinfo->obj, (ub2)OCI_OBJECTFREE_FORCE)); *if (!lIntSuccessFree) * msDebug("Error: %s\n", layerinfo->orahandlers->last_oci_error); */ /* Release Statement Handles */ if (layerinfo->orastmt != NULL) { msOCIFinishStatement(layerinfo->orastmt); layerinfo->orastmt = NULL; } if (layerinfo->orastmt2 != NULL) { msOCIFinishStatement(layerinfo->orastmt2); layerinfo->orastmt2 = NULL; } /* Release Datahandlers */ if (layer->debug>=4) msDebug("msOracleSpatialLayerClose. Cleaning layerinfo handlers.\n"); msOCICloseDataHandlers( layerinfo->oradatahandlers ); layerinfo->oradatahandlers = NULL; /* Free the OCI cache only if there is no more layer that could use it */ layerinfo->orahandlers->ref_count--; if (layerinfo->orahandlers->ref_count == 0) OCICacheFree (layerinfo->orahandlers->envhp, layerinfo->orahandlers->errhp, layerinfo->orahandlers->svchp); /* Release Mapserver Pool */ if (layer->debug>=4) msDebug("msOracleSpatialLayerClose. Release the Oracle Pool.\n"); msConnPoolRelease( layer, layerinfo->orahandlers ); /* Release Layerinfo */ layerinfo->orahandlers = NULL; msOCIClearLayerInfo( layerinfo ); layer->layerinfo = NULL; } return MS_SUCCESS; } /* create SQL statement for retrieving shapes */ /* Sets up cursor for use in *NextShape and *GetShape */ int msOracleSpatialLayerWhichShapes( layerObj *layer, rectObj rect, int isQuery) { int success, i; int function = 0; int version = 0; char query_str[6000]; char query_str2[256]; char *tmp_str=NULL, *tmp1_str=NULL; char *table_name; char *geom_column_name = NULL, *unique = NULL, *srid = NULL, *indexfield=NULL; OCIDefine *adtp = NULL; OCIDefine **items = NULL; OCINumber oci_number; OCIBind *bnd1p = NULL, *bnd2p = NULL; int existunique = MS_FALSE; int rownumisuniquekey = MS_FALSE; int numitemsinselect = 0; /* get layerinfo */ msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug>=3) msDebug("msOracleSpatialLayerWhichShapes was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerWhichShapes called on unopened layer", "msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; } /*init uniqueindex field*/ sthand->uniqueidindex=0; table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); /* parse geom_column_name and table_name */ if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &indexfield, &function, &version)) { msDebug( "Error parsing OracleSpatial DATA variable. Must be:" "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'." "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE." "Your data statement: (%s)" "in msOracleSpatialLayerWhichShapes()\n", layer->data ); msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. More info in server logs", "msOracleSpatialLayerWhichShapes()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } /*rownum will be the first in the select if no UNIQUE key is defined or will be added at the end of the select*/ rownumisuniquekey = MS_TRUE; /*Define the unique*/ if (unique[0] == '\0') strcpy( unique, "rownum" ); else rownumisuniquekey = MS_FALSE; /* Check if the unique field is already in the items list */ existunique = MS_FALSE; if (unique) { for( i=0; i < layer->numitems; ++i ) { if (strcasecmp(unique, layer->items[i])==0) { sthand->uniqueidindex = i; existunique = MS_TRUE; break; } } } /* If no SRID is provided, set it to -1 (NULL) for binding */ if (strcmp(srid,"NULL") == 0) strcpy(srid,"-1"); snprintf( query_str, sizeof(query_str), "SELECT "); numitemsinselect = layer->numitems; /* allocate enough space for items */ if (layer->numitems >= 0) { /*we will always add a rownumber in the selection*/ numitemsinselect++; /*if unique key in the data is specfied and is not part of the current item lists, we should add it to the select*/ if(existunique == MS_FALSE && rownumisuniquekey == MS_FALSE) numitemsinselect++; /*the usinque index is there was no uniqueid given or the uniqueid given was not part of the items lists*/ if (existunique == MS_FALSE) sthand->uniqueidindex = layer->numitems; sthand->items = (item_text_array *)malloc( sizeof(item_text_array) * (numitemsinselect) ); if (sthand->items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate layerinfo->items buffer","msOracleSpatialLayerWhichShapes()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if(indexfield) free(indexfield); free(table_name); return MS_FAILURE; } items = (OCIDefine **)malloc(sizeof(OCIDefine *)*(numitemsinselect)); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if(indexfield) free(indexfield); free(table_name); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*(numitemsinselect)); } /* define SQL query */ for( i=0; i < layer->numitems; ++i ) { snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "\"%s\", ", layer->items[i] ); } /*we add the uniqueid if it was not part of the current item list*/ if(existunique == MS_FALSE && rownumisuniquekey == MS_FALSE) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s,", unique); /*we always want to add rownum is the selection to allow paging to work*/ snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s, ", "rownum"); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s FROM %s", geom_column_name, table_name ); osFilteritem(layer, function, query_str, sizeof(query_str), 1); if (layerinfo->paging && layer->maxfeatures > 0 && layer->startindex < 0) { if (function == FUNCTION_NONE && layer->filter.native_string == NULL) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s"," WHERE "); else if (function == FUNCTION_NONE && layer->filter.native_string != NULL) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), "%s"," AND "); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " ROWNUM<=%d ", layer->maxfeatures); if (function != FUNCTION_NONE) snprintf (query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " AND "); } if ((((atol(srid) >= 8192) && (atol(srid) <= 8330)) || (atol(srid) == 2) || (atol(srid) == 5242888) || (atol(srid) == 2000001)) && (version == VERSION_9i)) osGeodeticData(function, version, query_str, sizeof(query_str), geom_column_name, indexfield, srid, rect); else osNoGeodeticData(function, version, query_str, sizeof(query_str), geom_column_name, indexfield, srid, rect); if( layer->sortBy.nProperties > 0 ) { msDebug("Layer sorting is requested\n"); tmp1_str = msLayerBuildSQLOrderBy(layer); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " ORDER BY %s ", tmp1_str ); msFree(tmp1_str); } /*assuming startindex starts at 1*/ if (layerinfo->paging && layer->startindex > 0) { tmp1_str = msStrdup("SELECT * from (SELECT atmp.*, ROWNUM rnum from ("); tmp_str = msStringConcatenate(tmp_str, tmp1_str); msFree(tmp1_str); tmp_str = msStringConcatenate(tmp_str, query_str); /*oder by rowid does not seem to work with function using the spatial filter, at least on layers loaded using ogr in a 11g database*/ if (function == FUNCTION_NONE || function == FUNCTION_RELATE || function == FUNCTION_GEOMRELATE) tmp1_str = msStrdup( "order by rowid"); /* Populate strOrderBy, if necessary */ else tmp1_str = msStrdup(""); if (layer->maxfeatures > 0) snprintf(query_str2, sizeof(query_str2), " %s) atmp where ROWNUM<=%d) where rnum >=%d", tmp1_str, layer->maxfeatures+layer->startindex-1, layer->startindex); else snprintf( query_str2, sizeof(query_str2), " %s) atmp) where rnum >=%d", tmp1_str, layer->startindex); msFree(tmp1_str); tmp_str = msStringConcatenate(tmp_str, query_str2); snprintf(query_str, sizeof(query_str), "%s", tmp_str); msFree(tmp_str); } if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes. Using this Sql to retrieve the data: %s\n", query_str); if (layer->debug) msDebug("msOracleSpatialLayerWhichShapes. Bind values: srid:%s minx:%f miny:%f maxx:%f maxy:%f \n", srid, rect.minx, rect.miny, rect.maxx, rect.maxy); /* prepare */ success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (layer->debug>=4) msDebug("msOracleSpatialLayerWhichShapes getting ordinate definition.\n"); /* get the object definition of the ordinate array */ ordinates_tdo = get_tdo(SDO_ORDINATE_ARRAY, hand, dthand ); if (layer->debug>=4) msDebug("msOracleSpatialLayerWhichShapes converting to OCIColl.\n"); /* initialized the collection array */ success = TRY( hand, OCIObjectNew(hand->envhp, hand->errhp, hand->svchp, OCI_TYPECODE_VARRAY, ordinates_tdo, (dvoid *)NULL, OCI_DURATION_SESSION, FALSE, (dvoid **)&ordinates) ); /* convert it to a OCI number and then append minx...maxy to the collection */ success = TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.minx), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.miny), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.maxx), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)) &&TRY ( hand, OCINumberFromReal(hand->errhp, (dvoid *)&(rect.maxy), (uword)sizeof(double),(dvoid *)&oci_number)) &&TRY ( hand, OCICollAppend(hand->envhp, hand->errhp,(dvoid *) &oci_number,(dvoid *)0, (OCIColl *)ordinates)); if (layer->debug>=3) msDebug("msOracleSpatialLayerWhichShapes bind by name and object.\n"); /* do the actual binding */ if (success && function != FUNCTION_NONE) { const char* bind_key; char* bind_value; char* bind_tag; success = TRY( hand, /* bind in srid */ OCIBindByName( sthand->stmthp, &bnd2p, hand->errhp, (text *) ":srid", strlen(":srid"),(ub1 *) srid, strlen(srid)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT) ) && TRY(hand, /* bind in rect by name */ OCIBindByName( sthand->stmthp, &bnd1p, hand->errhp, (text *)":ordinates", -1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0,(ub2 *)0, (ub4)0, (ub4 *)0, (ub4)OCI_DEFAULT)) && TRY(hand, /* bind in rect object */ OCIBindObject(bnd1p, hand->errhp, ordinates_tdo, (dvoid **)&ordinates, (ub4 *)0, (dvoid **)0, (ub4 *)0)); /* bind the variables from the bindvals hash */ bind_key = (char*)msFirstKeyFromHashTable(&layer->bindvals); while(bind_key != NULL) { bind_value = msLookupHashTable(&layer->bindvals, bind_key); bind_tag = (char*)malloc(sizeof(char) * strlen(bind_key) + 2); sprintf(bind_tag, ":%s", bind_key); success = success && TRY(hand, OCIBindByName( sthand->stmthp, &bnd2p, hand->errhp, (text *)bind_tag, strlen(bind_tag),(ub1 *) bind_value, strlen(bind_value)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)); bind_key = msNextKeyFromHashTable(&layer->bindvals, bind_key); } } if (layer->debug>=3) msDebug("msOracleSpatialLayerWhichShapes name and object now bound.\n"); if (success && layer->numitems >= 0) { for( i=0; i < numitemsinselect && success; ++i ){ if (i< numitemsinselect -1) { //msDebug("Defining by POS, for %s\n", layer->items[i]); //msDebug("datatype retrieved is %i\n", layer->iteminfo); } success = TRY( hand, OCIDefineByPos( sthand->stmthp, &items[i], hand->errhp, (ub4)i+1, (dvoid *)sthand->items[i], (sb4)TEXT_SIZE, SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT ) ); } } if (success) { int cursor_type = OCI_DEFAULT; if(isQuery) cursor_type =OCI_STMT_SCROLLABLE_READONLY; success = TRY( hand, /* define spatial position adtp ADT object */ OCIDefineByPos( sthand->stmthp, &adtp, hand->errhp, (ub4)numitemsinselect+1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT) ) && TRY( hand, /* define object tdo from adtp */ OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY(hand, /* execute */ OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)cursor_type ) ) && TRY( hand, /* get rows fetched */ OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ) && TRY( hand, /* get rows count */ OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_count, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); } if (!success) { msDebug( "Error: %s . " "Query statement: %s . " "Check your data statement." "msOracleSpatialLayerWhichShapes()\n", hand->last_oci_error, query_str ); msSetError( MS_ORACLESPATIALERR, "Check your data statement and server logs", "msOracleSpatialLayerWhichShapes()"); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } /* should begin processing first row */ sthand->row_num = sthand->row = 0; /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_SUCCESS; } /* fetch next shape from previous SELECT stmt (see *WhichShape()) */ int msOracleSpatialLayerNextShape( layerObj *layer, shapeObj *shape ) { SDOGeometryObj *obj; SDOGeometryInd *ind; int success, /*lIntSuccessFree,*/ i; /* get layerinfo */ msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerWhichShapes called on unopened layer", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; } /* no rows fetched */ if (sthand->rows_fetched == 0) return MS_DONE; if(layer->debug >=5 ) msDebug("msOracleSpatialLayerNextShape on layer %p, row_num: %d\n", layer, sthand->row_num); do { /* is buffer empty? */ if (sthand->row >= sthand->rows_fetched) { /* fetch more */ success = TRY( hand, OCIStmtFetch2( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_count, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); if (!success || sthand->rows_fetched == 0 || sthand->row_num >= sthand->rows_count) { hand->last_oci_status=MS_SUCCESS; return MS_DONE; } if(layer->debug >= 4 ) msDebug("msOracleSpatialLayerNextShape on layer %p, Fetched %d more rows (%d total)\n", layer, sthand->rows_fetched, sthand->rows_count); sthand->row = 0; /* reset buffer row index */ } /* set obj & ind for current row */ obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->index = atol( (char *)(sthand->items[sthand->uniqueidindex][ sthand->row ])); /* Primary Key */ shape->resultindex = sthand->row_num; shape->numvalues = layer->numitems; shape->values = (char **)malloc( sizeof(char*) * shape->numvalues ); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } for( i=0; i < shape->numvalues; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items[i][ sthand->row ])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { strcpy(shape->values[i], (char *)sthand->items[i][ sthand->row ]); shape->values[i][strlen((char *)sthand->items[i][ sthand->row ])] = '\0'; } } /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); /* increment for next row */ sthand->row_num++; sthand->row++; if (success != MS_SUCCESS) { return MS_FAILURE; } osShapeBounds(shape); } while(shape->type == MS_SHAPE_NULL); return MS_SUCCESS; } int msOracleSpatialLayerGetShape( layerObj *layer, shapeObj *shape, resultObj *record) { int success, i; SDOGeometryObj *obj; SDOGeometryInd *ind; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialLayerInfo *layerinfo; msOracleSpatialStatement *sthand = NULL; long shapeindex = record->shapeindex; int resultindex = record->resultindex; if(layer == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called on unopened layer","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called on unopened layer (layerinfo)","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } /* If resultindex is set, fetch the shape from the resultcache, otherwise fetch it from the DB */ if (resultindex >= 0) { long buffer_first_row_num, buffer_last_row_num; /* get layerinfo */ dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *)layerinfo->orastmt2; if (layer->resultcache == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape called before msOracleSpatialLayerWhichShapes()","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } if (resultindex >= sthand->rows_count) { if (layer->debug >= 5) msDebug("msOracleSpatialLayerGetShape problem with cursor. Trying to fetch record = %d of %d, falling back to GetShape\n", resultindex, sthand->rows_count); msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape record out of range","msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } if (layer->debug >= 5) msDebug("msOracleSpatialLayerGetShape was called. Using the record = %d of %d. (shape: %ld should equal pkey: %ld)\n", resultindex, layer->resultcache->numresults, layer->resultcache->results[resultindex].shapeindex, shapeindex); /* NOTE: with the way the resultcache works, we should see items in increasing order, but some may have been filtered out. */ /* Best case: item in buffer */ /* Next best case: item is in next fetch block */ /* Worst case: item is random access */ buffer_first_row_num = sthand->row_num - sthand->row; /* cursor id of first item in buffer */ buffer_last_row_num = buffer_first_row_num + sthand->rows_fetched - 1; /* cursor id of last item in buffer */ if(resultindex >= buffer_first_row_num && resultindex <= buffer_last_row_num) { /* Item is in buffer. Calculate position in buffer */ sthand->row += resultindex - sthand->row_num; /* move sthand row an row_num by offset from last call */ sthand->row_num += resultindex - sthand->row_num; } else { /* Item is not in buffer. Fetch item from Oracle */ if (layer->debug >= 4) msDebug("msOracleSpatialLayerGetShape: Fetching result from DB start: %ld end:%ld record: %d\n", buffer_first_row_num, buffer_last_row_num, resultindex); success = TRY( hand, OCIStmtFetch2( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_ABSOLUTE, (sb4)resultindex+1, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); sthand->row_num = resultindex; sthand->row = 0; /* reset row index */ if(ERROR("msOracleSpatialLayerGetShape", hand, dthand)) return MS_FAILURE; if (!success || sthand->rows_fetched == 0) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetShape could not fetch specified record.", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } } /* set obj & ind for current row */ obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->index = shapeindex; /* By definition this is what we asked for */ shape->numvalues = layer->numitems; shape->values = (char **)malloc( sizeof(char*) * shape->numvalues ); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } for( i=0; i < shape->numvalues; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items[i][ sthand->row ])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } else { strcpy(shape->values[i], (char *)sthand->items[i][ sthand->row ]); shape->values[i][strlen((char *)sthand->items[i][ sthand->row ])] = '\0'; } } /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Call to osGetOrdinates failed.", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } osShapeBounds(shape); if(shape->type == MS_SHAPE_NULL) { msSetError( MS_ORACLESPATIALERR, "Shape type is null... this probably means a record number was requested that could not have beeen in a result set (as returned by NextShape).", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } return (MS_SUCCESS); } else { /* no resultindex, fetch the shape from the DB */ char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL, *indexfield = NULL; int function = 0; int version = 0; sb2 *nullind = NULL; /*OCIDefine *adtp = NULL, *items[QUERY_SIZE] = { NULL };*/ OCIDefine *adtp = NULL; OCIDefine **items = NULL; if (layer->debug>=4) msDebug("msOracleSpatialLayerGetShape was called. Using the record = %ld.\n", shapeindex); dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; /* allocate enough space for items */ if (layer->numitems > 0) { if (sthand->items_query == NULL) sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate layerinfo->items_query buffer", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } nullind = (sb2 *)malloc( sizeof(sb2) * (layer->numitems) ); if (nullind == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate nullind buffer", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } memset(nullind ,0, sizeof(sb2) * (layer->numitems) ); items = (OCIDefine **)malloc(sizeof(OCIDefine *)*layer->numitems); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); /* clean nullind */ free(nullind); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*layer->numitems); } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &indexfield, &function, &version )) { msDebug( "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: (%s) msOracleSpatialLayerGetShape()\n", layer->data ); msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Check server logs. ", "msOracleSpatialLayerGetShape()"); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } /*Define the first query to retrive itens*/ if (unique[0] == '\0') { msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable for query. To execute " "query functions you need to define one " "unique column [USING UNIQUE <#column>]", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } else snprintf( query_str, sizeof(query_str), "SELECT"); /*Define the query*/ for( i = 0; i < layer->numitems; ++i ) snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " %s,", layer->items[i] ); snprintf( query_str + strlen(query_str), sizeof(query_str)-strlen(query_str), " %s FROM %s WHERE %s = %ld", geom_column_name, table_name, unique, shapeindex); /*if (layer->filter.native_string != NULL) sprintf( query_str + strlen(query_str), " AND %s", (layer->filter.string));*/ osFilteritem(layer, FUNCTION_NONE, query_str, sizeof(query_str), 2); if (layer->debug) msDebug("msOracleSpatialLayerGetShape. Sql: %s\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand,OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (success && layer->numitems > 0) { for( i = 0; i < layer->numitems && success; i++ ) success = TRY( hand, OCIDefineByPos( sthand->stmthp, &items[i], hand->errhp, (ub4)i+1, (dvoid *)sthand->items_query[i], (sb4)TEXT_SIZE, SQLT_STR, (sb2 *)&nullind[i], (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT ) ); } if(!success) { msSetError( MS_ORACLESPATIALERR, "Error: %s . " "Query statement: %s . " "Check your data statement.", "msOracleSpatialLayerGetShape()\n", hand->last_oci_error, query_str ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } if (success) { success = TRY( hand, OCIDefineByPos( sthand->stmthp, &adtp, hand->errhp, (ub4)layer->numitems+1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT) ) && TRY( hand, OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY (hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT )) && TRY (hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp )); } if(!success) { msDebug( "Error: %s . " "Query statement: %s ." "Check your data statement." "in msOracleSpatialLayerGetShape()\n", hand->last_oci_error, query_str ); msSetError( MS_ORACLESPATIALERR, "Error in Query statement. Check your server logs","msOracleSpatialLayerGetShape()"); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } shape->type = MS_SHAPE_NULL; /* no rows fetched */ if (sthand->rows_fetched == 0) { /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return (MS_DONE); } obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape->numvalues = layer->numitems; shape->values = (char **) malloc(sizeof(char *) * layer->numitems); if (shape->values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values.", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } shape->index = shapeindex; for( i = 0; i < layer->numitems; ++i ) { shape->values[i] = (char *)malloc(strlen((char *)sthand->items_query[sthand->row][i])+1); if (shape->values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer.", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } else { if (nullind[i] != OCI_IND_NULL) { strcpy(shape->values[i], (char *)sthand->items_query[sthand->row][i]); shape->values[i][strlen((char *)sthand->items_query[sthand->row][i])] = '\0'; } else { shape->values[i][0] = '\0'; } } } /* increment for next row */ sthand->row_num++; sthand->row++; /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Cannot execute query", "msOracleSpatialLayerGetShape()" ); /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } osShapeBounds(shape); sthand->row = sthand->row_num = 0; /* clean nullind */ free(nullind); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return (MS_SUCCESS); } } int msOracleSpatialLayerInitItemInfo( layerObj *layer ) { int i; int *itemindexes ; if (layer->debug>=3) msDebug("msOracleSpatialLayerInitItemInfo was called.\n"); if (layer->numitems == 0) return MS_SUCCESS; if (layer->iteminfo) free( layer->iteminfo ); if ((layer->iteminfo = (long *)malloc(sizeof(int)*layer->numitems))== NULL) { msSetError(MS_MEMERR, NULL, "msOracleSpatialLayerInitItemInfo()"); return MS_FAILURE; } itemindexes = (int*)layer->iteminfo; for(i=0; i < layer->numitems; i++){ itemindexes[i] = i; /*last one is always the geometry one - the rest are non-geom*/ } return MS_SUCCESS; } /* AutoProjection Support for RFC 37 #3333 * TODO: Needs testing */ int msOracleSpatialLayerGetAutoProjection( layerObj *layer, projectionObj *projection ) { char *table_name; char *query_str, *geom_column_name = NULL, *unique = NULL, *srid = NULL, *indexfield=NULL; int success; int function = 0; int version = 0; char wktext[4000]; OCIDefine *def1p = NULL; OCIBind *bnd1p = NULL, *bnd2p = NULL; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug>=3) msDebug("msOracleSpatialLayerGetAutoProjection was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetAutoProjection called on unopened layer","msOracleSpatialLayerGetAutoProjection()"); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &indexfield, &function, &version )) { msDebug( "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: (%s) " "in msOracleSpatialLayerGetAutoProjection()\n", layer->data ); msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable", "msOracleSpatialLayerGetAutoProjection()"); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } query_str = "SELECT wktext FROM mdsys.all_sdo_geom_metadata m, mdsys.cs_srs c WHERE c.srid = m.srid and m.owner||'.'||m.table_name = :table_name and m.column_name = :geo_col_name " "UNION SELECT wktext from mdsys.user_sdo_geom_metadata m, mdsys.cs_srs c WHERE c.srid = m.srid and m.table_name = :table_name and m.column_name = :geo_col_name"; if (layer->debug>=2) msDebug("msOracleSpatialLayerGetAutoProjection. Using this Sql to retrieve the projection: %s.\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIBindByName( sthand->stmthp, &bnd2p, hand->errhp, (text *) ":table_name", strlen(":table_name"), (ub1*) table_name, strlen(table_name)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT ) ) && TRY( hand, OCIBindByName( sthand->stmthp, &bnd1p, hand->errhp, (text *) ":geo_col_name", strlen(":geo_col_name"), (ub1*) geom_column_name, strlen(geom_column_name)+1, SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT ) ) && TRY( hand, OCIDefineByPos( sthand->stmthp, &def1p, hand->errhp, (ub4)1, (dvoid *)wktext, (sb4)4000, SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)0, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); if(!success) { msDebug( "Error: %s . " "Query statement: %s . " "Check your data statement." "in msOracleSpatialLayerGetAutoProjection()\n", hand->last_oci_error, query_str ); msSetError( MS_ORACLESPATIALERR, "Error " "Check your data statement and server logs", "msOracleSpatialLayerGetAutoProjection()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } do { success = TRY( hand, OCIStmtFetch( sthand->stmthp, hand->errhp, (ub4)1, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROWS_FETCHED, hand->errhp ) ); if (success && sthand->rows_fetched > 0) { if( layer->debug ) msDebug("Found WKT projection for table %s: %s\n", table_name, wktext); if(wktext != NULL && projection != NULL) if(msOGCWKT2ProjectionObj(wktext, projection, layer->debug) == MS_FAILURE) return(MS_FAILURE); } } while (sthand->rows_fetched > 0); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_SUCCESS; } /********************************************************************** * msOracleSpatialGetFieldDefn() * * Pass the field definitions through to the layer metadata in the * "gml_[item]_{type,width,precision}" set of metadata items for * defining fields. **********************************************************************/ static void msOracleSpatialGetFieldDefn( layerObj *layer, msOracleSpatialHandler *hand, const char *item, OCIParam *pard ) { const char *gml_type = "Character"; char md_item_name[256]; char gml_width[32], gml_precision[32]; int success; ub2 rzttype, nOCILen; gml_width[0] = '\0'; gml_precision[0] = '\0'; /* -------------------------------------------------------------------- */ /* Get basic parameter details. */ /* -------------------------------------------------------------------- */ success = TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&rzttype,(ub4 *)0, (ub4) OCI_ATTR_DATA_TYPE, hand->errhp )) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&nOCILen ,(ub4 *)0, (ub4) OCI_ATTR_DATA_SIZE, hand->errhp )); if( !success ) return; switch( rzttype ) { case SQLT_CHR: case SQLT_AFC: gml_type = "Character"; if( nOCILen <= 4000 ) sprintf( gml_width, "%d", nOCILen ); break; case SQLT_NUM: { /* NOTE: OCI docs say this should be ub1 type, but we have determined that oracle is actually returning a short so we use that type and try to compensate for possible problems by initializing, and dividing by 256 if it is large. */ unsigned short byPrecision = 0; sb1 nScale = 0; if( !TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&byPrecision ,(ub4 *)0, (ub4) OCI_ATTR_PRECISION, hand->errhp )) || !TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM, (dvoid*)&nScale,(ub4 *)0, (ub4) OCI_ATTR_SCALE, hand->errhp )) ) return; if( byPrecision > 255 ) byPrecision = byPrecision / 256; if( nScale > 0 ) { gml_type = "Real"; sprintf( gml_width, "%d", byPrecision ); sprintf( gml_precision, "%d", nScale ); } else if( nScale < 0 ) gml_type = "Real"; else { gml_type = "Integer"; if( byPrecision < 38 ) sprintf( gml_width, "%d", byPrecision ); } } break; case SQLT_DAT: case SQLT_DATE: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: case SQLT_TIME: case SQLT_TIME_TZ: gml_type = "Date"; break; default: gml_type = "Character"; } snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", item ); if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == 0 ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == 0 ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==0 ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } int msOracleSpatialLayerGetItems( layerObj *layer ) { char *rzt = ""; ub2 rzttype = 0; char *flk = ""; int function = 0; int version = 0; int existgeom; int count_item, flk_len, success, i; char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL, *indexfield=NULL; OCIParam *pard = (OCIParam *) 0; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *) layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; int get_field_details = 0; const char *value; if (layer->debug>=3) msDebug("msOracleSpatialLayerGetItems was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetItems called on unopened layer", "msOracleSpatialLayerGetItems()" ); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } /* Will we want to capture the field details? */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) get_field_details = 1; table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData(layer->data, &geom_column_name, &table_name, &unique, &srid, &indexfield, &function, &version)) { msDebug( "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: (%s)" "in msOracleSpatialLayerGetItems()\n", layer->data ); msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Check server logs. ", "msOracleSpatialLayerGetItems()"); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } snprintf( query_str, sizeof(query_str), "SELECT * FROM %s", table_name ); success = TRY( hand, OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DESCRIBE_ONLY) ) && TRY( hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DESCRIBE_ONLY ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&layer->numitems, (ub4 *)0, OCI_ATTR_PARAM_COUNT, hand->errhp) ); if (!success) { msSetError( MS_QUERYERR, "Cannot retrieve column list", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } sthand->row_num = sthand->row = 0; layer->numitems = layer->numitems-1; layer->items = malloc (sizeof(char *) * (layer->numitems)); if (layer->items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } if (layer->numitems > 0) { if (sthand->items_query == NULL) sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } } count_item = 0; existgeom = 0; /*Upcase conversion for the geom_column_name*/ for (i=0; geom_column_name[i] != '\0'; i++) geom_column_name[i] = toupper(geom_column_name[i]); /*Retrive columns name from the user table*/ for (i = 0; i <= layer->numitems; i++) { success = TRY( hand, OCIParamGet ((dvoid*) sthand->stmthp, (ub4)OCI_HTYPE_STMT,hand->errhp,(dvoid*)&pard, (ub4)i+1)) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM,(dvoid*)&rzttype,(ub4 *)0, (ub4) OCI_ATTR_DATA_TYPE, hand->errhp )) && TRY( hand, OCIParamGet ((dvoid*) sthand->stmthp, (ub4)OCI_HTYPE_STMT,hand->errhp,(dvoid*)&pard, (ub4)i+1)) && TRY( hand, OCIAttrGet ((dvoid *) pard,(ub4) OCI_DTYPE_PARAM,(dvoid*)&rzt,(ub4 *)&flk_len, (ub4) OCI_ATTR_NAME, hand->errhp )); /* if (layer->debug) msDebug("msOracleSpatialLayerGetItems checking type. Column = %s Type = %d\n", rzt, rzttype); */ flk = (char *)malloc(sizeof(char*) * flk_len+1); if (flk == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } else { //layer->iteminfo->dtype[i]= 1; strlcpy(flk, rzt, flk_len+1); } /*Comapre the column name (flk) with geom_column_name and ignore with true*/ if (strcmp(flk, geom_column_name) != 0) { if (rzttype!=OCI_TYPECODE_BLOB) { layer->items[count_item] = (char *)malloc(sizeof(char) * flk_len+1); if (layer->items[count_item] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); free(table_name); return MS_FAILURE; } strcpy(layer->items[count_item], flk); count_item++; if( get_field_details ) msOracleSpatialGetFieldDefn( layer, hand, layer->items[count_item-1], pard ); } } else existgeom = 1; strcpy( rzt, "" ); free(flk); /* Better?!*/ flk_len = 0; } layer->numitems = count_item; if (!(existgeom)) { msSetError (MS_ORACLESPATIALERR, "No geometry column, check stmt", "msOracleSpatialLayerGetItems()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return msOracleSpatialLayerInitItemInfo( layer ); } int msOracleSpatialLayerGetExtent(layerObj *layer, rectObj *extent) { char *table_name; char query_str[6000], *geom_column_name = NULL, *unique = NULL, *srid = NULL, *indexfield=NULL; int success, i; int function = 0; int version = 0; SDOGeometryObj *obj = NULL; SDOGeometryInd *ind = NULL; shapeObj shape; rectObj bounds; /*OCIDefine *adtp = NULL, *items[QUERY_SIZE] = { NULL };*/ OCIDefine *adtp = NULL; OCIDefine **items = NULL; msOracleSpatialLayerInfo *layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; msOracleSpatialDataHandler *dthand = NULL; msOracleSpatialHandler *hand = NULL; msOracleSpatialStatement *sthand = NULL; if (layer->debug>=3) msDebug("msOracleSpatialLayerGetExtent was called.\n"); if (layerinfo == NULL) { msSetError( MS_ORACLESPATIALERR, "msOracleSpatialLayerGetExtent called on unopened layer","msOracleSpatialLayerGetExtent()"); return MS_FAILURE; } else { dthand = (msOracleSpatialDataHandler *)layerinfo->oradatahandlers; hand = (msOracleSpatialHandler *)layerinfo->orahandlers; sthand = (msOracleSpatialStatement *) layerinfo->orastmt; } /* allocate enough space for items */ if (layer->numitems > 0) { sthand->items_query = (item_text_array_query *)malloc( sizeof(item_text_array_query) * (layer->numitems) ); if (sthand->items_query == NULL) { msSetError( MS_ORACLESPATIALERR, "Cannot allocate layerinfo->items buffer", "msOracleSpatialLayerGetExtent()" ); return MS_FAILURE; } items = (OCIDefine **)malloc(sizeof(OCIDefine *)*layer->numitems); if (items == NULL) { msSetError( MS_ORACLESPATIALERR,"Cannot allocate items buffer","msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } memset(items ,0,sizeof(OCIDefine *)*layer->numitems); } table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &indexfield, &function, &version )) { msDebug( "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: (%s) " "in msOracleSpatialLayerGetExtent()\n", layer->data ); msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Check server logs. ", "msOracleSpatialLayerGetExtent()"); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } //if (version == VERSION_10g) osAggrGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); /*else { if (((atol(srid) < 8192) || (atol(srid) > 8330)) && (atol(srid) != 2) && (atol(srid) != 5242888) && (atol(srid) != 2000001)) { if (version == VERSION_9i) osAggrGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); else osConvexHullGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); } else osConvexHullGetExtent(layer, query_str, sizeof(query_str), geom_column_name, table_name); } */ if (layer->debug>=3) msDebug("msOracleSpatialLayerGetExtent. Using this Sql to retrieve the extent: %s.\n", query_str); /*Prepare the handlers to the query*/ success = TRY( hand,OCIStmtPrepare( sthand->stmthp, hand->errhp, (text *)query_str, (ub4)strlen(query_str), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT) ); if (success && layer->numitems > 0) { for( i = 0; i < layer->numitems && success; ++i ) success = TRY( hand, OCIDefineByPos( sthand->stmthp, &items[i], hand->errhp, (ub4)i+1, (dvoid *)sthand->items_query[i], (sb4)TEXT_SIZE, SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT ) ); } if(!success) { msDebug( "Error: %s . " "Query statement: %s . " "Check your data statement." "in msOracleSpatialLayerGetExtent()\n", hand->last_oci_error, query_str ); msSetError( MS_ORACLESPATIALERR, "Check your data statement and server logs", "msOracleSpatialLayerGetExtent()" ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } if (success) { success = TRY( hand, OCIDefineByPos( sthand->stmthp, &adtp, hand->errhp, (ub4)layer->numitems+1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT) ) && TRY( hand, OCIDefineObject( adtp, hand->errhp, dthand->tdo, (dvoid **)sthand->obj, (ub4 *)0, (dvoid **)sthand->ind, (ub4 *)0 ) ) && TRY (hand, OCIStmtExecute( hand->svchp, sthand->stmthp, hand->errhp, (ub4)QUERY_SIZE, (ub4)0, (OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT )) && TRY (hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp )); } if(!success) { msDebug( "Error: %s . " "Query statement: %s ." "Check your data statement." "in msOracleSpatialLayerGetExtent()\n", hand->last_oci_error, query_str ); msSetError( MS_ORACLESPATIALERR, "Check your data statement and server logs", "msOracleSpatialLayerGetExtent()" ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } /* should begin processing first row */ sthand->row_num = sthand->row = 0; msInitShape( &shape ); do { /* is buffer empty? */ if (sthand->row_num >= sthand->rows_fetched) { /* fetch more */ success = TRY( hand, OCIStmtFetch( sthand->stmthp, hand->errhp, (ub4)ARRAY_SIZE, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT ) ) && TRY( hand, OCIAttrGet( (dvoid *)sthand->stmthp, (ub4)OCI_HTYPE_STMT, (dvoid *)&sthand->rows_fetched, (ub4 *)0, (ub4)OCI_ATTR_ROW_COUNT, hand->errhp ) ); if (!success || sthand->rows_fetched == 0 || sthand->row_num >= sthand->rows_fetched) { hand->last_oci_status=MS_SUCCESS; break; } sthand->row = 0; /* reset row index */ } /* no rows fetched */ if (sthand->rows_fetched == 0) break; obj = sthand->obj[ sthand->row ]; ind = sthand->ind[ sthand->row ]; /* get the items for the shape */ shape.numvalues = layer->numitems; shape.values = (char **) malloc(sizeof(char *) * layer->numitems); if (shape.values == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the values.", "msOracleSpatialLayerGetExtent()" ); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } shape.index = sthand->row_num; for( i = 0; i < layer->numitems; ++i ) { shape.values[i] = (char *)malloc(strlen((char *)sthand->items_query[sthand->row][i])+1); if (shape.values[i] == NULL) { msSetError( MS_ORACLESPATIALERR, "No memory avaliable to allocate the items buffer.", "msOracleSpatialLayerGetExtent()" ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } else { strcpy(shape.values[i], (char *)sthand->items_query[sthand->row][i]); shape.values[i][strlen((char *)sthand->items_query[sthand->row][i])] = '\0'; } } /* increment for next row */ sthand->row_num++; sthand->row++; /* fetch a layer->type object */ success = osGetOrdinates(dthand, hand, &shape, obj, ind); if (success != MS_SUCCESS) { msSetError( MS_ORACLESPATIALERR, "Cannot execute query", "msOracleSpatialLayerGetExtent()" ); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } } while(sthand->row <= sthand->rows_fetched); sthand->row = sthand->row_num = 0; osShapeBounds(&shape); bounds = shape.bounds; extent->minx = bounds.minx; extent->miny = bounds.miny; extent->maxx = bounds.maxx; extent->maxy = bounds.maxy; msFreeShape(&shape); /* clean items */ free(items); if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return(MS_SUCCESS); } void msOracleSpatialLayerFreeItemInfo( layerObj *layer ) { if (layer->debug>=3) msDebug("msOracleSpatialLayerFreeItemInfo was called.\n"); if (layer->iteminfo) free(layer->iteminfo); layer->iteminfo = NULL; /* nothing to do */ } int msOracleSpatialLayerGetAutoStyle( mapObj *map, layerObj *layer, classObj *c, shapeObj *shape ) { msSetError( MS_ORACLESPATIALERR, "Function not implemented yet", "msLayerGetAutoStyle()" ); return MS_FAILURE; } /************************************************************************/ /* msOracleSpatialEscapePropertyName */ /* */ /* Return the property name in a properly escaped and quoted form. */ /************************************************************************/ char *msOracleSpatialEscapePropertyName(layerObj *layer, const char* pszString) { char* pszEscapedStr=NULL; int i, j = 0; if (layer && pszString && strlen(pszString) > 0) { int nLength = strlen(pszString); pszEscapedStr = (char*) msSmallMalloc( 1 + 2 * nLength + 1 + 1); //pszEscapedStr[j++] = ''; for (i=0; idebug) // msDebug("msOracleSpatialLayerGetPaging was called.\n"); if(!msOracleSpatialLayerIsOpen(layer)) return MS_TRUE; assert( layer->layerinfo != NULL); layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; return layerinfo->paging; } void msOracleSpatialEnablePaging(layerObj *layer, int value) { msOracleSpatialLayerInfo *layerinfo = NULL; if (layer->debug>=3) msDebug("msOracleSpatialLayerEnablePaging was called.\n"); if(!msOracleSpatialLayerIsOpen(layer)) msOracleSpatialLayerOpen(layer); assert( layer->layerinfo != NULL); layerinfo = (msOracleSpatialLayerInfo *)layer->layerinfo; layerinfo->paging = value; return; } int msOracleSpatialLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) { char *native_string = NULL; int nodeCount = 0; int function = 0, version = 0, dwithin = 0, regexp_like = 0, case_ins = 0, ieq = 0; char *table_name; char *geom_column_name = NULL, *unique = NULL, *srid = NULL, *indexfield=NULL; char *snippet = NULL; char *strtmpl = NULL; double dfDistance = -1; table_name = (char *) malloc(sizeof(char) * TABLE_NAME_SIZE); if (!msSplitData( layer->data, &geom_column_name, &table_name, &unique, &srid, &indexfield, &function, &version )) { msDebug( "Error parsing OracleSpatial DATA variable. Must be: " "'geometry_column FROM table_name [USING UNIQUE SRID srid# FUNCTION]' or " "'geometry_column FROM (SELECT stmt) [USING UNIQUE SRID srid# FUNCTION]'. " "If want to set the FUNCTION statement you can use: FILTER, RELATE, GEOMRELATE or NONE. " "Your data statement: (%s)" "in msOracleSpatialLayerGetExtent()\n", layer->data ); msSetError( MS_ORACLESPATIALERR, "Error parsing OracleSpatial DATA variable. Check server logs. ", "msOracleSpatialLayerGetExtent()"); /* clean items */ if (geom_column_name) free(geom_column_name); if (srid) free(srid); if (unique) free(unique); if (indexfield) free(indexfield); free(table_name); return MS_FAILURE; } //msDebug("filter.string was set: %s\n",filter->string); if(!filter->string) return MS_SUCCESS; /* for backwards compatibility we continue to allow SQL snippets as a string */ if(filter->type == MS_STRING && filter->string && filteritem) { /* item/value pair */ if(filter->flags & MS_EXP_INSENSITIVE) { native_string = msStringConcatenate(native_string, "upper("); native_string = msStringConcatenate(native_string, filteritem); native_string = msStringConcatenate(native_string, ") = upper("); } else { native_string = msStringConcatenate(native_string, filteritem); native_string = msStringConcatenate(native_string, " = "); } strtmpl = "'%s'"; /* don't have a type for the righthand literal so assume it's a string and we quote */ snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(filter->string)); sprintf(snippet, strtmpl, filter->string); // TODO: escape filter->string (msPostGISEscapeSQLParam) native_string = msStringConcatenate(native_string, snippet); free(snippet); if(filter->flags & MS_EXP_INSENSITIVE) native_string = msStringConcatenate(native_string, ")"); if (layer->debug>=2) msDebug("msOracleSpatialLayerTranslateFilter: **item/value combo: %s\n", native_string); } else if(filter->type == MS_REGEX && filter->string && filteritem) { /* item/regex pair */ native_string = msStringConcatenate(native_string, "REGEXP_LIKE ("); native_string = msStrdup(filteritem); native_string = msStringConcatenate(native_string, ", "); strtmpl = "'%s'"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(filter->string)); sprintf(snippet, strtmpl, filter->string); // TODO: escape filter->string (msPostGISEscapeSQLParam) native_string = msStringConcatenate(native_string, snippet); if(filter->flags & MS_EXP_INSENSITIVE) { native_string = msStringConcatenate(native_string, ",i "); } native_string = msStringConcatenate(native_string, " )"); free(snippet); } else if(filter->type == MS_EXPRESSION) { tokenListNodeObjPtr node = NULL; //tokenListNodeObjPtr nextNode = NULL; if (layer->debug>2) msDebug("msOracleSpatialLayerTranslateFilter. String: %s \n", filter->string); if (layer->debug>2 && !filter->tokens) msDebug("msOracleSpatialLayerTranslateFilter. No tokens to process\n"); if(!filter->tokens) return MS_SUCCESS; /* nothing to work from */ if (layer->debug>2) msDebug("msOracleSpatialLayerTranslateFilter. There are tokens to process \n"); /* try to convert tokens */ node = filter->tokens; while (node != NULL) { //msDebug("token count :%i, token is %i\n", nodeCount, node->token); switch(node->token) { case '(': // if (buffer == MS_FALSE) native_string = msStringConcatenate(native_string, "( "); break; case ')': if (regexp_like == MS_TRUE) { if (case_ins == MS_TRUE) { native_string = msStringConcatenate(native_string, ",'i' "); case_ins = MS_FALSE; } regexp_like = MS_FALSE; native_string = msStringConcatenate(native_string, " )"); msDebug("closing RE comparison\n"); } native_string = msStringConcatenate(native_string, " )"); break; case MS_TOKEN_LITERAL_NUMBER: strtmpl = "%lf"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16); sprintf(snippet, strtmpl, node->tokenval.dblval); // TODO: escape strval if (dwithin == MS_TRUE) { dfDistance = node->tokenval.dblval; if (layer->units == MS_DD){ dfDistance *= msInchesPerUnit(MS_DD,0)/msInchesPerUnit(MS_METERS,0); //msDebug("Converted Distance value is %lf\n", dfDistance); } sprintf(snippet, strtmpl, dfDistance); native_string = msStringConcatenate(native_string, "'distance="); native_string = msStringConcatenate(native_string, snippet); native_string = msStringConcatenate(native_string, "'"); } else { native_string = msStringConcatenate(native_string, snippet); } free(snippet); break; case MS_TOKEN_LITERAL_STRING: strtmpl = "%s"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(node->tokenval.strval)); sprintf(snippet, strtmpl, node->tokenval.strval); // TODO: escape strval snippet = msReplaceSubstring(snippet,"'","''"); native_string = msStringConcatenate(native_string, "'"); if (ieq == MS_TRUE) { native_string = msStringConcatenate(native_string, "^"); } native_string = msStringConcatenate(native_string, snippet); if (ieq == MS_TRUE) { native_string = msStringConcatenate(native_string, "$"); ieq = MS_FALSE; } native_string = msStringConcatenate(native_string, "'"); msFree(snippet); break; case MS_TOKEN_LITERAL_BOOLEAN: if(node->tokenval.dblval == MS_TRUE) native_string = msStringConcatenate(native_string, "'TRUE'"); else native_string = msStringConcatenate(native_string, "'FALSE'"); break; case MS_TOKEN_LITERAL_TIME: { int resolution = msTimeGetResolution(node->tokensrc); snippet = (char *) msSmallMalloc(128); switch(resolution) { case TIME_RESOLUTION_YEAR: strtmpl = "to_date('%d-01','YYYY-MM')"; sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year+1900)); break; case TIME_RESOLUTION_MONTH: strtmpl = "to_date('%d-%02d','YYYY-MM')"; sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year+1900), (node->tokenval.tmval.tm_mon+1)); break; case TIME_RESOLUTION_DAY: strtmpl = "to_date('%d-%02d-%02d','YYYY-MM-DD') "; sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year+1900), (node->tokenval.tmval.tm_mon+1), node->tokenval.tmval.tm_mday); break; case TIME_RESOLUTION_HOUR: strtmpl = "to_timestamp('%d-%02d-%02d %02d','YYYY-MM-DD hh24')"; sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year+1900), (node->tokenval.tmval.tm_mon+1), node->tokenval.tmval.tm_mday, node->tokenval.tmval.tm_hour); break; case TIME_RESOLUTION_MINUTE: strtmpl = "to_timestamp('%d-%02d-%02d %02d:%02d','YYYY-MM-DD hh24:mi')"; sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year+1900), (node->tokenval.tmval.tm_mon+1), node->tokenval.tmval.tm_mday, node->tokenval.tmval.tm_hour, node->tokenval.tmval.tm_min); break; case TIME_RESOLUTION_SECOND: strtmpl = "to_timestamp('%d-%02d-%02d %02d:%02d:%02d','YYYY-MM-DD hh24:mi:ss')"; sprintf(snippet, strtmpl, (node->tokenval.tmval.tm_year+1900), (node->tokenval.tmval.tm_mon+1), node->tokenval.tmval.tm_mday, node->tokenval.tmval.tm_hour, node->tokenval.tmval.tm_min, node->tokenval.tmval.tm_sec); break; } native_string = msStringConcatenate(native_string, snippet); msFree(snippet); break; } case MS_TOKEN_LITERAL_SHAPE: native_string = msStringConcatenate(native_string, " SDO_GEOMETRY('"); native_string = msStringConcatenate(native_string, msShapeToWKT(node->tokenval.shpval)); native_string = msStringConcatenate(native_string, "'"); if(srid && strcmp(srid, "") != 0) { native_string = msStringConcatenate(native_string, ", "); native_string = msStringConcatenate(native_string, srid); } native_string = msStringConcatenate(native_string, ") "); //msDebug("------> srid node value: %s", node->tokenval.shpval); break; case MS_TOKEN_BINDING_DOUBLE: native_string = msStringConcatenate(native_string, node->tokenval.bindval.item); break; case MS_TOKEN_BINDING_INTEGER: native_string = msStringConcatenate(native_string, node->tokenval.bindval.item); break; case MS_TOKEN_BINDING_STRING: if (node->next->token == MS_TOKEN_COMPARISON_RE || node->next->token == MS_TOKEN_COMPARISON_IRE || node->next->token == MS_TOKEN_COMPARISON_IEQ ) { native_string = msStringConcatenate(native_string, "REGEXP_LIKE( "); } strtmpl = "%s"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(node->tokenval.strval)); sprintf(snippet, strtmpl, node->tokenval.strval); // TODO: escape strval (msPostGISEscapeSQLParam) native_string = msStringConcatenate(native_string, snippet); free(snippet); break; case MS_TOKEN_BINDING_TIME: native_string = msStringConcatenate(native_string, node->tokenval.bindval.item); break; case MS_TOKEN_BINDING_SHAPE: native_string = msStringConcatenate(native_string, geom_column_name); break; case MS_TOKEN_BINDING_MAP_CELLSIZE: strtmpl = "%lf"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16); sprintf(snippet, strtmpl, layer->map->cellsize); native_string = msStringConcatenate(native_string, snippet); free(snippet); break; case MS_TOKEN_LOGICAL_AND: native_string = msStringConcatenate(native_string, " AND "); break; case MS_TOKEN_LOGICAL_OR: native_string = msStringConcatenate(native_string, " OR "); break; case MS_TOKEN_LOGICAL_NOT: native_string = msStringConcatenate(native_string, " NOT "); break; case MS_TOKEN_COMPARISON_EQ: native_string = msStringConcatenate(native_string, " = "); break; case MS_TOKEN_COMPARISON_NE: native_string = msStringConcatenate(native_string, " != "); break; case MS_TOKEN_COMPARISON_GT: native_string = msStringConcatenate(native_string, " > "); break; case MS_TOKEN_COMPARISON_GE: native_string = msStringConcatenate(native_string, " >= "); break; case MS_TOKEN_COMPARISON_LT: native_string = msStringConcatenate(native_string, " < "); break; case MS_TOKEN_COMPARISON_LE: native_string = msStringConcatenate(native_string, " <= "); break; case MS_TOKEN_COMPARISON_IEQ: // this is for case insensitve equals check msDebug("got a IEQ comparison\n"); regexp_like = MS_TRUE; case_ins = MS_TRUE; ieq = MS_TRUE; native_string = msStringConcatenate(native_string, ", "); break; case MS_TOKEN_COMPARISON_RE: // the regex formats that MS uses as Oracle users are different so just return and eval the regex's in MS //return MS_SUCCESS; msDebug("got a RE comparison\n"); regexp_like = MS_TRUE; native_string = msStringConcatenate(native_string, ", "); break; case MS_TOKEN_COMPARISON_IRE: // the regex formats that MS uses as Oracle users are different so just return and eval the regex's in MS regexp_like = MS_TRUE; case_ins = MS_TRUE; native_string = msStringConcatenate(native_string, ", "); break; case MS_TOKEN_COMPARISON_IN: native_string = msStringConcatenate(native_string, " IN "); break; case MS_TOKEN_COMPARISON_LIKE: native_string = msStringConcatenate(native_string, " LIKE "); break; case MS_TOKEN_COMPARISON_INTERSECTS: native_string = msStringConcatenate(native_string, " ST_INTERSECTS "); break; case MS_TOKEN_COMPARISON_DISJOINT: native_string = msStringConcatenate(native_string, " NOT ST_INTERSECTS "); break; case MS_TOKEN_COMPARISON_TOUCHES: native_string = msStringConcatenate(native_string, " ST_TOUCH "); break; case MS_TOKEN_COMPARISON_OVERLAPS: native_string = msStringConcatenate(native_string, " ST_OVERLAPS "); break; case MS_TOKEN_COMPARISON_CROSSES: native_string = msStringConcatenate(native_string, " SDO_OVERLAPBDYDISJOINT "); break; case MS_TOKEN_COMPARISON_WITHIN: native_string = msStringConcatenate(native_string, " ST_INSIDE "); break; case MS_TOKEN_COMPARISON_CONTAINS: native_string = msStringConcatenate(native_string, " SDO_CONTAINS "); break; case MS_TOKEN_COMPARISON_EQUALS: native_string = msStringConcatenate(native_string, " SDO_EQUAL "); break; case MS_TOKEN_COMPARISON_BEYOND: //support for the wfs case dwithin = MS_TRUE; native_string = msStringConcatenate(native_string, "NOT SDO_WITHIN_DISTANCE "); break; case MS_TOKEN_COMPARISON_DWITHIN: dwithin = MS_TRUE; native_string = msStringConcatenate(native_string, "SDO_WITHIN_DISTANCE "); break; case MS_TOKEN_FUNCTION_LENGTH: break; case MS_TOKEN_FUNCTION_TOSTRING: break; case MS_TOKEN_FUNCTION_COMMIFY: break; case MS_TOKEN_FUNCTION_AREA: native_string = msStringConcatenate(native_string, "SDO_GEOM.SDO_AREA "); break; case MS_TOKEN_FUNCTION_ROUND: native_string = msStringConcatenate(native_string, "ROUND "); break; case MS_TOKEN_FUNCTION_FROMTEXT: native_string = msStringConcatenate(native_string, "SDO_GEOMETRY "); break; case MS_TOKEN_FUNCTION_BUFFER: // native_string = msStringConcatenate(native_string, " SDO_BUFFER "); //buffer = MS_TRUE; break; case MS_TOKEN_FUNCTION_DIFFERENCE: native_string = msStringConcatenate(native_string, "ST_DIFFERENCE "); break; case MS_TOKEN_FUNCTION_SIMPLIFY: native_string = msStringConcatenate(native_string, "SDO_UTIL.SIMPLIFY "); break; case MS_TOKEN_FUNCTION_SIMPLIFYPT: break; case MS_TOKEN_FUNCTION_GENERALIZE: native_string = msStringConcatenate(native_string, "SDO_UTIL.SIMPLIFY "); break; case ',': native_string = msStringConcatenate(native_string, ","); break; case '~': break; default: fprintf(stderr, "Translation to native SQL failed.\n"); msFree(native_string); if (layer->debug) { msDebug("Token not caught, exiting: Token is %i\n", node->token); } return MS_SUCCESS; /* not an error */ } nodeCount++; node = node->next; //fprintf(stderr, "native filter: %s\n", native_string); } filter->native_string = msStrdup(native_string); if (layer->debug>=4) msDebug("total filter tokens are %i\n,", nodeCount); msFree(native_string); } return MS_SUCCESS; } #else /* OracleSpatial "not-supported" procedures */ int msOracleSpatialLayerOpen(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerOpen()" ); return MS_FAILURE; } int msOracleSpatialLayerIsOpen(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerIsOpen()" ); return MS_FALSE; } int msOracleSpatialLayerClose(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerClose()" ); return MS_FAILURE; } int msOracleSpatialLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerWhichShapes()" ); return MS_FAILURE; } int msOracleSpatialLayerNextShape(layerObj *layer, shapeObj *shape) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerNextShape()" ); return MS_FAILURE; } int msOracleSpatialLayerGetItems(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetItems()" ); return MS_FAILURE; } int msOracleSpatialLayerGetShape( layerObj *layer, shapeObj *shape, resultObj *record ) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetShape()" ); return MS_FAILURE; } int msOracleSpatialLayerGetExtent(layerObj *layer, rectObj *extent) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerGetExtent()" ); return MS_FAILURE; } int msOracleSpatialLayerInitItemInfo(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerInitItemInfo()" ); return MS_FAILURE; } void msOracleSpatialLayerFreeItemInfo(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msOracleSpatialLayerFreeItemInfo()" ); } int msOracleSpatialLayerGetAutoStyle( mapObj *map, layerObj *layer, classObj *c, shapeObj *shape ) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerGetAutoStyle()" ); return MS_FAILURE; } void msOracleSpatialEnablePaging(layerObj *layer, int value) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerEnablePaging()" ); return; } int msOracleSpatialGetPaging(layerObj *layer) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerGetPaging()" ); return MS_FAILURE; } int msOracleSpatialLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerTranslateFilter()" ); return MS_FAILURE; } char *msOracleSpatialEscapePropertyName(layerObj *layer, const char* pszString) { msSetError( MS_ORACLESPATIALERR, "OracleSpatial is not supported", "msLayerEscapePropertyName()" ); return msStrdup(pszString); } #endif #if defined USE_ORACLE_PLUGIN MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer) { assert(layer != NULL); assert(vtable != NULL); vtable->LayerTranslateFilter = msOracleSpatialLayerTranslateFilter; vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo; vtable->LayerFreeItemInfo = msOracleSpatialLayerFreeItemInfo; vtable->LayerOpen = msOracleSpatialLayerOpen; vtable->LayerIsOpen = msOracleSpatialLayerIsOpen; vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes; vtable->LayerNextShape = msOracleSpatialLayerNextShape; vtable->LayerGetShape = msOracleSpatialLayerGetShape; vtable->LayerClose = msOracleSpatialLayerClose; vtable->LayerGetItems = msOracleSpatialLayerGetItems; vtable->LayerGetExtent = msOracleSpatialLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ vtable->LayerCloseConnection = msOracleSpatialLayerClose; vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; //vtable->LayerSetTimeFilter = msOracleSpatialLayerSetTimeFilter; //vtable->LayerEscapePropertyName = msOracleSpatialEscapePropertyName; /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection = msOracleSpatialLayerGetAutoProjection; Disabled until tested */ vtable->LayerEnablePaging = msOracleSpatialEnablePaging; vtable->LayerGetPaging = msOracleSpatialGetPaging; return MS_SUCCESS; } #else /*if ORACLE_PLUGIN is defined, then this file is not used by libmapserver and therefre there is no need to include this function */ int msOracleSpatialLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerTranslateFilter = msOracleSpatialLayerTranslateFilter; layer->vtable->LayerInitItemInfo = msOracleSpatialLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msOracleSpatialLayerFreeItemInfo; layer->vtable->LayerOpen = msOracleSpatialLayerOpen; layer->vtable->LayerIsOpen = msOracleSpatialLayerIsOpen; layer->vtable->LayerWhichShapes = msOracleSpatialLayerWhichShapes; layer->vtable->LayerNextShape = msOracleSpatialLayerNextShape; layer->vtable->LayerGetShape = msOracleSpatialLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerClose = msOracleSpatialLayerClose; layer->vtable->LayerGetItems = msOracleSpatialLayerGetItems; layer->vtable->LayerGetExtent = msOracleSpatialLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ layer->vtable->LayerCloseConnection = msOracleSpatialLayerClose; layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; //layer->vtable->LayerSetTimeFilter = msOracleSpatialLayerSetTimeFilter; //layer->vtable->LayerEscapePropertyName = msOracleSpatialEscapePropertyName; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection = msOracleSpatialLayerGetAutoProjection; Disabled until tested */ layer->vtable->LayerEnablePaging = msOracleSpatialEnablePaging; layer->vtable->LayerGetPaging = msOracleSpatialGetPaging; return MS_SUCCESS; } #endif mapserver-7.4.3/mapoutput.c000066400000000000000000001254031357574274700157650ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Various support code related to the outputFormatObj. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include #include "mapserver.h" #include "mapows.h" static outputFormatObj *msAllocOutputFormat( mapObj *map, const char *name, const char *driver ); /************************************************************************* NOTES on outputFormatObj: typedef struct { char *name; char *mimetype; char *driver; int imagemode; // MS_IMAGEMODE_* value. int transparent; int numformatoptions; char **formatoptions; } outputFormatObj; NAME - Associates an internal name with the declaration. The value used has not intrinsic meaning and is just used to associate with the MAP level IMAGETYPE. It is also the "name" used for the format in WMS capabilities documents, and FORMAT= requests. (required) MIMETYPE - The mime type to use for this format. If omitted, the value will be derived from the DRIVER or default to the value for untyped binary data will be used. (optional - may be NULL) DRIVER - This indicates which internal driver mechanism is to be used. Anything prefixed by "GDAL/" will be handled by the GDAL driver, with the remainder taken as the GDAL format name. (required) IMAGEMODE - Has one of "PC256", "RGB", or "RGBA" indicating whether the imaging should be done to a 256 pseudo-colored, 24bit RGB, or 32bit RGBA (A=alpha/transparency) result image. Note that the IMAGEMODE actually affects how all the rendering for the map is done, long before it is output to a particular output format. The default value is the traditional "PC256". Some output formats can only support some IMAGEMODE values. (optional) Translate as MS_IMAGEMODE_PC256, MS_IMAGEMODE_RGB and MS_IMAGEMODE_RGBA. For "GDAL/" drivers, the following extra imagemodes are supported: "BYTE" / MS_IMAGEMODE_BYTE "INT16" / MS_IMAGEMODE_INT16 "FLOAT32" / MS_IMAGEMODE_FLOAT32 Not too sure what this should be set to for output formats like flash and SVG. TRANSPARENT - A value of "ON" or "OFF" indicating whether transparency support should be enabled. Same as the old TRANSPARENT flag at the MAP level. FORMATOPTION - Contains an argument for the specific driver used. There may be any number of format options for a given OUTPUTFORMAT declaration. FORMATOPTION will be used to encode the older INTERLACE, and QUALITY values. Handled as a MapServer style CharArray. *************************************************************************/ struct defaultOutputFormatEntry { const char *name; const char *driver; const char *mimetype; } ; struct defaultOutputFormatEntry defaultoutputformats[] = { {"png","AGG/PNG","image/png"}, {"jpeg","AGG/JPEG","image/jpeg"}, {"png8","AGG/PNG8","image/png; mode=8bit"}, {"png24","AGG/PNG","image/png; mode=24bit"}, {"jpegpng", "AGG/MIXED", "image/vnd.jpeg-png"}, {"jpegpng8", "AGG/MIXED", "image/vnd.jpeg-png8"}, #ifdef USE_CAIRO {"pdf","CAIRO/PDF","application/x-pdf"}, {"svg","CAIRO/SVG","image/svg+xml"}, {"cairopng","CAIRO/PNG","image/png"}, #endif #ifdef USE_GDAL {"GTiff","GDAL/GTiff","image/tiff"}, #endif #ifdef USE_KML {"kml","KML","application/vnd.google-earth.kml+xml"}, {"kmz","KMZ","application/vnd.google-earth.kmz"}, #endif #ifdef USE_PBF {"mvt","MVT","application/vnd.mapbox-vector-tile"}, #endif {"json","UTFGrid","application/json"}, {NULL,NULL,NULL} }; /************************************************************************/ /* msPostMapParseOutputFormatSetup() */ /************************************************************************/ int msPostMapParseOutputFormatSetup( mapObj *map ) { outputFormatObj *format; /* If IMAGETYPE not set use the first user defined OUTPUTFORMAT. If none, use the first default format. */ if( map->imagetype == NULL && map->numoutputformats > 0 ) map->imagetype = msStrdup(map->outputformatlist[0]->name); if( map->imagetype == NULL) map->imagetype = msStrdup(defaultoutputformats[0].name); /* select the current outputformat into map->outputformat */ format = msSelectOutputFormat( map, map->imagetype ); if( format == NULL ) { msSetError(MS_MISCERR, "Unable to select IMAGETYPE `%s'.", "msPostMapParseOutputFormatSetup()", map->imagetype ? map->imagetype : "(null)" ); return MS_FAILURE; } msApplyOutputFormat( &(map->outputformat), format, map->transparent, map->interlace, map->imagequality ); return MS_SUCCESS; } /************************************************************************/ /* msCreateDefaultOutputFormat() */ /************************************************************************/ outputFormatObj *msCreateDefaultOutputFormat( mapObj *map, const char *driver, const char *name ) { outputFormatObj *format = NULL; if( strncasecmp(driver,"GD/",3) == 0 ) { return msCreateDefaultOutputFormat( map, "AGG/PNG8", name ); } if( strcasecmp(driver,"UTFGRID") == 0 ) { if(!name) name="utfgrid"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("application/json"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("json"); format->renderer = MS_RENDER_WITH_UTFGRID; } else if( strcasecmp(driver,"AGG/PNG") == 0 ) { if(!name) name="png24"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_AGG; } else if( strcasecmp(driver,"AGG/PNG8") == 0 ) { if(!name) name="png8"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png; mode=8bit"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_AGG; msSetOutputFormatOption( format, "QUANTIZE_FORCE", "on"); msSetOutputFormatOption( format, "QUANTIZE_COLORS", "256"); } else if( strcasecmp(driver,"AGG/JPEG") == 0 ) { if(!name) name="jpeg"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/jpeg"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("jpg"); format->renderer = MS_RENDER_WITH_AGG; } #if defined(USE_PBF) else if( strcasecmp(driver,"MVT") == 0 ) { if(!name) name="mvt"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("application/x-protobuf"); format->imagemode = MS_IMAGEMODE_FEATURE; format->extension = msStrdup("pbf"); format->renderer = MS_RENDER_WITH_MVT; } #endif else if( strcasecmp(driver,"AGG/MIXED") == 0 && name != NULL && strcasecmp(name,"jpegpng") == 0 ) { format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/vnd.jpeg-png"); format->imagemode = MS_IMAGEMODE_RGBA; format->extension = msStrdup("XXX"); format->renderer = MS_RENDER_WITH_AGG; msSetOutputFormatOption( format, "OPAQUE_FORMAT", "jpeg"); msSetOutputFormatOption( format, "TRANSPARENT_FORMAT", "png24"); } else if( strcasecmp(driver,"AGG/MIXED") == 0 && name != NULL && strcasecmp(name,"jpegpng8") == 0 ) { format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/vnd.jpeg-png8"); format->imagemode = MS_IMAGEMODE_RGBA; format->extension = msStrdup("XXX"); format->renderer = MS_RENDER_WITH_AGG; msSetOutputFormatOption( format, "OPAQUE_FORMAT", "jpeg"); msSetOutputFormatOption( format, "TRANSPARENT_FORMAT", "png8"); } else if( strcasecmp(driver,"AGG/MIXED") == 0 ) { if(!name) name="mixed"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/mixed"); format->imagemode = MS_IMAGEMODE_RGBA; format->extension = msStrdup("XXX"); format->renderer = MS_RENDER_WITH_AGG; } #if defined(USE_CAIRO) else if( strcasecmp(driver,"CAIRO/PNG") == 0 ) { if(!name) name="cairopng"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png; mode=24bit"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_CAIRO_RASTER; } else if( strcasecmp(driver,"CAIRO/JPEG") == 0 ) { if(!name) name="cairojpeg"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/jpeg"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("jpg"); format->renderer = MS_RENDER_WITH_CAIRO_RASTER; } else if( strcasecmp(driver,"CAIRO/PDF") == 0 ) { if(!name) name="pdf"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("application/x-pdf"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("pdf"); format->renderer = MS_RENDER_WITH_CAIRO_PDF; } else if( strcasecmp(driver,"CAIRO/SVG") == 0 ) { if(!name) name="svg"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/svg+xml"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("svg"); format->renderer = MS_RENDER_WITH_CAIRO_SVG; } #ifdef _WIN32 else if( strcasecmp(driver,"CAIRO/WINGDI") == 0 ) { if(!name) name="cairowinGDI"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup(""); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup(""); format->renderer = MS_RENDER_WITH_CAIRO_RASTER; } else if( strcasecmp(driver,"CAIRO/WINGDIPRINT") == 0 ) { if(!name) name="cairowinGDIPrint"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup(""); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup(""); format->renderer = MS_RENDER_WITH_CAIRO_RASTER; } #endif #endif #if defined(USE_OGL) else if( strcasecmp(driver,"OGL/PNG") == 0 ) { if(!name) name="oglpng24"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("image/png; mode=24bit"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("png"); format->renderer = MS_RENDER_WITH_OGL; } #endif #if defined(USE_KML) else if( strcasecmp(driver,"KML") == 0 ) { if(!name) name="kml"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("application/vnd.google-earth.kml+xml"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("kml"); format->renderer = MS_RENDER_WITH_KML; msSetOutputFormatOption( format, "ATTACHMENT", "mapserver.kml"); } else if( strcasecmp(driver,"KMZ") == 0 ) { if(!name) name="kmz"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("application/vnd.google-earth.kmz"); format->imagemode = MS_IMAGEMODE_RGB; format->extension = msStrdup("kmz"); format->renderer = MS_RENDER_WITH_KML; msSetOutputFormatOption( format, "ATTACHMENT", "mapserver.kmz"); } #endif #ifdef USE_GDAL else if( strncasecmp(driver,"gdal/",5) == 0 ) { if(!name) name=driver+5; format = msAllocOutputFormat( map, name, driver ); if( msInitDefaultGDALOutputFormat( format ) == MS_FAILURE ) { if( map != NULL ) { map->numoutputformats--; map->outputformatlist[map->numoutputformats] = NULL; } msFreeOutputFormat( format ); format = NULL; } } #endif #ifdef USE_OGR else if( strncasecmp(driver,"ogr/",4) == 0 ) { if(!name) name=driver+4; format = msAllocOutputFormat( map, name, driver ); if( msInitDefaultOGROutputFormat( format ) == MS_FAILURE ) { if( map != NULL ) { map->numoutputformats--; map->outputformatlist[map->numoutputformats] = NULL; } msFreeOutputFormat( format ); format = NULL; } } #endif else if( strcasecmp(driver,"imagemap") == 0 ) { if(!name) name="imagemap"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("text/html; driver=imagemap"); format->extension = msStrdup("html"); format->imagemode = MS_IMAGEMODE_NULL; format->renderer = MS_RENDER_WITH_IMAGEMAP; } else if( strcasecmp(driver,"template") == 0 ) { if(!name) name="template"; format = msAllocOutputFormat( map, name, driver ); format->mimetype = msStrdup("text/html"); format->extension = msStrdup("html"); format->imagemode = MS_IMAGEMODE_FEATURE; format->renderer = MS_RENDER_WITH_TEMPLATE; } if( format != NULL ) format->inmapfile = MS_FALSE; return format; } /************************************************************************/ /* msApplyDefaultOutputFormats() */ /************************************************************************/ void msApplyDefaultOutputFormats( mapObj *map ) { char *saved_imagetype; struct defaultOutputFormatEntry *defEntry; if( map->imagetype == NULL ) saved_imagetype = NULL; else saved_imagetype = msStrdup(map->imagetype); defEntry = defaultoutputformats; while(defEntry->name) { if( msSelectOutputFormat( map, defEntry->name ) == NULL ) msCreateDefaultOutputFormat( map, defEntry->driver, defEntry->name ); defEntry++; } if( map->imagetype != NULL ) free( map->imagetype ); map->imagetype = saved_imagetype; } /************************************************************************/ /* msFreeOutputFormat() */ /************************************************************************/ void msFreeOutputFormat( outputFormatObj *format ) { if( format == NULL ) return; if( MS_REFCNT_DECR_IS_NOT_ZERO(format) ) { return; } if(MS_RENDERER_PLUGIN(format) && format->vtable) { format->vtable->cleanup(MS_RENDERER_CACHE(format->vtable)); free( format->vtable ); } msFree( format->name ); msFree( format->mimetype ); msFree( format->driver ); msFree( format->extension ); msFreeCharArray( format->formatoptions, format->numformatoptions ); msFree( format ); } /************************************************************************/ /* msAllocOutputFormat() */ /************************************************************************/ static outputFormatObj *msAllocOutputFormat( mapObj *map, const char *name, const char *driver ) { outputFormatObj *format; /* -------------------------------------------------------------------- */ /* Allocate the format object. */ /* -------------------------------------------------------------------- */ format = (outputFormatObj *) calloc(1,sizeof(outputFormatObj)); if( format == NULL ) { msSetError( MS_MEMERR, NULL, "msAllocOutputFormat()" ); return NULL; } /* -------------------------------------------------------------------- */ /* Initialize various fields. */ /* -------------------------------------------------------------------- */ format->bands = 1; format->name = msStrdup(name); format->driver = msStrdup(driver); format->refcount = 0; format->vtable = NULL; format->device = NULL; format->imagemode = MS_IMAGEMODE_RGB; /* -------------------------------------------------------------------- */ /* Attach to map. */ /* -------------------------------------------------------------------- */ if( map != NULL ) { map->numoutputformats++; if( map->outputformatlist == NULL ) map->outputformatlist = (outputFormatObj **) malloc(sizeof(void*)); else map->outputformatlist = (outputFormatObj **) realloc(map->outputformatlist, sizeof(void*) * map->numoutputformats ); map->outputformatlist[map->numoutputformats-1] = format; format->refcount++; } return format; } /************************************************************************/ /* msAppendOutputFormat() */ /* */ /* Add an output format . */ /* http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=511 */ /************************************************************************/ int msAppendOutputFormat(mapObj *map, outputFormatObj *format) { /* -------------------------------------------------------------------- */ /* Attach to map. */ /* -------------------------------------------------------------------- */ assert(map); map->numoutputformats++; if (map->outputformatlist == NULL) map->outputformatlist = (outputFormatObj **) malloc(sizeof(void*)); else map->outputformatlist = (outputFormatObj **) realloc(map->outputformatlist, sizeof(void*) * map->numoutputformats ); map->outputformatlist[map->numoutputformats-1] = format; MS_REFCNT_INCR(format); return map->numoutputformats; } /************************************************************************/ /* msRemoveOutputFormat() */ /* */ /* Remove an output format (by name). */ /* http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=511 */ /************************************************************************/ int msRemoveOutputFormat(mapObj *map, const char *name) { int i, j; /* -------------------------------------------------------------------- */ /* Detach from map. */ /* -------------------------------------------------------------------- */ if (map != NULL) { if (map->outputformatlist == NULL) { msSetError(MS_CHILDERR, "Can't remove format from empty outputformatlist", "msRemoveOutputFormat()"); return MS_FAILURE; } else { i = msGetOutputFormatIndex(map, name); if (i >= 0) { map->numoutputformats--; if(MS_REFCNT_DECR_IS_ZERO(map->outputformatlist[i])) msFreeOutputFormat( map->outputformatlist[i] ); for (j=i; jnumoutputformats-1; j++) { map->outputformatlist[j] = map->outputformatlist[j+1]; } } map->outputformatlist = (outputFormatObj **) realloc(map->outputformatlist, sizeof(void*) * (map->numoutputformats) ); return MS_SUCCESS; } } return MS_FAILURE; } /************************************************************************/ /* msGetOutputFormatIndex() */ /* */ /* Pulled this out of msSelectOutputFormat for use in other cases. */ /************************************************************************/ int msGetOutputFormatIndex(mapObj *map, const char *imagetype) { int i; /* -------------------------------------------------------------------- */ /* Try to find the format in the maps list of formats, first by */ /* mime type, and then by output format name. */ /* -------------------------------------------------------------------- */ for (i = 0; i < map->numoutputformats; i++) { if (map->outputformatlist[i]->mimetype != NULL && strcasecmp(imagetype, map->outputformatlist[i]->mimetype) == 0 ) return i; } for( i = 0; i < map->numoutputformats; i++ ) { if( strcasecmp(imagetype,map->outputformatlist[i]->name) == 0 ) return i; } return -1; } /************************************************************************/ /* msSelectOutputFormat() */ /************************************************************************/ outputFormatObj *msSelectOutputFormat( mapObj *map, const char *imagetype ) { int index; outputFormatObj *format = NULL; if( map == NULL || imagetype == NULL || strlen(imagetype) == 0 ) return NULL; /* -------------------------------------------------------------------- */ /* Try to find the format in the maps list of formats, first by */ /* mime type, and then by output format name. */ /* -------------------------------------------------------------------- */ index = msGetOutputFormatIndex(map, imagetype); if (index >= 0) { format = map->outputformatlist[index]; } else { struct defaultOutputFormatEntry *formatEntry = defaultoutputformats; while(formatEntry->name) { if(!strcasecmp(imagetype,formatEntry->name) || !strcasecmp(imagetype,formatEntry->mimetype)) { format = msCreateDefaultOutputFormat( map, formatEntry->driver, formatEntry->name ); break; } formatEntry++; } } if (format) { if (map->imagetype) free(map->imagetype); map->imagetype = msStrdup(format->name); } if( format != NULL ) msOutputFormatValidate( format, MS_FALSE ); return format; } /************************************************************************/ /* msApplyOutputFormat() */ /************************************************************************/ void msApplyOutputFormat( outputFormatObj **target, outputFormatObj *format, int transparent, int interlaced, int imagequality ) { int change_needed = MS_FALSE; int old_imagequality, old_interlaced; outputFormatObj *formatToFree = NULL; assert( target != NULL ); if( *target != NULL && MS_REFCNT_DECR_IS_ZERO( (*target) ) ) { formatToFree = *target; *target = NULL; } if( format == NULL ) { if( formatToFree ) msFreeOutputFormat( formatToFree ); *target = NULL; return; } msOutputFormatValidate( format, MS_FALSE ); /* -------------------------------------------------------------------- */ /* Do we need to change any values? If not, then just apply */ /* and return. */ /* -------------------------------------------------------------------- */ if( transparent != MS_NOOVERRIDE && !format->transparent != !transparent ) change_needed = MS_TRUE; old_imagequality = atoi(msGetOutputFormatOption( format, "QUALITY", "75")); if( imagequality != MS_NOOVERRIDE && old_imagequality != imagequality ) change_needed = MS_TRUE; old_interlaced = strcasecmp(msGetOutputFormatOption( format, "INTERLACE", "ON"), "OFF") != 0; if( interlaced != MS_NOOVERRIDE && !interlaced != !old_interlaced ) change_needed = MS_TRUE; if( change_needed ) { char new_value[128]; if( format->refcount > 0 ) format = msCloneOutputFormat( format ); if( transparent != MS_NOOVERRIDE ) { format->transparent = transparent; if( format->imagemode == MS_IMAGEMODE_RGB ) format->imagemode = MS_IMAGEMODE_RGBA; } if( imagequality != MS_NOOVERRIDE && imagequality != old_imagequality ) { snprintf( new_value, sizeof(new_value), "%d", imagequality ); msSetOutputFormatOption( format, "QUALITY", new_value ); } if( interlaced != MS_NOOVERRIDE && !interlaced != !old_interlaced ) { if( interlaced ) msSetOutputFormatOption( format, "INTERLACE", "ON" ); else msSetOutputFormatOption( format, "INTERLACE", "OFF" ); } } *target = format; format->refcount++; if( MS_RENDERER_PLUGIN(format) ) { msInitializeRendererVTable(format); } if( formatToFree ) msFreeOutputFormat( formatToFree ); } /************************************************************************/ /* msCloneOutputFormat() */ /************************************************************************/ outputFormatObj *msCloneOutputFormat( outputFormatObj *src ) { outputFormatObj *dst; int i; dst = msAllocOutputFormat( NULL, src->name, src->driver ); msFree( dst->mimetype ); if( src->mimetype ) dst->mimetype = msStrdup( src->mimetype ); else dst->mimetype = NULL; msFree( dst->extension ); if( src->extension ) dst->extension = msStrdup( src->extension ); else dst->extension = NULL; dst->imagemode = src->imagemode; dst->renderer = src->renderer; dst->transparent = src->transparent; dst->bands = src->bands; dst->numformatoptions = src->numformatoptions; dst->formatoptions = (char **) malloc(sizeof(char *) * src->numformatoptions ); for( i = 0; i < src->numformatoptions; i++ ) dst->formatoptions[i] = msStrdup(src->formatoptions[i]); dst->inmapfile = src->inmapfile; return dst; } /************************************************************************/ /* msGetOutputFormatOption() */ /* */ /* Fetch the value of a particular option. It is assumed the */ /* options are in "KEY=VALUE" format. */ /************************************************************************/ const char *msGetOutputFormatOption( outputFormatObj *format, const char *optionkey, const char *defaultresult ) { int i, len = strlen(optionkey); for( i = 0; i < format->numformatoptions; i++ ) { if( strncasecmp(format->formatoptions[i],optionkey,len) == 0 && format->formatoptions[i][len] == '=' ) return format->formatoptions[i] + len + 1; } return defaultresult; } /************************************************************************/ /* msSetOutputFormatOption() */ /************************************************************************/ void msSetOutputFormatOption( outputFormatObj *format, const char *key, const char *value ) { char *newline; int i, len; if( value == NULL ) return; /* -------------------------------------------------------------------- */ /* Format the name=value pair into a newly allocated string. */ /* -------------------------------------------------------------------- */ newline = (char *) malloc(strlen(key)+strlen(value)+2); if( newline == NULL ) { assert( newline != NULL ); return; } sprintf( newline, "%s=%s", key, value ); /* -------------------------------------------------------------------- */ /* Does this key already occur? If so replace it. */ /* -------------------------------------------------------------------- */ len = strlen(key); for( i = 0; i < format->numformatoptions; i++ ) { if( strncasecmp(format->formatoptions[i],key,len) == 0 && format->formatoptions[i][len] == '=' ) { free( format->formatoptions[i] ); format->formatoptions[i] = newline; return; } } /* -------------------------------------------------------------------- */ /* otherwise, we need to grow the list. */ /* -------------------------------------------------------------------- */ format->numformatoptions++; format->formatoptions = (char **) realloc( format->formatoptions, sizeof(char*) * format->numformatoptions ); format->formatoptions[format->numformatoptions-1] = newline; /* -------------------------------------------------------------------- */ /* Capture generic value(s) we are interested in. */ /* -------------------------------------------------------------------- */ if( strcasecmp(key,"BAND_COUNT") == 0 ) format->bands = atoi(value); } /************************************************************************/ /* msGetOutputFormatMimeList() */ /************************************************************************/ void msGetOutputFormatMimeList( mapObj *map, char **mime_list, int max_mime ) { int mime_count = 0, i; msApplyDefaultOutputFormats(map); for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ ) { int j; if( map->outputformatlist[i]->mimetype == NULL ) continue; for( j = 0; j < mime_count; j++ ) { if( strcasecmp(mime_list[j], map->outputformatlist[i]->mimetype) == 0 ) break; } if( j == mime_count ) mime_list[mime_count++] = map->outputformatlist[i]->mimetype; } if( mime_count < max_mime ) mime_list[mime_count] = NULL; } /************************************************************************/ /* msGetOutputFormatMimeList() */ /************************************************************************/ void msGetOutputFormatMimeListImg( mapObj *map, char **mime_list, int max_mime ) { int mime_count = 0, i,j; const char *format_list = NULL; char **tokens = NULL; int numtokens = 0; outputFormatObj *format; msApplyDefaultOutputFormats(map); format_list = msOWSLookupMetadata(&(map->web.metadata), "M","getlegendgraphic_formatlist"); if ( format_list && strlen(format_list) > 0) tokens = msStringSplit(format_list, ',', &numtokens); if (tokens && numtokens > 0) { for(j = 0; j < numtokens; j++ ) { format = msSelectOutputFormat(map, tokens[j]); if (format != NULL) { mime_list[mime_count++] = format->mimetype; } } } else for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ ) { int j; if( map->outputformatlist[i]->mimetype == NULL ) continue; for( j = 0; j < mime_count; j++ ) { if( strcasecmp(mime_list[j], map->outputformatlist[i]->mimetype) == 0 ) break; } if( j == mime_count && map->outputformatlist[i]->driver && strncasecmp(map->outputformatlist[i]->driver, "AGG/", 4)==0) mime_list[mime_count++] = map->outputformatlist[i]->mimetype; } if( mime_count < max_mime ) mime_list[mime_count] = NULL; if(tokens) msFreeCharArray(tokens, numtokens); } /************************************************************************/ /* msGetOutputFormatMimeListWMS() */ /************************************************************************/ void msGetOutputFormatMimeListWMS( mapObj *map, char **mime_list, int max_mime ) { int mime_count = 0, i,j; const char *format_list = NULL; char **tokens = NULL; int numtokens = 0; outputFormatObj *format; msApplyDefaultOutputFormats(map); format_list = msOWSLookupMetadata(&(map->web.metadata), "M","getmap_formatlist"); if ( format_list && strlen(format_list) > 0) tokens = msStringSplit(format_list, ',', &numtokens); if (tokens && numtokens > 0) { for(j = 0; j < numtokens; j++ ) { format = msSelectOutputFormat(map, tokens[j]); if (format != NULL) { mime_list[mime_count++] = format->mimetype; } } } else { for( i = 0; i < map->numoutputformats && mime_count < max_mime; i++ ) { int j; if( map->outputformatlist[i]->mimetype == NULL ) continue; for( j = 0; j < mime_count; j++ ) { if( strcasecmp(mime_list[j], map->outputformatlist[i]->mimetype) == 0 ) break; } if( j == mime_count && map->outputformatlist[i]->driver && ( strncasecmp(map->outputformatlist[i]->driver, "GDAL/", 5)==0 || strncasecmp(map->outputformatlist[i]->driver, "AGG/", 4)==0 || strcasecmp(map->outputformatlist[i]->driver, "CAIRO/SVG")==0 || strcasecmp(map->outputformatlist[i]->driver, "CAIRO/PDF")==0 || strcasecmp(map->outputformatlist[i]->driver, "kml")==0 || strcasecmp(map->outputformatlist[i]->driver, "kmz")==0 || strcasecmp(map->outputformatlist[i]->driver, "mvt")==0 || strcasecmp(map->outputformatlist[i]->driver, "UTFGRID")==0)) mime_list[mime_count++] = map->outputformatlist[i]->mimetype; } } if( mime_count < max_mime ) mime_list[mime_count] = NULL; if(tokens) msFreeCharArray(tokens, numtokens); } /************************************************************************/ /* msOutputFormatValidate() */ /* */ /* Do some validation of the output format, and report to debug */ /* output if it doesn't seem valid. Fixup in place as best as */ /* possible. */ /************************************************************************/ int msOutputFormatValidate( outputFormatObj *format, int issue_error ) { int result = MS_TRUE; char *driver_ext; format->bands = atoi(msGetOutputFormatOption( format, "BAND_COUNT", "1" )); /* Enforce the requirement that JPEG be RGB and TRANSPARENT=OFF */ driver_ext = strstr(format->driver,"/"); if( driver_ext && ++driver_ext && !strcasecmp(driver_ext,"JPEG")) { if( format->transparent ) { if( issue_error ) msSetError( MS_MISCERR, "JPEG OUTPUTFORMAT %s has TRANSPARENT set ON, but this is not supported.\n" "It has been disabled.\n", "msOutputFormatValidate()", format->name ); else msDebug( "JPEG OUTPUTFORMAT %s has TRANSPARENT set ON, but this is not supported.\n" "It has been disabled.\n", format->name ); format->transparent = MS_FALSE; result = MS_FALSE; } if( format->imagemode == MS_IMAGEMODE_RGBA ) { if( issue_error ) msSetError( MS_MISCERR, "JPEG OUTPUTFORMAT %s has IMAGEMODE RGBA, but this is not supported.\n" "IMAGEMODE forced to RGB.\n", "msOutputFormatValidate()", format->name ); else msDebug( "JPEG OUTPUTFORMAT %s has IMAGEMODE RGBA, but this is not supported.\n" "IMAGEMODE forced to RGB.\n", format->name ); format->imagemode = MS_IMAGEMODE_RGB; result = MS_FALSE; } } if( format->transparent && format->imagemode == MS_IMAGEMODE_RGB ) { if( issue_error ) msSetError( MS_MISCERR, "OUTPUTFORMAT %s has TRANSPARENT set ON, but an IMAGEMODE\n" "of RGB instead of RGBA. Changing imagemode to RGBA.\n", "msOutputFormatValidate()", format->name ); else msDebug("OUTPUTFORMAT %s has TRANSPARENT set ON, but an IMAGEMODE\n" "of RGB instead of RGBA. Changing imagemode to RGBA.\n", format->name ); format->imagemode = MS_IMAGEMODE_RGBA; result = MS_FALSE; } /* Special checking around RAWMODE image modes. */ if( format->imagemode == MS_IMAGEMODE_INT16 || format->imagemode == MS_IMAGEMODE_FLOAT32 || format->imagemode == MS_IMAGEMODE_BYTE ) { if( strncmp(format->driver,"GDAL/",5) != 0 ) { result = MS_FALSE; if( issue_error ) msSetError( MS_MISCERR, "OUTPUTFORMAT %s has IMAGEMODE BYTE/INT16/FLOAT32, but this is only supported for GDAL drivers.", "msOutputFormatValidate()", format->name ); else msDebug( "OUTPUTFORMAT %s has IMAGEMODE BYTE/INT16/FLOAT32, but this is only supported for GDAL drivers.", format->name ); } if( format->renderer != MS_RENDER_WITH_RAWDATA ) /* see bug 724 */ format->renderer = MS_RENDER_WITH_RAWDATA; } if( !strcasecmp(format->driver,"AGG/MIXED") ) { if( !msGetOutputFormatOption(format, "TRANSPARENT_FORMAT", NULL) ) { result = MS_FALSE; if( issue_error ) msSetError( MS_MISCERR, "OUTPUTFORMAT %s lacks a 'TRANSPARENT_FORMAT' FORMATOPTION.", "msOutputFormatValidate()", format->name ); else msDebug( "OUTPUTFORMAT %s lacks a 'TRANSPARENT_FORMAT' FORMATOPTION.", format->name ); } if( !msGetOutputFormatOption(format, "OPAQUE_FORMAT", NULL) ) { result = MS_FALSE; if( issue_error ) msSetError( MS_MISCERR, "OUTPUTFORMAT %s lacks a 'OPAQUE_FORMAT' FORMATOPTION.", "msOutputFormatValidate()", format->name ); else msDebug( "OUTPUTFORMAT %s lacks a 'OPAQUE_FORMAT' FORMATOPTION.", format->name ); } } return result; } /************************************************************************/ /* msInitializeRendererVTable() */ /************************************************************************/ int msInitializeRendererVTable(outputFormatObj *format) { assert(format); if(format->vtable) { return MS_SUCCESS; } format->vtable = (rendererVTableObj*)calloc(1,sizeof(rendererVTableObj)); msInitializeDummyRenderer(format->vtable); switch(format->renderer) { case MS_RENDER_WITH_AGG: return msPopulateRendererVTableAGG(format->vtable); case MS_RENDER_WITH_UTFGRID: return msPopulateRendererVTableUTFGrid(format->vtable); #ifdef USE_PBF case MS_RENDER_WITH_MVT: return msPopulateRendererVTableMVT(format->vtable); #endif #ifdef USE_CAIRO case MS_RENDER_WITH_CAIRO_RASTER: return msPopulateRendererVTableCairoRaster(format->vtable); case MS_RENDER_WITH_CAIRO_PDF: return msPopulateRendererVTableCairoPDF(format->vtable); case MS_RENDER_WITH_CAIRO_SVG: return msPopulateRendererVTableCairoSVG(format->vtable); #endif #ifdef USE_OGL case MS_RENDER_WITH_OGL: return msPopulateRendererVTableOGL(format->vtable); #endif #ifdef USE_KML case MS_RENDER_WITH_KML: return msPopulateRendererVTableKML(format->vtable); #endif #ifdef USE_OGR case MS_RENDER_WITH_OGR: return msPopulateRendererVTableOGR(format->vtable); #endif default: msSetError(MS_MISCERR, "unsupported RendererVtable renderer %d", "msInitializeRendererVTable()",format->renderer); return MS_FAILURE; } /* this code should never be executed */ return MS_FAILURE; } /************************************************************************/ /* msOutputFormatResolveFromImage() */ /************************************************************************/ void msOutputFormatResolveFromImage( mapObj *map, imageObj* img ) { outputFormatObj* format = map->outputformat; assert( img->format == format ); assert( img->format->refcount >= 2 ); if( format->renderer == MS_RENDER_WITH_AGG && strcmp(format->driver, "AGG/MIXED") == 0 && (format->imagemode == MS_IMAGEMODE_RGB || format->imagemode == MS_IMAGEMODE_RGBA) ) { outputFormatObj * new_format; int has_non_opaque_pixels = MS_FALSE; const char* underlying_driver_type = NULL; const char* underlying_driver_name = NULL; // Check if the image has non opaque pixels if( format->imagemode == MS_IMAGEMODE_RGBA ) { rasterBufferObj rb; int ret; ret = format->vtable->getRasterBufferHandle(img,&rb); assert( ret == MS_SUCCESS ); if( rb.data.rgba.a ) { int row; for(row=0; rowname ); return; } new_format = msSelectOutputFormat( map, underlying_driver_name ); if( new_format == NULL ) { msSetError(MS_MISCERR, "Cannot find %s output format.", "msOutputFormatResolveFromImage()", underlying_driver_name ); return; } if( new_format->renderer != MS_RENDER_WITH_AGG ) { msSetError(MS_MISCERR, "%s cannot be used as the %s format of %s since it is not AGG based.", "msOutputFormatResolveFromImage()", underlying_driver_name, underlying_driver_type, format->name ); return; } msApplyOutputFormat( &(map->outputformat), new_format, has_non_opaque_pixels, MS_NOOVERRIDE, MS_NOOVERRIDE ); msFreeOutputFormat( format ); img->format = map->outputformat; img->format->refcount ++; } } mapserver-7.4.3/mapows.c000066400000000000000000003023511357574274700152340ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Web Services (WMS, WFS) support functions * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "maptime.h" #include "maptemplate.h" #include "mapows.h" #if defined(USE_LIBXML2) #include "maplibxml2.h" #elif defined(USE_GDAL) #include "cpl_minixml.h" #include "cpl_error.h" #endif #include "mapowscommon.h" #include /* isalnum() */ #include #include /* ** msOWSInitRequestObj() initializes an owsRequestObj; i.e: sets ** all internal pointers to NULL. */ static void msOWSInitRequestObj(owsRequestObj *ows_request) { ows_request->numlayers = 0; ows_request->enabled_layers = NULL; ows_request->service = NULL; ows_request->version = NULL; ows_request->request = NULL; ows_request->document = NULL; } /* ** msOWSClearRequestObj() releases all resources associated with an ** owsRequestObj. */ static void msOWSClearRequestObj(owsRequestObj *ows_request) { msFree(ows_request->enabled_layers); msFree(ows_request->service); msFree(ows_request->version); msFree(ows_request->request); if(ows_request->document) { #if defined(USE_LIBXML2) xmlFreeDoc(ows_request->document); xmlCleanupParser(); #elif defined(USE_GDAL) CPLDestroyXMLNode(ows_request->document); #endif } } #if defined(USE_LIBXML2) && LIBXML_VERSION < 20900 static int bExternalEntityAsked = MS_FALSE; static xmlParserInputPtr dummyEntityLoader(const char * URL, const char * ID, xmlParserCtxtPtr context ) { bExternalEntityAsked = MS_TRUE; return NULL; } #endif /* ** msOWSPreParseRequest() parses a cgiRequestObj either with GET/KVP ** or with POST/XML. Only SERVICE, VERSION (or WMTVER) and REQUEST are ** being determined, all WxS (or SOS) specific parameters are parsed ** within the according handler. ** The results are saved within an owsRequestObj. If the request was ** transmitted with POST/XML, either the document (if compiled with ** libxml2) or the root CPLXMLNode is saved to the ows_request->document ** field. ** Returns MS_SUCCESS upon success, MS_FAILURE if severe errors occurred ** or MS_DONE, if the service could not be determined. */ static int msOWSPreParseRequest(cgiRequestObj *request, owsRequestObj *ows_request) { /* decide if KVP or XML */ if (request->type == MS_GET_REQUEST || (request->type == MS_POST_REQUEST && request->contenttype && strncmp(request->contenttype, "application/x-www-form-urlencoded", strlen("application/x-www-form-urlencoded")) == 0)) { int i; /* parse KVP parameters service, version and request */ for (i = 0; i < request->NumParams; ++i) { if (ows_request->service == NULL && EQUAL(request->ParamNames[i], "SERVICE")) { ows_request->service = msStrdup(request->ParamValues[i]); } else if (ows_request->version == NULL && (EQUAL(request->ParamNames[i], "VERSION") || EQUAL(request->ParamNames[i], "WMTVER"))) { /* for WMS */ ows_request->version = msStrdup(request->ParamValues[i]); } else if (ows_request->request == NULL && EQUAL(request->ParamNames[i], "REQUEST")) { ows_request->request = msStrdup(request->ParamValues[i]); } /* stop if we have all necessary parameters */ if(ows_request->service && ows_request->version && ows_request->request) { break; } } } else if (request->type == MS_POST_REQUEST) { #if defined(USE_LIBXML2) xmlNodePtr root = NULL; #if LIBXML_VERSION < 20900 xmlExternalEntityLoader oldExternalEntityLoader; #endif #elif defined(USE_GDAL) CPLXMLNode *temp; #endif if (!request->postrequest || !strlen(request->postrequest)) { msSetError(MS_OWSERR, "POST request is empty.", "msOWSPreParseRequest()"); return MS_FAILURE; } #if defined(USE_LIBXML2) #if LIBXML_VERSION < 20900 oldExternalEntityLoader = xmlGetExternalEntityLoader(); /* to avoid XML External Entity vulnerability with libxml2 < 2.9 */ xmlSetExternalEntityLoader (dummyEntityLoader); bExternalEntityAsked = MS_FALSE; #endif /* parse to DOM-Structure with libxml2 and get the root element */ ows_request->document = xmlParseMemory(request->postrequest, strlen(request->postrequest)); #if LIBXML_VERSION < 20900 xmlSetExternalEntityLoader (oldExternalEntityLoader); if( bExternalEntityAsked ) { msSetError(MS_OWSERR, "XML parsing error: %s", "msOWSPreParseRequest()", "External entity fetch"); return MS_FAILURE; } #endif if (ows_request->document == NULL || (root = xmlDocGetRootElement(ows_request->document)) == NULL) { xmlErrorPtr error = xmlGetLastError(); msSetError(MS_OWSERR, "XML parsing error: %s", "msOWSPreParseRequest()", error->message); return MS_FAILURE; } /* Get service, version and request from root */ ows_request->service = (char *) xmlGetProp(root, BAD_CAST "service"); ows_request->version = (char *) xmlGetProp(root, BAD_CAST "version"); ows_request->request = msStrdup((char *) root->name); #elif defined(USE_GDAL) /* parse with CPLXML */ ows_request->document = CPLParseXMLString(request->postrequest); if (ows_request->document == NULL) { msSetError(MS_OWSERR, "XML parsing error: %s", "msOWSPreParseRequest()", CPLGetLastErrorMsg()); return MS_FAILURE; } /* remove all namespaces */ CPLStripXMLNamespace(ows_request->document, NULL, 1); for (temp = ows_request->document; temp != NULL; temp = temp->psNext) { if (temp->eType == CXT_Element) { const char *service, *version; ows_request->request = msStrdup(temp->pszValue); if ((service = CPLGetXMLValue(temp, "service", NULL)) != NULL) { ows_request->service = msStrdup(service); } if ((version = CPLGetXMLValue(temp, "version", NULL)) != NULL) { ows_request->version = msStrdup(version); } continue; } } #else /* could not parse XML since no parser was compiled */ msSetError(MS_OWSERR, "Could not parse the POST XML since MapServer" "was not compiled with libxml2 or GDAL.", "msOWSPreParseRequest()"); return MS_FAILURE; #endif /* defined(USE_LIBXML2) */ } else { msSetError(MS_OWSERR, "Unknown request method. Use either GET or POST.", "msOWSPreParseRequest()"); return MS_FAILURE; } /* certain WMS requests do not require the service parameter */ /* see: http://trac.osgeo.org/mapserver/ticket/2531 */ if (ows_request->service == NULL && ows_request->request != NULL) { if (EQUAL(ows_request->request, "GetMap") || EQUAL(ows_request->request, "GetFeatureInfo")) { ows_request->service = msStrdup("WMS"); } else { /* service could not be determined */ return MS_DONE; } } return MS_SUCCESS; } /* ** msOWSDispatch() is the entry point for any OWS request (WMS, WFS, ...) ** - If this is a valid request then it is processed and MS_SUCCESS is returned ** on success, or MS_FAILURE on failure. ** - If force_ows_mode is true then an exception will be produced if the ** request is not recognized as a valid request. ** - If force_ows_mode is false and this does not appear to be a valid OWS ** request then MS_DONE is returned and MapServer is expected to process ** this as a regular MapServer (traditional CGI) request. */ int msOWSDispatch(mapObj *map, cgiRequestObj *request, int ows_mode) { int status = MS_DONE, force_ows_mode = 0; owsRequestObj ows_request; if (!request) { return status; } force_ows_mode = (ows_mode == OWS || ows_mode == WFS); msOWSInitRequestObj(&ows_request); switch(msOWSPreParseRequest(request, &ows_request)) { case MS_FAILURE: /* a severe error occurred */ return MS_FAILURE; case MS_DONE: /* OWS Service could not be determined */ /* continue for now */ status = MS_DONE; } if (ows_request.service == NULL) { if (ows_request.request && EQUAL(ows_request.request, "GetMetadata")) { status = msMetadataDispatch(map, request, &ows_request); msOWSClearRequestObj(&ows_request); return status; } #ifdef USE_WFS_SVR if( msOWSLookupMetadata(&(map->web.metadata), "FO", "cite_wfs2") != NULL ) { status = msWFSException(map, "service", MS_OWS_ERROR_MISSING_PARAMETER_VALUE, NULL ); } else #endif /* exit if service is not set */ if(force_ows_mode) { msSetError( MS_MISCERR, "OWS Common exception: exceptionCode=MissingParameterValue, locator=SERVICE, ExceptionText=SERVICE parameter missing.", "msOWSDispatch()"); status = MS_FAILURE; } else { status = MS_DONE; } } else if (EQUAL(ows_request.service, "WMS")) { #ifdef USE_WMS_SVR status = msWMSDispatch(map, request, &ows_request, MS_FALSE); #else msSetError( MS_WMSERR, "SERVICE=WMS requested, but WMS support not configured in MapServer.", "msOWSDispatch()" ); #endif } else if (EQUAL(ows_request.service, "WFS")) { #ifdef USE_WFS_SVR status = msWFSDispatch(map, request, &ows_request, (ows_mode == WFS)); #else msSetError( MS_WFSERR, "SERVICE=WFS requested, but WFS support not configured in MapServer.", "msOWSDispatch()" ); #endif } else if (EQUAL(ows_request.service, "WCS")) { #ifdef USE_WCS_SVR status = msWCSDispatch(map, request, &ows_request); #else msSetError( MS_WCSERR, "SERVICE=WCS requested, but WCS support not configured in MapServer.", "msOWSDispatch()" ); #endif } else if (EQUAL(ows_request.service, "SOS")) { #ifdef USE_SOS_SVR status = msSOSDispatch(map, request, &ows_request); #else msSetError( MS_SOSERR, "SERVICE=SOS requested, but SOS support not configured in MapServer.", "msOWSDispatch()" ); #endif } else if(force_ows_mode) { msSetError( MS_MISCERR, "OWS Common exception: exceptionCode=InvalidParameterValue, locator=SERVICE, ExceptionText=SERVICE parameter value invalid.", "msOWSDispatch()"); status = MS_FAILURE; } msOWSClearRequestObj(&ows_request); return status; } /* ** msOWSIpParse() ** ** Parse the IP address or range into a binary array. ** Supports ipv4 and ipv6 addresses ** Ranges can be specified using the CIDR notation (ie: 192.100.100.0/24) ** ** Returns the parsed of the IP (4 or 16). */ int msOWSIpParse(const char* ip, unsigned char* ip1, unsigned char* mask) { int len = 0, masklen, seps; if (msCountChars((char*)ip, '.') == 3) { /* ipv4 */ unsigned char* val = ip1; len = 1; masklen = 32; *val = 0; while (*ip) { if (*ip >= '0' && *ip <= '9') (*val) = 10 * (*val) + (*ip - '0'); else if (*ip == '.') { ++val; *val = 0; ++len; } else if (*ip == '/') { masklen = atoi(ip+1); if (masklen > 32) masklen = 32; break; } else break; ++ip; } if (len != 4) return 0; /* write mask */ if (mask) { memset(mask, 0, len); val = mask; while (masklen) { if (masklen >= 8) { *val = 0xff; masklen -= 8; } else { *val = - ((unsigned char)pow(2, 8 - masklen)); break; } ++val; } } } else if ((seps = msCountChars((char*)ip, ':')) > 1 && seps < 8) { /* ipv6 */ unsigned short* val = (unsigned short*)ip1; len = 2; masklen = 128; *val = 0; while (*ip) { if (*ip >= '0' && *ip <= '9') (*val) = 16 * (*val) + (*ip - '0'); else if (*ip >= 'a' && *ip <= 'f') (*val) = 16 * (*val) + (*ip - 'a' + 10); else if (*ip >= 'A' && *ip <= 'F') (*val) = 16 * (*val) + (*ip - 'A' + 10); else if (*ip == ':') { ++ip; ++val; len += 2; *val = 0; if (*ip == ':') { /* insert 0 values */ while (seps <= 7) { ++val; len += 2; *val = 0; ++seps; } } else continue; } else if (*ip == '/') { masklen = atoi(ip+1); if (masklen > 128) masklen = 128; break; } else break; ++ip; } if (len != 16) return 0; /* write mask */ if (mask) { memset(mask, 0, len); val = (unsigned short*)mask; while (masklen) { if (masklen >= 16) { *val = 0xffff; masklen -= 16; } else { *val = - ((unsigned short)pow(2, 16 - masklen)); break; } ++val; } } } return len; } /* ** msOWSIpInList() ** ** Check if an ip is in a space separated list of IP addresses/ranges. ** Supports ipv4 and ipv6 addresses ** Ranges can be specified using the CIDR notation (ie: 192.100.100.0/24) ** ** Returns MS_TRUE if the IP is found. */ int msOWSIpInList(const char *ip_list, const char* ip) { int i, j, numips, iplen; unsigned char ip1[16]; unsigned char ip2[16]; unsigned char mask[16]; char** ips; /* Parse input IP */ iplen = msOWSIpParse(ip, (unsigned char*)&ip1, NULL); if (iplen != 4 && iplen != 16) /* ipv4 or ipv6 */ return MS_FALSE; ips = msStringSplit(ip_list, ' ', &numips); if (ips) { for (i = 0; i < numips; i++) { if (msOWSIpParse(ips[i], (unsigned char*)&ip2, (unsigned char*)&mask) == iplen) { for (j = 0; j < iplen; j++) { if ((ip1[j] & mask[j]) != (ip2[j] & mask[j])) break; } if (j == iplen) { msFreeCharArray(ips, numips); return MS_TRUE; /* match found */ } } } msFreeCharArray(ips, numips); } return MS_FALSE; } /* ** msOWSIpDisabled() ** ** Check if an ip is in a list specified in the metadata section. ** ** Returns MS_TRUE if the IP is found. */ int msOWSIpInMetadata(const char *ip_list, const char* ip) { FILE *stream; char buffer[MS_BUFFER_LENGTH]; int found = MS_FALSE; if (strncasecmp(ip_list, "file:", 5) == 0) { stream = fopen(ip_list + 5, "r"); if(stream) { found = MS_FALSE; while(fgets(buffer, MS_BUFFER_LENGTH, stream)) { if(msOWSIpInList(buffer, ip)) { found = MS_TRUE; break; } } fclose(stream); } } else { if(msOWSIpInList(ip_list, ip)) found = MS_TRUE; } return found; } /* ** msOWSIpDisabled() ** ** Check if the layers are enabled or disabled by IP list. ** ** 'namespaces' is a string with a letter for each namespace to lookup ** in the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ ** If namespaces is NULL then this function just does a regular metadata ** lookup. ** ** Returns the disabled flag. */ int msOWSIpDisabled(hashTableObj *metadata, const char *namespaces, const char* ip) { const char *ip_list; int disabled = MS_FALSE; if (!ip) return MS_FALSE; /* no endpoint ip */ ip_list = msOWSLookupMetadata(metadata, namespaces, "allowed_ip_list"); if (!ip_list) ip_list = msOWSLookupMetadata(metadata, "O", "allowed_ip_list"); if (ip_list) { disabled = MS_TRUE; if (msOWSIpInMetadata(ip_list, ip)) disabled = MS_FALSE; } ip_list = msOWSLookupMetadata(metadata, namespaces, "denied_ip_list"); if (!ip_list) ip_list = msOWSLookupMetadata(metadata, "O", "denied_ip_list"); if (ip_list && msOWSIpInMetadata(ip_list, ip)) disabled = MS_TRUE; return disabled; } /* ** msOWSRequestIsEnabled() ** ** Check if a layer is visible for a specific OWS request. ** ** 'namespaces' is a string with a letter for each namespace to lookup in ** the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ If ** namespaces is NULL then this function just does a regular metadata ** lookup. If check_all_layers is set to MS_TRUE, the function will check ** all layers to see if the request is enable. (returns as soon as one is found) */ int msOWSRequestIsEnabled(mapObj *map, layerObj *layer, const char *namespaces, const char *request, int check_all_layers) { int disabled = MS_FALSE; /* explicitly disabled flag */ const char *enable_request; const char *remote_ip; if (request == NULL) return MS_FALSE; remote_ip = getenv("REMOTE_ADDR"); /* First, we check in the layer metadata */ if (layer && check_all_layers == MS_FALSE) { enable_request = msOWSLookupMetadata(&layer->metadata, namespaces, "enable_request"); if (msOWSParseRequestMetadata(enable_request, request, &disabled)) return MS_TRUE; if (disabled) return MS_FALSE; enable_request = msOWSLookupMetadata(&layer->metadata, "O", "enable_request"); if (msOWSParseRequestMetadata(enable_request, request, &disabled)) return MS_TRUE; if (disabled) return MS_FALSE; if (msOWSIpDisabled(&layer->metadata, namespaces, remote_ip)) return MS_FALSE; } if (map && (check_all_layers == MS_FALSE || map->numlayers == 0)) { /* then we check in the map metadata */ enable_request = msOWSLookupMetadata(&map->web.metadata, namespaces, "enable_request"); if (msOWSParseRequestMetadata(enable_request, request, &disabled)) return MS_TRUE; if (disabled) return MS_FALSE; enable_request = msOWSLookupMetadata(&map->web.metadata, "O", "enable_request"); if (msOWSParseRequestMetadata(enable_request, request, &disabled)) return MS_TRUE; if (disabled) return MS_FALSE; if (msOWSIpDisabled(&map->web.metadata, namespaces, remote_ip)) return MS_FALSE; } if (map && check_all_layers == MS_TRUE) { int i, globally_enabled = MS_FALSE; enable_request = msOWSLookupMetadata(&map->web.metadata, namespaces, "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!globally_enabled && !disabled) { enable_request = msOWSLookupMetadata(&map->web.metadata, "O", "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, request, &disabled); } if (globally_enabled && msOWSIpDisabled(&map->web.metadata, namespaces, remote_ip)) globally_enabled = MS_FALSE; /* Check all layers */ for(i=0; inumlayers; i++) { int result = MS_FALSE; layerObj *lp; lp = (GET_LAYER(map, i)); enable_request = msOWSLookupMetadata(&lp->metadata, namespaces, "enable_request"); result = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!result && disabled) continue; /* if the request has been explicitly set to disabled, continue */ if (!result && !disabled) { /* if the request has not been found in the wms metadata, */ /* check the ows namespace */ enable_request = msOWSLookupMetadata(&lp->metadata, "O", "enable_request"); result = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!result && disabled) continue; } if (msOWSIpDisabled(&lp->metadata, namespaces, remote_ip)) continue; if (result || (!disabled && globally_enabled)) return MS_TRUE; } if (!disabled && globally_enabled) return MS_TRUE; } return MS_FALSE; } /* ** msOWSRequestLayersEnabled() ** ** Check if the layers are visible for a specific OWS request. ** ** 'namespaces' is a string with a letter for each namespace to lookup ** in the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ ** If namespaces is NULL then this function just does a regular metadata ** lookup. ** ** Generates an array of the layer ids enabled. */ void msOWSRequestLayersEnabled(mapObj *map, const char *namespaces, const char *request, owsRequestObj *ows_request) { int disabled = MS_FALSE; /* explicitly disabled flag */ int globally_enabled = MS_FALSE; const char *enable_request; const char *remote_ip; if (ows_request->numlayers > 0) msFree(ows_request->enabled_layers); ows_request->numlayers = 0; ows_request->enabled_layers = NULL; if (request == NULL || (map == NULL) || (map->numlayers <= 0)) return; remote_ip = getenv("REMOTE_ADDR"); enable_request = msOWSLookupMetadata(&map->web.metadata, namespaces, "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!globally_enabled && !disabled) { enable_request = msOWSLookupMetadata(&map->web.metadata, "O", "enable_request"); globally_enabled = msOWSParseRequestMetadata(enable_request, request, &disabled); } if (globally_enabled && msOWSIpDisabled(&map->web.metadata, namespaces, remote_ip)) globally_enabled = MS_FALSE; if (map->numlayers) { int i, layers_size = map->numlayers; /* for most of cases, this will be relatively small */ ows_request->enabled_layers = (int*)msSmallMalloc(sizeof(int)*layers_size); for(i=0; inumlayers; i++) { int result = MS_FALSE; layerObj *lp; lp = (GET_LAYER(map, i)); enable_request = msOWSLookupMetadata(&lp->metadata, namespaces, "enable_request"); result = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!result && disabled) continue; /* if the request has been explicitly set to disabled, continue */ if (!result && !disabled) { /* if the request has not been found in the wms metadata, */ /* check the ows namespace */ enable_request = msOWSLookupMetadata(&lp->metadata, "O", "enable_request"); result = msOWSParseRequestMetadata(enable_request, request, &disabled); if (!result && disabled) continue; } if (msOWSIpDisabled(&lp->metadata, namespaces, remote_ip)) continue; if (result || (!disabled && globally_enabled)) { ows_request->enabled_layers[ows_request->numlayers] = lp->index; ows_request->numlayers++; } } if (ows_request->numlayers == 0) { msFree(ows_request->enabled_layers); ows_request->enabled_layers = NULL; } } } /* msOWSParseRequestMetadata * * This function parse a enable_request metadata string and check if the * given request is present and enabled. */ int msOWSParseRequestMetadata(const char *metadata, const char *request, int *disabled) { char requestBuffer[32]; int wordFlag = MS_FALSE; int disableFlag = MS_FALSE; int allFlag = MS_FALSE; char *bufferPtr, *ptr = NULL; int i; size_t len = 0; *disabled = MS_FALSE; if (metadata == NULL) return MS_FALSE; ptr = (char*)metadata; len = strlen(ptr); requestBuffer[0] = '\0'; bufferPtr = requestBuffer; for (i=0; i<=len; ++i,++ptr) { if (!wordFlag && isspace(*ptr)) continue; wordFlag = MS_TRUE; if (*ptr == '!') { disableFlag = MS_TRUE; continue; } else if ( (*ptr == ' ') || (*ptr != '\0' && ptr[1] == '\0')) { /* end of word */ if (ptr[1] == '\0' && *ptr != ' ') { *bufferPtr = *ptr; ++bufferPtr; } *bufferPtr = '\0'; if (strcasecmp(request, requestBuffer) == 0) { *disabled = MS_TRUE; /* explicitly found, will stop the process in msOWSRequestIsEnabled() */ return (disableFlag ? MS_FALSE:MS_TRUE); } else { if (strcmp("*", requestBuffer) == 0) { /* check if we read the all flag */ if (disableFlag) *disabled = MS_TRUE; allFlag = disableFlag ? MS_FALSE:MS_TRUE; } /* reset flags */ wordFlag = MS_FALSE; disableFlag = MS_FALSE; bufferPtr = requestBuffer; } } else { *bufferPtr = *ptr; ++bufferPtr; } } return allFlag; } /* ** msOWSLookupMetadata() ** ** Attempts to lookup a given metadata name in multiple OWS namespaces. ** ** 'namespaces' is a string with a letter for each namespace to lookup ** in the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ ** If namespaces is NULL then this function just does a regular metadata ** lookup. */ const char *msOWSLookupMetadata(hashTableObj *metadata, const char *namespaces, const char *name) { const char *value = NULL; if (namespaces == NULL) { value = msLookupHashTable(metadata, (char*)name); } else { char buf[100] = "ows_"; strlcpy(buf+4, name, 96); while (value == NULL && *namespaces != '\0') { switch (*namespaces) { case 'O': /* ows_... */ buf[0] = 'o'; buf[1] = 'w'; buf[2] = 's'; break; case 'M': /* wms_... */ buf[0] = 'w'; buf[1] = 'm'; buf[2] = 's'; break; case 'F': /* wfs_... */ buf[0] = 'w'; buf[1] = 'f'; buf[2] = 's'; break; case 'C': /* wcs_... */ buf[0] = 'w'; buf[1] = 'c'; buf[2] = 's'; break; case 'G': /* gml_... */ buf[0] = 'g'; buf[1] = 'm'; buf[2] = 'l'; break; case 'S': /* sos_... */ buf[0] = 's'; buf[1] = 'o'; buf[2] = 's'; break; default: /* We should never get here unless an invalid code (typo) is */ /* present in the code, but since this happened before... */ msSetError(MS_WMSERR, "Unsupported metadata namespace code (%c).", "msOWSLookupMetadata()", *namespaces ); assert(MS_FALSE); return NULL; } value = msLookupHashTable(metadata, buf); namespaces++; } } return value; } /* ** msOWSLookupMetadataWithLanguage() ** ** Attempts to lookup a given metadata name in multiple OWS namespaces ** for a specific language. */ const char *msOWSLookupMetadataWithLanguage(hashTableObj *metadata, const char *namespaces, const char *name, const char* validated_language) { const char *value = NULL; if ( name && validated_language ) { size_t bufferSize = strlen(name)+strlen(validated_language)+2; char *name2 = (char *) msSmallMalloc( bufferSize ); snprintf(name2, bufferSize, "%s.%s", name, validated_language); value = msOWSLookupMetadata(metadata, namespaces, name2); free(name2); } if ( name && !value ) { value = msOWSLookupMetadata(metadata, namespaces, name); } return value; } /* ** msOWSLookupMetadata2() ** ** Attempts to lookup a given metadata name in multiple hashTables, and ** in multiple OWS namespaces within each. First searches the primary ** table and if no result is found, attempts the search using the ** secondary (fallback) table. ** ** 'namespaces' is a string with a letter for each namespace to lookup ** in the order they should be looked up. e.g. "MO" to lookup wms_ and ows_ ** If namespaces is NULL then this function just does a regular metadata ** lookup. */ const char *msOWSLookupMetadata2(hashTableObj *pri, hashTableObj *sec, const char *namespaces, const char *name) { const char *result; if ((result = msOWSLookupMetadata(pri, namespaces, name)) == NULL) { /* Try the secondary table */ result = msOWSLookupMetadata(sec, namespaces, name); } return result; } /* msOWSParseVersionString() ** ** Parse a version string in the format "a.b.c" or "a.b" and return an ** integer in the format 0x0a0b0c suitable for regular integer comparisons. ** ** Returns one of OWS_VERSION_NOTSET or OWS_VERSION_BADFORMAT if version ** could not be parsed. */ int msOWSParseVersionString(const char *pszVersion) { char **digits = NULL; int numDigits = 0; if (pszVersion) { int nVersion = 0; digits = msStringSplit(pszVersion, '.', &numDigits); if (digits == NULL || numDigits < 2 || numDigits > 3) { msSetError(MS_OWSERR, "Invalid version (%s). Version must be in the " "format 'x.y' or 'x.y.z'", "msOWSParseVersionString()", pszVersion); if (digits) msFreeCharArray(digits, numDigits); return OWS_VERSION_BADFORMAT; } nVersion = atoi(digits[0])*0x010000; nVersion += atoi(digits[1])*0x0100; if (numDigits > 2) nVersion += atoi(digits[2]); msFreeCharArray(digits, numDigits); return nVersion; } return OWS_VERSION_NOTSET; } /* msOWSGetVersionString() ** ** Returns a OWS version string in the format a.b.c from the integer ** version value passed as argument (0x0a0b0c) ** ** Fills in the pszBuffer and returns a reference to it. Recommended buffer ** size is OWS_VERSION_MAXLEN chars. */ const char *msOWSGetVersionString(int nVersion, char *pszBuffer) { if (pszBuffer) snprintf(pszBuffer, OWS_VERSION_MAXLEN-1, "%d.%d.%d", (nVersion/0x10000)%0x100, (nVersion/0x100)%0x100, nVersion%0x100); return pszBuffer; } #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) || defined(USE_WMS_LYR) || defined(USE_WFS_LYR) #if !defined(USE_PROJ) #error "PROJ.4 is required for WMS, WFS, WCS and SOS Server Support." #endif /* ** msRenameLayer() */ static int msRenameLayer(layerObj *lp, int count) { char *newname; newname = (char*)malloc((strlen(lp->name)+5)*sizeof(char)); if (!newname) { msSetError(MS_MEMERR, NULL, "msRenameLayer()"); return MS_FAILURE; } sprintf(newname, "%s_%2.2d", lp->name, count); free(lp->name); lp->name = newname; return MS_SUCCESS; } /* ** msOWSMakeAllLayersUnique() */ int msOWSMakeAllLayersUnique(mapObj *map) { int i, j; /* Make sure all layers in the map file have valid and unique names */ for(i=0; inumlayers; i++) { int count=1; for(j=i+1; jnumlayers; j++) { if (GET_LAYER(map, i)->name == NULL || GET_LAYER(map, j)->name == NULL) { continue; } if (strcasecmp(GET_LAYER(map, i)->name, GET_LAYER(map, j)->name) == 0 && msRenameLayer((GET_LAYER(map, j)), ++count) != MS_SUCCESS) { return MS_FAILURE; } } /* Don't forget to rename the first layer if duplicates were found */ if (count > 1 && msRenameLayer((GET_LAYER(map, i)), 1) != MS_SUCCESS) { return MS_FAILURE; } } return MS_SUCCESS; } /* ** msOWSNegotiateVersion() ** ** returns the most suitable version an OWS is to support given a client ** version parameter. ** ** supported_versions must be ordered from highest to lowest ** ** Returns a version integer of the supported version ** */ int msOWSNegotiateVersion(int requested_version, const int supported_versions[], int num_supported_versions) { int i; /* if version is not set return highest version */ if (! requested_version) return supported_versions[0]; /* if the requested version is lower than the lowest version return the lowest version */ if (requested_version < supported_versions[num_supported_versions-1]) return supported_versions[num_supported_versions-1]; /* return the first entry that's lower than or equal to the requested version */ for (i = 0; i < num_supported_versions; i++) { if (supported_versions[i] <= requested_version) return supported_versions[i]; } return requested_version; } /* ** msOWSTerminateOnlineResource() ** ** Append trailing "?" or "&" to an onlineresource URL if it doesn't have ** one already. The returned string is then ready to append GET parameters ** to it. ** ** Returns a newly allocated string that should be freed by the caller or ** NULL in case of error. */ char * msOWSTerminateOnlineResource(const char *src_url) { char *online_resource = NULL; size_t buffer_size = 0; if (src_url == NULL) return NULL; buffer_size = strlen(src_url)+2; online_resource = (char*) malloc(buffer_size); if (online_resource == NULL) { msSetError(MS_MEMERR, NULL, "msOWSTerminateOnlineResource()"); return NULL; } strlcpy(online_resource, src_url, buffer_size); /* Append trailing '?' or '&' if missing. */ if (strchr(online_resource, '?') == NULL) strlcat(online_resource, "?", buffer_size); else { char *c; c = online_resource+strlen(online_resource)-1; if (*c != '?' && *c != '&') strlcpy(c+1, "&", buffer_size-strlen(online_resource)); } return online_resource; } /* ** msOWSGetOnlineResource() ** ** Return the online resource for this service. First try to lookup ** specified metadata, and if not found then try to build the URL ourselves. ** ** Returns a newly allocated string that should be freed by the caller or ** NULL in case of error. */ char * msOWSGetOnlineResource(mapObj *map, const char *namespaces, const char *metadata_name, cgiRequestObj *req) { const char *value; char *online_resource = NULL; /* We need this script's URL, including hostname. */ /* Default to use the value of the "onlineresource" metadata, and if not */ /* set then build it: "http://$(SERVER_NAME):$(SERVER_PORT)$(SCRIPT_NAME)?" */ /* (+append the map=... param if it was explicitly passed in QUERY_STRING) */ /* */ if ((value = msOWSLookupMetadata(&(map->web.metadata), namespaces, metadata_name))) { online_resource = msOWSTerminateOnlineResource(value); } else { if ((online_resource = msBuildOnlineResource(map, req)) == NULL) { msSetError(MS_CGIERR, "Impossible to establish server URL. Please set \"%s\" metadata.", "msOWSGetOnlineResource()", metadata_name); return NULL; } } return online_resource; } /* ** msOWSGetOnlineResource() ** ** Return the online resource for this service and add language parameter. ** ** Returns a newly allocated string that should be freed by the caller or ** NULL in case of error. */ char * msOWSGetOnlineResource2(mapObj *map, const char *namespaces, const char *metadata_name, cgiRequestObj *req, const char* validated_language) { char *online_resource = msOWSGetOnlineResource(map, namespaces, metadata_name, req); if ( online_resource && validated_language ) { /* online_resource is already terminated, so we can simply add language=...& */ /* but first we need to make sure that online_resource has enough capacity */ online_resource = (char *)msSmallRealloc(online_resource, strlen(online_resource) + strlen(validated_language) + 11); strcat(online_resource, "language="); strcat(online_resource, validated_language); strcat(online_resource, "&"); } return online_resource; } /* msOWSGetSchemasLocation() ** ** schemas location is the root of the web tree where all WFS-related ** schemas can be found on this server. These URLs must exist in order ** to validate xml. ** ** Use value of "ows_schemas_location" metadata, if not set then ** return ".." as a default */ const char *msOWSGetSchemasLocation(mapObj *map) { const char *schemas_location; schemas_location = msLookupHashTable(&(map->web.metadata), "ows_schemas_location"); if (schemas_location == NULL) schemas_location = OWS_DEFAULT_SCHEMAS_LOCATION; return schemas_location; } /* msOWSGetInspireSchemasLocation() ** ** schemas location is the root of the web tree where all Inspire-related ** schemas can be found on this server. These URLs must exist in order ** to validate xml. ** ** Use value of "inspire_schemas_location" metadata */ const char *msOWSGetInspireSchemasLocation(mapObj *map) { const char *schemas_location; schemas_location = msLookupHashTable(&(map->web.metadata), "inspire_schemas_location"); if (schemas_location == NULL) schemas_location = "http://inspire.ec.europa.eu/schemas"; return schemas_location; } /* msOWSGetLanguage() ** ** returns the language via MAP/WEB/METADATA/ows_language ** ** Use value of "ows_language" metadata, if not set then ** return "undefined" as a default */ const char *msOWSGetLanguage(mapObj *map, const char *context) { const char *language; /* if this is an exception, MapServer always returns Exception messages in en-US */ if (strcmp(context,"exception") == 0) { language = MS_ERROR_LANGUAGE; } /* if not, fetch language from mapfile metadata */ else { language = msLookupHashTable(&(map->web.metadata), "ows_language"); if (language == NULL) { language = "undefined"; } } return language; } /* msOWSGetLanguageList ** ** Returns the list of languages that this service supports ** ** Use value of "languages" metadata (comma-separated list), or NULL if not set ** ** Returns a malloced char** of length numitems which must be freed ** by the caller, or NULL (with numitems = 0) */ char **msOWSGetLanguageList(mapObj *map, const char *namespaces, int *numitems) { const char *languages = NULL; languages = msOWSLookupMetadata(&(map->web.metadata), namespaces, "languages"); if (languages && strlen(languages) > 0) { return msStringSplit(languages, ',', numitems); } else { *numitems = 0; return NULL; } } /* msOWSGetLanguageFromList ** ** Returns a language according to the language requested by the client ** ** If the requested language is in the languages metadata then use it, ** otherwise ignore it and use the defaul language, which is the first entry in ** the languages metadata list. Calling with a NULL requested_langauge ** therefore returns this default language. If the language metadata list is ** not defined then the language is set to NULL. ** ** Returns a malloced char* which must be freed by the caller, or NULL */ char *msOWSGetLanguageFromList(mapObj *map, const char *namespaces, const char *requested_language) { int num_items = 0; char **languages = msOWSGetLanguageList(map, namespaces, &num_items); char *language = NULL; if( languages && num_items > 0 ) { if ( !requested_language || !msStringInArray( requested_language, languages, num_items) ) { language = msStrdup(languages[0]); } else { language = msStrdup(requested_language); } } msFreeCharArray(languages, num_items); return language; } /* msOWSLanguageNegotiation ** ** Returns a language according to the accepted languages requested by the client ** ** Returns a malloced char* which must be freed by the caller, or NULL */ char *msOWSLanguageNegotiation(mapObj *map, const char *namespaces, char **accept_languages, int num_accept_languages) { int num_languages = 0; char **languages = NULL; char *result_language = NULL; languages = msOWSGetLanguageList(map, namespaces, &num_languages); if (languages && num_languages > 0) { int i; for (i = 0; i < num_accept_languages; ++i) { const char *accept_language = accept_languages[i]; /* '*' means any language */ if (EQUAL(accept_language, "*")) { result_language = msStrdup(languages[0]); break; } else if (msStringInArray(accept_language, languages, num_languages)) { result_language = msStrdup(accept_language); break; } } if (result_language == NULL) { result_language = msStrdup(languages[0]); } } msFreeCharArray(languages, num_languages); return result_language; } /* msOWSPrintInspireCommonExtendedCapabilities ** ** Output INSPIRE common extended capabilities items to stream ** The currently supported items are metadata and languages ** ** tag_name is the name (including ns prefix) of the tag to include the whole ** extended capabilities block in ** ** service is currently included for future compatibility when differing ** extended capabilities elements are included for different service types ** ** Returns a status code; MS_NOERR if all ok, action_if_not_found otherwise */ int msOWSPrintInspireCommonExtendedCapabilities(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found, const char *tag_name, const char* tag_ns, const char *validated_language, const OWSServiceType service) { int metadataStatus = 0; int languageStatus = 0; if( tag_ns ) msIO_fprintf(stream, " <%s %s>\n", tag_name, tag_ns); else msIO_fprintf(stream, " <%s>\n", tag_name); metadataStatus = msOWSPrintInspireCommonMetadata(stream, map, namespaces, action_if_not_found, service); languageStatus = msOWSPrintInspireCommonLanguages(stream, map, namespaces, action_if_not_found, validated_language); msIO_fprintf(stream, " \n", tag_name); return (metadataStatus != MS_NOERR) ? metadataStatus : languageStatus; } /* msOWSPrintInspireCommonMetadata ** ** Output INSPIRE common metadata items to a stream ** ** Returns a status code; MS_NOERR if all OK, action_if_not_found otherwise */ int msOWSPrintInspireCommonMetadata(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found, const OWSServiceType service) { int status = MS_NOERR; const char *inspire_capabilities = NULL; inspire_capabilities = msOWSLookupMetadata(&(map->web.metadata), namespaces, "inspire_capabilities"); if(!inspire_capabilities) { if (OWS_WARN == action_if_not_found) { msIO_fprintf(stream, "\n"); } return action_if_not_found; } if (strcasecmp("url",inspire_capabilities) == 0) { if ( msOWSLookupMetadata(&(map->web.metadata), namespaces, "inspire_metadataurl_href") != NULL ) { msIO_fprintf(stream, " \n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_metadataurl_href", OWS_WARN, " %s\n", ""); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_metadataurl_format", OWS_WARN, " %s\n", ""); msIO_fprintf(stream, " \n"); } else { status = action_if_not_found; if (OWS_WARN == action_if_not_found) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), "inspire_metadataurl_href"); } } } else if (strcasecmp("embed",inspire_capabilities) == 0) { msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_resourcelocator", OWS_WARN, " \n %s\n \n", NULL); msIO_fprintf(stream," service\n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_temporal_reference", OWS_WARN, " \n %s\n \n", ""); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " -\n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_temporal_reference", OWS_NOERR, " %s\n", ""); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " notEvaluated\n"); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " \n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_mpoc_name", OWS_WARN, " %s\n", ""); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_mpoc_email", OWS_WARN, " %s\n", ""); msIO_fprintf(stream, " \n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_metadatadate", OWS_WARN, " %s\n", ""); if( service == OWS_WFS || service == OWS_WCS ) msIO_fprintf(stream," download\n"); else msIO_fprintf(stream," view\n"); msOWSPrintEncodeMetadata(stream, &(map->web.metadata), namespaces, "inspire_keyword", OWS_WARN, " \n %s\n \n", ""); } else { status = action_if_not_found; if (OWS_WARN == action_if_not_found) { msIO_fprintf(stream, "\n", inspire_capabilities); } } return status; } /* msOWSPrintInspireCommonLanguages ** ** Output INSPIRE supported languages block to stream ** ** Returns a status code; MS_NOERR if all OK; action_if_not_found otherwise */ int msOWSPrintInspireCommonLanguages(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found, const char *validated_language) { char *buffer = NULL; /* temp variable for malloced strings that will need freeing */ int status = MS_NOERR; char *default_language = msOWSGetLanguageFromList(map, namespaces, NULL); if(validated_language && default_language) { msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " %s" "\n", buffer = msEncodeHTMLEntities(default_language)); msFree(buffer); /* append _exclude to our default_language*/ default_language = msSmallRealloc(default_language,strlen(default_language)+strlen("_exclude")+1); strcat(default_language,"_exclude"); msOWSPrintEncodeMetadataList(stream, &(map->web.metadata), namespaces, "languages", NULL, NULL, " %s" "\n", default_language); msIO_fprintf(stream, " \n"); msIO_fprintf(stream, " %s" "\n", validated_language); } else { status = action_if_not_found; if (OWS_WARN == action_if_not_found) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), "languages"); } } msFree(default_language); return status; } /* ** msOWSPrintMetadata() ** ** Attempt to output a capability item. If corresponding metadata is not ** found then one of a number of predefined actions will be taken. ** If a default value is provided and metadata is absent then the ** default will be used. */ int msOWSPrintMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) { const char *value = NULL; int status = MS_NOERR; if((value = msOWSLookupMetadata(metadata, namespaces, name)) != NULL) { msIO_fprintf(stream, format, value); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } if (default_value) msIO_fprintf(stream, format, default_value); } return status; } /* ** msOWSPrintEncodeMetadata() ** ** Attempt to output a capability item. If corresponding metadata is not ** found then one of a number of predefined actions will be taken. ** If a default value is provided and metadata is absent then the ** default will be used. ** Also encode the value with msEncodeHTMLEntities. */ int msOWSPrintEncodeMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) { return msOWSPrintEncodeMetadata2(stream, metadata, namespaces, name, action_if_not_found, format, default_value, NULL); } /* ** msOWSPrintEncodeMetadata2() ** ** Attempt to output a capability item in the requested language. ** Fallback using no language parameter. */ int msOWSPrintEncodeMetadata2(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value, const char *validated_language) { const char *value; char * pszEncodedValue=NULL; int status = MS_NOERR; if((value = msOWSLookupMetadataWithLanguage(metadata, namespaces, name, validated_language))) { pszEncodedValue = msEncodeHTMLEntities(value); msIO_fprintf(stream, format, pszEncodedValue); free(pszEncodedValue); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name, (validated_language?".":""), (validated_language?validated_language:"")); status = action_if_not_found; } if (default_value) { pszEncodedValue = msEncodeHTMLEntities(default_value); msIO_fprintf(stream, format, default_value); free(pszEncodedValue); } } return status; } /* ** msOWSGetEncodeMetadata() ** ** Equivalent to msOWSPrintEncodeMetadata. Returns en encoded value of the ** metadata or the default value. ** Caller should free the returned string. */ char *msOWSGetEncodeMetadata(hashTableObj *metadata, const char *namespaces, const char *name, const char *default_value) { const char *value; char * pszEncodedValue=NULL; if((value = msOWSLookupMetadata(metadata, namespaces, name))) pszEncodedValue = msEncodeHTMLEntities(value); else if (default_value) pszEncodedValue = msEncodeHTMLEntities(default_value); return pszEncodedValue; } /* ** msOWSPrintValidateMetadata() ** ** Attempt to output a capability item. If corresponding metadata is not ** found then one of a number of predefined actions will be taken. ** If a default value is provided and metadata is absent then the ** default will be used. ** Also validate the value with msIsXMLTagValid. */ int msOWSPrintValidateMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) { const char *value; int status = MS_NOERR; if((value = msOWSLookupMetadata(metadata, namespaces, name))) { if(msIsXMLTagValid(value) == MS_FALSE) msIO_fprintf(stream, "\n", value); msIO_fprintf(stream, format, value); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } if (default_value) { if(msIsXMLTagValid(default_value) == MS_FALSE) msIO_fprintf(stream, "\n", default_value); msIO_fprintf(stream, format, default_value); } } return status; } /* ** msOWSPrintGroupMetadata() ** ** Attempt to output a capability item. If corresponding metadata is not ** found then one of a number of predefined actions will be taken. ** If a default value is provided and metadata is absent then the ** default will be used. */ int msOWSPrintGroupMetadata(FILE *stream, mapObj *map, char* pszGroupName, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) { return msOWSPrintGroupMetadata2(stream, map, pszGroupName, namespaces, name, action_if_not_found, format, default_value, NULL); } /* ** msOWSPrintGroupMetadata2() ** ** Attempt to output a capability item in the requested language. ** Fallback using no language parameter. */ int msOWSPrintGroupMetadata2(FILE *stream, mapObj *map, char* pszGroupName, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value, const char *validated_language) { const char *value; char *encoded; int status = MS_NOERR; int i; for (i=0; inumlayers; i++) { if (GET_LAYER(map, i)->group && (strcmp(GET_LAYER(map, i)->group, pszGroupName) == 0) && &(GET_LAYER(map, i)->metadata)) { if((value = msOWSLookupMetadataWithLanguage(&(GET_LAYER(map, i)->metadata), namespaces, name, validated_language))) { encoded = msEncodeHTMLEntities(value); msIO_fprintf(stream, format, encoded); msFree(encoded); return status; } } } if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } if (default_value) { encoded = msEncodeHTMLEntities(default_value); msIO_fprintf(stream, format, encoded); msFree(encoded); } return status; } /* msOWSPrintURLType() ** ** Attempt to output a URL item in capabilties. If corresponding metadata ** is not found then one of a number of predefined actions will be taken. ** Since it's a capability item, five metadata will be used to populate the ** XML elements. ** ** The 'name' argument is the basename of the metadata items relating to this ** URL type and the suffixes _type, _width, _height, _format and _href will ** be appended to the name in the metadata search. ** e.g. passing name=metadataurl will result in the following medata entries ** being used: ** ows_metadataurl_type ** ows_metadataurl_format ** ows_metadataurl_href ** ... (width and height are unused for metadata) ** ** As for all the msOWSPrint*() functions, the namespace argument specifies ** which prefix (ows_, wms_, wcs_, etc.) is used for the metadata names above. ** ** Then the final string will be built from ** the tag_name and the five metadata. The template is: ** %href ** ** For example the width format will usually be " width=\"%s\"". ** An extern format will be "> %s\n", tag_name); if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } } else { if(!type && type_format && default_type) { buffer_size_tmp = strlen(type_format) + strlen(default_type) + 2; type = (char*) malloc(buffer_size_tmp); snprintf(type, buffer_size_tmp, type_format, default_type); } else if(!type) type = msStrdup(""); if(!width && width_format && default_width) { buffer_size_tmp = strlen(width_format) + strlen(default_width) + 2; width = (char*) malloc(buffer_size_tmp); snprintf(width, buffer_size_tmp, width_format, default_width); } else if(!width) width = msStrdup(""); if(!height && height_format && default_height) { buffer_size_tmp = strlen(height_format) + strlen(default_height) + 2; height = (char*) malloc(buffer_size_tmp); snprintf(height, buffer_size_tmp, height_format, default_height); } else if(!height) height = msStrdup(""); if(!urlfrmt && urlfrmt_format && default_urlfrmt) { buffer_size_tmp = strlen(urlfrmt_format) + strlen(default_urlfrmt) + 2; urlfrmt = (char*) malloc(buffer_size_tmp); snprintf(urlfrmt, buffer_size_tmp, urlfrmt_format, default_urlfrmt); } else if(!urlfrmt) urlfrmt = msStrdup(""); if(!href && href_format && default_href) { buffer_size_tmp = strlen(href_format) + strlen(default_href) + 2; href = (char*) malloc(buffer_size_tmp); snprintf(href, buffer_size_tmp, href_format, default_href); } else if(!href) href = msStrdup(""); if(tag_format == NULL) msIO_fprintf(stream, "%s<%s%s%s%s%s>%s\n", tabspace, tag_name, type, width, height, urlfrmt, href, tag_name); else msIO_fprintf(stream, tag_format, type, width, height, urlfrmt, href); } msFree(type); msFree(width); msFree(height); msFree(urlfrmt); msFree(href); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", (namespaces?"..._":""), name); status = action_if_not_found; } } return status; } /* msOWSPrintParam() ** ** Same as printMetadata() but applied to mapfile parameters. **/ int msOWSPrintParam(FILE *stream, const char *name, const char *value, int action_if_not_found, const char *format, const char *default_value) { int status = MS_NOERR; if(value && strlen(value) > 0) { msIO_fprintf(stream, format, value); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", name); status = action_if_not_found; } if (default_value) msIO_fprintf(stream, format, default_value); } return status; } /* msOWSPrintEncodeParam() ** ** Same as printEncodeMetadata() but applied to mapfile parameters. **/ int msOWSPrintEncodeParam(FILE *stream, const char *name, const char *value, int action_if_not_found, const char *format, const char *default_value) { int status = MS_NOERR; char *encode; if(value && strlen(value) > 0) { encode = msEncodeHTMLEntities(value); msIO_fprintf(stream, format, encode); msFree(encode); } else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", name); status = action_if_not_found; } if (default_value) { encode = msEncodeHTMLEntities(default_value); msIO_fprintf(stream, format, encode); msFree(encode); } } return status; } /* msOWSPrintMetadataList() ** ** Prints comma-separated lists metadata. (e.g. keywordList) ** default_value serves 2 purposes if specified: ** - won't be printed if part of MetadataList (default_value == key"_exclude") ** (exclusion) ** - will be printed if MetadataList is empty (fallback) **/ int msOWSPrintMetadataList(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, const char *startTag, const char *endTag, const char *itemFormat, const char *default_value) { const char *value; value = msOWSLookupMetadata(metadata, namespaces, name); if(value == NULL) { value = default_value; default_value = NULL; } if(value != NULL) { char **keywords; int numkeywords; keywords = msStringSplit(value, ',', &numkeywords); if(keywords && numkeywords > 0) { int kw; if(startTag) msIO_fprintf(stream, "%s", startTag); for(kw=0; kw 0) { int kw; if(startTag) msIO_fprintf(stream, "%s", startTag); for(kw=0; kw 8 && strncasecmp(keywords[kw],default_value,strlen(keywords[kw])) == 0 && strncasecmp("_exclude",default_value+default_value_len-8,8) == 0) continue; encoded = msEncodeHTMLEntities(keywords[kw]); msIO_fprintf(stream, itemFormat, encoded); msFree(encoded); } if(endTag) msIO_fprintf(stream, "%s", endTag); } msFreeCharArray(keywords, numkeywords); return MS_TRUE; } return MS_FALSE; } /* msOWSPrintEncodeParamList() ** ** Same as msOWSPrintEncodeMetadataList() but applied to mapfile parameters. **/ int msOWSPrintEncodeParamList(FILE *stream, const char *name, const char *value, int action_if_not_found, char delimiter, const char *startTag, const char *endTag, const char *format, const char *default_value) { int status = MS_NOERR; char *encoded; char **items = NULL; int numitems = 0, i; if(value && strlen(value) > 0) items = msStringSplit(value, delimiter, &numitems); else { if (action_if_not_found == OWS_WARN) { msIO_fprintf(stream, "\n", name); status = action_if_not_found; } if (default_value) items = msStringSplit(default_value, delimiter, &numitems); } if(items && numitems > 0) { if(startTag) msIO_fprintf(stream, "%s", startTag); for(i=0; inumargs > 0 && !pj_is_latlong(srcproj->proj)) { projectionObj wgs84; msInitProjection(&wgs84); msLoadProjectionString(&wgs84, "+proj=longlat +ellps=WGS84 +datum=WGS84"); msProjectRect(srcproj, &wgs84, ext); msFreeProjection(&wgs84); } } /* ** msOWSPrintEX_GeographicBoundingBox() ** ** Print a EX_GeographicBoundingBox tag for WMS1.3.0 ** */ void msOWSPrintEX_GeographicBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj) { const char *pszTag = "EX_GeographicBoundingBox"; /* The default for WMS */ rectObj ext; ext = *extent; /* always project to lat long */ msOWSProjectToWGS84(srcproj, &ext); msIO_fprintf(stream, "%s<%s>\n", tabspace, pszTag); msIO_fprintf(stream, "%s %g\n", tabspace, ext.minx); msIO_fprintf(stream, "%s %g\n", tabspace, ext.maxx); msIO_fprintf(stream, "%s %g\n", tabspace, ext.miny); msIO_fprintf(stream, "%s %g\n", tabspace, ext.maxy); msIO_fprintf(stream, "%s\n", tabspace, pszTag); /* msIO_fprintf(stream, "%s<%s minx=\"%g\" miny=\"%g\" maxx=\"%g\" maxy=\"%g\" />\n", tabspace, pszTag, ext.minx, ext.miny, ext.maxx, ext.maxy); */ } /* ** msOWSPrintLatLonBoundingBox() ** ** Print a LatLonBoundingBox tag for WMS, or LatLongBoundingBox for WFS ** ... yes, the tag name differs between WMS and WFS, yuck! ** */ void msOWSPrintLatLonBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj, projectionObj *wfsproj, OWSServiceType nService) { const char *pszTag = "LatLonBoundingBox"; /* The default for WMS */ rectObj ext; ext = *extent; if (nService == OWS_WMS) { /* always project to lat long */ msOWSProjectToWGS84(srcproj, &ext); } else if (nService == OWS_WFS) { /* called from wfs 1.0.0 only: project to map srs, if set */ pszTag = "LatLongBoundingBox"; if (wfsproj) { if (msProjectionsDiffer(srcproj, wfsproj) == MS_TRUE) msProjectRect(srcproj, wfsproj, &ext); } } msIO_fprintf(stream, "%s<%s minx=\"%g\" miny=\"%g\" maxx=\"%g\" maxy=\"%g\" />\n", tabspace, pszTag, ext.minx, ext.miny, ext.maxx, ext.maxy); } /* ** Emit a bounding box if we can find projection information. ** If _bbox_extended is not set, emit a single bounding box ** using the layer's native SRS (ignoring any _srs metadata). ** ** If _bbox_extended is set to true, emit a bounding box ** for every projection listed in the _srs list. ** Check the map level metadata for both _bbox_extended and _srs, ** if there is no such metadata at the layer level. ** (These settings make more sense at the global/map level anyways) */ void msOWSPrintBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj, hashTableObj *layer_meta, hashTableObj *map_meta, const char *namespaces, int wms_version) { const char *value, *resx, *resy, *wms_bbox_extended; char *encoded, *encoded_resx, *encoded_resy, *epsg_str; char **epsgs; int i, num_epsgs; projectionObj proj; rectObj ext; wms_bbox_extended = msOWSLookupMetadata2(layer_meta, map_meta, namespaces, "bbox_extended"); if( wms_bbox_extended && strncasecmp(wms_bbox_extended, "true", 5) == 0 ) { /* get a list of all projections from the metadata try the layer metadata first, otherwise use the map's */ if( msOWSLookupMetadata(layer_meta, namespaces, "srs") ) { msOWSGetEPSGProj(srcproj, layer_meta, namespaces, MS_FALSE, &epsg_str); } else { msOWSGetEPSGProj(srcproj, map_meta, namespaces, MS_FALSE, &epsg_str); } epsgs = msStringSplit(epsg_str, ' ', &num_epsgs); msFree(epsg_str); } else { /* Look for EPSG code in PROJECTION block only. "wms_srs" metadata cannot be * used to establish the native projection of a layer for BoundingBox purposes. */ epsgs = (char **) msSmallMalloc(sizeof(char *)); num_epsgs = 1; msOWSGetEPSGProj(srcproj, layer_meta, namespaces, MS_TRUE, &(epsgs[0])); } for( i = 0; i < num_epsgs; i++) { value = epsgs[i]; if( value && *value) { memcpy(&ext, extent, sizeof(rectObj)); /* reproject the extents for each SRS's bounding box */ msInitProjection(&proj); if (msLoadProjectionStringEPSG(&proj, (char *)value) == 0) { if (msProjectionsDiffer(srcproj, &proj) == MS_TRUE) { msProjectRect(srcproj, &proj, &ext); } /*for wms 1.3.0 we need to make sure that we present the BBOX with a reversed axes for some espg codes*/ if (wms_version >= OWS_1_3_0 && value && strncasecmp(value, "EPSG:", 5) == 0) { msAxisNormalizePoints( &proj, 1, &(ext.minx), &(ext.miny) ); msAxisNormalizePoints( &proj, 1, &(ext.maxx), &(ext.maxy) ); } } msFreeProjection( &proj ); encoded = msEncodeHTMLEntities(value); if (wms_version >= OWS_1_3_0) msIO_fprintf(stream, "%s\n" ); } } msFreeCharArray(epsgs, num_epsgs); } /* ** Print the contact information */ void msOWSPrintContactInfo( FILE *stream, const char *tabspace, int nVersion, hashTableObj *metadata, const char *namespaces ) { /* contact information is a required element in 1.0.7 but the */ /* sub-elements such as ContactPersonPrimary, etc. are not! */ /* In 1.1.0, ContactInformation becomes optional. */ if (nVersion > OWS_1_0_0) { msIO_fprintf(stream, "%s\n", tabspace); /* ContactPersonPrimary is optional, but when present then all its */ /* sub-elements are mandatory */ if(msOWSLookupMetadata(metadata, namespaces, "contactperson") || msOWSLookupMetadata(metadata, namespaces, "contactorganization")) { msIO_fprintf(stream, "%s \n", tabspace); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactperson", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactorganization", OWS_WARN, " %s\n", NULL); msIO_fprintf(stream, "%s \n", tabspace); } if(msOWSLookupMetadata(metadata, namespaces, "contactposition")) { msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactposition", OWS_NOERR, " %s\n", NULL); } /* ContactAdress is optional, but when present then all its */ /* sub-elements are mandatory */ if(msOWSLookupMetadata( metadata, namespaces, "addresstype" ) || msOWSLookupMetadata( metadata, namespaces, "address" ) || msOWSLookupMetadata( metadata, namespaces, "city" ) || msOWSLookupMetadata( metadata, namespaces, "stateorprovince" ) || msOWSLookupMetadata( metadata, namespaces, "postcode" ) || msOWSLookupMetadata( metadata, namespaces, "country" )) { msIO_fprintf(stream, "%s \n", tabspace); msOWSPrintEncodeMetadata(stream, metadata, namespaces,"addresstype", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "address", OWS_WARN, "
%s
\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "city", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "stateorprovince", OWS_WARN," %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "postcode", OWS_WARN, " %s\n", NULL); msOWSPrintEncodeMetadata(stream, metadata, namespaces, "country", OWS_WARN, " %s\n", NULL); msIO_fprintf(stream, "%s
\n", tabspace); } if(msOWSLookupMetadata(metadata, namespaces, "contactvoicetelephone")) { msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactvoicetelephone", OWS_NOERR, " %s\n", NULL); } if(msOWSLookupMetadata(metadata, namespaces, "contactfacsimiletelephone")) { msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactfacsimiletelephone", OWS_NOERR, " %s\n", NULL); } if(msOWSLookupMetadata(metadata, namespaces, "contactelectronicmailaddress")) { msOWSPrintEncodeMetadata(stream, metadata, namespaces, "contactelectronicmailaddress", OWS_NOERR, " %s\n", NULL); } msIO_fprintf(stream, "%s
\n", tabspace); } } /* ** msOWSGetLayerExtent() ** ** Try to establish layer extent, first looking for "ows_extent" metadata, and ** if not found then call msLayerGetExtent() which will lookup the ** layer->extent member, and if not found will open layer to read extent. ** */ int msOWSGetLayerExtent(mapObj *map, layerObj *lp, const char *namespaces, rectObj *ext) { const char *value; if ((value = msOWSLookupMetadata(&(lp->metadata), namespaces, "extent")) != NULL) { char **tokens; int n; tokens = msStringSplit(value, ' ', &n); if (tokens==NULL || n != 4) { msSetError(MS_WMSERR, "Wrong number of arguments for EXTENT metadata.", "msOWSGetLayerExtent()"); return MS_FAILURE; } ext->minx = atof(tokens[0]); ext->miny = atof(tokens[1]); ext->maxx = atof(tokens[2]); ext->maxy = atof(tokens[3]); msFreeCharArray(tokens, n); return MS_SUCCESS; } else { return msLayerGetExtent(lp, ext); } return MS_FAILURE; } /********************************************************************** * msOWSExecuteRequests() * * Execute a number of WFS/WMS HTTP requests in parallel, and then * update layerObj information with the result of the requests. **********************************************************************/ int msOWSExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, mapObj *map, int bCheckLocalCache) { int nStatus, iReq; /* Execute requests */ #if defined(USE_CURL) nStatus = msHTTPExecuteRequests(pasReqInfo, numRequests, bCheckLocalCache); #else msSetError(MS_WMSERR, "msOWSExecuteRequests() called apparently without libcurl configured, msHTTPExecuteRequests() not available.", "msOWSExecuteRequests()"); return MS_FAILURE; #endif /* Scan list of layers and call the handler for each layer type to */ /* pass them the request results. */ for(iReq=0; iReq= 0 && pasReqInfo[iReq].nLayerId < map->numlayers) { layerObj *lp; lp = GET_LAYER(map, pasReqInfo[iReq].nLayerId); if (lp->connectiontype == MS_WFS) msWFSUpdateRequestInfo(lp, &(pasReqInfo[iReq])); } } return nStatus; } /********************************************************************** * msOWSProcessException() * **********************************************************************/ void msOWSProcessException(layerObj *lp, const char *pszFname, int nErrorCode, const char *pszFuncName) { FILE *fp; if ((fp = fopen(pszFname, "r")) != NULL) { char *pszBuf=NULL; int nBufSize=0; char *pszStart, *pszEnd; fseek(fp, 0, SEEK_END); nBufSize = ftell(fp); if(nBufSize < 0) { msSetError(MS_IOERR, NULL, "msOWSProcessException()"); fclose(fp); return; } rewind(fp); pszBuf = (char*)malloc((nBufSize+1)*sizeof(char)); if (pszBuf == NULL) { msSetError(MS_MEMERR, NULL, "msOWSProcessException()"); fclose(fp); return; } if ((int) fread(pszBuf, 1, nBufSize, fp) != nBufSize) { msSetError(MS_IOERR, NULL, "msOWSProcessException()"); free(pszBuf); fclose(fp); return; } pszBuf[nBufSize] = '\0'; /* OK, got the data in the buffer. Look for the tags */ if ((strstr(pszBuf, "") && /* WFS style */ (pszStart = strstr(pszBuf, "")) && (pszEnd = strstr(pszStart, "")) ) || (strstr(pszBuf, "") && /* WMS style */ (pszStart = strstr(pszBuf, "")) && (pszEnd = strstr(pszStart, "")) )) { pszStart = strchr(pszStart, '>')+1; *pszEnd = '\0'; msSetError(nErrorCode, "Got Remote Server Exception for layer %s: %s", pszFuncName, lp->name?lp->name:"(null)", pszStart); } else { msSetError(MS_WFSCONNERR, "Unable to parse Remote Server Exception Message for layer %s.", pszFuncName, lp->name?lp->name:"(null)"); } free(pszBuf); fclose(fp); } } /********************************************************************** * msOWSBuildURLFilename() * * Build a unique filename for this URL to use in caching remote server * requests. Slashes and illegal characters will be turned into '_' * * Returns a newly allocated buffer that should be freed by the caller or * NULL in case of error. **********************************************************************/ char *msOWSBuildURLFilename(const char *pszPath, const char *pszURL, const char *pszExt) { char *pszBuf, *pszPtr; int i; size_t nBufLen = 0; nBufLen = strlen(pszURL) + strlen(pszExt) +2; if (pszPath) nBufLen += (strlen(pszPath)+1); pszBuf = (char*)malloc(nBufLen); if (pszBuf == NULL) { msSetError(MS_MEMERR, NULL, "msOWSBuildURLFilename()"); return NULL; } pszBuf[0] = '\0'; if (pszPath) { #ifdef _WIN32 if (pszPath[strlen(pszPath) -1] != '/' && pszPath[strlen(pszPath) -1] != '\\') snprintf(pszBuf, nBufLen, "%s\\", pszPath); else snprintf(pszBuf, nBufLen, "%s", pszPath); #else if (pszPath[strlen(pszPath) -1] != '/') snprintf(pszBuf, nBufLen, "%s/", pszPath); else snprintf(pszBuf, nBufLen, "%s", pszPath); #endif } pszPtr = pszBuf + strlen(pszBuf); for(i=0; pszURL[i] != '\0'; i++) { if (isalnum(pszURL[i])) *pszPtr = pszURL[i]; else *pszPtr = '_'; pszPtr++; } strlcpy(pszPtr, pszExt, nBufLen); return pszBuf; } /* ** msOWSGetEPSGProj() ** ** Extract projection code for this layer/map. ** ** First look for a xxx_srs metadata. If not found then look for an EPSG ** code in projectionObj, and if not found then return NULL. ** ** If bReturnOnlyFirstOne=TRUE and metadata contains multiple EPSG codes ** then only the first one (which is assumed to be the layer's default ** projection) is returned. */ void msOWSGetEPSGProj(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne, char **epsgCode) { const char *value; *epsgCode = NULL; /* metadata value should already be in format "EPSG:n" or "AUTO:..." */ if (metadata && ((value = msOWSLookupMetadata(metadata, namespaces, "srs")) != NULL)) { const char *space_ptr; if (!bReturnOnlyFirstOne || (space_ptr = strchr(value,' ')) == NULL) { *epsgCode = msStrdup(value); return; } *epsgCode = msSmallMalloc((space_ptr - value + 1)*sizeof(char)); /* caller requested only first projection code, copy up to the first space character*/ strlcpy(*epsgCode, value, space_ptr - value + 1) ; return; } else if (proj && proj->numargs > 0 && (value = strstr(proj->args[0], "init=epsg:")) != NULL) { *epsgCode = msSmallMalloc((strlen("EPSG:")+strlen(value+10)+1)*sizeof(char)); sprintf(*epsgCode, "EPSG:%s", value+10); return; } else if (proj && proj->numargs > 0 && (value = strstr(proj->args[0], "init=crs:")) != NULL) { *epsgCode = msSmallMalloc((strlen("CRS:")+strlen(value+9)+1)*sizeof(char)); sprintf(*epsgCode, "CRS:%s", value+9); return; } else if (proj && proj->numargs > 0 && (strncasecmp(proj->args[0], "AUTO:", 5) == 0 || strncasecmp(proj->args[0], "AUTO2:", 6) == 0)) { *epsgCode = msStrdup(proj->args[0]); return; } } /* ** msOWSGetProjURN() ** ** Fetch an OGC URN for this layer or map. Similar to msOWSGetEPSGProj() ** but returns the result in the form "urn:ogc:def:crs:EPSG::27700". ** The returned buffer is dynamically allocated, and must be freed by the ** caller. */ char *msOWSGetProjURN(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne) { char *result; char **tokens; int numtokens, i; size_t bufferSize = 0; char *oldStyle; msOWSGetEPSGProj( proj, metadata, namespaces, bReturnOnlyFirstOne, &oldStyle ); if( oldStyle == NULL || strncmp(oldStyle,"EPSG:",5) != 0 ) return NULL; result = msStrdup(""); tokens = msStringSplit(oldStyle, ' ', &numtokens); msFree(oldStyle); for(i=0; tokens != NULL && i 0 ) { bufferSize = strlen(result)+strlen(urn)+2; result = (char *) realloc(result, bufferSize); if( strlen(result) > 0 ) strlcat( result, " ", bufferSize); strlcat( result, urn , bufferSize); } else { msDebug( "msOWSGetProjURN(): Failed to process SRS '%s', ignored.", tokens[i] ); } } msFreeCharArray(tokens, numtokens); if( strlen(result) == 0 ) { msFree( result ); return NULL; } else return result; } /* ** msOWSGetProjURI() ** ** Fetch an OGC URI for this layer or map. Similar to msOWSGetEPSGProj() ** but returns the result in the form "http://www.opengis.net/def/crs/EPSG/0/27700". ** The returned buffer is dynamically allocated, and must be freed by the ** caller. */ char *msOWSGetProjURI(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne) { char *result; char **tokens; int numtokens, i; char *oldStyle; msOWSGetEPSGProj( proj, metadata, namespaces, bReturnOnlyFirstOne, &oldStyle); if( oldStyle == NULL || !EQUALN(oldStyle,"EPSG:",5) ) return NULL; result = msStrdup(""); tokens = msStringSplit(oldStyle, ' ', &numtokens); msFree(oldStyle); for(i=0; tokens != NULL && i 0 ) { result = (char *) realloc(result,strlen(result)+strlen(urn)+2); if( strlen(result) > 0 ) strcat( result, " " ); strcat( result, urn ); } else { msDebug( "msOWSGetProjURI(): Failed to process SRS '%s', ignored.", tokens[i] ); } } msFreeCharArray(tokens, numtokens); if( strlen(result) == 0 ) { msFree( result ); return NULL; } else return result; } /* ** msOWSGetDimensionInfo() ** ** Extract dimension information from a layer's metadata ** ** Before 4.9, only the time dimension was support. With the addition of ** Web Map Context 1.1.0, we need to support every dimension types. ** This function get the dimension information from special metadata in ** the layer, but can also return default values for the time dimension. ** */ void msOWSGetDimensionInfo(layerObj *layer, const char *pszDimension, const char **papszDimUserValue, const char **papszDimUnits, const char **papszDimDefault, const char **papszDimNearValue, const char **papszDimUnitSymbol, const char **papszDimMultiValue) { char *pszDimensionItem; size_t bufferSize = 0; if(pszDimension == NULL || layer == NULL) return; bufferSize = strlen(pszDimension)+50; pszDimensionItem = (char*)malloc(bufferSize); /* units (mandatory in map context) */ if(papszDimUnits != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_units", pszDimension); *papszDimUnits = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* unitSymbol (mandatory in map context) */ if(papszDimUnitSymbol != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_unitsymbol", pszDimension); *papszDimUnitSymbol = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* userValue (mandatory in map context) */ if(papszDimUserValue != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_uservalue", pszDimension); *papszDimUserValue = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* default */ if(papszDimDefault != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_default", pszDimension); *papszDimDefault = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* multipleValues */ if(papszDimMultiValue != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_multiplevalues", pszDimension); *papszDimMultiValue = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* nearestValue */ if(papszDimNearValue != NULL) { snprintf(pszDimensionItem, bufferSize, "dimension_%s_nearestvalue", pszDimension); *papszDimNearValue = msOWSLookupMetadata(&(layer->metadata), "MO", pszDimensionItem); } /* Use default time value if necessary */ if(strcasecmp(pszDimension, "time") == 0) { if(papszDimUserValue != NULL && *papszDimUserValue == NULL) *papszDimUserValue = msOWSLookupMetadata(&(layer->metadata), "MO", "time"); if(papszDimDefault != NULL && *papszDimDefault == NULL) *papszDimDefault = msOWSLookupMetadata(&(layer->metadata), "MO", "timedefault"); if(papszDimUnits != NULL && *papszDimUnits == NULL) *papszDimUnits = "ISO8601"; if(papszDimUnitSymbol != NULL && *papszDimUnitSymbol == NULL) *papszDimUnitSymbol = "t"; if(papszDimNearValue != NULL && *papszDimNearValue == NULL) *papszDimNearValue = "0"; } free(pszDimensionItem); return; } /** * msOWSNegotiateUpdateSequence() * * returns the updateSequence value for an OWS * * @param requested_updatesequence the updatesequence passed by the client * @param updatesequence the updatesequence set by the server * * @return result of comparison (-1, 0, 1) * -1: lower / higher OR values not set by client or server * 1: higher / lower * 0: equal */ int msOWSNegotiateUpdateSequence(const char *requested_updatesequence, const char *updatesequence) { int i; int valtype1 = 1; /* default datatype for updatesequence passed by client */ int valtype2 = 1; /* default datatype for updatesequence set by server */ struct tm tm_requested_updatesequence, tm_updatesequence; /* if not specified by client, or set by server, server responds with latest Capabilities XML */ if (! requested_updatesequence || ! updatesequence) return -1; /* test to see if server value is an integer (1), string (2) or timestamp (3) */ if (msStringIsInteger(updatesequence) == MS_FAILURE) valtype1 = 2; if (valtype1 == 2) { /* test if timestamp */ msTimeInit(&tm_updatesequence); if (msParseTime(updatesequence, &tm_updatesequence) == MS_TRUE) valtype1 = 3; msResetErrorList(); } /* test to see if client value is an integer (1), string (2) or timestamp (3) */ if (msStringIsInteger(requested_updatesequence) == MS_FAILURE) valtype2 = 2; if (valtype2 == 2) { /* test if timestamp */ msTimeInit(&tm_requested_updatesequence); if (msParseTime(requested_updatesequence, &tm_requested_updatesequence) == MS_TRUE) valtype2 = 3; msResetErrorList(); } /* if the datatypes do not match, do not compare, */ if (valtype1 != valtype2) return -1; if (valtype1 == 1) { /* integer */ if (atoi(requested_updatesequence) < atoi(updatesequence)) return -1; if (atoi(requested_updatesequence) > atoi(updatesequence)) return 1; if (atoi(requested_updatesequence) == atoi(updatesequence)) return 0; } if (valtype1 == 2) /* string */ return strcasecmp(requested_updatesequence, updatesequence); if (valtype1 == 3) { /* timestamp */ /* compare timestamps */ i = msDateCompare(&tm_requested_updatesequence, &tm_updatesequence) + msTimeCompare(&tm_requested_updatesequence, &tm_updatesequence); return i; } /* return default -1 */ return -1; } /************************************************************************/ /* msOwsIsOutputFormatValid */ /* */ /* Utlity function to parse a comma separated list in a */ /* metedata object and select and outputformat. */ /************************************************************************/ outputFormatObj* msOwsIsOutputFormatValid(mapObj *map, const char *format, hashTableObj *metadata, const char *namespaces, const char *name) { char **tokens=NULL; int i,n; outputFormatObj *psFormat = NULL; const char * format_list=NULL; if (map && format && metadata && namespaces && name) { msApplyDefaultOutputFormats(map); format_list = msOWSLookupMetadata(metadata, namespaces, name); n = 0; if ( format_list) tokens = msStringSplit(format_list, ',', &n); if (tokens && n > 0) { for (i=0; ioutputformatlist[iFormat]->mimetype; msStringTrim(tokens[i]); if (strcasecmp(tokens[i], format) == 0) break; if (mimetype && strcasecmp(mimetype, format) == 0) break; } if (i < n) psFormat = msSelectOutputFormat( map, format); } if(tokens) msFreeCharArray(tokens, n); } return psFormat; } #endif /* USE_WMS_SVR || USE_WFS_SVR || USE_WCS_SVR */ mapserver-7.4.3/mapows.h000066400000000000000000000621731357574274700152460ustar00rootroot00000000000000/***************************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC Web Services (WMS, WFS, WCS) support function definitions * Author: Daniel Morissette, DM Solutions Group (morissette@dmsolutions.ca) * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPOWS_H #define MAPOWS_H #include "maphttp.h" #include /* This is the URL to the official OGC Schema Repository. We use it by * default for OGC services unless the ows_schemas_lcoation web metadata * is set in the mapfile. */ #define OWS_DEFAULT_SCHEMAS_LOCATION "http://schemas.opengis.net" #if defined USE_LIBXML2 && defined USE_WFS_SVR #include #endif #ifdef __cplusplus extern "C" { #endif /*==================================================================== * mapows.c *====================================================================*/ typedef struct { char *pszVersion; char *pszUpdateSequence; char *pszRequest; char *pszService; char *pszTypeName; char *pszFilter; char *pszFilterLanguage; char *pszGeometryName; int nMaxFeatures; char *pszBbox; /* only used with a Get Request */ char *pszOutputFormat; char *pszFeatureId; char *pszSrs; char *pszResultType; char *pszPropertyName; int nStartIndex; char *pszAcceptVersions; char *pszSections; char *pszSortBy; /* Not implemented yet */ char *pszLanguage; /* Inspire extension */ char *pszValueReference; /* For GetValueReference */ char *pszStoredQueryId; /* For DescribeStoredQueries */ int countGetFeatureById; /* Number of urn:ogc:def:query:OGC-WFS::GetFeatureById GetFeature requests */ int bHasPostStoredQuery; /* TRUE if a XML GetFeature StoredQuery is present */ } wfsParamsObj; /* * sosParamsObj * Used to preprocess SOS request parameters * */ typedef struct { char *pszVersion; char *pszAcceptVersions; char *pszUpdateSequence; char *pszRequest; char *pszService; char *pszOutputFormat; char *pszSensorId; char *pszProcedure; char *pszOffering; char *pszObservedProperty; char *pszEventTime; char *pszResult; char *pszResponseFormat; char *pszResultModel; char *pszResponseMode; char *pszBBox; char *pszFeatureOfInterest; char *pszSrsName; } sosParamsObj; /* wmsParamsObj * * Used to preprocess WMS request parameters and combine layers that can * be comined in a GetMap request. */ typedef struct { char *onlineresource; hashTableObj *params; int numparams; char *httpcookiedata; } wmsParamsObj; /* metadataParamsObj: Represent a metadata specific request with its enabled layers */ typedef struct { char *pszRequest; char *pszLayer; char *pszOutputSchema; } metadataParamsObj; /* owsRequestObj: Represent a OWS specific request with its enabled layers */ typedef struct { int numlayers; int *enabled_layers; char *service; char *version; char *request; void *document; /* xmlDocPtr or CPLXMLNode* */ } owsRequestObj; MS_DLL_EXPORT int msOWSDispatch(mapObj *map, cgiRequestObj *request, int ows_mode); MS_DLL_EXPORT const char * msOWSLookupMetadata(hashTableObj *metadata, const char *namespaces, const char *name); MS_DLL_EXPORT const char * msOWSLookupMetadataWithLanguage(hashTableObj *metadata, const char *namespaces, const char *name, const char *validated_language); MS_DLL_EXPORT const char * msOWSLookupMetadata2(hashTableObj *pri, hashTableObj *sec, const char *namespaces, const char *name); MS_DLL_EXPORT int msOWSRequestIsEnabled(mapObj *map, layerObj *layer, const char *namespaces, const char *name, int check_all_layers); MS_DLL_EXPORT void msOWSRequestLayersEnabled(mapObj *map, const char *namespaces, const char *request, owsRequestObj *request_layers); MS_DLL_EXPORT int msOWSParseRequestMetadata(const char *metadata, const char *request, int *disabled); /* Constants for OWS Service version numbers */ #define OWS_0_1_2 0x000102 #define OWS_0_1_4 0x000104 #define OWS_0_1_6 0x000106 #define OWS_0_1_7 0x000107 #define OWS_1_0_0 0x010000 #define OWS_1_0_1 0x010001 #define OWS_1_0_6 0x010006 #define OWS_1_0_7 0x010007 #define OWS_1_0_8 0x010008 #define OWS_1_1_0 0x010100 #define OWS_1_1_1 0x010101 #define OWS_1_1_2 0x010102 #define OWS_1_3_0 0x010300 #define OWS_2_0_0 0x020000 #define OWS_2_0_1 0x020001 #define OWS_VERSION_MAXLEN 20 /* Buffer size for msOWSGetVersionString() */ #define OWS_VERSION_NOTSET -1 #define OWS_VERSION_BADFORMAT -2 MS_DLL_EXPORT int msOWSParseVersionString(const char *pszVersion); MS_DLL_EXPORT const char *msOWSGetVersionString(int nVersion, char *pszBuffer); #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) || defined(USE_WMS_LYR) || defined(USE_WFS_LYR) MS_DLL_EXPORT int msOWSMakeAllLayersUnique(mapObj *map); MS_DLL_EXPORT int msOWSNegotiateVersion(int requested_version, const int supported_versions[], int num_supported_versions); MS_DLL_EXPORT char *msOWSTerminateOnlineResource(const char *src_url); MS_DLL_EXPORT char *msOWSGetOnlineResource(mapObj *map, const char *namespaces, const char *metadata_name, cgiRequestObj *req); MS_DLL_EXPORT char *msOWSGetOnlineResource2(mapObj *map, const char *namespaces, const char *metadata_name, cgiRequestObj *req, const char *validated_language); MS_DLL_EXPORT const char *msOWSGetSchemasLocation(mapObj *map); MS_DLL_EXPORT const char *msOWSGetInspireSchemasLocation(mapObj *map); MS_DLL_EXPORT const char *msOWSGetLanguage(mapObj *map, const char *context); MS_DLL_EXPORT char **msOWSGetLanguageList(mapObj *map, const char *namespaces, int *numitems); MS_DLL_EXPORT char *msOWSGetLanguageFromList(mapObj *map, const char *namespaces, const char *requested_language); MS_DLL_EXPORT char *msOWSLanguageNegotiation(mapObj *map, const char *namespaces, char **accept_languages, int num_accept_languages); /* OWS_NOERR and OWS_WARN passed as action_if_not_found to printMetadata() */ #define OWS_NOERR 0 #define OWS_WARN 1 /* OWS_WMS and OWS_WFS used for functions that differ in behavior between */ /* WMS and WFS services (e.g. msOWSPrintLatLonBoundingBox()) */ typedef enum { OWS_WMS = 1, OWS_WFS = 2, OWS_WCS = 3 } OWSServiceType; MS_DLL_EXPORT int msOWSPrintInspireCommonExtendedCapabilities(FILE *stream, mapObj *map, const char *namespaces, const int action_if_not_found, const char *tag_name, const char* tag_ns, const char *validated_language, const OWSServiceType service); int msOWSPrintInspireCommonMetadata(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found, const OWSServiceType service); int msOWSPrintInspireCommonLanguages(FILE *stream, mapObj *map, const char *namespaces, int action_if_not_found, const char *validated_language); MS_DLL_EXPORT int msOWSPrintMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintEncodeMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value) ; int msOWSPrintEncodeMetadata2(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value, const char *validated_language); char *msOWSGetEncodeMetadata(hashTableObj *metadata, const char *namespaces, const char *name, const char *default_value); int msOWSPrintValidateMetadata(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintGroupMetadata(FILE *stream, mapObj *map, char* pszGroupName, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintGroupMetadata2(FILE *stream, mapObj *map, char* pszGroupName, const char *namespaces, const char *name, int action_if_not_found, const char *format, const char *default_value, const char *validated_language); int msOWSPrintURLType(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, int action_if_not_found, const char *tag_format, const char *tag_name, const char *type_format, const char *width_format, const char *height_format, const char *urlfrmt_format, const char *href_format, int type_is_mandatory, int width_is_mandatory, int height_is_mandatory, int format_is_mandatory, int href_is_mandatory, const char *default_type, const char *default_width, const char *default_height, const char *default_urlfrmt, const char *default_href, const char *tabspace); int msOWSPrintParam(FILE *stream, const char *name, const char *value, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintEncodeParam(FILE *stream, const char *name, const char *value, int action_if_not_found, const char *format, const char *default_value); int msOWSPrintMetadataList(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, const char *startTag, const char *endTag, const char *itemFormat, const char *default_value); int msOWSPrintEncodeMetadataList(FILE *stream, hashTableObj *metadata, const char *namespaces, const char *name, const char *startTag, const char *endTag, const char *itemFormat, const char *default_value); int msOWSPrintEncodeParamList(FILE *stream, const char *name, const char *value, int action_if_not_found, char delimiter, const char *startTag, const char *endTag, const char *format, const char *default_value); void msOWSProjectToWGS84(projectionObj *srcproj, rectObj *ext); void msOWSPrintLatLonBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj, projectionObj *wfsproj, OWSServiceType nService); void msOWSPrintEX_GeographicBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj); void msOWSPrintBoundingBox(FILE *stream, const char *tabspace, rectObj *extent, projectionObj *srcproj, hashTableObj *layer_meta, hashTableObj *map_meta, const char *namespaces, int wms_version); void msOWSPrintContactInfo( FILE *stream, const char *tabspace, int nVersion, hashTableObj *metadata, const char *namespaces ); int msOWSGetLayerExtent(mapObj *map, layerObj *lp, const char *namespaces, rectObj *ext); int msOWSExecuteRequests(httpRequestObj *pasReqInfo, int numRequests, mapObj *map, int bCheckLocalCache); void msOWSProcessException(layerObj *lp, const char *pszFname, int nErrorCode, const char *pszFuncName); char *msOWSBuildURLFilename(const char *pszPath, const char *pszURL, const char *pszExt); void msOWSGetEPSGProj(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne, char **epsgProj); char *msOWSGetProjURN(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne); char *msOWSGetProjURI(projectionObj *proj, hashTableObj *metadata, const char *namespaces, int bReturnOnlyFirstOne); void msOWSGetDimensionInfo(layerObj *layer, const char *pszDimension, const char **pszDimUserValue, const char **pszDimUnits, const char **pszDimDefault, const char **pszDimNearValue, const char **pszDimUnitSymbol, const char **pszDimMultiValue); int msOWSNegotiateUpdateSequence(const char *requested_updateSequence, const char *updatesequence); outputFormatObj *msOwsIsOutputFormatValid(mapObj *map, const char *format, hashTableObj *metadata, const char *namespaces, const char *name); #endif /* #if any wxs service enabled */ /*==================================================================== * mapgml.c *====================================================================*/ typedef enum { OWS_GML2, /* 2.1.2 */ OWS_GML3, /* 3.1.1 */ OWS_GML32 /* 3.2.1 */ } OWSGMLVersion; #define OWS_WFS_FEATURE_COLLECTION_NAME "msFeatureCollection" #define OWS_GML_DEFAULT_GEOMETRY_NAME "msGeometry" #define OWS_GML_OCCUR_UNBOUNDED -1 /* TODO, there must be a better way to generalize these lists of objects... */ typedef struct { char *name; /* name of the item */ char *alias; /* is the item aliased for presentation? (NULL if not) */ char *type; /* raw type for this item (NULL for a "string") (TODO: should this be a lookup table instead?) */ #ifndef __cplusplus char *template; /* presentation string for this item, needs to be a complete XML tag */ #else char *_template; /* presentation string for this item, needs to be a complete XML tag */ #endif int encode; /* should the value be HTML encoded? Default is MS_TRUE */ int visible; /* should this item be output, default is MS_FALSE */ int width; /* field width, zero if unknown */ int precision; /* field precision (decimal places), zero if unknown or N/A */ int outputByDefault; /* whether this should be output in a GetFeature without PropertyName. MS_TRUE by default, unless gml_default_items is specified and the item name is not in it */ int minOccurs; /* 0 by default. Can be set to 1 by specifying item name in gml_mandatory_items */ } gmlItemObj; typedef struct { gmlItemObj *items; int numitems; } gmlItemListObj; typedef struct { char *name; /* name of the constant */ char *type; /* raw type for this item (NULL for a "string") */ char *value; /* output value for this constant (output will look like: value) */ } gmlConstantObj; typedef struct { gmlConstantObj *constants; int numconstants; } gmlConstantListObj; typedef struct { char *name; /* name of the geometry (type of GML property) */ char *type; /* raw type for these geometries (point|multipoint|line|multiline|polygon|multipolygon */ int occurmin, occurmax; /* number of occurances (default 0,1) */ } gmlGeometryObj; typedef struct { gmlGeometryObj *geometries; int numgeometries; } gmlGeometryListObj; typedef struct { char *name; /* name of the group */ char **items; /* list of items in the group */ int numitems; /* number of items */ char *type; /* name of the complex type */ } gmlGroupObj; typedef struct { gmlGroupObj *groups; int numgroups; } gmlGroupListObj; typedef struct { char *prefix; char *uri; char *schemalocation; } gmlNamespaceObj; typedef struct { gmlNamespaceObj *namespaces; int numnamespaces; } gmlNamespaceListObj; #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) MS_DLL_EXPORT int msItemInGroups(const char *name, gmlGroupListObj *groupList); MS_DLL_EXPORT gmlItemListObj *msGMLGetItems(layerObj *layer, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeItems(gmlItemListObj *itemList); MS_DLL_EXPORT gmlConstantListObj *msGMLGetConstants(layerObj *layer, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeConstants(gmlConstantListObj *constantList); MS_DLL_EXPORT gmlGeometryListObj *msGMLGetGeometries(layerObj *layer, const char *metadata_namespaces, int bWithDefaultGeom); MS_DLL_EXPORT void msGMLFreeGeometries(gmlGeometryListObj *geometryList); MS_DLL_EXPORT gmlGroupListObj *msGMLGetGroups(layerObj *layer, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeGroups(gmlGroupListObj *groupList); MS_DLL_EXPORT gmlNamespaceListObj *msGMLGetNamespaces(webObj *web, const char *metadata_namespaces); MS_DLL_EXPORT void msGMLFreeNamespaces(gmlNamespaceListObj *namespaceList); #endif /* export to fix bug 851 */ MS_DLL_EXPORT int msGMLWriteQuery(mapObj *map, char *filename, const char *namespaces); #ifdef USE_WFS_SVR void msGMLWriteWFSBounds(mapObj *map, FILE *stream, const char *tab, OWSGMLVersion outputformat, int nWFSVersion, int bUseURN); MS_DLL_EXPORT int msGMLWriteWFSQuery(mapObj *map, FILE *stream, const char *wfs_namespace, OWSGMLVersion outputformat, int nWFSVersion, int bUseURN, int bGetPropertyValueRequest); #endif /*==================================================================== * mapwms.c *====================================================================*/ int msWMSDispatch(mapObj *map, cgiRequestObj *req, owsRequestObj *ows_request, int force_wms_mode); MS_DLL_EXPORT int msWMSLoadGetMapParams(mapObj *map, int nVersion, char **names, char **values, int numentries, char *wms_exception_format, const char *wms_request, owsRequestObj *ows_request); /*==================================================================== * mapwmslayer.c *====================================================================*/ #define WMS_GETMAP 1 #define WMS_GETFEATUREINFO 2 #define WMS_GETLEGENDGRAPHIC 3 int msInitWmsParamsObj(wmsParamsObj *wmsparams); void msFreeWmsParamsObj(wmsParamsObj *wmsparams); int msPrepareWMSLayerRequest(int nLayerId, mapObj *map, layerObj *lp, int nRequestType, enum MS_CONNECTION_TYPE lastconnectiontype, wmsParamsObj *psLastWMSParams, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat, httpRequestObj *pasReqInfo, int *numRequests); int msDrawWMSLayerLow(int nLayerId, httpRequestObj *pasReqInfo, int numRequests, mapObj *map, layerObj *lp, imageObj *img); MS_DLL_EXPORT char *msWMSGetFeatureInfoURL(mapObj *map, layerObj *lp, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat); int msWMSLayerExecuteRequest(mapObj *map, int nOWSLayers, int nClickX, int nClickY, int nFeatureCount, const char *pszInfoFormat, int type); /*==================================================================== * mapmetadata.c *====================================================================*/ metadataParamsObj *msMetadataCreateParamsObj(void); void msMetadataFreeParamsObj(metadataParamsObj *metadataparams); int msMetadataParseRequest(mapObj *map, cgiRequestObj *request, owsRequestObj *ows_request, metadataParamsObj *metadataparams); int msMetadataDispatch(mapObj *map, cgiRequestObj *requestobj, owsRequestObj *ows_request); void msMetadataSetGetMetadataURL(layerObj *lp, const char *url); /*==================================================================== * mapwfs.c *====================================================================*/ MS_DLL_EXPORT int msWFSDispatch(mapObj *map, cgiRequestObj *requestobj, owsRequestObj *ows_request, int force_wfs_mode); int msWFSParseRequest(mapObj *map, cgiRequestObj *, owsRequestObj *ows_request, wfsParamsObj *, int force_wfs_mode); wfsParamsObj *msWFSCreateParamsObj(void); int msWFSHandleUpdateSequence(mapObj *map, wfsParamsObj *wfsparams, const char* pszFunction); void msWFSFreeParamsObj(wfsParamsObj *wfsparams); int msWFSIsLayerSupported(layerObj *lp); int msWFSException(mapObj *map, const char *locator, const char *code, const char *version); #ifdef USE_WFS_SVR const char *msWFSGetGeomElementName(mapObj *map, layerObj *lp); int msWFSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version); int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *wfsparams, cgiRequestObj *req, owsRequestObj *ows_request); #ifdef USE_LIBXML2 xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws, int nWFSVersion, const char* validate_language, char *script_url); #endif char *msWFSGetOutputFormatList(mapObj *map, layerObj *layer, int nWFSVersion); int msWFSException20(mapObj *map, const char *locator, const char *exceptionCode); int msWFSGetCapabilities20(mapObj *map, wfsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request); int msWFSListStoredQueries20(mapObj *map, wfsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request); int msWFSDescribeStoredQueries20(mapObj *map, wfsParamsObj *params, cgiRequestObj *req, owsRequestObj *ows_request); char* msWFSGetResolvedStoredQuery20(mapObj *map, wfsParamsObj *wfsparams, const char* id, hashTableObj* hashTable); #endif /*==================================================================== * mapwfslayer.c *====================================================================*/ int msPrepareWFSLayerRequest(int nLayerId, mapObj *map, layerObj *lp, httpRequestObj *pasReqInfo, int *numRequests); void msWFSUpdateRequestInfo(layerObj *lp, httpRequestObj *pasReqInfo); int msWFSLayerOpen(layerObj *lp, const char *pszGMLFilename, rectObj *defaultBBOX); int msWFSLayerIsOpen(layerObj *lp); int msWFSLayerInitItemInfo(layerObj *layer); int msWFSLayerGetItems(layerObj *layer); int msWFSLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery); int msWFSLayerClose(layerObj *lp); MS_DLL_EXPORT char *msWFSExecuteGetFeature(layerObj *lp); /*==================================================================== * mapcontext.c *====================================================================*/ MS_DLL_EXPORT int msWriteMapContext(mapObj *map, FILE *stream); MS_DLL_EXPORT int msSaveMapContext(mapObj *map, char *filename); MS_DLL_EXPORT int msLoadMapContext(mapObj *map, char *filename, int unique_layer_names); MS_DLL_EXPORT int msLoadMapContextURL(mapObj *map, char *urlfilename, int unique_layer_names); /*==================================================================== * mapwcs.c *====================================================================*/ int msWCSDispatch(mapObj *map, cgiRequestObj *requestobj, owsRequestObj *ows_request); /* only 1 public function */ /*==================================================================== * mapogsos.c *====================================================================*/ int msSOSDispatch(mapObj *map, cgiRequestObj *requestobj, owsRequestObj *ows_request); /* only 1 public function */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* MAPOWS_H */ mapserver-7.4.3/mapowscommon.c000066400000000000000000000660531357574274700164530ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC OWS Common Implementation for use by MapServer OGC code * versions: * 1.0.0 (OGC Document 05-008c1) * 1.1.0 (OGC document 06-121r3) * * Author: Tom Kralidis (tomkralidis@gmail.com) * ****************************************************************************** * Copyright (c) 2006, Tom Kralidis * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "mapows.h" #ifdef USE_LIBXML2 #include #include #include "mapowscommon.h" #include "maplibxml2.h" /** * msOWSCommonServiceIdentification() * * returns an object of ServiceIdentification as per: * * 1.0.0 subclause 7.4.3 * 1.1.1 subclause 7.4.4 * * @param map mapObj used to fetch WEB/METADATA * @param servicetype the OWS type * @param supported_versions the supported version(s) of the OWS * * @return psRootNode xmlNodePtr of XML construct * */ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, const char *servicetype, const char *supported_versions, const char *namespaces, const char *validated_language) { const char *value = NULL; xmlNodePtr psRootNode = NULL; xmlNodePtr psNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); /* create element name */ psRootNode = xmlNewNode(psNsOws, BAD_CAST "ServiceIdentification"); /* add child elements */ value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "title", validated_language); psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Title", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_title\" missing for ows:Title")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "abstract", validated_language); psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Abstract", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_abstract\" was missing for ows:Abstract")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "keywordlist", validated_language); if (value) { psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL); msLibXml2GenerateList(psNode, psNsOws, "Keyword", value, ','); } else { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_keywordlist\" was missing for ows:KeywordList")); } psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ServiceType", BAD_CAST servicetype); xmlNewProp(psNode, BAD_CAST "codeSpace", BAD_CAST MS_OWSCOMMON_OGC_CODESPACE); msLibXml2GenerateList(psRootNode, psNsOws, "ServiceTypeVersion", supported_versions, ','); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "fees", validated_language); psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Fees", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_fees\" was missing for ows:Fees")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "accessconstraints", validated_language); psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "AccessConstraints", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_accessconstraints\" was missing for ows:AccessConstraints")); } return psRootNode; } /** * msOWSCommonServiceProvider() * * returns an object of ServiceProvider as per: * * * 1.0.0 subclause 7.4.4 * 1.1.0 subclause 7.4.5 * * @param map mapObj to fetch MAP/WEB/METADATA * * @return psRootNode xmlNodePtr pointer of XML construct * */ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink, mapObj *map, const char *namespaces, const char *validated_language) { const char *value = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psRootNode = NULL; xmlNodePtr psSubNode = NULL; xmlNodePtr psSubSubNode = NULL; xmlNodePtr psSubSubSubNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psRootNode = xmlNewNode(psNsOws, BAD_CAST "ServiceProvider"); /* add child elements */ value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactorganization", validated_language); psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ProviderName", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Mandatory metadata \"ows_contactorganization\" was missing for ows:ProviderName")); } psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ProviderSite", NULL); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple"); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "service_onlineresource", validated_language); xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST value); if (!value) { xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_service_onlineresource\" was missing for ows:ProviderSite/@xlink:href")); } psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ServiceContact", NULL); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactperson", validated_language); psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "IndividualName", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactperson\" was missing for ows:IndividualName")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactposition", validated_language); psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "PositionName", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactposition\" was missing for ows:PositionName")); } psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "ContactInfo", NULL); psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "Phone", NULL); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactvoicetelephone", validated_language); psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Voice", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactvoicetelephone\" was missing for ows:Voice")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactfacsimiletelephone", validated_language); psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Facsimile", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactfacsimiletelephone\" was missing for ows:Facsimile")); } psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "Address", NULL); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "address", validated_language); psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "DeliveryPoint", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_address\" was missing for ows:DeliveryPoint")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "city", validated_language); psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "City", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_city\" was missing for ows:City")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "stateorprovince", validated_language); psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "AdministrativeArea", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_stateorprovince\" was missing for ows:AdministrativeArea")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "postcode", validated_language); psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "PostalCode", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_postcode\" was missing for ows:PostalCode")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "country", validated_language); psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Country", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_country\" was missing for ows:Country")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactelectronicmailaddress", validated_language); psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "ElectronicMailAddress", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactelectronicmailaddress\" was missing for ows:ElectronicMailAddress")); } psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "OnlineResource", NULL); xmlNewNsProp(psSubSubNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple"); value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "service_onlineresource", validated_language); xmlNewNsProp(psSubSubNode, psNsXLink, BAD_CAST "href", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_service_onlineresource\" was missing for ows:OnlineResource/@xlink:href")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "hoursofservice", validated_language); psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "HoursOfService", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_hoursofservice\" was missing for ows:HoursOfService")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactinstructions", validated_language); psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "ContactInstructions", BAD_CAST value); if (!value) { xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactinstructions\" was missing for ows:ContactInstructions")); } value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "role", validated_language); psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "Role", BAD_CAST value); if (!value) { xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_role\" was missing for ows:Role")); } return psRootNode; } /** * msOWSCommonOperationsMetadata() * * returns the root element of OperationsMetadata as per: * * 1.0.0 subclause 7.4.5 * 1.1.0 subclause 7.4.6 * * @return psRootNode xmlNodePtr pointer of XML construct * */ xmlNodePtr msOWSCommonOperationsMetadata(xmlNsPtr psNsOws) { xmlNodePtr psRootNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psRootNode = xmlNewNode(psNsOws, BAD_CAST "OperationsMetadata"); return psRootNode; } /** * msOWSCommonOperationsMetadataOperation() * * returns an Operation element of OperationsMetadata as per: * * 1.0.0 subclause 7.4.5 * 1.1.0 subclause 7.4.6 * * @param name name of the Operation * @param method HTTP method: OWS_METHOD_GET, OWS_METHOD_POST or OWS_METHOD_GETPOST) * @param url online resource URL * * @return psRootNode xmlNodePtr pointer of XML construct */ xmlNodePtr msOWSCommonOperationsMetadataOperation(xmlNsPtr psNsOws, xmlNsPtr psXLinkNs, char *name, int method, char *url) { xmlNodePtr psRootNode = NULL; xmlNodePtr psNode = NULL; xmlNodePtr psSubNode = NULL; xmlNodePtr psSubSubNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psRootNode = xmlNewNode(psNsOws, BAD_CAST "Operation"); xmlNewProp(psRootNode, BAD_CAST "name", BAD_CAST name); psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "DCP", NULL); psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "HTTP", NULL); if (method == OWS_METHOD_GET || method == OWS_METHOD_GETPOST ) { psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Get", NULL); xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "type", BAD_CAST "simple"); xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "href", BAD_CAST url); } if (method == OWS_METHOD_POST || method == OWS_METHOD_GETPOST ) { psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Post", NULL); xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "type", BAD_CAST "simple"); xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "href", BAD_CAST url); } return psRootNode; } /** * msOWSCommonOperationsMetadataDomainType() * * returns a Parameter or Constraint element (which are of type ows:DomainType) * of OperationsMetadata as per: * * 1.0.0 subclause 7.4.5 * 1.1.0 subclause 7.4.6 * * @param version the integerized x.y.z version of OWS Common to use * @param elname name of the element (Parameter | Constraint) * @param name name of the Parameter * @param values list of values (comma separated list) or NULL if none * * @return psRootNode xmlNodePtr pointer of XML construct * */ xmlNodePtr msOWSCommonOperationsMetadataDomainType(int version, xmlNsPtr psNsOws, char *elname, char *name, char *values) { xmlNodePtr psRootNode = NULL; xmlNodePtr psNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); psRootNode = xmlNewNode(psNsOws, BAD_CAST elname); xmlNewProp(psRootNode, BAD_CAST "name", BAD_CAST name); if (version == OWS_1_0_0) { msLibXml2GenerateList(psRootNode, psNsOws, "Value", values, ','); } if (version == OWS_1_1_0 || version == OWS_2_0_0) { psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "AllowedValues", NULL); msLibXml2GenerateList(psNode, psNsOws, "Value", values, ','); } return psRootNode; } /** * msOWSCommonExceptionReport() * * returns an object of ExceptionReport as per clause 8 * * @param ows_version the version of OWS Common to use * @param schemas_location URL to OGC Schemas Location base * @param version the version of the calling specification * @param language ISO3166 code of language * @param exceptionCode a code from the calling specification's list of exceptions, or from OWS Common * @param locator where the exception was encountered (i.e. "layers" keyword) * @param ExceptionText the actual error message * * @return psRootNode xmlNodePtr pointer of XML construct * */ xmlNodePtr msOWSCommonExceptionReport(xmlNsPtr psNsOws, int ows_version, const char *schemas_location, const char *version, const char *language, const char *exceptionCode, const char *locator, const char *ExceptionText) { char *xsi_schemaLocation = NULL; char szVersionBuf[OWS_VERSION_MAXLEN]; xmlNsPtr psNsXsi = NULL; xmlNodePtr psRootNode = NULL; xmlNodePtr psMainNode = NULL; psRootNode = xmlNewNode(psNsOws, BAD_CAST "ExceptionReport"); psNsXsi = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX); /* add attributes to root element */ xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST version); if (ows_version == OWS_1_0_0) { xmlNewProp(psRootNode, BAD_CAST "language", BAD_CAST language); } if (ows_version == OWS_1_1_0) { xmlNewProp(psRootNode, BAD_CAST "xml:lang", BAD_CAST language); } xsi_schemaLocation = msStrdup((char *)psNsOws->href); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " "); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *)schemas_location); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/ows/"); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, (char *)msOWSGetVersionString(ows_version, szVersionBuf)); xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/owsExceptionReport.xsd"); /* add namespace'd attributes to root element */ xmlNewNsProp(psRootNode, psNsXsi, BAD_CAST "schemaLocation", BAD_CAST xsi_schemaLocation); /* add child element */ psMainNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Exception", NULL); /* add attributes to child */ xmlNewProp(psMainNode, BAD_CAST "exceptionCode", BAD_CAST exceptionCode); if (locator != NULL) { xmlNewProp(psMainNode, BAD_CAST "locator", BAD_CAST locator); } if (ExceptionText != NULL) { xmlNewTextChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST ExceptionText); } free(xsi_schemaLocation); return psRootNode; } /** * msOWSCommonBoundingBox() * * returns an object of BoundingBox as per subclause 10.2.1 * * If necessary (ie. an EPSG URN GCS such as 4326) the tuple axes will be * reoriented to match the EPSG coordinate system expectations. * * @param psNsOws OWS namespace object * @param crs the CRS / EPSG code * @param dimensions number of dimensions of the coordinates * @param minx minx * @param miny miny * @param maxx maxx * @param maxy maxy * * @return psRootNode xmlNodePtr pointer of XML construct */ xmlNodePtr msOWSCommonBoundingBox(xmlNsPtr psNsOws, const char *crs, int dimensions, double minx, double miny, double maxx, double maxy) { char LowerCorner[100]; char UpperCorner[100]; char dim_string[100]; xmlNodePtr psRootNode = NULL; /* Do we need to reorient tuple axes? */ if(crs && strstr(crs, "imageCRS") == NULL) { projectionObj proj; msInitProjection( &proj ); if( msLoadProjectionString( &proj, (char *) crs ) == 0 ) { msAxisNormalizePoints( &proj, 1, &minx, &miny ); msAxisNormalizePoints( &proj, 1, &maxx, &maxy ); } msFreeProjection( &proj ); } if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); /* create element name */ psRootNode = xmlNewNode(psNsOws, BAD_CAST "BoundingBox"); /* add attributes to the root element */ xmlNewProp(psRootNode, BAD_CAST "crs", BAD_CAST crs); snprintf( dim_string, sizeof(dim_string), "%d", dimensions ); xmlNewProp(psRootNode, BAD_CAST "dimensions", BAD_CAST dim_string); snprintf(LowerCorner, sizeof(LowerCorner), "%.15g %.15g", minx, miny); snprintf(UpperCorner, sizeof(UpperCorner), "%.15g %.15g", maxx, maxy); /* add child elements */ xmlNewChild(psRootNode, psNsOws,BAD_CAST "LowerCorner",BAD_CAST LowerCorner); xmlNewChild(psRootNode, psNsOws,BAD_CAST "UpperCorner",BAD_CAST UpperCorner); return psRootNode; } /** * msOWSCommonWGS84BoundingBox() * * returns an object of WGS84BoundingBox as per subclause 10.2.2 * * @param psNsOws OWS namespace object * @param dimensions number of dimensions of the coordinates * @param minx minx * @param miny miny * @param maxx maxx * @param maxy maxy * * @return psRootNode xmlNodePtr pointer of XML construct */ xmlNodePtr msOWSCommonWGS84BoundingBox(xmlNsPtr psNsOws, int dimensions, double minx, double miny, double maxx, double maxy) { char LowerCorner[100]; char UpperCorner[100]; char dim_string[100]; xmlNodePtr psRootNode = NULL; if (_validateNamespace(psNsOws) == MS_FAILURE) psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX); /* create element name */ psRootNode = xmlNewNode(psNsOws, BAD_CAST "WGS84BoundingBox"); snprintf( dim_string, sizeof(dim_string), "%d", dimensions ); xmlNewProp(psRootNode, BAD_CAST "dimensions", BAD_CAST dim_string); snprintf(LowerCorner, sizeof(LowerCorner), "%.15g %.15g", minx, miny); snprintf(UpperCorner, sizeof(UpperCorner), "%.15g %.15g", maxx, maxy); /* add child elements */ xmlNewChild(psRootNode, psNsOws,BAD_CAST "LowerCorner",BAD_CAST LowerCorner); xmlNewChild(psRootNode, psNsOws,BAD_CAST "UpperCorner",BAD_CAST UpperCorner); return psRootNode; } /** * _validateNamespace() * * validates the namespace passed to this module's functions * * @param psNsOws namespace object * * @return MS_SUCCESS or MS_FAILURE * */ int _validateNamespace(xmlNsPtr psNsOws) { char namespace_prefix[10]; snprintf(namespace_prefix, sizeof(namespace_prefix), "%s", psNsOws->prefix); if (strcmp(namespace_prefix, MS_OWSCOMMON_OWS_NAMESPACE_PREFIX) == 0) return MS_SUCCESS; else return MS_FAILURE; } /* * Valid an xml string against an XML schema * Inpired from: http://xml.developpez.com/sources/?page=validation#validate_XSD_CppCLI_2 * taken from tinyows.org */ int msOWSSchemaValidation(const char* xml_schema, const char* xml) { xmlSchemaPtr schema; xmlSchemaParserCtxtPtr ctxt; xmlSchemaValidCtxtPtr validctxt; int ret; xmlDocPtr doc; if (!xml_schema || !xml) return MS_FAILURE; xmlInitParser(); schema = NULL; ret = -1; /* To valide WFS 2.0 requests, we might need to explicitely import */ /* GML and FES 2.0 */ if( strlen(xml_schema) > strlen(MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION) && strcmp(xml_schema + strlen(xml_schema) - strlen(MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION), MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION) == 0 ) { char szInMemSchema[2048]; char szBaseLocation[256]; strncpy(szBaseLocation, xml_schema, strlen(xml_schema) - strlen(MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION)); szBaseLocation[strlen(xml_schema) - strlen(MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION)] = '\0'; strcpy(szInMemSchema, "\n"); sprintf(szInMemSchema + strlen(szInMemSchema), "\n", MS_OWSCOMMON_WFS_20_NAMESPACE_URI, xml_schema); if( strstr(xml, MS_OWSCOMMON_FES_20_NAMESPACE_URI) != NULL ) { sprintf(szInMemSchema + strlen(szInMemSchema), "\n", MS_OWSCOMMON_FES_20_NAMESPACE_URI, szBaseLocation, MS_OWSCOMMON_FES_20_SCHEMA_LOCATION); } if( strstr(xml, MS_OWSCOMMON_GML_32_NAMESPACE_URI) != NULL ) { sprintf(szInMemSchema + strlen(szInMemSchema), "\n", MS_OWSCOMMON_GML_32_NAMESPACE_URI, szBaseLocation, MS_OWSCOMMON_GML_321_SCHEMA_LOCATION); } else if( strstr(xml, MS_OWSCOMMON_GML_NAMESPACE_URI) != NULL ) { if( strstr(xml, MS_OWSCOMMON_GML_212_SCHEMA_LOCATION) != NULL ) { sprintf(szInMemSchema + strlen(szInMemSchema), "\n", MS_OWSCOMMON_GML_NAMESPACE_URI, szBaseLocation, MS_OWSCOMMON_GML_212_SCHEMA_LOCATION); } else if( strstr(xml, MS_OWSCOMMON_GML_311_SCHEMA_LOCATION) != NULL ) { sprintf(szInMemSchema + strlen(szInMemSchema), "\n", MS_OWSCOMMON_GML_NAMESPACE_URI, szBaseLocation, MS_OWSCOMMON_GML_311_SCHEMA_LOCATION); } } strcat(szInMemSchema, "\n"); /*fprintf(stderr, "%s\n", szInMemSchema);*/ ctxt = xmlSchemaNewMemParserCtxt(szInMemSchema, strlen(szInMemSchema)); } else { /* Open XML Schema File */ ctxt = xmlSchemaNewParserCtxt(xml_schema); } /* xmlSchemaSetParserErrors(ctxt, (xmlSchemaValidityErrorFunc) libxml2_callback, (xmlSchemaValidityWarningFunc) libxml2_callback, stderr); */ schema = xmlSchemaParse(ctxt); xmlSchemaFreeParserCtxt(ctxt); /* If XML Schema hasn't been rightly loaded */ if (schema == NULL) { xmlSchemaCleanupTypes(); xmlMemoryDump(); xmlCleanupParser(); return ret; } doc = xmlParseDoc((xmlChar *)xml); if (doc != NULL) { /* Loading XML Schema content */ validctxt = xmlSchemaNewValidCtxt(schema); /* xmlSchemaSetValidErrors(validctxt, (xmlSchemaValidityErrorFunc) libxml2_callback, (xmlSchemaValidityWarningFunc) libxml2_callback, stderr); */ /* validation */ ret = xmlSchemaValidateDoc(validctxt, doc); xmlSchemaFreeValidCtxt(validctxt); } xmlSchemaFree(schema); xmlFreeDoc(doc); xmlCleanupParser(); return ret; } #endif /* defined(USE_LIBXML2) */ /** * msOWSCommonNegotiateVersion() * * returns a supported version as per subclause 7.3.2 * * @param requested_version the version passed by the client * @param supported_versions an array of supported versions * @param num_supported_versions size of supported_versions * * @return supported version integer, or -1 on error * */ int msOWSCommonNegotiateVersion(int requested_version, const int supported_versions[], int num_supported_versions) { int i; /* if version is not set return error */ if (! requested_version) return -1; /* return the first entry that's equal to the requested version */ for (i = 0; i < num_supported_versions; i++) { if (supported_versions[i] == requested_version) return supported_versions[i]; } /* no match; calling code should throw an exception */ return -1; } mapserver-7.4.3/mapowscommon.h000066400000000000000000000173571357574274700164630ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: OGC OWS Common Implementation include file * Author: Tom Kralidis (tomkralidis@gmail.com) * ****************************************************************************** * Copyright (c) 2006, Tom Kralidis * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPOWSCOMMON_H #define MAPOWSCOMMON_H #ifdef USE_LIBXML2 #include #include #endif /* W3C namespaces */ #define MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI "http://www.w3.org/1999/xlink" #define MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX "xlink" #define MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI "http://www.w3.org/2001/XMLSchema-instance" #define MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX "xsi" #define MS_OWSCOMMON_W3C_XS_NAMESPACE_URI "http://www.w3.org/2001/XMLSchema" #define MS_OWSCOMMON_W3C_XS_NAMESPACE_PREFIX "xs" /* OGC namespaces */ #define MS_OWSCOMMON_OGC_NAMESPACE_URI "http://www.opengis.net/ogc" #define MS_OWSCOMMON_OGC_NAMESPACE_PREFIX "ogc" #define MS_OWSCOMMON_OWS_NAMESPACE_URI "http://www.opengis.net/ows" #define MS_OWSCOMMON_OWS_NAMESPACE_PREFIX "ows" #define MS_OWSCOMMON_OWS_110_NAMESPACE_URI "http://www.opengis.net/ows/1.1" #define MS_OWSCOMMON_OWS_20_NAMESPACE_URI "http://www.opengis.net/ows/2.0" #define MS_OWSCOMMON_OWS_20_SCHEMAS_LOCATION "/ows/2.0/owsAll.xsd" /* OGC URNs */ #define MS_OWSCOMMON_URN_OGC_CRS_4326 "urn:opengis:def:crs:OGC:2:84" /* default OGC Schemas Location */ #define MS_OWSCOMMON_SCHEMAS_LOCATION "http://schemas.opengis.net" /* OGC codespace */ #define MS_OWSCOMMON_OGC_CODESPACE "OGC" /* WCS namespaces */ #define MS_OWSCOMMON_WCS_20_NAMESPACE_URI "http://www.opengis.net/wcs/2.0" #define MS_OWSCOMMON_WCS_20_SCHEMAS_LOCATION "/wcs/2.0/wcsAll.xsd" #define MS_OWSCOMMON_WCS_NAMESPACE_PREFIX "wcs" /* GML namespaces */ #define MS_OWSCOMMON_GML_NAMESPACE_URI "http://www.opengis.net/gml" #define MS_OWSCOMMON_GML_NAMESPACE_PREFIX "gml" #define MS_OWSCOMMON_GML_32_NAMESPACE_URI "http://www.opengis.net/gml/3.2" #define MS_OWSCOMMON_GML_212_SCHEMA_LOCATION "/gml/2.1.2/feature.xsd" #define MS_OWSCOMMON_GML_311_SCHEMA_LOCATION "/gml/3.1.1/base/gml.xsd" #define MS_OWSCOMMON_GML_321_SCHEMA_LOCATION "/gml/3.2.1/gml.xsd" /* WFS namespaces */ #define MS_OWSCOMMON_WFS_NAMESPACE_PREFIX "wfs" #define MS_OWSCOMMON_WFS_NAMESPACE_URI "http://www.opengis.net/wfs" #define MS_OWSCOMMON_WFS_20_NAMESPACE_URI "http://www.opengis.net/wfs/2.0" #define MS_OWSCOMMON_WFS_10_SCHEMA_LOCATION "/wfs/1.0.0/WFS-basic.xsd" #define MS_OWSCOMMON_WFS_11_SCHEMA_LOCATION "/wfs/1.1.0/wfs.xsd" #define MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION "/wfs/2.0/wfs.xsd" /* FES namespaces */ #define MS_OWSCOMMON_FES_20_NAMESPACE_PREFIX "fes" #define MS_OWSCOMMON_FES_20_NAMESPACE_URI "http://www.opengis.net/fes/2.0" #define MS_OWSCOMMON_FES_20_SCHEMA_LOCATION "/filter/2.0/filterAll.xsd" /* GMLCov namespaces */ #define MS_OWSCOMMON_GMLCOV_10_NAMESPACE_URI "http://www.opengis.net/gmlcov/1.0" #define MS_OWSCOMMON_GMLCOV_NAMESPACE_PREFIX "gmlcov" /* SWE namespaces */ #define MS_OWSCOMMON_SWE_20_NAMESPACE_URI "http://www.opengis.net/swe/2.0" #define MS_OWSCOMMON_SWE_NAMESPACE_PREFIX "swe" /* Inspire namespaces */ #define MS_INSPIRE_COMMON_NAMESPACE_URI "http://inspire.ec.europa.eu/schemas/common/1.0" #define MS_INSPIRE_COMMON_NAMESPACE_PREFIX "inspire_common" #define MS_INSPIRE_COMMON_SCHEMA_LOCATION "/common/1.0/common.xsd" #define MS_INSPIRE_VS_NAMESPACE_URI "http://inspire.ec.europa.eu/schemas/inspire_vs/1.0" #define MS_INSPIRE_VS_NAMESPACE_PREFIX "inspire_vs" #define MS_INSPIRE_VS_SCHEMA_LOCATION "/inspire_vs/1.0/inspire_vs.xsd" #define MS_INSPIRE_DLS_NAMESPACE_URI "http://inspire.ec.europa.eu/schemas/inspire_dls/1.0" #define MS_INSPIRE_DLS_NAMESPACE_PREFIX "inspire_dls" #define MS_INSPIRE_DLS_SCHEMA_LOCATION "/inspire_dls/1.0/inspire_dls.xsd" /* MapServer namespaces */ #define MS_DEFAULT_NAMESPACE_PREFIX "ms" #define MS_DEFAULT_NAMESPACE_URI "http://mapserver.gis.umn.edu/mapserver" /* OWS errors */ /* OWS 1.1.0 Table 25 */ #define MS_OWS_ERROR_OPERATION_NOT_SUPPORTED "OperationNotSupported" #define MS_OWS_ERROR_MISSING_PARAMETER_VALUE "MissingParameterValue" #define MS_OWS_ERROR_INVALID_PARAMETER_VALUE "InvalidParameterValue" #define MS_OWS_ERROR_VERSION_NEGOTIATION_FAILED "VersionNegotiationFailed" #define MS_OWS_ERROR_INVALID_UPDATE_SEQUENCE "InvalidUpdateSequence" #define MS_OWS_ERROR_OPTION_NOT_SUPPORTED "OptionNotSupported" #define MS_OWS_ERROR_NO_APPLICABLE_CODE "NoApplicableCode" #define MS_WFS_ERROR_OPERATION_PROCESSING_FAILED "OperationProcessingFailed" #ifdef USE_LIBXML2 /* function prototypes */ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map, const char *servicetype, const char *version, const char *namespaces, const char *validated_language); xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psXLinkNs, mapObj *map, const char *namespaces, const char *validated_language); xmlNodePtr msOWSCommonOperationsMetadata(xmlNsPtr psNsOws); #define OWS_METHOD_GET 1 #define OWS_METHOD_POST 2 #define OWS_METHOD_GETPOST 3 xmlNodePtr msOWSCommonOperationsMetadataOperation(xmlNsPtr psNsOws, xmlNsPtr psXLinkNs, char *name, int method, char *url); xmlNodePtr msOWSCommonOperationsMetadataDomainType(int version, xmlNsPtr psNsOws, char *elname, char *name, char *values); xmlNodePtr msOWSCommonExceptionReport(xmlNsPtr psNsOws, int ows_version, const char *schemas_location, const char *version, const char *language, const char *exceptionCode, const char *locator, const char *ExceptionText); xmlNodePtr msOWSCommonBoundingBox(xmlNsPtr psNsOws, const char *crs, int dimensions, double minx, double miny, double maxx, double maxy); xmlNodePtr msOWSCommonWGS84BoundingBox(xmlNsPtr psNsOws, int dimensions, double minx, double miny, double maxx, double maxy); int _validateNamespace(xmlNsPtr psNsOws); int msOWSSchemaValidation(const char* xml_schema, const char* xml); #endif /* defined(USE_LIBXML2) */ int msOWSCommonNegotiateVersion(int requested_version, const int supported_versions[], int num_supported_versions); #endif /* MAPOWSCOMMON_H */ mapserver-7.4.3/mapparser.c000066400000000000000000003020121357574274700157120ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison implementation for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "3.0.4" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Copy the first part of user declarations. */ #line 5 "mapparser.y" /* yacc.c:339 */ /* C declarations */ #include #include #include #include #include #include "mapserver.h" /* for TRUE/FALSE and REGEX includes */ #include "maptime.h" /* for time comparison routines */ #include "mapprimitive.h" /* for shapeObj */ #include "mapparser.h" /* for YYSTYPE in the function prototype for yylex() */ int yylex(YYSTYPE *, parseObj *); /* prototype functions, defined after the grammar */ int yyerror(parseObj *, const char *); #line 84 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULLPTR nullptr # else # define YY_NULLPTR 0 # endif # endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* In a future release of Bison, this section will be replaced by #include "mapparser.h". */ #ifndef YY_YY_HOME_EVEN_MAPSERVER_MAPSERVER_MAPPARSER_H_INCLUDED # define YY_YY_HOME_EVEN_MAPSERVER_MAPSERVER_MAPPARSER_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif #if YYDEBUG extern int yydebug; #endif /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { BOOLEAN = 258, NUMBER = 259, STRING = 260, TIME = 261, SHAPE = 262, OR = 263, AND = 264, NOT = 265, RE = 266, EQ = 267, NE = 268, LT = 269, GT = 270, LE = 271, GE = 272, IN = 273, IEQ = 274, IRE = 275, INTERSECTS = 276, DISJOINT = 277, TOUCHES = 278, OVERLAPS = 279, CROSSES = 280, WITHIN = 281, CONTAINS = 282, EQUALS = 283, BEYOND = 284, DWITHIN = 285, AREA = 286, LENGTH = 287, COMMIFY = 288, ROUND = 289, UPPER = 290, LOWER = 291, INITCAP = 292, FIRSTCAP = 293, TOSTRING = 294, YYBUFFER = 295, DIFFERENCE = 296, SIMPLIFY = 297, SIMPLIFYPT = 298, GENERALIZE = 299, SMOOTHSIA = 300, JAVASCRIPT = 301, NEG = 302 }; #endif /* Tokens. */ #define BOOLEAN 258 #define NUMBER 259 #define STRING 260 #define TIME 261 #define SHAPE 262 #define OR 263 #define AND 264 #define NOT 265 #define RE 266 #define EQ 267 #define NE 268 #define LT 269 #define GT 270 #define LE 271 #define GE 272 #define IN 273 #define IEQ 274 #define IRE 275 #define INTERSECTS 276 #define DISJOINT 277 #define TOUCHES 278 #define OVERLAPS 279 #define CROSSES 280 #define WITHIN 281 #define CONTAINS 282 #define EQUALS 283 #define BEYOND 284 #define DWITHIN 285 #define AREA 286 #define LENGTH 287 #define COMMIFY 288 #define ROUND 289 #define UPPER 290 #define LOWER 291 #define INITCAP 292 #define FIRSTCAP 293 #define TOSTRING 294 #define YYBUFFER 295 #define DIFFERENCE 296 #define SIMPLIFY 297 #define SIMPLIFYPT 298 #define GENERALIZE 299 #define SMOOTHSIA 300 #define JAVASCRIPT 301 #define NEG 302 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { #line 30 "mapparser.y" /* yacc.c:355 */ double dblval; int intval; char *strval; struct tm tmval; shapeObj *shpval; #line 226 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:355 */ }; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 #endif int yyparse (parseObj *p); #endif /* !YY_YY_HOME_EVEN_MAPSERVER_MAPSERVER_MAPPARSER_H_INCLUDED */ /* Copy the second part of user declarations. */ #line 242 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:358 */ #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #else typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ # define YY_(Msgid) Msgid # endif #endif #ifndef YY_ATTRIBUTE # if (defined __GNUC__ \ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C # define YY_ATTRIBUTE(Spec) __attribute__(Spec) # else # define YY_ATTRIBUTE(Spec) /* empty */ # endif #endif #ifndef YY_ATTRIBUTE_PURE # define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) #endif #ifndef YY_ATTRIBUTE_UNUSED # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif #if !defined _Noreturn \ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) # if defined _MSC_VER && 1200 <= _MSC_VER # define _Noreturn __declspec (noreturn) # else # define _Noreturn YY_ATTRIBUTE ((__noreturn__)) # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) #else # define YYUSE(E) /* empty */ #endif #if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value #endif #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif #ifndef YY_INITIAL_VALUE # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's 'empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED /* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ while (0) # endif # endif #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ #define YYFINAL 78 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 510 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 57 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 7 /* YYNRULES -- Number of rules. */ #define YYNRULES 97 /* YYNSTATES -- Number of states. */ #define YYNSTATES 287 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 302 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 2, 2, 54, 55, 49, 47, 56, 48, 2, 50, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 53, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 52 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 68, 68, 69, 82, 96, 109, 119, 120, 121, 125, 133, 142, 150, 159, 167, 176, 184, 193, 194, 195, 215, 235, 241, 247, 253, 259, 265, 271, 279, 287, 295, 303, 311, 319, 325, 331, 337, 343, 349, 355, 376, 396, 402, 410, 416, 427, 438, 449, 460, 471, 482, 493, 504, 515, 526, 537, 548, 559, 570, 581, 592, 602, 614, 615, 616, 617, 618, 619, 620, 627, 628, 629, 630, 638, 641, 642, 643, 653, 663, 673, 683, 693, 703, 713, 723, 734, 752, 753, 754, 758, 763, 767, 771, 775, 779, 785, 786 }; #endif #if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "BOOLEAN", "NUMBER", "STRING", "TIME", "SHAPE", "OR", "AND", "NOT", "RE", "EQ", "NE", "LT", "GT", "LE", "GE", "IN", "IEQ", "IRE", "INTERSECTS", "DISJOINT", "TOUCHES", "OVERLAPS", "CROSSES", "WITHIN", "CONTAINS", "EQUALS", "BEYOND", "DWITHIN", "AREA", "LENGTH", "COMMIFY", "ROUND", "UPPER", "LOWER", "INITCAP", "FIRSTCAP", "TOSTRING", "YYBUFFER", "DIFFERENCE", "SIMPLIFY", "SIMPLIFYPT", "GENERALIZE", "SMOOTHSIA", "JAVASCRIPT", "'+'", "'-'", "'*'", "'/'", "'%'", "NEG", "'^'", "'('", "')'", "','", "$accept", "input", "logical_exp", "math_exp", "shape_exp", "string_exp", "time_exp", YY_NULLPTR }; #endif # ifdef YYPRINT /* YYTOKNUM[NUM] -- (External) token number corresponding to the (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 43, 45, 42, 47, 37, 302, 94, 40, 41, 44 }; # endif #define YYPACT_NINF -44 #define yypact_value_is_default(Yystate) \ (!!((Yystate) == (-44))) #define YYTABLE_NINF -1 #define yytable_value_is_error(Yytable_value) \ 0 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int16 yypact[] = { 275, -44, -44, -44, -44, -44, 275, -3, -2, 1, 12, 19, 32, 33, 34, 35, 37, 47, 48, 49, 50, 51, 64, 65, 66, 67, 69, 81, 83, 110, 120, 123, 125, -1, 275, 45, 6, 324, 58, 247, 193, 42, 387, 58, 247, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 4, 4, -1, 4, 4, 4, 4, -1, 117, 117, 117, 117, 117, 117, 117, -1, 79, 8, 173, 219, 378, 9, -44, 275, 275, 275, 275, 275, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, 117, 117, 117, 117, 117, 117, 117, 117, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, -4, -4, -4, -4, -4, -4, -4, 117, 16, 124, 137, 155, 176, 199, 200, 201, 214, 215, 179, 4, -28, -11, 119, -9, 118, 129, 178, 360, 216, 230, 231, 232, 234, -7, 266, 371, -44, -44, -44, -44, -44, 23, 335, 42, 387, -44, 324, 23, 335, 42, 387, 457, 457, 457, 457, 457, 457, 189, 457, 18, 18, 79, 79, 79, 79, -44, -44, -44, -44, -44, -44, -44, -44, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, -44, -4, -44, -44, -44, -44, -44, -44, -44, 184, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, -44, 180, -44, -44, -1, -44, -44, -44, -44, 4, -1, 117, -1, -1, -1, -44, -1, 4, 220, 269, 272, 273, 276, 279, 290, 291, 300, 274, 301, 394, 183, 403, 303, 412, 421, 430, -43, 221, -44, -44, -44, -44, -44, -44, -44, -44, -1, -1, -44, -44, -44, -44, -44, -44, -44, -44, -1, -44, 439, 448, 78, -44, -44, -44, 4, 222, -44 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 2, 7, 63, 87, 96, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 6, 5, 0, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 76, 88, 97, 10, 12, 11, 13, 9, 0, 14, 16, 15, 17, 22, 23, 25, 24, 27, 26, 41, 42, 65, 66, 67, 69, 68, 71, 45, 48, 50, 52, 54, 56, 58, 60, 20, 28, 29, 31, 30, 33, 32, 40, 43, 21, 89, 0, 34, 35, 37, 36, 39, 38, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 72, 91, 0, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 49, 51, 53, 55, 57, 59, 46, 0, 0, 74, 90, 77, 78, 79, 80, 81, 83, 0, 86, 0, 0, 0, 62, 61, 84, 0, 0, 85 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -44, -44, -5, 59, 149, 0, -23 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 35, 36, 37, 43, 44, 40 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule whose number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint16 yytable[] = { 39, 41, 4, 2, 92, 93, 94, 95, 96, 3, 97, 77, 275, 276, 79, 80, 79, 80, 81, 116, 81, 117, 118, 119, 120, 121, 122, 222, 123, 73, 17, 18, 80, 20, 76, 81, 116, 19, 116, 21, 22, 23, 24, 25, 223, 78, 225, 33, 235, 236, 201, 45, 46, 71, 81, 47, 137, 138, 136, 140, 141, 142, 143, 153, 157, 42, 48, 94, 95, 96, 98, 97, 210, 49, 158, 160, 162, 164, 166, 99, 100, 101, 102, 103, 104, 105, 50, 51, 52, 53, 174, 54, 72, 74, 202, 203, 204, 205, 206, 207, 208, 55, 56, 57, 58, 59, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 139, 60, 61, 62, 63, 144, 64, 5, 92, 93, 94, 95, 96, 152, 97, 97, 283, 284, 65, 221, 66, 159, 161, 163, 165, 167, 168, 169, 170, 171, 172, 173, 38, 175, 176, 177, 178, 179, 180, 181, 26, 27, 28, 29, 30, 31, 32, 67, 116, 92, 93, 94, 95, 96, 124, 97, 226, 68, 224, 116, 69, 238, 70, 211, 82, 83, 75, 227, 84, 85, 86, 87, 88, 89, 90, 91, 212, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 117, 118, 119, 120, 121, 122, 213, 123, 145, 146, 147, 148, 149, 150, 151, 92, 93, 94, 95, 96, 116, 97, 116, 154, 250, 116, 98, 214, 228, 220, 156, 116, 257, 269, 155, 99, 100, 101, 102, 103, 104, 105, 182, 183, 184, 185, 186, 187, 188, 189, 215, 216, 217, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 116, 218, 219, 230, 209, 155, 157, 277, 286, 1, 2, 3, 4, 5, 249, 285, 6, 231, 232, 233, 251, 234, 253, 254, 255, 116, 256, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 237, 33, 258, 278, 279, 259, 260, 34, 266, 261, 82, 83, 262, 280, 84, 85, 86, 87, 88, 89, 90, 91, 83, 263, 264, 84, 85, 86, 87, 88, 89, 90, 91, 265, 0, 267, 271, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 0, 0, 92, 93, 94, 95, 96, 0, 97, 0, 0, 252, 0, 92, 93, 94, 95, 96, 0, 97, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 0, 97, 0, 0, 229, 0, 92, 93, 94, 95, 96, 0, 97, 116, 154, 0, 0, 0, 0, 0, 0, 156, 92, 93, 94, 95, 96, 0, 97, 92, 93, 94, 95, 96, 0, 97, 0, 268, 92, 93, 94, 95, 96, 0, 97, 0, 270, 92, 93, 94, 95, 96, 0, 97, 0, 272, 92, 93, 94, 95, 96, 0, 97, 0, 273, 92, 93, 94, 95, 96, 0, 97, 0, 274, 92, 93, 94, 95, 96, 0, 97, 0, 281, 92, 93, 94, 95, 96, 0, 97, 0, 282, 92, 93, 94, 95, 96, 0, 97 }; static const yytype_int16 yycheck[] = { 0, 6, 6, 4, 47, 48, 49, 50, 51, 5, 53, 34, 55, 56, 8, 9, 8, 9, 12, 47, 12, 12, 13, 14, 15, 16, 17, 55, 19, 34, 31, 32, 9, 34, 34, 12, 47, 33, 47, 35, 36, 37, 38, 39, 55, 0, 55, 48, 55, 56, 54, 54, 54, 54, 12, 54, 56, 57, 54, 59, 60, 61, 62, 55, 55, 6, 54, 49, 50, 51, 12, 53, 56, 54, 79, 80, 81, 82, 83, 21, 22, 23, 24, 25, 26, 27, 54, 54, 54, 54, 90, 54, 33, 34, 117, 118, 119, 120, 121, 122, 123, 54, 54, 54, 54, 54, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 58, 54, 54, 54, 54, 63, 54, 7, 47, 48, 49, 50, 51, 71, 53, 53, 55, 56, 54, 136, 54, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 91, 92, 93, 94, 95, 96, 97, 40, 41, 42, 43, 44, 45, 46, 54, 47, 47, 48, 49, 50, 51, 54, 53, 55, 54, 56, 47, 54, 201, 54, 56, 8, 9, 34, 55, 12, 13, 14, 15, 16, 17, 18, 19, 56, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 12, 13, 14, 15, 16, 17, 56, 19, 64, 65, 66, 67, 68, 69, 70, 47, 48, 49, 50, 51, 47, 53, 47, 55, 229, 47, 12, 56, 55, 55, 55, 47, 237, 55, 55, 21, 22, 23, 24, 25, 26, 27, 98, 99, 100, 101, 102, 103, 104, 105, 56, 56, 56, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 47, 47, 56, 56, 56, 124, 55, 55, 55, 55, 3, 4, 5, 6, 7, 224, 284, 10, 56, 56, 56, 230, 56, 232, 233, 234, 47, 236, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 56, 48, 55, 266, 267, 55, 55, 54, 56, 55, 8, 9, 55, 276, 12, 13, 14, 15, 16, 17, 18, 19, 9, 55, 55, 12, 13, 14, 15, 16, 17, 18, 19, 55, -1, 56, 55, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, -1, -1, 47, 48, 49, 50, 51, -1, 53, -1, -1, 231, -1, 47, 48, 49, 50, 51, -1, 53, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 12, 13, 14, 15, 16, 17, 18, 19, 47, 48, 49, 50, 51, -1, 53, -1, -1, 56, -1, 47, 48, 49, 50, 51, -1, 53, 47, 55, -1, -1, -1, -1, -1, -1, 55, 47, 48, 49, 50, 51, -1, 53, 47, 48, 49, 50, 51, -1, 53, -1, 55, 47, 48, 49, 50, 51, -1, 53, -1, 55, 47, 48, 49, 50, 51, -1, 53, -1, 55, 47, 48, 49, 50, 51, -1, 53, -1, 55, 47, 48, 49, 50, 51, -1, 53, -1, 55, 47, 48, 49, 50, 51, -1, 53, -1, 55, 47, 48, 49, 50, 51, -1, 53, -1, 55, 47, 48, 49, 50, 51, -1, 53 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 3, 4, 5, 6, 7, 10, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 54, 58, 59, 60, 61, 62, 63, 59, 60, 61, 62, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 60, 59, 60, 61, 62, 63, 0, 8, 9, 12, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 47, 48, 49, 50, 51, 53, 12, 21, 22, 23, 24, 25, 26, 27, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 47, 12, 13, 14, 15, 16, 17, 19, 54, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 54, 62, 62, 60, 62, 62, 62, 62, 60, 61, 61, 61, 61, 61, 61, 61, 60, 55, 55, 55, 55, 55, 59, 60, 59, 60, 59, 60, 59, 60, 59, 60, 60, 60, 60, 60, 60, 60, 62, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 54, 63, 63, 63, 63, 63, 63, 63, 61, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 55, 62, 55, 55, 56, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 55, 56, 56, 63, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 60, 62, 60, 61, 60, 60, 60, 60, 62, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 56, 55, 60, 60, 60, 55, 55, 55, 56, 62, 55 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 57, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 8, 8, 1, 3, 3, 3, 3, 3, 3, 2, 3, 4, 4, 6, 1, 3, 6, 6, 6, 6, 6, 4, 6, 8, 10, 6, 1, 3, 3, 6, 4, 4, 4, 4, 4, 1, 3 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ YYPOPSTACK (yylen); \ yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ yyerror (p, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) /* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) /* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value, p); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*----------------------------------------. | Print this symbol's value on YYOUTPUT. | `----------------------------------------*/ static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parseObj *p) { FILE *yyo = yyoutput; YYUSE (yyo); YYUSE (p); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parseObj *p) { YYFPRINTF (yyoutput, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep, p); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, parseObj *p) { unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], &(yyvsp[(yyi + 1) - (yynrhs)]) , p); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyssp, yyvsp, Rule, p); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T yystrlen (const char *yystr) { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * yystpcpy (char *yydest, const char *yysrc) { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN for the state stack whose top is YYSSP. Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is not large enough to hold the message. In that case, also set *YYMSG_ALLOC to the required number of bytes. Return 2 if the required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); YYSIZE_T yysize = yysize0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ const char *yyformat = YY_NULLPTR; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per "expected"). */ int yycount = 0; /* There are many possibilities here to consider: - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected tokens because there are none. - The only way there can be no lookahead present (in yychar) is if this state is a consistent state with a default action. Thus, detecting the absence of a lookahead is sufficient to determine that there is no unexpected or expected token to report. In that case, just report a simple "syntax error". - Don't assume there isn't a lookahead just because this state is a consistent state with a default action. There might have been a previous inconsistent state, consistent state with a non-default action, or user semantic action that manipulated yychar. - Of course, the expected token list depends on states to have correct lookahead information, and it depends on the parser not to perform extra reductions after fetching a lookahead from the scanner and before detecting a syntax error. Thus, state merging (from LALR or IELR) and default reductions corrupt the expected token list. However, the list is correct for canonical LR with one exception: it will still contain any token that will not be accepted due to an error action in a later state. */ if (yytoken != YYEMPTY) { int yyn = yypact[*yyssp]; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. In other words, skip the first -YYN actions for this state because they are default actions. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyx; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; break; } yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } } } } switch (yycount) { # define YYCASE_(N, S) \ case N: \ yyformat = S; \ break YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); # undef YYCASE_ } { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } if (*yymsg_alloc < yysize) { *yymsg_alloc = 2 * yysize; if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; return 1; } /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ { char *yyp = *yymsg; int yyi = 0; while ((*yyp = *yyformat) != '\0') if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyformat += 2; } else { yyp++; yyformat++; } } return 0; } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parseObj *p) { YYUSE (yyvaluep); YYUSE (p); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); YY_IGNORE_MAYBE_UNINITIALIZED_END } /*----------. | yyparse. | `----------*/ int yyparse (parseObj *p) { /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ /* Default value used for initialization, for pacifying older GCCs or non-GCC compilers. */ YY_INITIAL_VALUE (static YYSTYPE yyval_default;) YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); /* Number of syntax errors so far. */ int yynerrs; int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: 'yyss': related to states. 'yyvs': related to semantic values. Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yyssp = yyss = yyssa; yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = yylex (&yylval, p); } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 3: #line 69 "mapparser.y" /* yacc.c:1646 */ { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): p->result.intval = (yyvsp[0].intval); break; case(MS_PARSE_TYPE_STRING): if((yyvsp[0].intval)) p->result.strval = msStrdup("true"); else p->result.strval = msStrdup("false"); break; } } #line 1555 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 4: #line 82 "mapparser.y" /* yacc.c:1646 */ { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): if((yyvsp[0].dblval) != 0) p->result.intval = MS_TRUE; else p->result.intval = MS_FALSE; break; case(MS_PARSE_TYPE_STRING): p->result.strval = (char *)malloc(64); /* large enough for a double */ snprintf(p->result.strval, 64, "%g", (yyvsp[0].dblval)); break; } } #line 1574 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 5: #line 96 "mapparser.y" /* yacc.c:1646 */ { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): if((yyvsp[0].strval)) /* string is not NULL */ p->result.intval = MS_TRUE; else p->result.intval = MS_FALSE; break; case(MS_PARSE_TYPE_STRING): p->result.strval = (yyvsp[0].strval); // msStrdup($1); break; } } #line 1592 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 6: #line 109 "mapparser.y" /* yacc.c:1646 */ { switch(p->type) { case(MS_PARSE_TYPE_SHAPE): p->result.shpval = (yyvsp[0].shpval); p->result.shpval->scratch = MS_FALSE; break; } } #line 1605 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 8: #line 120 "mapparser.y" /* yacc.c:1646 */ { (yyval.intval) = (yyvsp[-1].intval); } #line 1611 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 9: #line 121 "mapparser.y" /* yacc.c:1646 */ { (yyval.intval) = MS_FALSE; if((yyvsp[-2].intval) == (yyvsp[0].intval)) (yyval.intval) = MS_TRUE; } #line 1620 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 10: #line 125 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else if((yyvsp[0].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1633 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 11: #line 133 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].intval) == MS_TRUE) { if((yyvsp[0].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } else (yyval.intval) = MS_FALSE; } #line 1647 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 12: #line 142 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else if((yyvsp[0].dblval) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1660 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 13: #line 150 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].intval) == MS_TRUE) { if((yyvsp[0].dblval) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } else (yyval.intval) = MS_FALSE; } #line 1674 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 14: #line 159 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) != 0) (yyval.intval) = MS_TRUE; else if((yyvsp[0].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1687 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 15: #line 167 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) != 0) { if((yyvsp[0].intval) == MS_TRUE) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } else (yyval.intval) = MS_FALSE; } #line 1701 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 16: #line 176 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) != 0) (yyval.intval) = MS_TRUE; else if((yyvsp[0].dblval) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1714 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 17: #line 184 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) != 0) { if((yyvsp[0].dblval) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } else (yyval.intval) = MS_FALSE; } #line 1728 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 18: #line 193 "mapparser.y" /* yacc.c:1646 */ { (yyval.intval) = !(yyvsp[0].intval); } #line 1734 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 19: #line 194 "mapparser.y" /* yacc.c:1646 */ { (yyval.intval) = !(yyvsp[0].dblval); } #line 1740 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 20: #line 195 "mapparser.y" /* yacc.c:1646 */ { ms_regex_t re; if(MS_STRING_IS_NULL_OR_EMPTY((yyvsp[-2].strval)) == MS_TRUE) { (yyval.intval) = MS_FALSE; } else { if(ms_regcomp(&re, (yyvsp[0].strval), MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { (yyval.intval) = MS_FALSE; } else { if(ms_regexec(&re, (yyvsp[-2].strval), 0, NULL, 0) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ms_regfree(&re); } } free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 1765 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 21: #line 215 "mapparser.y" /* yacc.c:1646 */ { ms_regex_t re; if(MS_STRING_IS_NULL_OR_EMPTY((yyvsp[-2].strval)) == MS_TRUE) { (yyval.intval) = MS_FALSE; } else { if(ms_regcomp(&re, (yyvsp[0].strval), MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) { (yyval.intval) = MS_FALSE; } else { if(ms_regexec(&re, (yyvsp[-2].strval), 0, NULL, 0) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; ms_regfree(&re); } } free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 1790 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 22: #line 235 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) == (yyvsp[0].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1801 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 23: #line 241 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) != (yyvsp[0].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1812 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 24: #line 247 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) > (yyvsp[0].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1823 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 25: #line 253 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) < (yyvsp[0].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1834 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 26: #line 259 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) >= (yyvsp[0].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1845 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 27: #line 265 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) <= (yyvsp[0].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1856 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 28: #line 271 "mapparser.y" /* yacc.c:1646 */ { if(strcmp((yyvsp[-2].strval), (yyvsp[0].strval)) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 1869 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 29: #line 279 "mapparser.y" /* yacc.c:1646 */ { if(strcmp((yyvsp[-2].strval), (yyvsp[0].strval)) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 1882 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 30: #line 287 "mapparser.y" /* yacc.c:1646 */ { if(strcmp((yyvsp[-2].strval), (yyvsp[0].strval)) > 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 1895 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 31: #line 295 "mapparser.y" /* yacc.c:1646 */ { if(strcmp((yyvsp[-2].strval), (yyvsp[0].strval)) < 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 1908 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 32: #line 303 "mapparser.y" /* yacc.c:1646 */ { if(strcmp((yyvsp[-2].strval), (yyvsp[0].strval)) >= 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 1921 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 33: #line 311 "mapparser.y" /* yacc.c:1646 */ { if(strcmp((yyvsp[-2].strval), (yyvsp[0].strval)) <= 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 1934 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 34: #line 319 "mapparser.y" /* yacc.c:1646 */ { if(msTimeCompare(&((yyvsp[-2].tmval)), &((yyvsp[0].tmval))) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1945 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 35: #line 325 "mapparser.y" /* yacc.c:1646 */ { if(msTimeCompare(&((yyvsp[-2].tmval)), &((yyvsp[0].tmval))) != 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1956 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 36: #line 331 "mapparser.y" /* yacc.c:1646 */ { if(msTimeCompare(&((yyvsp[-2].tmval)), &((yyvsp[0].tmval))) > 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1967 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 37: #line 337 "mapparser.y" /* yacc.c:1646 */ { if(msTimeCompare(&((yyvsp[-2].tmval)), &((yyvsp[0].tmval))) < 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1978 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 38: #line 343 "mapparser.y" /* yacc.c:1646 */ { if(msTimeCompare(&((yyvsp[-2].tmval)), &((yyvsp[0].tmval))) >= 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 1989 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 39: #line 349 "mapparser.y" /* yacc.c:1646 */ { if(msTimeCompare(&((yyvsp[-2].tmval)), &((yyvsp[0].tmval))) <= 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 2000 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 40: #line 355 "mapparser.y" /* yacc.c:1646 */ { char *delim, *bufferp; (yyval.intval) = MS_FALSE; bufferp=(yyvsp[0].strval); while((delim=strchr(bufferp,',')) != NULL) { *delim='\0'; if(strcmp((yyvsp[-2].strval),bufferp) == 0) { (yyval.intval) = MS_TRUE; break; } *delim=','; bufferp=delim+1; } if((yyval.intval) == MS_FALSE && strcmp((yyvsp[-2].strval),bufferp) == 0) // test for last (or only) item (yyval.intval) = MS_TRUE; free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 2026 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 41: #line 376 "mapparser.y" /* yacc.c:1646 */ { char *delim,*bufferp; (yyval.intval) = MS_FALSE; bufferp=(yyvsp[0].strval); while((delim=strchr(bufferp,',')) != NULL) { *delim='\0'; if((yyvsp[-2].dblval) == atof(bufferp)) { (yyval.intval) = MS_TRUE; break; } *delim=','; bufferp=delim+1; } if((yyvsp[-2].dblval) == atof(bufferp)) // is this test necessary? (yyval.intval) = MS_TRUE; free((yyvsp[0].strval)); } #line 2051 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 42: #line 396 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-2].dblval) == (yyvsp[0].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 2062 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 43: #line 402 "mapparser.y" /* yacc.c:1646 */ { if(strcasecmp((yyvsp[-2].strval), (yyvsp[0].strval)) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 2075 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 44: #line 410 "mapparser.y" /* yacc.c:1646 */ { if(msTimeCompare(&((yyvsp[-2].tmval)), &((yyvsp[0].tmval))) == 0) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 2086 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 45: #line 416 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSEquals((yyvsp[-2].shpval), (yyvsp[0].shpval)); if((yyvsp[-2].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-2].shpval)); if((yyvsp[0].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[0].shpval)); if(rval == -1) { yyerror(p, "Equals (EQ or ==) operator failed."); return(-1); } else (yyval.intval) = rval; } #line 2102 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 46: #line 427 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSEquals((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); if(rval == -1) { yyerror(p, "Equals function failed."); return(-1); } else (yyval.intval) = rval; } #line 2118 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 47: #line 438 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSIntersects((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); if(rval == -1) { yyerror(p, "Intersects function failed."); return(-1); } else (yyval.intval) = rval; } #line 2134 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 48: #line 449 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSIntersects((yyvsp[-2].shpval), (yyvsp[0].shpval)); if((yyvsp[-2].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-2].shpval)); if((yyvsp[0].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[0].shpval)); if(rval == -1) { yyerror(p, "Intersects operator failed."); return(-1); } else (yyval.intval) = rval; } #line 2150 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 49: #line 460 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSDisjoint((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); if(rval == -1) { yyerror(p, "Disjoint function failed."); return(-1); } else (yyval.intval) = rval; } #line 2166 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 50: #line 471 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSDisjoint((yyvsp[-2].shpval), (yyvsp[0].shpval)); if((yyvsp[-2].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-2].shpval)); if((yyvsp[0].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[0].shpval)); if(rval == -1) { yyerror(p, "Disjoint operator failed."); return(-1); } else (yyval.intval) = rval; } #line 2182 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 51: #line 482 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSTouches((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); if(rval == -1) { yyerror(p, "Touches function failed."); return(-1); } else (yyval.intval) = rval; } #line 2198 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 52: #line 493 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSTouches((yyvsp[-2].shpval), (yyvsp[0].shpval)); if((yyvsp[-2].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-2].shpval)); if((yyvsp[0].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[0].shpval)); if(rval == -1) { yyerror(p, "Touches operator failed."); return(-1); } else (yyval.intval) = rval; } #line 2214 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 53: #line 504 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSOverlaps((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); if(rval == -1) { yyerror(p, "Overlaps function failed."); return(-1); } else (yyval.intval) = rval; } #line 2230 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 54: #line 515 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSOverlaps((yyvsp[-2].shpval), (yyvsp[0].shpval)); if((yyvsp[-2].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-2].shpval)); if((yyvsp[0].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[0].shpval)); if(rval == -1) { yyerror(p, "Overlaps operator failed."); return(-1); } else (yyval.intval) = rval; } #line 2246 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 55: #line 526 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSCrosses((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); if(rval == -1) { yyerror(p, "Crosses function failed."); return(-1); } else (yyval.intval) = rval; } #line 2262 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 56: #line 537 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSCrosses((yyvsp[-2].shpval), (yyvsp[0].shpval)); if((yyvsp[-2].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-2].shpval)); if((yyvsp[0].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[0].shpval)); if(rval == -1) { yyerror(p, "Crosses operator failed."); return(-1); } else (yyval.intval) = rval; } #line 2278 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 57: #line 548 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSWithin((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); if(rval == -1) { yyerror(p, "Within function failed."); return(-1); } else (yyval.intval) = rval; } #line 2294 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 58: #line 559 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSWithin((yyvsp[-2].shpval), (yyvsp[0].shpval)); if((yyvsp[-2].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-2].shpval)); if((yyvsp[0].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[0].shpval)); if(rval == -1) { yyerror(p, "Within operator failed."); return(-1); } else (yyval.intval) = rval; } #line 2310 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 59: #line 570 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSContains((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); if(rval == -1) { yyerror(p, "Contains function failed."); return(-1); } else (yyval.intval) = rval; } #line 2326 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 60: #line 581 "mapparser.y" /* yacc.c:1646 */ { int rval; rval = msGEOSContains((yyvsp[-2].shpval), (yyvsp[0].shpval)); if((yyvsp[-2].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-2].shpval)); if((yyvsp[0].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[0].shpval)); if(rval == -1) { yyerror(p, "Contains operator failed."); return(-1); } else (yyval.intval) = rval; } #line 2342 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 61: #line 592 "mapparser.y" /* yacc.c:1646 */ { double d; d = msGEOSDistance((yyvsp[-5].shpval), (yyvsp[-3].shpval)); if((yyvsp[-5].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-5].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if(d <= (yyvsp[-1].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 2357 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 62: #line 602 "mapparser.y" /* yacc.c:1646 */ { double d; d = msGEOSDistance((yyvsp[-5].shpval), (yyvsp[-3].shpval)); if((yyvsp[-5].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-5].shpval)); if((yyvsp[-3].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-3].shpval)); if(d > (yyvsp[-1].dblval)) (yyval.intval) = MS_TRUE; else (yyval.intval) = MS_FALSE; } #line 2372 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 64: #line 615 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = (yyvsp[-1].dblval); } #line 2378 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 65: #line 616 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = (yyvsp[-2].dblval) + (yyvsp[0].dblval); } #line 2384 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 66: #line 617 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = (yyvsp[-2].dblval) - (yyvsp[0].dblval); } #line 2390 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 67: #line 618 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = (yyvsp[-2].dblval) * (yyvsp[0].dblval); } #line 2396 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 68: #line 619 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = (int)(yyvsp[-2].dblval) % (int)(yyvsp[0].dblval); } #line 2402 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 69: #line 620 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[0].dblval) == 0.0) { yyerror(p, "Division by zero."); return(-1); } else (yyval.dblval) = (yyvsp[-2].dblval) / (yyvsp[0].dblval); } #line 2414 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 70: #line 627 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = (yyvsp[0].dblval); } #line 2420 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 71: #line 628 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = pow((yyvsp[-2].dblval), (yyvsp[0].dblval)); } #line 2426 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 72: #line 629 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = strlen((yyvsp[-1].strval)); } #line 2432 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 73: #line 630 "mapparser.y" /* yacc.c:1646 */ { if((yyvsp[-1].shpval)->type != MS_SHAPE_POLYGON) { yyerror(p, "Area can only be computed for polygon shapes."); return(-1); } (yyval.dblval) = msGetPolygonArea((yyvsp[-1].shpval)); if((yyvsp[-1].shpval)->scratch == MS_TRUE) msFreeShape((yyvsp[-1].shpval)); } #line 2445 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 74: #line 638 "mapparser.y" /* yacc.c:1646 */ { (yyval.dblval) = (MS_NINT((yyvsp[-3].dblval)/(yyvsp[-1].dblval)))*(yyvsp[-1].dblval); } #line 2451 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 76: #line 642 "mapparser.y" /* yacc.c:1646 */ { (yyval.shpval) = (yyvsp[-1].shpval); } #line 2457 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 77: #line 643 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msGEOSBuffer((yyvsp[-3].shpval), (yyvsp[-1].dblval)); if(!s) { yyerror(p, "Executing buffer failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2472 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 78: #line 653 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msGEOSDifference((yyvsp[-3].shpval), (yyvsp[-1].shpval)); if(!s) { yyerror(p, "Executing difference failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2487 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 79: #line 663 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msGEOSSimplify((yyvsp[-3].shpval), (yyvsp[-1].dblval)); if(!s) { yyerror(p, "Executing simplify failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2502 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 80: #line 673 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msGEOSTopologyPreservingSimplify((yyvsp[-3].shpval), (yyvsp[-1].dblval)); if(!s) { yyerror(p, "Executing simplifypt failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2517 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 81: #line 683 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msGeneralize((yyvsp[-3].shpval), (yyvsp[-1].dblval)); if(!s) { yyerror(p, "Executing generalize failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2532 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 82: #line 693 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msSmoothShapeSIA((yyvsp[-1].shpval), 3, 1, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2547 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 83: #line 703 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msSmoothShapeSIA((yyvsp[-3].shpval), (yyvsp[-1].dblval), 1, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2562 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 84: #line 713 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msSmoothShapeSIA((yyvsp[-5].shpval), (yyvsp[-3].dblval), (yyvsp[-1].dblval), NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2577 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 85: #line 723 "mapparser.y" /* yacc.c:1646 */ { shapeObj *s; s = msSmoothShapeSIA((yyvsp[-7].shpval), (yyvsp[-5].dblval), (yyvsp[-3].dblval), (yyvsp[-1].strval)); free((yyvsp[-1].strval)); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; } #line 2593 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 86: #line 734 "mapparser.y" /* yacc.c:1646 */ { #ifdef USE_V8_MAPSCRIPT shapeObj *s; s = msV8TransformShape((yyvsp[-3].shpval), (yyvsp[-1].strval)); free((yyvsp[-1].strval)); if(!s) { yyerror(p, "Executing javascript failed."); return(-1); } s->scratch = MS_TRUE; (yyval.shpval) = s; #else yyerror(p, "Javascript support not compiled in"); return(-1); #endif } #line 2614 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 88: #line 753 "mapparser.y" /* yacc.c:1646 */ { (yyval.strval) = (yyvsp[-1].strval); } #line 2620 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 89: #line 754 "mapparser.y" /* yacc.c:1646 */ { (yyval.strval) = (char *)malloc(strlen((yyvsp[-2].strval)) + strlen((yyvsp[0].strval)) + 1); sprintf((yyval.strval), "%s%s", (yyvsp[-2].strval), (yyvsp[0].strval)); free((yyvsp[-2].strval)); free((yyvsp[0].strval)); } #line 2629 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 90: #line 758 "mapparser.y" /* yacc.c:1646 */ { (yyval.strval) = (char *) malloc(strlen((yyvsp[-1].strval)) + 64); /* Plenty big? Should use snprintf below... */ sprintf((yyval.strval), (yyvsp[-1].strval), (yyvsp[-3].dblval)); free((yyvsp[-1].strval)); } #line 2639 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 91: #line 763 "mapparser.y" /* yacc.c:1646 */ { (yyvsp[-1].strval) = msCommifyString((yyvsp[-1].strval)); (yyval.strval) = (yyvsp[-1].strval); } #line 2648 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 92: #line 767 "mapparser.y" /* yacc.c:1646 */ { msStringToUpper((yyvsp[-1].strval)); (yyval.strval) = (yyvsp[-1].strval); } #line 2657 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 93: #line 771 "mapparser.y" /* yacc.c:1646 */ { msStringToLower((yyvsp[-1].strval)); (yyval.strval) = (yyvsp[-1].strval); } #line 2666 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 94: #line 775 "mapparser.y" /* yacc.c:1646 */ { msStringInitCap((yyvsp[-1].strval)); (yyval.strval) = (yyvsp[-1].strval); } #line 2675 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 95: #line 779 "mapparser.y" /* yacc.c:1646 */ { msStringFirstCap((yyvsp[-1].strval)); (yyval.strval) = (yyvsp[-1].strval); } #line 2684 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; case 97: #line 786 "mapparser.y" /* yacc.c:1646 */ { (yyval.tmval) = (yyvsp[-1].tmval); } #line 2690 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ break; #line 2694 "/home/even/mapserver/mapserver/mapparser.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR or YYBACKUP, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*--------------------------------------. | yyerrlab -- here on detecting error. | `--------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (p, YY_("syntax error")); #else # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ yyssp, yytoken) { char const *yymsgp = YY_("syntax error"); int yysyntax_error_status; yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; else if (yysyntax_error_status == 1) { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); if (!yymsg) { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; yysyntax_error_status = 2; } else { yysyntax_error_status = YYSYNTAX_ERROR; yymsgp = yymsg; } } yyerror (p, yymsgp); if (yysyntax_error_status == 2) goto yyexhaustedlab; } # undef YYSYNTAX_ERROR #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval, p); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp, p); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (p, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval, p); } /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp, p); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif return yyresult; } #line 789 "mapparser.y" /* yacc.c:1906 */ /* ** Any extra C functions */ int yylex(YYSTYPE *lvalp, parseObj *p) { int token; if(p->expr->curtoken == NULL) return(0); /* done */ // fprintf(stderr, "in yylex() - curtoken=%d...\n", p->expr->curtoken->token); token = p->expr->curtoken->token; /* may override */ switch(p->expr->curtoken->token) { case MS_TOKEN_LITERAL_BOOLEAN: token = BOOLEAN; (*lvalp).intval = p->expr->curtoken->tokenval.dblval; break; case MS_TOKEN_LITERAL_NUMBER: token = NUMBER; (*lvalp).dblval = p->expr->curtoken->tokenval.dblval; break; case MS_TOKEN_LITERAL_SHAPE: token = SHAPE; // fprintf(stderr, "token value = %s\n", msShapeToWKT(p->expr->curtoken->tokenval.shpval)); (*lvalp).shpval = p->expr->curtoken->tokenval.shpval; break; case MS_TOKEN_LITERAL_STRING: // printf("token value = %s\n", p->expr->curtoken->tokenval.strval); token = STRING; (*lvalp).strval = msStrdup(p->expr->curtoken->tokenval.strval); break; case MS_TOKEN_LITERAL_TIME: token = TIME; (*lvalp).tmval = p->expr->curtoken->tokenval.tmval; break; case MS_TOKEN_COMPARISON_EQ: token = EQ; break; case MS_TOKEN_COMPARISON_IEQ: token = IEQ; break; case MS_TOKEN_COMPARISON_NE: token = NE; break; case MS_TOKEN_COMPARISON_LT: token = LT; break; case MS_TOKEN_COMPARISON_GT: token = GT; break; case MS_TOKEN_COMPARISON_LE: token = LE; break; case MS_TOKEN_COMPARISON_GE: token = GE; break; case MS_TOKEN_COMPARISON_RE: token = RE; break; case MS_TOKEN_COMPARISON_IRE: token = IRE; break; case MS_TOKEN_COMPARISON_IN: token = IN; break; case MS_TOKEN_COMPARISON_INTERSECTS: token = INTERSECTS; break; case MS_TOKEN_COMPARISON_DISJOINT: token = DISJOINT; break; case MS_TOKEN_COMPARISON_TOUCHES: token = TOUCHES; break; case MS_TOKEN_COMPARISON_OVERLAPS: token = OVERLAPS; break; case MS_TOKEN_COMPARISON_CROSSES: token = CROSSES; break; case MS_TOKEN_COMPARISON_WITHIN: token = WITHIN; break; case MS_TOKEN_COMPARISON_CONTAINS: token = CONTAINS; break; case MS_TOKEN_COMPARISON_EQUALS: token = EQUALS; break; case MS_TOKEN_COMPARISON_BEYOND: token = BEYOND; break; case MS_TOKEN_COMPARISON_DWITHIN: token = DWITHIN; break; case MS_TOKEN_LOGICAL_AND: token = AND; break; case MS_TOKEN_LOGICAL_OR: token = OR; break; case MS_TOKEN_LOGICAL_NOT: token = NOT; break; case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: token = NUMBER; (*lvalp).dblval = atof(p->shape->values[p->expr->curtoken->tokenval.bindval.index]); break; case MS_TOKEN_BINDING_STRING: token = STRING; (*lvalp).strval = msStrdup(p->shape->values[p->expr->curtoken->tokenval.bindval.index]); break; case MS_TOKEN_BINDING_SHAPE: token = SHAPE; // fprintf(stderr, "token value = %s\n", msShapeToWKT(p->shape)); (*lvalp).shpval = p->shape; break; case MS_TOKEN_BINDING_MAP_CELLSIZE: token = NUMBER; (*lvalp).dblval = p->dblval; break; case MS_TOKEN_BINDING_DATA_CELLSIZE: token = NUMBER; (*lvalp).dblval = p->dblval2; break; case MS_TOKEN_BINDING_TIME: token = TIME; msTimeInit(&((*lvalp).tmval)); if(msParseTime(p->shape->values[p->expr->curtoken->tokenval.bindval.index], &((*lvalp).tmval)) != MS_TRUE) { yyerror(p, "Parsing time value failed."); return(-1); } break; case MS_TOKEN_FUNCTION_AREA: token = AREA; break; case MS_TOKEN_FUNCTION_LENGTH: token = LENGTH; break; case MS_TOKEN_FUNCTION_TOSTRING: token = TOSTRING; break; case MS_TOKEN_FUNCTION_COMMIFY: token = COMMIFY; break; case MS_TOKEN_FUNCTION_UPPER: token = UPPER; break; case MS_TOKEN_FUNCTION_LOWER: token = LOWER; break; case MS_TOKEN_FUNCTION_INITCAP: token = INITCAP; break; case MS_TOKEN_FUNCTION_FIRSTCAP: token = FIRSTCAP; break; case MS_TOKEN_FUNCTION_ROUND: token = ROUND; break; case MS_TOKEN_FUNCTION_BUFFER: token = YYBUFFER; break; case MS_TOKEN_FUNCTION_DIFFERENCE: token = DIFFERENCE; break; case MS_TOKEN_FUNCTION_SIMPLIFY: token = SIMPLIFY; break; case MS_TOKEN_FUNCTION_SIMPLIFYPT: token = SIMPLIFYPT; break; case MS_TOKEN_FUNCTION_GENERALIZE: token = GENERALIZE; break; case MS_TOKEN_FUNCTION_SMOOTHSIA: token = SMOOTHSIA; break; case MS_TOKEN_FUNCTION_JAVASCRIPT: token = JAVASCRIPT; break; default: break; } p->expr->curtoken = p->expr->curtoken->next; /* re-position */ return(token); } int yyerror(parseObj *p, const char *s) { msSetError(MS_PARSEERR, "%s", "yyparse()", s); return(0); } mapserver-7.4.3/mapparser.h000066400000000000000000000076341357574274700157330ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison interface for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ #ifndef YY_YY_HOME_EVEN_MAPSERVER_MAPSERVER_MAPPARSER_H_INCLUDED # define YY_YY_HOME_EVEN_MAPSERVER_MAPSERVER_MAPPARSER_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif #if YYDEBUG extern int yydebug; #endif /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { BOOLEAN = 258, NUMBER = 259, STRING = 260, TIME = 261, SHAPE = 262, OR = 263, AND = 264, NOT = 265, RE = 266, EQ = 267, NE = 268, LT = 269, GT = 270, LE = 271, GE = 272, IN = 273, IEQ = 274, IRE = 275, INTERSECTS = 276, DISJOINT = 277, TOUCHES = 278, OVERLAPS = 279, CROSSES = 280, WITHIN = 281, CONTAINS = 282, EQUALS = 283, BEYOND = 284, DWITHIN = 285, AREA = 286, LENGTH = 287, COMMIFY = 288, ROUND = 289, UPPER = 290, LOWER = 291, INITCAP = 292, FIRSTCAP = 293, TOSTRING = 294, YYBUFFER = 295, DIFFERENCE = 296, SIMPLIFY = 297, SIMPLIFYPT = 298, GENERALIZE = 299, SMOOTHSIA = 300, JAVASCRIPT = 301, NEG = 302 }; #endif /* Tokens. */ #define BOOLEAN 258 #define NUMBER 259 #define STRING 260 #define TIME 261 #define SHAPE 262 #define OR 263 #define AND 264 #define NOT 265 #define RE 266 #define EQ 267 #define NE 268 #define LT 269 #define GT 270 #define LE 271 #define GE 272 #define IN 273 #define IEQ 274 #define IRE 275 #define INTERSECTS 276 #define DISJOINT 277 #define TOUCHES 278 #define OVERLAPS 279 #define CROSSES 280 #define WITHIN 281 #define CONTAINS 282 #define EQUALS 283 #define BEYOND 284 #define DWITHIN 285 #define AREA 286 #define LENGTH 287 #define COMMIFY 288 #define ROUND 289 #define UPPER 290 #define LOWER 291 #define INITCAP 292 #define FIRSTCAP 293 #define TOSTRING 294 #define YYBUFFER 295 #define DIFFERENCE 296 #define SIMPLIFY 297 #define SIMPLIFYPT 298 #define GENERALIZE 299 #define SMOOTHSIA 300 #define JAVASCRIPT 301 #define NEG 302 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { #line 30 "mapparser.y" /* yacc.c:1909 */ double dblval; int intval; char *strval; struct tm tmval; shapeObj *shpval; #line 156 "/home/even/mapserver/mapserver/mapparser.h" /* yacc.c:1909 */ }; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 #endif int yyparse (parseObj *p); #endif /* !YY_YY_HOME_EVEN_MAPSERVER_MAPSERVER_MAPPARSER_H_INCLUDED */ mapserver-7.4.3/mapparser.y000066400000000000000000000535041357574274700157510ustar00rootroot00000000000000/* ** Parser for the mapserver */ %{ /* C declarations */ #include #include #include #include #include #include "mapserver.h" /* for TRUE/FALSE and REGEX includes */ #include "maptime.h" /* for time comparison routines */ #include "mapprimitive.h" /* for shapeObj */ #include "mapparser.h" /* for YYSTYPE in the function prototype for yylex() */ int yylex(YYSTYPE *, parseObj *); /* prototype functions, defined after the grammar */ int yyerror(parseObj *, const char *); %} /* Bison/Yacc declarations */ /* %define api.pure */ %pure_parser %parse-param {parseObj *p} %lex-param {parseObj *p} %union { double dblval; int intval; char *strval; struct tm tmval; shapeObj *shpval; } %token BOOLEAN %token NUMBER %token STRING %token TIME %token SHAPE %left OR %left AND %left NOT %left RE EQ NE LT GT LE GE IN IEQ IRE %left INTERSECTS DISJOINT TOUCHES OVERLAPS CROSSES WITHIN CONTAINS EQUALS BEYOND DWITHIN %left AREA LENGTH COMMIFY ROUND %left UPPER LOWER INITCAP FIRSTCAP %left TOSTRING %left YYBUFFER DIFFERENCE SIMPLIFY SIMPLIFYPT GENERALIZE SMOOTHSIA JAVASCRIPT %left '+' '-' %left '*' '/' '%' %left NEG %right '^' %type logical_exp %type math_exp %type string_exp %type time_exp %type shape_exp /* Bison/Yacc grammar */ %% input: /* empty string */ | logical_exp { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): p->result.intval = $1; break; case(MS_PARSE_TYPE_STRING): if($1) p->result.strval = msStrdup("true"); else p->result.strval = msStrdup("false"); break; } } | math_exp { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): if($1 != 0) p->result.intval = MS_TRUE; else p->result.intval = MS_FALSE; break; case(MS_PARSE_TYPE_STRING): p->result.strval = (char *)malloc(64); /* large enough for a double */ snprintf(p->result.strval, 64, "%g", $1); break; } } | string_exp { switch(p->type) { case(MS_PARSE_TYPE_BOOLEAN): if($1) /* string is not NULL */ p->result.intval = MS_TRUE; else p->result.intval = MS_FALSE; break; case(MS_PARSE_TYPE_STRING): p->result.strval = $1; // msStrdup($1); break; } } | shape_exp { switch(p->type) { case(MS_PARSE_TYPE_SHAPE): p->result.shpval = $1; p->result.shpval->scratch = MS_FALSE; break; } } ; logical_exp: BOOLEAN | '(' logical_exp ')' { $$ = $2; } | logical_exp EQ logical_exp { $$ = MS_FALSE; if($1 == $3) $$ = MS_TRUE; } | logical_exp OR logical_exp { if($1 == MS_TRUE) $$ = MS_TRUE; else if($3 == MS_TRUE) $$ = MS_TRUE; else $$ = MS_FALSE; } | logical_exp AND logical_exp { if($1 == MS_TRUE) { if($3 == MS_TRUE) $$ = MS_TRUE; else $$ = MS_FALSE; } else $$ = MS_FALSE; } | logical_exp OR math_exp { if($1 == MS_TRUE) $$ = MS_TRUE; else if($3 != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | logical_exp AND math_exp { if($1 == MS_TRUE) { if($3 != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } else $$ = MS_FALSE; } | math_exp OR logical_exp { if($1 != 0) $$ = MS_TRUE; else if($3 == MS_TRUE) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp AND logical_exp { if($1 != 0) { if($3 == MS_TRUE) $$ = MS_TRUE; else $$ = MS_FALSE; } else $$ = MS_FALSE; } | math_exp OR math_exp { if($1 != 0) $$ = MS_TRUE; else if($3 != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp AND math_exp { if($1 != 0) { if($3 != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } else $$ = MS_FALSE; } | NOT logical_exp { $$ = !$2; } | NOT math_exp { $$ = !$2; } | string_exp RE string_exp { ms_regex_t re; if(MS_STRING_IS_NULL_OR_EMPTY($1) == MS_TRUE) { $$ = MS_FALSE; } else { if(ms_regcomp(&re, $3, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { $$ = MS_FALSE; } else { if(ms_regexec(&re, $1, 0, NULL, 0) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; ms_regfree(&re); } } free($1); free($3); } | string_exp IRE string_exp { ms_regex_t re; if(MS_STRING_IS_NULL_OR_EMPTY($1) == MS_TRUE) { $$ = MS_FALSE; } else { if(ms_regcomp(&re, $3, MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) { $$ = MS_FALSE; } else { if(ms_regexec(&re, $1, 0, NULL, 0) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; ms_regfree(&re); } } free($1); free($3); } | math_exp EQ math_exp { if($1 == $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp NE math_exp { if($1 != $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp GT math_exp { if($1 > $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp LT math_exp { if($1 < $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp GE math_exp { if($1 >= $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | math_exp LE math_exp { if($1 <= $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | string_exp EQ string_exp { if(strcmp($1, $3) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp NE string_exp { if(strcmp($1, $3) != 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp GT string_exp { if(strcmp($1, $3) > 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp LT string_exp { if(strcmp($1, $3) < 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp GE string_exp { if(strcmp($1, $3) >= 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | string_exp LE string_exp { if(strcmp($1, $3) <= 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | time_exp EQ time_exp { if(msTimeCompare(&($1), &($3)) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp NE time_exp { if(msTimeCompare(&($1), &($3)) != 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp GT time_exp { if(msTimeCompare(&($1), &($3)) > 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp LT time_exp { if(msTimeCompare(&($1), &($3)) < 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp GE time_exp { if(msTimeCompare(&($1), &($3)) >= 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | time_exp LE time_exp { if(msTimeCompare(&($1), &($3)) <= 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | string_exp IN string_exp { char *delim, *bufferp; $$ = MS_FALSE; bufferp=$3; while((delim=strchr(bufferp,',')) != NULL) { *delim='\0'; if(strcmp($1,bufferp) == 0) { $$ = MS_TRUE; break; } *delim=','; bufferp=delim+1; } if($$ == MS_FALSE && strcmp($1,bufferp) == 0) // test for last (or only) item $$ = MS_TRUE; free($1); free($3); } | math_exp IN string_exp { char *delim,*bufferp; $$ = MS_FALSE; bufferp=$3; while((delim=strchr(bufferp,',')) != NULL) { *delim='\0'; if($1 == atof(bufferp)) { $$ = MS_TRUE; break; } *delim=','; bufferp=delim+1; } if($1 == atof(bufferp)) // is this test necessary? $$ = MS_TRUE; free($3); } | math_exp IEQ math_exp { if($1 == $3) $$ = MS_TRUE; else $$ = MS_FALSE; } | string_exp IEQ string_exp { if(strcasecmp($1, $3) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; free($1); free($3); } | time_exp IEQ time_exp { if(msTimeCompare(&($1), &($3)) == 0) $$ = MS_TRUE; else $$ = MS_FALSE; } | shape_exp EQ shape_exp { int rval; rval = msGEOSEquals($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Equals (EQ or ==) operator failed."); return(-1); } else $$ = rval; } | EQUALS '(' shape_exp ',' shape_exp ')' { int rval; rval = msGEOSEquals($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(rval == -1) { yyerror(p, "Equals function failed."); return(-1); } else $$ = rval; } | INTERSECTS '(' shape_exp ',' shape_exp ')' { int rval; rval = msGEOSIntersects($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(rval == -1) { yyerror(p, "Intersects function failed."); return(-1); } else $$ = rval; } | shape_exp INTERSECTS shape_exp { int rval; rval = msGEOSIntersects($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Intersects operator failed."); return(-1); } else $$ = rval; } | DISJOINT '(' shape_exp ',' shape_exp ')' { int rval; rval = msGEOSDisjoint($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(rval == -1) { yyerror(p, "Disjoint function failed."); return(-1); } else $$ = rval; } | shape_exp DISJOINT shape_exp { int rval; rval = msGEOSDisjoint($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Disjoint operator failed."); return(-1); } else $$ = rval; } | TOUCHES '(' shape_exp ',' shape_exp ')' { int rval; rval = msGEOSTouches($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(rval == -1) { yyerror(p, "Touches function failed."); return(-1); } else $$ = rval; } | shape_exp TOUCHES shape_exp { int rval; rval = msGEOSTouches($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Touches operator failed."); return(-1); } else $$ = rval; } | OVERLAPS '(' shape_exp ',' shape_exp ')' { int rval; rval = msGEOSOverlaps($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(rval == -1) { yyerror(p, "Overlaps function failed."); return(-1); } else $$ = rval; } | shape_exp OVERLAPS shape_exp { int rval; rval = msGEOSOverlaps($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Overlaps operator failed."); return(-1); } else $$ = rval; } | CROSSES '(' shape_exp ',' shape_exp ')' { int rval; rval = msGEOSCrosses($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(rval == -1) { yyerror(p, "Crosses function failed."); return(-1); } else $$ = rval; } | shape_exp CROSSES shape_exp { int rval; rval = msGEOSCrosses($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Crosses operator failed."); return(-1); } else $$ = rval; } | WITHIN '(' shape_exp ',' shape_exp ')' { int rval; rval = msGEOSWithin($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(rval == -1) { yyerror(p, "Within function failed."); return(-1); } else $$ = rval; } | shape_exp WITHIN shape_exp { int rval; rval = msGEOSWithin($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Within operator failed."); return(-1); } else $$ = rval; } | CONTAINS '(' shape_exp ',' shape_exp ')' { int rval; rval = msGEOSContains($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(rval == -1) { yyerror(p, "Contains function failed."); return(-1); } else $$ = rval; } | shape_exp CONTAINS shape_exp { int rval; rval = msGEOSContains($1, $3); if($1->scratch == MS_TRUE) msFreeShape($1); if($3->scratch == MS_TRUE) msFreeShape($3); if(rval == -1) { yyerror(p, "Contains operator failed."); return(-1); } else $$ = rval; } | DWITHIN '(' shape_exp ',' shape_exp ',' math_exp ')' { double d; d = msGEOSDistance($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(d <= $7) $$ = MS_TRUE; else $$ = MS_FALSE; } | BEYOND '(' shape_exp ',' shape_exp ',' math_exp ')' { double d; d = msGEOSDistance($3, $5); if($3->scratch == MS_TRUE) msFreeShape($3); if($5->scratch == MS_TRUE) msFreeShape($5); if(d > $7) $$ = MS_TRUE; else $$ = MS_FALSE; } ; math_exp: NUMBER | '(' math_exp ')' { $$ = $2; } | math_exp '+' math_exp { $$ = $1 + $3; } | math_exp '-' math_exp { $$ = $1 - $3; } | math_exp '*' math_exp { $$ = $1 * $3; } | math_exp '%' math_exp { $$ = (int)$1 % (int)$3; } | math_exp '/' math_exp { if($3 == 0.0) { yyerror(p, "Division by zero."); return(-1); } else $$ = $1 / $3; } | '-' math_exp %prec NEG { $$ = $2; } | math_exp '^' math_exp { $$ = pow($1, $3); } | LENGTH '(' string_exp ')' { $$ = strlen($3); } | AREA '(' shape_exp ')' { if($3->type != MS_SHAPE_POLYGON) { yyerror(p, "Area can only be computed for polygon shapes."); return(-1); } $$ = msGetPolygonArea($3); if($3->scratch == MS_TRUE) msFreeShape($3); } | ROUND '(' math_exp ',' math_exp ')' { $$ = (MS_NINT($3/$5))*$5; } ; shape_exp: SHAPE | '(' shape_exp ')' { $$ = $2; } | YYBUFFER '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msGEOSBuffer($3, $5); if(!s) { yyerror(p, "Executing buffer failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | DIFFERENCE '(' shape_exp ',' shape_exp ')' { shapeObj *s; s = msGEOSDifference($3, $5); if(!s) { yyerror(p, "Executing difference failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SIMPLIFY '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msGEOSSimplify($3, $5); if(!s) { yyerror(p, "Executing simplify failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SIMPLIFYPT '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msGEOSTopologyPreservingSimplify($3, $5); if(!s) { yyerror(p, "Executing simplifypt failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | GENERALIZE '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msGeneralize($3, $5); if(!s) { yyerror(p, "Executing generalize failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SMOOTHSIA '(' shape_exp ')' { shapeObj *s; s = msSmoothShapeSIA($3, 3, 1, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SMOOTHSIA '(' shape_exp ',' math_exp ')' { shapeObj *s; s = msSmoothShapeSIA($3, $5, 1, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SMOOTHSIA '(' shape_exp ',' math_exp ',' math_exp ')' { shapeObj *s; s = msSmoothShapeSIA($3, $5, $7, NULL); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | SMOOTHSIA '(' shape_exp ',' math_exp ',' math_exp ',' string_exp ')' { shapeObj *s; s = msSmoothShapeSIA($3, $5, $7, $9); free($9); if(!s) { yyerror(p, "Executing smoothsia failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; } | JAVASCRIPT '(' shape_exp ',' string_exp ')' { #ifdef USE_V8_MAPSCRIPT shapeObj *s; s = msV8TransformShape($3, $5); free($5); if(!s) { yyerror(p, "Executing javascript failed."); return(-1); } s->scratch = MS_TRUE; $$ = s; #else yyerror(p, "Javascript support not compiled in"); return(-1); #endif } ; string_exp: STRING | '(' string_exp ')' { $$ = $2; } | string_exp '+' string_exp { $$ = (char *)malloc(strlen($1) + strlen($3) + 1); sprintf($$, "%s%s", $1, $3); free($1); free($3); } | TOSTRING '(' math_exp ',' string_exp ')' { $$ = (char *) malloc(strlen($5) + 64); /* Plenty big? Should use snprintf below... */ sprintf($$, $5, $3); free($5); } | COMMIFY '(' string_exp ')' { $3 = msCommifyString($3); $$ = $3; } | UPPER '(' string_exp ')' { msStringToUpper($3); $$ = $3; } | LOWER '(' string_exp ')' { msStringToLower($3); $$ = $3; } | INITCAP '(' string_exp ')' { msStringInitCap($3); $$ = $3; } | FIRSTCAP '(' string_exp ')' { msStringFirstCap($3); $$ = $3; } ; time_exp: TIME | '(' time_exp ')' { $$ = $2; } ; %% /* ** Any extra C functions */ int yylex(YYSTYPE *lvalp, parseObj *p) { int token; if(p->expr->curtoken == NULL) return(0); /* done */ // fprintf(stderr, "in yylex() - curtoken=%d...\n", p->expr->curtoken->token); token = p->expr->curtoken->token; /* may override */ switch(p->expr->curtoken->token) { case MS_TOKEN_LITERAL_BOOLEAN: token = BOOLEAN; (*lvalp).intval = p->expr->curtoken->tokenval.dblval; break; case MS_TOKEN_LITERAL_NUMBER: token = NUMBER; (*lvalp).dblval = p->expr->curtoken->tokenval.dblval; break; case MS_TOKEN_LITERAL_SHAPE: token = SHAPE; // fprintf(stderr, "token value = %s\n", msShapeToWKT(p->expr->curtoken->tokenval.shpval)); (*lvalp).shpval = p->expr->curtoken->tokenval.shpval; break; case MS_TOKEN_LITERAL_STRING: // printf("token value = %s\n", p->expr->curtoken->tokenval.strval); token = STRING; (*lvalp).strval = msStrdup(p->expr->curtoken->tokenval.strval); break; case MS_TOKEN_LITERAL_TIME: token = TIME; (*lvalp).tmval = p->expr->curtoken->tokenval.tmval; break; case MS_TOKEN_COMPARISON_EQ: token = EQ; break; case MS_TOKEN_COMPARISON_IEQ: token = IEQ; break; case MS_TOKEN_COMPARISON_NE: token = NE; break; case MS_TOKEN_COMPARISON_LT: token = LT; break; case MS_TOKEN_COMPARISON_GT: token = GT; break; case MS_TOKEN_COMPARISON_LE: token = LE; break; case MS_TOKEN_COMPARISON_GE: token = GE; break; case MS_TOKEN_COMPARISON_RE: token = RE; break; case MS_TOKEN_COMPARISON_IRE: token = IRE; break; case MS_TOKEN_COMPARISON_IN: token = IN; break; case MS_TOKEN_COMPARISON_INTERSECTS: token = INTERSECTS; break; case MS_TOKEN_COMPARISON_DISJOINT: token = DISJOINT; break; case MS_TOKEN_COMPARISON_TOUCHES: token = TOUCHES; break; case MS_TOKEN_COMPARISON_OVERLAPS: token = OVERLAPS; break; case MS_TOKEN_COMPARISON_CROSSES: token = CROSSES; break; case MS_TOKEN_COMPARISON_WITHIN: token = WITHIN; break; case MS_TOKEN_COMPARISON_CONTAINS: token = CONTAINS; break; case MS_TOKEN_COMPARISON_EQUALS: token = EQUALS; break; case MS_TOKEN_COMPARISON_BEYOND: token = BEYOND; break; case MS_TOKEN_COMPARISON_DWITHIN: token = DWITHIN; break; case MS_TOKEN_LOGICAL_AND: token = AND; break; case MS_TOKEN_LOGICAL_OR: token = OR; break; case MS_TOKEN_LOGICAL_NOT: token = NOT; break; case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: token = NUMBER; (*lvalp).dblval = atof(p->shape->values[p->expr->curtoken->tokenval.bindval.index]); break; case MS_TOKEN_BINDING_STRING: token = STRING; (*lvalp).strval = msStrdup(p->shape->values[p->expr->curtoken->tokenval.bindval.index]); break; case MS_TOKEN_BINDING_SHAPE: token = SHAPE; // fprintf(stderr, "token value = %s\n", msShapeToWKT(p->shape)); (*lvalp).shpval = p->shape; break; case MS_TOKEN_BINDING_MAP_CELLSIZE: token = NUMBER; (*lvalp).dblval = p->dblval; break; case MS_TOKEN_BINDING_DATA_CELLSIZE: token = NUMBER; (*lvalp).dblval = p->dblval2; break; case MS_TOKEN_BINDING_TIME: token = TIME; msTimeInit(&((*lvalp).tmval)); if(msParseTime(p->shape->values[p->expr->curtoken->tokenval.bindval.index], &((*lvalp).tmval)) != MS_TRUE) { yyerror(p, "Parsing time value failed."); return(-1); } break; case MS_TOKEN_FUNCTION_AREA: token = AREA; break; case MS_TOKEN_FUNCTION_LENGTH: token = LENGTH; break; case MS_TOKEN_FUNCTION_TOSTRING: token = TOSTRING; break; case MS_TOKEN_FUNCTION_COMMIFY: token = COMMIFY; break; case MS_TOKEN_FUNCTION_UPPER: token = UPPER; break; case MS_TOKEN_FUNCTION_LOWER: token = LOWER; break; case MS_TOKEN_FUNCTION_INITCAP: token = INITCAP; break; case MS_TOKEN_FUNCTION_FIRSTCAP: token = FIRSTCAP; break; case MS_TOKEN_FUNCTION_ROUND: token = ROUND; break; case MS_TOKEN_FUNCTION_BUFFER: token = YYBUFFER; break; case MS_TOKEN_FUNCTION_DIFFERENCE: token = DIFFERENCE; break; case MS_TOKEN_FUNCTION_SIMPLIFY: token = SIMPLIFY; break; case MS_TOKEN_FUNCTION_SIMPLIFYPT: token = SIMPLIFYPT; break; case MS_TOKEN_FUNCTION_GENERALIZE: token = GENERALIZE; break; case MS_TOKEN_FUNCTION_SMOOTHSIA: token = SMOOTHSIA; break; case MS_TOKEN_FUNCTION_JAVASCRIPT: token = JAVASCRIPT; break; default: break; } p->expr->curtoken = p->expr->curtoken->next; /* re-position */ return(token); } int yyerror(parseObj *p, const char *s) { msSetError(MS_PARSEERR, "%s", "yyparse()", s); return(0); } mapserver-7.4.3/mappluginlayer.c000066400000000000000000000206631357574274700167620ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of plug-in layer functionality * Author: Jani Averbach, SRC,LLC * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "mapthread.h" typedef struct { char *name; layerVTableObj vtable; } VTFactoryItemObj; typedef struct { unsigned int size; unsigned int first_free; VTFactoryItemObj ** vtItems; } VTFactoryObj; static VTFactoryObj gVirtualTableFactory = {0, 0, NULL}; static VTFactoryItemObj * createVTFItem(const char *name) { VTFactoryItemObj *pVTFI; pVTFI = (VTFactoryItemObj *)malloc(sizeof(VTFactoryItemObj)); MS_CHECK_ALLOC(pVTFI, sizeof(VTFactoryItemObj), NULL); pVTFI->name = msStrdup(name); memset(&pVTFI->vtable, 0, sizeof(layerVTableObj)); return pVTFI; } static void destroyVTFItem(VTFactoryItemObj **pVTFI) { free((*pVTFI)->name); (*pVTFI)->name = NULL; memset(&(*pVTFI)->vtable, 0, sizeof(layerVTableObj)); free(*pVTFI); *pVTFI = NULL; } static VTFactoryItemObj * lookupVTFItem(VTFactoryObj *VTFactory, const char *key) { unsigned int i; for (i=0; i < VTFactory->size && VTFactory->vtItems[i]; ++i) { if (0 == strcasecmp(key, VTFactory->vtItems[i]->name)) { return VTFactory->vtItems[i]; } } return NULL; } static int insertNewVTFItem(VTFactoryObj *pVTFactory, VTFactoryItemObj *pVTFI) { /* Ensure there is room for one more item in the array * (safe to use for initial alloc of the array as well) */ if (pVTFactory->first_free == pVTFactory->size) { int i; VTFactoryItemObj **vtItemPtr; vtItemPtr = (VTFactoryItemObj**)realloc(pVTFactory->vtItems, (pVTFactory->size+MS_LAYER_ALLOCSIZE)*sizeof(VTFactoryItemObj*)); MS_CHECK_ALLOC(vtItemPtr, (pVTFactory->size+MS_LAYER_ALLOCSIZE)*sizeof(VTFactoryItemObj*), MS_FAILURE); pVTFactory->size += MS_LAYER_ALLOCSIZE; pVTFactory->vtItems = vtItemPtr; for (i=pVTFactory->first_free; isize; i++) pVTFactory->vtItems[i] = NULL; } /* Insert item */ pVTFactory->vtItems[pVTFactory->first_free] = pVTFI; pVTFactory->first_free++; return MS_SUCCESS; } static VTFactoryItemObj * loadCustomLayerDLL(layerObj *layer, const char *library_path) { int (*pfnPluginInitVTable)(layerVTableObj *, layerObj *); VTFactoryItemObj *pVTFI; pfnPluginInitVTable = msGetSymbol(library_path, "PluginInitializeVirtualTable"); if ( ! pfnPluginInitVTable) { msSetError(MS_MISCERR, "Failed to load dynamic Layer LIB: %s", "loadCustomLayerDLL", library_path); return NULL; } pVTFI = createVTFItem(library_path); if ( ! pVTFI) { return NULL; } if (pfnPluginInitVTable(&pVTFI->vtable, layer)) { destroyVTFItem(&pVTFI); msSetError(MS_MISCERR, "Failed to initialize dynamic Layer: %s", "loadCustomLayerDLL", library_path); return NULL; } return pVTFI; } /* * copyVirtualTable * * copy one virtual table from dest to src. Both of dest and src * have to be allocated already. * * If src contains NULL fields, those are NOT copied over. * * Because of that, it is possible for plugin layer to use default * layer API default functions, just leave those function pointers to NULL. */ static void copyVirtualTable(layerVTableObj *dest, const layerVTableObj *src) { dest->LayerTranslateFilter = src->LayerTranslateFilter ? src->LayerTranslateFilter : dest->LayerTranslateFilter; dest->LayerSupportsCommonFilters = src->LayerSupportsCommonFilters ? src->LayerSupportsCommonFilters : dest->LayerSupportsCommonFilters; dest->LayerInitItemInfo = src->LayerInitItemInfo ? src->LayerInitItemInfo : dest->LayerInitItemInfo; dest->LayerFreeItemInfo = src->LayerFreeItemInfo ? src->LayerFreeItemInfo : dest->LayerFreeItemInfo; dest->LayerOpen = src->LayerOpen ? src->LayerOpen : dest->LayerOpen; dest->LayerIsOpen = src->LayerIsOpen ? src->LayerIsOpen : dest->LayerIsOpen; dest->LayerWhichShapes = src->LayerWhichShapes ? src->LayerWhichShapes : dest->LayerWhichShapes; dest->LayerNextShape = src->LayerNextShape ? src->LayerNextShape : dest->LayerNextShape; dest->LayerGetShape = src->LayerGetShape ? src->LayerGetShape : dest->LayerGetShape; /* dest->LayerResultsGetShape = src->LayerResultsGetShape ? src->LayerResultsGetShape : dest->LayerResultsGetShape; */ dest->LayerGetShapeCount = src->LayerGetShapeCount ? src->LayerGetShapeCount : dest->LayerGetShapeCount; dest->LayerClose = src->LayerClose ? src->LayerClose : dest->LayerClose; dest->LayerGetItems = src->LayerGetItems ? src->LayerGetItems : dest->LayerGetItems; dest->LayerGetExtent = src->LayerGetExtent ? src->LayerGetExtent : dest->LayerGetExtent; dest->LayerGetAutoStyle = src->LayerGetAutoStyle ? src->LayerGetAutoStyle : dest->LayerGetAutoStyle; dest->LayerCloseConnection = src->LayerCloseConnection ? src->LayerCloseConnection : dest->LayerCloseConnection; dest->LayerSetTimeFilter = src->LayerSetTimeFilter ? src->LayerSetTimeFilter : dest->LayerSetTimeFilter; dest->LayerApplyFilterToLayer = src->LayerApplyFilterToLayer ? src->LayerApplyFilterToLayer : dest->LayerApplyFilterToLayer; dest->LayerCreateItems = src->LayerCreateItems ? src->LayerCreateItems : dest->LayerCreateItems; dest->LayerGetNumFeatures = src->LayerGetNumFeatures ? src->LayerGetNumFeatures : dest->LayerGetNumFeatures; dest->LayerGetAutoProjection = src->LayerGetAutoProjection ? src->LayerGetAutoProjection: dest->LayerGetAutoProjection; dest->LayerEscapeSQLParam = src->LayerEscapeSQLParam ? src->LayerEscapeSQLParam: dest->LayerEscapeSQLParam; dest->LayerEscapePropertyName = src->LayerEscapePropertyName ? src->LayerEscapePropertyName: dest->LayerEscapePropertyName; dest->LayerEscapeSQLParam = src->LayerEscapeSQLParam ? src->LayerEscapeSQLParam: dest->LayerEscapeSQLParam; dest->LayerEnablePaging = src->LayerEnablePaging ? src->LayerEnablePaging: dest->LayerEnablePaging; dest->LayerGetPaging = src->LayerGetPaging ? src->LayerGetPaging: dest->LayerGetPaging; } int msPluginLayerInitializeVirtualTable(layerObj *layer) { VTFactoryItemObj *pVTFI; msAcquireLock(TLOCK_LAYER_VTABLE); pVTFI = lookupVTFItem(&gVirtualTableFactory, layer->plugin_library); if ( ! pVTFI) { pVTFI = loadCustomLayerDLL(layer, layer->plugin_library); if ( ! pVTFI) { msReleaseLock(TLOCK_LAYER_VTABLE); return MS_FAILURE; } if (insertNewVTFItem(&gVirtualTableFactory, pVTFI) != MS_SUCCESS) { destroyVTFItem(&pVTFI); msReleaseLock(TLOCK_LAYER_VTABLE); return MS_FAILURE; } } msReleaseLock(TLOCK_LAYER_VTABLE); copyVirtualTable(layer->vtable, &pVTFI->vtable); return MS_SUCCESS; } /* msPluginFreeVirtualTableFactory() ** Called by msCleanup() to free the virtual table factory */ void msPluginFreeVirtualTableFactory() { int i; msAcquireLock(TLOCK_LAYER_VTABLE); for (i=0; iconn = (PGconn *) msConnPoolRequest( layer ); 2) In msPOSTGISLayerOpen(): if msConnPoolRequest() returned NULL then manually open a connection to the database (ie. PQconnectcb()) and then register this handle with the pool API by calling msmsConnPoolRegister(). layerinfo->conn = PQconnectdb( layer->connection ); if (PQstatus(layerinfo->conn) == CONNECTION_BAD) else msConnPoolRegister( layer, layerinfo->conn, msPOSTGISCloseConnection ); 3) Implement a callback function (msPOSTGISCloseConnection) that the connection pooling API can call when it wants to close the connection. static void msPOSTGISCloseConnection( void *conn_handle ) { PQfinish( (PGconn*) conn_handle ); } 4) In msPOSTGISLayerClose() release the connection handle instead of directly closing it. msConnPoolRelease( layer, layerinfo->conn ); layerinfo->conn = NULL; 5) If there was any use of msCheckConnection() or the "sameconnection" member of the layerObj, then old style connection pooling is already present. Remove it. Thats it! Other Notes ----------- o The connection pooling API will report details about connection registrations, requests, releases and closes if the layer debug flag is on for the layers in question. o The connection pooling API will let a connection be used/referenced multiple times from a single thread, but will not allow a connection to be shared between different threads concurrently. But if a connection is released by one thread, it is available for use by another thread. ****************************************************************************/ #include "mapserver.h" #include "mapthread.h" /* defines for lifetime. A positive number is a time-from-last use in seconds */ #define MS_LIFE_FOREVER -1 #define MS_LIFE_ZEROREF -2 #define MS_LIFE_SINGLE -3 typedef struct { enum MS_CONNECTION_TYPE connectiontype; char *connection; int lifespan; int ref_count; void* thread_id; int debug; time_t last_used; void *conn_handle; void (*close)( void * ); } connectionObj; /* ** These static structures are protected by the TLOCK_POOL mutex. */ static int connectionCount = 0; static int connectionMax = 0; static connectionObj *connections = NULL; /************************************************************************/ /* msConnPoolRegister() */ /* */ /* Register a new connection with the connection pool tracker. */ /************************************************************************/ void msConnPoolRegister( layerObj *layer, void *conn_handle, void (*close_func)( void * ) ) { const char *close_connection = NULL; connectionObj *conn = NULL; if( layer->debug ) msDebug( "msConnPoolRegister(%s,%s,%p)\n", layer->name, layer->connection, conn_handle ); /* -------------------------------------------------------------------- */ /* We can't meaningful keep a connection with no connection or */ /* connection type string on the layer. */ /* -------------------------------------------------------------------- */ if( layer->connection == NULL ) { if( layer->tileindex != NULL && layer->connectiontype == MS_OGR ) { /* this is ok, no need to make a fuss */ } else { msDebug( "%s: Missing CONNECTION on layer %s.\n", "msConnPoolRegister()", layer->name ); msSetError( MS_MISCERR, "Missing CONNECTION on layer %s.", "msConnPoolRegister()", layer->name ); } return; } /* -------------------------------------------------------------------- */ /* Grow the array of connection information objects if needed. */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_POOL ); if( connectionCount == connectionMax ) { connectionMax += 10; connections = (connectionObj *) realloc(connections, sizeof(connectionObj) * connectionMax ); if( connections == NULL ) { msSetError(MS_MEMERR, NULL, "msConnPoolRegister()"); msReleaseLock( TLOCK_POOL ); return; } } /* -------------------------------------------------------------------- */ /* Set the new connection information. */ /* -------------------------------------------------------------------- */ conn = connections + connectionCount; connectionCount++; conn->connectiontype = layer->connectiontype; conn->connection = msStrdup( layer->connection ); conn->close = close_func; conn->ref_count = 1; conn->thread_id = msGetThreadId(); conn->last_used = time(NULL); conn->conn_handle = conn_handle; conn->debug = layer->debug; /* -------------------------------------------------------------------- */ /* Categorize the connection handling information. */ /* -------------------------------------------------------------------- */ close_connection = msLayerGetProcessingKey( layer, "CLOSE_CONNECTION" ); if( close_connection == NULL ) close_connection = "NORMAL"; if( strcasecmp(close_connection,"NORMAL") == 0 ) conn->lifespan = MS_LIFE_ZEROREF; else if( strcasecmp(close_connection,"DEFER") == 0 ) conn->lifespan = MS_LIFE_FOREVER; else if( strcasecmp(close_connection,"ALWAYS") == 0 ) conn->lifespan = MS_LIFE_SINGLE; else { msDebug("msConnPoolRegister(): " "Unrecognised CLOSE_CONNECTION value '%s'\n", close_connection ); msSetError( MS_MISCERR, "Unrecognised CLOSE_CONNECTION value '%s'", "msConnPoolRegister()", close_connection ); conn->lifespan = MS_LIFE_ZEROREF; } msReleaseLock( TLOCK_POOL ); } /************************************************************************/ /* msConnPoolClose() */ /* */ /* Close the indicated connection. The index in the connection */ /* table is passed. Remove the connection from the table as */ /* well. */ /************************************************************************/ static void msConnPoolClose( int conn_index ) { connectionObj *conn = connections + conn_index; if( conn->ref_count > 0 ) { if( conn->debug ) msDebug( "msConnPoolClose(): " "Closing connection %s even though ref_count=%d.\n", conn->connection, conn->ref_count ); msSetError( MS_MISCERR, "Closing connection %s even though ref_count=%d.", "msConnPoolClose()", conn->connection, conn->ref_count ); } if( conn->debug ) msDebug( "msConnPoolClose(%s,%p)\n", conn->connection, conn->conn_handle ); if( conn->close != NULL ) conn->close( conn->conn_handle ); /* free malloced() stuff in this connection */ free( conn->connection ); connectionCount--; if( connectionCount == 0 ) { /* if there are no connections left we will "cleanup". */ connectionMax = 0; free( connections ); connections = NULL; } else { /* move the last connection in place of our now closed one */ memcpy( connections + conn_index, connections + connectionCount, sizeof(connectionObj) ); } } /************************************************************************/ /* msConnPoolRequest() */ /* */ /* Ask for a connection from the connection pool for use with */ /* the current layer. If found (CONNECTION and CONNECTIONTYPE */ /* match) then return it and up the ref count. Otherwise */ /* return NULL. */ /************************************************************************/ void *msConnPoolRequest( layerObj *layer ) { int i; const char* close_connection; if( layer->connection == NULL ) return NULL; /* check if we must always create a new connection */ close_connection = msLayerGetProcessingKey( layer, "CLOSE_CONNECTION" ); if( close_connection && strcasecmp(close_connection,"ALWAYS") == 0 ) return NULL; msAcquireLock( TLOCK_POOL ); for( i = 0; i < connectionCount; i++ ) { connectionObj *conn = connections + i; if( layer->connectiontype == conn->connectiontype && strcasecmp( layer->connection, conn->connection ) == 0 && (conn->ref_count == 0 || conn->thread_id == msGetThreadId()) && conn->lifespan != MS_LIFE_SINGLE) { void *conn_handle = NULL; conn->ref_count++; conn->thread_id = msGetThreadId(); conn->last_used = time(NULL); if( layer->debug ) { msDebug( "msConnPoolRequest(%s,%s) -> got %p\n", layer->name, layer->connection, conn->conn_handle ); conn->debug = layer->debug; } conn_handle = conn->conn_handle; msReleaseLock( TLOCK_POOL ); return conn_handle; } } msReleaseLock( TLOCK_POOL ); return NULL; } /************************************************************************/ /* msConnPoolRelease() */ /* */ /* Release the passed connection for the given layer. */ /* Internally the reference count is dropped, and the */ /* connection may be closed. We assume the caller has already */ /* acquired the pool lock. */ /************************************************************************/ void msConnPoolRelease( layerObj *layer, void *conn_handle ) { int i; if( layer->debug ) msDebug( "msConnPoolRelease(%s,%s,%p)\n", layer->name, layer->connection, conn_handle ); if( layer->connection == NULL ) return; msAcquireLock( TLOCK_POOL ); for( i = 0; i < connectionCount; i++ ) { connectionObj *conn = connections + i; if( layer->connectiontype == conn->connectiontype && strcasecmp( layer->connection, conn->connection ) == 0 && conn->conn_handle == conn_handle ) { conn->ref_count--; conn->last_used = time(NULL); if( conn->ref_count == 0 ) conn->thread_id = 0; if( conn->ref_count == 0 && (conn->lifespan == MS_LIFE_ZEROREF || conn->lifespan == MS_LIFE_SINGLE) ) msConnPoolClose( i ); msReleaseLock( TLOCK_POOL ); return; } } msReleaseLock( TLOCK_POOL ); msDebug( "%s: Unable to find handle for layer '%s'.\n", "msConnPoolRelease()", layer->name ); msSetError( MS_MISCERR, "Unable to find handle for layer '%s'.", "msConnPoolRelease()", layer->name ); } /************************************************************************/ /* msConnPoolMapCloseUnreferenced() */ /* */ /* Close any unreferenced connections. */ /************************************************************************/ void msConnPoolCloseUnreferenced() { int i; /* this really needs to be commented out before commiting. */ /* msDebug( "msConnPoolCloseUnreferenced()\n" ); */ msAcquireLock( TLOCK_POOL ); for( i = connectionCount - 1; i >= 0; i-- ) { connectionObj *conn = connections + i; if( conn->ref_count == 0 ) { /* for now we don't assume the locks are re-entrant, so release */ /* it so msConnPoolClose() can get it. */ msConnPoolClose( i ); } } msReleaseLock( TLOCK_POOL ); } /************************************************************************/ /* msConnPoolFinalCleanup() */ /* */ /* Close any remaining open connections. This is normally */ /* called just before (voluntary) application termination. */ /************************************************************************/ void msConnPoolFinalCleanup() { /* this really needs to be commented out before commiting. */ /* msDebug( "msConnPoolFinalCleanup()\n" ); */ msAcquireLock( TLOCK_POOL ); while( connectionCount > 0 ) msConnPoolClose( 0 ); msReleaseLock( TLOCK_POOL ); } mapserver-7.4.3/mappostgis.c000066400000000000000000003736331357574274700161270ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: PostGIS CONNECTIONTYPE support. * Author: Paul Ramsey * Dave Blasby * ****************************************************************************** * Copyright (c) 2010 Paul Ramsey * Copyright (c) 2002 Refractions Research * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* ** Some theory of operation: ** ** Build SQL from DATA statement and LAYER state. SQL is always of the form: ** ** SELECT [this, that, other], geometry, uid ** FROM [table|(subquery) as sub] ** WHERE [box] AND [filter] ** ** So the geometry always resides at layer->numitems and the uid always ** resides at layer->numitems + 1 ** ** Geometry is requested as Hex encoded WKB. The endian is always requested ** as the client endianness. ** ** msPostGISLayerWhichShapes creates SQL based on DATA and LAYER state, ** executes it, and places the un-read PGresult handle in the layerinfo->pgresult, ** setting the layerinfo->rownum to 0. ** ** msPostGISNextShape reads a row, increments layerinfo->rownum, and returns ** MS_SUCCESS, until rownum reaches ntuples, and it returns MS_DONE instead. ** */ /* GNU needs this for strcasestr */ #define _GNU_SOURCE /* required for MSVC */ #define _USE_MATH_DEFINES #include #include #include #include "mapserver.h" #include "maptime.h" #include "mappostgis.h" #include "mapows.h" #define FP_EPSILON 1e-12 #define FP_EQ(a, b) (fabs((a)-(b)) < FP_EPSILON) #define FP_LEFT -1 #define FP_RIGHT 1 #define FP_COLINEAR 0 #define SEGMENT_ANGLE 10.0 #define SEGMENT_MINPOINTS 10 #define WKBZOFFSET_NONISO 0x80000000 #define WKBMOFFSET_NONISO 0x40000000 #define HAS_Z 0x1 #define HAS_M 0x2 #if TRANSFER_ENCODING == 256 #define RESULTSET_TYPE 1 #else #define RESULTSET_TYPE 0 #endif #ifdef USE_POSTGIS /* ** msPostGISCloseConnection() ** ** Handler registered witih msConnPoolRegister so that Mapserver ** can clean up open connections during a shutdown. */ void msPostGISCloseConnection(void *pgconn) { PQfinish((PGconn*)pgconn); } /* ** msPostGISCreateLayerInfo() */ msPostGISLayerInfo *msPostGISCreateLayerInfo(void) { msPostGISLayerInfo *layerinfo = msSmallMalloc(sizeof(msPostGISLayerInfo)); layerinfo->sql = NULL; layerinfo->srid = NULL; layerinfo->uid = NULL; layerinfo->pgconn = NULL; layerinfo->pgresult = NULL; layerinfo->geomcolumn = NULL; layerinfo->fromsource = NULL; layerinfo->endian = 0; layerinfo->rownum = 0; layerinfo->version = 0; layerinfo->paging = MS_TRUE; #ifdef USE_POINT_Z_M layerinfo->force2d = MS_FALSE; #else layerinfo->force2d = MS_TRUE; #endif return layerinfo; } /* ** msPostGISFreeLayerInfo() */ void msPostGISFreeLayerInfo(layerObj *layer) { msPostGISLayerInfo *layerinfo = NULL; layerinfo = (msPostGISLayerInfo*)layer->layerinfo; if ( layerinfo->sql ) free(layerinfo->sql); if ( layerinfo->uid ) free(layerinfo->uid); if ( layerinfo->srid ) free(layerinfo->srid); if ( layerinfo->geomcolumn ) free(layerinfo->geomcolumn); if ( layerinfo->fromsource ) free(layerinfo->fromsource); if ( layerinfo->pgresult ) PQclear(layerinfo->pgresult); if ( layerinfo->pgconn ) msConnPoolRelease(layer, layerinfo->pgconn); free(layerinfo); layer->layerinfo = NULL; } /* ** postgresqlNoticeHandler() ** ** Propagate messages from the database to the Mapserver log, ** set in PQsetNoticeProcessor during layer open. */ void postresqlNoticeHandler(void *arg, const char *message) { layerObj *lp; lp = (layerObj*)arg; if (lp->debug) { msDebug("%s\n", message); } } /* ** Expandable pointObj array. The lineObj unfortunately ** is not useful for this purpose, so we have this one. */ pointArrayObj* pointArrayNew(int maxpoints) { pointArrayObj *d = msSmallMalloc(sizeof(pointArrayObj)); if ( maxpoints < 1 ) maxpoints = 1; /* Avoid a degenerate case */ d->maxpoints = maxpoints; d->data = msSmallMalloc(maxpoints * sizeof(pointObj)); d->npoints = 0; return d; } /* ** Utility function to creal up the pointArrayObj */ void pointArrayFree(pointArrayObj *d) { if ( ! d ) return; if ( d->data ) free(d->data); free(d); } /* ** Add a pointObj to the pointObjArray, allocating ** extra storage space if we've used up our existing ** buffer. */ static int pointArrayAddPoint(pointArrayObj *d, const pointObj *p) { if ( !p || !d ) return MS_FAILURE; /* Avoid overwriting memory buffer */ if ( d->maxpoints - d->npoints == 0 ) { d->maxpoints *= 2; d->data = realloc(d->data, d->maxpoints * sizeof(pointObj)); } d->data[d->npoints] = *p; d->npoints++; return MS_SUCCESS; } /* ** Pass an input type number through the PostGIS version ** type map array to handle the pre-2.0 incorrect WKB types */ static int wkbTypeMap(wkbObj *w, int type, int* pnZMFlag) { *pnZMFlag = 0; /* PostGIS >= 2 : ISO SQL/MM style Z types ? */ if( type >= 1000 && type < 2000 ) { type -= 1000; *pnZMFlag = HAS_Z; } /* PostGIS >= 2 : ISO SQL/MM style M types ? */ else if( type >= 2000 && type < 3000 ) { type -= 2000; *pnZMFlag = HAS_M; } /* PostGIS >= 2 : ISO SQL/MM style ZM types ? */ else if( type >= 3000 && type < 4000 ) { type -= 3000; *pnZMFlag = HAS_Z | HAS_M; } /* PostGIS 1.X EWKB : Extended WKB Z or ZM ? */ else if( (type & WKBZOFFSET_NONISO) != 0 ) { if( (type & WKBMOFFSET_NONISO) != 0 ) *pnZMFlag = HAS_Z | HAS_M; else *pnZMFlag = HAS_Z; type &= 0x00FFFFFF; } /* PostGIS 1.X EWKB: Extended WKB M ? */ else if( (type & WKBMOFFSET_NONISO) != 0 ) { *pnZMFlag = HAS_M; type &= 0x00FFFFFF; } if ( type >= 0 && type < WKB_TYPE_COUNT ) return w->typemap[type]; else return 0; } /* ** Read the WKB type number from a wkbObj without ** advancing the read pointer. */ static int wkbType(wkbObj *w, int* pnZMFlag) { int t; memcpy(&t, (w->ptr + 1), sizeof(int)); return wkbTypeMap(w,t, pnZMFlag); } /* ** Read the type number of the first element of a ** collection without advancing the read pointer. */ static int wkbCollectionSubType(wkbObj *w, int* pnZMFlag) { int t; memcpy(&t, (w->ptr + 1 + 4 + 4 + 1), sizeof(int)); return wkbTypeMap(w,t, pnZMFlag); } /* ** Read one byte from the WKB and advance the read pointer */ static char wkbReadChar(wkbObj *w) { char c; memcpy(&c, w->ptr, sizeof(char)); w->ptr += sizeof(char); return c; } /* ** Read one integer from the WKB and advance the read pointer. ** We assume the endianess of the WKB is the same as this machine. */ static inline int wkbReadInt(wkbObj *w) { int i; memcpy(&i, w->ptr, sizeof(int)); w->ptr += sizeof(int); return i; } /* ** Read one double from the WKB and advance the read pointer. ** We assume the endianess of the WKB is the same as this machine. */ static inline double wkbReadDouble(wkbObj *w) { double d; memcpy(&d, w->ptr, sizeof(double)); w->ptr += sizeof(double); return d; } /* ** Read one pointObj (two doubles) from the WKB and advance the read pointer. ** We assume the endianess of the WKB is the same as this machine. */ static inline void wkbReadPointP(wkbObj *w, pointObj *p, int nZMFlag) { memcpy(&(p->x), w->ptr, sizeof(double)); w->ptr += sizeof(double); memcpy(&(p->y), w->ptr, sizeof(double)); w->ptr += sizeof(double); if( nZMFlag & HAS_Z ) { #ifdef USE_POINT_Z_M memcpy(&(p->z), w->ptr, sizeof(double)); if( !(nZMFlag & HAS_M) ) p->m = 0.0; #endif w->ptr += sizeof(double); } if( nZMFlag & HAS_M ) { #ifdef USE_POINT_Z_M if( !(nZMFlag & HAS_Z) ) p->z = 0.0; memcpy(&(p->m), w->ptr, sizeof(double)); #endif w->ptr += sizeof(double); } } /* ** Read one pointObj (two doubles) from the WKB and advance the read pointer. ** We assume the endianess of the WKB is the same as this machine. */ static inline pointObj wkbReadPoint(wkbObj *w, int nZMFlag) { pointObj p; wkbReadPointP(w, &p, nZMFlag); return p; } /* ** Read a "point array" and return an allocated lineObj. ** A point array is a WKB fragment that starts with a ** point count, which is followed by that number of doubles * 2. ** Linestrings, circular strings, polygon rings, all show this ** form. */ static void wkbReadLine(wkbObj *w, lineObj *line, int nZMFlag) { int i; pointObj p; int npoints = wkbReadInt(w); line->numpoints = npoints; line->point = msSmallMalloc(npoints * sizeof(pointObj)); for ( i = 0; i < npoints; i++ ) { wkbReadPointP(w, &p, nZMFlag); line->point[i] = p; } } /* ** Advance the read pointer past a geometry without returning any ** values. Used for skipping un-drawable elements in a collection. */ static void wkbSkipGeometry(wkbObj *w) { int type, npoints, nrings, ngeoms, i; int nZMFlag; int nCoordDim; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w), &nZMFlag); nCoordDim = 2 + (((nZMFlag & HAS_Z) != 0) ? 1 : 0) + (((nZMFlag & HAS_M) != 0) ? 1 : 0); switch(type) { case WKB_POINT: w->ptr += nCoordDim * sizeof(double); break; case WKB_CIRCULARSTRING: case WKB_LINESTRING: npoints = wkbReadInt(w); w->ptr += npoints * nCoordDim * sizeof(double); break; case WKB_POLYGON: nrings = wkbReadInt(w); for ( i = 0; i < nrings; i++ ) { npoints = wkbReadInt(w); w->ptr += npoints * nCoordDim * sizeof(double); } break; case WKB_MULTIPOINT: case WKB_MULTILINESTRING: case WKB_MULTIPOLYGON: case WKB_GEOMETRYCOLLECTION: case WKB_COMPOUNDCURVE: case WKB_CURVEPOLYGON: case WKB_MULTICURVE: case WKB_MULTISURFACE: ngeoms = wkbReadInt(w); for ( i = 0; i < ngeoms; i++ ) { wkbSkipGeometry(w); } } } /* ** Convert a WKB point to a shapeObj, advancing the read pointer as we go. */ static int wkbConvPointToShape(wkbObj *w, shapeObj *shape) { int type; lineObj line; int nZMFlag; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w),&nZMFlag); if( type != WKB_POINT ) return MS_FAILURE; if( ! (shape->type == MS_SHAPE_POINT) ) return MS_FAILURE; line.numpoints = 1; line.point = msSmallMalloc(sizeof(pointObj)); line.point[0] = wkbReadPoint(w, nZMFlag); msAddLineDirectly(shape, &line); return MS_SUCCESS; } /* ** Convert a WKB line string to a shapeObj, advancing the read pointer as we go. */ static int wkbConvLineStringToShape(wkbObj *w, shapeObj *shape) { int type; lineObj line; int nZMFlag; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w), &nZMFlag); if( type != WKB_LINESTRING ) return MS_FAILURE; wkbReadLine(w,&line, nZMFlag); msAddLineDirectly(shape, &line); return MS_SUCCESS; } /* ** Convert a WKB polygon to a shapeObj, advancing the read pointer as we go. */ static int wkbConvPolygonToShape(wkbObj *w, shapeObj *shape) { int type; int i, nrings; lineObj line; int nZMFlag; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w), &nZMFlag); if( type != WKB_POLYGON ) return MS_FAILURE; /* How many rings? */ nrings = wkbReadInt(w); /* Add each ring to the shape */ for( i = 0; i < nrings; i++ ) { wkbReadLine(w,&line, nZMFlag); msAddLineDirectly(shape, &line); } return MS_SUCCESS; } /* ** Convert a WKB curve polygon to a shapeObj, advancing the read pointer as we go. ** The arc portions of the rings will be stroked to linestrings as they ** are read by the underlying circular string handling. */ static int wkbConvCurvePolygonToShape(wkbObj *w, shapeObj *shape) { int type, i, ncomponents; int failures = 0; int was_poly = ( shape->type == MS_SHAPE_POLYGON ); int nZMFlag; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w), &nZMFlag); ncomponents = wkbReadInt(w); if( type != WKB_CURVEPOLYGON ) return MS_FAILURE; /* Lower the allowed dimensionality so we can * catch the linear ring components */ shape->type = MS_SHAPE_LINE; for ( i = 0; i < ncomponents; i++ ) { if ( wkbConvGeometryToShape(w, shape) == MS_FAILURE ) { wkbSkipGeometry(w); failures++; } } /* Go back to expected dimensionality */ if ( was_poly) shape->type = MS_SHAPE_POLYGON; if ( failures == ncomponents ) return MS_FAILURE; else return MS_SUCCESS; } /* ** Convert a WKB circular string to a shapeObj, advancing the read pointer as we go. ** Arcs will be stroked to linestrings. */ static int wkbConvCircularStringToShape(wkbObj *w, shapeObj *shape) { int type; int nZMFlag; lineObj line = {0, NULL}; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w), &nZMFlag); if( type != WKB_CIRCULARSTRING ) return MS_FAILURE; /* Stroke the string into a point array */ if ( arcStrokeCircularString(w, SEGMENT_ANGLE, &line, nZMFlag) == MS_FAILURE ) { if(line.point) free(line.point); return MS_FAILURE; } /* Fill in the lineObj */ if ( line.numpoints > 0 ) { msAddLine(shape, &line); if(line.point) free(line.point); } return MS_SUCCESS; } /* ** Compound curves need special handling. First we load ** each component of the curve on the a lineObj in a shape. ** Then we merge those lineObjs into a single lineObj. This ** allows compound curves to serve as closed rings in ** curve polygons. */ static int wkbConvCompoundCurveToShape(wkbObj *w, shapeObj *shape) { int npoints = 0; int type, ncomponents, i, j; lineObj line; shapeObj shapebuf; int nZMFlag; /*endian = */wkbReadChar(w); type = wkbTypeMap(w,wkbReadInt(w), &nZMFlag); /* Init our shape buffer */ msInitShape(&shapebuf); if( type != WKB_COMPOUNDCURVE ) return MS_FAILURE; /* How many components in the compound curve? */ ncomponents = wkbReadInt(w); /* We'll load each component onto a line in a shape */ for( i = 0; i < ncomponents; i++ ) wkbConvGeometryToShape(w, &shapebuf); /* Do nothing on empty */ if ( shapebuf.numlines == 0 ) return MS_FAILURE; /* Count the total number of points */ for( i = 0; i < shapebuf.numlines; i++ ) npoints += shapebuf.line[i].numpoints; /* Do nothing on empty */ if ( npoints == 0 ) return MS_FAILURE; line.numpoints = npoints; line.point = msSmallMalloc(sizeof(pointObj) * npoints); /* Copy in the points */ npoints = 0; for ( i = 0; i < shapebuf.numlines; i++ ) { for ( j = 0; j < shapebuf.line[i].numpoints; j++ ) { /* Don't add a start point that duplicates an endpoint */ if( j == 0 && i > 0 && memcmp(&(line.point[npoints - 1]),&(shapebuf.line[i].point[j]),sizeof(pointObj)) == 0 ) { continue; } line.point[npoints++] = shapebuf.line[i].point[j]; } } line.numpoints = npoints; /* Clean up */ msFreeShape(&shapebuf); /* Fill in the lineObj */ msAddLineDirectly(shape, &line); return MS_SUCCESS; } /* ** Convert a WKB collection string to a shapeObj, advancing the read pointer as we go. ** Many WKB types (MultiPoint, MultiLineString, MultiPolygon, MultiSurface, ** MultiCurve, GeometryCollection) can be treated identically as collections ** (they start with endian, type number and count of sub-elements, then provide the ** subelements as WKB) so are handled with this one function. */ static int wkbConvCollectionToShape(wkbObj *w, shapeObj *shape) { int i, ncomponents; int failures = 0; int nZMFlag; /*endian = */wkbReadChar(w); /*type = */wkbTypeMap(w,wkbReadInt(w), &nZMFlag); ncomponents = wkbReadInt(w); /* * If we can draw any portion of the collection, we will, * but if all the components fail, we will draw nothing. */ for ( i = 0; i < ncomponents; i++ ) { if ( wkbConvGeometryToShape(w, shape) == MS_FAILURE ) { wkbSkipGeometry(w); failures++; } } if ( failures == ncomponents || ncomponents == 0) return MS_FAILURE; else return MS_SUCCESS; } /* ** Generic handler to switch to the appropriate function for the WKB type. ** Note that we also handle switching here to avoid processing shapes ** we will be unable to draw. Example: we can't draw point features as ** a MS_SHAPE_LINE layer, so if the type is WKB_POINT and the layer is ** MS_SHAPE_LINE, we exit before converting. */ int wkbConvGeometryToShape(wkbObj *w, shapeObj *shape) { int nZMFlag; int wkbtype = wkbType(w, &nZMFlag); /* Peak at the type number */ switch(wkbtype) { /* Recurse into anonymous collections */ case WKB_GEOMETRYCOLLECTION: return wkbConvCollectionToShape(w, shape); /* Handle area types */ case WKB_POLYGON: return wkbConvPolygonToShape(w, shape); case WKB_MULTIPOLYGON: return wkbConvCollectionToShape(w, shape); case WKB_CURVEPOLYGON: return wkbConvCurvePolygonToShape(w, shape); case WKB_MULTISURFACE: return wkbConvCollectionToShape(w, shape); } /* We can't convert any of the following types into polygons */ if ( shape->type == MS_SHAPE_POLYGON ) return MS_FAILURE; /* Handle linear types */ switch(wkbtype) { case WKB_LINESTRING: return wkbConvLineStringToShape(w, shape); case WKB_CIRCULARSTRING: return wkbConvCircularStringToShape(w, shape); case WKB_COMPOUNDCURVE: return wkbConvCompoundCurveToShape(w, shape); case WKB_MULTILINESTRING: return wkbConvCollectionToShape(w, shape); case WKB_MULTICURVE: return wkbConvCollectionToShape(w, shape); } /* We can't convert any of the following types into lines */ if ( shape->type == MS_SHAPE_LINE ) return MS_FAILURE; /* Handle point types */ switch(wkbtype) { case WKB_POINT: return wkbConvPointToShape(w, shape); case WKB_MULTIPOINT: return wkbConvCollectionToShape(w, shape); } /* This is a WKB type we don't know about! */ return MS_FAILURE; } /* ** Calculate determinant of a 3x3 matrix. Handy for ** the circle center calculation. */ static inline double arcDeterminant3x3(double *m) { /* This had better be a 3x3 matrix or we'll fall to bits */ return m[0] * ( m[4] * m[8] - m[7] * m[5] ) - m[3] * ( m[1] * m[8] - m[7] * m[2] ) + m[6] * ( m[1] * m[5] - m[4] * m[2] ); } /* ** What side of p1->p2 is q on? */ static inline int arcSegmentSide(const pointObj *p1, const pointObj *p2, const pointObj *q) { double side = ( (q->x - p1->x) * (p2->y - p1->y) - (p2->x - p1->x) * (q->y - p1->y) ); if ( FP_EQ(side,0.0) ) { return FP_COLINEAR; } else { if ( side < 0.0 ) return FP_LEFT; else return FP_RIGHT; } } /* ** Calculate the center of the circle defined by three points. ** Using matrix approach from http://mathforum.org/library/drmath/view/55239.html */ int arcCircleCenter(const pointObj *p1, const pointObj *p2, const pointObj *p3, pointObj *center, double *radius) { pointObj c; double dx21, dy21, dx31, dy31, h21, h31, d, r; /* Circle is closed, so p2 must be opposite p1 & p3. */ if ((fabs(p1->x - p3->x) < FP_EPSILON) && (fabs(p1->y-p3->y) < FP_EPSILON)) { c.x = p1->x + (p2->x - p1->x) / 2.0; c.y = p1->y + (p2->y - p1->y) / 2.0; r = sqrt(pow(c.x - p1->x, 2.0) + pow(c.y - p1->y, 2.0)); } /* There is no circle here, the points are actually co-linear */ else if ( arcSegmentSide(p1, p3, p2) == FP_COLINEAR ) { return MS_FAILURE; } /* Calculate the center and radius. */ else { /* Radius */ dx21 = p2->x - p1->x; dy21 = p2->y - p1->y; dx31 = p3->x - p1->x; dy31 = p3->y - p1->y; h21 = pow(dx21, 2.0) + pow(dy21, 2.0); h31 = pow(dx31, 2.0) + pow(dy31, 2.0); /* 2 * |Cross product|, d<0 means clockwise and d>0 counterclockwise sweeping angle */ d = 2 * (dx21 * dy31 - dx31 * dy21); c.x = p1->x + (h21 * dy31 - h31 * dy21) / d; c.y = p1->y - (h21 * dx31 - h31 * dx21) / d; r = sqrt(pow(c.x - p1->x, 2) + pow(c.y - p1->y, 2)); } if ( radius ) *radius = r; if ( center ) *center = c; return MS_SUCCESS; } /* ** Write a stroked version of the circle defined by three points into a ** point buffer. The segment_angle (degrees) is the coverage of each stroke segment, ** and depending on whether this is the first arc in a circularstring, ** you might want to include_first */ int arcStrokeCircle(const pointObj *p1, const pointObj *p2, const pointObj *p3, double segment_angle, int include_first, pointArrayObj *pa) { pointObj center; /* Center of our circular arc */ double radius; /* Radius of our circular arc */ double sweep_angle_r; /* Total angular size of our circular arc in radians */ double segment_angle_r; /* Segment angle in radians */ double a1, /*a2,*/ a3; /* Angles represented by p1, p2, p3 relative to center */ int side = arcSegmentSide(p1, p3, p2); /* What side of p1,p3 is the middle point? */ int num_edges; /* How many edges we will be generating */ double current_angle_r; /* What angle are we generating now (radians)? */ int i; /* Counter */ pointObj p; /* Temporary point */ int is_closed = MS_FALSE; /* We need to know if we're dealing with a circle early */ if ( FP_EQ(p1->x, p3->x) && FP_EQ(p1->y, p3->y) ) is_closed = MS_TRUE; /* Check if the "arc" is actually straight */ if ( ! is_closed && side == FP_COLINEAR ) { /* We just need to write in the end points */ if ( include_first ) pointArrayAddPoint(pa, p1); pointArrayAddPoint(pa, p3); return MS_SUCCESS; } /* We should always be able to find the center of a non-linear arc */ if ( arcCircleCenter(p1, p2, p3, ¢er, &radius) == MS_FAILURE ) return MS_FAILURE; /* Calculate the angles that our three points represent */ a1 = atan2(p1->y - center.y, p1->x - center.x); /* UNUSED a2 = atan2(p2->y - center.y, p2->x - center.x); */ a3 = atan2(p3->y - center.y, p3->x - center.x); segment_angle_r = M_PI * segment_angle / 180.0; /* Closed-circle case, we sweep the whole circle! */ if ( is_closed ) { sweep_angle_r = 2.0 * M_PI; } /* Clockwise sweep direction */ else if ( side == FP_LEFT ) { if ( a3 > a1 ) /* Wrapping past 180? */ sweep_angle_r = a1 + (2.0 * M_PI - a3); else sweep_angle_r = a1 - a3; } /* Counter-clockwise sweep direction */ else if ( side == FP_RIGHT ) { if ( a3 > a1 ) /* Wrapping past 180? */ sweep_angle_r = a3 - a1; else sweep_angle_r = a3 + (2.0 * M_PI - a1); } else sweep_angle_r = 0.0; /* We don't have enough resolution, let's invert our strategy. */ if ( (sweep_angle_r / segment_angle_r) < SEGMENT_MINPOINTS ) { segment_angle_r = sweep_angle_r / (SEGMENT_MINPOINTS + 1); } /* We don't have enough resolution to stroke this arc, * so just join the start to the end. */ if ( sweep_angle_r < segment_angle_r ) { if ( include_first ) pointArrayAddPoint(pa, p1); pointArrayAddPoint(pa, p3); return MS_SUCCESS; } /* How many edges to generate (we add the final edge * by sticking on the last point */ num_edges = floor(sweep_angle_r / fabs(segment_angle_r)); /* Go backwards (negative angular steps) if we are stroking clockwise */ if ( side == FP_LEFT ) segment_angle_r *= -1; /* What point should we start with? */ if( include_first ) { current_angle_r = a1; } else { current_angle_r = a1 + segment_angle_r; num_edges--; } /* For each edge, increment or decrement by our segment angle */ for( i = 0; i < num_edges; i++ ) { if (segment_angle_r > 0.0 && current_angle_r > M_PI) current_angle_r -= 2*M_PI; if (segment_angle_r < 0.0 && current_angle_r < -1*M_PI) current_angle_r -= 2*M_PI; p.x = center.x + radius*cos(current_angle_r); p.y = center.y + radius*sin(current_angle_r); pointArrayAddPoint(pa, &p); current_angle_r += segment_angle_r; } /* Add the last point */ pointArrayAddPoint(pa, p3); return MS_SUCCESS; } /* ** This function does not actually take WKB as input, it takes the ** WKB starting from the numpoints integer. Each three-point edge ** is stroked into a linestring and appended into the lineObj ** argument. */ int arcStrokeCircularString(wkbObj *w, double segment_angle, lineObj *line, int nZMFlag) { pointObj p1, p2, p3; int npoints, nedges; int edge = 0; pointArrayObj *pa; if ( ! w || ! line ) return MS_FAILURE; npoints = wkbReadInt(w); nedges = npoints / 2; /* All CircularStrings have an odd number of points */ if ( npoints < 3 || npoints % 2 != 1 ) return MS_FAILURE; /* Make a large guess at how much space we'll need */ pa = pointArrayNew(nedges * 180 / segment_angle); wkbReadPointP(w,&p3,nZMFlag); /* Fill out the point array with stroked arcs */ while( edge < nedges ) { p1 = p3; wkbReadPointP(w,&p2,nZMFlag); wkbReadPointP(w,&p3,nZMFlag); if ( arcStrokeCircle(&p1, &p2, &p3, segment_angle, edge ? 0 : 1, pa) == MS_FAILURE ) { pointArrayFree(pa); return MS_FAILURE; } edge++; } /* Copy the point array into the line */ line->numpoints = pa->npoints; line->point = msSmallMalloc(line->numpoints * sizeof(pointObj)); memcpy(line->point, pa->data, line->numpoints * sizeof(pointObj)); /* Clean up */ pointArrayFree(pa); return MS_SUCCESS; } /* ** For LAYER types that are not the usual ones (charts, ** annotations, etc) we will convert to a shape type ** that "makes sense" given the WKB input. We do this ** by peaking at the type number of the first collection ** sub-element. */ static int msPostGISFindBestType(wkbObj *w, shapeObj *shape) { int wkbtype; int nZMFlag; /* What kind of geometry is this? */ wkbtype = wkbType(w, &nZMFlag); /* Generic collection, we need to look a little deeper. */ if ( wkbtype == WKB_GEOMETRYCOLLECTION ) wkbtype = wkbCollectionSubType(w, &nZMFlag); switch ( wkbtype ) { case WKB_POLYGON: case WKB_CURVEPOLYGON: case WKB_MULTIPOLYGON: shape->type = MS_SHAPE_POLYGON; break; case WKB_LINESTRING: case WKB_CIRCULARSTRING: case WKB_COMPOUNDCURVE: case WKB_MULTICURVE: case WKB_MULTILINESTRING: shape->type = MS_SHAPE_LINE; break; case WKB_POINT: case WKB_MULTIPOINT: shape->type = MS_SHAPE_POINT; break; default: return MS_FAILURE; } return wkbConvGeometryToShape(w, shape); } /* ** Recent versions of PgSQL provide the version as an int in a ** simple call to the connection handle. For earlier ones we have ** to parse the version string into a usable number. */ static int msPostGISRetrievePgVersion(PGconn *pgconn) { #ifndef POSTGIS_HAS_SERVER_VERSION int pgVersion = 0; char *strVersion = NULL; char *strParts[3] = { NULL, NULL, NULL }; int i = 0, j = 0, len = 0; int factor = 10000; if (pgconn == NULL) { msSetError(MS_QUERYERR, "Layer does not have a postgis connection.", "msPostGISRetrievePgVersion()"); return MS_FAILURE; } if (! PQparameterStatus(pgconn, "server_version") ) return MS_FAILURE; strVersion = msStrdup(PQparameterStatus(pgconn, "server_version")); if( ! strVersion ) return MS_FAILURE; strParts[j] = strVersion; j++; len = strlen(strVersion); for( i = 0; i < len; i++ ) { if( strVersion[i] == '.' ) { strVersion[i] = '\0'; if( j < 3 ) { strParts[j] = strVersion + i + 1; j++; } else { free(strVersion); msSetError(MS_QUERYERR, "Too many parts in version string.", "msPostGISRetrievePgVersion()"); return MS_FAILURE; } } } for( j = 0; j < 3 && strParts[j]; j++ ) { pgVersion += factor * atoi(strParts[j]); factor = factor / 100; } free(strVersion); return pgVersion; #else return PQserverVersion(pgconn); #endif } /* ** Get the PostGIS version number from the database as integer. ** Versions are multiplied out as with PgSQL: 1.5.2 -> 10502, 2.0.0 -> 20000. */ static int msPostGISRetrieveVersion(PGconn *pgconn) { static char* sql = "SELECT postgis_version()"; int version = 0; size_t strSize; char *strVersion = NULL; char *ptr; char *strParts[3] = { NULL, NULL, NULL }; int i = 0, j = 0; int factor = 10000; PGresult *pgresult = NULL; if ( ! pgconn ) { msSetError(MS_QUERYERR, "No open connection.", "msPostGISRetrieveVersion()"); return MS_FAILURE; } pgresult = PQexecParams(pgconn, sql,0, NULL, NULL, NULL, NULL, 0); if ( !pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK) { msDebug("Error executing SQL: (%s) in msPostGISRetrieveVersion()", sql); msSetError(MS_QUERYERR, "Error executing SQL. check server logs.", "msPostGISRetrieveVersion()"); return MS_FAILURE; } if (PQgetisnull(pgresult, 0, 0)) { PQclear(pgresult); msSetError(MS_QUERYERR,"Null result returned.","msPostGISRetrieveVersion()"); return MS_FAILURE; } strSize = PQgetlength(pgresult, 0, 0) + 1; strVersion = (char*)msSmallMalloc(strSize); strlcpy(strVersion, PQgetvalue(pgresult, 0, 0), strSize); PQclear(pgresult); ptr = strVersion; strParts[j++] = strVersion; while( *ptr != '\0' && j < 3 ) { if ( *ptr == '.' ) { *ptr = '\0'; strParts[j++] = ptr + 1; } if ( *ptr == ' ' ) { *ptr = '\0'; break; } ptr++; } for( i = 0; i < j; i++ ) { version += factor * atoi(strParts[i]); factor = factor / 100; } free(strVersion); return version; } /* ** msPostGISRetrievePK() ** ** Find out that the primary key is for this layer. ** The layerinfo->fromsource must already be populated and ** must not be a subquery. */ static int msPostGISRetrievePK(layerObj *layer) { PGresult *pgresult = NULL; char *sql = 0; size_t size; msPostGISLayerInfo *layerinfo = 0; int length; int pgVersion; if (layer->debug) { msDebug("msPostGISRetrievePK called.\n"); } layerinfo = (msPostGISLayerInfo *) layer->layerinfo; if (layerinfo->pgconn == NULL) { msSetError(MS_QUERYERR, "Layer does not have a postgis connection.", "msPostGISRetrievePK()"); return MS_FAILURE; } pgVersion = msPostGISRetrievePgVersion(layerinfo->pgconn); if (pgVersion < 70000) { if (layer->debug) { msDebug("msPostGISRetrievePK(): Major version below 7.\n"); } return MS_FAILURE; } if (pgVersion < 70200) { if (layer->debug) { msDebug("msPostGISRetrievePK(): Version below 7.2.\n"); } return MS_FAILURE; } if (pgVersion < 70300) { /* ** PostgreSQL v7.2 has a different representation of primary keys that ** later versions. This currently does not explicitly exclude ** multicolumn primary keys. */ static char *v72sql = "select b.attname from pg_class as a, pg_attribute as b, (select oid from pg_class where relname = '%s') as c, pg_index as d where d.indexrelid = a.oid and d.indrelid = c.oid and d.indisprimary and b.attrelid = a.oid and a.relnatts = 1"; sql = msSmallMalloc(strlen(layerinfo->fromsource) + strlen(v72sql) + 1); sprintf(sql, v72sql, layerinfo->fromsource); } else { /* Attempt to separate fromsource into schema.table */ char *pos_sep; char *schema = NULL; char *table = NULL; pos_sep = strstr(layerinfo->fromsource, "."); if (pos_sep) { length = strlen(layerinfo->fromsource) - strlen(pos_sep) + 1; schema = (char*)msSmallMalloc(length); strlcpy(schema, layerinfo->fromsource, length); length = strlen(pos_sep) + 1; table = (char*)msSmallMalloc(length); strlcpy(table, pos_sep + 1, length); if (layer->debug) { msDebug("msPostGISRetrievePK(): Found schema %s, table %s.\n", schema, table); } } /* ** PostgreSQL v7.3 and later treat primary keys as constraints. ** We only support single column primary keys, so multicolumn ** pks are explicitly excluded from the query. */ if (schema && table) { static char *v73sql = "select attname from pg_attribute, pg_constraint, pg_class, pg_namespace where pg_constraint.conrelid = pg_class.oid and pg_class.oid = pg_attribute.attrelid and pg_constraint.contype = 'p' and pg_constraint.conkey[1] = pg_attribute.attnum and pg_class.relname = '%s' and pg_class.relnamespace = pg_namespace.oid and pg_namespace.nspname = '%s' and pg_constraint.conkey[2] is null"; sql = msSmallMalloc(strlen(schema) + strlen(table) + strlen(v73sql) + 1); sprintf(sql, v73sql, table, schema); } else { static char *v73sql = "select attname from pg_attribute, pg_constraint, pg_class where pg_constraint.conrelid = pg_class.oid and pg_class.oid = pg_attribute.attrelid and pg_constraint.contype = 'p' and pg_constraint.conkey[1] = pg_attribute.attnum and pg_class.relname = '%s' and pg_table_is_visible(pg_class.oid) and pg_constraint.conkey[2] is null"; sql = msSmallMalloc(strlen(layerinfo->fromsource) + strlen(v73sql) + 1); sprintf(sql, v73sql, layerinfo->fromsource); } free(table); free(schema); } if (layer->debug > 1) { msDebug("msPostGISRetrievePK: %s\n", sql); } layerinfo = (msPostGISLayerInfo *) layer->layerinfo; if (layerinfo->pgconn == NULL) { msSetError(MS_QUERYERR, "Layer does not have a postgis connection.", "msPostGISRetrievePK()"); free(sql); return MS_FAILURE; } pgresult = PQexecParams(layerinfo->pgconn, sql, 0, NULL, NULL, NULL, NULL, 0); if ( !pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK) { static char *tmp1 = "Error executing SQL: "; char *tmp2 = NULL; size_t size2; size2 = sizeof(char)*(strlen(tmp1) + strlen(sql) + 1); tmp2 = (char*)msSmallMalloc(size2); strlcpy(tmp2, tmp1, size2); strlcat(tmp2, sql, size2); msSetError(MS_QUERYERR, "%s", "msPostGISRetrievePK()", tmp2); free(tmp2); free(sql); return MS_FAILURE; } if (PQntuples(pgresult) < 1) { if (layer->debug) { msDebug("msPostGISRetrievePK: No results found.\n"); } PQclear(pgresult); free(sql); return MS_FAILURE; } if (PQntuples(pgresult) > 1) { if (layer->debug) { msDebug("msPostGISRetrievePK: Multiple results found.\n"); } PQclear(pgresult); free(sql); return MS_FAILURE; } if (PQgetisnull(pgresult, 0, 0)) { if (layer->debug) { msDebug("msPostGISRetrievePK: Null result returned.\n"); } PQclear(pgresult); free(sql); return MS_FAILURE; } size = PQgetlength(pgresult, 0, 0) + 1; layerinfo->uid = (char*)msSmallMalloc(size); strlcpy(layerinfo->uid, PQgetvalue(pgresult, 0, 0), size); PQclear(pgresult); free(sql); return MS_SUCCESS; } /* ** msPostGISParseData() ** ** Parse the DATA string for geometry column name, table name, ** unique id column, srid, and SQL string. */ int msPostGISParseData(layerObj *layer) { char *pos_opt, *pos_scn, *tmp, *pos_srid, *pos_uid, *pos_geom, *data; int slength; msPostGISLayerInfo *layerinfo; assert(layer != NULL); assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo*)(layer->layerinfo); if (layer->debug) { msDebug("msPostGISParseData called.\n"); } if (!layer->data) { msSetError(MS_QUERYERR, "Missing DATA clause. DATA statement must contain 'geometry_column from table_name' or 'geometry_column from (sub-query) as sub'.", "msPostGISParseData()"); return MS_FAILURE; } data = layer->data; /* ** Clean up any existing strings first, as we will be populating these fields. */ if( layerinfo->srid ) { free(layerinfo->srid); layerinfo->srid = NULL; } if( layerinfo->uid ) { free(layerinfo->uid); layerinfo->uid = NULL; } if( layerinfo->geomcolumn ) { free(layerinfo->geomcolumn); layerinfo->geomcolumn = NULL; } if( layerinfo->fromsource ) { free(layerinfo->fromsource); layerinfo->fromsource = NULL; } /* ** Look for the optional ' using unique ID' string first. */ pos_uid = strcasestr(data, " using unique "); if (pos_uid) { /* Find the end of this case 'using unique ftab_id using srid=33' */ tmp = strstr(pos_uid + 14, " "); /* Find the end of this case 'using srid=33 using unique ftab_id' */ if (!tmp) { tmp = pos_uid + strlen(pos_uid); } layerinfo->uid = (char*) msSmallMalloc((tmp - (pos_uid + 14)) + 1); strlcpy(layerinfo->uid, pos_uid + 14, tmp - (pos_uid + 14)+1); msStringTrim(layerinfo->uid); } /* ** Look for the optional ' using srid=333 ' string next. */ pos_srid = strcasestr(data, " using srid="); if (!pos_srid) { layerinfo->srid = (char*) msSmallMalloc(1); (layerinfo->srid)[0] = '\0'; /* no SRID, so return just null terminator*/ } else { slength = strspn(pos_srid + 12, "-0123456789"); if (!slength) { msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. You specified 'USING SRID' but didn't have any numbers! %s", "msPostGISParseData()", data); return MS_FAILURE; } else { layerinfo->srid = (char*) msSmallMalloc(slength + 1); strlcpy(layerinfo->srid, pos_srid + 12, slength+1); msStringTrim(layerinfo->srid); } } /* ** This is a little hack so the rest of the code works. ** pos_opt should point to the start of the optional blocks. ** ** If they are both set, return the smaller one. */ if (pos_srid && pos_uid) { pos_opt = (pos_srid > pos_uid) ? pos_uid : pos_srid; } /* If one or none is set, return the larger one. */ else { pos_opt = (pos_srid > pos_uid) ? pos_srid : pos_uid; } /* No pos_opt? Move it to the end of the string. */ if (!pos_opt) { pos_opt = data + strlen(data); } /* ** Scan for the 'geometry from table' or 'geometry from () as foo' clause. */ /* Find the first non-white character to start from */ pos_geom = data; while( *pos_geom == ' ' || *pos_geom == '\t' || *pos_geom == '\n' || *pos_geom == '\r' ) pos_geom++; /* Find the end of the geom column name */ pos_scn = strcasestr(data, " from "); if (!pos_scn) { msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. Must contain 'geometry from table' or 'geometry from (subselect) as foo'. %s", "msPostGISParseData()", data); return MS_FAILURE; } /* Copy the geometry column name */ layerinfo->geomcolumn = (char*) msSmallMalloc((pos_scn - pos_geom) + 1); strlcpy(layerinfo->geomcolumn, pos_geom, pos_scn - pos_geom+1); msStringTrim(layerinfo->geomcolumn); /* Copy the table name or sub-select clause */ layerinfo->fromsource = (char*) msSmallMalloc((pos_opt - (pos_scn + 6)) + 1); strlcpy(layerinfo->fromsource, pos_scn + 6, pos_opt - (pos_scn + 6)+1); msStringTrim(layerinfo->fromsource); /* Something is wrong, our goemetry column and table references are not there. */ if (strlen(layerinfo->fromsource) < 1 || strlen(layerinfo->geomcolumn) < 1) { msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. Must contain 'geometry from table' or 'geometry from (subselect) as foo'. %s", "msPostGISParseData()", data); return MS_FAILURE; } /* ** We didn't find a ' using unique ' in the DATA string so try and find a ** primary key on the table. */ if ( ! (layerinfo->uid) ) { if ( strstr(layerinfo->fromsource, " ") ) { msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. You must specify 'using unique' when supplying a subselect in the data definition.", "msPostGISParseData()"); return MS_FAILURE; } if ( msPostGISRetrievePK(layer) != MS_SUCCESS ) { /* No user specified unique id so we will use the PostgreSQL oid */ /* TODO: Deprecate this, oids are deprecated in PostgreSQL */ layerinfo->uid = msStrdup("oid"); } } if (layer->debug) { msDebug("msPostGISParseData: unique_column=%s, srid=%s, geom_column_name=%s, table_name=%s\n", layerinfo->uid, layerinfo->srid, layerinfo->geomcolumn, layerinfo->fromsource); } return MS_SUCCESS; } /* ** Decode a hex character. */ static unsigned char msPostGISHexDecodeChar[256] = { /* not Hex characters */ 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, /* 0-9 */ 0,1,2,3,4,5,6,7,8,9, /* not Hex characters */ 64,64,64,64,64,64,64, /* A-F */ 10,11,12,13,14,15, /* not Hex characters */ 64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64, /* a-f */ 10,11,12,13,14,15, 64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, /* not Hex characters (upper 128 characters) */ 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64 }; /* ** Decode hex string "src" (null terminated) ** into "dest" (not null terminated). ** Returns length of decoded array or 0 on failure. */ int msPostGISHexDecode(unsigned char *dest, const char *src, int srclen) { if (src && *src && (srclen % 2 == 0) ) { unsigned char *p = dest; int i; for ( i=0; i>4) ); if (c3 != '=') { *p++=(((b2&0xf)<<4)|(b3>>2) ); } if (c4 != '=') { *p++=(((b3&0x3)<<6)|b4 ); } } free(buf); return(p-dest); } return 0; } /* ** msPostGISBuildSQLBox() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLBox(layerObj *layer, rectObj *rect, char *strSRID) { char *strBox = NULL; size_t sz; if (layer->debug) { msDebug("msPostGISBuildSQLBox called.\n"); } if ( strSRID ) { static char *strBoxTemplate = "ST_GeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%s)"; /* 10 doubles + 1 integer + template characters */ sz = 10 * 22 + strlen(strSRID) + strlen(strBoxTemplate); strBox = (char*)msSmallMalloc(sz+1); /* add space for terminating NULL */ if ( sz <= snprintf(strBox, sz, strBoxTemplate, rect->minx, rect->miny, rect->minx, rect->maxy, rect->maxx, rect->maxy, rect->maxx, rect->miny, rect->minx, rect->miny, strSRID)) { msSetError(MS_MISCERR,"Bounding box digits truncated.","msPostGISBuildSQLBox"); return NULL; } } else { static char *strBoxTemplate = "ST_GeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))')"; /* 10 doubles + template characters */ sz = 10 * 22 + strlen(strBoxTemplate); strBox = (char*)msSmallMalloc(sz+1); /* add space for terminating NULL */ if ( sz <= snprintf(strBox, sz, strBoxTemplate, rect->minx, rect->miny, rect->minx, rect->maxy, rect->maxx, rect->maxy, rect->maxx, rect->miny, rect->minx, rect->miny) ) { msSetError(MS_MISCERR,"Bounding box digits truncated.","msPostGISBuildSQLBox"); return NULL; } } return strBox; } /* ** msPostGISBuildSQLItems() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLItems(layerObj *layer) { char *strEndian = NULL; char *strGeom = NULL; char *strItems = NULL; msPostGISLayerInfo *layerinfo = NULL; if (layer->debug) { msDebug("msPostGISBuildSQLItems called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; if ( ! layerinfo->geomcolumn ) { msSetError(MS_MISCERR, "layerinfo->geomcolumn is not initialized.", "msPostGISBuildSQLItems()"); return NULL; } /* ** Get the server to transform the geometry into our ** native endian before transmitting it to us.. */ if (layerinfo->endian == LITTLE_ENDIAN) { strEndian = "NDR"; } else { strEndian = "XDR"; } { /* ** We transfer the geometry from server to client as a ** hex or base64 encoded WKB byte-array. We will have to decode this ** data once we get it. Forcing to 2D (via the AsBinary function ** which includes a 2D force in it) removes ordinates we don't ** need, saving transfer and encode/decode time. */ char *force2d = ""; #if TRANSFER_ENCODING == 64 const char *strGeomTemplate = "encode(ST_AsBinary(%s(\"%s\"),'%s'),'base64') as geom,\"%s\""; #elif TRANSFER_ENCODING == 256 const char *strGeomTemplate = "ST_AsBinary(%s(\"%s\"),'%s') as geom,\"%s\"::text"; #else const char *strGeomTemplate = "encode(ST_AsBinary(%s(\"%s\"),'%s'),'hex') as geom,\"%s\""; #endif if( layerinfo->force2d ) { if( layerinfo->version >= 20100 ) force2d = "ST_Force2D"; else force2d = "ST_Force_2D"; } else if( layerinfo->version < 20000 ) { /* Use AsEWKB() to get 3D */ #if TRANSFER_ENCODING == 64 strGeomTemplate = "encode(AsEWKB(%s(\"%s\"),'%s'),'base64') as geom,\"%s\""; #elif TRANSFER_ENCODING == 256 strGeomTemplate = "AsEWKB(%s(\"%s\"),'%s') as geom,\"%s\"::text"; #else strGeomTemplate = "encode(AsEWKB(%s(\"%s\"),'%s'),'hex') as geom,\"%s\""; #endif } strGeom = (char*)msSmallMalloc(strlen(strGeomTemplate) + strlen(force2d) + strlen(strEndian) + strlen(layerinfo->geomcolumn) + strlen(layerinfo->uid) + 1); sprintf(strGeom, strGeomTemplate, force2d, layerinfo->geomcolumn, strEndian, layerinfo->uid); } if( layer->debug > 1 ) { msDebug("msPostGISBuildSQLItems: %d items requested.\n",layer->numitems); } /* ** Not requesting items? We just need geometry and unique id. */ if (layer->numitems == 0) { strItems = msStrdup(strGeom); } /* ** Build SQL to pull all the items. */ else { int length = strlen(strGeom) + 2; int t; for ( t = 0; t < layer->numitems; t++ ) { length += strlen(layer->items[t]) + 3; /* itemname + "", */ #if TRANSFER_ENCODING == 256 length +=6; /*add a ::text*/ #endif } strItems = (char*)msSmallMalloc(length); strItems[0] = '\0'; for ( t = 0; t < layer->numitems; t++ ) { strlcat(strItems, "\"", length); strlcat(strItems, layer->items[t], length); #if TRANSFER_ENCODING == 256 strlcat(strItems, "\"::text,", length); #else strlcat(strItems, "\",", length); #endif } strlcat(strItems, strGeom, length); } free(strGeom); return strItems; } /* ** msPostGISFindTableName() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISFindTableName(char* fromsource) { char *f_table_name = NULL; char *pos = strstr(fromsource, " "); if ( ! pos ) { /* target table is one word */ f_table_name = msStrdup(fromsource); } else { /* target table is hiding in sub-select clause */ pos = strcasestr(fromsource, " from "); if ( pos ) { char *pos_paren; char *pos_space; pos += 6; /* should be start of table name */ pos_paren = strstr(pos, ")"); /* first ) after table name */ pos_space = strstr(pos, " "); /* first space after table name */ if ( pos_space < pos_paren ) { /* found space first */ f_table_name = (char*)msSmallMalloc(pos_space - pos + 1); strlcpy(f_table_name, pos, pos_space - pos+1); } else { /* found ) first */ f_table_name = (char*)msSmallMalloc(pos_paren - pos + 1); strlcpy(f_table_name, pos, pos_paren - pos+1); } } } return f_table_name; } /* ** msPostGISBuildSQLSRID() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLSRID(layerObj *layer) { char *strSRID = NULL; msPostGISLayerInfo *layerinfo = NULL; if (layer->debug) { msDebug("msPostGISBuildSQLSRID called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; /* An SRID was already provided in the DATA line. */ if ( layerinfo->srid && (strlen(layerinfo->srid) > 0) ) { strSRID = msStrdup(layerinfo->srid); if( layer->debug > 1 ) { msDebug("msPostGISBuildSQLSRID: SRID provided (%s)\n", strSRID); } } /* ** No SRID in data line, so extract target table from the 'fromsource'. ** Either of form "thetable" (one word) or "(select ... from thetable)" ** or "(select ... from thetable where ...)". */ else { char *f_table_name = msPostGISFindTableName(layerinfo->fromsource); char *strSRIDTemplate = "find_srid('','%s','%s')"; if( layer->debug > 1 ) { msDebug("msPostGISBuildSQLSRID: Building find_srid line.\n"); } if (!f_table_name) return NULL; /* should not happen */ strSRID = msSmallMalloc(strlen(strSRIDTemplate) + strlen(f_table_name) + strlen(layerinfo->geomcolumn) + 1); sprintf(strSRID, strSRIDTemplate, f_table_name, layerinfo->geomcolumn); free(f_table_name); } return strSRID; } /* ** msPostGISReplaceBoxToken() ** ** Convert a fromsource data statement into something usable by replacing the !BOX! token. ** ** Returns malloc'ed char* that must be freed by caller. */ static char *msPostGISReplaceBoxToken(layerObj *layer, rectObj *rect, const char *fromsource) { char *result = NULL; if ( strstr(fromsource, BOXTOKEN) && rect ) { char *strBox = NULL; char *strSRID = NULL; /* We see to set the SRID on the box, but to what SRID? */ strSRID = msPostGISBuildSQLSRID(layer); if ( ! strSRID ) { return NULL; } /* Create a suitable SQL string from the rectangle and SRID. */ strBox = msPostGISBuildSQLBox(layer, rect, strSRID); if ( ! strBox ) { msSetError(MS_MISCERR, "Unable to build box SQL.", "msPostGISReplaceBoxToken()"); if (strSRID) free(strSRID); return NULL; } /* Do the substitution. */ while ( strstr(fromsource, BOXTOKEN) ) { char *start, *end; char *oldresult = result; size_t buffer_size = 0; start = strstr(fromsource, BOXTOKEN); end = start + BOXTOKENLENGTH; buffer_size = (start - fromsource) + strlen(strBox) + strlen(end) +1; result = (char*)msSmallMalloc(buffer_size); strlcpy(result, fromsource, start - fromsource +1); strlcpy(result + (start - fromsource), strBox, buffer_size-(start - fromsource)); strlcat(result, end, buffer_size); fromsource = result; if (oldresult != NULL) free(oldresult); } if (strSRID) free(strSRID); if (strBox) free(strBox); } else { result = msStrdup(fromsource); } return result; } /* ** msPostGISBuildSQLFrom() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLFrom(layerObj *layer, rectObj *rect) { char *strFrom = 0; msPostGISLayerInfo *layerinfo; if (layer->debug) { msDebug("msPostGISBuildSQLFrom called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; if ( ! layerinfo->fromsource ) { msSetError(MS_MISCERR, "Layerinfo->fromsource is not initialized.", "msPostGISBuildSQLFrom()"); return NULL; } /* ** If there's a '!BOX!' in our source we need to substitute the ** current rectangle for it... */ strFrom = msPostGISReplaceBoxToken(layer, rect, layerinfo->fromsource); return strFrom; } /* ** msPostGISBuildSQLWhere() ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQLWhere(layerObj *layer, rectObj *rect, long *uid, rectObj *rectInOtherSRID, int otherSRID) { char *strRect = 0; char *strFilter1=0, *strFilter2=0; char *strUid = 0; char *strWhere = 0; char *strOrderBy = 0; char *strLimit = 0; char *strOffset = 0; size_t strRectLength = 0; size_t strFilterLength1=0, strFilterLength2=0; size_t strUidLength = 0; size_t strOrderByLength = 0; size_t strLimitLength = 0; size_t strOffsetLength = 0; size_t bufferSize = 0; int insert_and = 0; msPostGISLayerInfo *layerinfo; if (layer->debug) { msDebug("msPostGISBuildSQLWhere called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; if ( ! layerinfo->fromsource ) { msSetError(MS_MISCERR, "Layerinfo->fromsource is not initialized.", "msPostGISBuildSQLWhere()"); return NULL; } /* Populate strLimit, if necessary. */ if ( layerinfo->paging && layer->maxfeatures >= 0 ) { static char *strLimitTemplate = " limit %d"; strLimit = msSmallMalloc(strlen(strLimitTemplate) + 12); sprintf(strLimit, strLimitTemplate, layer->maxfeatures); strLimitLength = strlen(strLimit); } /* Populate strOffset, if necessary. */ if ( layerinfo->paging && layer->startindex > 0 ) { static char *strOffsetTemplate = " offset %d"; strOffset = msSmallMalloc(strlen(strOffsetTemplate) + 12); sprintf(strOffset, strOffsetTemplate, layer->startindex-1); strOffsetLength = strlen(strOffset); } /* Populate strRect, if necessary. */ if ( rect && layerinfo->geomcolumn ) { char *strBox = 0; char *strSRID = 0; size_t strBoxLength = 0; static const char *strRectTemplate = "\"%s\" && %s"; /* We see to set the SRID on the box, but to what SRID? */ strSRID = msPostGISBuildSQLSRID(layer); if ( ! strSRID ) { free( strLimit ); free( strOffset ); return NULL; } strBox = msPostGISBuildSQLBox(layer, rect, strSRID); msFree(strSRID); if ( strBox ) { strBoxLength = strlen(strBox); } else { msSetError(MS_MISCERR, "Unable to build box SQL.", "msPostGISBuildSQLWhere()"); free( strLimit ); free( strOffset ); return NULL; } strRect = (char*)msSmallMalloc(strlen(strRectTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 ); sprintf(strRect, strRectTemplate, layerinfo->geomcolumn, strBox); strRectLength = strlen(strRect); free(strBox); /* Combine with other rectangle expressed in another SRS */ /* (generally equivalent to the above in current code paths) */ if( rectInOtherSRID != NULL && otherSRID > 0 ) { char* strRectOtherSRID; static const char *strRectOtherSRIDTemplate = "NOT ST_Disjoint(ST_Transform(%s,%d),%s)"; char szSRID[32]; char* strTmp = NULL; sprintf(szSRID, "%d", otherSRID); strBox = msPostGISBuildSQLBox(layer, rectInOtherSRID, szSRID); if ( strBox ) { strBoxLength = strlen(strBox); } else { msSetError(MS_MISCERR, "Unable to build box SQL.", "msPostGISBuildSQLWhere()"); free( strLimit ); free( strOffset ); return NULL; } strRectOtherSRID = (char*)msSmallMalloc(strlen(strRectOtherSRIDTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 ); sprintf(strRectOtherSRID, strRectOtherSRIDTemplate, layerinfo->geomcolumn, otherSRID, strBox); free(strBox); strTmp = msStringConcatenate(strTmp, "(("); strTmp = msStringConcatenate(strTmp, strRect); strTmp = msStringConcatenate(strTmp, ") AND "); strTmp = msStringConcatenate(strTmp, strRectOtherSRID); strTmp = msStringConcatenate(strTmp, ")"); msFree(strRect); msFree(strRectOtherSRID); strRect = strTmp; strRectLength = strlen(strRect); } else if( rectInOtherSRID != NULL && otherSRID < 0 ) { char* strSRID; char* strRectOtherSRID; static const char *strRectOtherSRIDTemplate = "NOT ST_Disjoint(%s,%s)"; char* strTmp = NULL; strSRID = msPostGISBuildSQLSRID(layer); if ( ! strSRID ) { free( strLimit ); free( strOffset ); return NULL; } strBox = msPostGISBuildSQLBox(layer, rectInOtherSRID, strSRID); msFree(strSRID); if ( strBox ) { strBoxLength = strlen(strBox); } else { msSetError(MS_MISCERR, "Unable to build box SQL.", "msPostGISBuildSQLWhere()"); free( strLimit ); free( strOffset ); return NULL; } strRectOtherSRID = (char*)msSmallMalloc(strlen(strRectOtherSRIDTemplate) + strBoxLength + strlen(layerinfo->geomcolumn) +1 ); sprintf(strRectOtherSRID, strRectOtherSRIDTemplate, layerinfo->geomcolumn, strBox); free(strBox); strTmp = msStringConcatenate(strTmp, "(("); strTmp = msStringConcatenate(strTmp, strRect); strTmp = msStringConcatenate(strTmp, ") AND "); strTmp = msStringConcatenate(strTmp, strRectOtherSRID); strTmp = msStringConcatenate(strTmp, ")"); msFree(strRect); msFree(strRectOtherSRID); strRect = strTmp; strRectLength = strlen(strRect); } } /* Handle a translated filter (RFC91). */ if ( layer->filter.native_string ) { static char *strFilterTemplate = "(%s)"; strFilter1 = (char *) msSmallMalloc(strlen(strFilterTemplate) + strlen(layer->filter.native_string)+1); sprintf(strFilter1, strFilterTemplate, layer->filter.native_string); strFilterLength1 = strlen(strFilter1); } /* Handle a native filter set as a PROCESSING option (#5001). */ if( msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL ) { static char *strFilterTemplate = "(%s)"; char *native_filter = msLayerGetProcessingKey(layer, "NATIVE_FILTER"); strFilter2 = (char *) msSmallMalloc(strlen(strFilterTemplate) + strlen(native_filter)+1); sprintf(strFilter2, strFilterTemplate, native_filter); strFilterLength2 = strlen(strFilter2); } /* Populate strUid, if necessary. */ if ( uid ) { static char *strUidTemplate = "\"%s\" = %ld"; strUid = (char*)msSmallMalloc(strlen(strUidTemplate) + strlen(layerinfo->uid) + 64); sprintf(strUid, strUidTemplate, layerinfo->uid, *uid); strUidLength = strlen(strUid); } /* Populate strOrderBy, if necessary */ if( layer->sortBy.nProperties > 0 ) { char* pszTmp = msLayerBuildSQLOrderBy(layer); strOrderBy = msStringConcatenate(strOrderBy, " ORDER BY "); strOrderBy = msStringConcatenate(strOrderBy, pszTmp); msFree(pszTmp); strOrderByLength = strlen(strOrderBy); } bufferSize = strRectLength + 5 + (strFilterLength1 + 5) + (strFilterLength2 + 5) + strUidLength + strLimitLength + strOffsetLength + strOrderByLength + 1; strWhere = (char*)msSmallMalloc(bufferSize); *strWhere = '\0'; if ( strRect ) { strlcat(strWhere, strRect, bufferSize); insert_and++; free(strRect); } if ( strFilter1 ) { if ( insert_and ) { strlcat(strWhere, " and ", bufferSize); } strlcat(strWhere, strFilter1, bufferSize); free(strFilter1); insert_and++; } if ( strFilter2 ) { if ( insert_and ) { strlcat(strWhere, " and ", bufferSize); } strlcat(strWhere, strFilter2, bufferSize); free(strFilter2); insert_and++; } if ( strUid ) { if ( insert_and ) { strlcat(strWhere, " and ", bufferSize); } strlcat(strWhere, strUid, bufferSize); free(strUid); insert_and++; } if ( strOrderBy ) { strlcat(strWhere, strOrderBy, bufferSize); free(strOrderBy); } if ( strLimit ) { strlcat(strWhere, strLimit, bufferSize); free(strLimit); } if ( strOffset ) { strlcat(strWhere, strOffset, bufferSize); free(strOffset); } return strWhere; } /* ** msPostGISBuildSQL() ** ** rect is the search rectangle in layer SRS. It can be set to NULL ** uid can be set to NULL ** rectInOtherSRID is an additional rectangle potentially in another SRS. It can be set to NULL. ** Only used if rect != NULL ** otherSRID is the SRID of the additional rectangle. It can be set to -1 if ** rectInOtherSRID is in the SRID of the layer. ** ** Returns malloc'ed char* that must be freed by caller. */ char *msPostGISBuildSQL(layerObj *layer, rectObj *rect, long *uid, rectObj *rectInOtherSRID, int otherSRID) { msPostGISLayerInfo *layerinfo = 0; char *strFrom = 0; char *strItems = 0; char *strWhere = 0; char *strSQL = 0; static char *strSQLTemplate0 = "select %s from %s where %s"; static char *strSQLTemplate1 = "select %s from %s%s"; char *strSQLTemplate = 0; if (layer->debug) { msDebug("msPostGISBuildSQL called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; strItems = msPostGISBuildSQLItems(layer); if ( ! strItems ) { msSetError(MS_MISCERR, "Failed to build SQL items.", "msPostGISBuildSQL()"); return NULL; } strFrom = msPostGISBuildSQLFrom(layer, rect); if ( ! strFrom ) { msSetError(MS_MISCERR, "Failed to build SQL 'from'.", "msPostGISBuildSQL()"); return NULL; } /* If there's BOX hackery going on, we don't want to append a box index test at the end of the query, the user is going to be responsible for making things work with their hackery. */ if ( strstr(layerinfo->fromsource, BOXTOKEN) ) strWhere = msPostGISBuildSQLWhere(layer, NULL, uid, rectInOtherSRID, otherSRID); else strWhere = msPostGISBuildSQLWhere(layer, rect, uid, rectInOtherSRID, otherSRID); if ( ! strWhere ) { msSetError(MS_MISCERR, "Failed to build SQL 'where'.", "msPostGISBuildSQL()"); return NULL; } strSQLTemplate = strlen(strWhere) ? strSQLTemplate0 : strSQLTemplate1; strSQL = msSmallMalloc(strlen(strSQLTemplate) + strlen(strFrom) + strlen(strItems) + strlen(strWhere) + 1); sprintf(strSQL, strSQLTemplate, strItems, strFrom, strWhere); free(strItems); free(strFrom); free(strWhere); return strSQL; } #define wkbstaticsize 4096 int msPostGISReadShape(layerObj *layer, shapeObj *shape) { char *wkbstr = NULL; unsigned char wkbstatic[wkbstaticsize]; unsigned char *wkb = NULL; wkbObj w; msPostGISLayerInfo *layerinfo = NULL; int result = 0; int wkbstrlen = 0; if (layer->debug) { msDebug("msPostGISReadShape called.\n"); } assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Retrieve the geometry. */ wkbstr = (char*)PQgetvalue(layerinfo->pgresult, layerinfo->rownum, layer->numitems ); wkbstrlen = PQgetlength(layerinfo->pgresult, layerinfo->rownum, layer->numitems); if ( ! wkbstr ) { msSetError(MS_QUERYERR, "WKB returned is null!", "msPostGISReadShape()"); return MS_FAILURE; } if(wkbstrlen > wkbstaticsize) { wkb = calloc(wkbstrlen, sizeof(char)); } else { wkb = wkbstatic; } #if TRANSFER_ENCODING == 64 result = msPostGISBase64Decode(wkb, wkbstr, wkbstrlen - 1); w.size = (wkbstrlen - 1)/2; #elif TRANSFER_ENCODING == 256 result = 1; memcpy(wkb, wkbstr, wkbstrlen); w.size = wkbstrlen; #else result = msPostGISHexDecode(wkb, wkbstr, wkbstrlen); w.size = (wkbstrlen - 1)/2; #endif if( ! result ) { if(wkb!=wkbstatic) free(wkb); return MS_FAILURE; } /* Initialize our wkbObj */ w.wkb = (char*)wkb; w.ptr = w.wkb; /* Set the type map according to what version of PostGIS we are dealing with */ if( layerinfo->version >= 20000 ) /* PostGIS 2.0+ */ w.typemap = wkb_postgis20; else { w.typemap = wkb_postgis15; if( layerinfo->force2d == MS_FALSE ) { /* Is there SRID ? Skip it */ if( w.size >= 9 && (w.ptr[4] & 0x20) != 0 ) { w.ptr[5] = w.ptr[1]; w.ptr[6] = w.ptr[2]; w.ptr[7] = w.ptr[3]; w.ptr[8] = w.ptr[4] & ~(0x20); w.ptr[4] = 1; w.ptr += 4; w.size -= 4; } } } switch (layer->type) { case MS_LAYER_POINT: shape->type = MS_SHAPE_POINT; result = wkbConvGeometryToShape(&w, shape); break; case MS_LAYER_LINE: shape->type = MS_SHAPE_LINE; result = wkbConvGeometryToShape(&w, shape); break; case MS_LAYER_POLYGON: shape->type = MS_SHAPE_POLYGON; result = wkbConvGeometryToShape(&w, shape); break; case MS_LAYER_QUERY: case MS_LAYER_CHART: result = msPostGISFindBestType(&w, shape); break; case MS_LAYER_RASTER: msDebug("Ignoring MS_LAYER_RASTER in msPostGISReadShape.\n"); break; case MS_LAYER_CIRCLE: msDebug("Ignoring MS_LAYER_RASTER in msPostGISReadShape.\n"); break; default: msDebug("Unsupported layer type in msPostGISReadShape()!\n"); break; } /* All done with WKB geometry, free it! */ if(wkb!=wkbstatic) free(wkb); if (result != MS_FAILURE) { int t; long uid; char *tmp; /* Found a drawable shape, so now retreive the attributes. */ shape->values = (char**) msSmallMalloc(sizeof(char*) * layer->numitems); for ( t = 0; t < layer->numitems; t++) { int size = PQgetlength(layerinfo->pgresult, layerinfo->rownum, t); char *val = (char*)PQgetvalue(layerinfo->pgresult, layerinfo->rownum, t); int isnull = PQgetisnull(layerinfo->pgresult, layerinfo->rownum, t); if ( isnull ) { shape->values[t] = msStrdup(""); } else { shape->values[t] = (char*) msSmallMalloc(size + 1); memcpy(shape->values[t], val, size); shape->values[t][size] = '\0'; /* null terminate it */ msStringTrimBlanks(shape->values[t]); } if( layer->debug > 4 ) { msDebug("msPostGISReadShape: PQgetlength = %d\n", size); } if( layer->debug > 1 ) { msDebug("msPostGISReadShape: [%s] \"%s\"\n", layer->items[t], shape->values[t]); } } /* t is the geometry, t+1 is the uid */ tmp = PQgetvalue(layerinfo->pgresult, layerinfo->rownum, t + 1); if( tmp ) { uid = strtol( tmp, NULL, 10 ); } else { uid = 0; } if( layer->debug > 4 ) { msDebug("msPostGISReadShape: Setting shape->index = %ld\n", uid); msDebug("msPostGISReadShape: Setting shape->resultindex = %ld\n", layerinfo->rownum); } shape->index = uid; shape->resultindex = layerinfo->rownum; if( layer->debug > 2 ) { msDebug("msPostGISReadShape: [index] %ld\n", shape->index); } shape->numvalues = layer->numitems; msComputeBounds(shape); } else { shape->type = MS_SHAPE_NULL; } if( layer->debug > 2 ) { char *tmp = msShapeToWKT(shape); msDebug("msPostGISReadShape: [shape] %s\n", tmp); free(tmp); } return MS_SUCCESS; } #endif /* USE_POSTGIS */ /* ** msPostGISLayerOpen() ** ** Registered vtable->LayerOpen function. */ int msPostGISLayerOpen(layerObj *layer) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo; int order_test = 1; const char* force2d_processing; assert(layer != NULL); if (layer->debug) { msDebug("msPostGISLayerOpen called: %s\n", layer->data); } if (layer->layerinfo) { if (layer->debug) { msDebug("msPostGISLayerOpen: Layer is already open!\n"); } return MS_SUCCESS; /* already open */ } if (!layer->data) { msSetError(MS_QUERYERR, "Nothing specified in DATA statement.", "msPostGISLayerOpen()"); return MS_FAILURE; } /* ** Initialize the layerinfo **/ layerinfo = msPostGISCreateLayerInfo(); if (((char*) &order_test)[0] == 1) { layerinfo->endian = LITTLE_ENDIAN; } else { layerinfo->endian = BIG_ENDIAN; } /* ** Get a database connection from the pool. */ layerinfo->pgconn = (PGconn *) msConnPoolRequest(layer); /* No connection in the pool, so set one up. */ if (!layerinfo->pgconn) { char *conn_decrypted; if (layer->debug) { msDebug("msPostGISLayerOpen: No connection in pool, creating a fresh one.\n"); } if (!layer->connection) { msSetError(MS_MISCERR, "Missing CONNECTION keyword.", "msPostGISLayerOpen()"); free(layerinfo); return MS_FAILURE; } /* ** Decrypt any encrypted token in connection string and attempt to connect. */ conn_decrypted = msDecryptStringTokens(layer->map, layer->connection); if (conn_decrypted == NULL) { free(layerinfo); return MS_FAILURE; /* An error should already have been produced */ } layerinfo->pgconn = PQconnectdb(conn_decrypted); msFree(conn_decrypted); conn_decrypted = NULL; /* ** Connection failed, return error message with passwords ***ed out. */ if (!layerinfo->pgconn || PQstatus(layerinfo->pgconn) == CONNECTION_BAD) { char *index, *maskeddata; if (layer->debug) msDebug("msPostGISLayerOpen: Connection failure.\n"); maskeddata = msStrdup(layer->connection); index = strstr(maskeddata, "password="); if (index != NULL) { index = (char*)(index + 9); while (*index != '\0' && *index != ' ') { *index = '*'; index++; } } msDebug( "Database connection failed (%s) with connect string '%s'\nIs the database running? Is it allowing connections? Does the specified user exist? Is the password valid? Is the database on the standard port? in msPostGISLayerOpen()", PQerrorMessage(layerinfo->pgconn), maskeddata); msSetError(MS_QUERYERR, "Database connection failed. Check server logs for more details.Is the database running? Is it allowing connections? Does the specified user exist? Is the password valid? Is the database on the standard port?", "msPostGISLayerOpen()"); if(layerinfo->pgconn) PQfinish(layerinfo->pgconn); free(maskeddata); free(layerinfo); return MS_FAILURE; } /* Register to receive notifications from the database. */ PQsetNoticeProcessor(layerinfo->pgconn, postresqlNoticeHandler, (void *) layer); /* Save this connection in the pool for later. */ msConnPoolRegister(layer, layerinfo->pgconn, msPostGISCloseConnection); } else { /* Connection in the pool should be tested to see if backend is alive. */ if( PQstatus(layerinfo->pgconn) != CONNECTION_OK ) { /* Uh oh, bad connection. Can we reset it? */ PQreset(layerinfo->pgconn); if( PQstatus(layerinfo->pgconn) != CONNECTION_OK ) { /* Nope, time to bail out. */ msSetError(MS_QUERYERR, "PostgreSQL database connection. Check server logs for more details", "msPostGISLayerOpen()"); msDebug( "PostgreSQL database connection gone bad (%s) in msPostGISLayerOpen()", PQerrorMessage(layerinfo->pgconn)); free(layerinfo); /* FIXME: we should also release the connection from the pool in this case, but it is stale... * for the time being we do not release it so it can never be used again. If this happens multiple * times there will be a leak... */ return MS_FAILURE; } } } /* Get the PostGIS version number from the database */ layerinfo->version = msPostGISRetrieveVersion(layerinfo->pgconn); if( layerinfo->version == MS_FAILURE ) { msConnPoolRelease(layer, layerinfo->pgconn); free(layerinfo); return MS_FAILURE; } if (layer->debug) msDebug("msPostGISLayerOpen: Got PostGIS version %d.\n", layerinfo->version); force2d_processing = msLayerGetProcessingKey( layer, "FORCE2D" ); if(force2d_processing && !strcasecmp(force2d_processing,"no")) { layerinfo->force2d = MS_FALSE; } else if(force2d_processing && !strcasecmp(force2d_processing,"yes")) { layerinfo->force2d = MS_TRUE; } if (layer->debug) msDebug("msPostGISLayerOpen: Forcing 2D geometries: %s.\n", (layerinfo->force2d)?"yes":"no"); /* Save the layerinfo in the layerObj. */ layer->layerinfo = (void*)layerinfo; return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerOpen()"); return MS_FAILURE; #endif } /* ** msPostGISLayerClose() ** ** Registered vtable->LayerClose function. */ int msPostGISLayerClose(layerObj *layer) { #ifdef USE_POSTGIS if (layer->debug) { msDebug("msPostGISLayerClose called: %s\n", layer->data); } if( layer->layerinfo ) { msPostGISFreeLayerInfo(layer); } return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerClose()"); return MS_FAILURE; #endif } /* ** msPostGISLayerIsOpen() ** ** Registered vtable->LayerIsOpen function. */ int msPostGISLayerIsOpen(layerObj *layer) { #ifdef USE_POSTGIS if (layer->debug) { msDebug("msPostGISLayerIsOpen called.\n"); } if (layer->layerinfo) return MS_TRUE; else return MS_FALSE; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerIsOpen()"); return MS_FAILURE; #endif } /* ** msPostGISLayerFreeItemInfo() ** ** Registered vtable->LayerFreeItemInfo function. */ void msPostGISLayerFreeItemInfo(layerObj *layer) { #ifdef USE_POSTGIS if (layer->debug) { msDebug("msPostGISLayerFreeItemInfo called.\n"); } if (layer->iteminfo) { free(layer->iteminfo); } layer->iteminfo = NULL; #endif } /* ** msPostGISLayerInitItemInfo() ** ** Registered vtable->LayerInitItemInfo function. ** Our iteminfo is list of indexes from 1..numitems. */ int msPostGISLayerInitItemInfo(layerObj *layer) { #ifdef USE_POSTGIS int i; int *itemindexes ; if (layer->debug) { msDebug("msPostGISLayerInitItemInfo called.\n"); } if (layer->numitems == 0) { return MS_SUCCESS; } if (layer->iteminfo) { free(layer->iteminfo); } layer->iteminfo = msSmallMalloc(sizeof(int) * layer->numitems); if (!layer->iteminfo) { msSetError(MS_MEMERR, "Out of memory.", "msPostGISLayerInitItemInfo()"); return MS_FAILURE; } itemindexes = (int*)layer->iteminfo; for (i = 0; i < layer->numitems; i++) { itemindexes[i] = i; /* Last item is always the geometry. The rest are non-geometry. */ } return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerInitItemInfo()"); return MS_FAILURE; #endif } /* ** msPostGISLayerWhichShapes() ** ** Registered vtable->LayerWhichShapes function. */ int msPostGISLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; char *strSQL = NULL; PGresult *pgresult = NULL; const char** layer_bind_values = NULL; const char* bind_value; char* bind_key = NULL; int num_bind_values = 0; assert(layer != NULL); assert(layer->layerinfo != NULL); if (layer->debug) { msDebug("msPostGISLayerWhichShapes called.\n"); } /* Fill out layerinfo with our current DATA state. */ if ( msPostGISParseData(layer) != MS_SUCCESS) { return MS_FAILURE; } /* try to get the first bind value */ layer_bind_values = (const char**)msSmallMalloc(sizeof(const char*) * 1000); bind_key = (char*)msSmallMalloc(3); bind_value = msLookupHashTable(&layer->bindvals, "1"); while(bind_value != NULL) { /* put the bind value on the stack */ layer_bind_values[num_bind_values] = bind_value; /* increment the counter */ num_bind_values++; /* create a new lookup key */ sprintf(bind_key, "%d", num_bind_values+1); /* get the bind_value */ bind_value = msLookupHashTable(&layer->bindvals, bind_key); } /* ** This comes *after* parsedata, because parsedata fills in ** layer->layerinfo. */ layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Build a SQL query based on our current state. */ strSQL = msPostGISBuildSQL(layer, &rect, NULL, NULL, -1); if ( ! strSQL ) { msSetError(MS_QUERYERR, "Failed to build query SQL.", "msPostGISLayerWhichShapes()"); return MS_FAILURE; } if (layer->debug) { msDebug("msPostGISLayerWhichShapes query: %s\n", strSQL); } // fprintf(stderr, "SQL: %s\n", strSQL); if(num_bind_values > 0) { pgresult = PQexecParams(layerinfo->pgconn, strSQL, num_bind_values, NULL, layer_bind_values, NULL, NULL, RESULTSET_TYPE); } else { pgresult = PQexecParams(layerinfo->pgconn, strSQL,0, NULL, NULL, NULL, NULL, RESULTSET_TYPE); } /* free bind values */ free(bind_key); free(layer_bind_values); if ( layer->debug > 1 ) { msDebug("msPostGISLayerWhichShapes query status: %s (%d)\n", PQresStatus(PQresultStatus(pgresult)), PQresultStatus(pgresult)); } /* Something went wrong. */ if (!pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK) { msDebug("msPostGISLayerWhichShapes(): Error (%s) executing query: %s\n", PQerrorMessage(layerinfo->pgconn), strSQL); msSetError(MS_QUERYERR, "Error executing query. Check server logs","msPostGISLayerWhichShapes()"); free(strSQL); if (pgresult) { PQclear(pgresult); } return MS_FAILURE; } if ( layer->debug ) { msDebug("msPostGISLayerWhichShapes got %d records in result.\n", PQntuples(pgresult)); } /* Clean any existing pgresult before storing current one. */ if(layerinfo->pgresult) PQclear(layerinfo->pgresult); layerinfo->pgresult = pgresult; /* Clean any existing SQL before storing current. */ if(layerinfo->sql) free(layerinfo->sql); layerinfo->sql = strSQL; layerinfo->rownum = 0; return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerWhichShapes()"); return MS_FAILURE; #endif } /* ** msPostGISLayerNextShape() ** ** Registered vtable->LayerNextShape function. */ int msPostGISLayerNextShape(layerObj *layer, shapeObj *shape) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo; if (layer->debug) { msDebug("msPostGISLayerNextShape called.\n"); } assert(layer != NULL); assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo*) layer->layerinfo; shape->type = MS_SHAPE_NULL; /* ** Roll through pgresult until we hit non-null shape (usually right away). */ while (shape->type == MS_SHAPE_NULL) { if (layerinfo->rownum < PQntuples(layerinfo->pgresult)) { /* Retrieve this shape, cursor access mode. */ msPostGISReadShape(layer, shape); if( shape->type != MS_SHAPE_NULL ) { (layerinfo->rownum)++; /* move to next shape */ return MS_SUCCESS; } else { (layerinfo->rownum)++; /* move to next shape */ } } else { return MS_DONE; } } /* Found nothing, clean up and exit. */ msFreeShape(shape); return MS_FAILURE; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerNextShape()"); return MS_FAILURE; #endif } /* ** msPostGISLayerGetShape() ** */ int msPostGISLayerGetShapeCount(layerObj *layer, rectObj rect, projectionObj *rectProjection) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; char *strSQL = NULL; char *strSQLCount = NULL; PGresult *pgresult = NULL; const char** layer_bind_values = NULL; const char* bind_value; char* bind_key = NULL; int num_bind_values = 0; int nCount = 0; int rectSRID = -1; rectObj searchrectInLayerProj = rect; assert(layer != NULL); assert(layer->layerinfo != NULL); if (layer->debug) { msDebug("msPostGISLayerGetShapeCount called.\n"); } #ifdef USE_PROJ // Special processing if the specified projection for the rect is different from the layer projection // We want to issue a WHERE that includes // ((the_geom && rect_reprojected_in_layer_SRID) AND NOT ST_Disjoint(ST_Transform(the_geom, rect_SRID), rect)) if( rectProjection != NULL && layer->project && msProjectionsDiffer(&(layer->projection), rectProjection) ) { // If we cannot guess the EPSG code of the rectProjection, we cannot // use ST_Transform, so fallback on slow implementation if( rectProjection->numargs < 1 || strncasecmp(rectProjection->args[0], "init=epsg:", strlen("init=epsg:")) != 0 ) { if (layer->debug) { msDebug("msPostGISLayerGetShapeCount(): cannot find EPSG code of rectProjection. Falling back on client-side feature count.\n"); } return LayerDefaultGetShapeCount(layer, rect, rectProjection); } // Reproject the passed rect into the layer projection and get // the SRID from the rectProjection msProjectRect(rectProjection, &(layer->projection), &searchrectInLayerProj); /* project the searchrect to source coords */ rectSRID = atoi(rectProjection->args[0] + strlen("init=epsg:")); } #endif msLayerTranslateFilter(layer, &layer->filter, layer->filteritem); /* Fill out layerinfo with our current DATA state. */ if ( msPostGISParseData(layer) != MS_SUCCESS) { return -1; } /* try to get the first bind value */ layer_bind_values = (const char**)msSmallMalloc(sizeof(const char*) * 1000); bind_value = msLookupHashTable(&layer->bindvals, "1"); bind_key = (char*)msSmallMalloc(3); while(bind_value != NULL) { /* put the bind value on the stack */ layer_bind_values[num_bind_values] = bind_value; /* increment the counter */ num_bind_values++; /* create a new lookup key */ sprintf(bind_key, "%d", num_bind_values+1); /* get the bind_value */ bind_value = msLookupHashTable(&layer->bindvals, bind_key); } /* ** This comes *after* parsedata, because parsedata fills in ** layer->layerinfo. */ layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Build a SQL query based on our current state. */ strSQL = msPostGISBuildSQL(layer, &searchrectInLayerProj, NULL, &rect, rectSRID); if ( ! strSQL ) { msSetError(MS_QUERYERR, "Failed to build query SQL.", "msPostGISLayerGetShapeCount()"); return -1; } strSQLCount = NULL; strSQLCount = msStringConcatenate(strSQLCount, "SELECT COUNT(*) FROM ("); strSQLCount = msStringConcatenate(strSQLCount, strSQL); strSQLCount = msStringConcatenate(strSQLCount, ") msQuery"); msFree(strSQL); if (layer->debug) { msDebug("msPostGISLayerGetShapeCount query: %s\n", strSQLCount); } if(num_bind_values > 0) { pgresult = PQexecParams(layerinfo->pgconn, strSQLCount, num_bind_values, NULL, layer_bind_values, NULL, NULL, 1); } else { pgresult = PQexecParams(layerinfo->pgconn, strSQLCount,0, NULL, NULL, NULL, NULL, 0); } /* free bind values */ free(bind_key); free(layer_bind_values); if ( layer->debug > 1 ) { msDebug("msPostGISLayerWhichShapes query status: %s (%d)\n", PQresStatus(PQresultStatus(pgresult)), PQresultStatus(pgresult)); } /* Something went wrong. */ if (!pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK) { msDebug("msPostGISLayerGetShapeCount(): Error (%s) executing query: %s. " "Falling back to client-side evaluation\n", PQerrorMessage(layerinfo->pgconn), strSQLCount); msFree(strSQLCount); if (pgresult) { PQclear(pgresult); } return LayerDefaultGetShapeCount(layer, rect, rectProjection); } msFree(strSQLCount); nCount = atoi(PQgetvalue(pgresult, 0, 0 )); if ( layer->debug ) { msDebug("msPostGISLayerWhichShapes return: %d.\n", nCount); } PQclear(pgresult); return nCount; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetShapeCount()"); return -1; #endif } /* ** msPostGISLayerGetShape() ** ** Registered vtable->LayerGetShape function. For pulling from a prepared and ** undisposed result set. */ int msPostGISLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { #ifdef USE_POSTGIS PGresult *pgresult = NULL; msPostGISLayerInfo *layerinfo = NULL; long shapeindex = record->shapeindex; int resultindex = record->resultindex; assert(layer != NULL); assert(layer->layerinfo != NULL); if (layer->debug) { msDebug("msPostGISLayerGetShape called for record = %i\n", resultindex); } /* If resultindex is set, fetch the shape from the resultcache, otherwise fetch it from the DB */ if (resultindex >= 0) { int status; layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Check the validity of the open result. */ pgresult = layerinfo->pgresult; if ( ! pgresult ) { msSetError( MS_MISCERR, "PostgreSQL result set is null.", "msPostGISLayerGetShape()"); return MS_FAILURE; } status = PQresultStatus(pgresult); if ( layer->debug > 1 ) { msDebug("msPostGISLayerGetShape query status: %s (%d)\n", PQresStatus(status), status); } if( ! ( status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) ) { msSetError( MS_MISCERR, "PostgreSQL result set is not ready.", "msPostGISLayerGetShape()"); return MS_FAILURE; } /* Check the validity of the requested record number. */ if( resultindex >= PQntuples(pgresult) ) { msDebug("msPostGISLayerGetShape got request for (%d) but only has %d tuples.\n", resultindex, PQntuples(pgresult)); msSetError( MS_MISCERR, "Got request larger than result set.", "msPostGISLayerGetShape()"); return MS_FAILURE; } layerinfo->rownum = resultindex; /* Only return one result. */ /* We don't know the shape type until we read the geometry. */ shape->type = MS_SHAPE_NULL; /* Return the shape, cursor access mode. */ msPostGISReadShape(layer, shape); return (shape->type == MS_SHAPE_NULL) ? MS_FAILURE : MS_SUCCESS; } else { /* no resultindex, fetch the shape from the DB */ int num_tuples; char *strSQL = 0; /* Fill out layerinfo with our current DATA state. */ if ( msPostGISParseData(layer) != MS_SUCCESS) { return MS_FAILURE; } /* ** This comes *after* parsedata, because parsedata fills in ** layer->layerinfo. */ layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* Build a SQL query based on our current state. */ strSQL = msPostGISBuildSQL(layer, NULL, &shapeindex, NULL, -1); if ( ! strSQL ) { msSetError(MS_QUERYERR, "Failed to build query SQL.", "msPostGISLayerGetShape()"); return MS_FAILURE; } if (layer->debug) { msDebug("msPostGISLayerGetShape query: %s\n", strSQL); } pgresult = PQexecParams(layerinfo->pgconn, strSQL,0, NULL, NULL, NULL, NULL, RESULTSET_TYPE); /* Something went wrong. */ if ( (!pgresult) || (PQresultStatus(pgresult) != PGRES_TUPLES_OK) ) { msDebug("msPostGISLayerGetShape(): Error (%s) executing SQL: %s\n", PQerrorMessage(layerinfo->pgconn), strSQL ); msSetError(MS_QUERYERR, "Error executing SQL. Check server logs.","msPostGISLayerGetShape()"); if (pgresult) { PQclear(pgresult); } free(strSQL); return MS_FAILURE; } /* Clean any existing pgresult before storing current one. */ if(layerinfo->pgresult) PQclear(layerinfo->pgresult); layerinfo->pgresult = pgresult; /* Clean any existing SQL before storing current. */ if(layerinfo->sql) free(layerinfo->sql); layerinfo->sql = strSQL; layerinfo->rownum = 0; /* Only return one result. */ /* We don't know the shape type until we read the geometry. */ shape->type = MS_SHAPE_NULL; num_tuples = PQntuples(pgresult); if (layer->debug) { msDebug("msPostGISLayerGetShape number of records: %d\n", num_tuples); } if (num_tuples > 0) { /* Get shape in random access mode. */ msPostGISReadShape(layer, shape); } return (shape->type == MS_SHAPE_NULL) ? MS_FAILURE : ( (num_tuples > 0) ? MS_SUCCESS : MS_DONE ); } #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetShape()"); return MS_FAILURE; #endif } /********************************************************************** * msPostGISPassThroughFieldDefinitions() * * Pass the field definitions through to the layer metadata in the * "gml_[item]_{type,width,precision}" set of metadata items for * defining fields. **********************************************************************/ /* These are the OIDs for some builtin types, as returned by PQftype(). */ /* They were copied from pg_type.h in src/include/catalog/pg_type.h */ #ifndef BOOLOID #define BOOLOID 16 #define BYTEAOID 17 #define CHAROID 18 #define NAMEOID 19 #define INT8OID 20 #define INT2OID 21 #define INT2VECTOROID 22 #define INT4OID 23 #define REGPROCOID 24 #define TEXTOID 25 #define OIDOID 26 #define TIDOID 27 #define XIDOID 28 #define CIDOID 29 #define OIDVECTOROID 30 #define FLOAT4OID 700 #define FLOAT8OID 701 #define INT4ARRAYOID 1007 #define TEXTARRAYOID 1009 #define BPCHARARRAYOID 1014 #define VARCHARARRAYOID 1015 #define FLOAT4ARRAYOID 1021 #define FLOAT8ARRAYOID 1022 #define BPCHAROID 1042 #define VARCHAROID 1043 #define DATEOID 1082 #define TIMEOID 1083 #define TIMESTAMPOID 1114 #define TIMESTAMPTZOID 1184 #define NUMERICOID 1700 #endif #ifdef USE_POSTGIS static void msPostGISPassThroughFieldDefinitions( layerObj *layer, PGresult *pgresult ) { int i, numitems = PQnfields(pgresult); msPostGISLayerInfo *layerinfo = layer->layerinfo; for(i=0; igeomcolumn) == 0 ) continue; oid = PQftype(pgresult,i); fmod = PQfmod(pgresult,i); if( (oid == BPCHAROID || oid == VARCHAROID) && fmod >= 4 ) { sprintf( gml_width, "%d", fmod-4 ); } else if( oid == BOOLOID ) { gml_type = "Integer"; sprintf( gml_width, "%d", 1 ); } else if( oid == INT2OID ) { gml_type = "Integer"; sprintf( gml_width, "%d", 5 ); } else if( oid == INT4OID ) { gml_type = "Integer"; } else if( oid == INT8OID ) { gml_type = "Long"; } else if( oid == FLOAT4OID || oid == FLOAT8OID ) { gml_type = "Real"; } else if( oid == NUMERICOID ) { gml_type = "Real"; if( fmod >= 4 && ((fmod - 4) & 0xFFFF) == 0 ) { gml_type = "Integer"; sprintf( gml_width, "%d", (fmod - 4) >> 16 ); } else if( fmod >= 4 ) { sprintf( gml_width, "%d", (fmod - 4) >> 16 ); sprintf( gml_precision, "%d", ((fmod-4) & 0xFFFF) ); } } else if( oid == DATEOID || oid == TIMESTAMPOID || oid == TIMESTAMPTZOID ) { gml_type = "Date"; } snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", item ); if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } } #endif /* defined(USE_POSTGIS) */ /* ** msPostGISLayerGetItems() ** ** Registered vtable->LayerGetItems function. Query the database for ** column information about the requested layer. Rather than look in ** system tables, we just run a zero-cost query and read out of the ** result header. */ int msPostGISLayerGetItems(layerObj *layer) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; static char *strSQLTemplate = "select * from %s where false limit 0"; PGresult *pgresult = NULL; char *col = NULL; char *sql = NULL; char *strFrom = NULL; char found_geom = 0; const char *value; int t, item_num; rectObj rect; /* A useless rectangle for our useless query */ rect.minx = rect.miny = rect.maxx = rect.maxy = 0.0; assert(layer != NULL); assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo*) layer->layerinfo; assert(layerinfo->pgconn); if (layer->debug) { msDebug("msPostGISLayerGetItems called.\n"); } /* Fill out layerinfo with our current DATA state. */ if ( msPostGISParseData(layer) != MS_SUCCESS) { return MS_FAILURE; } layerinfo = (msPostGISLayerInfo*) layer->layerinfo; /* This allocates a fresh string, so remember to free it... */ strFrom = msPostGISReplaceBoxToken(layer, &rect, layerinfo->fromsource); /* ** Both the "table" and "(select ...) as sub" cases can be handled with the ** same SQL. */ sql = (char*) msSmallMalloc(strlen(strSQLTemplate) + strlen(strFrom)); sprintf(sql, strSQLTemplate, strFrom); free(strFrom); if (layer->debug) { msDebug("msPostGISLayerGetItems executing SQL: %s\n", sql); } pgresult = PQexecParams(layerinfo->pgconn, sql,0, NULL, NULL, NULL, NULL, 0); if ( (!pgresult) || (PQresultStatus(pgresult) != PGRES_TUPLES_OK) ) { msDebug("msPostGISLayerGetItems(): Error (%s) executing SQL: %s\n", PQerrorMessage(layerinfo->pgconn), sql); msSetError(MS_QUERYERR, "Error executing SQL. Check server logs","msPostGISLayerGetItems()"); if (pgresult) { PQclear(pgresult); } free(sql); return MS_FAILURE; } free(sql); layer->numitems = PQnfields(pgresult) - 1; /* dont include the geometry column (last entry)*/ layer->items = msSmallMalloc(sizeof(char*) * (layer->numitems + 1)); /* +1 in case there is a problem finding geometry column */ found_geom = 0; /* havent found the geom field */ item_num = 0; for (t = 0; t < PQnfields(pgresult); t++) { col = PQfname(pgresult, t); if ( strcmp(col, layerinfo->geomcolumn) != 0 ) { /* this isnt the geometry column */ layer->items[item_num] = msStrdup(col); item_num++; } else { found_geom = 1; } } /* ** consider populating the field definitions in metadata. */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) msPostGISPassThroughFieldDefinitions( layer, pgresult ); /* ** Cleanup */ PQclear(pgresult); if (!found_geom) { msSetError(MS_QUERYERR, "Tried to find the geometry column in the database, but couldn't find it. Is it mis-capitalized? '%s'", "msPostGISLayerGetItems()", layerinfo->geomcolumn); return MS_FAILURE; } return msPostGISLayerInitItemInfo(layer); #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetItems()"); return MS_FAILURE; #endif } /* ** msPostGISLayerGetExtent() ** ** Registered vtable->LayerGetExtent function. Query the database for ** the extent of the requested layer. */ int msPostGISLayerGetExtent(layerObj *layer, rectObj *extent) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; char *strSQL = NULL; char *strFilter1 = 0, *strFilter2 = 0; char *f_table_name; static char *sqlExtentTemplate = "SELECT ST_Extent(%s) FROM %s"; size_t buffer_len; size_t strFilterLength1 = 0, strFilterLength2 = 0; PGresult *pgresult = NULL; if (layer->debug) { msDebug("msPostGISLayerGetExtent called.\n"); } assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; if ( msPostGISParseData(layer) != MS_SUCCESS) { return MS_FAILURE; } /* if we have !BOX! substitution then we use just the table name */ if ( strstr(layerinfo->fromsource, BOXTOKEN) ) f_table_name = msPostGISFindTableName(layerinfo->fromsource); else f_table_name = msStrdup(layerinfo->fromsource); if ( !f_table_name ) { msSetError(MS_MISCERR, "Failed to get table name.", "msPostGISLayerGetExtent()"); return MS_FAILURE; } /* Handle a translated filter (RFC91). */ if (layer->filter.native_string) { static char *strFilterTemplate = "(%s)"; strFilter1 = (char *)msSmallMalloc(strlen(strFilterTemplate) + strlen(layer->filter.native_string) + 1); sprintf(strFilter1, strFilterTemplate, layer->filter.native_string); strFilterLength1 = strlen(strFilter1) + 7; } /* Handle a native filter set as a PROCESSING option (#5001). */ if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { static char *strFilterTemplate = "(%s)"; char *native_filter = msLayerGetProcessingKey(layer, "NATIVE_FILTER"); strFilter2 = (char *)msSmallMalloc(strlen(strFilterTemplate) + strlen(native_filter) + 1); sprintf(strFilter2, strFilterTemplate, native_filter); strFilterLength2 = strlen(strFilter2) + 7; } buffer_len = strlen(layerinfo->geomcolumn) + strlen(f_table_name) + strlen(sqlExtentTemplate) + strFilterLength1 + strFilterLength2; strSQL = (char*)msSmallMalloc(buffer_len+1); /* add space for terminating NULL */ snprintf(strSQL, buffer_len, sqlExtentTemplate, layerinfo->geomcolumn, f_table_name); msFree(f_table_name); if (strFilter1) { strlcat(strSQL, " where ", buffer_len); strlcat(strSQL, strFilter1, buffer_len); msFree(strFilter1); if (strFilter2) { strlcat(strSQL, " and ", buffer_len); strlcat(strSQL, strFilter2, buffer_len); msFree(strFilter2); } } else if (strFilter2) { strlcat(strSQL, " where ", buffer_len); strlcat(strSQL, strFilter2, buffer_len); msFree(strFilter2); } if (layer->debug) { msDebug("msPostGISLayerGetExtent executing SQL: %s\n", strSQL); } /* executing the query */ pgresult = PQexecParams(layerinfo->pgconn, strSQL,0, NULL, NULL, NULL, NULL, 0); msFree(strSQL); if ( (!pgresult) || (PQresultStatus(pgresult) != PGRES_TUPLES_OK) ) { msDebug("Error executing SQL: (%s) in msPostGISLayerGetExtent()", PQerrorMessage(layerinfo->pgconn)); msSetError(MS_MISCERR, "Error executing SQL. Check server logs.","msPostGISLayerGetExtent()"); if (pgresult) PQclear(pgresult); return MS_FAILURE; } /* process results */ if (PQntuples(pgresult) < 1) { msSetError(MS_MISCERR, "msPostGISLayerGetExtent: No results found.", "msPostGISLayerGetExtent()"); PQclear(pgresult); return MS_FAILURE; } if (PQgetisnull(pgresult, 0, 0)) { msSetError(MS_MISCERR, "msPostGISLayerGetExtent: Null result returned.", "msPostGISLayerGetExtent()"); PQclear(pgresult); return MS_FAILURE; } if (sscanf(PQgetvalue(pgresult, 0, 0), "BOX(%lf %lf,%lf %lf)", &extent->minx, &extent->miny, &extent->maxx, &extent->maxy) != 4) { msSetError(MS_MISCERR, "Failed to process result data.", "msPostGISLayerGetExtent()"); PQclear(pgresult); return MS_FAILURE; } /* cleanup */ PQclear(pgresult); return MS_SUCCESS; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetExtent()"); return MS_FAILURE; #endif } /* ** msPostGISLayerGetNumFeatures() ** ** Registered vtable->LayerGetNumFeatures function. Query the database for ** the feature count of the requested layer. */ int msPostGISLayerGetNumFeatures(layerObj *layer) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; char *strSQL = NULL; char *strFilter1 = 0, *strFilter2 = 0; char *f_table_name; static char *sqlNumFeaturesTemplate = "SELECT count(*) FROM %s"; size_t buffer_len; size_t strFilterLength1 = 0, strFilterLength2 = 0; PGresult *pgresult = NULL; int result; char *tmp; if (layer->debug) { msDebug("msPostGISLayerGetNumFeatures called.\n"); } assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; if (msPostGISParseData(layer) != MS_SUCCESS) { return -1; } /* if we have !BOX! substitution then we use just the table name */ if (strstr(layerinfo->fromsource, BOXTOKEN)) f_table_name = msPostGISFindTableName(layerinfo->fromsource); else f_table_name = msStrdup(layerinfo->fromsource); if (!f_table_name) { msSetError(MS_MISCERR, "Failed to get table name.", "msPostGISLayerGetExtent()"); return -1; } /* Handle a translated filter (RFC91). */ if (layer->filter.native_string) { static char *strFilterTemplate = "(%s)"; strFilter1 = (char *)msSmallMalloc(strlen(strFilterTemplate) + strlen(layer->filter.native_string) + 1); sprintf(strFilter1, strFilterTemplate, layer->filter.native_string); strFilterLength1 = strlen(strFilter1) + 7; } /* Handle a native filter set as a PROCESSING option (#5001). */ if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) { static char *strFilterTemplate = "(%s)"; char *native_filter = msLayerGetProcessingKey(layer, "NATIVE_FILTER"); strFilter2 = (char *)msSmallMalloc(strlen(strFilterTemplate) + strlen(native_filter) + 1); sprintf(strFilter2, strFilterTemplate, native_filter); strFilterLength2 = strlen(strFilter2) + 7; } buffer_len = strlen(f_table_name) + strlen(sqlNumFeaturesTemplate) + strFilterLength1 + strFilterLength2; strSQL = (char*)msSmallMalloc(buffer_len + 1); /* add space for terminating NULL */ snprintf(strSQL, buffer_len, sqlNumFeaturesTemplate, f_table_name); msFree(f_table_name); if (strFilter1) { strlcat(strSQL, " where ", buffer_len); strlcat(strSQL, strFilter1, buffer_len); msFree(strFilter1); if (strFilter2) { strlcat(strSQL, " and ", buffer_len); strlcat(strSQL, strFilter2, buffer_len); msFree(strFilter2); } } else if (strFilter2) { strlcat(strSQL, " where ", buffer_len); strlcat(strSQL, strFilter2, buffer_len); msFree(strFilter2); } if (layer->debug) { msDebug("msPostGISLayerGetNumFeatures executing SQL: %s\n", strSQL); } /* executing the query */ pgresult = PQexecParams(layerinfo->pgconn, strSQL, 0, NULL, NULL, NULL, NULL, 0); msFree(strSQL); if ((!pgresult) || (PQresultStatus(pgresult) != PGRES_TUPLES_OK)) { msDebug("Error executing SQL: (%s) in msPostGISLayerGetNumFeatures()", PQerrorMessage(layerinfo->pgconn)); msSetError(MS_MISCERR, "Error executing SQL. Check server logs.", "msPostGISLayerGetNumFeatures()"); if (pgresult) PQclear(pgresult); return -1; } /* process results */ if (PQntuples(pgresult) < 1) { msSetError(MS_MISCERR, "msPostGISLayerGetNumFeatures: No results found.", "msPostGISLayerGetNumFeatures()"); PQclear(pgresult); return -1; } if (PQgetisnull(pgresult, 0, 0)) { msSetError(MS_MISCERR, "msPostGISLayerGetNumFeatures: Null result returned.", "msPostGISLayerGetNumFeatures()"); PQclear(pgresult); return -1; } tmp = PQgetvalue(pgresult, 0, 0); if (tmp) { result = strtol(tmp, NULL, 10); } else { result = 0; } /* cleanup */ PQclear(pgresult); return result; #else msSetError(MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerGetNumFeatures()"); return -1; #endif } /* * make sure that the timestring is complete and acceptable * to the date_trunc function : * - if the resolution is year (2004) or month (2004-01), * a complete string for time would be 2004-01-01 * - if the resolluion is hour or minute (2004-01-01 15), a * complete time is 2004-01-01 15:00:00 */ int postgresTimeStampForTimeString(const char *timestring, char *dest, size_t destsize) { int nlength = strlen(timestring); int timeresolution = msTimeGetResolution(timestring); int bNoDate = (*timestring == 'T'); if (timeresolution < 0) return MS_FALSE; switch(timeresolution) { case TIME_RESOLUTION_YEAR: if (timestring[nlength-1] != '-') { snprintf(dest, destsize,"date '%s-01-01'",timestring); } else { snprintf(dest, destsize,"date '%s01-01'",timestring); } break; case TIME_RESOLUTION_MONTH: if (timestring[nlength-1] != '-') { snprintf(dest, destsize,"date '%s-01'",timestring); } else { snprintf(dest, destsize,"date '%s01'",timestring); } break; case TIME_RESOLUTION_DAY: snprintf(dest, destsize,"date '%s'",timestring); break; case TIME_RESOLUTION_HOUR: if (timestring[nlength-1] != ':') { if(bNoDate) snprintf(dest, destsize,"time '%s:00:00'", timestring); else snprintf(dest, destsize,"timestamp '%s:00:00'", timestring); } else { if(bNoDate) snprintf(dest, destsize,"time '%s00:00'", timestring); else snprintf(dest, destsize,"timestamp '%s00:00'", timestring); } break; case TIME_RESOLUTION_MINUTE: if (timestring[nlength-1] != ':') { if(bNoDate) snprintf(dest, destsize,"time '%s:00'", timestring); else snprintf(dest, destsize,"timestamp '%s:00'", timestring); } else { if(bNoDate) snprintf(dest, destsize,"time '%s00'", timestring); else snprintf(dest, destsize,"timestamp '%s00'", timestring); } break; case TIME_RESOLUTION_SECOND: if(bNoDate) snprintf(dest, destsize,"time '%s'", timestring); else snprintf(dest, destsize,"timestamp '%s'", timestring); break; default: return MS_FAILURE; } return MS_SUCCESS; } /* * create a postgresql where clause for the given timestring, taking into account * the resolution (e.g. second, day, month...) of the given timestring * we apply the date_trunc function on the given timestring and not on the time * column in order for postgres to take advantage of an eventual index on the * time column * * the generated sql is * * ( * timecol >= date_trunc(timestring,resolution) * and * timecol < date_trunc(timestring,resolution) + interval '1 resolution' * ) */ int createPostgresTimeCompareEquals(const char *timestring, char *dest, size_t destsize) { int timeresolution = msTimeGetResolution(timestring); char timeStamp[100]; char *interval; if (timeresolution < 0) return MS_FALSE; postgresTimeStampForTimeString(timestring,timeStamp,100); switch(timeresolution) { case TIME_RESOLUTION_YEAR: interval = "year"; break; case TIME_RESOLUTION_MONTH: interval = "month"; break; case TIME_RESOLUTION_DAY: interval = "day"; break; case TIME_RESOLUTION_HOUR: interval = "hour"; break; case TIME_RESOLUTION_MINUTE: interval = "minute"; break; case TIME_RESOLUTION_SECOND: interval = "second"; break; default: return MS_FAILURE; } snprintf(dest, destsize, " between date_trunc('%s',%s) and date_trunc('%s',%s) + interval '1 %s' - interval '1 second'", interval, timeStamp, interval, timeStamp, interval); return MS_SUCCESS; } int createPostgresTimeCompareGreaterThan(const char *timestring, char *dest, size_t destsize) { int timeresolution = msTimeGetResolution(timestring); char timestamp[100]; char *interval; if (timeresolution < 0) return MS_FALSE; postgresTimeStampForTimeString(timestring,timestamp,100); switch(timeresolution) { case TIME_RESOLUTION_YEAR: interval = "year"; break; case TIME_RESOLUTION_MONTH: interval = "month"; break; case TIME_RESOLUTION_DAY: interval = "day"; break; case TIME_RESOLUTION_HOUR: interval = "hour"; break; case TIME_RESOLUTION_MINUTE: interval = "minute"; break; case TIME_RESOLUTION_SECOND: interval = "second"; break; default: return MS_FAILURE; } snprintf(dest, destsize,"date_trunc('%s',%s)", interval, timestamp); return MS_SUCCESS; } /* * create a postgresql where clause for the range given by the two input timestring, * taking into account the resolution (e.g. second, day, month...) of each of the * given timestrings (both timestrings can have different resolutions, although I don't * know if that's a valid TIME range * we apply the date_trunc function on the given timestrings and not on the time * column in order for postgres to take advantage of an eventual index on the * time column * * the generated sql is * * ( * timecol >= date_trunc(mintimestring,minresolution) * and * timecol < date_trunc(maxtimestring,maxresolution) + interval '1 maxresolution' * ) */ int createPostgresTimeCompareLessThan(const char *timestring, char *dest, size_t destsize) { int timeresolution = msTimeGetResolution(timestring); char timestamp[100]; char *interval; if (timeresolution < 0)return MS_FALSE; postgresTimeStampForTimeString(timestring,timestamp,100); switch(timeresolution) { case TIME_RESOLUTION_YEAR: interval = "year"; break; case TIME_RESOLUTION_MONTH: interval = "month"; break; case TIME_RESOLUTION_DAY: interval = "day"; break; case TIME_RESOLUTION_HOUR: interval = "hour"; break; case TIME_RESOLUTION_MINUTE: interval = "minute"; break; case TIME_RESOLUTION_SECOND: interval = "second"; break; default: return MS_FAILURE; } snprintf(dest, destsize,"(date_trunc('%s',%s) + interval '1 %s' - interval '1 second')", interval, timestamp, interval); return MS_SUCCESS; } char *msPostGISEscapeSQLParam(layerObj *layer, const char *pszString) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; int nError; size_t nSrcLen; char* pszEscapedStr =NULL; if (layer && pszString) { if(!msPostGISLayerIsOpen(layer)) msPostGISLayerOpen(layer); assert(layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *) layer->layerinfo; nSrcLen = strlen(pszString); pszEscapedStr = (char*) msSmallMalloc( 2 * nSrcLen + 1); PQescapeStringConn (layerinfo->pgconn, pszEscapedStr, pszString, nSrcLen, &nError); if (nError != 0) { free(pszEscapedStr); pszEscapedStr = NULL; } } return pszEscapedStr; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISEscapeSQLParam()"); return NULL; #endif } void msPostGISEnablePaging(layerObj *layer, int value) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; if (layer->debug) { msDebug("msPostGISEnablePaging called.\n"); } if(!msPostGISLayerIsOpen(layer)) msPostGISLayerOpen(layer); assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; layerinfo->paging = value; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISEnablePaging()"); #endif return; } int msPostGISGetPaging(layerObj *layer) { #ifdef USE_POSTGIS msPostGISLayerInfo *layerinfo = NULL; if (layer->debug) { msDebug("msPostGISGetPaging called.\n"); } if(!msPostGISLayerIsOpen(layer)) return MS_TRUE; assert( layer->layerinfo != NULL); layerinfo = (msPostGISLayerInfo *)layer->layerinfo; return layerinfo->paging; #else msSetError( MS_MISCERR, "PostGIS support is not available.", "msPostGISEnablePaging()"); return MS_FAILURE; #endif } /* ** Look ahead to find the next node of a specific type. */ tokenListNodeObjPtr findNextTokenByType(tokenListNodeObjPtr node, int type) { while (node != NULL) { if(node->token == type) return node; node = node->next; /* keep looking */ } return NULL; /* not found */ } /* ** msPostGISLayerTranslateFilter() ** ** Registered vtable->LayerTranslateFilter function. */ int msPostGISLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem) { #ifdef USE_POSTGIS tokenListNodeObjPtr node = NULL; char *snippet = NULL; char *native_string = NULL; char *strtmpl = NULL; char *stresc = NULL; int comparisonToken = -1; int bindingToken = -1; msPostGISLayerInfo *layerinfo = layer->layerinfo; if(!filter->string) return MS_SUCCESS; /* not an error, just nothing to do */ // fprintf(stderr, "input: %s, %s, %d\n", filter->string, filteritem, filter->type); /* ** FILTERs use MapServer syntax *only* (#5001). */ if(filter->type == MS_STRING && filter->string && filteritem) { /* item/value pair - add escaping */ stresc = msLayerEscapePropertyName(layer, filteritem); if(filter->flags & MS_EXP_INSENSITIVE) { native_string = msStringConcatenate(native_string, "upper("); native_string = msStringConcatenate(native_string, stresc); native_string = msStringConcatenate(native_string, "::text) = upper("); } else { native_string = msStringConcatenate(native_string, stresc); native_string = msStringConcatenate(native_string, "::text = "); } msFree(stresc); strtmpl = "'%s'"; /* don't have a type for the righthand literal so assume it's a string and we quote */ stresc = msPostGISEscapeSQLParam(layer, filter->string); snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); sprintf(snippet, strtmpl, stresc); native_string = msStringConcatenate(native_string, snippet); msFree(snippet); msFree(stresc); if(filter->flags & MS_EXP_INSENSITIVE) native_string = msStringConcatenate(native_string, ")"); } else if(filter->type == MS_REGEX && filter->string && filteritem) { /* item/regex pair - add escaping */ stresc = msLayerEscapePropertyName(layer, filteritem); native_string = msStringConcatenate(native_string, stresc); if(filter->flags & MS_EXP_INSENSITIVE) { native_string = msStringConcatenate(native_string, "::text ~* "); } else { native_string = msStringConcatenate(native_string, "::text ~ "); } msFree(stresc); strtmpl = "'%s'"; stresc = msPostGISEscapeSQLParam(layer, filter->string); snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); sprintf(snippet, strtmpl, stresc); native_string = msStringConcatenate(native_string, snippet); msFree(snippet); msFree(stresc); } else if(filter->type == MS_EXPRESSION) { int ieq_expected = MS_FALSE; if(msPostGISParseData(layer) != MS_SUCCESS) return MS_FAILURE; if(layer->debug >= 2) msDebug("msPostGISLayerTranslateFilter. String: %s.\n", filter->string); if(!filter->tokens) return MS_SUCCESS; if(layer->debug >= 2) msDebug("msPostGISLayerTranslateFilter. There are tokens to process... \n"); node = filter->tokens; while (node != NULL) { /* ** Do any token caching/tracking here, easier to have it in one place. */ if(node->token == MS_TOKEN_BINDING_TIME) { bindingToken = node->token; } else if(node->token == MS_TOKEN_COMPARISON_EQ || node->token == MS_TOKEN_COMPARISON_IEQ || node->token == MS_TOKEN_COMPARISON_NE || node->token == MS_TOKEN_COMPARISON_GT || node->token == MS_TOKEN_COMPARISON_GE || node->token == MS_TOKEN_COMPARISON_LT || node->token == MS_TOKEN_COMPARISON_LE || node->token == MS_TOKEN_COMPARISON_IN) { comparisonToken = node->token; } switch(node->token) { /* literal tokens */ case MS_TOKEN_LITERAL_BOOLEAN: if(node->tokenval.dblval == MS_TRUE) native_string = msStringConcatenate(native_string, "TRUE"); else native_string = msStringConcatenate(native_string, "FALSE"); break; case MS_TOKEN_LITERAL_NUMBER: snippet = (char *) msSmallMalloc(32); if( node->tokenval.dblval >= INT_MIN && node->tokenval.dblval <= INT_MAX && node->tokenval.dblval == (int)node->tokenval.dblval ) sprintf(snippet, "%d", (int)node->tokenval.dblval); else sprintf(snippet, "%.18g", node->tokenval.dblval); native_string = msStringConcatenate(native_string, snippet); msFree(snippet); break; case MS_TOKEN_LITERAL_STRING: if(comparisonToken == MS_TOKEN_COMPARISON_IN) { /* issue 5490 */ char **strings=NULL; int i, nstrings=0; strings = msStringSplit(node->tokenval.strval, ',', &nstrings); if(nstrings > 0) { native_string = msStringConcatenate(native_string, "("); for(i=0; itokenval.strval); snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); sprintf(snippet, strtmpl, stresc); native_string = msStringConcatenate(native_string, snippet); msFree(snippet); msFree(stresc); } break; case MS_TOKEN_LITERAL_TIME: { snippet = (char *) msSmallMalloc(512); if(comparisonToken == MS_TOKEN_COMPARISON_EQ) { // TODO: support != createPostgresTimeCompareEquals(node->tokensrc, snippet, 512); } else if(comparisonToken == MS_TOKEN_COMPARISON_GT || comparisonToken == MS_TOKEN_COMPARISON_GE) { createPostgresTimeCompareGreaterThan(node->tokensrc, snippet, 512); } else if(comparisonToken == MS_TOKEN_COMPARISON_LT || comparisonToken == MS_TOKEN_COMPARISON_LE) { createPostgresTimeCompareLessThan(node->tokensrc, snippet, 512); } else { goto cleanup; } comparisonToken = -1; bindingToken = -1; /* reset */ native_string = msStringConcatenate(native_string, snippet); msFree(snippet); break; } case MS_TOKEN_LITERAL_SHAPE: { char* wkt = msShapeToWKT(node->tokenval.shpval); native_string = msStringConcatenate(native_string, "ST_GeomFromText('"); native_string = msStringConcatenate(native_string, wkt); msFree(wkt); native_string = msStringConcatenate(native_string, "'"); if(layerinfo->srid && strcmp(layerinfo->srid, "") != 0) { native_string = msStringConcatenate(native_string, ","); native_string = msStringConcatenate(native_string, layerinfo->srid); } native_string = msStringConcatenate(native_string, ")"); break; } /* data binding tokens */ case MS_TOKEN_BINDING_TIME: case MS_TOKEN_BINDING_DOUBLE: case MS_TOKEN_BINDING_INTEGER: case MS_TOKEN_BINDING_STRING: if (node->token == MS_TOKEN_BINDING_STRING && node->next->token == MS_TOKEN_COMPARISON_IEQ ) { strtmpl = "lower(%s::text)"; ieq_expected = MS_TRUE; } else if(node->token == MS_TOKEN_BINDING_STRING || node->next->token == MS_TOKEN_COMPARISON_RE || node->next->token == MS_TOKEN_COMPARISON_IRE) strtmpl = "%s::text"; /* explicit cast necessary for certain operators */ else strtmpl = "%s"; stresc = msLayerEscapePropertyName(layer, node->tokenval.bindval.item); snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc)); sprintf(snippet, strtmpl, stresc); native_string = msStringConcatenate(native_string, snippet); msFree(snippet); msFree(stresc); break; case MS_TOKEN_BINDING_SHAPE: native_string = msStringConcatenate(native_string, layerinfo->geomcolumn); break; case MS_TOKEN_BINDING_MAP_CELLSIZE: strtmpl = "%lf"; snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16); sprintf(snippet, strtmpl, layer->map->cellsize); native_string = msStringConcatenate(native_string, snippet); msFree(snippet); break; /* spatial comparison tokens */ case MS_TOKEN_COMPARISON_INTERSECTS: case MS_TOKEN_COMPARISON_DISJOINT: case MS_TOKEN_COMPARISON_TOUCHES: case MS_TOKEN_COMPARISON_OVERLAPS: case MS_TOKEN_COMPARISON_CROSSES: case MS_TOKEN_COMPARISON_WITHIN: case MS_TOKEN_COMPARISON_CONTAINS: case MS_TOKEN_COMPARISON_EQUALS: case MS_TOKEN_COMPARISON_DWITHIN: if(node->next->token != '(') goto cleanup; native_string = msStringConcatenate(native_string, "st_"); native_string = msStringConcatenate(native_string, msExpressionTokenToString(node->token)); break; /* functions */ case MS_TOKEN_FUNCTION_LENGTH: case MS_TOKEN_FUNCTION_AREA: case MS_TOKEN_FUNCTION_BUFFER: case MS_TOKEN_FUNCTION_DIFFERENCE: native_string = msStringConcatenate(native_string, "st_"); native_string = msStringConcatenate(native_string, msExpressionTokenToString(node->token)); break; case MS_TOKEN_COMPARISON_IEQ: if( ieq_expected ) { native_string = msStringConcatenate(native_string, "="); ieq_expected = MS_FALSE; } else { goto cleanup; } break; /* unsupported tokens */ case MS_TOKEN_COMPARISON_BEYOND: case MS_TOKEN_FUNCTION_TOSTRING: case MS_TOKEN_FUNCTION_ROUND: case MS_TOKEN_FUNCTION_SIMPLIFY: case MS_TOKEN_FUNCTION_SIMPLIFYPT: case MS_TOKEN_FUNCTION_GENERALIZE: goto cleanup; break; default: /* by default accept the general token to string conversion */ if(node->token == MS_TOKEN_COMPARISON_EQ && node->next != NULL && node->next->token == MS_TOKEN_LITERAL_TIME) break; /* skip, handled with the next token */ if(bindingToken == MS_TOKEN_BINDING_TIME && (node->token == MS_TOKEN_COMPARISON_EQ || node->token == MS_TOKEN_COMPARISON_NE)) break; /* skip, handled elsewhere */ if(node->token == MS_TOKEN_COMPARISON_EQ && node->next != NULL && node->next->token == MS_TOKEN_LITERAL_STRING && strcmp(node->next->tokenval.strval, "_MAPSERVER_NULL_") == 0 ) { native_string = msStringConcatenate(native_string, " IS NULL"); node = node->next; break; } native_string = msStringConcatenate(native_string, msExpressionTokenToString(node->token)); break; } node = node->next; } } filter->native_string = msStrdup(native_string); msFree(native_string); // fprintf(stderr, "output: %s\n", filter->native_string); return MS_SUCCESS; cleanup: msSetError(MS_MISCERR, "Translation to native SQL failed.", "msPostGISLayerTranslateFilter()"); msFree(native_string); return MS_FAILURE; #else msSetError(MS_MISCERR, "PostGIS support is not available.", "msPostGISLayerTranslateFilter()"); return MS_FAILURE; #endif } int msPostGISLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerTranslateFilter = msPostGISLayerTranslateFilter; layer->vtable->LayerInitItemInfo = msPostGISLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msPostGISLayerFreeItemInfo; layer->vtable->LayerOpen = msPostGISLayerOpen; layer->vtable->LayerIsOpen = msPostGISLayerIsOpen; layer->vtable->LayerWhichShapes = msPostGISLayerWhichShapes; layer->vtable->LayerNextShape = msPostGISLayerNextShape; layer->vtable->LayerGetShape = msPostGISLayerGetShape; layer->vtable->LayerGetShapeCount = msPostGISLayerGetShapeCount; layer->vtable->LayerClose = msPostGISLayerClose; layer->vtable->LayerGetItems = msPostGISLayerGetItems; layer->vtable->LayerGetExtent = msPostGISLayerGetExtent; layer->vtable->LayerApplyFilterToLayer = msLayerApplyCondSQLFilterToLayer; /* layer->vtable->LayerGetAutoStyle, not supported for this layer */ /* layer->vtable->LayerCloseConnection = msPostGISLayerClose; */ // layer->vtable->LayerSetTimeFilter = msPostGISLayerSetTimeFilter; layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerCreateItems, use default */ layer->vtable->LayerGetNumFeatures = msPostGISLayerGetNumFeatures; /* layer->vtable->LayerGetAutoProjection, use defaut*/ layer->vtable->LayerEscapeSQLParam = msPostGISEscapeSQLParam; layer->vtable->LayerEnablePaging = msPostGISEnablePaging; layer->vtable->LayerGetPaging = msPostGISGetPaging; return MS_SUCCESS; } mapserver-7.4.3/mappostgis.h000066400000000000000000000122331357574274700161160ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: PostGIS CONNECTIONTYPE support. * Author: Paul Ramsey * Dave Blasby * ****************************************************************************** * Copyright (c) 2010 Paul Ramsey * Copyright (c) 2002 Refractions Research * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifdef USE_POSTGIS #include "libpq-fe.h" #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN 1 #endif #ifndef BIG_ENDIAN #define BIG_ENDIAN 2 #endif /* HEX = 16, BASE64 = 64, RAW = 256*/ #define TRANSFER_ENCODING 256 /* Substitution token for box hackery */ #define BOXTOKEN "!BOX!" #define BOXTOKENLENGTH 5 /* ** msPostGISLayerInfo ** ** Specific information needed for managing this layer. */ typedef struct { char *sql; /* SQL query to send to database */ PGconn *pgconn; /* Connection to database */ long rownum; /* What row is the next to be read (for random access) */ PGresult *pgresult; /* For fetching rows from the database */ char *uid; /* Name of user-specified unique identifier, if set */ char *srid; /* Name of user-specified SRID: zero-length => calculate; non-zero => use this value! */ char *geomcolumn; /* Specified geometry column, eg "THEGEOM from thetable" */ char *fromsource; /* Specified record source, ed "thegeom from THETABLE" or "thegeom from (SELECT..) AS FOO" */ int endian; /* Endianness of the mapserver host */ int version; /* PostGIS version of the database */ int paging; /* Driver handling of pagination, enabled by default */ int force2d; /* Pass geometry through ST_Force2D */ } msPostGISLayerInfo; /* ** Utility structure for handling the WKB returned by the database while ** reading. */ typedef struct { char *wkb; /* Pointer to front of WKB */ char *ptr; /* Pointer to current write point */ size_t size; /* Size of allocated space */ int *typemap; /* Look-up array to valid OGC types */ } wkbObj; /* ** Utility structure used when building up stroked lines while ** handling curved feature types. */ typedef struct { pointObj *data; /* Re-sizeable point buffer */ int npoints; /* How many points are we currently storing */ int maxpoints; /* How big is our point buffer */ } pointArrayObj; /* ** All the WKB type numbers from the OGC */ typedef enum { WKB_POINT=1, WKB_LINESTRING=2, WKB_POLYGON=3, WKB_MULTIPOINT=4, WKB_MULTILINESTRING=5, WKB_MULTIPOLYGON=6, WKB_GEOMETRYCOLLECTION=7, WKB_CIRCULARSTRING=8, WKB_COMPOUNDCURVE=9, WKB_CURVEPOLYGON=10, WKB_MULTICURVE=11, WKB_MULTISURFACE=12 } wkb_typenum; /* ** See below. */ #define WKB_TYPE_COUNT 16 /* ** Map the WKB type numbers returned by PostGIS < 2.0 to the ** valid OGC numbers */ static int wkb_postgis15[WKB_TYPE_COUNT] = { 0, WKB_POINT, WKB_LINESTRING, WKB_POLYGON, WKB_MULTIPOINT, WKB_MULTILINESTRING, WKB_MULTIPOLYGON, WKB_GEOMETRYCOLLECTION, WKB_CIRCULARSTRING, WKB_COMPOUNDCURVE, 0,0,0, WKB_CURVEPOLYGON, WKB_MULTICURVE, WKB_MULTISURFACE }; /* ** Map the WKB type numbers returned by PostGIS >= 2.0 to the ** valid OGC numbers */ static int wkb_postgis20[WKB_TYPE_COUNT] = { 0, WKB_POINT, WKB_LINESTRING, WKB_POLYGON, WKB_MULTIPOINT, WKB_MULTILINESTRING, WKB_MULTIPOLYGON, WKB_GEOMETRYCOLLECTION, WKB_CIRCULARSTRING, WKB_COMPOUNDCURVE, WKB_CURVEPOLYGON, WKB_MULTICURVE, WKB_MULTISURFACE, 0,0,0 }; /* ** Prototypes */ void msPostGISFreeLayerInfo(layerObj *layer); msPostGISLayerInfo *msPostGISCreateLayerInfo(void); char *msPostGISBuildSQL(layerObj *layer, rectObj *rect, long *uid, rectObj *rectInOtherSRID, int rectOtherSRID); int msPostGISParseData(layerObj *layer); int arcStrokeCircularString(wkbObj *w, double segment_angle, lineObj *line, int pnZMFlag); int wkbConvGeometryToShape(wkbObj *w, shapeObj *shape); pointArrayObj* pointArrayNew(int maxpoints); void pointArrayFree(pointArrayObj *d); #endif /* USE_POSTGIS */ mapserver-7.4.3/mappostgresql.c000066400000000000000000000344031357574274700166270ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Postgres CONNECTIONTYPE support. * Author: Mark Leslie, Refractions Research * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* $Id$ */ #include #include "mapserver.h" #include "maptime.h" #ifndef FLT_MAX #define FLT_MAX 25000000.0 #endif #ifdef USE_POSTGIS #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN 1 #endif #ifndef BIG_ENDIAN #define BIG_ENDIAN 2 #endif #include "libpq-fe.h" #include #include /* tolower() */ typedef struct { PGconn *conn; /* connection to db */ long row_num; /* what row is the NEXT to be read (for random access) */ PGresult *query_result; /* for fetching rows from the db */ int from_index; char *to_column; char *from_value; int layer_debug; /* there's no debug on the join, so use the layer */ } msPOSTGRESQLJoinInfo; /************************************************************************/ /* msPOSTGRESQLJoinConnect() */ /* */ /* Creates and populates the joininfo struct, including establishing */ /* a connection to the database. Since the join and layer won't always */ /* share connection details, there is currently no mechanism to use */ /* pooled connections with joins. */ /************************************************************************/ int msPOSTGRESQLJoinConnect(layerObj *layer, joinObj *join) { char *maskeddata, *temp, *sql, *column; char *conn_decrypted; int i, test; PGresult *query_result; msPOSTGRESQLJoinInfo *joininfo; if(join->joininfo) return MS_SUCCESS; joininfo = (msPOSTGRESQLJoinInfo *)malloc(sizeof(msPOSTGRESQLJoinInfo)); if(!joininfo) { msSetError(MS_MEMERR, "Error allocating join info struct.", "msPOSTGRESQLJoinConnect()"); return MS_FAILURE; } joininfo->conn = NULL; joininfo->row_num = 0; joininfo->query_result = NULL; joininfo->from_index = 0; joininfo->to_column = join->to; joininfo->from_value = NULL; joininfo->layer_debug = layer->debug; join->joininfo = joininfo; /* * We need three things at a minimum, the connection string, a table * name, and a column to join on. */ if(!join->connection) { msSetError(MS_QUERYERR, "No connection information provided.", "MSPOSTGRESQLJoinConnect()"); return MS_FAILURE; } if(!join->table) { msSetError(MS_QUERYERR, "No join table name found.", "msPOSTGRESQLJoinConnect()"); return MS_FAILURE; } if(!joininfo->to_column) { msSetError(MS_QUERYERR, "No join to column name found.", "msPOSTGRESQLJoinConnect()"); return MS_FAILURE; } /* Establish database connection */ conn_decrypted = msDecryptStringTokens(layer->map, join->connection); if (conn_decrypted != NULL) { joininfo->conn = PQconnectdb(conn_decrypted); free(conn_decrypted); } if(!joininfo->conn || PQstatus(joininfo->conn) == CONNECTION_BAD) { maskeddata = (char *)malloc(strlen(layer->connection) + 1); strcpy(maskeddata, join->connection); temp = strstr(maskeddata, "password="); if(temp) { temp = (char *)(temp + 9); while (*temp != '\0' && *temp != ' ') { *temp = '*'; temp++; } } msSetError(MS_QUERYERR, "Unable to connect to PostgreSQL using the string %s.\n Error reported: %s\n", "msPOSTGRESQLJoinConnect()", maskeddata, PQerrorMessage(joininfo->conn)); free(maskeddata); if(!joininfo->conn) { free(joininfo->conn); } free(joininfo); join->joininfo = NULL; return MS_FAILURE; } /* Determine the number and names of columns in the join table. */ sql = (char *)malloc(36 + strlen(join->table) + 1); sprintf(sql, "SELECT * FROM %s WHERE false LIMIT 0", join->table); if(joininfo->layer_debug) { msDebug("msPOSTGRESQLJoinConnect(): executing %s.\n", sql); } query_result = PQexec(joininfo->conn, sql); if(!query_result || PQresultStatus(query_result) != PGRES_TUPLES_OK) { msSetError(MS_QUERYERR, "Error determining join items: %s.", "msPOSTGRESQLJoinConnect()", PQerrorMessage(joininfo->conn)); if(query_result) { PQclear(query_result); query_result = NULL; } free(sql); return MS_FAILURE; } free(sql); join->numitems = PQnfields(query_result); join->items = malloc(sizeof(char *) * (join->numitems)); /* We want the join-to column to be first in the list. */ test = 1; for(i = 0; i < join->numitems; i++) { column = PQfname(query_result, i); if(strcmp(column, joininfo->to_column) != 0) { join->items[i + test] = (char *)malloc(strlen(column) + 1); strcpy(join->items[i + test], column); } else { test = 0; join->items[0] = (char *)malloc(strlen(column) + 1); strcpy(join->items[0], column); } } PQclear(query_result); query_result = NULL; if(test == 1) { msSetError(MS_QUERYERR, "Unable to find join to column: %s", "msPOSTGRESQLJoinConnect()", joininfo->to_column); return MS_FAILURE; } if(joininfo->layer_debug) { for(i = 0; i < join->numitems; i++) { msDebug("msPOSTGRESQLJoinConnect(): Column %d named %s\n", i, join->items[i]); } } /* Determine the index of the join from column. */ for(i = 0; i < layer->numitems; i++) { if(strcasecmp(layer->items[i], join->from) == 0) { joininfo->from_index = i; break; } } if(i == layer->numitems) { msSetError(MS_JOINERR, "Item %s not found in layer %s.", "msPOSTGRESQLJoinConnect()", join->from, layer->name); return MS_FAILURE; } return MS_SUCCESS; } /************************************************************************/ /* */ /* msPOSTGRESQLJoinPrepare() */ /* Sets up the joininfo to be ready to join against the given shape. */ /* There's not much involved here, just freeing previous results and */ /* resources, and setting the next value to join to. */ /************************************************************************/ int msPOSTGRESQLJoinPrepare(joinObj *join, shapeObj *shape) { /* We need a connection, and a shape with values to join to. */ msPOSTGRESQLJoinInfo *joininfo = join->joininfo; if(!joininfo) { msSetError(MS_JOINERR, "Join has not been connected.", "msPOSTGRESQLJoinPrepare()"); return MS_FAILURE; } if(!shape) { msSetError(MS_JOINERR, "Null shape provided for join.", "msPOSTGRESQLJoinPrepare()"); return MS_FAILURE; } if(!shape->values) { msSetError(MS_JOINERR, "Shape has no attributes. Kinda hard to join against.", "msPOSTGRESQLJoinPrepare()"); return MS_FAILURE; } joininfo->row_num = 0; /* Free the previous join value, if any. */ if(joininfo->from_value) { free(joininfo->from_value); } /* Free the previous results, if any. */ if(joininfo->query_result) { PQclear(joininfo->query_result); joininfo->query_result = NULL; } /* Copy the next join value from the shape. */ joininfo->from_value = msStrdup(shape->values[joininfo->from_index]); if(joininfo->layer_debug) { msDebug("msPOSTGRESQLJoinPrepare() preping for value %s.\n", joininfo->from_value); } return MS_SUCCESS; } /************************************************************************/ /* msPOSTGRESQLJoinNext() */ /* */ /* The goal here is to populate join->values with the detail of the */ /* join against the previously prepared shapeObj. This will be called */ /* only once for a one-to-one join, with msPOSTGRESQLJoinPrepare() */ /* being called before each. It will be called repeatedly for */ /* one-to-many joins, until in returns MS_DONE. To accomodate this, */ /* we store the next row number and query results in the joininfo and */ /* process the next tuple on each call. */ /************************************************************************/ int msPOSTGRESQLJoinNext(joinObj *join) { msPOSTGRESQLJoinInfo *joininfo = join->joininfo; int i, length, row_count; char *sql, *columns; /* We need a connection, and a join value. */ if(!joininfo || !joininfo->conn) { msSetError(MS_JOINERR, "Join has not been connected.\n", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } if(!joininfo->from_value) { msSetError(MS_JOINERR, "Join has not been prepared.\n", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } /* Free the previous results. */ if(join->values) { msFreeCharArray(join->values, join->numitems); join->values = NULL; } /* We only need to execute the query if no results exist. */ if(!joininfo->query_result) { /* Write the list of column names. */ length = 0; for(i = 0; i < join->numitems; i++) { length += 8 + strlen(join->items[i]) + 2; } columns = (char *)malloc(length); if(!columns) { msSetError(MS_MEMERR, "Failure to malloc.\n", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } strcpy(columns, ""); for(i = 0; i < join->numitems; i++) { strcat(columns, "\""); strcat(columns, join->items[i]); strcat(columns, "\"::text"); if(i != join->numitems - 1) { strcat(columns, ", "); } } /* Create the query string. */ sql = (char *)malloc(26 + strlen(columns) + strlen(join->table) + strlen(join->to) + strlen(joininfo->from_value)); if(!sql) { msSetError(MS_MEMERR, "Failure to malloc.\n", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } sprintf(sql, "SELECT %s FROM %s WHERE %s = '%s'", columns, join->table, join->to, joininfo->from_value); if(joininfo->layer_debug) { msDebug("msPOSTGRESQLJoinNext(): executing %s.\n", sql); } free(columns); joininfo->query_result = PQexec(joininfo->conn, sql); if(!joininfo->query_result || PQresultStatus(joininfo->query_result) != PGRES_TUPLES_OK) { msSetError(MS_QUERYERR, "Error executing queri %s: %s\n", "msPOSTGRESQLJoinNext()", sql, PQerrorMessage(joininfo->conn)); if(joininfo->query_result) { PQclear(joininfo->query_result); joininfo->query_result = NULL; } free(sql); return MS_FAILURE; } free(sql); } row_count = PQntuples(joininfo->query_result); /* see if we're done processing this set */ if(joininfo->row_num >= row_count) { return(MS_DONE); } if(joininfo->layer_debug) { msDebug("msPOSTGRESQLJoinNext(): fetching row %ld.\n", joininfo->row_num); } /* Copy the resulting values into the joinObj. */ join->values = (char **)malloc(sizeof(char *) * join->numitems); for(i = 0; i < join->numitems; i++) { join->values[i] = msStrdup(PQgetvalue( joininfo->query_result, joininfo->row_num, i)); } joininfo->row_num++; return MS_SUCCESS; } /************************************************************************/ /* msPOSTGRESQLJoinClose() */ /* */ /* Closes the connection and frees the resources used by the joininfo. */ /************************************************************************/ int msPOSTGRESQLJoinClose(joinObj *join) { msPOSTGRESQLJoinInfo *joininfo = join->joininfo; if(!joininfo) { msDebug("msPOSTGRESQLJoinClose() already close or never opened.\n"); return MS_SUCCESS; } if(joininfo->query_result) { msDebug("msPOSTGRESQLJoinClose(): clearing query_result.\n"); PQclear(joininfo->query_result); joininfo->query_result = NULL; } if(joininfo->conn) { msDebug("msPOSTGRESQLJoinClose(): closing connection.\n"); PQfinish(joininfo->conn); joininfo->conn = NULL; } /* removed free(joininfo->to_column), see bug #2936 */ if(joininfo->from_value) { free(joininfo->from_value); } free(joininfo); join->joininfo = NULL; return MS_SUCCESS; } #else /* not USE_POSTGIS */ int msPOSTGRESQLJoinConnect(layerObj *layer, joinObj *join) { msSetError(MS_QUERYERR, "PostgreSQL support not available.", "msPOSTGRESQLJoinConnect()"); return MS_FAILURE; } int msPOSTGRESQLJoinPrepare(joinObj *join, shapeObj *shape) { msSetError(MS_QUERYERR, "PostgreSQL support not available.", "msPOSTGRESQLJoinPrepare()"); return MS_FAILURE; } int msPOSTGRESQLJoinNext(joinObj *join) { msSetError(MS_QUERYERR, "PostgreSQL support not available.", "msPOSTGRESQLJoinNext()"); return MS_FAILURE; } int msPOSTGRESQLJoinClose(joinObj *join) { msSetError(MS_QUERYERR, "PostgreSQL support not available.", "msPOSTGRESQLJoinClose()"); return MS_FAILURE; } #endif mapserver-7.4.3/mapprimitive.c000066400000000000000000002306761357574274700164460ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementations for rectObj, pointObj, lineObj, shapeObj, etc. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "mapprimitive.h" #include #include #include "fontcache.h" typedef enum {CLIP_LEFT, CLIP_MIDDLE, CLIP_RIGHT} CLIP_STATE; #define CLIP_CHECK(min, a, max) ((a) < (min) ? CLIP_LEFT : ((a) > (max) ? CLIP_RIGHT : CLIP_MIDDLE)); #define ROUND(a) ( (a) + 0.5 ) #define SWAP( a, b, t) ( (t) = (a), (a) = (b), (b) = (t) ) #define EDGE_CHECK( x0, x, x1) ((x) < MS_MIN( (x0), (x1)) ? CLIP_LEFT : ((x) > MS_MAX( (x0), (x1)) ? CLIP_RIGHT : CLIP_MIDDLE )) #ifndef INFINITY #define INFINITY (1.0e+30) #endif #define NEARZERO (1.0e-30) /* 1/INFINITY */ void msPrintShape(shapeObj *p) { int i,j; msDebug("Shape contains %d parts.\n", p->numlines); for (i=0; inumlines; i++) { msDebug("\tPart %d contains %d points.\n", i, p->line[i].numpoints); for (j=0; jline[i].numpoints; j++) { msDebug("\t\t%d: (%f, %f)\n", j, p->line[i].point[j].x, p->line[i].point[j].y); } } } shapeObj *msShapeFromWKT(const char *string) { #ifdef USE_GEOS return msGEOSShapeFromWKT(string); #elif defined(USE_OGR) return msOGRShapeFromWKT(string); #else msSetError(MS_MISCERR, "WKT support is not available, please compile MapServer with GEOS or OGR support.", "msShapeFromWKT()"); return NULL; #endif } char *msShapeToWKT(shapeObj *shape) { #ifdef USE_GEOS char* pszGEOSStr; char* pszStr; pszGEOSStr = msGEOSShapeToWKT(shape); pszStr = (pszGEOSStr) ? msStrdup(pszGEOSStr) : NULL; msGEOSFreeWKT(pszGEOSStr); return pszStr; #elif defined(USE_OGR) return msOGRShapeToWKT(shape); #else msSetError(MS_MISCERR, "WKT support is not available, please compile MapServer with GEOS or OGR support.", "msShapeToWKT()"); return NULL; #endif } void msInitShape(shapeObj *shape) { /* spatial component */ shape->line = NULL; shape->numlines = 0; shape->type = MS_SHAPE_NULL; shape->bounds.minx = shape->bounds.miny = -1; shape->bounds.maxx = shape->bounds.maxy = -1; /* attribute component */ shape->values = NULL; shape->numvalues = 0; shape->geometry = NULL; shape->renderer_cache = NULL; /* annotation component */ shape->text = NULL; /* bookkeeping component */ shape->classindex = 0; /* default class */ shape->tileindex = shape->index = shape->resultindex = -1; shape->scratch = MS_FALSE; /* not a temporary/scratch shape */ } int msCopyShape(shapeObj *from, shapeObj *to) { int i; if(!from || !to) return(-1); for(i=0; inumlines; i++) msAddLine(to, &(from->line[i])); /* copy each line */ to->type = from->type; to->bounds.minx = from->bounds.minx; to->bounds.miny = from->bounds.miny; to->bounds.maxx = from->bounds.maxx; to->bounds.maxy = from->bounds.maxy; if(from->text) to->text = msStrdup(from->text); to->classindex = from->classindex; to->index = from->index; to->tileindex = from->tileindex; to->resultindex = from->resultindex; if(from->values) { to->values = (char **)msSmallMalloc(sizeof(char *)*from->numvalues); for(i=0; inumvalues; i++) to->values[i] = msStrdup(from->values[i]); to->numvalues = from->numvalues; } to->geometry = NULL; /* GEOS code will build automatically if necessary */ to->scratch = from->scratch; return(0); } void msFreeShape(shapeObj *shape) { int c; if(!shape) return; /* for safety */ for (c= 0; c < shape->numlines; c++) free(shape->line[c].point); if (shape->line) free(shape->line); if(shape->values) msFreeCharArray(shape->values, shape->numvalues); if(shape->text) free(shape->text); #ifdef USE_GEOS msGEOSFreeGeometry(shape); #endif msInitShape(shape); /* now reset */ } int msGetShapeRAMSize(shapeObj* shape) { int i; int size = 0; size += sizeof(shapeObj); size += shape->numlines * sizeof(lineObj); for (i = 0; i < shape->numlines; i++) { size += shape->line[i].numpoints * sizeof(pointObj); } size += shape->numvalues * sizeof(char*); for( i = 0; i < shape->numvalues; i++ ) { if( shape->values[i] ) size += strlen( shape->values[i] ) + 1; } if( shape->text ) size += strlen( shape->text ) + 1; return size; } void msFreeLabelPathObj(labelPathObj *path) { msFreeShape(&(path->bounds)); msFree(path->path.point); msFree(path->angles); msFree(path); } void msShapeDeleteLine( shapeObj *shape, int line ) { if( line < 0 || line >= shape->numlines ) { assert( 0 ); return; } free( shape->line[line].point ); if( line < shape->numlines - 1 ) { memmove( shape->line + line, shape->line + line + 1, sizeof(lineObj) * (shape->numlines - line - 1) ); } shape->numlines--; } void msComputeBounds(shapeObj *shape) { int i, j; if(shape->numlines <= 0) return; for(i=0; inumlines; i++) { if(shape->line[i].numpoints > 0) { shape->bounds.minx = shape->bounds.maxx = shape->line[i].point[0].x; shape->bounds.miny = shape->bounds.maxy = shape->line[i].point[0].y; break; } } if(i == shape->numlines) return; for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { shape->bounds.minx = MS_MIN(shape->bounds.minx, shape->line[i].point[j].x); shape->bounds.maxx = MS_MAX(shape->bounds.maxx, shape->line[i].point[j].x); shape->bounds.miny = MS_MIN(shape->bounds.miny, shape->line[i].point[j].y); shape->bounds.maxy = MS_MAX(shape->bounds.maxy, shape->line[i].point[j].y); } } } /* checks to see if ring r is an outer ring of shape */ int msIsOuterRing(shapeObj *shape, int r) { int i, status=MS_TRUE; int result1, result2; if(shape->numlines == 1) return(MS_TRUE); for(i=0; inumlines; i++) { if(i == r) continue; /* ** We have to test 2, or perhaps 3 points on the shape against the ring because ** it is possible that at most one point could touch the ring and the function ** msPointInPolygon() is indeterminite in that case. (bug #2434) */ result1 = msPointInPolygon(&(shape->line[r].point[0]), &(shape->line[i])); result2 = msPointInPolygon(&(shape->line[r].point[1]), &(shape->line[i])); if(result1 == result2) { /* same result twice, neither point was on the edge */ if(result1 == MS_TRUE) status = !status; } else { /* one of the first 2 points were on the edge of the ring, the next one isn't */ if(msPointInPolygon(&(shape->line[r].point[2]), &(shape->line[i])) == MS_TRUE) status = !status; } } return(status); } /* ** Returns a list of outer rings for shape (the list has one entry for each ring, ** MS_TRUE for outer rings). */ int *msGetOuterList(shapeObj *shape) { int i; int *list; list = (int *)malloc(sizeof(int)*shape->numlines); MS_CHECK_ALLOC(list, sizeof(int)*shape->numlines, NULL); for(i=0; inumlines; i++) list[i] = msIsOuterRing(shape, i); return(list); } /* ** Returns a list of inner rings for ring r in shape (given a list of outer rings). */ int *msGetInnerList(shapeObj *shape, int r, int *outerlist) { int i; int *list; list = (int *)malloc(sizeof(int)*shape->numlines); MS_CHECK_ALLOC(list, sizeof(int)*shape->numlines, NULL); for(i=0; inumlines; i++) { /* test all rings against the ring */ if(outerlist[i] == MS_TRUE) { /* ring is an outer and can't be an inner */ list[i] = MS_FALSE; continue; } /* A valid inner ring may touch its outer ring at most one point. */ /* In the case the first point matches a vertex of an outer ring, */ /* msPointInPolygon() might return 0 or 1 (depending on coordinate values, */ /* see msGetOuterList()), so test a second point if the first test */ /* returned that the point is not inside the outer ring. */ /* Fixes #5299 */ /* Of course all of this assumes that the geometries are indeed valid in */ /* OGC terms, otherwise all logic of msIsOuterRing(), msGetOuterList(), */ /* and msGetInnerList() has undefined behaviour. */ list[i] = msPointInPolygon(&(shape->line[i].point[0]), &(shape->line[r])) || msPointInPolygon(&(shape->line[i].point[1]), &(shape->line[r])); } return(list); } /* ** Add point to a line object. ** ** Note that reallocating the point array larger for each point can ** be pretty inefficient, so use this function sparingly. Mostly ** geometries creators should create their own working lineObj and ** then call msAddLine() to add it to a shape. */ int msAddPointToLine(lineObj *line, pointObj *point ) { line->numpoints += 1; line->point = (pointObj *) msSmallRealloc(line->point, sizeof(pointObj) * line->numpoints); line->point[line->numpoints-1] = *point; return MS_SUCCESS; } int msAddLine(shapeObj *p, lineObj *new_line) { lineObj lineCopy; lineCopy.numpoints = new_line->numpoints; lineCopy.point = (pointObj *) malloc(new_line->numpoints*sizeof(pointObj)); MS_CHECK_ALLOC(lineCopy.point, new_line->numpoints*sizeof(pointObj), MS_FAILURE); memcpy( lineCopy.point, new_line->point, sizeof(pointObj) * new_line->numpoints ); return msAddLineDirectly( p, &lineCopy ); } /* ** Same as msAddLine(), except that this version "seizes" the points ** array from the passed in line and uses it instead of copying it. */ int msAddLineDirectly(shapeObj *p, lineObj *new_line) { int c; if( p->numlines == 0 ) { p->line = (lineObj *) malloc(sizeof(lineObj)); MS_CHECK_ALLOC(p->line, sizeof(lineObj), MS_FAILURE); } else { p->line = (lineObj *) realloc(p->line, (p->numlines+1)*sizeof(lineObj)); MS_CHECK_ALLOC(p->line, (p->numlines+1)*sizeof(lineObj), MS_FAILURE); } /* Copy the new line onto the end of the extended line array */ c= p->numlines; p->line[c].numpoints = new_line->numpoints; p->line[c].point = new_line->point; /* strip points reference off the passed in lineObj */ new_line->point = NULL; new_line->numpoints = 0; /* Update the polygon information */ p->numlines++; return(MS_SUCCESS); } /* ** Converts a rect array to a shapeObj structure. Note order is CW assuming y origin ** is in the lower left corner (normal cartesian coordinate system). Also polygon is ** is closed (i.e. first=last). This conforms to the shapefile specification. For image ** coordinate systems (i.e. GD) this is back-ass-ward, which is fine cause the function ** that calculates direction assumes min y = lower left, this way it'll still work. Drawing ** functions are independent of direction. Orientation problems can cause some nasty bugs. */ void msRectToPolygon(rectObj rect, shapeObj *poly) { lineObj line= {0,NULL}; line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*5); line.point[0].x = rect.minx; line.point[0].y = rect.miny; line.point[1].x = rect.minx; line.point[1].y = rect.maxy; line.point[2].x = rect.maxx; line.point[2].y = rect.maxy; line.point[3].x = rect.maxx; line.point[3].y = rect.miny; line.point[4].x = line.point[0].x; line.point[4].y = line.point[0].y; line.numpoints = 5; msAddLine(poly, &line); if(poly->numlines == 1) { /* poly was empty to begin with */ poly->type = MS_SHAPE_POLYGON; poly->bounds = rect; } else msMergeRect(&poly->bounds, &rect); free(line.point); } /* ** Private implementation of the Sutherland-Cohen algorithm. Inspired by ** "Getting Graphic: Programming Fundamentals in C and C++" by Mark Finlay ** and John Petritis. (pages 179-182) */ static int clipLine(double *x1, double *y1, double *x2, double *y2, rectObj rect) { double x, y; double slope; CLIP_STATE check1, check2; if(*x1 < rect.minx && *x2 < rect.minx) return(MS_FALSE); if(*x1 > rect.maxx && *x2 > rect.maxx) return(MS_FALSE); check1 = CLIP_CHECK(rect.minx, *x1, rect.maxx); check2 = CLIP_CHECK(rect.minx, *x2, rect.maxx); if(check1 == CLIP_LEFT || check2 == CLIP_LEFT) { slope = (*y2 - *y1)/(*x2 - *x1); y = *y1 + (rect.minx - *x1)*slope; if(check1 == CLIP_LEFT) { *x1 = rect.minx; *y1 = y; } else { *x2 = rect.minx; *y2 = y; } } if(check1 == CLIP_RIGHT || check2 == CLIP_RIGHT) { slope = (*y2 - *y1)/(*x2 - *x1); y = *y1 + (rect.maxx - *x1)*slope; if(check1 == CLIP_RIGHT) { *x1 = rect.maxx; *y1 = y; } else { *x2 = rect.maxx; *y2 = y; } } if(*y1 < rect.miny && *y2 < rect.miny) return(MS_FALSE); if(*y1 > rect.maxy && *y2 > rect.maxy) return(MS_FALSE); check1 = CLIP_CHECK(rect.miny, *y1, rect.maxy); check2 = CLIP_CHECK(rect.miny, *y2, rect.maxy); if(check1 == CLIP_LEFT || check2 == CLIP_LEFT) { slope = (*x2 - *x1)/(*y2 - *y1); x = *x1 + (rect.miny - *y1)*slope; if(check1 == CLIP_LEFT) { *x1 = x; *y1 = rect.miny; } else { *x2 = x; *y2 = rect.miny; } } if(check1 == CLIP_RIGHT || check2 == CLIP_RIGHT) { slope = (*x2 - *x1)/(*y2 - *y1); x = *x1 + (rect.maxy - *y1)*slope; if(check1 == CLIP_RIGHT) { *x1 = x; *y1 = rect.maxy; } else { *x2 = x; *y2 = rect.maxy; } } return(MS_TRUE); } /* ** Routine for clipping a polyline, stored in a shapeObj struct, to a ** rectangle. Uses clipLine() function to create a new shapeObj. */ void msClipPolylineRect(shapeObj *shape, rectObj rect) { int i,j; lineObj line= {0,NULL}; double x1, x2, y1, y2; shapeObj tmp; memset( &tmp, 0, sizeof(shapeObj) ); if(shape->numlines == 0) /* nothing to clip */ return; /* ** Don't do any clip processing of shapes completely within the ** clip rectangle based on a comparison of bounds. We could do ** something similar for completely outside, but that rarely occurs ** since the spatial query at the layer read level has generally already ** discarded all shapes completely outside the rect. */ if( shape->bounds.maxx <= rect.maxx && shape->bounds.minx >= rect.minx && shape->bounds.maxy <= rect.maxy && shape->bounds.miny >= rect.miny ) { return; } for(i=0; inumlines; i++) { line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*shape->line[i].numpoints); line.numpoints = 0; x1 = shape->line[i].point[0].x; y1 = shape->line[i].point[0].y; for(j=1; jline[i].numpoints; j++) { x2 = shape->line[i].point[j].x; y2 = shape->line[i].point[j].y; if(clipLine(&x1,&y1,&x2,&y2,rect) == MS_TRUE) { if(line.numpoints == 0) { /* first segment, add both points */ line.point[0].x = x1; line.point[0].y = y1; line.point[1].x = x2; line.point[1].y = y2; line.numpoints = 2; } else { /* add just the last point */ line.point[line.numpoints].x = x2; line.point[line.numpoints].y = y2; line.numpoints++; } if((x2 != shape->line[i].point[j].x) || (y2 != shape->line[i].point[j].y)) { msAddLine(&tmp, &line); line.numpoints = 0; /* new line */ } } x1 = shape->line[i].point[j].x; y1 = shape->line[i].point[j].y; } if(line.numpoints > 0) { msAddLineDirectly(&tmp, &line); } else { free(line.point); line.numpoints = 0; /* new line */ } } for (i=0; inumlines; i++) free(shape->line[i].point); free(shape->line); shape->line = tmp.line; shape->numlines = tmp.numlines; msComputeBounds(shape); } /* ** Slightly modified version of the Liang-Barsky polygon clipping algorithm */ void msClipPolygonRect(shapeObj *shape, rectObj rect) { int i, j; double deltax, deltay, xin,xout, yin,yout; double tinx,tiny, toutx,touty, tin1, tin2, tout; double x1,y1, x2,y2; shapeObj tmp; lineObj line= {0,NULL}; msInitShape(&tmp); if(shape->numlines == 0) /* nothing to clip */ return; /* ** Don't do any clip processing of shapes completely within the ** clip rectangle based on a comparison of bounds. We could do ** something similar for completely outside, but that rarely occurs ** since the spatial query at the layer read level has generally already ** discarded all shapes completely outside the rect. */ if( shape->bounds.maxx <= rect.maxx && shape->bounds.minx >= rect.minx && shape->bounds.maxy <= rect.maxy && shape->bounds.miny >= rect.miny ) { return; } for(j=0; jnumlines; j++) { line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*2*shape->line[j].numpoints+1); /* worst case scenario, +1 allows us to duplicate the 1st and last point */ line.numpoints = 0; for (i = 0; i < shape->line[j].numpoints-1; i++) { x1 = shape->line[j].point[i].x; y1 = shape->line[j].point[i].y; x2 = shape->line[j].point[i+1].x; y2 = shape->line[j].point[i+1].y; deltax = x2-x1; if (deltax == 0) { /* bump off of the vertical */ deltax = (x1 > rect.minx) ? -NEARZERO : NEARZERO ; } deltay = y2-y1; if (deltay == 0) { /* bump off of the horizontal */ deltay = (y1 > rect.miny) ? -NEARZERO : NEARZERO ; } if (deltax > 0) { /* points to right */ xin = rect.minx; xout = rect.maxx; } else { xin = rect.maxx; xout = rect.minx; } if (deltay > 0) { /* points up */ yin = rect.miny; yout = rect.maxy; } else { yin = rect.maxy; yout = rect.miny; } tinx = (xin - x1)/deltax; tiny = (yin - y1)/deltay; if (tinx < tiny) { /* hits x first */ tin1 = tinx; tin2 = tiny; } else { /* hits y first */ tin1 = tiny; tin2 = tinx; } if (1 >= tin1) { if (0 < tin1) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = yin; line.numpoints++; } if (1 >= tin2) { toutx = (xout - x1)/deltax; touty = (yout - y1)/deltay; tout = (toutx < touty) ? toutx : touty ; if (0 < tin2 || 0 < tout) { if (tin2 <= tout) { if (0 < tin2) { if (tinx > tiny) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = y1 + tinx*deltay; line.numpoints++; } else { line.point[line.numpoints].x = x1 + tiny*deltax; line.point[line.numpoints].y = yin; line.numpoints++; } } if (1 > tout) { if (toutx < touty) { line.point[line.numpoints].x = xout; line.point[line.numpoints].y = y1 + toutx*deltay; line.numpoints++; } else { line.point[line.numpoints].x = x1 + touty*deltax; line.point[line.numpoints].y = yout; line.numpoints++; } } else { line.point[line.numpoints].x = x2; line.point[line.numpoints].y = y2; line.numpoints++; } } else { if (tinx > tiny) { line.point[line.numpoints].x = xin; line.point[line.numpoints].y = yout; line.numpoints++; } else { line.point[line.numpoints].x = xout; line.point[line.numpoints].y = yin; line.numpoints++; } } } } } } if(line.numpoints > 0) { line.point[line.numpoints].x = line.point[0].x; /* force closure */ line.point[line.numpoints].y = line.point[0].y; line.numpoints++; msAddLineDirectly(&tmp, &line); } else { free(line.point); } } /* next line */ for (i=0; inumlines; i++) free(shape->line[i].point); free(shape->line); shape->line = tmp.line; shape->numlines = tmp.numlines; msComputeBounds(shape); return; } /* ** offsets a point relative to an image position */ void msOffsetPointRelativeTo(pointObj *point, layerObj *layer) { double x=0, y=0; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return; if(layer->transform == MS_TRUE) return; /* nothing to do */ if(layer->units == MS_PERCENTAGES) { point->x *= (layer->map->width-1); point->y *= (layer->map->height-1); } if(layer->transform == MS_FALSE || layer->transform == MS_UL) return; /* done */ switch(layer->transform) { case MS_UC: x = (layer->map->width-1)/2; y = 0; break; case MS_UR: x = layer->map->width-1; y = 0; break; case MS_CL: x = 0; y = layer->map->height/2; break; case MS_CC: x = layer->map->width/2; y = layer->map->height/2; break; case MS_CR: x = layer->map->width-1; y = layer->map->height/2; break; case MS_LL: x = 0; y = layer->map->height-1; break; case MS_LC: x = layer->map->width/2; y = layer->map->height-1; break; case MS_LR: x = layer->map->width-1; y = layer->map->height-1; break; } point->x += x; point->y += y; return; } /* ** offsets a shape relative to an image position */ void msOffsetShapeRelativeTo(shapeObj *shape, layerObj *layer) { int i, j; double x=0, y=0; if(layer->transform == MS_TRUE) return; /* nothing to do */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return; if(layer->units == MS_PERCENTAGES) { for (i=0; inumlines; i++) { for (j=0; jline[i].numpoints; j++) { shape->line[i].point[j].x *= (layer->map->width-1); shape->line[i].point[j].y *= (layer->map->height-1); } } } if(layer->transform == MS_FALSE || layer->transform == MS_UL) return; /* done */ switch(layer->transform) { case MS_UC: x = (layer->map->width-1)/2; y = 0; break; case MS_UR: x = layer->map->width-1; y = 0; break; case MS_CL: x = 0; y = layer->map->height/2; break; case MS_CC: x = layer->map->width/2; y = layer->map->height/2; break; case MS_CR: x = layer->map->width-1; y = layer->map->height/2; break; case MS_LL: x = 0; y = layer->map->height-1; break; case MS_LC: x = layer->map->width/2; y = layer->map->height-1; break; case MS_LR: x = layer->map->width-1; y = layer->map->height-1; break; } for (i=0; inumlines; i++) { for (j=0; jline[i].numpoints; j++) { shape->line[i].point[j].x += x; shape->line[i].point[j].y += y; } } return; } void msTransformShapeSimplify(shapeObj *shape, rectObj extent, double cellsize) { int i,j,k,beforelast; /* loop counters */ double dx,dy; pointObj *point; double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */ int ok = 0; if(shape->numlines == 0) return; /* nothing to transform */ if(shape->type == MS_SHAPE_LINE) { /* * loop through the shape's lines, and do naive simplification * to discard the points that are too close to one another. * currently the threshold is to discard points if they fall * less than a pixel away from their predecessor. * the simplified line is guaranteed to contain at * least its first and last point */ for(i=0; inumlines; i++) { /* for each part */ if(shape->line[i].numpoints<2) { shape->line[i].numpoints=0; continue; /*skip degenerate lines*/ } point=shape->line[i].point; /*always keep first point*/ point[0].x = MS_MAP2IMAGE_X_IC_DBL(point[0].x, extent.minx, inv_cs); point[0].y = MS_MAP2IMAGE_Y_IC_DBL(point[0].y, extent.maxy, inv_cs); beforelast=shape->line[i].numpoints-1; for(j=1,k=1; j < beforelast; j++ ) { /*loop from second point to first-before-last point*/ point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); dx=(point[k].x-point[k-1].x); dy=(point[k].y-point[k-1].y); if(dx*dx+dy*dy>1) k++; } /* try to keep last point */ point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); /* discard last point if equal to the one before it */ if(point[k].x!=point[k-1].x || point[k].y!=point[k-1].y) { shape->line[i].numpoints=k+1; } else { shape->line[i].numpoints=k; } /* skip degenerate line once more */ if(shape->line[i].numpoints<2) { shape->line[i].numpoints=0; } else { ok = 1; /* we have at least one line with more than two points */ } } } else if(shape->type == MS_SHAPE_POLYGON) { /* * loop through the shape's lines, and do naive simplification * to discard the points that are too close to one another. * currently the threshold is to discard points if they fall * less than a pixel away from their predecessor. * the simplified polygon is guaranteed to contain at * least its first, second and last point */ for(i=0; inumlines; i++) { /* for each part */ if(shape->line[i].numpoints<4) { shape->line[i].numpoints=0; continue; /*skip degenerate lines*/ } point=shape->line[i].point; /*always keep first and second point*/ point[0].x = MS_MAP2IMAGE_X_IC_DBL(point[0].x, extent.minx, inv_cs); point[0].y = MS_MAP2IMAGE_Y_IC_DBL(point[0].y, extent.maxy, inv_cs); point[1].x = MS_MAP2IMAGE_X_IC_DBL(point[1].x, extent.minx, inv_cs); point[1].y = MS_MAP2IMAGE_Y_IC_DBL(point[1].y, extent.maxy, inv_cs); beforelast=shape->line[i].numpoints-2; for(j=2,k=2; j < beforelast; j++ ) { /*loop from second point to second-before-last point*/ point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); dx=(point[k].x-point[k-1].x); dy=(point[k].y-point[k-1].y); if(dx*dx+dy*dy>1) k++; } /*always keep last two points (the last point is the repetition of the * first one */ point[k].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[k].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); point[k+1].x = MS_MAP2IMAGE_X_IC_DBL(point[j+1].x, extent.minx, inv_cs); point[k+1].y = MS_MAP2IMAGE_Y_IC_DBL(point[j+1].y, extent.maxy, inv_cs); shape->line[i].numpoints = k+2; ok = 1; } } else { /* only for untyped shapes, as point layers don't go through this function */ for(i=0; inumlines; i++) { point=shape->line[i].point; for(j=0; jline[i].numpoints; j++) { point[j].x = MS_MAP2IMAGE_X_IC_DBL(point[j].x, extent.minx, inv_cs); point[j].y = MS_MAP2IMAGE_Y_IC_DBL(point[j].y, extent.maxy, inv_cs); } } ok = 1; } if(!ok) { for(i=0; inumlines; i++) { free(shape->line[i].point); } shape->numlines = 0 ; } } /** * Generic function to transorm the shape coordinates to output coordinates */ void msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image) { if (image != NULL && MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); if(renderer->transform_mode == MS_TRANSFORM_SNAPTOGRID) { msTransformShapeToPixelSnapToGrid(shape, extent, cellsize, renderer->approximation_scale); } else if(renderer->transform_mode == MS_TRANSFORM_SIMPLIFY) { msTransformShapeSimplify(shape, extent, cellsize); } else if(renderer->transform_mode == MS_TRANSFORM_ROUND) { msTransformShapeToPixelRound(shape, extent, cellsize); } else if(renderer->transform_mode == MS_TRANSFORM_FULLRESOLUTION) { msTransformShapeToPixelDoublePrecision(shape,extent,cellsize); } else if(renderer->transform_mode == MS_TRANSFORM_NONE) { /* nothing to do */ return; } /* unknown, do nothing */ return; } msTransformShapeToPixelRound(shape, extent, cellsize); } void msTransformShapeToPixelSnapToGrid(shapeObj *shape, rectObj extent, double cellsize, double grid_resolution) { int i,j,k; /* loop counters */ double inv_cs; if(shape->numlines == 0) return; inv_cs = 1.0 / cellsize; /* invert and multiply much faster */ if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */ for(i=0; inumlines; i++) { /* for each part */ int snap = 1; double x0,y0,x1,y1,x2,y2; /*do a quick heuristic: will we risk having a degenerate shape*/ if(shape->type == MS_SHAPE_LINE) { /*a line is degenerate if it has a single pixel. we check that the first and last pixel are different*/ x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution); y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution); x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs, grid_resolution); y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs, grid_resolution); if(x0 == x1 && y0 == y1) { snap = 0; } } else if(shape->type == MS_SHAPE_POLYGON) { x0 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[0].x, extent.minx, inv_cs, grid_resolution); y0 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[0].y, extent.maxy, inv_cs, grid_resolution); x1 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].x, extent.minx, inv_cs, grid_resolution); y1 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3].y, extent.maxy, inv_cs, grid_resolution); x2 = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].x, extent.minx, inv_cs, grid_resolution); y2 = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[shape->line[i].numpoints/3*2].y, extent.maxy, inv_cs, grid_resolution); if((x0 == x1 && y0 == y1) || (x0 == x2 && y0 == y2) || (x1 == x2 && y1 == y2)) { snap = 0; } } else snap = 0; if(snap) { shape->line[i].point[0].x = x0; shape->line[i].point[0].y = y0; for(j=1, k=1; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC_SNAP(shape->line[i].point[j].x, extent.minx, inv_cs, grid_resolution); shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC_SNAP(shape->line[i].point[j].y, extent.maxy, inv_cs, grid_resolution); if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y) k++; } shape->line[i].numpoints=k; } else { if(shape->type == MS_SHAPE_LINE) { shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[0].x, extent.minx, inv_cs); shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[0].y, extent.maxy, inv_cs); shape->line[i].point[1].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].x, extent.minx, inv_cs); shape->line[i].point[1].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[shape->line[i].numpoints-1].y, extent.maxy, inv_cs); shape->line[i].numpoints = 2; } else { for(j=0; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs); } } } } } else { /* points or untyped shapes */ for(i=0; inumlines; i++) { /* for each part */ for(j=1; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs); } } } } void msTransformShapeToPixelRound(shapeObj *shape, rectObj extent, double cellsize) { int i,j,k; /* loop counters */ double inv_cs; if(shape->numlines == 0) return; inv_cs = 1.0 / cellsize; /* invert and multiply much faster */ if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove duplicate vertices */ for(i=0; inumlines; i++) { /* for each part */ shape->line[i].point[0].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[0].x, extent.minx, inv_cs);; shape->line[i].point[0].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[0].y, extent.maxy, inv_cs); for(j=1, k=1; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[k].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[k].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs); if(shape->line[i].point[k].x!=shape->line[i].point[k-1].x || shape->line[i].point[k].y!=shape->line[i].point[k-1].y) k++; } shape->line[i].numpoints=k; } } else { /* points or untyped shapes */ for(i=0; inumlines; i++) { /* for each part */ for(j=0; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC(shape->line[i].point[j].y, extent.maxy, inv_cs); } } } } void msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize) { int i,j; /* loop counters */ double inv_cs = 1.0 / cellsize; /* invert and multiply much faster */ for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { shape->line[i].point[j].x = MS_MAP2IMAGE_X_IC_DBL(shape->line[i].point[j].x, extent.minx, inv_cs); shape->line[i].point[j].y = MS_MAP2IMAGE_Y_IC_DBL(shape->line[i].point[j].y, extent.maxy, inv_cs); } } } /* ** Converts from map coordinates to image coordinates */ void msTransformPixelToShape(shapeObj *shape, rectObj extent, double cellsize) { int i,j; /* loop counters */ if(shape->numlines == 0) return; /* nothing to transform */ if(shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) { /* remove co-linear vertices */ for(i=0; inumlines; i++) { /* for each part */ for(j=0; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_IMAGE2MAP_X(shape->line[i].point[j].x, extent.minx, cellsize); shape->line[i].point[j].y = MS_IMAGE2MAP_Y(shape->line[i].point[j].y, extent.maxy, cellsize); } } } else { /* points or untyped shapes */ for(i=0; inumlines; i++) { /* for each part */ for(j=1; j < shape->line[i].numpoints; j++ ) { shape->line[i].point[j].x = MS_IMAGE2MAP_X(shape->line[i].point[j].x, extent.minx, cellsize); shape->line[i].point[j].y = MS_IMAGE2MAP_Y(shape->line[i].point[j].y, extent.maxy, cellsize); } } } return; } /* ** Not a generic intersection test, we KNOW the lines aren't parallel or coincident. To be used with the next ** buffering code only. See code in mapsearch.c for a boolean test for intersection. */ static pointObj generateLineIntersection(pointObj a, pointObj b, pointObj c, pointObj d) { pointObj p; double r; double denominator, numerator; if(b.x == c.x && b.y == c.y) return(b); numerator = ((a.y-c.y)*(d.x-c.x) - (a.x-c.x)*(d.y-c.y)); denominator = ((b.x-a.x)*(d.y-c.y) - (b.y-a.y)*(d.x-c.x)); r = numerator/denominator; p.x = MS_NINT(a.x + r*(b.x-a.x)); p.y = MS_NINT(a.y + r*(b.y-a.y)); return(p); } void bufferPolyline(shapeObj *p, shapeObj *op, int w) { int i, j; pointObj a; lineObj inside, outside; double angle; double dx, dy; for (i = 0; i < p->numlines; i++) { inside.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*p->line[i].numpoints); outside.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*p->line[i].numpoints); inside.numpoints = outside.numpoints = p->line[i].numpoints; angle = asin(MS_ABS(p->line[i].point[1].x - p->line[i].point[0].x)/sqrt((((p->line[i].point[1].x - p->line[i].point[0].x)*(p->line[i].point[1].x - p->line[i].point[0].x)) + ((p->line[i].point[1].y - p->line[i].point[0].y)*(p->line[i].point[1].y - p->line[i].point[0].y))))); if(p->line[i].point[0].x < p->line[i].point[1].x) dy = sin(angle) * (w/2); else dy = -sin(angle) * (w/2); if(p->line[i].point[0].y < p->line[i].point[1].y) dx = -cos(angle) * (w/2); else dx = cos(angle) * (w/2); inside.point[0].x = p->line[i].point[0].x + dx; inside.point[1].x = p->line[i].point[1].x + dx; inside.point[0].y = p->line[i].point[0].y + dy; inside.point[1].y = p->line[i].point[1].y + dy; outside.point[0].x = p->line[i].point[0].x - dx; outside.point[1].x = p->line[i].point[1].x - dx; outside.point[0].y = p->line[i].point[0].y - dy; outside.point[1].y = p->line[i].point[1].y - dy; for(j=2; jline[i].numpoints; j++) { angle = asin(MS_ABS(p->line[i].point[j].x - p->line[i].point[j-1].x)/sqrt((((p->line[i].point[j].x - p->line[i].point[j-1].x)*(p->line[i].point[j].x - p->line[i].point[j-1].x)) + ((p->line[i].point[j].y - p->line[i].point[j-1].y)*(p->line[i].point[j].y - p->line[i].point[j-1].y))))); if(p->line[i].point[j-1].x < p->line[i].point[j].x) dy = sin(angle) * (w/2); else dy = -sin(angle) * (w/2); if(p->line[i].point[j-1].y < p->line[i].point[j].y) dx = -cos(angle) * (w/2); else dx = cos(angle) * (w/2); a.x = p->line[i].point[j-1].x + dx; inside.point[j].x = p->line[i].point[j].x + dx; a.y = p->line[i].point[j-1].y + dy; inside.point[j].y = p->line[i].point[j].y + dy; inside.point[j-1] = generateLineIntersection(inside.point[j-2], inside.point[j-1], a, inside.point[j]); a.x = p->line[i].point[j-1].x - dx; outside.point[j].x = p->line[i].point[j].x - dx; a.y = p->line[i].point[j-1].y - dy; outside.point[j].y = p->line[i].point[j].y - dy; outside.point[j-1] = generateLineIntersection(outside.point[j-2], outside.point[j-1], a, outside.point[j]); } /* need a touch of code if 1st point equals last point in p (find intersection) */ msAddLine(op, &inside); msAddLine(op, &outside); free(inside.point); free(outside.point); } return; } static double getRingArea(lineObj *ring) { int i; double s=0; for(i=0; inumpoints-1; i++) s += (ring->point[i].x*ring->point[i+1].y - ring->point[i+1].x*ring->point[i].y); return (MS_ABS(s/2)); } double msGetPolygonArea(shapeObj *p) { int i; double area=0; for(i=0; inumlines; i++) { if(msIsOuterRing(p, i)) area += getRingArea(&(p->line[i])); else area -= getRingArea(&(p->line[i])); /* hole */ } return area; } /* ** Computes the center of gravity for a polygon based on it's largest outer ring only. */ static int getPolygonCenterOfGravity(shapeObj *p, pointObj *lp) { int i, j; double area=0; double sx=0, sy=0, tsx, tsy, s; /* sums */ double a; double largestArea=0; for(i=0; inumlines; i++) { tsx = tsy = s = 0; /* reset the ring sums */ for(j=0; jline[i].numpoints-1; j++) { a = p->line[i].point[j].x*p->line[i].point[j+1].y - p->line[i].point[j+1].x*p->line[i].point[j].y; s += a; tsx += (p->line[i].point[j].x + p->line[i].point[j+1].x)*a; tsy += (p->line[i].point[j].y + p->line[i].point[j+1].y)*a; } area = MS_ABS(s/2); if(area > largestArea) { largestArea = area; sx = s>0?tsx:-tsx; sy = s>0?tsy:-tsy; } } if(largestArea == 0) /*degenerate polygon*/ return MS_FAILURE; lp->x = sx/(6*largestArea); lp->y = sy/(6*largestArea); return MS_SUCCESS; } int msGetPolygonCentroid(shapeObj *p, pointObj *lp, double *miny, double *maxy) { int i,j; double cent_weight_x=0.0, cent_weight_y=0.0; double len, total_len=0; *miny = *maxy = p->line[0].point[0].y; for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { *miny = MS_MIN(*miny, p->line[i].point[j].y); *maxy = MS_MAX(*maxy, p->line[i].point[j].y); len = msDistancePointToPoint(&(p->line[i].point[j-1]), &(p->line[i].point[j])); cent_weight_x += len * ((p->line[i].point[j-1].x + p->line[i].point[j].x)/2); cent_weight_y += len * ((p->line[i].point[j-1].y + p->line[i].point[j].y)/2); total_len += len; } } if(total_len == 0) return(MS_FAILURE); lp->x = cent_weight_x / total_len; lp->y = cent_weight_y / total_len; return(MS_SUCCESS); } /* ** Find a label point in a polygon. */ int msPolygonLabelPoint(shapeObj *p, pointObj *lp, double min_dimension) { double slope; pointObj *point1=NULL, *point2=NULL, cp; int i, j, nfound; double x, y, *intersect, temp; double min, max; int wrong_order, n; double len, max_len=0; double minx, maxx, maxy, miny; #ifdef notdef int method = 2; #endif msComputeBounds(p); minx = p->bounds.minx; miny = p->bounds.miny; maxx = p->bounds.maxx; maxy = p->bounds.maxy; if(min_dimension > 0) if(MS_MIN(maxx-minx,maxy-miny) < min_dimension) return(MS_FAILURE); cp.x = (maxx+minx)/2.0; cp.y = (maxy+miny)/2.0; #ifdef notdef switch (method) { case 0: /* MBR */ lp->x = cp.x; lp->y = cp.y; break; case 1: /* centroid */ if(msGetPolygonCentroid(p, lp, &miny, &maxy) != MS_SUCCESS) return(MS_FAILURE); break; case 2: /* center of gravity */ if(getPolygonCenterOfGravity(p, lp) != MS_SUCCESS) return(MS_FAILURE); break; } #else if(getPolygonCenterOfGravity(p, lp) != MS_SUCCESS) return(MS_FAILURE); #endif if(msIntersectPointPolygon(lp, p) == MS_TRUE) { double dist, min_dist=-1; /* compute a distance to the polygon */ for(j=0; jnumlines; j++) { for(i=1; iline[j].numpoints; i++) { dist = msSquareDistancePointToSegment(lp, &(p->line[j].point[i-1]), &(p->line[j].point[i])); if((dist < min_dist) || (min_dist < 0)) min_dist = dist; } } min_dist = sqrt(min_dist); if(min_dist > .1*MS_MAX(maxx-minx, maxy-miny)) return(MS_SUCCESS); /* point is not too close to the edge */ } /* printf("label: %s\n", p->text); printf(" bbox: %g %g %g %g\n",minx, miny, maxx, maxy); printf(" center: %g %g\n", cp.x, cp.y); printf(" center of gravity: %g %g\n", lp->x, lp->y); printf(" dx: %g, dy: %g\n", lp->x-cp.x, lp->y-cp.y); printf(" distance to parent shape: %g\n", min_dist); return MS_SUCCESS; */ n=0; for(j=0; jnumlines; j++) /* count total number of points */ n += p->line[j].numpoints; intersect = (double *) calloc(n, sizeof(double)); MS_CHECK_ALLOC(intersect, n*sizeof(double), MS_FAILURE); if(MS_ABS((int)lp->x - (int)cp.x) > MS_ABS((int)lp->y - (int)cp.y)) { /* center horizontally, fix y */ y = lp->y; /* need to find a y that won't intersect any vertices exactly */ max = y - 1; /* first initializing min, max to be any 2 pnts on either side of y */ min = y + 1; for(j=0; jnumlines; j++) { if((min < y) && (max >= y)) break; for(i=0; i < p->line[j].numpoints; i++) { if((min < y) && (max >= y)) break; if(p->line[j].point[i].y < y) min = p->line[j].point[i].y; if(p->line[j].point[i].y >= y) max = p->line[j].point[i].y; } } n=0; for(j=0; jnumlines; j++) { for(i=0; i < p->line[j].numpoints; i++) { if((p->line[j].point[i].y < y) && ((y - p->line[j].point[i].y) < (y - min))) min = p->line[j].point[i].y; if((p->line[j].point[i].y >= y) && ((p->line[j].point[i].y - y) < (max - y))) max = p->line[j].point[i].y; } } if(min == max) { msFree(intersect); return (MS_FAILURE); } else y = (max + min)/2.0; nfound = 0; for(j=0; jnumlines; j++) { /* for each line */ point1 = &( p->line[j].point[p->line[j].numpoints-1] ); for(i=0; i < p->line[j].numpoints; i++) { point2 = &( p->line[j].point[i] ); if(EDGE_CHECK(point1->y, y, point2->y) == CLIP_MIDDLE) { if(point1->y == point2->y) continue; /* ignore horizontal edges */ else slope = (point2->x - point1->x) / (point2->y - point1->y); x = point1->x + (y - point1->y)*slope; intersect[nfound++] = x; } /* end checking this edge */ point1 = point2; /* next edge */ } } /* finished line */ /* sort the intersections */ do { wrong_order = 0; for(i=0; i < nfound-1; i++) { if(intersect[i] > intersect[i+1]) { wrong_order = 1; SWAP(intersect[i], intersect[i+1], temp); } } } while(wrong_order); /* find longest span */ for(i=0; i < nfound; i += 2) { len = fabs(intersect[i] - intersect[i+1]); if(len > max_len) { max_len = len; lp->x = (intersect[i] + intersect[i+1])/2; lp->y = y; } } } else { /* center vertically, fix x */ x = lp->x; /* need to find a x that won't intersect any vertices exactly */ max = x - 1; /* first initializing min, max to be any 2 pnts on either side of x */ min = x + 1; for(j=0; jnumlines; j++) { if((min < x) && (max >= x)) break; for(i=0; i < p->line[j].numpoints; i++) { if((min < x) && (max >= x)) break; if(p->line[j].point[i].x < x) min = p->line[j].point[i].x; if(p->line[j].point[i].x >= x) max = p->line[j].point[i].x; } } n=0; for(j=0; jnumlines; j++) { for(i=0; i < p->line[j].numpoints; i++) { if((p->line[j].point[i].x < x) && ((x - p->line[j].point[i].x) < (x - min))) min = p->line[j].point[i].x; if((p->line[j].point[i].x >= x) && ((p->line[j].point[i].x - x) < (max - x))) max = p->line[j].point[i].x; } } if(min == max) { msFree(intersect); return (MS_FAILURE); } else x = (max + min)/2.0; nfound = 0; for(j=0; jnumlines; j++) { /* for each line */ point1 = &( p->line[j].point[p->line[j].numpoints-1] ); for(i=0; i < p->line[j].numpoints; i++) { point2 = &( p->line[j].point[i] ); if(EDGE_CHECK(point1->x, x, point2->x) == CLIP_MIDDLE) { if(point1->x == point2->x) continue; /* ignore vertical edges */ else if(point1->y == point2->y) y = point1->y; /* for a horizontal edge we know y */ else { slope = (point2->x - point1->x) / (point2->y - point1->y); y = (x - point1->x)/slope + point1->y; } intersect[nfound++] = y; } /* end checking this edge */ point1 = point2; /* next edge */ } } /* finished line */ /* sort the intersections */ do { wrong_order = 0; for(i=0; i < nfound-1; i++) { if(intersect[i] > intersect[i+1]) { wrong_order = 1; SWAP(intersect[i], intersect[i+1], temp); } } } while(wrong_order); /* find longest span */ for(i=0; i < nfound; i += 2) { len = fabs(intersect[i] - intersect[i+1]); if(len > max_len) { max_len = len; lp->y = (intersect[i] + intersect[i+1])/2; lp->x = x; } } } free(intersect); if(max_len > 0) return(MS_SUCCESS); else return(MS_FAILURE); } /* Compute all the lineString/segment lengths and determine the longest lineString of a multiLineString * shape: in paramater, the multiLineString to compute. * struct polyline_lengths pll: out parameter, all line and segment lengths */ void msPolylineComputeLineSegments(shapeObj *shape, struct polyline_lengths *pll) { int i, j; double max_line_length=0, max_segment_length=0, segment_length; pll->ll = msSmallMalloc(shape->numlines * sizeof(struct line_lengths)); pll->total_length = 0; pll->longest_line_index = 0; for(i=0; inumlines; i++) { struct line_lengths *ll = &pll->ll[i]; double max_subline_segment_length = 0; if(shape->line[i].numpoints > 1) { ll->segment_lengths = (double*) msSmallMalloc(sizeof(double) * (shape->line[i].numpoints - 1)); } else { ll->segment_lengths = NULL; } ll->total_length = 0; for(j=1; jline[i].numpoints; j++) { segment_length = sqrt((((shape->line[i].point[j].x-shape->line[i].point[j-1].x)*(shape->line[i].point[j].x-shape->line[i].point[j-1].x)) + ((shape->line[i].point[j].y-shape->line[i].point[j-1].y)*(shape->line[i].point[j].y-shape->line[i].point[j-1].y)))); ll->total_length += segment_length; ll->segment_lengths[j-1] = segment_length; if(segment_length > max_subline_segment_length) { max_subline_segment_length = segment_length; ll->longest_segment_index = j; } if(segment_length > max_segment_length) { max_segment_length = segment_length; pll->longest_segment_line_index = i; pll->longest_segment_point_index = j; } } pll->total_length += ll->total_length; if(ll->total_length > max_line_length) { max_line_length = ll->total_length; pll->longest_line_index = i; } } } /* ** If no repeatdistance, find center of longest segment in polyline p. The polyline must have been converted ** to image coordinates before calling this function. */ int msPolylineLabelPoint(mapObj *map, shapeObj *p, textSymbolObj *ts, labelObj *label, struct label_auto_result *lar, double resolutionfactor) { struct polyline_lengths pll; int i, ret = MS_SUCCESS; double minfeaturesize = -1; assert(ts->annotext); if(label && ts) { if(label->autominfeaturesize) { if(!ts->textpath) { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,ts))) return MS_FAILURE; } minfeaturesize = ts->textpath->bounds.bbox.maxx; } else if(label->minfeaturesize) { minfeaturesize = label->minfeaturesize * resolutionfactor; } } /* compute line lengths, in order to: - extract the longest line if we're not repeating - check that each line is longer than the text length if using minfeaturesize auto - check that each line is long enough if using minfeaturesize */ msPolylineComputeLineSegments(p, &pll); if(label && label->repeatdistance > 0) { for(i=0; inumlines; i++) { if(pll.ll[i].total_length > minfeaturesize) { ret = msLineLabelPoint(map,&p->line[i], ts, &pll.ll[i],lar, label, resolutionfactor); } } } else { i = pll.longest_line_index; if(pll.ll[i].total_length > minfeaturesize) { ret = msLineLabelPoint(map,&p->line[i], ts, &pll.ll[i],lar, label, resolutionfactor); } } /* freeing memory: allocated by msPolylineComputeLineSegments */ for ( i = 0; i < p->numlines; i++ ) { free(pll.ll[i].segment_lengths); } free(pll.ll); return ret; } int msLineLabelPoint(mapObj *map, lineObj *p, textSymbolObj *ts, struct line_lengths *ll, struct label_auto_result *lar, labelObj *label, double resolutionfactor) { int j, l, n, point_repeat; double t, theta, fwd_length, point_distance; double center_point_position, left_point_position, right_point_position, point_position; double repeat_distance = -1; if(label) { repeat_distance = label->repeatdistance * resolutionfactor; } if(UNLIKELY(p->numpoints < 2)) return MS_FAILURE; point_distance = 0; point_repeat = 1; left_point_position = right_point_position = center_point_position = ll->total_length / 2.0; if (repeat_distance > 0) { point_repeat = ll->total_length / repeat_distance; if (point_repeat > 1) { if (point_repeat % 2 == 0) point_repeat -= 1; point_distance = (ll->total_length / point_repeat); /* buffer allowed per point */ /* initial point position */ left_point_position -= ((point_repeat-1)/2 * point_distance); right_point_position += ((point_repeat-1)/2 * point_distance); point_repeat = (point_repeat-1)/2+1; } else point_repeat = 1; } for (l=0; l < point_repeat; ++l) { if (l == point_repeat-1) { /* last point to place is always the center point */ point_position = center_point_position; n = 1; } else { point_position = right_point_position; n = 0; } do { lar->angles = msSmallRealloc(lar->angles, (lar->num_label_points+1)*sizeof(double)); lar->label_points = msSmallRealloc(lar->label_points, (lar->num_label_points+1)*sizeof(pointObj)); /* if there is only 1 label to place... put it in the middle of the current segment (as old behavior) */ if ( point_repeat == 1 ) { j = ll->longest_segment_index; lar->label_points[lar->num_label_points].x = (p->point[j-1].x + p->point[j].x)/2.0; lar->label_points[lar->num_label_points].y = (p->point[j-1].y + p->point[j].y)/2.0; } else { j=0; fwd_length = 0; while (fwd_length < point_position) { fwd_length += ll->segment_lengths[j++]; } assert(j>0); t = 1 - (fwd_length - point_position) / ll->segment_lengths[j-1]; lar->label_points[lar->num_label_points].x = t * (p->point[j].x - p->point[j-1].x) + p->point[j-1].x; lar->label_points[lar->num_label_points].y = t * (p->point[j].y - p->point[j-1].y) + p->point[j-1].y; } if(label && ts) { if(label->anglemode != MS_NONE) { theta = atan2(p->point[j].x - p->point[j-1].x, p->point[j].y - p->point[j-1].y); if(label->anglemode == MS_AUTO2) { theta -= MS_PI2; } else { /* AUTO, FOLLOW */ if(p->point[j-1].x < p->point[j].x) { /* i.e. to the left */ theta -= MS_PI2; } else { theta += MS_PI2; } } lar->angles[lar->num_label_points] = theta; } else { lar->angles[lar->num_label_points] = MS_DEG_TO_RAD * ts->label->angle; } } else { lar->angles[lar->num_label_points] = 0; } lar->num_label_points++; point_position = left_point_position; n++; } while (n<2); /* we place the right point then the left point. */ right_point_position -= point_distance; left_point_position += point_distance; } return MS_SUCCESS; } /* Calculate the labelpath for each line if repeatdistance is enabled, else the labelpath of the longest line segment */ int msPolylineLabelPath(mapObj *map, imageObj *image, shapeObj *p, textSymbolObj *ts, labelObj *label, struct label_follow_result *lfr) { struct polyline_lengths pll; int i,ret = MS_SUCCESS; double minfeaturesize = -1; assert(ts->annotext); lfr->num_follow_labels = lfr->lar.num_label_points = 0; /* we first offset the line if we want an offsetted label */ if(label->offsetx != 0 && IS_PERPENDICULAR_OFFSET(label->offsety)) { double offset; if(label->offsetx > 0) { offset = label->offsetx + label->size/2; } else { offset = label->offsetx - label->size/2; } if(label->offsety == MS_LABEL_PERPENDICULAR_TOP_OFFSET && p->numlines>0 && p->line[0].numpoints > 0) { /* is the line mostly left-to-right or right-to-left ? * FIXME this should be done line by line, by stepping through shape->lines, however * the OffsetPolyline function works on shapeObjs, not lineObjs * we only check the first line */ if(p->line[0].point[0].x < p->line[0].point[p->line[0].numpoints-1].x) { /* line is left to right */ offset = -offset; } } p = msOffsetPolyline(p,offset, MS_STYLE_SINGLE_SIDED_OFFSET); if(!p) return MS_FAILURE; } /* compute line lengths, in order to: - extract the longest line if we're not repeating - check that each line is longer than the text length if using minfeaturesize auto - check that each line is long enough if using minfeaturesize */ msPolylineComputeLineSegments(p, &pll); if(label->autominfeaturesize) { if(!ts->textpath) { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,ts))) { return MS_FAILURE; } } minfeaturesize = ts->textpath->bounds.bbox.maxx; } else if(label->minfeaturesize) { minfeaturesize = label->minfeaturesize * image->resolutionfactor; } if(label->repeatdistance > 0) { for(i=0; inumlines; i++) { if(pll.ll[i].total_length > minfeaturesize) { ret = msLineLabelPath(map,image,&p->line[i], ts, &pll.ll[i],lfr, label); } } } else { i = pll.longest_line_index; if(pll.ll[i].total_length > minfeaturesize) { ret = msLineLabelPath(map,image,&p->line[i], ts, &pll.ll[i],lfr, label); } } /* freeing memory: allocated by msPolylineComputeLineSegments */ for ( i = 0; i < p->numlines; i++ ) { free(pll.ll[i].segment_lengths); } free(pll.ll); if(IS_PERPENDICULAR_OFFSET(label->offsety) && label->offsetx != 0) { msFreeShape(p); msFree(p); } return ret; } static double compute_retry_offset(textSymbolObj *ts, int fail_idx, double retried_offset, double max_dec_offset, double max_inc_offset) { /* fail_idx: the glyph index in the textpath that originally failed (i.e. before any displacement was tested */ /* retried_offset: the last offset that was tried and is failing, so we can return the next one (or 0 if none left)*/ int inc = 1,dec_found=0, inc_found=0; double inc_offset = 0, dec_offset = 0; retried_offset = fabs(retried_offset); do { if(fail_idx - inc - 1 >= 0) { dec_offset += ts->textpath->glyphs[fail_idx - inc].glyph->metrics.advance; if(dec_offset > max_dec_offset) break; if(dec_offset > retried_offset && msIsGlyphASpace(&ts->textpath->glyphs[fail_idx - inc - 1])) { dec_found = 1; dec_offset += ts->textpath->glyphs[fail_idx - inc -1].glyph->metrics.advance / 2.0; break; } } inc++; } while(dec_offset0); if(!dec_found) { /* try the starting position */ dec_offset += ts->textpath->glyphs[0].glyph->metrics.advance; if(dec_offset > retried_offset && dec_offsettextpath->glyphs[fail_idx].glyph->metrics.advance; do{ if(fail_idx + inc < ts->textpath->numglyphs - 1) { if(inc_offset > retried_offset && msIsGlyphASpace(&ts->textpath->glyphs[fail_idx + inc])) { inc_offset += ts->textpath->glyphs[fail_idx + inc].glyph->metrics.advance / 2; if(inc_offset < max_inc_offset) inc_found = 1; break; } inc_offset += ts->textpath->glyphs[fail_idx + inc].glyph->metrics.advance; } inc++; } while(inc_offsettextpath->numglyphs-1); if(!inc_found) { inc_offset += ts->textpath->glyphs[ts->textpath->numglyphs-1].glyph->metrics.advance; if(inc_offset > retried_offset && inc_offsetrepeatdistance * ts->resolutionfactor; double segment_length, fwd_line_length, rev_line_length, text_length, text_start_length, label_buffer, text_end_length, cur_label_position, first_label_position; double max_retry_offset; int j,k,l,inc, final_j, label_repeat; double direction; rectObj bbox; lineObj *bounds; double t; double cx, cy; /* centre of a character, x & y values. */ double theta; double dx, dy, w, cos_t, sin_t; const double letterspacing = 1.00; /* As per RFC 60, if label->maxoverlapangle == 0 then fall back on pre-6.0 behavior which was to use maxoverlapangle = 0.4*MS_PI ( 40% of 180 degrees ) */ double maxoverlapangle = 0.4 * MS_PI; if(p->numpoints < 2) { /* degenerate */ return MS_FAILURE; } if(p->numpoints == 2) /* use the regular angled text algorithm */ return msLineLabelPoint(map,p,ts,ll,&lfr->lar,label, img->resolutionfactor); if(!ts->textpath) { if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,ts))) { return MS_FAILURE; } } /* skip the label and use the normal algorithm if it has fewer than 2 characters */ if(ts->textpath->numglyphs < 2) return msLineLabelPoint(map,p,ts,ll,&lfr->lar,label, img->resolutionfactor); text_length = letterspacing * ts->textpath->bounds.bbox.maxx; /* ** if the text length is way longer than the line, skip adding the ** label if it isn't forced (long extrapolated labels tend to be ugly) */ if ( text_length > 1.5 * ll->total_length ) { if(ts->label->force == MS_FALSE ) { return MS_SUCCESS; } else { repeat_distance = 0; /* disable repetition */ } } /* We compute the number of labels we can repeat in the line: - space occupied by one label - plus N times space occupied by one label + repeat_distance interspacing */ label_buffer = text_length + repeat_distance; /* distance occupied by one label + inter-repeat spacing */ if( repeat_distance > 0 && ll->total_length > text_length) { label_repeat = 1 + (int)((ll->total_length - text_length) / label_buffer); max_retry_offset = repeat_distance / 2.1; } else { label_repeat = 1; max_retry_offset = (ll->total_length - text_length) / 2.1; } /* compute the starting point of where we'll be placing the first label */ if(label_repeat % 2) { /* odd number of labels: account for the center label that will be centered on the line * ----llll_____llll_____llll---- */ first_label_position = (ll->total_length - text_length) / 2.0 - (label_repeat / 2) * label_buffer; } else { /* even number of labels: * repeat_distance is centered on the line * space for one label * eventually space for label_repeat*2-1 labels+spacing * ----llll_____llll---- * --llll_____llll_____llll_____llll-- */ first_label_position = (ll->total_length - repeat_distance) / 2.0 - text_length - (label_repeat/2 - 1) * label_buffer; } if(label->maxoverlapangle > 0) maxoverlapangle = label->maxoverlapangle * MS_DEG_TO_RAD; /* radian */ cur_label_position = first_label_position; for (l=0; l < label_repeat; l++) { double retry_offset = 0.0; int first_retry_idx = 0; //max_dec_retry_offset = max_inc_retry_offset = max_retry_offset; textPathObj *tp = msSmallCalloc(1,sizeof(textPathObj)); /* copy the textPath, we will be overriding the copy's positions and angles */ msCopyTextPath(tp,ts->textpath); tp->bounds.poly = msSmallMalloc(sizeof(lineObj)); bounds = tp->bounds.poly; /* ** The bounds will have two points for each character plus an endpoint: ** the UL corners of each bbox will be tied together and the LL corners ** will be tied together. */ bounds->numpoints = 2*tp->numglyphs + 1; bounds->point = (pointObj *) msSmallMalloc(sizeof(pointObj) * bounds->numpoints); do { int overlap_collision_detected = 0; text_start_length = cur_label_position + retry_offset; text_end_length = 0; for(k=0;knumglyphs;k++) { tp->glyphs[k].pnt.x = 0; tp->glyphs[k].pnt.y = 0; } /* the points start at (line_length - text_length) / 2 in order to be centred */ /* text_start_length = (line_length - text_length) / 2.0; */ j = 0; fwd_line_length = 0; if(text_start_length >= 0.0) { while ( fwd_line_length < text_start_length ) fwd_line_length += ll->segment_lengths[j++]; j--; } final_j = p->numpoints - 1; rev_line_length = 0; if(text_start_length+text_length <= ll->total_length) { text_end_length = ll->total_length - (text_start_length + text_length); while(rev_line_length < text_end_length) { rev_line_length += ll->segment_lengths[final_j - 1]; final_j--; } final_j++; } if(final_j == 0) final_j = 1; /* determine if the line is mostly left to right or right to left, see bug 1620 discussion by Steve Woodbridge */ direction = p->point[final_j].x - p->point[j].x; if(direction > 0) { inc = 1; /* j is already correct */ /* length of the segment containing the starting point */ segment_length = ll->segment_lengths[j]; /* determine how far along the segment we need to go */ if(text_start_length < 0.0) t = text_start_length / segment_length; else t = 1 - (fwd_line_length - text_start_length) / segment_length; } else { j = final_j; inc = -1; /* length of the segment containing the starting point */ segment_length = ll->segment_lengths[j-1]; if(text_start_length < 0.0) t = text_start_length / segment_length; else t = 1 - (rev_line_length - text_end_length) / segment_length; } distance_along_segment = t * segment_length; /* starting point */ theta = 0; k = 0; w = 0; while ( k < tp->numglyphs ) { double x,y; x = t * (p->point[j+inc].x - p->point[j].x) + p->point[j].x; y = t * (p->point[j+inc].y - p->point[j].y) + p->point[j].y; tp->glyphs[k].pnt.x = x; tp->glyphs[k].pnt.y = y; w = letterspacing*tp->glyphs[k].glyph->metrics.advance; /* add the character's width to the distance along the line */ distance_along_segment += w; /* if we still have segments left and we've past the current segment, move to the next one */ if(inc == 1 && j < p->numpoints - 2) { while ( j < p->numpoints - 2 && distance_along_segment > ll->segment_lengths[j] ) { distance_along_segment -= ll->segment_lengths[j]; j += inc; /* move to next segment */ } segment_length = ll->segment_lengths[j]; } else if( inc == -1 && j > 1 ) { while ( j > 1 && distance_along_segment > ll->segment_lengths[j-1] ) { distance_along_segment -= ll->segment_lengths[j-1]; j += inc; /* move to next segment */ } segment_length = ll->segment_lengths[j-1]; } /* Recalculate interpolation parameter */ t = distance_along_segment / segment_length; k++; } /* pre-calc the character's centre y value. Used for rotation adjustment. */ cy = -ts->textpath->glyph_size / 2.0; #ifdef USE_KERNEL tp->glyphs[0].pnt.x /= kernel_normal; tp->glyphs[0].pnt.y /= kernel_normal; #endif /* Average the points and calculate each angle */ overlap_collision_detected = 0; for (k = 1; k <= tp->numglyphs; k++) { double anglediff; if ( k < tp->numglyphs ) { #ifdef USE_KERNEL tp->glyphs[k].pnt.x /= kernel_normal; tp->glyphs[k].pnt.y /= kernel_normal; #endif dx = tp->glyphs[k].pnt.x - tp->glyphs[k-1].pnt.x; dy = tp->glyphs[k].pnt.y - tp->glyphs[k-1].pnt.y; } else { /* Handle the last character */ dx = t * (p->point[j+inc].x - p->point[j].x) + p->point[j].x - tp->glyphs[k-1].pnt.x; dy = t * (p->point[j+inc].y - p->point[j].y) + p->point[j].y - tp->glyphs[k-1].pnt.y; } if(dx || dy || k==1) { theta = -atan2(dy,dx); if (maxoverlapangle > 0 && k > 1) { /* no use testing for overlap if glyph or previous glyph is a space */ if(!msIsGlyphASpace(&tp->glyphs[k-1]) && !msIsGlyphASpace(&tp->glyphs[k-2])) { /* If the difference between the last char angle and the current one is greater than the MAXOVERLAPANGLE value (set at 80% of 180deg by default) , bail the label */ anglediff = fabs(theta - tp->glyphs[k-2].rot); anglediff = MS_MIN(anglediff, MS_2PI - anglediff); if(anglediff > maxoverlapangle ) { double max_dec_retry_offset; double max_inc_retry_offset; if(label_repeat == 1) { max_dec_retry_offset = max_inc_retry_offset = first_label_position; } else if(l==0) { if(direction>0) { max_dec_retry_offset = MS_MIN(first_label_position, max_retry_offset); max_inc_retry_offset = max_retry_offset; } else { max_dec_retry_offset = max_retry_offset; max_inc_retry_offset = MS_MIN(first_label_position, max_retry_offset); //max_inc_retry_offset = MS_MIN(ll->total_length-cur_label_position-text_length, max_retry_offset); } } else if(l == label_repeat-1) { if(direction>0) { max_inc_retry_offset = MS_MIN(first_label_position, max_retry_offset); max_dec_retry_offset = max_retry_offset; } else { max_inc_retry_offset = max_retry_offset; max_dec_retry_offset = MS_MIN(first_label_position, max_retry_offset); //max_inc_retry_offset = MS_MIN(ll->total_length-cur_label_position-text_length, max_retry_offset); } } else { max_dec_retry_offset = max_inc_retry_offset = max_retry_offset; } overlap_collision_detected = 1; if(retry_offset == 0.0) { first_retry_idx = k-1; } retry_offset = compute_retry_offset(ts, first_retry_idx, retry_offset, max_inc_retry_offset, max_dec_retry_offset); if(retry_offset == 0.0) { /* no offsetted position to try */ freeTextPath(tp); free(tp); } else { if(direction<0) { retry_offset = -retry_offset; } } break; } } } } else { /* * handle the 0-advance case, as the complex text shaping may have placed multiple * glyphs at the same position */ theta = tp->glyphs[k-2].rot; } /* msDebug("s: %c (x,y): (%0.2f,%0.2f) t: %0.2f\n", string[k-1], labelpath->path.point[k-1].x, labelpath->path.point[k-1].y, theta); */ tp->glyphs[k-1].rot = theta; /* Move the previous point so that when the character is rotated and placed it is centred on the line */ cos_t = cos(theta); sin_t = sin(theta); w = letterspacing*tp->glyphs[k-1].glyph->metrics.advance; cx = 0; /* Center the character vertically only */ dx = - (cx * cos_t + cy * sin_t); dy = - (cy * cos_t - cx * sin_t); tp->glyphs[k-1].pnt.x += dx; tp->glyphs[k-1].pnt.y += dy; /* Calculate the bounds */ bbox.minx = 0; bbox.maxx = w; bbox.maxy = 0; bbox.miny = -ts->textpath->glyph_size; /* Add the label buffer to the bounds */ bbox.maxx += ts->label->buffer * ts->resolutionfactor; bbox.maxy += ts->label->buffer * ts->resolutionfactor; bbox.minx -= ts->label->buffer * ts->resolutionfactor; bbox.miny -= ts->label->buffer * ts->resolutionfactor; if ( k < tp->numglyphs ) { /* Transform the bbox too. We take the UL and LL corners and rotate then translate them. */ bounds->point[k-1].x = (bbox.minx * cos_t + bbox.maxy * sin_t) + tp->glyphs[k-1].pnt.x; bounds->point[k-1].y = (bbox.maxy * cos_t - bbox.minx * sin_t) + tp->glyphs[k-1].pnt.y; /* Start at end and work towards the half way point */ bounds->point[bounds->numpoints - k - 1].x = (bbox.minx * cos_t + bbox.miny * sin_t) + tp->glyphs[k-1].pnt.x; bounds->point[bounds->numpoints - k - 1].y = (bbox.miny * cos_t - bbox.minx * sin_t) + tp->glyphs[k-1].pnt.y; } else { /* This is the last character in the string so we take the UR and LR corners of the bbox */ bounds->point[k-1].x = (bbox.maxx * cos_t + bbox.maxy * sin_t) + tp->glyphs[k-1].pnt.x; bounds->point[k-1].y = (bbox.maxy * cos_t - bbox.maxx * sin_t) + tp->glyphs[k-1].pnt.y; bounds->point[bounds->numpoints - k - 1].x = (bbox.maxx * cos_t + bbox.miny * sin_t) + tp->glyphs[k-1].pnt.x; bounds->point[bounds->numpoints - k - 1].y = (bbox.miny * cos_t - bbox.maxx * sin_t) + tp->glyphs[k-1].pnt.y; } } if(overlap_collision_detected) { continue; } /* Close the bounds */ bounds->point[bounds->numpoints - 1].x = bounds->point[0].x; bounds->point[bounds->numpoints - 1].y = bounds->point[0].y; /* compute the bounds */ fastComputeBounds(bounds,&tp->bounds.bbox); { textPathObj *tmptp; textSymbolObj *tsnew; lfr->num_follow_labels++; lfr->follow_labels = msSmallRealloc(lfr->follow_labels,lfr->num_follow_labels * sizeof(textSymbolObj*)); tmptp = ts->textpath; ts->textpath = NULL; lfr->follow_labels[lfr->num_follow_labels - 1] = msSmallMalloc(sizeof(textSymbolObj)); tsnew = lfr->follow_labels[lfr->num_follow_labels - 1]; initTextSymbol(tsnew); msCopyTextSymbol(tsnew,ts); ts->textpath = tmptp; tsnew->textpath = tp; tsnew->textpath->absolute = 1; } cur_label_position += label_buffer; retry_offset = 0; } while(retry_offset); } return MS_SUCCESS; } /* =========================================================================== Pretty printing of primitive objects ======================================================================== */ void msRectToFormattedString(rectObj *rect, char *format, char *buffer, int buffer_length) { snprintf(buffer, buffer_length, format, rect->minx, rect->miny, rect->maxx, rect->maxy); } void msPointToFormattedString(pointObj *point, const char *format, char *buffer, int buffer_length) { #ifdef USE_POINT_Z_M snprintf(buffer, buffer_length, format, point->x, point->y, point->z, point->m); #else snprintf(buffer, buffer_length, format, point->x, point->y); #endif } /* Returns true if a shape contains only degenerate parts */ int msIsDegenerateShape(shapeObj *shape) { int i; int non_degenerate_parts = 0; for(i=0; inumlines; i++) { /* e.g. part */ /* skip degenerate parts, really should only happen with pixel output */ if((shape->type == MS_SHAPE_LINE && shape->line[i].numpoints < 2) || (shape->type == MS_SHAPE_POLYGON && shape->line[i].numpoints < 3)) continue; non_degenerate_parts++; } return( non_degenerate_parts == 0 ); } mapserver-7.4.3/mapprimitive.h000066400000000000000000000054631357574274700164450ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations for rectObj, pointObj, lineObj, shapeObj, etc. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPPRIMITIVE_H #define MAPPRIMITIVE_H /* feature primitives */ typedef struct { double minx, miny, maxx, maxy; } rectObj; #ifndef SWIG typedef struct { double x; double y; } vectorObj; #endif /*SWIG*/ typedef struct { double x; double y; #ifdef USE_POINT_Z_M double z; double m; #endif } pointObj; typedef struct { #ifdef SWIG %immutable; #endif int numpoints; #ifndef SWIG pointObj *point; #endif #ifdef SWIG %mutable; #endif } lineObj; typedef struct { #ifdef SWIG %immutable; #endif int numlines; int numvalues; #ifndef SWIG lineObj *line; char **values; void *geometry; void *renderer_cache; #endif #ifdef SWIG %mutable; #endif rectObj bounds; int type; /* MS_SHAPE_TYPE */ long index; int tileindex; int classindex; char *text; int scratch; int resultindex; /* index within a query result set */ } shapeObj; typedef lineObj multipointObj; #ifndef SWIG /* attribute primatives */ typedef struct { char *name; long type; int index; int size; short numdecimals; } itemObj; #endif #ifndef SWIG typedef struct { int need_geotransform; double rotation_angle; double geotransform[6]; /* Pixel/line to georef. */ double invgeotransform[6]; /* georef to pixel/line */ } geotransformObj; #endif #endif /* MAPPRIMITIVE_H */ mapserver-7.4.3/mapproject.c000066400000000000000000001472471357574274700161050ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: projectionObj / PROJ.4 interface. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "mapproject.h" #include "mapthread.h" #include #include #include #include "mapaxisorder.h" #ifdef USE_PROJ static int msTestNeedWrap( pointObj pt1, pointObj pt2, pointObj pt2_geo, projectionObj *src_proj, projectionObj *dst_proj ); #endif /************************************************************************/ /* int msIsAxisInverted */ /* Check to see if we should invert the axis. */ /* */ /************************************************************************/ int msIsAxisInverted(int epsg_code) { const unsigned int row = epsg_code / 8; const unsigned char index = epsg_code % 8; /*check the static table*/ if ((row < sizeof(axisOrientationEpsgCodes)) && (axisOrientationEpsgCodes[row] & (1 << index))) return MS_TRUE; else return MS_FALSE; } /************************************************************************/ /* msProjectPoint() */ /************************************************************************/ int msProjectPoint(projectionObj *in, projectionObj *out, pointObj *point) { #ifdef USE_PROJ projUV p; int error; if( in && in->gt.need_geotransform ) { double x_out, y_out; x_out = in->gt.geotransform[0] + in->gt.geotransform[1] * point->x + in->gt.geotransform[2] * point->y; y_out = in->gt.geotransform[3] + in->gt.geotransform[4] * point->x + in->gt.geotransform[5] * point->y; point->x = x_out; point->y = y_out; } /* -------------------------------------------------------------------- */ /* If the source and destination are simple and equal, then do */ /* nothing. */ /* -------------------------------------------------------------------- */ if( in && in->numargs == 1 && out && out->numargs == 1 && strcmp(in->args[0],out->args[0]) == 0 ) { /* do nothing, no transformation required */ } /* -------------------------------------------------------------------- */ /* If we have a fully defined input coordinate system and */ /* output coordinate system, then we will use pj_transform. */ /* -------------------------------------------------------------------- */ else if( in && in->proj && out && out->proj ) { double z = 0.0; if( pj_is_latlong(in->proj) ) { point->x *= DEG_TO_RAD; point->y *= DEG_TO_RAD; } #if PJ_VERSION < 480 msAcquireLock( TLOCK_PROJ ); #endif error = pj_transform( in->proj, out->proj, 1, 0, &(point->x), &(point->y), &z ); #if PJ_VERSION < 480 msReleaseLock( TLOCK_PROJ ); #endif if( error || point->x == HUGE_VAL || point->y == HUGE_VAL ) { // msSetError(MS_PROJERR,"proj says: %s","msProjectPoint()",pj_strerrno(error)); return MS_FAILURE; } if( pj_is_latlong(out->proj) ) { point->x *= RAD_TO_DEG; point->y *= RAD_TO_DEG; } } /* -------------------------------------------------------------------- */ /* Otherwise we fallback to using pj_fwd() or pj_inv() and */ /* assuming that the NULL projectionObj is supposed to be */ /* lat/long in the same datum as the other projectionObj. This */ /* is essentially a backwards compatibility mode. */ /* -------------------------------------------------------------------- */ else { /* nothing to do if the other coordinate system is also lat/long */ if( in == NULL && (out == NULL || pj_is_latlong(out->proj) )) return MS_SUCCESS; if( out == NULL && in != NULL && pj_is_latlong(in->proj) ) return MS_SUCCESS; p.u = point->x; p.v = point->y; if(in==NULL || in->proj==NULL) { /* input coordinates are lat/lon */ p.u *= DEG_TO_RAD; /* convert to radians */ p.v *= DEG_TO_RAD; p = pj_fwd(p, out->proj); } else { if(out==NULL || out->proj==NULL) { /* output coordinates are lat/lon */ p = pj_inv(p, in->proj); p.u *= RAD_TO_DEG; /* convert to decimal degrees */ p.v *= RAD_TO_DEG; } else { /* need to go from one projection to another */ p = pj_inv(p, in->proj); p = pj_fwd(p, out->proj); } } if( p.u == HUGE_VAL || p.v == HUGE_VAL ) return MS_FAILURE; point->x = p.u; point->y = p.v; } if( out && out->gt.need_geotransform ) { double x_out, y_out; x_out = out->gt.invgeotransform[0] + out->gt.invgeotransform[1] * point->x + out->gt.invgeotransform[2] * point->y; y_out = out->gt.invgeotransform[3] + out->gt.invgeotransform[4] * point->x + out->gt.invgeotransform[5] * point->y; point->x = x_out; point->y = y_out; } return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectPoint()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectGrowRect() */ /************************************************************************/ #ifdef USE_PROJ static void msProjectGrowRect(projectionObj *in, projectionObj *out, rectObj *prj_rect, int *rect_initialized, pointObj *prj_point, int *failure ) { if( msProjectPoint(in, out, prj_point) == MS_SUCCESS ) { if( *rect_initialized ) { prj_rect->miny = MS_MIN(prj_rect->miny, prj_point->y); prj_rect->maxy = MS_MAX(prj_rect->maxy, prj_point->y); prj_rect->minx = MS_MIN(prj_rect->minx, prj_point->x); prj_rect->maxx = MS_MAX(prj_rect->maxx, prj_point->x); } else { prj_rect->minx = prj_rect->maxx = prj_point->x; prj_rect->miny = prj_rect->maxy = prj_point->y; *rect_initialized = MS_TRUE; } } else (*failure)++; } #endif /* def USE_PROJ */ /************************************************************************/ /* msProjectSegment() */ /* */ /* Interpolate along a line segment for which one end */ /* reprojects and the other end does not. Finds the horizon. */ /************************************************************************/ #ifdef USE_PROJ static int msProjectSegment( projectionObj *in, projectionObj *out, pointObj *start, pointObj *end ) { pointObj testPoint, subStart, subEnd; /* -------------------------------------------------------------------- */ /* Without loss of generality we assume the first point */ /* reprojects, and the second doesn't. If that is not the case */ /* then re-call with the points reversed. */ /* -------------------------------------------------------------------- */ testPoint = *start; if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE ) { testPoint = *end; if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE ) return MS_FAILURE; else return msProjectSegment( in, out, end, start ); } /* -------------------------------------------------------------------- */ /* We will apply a binary search till we are within out */ /* tolerance. */ /* -------------------------------------------------------------------- */ subStart = *start; subEnd = *end; #define TOLERANCE 0.01 while( fabs(subStart.x - subEnd.x) + fabs(subStart.y - subEnd.y) > TOLERANCE ) { pointObj midPoint; midPoint.x = (subStart.x + subEnd.x) * 0.5; midPoint.y = (subStart.y + subEnd.y) * 0.5; testPoint = midPoint; if( msProjectPoint( in, out, &testPoint ) == MS_FAILURE ) { if (midPoint.x == subEnd.x && midPoint.y == subEnd.y) return MS_FAILURE; /* break infinite loop */ subEnd = midPoint; } else { if (midPoint.x == subStart.x && midPoint.y == subStart.y) return MS_FAILURE; /* break infinite loop */ subStart = midPoint; } } /* -------------------------------------------------------------------- */ /* Now reproject the end points and return. */ /* -------------------------------------------------------------------- */ *end = subStart; if( msProjectPoint( in, out, end ) == MS_FAILURE || msProjectPoint( in, out, start ) == MS_FAILURE ) return MS_FAILURE; else return MS_SUCCESS; } #endif /************************************************************************/ /* msProjectShapeLine() */ /* */ /* Reproject a single linestring, potentially splitting into */ /* more than one line string if there are over the horizon */ /* portions. */ /* */ /* For polygons, no splitting takes place, but over the horizon */ /* points are clipped, and one segment is run from the fall */ /* over the horizon point to the come back over the horizon point. */ /************************************************************************/ #ifdef USE_PROJ static int msProjectShapeLine(projectionObj *in, projectionObj *out, shapeObj *shape, int line_index) { int i; pointObj lastPoint, thisPoint, wrkPoint; lineObj *line = shape->line + line_index; lineObj *line_out = line; int valid_flag = 0; /* 1=true, -1=false, 0=unknown */ int numpoints_in = line->numpoints; int line_alloc = numpoints_in; int wrap_test; #ifdef USE_PROJ_FASTPATHS #define MAXEXTENT 20037508.34 #define M_PIby360 .0087266462599716479 #define MAXEXTENTby180 111319.4907777777777777777 #define p_x line->point[i].x #define p_y line->point[i].y if(in->wellknownprojection == wkp_lonlat && out->wellknownprojection == wkp_gmerc) { for( i = line->numpoints-1; i >= 0; i-- ) { p_x *= MAXEXTENTby180; p_y = log(tan((90 + p_y) * M_PIby360)) * MS_RAD_TO_DEG; p_y *= MAXEXTENTby180; if (p_x > MAXEXTENT) p_x = MAXEXTENT; if (p_x < -MAXEXTENT) p_x = -MAXEXTENT; if (p_y > MAXEXTENT) p_y = MAXEXTENT; if (p_y < -MAXEXTENT) p_y = -MAXEXTENT; } return MS_SUCCESS; } if(in->wellknownprojection == wkp_gmerc && out->wellknownprojection == wkp_lonlat) { for( i = line->numpoints-1; i >= 0; i-- ) { if (p_x > MAXEXTENT) p_x = MAXEXTENT; else if (p_x < -MAXEXTENT) p_x = -MAXEXTENT; if (p_y > MAXEXTENT) p_y = MAXEXTENT; else if (p_y < -MAXEXTENT) p_y = -MAXEXTENT; p_x = (p_x / MAXEXTENT) * 180; p_y = (p_y / MAXEXTENT) * 180; p_y = MS_RAD_TO_DEG * (2 * atan(exp(p_y * MS_DEG_TO_RAD)) - MS_PI2); } msComputeBounds( shape ); /* fixes bug 1586 */ return MS_SUCCESS; } #undef p_x #undef p_y #endif wrap_test = out != NULL && out->proj != NULL && pj_is_latlong(out->proj) && !pj_is_latlong(in->proj); line->numpoints = 0; memset( &lastPoint, 0, sizeof(lastPoint) ); /* -------------------------------------------------------------------- */ /* Loop over all input points in linestring. */ /* -------------------------------------------------------------------- */ for( i=0; i < numpoints_in; i++ ) { int ms_err; wrkPoint = thisPoint = line->point[i]; ms_err = msProjectPoint(in, out, &wrkPoint ); /* -------------------------------------------------------------------- */ /* Apply wrap logic. */ /* -------------------------------------------------------------------- */ if( wrap_test && i > 0 && ms_err != MS_FAILURE ) { double dist; pointObj pt1Geo; if( line_out->numpoints > 0 ) pt1Geo = line_out->point[line_out->numpoints-1]; else pt1Geo = wrkPoint; /* this is a cop out */ dist = wrkPoint.x - pt1Geo.x; if( fabs(dist) > 180.0 && msTestNeedWrap( thisPoint, lastPoint, pt1Geo, in, out ) ) { if( dist > 0.0 ) wrkPoint.x -= 360.0; else if( dist < 0.0 ) wrkPoint.x += 360.0; } } /* -------------------------------------------------------------------- */ /* Put result into output line with appropriate logic for */ /* failure breaking lines, etc. */ /* -------------------------------------------------------------------- */ if( ms_err == MS_FAILURE ) { /* We have started out invalid */ if( i == 0 ) { valid_flag = -1; } /* valid data has ended, we need to work out the horizon */ else if( valid_flag == 1 ) { pointObj startPoint, endPoint; startPoint = lastPoint; endPoint = thisPoint; if( msProjectSegment( in, out, &startPoint, &endPoint ) == MS_SUCCESS ) { line_out->point[line_out->numpoints++] = endPoint; } valid_flag = -1; } /* Still invalid ... */ else if( valid_flag == -1 ) { /* do nothing */ } } else { /* starting out valid. */ if( i == 0 ) { line_out->point[line_out->numpoints++] = wrkPoint; valid_flag = 1; } /* Still valid, nothing special */ else if( valid_flag == 1 ) { line_out->point[line_out->numpoints++] = wrkPoint; } /* we have come over the horizon, figure out where, start newline*/ else { pointObj startPoint, endPoint; startPoint = lastPoint; endPoint = thisPoint; if( msProjectSegment( in, out, &endPoint, &startPoint ) == MS_SUCCESS ) { lineObj newLine; /* force pre-allocation of lots of points room */ if( line_out->numpoints > 0 && shape->type == MS_SHAPE_LINE ) { newLine.numpoints = numpoints_in - i + 1; newLine.point = line->point; msAddLine( shape, &newLine ); /* new line is now lineout, but start without any points */ line_out = shape->line + shape->numlines-1; line_out->numpoints = 0; /* the shape->line array is realloc, refetch "line" */ line = shape->line + line_index; } else if( line_out == line && line->numpoints >= i-2 ) { newLine.numpoints = numpoints_in; newLine.point = line->point; msAddLine( shape, &newLine ); line = shape->line + line_index; line_out = shape->line + shape->numlines-1; line_out->numpoints = line->numpoints; line->numpoints = 0; /* * Now realloc this array large enough to hold all * the points we could possibly need to add. */ line_alloc = line_alloc * 2; line_out->point = (pointObj *) realloc(line_out->point, sizeof(pointObj) * line_alloc); } line_out->point[line_out->numpoints++] = startPoint; } line_out->point[line_out->numpoints++] = wrkPoint; valid_flag = 1; } } lastPoint = thisPoint; } /* -------------------------------------------------------------------- */ /* Make sure that polygons are closed, even if the trip over */ /* the horizon left them unclosed. */ /* -------------------------------------------------------------------- */ if( shape->type == MS_SHAPE_POLYGON && line_out->numpoints > 2 && (line_out->point[0].x != line_out->point[line_out->numpoints-1].x || line_out->point[0].y != line_out->point[line_out->numpoints-1].y) ) { /* make a copy because msAddPointToLine can realloc the array */ pointObj sFirstPoint = line_out->point[0]; msAddPointToLine( line_out, &sFirstPoint ); } return(MS_SUCCESS); } #endif /************************************************************************/ /* msProjectShape() */ /************************************************************************/ int msProjectShape(projectionObj *in, projectionObj *out, shapeObj *shape) { #ifdef USE_PROJ int i; #ifdef USE_PROJ_FASTPATHS int j; #define p_x shape->line[i].point[j].x #define p_y shape->line[i].point[j].y if(in->wellknownprojection == wkp_lonlat && out->wellknownprojection == wkp_gmerc) { for( i = shape->numlines-1; i >= 0; i-- ) { for( j = shape->line[i].numpoints-1; j >= 0; j-- ) { p_x *= MAXEXTENTby180; p_y = log(tan((90 + p_y) * M_PIby360)) * MS_RAD_TO_DEG; p_y *= MAXEXTENTby180; if (p_x > MAXEXTENT) p_x = MAXEXTENT; else if (p_x < -MAXEXTENT) p_x = -MAXEXTENT; if (p_y > MAXEXTENT) p_y = MAXEXTENT; else if (p_y < -MAXEXTENT) p_y = -MAXEXTENT; } } msComputeBounds( shape ); /* fixes bug 1586 */ return MS_SUCCESS; } if(in->wellknownprojection == wkp_gmerc && out->wellknownprojection == wkp_lonlat) { for( i = shape->numlines-1; i >= 0; i-- ) { for( j = shape->line[i].numpoints-1; j >= 0; j-- ) { if (p_x > MAXEXTENT) p_x = MAXEXTENT; else if (p_x < -MAXEXTENT) p_x = -MAXEXTENT; if (p_y > MAXEXTENT) p_y = MAXEXTENT; else if (p_y < -MAXEXTENT) p_y = -MAXEXTENT; p_x = (p_x / MAXEXTENT) * 180; p_y = (p_y / MAXEXTENT) * 180; p_y = MS_RAD_TO_DEG * (2 * atan(exp(p_y * MS_DEG_TO_RAD)) - MS_PI2); } } msComputeBounds( shape ); /* fixes bug 1586 */ return MS_SUCCESS; } #undef p_x #undef p_y #endif for( i = shape->numlines-1; i >= 0; i-- ) { if( shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON ) { if( msProjectShapeLine( in, out, shape, i ) == MS_FAILURE ) msShapeDeleteLine( shape, i ); } else if( msProjectLine(in, out, shape->line+i ) == MS_FAILURE ) { msShapeDeleteLine( shape, i ); } } if( shape->numlines == 0 ) { msFreeShape( shape ); return MS_FAILURE; } else { msComputeBounds( shape ); /* fixes bug 1586 */ return(MS_SUCCESS); } #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectShape()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectLine() */ /* */ /* This function is now normally only used for point data. */ /* msProjectShapeLine() is used for lines and polygons and has */ /* lots of logic to handle horizon crossing. */ /************************************************************************/ int msProjectLine(projectionObj *in, projectionObj *out, lineObj *line) { #ifdef USE_PROJ int i, be_careful = 1; if( be_careful ) be_careful = out->proj != NULL && pj_is_latlong(out->proj) && !pj_is_latlong(in->proj); if( be_careful ) { pointObj startPoint, thisPoint; /* locations in projected space */ startPoint = line->point[0]; for(i=0; inumpoints; i++) { double dist; thisPoint = line->point[i]; /* ** Read comments before msTestNeedWrap() to better understand ** this dateline wrapping logic. */ msProjectPoint(in, out, &(line->point[i])); if( i > 0 ) { dist = line->point[i].x - line->point[0].x; if( fabs(dist) > 180.0 ) { if( msTestNeedWrap( thisPoint, startPoint, line->point[0], in, out ) ) { if( dist > 0.0 ) { line->point[i].x -= 360.0; } else if( dist < 0.0 ) { line->point[i].x += 360.0; } } } } } } else { for(i=0; inumpoints; i++) { if( msProjectPoint(in, out, &(line->point[i])) == MS_FAILURE ) return MS_FAILURE; } } return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectLine()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectRectGrid() */ /************************************************************************/ #define NUMBER_OF_SAMPLE_POINTS 100 int msProjectRectGrid(projectionObj *in, projectionObj *out, rectObj *rect) { #ifdef USE_PROJ pointObj prj_point; rectObj prj_rect; int rect_initialized = MS_FALSE, failure=0; int ix, iy; double dx, dy; double x, y; dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS; dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS; /* first ensure the top left corner is processed, even if the rect turns out to be degenerate. */ prj_point.x = rect->minx; prj_point.y = rect->miny; #ifdef USE_POINT_Z_M prj_point.z = 0.0; prj_point.m = 0.0; #endif /* USE_POINT_Z_M */ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); failure = 0; for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ ) { x = rect->minx + ix * dx; for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ ) { y = rect->miny + iy * dy; prj_point.x = x; prj_point.y = y; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); } } if( !rect_initialized ) { prj_rect.minx = 0; prj_rect.maxx = 0; prj_rect.miny = 0; prj_rect.maxy = 0; msSetError(MS_PROJERR, "All points failed to reproject.", "msProjectRect()"); } else { msDebug( "msProjectRect(): some points failed to reproject, doing internal sampling.\n" ); } rect->minx = prj_rect.minx; rect->miny = prj_rect.miny; rect->maxx = prj_rect.maxx; rect->maxy = prj_rect.maxy; if( !rect_initialized ) return MS_FAILURE; else return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectRectTraditionalEdge() */ /************************************************************************/ #ifdef notdef static int msProjectRectTraditionalEdge(projectionObj *in, projectionObj *out, rectObj *rect) { #ifdef USE_PROJ pointObj prj_point; rectObj prj_rect; int rect_initialized = MS_FALSE, failure=0; int ix, iy; double dx, dy; double x, y; dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS; dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS; /* first ensure the top left corner is processed, even if the rect turns out to be degenerate. */ prj_point.x = rect->minx; prj_point.y = rect->miny; #ifdef USE_POINT_Z_M prj_point.z = 0.0; prj_point.m = 0.0; #endif /* USE_POINT_Z_M */ msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); /* sample along top and bottom */ if(dx > 0) { for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ ) { x = rect->minx + ix * dx; prj_point.x = x; prj_point.y = rect->miny; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); prj_point.x = x; prj_point.y = rect->maxy; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); } } /* sample along left and right */ if(dy > 0) { for(iy = 0; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ ) { y = rect->miny + iy * dy; prj_point.y = y; prj_point.x = rect->minx; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); prj_point.x = rect->maxx; prj_point.y = y; msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point, &failure); } } /* ** If there have been any failures around the edges, then we had better ** try and fill in the interior to get a close bounds. */ if( failure > 0 ) return msProjectRectGrid( in, out, rect ); rect->minx = prj_rect.minx; rect->miny = prj_rect.miny; rect->maxx = prj_rect.maxx; rect->maxy = prj_rect.maxy; if( !rect_initialized ) return MS_FAILURE; else return(MS_SUCCESS); #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()"); return(MS_FAILURE); #endif } #endif /* def notdef */ /************************************************************************/ /* msProjectRectAsPolygon() */ /************************************************************************/ static int msProjectRectAsPolygon(projectionObj *in, projectionObj *out, rectObj *rect) { #ifdef USE_PROJ shapeObj polygonObj; lineObj ring; /* pointObj ringPoints[NUMBER_OF_SAMPLE_POINTS*4+4]; */ pointObj *ringPoints; int ix, iy, ixy; double dx, dy; /* If projecting from longlat to projected */ /* This hack was introduced for WFS 2.0 compliance testing, but is far */ /* from being perfect */ if( out && !pj_is_latlong(out->proj) && in && pj_is_latlong(in->proj) && fabs(rect->minx - -180.0) < 1e-5 && fabs(rect->miny - -90.0) < 1e-5 && fabs(rect->maxx - 180.0) < 1e-5 && fabs(rect->maxy - 90.0) < 1e-5) { pointObj pointTest; pointTest.x = -180; pointTest.y = 85; msProjectPoint(in, out, &pointTest); /* Detect if we are reprojecting from EPSG:4326 to EPSG:3857 */ /* and if so use more plausible bounds to avoid issues with computed */ /* resolution for WCS */ if (fabs(pointTest.x - -20037508.3427892) < 1e-5 && fabs(pointTest.y - 19971868.8804086) ) { rect->minx = -20037508.3427892; rect->miny = -20037508.3427892; rect->maxx = 20037508.3427892; rect->maxy = 20037508.3427892; } else { rect->minx = -1e15; rect->miny = -1e15; rect->maxx = 1e15; rect->maxy = 1e15; } return MS_SUCCESS; } /* -------------------------------------------------------------------- */ /* Build polygon as steps around the source rectangle */ /* and possibly its diagonal. */ /* -------------------------------------------------------------------- */ dx = (rect->maxx - rect->minx)/NUMBER_OF_SAMPLE_POINTS; dy = (rect->maxy - rect->miny)/NUMBER_OF_SAMPLE_POINTS; if(dx==0 && dy==0) { pointObj foo; msDebug( "msProjectRect(): Warning: degenerate rect {%f,%f,%f,%f}\n",rect->minx,rect->miny,rect->minx,rect->miny ); foo.x = rect->minx; foo.y = rect->miny; msProjectPoint(in,out,&foo); rect->minx=rect->maxx=foo.x; rect->miny=rect->maxy=foo.y; return MS_SUCCESS; } /* If there is more than two sample points we will also get samples from the diagonal line */ ringPoints = (pointObj*) calloc(sizeof(pointObj),NUMBER_OF_SAMPLE_POINTS*5+3); ring.point = ringPoints; ring.numpoints = 0; msInitShape( &polygonObj ); polygonObj.type = MS_SHAPE_POLYGON; /* sample along top */ if(dx != 0) { for(ix = 0; ix <= NUMBER_OF_SAMPLE_POINTS; ix++ ) { ringPoints[ring.numpoints].x = rect->minx + ix * dx; ringPoints[ring.numpoints++].y = rect->miny; } } /* sample along right side */ if(dy != 0) { for(iy = 1; iy <= NUMBER_OF_SAMPLE_POINTS; iy++ ) { ringPoints[ring.numpoints].x = rect->maxx; ringPoints[ring.numpoints++].y = rect->miny + iy * dy; } } /* sample along bottom */ if(dx != 0) { for(ix = NUMBER_OF_SAMPLE_POINTS-1; ix >= 0; ix-- ) { ringPoints[ring.numpoints].x = rect->minx + ix * dx; ringPoints[ring.numpoints++].y = rect->maxy; } } /* sample along left side */ if(dy != 0) { for(iy = NUMBER_OF_SAMPLE_POINTS-1; iy >= 0; iy-- ) { ringPoints[ring.numpoints].x = rect->minx; ringPoints[ring.numpoints++].y = rect->miny + iy * dy; } } /* sample along diagonal line */ /* This is done to handle cases where reprojection from world covering projection to one */ /* which isn't could cause min and max values of the projected rectangle to be invalid */ if(dy != 0 && dx != 0) { /* No need to compute corners as they've already been computed */ for(ixy = NUMBER_OF_SAMPLE_POINTS-2; ixy >= 1; ixy-- ) { ringPoints[ring.numpoints].x = rect->minx + ixy * dx; ringPoints[ring.numpoints++].y = rect->miny + ixy * dy; } } msAddLineDirectly( &polygonObj, &ring ); #ifdef notdef FILE *wkt = fopen("/tmp/www-before.wkt","w"); char *tmp = msShapeToWKT(&polygonObj); fprintf(wkt,"%s\n", tmp); free(tmp); fclose(wkt); #endif /* -------------------------------------------------------------------- */ /* Attempt to reproject. */ /* -------------------------------------------------------------------- */ msProjectShapeLine( in, out, &polygonObj, 0 ); /* If no points reprojected, try a grid sampling */ if( polygonObj.numlines == 0 || polygonObj.line[0].numpoints == 0 ) { msFreeShape( &polygonObj ); return msProjectRectGrid( in, out, rect ); } #ifdef notdef wkt = fopen("/tmp/www-after.wkt","w"); tmp = msShapeToWKT(&polygonObj); fprintf(wkt,"%s\n", tmp); free(tmp); fclose(wkt); #endif /* -------------------------------------------------------------------- */ /* Collect bounds. */ /* -------------------------------------------------------------------- */ rect->minx = rect->maxx = polygonObj.line[0].point[0].x; rect->miny = rect->maxy = polygonObj.line[0].point[0].y; for( ix = 1; ix < polygonObj.line[0].numpoints; ix++ ) { pointObj *pnt = polygonObj.line[0].point + ix; rect->minx = MS_MIN(rect->minx,pnt->x); rect->maxx = MS_MAX(rect->maxx,pnt->x); rect->miny = MS_MIN(rect->miny,pnt->y); rect->maxy = MS_MAX(rect->maxy,pnt->y); } msFreeShape( &polygonObj ); /* -------------------------------------------------------------------- */ /* Special case to handle reprojection from "more than the */ /* whole world" projected coordinates that sometimes produce a */ /* region greater than 360 degrees wide due to various wrapping */ /* logic. */ /* -------------------------------------------------------------------- */ if( out && pj_is_latlong(out->proj) && in && !pj_is_latlong(in->proj) && rect->maxx - rect->minx > 360.0 && !out->gt.need_geotransform ) { rect->maxx = 180; rect->minx = -180; } return MS_SUCCESS; #else msSetError(MS_PROJERR, "Projection support is not available.", "msProjectRect()"); return(MS_FAILURE); #endif } /************************************************************************/ /* msProjectHasLonWrap() */ /************************************************************************/ int msProjectHasLonWrap(projectionObj *in, double* pdfLonWrap) { int i; if( pdfLonWrap ) *pdfLonWrap = 0; #if USE_PROJ if( !pj_is_latlong(in->proj) ) return MS_FALSE; #endif for( i = 0; i < in->numargs; i++ ) { if( strncmp(in->args[i], "lon_wrap=", strlen("lon_wrap=")) == 0 ) { if( pdfLonWrap ) *pdfLonWrap = atof(in->args[i] + strlen("lon_wrap=")); return MS_TRUE; } } return MS_FALSE; } /************************************************************************/ /* msProjectRect() */ /************************************************************************/ int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect) { #ifdef notdef return msProjectRectTraditionalEdge( in, out, rect ); #else char *over = "+over"; int ret; int bFreeInOver = MS_FALSE; int bFreeOutOver = MS_FALSE; projectionObj in_over,out_over,*inp,*outp; double dfLonWrap = 0.0; #if USE_PROJ /* Detect projecting from north polar stereographic to longlat */ if( in && !in->gt.need_geotransform && out && !out->gt.need_geotransform && !pj_is_latlong(in->proj) && pj_is_latlong(out->proj) ) { pointObj p; p.x = 0.0; p.y = 0.0; if( msProjectPoint(in, out, &p) == MS_SUCCESS && fabs(p.y - 90) < 1e-8 ) { /* Is the pole in the rectangle ? */ if( 0 >= rect->minx && 0 >= rect->miny && 0 <= rect->maxx && 0 <= rect->maxy ) { if( msProjectRectAsPolygon(in, out, rect ) == MS_SUCCESS ) { rect->minx = -180.0; rect->maxx = 180.0; rect->maxy = 90.0; return MS_SUCCESS; } } /* Are we sure the dateline is not enclosed ? */ else if( rect->maxy < 0 || rect->maxx < 0 || rect->minx > 0 ) { return msProjectRectAsPolygon(in, out, rect ); } } } #endif if(in && msProjectHasLonWrap(in, &dfLonWrap) && dfLonWrap == 180.0) { inp = in; outp = out; if( rect->maxx > 180.0 ) { rect->minx = -180.0; rect->maxx = 180.0; } } /* * Issue #4892: When projecting a rectangle we do not want proj to wrap resulting * coordinates around the dateline, as in practice a requested bounding box of * -22.000.000, -YYY, 22.000.000, YYY should be projected as * -190,-YYY,190,YYY rather than 170,-YYY,-170,YYY as would happen when wrapping (and * vice-versa when projecting from lonlat to metric). * To enforce this, we clone the input projections and add the "+over" proj * parameter in order to disable dateline wrapping. */ else { if(out) { bFreeOutOver = MS_TRUE; msInitProjection(&out_over); msCopyProjectionExtended(&out_over,out,&over,1); outp = &out_over; } else { outp = out; } if(in) { bFreeInOver = MS_TRUE; msInitProjection(&in_over); msCopyProjectionExtended(&in_over,in,&over,1); inp = &in_over; } else { inp = in; } } ret = msProjectRectAsPolygon(inp,outp, rect ); if(bFreeInOver) msFreeProjection(&in_over); if(bFreeOutOver) msFreeProjection(&out_over); return ret; #endif } #ifdef USE_PROJ static int msProjectSortString(const void* firstelt, const void* secondelt) { char* firststr = *(char**)firstelt; char* secondstr = *(char**)secondelt; return strcmp(firststr, secondstr); } /************************************************************************/ /* msGetProjectNormalized() */ /************************************************************************/ static projectionObj* msGetProjectNormalized( const projectionObj* p ) { int i; char* pszNewProj4Def; projectionObj* pnew; pnew = (projectionObj*)msSmallMalloc(sizeof(projectionObj)); msInitProjection(pnew); msCopyProjection(pnew, (projectionObj*)p); if(p->proj == NULL ) return pnew; /* Normalize definition so that msProjectDiffers() works better */ pszNewProj4Def = pj_get_def( p->proj, 0 ); msFreeCharArray(pnew->args, pnew->numargs); pnew->args = msStringSplit(pszNewProj4Def,'+', &pnew->numargs); for(i = 0; i < pnew->numargs; i++) { /* Remove trailing space */ if( strlen(pnew->args[i]) > 0 && pnew->args[i][strlen(pnew->args[i])-1] == ' ' ) pnew->args[i][strlen(pnew->args[i])-1] = '\0'; /* Remove spurious no_defs or init= */ if( strcmp(pnew->args[i], "no_defs") == 0 || strncmp(pnew->args[i], "init=", 5) == 0 ) { if( i < pnew->numargs - 1 ) { msFree(pnew->args[i]); memmove(pnew->args + i, pnew->args + i + 1, sizeof(char*) * (pnew->numargs - 1 -i )); } else { msFree(pnew->args[i]); } pnew->numargs --; i --; continue; } } /* Sort the strings so they can be compared */ qsort(pnew->args, pnew->numargs, sizeof(char*), msProjectSortString); /*{ fprintf(stderr, "'%s' =\n", pszNewProj4Def); for(i = 0; i < p->numargs; i++) fprintf(stderr, "'%s' ", p->args[i]); fprintf(stderr, "\n"); }*/ pj_dalloc(pszNewProj4Def); return pnew; } #endif /* USE_PROJ */ /************************************************************************/ /* msProjectionsDiffer() */ /************************************************************************/ /* ** Compare two projections, and return MS_TRUE if they differ. ** ** For now this is implemented by exact comparison of the projection ** arguments, but eventually this should call a PROJ.4 function with ** more awareness of the issues. ** ** NOTE: MS_FALSE is returned if either of the projection objects ** has no arguments, since reprojection won't work anyways. */ static int msProjectionsDifferInternal( projectionObj *proj1, projectionObj *proj2 ) { int i; if( proj1->numargs == 0 || proj2->numargs == 0 ) return MS_FALSE; if( proj1->numargs != proj2->numargs ) return MS_TRUE; /* This test should be more rigerous. */ if( proj1->gt.need_geotransform || proj2->gt.need_geotransform ) return MS_TRUE; for( i = 0; i < proj1->numargs; i++ ) { if( strcmp(proj1->args[i],proj2->args[i]) != 0 ) return MS_TRUE; } return MS_FALSE; } int msProjectionsDiffer( projectionObj *proj1, projectionObj *proj2 ) { #ifdef USE_PROJ int ret; ret = msProjectionsDifferInternal(proj1, proj2); if( ret && /* to speed up things, do normalization only if one proj is */ /* likely of the form init=epsg:XXX and the other proj=XXX datum=YYY... */ ( (proj1->numargs == 1 && proj2->numargs > 1) || (proj1->numargs > 1 && proj2->numargs == 1) ) ) { projectionObj* p1normalized; projectionObj* p2normalized; p1normalized = msGetProjectNormalized( proj1 ); p2normalized = msGetProjectNormalized( proj2 ); ret = msProjectionsDifferInternal(p1normalized, p2normalized); msFreeProjection(p1normalized); msFree(p1normalized); msFreeProjection(p2normalized); msFree(p2normalized); } return ret; #else return msProjectionsDifferInternal(proj1, proj2); #endif } /************************************************************************/ /* msTestNeedWrap() */ /************************************************************************/ /* Frank Warmerdam, Nov, 2001. See Also: http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=15 Proposal: Modify msProjectLine() so that it "dateline wraps" objects when necessary in order to preserve their shape when reprojecting to lat/long. This will be accomplished by: 1) As each vertex is reprojected, compare the X distance between that vertex and the previous vertex. If it is less than 180 then proceed to the next vertex without any special logic, otherwise: 2) Reproject the center point of the line segment from the last vertex to the current vertex into lat/long. Does it's longitude lie between the longitudes of the start and end point. If yes, return to step 1) for the next vertex ... everything is fine. 3) We have determined that this line segment is suffering from 360 degree wrap to keep in the -180 to +180 range. Now add or subtract 360 degrees as determined from the original sign of the distances. This is similar to the code there now (though disabled in CVS); however, it will ensure that big boxes will remain big, and not get dateline wrapped because of the extra test in step 2). However step 2 is invoked only very rarely so this process takes little more than the normal process. In fact, if we were sufficiently concerned about performance we could do a test on the shape MBR in lat/long space, and if the width is less than 180 we know we never need to even do test 1). What doesn't this resolve: This ensures that individual lines are kept in the proper shape when reprojected to geographic space. However, it does not: o Ensure that all rings of a polygon will get transformed to the same "side" of the world. Depending on starting points of the different rings it is entirely possible for one ring to end up in the -180 area and another ring from the same polygon to end up in the +180 area. We might possibly be able to achieve this though, by treating the multi-ring polygon as a whole and testing the first point of each additional ring against the last vertex of the previous ring (or any previous vertex for that matter). o It does not address the need to cut up lines and polygons into distinct chunks to preserve the correct semantics. Really a polygon that spaces the dateline in a -180 to 180 view should get split into two polygons. We haven't addressed that, though if it were to be addressed, it could be done as a followon and distinct step from what we are doing above. In fact this sort of improvement (split polygons based on dateline or view window) should be done for all lat/long shapes regardless of whether they are being reprojected from another projection. o It does not address issues related to viewing rectangles that go outside the -180 to 180 longitude range. For instance, it is entirely reasonable to want a 160 to 200 longitude view to see an area on the dateline clearly. Currently shapes in the -180 to -160 range which should be displayed in the 180 to 200 portion of that view will not be because there is no recogition that they belong there. */ #ifdef USE_PROJ static int msTestNeedWrap( pointObj pt1, pointObj pt2, pointObj pt2_geo, projectionObj *in, projectionObj *out ) { pointObj middle; middle.x = (pt1.x + pt2.x) * 0.5; middle.y = (pt1.y + pt2.y) * 0.5; if( msProjectPoint( in, out, &pt1 ) == MS_FAILURE || msProjectPoint( in, out, &pt2 ) == MS_FAILURE || msProjectPoint( in, out, &middle ) == MS_FAILURE ) return 0; /* * If the last point was moved, then we are considered due for a * move to. */ if( fabs(pt2_geo.x-pt2.x) > 180.0 ) return 1; /* * Otherwise, test to see if the middle point transforms * to be between the end points. If yes, no wrapping is needed. * Otherwise wrapping is needed. */ if( (middle.x < pt1.x && middle.x < pt2_geo.x) || (middle.x > pt1.x && middle.x > pt2_geo.x) ) return 1; else return 0; } #endif /* def USE_PROJ */ /************************************************************************/ /* msProjFinder() */ /************************************************************************/ #ifdef USE_PROJ static char *ms_proj_lib = NULL; static char *last_filename = NULL; static const char *msProjFinder( const char *filename) { if( last_filename != NULL ) free( last_filename ); if( filename == NULL ) return NULL; if( ms_proj_lib == NULL ) return filename; last_filename = (char *) malloc(strlen(filename)+strlen(ms_proj_lib)+2); sprintf( last_filename, "%s/%s", ms_proj_lib, filename ); return last_filename; } #endif /* def USE_PROJ */ /************************************************************************/ /* msProjLibInitFromEnv() */ /************************************************************************/ void msProjLibInitFromEnv() { const char *val; if( (val=getenv( "PROJ_LIB" )) != NULL ) { msSetPROJ_LIB(val, NULL); } } /************************************************************************/ /* msSetPROJ_LIB() */ /************************************************************************/ void msSetPROJ_LIB( const char *proj_lib, const char *pszRelToPath ) { #ifdef USE_PROJ static int finder_installed = 0; char *extended_path = NULL; /* Handle relative path if applicable */ if( proj_lib && pszRelToPath && proj_lib[0] != '/' && proj_lib[0] != '\\' && !(proj_lib[0] != '\0' && proj_lib[1] == ':') ) { struct stat stat_buf; extended_path = (char*) msSmallMalloc(strlen(pszRelToPath) + strlen(proj_lib) + 10); sprintf( extended_path, "%s/%s", pszRelToPath, proj_lib ); #ifndef S_ISDIR # define S_ISDIR(x) ((x) & S_IFDIR) #endif if( stat( extended_path, &stat_buf ) == 0 && S_ISDIR(stat_buf.st_mode) ) proj_lib = extended_path; } msAcquireLock( TLOCK_PROJ ); if( finder_installed == 0 && proj_lib != NULL) { finder_installed = 1; pj_set_finder( msProjFinder ); } if (proj_lib == NULL) pj_set_finder(NULL); if( ms_proj_lib != NULL ) { free( ms_proj_lib ); ms_proj_lib = NULL; } if( last_filename != NULL ) { free( last_filename ); last_filename = NULL; } if( proj_lib != NULL ) ms_proj_lib = msStrdup( proj_lib ); msReleaseLock( TLOCK_PROJ ); if ( extended_path ) msFree( extended_path ); #endif } /************************************************************************/ /* msGetProjectionString() */ /* */ /* Return the projection string. */ /************************************************************************/ char *msGetProjectionString(projectionObj *proj) { char *pszProjString = NULL; int i = 0, nLen = 0; if (proj) { /* -------------------------------------------------------------------- */ /* Alloc buffer large enough to hold the whole projection defn */ /* -------------------------------------------------------------------- */ for (i=0; inumargs; i++) { if (proj->args[i]) nLen += (strlen(proj->args[i]) + 2); } pszProjString = (char*)malloc(sizeof(char) * nLen+1); pszProjString[0] = '\0'; /* -------------------------------------------------------------------- */ /* Plug each arg into the string with a '+' prefix */ /* -------------------------------------------------------------------- */ for (i=0; inumargs; i++) { if (!proj->args[i] || strlen(proj->args[i]) == 0) continue; if (pszProjString[0] == '\0') { /* no space at beginning of line */ if (proj->args[i][0] != '+') strcat(pszProjString, "+"); } else { if (proj->args[i][0] != '+') strcat(pszProjString, " +"); else strcat(pszProjString, " "); } strcat(pszProjString, proj->args[i]); } } return pszProjString; } /************************************************************************/ /* msIsAxisInvertedProj() */ /* */ /* Return MS_TRUE is the proj object has epgsaxis=ne */ /************************************************************************/ int msIsAxisInvertedProj( projectionObj *proj ) { int i; const char *axis = NULL; for( i = 0; i < proj->numargs; i++ ) { if( strstr(proj->args[i],"epsgaxis=") != NULL ) { axis = strstr(proj->args[i],"=") + 1; break; } } if( axis == NULL ) return MS_FALSE; if( strcasecmp(axis,"en") == 0 ) return MS_FALSE; if( strcasecmp(axis,"ne") != 0 ) { msDebug( "msIsAxisInvertedProj(): odd +epsgaxis= value: '%s'.", axis ); return MS_FALSE; } return MS_TRUE; } /************************************************************************/ /* msAxisNormalizePoints() */ /* */ /* Convert the passed points to "easting, northing" axis */ /* orientation if they are not already. */ /************************************************************************/ void msAxisNormalizePoints( projectionObj *proj, int count, double *x, double *y ) { int i; if( !msIsAxisInvertedProj(proj ) ) return; /* Switch axes */ for( i = 0; i < count; i++ ) { double tmp; tmp = x[i]; x[i] = y[i]; y[i] = tmp; } } /************************************************************************/ /* msAxisSwapShape */ /* */ /* Utility function to swap x and y coordiatesn Use for now for */ /* WFS 1.1.x */ /************************************************************************/ void msAxisSwapShape(shapeObj *shape) { double tmp; int i,j; if (shape) { for(i=0; inumlines; i++) { for( j=0; jline[i].numpoints; j++ ) { tmp = shape->line[i].point[j].x; shape->line[i].point[j].x = shape->line[i].point[j].y; shape->line[i].point[j].y = tmp; } } /*swap bounds*/ tmp = shape->bounds.minx; shape->bounds.minx = shape->bounds.miny; shape->bounds.miny = tmp; tmp = shape->bounds.maxx; shape->bounds.maxx = shape->bounds.maxy; shape->bounds.maxy = tmp; } } /************************************************************************/ /* msAxisDenormalizePoints() */ /* */ /* Convert points from easting,northing orientation to the */ /* preferred epsg orientation of this projectionObj. */ /************************************************************************/ void msAxisDenormalizePoints( projectionObj *proj, int count, double *x, double *y ) { /* For how this is essentially identical to normalizing */ msAxisNormalizePoints( proj, count, x, y ); } mapserver-7.4.3/mapproject.h000066400000000000000000000104541357574274700160770ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations of the projectionObj and related functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPPROJECT_H #define MAPPROJECT_H #include "mapprimitive.h" #include "maphash.h" #ifdef __cplusplus extern "C" { #endif /* workaround to allow compiling against Proj 6.x (#5766) */ #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 1 #ifdef USE_PROJ # include #if PJ_VERSION >= 470 && PJ_VERSION < 480 void pj_clear_initcache(); #endif #endif #define wkp_none 0 #define wkp_lonlat 1 #define wkp_gmerc 2 typedef struct { #ifdef SWIG %immutable; #endif int numargs; /* actual number of projection args */ int automatic; /* projection object was to fetched from the layer */ #ifdef SWIG %mutable; #endif #ifndef SWIG char **args; /* variable number of projection args */ #ifdef USE_PROJ projPJ proj; /* a projection structure for the PROJ package */ #if PJ_VERSION >= 480 projCtx proj_ctx; #endif #else void *proj; #endif geotransformObj gt; /* extra transformation to apply */ #endif int wellknownprojection; } projectionObj; #ifndef SWIG MS_DLL_EXPORT int msIsAxisInverted(int epsg_code); MS_DLL_EXPORT int msProjectPoint(projectionObj *in, projectionObj *out, pointObj *point); MS_DLL_EXPORT int msProjectShape(projectionObj *in, projectionObj *out, shapeObj *shape); MS_DLL_EXPORT int msProjectLine(projectionObj *in, projectionObj *out, lineObj *line); MS_DLL_EXPORT int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect); MS_DLL_EXPORT int msProjectionsDiffer(projectionObj *, projectionObj *); MS_DLL_EXPORT int msOGCWKT2ProjectionObj( const char *pszWKT, projectionObj *proj, int debug_flag ); MS_DLL_EXPORT char *msProjectionObj2OGCWKT( projectionObj *proj ); MS_DLL_EXPORT void msFreeProjection(projectionObj *p); MS_DLL_EXPORT int msInitProjection(projectionObj *p); MS_DLL_EXPORT int msProcessProjection(projectionObj *p); MS_DLL_EXPORT int msLoadProjectionString(projectionObj *p, const char *value); MS_DLL_EXPORT int msLoadProjectionStringEPSG(projectionObj *p, const char *value); MS_DLL_EXPORT char *msGetProjectionString(projectionObj *proj); int msIsAxisInvertedProj( projectionObj *proj ); void msAxisSwapShape(shapeObj *shape); MS_DLL_EXPORT void msAxisNormalizePoints( projectionObj *proj, int count, double *x, double *y ); MS_DLL_EXPORT void msAxisDenormalizePoints( projectionObj *proj, int count, double *x, double *y ); MS_DLL_EXPORT void msSetPROJ_LIB( const char *, const char * ); MS_DLL_EXPORT void msProjLibInitFromEnv(); /* Provides compatiblity with PROJ.4 4.4.2 */ #ifndef PJ_VERSION # define pj_is_latlong(x) ((x)->is_latlong) #endif /*utility functions */ MS_DLL_EXPORT int GetMapserverUnitUsingProj(projectionObj *psProj); int msProjectHasLonWrap(projectionObj *in, double* pdfLonWrap); #endif #ifdef __cplusplus } #endif #endif /* MAPPROJECT_H */ mapserver-7.4.3/mapprojhack.c000066400000000000000000000116101357574274700162200ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of utility functions related to the PROJ4 library * Author: DM Solutions Group (assefa@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2001, Y. Assefa, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ****************************************************************************/ #include #include "mapserver.h" /************************************************************************/ /* ConvertProjUnitStringToMS */ /* */ /* Returns mapserver's unit code corresponding to the proj */ /* unit passed as argument. */ /* Please refer to ./src/pj_units.c file in the Proj.4 module. */ /************************************************************************/ #ifdef USE_PROJ static int ConvertProjUnitStringToMS(const char *pszProjUnit) { if (strcmp(pszProjUnit, "m") ==0) { return MS_METERS; } else if (strcmp(pszProjUnit, "km") ==0) { return MS_KILOMETERS; } else if (strcmp(pszProjUnit, "mi") ==0 || strcmp(pszProjUnit, "us-mi") ==0) { return MS_MILES; } else if (strcmp(pszProjUnit, "in") ==0 || strcmp(pszProjUnit, "us-in") ==0 ) { return MS_INCHES; } else if (strcmp(pszProjUnit, "ft") ==0 || strcmp(pszProjUnit, "us-ft") ==0) { return MS_FEET; } else if (strcmp(pszProjUnit, "kmi") == 0) { return MS_NAUTICALMILES; } return -1; } #endif /* def USE_PROJ */ /************************************************************************/ /* int GetMapserverUnitUsingProj(projectionObj *psProj) */ /* */ /* Return a mapserver unit corresponding to the projection */ /* passed. Retunr -1 on failure */ /************************************************************************/ int GetMapserverUnitUsingProj(projectionObj *psProj) { #ifdef USE_PROJ char *proj_str; if( pj_is_latlong( psProj->proj ) ) return MS_DD; proj_str = pj_get_def( psProj->proj, 0 ); /* -------------------------------------------------------------------- */ /* Handle case of named units. */ /* -------------------------------------------------------------------- */ if( strstr(proj_str,"units=") != NULL ) { char units[32]; char *blank; strlcpy( units, (strstr(proj_str,"units=")+6), sizeof(units) ); pj_dalloc( proj_str ); blank = strchr(units, ' '); if( blank != NULL ) *blank = '\0'; return ConvertProjUnitStringToMS( units ); } /* -------------------------------------------------------------------- */ /* Handle case of to_meter value. */ /* -------------------------------------------------------------------- */ if( strstr(proj_str,"to_meter=") != NULL ) { char to_meter_str[32]; char *blank; double to_meter; strlcpy(to_meter_str,(strstr(proj_str,"to_meter=")+9), sizeof(to_meter_str)); pj_dalloc( proj_str ); blank = strchr(to_meter_str, ' '); if( blank != NULL ) *blank = '\0'; to_meter = atof(to_meter_str); if( fabs(to_meter-1.0) < 0.0000001 ) return MS_METERS; else if( fabs(to_meter-1000.0) < 0.00001 ) return MS_KILOMETERS; else if( fabs(to_meter-0.3048) < 0.0001 ) return MS_FEET; else if( fabs(to_meter-0.0254) < 0.0001 ) return MS_INCHES; else if( fabs(to_meter-1609.344) < 0.001 ) return MS_MILES; else if( fabs(to_meter-1852.0) < 0.1 ) return MS_NAUTICALMILES; else return -1; } pj_dalloc( proj_str ); #endif return -1; } mapserver-7.4.3/mapquantization.c000066400000000000000000000561641357574274700171620ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: RGB(A) to Palette Support Functions * Author: Thomas Bonfort * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** */ /* * derivations from pngquant and ppmquant * ** pngquant.c - quantize the colors in an alphamap down to a specified number ** ** Copyright (C) 1989, 1991 by Jef Poskanzer. ** Copyright (C) 1997, 2000, 2002 by Greg Roelofs; based on an idea by ** Stefan Schneider. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ #include "mapserver.h" #include #define PAM_GETR(p) ((p).r) #define PAM_GETG(p) ((p).g) #define PAM_GETB(p) ((p).b) #define PAM_GETA(p) ((p).a) #define PAM_ASSIGN(p,red,grn,blu,alf) \ do { (p).r = (red); (p).g = (grn); (p).b = (blu); (p).a = (alf); } while (0) #define PAM_EQUAL(p,q) \ ((p).r == (q).r && (p).g == (q).g && (p).b == (q).b && (p).a == (q).a) #define PAM_DEPTH(newp,p,oldmaxval,newmaxval) \ PAM_ASSIGN( (newp), \ ( (int) PAM_GETR(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \ ( (int) PAM_GETG(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \ ( (int) PAM_GETB(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \ ( (int) PAM_GETA(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval) ) /* from pamcmap.h */ typedef struct acolorhist_item *acolorhist_vector; struct acolorhist_item { rgbaPixel acolor; int value; }; typedef struct acolorhist_list_item *acolorhist_list; struct acolorhist_list_item { struct acolorhist_item ch; acolorhist_list next; }; typedef acolorhist_list *acolorhash_table; #define MAXCOLORS 32767 #define LARGE_NORM #define REP_AVERAGE_PIXELS typedef struct box *box_vector; struct box { int ind; int colors; int sum; }; static acolorhist_vector mediancut (acolorhist_vector achv, int colors, int sum, unsigned char maxval, int newcolors); static int redcompare (const void *ch1, const void *ch2); static int greencompare (const void *ch1, const void *ch2); static int bluecompare (const void *ch1, const void *ch2); static int alphacompare (const void *ch1, const void *ch2); static int sumcompare (const void *b1, const void *b2); static acolorhist_vector pam_acolorhashtoacolorhist (acolorhash_table acht, int maxacolors); static acolorhist_vector pam_computeacolorhist (rgbaPixel **apixels, int cols, int rows, int maxacolors, int* acolorsP); static acolorhash_table pam_computeacolorhash (rgbaPixel** apixels, int cols, int rows, int maxacolors, int* acolorsP); static acolorhash_table pam_allocacolorhash (void); static int pam_addtoacolorhash (acolorhash_table acht, rgbaPixel *acolorP, int value); static int pam_lookupacolor (acolorhash_table acht, rgbaPixel* acolorP); static void pam_freeacolorhist (acolorhist_vector achv); static void pam_freeacolorhash (acolorhash_table acht); /** * Compute a palette for the given RGBA rasterBuffer using a median cut quantization. * - rb: the rasterBuffer to quantize * - reqcolors: the desired number of colors the palette should contain. will be set * with the actual number of entries in the computed palette * - forced_palette: entries that should appear in the computed palette * - num_forced_palette_entries: number of entries contained in "force_palette". if 0, * "force_palette" can be NULL * - palette_scaling_maxval: the quantization process may have to reduce the image depth * by iteratively dividing the pixels by 2. In case palette_scaling_maxval is set to * something different than 255, the returned palette colors have to be scaled back up to * 255, and rb's pixels will have been scaled down to maxsize (see bug #3848) */ int msQuantizeRasterBuffer(rasterBufferObj *rb, unsigned int *reqcolors, rgbaPixel *palette, rgbaPixel *forced_palette, int num_forced_palette_entries, unsigned int *palette_scaling_maxval) { rgbaPixel **apixels=NULL; /* pointer to the start rows of truecolor pixels */ register rgbaPixel *pP; register int col; unsigned char newmaxval; acolorhist_vector achv, acolormap=NULL; int row; int colors; int newcolors = 0; int x; /* int channels; */ assert(rb->type == MS_BUFFER_BYTE_RGBA); *palette_scaling_maxval = 255; apixels=(rgbaPixel**)msSmallMalloc(rb->height*sizeof(rgbaPixel*)); for(row=0; rowheight; row++) { apixels[row]=(rgbaPixel*)(&(rb->data.rgba.pixels[row * rb->data.rgba.row_step])); } /* ** Step 2: attempt to make a histogram of the colors, unclustered. ** If at first we don't succeed, lower maxval to increase color ** coherence and try again. This will eventually terminate, with ** maxval at worst 15, since 32^3 is approximately MAXCOLORS. [GRR POSSIBLE BUG: what about 32^4 ?] */ for ( ; ; ) { achv = pam_computeacolorhist( apixels, rb->width, rb->height, MAXCOLORS, &colors ); if ( achv != (acolorhist_vector) 0 ) break; newmaxval = *palette_scaling_maxval / 2; for ( row = 0; row < rb->height; ++row ) for ( col = 0, pP = apixels[row]; col < rb->width; ++col, ++pP ) PAM_DEPTH( *pP, *pP, *palette_scaling_maxval, newmaxval ); *palette_scaling_maxval = newmaxval; } newcolors = MS_MIN(colors, *reqcolors); acolormap = mediancut(achv, colors, rb->width*rb->height, *palette_scaling_maxval, newcolors); pam_freeacolorhist(achv); *reqcolors = newcolors; for (x = 0; x < newcolors; ++x) { palette[x].r = acolormap[x].acolor.r; palette[x].g = acolormap[x].acolor.g; palette[x].b = acolormap[x].acolor.b; palette[x].a = acolormap[x].acolor.a; } free(acolormap); free(apixels); return MS_SUCCESS; } int msClassifyRasterBuffer(rasterBufferObj *rb, rasterBufferObj *qrb) { register int ind; unsigned char *outrow,*pQ; register rgbaPixel *pP; acolorhash_table acht; int usehash, row, col; /* ** Step 4: map the colors in the image to their closest match in the ** new colormap, and write 'em out. */ acht = pam_allocacolorhash( ); usehash = 1; for ( row = 0; row < qrb->height; ++row ) { outrow = &(qrb->data.palette.pixels[row*qrb->width]); col = 0; pP = (rgbaPixel*)(&(rb->data.rgba.pixels[row * rb->data.rgba.row_step]));; pQ = outrow; do { /* Check hash table to see if we have already matched this color. */ ind = pam_lookupacolor( acht, pP ); if ( ind == -1 ) { /* No; search acolormap for closest match. */ register int i, r1, g1, b1, a1, r2, g2, b2, a2; register long dist, newdist; r1 = PAM_GETR( *pP ); g1 = PAM_GETG( *pP ); b1 = PAM_GETB( *pP ); a1 = PAM_GETA( *pP ); dist = 2000000000; for ( i = 0; i < qrb->data.palette.num_entries; ++i ) { r2 = PAM_GETR( qrb->data.palette.palette[i] ); g2 = PAM_GETG( qrb->data.palette.palette[i] ); b2 = PAM_GETB( qrb->data.palette.palette[i] ); a2 = PAM_GETA( qrb->data.palette.palette[i] ); /* GRR POSSIBLE BUG */ newdist = ( r1 - r2 ) * ( r1 - r2 ) + /* may overflow? */ ( g1 - g2 ) * ( g1 - g2 ) + ( b1 - b2 ) * ( b1 - b2 ) + ( a1 - a2 ) * ( a1 - a2 ); if ( newdist < dist ) { ind = i; dist = newdist; } } if ( usehash ) { if ( pam_addtoacolorhash( acht, pP, ind ) < 0 ) { usehash = 0; } } } /* *pP = acolormap[ind].acolor; */ *pQ = (unsigned char)ind; ++col; ++pP; ++pQ; } while ( col != rb->width ); } pam_freeacolorhash(acht); return MS_SUCCESS; } /* ** Here is the fun part, the median-cut colormap generator. This is based ** on Paul Heckbert's paper, "Color Image Quantization for Frame Buffer ** Display," SIGGRAPH 1982 Proceedings, page 297. */ static acolorhist_vector mediancut( acolorhist_vector achv, int colors, int sum, unsigned char maxval, int newcolors ) { acolorhist_vector acolormap; box_vector bv; register int bi, i; int boxes; bv = (box_vector) malloc( sizeof(struct box) * newcolors ); acolormap = (acolorhist_vector) malloc( sizeof(struct acolorhist_item) * newcolors); if ( bv == (box_vector) 0 || acolormap == (acolorhist_vector) 0 ) { fprintf( stderr, " out of memory allocating box vector\n" ); fflush(stderr); exit(6); } for ( i = 0; i < newcolors; ++i ) PAM_ASSIGN( acolormap[i].acolor, 0, 0, 0, 0 ); /* ** Set up the initial box. */ bv[0].ind = 0; bv[0].colors = colors; bv[0].sum = sum; boxes = 1; /* ** Main loop: split boxes until we have enough. */ while ( boxes < newcolors ) { register int indx, clrs; int sm; register int minr, maxr, ming, mina, maxg, minb, maxb, maxa, v; int halfsum, lowersum; /* ** Find the first splittable box. */ for ( bi = 0; bi < boxes; ++bi ) if ( bv[bi].colors >= 2 ) break; if ( bi == boxes ) break; /* ran out of colors! */ indx = bv[bi].ind; clrs = bv[bi].colors; sm = bv[bi].sum; /* ** Go through the box finding the minimum and maximum of each ** component - the boundaries of the box. */ minr = maxr = PAM_GETR( achv[indx].acolor ); ming = maxg = PAM_GETG( achv[indx].acolor ); minb = maxb = PAM_GETB( achv[indx].acolor ); mina = maxa = PAM_GETA( achv[indx].acolor ); for ( i = 1; i < clrs; ++i ) { v = PAM_GETR( achv[indx + i].acolor ); if ( v < minr ) minr = v; if ( v > maxr ) maxr = v; v = PAM_GETG( achv[indx + i].acolor ); if ( v < ming ) ming = v; if ( v > maxg ) maxg = v; v = PAM_GETB( achv[indx + i].acolor ); if ( v < minb ) minb = v; if ( v > maxb ) maxb = v; v = PAM_GETA( achv[indx + i].acolor ); if ( v < mina ) mina = v; if ( v > maxa ) maxa = v; } /* ** Find the largest dimension, and sort by that component. I have ** included two methods for determining the "largest" dimension; ** first by simply comparing the range in RGB space, and second ** by transforming into luminosities before the comparison. You ** can switch which method is used by switching the commenting on ** the LARGE_ defines at the beginning of this source file. */ #ifdef LARGE_NORM if ( maxa - mina >= maxr - minr && maxa - mina >= maxg - ming && maxa - mina >= maxb - minb ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), alphacompare ); else if ( maxr - minr >= maxg - ming && maxr - minr >= maxb - minb ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), redcompare ); else if ( maxg - ming >= maxb - minb ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), greencompare ); else qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), bluecompare ); #endif /*LARGE_NORM*/ #ifdef LARGE_LUM { apixel p; float rl, gl, bl, al; PAM_ASSIGN(p, maxr - minr, 0, 0, 0); rl = PPM_LUMIN(p); PAM_ASSIGN(p, 0, maxg - ming, 0, 0); gl = PPM_LUMIN(p); PAM_ASSIGN(p, 0, 0, maxb - minb, 0); bl = PPM_LUMIN(p); /* GRR: treat alpha as grayscale and assign (maxa - mina) to each of R, G, B? assign (maxa - mina)/3 to each? use alpha-fractional luminosity? (normalized_alpha * lum(r,g,b)) al = dunno ... [probably should read Heckbert's paper to decide] */ if ( al >= rl && al >= gl && al >= bl ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), alphacompare ); else if ( rl >= gl && rl >= bl ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), redcompare ); else if ( gl >= bl ) qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), greencompare ); else qsort( (char*) &(achv[indx]), clrs, sizeof(struct acolorhist_item), bluecompare ); } #endif /*LARGE_LUM*/ /* ** Now find the median based on the counts, so that about half the ** pixels (not colors, pixels) are in each subdivision. */ lowersum = achv[indx].value; halfsum = sm / 2; for ( i = 1; i < clrs - 1; ++i ) { if ( lowersum >= halfsum ) break; lowersum += achv[indx + i].value; } /* ** Split the box, and sort to bring the biggest boxes to the top. */ bv[bi].colors = i; bv[bi].sum = lowersum; bv[boxes].ind = indx + i; bv[boxes].colors = clrs - i; bv[boxes].sum = sm - lowersum; ++boxes; qsort( (char*) bv, boxes, sizeof(struct box), sumcompare ); } /* ** Ok, we've got enough boxes. Now choose a representative color for ** each box. There are a number of possible ways to make this choice. ** One would be to choose the center of the box; this ignores any structure ** within the boxes. Another method would be to average all the colors in ** the box - this is the method specified in Heckbert's paper. A third ** method is to average all the pixels in the box. You can switch which ** method is used by switching the commenting on the REP_ defines at ** the beginning of this source file. */ for ( bi = 0; bi < boxes; ++bi ) { #ifdef REP_CENTER_BOX register int indx = bv[bi].ind; register int clrs = bv[bi].colors; register int minr, maxr, ming, maxg, minb, maxb, mina, maxa, v; minr = maxr = PAM_GETR( achv[indx].acolor ); ming = maxg = PAM_GETG( achv[indx].acolor ); minb = maxb = PAM_GETB( achv[indx].acolor ); mina = maxa = PAM_GETA( achv[indx].acolor ); for ( i = 1; i < clrs; ++i ) { v = PAM_GETR( achv[indx + i].acolor ); minr = min( minr, v ); maxr = max( maxr, v ); v = PAM_GETG( achv[indx + i].acolor ); ming = min( ming, v ); maxg = max( maxg, v ); v = PAM_GETB( achv[indx + i].acolor ); minb = min( minb, v ); maxb = max( maxb, v ); v = PAM_GETA( achv[indx + i].acolor ); mina = min( mina, v ); maxa = max( maxa, v ); } PAM_ASSIGN( acolormap[bi].acolor, ( minr + maxr ) / 2, ( ming + maxg ) / 2, ( minb + maxb ) / 2, ( mina + maxa ) / 2 ); #endif /*REP_CENTER_BOX*/ #ifdef REP_AVERAGE_COLORS register int indx = bv[bi].ind; register int clrs = bv[bi].colors; register long r = 0, g = 0, b = 0, a = 0; for ( i = 0; i < clrs; ++i ) { r += PAM_GETR( achv[indx + i].acolor ); g += PAM_GETG( achv[indx + i].acolor ); b += PAM_GETB( achv[indx + i].acolor ); a += PAM_GETA( achv[indx + i].acolor ); } r = r / clrs; g = g / clrs; b = b / clrs; a = a / clrs; PAM_ASSIGN( acolormap[bi].acolor, r, g, b, a ); #endif /*REP_AVERAGE_COLORS*/ #ifdef REP_AVERAGE_PIXELS register int indx = bv[bi].ind; register int clrs = bv[bi].colors; register long r = 0, g = 0, b = 0, a = 0, sum = 0; for ( i = 0; i < clrs; ++i ) { r += PAM_GETR( achv[indx + i].acolor ) * achv[indx + i].value; g += PAM_GETG( achv[indx + i].acolor ) * achv[indx + i].value; b += PAM_GETB( achv[indx + i].acolor ) * achv[indx + i].value; a += PAM_GETA( achv[indx + i].acolor ) * achv[indx + i].value; sum += achv[indx + i].value; } if(sum>0) { r = r / sum; if ( r > maxval ) r = maxval; /* avoid math errors */ g = g / sum; if ( g > maxval ) g = maxval; b = b / sum; if ( b > maxval ) b = maxval; a = a / sum; if ( a > maxval ) a = maxval; } else { r = g = b = a = maxval; } /* GRR 20001228: added casts to quiet warnings; 255 DEPENDENCY */ PAM_ASSIGN( acolormap[bi].acolor, (unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a ); #endif /*REP_AVERAGE_PIXELS*/ } /* ** All done. */ free(bv); return acolormap; } static int redcompare( const void *ch1, const void *ch2 ) { return (int) PAM_GETR( ((acolorhist_vector)ch1)->acolor ) - (int) PAM_GETR( ((acolorhist_vector)ch2)->acolor ); } static int greencompare( const void *ch1, const void *ch2 ) { return (int) PAM_GETG( ((acolorhist_vector)ch1)->acolor ) - (int) PAM_GETG( ((acolorhist_vector)ch2)->acolor ); } static int bluecompare( const void *ch1, const void *ch2 ) { return (int) PAM_GETB( ((acolorhist_vector)ch1)->acolor ) - (int) PAM_GETB( ((acolorhist_vector)ch2)->acolor ); } static int alphacompare( const void *ch1, const void *ch2 ) { return (int) PAM_GETA( ((acolorhist_vector)ch1)->acolor ) - (int) PAM_GETA( ((acolorhist_vector)ch2)->acolor ); } static int sumcompare( const void *b1, const void *b2 ) { return ((box_vector)b2)->sum - ((box_vector)b1)->sum; } /*===========================================================================*/ /* libpam3.c - pam (portable alpha map) utility library part 3 ** ** Colormap routines. ** ** Copyright (C) 1989, 1991 by Jef Poskanzer. ** Copyright (C) 1997 by Greg Roelofs. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ /* #include "pam.h" #include "pamcmap.h" */ #define HASH_SIZE 20023 #define pam_hashapixel(p) ( ( ( (long) PAM_GETR(p) * 33023 + \ (long) PAM_GETG(p) * 30013 + \ (long) PAM_GETB(p) * 27011 + \ (long) PAM_GETA(p) * 24007 ) \ & 0x7fffffff ) % HASH_SIZE ) static acolorhist_vector pam_computeacolorhist( apixels, cols, rows, maxacolors, acolorsP ) rgbaPixel** apixels; int cols, rows, maxacolors; int* acolorsP; { acolorhash_table acht; acolorhist_vector achv; acht = pam_computeacolorhash( apixels, cols, rows, maxacolors, acolorsP ); if ( acht == (acolorhash_table) 0 ) return (acolorhist_vector) 0; achv = pam_acolorhashtoacolorhist( acht, maxacolors ); pam_freeacolorhash( acht ); return achv; } static acolorhash_table pam_computeacolorhash( apixels, cols, rows, maxacolors, acolorsP ) rgbaPixel** apixels; int cols, rows, maxacolors; int* acolorsP; { acolorhash_table acht; register rgbaPixel* pP; acolorhist_list achl; int col, row, hash; acht = pam_allocacolorhash( ); *acolorsP = 0; /* Go through the entire image, building a hash table of colors. */ for ( row = 0; row < rows; ++row ) for ( col = 0, pP = apixels[row]; col < cols; ++col, ++pP ) { hash = pam_hashapixel( *pP ); for ( achl = acht[hash]; achl != (acolorhist_list) 0; achl = achl->next ) if ( PAM_EQUAL( achl->ch.acolor, *pP ) ) break; if ( achl != (acolorhist_list) 0 ) ++(achl->ch.value); else { if ( ++(*acolorsP) > maxacolors ) { pam_freeacolorhash( acht ); return (acolorhash_table) 0; } achl = (acolorhist_list) malloc( sizeof(struct acolorhist_list_item) ); if ( achl == 0 ) { fprintf( stderr, " out of memory computing hash table\n" ); exit(7); } achl->ch.acolor = *pP; achl->ch.value = 1; achl->next = acht[hash]; acht[hash] = achl; } } return acht; } static acolorhash_table pam_allocacolorhash( ) { acolorhash_table acht; int i; acht = (acolorhash_table) malloc( HASH_SIZE * sizeof(acolorhist_list) ); if ( acht == 0 ) { fprintf( stderr, " out of memory allocating hash table\n" ); exit(8); } for ( i = 0; i < HASH_SIZE; ++i ) acht[i] = (acolorhist_list) 0; return acht; } static int pam_addtoacolorhash( acht, acolorP, value ) acolorhash_table acht; rgbaPixel* acolorP; int value; { register int hash; register acolorhist_list achl; achl = (acolorhist_list) msSmallMalloc( sizeof(struct acolorhist_list_item) ); hash = pam_hashapixel( *acolorP ); achl->ch.acolor = *acolorP; achl->ch.value = value; achl->next = acht[hash]; acht[hash] = achl; return 0; } static acolorhist_vector pam_acolorhashtoacolorhist( acht, maxacolors ) acolorhash_table acht; int maxacolors; { acolorhist_vector achv; acolorhist_list achl; int i, j; /* Now collate the hash table into a simple acolorhist array. */ achv = (acolorhist_vector) malloc( maxacolors * sizeof(struct acolorhist_item) ); /* (Leave room for expansion by caller.) */ if ( achv == (acolorhist_vector) 0 ) { fprintf( stderr, " out of memory generating histogram\n" ); exit(9); } /* Loop through the hash table. */ j = 0; for ( i = 0; i < HASH_SIZE; ++i ) for ( achl = acht[i]; achl != (acolorhist_list) 0; achl = achl->next ) { /* Add the new entry. */ achv[j] = achl->ch; ++j; } /* All done. */ return achv; } static int pam_lookupacolor( acht, acolorP ) acolorhash_table acht; rgbaPixel* acolorP; { int hash; acolorhist_list achl; hash = pam_hashapixel( *acolorP ); for ( achl = acht[hash]; achl != (acolorhist_list) 0; achl = achl->next ) if ( PAM_EQUAL( achl->ch.acolor, *acolorP ) ) return achl->ch.value; return -1; } static void pam_freeacolorhist( achv ) acolorhist_vector achv; { free( (char*) achv ); } static void pam_freeacolorhash( acht ) acolorhash_table acht; { int i; acolorhist_list achl, achlnext; for ( i = 0; i < HASH_SIZE; ++i ) for ( achl = acht[i]; achl != (acolorhist_list) 0; achl = achlnext ) { achlnext = achl->next; free( (char*) achl ); } free( (char*) acht ); } mapserver-7.4.3/mapquery.c000066400000000000000000002262361357574274700156000ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Layer query support. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "mapows.h" /* This object is used by the various mapQueryXXXXX() functions. It stores * the total amount of shapes and their RAM footprint, when they are cached * in the resultCacheObj* of layers. This is the total number accross all queried * layers. However this is isn't persistant accross several calls to * mapQueryXXXXX(), if the resultCacheObj* objects weren't cleaned up. This * is not needed in the context of WFS, for which this is used for now. */ typedef struct { int cachedShapeCountWarningEmitted; int cachedShapeCount; int cachedShapeRAMWarningEmitted; int cachedShapeRAM; } queryCacheObj; int msInitQuery(queryObj *query) { if(!query) return MS_FAILURE; msFreeQuery(query); /* clean up anything previously allocated */ query->type = MS_QUERY_IS_NULL; /* nothing defined */ query->mode = MS_QUERY_SINGLE; query->layer = query->slayer = -1; query->point.x = query->point.y = -1; query->buffer = 0.0; query->maxresults = 0; /* only used by msQueryByPoint() apparently */ query->rect.minx = query->rect.miny = query->rect.maxx = query->rect.maxy = -1; query->shape = NULL; query->shapeindex = query->tileindex = -1; query->clear_resultcache = MS_TRUE; /* index queries allow the old results to persist */ query->maxfeatures = -1; query->startindex = -1; query->only_cache_result_count = 0; query->filteritem = NULL; msInitExpression(&query->filter); query->cache_shapes = MS_FALSE; query->max_cached_shape_count = 0; query->max_cached_shape_ram_amount = 0; return MS_SUCCESS; } void msFreeQuery(queryObj *query) { if(query->shape) { msFreeShape(query->shape); free(query->shape); } if(query->filteritem) free(query->filteritem); msFreeExpression(&query->filter); } /* ** Wrapper for all query functions, just feed is a mapObj with a populated queryObj... */ int msExecuteQuery(mapObj *map) { int tmp=-1, status; /* handle slayer/qlayer management for feature queries */ if(map->query.slayer >= 0) { tmp = map->query.layer; map->query.layer = map->query.slayer; } switch(map->query.type) { case MS_QUERY_BY_POINT: status = msQueryByPoint(map); break; case MS_QUERY_BY_RECT: status = msQueryByRect(map); break; case MS_QUERY_BY_FILTER: status = msQueryByFilter(map); break; case MS_QUERY_BY_SHAPE: status = msQueryByShape(map); break; case MS_QUERY_BY_INDEX: status = msQueryByIndex(map); break; default: msSetError(MS_QUERYERR, "Malformed queryObj.", "msExecuteQuery()"); return(MS_FAILURE); } if(map->query.slayer >= 0) { map->query.layer = tmp; /* restore layer */ if(status == MS_SUCCESS) status = msQueryByFeatures(map); } return status; } /* ** msIsLayerQueryable() returns MS_TRUE/MS_FALSE */ int msIsLayerQueryable(layerObj *lp) { int i; if ( lp->type == MS_LAYER_TILEINDEX ) return MS_FALSE; if(lp->template && strlen(lp->template) > 0) return MS_TRUE; for(i=0; inumclasses; i++) { if(lp->class[i]->template && strlen(lp->class[i]->template) > 0) return MS_TRUE; } return MS_FALSE; } static void initQueryCache(queryCacheObj* queryCache) { queryCache->cachedShapeCountWarningEmitted = MS_FALSE; queryCache->cachedShapeCount = 0; queryCache->cachedShapeRAMWarningEmitted = MS_FALSE; queryCache->cachedShapeRAM = 0; } /** Check whether we should store the shape in resultCacheObj* given the * limits allowed in map->query.max_cached_shape_count and * map->query.max_cached_shape_ram_amount. */ static int canCacheShape(mapObj* map, queryCacheObj *queryCache, shapeObj* shape, int shape_ram_size) { if( !map->query.cache_shapes ) return MS_FALSE; if( queryCache->cachedShapeCountWarningEmitted || (map->query.max_cached_shape_count > 0 && queryCache->cachedShapeCount >= map->query.max_cached_shape_count) ) { if( !queryCache->cachedShapeCountWarningEmitted ) { queryCache->cachedShapeCountWarningEmitted = MS_TRUE; msDebug("map->query.max_cached_shape_count = %d reached. " "Next features will not be cached.\n", map->query.max_cached_shape_count); } return MS_FALSE; } if( queryCache->cachedShapeRAMWarningEmitted || (map->query.max_cached_shape_ram_amount > 0 && queryCache->cachedShapeRAM + shape_ram_size > map->query.max_cached_shape_ram_amount) ) { if( !queryCache->cachedShapeRAMWarningEmitted ) { queryCache->cachedShapeRAMWarningEmitted = MS_TRUE; msDebug("map->query.max_cached_shape_ram_amount = %d reached after %d cached features. " "Next features will not be cached.\n", map->query.max_cached_shape_ram_amount, queryCache->cachedShapeCount); } return MS_FALSE; } return MS_TRUE; } static int addResult(mapObj* map, resultCacheObj *cache, queryCacheObj* queryCache, shapeObj *shape) { int i; int shape_ram_size = (map->query.max_cached_shape_ram_amount > 0) ? msGetShapeRAMSize( shape ) : 0; int store_shape = canCacheShape (map, queryCache, shape, shape_ram_size); if(cache->numresults == cache->cachesize) { /* just add it to the end */ if(cache->cachesize == 0) cache->results = (resultObj *) malloc(sizeof(resultObj)*MS_RESULTCACHEINCREMENT); else cache->results = (resultObj *) realloc(cache->results, sizeof(resultObj)*(cache->cachesize+MS_RESULTCACHEINCREMENT)); if(!cache->results) { msSetError(MS_MEMERR, "Realloc() error.", "addResult()"); return(MS_FAILURE); } cache->cachesize += MS_RESULTCACHEINCREMENT; } i = cache->numresults; cache->results[i].classindex = shape->classindex; cache->results[i].tileindex = shape->tileindex; cache->results[i].shapeindex = shape->index; cache->results[i].resultindex = shape->resultindex; if( store_shape ) { cache->results[i].shape = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(cache->results[i].shape); msCopyShape(shape, cache->results[i].shape); queryCache->cachedShapeCount ++; queryCache->cachedShapeRAM += shape_ram_size; } else cache->results[i].shape = NULL; cache->numresults++; cache->previousBounds = cache->bounds; if(cache->numresults == 1) cache->bounds = shape->bounds; else msMergeRect(&(cache->bounds), &(shape->bounds)); return(MS_SUCCESS); } /* ** Serialize a query result set to disk. */ static int saveQueryResults(mapObj *map, char *filename) { FILE *stream; int i, j, n=0; if(!filename) { msSetError(MS_MISCERR, "No filename provided to save query results to.", "saveQueryResults()"); return MS_FAILURE; } stream = fopen(filename, "w"); if(!stream) { msSetError(MS_IOERR, "(%s)", "saveQueryResults()", filename); return MS_FAILURE; } fprintf(stream, "%s - Generated by msSaveQuery()\n", MS_QUERY_RESULTS_MAGIC_STRING); /* count the number of layers with results */ for(i=0; inumlayers; i++) if(GET_LAYER(map, i)->resultcache) n++; fwrite(&n, sizeof(int), 1, stream); /* now write the result set for each layer */ for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->resultcache) { fwrite(&i, sizeof(int), 1, stream); /* layer index */ fwrite(&(GET_LAYER(map, i)->resultcache->numresults), sizeof(int), 1, stream); /* number of results */ fwrite(&(GET_LAYER(map, i)->resultcache->bounds), sizeof(rectObj), 1, stream); /* bounding box */ for(j=0; jresultcache->numresults; j++) fwrite(&(GET_LAYER(map, i)->resultcache->results[j]), sizeof(resultObj), 1, stream); /* each result */ } } fclose(stream); return MS_SUCCESS; } static int loadQueryResults(mapObj *map, FILE *stream) { int i, j, k, n=0; if(1 != fread(&n, sizeof(int), 1, stream)) { msSetError(MS_MISCERR,"failed to read query count from query file stream", "loadQueryResults()"); return MS_FAILURE; } /* now load the result set for each layer found in the query file */ for(i=0; imap->numlayers) { msSetError(MS_MISCERR, "Invalid layer index loaded from query file.", "loadQueryResults()"); return MS_FAILURE; } /* inialize the results for this layer */ GET_LAYER(map, j)->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(GET_LAYER(map, j)->resultcache, sizeof(resultCacheObj), MS_FAILURE); if(1 != fread(&(GET_LAYER(map, j)->resultcache->numresults), sizeof(int), 1, stream) || (GET_LAYER(map, j)->resultcache->numresults < 0)) { /* number of results */ msSetError(MS_MISCERR,"failed to read number of results from query file stream", "loadQueryResults()"); free(GET_LAYER(map, j)->resultcache); GET_LAYER(map, j)->resultcache = NULL; return MS_FAILURE; } GET_LAYER(map, j)->resultcache->cachesize = GET_LAYER(map, j)->resultcache->numresults; if(1 != fread(&(GET_LAYER(map, j)->resultcache->bounds), sizeof(rectObj), 1, stream)) { /* bounding box */ msSetError(MS_MISCERR,"failed to read bounds from query file stream", "loadQueryResults()"); free(GET_LAYER(map, j)->resultcache); GET_LAYER(map, j)->resultcache = NULL; return MS_FAILURE; } GET_LAYER(map, j)->resultcache->results = (resultObj *) malloc(sizeof(resultObj)*GET_LAYER(map, j)->resultcache->numresults); if (GET_LAYER(map, j)->resultcache->results == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "loadQueryResults()", __FILE__, __LINE__, (unsigned int)(sizeof(resultObj)*GET_LAYER(map, j)->resultcache->numresults)); free(GET_LAYER(map, j)->resultcache); GET_LAYER(map, j)->resultcache = NULL; return MS_FAILURE; } for(k=0; kresultcache->numresults; k++) { if(1 != fread(&(GET_LAYER(map, j)->resultcache->results[k]), sizeof(resultObj), 1, stream)) { /* each result */ msSetError(MS_MISCERR,"failed to read result %d from query file stream", "loadQueryResults()", k); free(GET_LAYER(map, j)->resultcache->results); free(GET_LAYER(map, j)->resultcache); GET_LAYER(map, j)->resultcache = NULL; return MS_FAILURE; } if(!GET_LAYER(map, j)->tileindex) GET_LAYER(map, j)->resultcache->results[k].tileindex = -1; /* reset the tile index for non-tiled layers */ GET_LAYER(map, j)->resultcache->results[k].resultindex = -1; /* all results loaded this way have a -1 result (set) index */ } } return MS_SUCCESS; } /* ** Serialize the parameters necessary to duplicate a query to disk. (TODO: add filter query...) */ static int saveQueryParams(mapObj *map, char *filename) { FILE *stream; if(!filename) { msSetError(MS_MISCERR, "No filename provided to save query to.", "saveQueryParams()"); return MS_FAILURE; } stream = fopen(filename, "w"); if(!stream) { msSetError(MS_IOERR, "(%s)", "saveQueryParams()", filename); return MS_FAILURE; } fprintf(stream, "%s - Generated by msSaveQuery()\n", MS_QUERY_PARAMS_MAGIC_STRING); fprintf(stream, "%d %d %d %d\n", map->query.mode, map->query.type, map->query.layer, map->query.slayer); /* all queries */ fprintf(stream, "%.15g %.15g %g %d\n", map->query.point.x, map->query.point.y, map->query.buffer, map->query.maxresults); /* by point */ fprintf(stream, "%.15g %.15g %.15g %.15g\n", map->query.rect.minx, map->query.rect.miny, map->query.rect.maxx, map->query.rect.maxy); /* by rect */ fprintf(stream, "%ld %ld %d\n", map->query.shapeindex, map->query.tileindex, map->query.clear_resultcache); /* by index */ fprintf(stream, "%s\n", (map->query.filteritem)?map->query.filteritem:"NULL"); /* by filter */ fprintf(stream, "%s\n", (map->query.filter.string)?map->query.filter.string:"NULL"); if(map->query.shape) { /* by shape */ int i, j; shapeObj *s = map->query.shape; fprintf(stream, "%d\n", s->type); fprintf(stream, "%d\n", s->numlines); for(i=0; inumlines; i++) { fprintf(stream, "%d\n", s->line[i].numpoints); for(j=0; jline[i].numpoints; j++) fprintf(stream, "%.15g %.15g\n", s->line[i].point[j].x, s->line[i].point[j].y); } } else { fprintf(stream, "%d\n", MS_SHAPE_NULL); /* NULL shape */ } fclose(stream); return MS_SUCCESS; } static int loadQueryParams(mapObj *map, FILE *stream) { char buffer[MS_BUFFER_LENGTH]; int lineno; int shapetype, numlines, numpoints; msInitQuery(&(map->query)); /* this will free any previous query as well */ lineno = 2; /* line 1 is the magic string */ while(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) { switch(lineno) { case 2: if(sscanf(buffer, "%d %d %d %d\n", &(map->query.mode), &(map->query.type), &(map->query.layer), &(map->query.slayer)) != 4) goto parse_error; break; case 3: if(sscanf(buffer, "%lf %lf %lf %d\n", &map->query.point.x, &map->query.point.y, &map->query.buffer, &map->query.maxresults) != 4) goto parse_error; break; case 4: if(sscanf(buffer, "%lf %lf %lf %lf\n", &map->query.rect.minx, &map->query.rect.miny, &map->query.rect.maxx, &map->query.rect.maxy) != 4) goto parse_error; break; case 5: if(sscanf(buffer, "%ld %ld %d\n", &map->query.shapeindex, &map->query.tileindex, &map->query.clear_resultcache) != 3) goto parse_error; break; case 6: if(strncmp(buffer, "NULL", 4) != 0) { map->query.filteritem = msStrdup(buffer); msStringChop(map->query.filteritem); } break; case 7: if(strncmp(buffer, "NULL", 4) != 0) msLoadExpressionString(&map->query.filter, buffer); /* chop buffer */ break; case 8: if(sscanf(buffer, "%d\n", &shapetype) != 1) goto parse_error; if(shapetype != MS_SHAPE_NULL) { /* load the rest of the shape */ int i, j; lineObj line; map->query.shape = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(map->query.shape); map->query.shape->type = shapetype; if(fscanf(stream, "%d\n", &numlines) != 1) goto parse_error; for(i=0; iquery.shape, &line); free(line.point); } } break; default: break; } lineno++; } /* TODO: should we throw an error if lineno != 10? */ /* force layer and slayer on */ if(map->query.layer >= 0 && map->query.layer < map->numlayers) GET_LAYER(map, map->query.layer)->status = MS_ON; if(map->query.slayer >= 0 && map->query.slayer < map->numlayers) GET_LAYER(map, map->query.slayer)->status = MS_ON; /* now execute the query */ return msExecuteQuery(map); parse_error: msSetError(MS_MISCERR, "Parse error line %d.", "loadQueryParameters()", lineno); return MS_FAILURE; } /* ** Save (serialize) a query to disk. There are two methods, one saves the query parameters and the other saves ** all the shape indexes. Note the latter can be very slow against certain data sources but has a certain usefulness ** on occation. */ int msSaveQuery(mapObj *map, char *filename, int results) { if(results) return saveQueryResults(map, filename); else return saveQueryParams(map, filename); } /* ** Loads a query file contained either serialized 1) query parameters or 2) query results (e.g. indexes). */ int msLoadQuery(mapObj *map, char *filename) { FILE *stream; char buffer[MS_BUFFER_LENGTH]; int retval=MS_FAILURE; if(!filename) { msSetError(MS_MISCERR, "No filename provided to load query from.", "msLoadQuery()"); return MS_FAILURE; } /* ** Make sure the file at least has the right extension. */ if(msEvalRegex("\\.qy$", filename) != MS_TRUE) { msSetError(MS_MISCERR, "Queryfile %s has incorrect file extension.", "msLoadQuery()", filename); return MS_FAILURE; } /* ** Open the file and inspect the first line. */ stream = fopen(filename, "r"); if(!stream) { msSetError(MS_IOERR, "(%s)", "msLoadQuery()", filename); return MS_FAILURE; } if(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) { /* ** Call correct reader based on the magic string. */ if(strncasecmp(buffer, MS_QUERY_RESULTS_MAGIC_STRING, strlen(MS_QUERY_RESULTS_MAGIC_STRING)) == 0) { retval = loadQueryResults(map, stream); } else if(strncasecmp(buffer, MS_QUERY_PARAMS_MAGIC_STRING, strlen(MS_QUERY_PARAMS_MAGIC_STRING)) == 0) { retval = loadQueryParams(map, stream); } else { msSetError(MS_WEBERR, "Missing magic string, %s doesn't look like a MapServer query file.", "msLoadQuery()", filename); retval = MS_FAILURE; } } else { msSetError(MS_WEBERR, "Empty file or failed read for %s.", "msLoadQuery()", filename); retval = MS_FAILURE; } fclose(stream); return retval; } int msQueryByIndex(mapObj *map) { layerObj *lp; int status; resultObj record; queryCacheObj queryCache; shapeObj shape; double minfeaturesize = -1; initQueryCache(&queryCache); if(map->query.type != MS_QUERY_BY_INDEX) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByIndex()"); return(MS_FAILURE); } if(map->query.layer < 0 || map->query.layer >= map->numlayers) { msSetError(MS_QUERYERR, "No query layer defined.", "msQueryByIndex()"); return(MS_FAILURE); } lp = (GET_LAYER(map, map->query.layer)); if(!msIsLayerQueryable(lp)) { msSetError(MS_QUERYERR, "Requested layer has no templates defined.", "msQueryByIndex()"); return(MS_FAILURE); } if(map->query.clear_resultcache) { if(lp->resultcache) { cleanupResultCache(lp->resultcache); free(lp->resultcache); lp->resultcache = NULL; } } msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); /* disable driver paging */ msLayerEnablePaging(lp, MS_FALSE); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); if(map->query.clear_resultcache || lp->resultcache == NULL) { lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); } msInitShape(&shape); record.resultindex = -1; record.shapeindex = map->query.shapeindex; record.tileindex = map->query.tileindex; status = msLayerGetShape(lp, &shape, &record); if(status != MS_SUCCESS) { msSetError(MS_NOTFOUND, "Not valid record request.", "msQueryByIndex()"); return(MS_FAILURE); } /* * The resultindex is used to retrieve a specific item from the result cache. * Usually, the row number will be used as resultindex. But when working with * databases and querying a single result, the row number is typically 0 and * thus useless as the index in the result cache. See #4926 #4076. Only shape * files are considered to have consistent row numbers. */ if ( !(lp->connectiontype == MS_SHAPEFILE || lp->connectiontype == MS_TILED_SHAPEFILE) ) { shape.resultindex = -1; } if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { msSetError(MS_NOTFOUND, "Requested shape not valid against layer minfeaturesize.", "msQueryByIndex()"); msFreeShape(&shape); msLayerClose(lp); return(MS_FAILURE); } } shape.classindex = msShapeGetClass(lp, map, &shape, NULL, 0); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msSetError(MS_NOTFOUND, "Requested shape not valid against layer classification scheme.", "msQueryByIndex()"); msFreeShape(&shape); msLayerClose(lp); return(MS_FAILURE); } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msSetError(MS_NOTFOUND, "Requested shape does not have a valid template, no way to present results.", "msQueryByIndex()"); msFreeShape(&shape); msLayerClose(lp); return(MS_FAILURE); } addResult(map, lp->resultcache, &queryCache, &shape); msFreeShape(&shape); /* msLayerClose(lp); */ return(MS_SUCCESS); } static char *filterTranslateToLogical(expressionObj *filter, char *filteritem) { char *string = NULL; if(filter->type == MS_STRING && filteritem) { string = msStrdup("'["); string = msStringConcatenate(string, filteritem); string = msStringConcatenate(string, "]'"); if(filter->flags & MS_EXP_INSENSITIVE) string = msStringConcatenate(string, " =* '"); else string = msStringConcatenate(string, " = '"); string = msStringConcatenate(string, filter->string); string = msStringConcatenate(string, "'"); } else if(filter->type == MS_REGEX && filteritem) { string = msStrdup("'["); string = msStringConcatenate(string, filteritem); string = msStringConcatenate(string, "]'"); if(filter->flags & MS_EXP_INSENSITIVE) string = msStringConcatenate(string, " ~* '"); else string = msStringConcatenate(string, " ~ '"); string = msStringConcatenate(string, filter->string); string = msStringConcatenate(string, "'"); } else if(filter->type == MS_EXPRESSION) { string = msStrdup(filter->string); } else { /* native expression, nothing we can do - sigh */ } return string; } static expressionObj mergeFilters(expressionObj *filter1, char *filteritem1, expressionObj *filter2, char *filteritem2) { expressionObj filter; char *tmpstr1=NULL; char *tmpstr2=NULL; msInitExpression(&filter); filter.type = MS_EXPRESSION; /* we're building a logical expression */ tmpstr1 = filterTranslateToLogical(filter1, filteritem1); if(!tmpstr1) return filter; /* should only happen if the filter was a native filter */ tmpstr2 = filterTranslateToLogical(filter2, filteritem2); if(!tmpstr2) { msFree(tmpstr1); return filter; /* should only happen if the filter was a native filter */ } filter.string = msStrdup(tmpstr1); filter.string = msStringConcatenate(filter.string, " AND "); filter.string = msStringConcatenate(filter.string, tmpstr2); msFree(tmpstr1); msFree(tmpstr2); return filter; } /* ** Query using common expression syntax. */ int msQueryByFilter(mapObj *map) { int l; int start, stop=0; layerObj *lp; char status; char *old_filteritem=NULL; expressionObj old_filter; rectObj search_rect; const rectObj invalid_rect = MS_INIT_INVALID_RECT; shapeObj shape; int paging; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; queryCacheObj queryCache; initQueryCache(&queryCache); if(map->query.type != MS_QUERY_BY_FILTER) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByFilter()"); return(MS_FAILURE); } if(!map->query.filter.string) { msSetError(MS_QUERYERR, "Filter is not set.", "msQueryByFilter()"); return(MS_FAILURE); } // fprintf(stderr, "in msQueryByFilter: filter=%s, filteritem=%s\n", map->query.filter.string, map->query.filteritem); msInitShape(&shape); if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; for(l=start; l>=stop; l--) { lp = (GET_LAYER(map, l)); if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(lp->type == MS_LAYER_RASTER) continue; /* ok to skip? */ if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } paging = msLayerGetPaging(lp); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) goto query_error; msLayerEnablePaging(lp, paging); /* disable driver paging */ // msLayerEnablePaging(lp, MS_FALSE); old_filteritem = lp->filteritem; /* cache the existing filter/filteritem */ msInitExpression(&old_filter); msCopyExpression(&old_filter, &lp->filter); /* ** Set the lp->filter and lp->filteritem (may need to merge). Remember filters are *always* MapServer syntax. */ lp->filteritem = map->query.filteritem; /* re-point lp->filteritem */ if(old_filter.string != NULL) { /* need to merge filters to create one logical expression */ msFreeExpression(&lp->filter); lp->filter = mergeFilters(&map->query.filter, map->query.filteritem, &old_filter, old_filteritem); if(!lp->filter.string) { msSetError(MS_MISCERR, "Filter merge failed, able to process query.", "msQueryByFilter()"); goto query_error; } } else { msCopyExpression(&lp->filter, &map->query.filter); /* apply new filter */ } /* build item list, we want *all* items, note this *also* build tokens for the layer filter */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) goto query_error; search_rect = map->query.rect; /* If only result count is needed, we can use msLayerGetShapeCount() */ /* that has optimizations to avoid retrieving individual features */ if( map->query.only_cache_result_count && lp->template != NULL && /* always TRUE for WFS case */ lp->minfeaturesize <= 0 ) { int bUseLayerSRS = MS_FALSE; int numFeatures = -1; #if defined(USE_PROJ) && (defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) || defined(USE_WMS_LYR) || defined(USE_WFS_LYR)) /* Optimization to detect the case where a WFS query uses in fact the */ /* whole layer extent, but expressed in a map SRS different from the layer SRS */ /* In the case, we can directly request against the layer extent in its native SRS */ if( lp->project && memcmp( &search_rect, &invalid_rect, sizeof(search_rect) ) != 0 && msProjectionsDiffer(&(lp->projection), &(map->projection)) ) { rectObj layerExtent; if ( msOWSGetLayerExtent(map, lp, "FO", &layerExtent) == MS_SUCCESS) { rectObj ext = layerExtent; ext.minx -= 1e-5; ext.miny -= 1e-5; ext.maxx += 1e-5; ext.maxy += 1e-5; msProjectRect(&(lp->projection), &(map->projection), &ext); if( fabs(ext.minx - search_rect.minx) <= 2e-5 && fabs(ext.miny - search_rect.miny) <= 2e-5 && fabs(ext.maxx - search_rect.maxx) <= 2e-5 && fabs(ext.maxy - search_rect.maxy) <= 2e-5 ) { bUseLayerSRS = MS_TRUE; numFeatures = msLayerGetShapeCount(lp, layerExtent, &(lp->projection)); } } } #endif if( !bUseLayerSRS ) numFeatures = msLayerGetShapeCount(lp, search_rect, &(map->projection)); if( numFeatures >= 0 ) { lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); lp->resultcache->numresults = numFeatures; if (!msLayerGetPaging(lp) && map->query.startindex > 1) { lp->resultcache->numresults -= (map->query.startindex-1); } lp->filteritem = old_filteritem; /* point back to original value */ msCopyExpression(&lp->filter, &old_filter); /* restore old filter */ msFreeExpression(&old_filter); continue; } // Fallback in case of error (should not happen normally) } #ifdef USE_PROJ lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection)); if(lp->project && memcmp( &search_rect, &invalid_rect, sizeof(search_rect) ) != 0 ) msProjectRect(&(map->projection), &(lp->projection), &search_rect); /* project the searchrect to source coords */ #endif status = msLayerWhichShapes(lp, search_rect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); continue; } else if(status != MS_SUCCESS) goto query_error; lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ initResultCache( lp->resultcache); nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes - if necessary the filter is applied in msLayerNextShape(...) */ /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByFilter(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project) msProjectShape(&(lp->projection), &(map->projection), &shape); #endif /* Should we skip this feature? */ if (!paging && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } if( map->query.only_cache_result_count ) lp->resultcache->numresults ++; else addResult(map, lp->resultcache, &queryCache, &shape); msFreeShape(&shape); if(map->query.mode == MS_QUERY_SINGLE) { /* no need to look any further */ status = MS_DONE; break; } /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if(classgroup) msFree(classgroup); lp->filteritem = old_filteritem; /* point back to original value */ msCopyExpression(&lp->filter, &old_filter); /* restore old filter */ msFreeExpression(&old_filter); if(status != MS_DONE) goto query_error; if(!map->query.only_cache_result_count && lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ } /* next layer */ /* was anything found? */ for(l=start; l>=stop; l--) { if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return MS_SUCCESS; } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByFilter()"); return MS_FAILURE; query_error: // msFree(lp->filteritem); // lp->filteritem = old_filteritem; // msCopyExpression(&lp->filter, &old_filter); /* restore old filter */ // msFreeExpression(&old_filter); // msLayerClose(lp); return MS_FAILURE; } int msQueryByRect(mapObj *map) { int l; /* counters */ int start, stop=0; layerObj *lp; char status; shapeObj shape, searchshape; rectObj searchrect, searchrectInMapProj; const rectObj invalid_rect = MS_INIT_INVALID_RECT; double layer_tolerance = 0, tolerance = 0; int paging; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; queryCacheObj queryCache; initQueryCache(&queryCache); if(map->query.type != MS_QUERY_BY_RECT) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByRect()"); return(MS_FAILURE); } msInitShape(&shape); msInitShape(&searchshape); if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; for(l=start; l>=stop; l--) { lp = (GET_LAYER(map, l)); /* Set the global maxfeatures */ if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } searchrect = map->query.rect; if(lp->tolerance > 0) { layer_tolerance = lp->tolerance; if(lp->toleranceunits == MS_PIXELS) tolerance = layer_tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else tolerance = layer_tolerance * (msInchesPerUnit(lp->toleranceunits,0)/msInchesPerUnit(map->units,0)); searchrect.minx -= tolerance; searchrect.maxx += tolerance; searchrect.miny -= tolerance; searchrect.maxy += tolerance; } searchrectInMapProj = searchrect; msRectToPolygon(searchrect, &searchshape); /* Raster layers are handled specially. */ if( lp->type == MS_LAYER_RASTER ) { if( msRasterQueryByRect( map, lp, searchrect ) == MS_FAILURE) return MS_FAILURE; continue; } /* Paging could have been disabled before */ paging = msLayerGetPaging(lp); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) { msFreeShape(&searchshape); return(MS_FAILURE); } msLayerEnablePaging(lp, paging); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) { msFreeShape(&searchshape); return(MS_FAILURE); } /* If only result count is needed, we can use msLayerGetShapeCount() */ /* that has optimizations to avoid retrieving individual features */ if( map->query.only_cache_result_count && lp->template != NULL && /* always TRUE for WFS case */ lp->minfeaturesize <= 0 ) { int bUseLayerSRS = MS_FALSE; int numFeatures = -1; #if defined(USE_PROJ) && (defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) || defined(USE_WMS_LYR) || defined(USE_WFS_LYR)) /* Optimization to detect the case where a WFS query uses in fact the */ /* whole layer extent, but expressed in a map SRS different from the layer SRS */ /* In the case, we can directly request against the layer extent in its native SRS */ if( lp->project && memcmp( &searchrect, &invalid_rect, sizeof(searchrect) ) != 0 && msProjectionsDiffer(&(lp->projection), &(map->projection)) ) { rectObj layerExtent; if ( msOWSGetLayerExtent(map, lp, "FO", &layerExtent) == MS_SUCCESS) { rectObj ext = layerExtent; ext.minx -= 1e-5; ext.miny -= 1e-5; ext.maxx += 1e-5; ext.maxy += 1e-5; msProjectRect(&(lp->projection), &(map->projection), &ext); if( fabs(ext.minx - searchrect.minx) <= 2e-5 && fabs(ext.miny - searchrect.miny) <= 2e-5 && fabs(ext.maxx - searchrect.maxx) <= 2e-5 && fabs(ext.maxy - searchrect.maxy) <= 2e-5 ) { bUseLayerSRS = MS_TRUE; numFeatures = msLayerGetShapeCount(lp, layerExtent, &(lp->projection)); } } } #endif if( !bUseLayerSRS ) numFeatures = msLayerGetShapeCount(lp, searchrect, &(map->projection)); if( numFeatures >= 0 ) { lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); lp->resultcache->numresults = numFeatures; if (!paging && map->query.startindex > 1) { lp->resultcache->numresults -= (map->query.startindex-1); } msFreeShape(&searchshape); continue; } // Fallback in case of error (should not happen normally) } #ifdef USE_PROJ lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection)); if(lp->project && memcmp( &searchrect, &invalid_rect, sizeof(searchrect) ) != 0 ) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); continue; } else if(status != MS_SUCCESS) { msLayerClose(lp); msFreeShape(&searchshape); return(MS_FAILURE); } lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByRect(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project) msProjectShape(&(lp->projection), &(map->projection), &shape); #endif if(msRectContained(&shape.bounds, &searchrectInMapProj) == MS_TRUE) { /* if the whole shape is in, don't intersect */ status = MS_TRUE; } else { switch(shape.type) { /* make sure shape actually intersects the qrect (ADD FUNCTIONS SPECIFIC TO RECTOBJ) */ case MS_SHAPE_POINT: status = msIntersectMultipointPolygon(&shape, &searchshape); break; case MS_SHAPE_LINE: status = msIntersectPolylinePolygon(&shape, &searchshape); break; case MS_SHAPE_POLYGON: status = msIntersectPolygons(&shape, &searchshape); break; default: break; } } if(status == MS_TRUE) { /* Should we skip this feature? */ if (!paging && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } if( map->query.only_cache_result_count ) lp->resultcache->numresults ++; else addResult(map, lp->resultcache, &queryCache, &shape); --map->query.maxfeatures; } msFreeShape(&shape); /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if (classgroup) msFree(classgroup); if(status != MS_DONE) { msFreeShape(&searchshape); return(MS_FAILURE); } if( !map->query.only_cache_result_count && lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ } /* next layer */ msFreeShape(&searchshape); /* was anything found? */ for(l=start; l>=stop; l--) { if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return(MS_SUCCESS); } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByRect()"); return(MS_FAILURE); } static int is_duplicate(resultCacheObj *resultcache, int shapeindex, int tileindex) { int i; for(i=0; inumresults; i++) if(resultcache->results[i].shapeindex == shapeindex && resultcache->results[i].tileindex == tileindex) return(MS_TRUE); return(MS_FALSE); } int msQueryByFeatures(mapObj *map) { int i, l; int start, stop=0; layerObj *lp, *slp; char status; double distance, tolerance, layer_tolerance; rectObj searchrect; shapeObj shape, selectshape; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; queryCacheObj queryCache; initQueryCache(&queryCache); if(map->debug) msDebug("in msQueryByFeatures()\n"); /* is the selection layer valid and has it been queried */ if(map->query.slayer < 0 || map->query.slayer >= map->numlayers) { msSetError(MS_QUERYERR, "Invalid selection layer index.", "msQueryByFeatures()"); return(MS_FAILURE); } slp = (GET_LAYER(map, map->query.slayer)); if(!slp->resultcache) { msSetError(MS_QUERYERR, "Selection layer has not been queried.", "msQueryByFeatures()"); return(MS_FAILURE); } /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ slp->project = msProjectionsDiffer(&(slp->projection), &(map->projection)); if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; /* selection layers should already be open */ /* status = msLayerOpen(slp); if(status != MS_SUCCESS) return(MS_FAILURE); */ msInitShape(&shape); /* initialize a few things */ msInitShape(&selectshape); for(l=start; l>=stop; l--) { if(l == map->query.slayer) continue; /* skip the selection layer */ lp = (GET_LAYER(map, l)); if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection)); /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } /* Get the layer tolerance default is 3 for point and line layers, 0 for others */ if(lp->tolerance == -1) { if(lp->type == MS_LAYER_POINT || lp->type == MS_LAYER_LINE) layer_tolerance = 3; else layer_tolerance = 0; } else layer_tolerance = lp->tolerance; if(lp->toleranceunits == MS_PIXELS) tolerance = layer_tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else tolerance = layer_tolerance * (msInchesPerUnit(lp->toleranceunits,0)/msInchesPerUnit(map->units,0)); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); msLayerEnablePaging(lp, MS_FALSE); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); /* for each selection shape */ for(i=0; iresultcache->numresults; i++) { status = msLayerGetShape(slp, &selectshape, &(slp->resultcache->results[i])); if(status != MS_SUCCESS) { msLayerClose(lp); msLayerClose(slp); return(MS_FAILURE); } if(selectshape.type != MS_SHAPE_POLYGON && selectshape.type != MS_SHAPE_LINE) { msLayerClose(lp); msLayerClose(slp); msSetError(MS_QUERYERR, "Selection features MUST be polygons or lines.", "msQueryByFeatures()"); return(MS_FAILURE); } #ifdef USE_PROJ if(slp->project) msProjectShape(&(slp->projection), &(map->projection), &selectshape); #endif /* identify target shapes */ searchrect = selectshape.bounds; searchrect.minx -= tolerance; /* expand the search box to account for layer tolerances (e.g. buffered searches) */ searchrect.maxx += tolerance; searchrect.miny -= tolerance; searchrect.maxy += tolerance; #ifdef USE_PROJ if(lp->project) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); break; /* next layer */ } else if(status != MS_SUCCESS) { msLayerClose(lp); msLayerClose(slp); return(MS_FAILURE); } if(i == 0) { lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); } nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* check for dups when there are multiple selection shapes */ if(i > 0 && is_duplicate(lp->resultcache, shape.index, shape.tileindex)) continue; /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByFeature(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project) msProjectShape(&(lp->projection), &(map->projection), &shape); #endif switch(selectshape.type) { /* may eventually support types other than polygon on line */ case MS_SHAPE_POLYGON: switch(shape.type) { /* make sure shape actually intersects the selectshape */ case MS_SHAPE_POINT: if(tolerance == 0) /* just test for intersection */ status = msIntersectMultipointPolygon(&shape, &selectshape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_LINE: if(tolerance == 0) { /* just test for intersection */ status = msIntersectPolylinePolygon(&shape, &selectshape); } else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_POLYGON: if(tolerance == 0) /* just test for intersection */ status = msIntersectPolygons(&shape, &selectshape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; default: status = MS_FALSE; break; } break; case MS_SHAPE_LINE: switch(shape.type) { /* make sure shape actually intersects the selectshape */ case MS_SHAPE_POINT: if(tolerance == 0) { /* just test for intersection */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance == 0) status = MS_TRUE; } else { distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_LINE: if(tolerance == 0) { /* just test for intersection */ status = msIntersectPolylines(&shape, &selectshape); } else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_POLYGON: if(tolerance == 0) /* just test for intersection */ status = msIntersectPolylinePolygon(&selectshape, &shape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(&selectshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; default: status = MS_FALSE; break; } break; default: break; /* should never get here as we test for selection shape type explicitly earlier */ } if(status == MS_TRUE) { /* Should we skip this feature? */ if (!msLayerGetPaging(lp) && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } addResult(map, lp->resultcache, &queryCache, &shape); } msFreeShape(&shape); /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if (classgroup) msFree(classgroup); if(status != MS_DONE) return(MS_FAILURE); msFreeShape(&selectshape); } /* next selection shape */ if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ } /* next layer */ /* was anything found? */ for(l=start; l>=stop; l--) { if(l == map->query.slayer) continue; /* skip the selection layer */ if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return(MS_SUCCESS); } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByFeatures()"); return(MS_FAILURE); } /* msQueryByPoint() * * With mode=MS_QUERY_SINGLE: * Set maxresults = 0 to have a single result across all layers (the closest * shape from the first layer that finds a match). * Set maxresults = 1 to have up to one result per layer (the closest shape * from each layer). * * With mode=MS_QUERY_MULTIPLE: * Set maxresults = 0 to have an unlimited number of results. * Set maxresults > 0 to limit the number of results per layer (the shapes * returned are the first ones found in each layer and are not necessarily * the closest ones). */ int msQueryByPoint(mapObj *map) { int l; int start, stop=0; double d, t; double layer_tolerance; layerObj *lp; int paging; char status; rectObj rect, searchrect; shapeObj shape; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; queryCacheObj queryCache; initQueryCache(&queryCache); if(map->query.type != MS_QUERY_BY_POINT) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByPoint()"); return(MS_FAILURE); } msInitShape(&shape); if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; for(l=start; l>=stop; l--) { lp = (GET_LAYER(map, l)); if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } /* Raster layers are handled specially. */ if( lp->type == MS_LAYER_RASTER ) { if( msRasterQueryByPoint( map, lp, map->query.mode, map->query.point, map->query.buffer, map->query.maxresults ) == MS_FAILURE ) return MS_FAILURE; continue; } /* Get the layer tolerance default is 3 for point and line layers, 0 for others */ if(lp->tolerance == -1) { if(lp->type == MS_LAYER_POINT || lp->type == MS_LAYER_LINE) layer_tolerance = 3; else layer_tolerance = 0; } else layer_tolerance = lp->tolerance; if(map->query.buffer <= 0) { /* use layer tolerance */ if(lp->toleranceunits == MS_PIXELS) t = layer_tolerance * MS_MAX(MS_CELLSIZE(map->extent.minx, map->extent.maxx, map->width), MS_CELLSIZE(map->extent.miny, map->extent.maxy, map->height)); else t = layer_tolerance * (msInchesPerUnit(lp->toleranceunits,0)/msInchesPerUnit(map->units,0)); } else /* use buffer distance */ t = map->query.buffer; rect.minx = map->query.point.x - t; rect.maxx = map->query.point.x + t; rect.miny = map->query.point.y - t; rect.maxy = map->query.point.y + t; /* Paging could have been disabled before */ paging = msLayerGetPaging(lp); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); msLayerEnablePaging(lp, paging); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); /* identify target shapes */ searchrect = rect; #ifdef USE_PROJ lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection)); if(lp->project) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); continue; } else if(status != MS_SUCCESS) { msLayerClose(lp); return(MS_FAILURE); } lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); nclasses = 0; classgroup = NULL; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByPoint(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project) msProjectShape(&(lp->projection), &(map->projection), &shape); #endif d = msDistancePointToShape(&(map->query.point), &shape); if( d <= t ) { /* found one */ /* Should we skip this feature? */ if (!paging && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } if(map->query.mode == MS_QUERY_SINGLE) { cleanupResultCache(lp->resultcache); initQueryCache(&queryCache); addResult(map, lp->resultcache, &queryCache, &shape); t = d; /* next one must be closer */ } else { addResult(map, lp->resultcache, &queryCache, &shape); } } msFreeShape(&shape); if(map->query.mode == MS_QUERY_MULTIPLE && map->query.maxresults > 0 && lp->resultcache->numresults == map->query.maxresults) { status = MS_DONE; /* got enough results for this layer */ break; } /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if (classgroup) msFree(classgroup); if(status != MS_DONE) return(MS_FAILURE); if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ if((lp->resultcache->numresults > 0) && (map->query.mode == MS_QUERY_SINGLE) && (map->query.maxresults == 0)) break; /* no need to search any further */ } /* next layer */ /* was anything found? */ for(l=start; l>=stop; l--) { if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return(MS_SUCCESS); } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByPoint()"); return(MS_FAILURE); } int msQueryByShape(mapObj *map) { int start, stop=0, l; shapeObj shape, *qshape=NULL; layerObj *lp; char status; double distance, tolerance, layer_tolerance; rectObj searchrect; int nclasses = 0; int *classgroup = NULL; double minfeaturesize = -1; queryCacheObj queryCache; initQueryCache(&queryCache); if(map->query.type != MS_QUERY_BY_SHAPE) { msSetError(MS_QUERYERR, "The query is not properly defined.", "msQueryByShape()"); return(MS_FAILURE); } if(!(map->query.shape)) { msSetError(MS_QUERYERR, "Query shape is not defined.", "msQueryByShape()"); return(MS_FAILURE); } if(map->query.shape->type != MS_SHAPE_POLYGON && map->query.shape->type != MS_SHAPE_LINE && map->query.shape->type != MS_SHAPE_POINT) { msSetError(MS_QUERYERR, "Query shape MUST be a polygon, line or point.", "msQueryByShape()"); return(MS_FAILURE); } msInitShape(&shape); qshape = map->query.shape; /* for brevity */ if(map->query.layer < 0 || map->query.layer >= map->numlayers) start = map->numlayers-1; else start = stop = map->query.layer; msComputeBounds(qshape); /* make sure an accurate extent exists */ for(l=start; l>=stop; l--) { /* each layer */ lp = (GET_LAYER(map, l)); if (map->query.maxfeatures == 0) break; /* nothing else to do */ else if (map->query.maxfeatures > 0) lp->maxfeatures = map->query.maxfeatures; /* using mapscript, the map->query.startindex will be unset... */ if (lp->startindex > 1 && map->query.startindex < 0) map->query.startindex = lp->startindex; /* conditions may have changed since this layer last drawn, so set layer->project true to recheck projection needs (Bug #673) */ lp->project = MS_TRUE; /* free any previous search results, do it now in case one of the next few tests fail */ if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } if(!msIsLayerQueryable(lp)) continue; if(lp->status == MS_OFF) continue; if(map->scaledenom > 0) { if((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom)) continue; if((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom)) continue; } if (lp->maxscaledenom <= 0 && lp->minscaledenom <= 0) { if((lp->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > lp->maxgeowidth)) continue; if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue; } /* Raster layers are handled specially. */ if( lp->type == MS_LAYER_RASTER ) { if( msRasterQueryByShape(map, lp, qshape) == MS_FAILURE ) return MS_FAILURE; continue; } /* Get the layer tolerance default is 3 for point and line layers, 0 for others */ if(lp->tolerance == -1) { if(lp->type == MS_LAYER_POINT || lp->type == MS_LAYER_LINE) layer_tolerance = 3; else layer_tolerance = 0; } else layer_tolerance = lp->tolerance; if(lp->toleranceunits == MS_PIXELS) tolerance = layer_tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else tolerance = layer_tolerance * (msInchesPerUnit(lp->toleranceunits,0)/msInchesPerUnit(map->units,0)); msLayerClose(lp); /* reset */ status = msLayerOpen(lp); if(status != MS_SUCCESS) return(MS_FAILURE); /* disable driver paging */ msLayerEnablePaging(lp, MS_FALSE); /* build item list, we want *all* items */ status = msLayerWhichItems(lp, MS_TRUE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); /* identify target shapes */ searchrect = qshape->bounds; searchrect.minx -= tolerance; /* expand the search box to account for layer tolerances (e.g. buffered searches) */ searchrect.maxx += tolerance; searchrect.miny -= tolerance; searchrect.maxy += tolerance; #ifdef USE_PROJ lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection)); if(lp->project) msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */ #endif status = msLayerWhichShapes(lp, searchrect, MS_TRUE); if(status == MS_DONE) { /* no overlap */ msLayerClose(lp); continue; } else if(status != MS_SUCCESS) { msLayerClose(lp); return(MS_FAILURE); } lp->resultcache = (resultCacheObj *)malloc(sizeof(resultCacheObj)); /* allocate and initialize the result cache */ MS_CHECK_ALLOC(lp->resultcache, sizeof(resultCacheObj), MS_FAILURE); initResultCache( lp->resultcache); nclasses = 0; if (lp->classgroup && lp->numclasses > 0) classgroup = msAllocateValidClassGroups(lp, &nclasses); if (lp->minfeaturesize > 0) minfeaturesize = Pix2LayerGeoref(map, lp, lp->minfeaturesize); while((status = msLayerNextShape(lp, &shape)) == MS_SUCCESS) { /* step through the shapes */ /* Check if the shape size is ok to be drawn */ if ( (shape.type == MS_SHAPE_LINE || shape.type == MS_SHAPE_POLYGON) && (minfeaturesize > 0) ) { if (msShapeCheckSize(&shape, minfeaturesize) == MS_FALSE) { if( lp->debug >= MS_DEBUGLEVEL_V ) msDebug("msQueryByShape(): Skipping shape (%ld) because LAYER::MINFEATURESIZE is bigger than shape size\n", shape.index); msFreeShape(&shape); continue; } } shape.classindex = msShapeGetClass(lp, map, &shape, classgroup, nclasses); if(!(lp->template) && ((shape.classindex == -1) || (lp->class[shape.classindex]->status == MS_OFF))) { /* not a valid shape */ msFreeShape(&shape); continue; } if(!(lp->template) && !(lp->class[shape.classindex]->template)) { /* no valid template */ msFreeShape(&shape); continue; } #ifdef USE_PROJ if(lp->project) msProjectShape(&(lp->projection), &(map->projection), &shape); #endif switch(qshape->type) { /* may eventually support types other than polygon or line */ case MS_SHAPE_POLYGON: switch(shape.type) { /* make sure shape actually intersects the shape */ case MS_SHAPE_POINT: if(tolerance == 0) /* just test for intersection */ status = msIntersectMultipointPolygon(&shape, qshape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_LINE: if(tolerance == 0) { /* just test for intersection */ status = msIntersectPolylinePolygon(&shape, qshape); } else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_POLYGON: if(tolerance == 0) /* just test for intersection */ status = msIntersectPolygons(&shape, qshape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; default: break; } break; case MS_SHAPE_LINE: switch(shape.type) { /* make sure shape actually intersects the selectshape */ case MS_SHAPE_POINT: if(tolerance == 0) { /* just test for intersection */ distance = msDistanceShapeToShape(qshape, &shape); if(distance == 0) status = MS_TRUE; } else { distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_LINE: if(tolerance == 0) { /* just test for intersection */ status = msIntersectPolylines(&shape, qshape); } else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; case MS_SHAPE_POLYGON: if(tolerance == 0) /* just test for intersection */ status = msIntersectPolylinePolygon(qshape, &shape); else { /* check distance, distance=0 means they intersect */ distance = msDistanceShapeToShape(qshape, &shape); if(distance < tolerance) status = MS_TRUE; } break; default: status = MS_FALSE; break; } break; case MS_SHAPE_POINT: distance = msDistanceShapeToShape(qshape, &shape); status = MS_FALSE; if(tolerance == 0 && distance == 0) status = MS_TRUE; /* shapes intersect */ else if(distance < tolerance) status = MS_TRUE; /* shapes are close enough */ break; default: break; /* should never get here as we test for selection shape type explicitly earlier */ } if(status == MS_TRUE) { /* Should we skip this feature? */ if (!msLayerGetPaging(lp) && map->query.startindex > 1) { --map->query.startindex; msFreeShape(&shape); continue; } addResult(map, lp->resultcache, &queryCache, &shape); } msFreeShape(&shape); /* check shape count */ if(lp->maxfeatures > 0 && lp->maxfeatures == lp->resultcache->numresults) { status = MS_DONE; break; } } /* next shape */ if(status != MS_DONE) { free(classgroup); return(MS_FAILURE); } if(lp->resultcache->numresults == 0) msLayerClose(lp); /* no need to keep the layer open */ free(classgroup); classgroup = NULL; } /* next layer */ /* was anything found? */ for(l=start; l>=stop; l--) { if(GET_LAYER(map, l)->resultcache && GET_LAYER(map, l)->resultcache->numresults > 0) return(MS_SUCCESS); } msSetError(MS_NOTFOUND, "No matching record(s) found.", "msQueryByShape()"); return(MS_FAILURE); } /* msGetQueryResultBounds() * * Compute the BBOX of all query results, returns the number of layers found * that contained query results and were included in the BBOX. * i.e. if we return 0 then the value in bounds is invalid. */ int msGetQueryResultBounds(mapObj *map, rectObj *bounds) { int i, found=0; rectObj tmpBounds; for(i=0; inumlayers; i++) { layerObj *lp; lp = (GET_LAYER(map, i)); if(!lp->resultcache) continue; if(lp->resultcache->numresults <= 0) continue; tmpBounds = lp->resultcache->bounds; if(found == 0) { *bounds = tmpBounds; } else { msMergeRect(bounds, &tmpBounds); } found++; } return found; } /* TODO: Rename this msFreeResultSet() or something along those lines... */ /* msQueryFree() * * Free layer's query results. If qlayer == -1, all layers will be treated. */ void msQueryFree(mapObj *map, int qlayer) { int l; /* counters */ int start, stop=0; layerObj *lp; if(qlayer < 0 || qlayer >= map->numlayers) start = map->numlayers-1; else start = stop = qlayer; for(l=start; l>=stop; l--) { lp = (GET_LAYER(map, l)); if(lp->resultcache) { if(lp->resultcache->results) free(lp->resultcache->results); free(lp->resultcache); lp->resultcache = NULL; } } } mapserver-7.4.3/mapraster.c000066400000000000000000001201161357574274700157210ustar00rootroot00000000000000/****************************************************************************** * $id: mapraster.c 10772 2010-11-29 18:27:02Z aboudreault $ * * Project: MapServer * Purpose: msDrawRasterLayer(): generic raster layer drawing. * Author: Frank Warmerdam, warmerdam@pobox.com * Pete Olson (LMIC) * Steve Lime * ****************************************************************************** * Copyright (c) 1996-2010 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include "mapserver.h" #include "mapfile.h" #include "mapresample.h" #include "mapthread.h" extern int msyylex_destroy(void); extern int yyparse(parseObj *); extern parseResultObj yypresult; /* result of parsing, true/false */ #ifdef USE_GDAL #include "gdal.h" #include "cpl_string.h" #endif #include "mapraster.h" #define MAXCOLORS 256 #define BUFLEN 1024 #define HDRLEN 8 #define CVT(x) ((x) >> 8) /* converts to 8-bit color value */ #define NUMGRAYS 16 /************************************************************************/ /* msGetClass_String() */ /************************************************************************/ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value, int firstClassToTry ) { int i; const char *tmpstr1=NULL; int numitems; char *item_names[4] = { "pixel", "red", "green", "blue" }; char *item_values[4]; char red_value[8], green_value[8], blue_value[8]; /* -------------------------------------------------------------------- */ /* No need to do a lookup in the case of one default class. */ /* -------------------------------------------------------------------- */ if((layer->numclasses == 1) && !(layer->class[0]->expression.string)) /* no need to do lookup */ return(0); /* -------------------------------------------------------------------- */ /* Setup values list for expressions. */ /* -------------------------------------------------------------------- */ numitems = 4; if( color->red == -1 && color->green == -1 && color->blue == -1 ) { strcpy(red_value, "-1"); strcpy(green_value, "-1"); strcpy(blue_value, "-1"); } else { sprintf( red_value, "%d", color->red ); sprintf( green_value, "%d", color->green ); sprintf( blue_value, "%d", color->blue ); } item_values[0] = (char *)pixel_value; item_values[1] = red_value; item_values[2] = green_value; item_values[3] = blue_value; /* -------------------------------------------------------------------- */ /* Loop over classes till we find a match. */ /* -------------------------------------------------------------------- */ for(i= (firstClassToTry < 0 ) ? 0 : -1; inumclasses; i++) { int idx = i; if( i < 0 ) idx = firstClassToTry; else if( i == firstClassToTry ) continue; /* check for correct classgroup, if set */ if ( layer->class[idx]->group && layer->classgroup && strcasecmp(layer->class[idx]->group, layer->classgroup) != 0 ) continue; /* Empty expression - always matches */ if (layer->class[idx]->expression.string == NULL) return(i); switch(layer->class[idx]->expression.type) { /* -------------------------------------------------------------------- */ /* Simple string match */ /* -------------------------------------------------------------------- */ case(MS_STRING): /* trim junk white space */ tmpstr1= pixel_value; while( *tmpstr1 == ' ' ) tmpstr1++; if(strcmp(layer->class[idx]->expression.string, tmpstr1) == 0) return(idx); /* matched */ break; /* -------------------------------------------------------------------- */ /* Regular expression. Rarely used for raster. */ /* -------------------------------------------------------------------- */ case(MS_REGEX): if(!layer->class[idx]->expression.compiled) { if(ms_regcomp(&(layer->class[idx]->expression.regex), layer->class[idx]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */ msSetError(MS_REGEXERR, "Invalid regular expression.", "msGetClass()"); return(-1); } layer->class[idx]->expression.compiled = MS_TRUE; } if(ms_regexec(&(layer->class[idx]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(idx); /* got a match */ break; /* -------------------------------------------------------------------- */ /* Parsed expression. */ /* -------------------------------------------------------------------- */ case(MS_EXPRESSION): { int status; parseObj p; shapeObj dummy_shape; expressionObj *expression = &(layer->class[idx]->expression); dummy_shape.numvalues = numitems; dummy_shape.values = item_values; if( expression->tokens == NULL ) msTokenizeExpression( expression, item_names, &numitems ); p.shape = &dummy_shape; p.expr = expression; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_BOOLEAN; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to parse expression: %s", "msGetClass_FloatRGB", expression->string); return -1; } if( p.result.intval ) return idx; break; } } } return(-1); /* not found */ } /************************************************************************/ /* msGetClass() */ /************************************************************************/ int msGetClass(layerObj *layer, colorObj *color, int colormap_index) { char pixel_value[12]; snprintf( pixel_value, sizeof(pixel_value), "%d", colormap_index ); return msGetClass_String( layer, color, pixel_value, -1 ); } /************************************************************************/ /* msGetClass_FloatRGB() */ /* */ /* Returns the class based on classification of a floating */ /* pixel value. */ /************************************************************************/ int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue ) { return msGetClass_FloatRGB_WithFirstClassToTry( layer, fValue, red, green, blue, -1); } int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry ) { char pixel_value[100]; colorObj color; color.red = red; color.green = green; color.blue = blue; snprintf( pixel_value, sizeof(pixel_value), "%18g", fValue ); return msGetClass_String( layer, &color, pixel_value, firstClassToTry ); } #if defined(USE_GDAL) /************************************************************************/ /* msRasterSetupTileLayer() */ /* */ /* Setup the tile layer. */ /************************************************************************/ int msDrawRasterSetupTileLayer(mapObj *map, layerObj *layer, rectObj* psearchrect, int is_query, int* ptilelayerindex, /* output */ int* ptileitemindex, /* output */ int* ptilesrsindex, /* output */ layerObj **ptlp /* output */ ) { int i; char* requested_fields; int status; layerObj* tlp = NULL; *ptilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); if(*ptilelayerindex == -1) { /* the tileindex references a file, not a layer */ /* so we create a temporary layer */ tlp = (layerObj *) malloc(sizeof(layerObj)); MS_CHECK_ALLOC(tlp, sizeof(layerObj), MS_FAILURE); initLayer(tlp, map); *ptlp = tlp; /* set a few parameters for a very basic shapefile-based layer */ tlp->name = msStrdup("TILE"); tlp->type = MS_LAYER_TILEINDEX; tlp->data = msStrdup(layer->tileindex); if( is_query ) { tlp->map = map; /*needed when scaletokens are applied, to extract current map scale */ for(i = 0; i < layer->numscaletokens; i++) { if(msGrowLayerScaletokens(tlp) == NULL) { return MS_FAILURE; } initScaleToken(&tlp->scaletokens[i]); msCopyScaleToken(&layer->scaletokens[i],&tlp->scaletokens[i]); tlp->numscaletokens++; } } if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { tlp->projection.numargs = 1; tlp->projection.args[0] = msStrdup("auto"); } if (layer->filteritem) tlp->filteritem = msStrdup(layer->filteritem); if (layer->filter.string) { if (layer->filter.type == MS_EXPRESSION) { char* pszTmp = (char *)msSmallMalloc(sizeof(char)*(strlen(layer->filter.string)+3)); sprintf(pszTmp,"(%s)",layer->filter.string); msLoadExpressionString(&tlp->filter, pszTmp); free(pszTmp); } else if (layer->filter.type == MS_REGEX || layer->filter.type == MS_IREGEX) { char* pszTmp = (char *)msSmallMalloc(sizeof(char)*(strlen(layer->filter.string)+3)); sprintf(pszTmp,"/%s/",layer->filter.string); msLoadExpressionString(&tlp->filter, pszTmp); free(pszTmp); } else msLoadExpressionString(&tlp->filter, layer->filter.string); tlp->filter.type = layer->filter.type; } } else { if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tlp = (GET_LAYER(layer->map, *ptilelayerindex)); *ptlp = tlp; } status = msLayerOpen(tlp); if(status != MS_SUCCESS) { return status; } /* fetch tileitem and tilesrs fields */ requested_fields = (char*) msSmallMalloc(sizeof(char)*(strlen(layer->tileitem)+1+ (layer->tilesrs ? strlen(layer->tilesrs) : 0) + 1)); if( layer->tilesrs != NULL ) sprintf(requested_fields, "%s,%s", layer->tileitem, layer->tilesrs); else strcpy(requested_fields, layer->tileitem); status = msLayerWhichItems(tlp, MS_FALSE, requested_fields); msFree(requested_fields); if(status != MS_SUCCESS) { return status; } /* get the tileitem and tilesrs index */ for(i=0; inumitems; i++) { if(strcasecmp(tlp->items[i], layer->tileitem) == 0) { *ptileitemindex = i; } if(layer->tilesrs != NULL && strcasecmp(tlp->items[i], layer->tilesrs) == 0) { *ptilesrsindex = i; } } if(*ptileitemindex < 0) { /* didn't find it */ msSetError(MS_MEMERR, "Could not find attribute %s in tileindex.", "msDrawRasterLayerLow()", layer->tileitem); return MS_FAILURE; } if(layer->tilesrs != NULL && *ptilesrsindex < 0) { /* didn't find it */ msSetError(MS_MEMERR, "Could not find attribute %s in tileindex.", "msDrawRasterLayerLow()", layer->tilesrs); return MS_FAILURE; } #ifdef USE_PROJ /* if necessary, project the searchrect to source coords */ if((map->projection.numargs > 0) && (layer->projection.numargs > 0) && !EQUAL(layer->projection.args[0], "auto")) { if( msProjectRect(&map->projection, &layer->projection, psearchrect) != MS_SUCCESS ) { msDebug( "msDrawRasterLayerLow(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name ); return MS_FAILURE; } } else if((map->projection.numargs > 0) && (tlp->projection.numargs > 0) && !EQUAL(tlp->projection.args[0], "auto")) { if( msProjectRect(&map->projection, &tlp->projection, psearchrect) != MS_SUCCESS ) { msDebug( "msDrawRasterLayerLow(%s): unable to reproject map request rectangle into layer projection, canceling.\n", layer->name ); return MS_FAILURE; } } #endif return msLayerWhichShapes(tlp, *psearchrect, MS_FALSE); } /************************************************************************/ /* msDrawRasterCleanupTileLayer() */ /* */ /* Cleanup the tile layer. */ /************************************************************************/ void msDrawRasterCleanupTileLayer(layerObj* tlp, int tilelayerindex) { msLayerClose(tlp); if(tilelayerindex == -1) { freeLayer(tlp); free(tlp); } } /************************************************************************/ /* msDrawRasterIterateTileIndex() */ /* */ /* Iterate over the tile layer. */ /************************************************************************/ int msDrawRasterIterateTileIndex(layerObj *layer, layerObj* tlp, shapeObj* ptshp, /* input-output */ int tileitemindex, int tilesrsindex, char* tilename, /* output */ size_t sizeof_tilename, char* tilesrsname, /* output */ size_t sizeof_tilesrsname) { int status; status = msLayerNextShape(tlp, ptshp); if( status == MS_FAILURE || status == MS_DONE ) { return status; } if(layer->data == NULL || strlen(layer->data) == 0 ) { /* assume whole filename is in attribute field */ strlcpy( tilename, ptshp->values[tileitemindex], sizeof_tilename); } else snprintf(tilename, sizeof_tilename, "%s/%s", ptshp->values[tileitemindex], layer->data); tilesrsname[0] = '\0'; if( tilesrsindex >= 0 ) { if(ptshp->values[tilesrsindex] != NULL ) strlcpy( tilesrsname, ptshp->values[tilesrsindex], sizeof_tilesrsname ); } msFreeShape(ptshp); /* done with the shape */ return status; } /************************************************************************/ /* msDrawRasterBuildRasterPath() */ /* */ /* Build the path of the raster to open. */ /************************************************************************/ int msDrawRasterBuildRasterPath(mapObj *map, layerObj *layer, const char* filename, char szPath[MS_MAXPATHLEN] /* output */) { /* ** If using a tileindex then build the path relative to that file if SHAPEPATH is not set. */ if(layer->tileindex && !map->shapepath) { char tiAbsFilePath[MS_MAXPATHLEN]; char *tiAbsDirPath = NULL; msTryBuildPath(tiAbsFilePath, map->mappath, layer->tileindex); /* absolute path to tileindex file */ tiAbsDirPath = msGetPath(tiAbsFilePath); /* tileindex file's directory */ msBuildPath(szPath, tiAbsDirPath, filename); free(tiAbsDirPath); } else { msTryBuildPath3(szPath, map->mappath, map->shapepath, filename); } return MS_SUCCESS; } /************************************************************************/ /* msDrawRasterGetCPLErrorMsg() */ /* */ /* Return the CPL error message, and filter out sensitive info. */ /************************************************************************/ const char* msDrawRasterGetCPLErrorMsg(const char* decrypted_path, const char* szPath) { const char *cpl_error_msg = CPLGetLastErrorMsg(); /* we wish to avoid reporting decrypted paths */ if( cpl_error_msg != NULL && strstr(cpl_error_msg,decrypted_path) != NULL && strcmp(decrypted_path,szPath) != 0 ) cpl_error_msg = NULL; /* we wish to avoid reporting the stock GDALOpen error messages */ if( cpl_error_msg != NULL && (strstr(cpl_error_msg,"not recognised as a supported") != NULL || strstr(cpl_error_msg,"does not exist") != NULL) ) cpl_error_msg = NULL; if( cpl_error_msg == NULL ) cpl_error_msg = ""; return cpl_error_msg; } /************************************************************************/ /* msDrawRasterLoadProjection() */ /* */ /* Handle TILESRS or PROJECTION AUTO for each tile. */ /************************************************************************/ int msDrawRasterLoadProjection(layerObj *layer, GDALDatasetH hDS, const char* filename, int tilesrsindex, const char* tilesrsname) { /* ** Generate the projection information if using TILESRS. */ if( tilesrsindex >= 0 ) { const char *pszWKT; if( tilesrsname[0] != '\0' ) pszWKT = tilesrsname; else pszWKT = GDALGetProjectionRef( hDS ); if( pszWKT != NULL && strlen(pszWKT) > 0 ) { if( msOGCWKT2ProjectionObj(pszWKT, &(layer->projection), layer->debug ) != MS_SUCCESS ) { char szLongMsg[MESSAGELENGTH*2]; errorObj *ms_error = msGetErrorObj(); snprintf( szLongMsg, sizeof(szLongMsg), "%s\n" "PROJECTION '%s' cannot be used for this " "GDAL raster (`%s').", ms_error->message, pszWKT, filename); szLongMsg[MESSAGELENGTH-1] = '\0'; msSetError(MS_OGRERR, "%s","msDrawRasterLayer()", szLongMsg); return MS_FAILURE; } } } /* ** Generate the projection information if using AUTO. */ else if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { const char *pszWKT; pszWKT = GDALGetProjectionRef( hDS ); if( pszWKT != NULL && strlen(pszWKT) > 0 ) { if( msOGCWKT2ProjectionObj(pszWKT, &(layer->projection), layer->debug ) != MS_SUCCESS ) { char szLongMsg[MESSAGELENGTH*2]; errorObj *ms_error = msGetErrorObj(); snprintf( szLongMsg, sizeof(szLongMsg), "%s\n" "PROJECTION AUTO cannot be used for this " "GDAL raster (`%s').", ms_error->message, filename); szLongMsg[MESSAGELENGTH-1] = '\0'; msSetError(MS_OGRERR, "%s","msDrawRasterLayer()", szLongMsg); return MS_FAILURE; } } } return MS_SUCCESS; } #endif // defined(USE_GDAL) #if defined(USE_GDAL) typedef enum { CDRT_OK, CDRT_RETURN_MS_FAILURE, CDRT_CONTINUE_NEXT_TILE } CheckDatasetReturnType; /************************************************************************/ /* msDrawRasterLayerLowCheckDataset() */ /************************************************************************/ static CheckDatasetReturnType msDrawRasterLayerLowCheckDataset(mapObj *map, layerObj *layer, GDALDatasetH hDS, const char* decrypted_path, const char* szPath) { /* ** If GDAL doesn't recognise it, and it wasn't successfully opened ** Generate an error. */ if(hDS == NULL) { int ignore_missing = msMapIgnoreMissingData(map); const char *cpl_error_msg = msDrawRasterGetCPLErrorMsg(decrypted_path, szPath); if(ignore_missing == MS_MISSING_DATA_FAIL) { msSetError(MS_IOERR, "Corrupt, empty or missing file '%s' for layer '%s'. %s", "msDrawRasterLayerLow()", szPath, layer->name, cpl_error_msg ); return(CDRT_RETURN_MS_FAILURE); } else if( ignore_missing == MS_MISSING_DATA_LOG ) { if( layer->debug || layer->map->debug ) { msDebug( "Corrupt, empty or missing file '%s' for layer '%s' ... ignoring this missing data. %s\n", szPath, layer->name, cpl_error_msg ); } return(CDRT_CONTINUE_NEXT_TILE); } else if( ignore_missing == MS_MISSING_DATA_IGNORE ) { return(CDRT_CONTINUE_NEXT_TILE); } else { /* never get here */ msSetError(MS_IOERR, "msIgnoreMissingData returned unexpected value.", "msDrawRasterLayerLow()"); return(CDRT_RETURN_MS_FAILURE); } } return CDRT_OK; } #endif /************************************************************************/ /* msDrawRasterLayerLowOpenDataset() */ /************************************************************************/ void* msDrawRasterLayerLowOpenDataset(mapObj *map, layerObj *layer, const char* filename, char szPath[MS_MAXPATHLEN], char** p_decrypted_path) { #if !defined(USE_GDAL) msSetError(MS_MISCERR, "Attempt to render a RASTER (or WMS) layer but without\n" "GDAL support enabled. Raster rendering requires GDAL.", "msDrawRasterLayerLow()" ); *p_decrypted_path = NULL; return NULL; #else /* defined(USE_GDAL) */ const char* pszPath; msGDALInitialize(); if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): Filename is: %s\n", layer->name, filename); if( strncmp(filename, "debug == MS_TRUE) msDebug("msDrawRasterLayerLow(%s): Path is: %s\n", layer->name, pszPath); /* ** Note: because we do decryption after the above path expansion ** which depends on actually finding a file, it essentially means that ** fancy path manipulation is essentially disabled when using encrypted ** components. But that is mostly ok, since stuff like sde,postgres and ** oracle georaster do not use real paths. */ *p_decrypted_path = msDecryptStringTokens( map, pszPath ); if( *p_decrypted_path == NULL ) return NULL; msAcquireLock( TLOCK_GDAL ); return GDALOpenShared( *p_decrypted_path, GA_ReadOnly ); #endif } /************************************************************************/ /* msDrawRasterLayerLowCloseDataset() */ /************************************************************************/ void msDrawRasterLayerLowCloseDataset(layerObj *layer, void* hDS) { #if !defined(USE_GDAL) (void)hDS; #else if( hDS ) { const char *close_connection; close_connection = msLayerGetProcessingKey( layer, "CLOSE_CONNECTION" ); if( close_connection == NULL && layer->tileindex == NULL ) close_connection = "DEFER"; if( close_connection != NULL && strcasecmp(close_connection,"DEFER") == 0 ) { GDALDereferenceDataset( (GDALDatasetH)hDS ); } else { GDALClose( (GDALDatasetH)hDS ); } msReleaseLock( TLOCK_GDAL ); } #endif } /************************************************************************/ /* msDrawRasterLayerLowCheckIfMustDraw() */ /* */ /* Return 1 if the layer should be drawn. */ /************************************************************************/ int msDrawRasterLayerLowCheckIfMustDraw(mapObj *map, layerObj *layer) { #if !defined(USE_GDAL) return 0; #else if(!layer->data && !layer->tileindex && !(layer->connectiontype==MS_KERNELDENSITY)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): layer data and tileindex NULL ... doing nothing.", layer->name ); return(0); } if((layer->status != MS_ON) && (layer->status != MS_DEFAULT)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): not status ON or DEFAULT, doing nothing.", layer->name ); return(0); } if(map->scaledenom > 0) { if((layer->maxscaledenom > 0) && (map->scaledenom > layer->maxscaledenom)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): skipping, map scale %.2g > MAXSCALEDENOM=%g\n", layer->name, map->scaledenom, layer->maxscaledenom ); return(0); } if((layer->minscaledenom > 0) && (map->scaledenom <= layer->minscaledenom)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): skipping, map scale %.2g < MINSCALEDENOM=%g\n", layer->name, map->scaledenom, layer->minscaledenom ); return(0); } } if(layer->maxscaledenom <= 0 && layer->minscaledenom <= 0) { if((layer->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > layer->maxgeowidth)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): skipping, map width %.2g > MAXSCALEDENOM=%g\n", layer->name, (map->extent.maxx - map->extent.minx), layer->maxgeowidth ); return(0); } if((layer->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < layer->mingeowidth)) { if(layer->debug == MS_TRUE) msDebug( "msDrawRasterLayerLow(%s): skipping, map width %.2g < MINSCALEDENOM=%g\n", layer->name, (map->extent.maxx - map->extent.minx), layer->mingeowidth ); return(0); } } return 1; #endif } /************************************************************************/ /* msDrawRasterLayerLow() */ /* */ /* Check for various file types and act appropriately. Handle */ /* tile indexing. */ /************************************************************************/ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb ) { return msDrawRasterLayerLowWithDataset(map, layer, image, rb, NULL); } int msDrawRasterLayerLowWithDataset(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void* hDatasetIn ) { /* -------------------------------------------------------------------- */ /* As of MapServer 6.0 GDAL is required for rendering raster */ /* imagery. */ /* -------------------------------------------------------------------- */ #if !defined(USE_GDAL) msSetError(MS_MISCERR, "Attempt to render a RASTER (or WMS) layer but without\n" "GDAL support enabled. Raster rendering requires GDAL.", "msDrawRasterLayerLow()" ); return MS_FAILURE; #else /* defined(USE_GDAL) */ int status, done; char *filename=NULL, tilename[MS_MAXPATHLEN], tilesrsname[1024]; layerObj *tlp=NULL; /* pointer to the tile layer either real or temporary */ int tileitemindex=-1, tilelayerindex=-1, tilesrsindex=-1; shapeObj tshp; char szPath[MS_MAXPATHLEN] = { 0 }; char *decrypted_path = NULL; int final_status = MS_SUCCESS; rectObj searchrect; GDALDatasetH hDS; double adfGeoTransform[6]; void *kernel_density_cleanup_ptr = NULL; if(layer->debug > 0 || map->debug > 1) msDebug( "msDrawRasterLayerLow(%s): entering.\n", layer->name ); if( hDatasetIn == NULL && !msDrawRasterLayerLowCheckIfMustDraw(map, layer) ) { return MS_SUCCESS; } msGDALInitialize(); if(layer->tileindex) { /* we have an index file */ msInitShape(&tshp); searchrect = map->extent; status = msDrawRasterSetupTileLayer(map, layer, &searchrect, MS_FALSE, &tilelayerindex, &tileitemindex, &tilesrsindex, &tlp); if(status != MS_SUCCESS) { if (status != MS_DONE) final_status = status; goto cleanup; } } done = MS_FALSE; while(done != MS_TRUE) { if(layer->tileindex) { status = msDrawRasterIterateTileIndex(layer, tlp, &tshp, tileitemindex, tilesrsindex, tilename, sizeof(tilename), tilesrsname, sizeof(tilesrsname)); if( status == MS_FAILURE) { final_status = MS_FAILURE; break; } if(status == MS_DONE) break; /* no more tiles/images */ filename = tilename; } else { filename = layer->data; done = MS_TRUE; /* only one image so we're done after this */ } if(layer->connectiontype == MS_KERNELDENSITY) { msAcquireLock( TLOCK_GDAL ); status = msComputeKernelDensityDataset(map, image, layer, &hDS, &kernel_density_cleanup_ptr); if(status != MS_SUCCESS) { msReleaseLock( TLOCK_GDAL ); final_status = status; goto cleanup; } done = MS_TRUE; if(msProjectionsDiffer(&map->projection,&layer->projection)) { char *mapProjStr = msGetProjectionString(&(map->projection)); /* Set the projection to the map file projection */ if (msLoadProjectionString(&(layer->projection), mapProjStr) != 0) { GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); msSetError(MS_CGIERR, "Unable to set projection on interpolation layer.", "msDrawRasterLayerLow()"); return(MS_FAILURE); } free(mapProjStr); } } else { if(strlen(filename) == 0) continue; if( hDatasetIn ) { hDS = (GDALDatasetH)hDatasetIn; } else { hDS = (GDALDatasetH)msDrawRasterLayerLowOpenDataset( map, layer, filename, szPath, &decrypted_path); } } if( hDatasetIn == NULL ) { CheckDatasetReturnType eRet = msDrawRasterLayerLowCheckDataset(map,layer,hDS,decrypted_path,szPath); msFree( decrypted_path ); decrypted_path = NULL; if( eRet == CDRT_CONTINUE_NEXT_TILE ) { msReleaseLock( TLOCK_GDAL ); continue; } if( eRet == CDRT_RETURN_MS_FAILURE ) { msReleaseLock( TLOCK_GDAL ); return MS_FAILURE; } } if( msDrawRasterLoadProjection(layer, hDS, filename, tilesrsindex, tilesrsname) != MS_SUCCESS ) { if( hDatasetIn == NULL ) { GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); } final_status = MS_FAILURE; break; } msGetGDALGeoTransform( hDS, map, layer, adfGeoTransform ); /* ** We want to resample if the source image is rotated, if ** the projections differ or if resampling has been explicitly ** requested, or if the image has north-down instead of north-up. */ #ifdef USE_PROJ if( ((adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] > 0.0 || adfGeoTransform[1] < 0.0 ) && layer->transform ) || msProjectionsDiffer( &(map->projection), &(layer->projection) ) || CSLFetchNameValue( layer->processing, "RESAMPLE" ) != NULL ) { status = msResampleGDALToMap( map, layer, image, rb, hDS ); } else #endif { if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 ) { if( layer->debug || map->debug ) msDebug( "Layer %s has rotational coefficients but we\n" "are unable to use them, projections support\n" "needs to be built in.", layer->name ); } status = msDrawRasterLayerGDAL(map, layer, image, rb, hDS ); } if( status == -1 ) { if( hDatasetIn == NULL ) { GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); } final_status = MS_FAILURE; break; } /* ** Should we keep this file open for future use? ** default to keeping open for single data files, and ** to closing for tile indexes */ if(layer->connectiontype == MS_KERNELDENSITY) { /* ** Fix issue #5330 ** The in-memory kernel density heatmap gdal dataset handle (hDS) gets re-used ** but the associated rasterband cache doesn't get flushed, which causes old data ** to be rendered instead of the newly generated imagery. To fix, simply close the ** the handle and prevent further re-use. ** Note that instead of this workaround, we could explicitely set ** CLOSE_CONNECTION=ALWAYS on the kerneldensity layer. */ GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); } else { if( hDatasetIn == NULL) msDrawRasterLayerLowCloseDataset(layer, hDS); } } /* next tile */ cleanup: if(layer->tileindex) { /* tiling clean-up */ msDrawRasterCleanupTileLayer(tlp, tilelayerindex); } if(layer->connectiontype == MS_KERNELDENSITY && kernel_density_cleanup_ptr) { msCleanupKernelDensityDataset(map, image, layer, kernel_density_cleanup_ptr); } return final_status; #endif /* defined(USE_GDAL) */ } /************************************************************************/ /* msDrawReferenceMap() */ /************************************************************************/ imageObj *msDrawReferenceMap(mapObj *map) { double cellsize; int x1,y1,x2,y2; char szPath[MS_MAXPATHLEN]; int status = MS_SUCCESS; imageObj *image = NULL; styleObj style; rendererVTableObj *renderer = MS_MAP_RENDERER(map); rasterBufferObj *refImage = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); MS_CHECK_ALLOC(refImage, sizeof(rasterBufferObj), NULL); if(MS_SUCCESS != renderer->loadImageFromFile(msBuildPath(szPath, map->mappath, map->reference.image),refImage)) { msSetError(MS_MISCERR,"error loading reference image %s","msDrawREferenceMap()",szPath); return NULL; } image = msImageCreate(refImage->width, refImage->height, map->outputformat, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &(map->reference.color)); if(!image) return NULL; status = renderer->mergeRasterBuffer(image,refImage,1.0,0,0,0,0,refImage->width, refImage->height); msFreeRasterBuffer(refImage); free(refImage); if(UNLIKELY(status == MS_FAILURE)) return NULL; /* make sure the extent given in mapfile fits the image */ cellsize = msAdjustExtent(&(map->reference.extent), image->width, image->height); /* convert map extent to reference image coordinates */ x1 = MS_MAP2IMAGE_X(map->extent.minx, map->reference.extent.minx, cellsize); x2 = MS_MAP2IMAGE_X(map->extent.maxx, map->reference.extent.minx, cellsize); y1 = MS_MAP2IMAGE_Y(map->extent.maxy, map->reference.extent.maxy, cellsize); y2 = MS_MAP2IMAGE_Y(map->extent.miny, map->reference.extent.maxy, cellsize); initStyle(&style); style.color = map->reference.color; style.outlinecolor = map->reference.outlinecolor; /* if extent are smaller than minbox size */ /* draw that extent on the reference image */ if( (abs(x2 - x1) > map->reference.minboxsize) || (abs(y2 - y1) > map->reference.minboxsize) ) { shapeObj rect; lineObj line; pointObj points[5]; msInitShape(&rect); line.point = points; line.numpoints = 5; rect.line = &line; rect.numlines = 1; rect.type = MS_SHAPE_POLYGON; line.point[0].x = x1; line.point[0].y = y1; line.point[1].x = x1; line.point[1].y = y2; line.point[2].x = x2; line.point[2].y = y2; line.point[3].x = x2; line.point[3].y = y1; line.point[4].x = line.point[0].x; line.point[4].y = line.point[0].y; line.numpoints = 5; if( map->reference.maxboxsize == 0 || ((abs(x2 - x1) < map->reference.maxboxsize) && (abs(y2 - y1) < map->reference.maxboxsize)) ) { if(UNLIKELY(MS_FAILURE == msDrawShadeSymbol(map, image, &rect, &style, 1.0))) { msFreeImage(image); return NULL; } } } else { /* else draw the marker symbol */ if( map->reference.maxboxsize == 0 || ((abs(x2 - x1) < map->reference.maxboxsize) && (abs(y2 - y1) < map->reference.maxboxsize)) ) { style.size = map->reference.markersize; /* if the marker symbol is specify draw this symbol else draw a cross */ if(map->reference.marker || map->reference.markername) { pointObj point; point.x = (double)(x1 + x2)/2; point.y = (double)(y1 + y2)/2; if(map->reference.marker) { style.symbol = map->reference.marker; } else { style.symbol = msGetSymbolIndex(&map->symbolset, map->reference.markername, MS_TRUE); } if(UNLIKELY(MS_FAILURE == msDrawMarkerSymbol(map, image, &point, &style, 1.0))) { msFreeImage(image); return NULL; } } else { int x21, y21; shapeObj cross; lineObj lines[4]; pointObj point[8]; int i; /* determine the center point */ x21 = MS_NINT((x1 + x2)/2); y21 = MS_NINT((y1 + y2)/2); msInitShape(&cross); cross.numlines = 4; cross.line = lines; for(i=0; i<4; i++) { cross.line[i].numpoints = 2; cross.line[i].point = &(point[2*i]); } /* draw a cross */ cross.line[0].point[0].x = x21-8; cross.line[0].point[0].y = y21; cross.line[0].point[1].x = x21-3; cross.line[0].point[1].y = y21; cross.line[1].point[0].x = x21; cross.line[1].point[0].y = y21-8; cross.line[1].point[1].x = x21; cross.line[1].point[1].y = y21-3; cross.line[2].point[0].x = x21; cross.line[2].point[0].y = y21+3; cross.line[2].point[1].x = x21; cross.line[2].point[1].y = y21+8; cross.line[3].point[0].x = x21+3; cross.line[3].point[0].y = y21; cross.line[3].point[1].x = x21+8; cross.line[3].point[1].y = y21; if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map,image,&cross,&style,1.0))) { msFreeImage(image); return NULL; } } } } return(image); } mapserver-7.4.3/mapraster.h000066400000000000000000000062111357574274700157250ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Private include file used by mapraster.c and maprasterquery.c * Author: Even Rouault * ****************************************************************************** * Copyright (c) 2013 Regents of the University of Minnesota. * * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #ifndef MAPRASTER_H #define MAPRASTER_H #if defined(USE_GDAL) int msDrawRasterSetupTileLayer(mapObj *map, layerObj *layer, rectObj* psearchrect, int is_query, int* ptilelayerindex, /* output */ int* ptileitemindex, /* output */ int* ptilesrsindex, /* output */ layerObj **ptlp /* output */ ); void msDrawRasterCleanupTileLayer(layerObj* tlp, int tilelayerindex); int msDrawRasterIterateTileIndex(layerObj *layer, layerObj* tlp, shapeObj* ptshp, /* input-output */ int tileitemindex, int tilesrsindex, char* tilename, /* output */ size_t sizeof_tilename, char* tilesrsname, /* output */ size_t sizeof_tilesrsname); int msDrawRasterBuildRasterPath(mapObj *map, layerObj *layer, const char* filename, char szPath[MS_MAXPATHLEN]); const char* msDrawRasterGetCPLErrorMsg(const char* decrypted_path, const char* szPath); int msDrawRasterLoadProjection(layerObj *layer, GDALDatasetH hDS, const char* filename, int tilesrsindex, const char* tilesrsname); #endif #endif /* MAPRASTER_H */ mapserver-7.4.3/maprasterquery.c000066400000000000000000001603741357574274700170210ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of query operations on rasters. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include "mapserver.h" #include "mapresample.h" #include "mapthread.h" #include "mapraster.h" int msRASTERLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record); int msRASTERLayerGetItems(layerObj *layer); #ifdef USE_GDAL /* ==================================================================== */ /* For now the rasterLayerInfo lives here since it is just used */ /* to hold information related to queries. */ /* ==================================================================== */ typedef struct { /* query cache results */ int query_results; int query_alloc_max; int query_request_max; int query_result_hard_max; int raster_query_mode; int band_count; int refcount; rectObj which_rect; int next_shape; double *qc_x; double *qc_y; double *qc_x_reproj; double *qc_y_reproj; float *qc_values; int *qc_class; int *qc_red; int *qc_green; int *qc_blue; int *qc_count; int *qc_tileindex; /* query bound in force */ shapeObj *searchshape; /* Only nearest result to this point. */ int range_mode; /* MS_QUERY_SINGLE, MS_QUERY_MULTIPLE or -1 (skip test) */ double range_dist; pointObj target_point; GDALColorTableH hCT; double shape_tolerance; } rasterLayerInfo; #define RQM_UNKNOWN 0 #define RQM_ENTRY_PER_PIXEL 1 #define RQM_HIST_ON_CLASS 2 #define RQM_HIST_ON_VALUE 3 extern int InvGeoTransform( double *gt_in, double *gt_out ); #define GEO_TRANS(tr,x,y) ((tr)[0]+(tr)[1]*(x)+(tr)[2]*(y)) /************************************************************************/ /* addResult() */ /* */ /* this is a copy of the code in mapquery.c. Should we prepare */ /* a small public API for managing results caches? */ /************************************************************************/ static int addResult(resultCacheObj *cache, int classindex, int shapeindex, int tileindex) { int i; if(cache->numresults == cache->cachesize) { /* just add it to the end */ if(cache->cachesize == 0) cache->results = (resultObj *) malloc(sizeof(resultObj)*MS_RESULTCACHEINCREMENT); else cache->results = (resultObj *) realloc(cache->results, sizeof(resultObj)*(cache->cachesize+MS_RESULTCACHEINCREMENT)); if(!cache->results) { msSetError(MS_MEMERR, "Realloc() error.", "addResult()"); return(MS_FAILURE); } cache->cachesize += MS_RESULTCACHEINCREMENT; } i = cache->numresults; cache->results[i].classindex = classindex; cache->results[i].tileindex = tileindex; cache->results[i].shapeindex = shapeindex; cache->results[i].resultindex = -1; /* unused */ cache->results[i].shape = NULL; cache->numresults++; return(MS_SUCCESS); } /************************************************************************/ /* msRasterLayerInfoFree() */ /************************************************************************/ static void msRasterLayerInfoFree( layerObj *layer ) { rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo == NULL ) return; if( rlinfo->qc_x != NULL ) { free( rlinfo->qc_x ); free( rlinfo->qc_y ); free( rlinfo->qc_x_reproj ); free( rlinfo->qc_y_reproj ); } if( rlinfo->qc_values ) free( rlinfo->qc_values ); if( rlinfo->qc_class ) { free( rlinfo->qc_class ); } if( rlinfo->qc_red ) { free( rlinfo->qc_red ); free( rlinfo->qc_green ); free( rlinfo->qc_blue ); } if( rlinfo->qc_count != NULL ) free( rlinfo->qc_count ); if( rlinfo->qc_tileindex != NULL ) free( rlinfo->qc_tileindex ); free( rlinfo ); layer->layerinfo = NULL; } /************************************************************************/ /* msRasterLayerInfoInitialize() */ /************************************************************************/ static void msRasterLayerInfoInitialize( layerObj *layer ) { rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo != NULL ) return; rlinfo = (rasterLayerInfo *) msSmallCalloc(1,sizeof(rasterLayerInfo)); layer->layerinfo = rlinfo; rlinfo->band_count = -1; rlinfo->raster_query_mode = RQM_ENTRY_PER_PIXEL; rlinfo->range_mode = -1; /* inactive */ rlinfo->refcount = 0; rlinfo->shape_tolerance = 0.0; /* We need to do this or the layer->layerinfo will be interpreted */ /* as shapefile access info because the default connectiontype is */ /* MS_SHAPEFILE. */ if (layer->connectiontype != MS_WMS && layer->connectiontype != MS_KERNELDENSITY) layer->connectiontype = MS_RASTER; rlinfo->query_result_hard_max = 1000000; if( CSLFetchNameValue( layer->processing, "RASTER_QUERY_MAX_RESULT" ) != NULL ) { rlinfo->query_result_hard_max = atoi(CSLFetchNameValue( layer->processing, "RASTER_QUERY_MAX_RESULT" )); } } /************************************************************************/ /* msRasterQueryAddPixel() */ /************************************************************************/ static void msRasterQueryAddPixel( layerObj *layer, pointObj *location, pointObj *reprojectedLocation, float *values ) { rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; int red = 0, green = 0, blue = 0, nodata = FALSE; int p_class = -1; if( rlinfo->query_results == rlinfo->query_result_hard_max ) return; /* -------------------------------------------------------------------- */ /* Is this our first time in? If so, do an initial allocation */ /* for the data arrays suitable to our purposes. */ /* -------------------------------------------------------------------- */ if( rlinfo->query_alloc_max == 0 ) { rlinfo->query_alloc_max = 2; switch( rlinfo->raster_query_mode ) { case RQM_ENTRY_PER_PIXEL: rlinfo->qc_x = (double *) msSmallCalloc(sizeof(double),rlinfo->query_alloc_max); rlinfo->qc_y = (double *) msSmallCalloc(sizeof(double),rlinfo->query_alloc_max); rlinfo->qc_x_reproj = (double *) msSmallCalloc(sizeof(double),rlinfo->query_alloc_max); rlinfo->qc_y_reproj = (double *) msSmallCalloc(sizeof(double),rlinfo->query_alloc_max); rlinfo->qc_values = (float *) msSmallCalloc(sizeof(float), rlinfo->query_alloc_max*rlinfo->band_count); rlinfo->qc_red = (int *) msSmallCalloc(sizeof(int),rlinfo->query_alloc_max); rlinfo->qc_green = (int *) msSmallCalloc(sizeof(int),rlinfo->query_alloc_max); rlinfo->qc_blue = (int *) msSmallCalloc(sizeof(int),rlinfo->query_alloc_max); if( layer->numclasses > 0 ) rlinfo->qc_class = (int *) msSmallCalloc(sizeof(int),rlinfo->query_alloc_max); break; case RQM_HIST_ON_CLASS: break; case RQM_HIST_ON_VALUE: break; default: assert( FALSE ); } } /* -------------------------------------------------------------------- */ /* Reallocate the data arrays larger if they are near the max */ /* now. */ /* -------------------------------------------------------------------- */ if( rlinfo->query_results == rlinfo->query_alloc_max ) { rlinfo->query_alloc_max = rlinfo->query_alloc_max * 2 + 100; if( rlinfo->qc_x != NULL ) rlinfo->qc_x = msSmallRealloc(rlinfo->qc_x, sizeof(double) * rlinfo->query_alloc_max); if( rlinfo->qc_y != NULL ) rlinfo->qc_y = msSmallRealloc(rlinfo->qc_y, sizeof(double) * rlinfo->query_alloc_max); if( rlinfo->qc_x_reproj != NULL ) rlinfo->qc_x_reproj = msSmallRealloc(rlinfo->qc_x_reproj, sizeof(double) * rlinfo->query_alloc_max); if( rlinfo->qc_y_reproj != NULL ) rlinfo->qc_y_reproj = msSmallRealloc(rlinfo->qc_y_reproj, sizeof(double) * rlinfo->query_alloc_max); if( rlinfo->qc_values != NULL ) rlinfo->qc_values = msSmallRealloc(rlinfo->qc_values, sizeof(float) * rlinfo->query_alloc_max * rlinfo->band_count ); if( rlinfo->qc_class != NULL ) rlinfo->qc_class = msSmallRealloc(rlinfo->qc_class, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_red != NULL ) rlinfo->qc_red = msSmallRealloc(rlinfo->qc_red, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_green != NULL ) rlinfo->qc_green = msSmallRealloc(rlinfo->qc_green, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_blue != NULL ) rlinfo->qc_blue = msSmallRealloc(rlinfo->qc_blue, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_count != NULL ) rlinfo->qc_count = msSmallRealloc(rlinfo->qc_count, sizeof(int) * rlinfo->query_alloc_max); if( rlinfo->qc_tileindex != NULL ) rlinfo->qc_tileindex = msSmallRealloc(rlinfo->qc_tileindex, sizeof(int) * rlinfo->query_alloc_max); } /* -------------------------------------------------------------------- */ /* Handle colormap */ /* -------------------------------------------------------------------- */ if( rlinfo->hCT != NULL ) { int pct_index = (int) floor(values[0]); GDALColorEntry sEntry; if( GDALGetColorEntryAsRGB( rlinfo->hCT, pct_index, &sEntry ) ) { red = sEntry.c1; green = sEntry.c2; blue = sEntry.c3; if( sEntry.c4 == 0 ) nodata = TRUE; } else nodata = TRUE; } /* -------------------------------------------------------------------- */ /* Color derived from greyscale value. */ /* -------------------------------------------------------------------- */ else { if( rlinfo->band_count >= 3 ) { red = (int) MS_MAX(0,MS_MIN(255,values[0])); green = (int) MS_MAX(0,MS_MIN(255,values[1])); blue = (int) MS_MAX(0,MS_MIN(255,values[2])); } else { red = green = blue = (int) MS_MAX(0,MS_MIN(255,values[0])); } } /* -------------------------------------------------------------------- */ /* Handle classification. */ /* */ /* NOTE: The following is really quite inadequate to deal with */ /* classifications based on [red], [green] and [blue] as */ /* described in: */ /* http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1021 */ /* -------------------------------------------------------------------- */ if( rlinfo->qc_class != NULL ) { p_class = msGetClass_FloatRGB(layer, values[0], red, green, blue ); if( p_class == -1 ) nodata = TRUE; else { nodata = FALSE; rlinfo->qc_class[rlinfo->query_results] = p_class; if( layer->class[p_class]->numstyles > 0 ) { red = layer->class[p_class]->styles[0]->color.red; green = layer->class[p_class]->styles[0]->color.green; blue = layer->class[p_class]->styles[0]->color.blue; } else { red = green = blue = 0; } } } /* -------------------------------------------------------------------- */ /* Record the color. */ /* -------------------------------------------------------------------- */ rlinfo->qc_red[rlinfo->query_results] = red; rlinfo->qc_green[rlinfo->query_results] = green; rlinfo->qc_blue[rlinfo->query_results] = blue; /* -------------------------------------------------------------------- */ /* Record spatial location. */ /* -------------------------------------------------------------------- */ if( rlinfo->qc_x != NULL ) { rlinfo->qc_x[rlinfo->query_results] = location->x; rlinfo->qc_y[rlinfo->query_results] = location->y; rlinfo->qc_x_reproj[rlinfo->query_results] = reprojectedLocation->x; rlinfo->qc_y_reproj[rlinfo->query_results] = reprojectedLocation->y; } /* -------------------------------------------------------------------- */ /* Record actual pixel value(s). */ /* -------------------------------------------------------------------- */ if( rlinfo->qc_values != NULL ) memcpy( rlinfo->qc_values + rlinfo->query_results * rlinfo->band_count, values, sizeof(float) * rlinfo->band_count ); /* -------------------------------------------------------------------- */ /* Add to the results cache. */ /* -------------------------------------------------------------------- */ if( ! nodata ) { addResult( layer->resultcache, p_class, rlinfo->query_results, 0 ); rlinfo->query_results++; } } /************************************************************************/ /* msRasterQueryByRectLow() */ /************************************************************************/ static int msRasterQueryByRectLow(mapObj *map, layerObj *layer, GDALDatasetH hDS, rectObj queryRect) { double adfGeoTransform[6], adfInvGeoTransform[6]; double dfXMin, dfYMin, dfXMax, dfYMax, dfX, dfY, dfAdjustedRange; int nWinXOff, nWinYOff, nWinXSize, nWinYSize; int nRXSize, nRYSize; float *pafRaster; int nBandCount, *panBandMap, iPixel, iLine; CPLErr eErr; rasterLayerInfo *rlinfo; rectObj searchrect; rlinfo = (rasterLayerInfo *) layer->layerinfo; /* -------------------------------------------------------------------- */ /* Reproject the search rect into the projection of this */ /* layer/file if needed. */ /* -------------------------------------------------------------------- */ searchrect = queryRect; #ifdef USE_PROJ layer->project = msProjectionsDiffer(&(layer->projection), &(map->projection)); if(layer->project) msProjectRect(&(map->projection), &(layer->projection), &searchrect); #endif /* -------------------------------------------------------------------- */ /* Transform the rectangle in target ground coordinates to */ /* pixel/line extents on the file. Process all 4 corners, to */ /* build extents. */ /* -------------------------------------------------------------------- */ nRXSize = GDALGetRasterXSize( hDS ); nRYSize = GDALGetRasterYSize( hDS ); msGetGDALGeoTransform( hDS, map, layer, adfGeoTransform ); InvGeoTransform( adfGeoTransform, adfInvGeoTransform ); /* top left */ dfXMin = dfXMax = GEO_TRANS(adfInvGeoTransform, searchrect.minx, searchrect.maxy); dfYMin = dfYMax = GEO_TRANS(adfInvGeoTransform+3, searchrect.minx, searchrect.maxy); /* top right */ dfX = GEO_TRANS(adfInvGeoTransform , searchrect.maxx, searchrect.maxy); dfY = GEO_TRANS(adfInvGeoTransform+3, searchrect.maxx, searchrect.maxy); dfXMin = MS_MIN(dfXMin,dfX); dfXMax = MS_MAX(dfXMax,dfX); dfYMin = MS_MIN(dfYMin,dfY); dfYMax = MS_MAX(dfYMax,dfY); /* bottom left */ dfX = GEO_TRANS(adfInvGeoTransform , searchrect.minx, searchrect.miny); dfY = GEO_TRANS(adfInvGeoTransform+3, searchrect.minx, searchrect.miny); dfXMin = MS_MIN(dfXMin,dfX); dfXMax = MS_MAX(dfXMax,dfX); dfYMin = MS_MIN(dfYMin,dfY); dfYMax = MS_MAX(dfYMax,dfY); /* bottom right */ dfX = GEO_TRANS(adfInvGeoTransform , searchrect.maxx, searchrect.miny); dfY = GEO_TRANS(adfInvGeoTransform+3, searchrect.maxx, searchrect.miny); dfXMin = MS_MIN(dfXMin,dfX); dfXMax = MS_MAX(dfXMax,dfX); dfYMin = MS_MIN(dfYMin,dfY); dfYMax = MS_MAX(dfYMax,dfY); /* -------------------------------------------------------------------- */ /* Trim the rectangle to the area of the file itself, but out */ /* to the edges of the touched edge pixels. */ /* -------------------------------------------------------------------- */ dfXMin = MS_MAX(0.0,MS_MIN(nRXSize,floor(dfXMin))); dfYMin = MS_MAX(0.0,MS_MIN(nRYSize,floor(dfYMin))); dfXMax = MS_MAX(0.0,MS_MIN(nRXSize,ceil(dfXMax))); dfYMax = MS_MAX(0.0,MS_MIN(nRYSize,ceil(dfYMax))); /* -------------------------------------------------------------------- */ /* Convert to integer offset/size values. */ /* -------------------------------------------------------------------- */ nWinXOff = (int) dfXMin; nWinYOff = (int) dfYMin; nWinXSize = (int) (dfXMax - dfXMin); nWinYSize = (int) (dfYMax - dfYMin); /* -------------------------------------------------------------------- */ /* What bands are we operating on? */ /* -------------------------------------------------------------------- */ panBandMap = msGetGDALBandList( layer, hDS, 0, &nBandCount ); if( rlinfo->band_count == -1 ) rlinfo->band_count = nBandCount; if( nBandCount != rlinfo->band_count ) { msSetError( MS_IMGERR, "Got %d bands, but expected %d bands.", "msRasterQueryByRectLow()", nBandCount, rlinfo->band_count ); return -1; } /* -------------------------------------------------------------------- */ /* Try to load the raster data. For now we just load the first */ /* band in the file. Later we will deal with the various band */ /* selection criteria. */ /* -------------------------------------------------------------------- */ pafRaster = (float *) calloc(sizeof(float),nWinXSize*nWinYSize*nBandCount); MS_CHECK_ALLOC(pafRaster, sizeof(float)*nWinXSize*nWinYSize*nBandCount, -1); eErr = GDALDatasetRasterIO( hDS, GF_Read, nWinXOff, nWinYOff, nWinXSize, nWinYSize, pafRaster, nWinXSize, nWinYSize, GDT_Float32, nBandCount, panBandMap, 4 * nBandCount, 4 * nBandCount * nWinXSize, 4 ); if( eErr != CE_None ) { msSetError( MS_IOERR, "GDALDatasetRasterIO() failed: %s", "msRasterQueryByRectLow()", CPLGetLastErrorMsg() ); free( pafRaster ); return -1; } /* -------------------------------------------------------------------- */ /* Fetch color table for intepreting colors if needed. */ /* -------------------------------------------------------------------- */ rlinfo->hCT = GDALGetRasterColorTable( GDALGetRasterBand( hDS, panBandMap[0] ) ); free( panBandMap ); /* -------------------------------------------------------------------- */ /* When computing whether pixels are within range we do it */ /* based on the center of the pixel to the target point but */ /* really it ought to be the nearest point on the pixel. It */ /* would be too much trouble to do this rigerously, so we just */ /* add a fudge factor so that a range of zero will find the */ /* pixel the target falls in at least. */ /* -------------------------------------------------------------------- */ dfAdjustedRange = sqrt(adfGeoTransform[1] * adfGeoTransform[1] + adfGeoTransform[2] * adfGeoTransform[2] + adfGeoTransform[4] * adfGeoTransform[4] + adfGeoTransform[5] * adfGeoTransform[5]) * 0.5 * 1.41421356237 + sqrt( rlinfo->range_dist ); dfAdjustedRange = dfAdjustedRange * dfAdjustedRange; /* -------------------------------------------------------------------- */ /* Loop over all pixels determining which are "in". */ /* -------------------------------------------------------------------- */ for( iLine = 0; iLine < nWinYSize; iLine++ ) { for( iPixel = 0; iPixel < nWinXSize; iPixel++ ) { pointObj sPixelLocation,sReprojectedPixelLocation; if( rlinfo->query_results == rlinfo->query_result_hard_max ) break; /* transform pixel/line to georeferenced */ sPixelLocation.x = GEO_TRANS(adfGeoTransform, iPixel + nWinXOff + 0.5, iLine + nWinYOff + 0.5 ); sPixelLocation.y = GEO_TRANS(adfGeoTransform+3, iPixel + nWinXOff + 0.5, iLine + nWinYOff + 0.5 ); /* If projections differ, convert this back into the map */ /* projection for distance testing, and comprison to the */ /* search shape. Save the original pixel location coordinates */ /* in sPixelLocationInLayerSRS, so that we can return those */ /* coordinates if we have a hit */ sReprojectedPixelLocation = sPixelLocation; if( layer->project ) msProjectPoint( &(layer->projection), &(map->projection), &sReprojectedPixelLocation); /* If we are doing QueryByShape, check against the shape now */ if( rlinfo->searchshape != NULL ) { if( rlinfo->shape_tolerance == 0.0 && rlinfo->searchshape->type == MS_SHAPE_POLYGON ) { if( msIntersectPointPolygon( &sReprojectedPixelLocation, rlinfo->searchshape ) == MS_FALSE ) continue; } else { shapeObj tempShape; lineObj tempLine; memset( &tempShape, 0, sizeof(shapeObj) ); tempShape.type = MS_SHAPE_POINT; tempShape.numlines = 1; tempShape.line = &tempLine; tempLine.numpoints = 1; tempLine.point = &sReprojectedPixelLocation; if( msDistanceShapeToShape(rlinfo->searchshape, &tempShape) > rlinfo->shape_tolerance ) continue; } } if( rlinfo->range_mode >= 0 ) { double dist; dist = (rlinfo->target_point.x - sReprojectedPixelLocation.x) * (rlinfo->target_point.x - sReprojectedPixelLocation.x) + (rlinfo->target_point.y - sReprojectedPixelLocation.y) * (rlinfo->target_point.y - sReprojectedPixelLocation.y); if( dist >= dfAdjustedRange ) continue; /* If we can only have one feature, trim range and clear */ /* previous result. */ if( rlinfo->range_mode == MS_QUERY_SINGLE ) { rlinfo->range_dist = dist; rlinfo->query_results = 0; } } msRasterQueryAddPixel( layer, &sPixelLocation, // return coords in layer SRS &sReprojectedPixelLocation, pafRaster + (iLine*nWinXSize + iPixel) * nBandCount ); } } /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ free( pafRaster ); return MS_SUCCESS; } #endif /* def USE_GDAL */ /************************************************************************/ /* msRasterQueryByRect() */ /************************************************************************/ int msRasterQueryByRect(mapObj *map, layerObj *layer, rectObj queryRect) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRasterQueryByRect()" ); return MS_FAILURE; #else int status = MS_SUCCESS; char *filename=NULL; layerObj *tlp=NULL; /* pointer to the tile layer either real or temporary */ int tileitemindex=-1, tilelayerindex=-1, tilesrsindex=-1; shapeObj tshp; char tilename[MS_PATH_LENGTH], tilesrsname[1024]; int done, destroy_on_failure; char szPath[MS_MAXPATHLEN]; rectObj searchrect; rasterLayerInfo *rlinfo = NULL; /* -------------------------------------------------------------------- */ /* Get the layer info. */ /* -------------------------------------------------------------------- */ if(!layer->layerinfo) { msRasterLayerInfoInitialize( layer ); destroy_on_failure = 1; } else { destroy_on_failure = 0; } rlinfo = (rasterLayerInfo *) layer->layerinfo; /* -------------------------------------------------------------------- */ /* Clear old results cache. */ /* -------------------------------------------------------------------- */ if(layer->resultcache) { if(layer->resultcache->results) free(layer->resultcache->results); free(layer->resultcache); layer->resultcache = NULL; } /* -------------------------------------------------------------------- */ /* Initialize the results cache. */ /* -------------------------------------------------------------------- */ layer->resultcache = (resultCacheObj *)msSmallMalloc(sizeof(resultCacheObj)); layer->resultcache->results = NULL; layer->resultcache->numresults = layer->resultcache->cachesize = 0; layer->resultcache->bounds.minx = layer->resultcache->bounds.miny = layer->resultcache->bounds.maxx = layer->resultcache->bounds.maxy = -1; /* -------------------------------------------------------------------- */ /* Check if we should really be acting on this layer and */ /* provide debug info in various cases. */ /* -------------------------------------------------------------------- */ if(layer->debug > 0 || map->debug > 1) msDebug( "msRasterQueryByRect(%s): entering.\n", layer->name ); if(!layer->data && !layer->tileindex) { if(layer->debug > 0 || map->debug > 0 ) msDebug( "msRasterQueryByRect(%s): layer data and tileindex NULL ... doing nothing.", layer->name ); return MS_SUCCESS; } if((layer->status != MS_ON) && layer->status != MS_DEFAULT ) { if(layer->debug > 0 ) msDebug( "msRasterQueryByRect(%s): not status ON or DEFAULT, doing nothing.", layer->name ); return MS_SUCCESS; } /* ==================================================================== */ /* Handle setting up tileindex layer. */ /* ==================================================================== */ if(layer->tileindex) { /* we have an index file */ msInitShape(&tshp); searchrect = queryRect; status = msDrawRasterSetupTileLayer(map, layer, &searchrect, MS_TRUE, &tilelayerindex, &tileitemindex, &tilesrsindex, &tlp); if (status != MS_SUCCESS) { goto cleanup; } } else { /* we have to manually apply to scaletoken logic as we're not going through msLayerOpen() */ status = msLayerApplyScaletokens(layer,map->scaledenom); if (status != MS_SUCCESS) { goto cleanup; } } /* -------------------------------------------------------------------- */ /* Iterate over all tiles (just one in untiled case). */ /* -------------------------------------------------------------------- */ done = MS_FALSE; while( done == MS_FALSE && status == MS_SUCCESS ) { GDALDatasetH hDS; char *decrypted_path = NULL; /* -------------------------------------------------------------------- */ /* Get filename. */ /* -------------------------------------------------------------------- */ if(layer->tileindex) { status = msDrawRasterIterateTileIndex(layer, tlp, &tshp, tileitemindex, tilesrsindex, tilename, sizeof(tilename), tilesrsname, sizeof(tilesrsname)); if( status == MS_FAILURE) { break; } if(status == MS_DONE) break; /* no more tiles/images */ filename = tilename; } else { filename = layer->data; done = MS_TRUE; /* only one image so we're done after this */ } if(strlen(filename) == 0) continue; /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ msGDALInitialize(); msDrawRasterBuildRasterPath(map, layer, filename, szPath); decrypted_path = msDecryptStringTokens( map, szPath ); if( !decrypted_path ) { status = MS_FAILURE; goto cleanup; } msAcquireLock( TLOCK_GDAL ); hDS = GDALOpen(decrypted_path, GA_ReadOnly ); if( hDS == NULL ) { int ignore_missing = msMapIgnoreMissingData( map ); const char *cpl_error_msg = msDrawRasterGetCPLErrorMsg(decrypted_path, szPath); msFree( decrypted_path ); decrypted_path = NULL; msReleaseLock( TLOCK_GDAL ); if ( ignore_missing == MS_MISSING_DATA_FAIL ) { if( layer->debug || map->debug ) msSetError( MS_IMGERR, "Unable to open file %s for layer %s ... fatal error.\n%s", "msRasterQueryByRect()", szPath, layer->name, cpl_error_msg); status = MS_FAILURE; goto cleanup; } if( ignore_missing == MS_MISSING_DATA_LOG ) { if( layer->debug || map->debug ) msDebug( "Unable to open file %s for layer %s ... ignoring this missing data.\n%s", filename, layer->name, cpl_error_msg ); } continue; } msFree( decrypted_path ); decrypted_path = NULL; if( msDrawRasterLoadProjection(layer, hDS, filename, tilesrsindex, tilesrsname) != MS_SUCCESS ) { msReleaseLock( TLOCK_GDAL ); status = MS_FAILURE; goto cleanup; } /* -------------------------------------------------------------------- */ /* Perform actual query on this file. */ /* -------------------------------------------------------------------- */ if( status == MS_SUCCESS ) status = msRasterQueryByRectLow( map, layer, hDS, queryRect ); GDALClose( hDS ); msReleaseLock( TLOCK_GDAL ); } /* next tile */ /* -------------------------------------------------------------------- */ /* Cleanup tileindex if it is open. */ /* -------------------------------------------------------------------- */ cleanup: if(layer->tileindex) { /* tiling clean-up */ msDrawRasterCleanupTileLayer(tlp, tilelayerindex); } else { msLayerRestoreFromScaletokens(layer); } /* -------------------------------------------------------------------- */ /* On failure, or empty result set, cleanup the rlinfo since we */ /* likely won't ever have it accessed or cleaned up later. */ /* -------------------------------------------------------------------- */ if( status == MS_FAILURE || rlinfo->query_results == 0 ) { if(destroy_on_failure) { msRasterLayerInfoFree( layer ); } } else { /* populate the items/numitems layer-level values */ msRASTERLayerGetItems(layer); } return status; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRasterQueryByShape() */ /************************************************************************/ int msRasterQueryByShape(mapObj *map, layerObj *layer, shapeObj *selectshape) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRasterQueryByRect()" ); return MS_FAILURE; #else rasterLayerInfo *rlinfo = NULL; int status; double tolerance; rectObj searchrect; msRasterLayerInfoInitialize( layer ); rlinfo = (rasterLayerInfo *) layer->layerinfo; /* If the selection shape is point or line we use the default tolerance of 3, but for polygons we require an exact hit. */ if(layer->tolerance == -1) { if(selectshape->type == MS_SHAPE_POINT || selectshape->type == MS_SHAPE_LINE) tolerance = 3; else tolerance = 0; } else tolerance = layer->tolerance; if(layer->toleranceunits == MS_PIXELS) tolerance = tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else tolerance = tolerance * (msInchesPerUnit(layer->toleranceunits,0) / msInchesPerUnit(map->units,0)); rlinfo->searchshape = selectshape; rlinfo->shape_tolerance = tolerance; msComputeBounds( selectshape ); searchrect = selectshape->bounds; searchrect.minx -= tolerance; /* expand the search box to account for layer tolerances (e.g. buffered searches) */ searchrect.maxx += tolerance; searchrect.miny -= tolerance; searchrect.maxy += tolerance; status = msRasterQueryByRect( map, layer, searchrect ); rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo ) rlinfo->searchshape = NULL; return status; #endif /* USE_GDAL */ } /************************************************************************/ /* msRasterQueryByPoint() */ /************************************************************************/ int msRasterQueryByPoint(mapObj *map, layerObj *layer, int mode, pointObj p, double buffer, int maxresults) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRasterQueryByRect()" ); return MS_FAILURE; #else int result; int previous_maxresults; double layer_tolerance; rectObj bufferRect; rasterLayerInfo *rlinfo = NULL; msRasterLayerInfoInitialize( layer ); rlinfo = (rasterLayerInfo *) layer->layerinfo; /* -------------------------------------------------------------------- */ /* If the buffer is not set, then use layer tolerances */ /* instead. The "buffer" distince is now in georeferenced */ /* units. Note that tolerances in pixels are basically map */ /* display pixels, not underlying raster pixels. It isn't */ /* clear that there is any way of requesting a buffer size in */ /* underlying pixels. */ /* -------------------------------------------------------------------- */ if(buffer <= 0) { /* use layer tolerance */ if(layer->tolerance == -1) layer_tolerance = 3; else layer_tolerance = layer->tolerance; if(layer->toleranceunits == MS_PIXELS) buffer = layer_tolerance * msAdjustExtent(&(map->extent), map->width, map->height); else buffer = layer_tolerance * (msInchesPerUnit(layer->toleranceunits,0) / msInchesPerUnit(map->units,0)); } /* -------------------------------------------------------------------- */ /* Setup target point information, at this point they are in */ /* map coordinates. */ /* -------------------------------------------------------------------- */ rlinfo->range_dist = buffer * buffer; rlinfo->target_point = p; /* -------------------------------------------------------------------- */ /* if we are in the MS_QUERY_SINGLE mode, first try a query with */ /* zero tolerance. If this gets a raster pixel then we can be */ /* reasonably assured that it is the closest to the query */ /* point. This will potentially be must more efficient than */ /* processing all pixels within the tolerance. */ /* -------------------------------------------------------------------- */ if( mode == MS_QUERY_SINGLE ) { rectObj pointRect; pointRect.minx = p.x; pointRect.maxx = p.x; pointRect.miny = p.y; pointRect.maxy = p.y; rlinfo->range_mode = MS_QUERY_SINGLE; result = msRasterQueryByRect( map, layer, pointRect ); if( rlinfo->query_results > 0 ) return result; } /* -------------------------------------------------------------------- */ /* Setup a rectangle that is everything within the designated */ /* range and do a search against that. */ /* -------------------------------------------------------------------- */ bufferRect.minx = p.x - buffer; bufferRect.maxx = p.x + buffer; bufferRect.miny = p.y - buffer; bufferRect.maxy = p.y + buffer; rlinfo->range_mode = mode; if( maxresults != 0 ) { previous_maxresults = rlinfo->query_result_hard_max; rlinfo->query_result_hard_max = maxresults; } result = msRasterQueryByRect( map, layer, bufferRect ); if( maxresults != 0 ) rlinfo->query_result_hard_max = previous_maxresults; return result; #endif /* USE_GDAL */ } /************************************************************************/ /* ==================================================================== */ /* RASTER Query Layer */ /* */ /* The results of a raster query are treated as a set of shapes */ /* that can be accessed using the normal layer semantics. */ /* ==================================================================== */ /************************************************************************/ /************************************************************************/ /* msRASTERLayerOpen() */ /************************************************************************/ int msRASTERLayerOpen(layerObj *layer) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRASTERLayerOpen()" ); return MS_FAILURE; #else rasterLayerInfo *rlinfo; /* If we don't have info, initialize an empty one now */ if( layer->layerinfo == NULL ) msRasterLayerInfoInitialize( layer ); rlinfo = (rasterLayerInfo *) layer->layerinfo; rlinfo->refcount = rlinfo->refcount + 1; return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERIsLayerOpen() */ /************************************************************************/ int msRASTERLayerIsOpen(layerObj *layer) { #ifndef USE_GDAL msSetError( MS_IMGERR, "Rasters queries only supported with GDAL support enabled.", "msRasterLayerIsOpen()" ); return MS_FALSE; #else if (layer->layerinfo) return MS_TRUE; return MS_FALSE; #endif } /************************************************************************/ /* msRASTERLayerFreeItemInfo() */ /************************************************************************/ void msRASTERLayerFreeItemInfo(layerObj *layer) {} /************************************************************************/ /* msRASTERLayerInitItemInfo() */ /* */ /* Perhaps we should be validating the requested items here? */ /************************************************************************/ int msRASTERLayerInitItemInfo(layerObj *layer) { return MS_SUCCESS; } /************************************************************************/ /* msRASTERLayerWhichShapes() */ /************************************************************************/ int msRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; rlinfo->which_rect = rect; rlinfo->next_shape = 0; return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerClose() */ /************************************************************************/ int msRASTERLayerClose(layerObj *layer) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo != NULL ) { rlinfo->refcount--; if( rlinfo->refcount < 0 ) msRasterLayerInfoFree( layer ); } return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerNextShape() */ /************************************************************************/ int msRASTERLayerNextShape(layerObj *layer, shapeObj *shape) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo->next_shape < 0 || rlinfo->next_shape >= rlinfo->query_results ) { msFreeShape(shape); shape->type = MS_SHAPE_NULL; return MS_DONE; } else { resultObj record; record.shapeindex = rlinfo->next_shape++; record.tileindex = 0; record.classindex = record.resultindex = -1; return msRASTERLayerGetShape( layer, shape, &record); } #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerGetShape() */ /************************************************************************/ int msRASTERLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { #ifndef USE_GDAL return MS_FAILURE; #else rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; int i; long shapeindex = record->shapeindex; msFreeShape(shape); shape->type = MS_SHAPE_NULL; /* -------------------------------------------------------------------- */ /* Validate requested record id. */ /* -------------------------------------------------------------------- */ if( shapeindex < 0 || shapeindex >= rlinfo->query_results ) { msSetError(MS_MISCERR, "Out of range shape index requested. Requested %ld\n" "but only %d shapes available.", "msRASTERLayerGetShape()", shapeindex, rlinfo->query_results ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Apply the geometry. */ /* -------------------------------------------------------------------- */ if( rlinfo->qc_x != NULL ) { lineObj line; pointObj point; shape->type = MS_SHAPE_POINT; line.numpoints = 1; line.point = &point; point.x = rlinfo->qc_x[shapeindex]; point.y = rlinfo->qc_y[shapeindex]; #ifdef USE_POINT_Z_M point.m = 0.0; #endif msAddLine( shape, &line ); msComputeBounds( shape ); } /* -------------------------------------------------------------------- */ /* Apply the requested items. */ /* -------------------------------------------------------------------- */ if( layer->numitems > 0 ) { shape->values = (char **) msSmallMalloc(sizeof(char *) * layer->numitems); shape->numvalues = layer->numitems; for( i = 0; i < layer->numitems; i++ ) { const size_t bufferSize = 1000; char szWork[1000]; szWork[0] = '\0'; if( EQUAL(layer->items[i],"x") && rlinfo->qc_x_reproj ) snprintf( szWork, bufferSize, "%.8g", rlinfo->qc_x_reproj[shapeindex] ); else if( EQUAL(layer->items[i],"y") && rlinfo->qc_y_reproj ) snprintf( szWork, bufferSize, "%.8g", rlinfo->qc_y_reproj[shapeindex] ); else if( EQUAL(layer->items[i],"value_list") && rlinfo->qc_values ) { int iValue; for( iValue = 0; iValue < rlinfo->band_count; iValue++ ) { if( iValue != 0 ) strlcat( szWork, ",", bufferSize); snprintf( szWork+strlen(szWork), bufferSize-strlen(szWork), "%.8g", rlinfo->qc_values[shapeindex * rlinfo->band_count + iValue] ); } } else if( EQUALN(layer->items[i],"value_",6) && rlinfo->qc_values ) { int iValue = atoi(layer->items[i]+6); snprintf( szWork, bufferSize, "%.8g", rlinfo->qc_values[shapeindex*rlinfo->band_count+iValue] ); } else if( EQUAL(layer->items[i],"class") && rlinfo->qc_class ) { int p_class = rlinfo->qc_class[shapeindex]; if( layer->class[p_class]->name != NULL ) snprintf( szWork, bufferSize, "%.999s", layer->class[p_class]->name ); else snprintf( szWork, bufferSize, "%d", p_class ); } else if( EQUAL(layer->items[i],"red") && rlinfo->qc_red ) snprintf( szWork, bufferSize, "%d", rlinfo->qc_red[shapeindex] ); else if( EQUAL(layer->items[i],"green") && rlinfo->qc_green ) snprintf( szWork, bufferSize, "%d", rlinfo->qc_green[shapeindex] ); else if( EQUAL(layer->items[i],"blue") && rlinfo->qc_blue ) snprintf( szWork, bufferSize, "%d", rlinfo->qc_blue[shapeindex] ); else if( EQUAL(layer->items[i],"count") && rlinfo->qc_count ) snprintf( szWork, bufferSize, "%d", rlinfo->qc_count[shapeindex] ); shape->values[i] = msStrdup(szWork); } } /* -------------------------------------------------------------------- */ /* Eventually we should likey apply the geometry properly but */ /* we don't really care about the geometry for query purposes. */ /* -------------------------------------------------------------------- */ return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerGetItems() */ /************************************************************************/ int msRASTERLayerGetItems(layerObj *layer) { #ifndef USE_GDAL return MS_FAILURE; #else int maxnumitems = 0; rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo; if( rlinfo == NULL ) return MS_FAILURE; maxnumitems = 8 + (rlinfo->qc_values?rlinfo->band_count:0); layer->items = (char **) msSmallCalloc(sizeof(char *),maxnumitems); layer->numitems = 0; if( rlinfo->qc_x_reproj ) layer->items[layer->numitems++] = msStrdup("x"); if( rlinfo->qc_y_reproj ) layer->items[layer->numitems++] = msStrdup("y"); if( rlinfo->qc_values ) { int i; for( i = 0; i < rlinfo->band_count; i++ ) { char szName[100]; snprintf( szName, sizeof(szName), "value_%d", i ); layer->items[layer->numitems++] = msStrdup(szName); } layer->items[layer->numitems++] = msStrdup("value_list"); } if( rlinfo->qc_class ) layer->items[layer->numitems++] = msStrdup("class"); if( rlinfo->qc_red ) layer->items[layer->numitems++] = msStrdup("red"); if( rlinfo->qc_green ) layer->items[layer->numitems++] = msStrdup("green"); if( rlinfo->qc_blue ) layer->items[layer->numitems++] = msStrdup("blue"); if( rlinfo->qc_count ) layer->items[layer->numitems++] = msStrdup("count"); assert(layer->numitems <= maxnumitems); return msRASTERLayerInitItemInfo(layer); #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerGetExtent() */ /************************************************************************/ int msRASTERLayerGetExtent(layerObj *layer, rectObj *extent) { #ifndef USE_GDAL return MS_FAILURE; #else char szPath[MS_MAXPATHLEN]; mapObj *map = layer->map; double adfGeoTransform[6]; int nXSize, nYSize; GDALDatasetH hDS; shapefileObj *tileshpfile; int tilelayerindex = -1; CPLErr eErr = CE_Failure; char *decrypted_path; if( (!layer->data || strlen(layer->data) == 0) && layer->tileindex == NULL) { /* should we be issuing a specific error about not supporting extents for tileindexed raster layers? */ return MS_FAILURE; } if( map == NULL ) return MS_FAILURE; /* If the layer use a tileindex, return the extent of the tileindex shapefile/referenced layer */ if (layer->tileindex) { tilelayerindex = msGetLayerIndex(map, layer->tileindex); if(tilelayerindex != -1) /* does the tileindex reference another layer */ return msLayerGetExtent(GET_LAYER(map, tilelayerindex), extent); else { tileshpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); MS_CHECK_ALLOC(tileshpfile, sizeof(shapefileObj), MS_FAILURE); if(msShapefileOpen(tileshpfile, "rb", msBuildPath3(szPath, map->mappath, map->shapepath, layer->tileindex), MS_TRUE) == -1) if(msShapefileOpen(tileshpfile, "rb", msBuildPath(szPath, map->mappath, layer->tileindex), MS_TRUE) == -1) return MS_FAILURE; *extent = tileshpfile->bounds; msShapefileClose(tileshpfile); free(tileshpfile); return MS_SUCCESS; } } msTryBuildPath3(szPath, map->mappath, map->shapepath, layer->data); decrypted_path = msDecryptStringTokens( map, szPath ); msAcquireLock( TLOCK_GDAL ); if( decrypted_path ) { hDS = GDALOpen(decrypted_path, GA_ReadOnly ); msFree( decrypted_path ); } else hDS = NULL; if( hDS != NULL ) { nXSize = GDALGetRasterXSize( hDS ); nYSize = GDALGetRasterYSize( hDS ); eErr = GDALGetGeoTransform( hDS, adfGeoTransform ); GDALClose( hDS ); } msReleaseLock( TLOCK_GDAL ); if( hDS == NULL || eErr != CE_None ) { return MS_FAILURE; } /* If this appears to be an ungeoreferenced raster than flip it for mapservers purposes. */ if( adfGeoTransform[5] == 1.0 && adfGeoTransform[3] == 0.0 ) { adfGeoTransform[5] = -1.0; adfGeoTransform[3] = nYSize; } extent->minx = adfGeoTransform[0]; extent->maxy = adfGeoTransform[3]; extent->maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1]; extent->miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5]; return MS_SUCCESS; #endif /* def USE_GDAL */ } /************************************************************************/ /* msRASTERLayerSetTimeFilter() */ /* */ /* This function is actually just used in the context of */ /* setting a filter on the tileindex for time based queries. */ /* For instance via WMS requests. So it isn't really related */ /* to the "raster query" support at all. */ /* */ /* If a local shapefile tileindex is in use, we will set a */ /* backtics filter (shapefile compatible). If another layer is */ /* being used as the tileindex then we will forward the */ /* SetTimeFilter call to it. If there is no tileindex in */ /* place, we do nothing. */ /************************************************************************/ int msRASTERLayerSetTimeFilter(layerObj *layer, const char *timestring, const char *timefield) { int tilelayerindex; /* -------------------------------------------------------------------- */ /* If we don't have a tileindex the time filter has no effect. */ /* -------------------------------------------------------------------- */ if( layer->tileindex == NULL ) return MS_SUCCESS; /* -------------------------------------------------------------------- */ /* Find the tileindex layer. */ /* -------------------------------------------------------------------- */ tilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); /* -------------------------------------------------------------------- */ /* If we are using a local shapefile as our tileindex (that is */ /* to say, the tileindex name is not of another layer), then we */ /* just install a backtics style filter on the raster layer. */ /* This is propogated to the "working layer" created for the */ /* tileindex by code in mapraster.c. */ /* -------------------------------------------------------------------- */ if( tilelayerindex == -1 ) return msLayerMakeBackticsTimeFilter( layer, timestring, timefield ); /* -------------------------------------------------------------------- */ /* Otherwise we invoke the tileindex layers SetTimeFilter */ /* method. */ /* -------------------------------------------------------------------- */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; return msLayerSetTimeFilter( layer->GET_LAYER(map,tilelayerindex), timestring, timefield ); } /************************************************************************/ /* msRASTERLayerInitializeVirtualTable() */ /************************************************************************/ int msRASTERLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msRASTERLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msRASTERLayerFreeItemInfo; layer->vtable->LayerOpen = msRASTERLayerOpen; layer->vtable->LayerIsOpen = msRASTERLayerIsOpen; layer->vtable->LayerWhichShapes = msRASTERLayerWhichShapes; layer->vtable->LayerNextShape = msRASTERLayerNextShape; layer->vtable->LayerGetShape = msRASTERLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerClose = msRASTERLayerClose; layer->vtable->LayerGetItems = msRASTERLayerGetItems; layer->vtable->LayerGetExtent = msRASTERLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCloseConnection = msRASTERLayerClose; */ /* we use backtics for proper tileindex shapefile functioning */ layer->vtable->LayerSetTimeFilter = msRASTERLayerSetTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } mapserver-7.4.3/mapregex.c000066400000000000000000000056631357574274700155440ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Regex wrapper * Author: Bill Binko * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* we can't include mapserver.h, so we need our own basics */ #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #else #include #endif /*Need to specify this so that mapregex.h doesn't defined constants and doesn't #define away our ms_*/ #if defined(_WIN32) && !defined(__CYGWIN__) && _MSC_VER < 1900 #define off_t long #endif #include "mapserver.h" #include "mapregex.h" #include MS_API_EXPORT(int) ms_regcomp(ms_regex_t *regex, const char *expr, int cflags) { /* Must free in regfree() */ regex_t* sys_regex = (regex_t*) msSmallMalloc(sizeof(regex_t)); regex->sys_regex = (void*) sys_regex; return regcomp(sys_regex, expr, cflags); } MS_API_EXPORT(size_t) ms_regerror(int errcode, const ms_regex_t *regex, char *errbuf, size_t errbuf_size) { return regerror(errcode, (regex_t*)(regex->sys_regex), errbuf, errbuf_size); } MS_API_EXPORT(int) ms_regexec(const ms_regex_t *regex, const char *string, size_t nmatch, ms_regmatch_t pmatch[], int eflags) { /*This next line only works because we know that regmatch_t and ms_regmatch_t are exactly alike (POSIX STANDARD)*/ return regexec((const regex_t*)(regex->sys_regex), string, nmatch, (regmatch_t*) pmatch, eflags); } MS_API_EXPORT(void) ms_regfree(ms_regex_t *regex) { regfree((regex_t*)(regex->sys_regex)); free(regex->sys_regex); return; } mapserver-7.4.3/mapregex.h000066400000000000000000000071201357574274700155370ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Regex wrapper * Author: Bill Binko * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAP_REGEX_H #define MAP_REGEX_H #ifdef __cplusplus extern "C" { #endif /* We want these to match the POSIX standard, so we need these*/ /* === regex2.h === */ #ifdef WIN32 #define MS_API_EXPORT(type) __declspec(dllexport) type __stdcall #elif defined(__GNUC__) && __GNUC__ >= 4 #define MS_API_EXPORT(type) __attribute__ ((visibility("default"))) type #else #define MS_API_EXPORT(type) type #endif typedef struct { void* sys_regex; } ms_regex_t; typedef int ms_regoff_t; typedef struct { ms_regoff_t rm_so; /* Byte offset from string's start to substring's start. */ ms_regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ } ms_regmatch_t; MS_API_EXPORT(int) ms_regcomp(ms_regex_t *, const char *, int); MS_API_EXPORT(size_t) ms_regerror(int, const ms_regex_t *, char *, size_t); MS_API_EXPORT(int) ms_regexec(const ms_regex_t *, const char *, size_t, ms_regmatch_t [], int); MS_API_EXPORT(void) ms_regfree(ms_regex_t *); #ifndef BUILDING_REGEX_PROXY /* === regcomp.c === */ #define MS_REG_BASIC 0000 #define MS_REG_EXTENDED 0001 #define MS_REG_ICASE 0002 #define MS_REG_NOSUB 0004 #define MS_REG_NEWLINE 0010 #define MS_REG_NOSPEC 0020 #define MS_REG_PEND 0040 #define MS_REG_DUMP 0200 /* === regerror.c === */ #define MS_REG_OKAY 0 #define MS_REG_NOMATCH 1 #define MS_REG_BADPAT 2 #define MS_REG_ECOLLATE 3 #define MS_REG_ECTYPE 4 #define MS_REG_EESCAPE 5 #define MS_REG_ESUBREG 6 #define MS_REG_EBRACK 7 #define MS_REG_EPAREN 8 #define MS_REG_EBRACE 9 #define MS_REG_BADBR 10 #define MS_REG_ERANGE 11 #define MS_REG_ESPACE 12 #define MS_REG_BADRPT 13 #define MS_REG_EMPTY 14 #define MS_REG_ASSERT 15 #define MS_REG_INVARG 16 #define MS_REG_ATOI 255 /* convert name to number (!) */ #define MS_REG_ITOA 0400 /* convert number to name (!) */ /* === regexec.c === */ #define MS_REG_NOTBOL 00001 #define MS_REG_NOTEOL 00002 #define MS_REG_STARTEND 00004 #define MS_REG_TRACE 00400 /* tracing of execution */ #define MS_REG_LARGE 01000 /* force large representation */ #define MS_REG_BACKR 02000 /* force use of backref code */ #endif #ifdef __cplusplus } #endif #endif mapserver-7.4.3/maprendering.c000066400000000000000000001217731357574274700164100ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Rendering utility functions * Author: Thomas Bonfort and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2011 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "mapcopy.h" #include "fontcache.h" void computeSymbolStyle(symbolStyleObj *s, styleObj *src, symbolObj *symbol, double scalefactor, double resolutionfactor) { double default_size; double target_size; double style_size; default_size = msSymbolGetDefaultSize(symbol); style_size = (src->size==-1)?default_size:src->size; INIT_SYMBOL_STYLE(*s); if(symbol->type == MS_SYMBOL_PIXMAP) { s->color = s->outlinecolor = NULL; } else if(symbol->filled || symbol->type == MS_SYMBOL_TRUETYPE) { if(MS_VALID_COLOR(src->color)) s->color = &src->color; if(MS_VALID_COLOR(src->outlinecolor)) s->outlinecolor = &src->outlinecolor; } else { if(MS_VALID_COLOR(src->color)) s->outlinecolor = &(src->color); else if(MS_VALID_COLOR(src->outlinecolor)) s->outlinecolor = &(src->outlinecolor); s->color = NULL; } if(MS_VALID_COLOR(src->backgroundcolor)) { s->backgroundcolor = &(src->backgroundcolor); } target_size = style_size * scalefactor; target_size = MS_MAX(target_size, src->minsize*resolutionfactor); target_size = MS_MIN(target_size, src->maxsize*resolutionfactor); s->scale = target_size / default_size; s->gap = src->gap * target_size / style_size; if(s->outlinecolor) { s->outlinewidth = src->width * scalefactor; s->outlinewidth = MS_MAX(s->outlinewidth, src->minwidth*resolutionfactor); s->outlinewidth = MS_MIN(s->outlinewidth, src->maxwidth*resolutionfactor); } else { s->outlinewidth = 0; } s->rotation = src->angle * MS_DEG_TO_RAD; } #define COMPARE_COLORS(a,b) (\ ((a).red==(b).red) && \ ((a).green==(b).green) && \ ((a).blue==(b).blue) && \ ((a).alpha==(b).alpha)) tileCacheObj *searchTileCache(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int width, int height) { tileCacheObj *cur = img->tilecache; while(cur != NULL) { if( cur->width == width && cur->height == height && cur->symbol == symbol && cur->outlinewidth == s->outlinewidth && cur->rotation == s->rotation && cur->scale == s->scale && (!s->color || COMPARE_COLORS(cur->color,*s->color)) && (!s->backgroundcolor || COMPARE_COLORS(cur->backgroundcolor,*s->backgroundcolor)) && (!s->outlinecolor || COMPARE_COLORS(cur->outlinecolor,*s->outlinecolor))) return cur; cur = cur->next; } return NULL; } int preloadSymbol(symbolSetObj *symbolset, symbolObj *symbol, rendererVTableObj *renderer) { switch(symbol->type) { case MS_SYMBOL_VECTOR: case MS_SYMBOL_ELLIPSE: case MS_SYMBOL_SIMPLE: case (MS_SYMBOL_TRUETYPE): break; case (MS_SYMBOL_SVG): #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) return msPreloadSVGSymbol(symbol); #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "preloadSymbol()"); return MS_FAILURE; #endif break; case (MS_SYMBOL_PIXMAP): { if(!symbol->pixmap_buffer) { if(MS_SUCCESS != msPreloadImageSymbol(renderer,symbol)) return MS_FAILURE; } } break; default: msSetError(MS_MISCERR,"unsupported symbol type %d", "preloadSymbol()", symbol->type); return MS_FAILURE; } return MS_SUCCESS; } /* add a cached tile to the current image's cache */ tileCacheObj *addTileCache(imageObj *img, imageObj *tile, symbolObj *symbol, symbolStyleObj *style, int width, int height) { tileCacheObj *cachep; if(img->ntiles >= MS_IMAGECACHESIZE) { /* remove last element, size stays the same */ cachep = img->tilecache; /*go to the before last cache object*/ while(cachep->next && cachep->next->next) cachep = cachep->next; /*free the last tile's data*/ msFreeImage(cachep->next->image); /*reuse the last tile object*/ /* make the cache point to the start of the list*/ cachep->next->next = img->tilecache; /* point the global cache to the new first */ img->tilecache = cachep->next; /* the before last cache is now last, so it has no successor*/ cachep->next = NULL; } else { img->ntiles += 1; cachep = (tileCacheObj*)malloc(sizeof(tileCacheObj)); MS_CHECK_ALLOC(cachep, sizeof(tileCacheObj), NULL); cachep->next = img->tilecache; img->tilecache = cachep; } cachep = img->tilecache; cachep->image = tile; cachep->outlinewidth = style->outlinewidth; cachep->scale = style->scale; cachep->rotation = style->rotation; cachep->outlinewidth = style->outlinewidth; if(style->color) MS_COPYCOLOR(&cachep->color,style->color); if(style->outlinecolor) MS_COPYCOLOR(&cachep->outlinecolor,style->outlinecolor); if(style->backgroundcolor) MS_COPYCOLOR(&cachep->backgroundcolor,style->backgroundcolor); cachep->width = width; cachep->height = height; cachep->symbol = symbol; return(cachep); } /* helper function to center glyph on the desired point */ int WARN_UNUSED drawGlyphMarker(imageObj *img, face_element *face, glyph_element *glyphc, double px, double py, int size, double rotation, colorObj *clr, colorObj *oclr, int olwidth) { double ox, oy; textPathObj path; glyphObj glyph; rendererVTableObj *renderer = img->format->vtable; if(!renderer->renderGlyphs) return MS_FAILURE; path.numglyphs = 1; glyph.glyph = glyphc; glyph.face = face; path.glyphs = &glyph; path.glyph_size = size; glyph.rot = rotation; ox = (glyphc->metrics.maxx + glyphc->metrics.minx) / 2.0; oy = (glyphc->metrics.maxy + glyphc->metrics.miny) / 2.0; if(rotation != 0) { double sina, cosa; double rox,roy; sina = sin(rotation); cosa = cos(rotation); rox = ox * cosa - oy * sina; roy = ox * sina + oy * cosa; px -= rox; py += roy; glyph.pnt.x = px; glyph.pnt.y = py; } else { glyph.pnt.x = px - ox; glyph.pnt.y = py + oy; } return renderer->renderGlyphs(img, &path, clr, oclr, olwidth); } imageObj *getTile(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int width, int height, int seamlessmode) { tileCacheObj *tile; int status = MS_SUCCESS; rendererVTableObj *renderer = img->format->vtable; if(width==-1 || height == -1) { width=height=MS_MAX(symbol->sizex,symbol->sizey); } tile = searchTileCache(img,symbol,s,width,height); if(tile==NULL) { imageObj *tileimg; double p_x,p_y; tileimg = msImageCreate(width,height,img->format,NULL,NULL,img->resolution, img->resolution, NULL); if(UNLIKELY(!tileimg)) { return NULL; } if(!seamlessmode) { p_x = width/2.0; p_y = height/2.0; switch(symbol->type) { case (MS_SYMBOL_TRUETYPE): { unsigned int unicode; glyph_element *glyphc; face_element *face = msGetFontFace(symbol->font, &img->map->fontset); if(UNLIKELY(!face)) { status = MS_FAILURE; break; } msUTF8ToUniChar(symbol->character, &unicode); unicode = msGetGlyphIndex(face,unicode); glyphc = msGetGlyphByIndex(face, MS_MAX(MS_NINT(s->scale),1), unicode); if(UNLIKELY(!glyphc)) { status = MS_FAILURE; break; } status = drawGlyphMarker(tileimg, face, glyphc, p_x, p_y, s->scale, s->rotation, s->color, s->outlinecolor, s->outlinewidth); } break; case (MS_SYMBOL_PIXMAP): status = msPreloadImageSymbol(renderer,symbol); if(UNLIKELY(status == MS_FAILURE)) { break; } status = renderer->renderPixmapSymbol(tileimg, p_x, p_y, symbol, s); break; case (MS_SYMBOL_ELLIPSE): status = renderer->renderEllipseSymbol(tileimg, p_x, p_y,symbol, s); break; case (MS_SYMBOL_VECTOR): status = renderer->renderVectorSymbol(tileimg, p_x, p_y, symbol, s); break; case (MS_SYMBOL_SVG): #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) status = msPreloadSVGSymbol(symbol); if(LIKELY(status == MS_SUCCESS)) { if (renderer->supports_svg) { status = renderer->renderSVGSymbol(tileimg, p_x, p_y, symbol, s); } else { status = msRenderRasterizedSVGSymbol(tileimg,p_x,p_y,symbol, s); } } #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "getTile()"); status = MS_FAILURE; #endif break; default: msSetError(MS_SYMERR, "Unknown symbol type %d", "getTile()", symbol->type); status = MS_FAILURE; break; } if(UNLIKELY(status == MS_FAILURE)) { msFreeImage(tileimg); return NULL; } } else { /* * in seamless mode, we render the the symbol 9 times on a 3x3 grid to account for * antialiasing blending from one tile to the next. We finally keep the center tile */ imageObj *tile3img = msImageCreate(width*3,height*3,img->format,NULL,NULL, img->resolution, img->resolution, NULL); int i,j; rasterBufferObj tmpraster; for(i=1; i<=3; i++) { p_x = (i+0.5)*width; for(j=1; j<=3; j++) { p_y = (j+0.5) * height; switch(symbol->type) { case (MS_SYMBOL_TRUETYPE): { unsigned int unicode; glyph_element *glyphc; face_element *face = msGetFontFace(symbol->font, &img->map->fontset); if(UNLIKELY(!face)) { status = MS_FAILURE; break; } msUTF8ToUniChar(symbol->character, &unicode); unicode = msGetGlyphIndex(face,unicode); glyphc = msGetGlyphByIndex(face, MS_MAX(MS_NINT(s->scale),1), unicode); if(UNLIKELY(!glyphc)) { status = MS_FAILURE; break; } status = drawGlyphMarker(tileimg, face, glyphc, p_x, p_y, s->scale, s->rotation, s->color, s->outlinecolor, s->outlinewidth); } break; case (MS_SYMBOL_PIXMAP): status = msPreloadImageSymbol(renderer,symbol); if(UNLIKELY(status == MS_FAILURE)) { break; } status = renderer->renderPixmapSymbol(tile3img, p_x, p_y, symbol, s); break; case (MS_SYMBOL_ELLIPSE): status = renderer->renderEllipseSymbol(tile3img, p_x, p_y,symbol, s); break; case (MS_SYMBOL_VECTOR): status = renderer->renderVectorSymbol(tile3img, p_x, p_y, symbol, s); break; default: msSetError(MS_SYMERR, "BUG: Seamless mode is only for vector symbols", "getTile()"); return NULL; } if(UNLIKELY(status == MS_FAILURE)) { msFreeImage(tile3img); return NULL; } } } if(UNLIKELY(status == MS_FAILURE)) { msFreeImage(tile3img); return NULL; } status = MS_IMAGE_RENDERER(tile3img)->getRasterBufferHandle(tile3img,&tmpraster); if(UNLIKELY(status == MS_FAILURE)) { msFreeImage(tile3img); return NULL; } status = renderer->mergeRasterBuffer(tileimg, &tmpraster, 1.0,width,height,0,0,width,height ); msFreeImage(tile3img); } if(UNLIKELY(status == MS_FAILURE)) { msFreeImage(tileimg); return NULL; } tile = addTileCache(img,tileimg,symbol,s,width,height); } return tile->image; } int msImagePolylineMarkers(imageObj *image, shapeObj *p, symbolObj *symbol, symbolStyleObj *style, double spacing, double initialgap, int auto_angle) { rendererVTableObj *renderer = MS_IMAGE_RENDERER(image); int i,j; pointObj point; double original_rotation = style->rotation; double symbol_width,symbol_height; glyph_element *glyphc = NULL; face_element *face = NULL; int ret = MS_SUCCESS; if(symbol->type != MS_SYMBOL_TRUETYPE) { symbol_width = MS_MAX(1,symbol->sizex*style->scale); symbol_height = MS_MAX(1,symbol->sizey*style->scale); } else { unsigned int unicode; msUTF8ToUniChar(symbol->character, &unicode); face = msGetFontFace(symbol->font, &image->map->fontset); if(UNLIKELY(!face)) return MS_FAILURE; unicode = msGetGlyphIndex(face,unicode); glyphc = msGetGlyphByIndex(face, MS_MAX(MS_NINT(style->scale),1), unicode); if(UNLIKELY(!glyphc)) return MS_FAILURE; symbol_width = glyphc->metrics.maxx - glyphc->metrics.minx; symbol_height = glyphc->metrics.maxy - glyphc->metrics.miny; } for(i=0; inumlines; i++) { int line_in = 0; double line_length=0; double current_length; if(initialgap < 0) { current_length = spacing/2.0; /* initial padding for each line */ } else { current_length = initialgap; /* initial padding for each line */ } for(j=1; jline[i].numpoints; j++) { double rx,ry,theta,length; length = sqrt((pow((p->line[i].point[j].x - p->line[i].point[j-1].x),2) + pow((p->line[i].point[j].y - p->line[i].point[j-1].y),2))); line_length += length; if(length==0)continue; rx = (p->line[i].point[j].x - p->line[i].point[j-1].x)/length; ry = (p->line[i].point[j].y - p->line[i].point[j-1].y)/length; if (auto_angle) { theta = asin(ry); if(rx < 0) { theta += MS_PI; } else theta = -theta; style->rotation = original_rotation + theta; } while (current_length <= length) { point.x = p->line[i].point[j - 1].x + current_length * rx; point.y = p->line[i].point[j - 1].y + current_length * ry; if(symbol->anchorpoint_x != 0.5 || symbol->anchorpoint_y != 0.5) { double ox, oy; ox = (0.5 - symbol->anchorpoint_x) * symbol_width; oy = (0.5 - symbol->anchorpoint_y) * symbol_height; if(style->rotation != 0) { double sina,cosa; double rox,roy; sina = sin(-style->rotation); cosa = cos(-style->rotation); rox = ox * cosa - oy * sina; roy = ox * sina + oy * cosa; point.x += rox; point.y += roy; } else { point.x += ox; point.y += oy; } } /* if the point is not in the map extent, skip it. (POLYLINE_NO_CLIP) */ if ( (point.x < -(symbol_width) || point.x > (image->width+symbol_width)) || (point.y < -(symbol_height) || point.y > (image->height+symbol_height)) ) { current_length += spacing; line_in=1; continue; } switch (symbol->type) { case MS_SYMBOL_PIXMAP: ret = renderer->renderPixmapSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_ELLIPSE: ret = renderer->renderEllipseSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_VECTOR: ret = renderer->renderVectorSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_TRUETYPE: ret = drawGlyphMarker(image, face, glyphc, point.x, point.y, style->scale, style->rotation, style->color, style->outlinecolor, style->outlinewidth); break; case (MS_SYMBOL_SVG): #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) if (renderer->supports_svg) { ret = renderer->renderSVGSymbol(image, point.x, point.y, symbol, style); } else { ret = msRenderRasterizedSVGSymbol(image,point.x,point.y,symbol, style); } #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msImagePolylineMarkers()()"); ret = MS_FAILURE; #endif break; } if( ret != MS_SUCCESS) return ret; current_length += spacing; line_in=1; } current_length -= length; } /* * if we couldn't place a symbol on the line and no initialgap was * specified, add one now we don't add the symbol if the line is shorter * than the length of the symbol itself */ if(initialgap < 0 && !line_in && line_length>symbol_width) { /* total lengths of beginnning and end of current segment */ double before_length=0,after_length=0; /*optimize*/ line_length /= 2.0; for(j=1; jline[i].numpoints; j++) { double length; length = sqrt((pow((p->line[i].point[j].x - p->line[i].point[j-1].x),2) + pow((p->line[i].point[j].y - p->line[i].point[j-1].y),2))); after_length += length; if(after_length>line_length) { double rx,ry,theta; /* offset where the symbol should be drawn on the current * segment */ double offset = line_length - before_length; rx = (p->line[i].point[j].x - p->line[i].point[j-1].x)/length; ry = (p->line[i].point[j].y - p->line[i].point[j-1].y)/length; if (auto_angle) { theta = asin(ry); if(rx < 0) { theta += MS_PI; } else theta = -theta; style->rotation = original_rotation + theta; } point.x = p->line[i].point[j - 1].x + offset * rx; point.y = p->line[i].point[j - 1].y + offset * ry; switch (symbol->type) { case MS_SYMBOL_PIXMAP: ret = renderer->renderPixmapSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_ELLIPSE: ret = renderer->renderEllipseSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_VECTOR: ret = renderer->renderVectorSymbol(image, point.x, point.y, symbol, style); break; case MS_SYMBOL_TRUETYPE: ret = drawGlyphMarker(image, face, glyphc, point.x, point.y, style->scale, style->rotation, style->color, style->outlinecolor, style->outlinewidth); break; case (MS_SYMBOL_SVG): #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) if (renderer->supports_svg) { ret = renderer->renderSVGSymbol(image, point.x, point.y, symbol, style); } else { ret = msRenderRasterizedSVGSymbol(image,point.x,point.y,symbol, style); } #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msImagePolylineMarkers()()"); ret = MS_FAILURE; #endif break; } break; /* we have rendered the single marker for this line */ } before_length += length; } } } return ret; } int msDrawLineSymbol(mapObj *map, imageObj *image, shapeObj *p, styleObj *style, double scalefactor) { int status = MS_SUCCESS; if (image) { if (MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; symbolObj *symbol; shapeObj *offsetLine = p; int i; double width; double finalscalefactor; if (p->numlines == 0) return MS_SUCCESS; if (style->symbol >= map->symbolset.numsymbols || style->symbol < 0) return MS_SUCCESS; /* no such symbol, 0 is OK */ symbol = map->symbolset.symbol[style->symbol]; /* store a reference to the renderer to be used for freeing */ symbol->renderer = renderer; width = style->width * scalefactor; width = MS_MIN(width,style->maxwidth*image->resolutionfactor); width = MS_MAX(width,style->minwidth*image->resolutionfactor); if(style->width != 0) { finalscalefactor = width / style->width; } else { finalscalefactor = 1.0; } if(style->offsety==MS_STYLE_SINGLE_SIDED_OFFSET) { offsetLine = msOffsetPolyline(p,style->offsetx * finalscalefactor ,MS_STYLE_SINGLE_SIDED_OFFSET); } else if(style->offsety==MS_STYLE_DOUBLE_SIDED_OFFSET) { offsetLine = msOffsetPolyline(p,style->offsetx * finalscalefactor ,MS_STYLE_DOUBLE_SIDED_OFFSET); } else if(style->offsetx!=0 || style->offsety!=0) { offsetLine = msOffsetPolyline(p, style->offsetx * finalscalefactor, style->offsety * finalscalefactor); } if(style->symbol == 0 || (symbol->type==MS_SYMBOL_SIMPLE)) { strokeStyleObj s; s.linecap = style->linecap; s.linejoin = style->linejoin; s.linejoinmaxsize = style->linejoinmaxsize; s.width = width; s.patternlength = style->patternlength; for(i=0; ipattern[i] * finalscalefactor; s.patternoffset = (style->initialgap<=0) ? 0 : (style->initialgap * finalscalefactor); if(MS_VALID_COLOR(style->color)) s.color = &style->color; else if(MS_VALID_COLOR(style->outlinecolor)) s.color = &style->outlinecolor; else { /* msSetError(MS_MISCERR,"no color defined for line styling","msDrawLineSymbol()"); * not really an error */ status = MS_SUCCESS; goto line_cleanup; } status = renderer->renderLine(image,offsetLine,&s); } else { symbolStyleObj s; if(preloadSymbol(&map->symbolset, symbol, renderer) != MS_SUCCESS) { status = MS_FAILURE; goto line_cleanup; } INIT_SYMBOL_STYLE(s); computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor); s.style = style; /* compute a markerStyle and use it on the line */ if(style->gap<0) { /* special function that treats any other symbol used as a marker, not a brush */ status = msImagePolylineMarkers(image,offsetLine,symbol,&s,-s.gap, style->initialgap * finalscalefactor, 1); } else if(style->gap>0) { status = msImagePolylineMarkers(image,offsetLine,symbol,&s,s.gap, style->initialgap * finalscalefactor,0); } else { if(renderer->renderLineTiled != NULL) { int pw,ph; imageObj* tile=NULL; if(s.scale != 1) { pw = MS_NINT(symbol->sizex * s.scale); ph = MS_NINT(symbol->sizey * s.scale); } else { pw = symbol->sizex; ph = symbol->sizey; } if(pw<1) pw=1; if(ph<1) ph=1; tile = getTile(image, symbol,&s,pw,ph,0); status = renderer->renderLineTiled(image, offsetLine, tile); } else { msSetError(MS_RENDERERERR, "renderer does not support brushed lines", "msDrawLineSymbol()"); status = MS_FAILURE; } } } line_cleanup: if(offsetLine!=p) { msFreeShape(offsetLine); msFree(offsetLine); } return status; } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawLineSymbolIM(map, image, p, style, scalefactor); else { msSetError(MS_RENDERERERR, "unsupported renderer", "msDrawShadeSymbol()"); status = MS_FAILURE; } } else { status = MS_FAILURE; } return status; } int msDrawShadeSymbol(mapObj *map, imageObj *image, shapeObj *p, styleObj *style, double scalefactor) { int ret = MS_SUCCESS; symbolObj *symbol; if (!p) return MS_SUCCESS; if (p->numlines <= 0) return MS_SUCCESS; if (style->symbol >= map->symbolset.numsymbols || style->symbol < 0) return MS_SUCCESS; /* no such symbol, 0 is OK */ symbol = map->symbolset.symbol[style->symbol]; /* * if only an outlinecolor was defined, and not a color, * switch to the line drawing function * * this behavior is kind of a mapfile hack, and must be * kept for backwards compatibility */ if (symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG ) { if (!MS_VALID_COLOR(style->color)) { if(MS_VALID_COLOR(style->outlinecolor)) return msDrawLineSymbol(map, image, p, style, scalefactor); else { /* just do nothing if no color has been set */ return MS_SUCCESS; } } } if (image) { if (MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; shapeObj *offsetPolygon = NULL; /* store a reference to the renderer to be used for freeing */ if(style->symbol) symbol->renderer = renderer; if (style->offsetx != 0 || style->offsety != 0) { if(style->offsety==MS_STYLE_SINGLE_SIDED_OFFSET) { offsetPolygon = msOffsetPolyline(p, style->offsetx*scalefactor, MS_STYLE_SINGLE_SIDED_OFFSET); } else if(style->offsety==MS_STYLE_DOUBLE_SIDED_OFFSET) { offsetPolygon = msOffsetPolyline(p,style->offsetx * scalefactor ,MS_STYLE_DOUBLE_SIDED_OFFSET); } else { offsetPolygon = msOffsetPolyline(p, style->offsetx*scalefactor,style->offsety*scalefactor); } } else { offsetPolygon=p; } /* simple polygon drawing, without any specific symbol. * also draws an optional outline */ if(style->symbol == 0 || symbol->type == MS_SYMBOL_SIMPLE) { ret = renderer->renderPolygon(image,offsetPolygon,&style->color); if(ret != MS_SUCCESS) goto cleanup; if(MS_VALID_COLOR(style->outlinecolor)) { strokeStyleObj s; INIT_STROKE_STYLE(s); s.color = &style->outlinecolor; s.color->alpha = style->color.alpha; s.width = (style->width == 0)?scalefactor:style->width*scalefactor; s.width = MS_MIN(s.width, style->maxwidth); s.width = MS_MAX(s.width, style->minwidth); ret = renderer->renderLine(image,offsetPolygon,&s); } goto cleanup; /*finished plain polygon*/ } else if(symbol->type == MS_SYMBOL_HATCH) { double width, spacing; double pattern[MS_MAXPATTERNLENGTH]; int i; if(MS_VALID_COLOR(style->backgroundcolor)) { ret = renderer->renderPolygon(image,offsetPolygon, &style->backgroundcolor); if(ret != MS_SUCCESS) goto cleanup; } width = (style->width <= 0)?scalefactor:style->width*scalefactor; width = MS_MIN(width, style->maxwidth*image->resolutionfactor); width = MS_MAX(width, style->minwidth*image->resolutionfactor); spacing = (style->size <= 0)?scalefactor:style->size*scalefactor; spacing = MS_MIN(spacing, style->maxsize*image->resolutionfactor); spacing = MS_MAX(spacing, style->minsize*image->resolutionfactor); /* scale the pattern by the factor applied to the width */ for(i=0; ipatternlength; i++) { pattern[i] = style->pattern[i]*width/style->width; } ret = msHatchPolygon(image,offsetPolygon,spacing,width,pattern,style->patternlength,style->angle, &style->color); goto cleanup; } else { symbolStyleObj s; int pw,ph; imageObj *tile; int seamless = 0; if(preloadSymbol(&map->symbolset,symbol,renderer) != MS_SUCCESS) { ret = MS_FAILURE; goto cleanup; } INIT_SYMBOL_STYLE(s); computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor); s.style = style; if (!s.color && !s.outlinecolor && symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG) { ret = MS_SUCCESS; /* nothing to do (colors are required except for PIXMAP symbols */ goto cleanup; } if(s.backgroundcolor) { ret = renderer->renderPolygon(image,offsetPolygon, s.backgroundcolor); if(ret != MS_SUCCESS) goto cleanup; } if(s.scale != 1) { if (s.gap > 0) { pw = MS_MAX(MS_NINT(s.gap),symbol->sizex * s.scale); ph = MS_MAX(MS_NINT(s.gap),symbol->sizey * s.scale); } else { pw = MS_NINT(symbol->sizex * s.scale); ph = MS_NINT(symbol->sizey * s.scale); } } else { if (s.gap > 0) { pw = MS_MAX(s.gap,symbol->sizex); ph = MS_MAX(s.gap,symbol->sizey); } else { pw = symbol->sizex; ph = symbol->sizey; } } if(pw<1) pw=1; if(ph<1) ph=1; /* if we're doing vector symbols with an antialiased pixel rendererer, we want to enable * seamless mode, i.e. comute a tile that accounts for the blending of neighbouring * tiles at the tile border */ if(symbol->type == MS_SYMBOL_VECTOR && style->gap == 0 && (image->format->renderer == MS_RENDER_WITH_AGG || image->format->renderer == MS_RENDER_WITH_CAIRO_RASTER)) { seamless = 1; } tile = getTile(image,symbol,&s,pw,ph,seamless); ret = renderer->renderPolygonTiled(image,offsetPolygon, tile); } cleanup: if (offsetPolygon != p) { msFreeShape(offsetPolygon); msFree(offsetPolygon); } return ret; } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawShadeSymbolIM(map, image, p, style, scalefactor); } return ret; } int msDrawMarkerSymbol(mapObj *map, imageObj *image, pointObj *p, styleObj *style, double scalefactor) { int ret = MS_SUCCESS; if (!p) return MS_SUCCESS; if (style->symbol >= map->symbolset.numsymbols || style->symbol <= 0) return MS_SUCCESS; /* no such symbol, 0 is OK */ if (image) { if(MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; symbolStyleObj s; double p_x,p_y; symbolObj *symbol = map->symbolset.symbol[style->symbol]; /* store a reference to the renderer to be used for freeing */ symbol->renderer = renderer; if(preloadSymbol(&map->symbolset,symbol,renderer) != MS_SUCCESS) { return MS_FAILURE; } computeSymbolStyle(&s,style,symbol,scalefactor,image->resolutionfactor); s.style = style; if (!s.color && !s.outlinecolor && symbol->type != MS_SYMBOL_PIXMAP && symbol->type != MS_SYMBOL_SVG) { return MS_SUCCESS; // nothing to do if no color, except for pixmap symbols } if(s.scale == 0) { return MS_SUCCESS; } /* TODO: skip the drawing of the symbol if it's smaller than a pixel ? if (s.size < 1) return; // size too small */ p_x = p->x; p_y = p->y; if (style->polaroffsetpixel != 0 || style->polaroffsetangle != 0) { double angle = style->polaroffsetangle * MS_DEG_TO_RAD; p_x += (style->polaroffsetpixel * cos(-angle)) * scalefactor; p_y += (style->polaroffsetpixel * sin(-angle)) * scalefactor; } p_x += style->offsetx * scalefactor; p_y += style->offsety * scalefactor; if(symbol->anchorpoint_x != 0.5 || symbol->anchorpoint_y != 0.5) { double sx,sy; double ox, oy; if(UNLIKELY(MS_FAILURE == msGetMarkerSize(map, style, &sx, &sy, scalefactor))) { return MS_FAILURE; } ox = (0.5 - symbol->anchorpoint_x) * sx; oy = (0.5 - symbol->anchorpoint_y) * sy; if(s.rotation != 0) { double sina, cosa; double rox,roy; sina = sin(-s.rotation); cosa = cos(-s.rotation); rox = ox * cosa - oy * sina; roy = ox * sina + oy * cosa; p_x += rox; p_y += roy; } else { p_x += ox; p_y += oy; } } if(renderer->use_imagecache) { imageObj *tile = getTile(image, symbol, &s, -1, -1,0); if(tile!=NULL) return renderer->renderTile(image, tile, p_x, p_y); else { msSetError(MS_RENDERERERR, "problem creating cached tile", "msDrawMarkerSymbol()"); return MS_FAILURE; } } switch (symbol->type) { case (MS_SYMBOL_TRUETYPE): { unsigned int unicode; glyph_element *glyphc; face_element *face = msGetFontFace(symbol->font, &map->fontset); if(UNLIKELY(!face)) return MS_FAILURE; msUTF8ToUniChar(symbol->character,&unicode); unicode = msGetGlyphIndex(face,unicode); glyphc = msGetGlyphByIndex(face, MS_MAX(MS_NINT(s.scale),1), unicode); if(UNLIKELY(!glyphc)) return MS_FAILURE; ret = drawGlyphMarker(image, face, glyphc, p_x, p_y, s.scale, s.rotation, s.color, s.outlinecolor, s.outlinewidth); } break; case (MS_SYMBOL_PIXMAP): { assert(symbol->pixmap_buffer); ret = renderer->renderPixmapSymbol(image,p_x,p_y,symbol,&s); } break; case (MS_SYMBOL_ELLIPSE): { ret = renderer->renderEllipseSymbol(image, p_x, p_y,symbol, &s); } break; case (MS_SYMBOL_VECTOR): { ret = renderer->renderVectorSymbol(image, p_x, p_y, symbol, &s); } break; case (MS_SYMBOL_SVG): { if (renderer->supports_svg) { ret = renderer->renderSVGSymbol(image, p_x, p_y, symbol, &s); } else { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) ret = msRenderRasterizedSVGSymbol(image, p_x,p_y, symbol, &s); #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msDrawMarkerSymbol()"); return MS_FAILURE; #endif } } break; default: break; } return ret; } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawMarkerSymbolIM(map, image, p, style, scalefactor); } return ret; } int msDrawLabelBounds(mapObj *map, imageObj *image, label_bounds *bnds, styleObj *style, double scalefactor) { /* * helper function to draw label bounds, where we might have only a rectObj and not * a lineObj/shapeObj */ shapeObj shape; shape.numlines = 1; if(bnds->poly) { shape.line = bnds->poly; return msDrawShadeSymbol(map,image,&shape,style,scalefactor); } else { pointObj pnts1[5]; lineObj l; l.point = pnts1; l.numpoints = 5; pnts1[0].x = pnts1[1].x = pnts1[4].x = bnds->bbox.minx; pnts1[2].x = pnts1[3].x = bnds->bbox.maxx; pnts1[0].y = pnts1[3].y = pnts1[4].y = bnds->bbox.miny; pnts1[1].y = pnts1[2].y = bnds->bbox.maxy; shape.line = &l; // must return from this block return msDrawShadeSymbol(map,image,&shape,style,scalefactor); } } int msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbolObj *ts) { rendererVTableObj *renderer = image->format->vtable; colorObj *c = NULL, *oc = NULL; int ow; assert(ts->textpath); if(!renderer->renderGlyphs) return MS_FAILURE; if(!ts->textpath->absolute) { int g; double cosa,sina; double x = labelPnt.x; double y = labelPnt.y; if(ts->rotation != 0) { cosa = cos(ts->rotation); sina = sin(ts->rotation); for(g=0;gtextpath->numglyphs;g++) { double ox = ts->textpath->glyphs[g].pnt.x; double oy = ts->textpath->glyphs[g].pnt.y; ts->textpath->glyphs[g].pnt.x = ox * cosa + oy * sina + x; ts->textpath->glyphs[g].pnt.y = -ox * sina + oy * cosa + y; ts->textpath->glyphs[g].rot = ts->rotation; } } else { for(g=0;gtextpath->numglyphs;g++) { ts->textpath->glyphs[g].pnt.x += x; ts->textpath->glyphs[g].pnt.y += y; } } } if(MS_VALID_COLOR(ts->label->shadowcolor)) { textSymbolObj *ts_shadow; int g; double ox, oy; double cosa,sina; int ret; if(ts->rotation != 0) { cosa = cos(ts->rotation); sina = sin(ts->rotation); ox = ts->scalefactor * (cosa * ts->label->shadowsizex + sina * ts->label->shadowsizey); oy = ts->scalefactor * (-sina * ts->label->shadowsizex + cosa * ts->label->shadowsizey); } else { ox = ts->scalefactor * ts->label->shadowsizex; oy = ts->scalefactor * ts->label->shadowsizey; } ts_shadow = msSmallMalloc(sizeof(textSymbolObj)); initTextSymbol(ts_shadow); msCopyTextSymbol(ts_shadow,ts); for(g=0;gtextpath->numglyphs;g++) { ts_shadow->textpath->glyphs[g].pnt.x += ox; ts_shadow->textpath->glyphs[g].pnt.y += oy; } ret = renderer->renderGlyphs(image,ts_shadow->textpath,&ts->label->shadowcolor,NULL,0); freeTextSymbol(ts_shadow); msFree(ts_shadow); if( ret != MS_SUCCESS ) return ret; } if(MS_VALID_COLOR(ts->label->color)) c = &ts->label->color; if(MS_VALID_COLOR(ts->label->outlinecolor)) oc = &ts->label->outlinecolor; ow = MS_NINT((double)ts->label->outlinewidth * ((double)ts->textpath->glyph_size / (double)ts->label->size)); return renderer->renderGlyphs(image,ts->textpath,c,oc,ow); } /************************************************************************/ /* msCircleDrawLineSymbol */ /* */ /************************************************************************/ int msCircleDrawLineSymbol(mapObj *map, imageObj *image, pointObj *p, double r, styleObj *style, double scalefactor) { shapeObj *circle; int status; if (!image) return MS_FAILURE; circle = msRasterizeArc(p->x, p->y, r, 0, 360, 0); if (!circle) return MS_FAILURE; status = msDrawLineSymbol(map, image, circle, style, scalefactor); msFreeShape(circle); msFree(circle); return status; } int msCircleDrawShadeSymbol(mapObj *map, imageObj *image, pointObj *p, double r, styleObj *style, double scalefactor) { shapeObj *circle; int status; if (!image) return MS_FAILURE; circle = msRasterizeArc(p->x, p->y, r, 0, 360, 0); if (!circle) return MS_FAILURE; status = msDrawShadeSymbol(map, image, circle, style, scalefactor); msFreeShape(circle); msFree(circle); return status; } int msDrawPieSlice(mapObj *map, imageObj *image, pointObj *p, styleObj *style, double radius, double start, double end) { int status; shapeObj *circle; double center_x = p->x; double center_y = p->y; if (!image) return MS_FAILURE; if(style->offsetx>0) { center_x+=style->offsetx*cos(((-start-end)*MS_PI/360.)); center_y-=style->offsetx*sin(((-start-end)*MS_PI/360.)); } circle = msRasterizeArc(center_x, center_y, radius, start, end, 1); if (!circle) return MS_FAILURE; status = msDrawShadeSymbol(map, image, circle, style, 1.0); msFreeShape(circle); msFree(circle); return status; } /* * RFC 49 implementation * if an outlinewidth is used: * - augment the style's width to account for the outline width * - swap the style color and outlinecolor * - draw the shape (the outline) in the first pass of the * caching mechanism */ void msOutlineRenderingPrepareStyle(styleObj *pStyle, mapObj *map, layerObj *layer, imageObj *image) { colorObj tmp; if (pStyle->outlinewidth > 0) { /* adapt width (must take scalefactor into account) */ pStyle->width += (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2; pStyle->minwidth += pStyle->outlinewidth * 2; pStyle->maxwidth += pStyle->outlinewidth * 2; pStyle->size += (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution)); /*swap color and outlinecolor*/ tmp = pStyle->color; pStyle->color = pStyle->outlinecolor; pStyle->outlinecolor = tmp; } } /* * RFC 49 implementation: switch back the styleobj to its * original state, so the line fill will be drawn in the * second pass of the caching mechanism */ void msOutlineRenderingRestoreStyle(styleObj *pStyle, mapObj *map, layerObj *layer, imageObj *image) { colorObj tmp; if (pStyle->outlinewidth > 0) { /* reset widths to original state */ pStyle->width -= (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2; pStyle->minwidth -= pStyle->outlinewidth * 2; pStyle->maxwidth -= pStyle->outlinewidth * 2; pStyle->size -= (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution)); /*reswap colors to original state*/ tmp = pStyle->color; pStyle->color = pStyle->outlinecolor; pStyle->outlinecolor = tmp; } } mapserver-7.4.3/mapresample.c000066400000000000000000002051711357574274700162360ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Assorted code related to resampling rasters. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include #include "mapresample.h" #include "mapthread.h" #define SKIP_MASK(x,y) (mask_rb && !*(mask_rb->data.rgba.a+(y)*mask_rb->data.rgba.row_step+(x)*mask_rb->data.rgba.pixel_step)) /************************************************************************/ /* InvGeoTransform() */ /* */ /* Invert a standard 3x2 "GeoTransform" style matrix with an */ /* implicit [1 0 0] final row. */ /************************************************************************/ int InvGeoTransform( double *gt_in, double *gt_out ) { double det, inv_det; /* we assume a 3rd row that is [1 0 0] */ /* Compute determinate */ det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4]; if( fabs(det) < 0.000000000000001 ) return 0; inv_det = 1.0 / det; /* compute adjoint, and devide by determinate */ gt_out[1] = gt_in[5] * inv_det; gt_out[4] = -gt_in[4] * inv_det; gt_out[2] = -gt_in[2] * inv_det; gt_out[5] = gt_in[1] * inv_det; gt_out[0] = ( gt_in[2] * gt_in[3] - gt_in[0] * gt_in[5]) * inv_det; gt_out[3] = (-gt_in[1] * gt_in[3] + gt_in[0] * gt_in[4]) * inv_det; return 1; } #if defined(USE_PROJ) && defined(USE_GDAL) /************************************************************************/ /* msNearestRasterResample() */ /************************************************************************/ static int msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, imageObj *psDstImage, rasterBufferObj *dst_rb, int *panCMap, SimpleTransformer pfnTransform, void *pCBData, int debug, rasterBufferObj *mask_rb, int bWrapAtLeftRight ) { double *x, *y; int nDstX, nDstY; int *panSuccess; int nDstXSize = psDstImage->width; int nDstYSize = psDstImage->height; int nSrcXSize = psSrcImage->width; int nSrcYSize = psSrcImage->height; int nFailedPoints = 0, nSetPoints = 0; assert(!MS_RENDERER_PLUGIN(psSrcImage->format) || src_rb->type == MS_BUFFER_BYTE_RGBA); x = (double *) msSmallMalloc( sizeof(double) * nDstXSize ); y = (double *) msSmallMalloc( sizeof(double) * nDstXSize ); panSuccess = (int *) msSmallMalloc( sizeof(int) * nDstXSize ); for( nDstY = 0; nDstY < nDstYSize; nDstY++ ) { for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { x[nDstX] = nDstX + 0.5; y[nDstX] = nDstY + 0.5; } pfnTransform( pCBData, nDstXSize, x, y, panSuccess ); for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { int nSrcX, nSrcY; if(SKIP_MASK(nDstX,nDstY)) continue; if( !panSuccess[nDstX] ) { nFailedPoints++; continue; } nSrcX = (int) x[nDstX]; nSrcY = (int) y[nDstX]; if( bWrapAtLeftRight && nSrcX >= nSrcXSize && nSrcX < 2 * nSrcXSize ) nSrcX -= nSrcXSize; /* * We test the original floating point values to * avoid errors related to asymmetric rounding around zero. * (Also note bug #3120 regarding nearly redundent x/y < 0 checks). */ if( x[nDstX] < 0.0 || y[nDstX] < 0.0 || nSrcX < 0 || nSrcY < 0 || nSrcX >= nSrcXSize || nSrcY >= nSrcYSize ) { continue; } if( MS_RENDERER_PLUGIN(psSrcImage->format) ) { int src_rb_off; rgbaArrayObj *src,*dst; assert( src_rb->type == MS_BUFFER_BYTE_RGBA ); src = &src_rb->data.rgba; dst = &dst_rb->data.rgba; assert( src_rb && dst_rb ); src_rb_off = nSrcX * src->pixel_step + nSrcY * src->row_step; if( src->a == NULL || src->a[src_rb_off] == 255 ) { int dst_rb_off; dst_rb_off = nDstX * dst->pixel_step + nDstY * dst->row_step; nSetPoints++; dst->r[dst_rb_off] = src->r[src_rb_off]; dst->g[dst_rb_off] = src->g[src_rb_off]; dst->b[dst_rb_off] = src->b[src_rb_off]; if( dst->a ) dst->a[dst_rb_off] = 255; } else if( src->a[src_rb_off] != 0 ) { int dst_rb_off; dst_rb_off = nDstX * dst->pixel_step + nDstY * dst->row_step; nSetPoints++; /* actual alpha blending is required */ msAlphaBlendPM( src->r[src_rb_off], src->g[src_rb_off], src->b[src_rb_off], src->a[src_rb_off], dst->r + dst_rb_off, dst->g + dst_rb_off, dst->b + dst_rb_off, dst->a ? dst->a + dst_rb_off : NULL ); } } else if( MS_RENDERER_RAWDATA(psSrcImage->format) ) { int band, src_off, dst_off; src_off = nSrcX + nSrcY * psSrcImage->width; if( !MS_GET_BIT(psSrcImage->img_mask,src_off) ) continue; nSetPoints++; dst_off = nDstX + nDstY * psDstImage->width; MS_SET_BIT(psDstImage->img_mask,dst_off); for( band = 0; band < psSrcImage->format->bands; band++ ) { if( psSrcImage->format->imagemode == MS_IMAGEMODE_INT16 ) { psDstImage->img.raw_16bit[dst_off] = psSrcImage->img.raw_16bit[src_off]; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_FLOAT32) { psDstImage->img.raw_float[dst_off] = psSrcImage->img.raw_float[src_off]; } else if(psSrcImage->format->imagemode == MS_IMAGEMODE_BYTE) { psDstImage->img.raw_byte[dst_off] = psSrcImage->img.raw_byte[src_off]; } else { assert( 0 ); } src_off += psSrcImage->width * psSrcImage->height; dst_off += psDstImage->width * psDstImage->height; } } } } free( panSuccess ); free( x ); free( y ); /* -------------------------------------------------------------------- */ /* Some debugging output. */ /* -------------------------------------------------------------------- */ if( nFailedPoints > 0 && debug ) { msDebug( "msNearestRasterResampler: " "%d failed to transform, %d actually set.\n", nFailedPoints, nSetPoints ); } return 0; } /************************************************************************/ /* msSourceSample() */ /************************************************************************/ static void msSourceSample( imageObj *psSrcImage, rasterBufferObj *rb, int iSrcX, int iSrcY, double *padfPixelSum, double dfWeight, double *pdfWeightSum ) { if( MS_RENDERER_PLUGIN(psSrcImage->format) ) { rgbaArrayObj *rgba; int rb_off; assert(rb && rb->type == MS_BUFFER_BYTE_RGBA); rgba = &(rb->data.rgba); rb_off = iSrcX * rgba->pixel_step + iSrcY * rgba->row_step; if( rgba->a == NULL || rgba->a[rb_off] > 1 ) { padfPixelSum[0] += rgba->r[rb_off] * dfWeight; padfPixelSum[1] += rgba->g[rb_off] * dfWeight; padfPixelSum[2] += rgba->b[rb_off] * dfWeight; if( rgba->a == NULL ) *pdfWeightSum += dfWeight; else *pdfWeightSum += dfWeight * (rgba->a[rb_off] / 255.0); } } else if( MS_RENDERER_RAWDATA(psSrcImage->format) ) { int band; int src_off; src_off = iSrcX + iSrcY * psSrcImage->width; if( !MS_GET_BIT(psSrcImage->img_mask,src_off) ) return; for( band = 0; band < psSrcImage->format->bands; band++ ) { if( psSrcImage->format->imagemode == MS_IMAGEMODE_INT16 ) { int nValue; nValue = psSrcImage->img.raw_16bit[src_off]; padfPixelSum[band] += dfWeight * nValue; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_FLOAT32) { float fValue; fValue = psSrcImage->img.raw_float[src_off]; padfPixelSum[band] += fValue * dfWeight; } else if(psSrcImage->format->imagemode == MS_IMAGEMODE_BYTE) { int nValue; nValue = psSrcImage->img.raw_byte[src_off]; padfPixelSum[band] += nValue * dfWeight; } else { assert( 0 ); return; } src_off += psSrcImage->width * psSrcImage->height; } *pdfWeightSum += dfWeight; } } /************************************************************************/ /* msBilinearRasterResample() */ /************************************************************************/ static int msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, imageObj *psDstImage, rasterBufferObj *dst_rb, int *panCMap, SimpleTransformer pfnTransform, void *pCBData, int debug, rasterBufferObj *mask_rb, int bWrapAtLeftRight ) { double *x, *y; int nDstX, nDstY, i; int *panSuccess; int nDstXSize = psDstImage->width; int nDstYSize = psDstImage->height; int nSrcXSize = psSrcImage->width; int nSrcYSize = psSrcImage->height; int nFailedPoints = 0, nSetPoints = 0; double *padfPixelSum; int bandCount = MS_MAX(4,psSrcImage->format->bands); padfPixelSum = (double *) msSmallMalloc(sizeof(double) * bandCount); x = (double *) msSmallMalloc( sizeof(double) * nDstXSize ); y = (double *) msSmallMalloc( sizeof(double) * nDstXSize ); panSuccess = (int *) msSmallMalloc( sizeof(int) * nDstXSize ); for( nDstY = 0; nDstY < nDstYSize; nDstY++ ) { for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { x[nDstX] = nDstX + 0.5; y[nDstX] = nDstY + 0.5; } pfnTransform( pCBData, nDstXSize, x, y, panSuccess ); for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { int nSrcX, nSrcY, nSrcX2, nSrcY2; double dfRatioX2, dfRatioY2, dfWeightSum = 0.0; if(SKIP_MASK(nDstX,nDstY)) continue; if( !panSuccess[nDstX] ) { nFailedPoints++; continue; } /* ** Offset to treat TL pixel corners as pixel location instead ** of the center. */ x[nDstX] -= 0.5; y[nDstX] -= 0.5; nSrcX = (int) floor(x[nDstX]); nSrcY = (int) floor(y[nDstX]); nSrcX2 = nSrcX+1; nSrcY2 = nSrcY+1; dfRatioX2 = x[nDstX] - nSrcX; dfRatioY2 = y[nDstX] - nSrcY; /* If we are right off the source, skip this pixel */ if( nSrcX2 < 0 || (!bWrapAtLeftRight && nSrcX >= nSrcXSize) || nSrcY2 < 0 || nSrcY >= nSrcYSize ) continue; /* Trim in stuff one pixel off the edge */ nSrcX = MS_MAX(nSrcX,0); nSrcY = MS_MAX(nSrcY,0); if( !bWrapAtLeftRight ) nSrcX2 = MS_MIN(nSrcX2,nSrcXSize-1); nSrcY2 = MS_MIN(nSrcY2,nSrcYSize-1); memset( padfPixelSum, 0, sizeof(double) * bandCount); msSourceSample( psSrcImage, src_rb, nSrcX % nSrcXSize, nSrcY, padfPixelSum, (1.0 - dfRatioX2) * (1.0 - dfRatioY2), &dfWeightSum ); msSourceSample( psSrcImage, src_rb, nSrcX2 % nSrcXSize, nSrcY, padfPixelSum, (dfRatioX2) * (1.0 - dfRatioY2), &dfWeightSum ); msSourceSample( psSrcImage, src_rb, nSrcX % nSrcXSize, nSrcY2, padfPixelSum, (1.0 - dfRatioX2) * (dfRatioY2), &dfWeightSum ); msSourceSample( psSrcImage, src_rb, nSrcX2 % nSrcXSize, nSrcY2, padfPixelSum, (dfRatioX2) * (dfRatioY2), &dfWeightSum ); if( dfWeightSum == 0.0 ) continue; if( MS_RENDERER_PLUGIN(psSrcImage->format) ) { assert(src_rb && dst_rb); assert( src_rb->type == MS_BUFFER_BYTE_RGBA ); assert( src_rb->type == dst_rb->type ); nSetPoints++; if( dfWeightSum > 0.001 ) { int dst_rb_off = nDstX * dst_rb->data.rgba.pixel_step + nDstY * dst_rb->data.rgba.row_step; unsigned char red, green, blue, alpha; red = (unsigned char) MS_MAX(0,MS_MIN(255,padfPixelSum[0])); green = (unsigned char) MS_MAX(0,MS_MIN(255,padfPixelSum[1])); blue = (unsigned char) MS_MAX(0,MS_MIN(255,padfPixelSum[2])); alpha = (unsigned char)MS_MAX(0,MS_MIN(255,255.5*dfWeightSum)); msAlphaBlendPM( red, green, blue, alpha, dst_rb->data.rgba.r + dst_rb_off, dst_rb->data.rgba.g + dst_rb_off, dst_rb->data.rgba.b + dst_rb_off, (dst_rb->data.rgba.a == NULL) ? NULL : dst_rb->data.rgba.a + dst_rb_off ); } } else if( MS_RENDERER_RAWDATA(psSrcImage->format) ) { int band; int dst_off = nDstX + nDstY * psDstImage->width; for( i = 0; i < bandCount; i++ ) padfPixelSum[i] /= dfWeightSum; MS_SET_BIT(psDstImage->img_mask,dst_off); for( band = 0; band < psSrcImage->format->bands; band++ ) { if( psSrcImage->format->imagemode == MS_IMAGEMODE_INT16 ) { psDstImage->img.raw_16bit[dst_off] = (short) padfPixelSum[band]; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_FLOAT32) { psDstImage->img.raw_float[dst_off] = (float) padfPixelSum[band]; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_BYTE ) { psDstImage->img.raw_byte[dst_off] = (unsigned char)MS_MAX(0,MS_MIN(255,padfPixelSum[band])); } dst_off += psDstImage->width*psDstImage->height; } } } } free( padfPixelSum ); free( panSuccess ); free( x ); free( y ); /* -------------------------------------------------------------------- */ /* Some debugging output. */ /* -------------------------------------------------------------------- */ if( nFailedPoints > 0 && debug ) { msDebug( "msBilinearRasterResampler: " "%d failed to transform, %d actually set.\n", nFailedPoints, nSetPoints ); } return 0; } /************************************************************************/ /* msAverageSample() */ /************************************************************************/ static int msAverageSample( imageObj *psSrcImage, rasterBufferObj *src_rb, double dfXMin, double dfYMin, double dfXMax, double dfYMax, double *padfPixelSum, double *pdfAlpha01 ) { int nXMin, nXMax, nYMin, nYMax, iX, iY; double dfWeightSum = 0.0; double dfMaxWeight = 0.0; nXMin = (int) dfXMin; nYMin = (int) dfYMin; nXMax = (int) ceil(dfXMax); nYMax = (int) ceil(dfYMax); *pdfAlpha01 = 0.0; for( iY = nYMin; iY < nYMax; iY++ ) { double dfYCellMin, dfYCellMax; dfYCellMin = MS_MAX(iY,dfYMin); dfYCellMax = MS_MIN(iY+1,dfYMax); for( iX = nXMin; iX < nXMax; iX++ ) { double dfXCellMin, dfXCellMax, dfWeight; dfXCellMin = MS_MAX(iX,dfXMin); dfXCellMax = MS_MIN(iX+1,dfXMax); dfWeight = (dfXCellMax-dfXCellMin) * (dfYCellMax-dfYCellMin); msSourceSample( psSrcImage, src_rb, iX, iY, padfPixelSum, dfWeight, &dfWeightSum ); dfMaxWeight += dfWeight; } } if( dfWeightSum == 0.0 ) return MS_FALSE; for( iX = 0; iX < 4; iX++ ) padfPixelSum[iX] /= dfWeightSum; *pdfAlpha01 = dfWeightSum / dfMaxWeight; return MS_TRUE; } /************************************************************************/ /* msAverageRasterResample() */ /************************************************************************/ static int msAverageRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb, imageObj *psDstImage, rasterBufferObj *dst_rb, int *panCMap, SimpleTransformer pfnTransform, void *pCBData, int debug, rasterBufferObj *mask_rb ) { double *x1, *y1, *x2, *y2; int nDstX, nDstY; int *panSuccess1, *panSuccess2; int nDstXSize = psDstImage->width; int nDstYSize = psDstImage->height; int nFailedPoints = 0, nSetPoints = 0; double *padfPixelSum; int bandCount = MS_MAX(4,psSrcImage->format->bands); padfPixelSum = (double *) msSmallMalloc(sizeof(double) * bandCount); x1 = (double *) msSmallMalloc( sizeof(double) * (nDstXSize+1) ); y1 = (double *) msSmallMalloc( sizeof(double) * (nDstXSize+1) ); x2 = (double *) msSmallMalloc( sizeof(double) * (nDstXSize+1) ); y2 = (double *) msSmallMalloc( sizeof(double) * (nDstXSize+1) ); panSuccess1 = (int *) msSmallMalloc( sizeof(int) * (nDstXSize+1) ); panSuccess2 = (int *) msSmallMalloc( sizeof(int) * (nDstXSize+1) ); for( nDstY = 0; nDstY < nDstYSize; nDstY++ ) { for( nDstX = 0; nDstX <= nDstXSize; nDstX++ ) { x1[nDstX] = nDstX; y1[nDstX] = nDstY; x2[nDstX] = nDstX; y2[nDstX] = nDstY+1; } pfnTransform( pCBData, nDstXSize+1, x1, y1, panSuccess1 ); pfnTransform( pCBData, nDstXSize+1, x2, y2, panSuccess2 ); for( nDstX = 0; nDstX < nDstXSize; nDstX++ ) { double dfXMin, dfYMin, dfXMax, dfYMax; double dfAlpha01; if(SKIP_MASK(nDstX,nDstY)) continue; /* Do not generate a pixel unless all four corners transformed */ if( !panSuccess1[nDstX] || !panSuccess1[nDstX+1] || !panSuccess2[nDstX] || !panSuccess2[nDstX+1] ) { nFailedPoints++; continue; } dfXMin = MS_MIN(MS_MIN(x1[nDstX],x1[nDstX+1]), MS_MIN(x2[nDstX],x2[nDstX+1])); dfYMin = MS_MIN(MS_MIN(y1[nDstX],y1[nDstX+1]), MS_MIN(y2[nDstX],y2[nDstX+1])); dfXMax = MS_MAX(MS_MAX(x1[nDstX],x1[nDstX+1]), MS_MAX(x2[nDstX],x2[nDstX+1])); dfYMax = MS_MAX(MS_MAX(y1[nDstX],y1[nDstX+1]), MS_MAX(y2[nDstX],y2[nDstX+1])); dfXMin = MS_MIN(MS_MAX(dfXMin,0),psSrcImage->width+1); dfYMin = MS_MIN(MS_MAX(dfYMin,0),psSrcImage->height+1); dfXMax = MS_MIN(MS_MAX(-1,dfXMax),psSrcImage->width); dfYMax = MS_MIN(MS_MAX(-1,dfYMax),psSrcImage->height); memset( padfPixelSum, 0, sizeof(double)*bandCount ); if( !msAverageSample( psSrcImage, src_rb, dfXMin, dfYMin, dfXMax, dfYMax, padfPixelSum, &dfAlpha01 ) ) continue; if( MS_RENDERER_PLUGIN(psSrcImage->format) ) { assert(dst_rb && src_rb); assert( dst_rb->type == MS_BUFFER_BYTE_RGBA ); assert( src_rb->type == dst_rb ->type ); nSetPoints++; if( dfAlpha01 > 0 ) { unsigned char red, green, blue, alpha; red = (unsigned char) MS_MAX(0,MS_MIN(255,padfPixelSum[0]+0.5)); green = (unsigned char) MS_MAX(0,MS_MIN(255,padfPixelSum[1]+0.5)); blue = (unsigned char) MS_MAX(0,MS_MIN(255,padfPixelSum[2]+0.5)); alpha = (unsigned char) MS_MAX(0,MS_MIN(255,255*dfAlpha01+0.5)); RB_MIX_PIXEL(dst_rb,nDstX,nDstY, red, green, blue, alpha ); } } else if( MS_RENDERER_RAWDATA(psSrcImage->format) ) { int band; int dst_off = nDstX + nDstY * psDstImage->width; MS_SET_BIT(psDstImage->img_mask,dst_off); for( band = 0; band < psSrcImage->format->bands; band++ ) { if( psSrcImage->format->imagemode == MS_IMAGEMODE_INT16 ) { psDstImage->img.raw_16bit[dst_off] = (short) (padfPixelSum[band]+0.5); } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_FLOAT32) { psDstImage->img.raw_float[dst_off] = (float) padfPixelSum[band]; } else if( psSrcImage->format->imagemode == MS_IMAGEMODE_BYTE ) { psDstImage->img.raw_byte[dst_off] = (unsigned char) padfPixelSum[band]; } dst_off += psDstImage->width * psDstImage->height; } } } } free( padfPixelSum ); free( panSuccess1 ); free( x1 ); free( y1 ); free( panSuccess2 ); free( x2 ); free( y2 ); /* -------------------------------------------------------------------- */ /* Some debugging output. */ /* -------------------------------------------------------------------- */ if( nFailedPoints > 0 && debug ) { msDebug( "msAverageRasterResampler: " "%d failed to transform, %d actually set.\n", nFailedPoints, nSetPoints ); } return 0; } /************************************************************************/ /* ==================================================================== */ /* PROJ.4 based transformer. */ /* ==================================================================== */ /************************************************************************/ typedef struct { projectionObj *psSrcProjObj; projPJ psSrcProj; int bSrcIsGeographic; double adfInvSrcGeoTransform[6]; projectionObj *psDstProjObj; projPJ psDstProj; int bDstIsGeographic; double adfDstGeoTransform[6]; int bUseProj; } msProjTransformInfo; /************************************************************************/ /* msInitProjTransformer() */ /************************************************************************/ void *msInitProjTransformer( projectionObj *psSrc, double *padfSrcGeoTransform, projectionObj *psDst, double *padfDstGeoTransform ) { msProjTransformInfo *psPTInfo; psPTInfo = (msProjTransformInfo *) msSmallCalloc(1,sizeof(msProjTransformInfo)); /* -------------------------------------------------------------------- */ /* We won't even use PROJ.4 if either coordinate system is */ /* NULL. */ /* -------------------------------------------------------------------- */ psPTInfo->bUseProj = (psSrc->proj != NULL && psDst->proj != NULL && msProjectionsDiffer( psSrc, psDst ) ); /* -------------------------------------------------------------------- */ /* Record source image information. We invert the source */ /* transformation for more convenient inverse application in */ /* the transformer. */ /* -------------------------------------------------------------------- */ psPTInfo->psSrcProj = psSrc->proj; if( psPTInfo->bUseProj ) psPTInfo->bSrcIsGeographic = pj_is_latlong(psSrc->proj); else psPTInfo->bSrcIsGeographic = MS_FALSE; if( !InvGeoTransform(padfSrcGeoTransform, psPTInfo->adfInvSrcGeoTransform) ) { free(psPTInfo); return NULL; } /* -------------------------------------------------------------------- */ /* Record destination image information. */ /* -------------------------------------------------------------------- */ psPTInfo->psDstProj = psDst->proj; if( psPTInfo->bUseProj ) psPTInfo->bDstIsGeographic = pj_is_latlong(psDst->proj); else psPTInfo->bDstIsGeographic = MS_FALSE; memcpy( psPTInfo->adfDstGeoTransform, padfDstGeoTransform, sizeof(double) * 6 ); return psPTInfo; } /************************************************************************/ /* msFreeProjTransformer() */ /************************************************************************/ void msFreeProjTransformer( void * pCBData ) { free( pCBData ); } /************************************************************************/ /* msProjTransformer */ /************************************************************************/ int msProjTransformer( void *pCBData, int nPoints, double *x, double *y, int *panSuccess ) { int i; msProjTransformInfo *psPTInfo = (msProjTransformInfo*) pCBData; double x_out; /* -------------------------------------------------------------------- */ /* Transform into destination georeferenced space. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nPoints; i++ ) { x_out = psPTInfo->adfDstGeoTransform[0] + psPTInfo->adfDstGeoTransform[1] * x[i] + psPTInfo->adfDstGeoTransform[2] * y[i]; y[i] = psPTInfo->adfDstGeoTransform[3] + psPTInfo->adfDstGeoTransform[4] * x[i] + psPTInfo->adfDstGeoTransform[5] * y[i]; x[i] = x_out; panSuccess[i] = 1; } /* -------------------------------------------------------------------- */ /* Transform from degrees to radians if geographic. */ /* -------------------------------------------------------------------- */ if( psPTInfo->bDstIsGeographic ) { for( i = 0; i < nPoints; i++ ) { x[i] = x[i] * DEG_TO_RAD; y[i] = y[i] * DEG_TO_RAD; } } /* -------------------------------------------------------------------- */ /* Transform back to source projection space. */ /* -------------------------------------------------------------------- */ if( psPTInfo->bUseProj ) { double *z; int tr_result; z = (double *) msSmallCalloc(sizeof(double),nPoints); msAcquireLock( TLOCK_PROJ ); tr_result = pj_transform( psPTInfo->psDstProj, psPTInfo->psSrcProj, nPoints, 1, x, y, z); msReleaseLock( TLOCK_PROJ ); if( tr_result != 0 ) { free( z ); for( i = 0; i < nPoints; i++ ) panSuccess[i] = 0; return MS_FALSE; } free( z ); for( i = 0; i < nPoints; i++ ) { if( x[i] == HUGE_VAL || y[i] == HUGE_VAL ) panSuccess[i] = 0; } } /* -------------------------------------------------------------------- */ /* Transform back to degrees if source is geographic. */ /* -------------------------------------------------------------------- */ if( psPTInfo->bSrcIsGeographic ) { for( i = 0; i < nPoints; i++ ) { if( panSuccess[i] ) { x[i] = x[i] * RAD_TO_DEG; y[i] = y[i] * RAD_TO_DEG; } } } /* -------------------------------------------------------------------- */ /* Transform to source raster space. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nPoints; i++ ) { if( panSuccess[i] ) { x_out = psPTInfo->adfInvSrcGeoTransform[0] + psPTInfo->adfInvSrcGeoTransform[1] * x[i] + psPTInfo->adfInvSrcGeoTransform[2] * y[i]; y[i] = psPTInfo->adfInvSrcGeoTransform[3] + psPTInfo->adfInvSrcGeoTransform[4] * x[i] + psPTInfo->adfInvSrcGeoTransform[5] * y[i]; x[i] = x_out; } else { x[i] = -1; y[i] = -1; } } return 1; } /************************************************************************/ /* ==================================================================== */ /* Approximate transformer. */ /* ==================================================================== */ /************************************************************************/ typedef struct { SimpleTransformer pfnBaseTransformer; void *pBaseCBData; double dfMaxError; } msApproxTransformInfo; /************************************************************************/ /* msInitApproxTransformer() */ /************************************************************************/ static void *msInitApproxTransformer( SimpleTransformer pfnBaseTransformer, void *pBaseCBData, double dfMaxError ) { msApproxTransformInfo *psATInfo; psATInfo = (msApproxTransformInfo *) msSmallMalloc(sizeof(msApproxTransformInfo)); psATInfo->pfnBaseTransformer = pfnBaseTransformer; psATInfo->pBaseCBData = pBaseCBData; psATInfo->dfMaxError = dfMaxError; return psATInfo; } /************************************************************************/ /* msFreeApproxTransformer() */ /************************************************************************/ static void msFreeApproxTransformer( void * pCBData ) { free( pCBData ); } /************************************************************************/ /* msApproxTransformer */ /************************************************************************/ static int msApproxTransformer( void *pCBData, int nPoints, double *x, double *y, int *panSuccess ) { msApproxTransformInfo *psATInfo = (msApproxTransformInfo *) pCBData; double x2[3], y2[3], dfDeltaX, dfDeltaY, dfError, dfDist; int nMiddle, anSuccess2[3], i, bSuccess; nMiddle = (nPoints-1)/2; /* -------------------------------------------------------------------- */ /* Bail if our preconditions are not met, or if error is not */ /* acceptable. */ /* -------------------------------------------------------------------- */ if( y[0] != y[nPoints-1] || y[0] != y[nMiddle] || x[0] == x[nPoints-1] || x[0] == x[nMiddle] || psATInfo->dfMaxError == 0.0 || nPoints <= 5 ) { return psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, nPoints, x, y, panSuccess ); } /* -------------------------------------------------------------------- */ /* Transform first, last and middle point. */ /* -------------------------------------------------------------------- */ x2[0] = x[0]; y2[0] = y[0]; x2[1] = x[nMiddle]; y2[1] = y[nMiddle]; x2[2] = x[nPoints-1]; y2[2] = y[nPoints-1]; bSuccess = psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, 3, x2, y2, anSuccess2 ); if( !bSuccess || !anSuccess2[0] || !anSuccess2[1] || !anSuccess2[2] ) return psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, nPoints, x, y, panSuccess ); /* -------------------------------------------------------------------- */ /* Is the error at the middle acceptable relative to an */ /* interpolation of the middle position? */ /* -------------------------------------------------------------------- */ dfDeltaX = (x2[2] - x2[0]) / (x[nPoints-1] - x[0]); dfDeltaY = (y2[2] - y2[0]) / (x[nPoints-1] - x[0]); dfError = fabs((x2[0] + dfDeltaX * (x[nMiddle] - x[0])) - x2[1]) + fabs((y2[0] + dfDeltaY * (x[nMiddle] - x[0])) - y2[1]); if( dfError > psATInfo->dfMaxError ) { bSuccess = msApproxTransformer( psATInfo, nMiddle, x, y, panSuccess ); if( !bSuccess ) { return psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, nPoints, x, y, panSuccess ); } bSuccess = msApproxTransformer( psATInfo, nPoints - nMiddle, x+nMiddle, y+nMiddle, panSuccess+nMiddle ); if( !bSuccess ) { return psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, nPoints, x, y, panSuccess ); } return 1; } /* -------------------------------------------------------------------- */ /* Error is OK, linearly interpolate all points along line. */ /* -------------------------------------------------------------------- */ for( i = nPoints-1; i >= 0; i-- ) { dfDist = (x[i] - x[0]); y[i] = y2[0] + dfDeltaY * dfDist; x[i] = x2[0] + dfDeltaX * dfDist; panSuccess[i] = 1; } return 1; } /************************************************************************/ /* msTransformMapToSource() */ /* */ /* Compute the extents of the current map view if transformed */ /* onto the source raster. */ /************************************************************************/ static int msTransformMapToSource( int nDstXSize, int nDstYSize, double * adfDstGeoTransform, projectionObj *psDstProj, int nSrcXSize, int nSrcYSize, double * adfInvSrcGeoTransform, projectionObj *psSrcProj, rectObj *psSrcExtent, int bUseGrid ) { int nFailures = 0; #define EDGE_STEPS 10 #define MAX_SIZE ((EDGE_STEPS+1)*(EDGE_STEPS+1)) int i, nSamples = 0, bOutInit = 0; double dfRatio; double x[MAX_SIZE], y[MAX_SIZE], z[MAX_SIZE]; /* -------------------------------------------------------------------- */ /* Collect edges in map image pixel/line coordinates */ /* -------------------------------------------------------------------- */ if( !bUseGrid ) { for( dfRatio = 0.0; dfRatio <= 1.001; dfRatio += (1.0/EDGE_STEPS) ) { assert( nSamples < MAX_SIZE ); x[nSamples ] = dfRatio * nDstXSize; y[nSamples++] = 0.0; x[nSamples ] = dfRatio * nDstXSize; y[nSamples++] = nDstYSize; x[nSamples ] = 0.0; y[nSamples++] = dfRatio * nDstYSize; x[nSamples ] = nDstXSize; y[nSamples++] = dfRatio * nDstYSize; } } /* -------------------------------------------------------------------- */ /* Collect a grid in the hopes of a more accurate region. */ /* -------------------------------------------------------------------- */ else { double dfRatio2; for( dfRatio = 0.0; dfRatio <= 1.001; dfRatio += (1.0/EDGE_STEPS) ) { for( dfRatio2=0.0; dfRatio2 <= 1.001; dfRatio2 += (1.0/EDGE_STEPS)) { assert( nSamples < MAX_SIZE ); x[nSamples ] = dfRatio2 * nDstXSize; y[nSamples++] = dfRatio * nDstYSize; } } } /* -------------------------------------------------------------------- */ /* transform to map georeferenced units */ /* -------------------------------------------------------------------- */ for( i = 0; i < nSamples; i++ ) { double x_out, y_out; x_out = adfDstGeoTransform[0] + x[i] * adfDstGeoTransform[1] + y[i] * adfDstGeoTransform[2]; y_out = adfDstGeoTransform[3] + x[i] * adfDstGeoTransform[4] + y[i] * adfDstGeoTransform[5]; x[i] = x_out; y[i] = y_out; z[i] = 0.0; } /* -------------------------------------------------------------------- */ /* Transform to layer georeferenced coordinates. */ /* -------------------------------------------------------------------- */ if( psDstProj->proj && psSrcProj->proj ) { int tr_result; if( pj_is_latlong(psDstProj->proj) ) { for( i = 0; i < nSamples; i++ ) { x[i] = x[i] * DEG_TO_RAD; y[i] = y[i] * DEG_TO_RAD; } } msAcquireLock( TLOCK_PROJ ); tr_result = pj_transform( psDstProj->proj, psSrcProj->proj, nSamples, 1, x, y, z ); msReleaseLock( TLOCK_PROJ ); if( tr_result != 0 ) return MS_FALSE; if( pj_is_latlong(psSrcProj->proj) ) { for( i = 0; i < nSamples; i++ ) { if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ) { x[i] = x[i] * RAD_TO_DEG; y[i] = y[i] * RAD_TO_DEG; } } } } /* -------------------------------------------------------------------- */ /* If we just using the edges (not a grid) and we go some */ /* errors, then we need to restart using a grid pattern. */ /* -------------------------------------------------------------------- */ if( !bUseGrid ) { for( i = 0; i < nSamples; i++ ) { if( x[i] == HUGE_VAL || y[i] == HUGE_VAL ) { return msTransformMapToSource( nDstXSize, nDstYSize, adfDstGeoTransform, psDstProj, nSrcXSize, nSrcYSize, adfInvSrcGeoTransform,psSrcProj, psSrcExtent, 1 ); } } } /* -------------------------------------------------------------------- */ /* transform to layer raster coordinates, and collect bounds. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nSamples; i++ ) { double x_out, y_out; if( x[i] == HUGE_VAL || y[i] == HUGE_VAL ) { nFailures++; continue; } x_out = adfInvSrcGeoTransform[0] + x[i]*adfInvSrcGeoTransform[1] + y[i]*adfInvSrcGeoTransform[2]; y_out = adfInvSrcGeoTransform[3] + x[i]*adfInvSrcGeoTransform[4] + y[i]*adfInvSrcGeoTransform[5]; if( !bOutInit ) { psSrcExtent->minx = psSrcExtent->maxx = x_out; psSrcExtent->miny = psSrcExtent->maxy = y_out; bOutInit = 1; } else { psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out); psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out); psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out); psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out); } } /* -------------------------------------------------------------------- */ /* Deal with discontinuities related to lon_wrap=XXX in source */ /* projection. In that case we must check if the points at */ /* lon_wrap +/- 180deg are in the output raster. */ /* -------------------------------------------------------------------- */ if( bOutInit && pj_is_latlong(psSrcProj->proj) ) { double dfLonWrap = 0; int bHasLonWrap = msProjectHasLonWrap(psSrcProj, &dfLonWrap); if( bHasLonWrap ) { double x2[2], y2[2], z2[2]; int nCountY = 0; double dfY = 0.0; double dfXMinOut = 0.0; double dfYMinOut = 0.0; double dfXMaxOut = 0.0; double dfYMaxOut = 0.0; /* Find out average y coordinate in src projection */ for( i = 0; i < nSamples; i++ ) { if( y[i] != HUGE_VAL ) { dfY += y[i]; nCountY ++; } } dfY /= nCountY; /* Compute bounds of output raster */ for( i = 0; i < 4; i ++ ) { double dfX = adfDstGeoTransform[0] + ((i == 1 || i == 2) ? nDstXSize : 0) * adfDstGeoTransform[1] + ((i == 1 || i == 3 ) ? nDstYSize : 0) * adfDstGeoTransform[2]; double dfY = adfDstGeoTransform[3] + ((i == 1 || i == 2) ? nDstXSize : 0) * adfDstGeoTransform[4] + ((i == 1 || i == 3 ) ? nDstYSize : 0) * adfDstGeoTransform[5]; if( i == 0 || dfX < dfXMinOut ) dfXMinOut = dfX; if( i == 0 || dfY < dfYMinOut ) dfYMinOut = dfY; if( i == 0 || dfX > dfXMaxOut ) dfXMaxOut = dfX; if( i == 0 || dfY > dfYMaxOut ) dfYMaxOut = dfY; } x2[0] = dfLonWrap-180+1e-7; y2[0] = dfY; z2[0] = 0.0; x2[1] = dfLonWrap+180-1e-7; y2[1] = dfY; z2[1] = 0.0; msAcquireLock( TLOCK_PROJ ); pj_transform( psSrcProj->proj, psDstProj->proj, 2, 1, x2, y2, z2 ); msReleaseLock( TLOCK_PROJ ); if( x2[0] >= dfXMinOut && x2[0] <= dfXMaxOut && y2[0] >= dfYMinOut && y2[0] <= dfYMaxOut ) { double x_out = adfInvSrcGeoTransform[0] + (dfLonWrap-180)*adfInvSrcGeoTransform[1] + dfY*adfInvSrcGeoTransform[2]; double y_out = adfInvSrcGeoTransform[3] + (dfLonWrap-180)*adfInvSrcGeoTransform[4] + dfY*adfInvSrcGeoTransform[5]; /* Does the raster cover a whole 360 deg range ? */ if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) ) { psSrcExtent->minx = 0; psSrcExtent->maxx = nSrcXSize; } else { psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out); psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out); } psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out); psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out); } if( x2[1] >= dfXMinOut && x2[1] <= dfXMaxOut && x2[1] >= dfYMinOut && y2[1] <= dfYMaxOut ) { double x_out = adfInvSrcGeoTransform[0] + (dfLonWrap+180)*adfInvSrcGeoTransform[1] + dfY*adfInvSrcGeoTransform[2]; double y_out = adfInvSrcGeoTransform[3] + (dfLonWrap+180)*adfInvSrcGeoTransform[4] + dfY*adfInvSrcGeoTransform[5]; /* Does the raster cover a whole 360 deg range ? */ if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) ) { psSrcExtent->minx = 0; psSrcExtent->maxx = nSrcXSize; } else { psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out); psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out); } psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out); psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out); } } } if( !bOutInit ) return MS_FALSE; /* -------------------------------------------------------------------- */ /* If we had some failures, we need to expand the region to */ /* represent our very coarse sampling grid. */ /* -------------------------------------------------------------------- */ if( nFailures > 0 ) { int nGrowAmountX = (int) (psSrcExtent->maxx - psSrcExtent->minx)/EDGE_STEPS + 1; int nGrowAmountY = (int) (psSrcExtent->maxy - psSrcExtent->miny)/EDGE_STEPS + 1; psSrcExtent->minx = MS_MAX(psSrcExtent->minx - nGrowAmountX,0); psSrcExtent->miny = MS_MAX(psSrcExtent->miny - nGrowAmountY,0); psSrcExtent->maxx = MS_MIN(psSrcExtent->maxx + nGrowAmountX,nSrcXSize); psSrcExtent->maxy = MS_MIN(psSrcExtent->maxy + nGrowAmountY,nSrcYSize); } return MS_TRUE; } #endif /* def USE_PROJ */ #ifdef USE_GDAL /************************************************************************/ /* msResampleGDALToMap() */ /************************************************************************/ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, GDALDatasetH hDS ) { /* -------------------------------------------------------------------- */ /* We require PROJ.4 4.4.2 or later. Earlier versions don't */ /* have PJD_GRIDSHIFT. */ /* -------------------------------------------------------------------- */ #if !defined(PJD_GRIDSHIFT) && !defined(PJ_VERSION) msSetError(MS_PROJERR, "Projection support is not available, so msResampleGDALToMap() fails.", "msProjectRect()"); return(MS_FAILURE); #else int nSrcXSize, nSrcYSize, nDstXSize, nDstYSize; int result, bSuccess; double adfSrcGeoTransform[6], adfDstGeoTransform[6]; double adfInvSrcGeoTransform[6], dfNominalCellSize; rectObj sSrcExtent, sOrigSrcExtent; mapObj sDummyMap; imageObj *srcImage; void *pTCBData; void *pACBData; int anCMap[256]; char **papszAlteredProcessing = NULL; int nLoadImgXSize, nLoadImgYSize; double dfOversampleRatio; rasterBufferObj src_rb, *psrc_rb = NULL, *mask_rb = NULL; int bAddPixelMargin = MS_TRUE; int bWrapAtLeftRight = MS_FALSE; const char *resampleMode = CSLFetchNameValue( layer->processing, "RESAMPLE" ); if( resampleMode == NULL ) resampleMode = "NEAREST"; if(layer->mask) { int ret, maskLayerIdx; layerObj *maskLayer; maskLayerIdx = msGetLayerIndex(map,layer->mask); if(maskLayerIdx == -1) { msSetError(MS_MISCERR, "Invalid mask layer specified", "msResampleGDALToMap()"); return -1; } maskLayer = GET_LAYER(map, maskLayerIdx); mask_rb = msSmallCalloc(1,sizeof(rasterBufferObj)); ret = MS_IMAGE_RENDERER(maskLayer->maskimage)->getRasterBufferHandle(maskLayer->maskimage,mask_rb); if(ret != MS_SUCCESS) { free(mask_rb); return -1; } } /* -------------------------------------------------------------------- */ /* We will require source and destination to have a valid */ /* projection object. */ /* -------------------------------------------------------------------- */ if( map->projection.proj == NULL || layer->projection.proj == NULL ) { if( layer->debug ) msDebug( "msResampleGDALToMap(): " "Either map or layer projection is NULL, assuming compatible.\n" ); } /* -------------------------------------------------------------------- */ /* Initialize some information. */ /* -------------------------------------------------------------------- */ nDstXSize = image->width; nDstYSize = image->height; memcpy( adfDstGeoTransform, map->gt.geotransform, sizeof(double)*6 ); msGetGDALGeoTransform( hDS, map, layer, adfSrcGeoTransform ); nSrcXSize = GDALGetRasterXSize( hDS ); nSrcYSize = GDALGetRasterYSize( hDS ); InvGeoTransform( adfSrcGeoTransform, adfInvSrcGeoTransform ); /* -------------------------------------------------------------------- */ /* We need to find the extents in the source layer projection */ /* of the output requested region. We will accomplish this by */ /* collecting the extents of a region around the edge of the */ /* destination chunk. */ /* -------------------------------------------------------------------- */ if( CSLFetchBoolean( layer->processing, "LOAD_WHOLE_IMAGE", FALSE ) ) bSuccess = FALSE; else { bSuccess = msTransformMapToSource( nDstXSize, nDstYSize, adfDstGeoTransform, &(map->projection), nSrcXSize, nSrcYSize,adfInvSrcGeoTransform, &(layer->projection), &sSrcExtent, FALSE ); if (bSuccess) { /* -------------------------------------------------------------------- */ /* Repeat transformation for a rectangle interior to the output */ /* requested region. If the latter results in a more extreme y */ /* extent, then extend extents in source layer projection to */ /* southern/northing bounds and entire x extent. */ /* -------------------------------------------------------------------- */ memcpy( &sOrigSrcExtent, &sSrcExtent, sizeof(sSrcExtent) ); adfDstGeoTransform[0] = adfDstGeoTransform[0] + adfDstGeoTransform[1]; adfDstGeoTransform[3] = adfDstGeoTransform[3] + adfDstGeoTransform[5]; bSuccess = msTransformMapToSource( nDstXSize-2, nDstYSize-2, adfDstGeoTransform, &(map->projection), nSrcXSize, nSrcYSize,adfInvSrcGeoTransform, &(layer->projection), &sSrcExtent, FALSE ); /* Reset this array to its original value! */ memcpy( adfDstGeoTransform, map->gt.geotransform, sizeof(double)*6 ); if (bSuccess) { if (sSrcExtent.maxy > sOrigSrcExtent.maxy || sSrcExtent.miny < sOrigSrcExtent.miny) { msDebug( "msTransformMapToSource(): extending bounds.\n"); sOrigSrcExtent.minx = 0; sOrigSrcExtent.maxx = nSrcXSize; if (sSrcExtent.maxy > sOrigSrcExtent.maxy) sOrigSrcExtent.maxy = nSrcYSize; if (sSrcExtent.miny < sOrigSrcExtent.miny) sOrigSrcExtent.miny = 0; } } memcpy( &sSrcExtent, &sOrigSrcExtent, sizeof(sOrigSrcExtent) ); bSuccess = TRUE; } } /* -------------------------------------------------------------------- */ /* If the transformation failed, it is likely that we have such */ /* broad extents that the projection transformation failed at */ /* points around the extents. If so, we will assume we need */ /* the whole raster. This and later assumptions are likely to */ /* result in the raster being loaded at a higher resolution */ /* than really needed but should give decent results. */ /* -------------------------------------------------------------------- */ if( !bSuccess ) { if( layer->debug ) { if( CSLFetchBoolean( layer->processing, "LOAD_WHOLE_IMAGE", FALSE )) msDebug( "msResampleGDALToMap(): " "LOAD_WHOLE_IMAGE set, loading whole image.\n" ); else msDebug( "msTransformMapToSource(): " "pj_transform() failed. Out of bounds? Loading whole image.\n" ); } sSrcExtent.minx = 0; sSrcExtent.maxx = nSrcXSize; sSrcExtent.miny = 0; sSrcExtent.maxy = nSrcYSize; } /* -------------------------------------------------------------------- */ /* If requesting at the raster resolution, on pixel boundaries, */ /* and no reprojection is involved, we don't need any resampling. */ /* And if they match an integral subsampling factor, no need to */ /* add pixel margin. */ /* This optimization helps a lot when operating with mode=tile */ /* and that the underlying raster is tiled and share the same */ /* tiling scheme as the queried tile mode. */ /* -------------------------------------------------------------------- */ #define IS_ALMOST_INTEGER(x, eps) (fabs((x)-(int)((x)+0.5)) < (eps)) if( adfSrcGeoTransform[1] > 0.0 && adfSrcGeoTransform[2] == 0.0 && adfSrcGeoTransform[4] == 0.0 && adfSrcGeoTransform[5] < 0.0 && IS_ALMOST_INTEGER(sSrcExtent.minx, 0.1) && IS_ALMOST_INTEGER(sSrcExtent.miny, 0.1) && IS_ALMOST_INTEGER(sSrcExtent.maxx, 0.1) && IS_ALMOST_INTEGER(sSrcExtent.maxy, 0.1) && !msProjectionsDiffer( &(map->projection), &(layer->projection)) ) { double dfXFactor, dfYFactor; sSrcExtent.minx = (int)(sSrcExtent.minx + 0.5); sSrcExtent.miny = (int)(sSrcExtent.miny + 0.5); sSrcExtent.maxx = (int)(sSrcExtent.maxx + 0.5); sSrcExtent.maxy = (int)(sSrcExtent.maxy + 0.5); if( (int)(sSrcExtent.maxx - sSrcExtent.minx + 0.5) == nDstXSize && (int)(sSrcExtent.maxy - sSrcExtent.miny + 0.5) == nDstYSize ) { if( layer->debug ) msDebug( "msResampleGDALToMap(): Request matching raster resolution and pixel boundaries. " "No need to do resampling/reprojection.\n" ); msFree(mask_rb); return msDrawRasterLayerGDAL( map, layer, image, rb, hDS ); } dfXFactor = (sSrcExtent.maxx - sSrcExtent.minx) / nDstXSize; dfYFactor = (sSrcExtent.maxy - sSrcExtent.miny) / nDstYSize; if( IS_ALMOST_INTEGER(dfXFactor, 1e-5) && IS_ALMOST_INTEGER(dfYFactor, 1e-5) && IS_ALMOST_INTEGER(sSrcExtent.minx/dfXFactor, 0.1) && IS_ALMOST_INTEGER(sSrcExtent.miny/dfXFactor, 0.1) && IS_ALMOST_INTEGER(sSrcExtent.maxx/dfYFactor, 0.1) && IS_ALMOST_INTEGER(sSrcExtent.maxy/dfYFactor, 0.1) ) { bAddPixelMargin = MS_FALSE; if( layer->debug ) msDebug( "msResampleGDALToMap(): Request matching raster resolution " "and pixel boundaries matching an integral subsampling factor\n" ); } } /* -------------------------------------------------------------------- */ /* Project desired extents out by 2 pixels, and then strip to */ /* available data. */ /* -------------------------------------------------------------------- */ memcpy( &sOrigSrcExtent, &sSrcExtent, sizeof(sSrcExtent) ); if( bAddPixelMargin ) { sSrcExtent.minx = floor(sSrcExtent.minx-1.0); sSrcExtent.maxx = ceil (sSrcExtent.maxx+1.0); sSrcExtent.miny = floor(sSrcExtent.miny-1.0); sSrcExtent.maxy = ceil (sSrcExtent.maxy+1.0); } sSrcExtent.minx = MS_MAX(0,sSrcExtent.minx); sSrcExtent.maxx = MS_MIN(sSrcExtent.maxx, nSrcXSize ); sSrcExtent.miny = MS_MAX(sSrcExtent.miny, 0 ); sSrcExtent.maxy = MS_MIN(sSrcExtent.maxy, nSrcYSize ); if( sSrcExtent.maxx <= sSrcExtent.minx || sSrcExtent.maxy <= sSrcExtent.miny ) { if( layer->debug ) msDebug( "msResampleGDALToMap(): no overlap ... no result.\n" ); msFree(mask_rb); return 0; } /* -------------------------------------------------------------------- */ /* Determine desired oversampling ratio. Default to 2.0 if not */ /* otherwise set. */ /* -------------------------------------------------------------------- */ dfOversampleRatio = 2.0; if( CSLFetchNameValue( layer->processing, "OVERSAMPLE_RATIO" ) != NULL ) { dfOversampleRatio = atof(CSLFetchNameValue( layer->processing, "OVERSAMPLE_RATIO" )); } /* -------------------------------------------------------------------- */ /* Decide on a resolution to read from the source image at. We */ /* will operate from full resolution data, if we are requesting */ /* at near to full resolution. Otherwise we will read the data */ /* at twice the resolution of the eventual map. */ /* -------------------------------------------------------------------- */ dfNominalCellSize = sqrt(adfSrcGeoTransform[1] * adfSrcGeoTransform[1] + adfSrcGeoTransform[2] * adfSrcGeoTransform[2]); /* Check first that the requested extent is not well beyond than the source */ /* raster. This might be the case for example if asking to visualize */ /* -180,-89,180,90 in EPSG:4326 from a raster in Arctic Polar Stereographic */ /* But restrict that to rasters of modest size, otherwise we may end up */ /* requesting very large dimensions in other legit reprojection cases */ /* See https://github.com/mapserver/mapserver/issues/5402 */ if( !(sOrigSrcExtent.minx <= -4 * nSrcXSize && sOrigSrcExtent.miny <= -4 * nSrcYSize && sOrigSrcExtent.maxx >= 5 * nSrcXSize && sOrigSrcExtent.maxy >= 5 * nSrcYSize && nSrcXSize < 4000 && nSrcYSize < 4000) && (sOrigSrcExtent.maxx - sOrigSrcExtent.minx) > dfOversampleRatio * nDstXSize && !CSLFetchBoolean( layer->processing, "LOAD_FULL_RES_IMAGE", FALSE )) sDummyMap.cellsize = (dfNominalCellSize * (sOrigSrcExtent.maxx - sOrigSrcExtent.minx)) / (dfOversampleRatio * nDstXSize); else sDummyMap.cellsize = dfNominalCellSize; nLoadImgXSize = MS_MAX(1, (int) (sSrcExtent.maxx - sSrcExtent.minx) * (dfNominalCellSize / sDummyMap.cellsize)); nLoadImgYSize = MS_MAX(1, (int) (sSrcExtent.maxy - sSrcExtent.miny) * (dfNominalCellSize / sDummyMap.cellsize)); /* ** Because the previous calculation involved some round off, we need ** to fixup the cellsize to ensure the map region represents the whole ** RAW_WINDOW (at least in X). Re: bug 1715. */ sDummyMap.cellsize = ((sSrcExtent.maxx - sSrcExtent.minx) * dfNominalCellSize) / nLoadImgXSize; if( layer->debug ) msDebug( "msResampleGDALToMap in effect: cellsize = %f\n", sDummyMap.cellsize ); adfSrcGeoTransform[0] += + adfSrcGeoTransform[1] * sSrcExtent.minx + adfSrcGeoTransform[2] * sSrcExtent.miny; adfSrcGeoTransform[1] *= (sDummyMap.cellsize / dfNominalCellSize); adfSrcGeoTransform[2] *= (sDummyMap.cellsize / dfNominalCellSize); adfSrcGeoTransform[3] += + adfSrcGeoTransform[4] * sSrcExtent.minx + adfSrcGeoTransform[5] * sSrcExtent.miny; adfSrcGeoTransform[4] *= (sDummyMap.cellsize / dfNominalCellSize); adfSrcGeoTransform[5] *= (sDummyMap.cellsize / dfNominalCellSize); /* In the non-rotated case, make sure that the geotransform exactly */ /* matches the sSrcExtent, even if that generates non-square pixels (#1715) */ /* The rotated case should ideally be dealt with, but not for now... */ if( adfSrcGeoTransform[2] == 0 && adfSrcGeoTransform[4] == 0 && adfSrcGeoTransform[5] < 0 && /* But do that only if the pixels were square before, otherwise */ /* this is going to mess with source rasters whose pixels aren't at */ /* all square (#5445) */ fabs(fabs(adfSrcGeoTransform[1]) - fabs(adfSrcGeoTransform[5])) < 0.01 * fabs(adfSrcGeoTransform[1]) ) { adfSrcGeoTransform[1] = (sSrcExtent.maxx - sSrcExtent.minx) * dfNominalCellSize / nLoadImgXSize; adfSrcGeoTransform[5] = -(sSrcExtent.maxy - sSrcExtent.miny) * dfNominalCellSize / nLoadImgYSize; } papszAlteredProcessing = CSLDuplicate( layer->processing ); papszAlteredProcessing = CSLSetNameValue( papszAlteredProcessing, "RAW_WINDOW", CPLSPrintf( "%d %d %d %d", (int) sSrcExtent.minx, (int) sSrcExtent.miny, (int) (sSrcExtent.maxx-sSrcExtent.minx), (int) (sSrcExtent.maxy-sSrcExtent.miny))); /* -------------------------------------------------------------------- */ /* We clone this without referencing it knowing that the */ /* srcImage will take a reference on it. The sDummyMap is */ /* destroyed off the stack, so the missing map reference is */ /* never a problem. The image's dereference of the */ /* outputformat during the msFreeImage() calls will result in */ /* the output format being cleaned up. */ /* */ /* We make a copy so we can easily modify the outputformat used */ /* for the temporary image to include transparentency support. */ /* -------------------------------------------------------------------- */ sDummyMap.outputformat = msCloneOutputFormat( image->format ); sDummyMap.width = nLoadImgXSize; sDummyMap.height = nLoadImgYSize; sDummyMap.mappath = map->mappath; sDummyMap.shapepath = map->shapepath; /* -------------------------------------------------------------------- */ /* If we are working in 256 color GD mode, allocate 0 as the */ /* transparent color on the temporary image so it will be */ /* initialized to see-through. We pick an arbitrary rgb tuple */ /* as our transparent color, but ensure it is initalized in the */ /* map so that normal transparent avoidance will apply. */ /* -------------------------------------------------------------------- */ if( MS_RENDERER_PLUGIN(sDummyMap.outputformat) ) { assert(rb); msInitializeRendererVTable(sDummyMap.outputformat); assert( sDummyMap.outputformat->imagemode == MS_IMAGEMODE_RGB || sDummyMap.outputformat->imagemode == MS_IMAGEMODE_RGBA ); sDummyMap.outputformat->transparent = MS_TRUE; sDummyMap.outputformat->imagemode = MS_IMAGEMODE_RGBA; MS_INIT_COLOR(sDummyMap.imagecolor,-1,-1,-1,255); } /* -------------------------------------------------------------------- */ /* Setup a dummy map object we can use to read from the source */ /* raster, with the newly established extents, and resolution. */ /* -------------------------------------------------------------------- */ srcImage = msImageCreate( nLoadImgXSize, nLoadImgYSize, sDummyMap.outputformat, NULL, NULL, map->resolution, map->defresolution, &(sDummyMap.imagecolor)); if (srcImage == NULL) { msFree(mask_rb); return -1; /* msSetError() should have been called already */ } if( MS_RENDERER_PLUGIN( srcImage->format ) ) { psrc_rb = &src_rb; memset( psrc_rb, 0, sizeof(rasterBufferObj) ); if( srcImage->format->vtable->supports_pixel_buffer ) { if(UNLIKELY(MS_FAILURE == srcImage->format->vtable->getRasterBufferHandle( srcImage, psrc_rb ))) { msFree(mask_rb); return -1; } } else { if(UNLIKELY(MS_FAILURE == srcImage->format->vtable->initializeRasterBuffer(psrc_rb,nLoadImgXSize, nLoadImgYSize,MS_IMAGEMODE_RGBA))) { msFree(mask_rb); return -1; } } } /* -------------------------------------------------------------------- */ /* Draw into the temporary image. Temporarily replace the */ /* layer processing directive so that we use our RAW_WINDOW. */ /* -------------------------------------------------------------------- */ { char **papszSavedProcessing = layer->processing; char* origMask = layer->mask; layer->mask = NULL; layer->processing = papszAlteredProcessing; result = msDrawRasterLayerGDAL( &sDummyMap, layer, srcImage, psrc_rb, hDS ); layer->processing = papszSavedProcessing; layer->mask = origMask; CSLDestroy( papszAlteredProcessing ); if( result ) { if( MS_RENDERER_PLUGIN( srcImage->format ) && !srcImage->format->vtable->supports_pixel_buffer) msFreeRasterBuffer(psrc_rb); msFreeImage( srcImage ); msFree(mask_rb); return result; } } /* -------------------------------------------------------------------- */ /* Setup transformations between our source image, and the */ /* target map image. */ /* -------------------------------------------------------------------- */ pTCBData = msInitProjTransformer( &(layer->projection), adfSrcGeoTransform, &(map->projection), adfDstGeoTransform ); if( pTCBData == NULL ) { if( layer->debug ) msDebug( "msInitProjTransformer() returned NULL.\n" ); if( MS_RENDERER_PLUGIN( srcImage->format ) && !srcImage->format->vtable->supports_pixel_buffer) msFreeRasterBuffer(psrc_rb); msFreeImage( srcImage ); msFree(mask_rb); return MS_PROJERR; } /* -------------------------------------------------------------------- */ /* It is cheaper to use linear approximations as long as our */ /* error is modest (less than 0.333 pixels). */ /* -------------------------------------------------------------------- */ pACBData = msInitApproxTransformer( msProjTransformer, pTCBData, 0.333 ); if( pj_is_latlong(layer->projection.proj) ) { /* Does the raster cover a whole 360 deg range ? */ if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) ) bWrapAtLeftRight = MS_TRUE; } /* -------------------------------------------------------------------- */ /* Perform the resampling. */ /* -------------------------------------------------------------------- */ if( EQUAL(resampleMode,"AVERAGE") ) result = msAverageRasterResampler( srcImage, psrc_rb, image, rb, anCMap, msApproxTransformer, pACBData, layer->debug, mask_rb ); else if( EQUAL(resampleMode,"BILINEAR") ) result = msBilinearRasterResampler( srcImage, psrc_rb, image, rb, anCMap, msApproxTransformer, pACBData, layer->debug, mask_rb, bWrapAtLeftRight ); else result = msNearestRasterResampler( srcImage, psrc_rb, image, rb, anCMap, msApproxTransformer, pACBData, layer->debug, mask_rb, bWrapAtLeftRight ); /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ msFree(mask_rb); if( MS_RENDERER_PLUGIN( srcImage->format ) && !srcImage->format->vtable->supports_pixel_buffer) msFreeRasterBuffer(psrc_rb); msFreeImage( srcImage ); msFreeProjTransformer( pTCBData ); msFreeApproxTransformer( pACBData ); return result; #endif } #endif /* def USE_GDAL */ mapserver-7.4.3/mapresample.h000066400000000000000000000046001357574274700162350ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: CFS OGC MapServer * Purpose: Definitions related to raster resampling support. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2001, Frank Warmerdam, DM Solutions Group Inc * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef RESAMPLE_H #define RESAMPLE_H #include "mapserver.h" #include "mapproject.h" #ifdef USE_GDAL # include # include #endif typedef int (*SimpleTransformer)( void *pCBData, int nPoints, double *x, double *y, int *panSuccess ); void *msInitProjTransformer( projectionObj *psSrc, double *padfSrcGeoTransform, projectionObj *psDst, double *padfDstGeoTransform ); void msFreeProjTransformer( void * ); int msProjTransformer( void *pCBData, int nPoints, double *x, double *y, int *panSuccess ); #ifdef USE_GDAL int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, GDALDatasetH hDS ); #endif #endif /* ndef RESAMPLE_H */ mapserver-7.4.3/mapscale.c000066400000000000000000000525451357574274700155220ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Scale object rendering. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #define VMARGIN 3 /* buffer around the scalebar */ #define HMARGIN 3 #define VSPACING .8 /* spacing (% of font height) between scalebar and text */ #define VSLOP 5 /* makes things fit a bit better vertically */ /* ** Match this with with unit enumerations is mapserver.h */ static char *unitText[9]= {"in", "ft", "mi", "m", "km", "dd", "??", "??", "NM"}; /* MS_PIXEL and MS_PERCENTAGE not used */ double inchesPerUnit[9]= {1, 12, 63360.0, 39.3701, 39370.1, 4374754, 1, 1, 72913.3858 }; static double roundInterval(double d) { if(d<.001) return(MS_NINT(d*10000)/10000.0); if(d<.01) return(MS_NINT(d*1000)/1000.0); if(d<.1) return(MS_NINT(d*100)/100.0); if(d<1) return(MS_NINT(d*10)/10.0); if(d<100) return(MS_NINT(d)); if(d<1000) return(MS_NINT(d/10) * 10); if(d<10000) return(MS_NINT(d/100) * 100); if(d<100000) return(MS_NINT(d/1000) * 1000); if(d<1000000) return(MS_NINT(d/10000) * 10000); if(d<10000000) return(MS_NINT(d/100000) * 100000); if(d<100000000) return(MS_NINT(d/1000000) * 1000000); return(-1); } /* ** Calculate the approximate scale based on a few parameters. Note that this assumes the scale is ** the same in the x direction as in the y direction, so run msAdjustExtent(...) first. */ int msCalculateScale(rectObj extent, int units, int width, int height, double resolution, double *scale) { double md, gd, center_y; /* if((extent.maxx == extent.minx) || (extent.maxy == extent.miny)) */ if(!MS_VALID_EXTENT(extent)) { msSetError(MS_MISCERR, "Invalid image extent, minx=%lf, miny=%lf, maxx=%lf, maxy=%lf.", "msCalculateScale()", extent.minx, extent.miny, extent.maxx, extent.maxy); return(MS_FAILURE); } if((width <= 0) || (height <= 0)) { msSetError(MS_MISCERR, "Invalid image width or height.", "msCalculateScale()"); return(MS_FAILURE); } switch (units) { case(MS_DD): case(MS_METERS): case(MS_KILOMETERS): case(MS_MILES): case(MS_NAUTICALMILES): case(MS_INCHES): case(MS_FEET): center_y = (extent.miny+extent.maxy)/2.0; md = (width-1)/(resolution*msInchesPerUnit(units, center_y)); /* remember, we use a pixel-center to pixel-center extent, hence the width-1 */ gd = extent.maxx - extent.minx; *scale = gd/md; break; default: *scale = -1; /* this is not an error */ break; } return(MS_SUCCESS); } double msInchesPerUnit(int units, double center_lat) { double lat_adj = 1.0, ipu = 1.0; switch (units) { case(MS_METERS): case(MS_KILOMETERS): case(MS_MILES): case(MS_NAUTICALMILES): case(MS_INCHES): case(MS_FEET): ipu = inchesPerUnit[units]; break; case(MS_DD): /* With geographical (DD) coordinates, we adjust the inchesPerUnit * based on the latitude of the center of the view. For this we assume * we have a perfect sphere and just use cos(lat) in our calculation. */ #ifdef ENABLE_VARIABLE_INCHES_PER_DEGREE if (center_lat != 0.0) { double cos_lat; cos_lat = cos(MS_PI*center_lat/180.0); lat_adj = sqrt(1+cos_lat*cos_lat)/sqrt(2.0); } #endif ipu = inchesPerUnit[units]*lat_adj; break; default: break; } return ipu; } #define X_STEP_SIZE 5 imageObj *msDrawScalebar(mapObj *map) { int status; char label[32]; double i, msx; int j; int isx, sx, sy, ox, oy, state, dsx; pointObj p; rectObj r; imageObj *image = NULL; double fontWidth, fontHeight; outputFormatObj *format = NULL; strokeStyleObj strokeStyle; shapeObj shape; lineObj line; pointObj points[5]; textSymbolObj ts; rendererVTableObj *renderer; strokeStyle.patternlength=0; initTextSymbol(&ts); if(map->units == -1) { msSetError(MS_MISCERR, "Map units not set.", "msDrawScalebar()"); return(NULL); } renderer = MS_MAP_RENDERER(map); if(!renderer || !MS_MAP_RENDERER(map)->supports_pixel_buffer) { msSetError(MS_MISCERR, "Outputformat not supported for scalebar", "msDrawScalebar()"); return(NULL); } msPopulateTextSymbolForLabelAndString(&ts,&map->scalebar.label,msStrdup("0123456789"),1.0,map->resolution/map->defresolution, 0); /* * A string containing the ten decimal digits is rendered to compute an average cell size * for each number, which is used later to place labels on the scalebar. */ if(msGetTextSymbolSize(map,&ts,&r) != MS_SUCCESS) { return NULL; } fontWidth = (r.maxx-r.minx)/10.0; fontHeight = r.maxy -r.miny; map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); status = msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom); if(status != MS_SUCCESS) { return(NULL); } dsx = map->scalebar.width - 2*HMARGIN; do { msx = (map->cellsize * dsx)/(msInchesPerUnit(map->scalebar.units,0)/msInchesPerUnit(map->units,0)); i = roundInterval(msx/map->scalebar.intervals); snprintf(label, sizeof(label), "%g", map->scalebar.intervals*i); /* last label */ isx = MS_NINT((i/(msInchesPerUnit(map->units,0)/msInchesPerUnit(map->scalebar.units,0)))/map->cellsize); sx = (map->scalebar.intervals*isx) + MS_NINT((1.5 + strlen(label)/2.0 + strlen(unitText[map->scalebar.units]))*fontWidth); if(sx <= (map->scalebar.width - 2*HMARGIN)) break; /* it will fit */ dsx -= X_STEP_SIZE; /* change the desired size in hopes that it will fit in user supplied width */ } while(1); sy = (2*VMARGIN) + MS_NINT(VSPACING*fontHeight) + fontHeight + map->scalebar.height - VSLOP; /*Ensure we have an image format representing the options for the scalebar.*/ msApplyOutputFormat( &format, map->outputformat, map->scalebar.transparent, map->scalebar.interlace, MS_NOOVERRIDE ); if(map->scalebar.transparent == MS_OFF) { if(!MS_VALID_COLOR(map->scalebar.imagecolor)) MS_INIT_COLOR(map->scalebar.imagecolor,255,255,255,255); } image = msImageCreate(map->scalebar.width, sy, format, map->web.imagepath, map->web.imageurl, map->resolution, map->defresolution, &map->scalebar.imagecolor); image->map = map; /* drop this reference to output format */ msApplyOutputFormat( &format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); /* did we succeed in creating the image? */ if(!image) { msSetError(MS_MISCERR, "Unable to initialize image.", "msDrawScalebar()"); return NULL; } switch(map->scalebar.align) { case(MS_ALIGN_LEFT): ox = HMARGIN; break; case(MS_ALIGN_RIGHT): ox = MS_NINT((map->scalebar.width - sx) + fontWidth); break; default: ox = MS_NINT((map->scalebar.width - sx)/2.0 + fontWidth/2.0); /* center the computed scalebar */ } oy = VMARGIN; switch(map->scalebar.style) { case(0): { line.numpoints = 5; line.point = points; shape.line = &line; shape.numlines = 1; if(MS_VALID_COLOR(map->scalebar.color)) { INIT_STROKE_STYLE(strokeStyle); strokeStyle.color = &map->scalebar.outlinecolor; strokeStyle.color->alpha = 255; strokeStyle.width = 1; } map->scalebar.backgroundcolor.alpha = 255; map->scalebar.color.alpha = 255; state = 1; /* 1 means filled */ for(j=0; jscalebar.intervals; j++) { points[0].x = points[4].x = points[3].x = ox + j*isx + 0.5; points[0].y = points[4].y = points[1].y = oy + 0.5; points[1].x = points[2].x = ox + (j+1)*isx + 0.5; points[2].y = points[3].y = oy + map->scalebar.height + 0.5; if(state == 1 && MS_VALID_COLOR(map->scalebar.color)) status = renderer->renderPolygon(image,&shape,&map->scalebar.color); else if(MS_VALID_COLOR(map->scalebar.backgroundcolor)) status = renderer->renderPolygon(image,&shape,&map->scalebar.backgroundcolor); if(UNLIKELY(status == MS_FAILURE)) { goto scale_cleanup; } if(strokeStyle.color) { status = renderer->renderLine(image,&shape,&strokeStyle); if(UNLIKELY(status == MS_FAILURE)) { goto scale_cleanup; } } sprintf(label, "%g", j*i); map->scalebar.label.position = MS_CC; p.x = ox + j*isx; /* + MS_NINT(fontPtr->w/2); */ p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); status = msDrawLabel(map,image,p,msStrdup(label),&map->scalebar.label,1.0); if(UNLIKELY(status == MS_FAILURE)) { goto scale_cleanup; } state = -state; } sprintf(label, "%g", j*i); ox = ox + j*isx - MS_NINT((strlen(label)*fontWidth)/2.0); sprintf(label, "%g %s", j*i, unitText[map->scalebar.units]); map->scalebar.label.position = MS_CR; p.x = ox; /* + MS_NINT(fontPtr->w/2); */ p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); status = msDrawLabel(map,image,p,msStrdup(label),&map->scalebar.label,1.0); if(UNLIKELY(status == MS_FAILURE)) { goto scale_cleanup; } break; } case(1): { line.numpoints = 2; line.point = points; shape.line = &line; shape.numlines = 1; if(MS_VALID_COLOR(map->scalebar.color)) { strokeStyle.width = 1; strokeStyle.color = &map->scalebar.color; } points[0].y = points[1].y = oy; points[0].x = ox; points[1].x = ox + isx*map->scalebar.intervals; status = renderer->renderLine(image,&shape,&strokeStyle); if(UNLIKELY(status == MS_FAILURE)) { goto scale_cleanup; } points[0].y = oy; points[1].y = oy + map->scalebar.height; p.y = oy + map->scalebar.height + MS_NINT(VSPACING*fontHeight); for(j=0; j<=map->scalebar.intervals; j++) { points[0].x = points[1].x = ox + j*isx; status = renderer->renderLine(image,&shape,&strokeStyle); if(UNLIKELY(status == MS_FAILURE)) { goto scale_cleanup; } sprintf(label, "%g", j*i); if(j!=map->scalebar.intervals) { map->scalebar.label.position = MS_CC; p.x = ox + j*isx; /* + MS_NINT(fontPtr->w/2); */ } else { sprintf(label, "%g %s", j*i, unitText[map->scalebar.units]); map->scalebar.label.position = MS_CR; p.x = ox + j*isx - MS_NINT((strlen(label)*fontWidth)/2.0); } status = msDrawLabel(map,image,p,msStrdup(label),&map->scalebar.label,1.0); if(UNLIKELY(status == MS_FAILURE)) { goto scale_cleanup; } } break; } default: msSetError(MS_MISCERR, "Unsupported scalebar style.", "msDrawScalebar()"); return(NULL); } scale_cleanup: freeTextSymbol(&ts); if(UNLIKELY(status == MS_FAILURE)) { msFreeImage(image); return NULL; } return(image); } int msEmbedScalebar(mapObj *map, imageObj *img) { int l,index,s,status = MS_SUCCESS; pointObj point; imageObj *image = NULL; rendererVTableObj *renderer; symbolObj *embededSymbol; char* imageType = NULL; index = msGetSymbolIndex(&(map->symbolset), "scalebar", MS_FALSE); if(index != -1) msRemoveSymbol(&(map->symbolset), index); /* remove cached symbol in case the function is called multiple times with different zoom levels */ if((embededSymbol=msGrowSymbolSet(&map->symbolset)) == NULL) return MS_FAILURE; s = map->symbolset.numsymbols; map->symbolset.numsymbols++; if(!MS_RENDERER_PLUGIN(map->outputformat) || !MS_MAP_RENDERER(map)->supports_pixel_buffer) { imageType = msStrdup(map->imagetype); /* save format */ if MS_DRIVER_CAIRO(map->outputformat) map->outputformat = msSelectOutputFormat( map, "cairopng" ); else map->outputformat = msSelectOutputFormat( map, "png" ); msInitializeRendererVTable(map->outputformat); } renderer = MS_MAP_RENDERER(map); image = msDrawScalebar(map); if (imageType) { map->outputformat = msSelectOutputFormat( map, imageType ); /* restore format */ msFree(imageType); } if(!image) { return MS_FAILURE; } embededSymbol->pixmap_buffer = calloc(1,sizeof(rasterBufferObj)); MS_CHECK_ALLOC(embededSymbol->pixmap_buffer, sizeof(rasterBufferObj), MS_FAILURE); if(MS_SUCCESS != renderer->getRasterBufferCopy(image,embededSymbol->pixmap_buffer)) { return MS_FAILURE; } embededSymbol->type = MS_SYMBOL_PIXMAP; /* intialize a few things */ embededSymbol->name = msStrdup("scalebar"); embededSymbol->sizex = embededSymbol->pixmap_buffer->width; embededSymbol->sizey = embededSymbol->pixmap_buffer->height; if(map->scalebar.transparent) { embededSymbol->transparent = MS_TRUE; embededSymbol->transparentcolor = 0; } switch(map->scalebar.position) { case(MS_LL): point.x = MS_NINT(embededSymbol->pixmap_buffer->width/2.0) + map->scalebar.offsetx; point.y = map->height - MS_NINT(embededSymbol->pixmap_buffer->height/2.0) - map->scalebar.offsety; break; case(MS_LR): point.x = map->width - MS_NINT(embededSymbol->pixmap_buffer->width/2.0) - map->scalebar.offsetx; point.y = map->height - MS_NINT(embededSymbol->pixmap_buffer->height/2.0) - map->scalebar.offsety; break; case(MS_LC): point.x = MS_NINT(map->width/2.0) + map->scalebar.offsetx; point.y = map->height - MS_NINT(embededSymbol->pixmap_buffer->height/2.0) - map->scalebar.offsety; break; case(MS_UR): point.x = map->width - MS_NINT(embededSymbol->pixmap_buffer->width/2.0) - map->scalebar.offsetx; point.y = MS_NINT(embededSymbol->pixmap_buffer->height/2.0) + map->scalebar.offsety; break; case(MS_UL): point.x = MS_NINT(embededSymbol->pixmap_buffer->width/2.0) + map->scalebar.offsetx; point.y = MS_NINT(embededSymbol->pixmap_buffer->height/2.0) + map->scalebar.offsety; break; case(MS_UC): point.x = MS_NINT(map->width/2.0) + map->scalebar.offsetx; point.y = MS_NINT(embededSymbol->pixmap_buffer->height/2.0) + map->scalebar.offsety; break; } l = msGetLayerIndex(map, "__embed__scalebar"); if(l == -1) { if (msGrowMapLayers(map) == NULL) return(-1); l = map->numlayers; map->numlayers++; if(initLayer((GET_LAYER(map, l)), map) == -1) return(-1); GET_LAYER(map, l)->name = msStrdup("__embed__scalebar"); GET_LAYER(map, l)->type = MS_LAYER_POINT; if (msGrowLayerClasses( GET_LAYER(map, l) ) == NULL) return(-1); if(initClass(GET_LAYER(map, l)->class[0]) == -1) return(-1); GET_LAYER(map, l)->numclasses = 1; /* so we make sure to free it */ /* update the layer order list with the layer's index. */ map->layerorder[l] = l; } GET_LAYER(map, l)->status = MS_ON; if(map->scalebar.postlabelcache) { /* add it directly to the image */ if(msMaybeAllocateClassStyle(GET_LAYER(map, l)->class[0], 0)==MS_FAILURE) return MS_FAILURE; GET_LAYER(map, l)->class[0]->styles[0]->symbol = s; status = msDrawMarkerSymbol(map, img, &point, GET_LAYER(map, l)->class[0]->styles[0], 1.0); if(UNLIKELY(status == MS_FAILURE)) { goto embed_cleanup; } } else { if(!GET_LAYER(map, l)->class[0]->labels) { if(msGrowClassLabels(GET_LAYER(map, l)->class[0]) == NULL) return MS_FAILURE; initLabel(GET_LAYER(map, l)->class[0]->labels[0]); GET_LAYER(map, l)->class[0]->numlabels = 1; GET_LAYER(map, l)->class[0]->labels[0]->force = MS_TRUE; GET_LAYER(map, l)->class[0]->labels[0]->size = MS_MEDIUM; /* must set a size to have a valid label definition */ GET_LAYER(map, l)->class[0]->labels[0]->priority = MS_MAX_LABEL_PRIORITY; } if(GET_LAYER(map, l)->class[0]->labels[0]->numstyles == 0) { if(msGrowLabelStyles(GET_LAYER(map,l)->class[0]->labels[0]) == NULL) return(MS_FAILURE); GET_LAYER(map,l)->class[0]->labels[0]->numstyles = 1; initStyle(GET_LAYER(map,l)->class[0]->labels[0]->styles[0]); GET_LAYER(map,l)->class[0]->labels[0]->styles[0]->_geomtransform.type = MS_GEOMTRANSFORM_LABELPOINT; } GET_LAYER(map,l)->class[0]->labels[0]->styles[0]->symbol = s; status = msAddLabel(map, img, GET_LAYER(map, l)->class[0]->labels[0], l, 0, NULL, &point, -1, NULL); if(UNLIKELY(status == MS_FAILURE)) { goto embed_cleanup; } } embed_cleanup: /* Mark layer as deleted so that it doesn't interfere with html legends or with saving maps */ GET_LAYER(map, l)->status = MS_DELETE; msFreeImage( image ); return status; } /************************************************************************/ /* These two functions are used in PHP/Mapscript and Swig/Mapscript */ /************************************************************************/ /************************************************************************/ /* double GetDeltaExtentsUsingScale(double scale, int units, */ /* double centerLat, int width, */ /* double resolution) */ /* */ /* Utility function to return the maximum extent using the */ /* scale and the width of the image. */ /* */ /* Base on the function msCalculateScale (mapscale.c) */ /************************************************************************/ double GetDeltaExtentsUsingScale(double scale, int units, double centerLat, int width, double resolution) { double md = 0.0; double dfDelta = -1.0; if (scale <= 0 || width <=0) return -1; switch (units) { case(MS_DD): case(MS_METERS): case(MS_KILOMETERS): case(MS_MILES): case(MS_NAUTICALMILES): case(MS_INCHES): case(MS_FEET): /* remember, we use a pixel-center to pixel-center extent, hence the width-1 */ md = (width-1)/(resolution*msInchesPerUnit(units,centerLat)); dfDelta = md * scale; break; default: break; } return dfDelta; } /************************************************************************/ /* static double Pix2Georef(int nPixPos, int nPixMin, double nPixMax,*/ /* double dfGeoMin, double dfGeoMax, */ /* bool bULisYOrig) */ /* */ /* Utility function to convert a pixel pos to georef pos. If */ /* bULisYOrig parameter is set to true then the upper left is */ /* considered to be the Y origin. */ /* */ /************************************************************************/ double Pix2Georef(int nPixPos, int nPixMin, int nPixMax, double dfGeoMin, double dfGeoMax, int bULisYOrig) { double dfWidthGeo = 0.0; int nWidthPix = 0; double dfPixToGeo = 0.0; double dfPosGeo = 0.0; double dfDeltaGeo = 0.0; int nDeltaPix = 0; dfWidthGeo = dfGeoMax - dfGeoMin; nWidthPix = nPixMax - nPixMin; if (dfWidthGeo > 0.0 && nWidthPix > 0) { dfPixToGeo = dfWidthGeo / (double)nWidthPix; if (!bULisYOrig) nDeltaPix = nPixPos - nPixMin; else nDeltaPix = nPixMax - nPixPos; dfDeltaGeo = nDeltaPix * dfPixToGeo; dfPosGeo = dfGeoMin + dfDeltaGeo; } return (dfPosGeo); } /* This function converts a pixel value in geo ref. The return value is in * layer units. This function has been added for the purpose of the ticket #1340 */ double Pix2LayerGeoref(mapObj *map, layerObj *layer, int value) { double cellsize = MS_MAX(MS_CELLSIZE(map->extent.minx, map->extent.maxx, map->width), MS_CELLSIZE(map->extent.miny, map->extent.maxy, map->height)); double resolutionFactor = map->resolution/map->defresolution; double unitsFactor = 1; if (layer->sizeunits != MS_PIXELS) unitsFactor = msInchesPerUnit(map->units,0)/msInchesPerUnit(layer->sizeunits,0); return value*cellsize*resolutionFactor*unitsFactor; } mapserver-7.4.3/mapscript/000077500000000000000000000000001357574274700155605ustar00rootroot00000000000000mapserver-7.4.3/mapscript/README.rst000066400000000000000000000041631357574274700172530ustar00rootroot00000000000000MapServer MapScript Modules =========================== Much of MapServer's functionality is accessible from Java, Perl, PHP, Python, Ruby, C#, and Tcl. MapScript is not a language like JavaScript or Python. It is a loadable module that brings MapServer capabilities to your favorite high level programming language. PHP and SWIG Branches of MapScript ---------------------------------- The MapScript family tree looks like this: :: MapServer /\ / \ / \ PHPMapScript \ SWIGMapScript PHP5/7 +----+-----+----+----+--+----+------------+ | | | | | | | | Perl Python Ruby Java C# Tcl PHP7 (PHPNG) ... The SWIGMapScript modules are generated by `SWIG `_. The PHPMapScript module is developed using the PHP C API without using SWIG. PHP users therefore have a choice of using the SWIG generated module or the custom written PHP module. PHPMapScript ------------ Source code, detailed installation instructions are located in the ``mapscript/php`` folder. Documentation can be found in the `PHP MapScript Documentation `_ section. SWIG MapScript -------------- Installation instructions are located in the individual languages directories such as ``mapscript/perl``, ``mapscript/python``. The main MapScript SWIG interface file is ``mapscript/mapscript.i``. This file includes specific class interface files from ``mapscript/swiginc`` and language specific code from the language directories. Note the **v8** folder contains files for `V8 MapScript Support `_. This is not a JavaScript version of MapScript, but provides support for the use of JavaScript in `STYLEITEM `_ and `GEOTRANSFORM `_. API Documentation can be found at the `Shared SWIG MapScript Documentation `_ page. mapserver-7.4.3/mapscript/csharp/000077500000000000000000000000001357574274700170405ustar00rootroot00000000000000mapserver-7.4.3/mapscript/csharp/CMakeLists.txt000066400000000000000000000153741357574274700216120ustar00rootroot00000000000000FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PROGRAM (CSHARP_COMPILER NAMES csc mcs gmcs gmcs2) IF (CSHARP_COMPILER) MESSAGE(STATUS "Found CSharp compiler: ${CSHARP_COMPILER}") ELSE (CSHARP_COMPILER) MESSAGE(FATAL_ERROR "Could not find csharp compiler") ENDIF (CSHARP_COMPILER) if (WIN32) if (NOT MSVC71) if (CMAKE_CL_64) set(PLATFORM_TARGET /platform:anycpu) else(CMAKE_CL_64) set(PLATFORM_TARGET /platform:x86) endif(CMAKE_CL_64) set (KEYFILE_SPEC /keyfile:${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\mapscript.snk) endif (NOT MSVC71) if (MSVC_VERSION GREATER 1500) set(PLATFORM_TARGET ${PLATFORM_TARGET} /define:CLR4) endif (MSVC_VERSION GREATER 1500) MESSAGE(STATUS "Cmake build type: ${CMAKE_BUILD_TYPE}") if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") set(PLATFORM_TARGET ${PLATFORM_TARGET} /debug:full) endif (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") else() set (KEYFILE_SPEC -keyfile:${PROJECT_SOURCE_DIR}/mapscript/csharp/mapscript.snk) endif(WIN32) MARK_AS_ADVANCED(CSHARP_COMPILER) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) include_directories(${PROJECT_SOURCE_DIR}/mapscript/csharp) SET (CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}") SET( CMAKE_SWIG_FLAGS -namespace OSGeo.MapServer ${MAPSERVER_COMPILE_DEFINITIONS}) if (${CMAKE_VERSION} VERSION_LESS "3.8.0") SWIG_ADD_MODULE(mapscript csharp ../mapscript.i) else() SWIG_ADD_LIBRARY(mapscript LANGUAGE csharp SOURCES ../mapscript.i) endif() if (WIN32) set_target_properties(mapscript PROPERTIES OUTPUT_NAME "mapscript") else() set_target_properties(mapscript PROPERTIES OUTPUT_NAME "libmapscript") endif() SWIG_LINK_LIBRARIES(mapscript ${MAPSERVER_LIBMAPSERVER}) if (WIN32) ADD_CUSTOM_COMMAND(TARGET mapscript WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} POST_BUILD COMMAND set MAPSCRIPT_SNK=${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\mapscript.snk COMMAND set MAPSCRIPT_SNK=%MAPSCRIPT_SNK:/=\\% COMMAND copy /Y \"%MAPSCRIPT_SNK%\" COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /t:library /out:mapscript_csharp.dll ${KEYFILE_SPEC} *.cs ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\config\\AssemblyInfo.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:shpdump.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\shpdump.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:drawmap.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmap.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:shapeinfo.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\shapeinfo.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:drawquery.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawquery.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:getbytes.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\getbytes.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:HTMLtemplate.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\HTMLtemplate.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:RFC24.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\RFC24.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirect.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirect.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirectPrint.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapGDIPlus.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapGDIPlus.cs #COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /lib:C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF /r:mapscript_csharp.dll /r:System.Xaml.dll /r:WindowsBase.dll /r:PresentationCore.dll /out:drawmapWPF.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapWPF.cs COMMENT "Compiling c# source files" ) else() ADD_CUSTOM_COMMAND(TARGET mapscript WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} POST_BUILD COMMAND cp -f ${PROJECT_SOURCE_DIR}/mapscript/csharp/mapscript.snk ./ COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -target:library -out:mapscript_csharp.dll ${KEYFILE_SPEC} *.cs ${PROJECT_SOURCE_DIR}/mapscript/csharp/config/AssemblyInfo.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -out:shpdump.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/shpdump.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -out:drawmap.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/drawmap.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -out:shapeinfo.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/shapeinfo.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -out:drawquery.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/drawquery.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -reference:System.Drawing.dll -out:getbytes.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/getbytes.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -out:HTMLtemplate.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/HTMLtemplate.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -out:RFC24.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/RFC24.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -reference:System.Drawing.dll -out:drawmapDirect.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/drawmapDirect.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -reference:System.Drawing.dll -out:drawmapDirectPrint.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/drawmapDirectPrint.cs COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} -reference:mapscript_csharp.dll -reference:System.Drawing.dll -out:drawmapGDIPlus.exe ${PROJECT_SOURCE_DIR}/mapscript/csharp/examples/drawmapGDIPlus.cs #COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /lib:C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF /r:mapscript_csharp.dll /r:System.Xaml.dll /r:WindowsBase.dll /r:PresentationCore.dll /out:drawmapWPF.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapWPF.cs COMMENT "Compiling c# source files" ) endif() mapserver-7.4.3/mapscript/csharp/Makefile.in000066400000000000000000000057141357574274700211140ustar00rootroot00000000000000# $Id$ # # Run ./configure in the main MapServer directory to turn this Makefile.in # into a proper Makefile # # If you want to ignore missing datafile errors uncomment the following # line. This is especially useful with large tiled datasets that may not # have complete data for each tile. # #IGNORE_MISSING_DATA=-DIGNORE_MISSING_DATA IGNORE_MISSING_DATA = @IGNORE_MISSING_DATA@ # # If you want to use shape Z and M parameter this option must be set. # It's OFF by default. # #USE_POINT_Z_M=-DUSE_POINT_Z_M USE_POINT_Z_M = @USE_POINT_Z_M@ # # Apparently these aren't as commonplace as I'd hoped. Edit the # following line to reflect the missing functions on your platform. # # STRINGS=-DNEED_STRCASECMP -DNEED_STRNCASECMP -DNEED_STRDUP -DNEED_STRLCAT STRINGS= @STRINGS@ # # Flags. # XTRALIBS= @XTRALIBS@ RUNPATHS= @RPATHS@ FLAGS = @DEBUG_FLAGS@ @ALL_ENABLED@ @ALL_INC@ $(STRINGS) $(IGNORE_MISSING_DATA) $(USE_POINT_Z_M) CCFLAGS = @CFLAGS@ $(FLAGS) # Link flags and shared libs only SUP_LIBS = @ALL_LIB@ # STATIC_LIBS is full filename with path of libs that will be statically linked STATIC_LIBS= $(GD_STATIC) LDFLAGS= $(RUNPATHS) -L../.. -lmapserver $(SUP_LIBS) $(STATIC_LIBS) LIBMAPSCRIPT_SHARED= libmapscript.@SO_EXT@ LD_SHARED= @LD_SHARED@ # END OF CONFIGURE---- # # SWIG Stuff # SWIG= swig # # CSHARP Stuff # CSC= mcs CC= @CC@ # # --- You shouldn't have to edit anything else. --- # all: interface mapscript_so mapscript_csharp sign: sn -k mapscript.snk interface: ../mapscript.i $(SWIG) -csharp -namespace OSGeo.MapServer $(FLAGS) -o mapscript_wrap.c ../mapscript.i mapscript_so: mapscript_wrap.c $(CC) -fpic -c $(CCFLAGS) mapscript_wrap.c $(LD_SHARED) mapscript_wrap.o -o $(LIBMAPSCRIPT_SHARED) $(LDFLAGS) mapscript_csharp:: $(CSC) /t:library /out:mapscript_csharp.dll *.cs config/AssemblyInfo.cs $(CSC) /r:mapscript_csharp.dll /out:shpdump.exe examples/shpdump.cs $(CSC) /r:mapscript_csharp.dll /out:shapeinfo.exe examples/shapeinfo.cs $(CSC) /r:mapscript_csharp.dll /out:drawmap.exe examples/drawmap.cs $(CSC) /r:mapscript_csharp.dll /out:inline.exe examples/inline.cs $(CSC) /r:mapscript_csharp.dll /out:drawquery.exe examples/drawquery.cs $(CSC) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:getbytes.exe examples/getbytes.cs $(CSC) /r:mapscript_csharp.dll /out:HTMLtemplate.exe examples/HTMLtemplate.cs $(CSC) /r:mapscript_csharp.dll /out:RFC24.exe examples/RFC24.cs dll_config: Makefile rm -rf mapscript_csharp.dll.config echo "" >> mapscript_csharp.dll.config echo "" >> mapscript_csharp.dll.config echo "" >> mapscript_csharp.dll.config clean: rm -rf edu *.o *.c *.cs *.@SO_EXT@ *.dll *.dll.config test: LC_ALL=C mono ./shpdump.exe ../../tests/point.shp LC_ALL=C mono ./shapeinfo.exe ../../tests/point.shp LC_ALL=C mono ./inline.exe png24 inline_test.png LC_ALL=C mono ./getbytes.exe ../../tests/test.map test_csharp2.png LC_ALL=C mono ./RFC24.exe ../../tests/test.map mapserver-7.4.3/mapscript/csharp/Makefile.vc000077500000000000000000000071611357574274700211170ustar00rootroot00000000000000# # makefile.vc - MSVC++ makefile for the C#/MapScript extension # # This VC++ makefile will build the PHP module CSHARP_MAPSCRIPT.DLL # # To use the makefile: # - Open a DOS prompt window # - Run the VCVARS32.BAT script to initialize the VC++ environment variables # - Start the build with: nmake /f makefile.vc # # $Id$ # # Flag indicating to the option files that this is the build of C#/MapScript !INCLUDE ../../nmake.opt # Be aware when setting different options for libmap.dll and mapscript.dll (Bug 1476) # To change the options for mapscript.dll uncomment the following line # otherwise the options of nmake.opt will be used #OPTFLAGS = /nologo /Zi /MD $(WARNING_LEVEL) $(DEBUG) BASE_CFLAGS = $(OPTFLAGS) -DWIN32 -D_WIN32 #LDFLAGS = /NODEFAULTLIB:msvcrt /NODEFAULTLIB:libcd /dll $(LDEBUG) LDFLAGS = /dll $(LDEBUG) CFLAGS = $(BASE_CFLAGS) $(MS_CFLAGS) -I../.. CC= cl LINK= link !IFDEF MS_DEBUG CSDEBUG = /debug:full !ELSE CSDEBUG = !ENDIF !IFDEF MONO CSC = mcs !ELSE !IF $(MSVC_VER) >= 1400 !IFDEF WIN64 CSC = csc /platform:anycpu $(CSDEBUG) !ELSE CSC = csc /platform:x86 $(CSDEBUG) !ENDIF !ELSE CSC = csc $(CSDEBUG) !ENDIF !ENDIF !IF $(MSVC_VER) >= 1600 CSC = $(CSC) /define:CLR4 !ENDIF #SWIG = swig !IFDEF DLLBUILD MS_LIBS = ../../mapserver_i.lib $(EXTERNAL_LIBS) !ELSE MS_LIBS = $(EXTERNAL_LIBS) ../../mapserver.lib !ENDIF # # The rest of the file should not have to be edited... # MAPSCRIPT_OBJS = mapscript_wrap.obj MAPSCRIPT_DLL = mapscript.dll CSHARP_DLL = mapscript_csharp.dll default: all all: interface $(MAPSCRIPT_DLL) $(CSHARP_DLL) sign: sn -k mapscript.snk interface: ../mapscript.i $(SWIG) -csharp -namespace OSGeo.MapServer $(MS_DEFS) -DWIN32 -o mapscript_wrap.c ../mapscript.i .c.obj: $(CC) $(CFLAGS) /DCOMPILE_DL=1 /c $*.c /Fo$*.obj $(MAPSCRIPT_DLL): $(MAPSCRIPT_OBJS) $(LINK) $(LDFLAGS) /out:$(MAPSCRIPT_DLL) $(MAPSCRIPT_OBJS) $(MS_LIBS) if exist $(MAPSCRIPT_DLL).manifest mt -manifest $(MAPSCRIPT_DLL).manifest -outputresource:$(MAPSCRIPT_DLL);2 $(CSHARP_DLL):: $(CSC) $(CSFLAGS) /t:library /out:mapscript_csharp.dll *.cs config\AssemblyInfo.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:shpdump.exe examples\shpdump.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:drawmap.exe examples\drawmap.cs # $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:inline.exe examples\inline.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:shapeinfo.exe examples\shapeinfo.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:drawquery.exe examples\drawquery.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:getbytes.exe examples\getbytes.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:HTMLtemplate.exe examples\HTMLtemplate.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:RFC24.exe examples\RFC24.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirect.exe examples\drawmapDirect.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe examples\drawmapDirectPrint.cs $(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapGDIPlus.exe examples\drawmapGDIPlus.cs test: !IFDEF MONO mono shpdump.exe ../../tests/point.shp mono shapeinfo.exe ../../tests/point.shp # mono inline.exe aggpng24 inline_test.png mono getbytes.exe ../../tests/test.map test_csharp2.png mono RFC24.exe ../../tests/test.map !ELSE shpdump ../../tests/point.shp shapeinfo ../../tests/point.shp # inline png24 inline_test.png getbytes ../../tests/test.map test_csharp2.png RFC24.exe ../../tests/test.map !ENDIF clean: del *.obj del *.dll del *.lib del *.pdb del *.exp del *.ilk del *.cs del *.c del *.exe del *.manifest mapserver-7.4.3/mapscript/csharp/README000066400000000000000000000330551357574274700177260ustar00rootroot00000000000000-- $Id$ The most recent version of this document can be found on http://mapserver.gis.umn.edu/docs/howto/mapscriptcscompile 1. Compilation ============== Before compiling C# mapscript you should compile mapserver with the options for your requirements. For more information about the compilation of mapserver please see `Win32 Compilation and Installation `__ . It is highly recommended to minimize the library dependency of your application, so when compiling mapserver enable only the features really needed. To compile the C# binding SWIG 1.3.27 or later is required. 1.1 Win32 compilation targeting the MS.NET framework 1.1 -------------------------------------------------------- You should compile mapserver, mapscript and all of the subsequent libraries using Visual Studio 2003. Download and uncompress the latest SWIGWIN package that contains the precompiled swig.exe Open the Visual Studio .NET 2003 Command Prompt and step into the /mapscript/csharp directory Edit makefile.vc and set the SWIG variable to the location of your swig.exe Use :: nmake -f makefile.vc to compile mapscript.dll and mapscript_csharp.dll. 1.2 Win32 compilation targeting the MS.NET framework 2.0 -------------------------------------------------------- You should compile mapserver, mapscript and all of the subsequent libraries using Visual Studio 2005. Download and uncompress the latest SWIGWIN package that contains the precompiled swig.exe Open the Visual Studio 2005 Command Prompt and step into the /mapscript/csharp directory Edit makefile.vc and set the SWIG variable to the location of your swig.exe Use :: nmake -f makefile.vc to compile mapscript.dll and mapscript_csharp.dll. 1.3 Win32 compilation targeting the MONO framework -------------------------------------------------- Before the compilation you should download and install the recent mono Win32 setup package (eg. mono-1.1.13.2-gtksharp-2.8.1-win32-1.exe) Edit makefile.vc and set the CSC variable to the location of your mcs.exe. Alternatively you can define :: MONO = YES In your nmake.opt file. You should use the same compiler for compiling mapscript as the compiler has been used for the mapserver compilation. To compile mapscript open the Command Prompt supplied with your compiler and use :: nmake -f makefile.vc to compile mapscript.dll and mapscript_csharp.dll. 1.4 Alternative compilation methods on Windows ---------------------------------------------- Beginning from mapserver 4.8.3 you can invoke the C# compilation from the mapserver directory by uncommenting DOT_NET in nmake.opt :: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # .NET/C# MapScript # ---------------------------------------------------------------------- # .NET will of course only work with MSVC 7.0 and 7.1. Also note that # you will definitely want USE_THREAD defined. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #DOT_NET = YES and invoking the compilation by :: nmake -f makefile.vc csharp You can also use :: nmake -f makefile.vc install for making the compilation an copying the targets into a common output directory. 1.5 Testing the compilation --------------------------- For testing the compilation and the runtime environment you can use :: nmake -f makefile.vc test within the csharp directory for starting the sample applications compiled previously. Before making the test the location of the corresponding libraries should be incuded in the system PATH. 1.6 Linux compilation targeting the MONO framework -------------------------------------------------- Before the compilation you should download and install the recent mono Linux package. Some distributions have precompiled binaries to install, but for using the latest version you might want to compile and install it from the source. Download and uncompress the latest SWIG release. You should probably compile it from the source if precompiled binaries are not available for your platform. Before compiling mapscript mapserver should be configured and compiled. Beginning from mapserver 4.8.2 during configuration the mapscript/csharp/Makefile will be created according to the configuration options. Edit this file and set the SWIG and CSC for the corresponding executable pathes if the files could not be accessed by default. To compile at a console step into the /mapscript/csharp directory use :: make to compile libmapscript.so and mapscript_csharp.dll. For testing the compilation and the runtime environment you can use :: make test for starting the sample applications compiled previously. 1.7 OSX compilation targeting the MONO framework ------------------------------------------------ Beginning from 4.10.0 the csharp/Makefile supports the OSX builds. Before making the build the recent MONO package should be installed on the system. Before compiling mapscript mapserver should be configured and compiled. Beginning from mapserver 4.8.2 during configuration the mapscript/csharp/Makefile will be created according to the configuration options. Edit this file and set the SWIG and CSC for the corresponding executable pathes if the files could not be accessed by default. To compile at a console step into the /mapscript/csharp directory use :: make to compile libmapscript.dylib and mapscript_csharp.dll. For testing the compilation and the runtime environment you can use :: make test for starting the sample applications compiled previously. To run the applications mapscript_csharp.dll.config is needed along with the mapscript_csharp.dll file. This file is created during the make process 2. Installation =============== The files required for your application should be manually installed. It is highly recommended to copy the files into the same folder as the executable resides. 3. Known issues =============== 3.1 Visual Studio 2005 requires a manifest file to load the CRT native assembly wrapper --------------------------------------------------------------------------------------- If you have compiled mapserver for using the CRT libraries and you are using the MS.NET framework 2.0 as the execution runtime you should supply a proper manifest file along with your executable, like: :: UMOlhUBGeKRrrg9DaaPNgyhRjyM= This will inform the CLR that your exe depends on the CRT and the proper assembly wrapper is to be used. If you are using the IDE the manifest file could be pregenerated by adding a reference to Microsoft.VC80.CRT.manifest within the /Microsoft Visual Studio 8/VC/redist/x86/Microsoft.VC80.CRT directory. 3.2 Manifests for the dll-s must be embedded as a resource ---------------------------------------------------------- According to the windows makefile the mapscript compilation target (mapscript.dll) is linked with the /MD option. In this case the VS2005 linker will generate a manifest file containing the unmanaged assembly dependency. The sample contents of the manifest file are: :: Like previously mentioned if you are creating a windows application the common language runtime will search for a manifest file for the application. The name of the manifest file should be the same as the executable appendend with the .manifest extension. However if the host process is not controlled by you (like web mapping applications using aspnet_wp.exe as the host process) you will not be certain if the host process (.exe) will have a manifest containing a reference to the CRT wrapper. In this case you may have to embed the manifest into the dll as a resource using the mt tool like: :: mt /manifest mapscript.dll.manifest /outputresource:mapscript.dll;#2 the common language runtime will search for the embedded resource and load the CRT assembly properly. Normally it is enough to load the CRT with the root dll (mapscript.dll), but it is not harmful embedding the manifest into the dependent libraries as well. 3.3 Issue with regex and Visual Studio 2005 ------------------------------------------- When compiling with Microsoft Visual Studio 2005 variable name collision may occur between regex.c and crtdefs.h. For more details see: http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1651 3.4 C# mapscript library name mapping with MONO ----------------------------------------------- Using the mapscript interface created by the SWIG interface generator the communication between the C# wrapper classes (mapscript_csharp.dll) and the C code (mapscript.dll) takes place using platform invoke like: :: [DllImport("mapscript", EntryPoint="CSharp_new_mapObj")] public static extern IntPtr new_mapObj(string jarg1); The DllImport declaration contains the library name, however to transform the library name into a file name is platform dependent. On Windows the library name is simply appended with the .dll extension (mapscript.dll). On the Unix systems the library file name normally starts with the lib prefix and appended with the .so extension (libmapscript.so). Mapping of the library name may be manually controlled using a dll.config file. This simply maps the library file the DllImport is looking for to its unix equivalent. The file normally contains the following information (mapscript_csharp.dll.config): :: and with the OSX builds: :: The file should be placed along with the corresponding mapscript_csharp.dll file, and created by default during the make process. For more information see: http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1596 http://www.mono-project.com/Interop_with_Native_Libraries 3.5 Localization issues with MONO/Linux --------------------------------------- According to http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1762 mapserver may not operate equally well on different locale settings. Especially when the decimal separator is other than "." inside the locale of the process may cause parse errors when the mapfile contains float numbers. Since the MONO process takes over the locale settings of the environment it is worth considering to set the default locale to "C" of the host process, like: :: LC_ALL=C mono ./drawmap.exe ../../tests/test.map test_csharp.png 4. Most frequent errors ======================= This chapter will summarize the most frequent problems the user can run into. The issues were collected mainly from the -users list and the IRC. 4.1 Unable to load dll (mapscript) ---------------------------------- You can get this problem on Windows and in most cases it can be dedicated to a missing or an unloadable shared library. The error message talks about mapscript.dll but surely one or more of the dll-s are missing that libmap.dll depends on. So firstly you might want to check for the dependencies of your libmap.dll in your application directory. You can use the Visual Studio Dependency Walker to accomplish this task. You can also use a file monitoring tool (like SysInternal's filemon) to detect the dll-s that could not be loaded. I propose to store all of the dll-s required by your application in the application folder. If you can run the drawmap C# sample application with your mapfile your compilation might be correct and all of the dlls are available. You may find that the mapscript C# interface behaves differently for the desktop and the ASP.NET applications. Although you can run the drawmap sample correctly you may encounter the dll loading problem with the ASP.NET applications. When creating an ASP.NET project your application folder will be '\Inetpub\wwwroot\[YourApp]\bin' by default. The host process of the application will aspnet_wp.exe or w3wp.exe depending on your system. The application will run under a different security context than the interactive user (under the context of the ASPNET user by default). When placing the dll-s outside of your application directory you should consider that the PATH environment variable may differ between the interactive and the ASPNET user and/or you may not have enough permission to access a dll outside of your application folder. 5. Bug reports ============== If you find a problem dedicated to the mapscript C# interface feel free to file a bug report to BugZilla. mapserver-7.4.3/mapscript/csharp/config/000077500000000000000000000000001357574274700203055ustar00rootroot00000000000000mapserver-7.4.3/mapscript/csharp/config/AssemblyInfo.cs000066400000000000000000000105061357574274700232310ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapScript CSharp Assembly Information * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System.Reflection; using System.Runtime.CompilerServices; using System.Security; // // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. // [assembly: AssemblyTitle("mapscript")] [assembly: AssemblyDescription("MapScript C# Library")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.*")] // // In order to sign your assembly you must specify a key to use. Refer to the // Microsoft .NET Framework documentation for more information on assembly signing. // // Use the attributes below to control which key is used for signing. // // Notes: // (*) If no key is specified, the assembly is not signed. // (*) KeyName refers to a key that has been installed in the Crypto Service // Provider (CSP) on your machine. KeyFile refers to a file which contains // a key. // (*) If the KeyFile and the KeyName values are both specified, the // following processing occurs: // (1) If the KeyName can be found in the CSP, that key is used. // (2) If the KeyName does not exist and the KeyFile does exist, the key // in the KeyFile is installed into the CSP and used. // (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. // When specifying the KeyFile, the location of the KeyFile should be // relative to the project output directory which is // %Project Directory%\obj\. For example, if your KeyFile is // located in the project directory, you would specify the AssemblyKeyFile // attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] // (*) Delay Signing is an advanced option - see the Microsoft .NET Framework // documentation for more information on this. // [assembly: AssemblyDelaySign(false)] [assembly: AssemblyKeyFile("mapscript.snk")] [assembly: AssemblyKeyName("")] // The AllowPartiallyTrustedCallersAttribute requires the assembly to be signed with a strong name key. // This attribute is necessary since the control is called by either an intranet or Internet // Web page that should be running under restricted permissions. [assembly: AllowPartiallyTrustedCallers] // Use the .NET Framework 2.0 transparency rules (level 1 transparency) as default #if (CLR4) [assembly: SecurityRules(SecurityRuleSet.Level1)] #endifmapserver-7.4.3/mapscript/csharp/config/mapscript_csharp.dll.config000066400000000000000000000001311357574274700256030ustar00rootroot00000000000000 mapserver-7.4.3/mapscript/csharp/csmodule.i000066400000000000000000000415101357574274700210260ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: C#-specific enhancements to MapScript * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ /*Uncomment the following lines if you want to receive subsequent exceptions as inner exceptions. Otherwise the exception message will be concatenated*/ //#if SWIG_VERSION >= 0x010329 //#define ALLOW_INNER_EXCEPTIONS //#endif %ignore fp; /****************************************************************************** * Implement Equals and GetHashCode properly *****************************************************************************/ %typemap(cscode) SWIGTYPE %{ public override bool Equals(object obj) { if (obj == null) return false; if (this.GetType() != obj.GetType()) return false; return swigCPtr.Handle.Equals($csclassname.getCPtr(($csclassname)obj).Handle); } public override int GetHashCode() { return swigCPtr.Handle.GetHashCode(); } %} /****************************************************************************** * Module initialization helper (bug 1665) *****************************************************************************/ %pragma(csharp) imclasscode=%{ protected class $moduleHelper { static $moduleHelper() { $module.msSetup(); } ~$moduleHelper() { //$module.msCleanup(); } } protected static $moduleHelper the$moduleHelper = new $moduleHelper(); %} /****************************************************************************** * C# exception redefinition *****************************************************************************/ #ifdef ALLOW_INNER_EXCEPTIONS %exception { errorObj *ms_error; $action ms_error = msGetErrorObj(); if (ms_error != NULL && ms_error->code != MS_NOERR) { if (ms_error->code != MS_NOTFOUND && ms_error->code != -1) { int ms_errorcode = ms_error->code; while (ms_error!=NULL && ms_error->code != MS_NOERR) { char* msg = msAddErrorDisplayString(NULL, ms_error); if (msg) { SWIG_CSharpException(SWIG_SystemError, msg); free(msg); } else SWIG_CSharpException(SWIG_SystemError, "MapScript unknown error"); ms_error = ms_error->next; } msResetErrorList(); return $null; } msResetErrorList(); } } #else %exception { errorObj *ms_error; $action ms_error = msGetErrorObj(); if (ms_error != NULL && ms_error->code != MS_NOERR) { if (ms_error->code != MS_NOTFOUND && ms_error->code != -1) { char* msg = msGetErrorString(";"); if (msg) { SWIG_CSharpException(SWIG_SystemError, msg); free(msg); } else SWIG_CSharpException(SWIG_SystemError, "MapScript unknown error"); msResetErrorList(); return $null; } msResetErrorList(); } } #endif /****************************************************************************** * typemaps for string arrays (for supporting map templates) *****************************************************************************/ %pragma(csharp) imclasscode=%{ public class StringArrayMarshal : global::System.IDisposable { public readonly System.IntPtr[] _ar; public StringArrayMarshal(string[] ar) { _ar = new System.IntPtr[ar.Length]; for (int cx = 0; cx < _ar.Length; cx++) { _ar[cx] = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(ar[cx]); } } public virtual void Dispose() { for (int cx = 0; cx < _ar.Length; cx++) { System.Runtime.InteropServices.Marshal.FreeHGlobal(_ar[cx]); } System.GC.SuppressFinalize(this); } } %} %typemap(imtype, out="System.IntPtr") char** "System.IntPtr[]" %typemap(cstype) char** %{string[]%} %typemap(in) char** %{ $1 = ($1_ltype)$input; %} %typemap(out) char** %{ $result = $1; %} %typemap(csin) char** "new $modulePINVOKE.StringArrayMarshal($csinput)._ar" %typemap(csout, excode=SWIGEXCODE) char** { $excode throw new System.NotSupportedException("Returning string arrays is not implemented yet."); } %typemap(csvarin, excode=SWIGEXCODE2) char** %{ set { $excode throw new System.NotSupportedException("Setting string arrays is not supported now."); } %} /* specializations */ %typemap(csvarout, excode=SWIGEXCODE2) char** formatoptions %{ get { System.IntPtr cPtr = $imcall; System.IntPtr objPtr; string[] ret = new string[this.numformatoptions]; for(int cx = 0; cx < this.numformatoptions; cx++) { objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(System.IntPtr))); ret[cx]= (objPtr == System.IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr); } $excode return ret; } %} %typemap(csvarout, excode=SWIGEXCODE2) char** values %{ get { System.IntPtr cPtr = $imcall; System.IntPtr objPtr; string[] ret = new string[this.numvalues]; for(int cx = 0; cx < this.numvalues; cx++) { objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(System.IntPtr))); ret[cx]= (objPtr == System.IntPtr.Zero) ? null : System.Runtime.InteropServices.Marshal.PtrToStringAnsi(objPtr); } $excode return ret; } %} /****************************************************************************** * typemaps for outputFormatObj arrays *****************************************************************************/ %typemap(ctype) outputFormatObj** "void*" %typemap(imtype) outputFormatObj** "System.IntPtr" %typemap(cstype) outputFormatObj** "outputFormatObj[]" %typemap(out) outputFormatObj** %{ $result = $1; %} %typemap(csout, excode=SWIGEXCODE) outputFormatObj** { System.IntPtr cPtr = $imcall; System.IntPtr objPtr; outputFormatObj[] ret = new outputFormatObj[this.numoutputformats]; for(int cx = 0; cx < this.numoutputformats; cx++) { objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(System.IntPtr))); ret[cx] = (objPtr == System.IntPtr.Zero) ? null : new outputFormatObj(objPtr, false, ThisOwn_false()); } $excode return ret; } %typemap(csvarout, excode=SWIGEXCODE2) outputFormatObj** %{ get { System.IntPtr cPtr = $imcall; System.IntPtr objPtr; outputFormatObj[] ret = new outputFormatObj[this.numoutputformats]; for(int cx = 0; cx < this.numoutputformats; cx++) { objPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(cPtr, cx * System.Runtime.InteropServices.Marshal.SizeOf(typeof(System.IntPtr))); ret[cx] = (objPtr == System.IntPtr.Zero) ? null : new outputFormatObj(objPtr, false, ThisOwn_false()); } $excode return ret; } %} /****************************************************************************** * gdBuffer Typemaps and helpers *****************************************************************************/ %pragma(csharp) imclasscode=%{ public delegate void SWIGByteArrayDelegate(System.IntPtr data, int size); %} %insert(runtime) %{ /* Callback for returning byte arrays to C# */ typedef void (SWIGSTDCALL* SWIG_CSharpByteArrayHelperCallback)(const unsigned char *, const int); /* Default callback interface */ static SWIG_CSharpByteArrayHelperCallback SWIG_csharp_bytearray_callback = NULL; %} %typemap(ctype) SWIG_CSharpByteArrayHelperCallback %{SWIG_CSharpByteArrayHelperCallback%} %typemap(imtype) SWIG_CSharpByteArrayHelperCallback %{SWIGByteArrayDelegate%} %typemap(cstype) SWIG_CSharpByteArrayHelperCallback %{$modulePINVOKE.SWIGByteArrayDelegate%} %typemap(in) SWIG_CSharpByteArrayHelperCallback %{ $1 = ($1_ltype)$input; %} %typemap(csin) SWIG_CSharpByteArrayHelperCallback "$csinput" %typemap(imtype) (unsigned char* pixels) "System.IntPtr" %typemap(cstype) (unsigned char* pixels) "System.IntPtr" %typemap(in) (unsigned char* pixels) %{ $1 = ($1_ltype)$input; %} %typemap(csin) (unsigned char* pixels) "$csinput" %csmethodmodifiers getBytes "private"; %ignore imageObj::getBytes(); %extend imageObj { void getBytes(SWIG_CSharpByteArrayHelperCallback callback) { gdBuffer buffer; buffer.owns_data = MS_TRUE; buffer.data = msSaveImageBuffer(self, &buffer.size, self->format); if( buffer.data == NULL || buffer.size == 0 ) { msSetError(MS_MISCERR, "Failed to get image buffer", "getBytes"); return; } callback(buffer.data, buffer.size); msFree(buffer.data); } int getRawPixels(unsigned char* pixels) { if (MS_RENDERER_PLUGIN(self->format)) { rendererVTableObj *renderer = self->format->vtable; if(renderer->supports_pixel_buffer) { rasterBufferObj rb; int status = MS_SUCCESS; int size = self->width * self->height * 4 * sizeof(unsigned char); status = renderer->getRasterBufferHandle(self,&rb); if(UNLIKELY(status == MS_FAILURE)) { return MS_FAILURE; } memcpy(pixels, rb.data.rgba.pixels, size); return status; } } return MS_FAILURE; } } %ignore imageObj::write; %typemap(cscode) imageObj, struct imageObj %{ private byte[] gdbuffer; private void CreateByteArray(System.IntPtr data, int size) { gdbuffer = new byte[size]; System.Runtime.InteropServices.Marshal.Copy(data, gdbuffer, 0, size); } public byte[] getBytes() { getBytes(new $modulePINVOKE.SWIGByteArrayDelegate(this.CreateByteArray)); return gdbuffer; } public void write(System.IO.Stream stream) { getBytes(new $modulePINVOKE.SWIGByteArrayDelegate(this.CreateByteArray)); stream.Write(gdbuffer, 0, gdbuffer.Length); } %} %csmethodmodifiers processTemplate "private"; %csmethodmodifiers processLegendTemplate "private"; %csmethodmodifiers processQueryTemplate "private"; %typemap(csinterfaces) mapObj "System.IDisposable, System.Runtime.Serialization.ISerializable"; %typemap(csattributes) mapObj "[Serializable]" %typemap(cscode) mapObj, struct mapObj %{ public string processTemplate(int bGenerateImages, string[] names, string[] values) { if (names.Length != values.Length) throw new System.ArgumentException("Invalid array length specified!"); return processTemplate(bGenerateImages, names, values, values.Length); } public string processLegendTemplate(string[] names, string[] values) { if (names.Length != values.Length) throw new System.ArgumentException("Invalid array length specified!"); return processLegendTemplate(names, values, values.Length); } public string processQueryTemplate(string[] names, string[] values) { if (names.Length != values.Length) throw new System.ArgumentException("Invalid array length specified!"); return processQueryTemplate(names, values, values.Length); } public mapObj( System.Runtime.Serialization.SerializationInfo info , System.Runtime.Serialization.StreamingContext context) : this(info.GetString("mapText"), 1) { //this constructor is needed for ISerializable interface } public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { info.AddValue( "mapText", this.convertToString() ); } %} %typemap(ctype) gdBuffer %{void%} %typemap(imtype) gdBuffer %{void%} %typemap(cstype) gdBuffer %{byte[]%} %typemap(out, null="") gdBuffer %{ SWIG_csharp_bytearray_callback($1.data, $1.size); if( $1.owns_data ) msFree($1.data); %} // SWIGEXCODE is a macro used by many other csout typemaps #ifdef SWIGEXCODE %typemap(csout, excode=SWIGEXCODE) gdBuffer { $imcall;$excode return $modulePINVOKE.GetBytes(); } #else %typemap(csout) gdBuffer { $imcall; return $modulePINVOKE.GetBytes(); } #endif %pragma(csharp) imclasscode=%{ protected class SWIGByteArrayHelper { public delegate void SWIGByteArrayDelegate(System.IntPtr data, int size); static SWIGByteArrayDelegate bytearrayDelegate = new SWIGByteArrayDelegate(CreateByteArray); [System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="SWIGRegisterByteArrayCallback_$module")] public static extern void SWIGRegisterByteArrayCallback_mapscript(SWIGByteArrayDelegate bytearrayDelegate); static void CreateByteArray(System.IntPtr data, int size) { arraybuffer = new byte[size]; System.Runtime.InteropServices.Marshal.Copy(data, arraybuffer, 0, size); } static SWIGByteArrayHelper() { SWIGRegisterByteArrayCallback_$module(bytearrayDelegate); } } protected static SWIGByteArrayHelper bytearrayHelper = new SWIGByteArrayHelper(); [System.ThreadStatic] private static byte[] arraybuffer; internal static byte[] GetBytes() { return arraybuffer; } %} %insert(runtime) %{ #ifdef __cplusplus extern "C" #endif #ifdef SWIGEXPORT SWIGEXPORT void SWIGSTDCALL SWIGRegisterByteArrayCallback_$module(SWIG_CSharpByteArrayHelperCallback callback) { SWIG_csharp_bytearray_callback = callback; } #else DllExport void SWIGSTDCALL SWIGRegisterByteArrayCallback_$module(SWIG_CSharpByteArrayHelperCallback callback) { SWIG_csharp_bytearray_callback = callback; } #endif %} /* Typemaps for pattern array */ %typemap(imtype) (double pattern[ANY]) "System.IntPtr" %typemap(cstype) (double pattern[ANY]) "double[]" %typemap(in) (double pattern[ANY]) %{ $1 = ($1_ltype)$input; %} %typemap(csin) (double pattern[ANY]) "$csinput" %typemap(csvarout, excode=SWIGEXCODE2) (double pattern[ANY]) %{ get { System.IntPtr cPtr = $imcall; double[] ret = new double[patternlength]; if (patternlength > 0) { System.Runtime.InteropServices.Marshal.Copy(cPtr, ret, 0, patternlength); } $excode return ret; } set { System.IntPtr cPtr = $imcall; if (value.Length > 0) { System.Runtime.InteropServices.Marshal.Copy(value, 0, cPtr, value.Length); } patternlength = value.Length; $excode } %} %typemap(csvarin, excode="") (double pattern[ANY]) %{$excode%} /* Typemaps for int array */ %typemap(imtype, out="System.IntPtr") int *panIndexes "int[]" %typemap(cstype) int *panIndexes %{int[]%} %typemap(in) int *panIndexes %{ $1 = ($1_ltype)$input; %} %typemap(csin) (int *panIndexes) "$csinput" /* Typemaps for device handle */ %typemap(imtype) (void* device) %{System.IntPtr%} %typemap(cstype) (void* device) %{System.IntPtr%} %typemap(in) (void* device) %{ $1 = ($1_ltype)$input; %} %typemap(csin) (void* device) "$csinput" /****************************************************************************** * Preventing to take ownership of the memory when constructing objects * with parent objects (causing nullreference exception, Bug 1743) *****************************************************************************/ %typemap(csconstruct, excode=SWIGEXCODE) layerObj(mapObj map) %{: this($imcall, true, map) { $excode } %} %typemap(csconstruct, excode=SWIGEXCODE) classObj(layerObj layer) %{: this($imcall, true, layer) { $excode } %} %typemap(csconstruct, excode=SWIGEXCODE) styleObj(classObj parent_class) %{: this($imcall, true, parent_class) { $excode } %} %typemap(csout, excode=SWIGEXCODE) classObj* getClass, layerObj* getLayer, layerObj *getLayerByName, styleObj* getStyle { System.IntPtr cPtr = $imcall; $csclassname ret = (cPtr == System.IntPtr.Zero) ? null : new $csclassname(cPtr, $owner, ThisOwn_false());$excode return ret; } mapserver-7.4.3/mapscript/csharp/examples/000077500000000000000000000000001357574274700206565ustar00rootroot00000000000000mapserver-7.4.3/mapscript/csharp/examples/HTMLtemplate.cs000066400000000000000000000044271357574274700235140ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to show the usage of HTML templates. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using OSGeo.MapServer; /// /// A C# based mapscript example to show the usage of HTML templates. /// class HTMLTemplate { public static void usage() { Console.WriteLine("usage: HTMLTemplate {mapfile} {templatefile} {outdir}"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length < 3) usage(); mapObj map = new mapObj(args[0]); map.legend.template = args[1]; map.web.imagepath = args[2]; map.web.imageurl = ""; string str = null; string[] names = null, values = null; names = new string[] {"map"}; values = new string[] { args[0] }; str = map.processLegendTemplate(names, values); Console.Write(str); } } mapserver-7.4.3/mapscript/csharp/examples/RFC24.cs000066400000000000000000000347111357574274700217730ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Tests for RFC24 implementation. * (http://mapserver.gis.umn.edu/development/rfc/ms-rfc-24/). * Author: Tamas Szekeres, szekerest@gmail.com * Umberto Nicoletti, umberto.nicoletti@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using OSGeo.MapServer; /** *

Title: Mapscript RFC24 tests.

*

Description: Tests for RFC24 implementation. (http://mapserver.gis.umn.edu/development/rfc/ms-rfc-24/)

* @author Umberto Nicoletti (umberto.nicoletti@gmail.com) */ class RFC24 { string mapfile; int fails = 0; public static void Main(string[] args) { new RFC24(args[0]).run(); } public RFC24(string mapfile) { this.mapfile=mapfile; } public void run() { Console.WriteLine("Running RFC24"); testLayerObj(); testLayerObjDestroy(); testClassObj(); testClassObjDestroy(); testInsertLayerObj(); testInsertLayerObjDestroy(); testRemoveLayerObj(); testInsertClassObj(); testInsertClassObjDestroy(); testRemoveClassObj(); testGetLayerObj(); testGetLayerObjDestroy(); testGetLayerObjByName(); testGetLayerObjByNameDestroy(); testGetClassObj(); testGetClassObjDestroy(); try { testStyleObj(); } catch (Exception e) { Console.WriteLine("\t- testStyleObj exception:" + e.Message); } testStyleObjDestroy(); try { testInsertStyleObj(); } catch (Exception e) { Console.WriteLine("\t- testInsertStyleObj exception:" + e.Message); } testInsertStyleObjDestroy(); testRemoveStyleObj(); try { testGetStyleObj(); } catch (Exception e) { Console.WriteLine("\t- testGetStyleObj exception:" + e.Message); } testGetStyleObjDestroy(); try { testlegendObj(); } catch (Exception e) { Console.WriteLine("\t- testlegendObj exception:" + e.Message); } try { testreferenceMapObj(); } catch (Exception e) { Console.WriteLine("\t- testreferenceMapObj exception:" + e.Message); } try { testwebObj(); } catch (Exception e) { Console.WriteLine("\t- testwebObj exception:" + e.Message); } try { testqueryMapObj(); } catch (Exception e) { Console.WriteLine("\t- testqueryMapObj exception:" + e.Message); } try { testmapObjHashTable(); } catch (Exception e) { Console.WriteLine("\t- testmapObjHashTable exception:" + e.Message); } try { testsymbolSetObj(); } catch (Exception e) { Console.WriteLine("\t- testsymbolSetObj exception:" + e.Message); } try { testimageObj(); } catch (Exception e) { Console.WriteLine("\t- testimageObj exception:" + e.Message); } if (fails > 0) Console.WriteLine("\n " + fails + " tests were FAILED!!!\n"); Console.WriteLine("Finished RFC24"); } public void testlegendObj() { mapObj map=new mapObj(mapfile); legendObj legend = map.legend; legend.template = "This is a sample!"; map=null; gc(); assert(legend.template == "This is a sample!", "testlegendObj"); } public void testmapObjHashTable() { mapObj map=new mapObj(mapfile); hashTableObj configoptions = map.configoptions; configoptions.set("key", "test value"); map=null; gc(); assert(configoptions.get("key", "") == "test value", "testmapObjHashTable"); } public void testsymbolSetObj() { mapObj map=new mapObj(mapfile); symbolSetObj symbolset = map.symbolset; symbolset.filename = "filename"; map=null; gc(); assert(symbolset.filename == "filename", "testsymbolSetObj"); } public void testreferenceMapObj() { mapObj map=new mapObj(mapfile); referenceMapObj refmap = map.reference; refmap.markername = "This is a sample!"; map=null; gc(); assert(refmap.markername == "This is a sample!", "testreferenceMapObj"); } public void testwebObj() { mapObj map=new mapObj(mapfile); webObj web = map.web; web.template = "This is a sample!"; map=null; gc(); assert(web.template == "This is a sample!", "testwebObj"); } public void testqueryMapObj() { mapObj map=new mapObj(mapfile); queryMapObj querymap = map.querymap; querymap.color.setHex( "#13ba88" ); map=null; gc(); assert(querymap.color.toHex() == "#13ba88", "testqueryMapObj"); } public void testimageObj() { mapObj map=new mapObj(mapfile); imageObj image = map.draw(); outputFormatObj format = image.format; format.setOption( "INTERLACE", "OFF"); map=null; gc(); assert(format.getOption("INTERLACE", "") == "OFF", "testimageObj"); } public void testLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(map); map=null; gc(); assertNotNull(newLayer.map, "testLayerObj"); assert(newLayer.refcount == 2, "testLayerObj refcount"); } public void testLayerObjDestroy() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(map); layerObj reference = map.getLayer(map.numlayers-1); assert(newLayer.refcount == 3, "testLayerObjDestroy precondition"); newLayer.Dispose(); // force the destruction for Mono on Windows because of the constructor overload newLayer = null; gc(); assert(reference.refcount == 2, "testLayerObjDestroy"); } public void testInsertLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(null); map.insertLayer(newLayer,-1); map=null; gc(); assertNotNull(newLayer.map, "testInsertLayerObj"); assert(newLayer.refcount == 2, "testInsertLayerObj refcount"); } public void testInsertLayerObjDestroy() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(null); map.insertLayer(newLayer,0); layerObj reference = map.getLayer(0); assert(newLayer.refcount == 3, "testInsertLayerObjDestroy precondition"); newLayer.Dispose(); // force the destruction for Mono on Windows because of the constructor overload newLayer=null; gc(); assert(reference.refcount == 2, "testInsertLayerObjDestroy"); } public void testRemoveLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=new layerObj(null); map.insertLayer(newLayer,0); map.removeLayer(0); map=null; gc(); assert(newLayer.refcount == 1, "testRemoveLayerObj"); } public void testGetLayerObj() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayer(1); map=null; gc(); assertNotNull(newLayer.map, "testGetLayerObj"); assert(newLayer.refcount == 2, "testGetLayerObj refcount"); } public void testGetLayerObjDestroy() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayer(1); layerObj reference = map.getLayer(1); assert(newLayer.refcount == 3, "testGetLayerObjDestroy precondition"); //newLayer.Dispose(); // force the destruction needed for Mono on Windows newLayer=null; gc(); assert(reference.refcount == 2, "testGetLayerObjDestroy"); } public void testGetLayerObjByName() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayerByName("POLYGON"); map=null; gc(); assertNotNull(newLayer.map, "testGetLayerObjByName"); assert(newLayer.refcount == 2, "testGetLayerObjByName refcount"); } public void testGetLayerObjByNameDestroy() { mapObj map=new mapObj(mapfile); layerObj newLayer=map.getLayerByName("POLYGON"); layerObj reference=map.getLayerByName("POLYGON"); assert(newLayer.refcount == 3, "testGetLayerObjByNameDestroy precondition"); //newLayer.Dispose(); // force the destruction needed for Mono on Windows newLayer=null; gc(); assert(reference.refcount == 2, "testGetLayerObjByNameDestroy"); } public void testClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(layer); map=null; layer=null; gc(); assertNotNull(newClass.layer, "testClassObj"); assert(newClass.refcount == 2, "testClassObj refcount"); } public void testClassObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(layer); classObj reference=layer.getClass(layer.numclasses-1); assert(newClass.refcount == 3, "testClassObjDestroy precondition"); newClass.Dispose(); // force the destruction for Mono on Windows because of the constructor overload map=null; layer=null; newClass=null; gc(); assert(reference.refcount == 2, "testClassObjDestroy"); } public void testStyleObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle=new styleObj(classobj); map=null; layer=null; classobj=null; gc(); assert(newStyle.refcount == 2, "testStyleObj"); } public void testStyleObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle=new styleObj(classobj); styleObj reference=classobj.getStyle(classobj.numstyles-1); assert(newStyle.refcount == 3, "testStyleObjDestroy"); newStyle.Dispose(); // force the destruction for Mono on Windows because of the constructor overload map=null; layer=null; classobj=null; newStyle=null; gc(); assert(reference.refcount == 2, "testStyleObjDestroy"); } public void testInsertClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(null); layer.insertClass(newClass,-1); assertNotNull(newClass.layer, "testInsertClassObj precondition"); map=null; layer=null; gc(); assertNotNull(newClass.layer, "testInsertClassObj"); assert(newClass.refcount == 2, "testInsertClassObj refcount"); } public void testRemoveClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(null); layer.insertClass(newClass,0); layer.removeClass(0); map=null; layer=null; gc(); assert(newClass.refcount == 1, "testRemoveClassObj"); } public void testInsertClassObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=new classObj(null); layer.insertClass(newClass,0); classObj reference = layer.getClass(0); assert(newClass.refcount == 3, "testInsertClassObjDestroy precondition"); newClass.Dispose(); // force the destruction for Mono on Windows because of the constructor overload map=null; layer=null; newClass=null; gc(); assert(reference.refcount == 2, "testInsertClassObjDestroy"); } public void testInsertStyleObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle = new styleObj(null); classobj.insertStyle(newStyle,-1); assert(newStyle.refcount == 2, "testInsertStyleObj precondition"); map=null; layer=null; classobj=null; gc(); assert(newStyle.refcount == 2, "testInsertStyleObj"); } public void testRemoveStyleObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle = new styleObj(null); classobj.insertStyle(newStyle,0); classobj.removeStyle(0); map=null; layer=null; classobj=null; gc(); assert(newStyle.refcount == 1, "testRemoveStyleObj"); } public void testInsertStyleObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj newStyle = new styleObj(null); classobj.insertStyle(newStyle,0); styleObj reference = classobj.getStyle(0); assert(newStyle.refcount == 3, "testInsertStyleObjDestroy precondition"); newStyle.Dispose(); // force the destruction for Mono on Windows because of the constructor overload map=null; layer=null; classobj=null; newStyle=null; gc(); assert(reference.refcount == 2, "testInsertStyleObjDestroy"); } public void testGetClassObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=layer.getClass(0); map=null; layer=null; gc(); assertNotNull(newClass.layer, "testGetClassObj"); assert(newClass.refcount == 2, "testGetClassObj refcount"); } public void testGetClassObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj newClass=layer.getClass(0); classObj reference = layer.getClass(0); assert(newClass.refcount == 3, "testGetClassObjDestroy precondition"); map=null; layer=null; newClass=null; gc(); assert(reference.refcount == 2, "testGetClassObjDestroy"); } public void testGetStyleObj() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj style=classobj.getStyle(0); map=null; layer=null; classobj=null; gc(); assert(style.refcount == 2, "testGetStyleObj"); } public void testGetStyleObjDestroy() { mapObj map=new mapObj(mapfile); layerObj layer=map.getLayer(1); classObj classobj=layer.getClass(0); styleObj style=classobj.getStyle(0); styleObj reference=classobj.getStyle(0); assert(style.refcount == 3, "testGetStyleObjDestroy precondition"); map=null; layer=null; classobj=null; style=null; gc(); assert(reference.refcount == 2, "testGetStyleObjDestroy"); } public void gc() { for (int i=0; i<100; i++) { GC.Collect(); GC.WaitForPendingFinalizers(); } } public void assertNotNull(object o, string test) { if ( o != null ) Console.WriteLine("\t- "+test+" PASSED"); else { Console.WriteLine("\t- "+test+" FAILED"); ++fails; } } public void assert(bool val, string test) { if ( val ) Console.WriteLine("\t- "+test+" PASSED"); else { Console.WriteLine("\t- "+test+" FAILED"); ++fails; } } } mapserver-7.4.3/mapscript/csharp/examples/drawmap.cs000066400000000000000000000060771357574274700226520ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to create an image given a mapfile. * Author: Tamas Szekeres, szekerest@gmail.com * Yew K Choo, ykchoo@geozervice.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using OSGeo.MapServer; /// /// A C# based mapscript mapscript example to create an image given a mapfile. /// class DrawMap { public static void usage() { Console.WriteLine("usage: DrawMap {mapfile} {outfile} {imagetype optional}"); System.Environment.Exit(-1); } public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 2) usage(); mapObj m_obj = new mapObj(args[0]); if (args.Length >= 3) { Console.WriteLine("Setting the imagetype to " + args[2]); m_obj.setImageType(args[2]); } Console.WriteLine ("# Map layers " + m_obj.numlayers + "; Map name = " + m_obj.name); for (int i=0; i /// A C# based mapscript example to draw the map directly onto a GDI device context. /// class DrawMap { public static void usage() { Console.WriteLine("usage: DrawMapDirect {mapfile} {outfile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 2) usage(); mapObj map = new mapObj(args[0]); Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name); for (int i = 0; i < map.numlayers; i++) { Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name); } try { // Create the output format outputFormatObj of = new outputFormatObj("CAIRO/WINGDI", "cairowinGDI"); map.appendOutputFormat(of); map.selectOutputFormat("cairowinGDI"); Bitmap mapImage = new Bitmap(map.width, map.height, PixelFormat.Format32bppRgb); using (Graphics g = Graphics.FromImage(mapImage)) { IntPtr hdc = g.GetHdc(); try { // Attach the device to the outputformat for drawing of.attachDevice(hdc); // Drawing directly to the GDI context using (imageObj image = map.draw()) { }; } finally { of.attachDevice(IntPtr.Zero); g.ReleaseHdc(hdc); } } mapImage.Save(args[1]); } catch (Exception ex) { Console.WriteLine( "\nMessage ---\n{0}", ex.Message ); Console.WriteLine( "\nHelpLink ---\n{0}", ex.HelpLink ); Console.WriteLine( "\nSource ---\n{0}", ex.Source ); Console.WriteLine( "\nStackTrace ---\n{0}", ex.StackTrace ); Console.WriteLine( "\nTargetSite ---\n{0}", ex.TargetSite ); } } } mapserver-7.4.3/mapscript/csharp/examples/drawmapDirectPrint.cs000066400000000000000000000105451357574274700250150ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to draw the map directly onto a GDI * printing device context. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using System.Drawing; using System.Drawing.Printing; using OSGeo.MapServer; /// /// A C# based mapscript example to draw the map directly onto a GDI printing device context. /// class DrawMap { public static void usage() { Console.WriteLine("usage: DrawMapDirectPrint {mapfile} {printername}"); System.Environment.Exit(-1); } static mapObj map; public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 2) usage(); map = new mapObj(args[0]); Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name); for (int i = 0; i < map.numlayers; i++) { Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name); } try { PrintDocument doc = new PrintDocument(); doc.PrintPage += new PrintPageEventHandler(doc_PrintPage); // Specify the printer to use. doc.PrinterSettings.PrinterName = args[1]; doc.Print(); } catch (Exception ex) { Console.WriteLine( "\nMessage ---\n{0}", ex.Message ); Console.WriteLine( "\nHelpLink ---\n{0}", ex.HelpLink ); Console.WriteLine( "\nSource ---\n{0}", ex.Source ); Console.WriteLine( "\nStackTrace ---\n{0}", ex.StackTrace ); Console.WriteLine( "\nTargetSite ---\n{0}", ex.TargetSite ); } } static void doc_PrintPage(object sender, PrintPageEventArgs e) { // Create the output format outputFormatObj of = new outputFormatObj("CAIRO/WINGDIPRINT", "cairowinGDIPrint"); map.appendOutputFormat(of); map.selectOutputFormat("cairowinGDIPrint"); map.resolution = e.Graphics.DpiX; Console.WriteLine("map resolution = " + map.resolution.ToString() + "DPI defresolution = " + map.defresolution.ToString() + " DPI"); // Calculating the desired image size to cover the entire area; map.width = Convert.ToInt32(e.PageBounds.Width * e.Graphics.DpiX / 100); map.height = Convert.ToInt32(e.PageBounds.Height * e.Graphics.DpiY / 100); Console.WriteLine("map size = " + map.width.ToString() + " * " + map.height.ToString() + " pixels"); IntPtr hdc = e.Graphics.GetHdc(); try { // Attach the device to the outputformat for drawing of.attachDevice(hdc); // Drawing directly to the GDI context using (imageObj image = map.draw()) { }; } finally { of.attachDevice(IntPtr.Zero); e.Graphics.ReleaseHdc(hdc); } e.HasMorePages = false; } } mapserver-7.4.3/mapscript/csharp/examples/drawmapGDIPlus.cs000066400000000000000000000070031357574274700240300ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to draw the map directly onto a GDI+ bitmap. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using OSGeo.MapServer; /// /// A C# based mapscript example to draw the map directly onto a GDI+ bitmap. /// class DrawMap { public static void usage() { Console.WriteLine("usage: DrawMapGDIPlus {mapfile} {outfile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 2) usage(); mapObj map = new mapObj(args[0]); Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name); for (int i = 0; i < map.numlayers; i++) { Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name); } try { Bitmap mapImage = new Bitmap(map.width, map.height, PixelFormat.Format32bppRgb); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); using (imageObj image = map.draw()) { BitmapData bitmapData = mapImage.LockBits(new Rectangle(0, 0, image.width, image.height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb); try { if (image.getRawPixels(bitmapData.Scan0) == (int)MS_RETURN_VALUE.MS_FAILURE) { Console.WriteLine("Unable to get image contents"); } } finally { mapImage.UnlockBits(bitmapData); } Console.WriteLine("Rendering time: " + stopwatch.ElapsedMilliseconds + "ms"); mapImage.Save(args[1]); } } catch (Exception ex) { Console.WriteLine( "\nMessage ---\n{0}", ex.Message ); Console.WriteLine( "\nHelpLink ---\n{0}", ex.HelpLink ); Console.WriteLine( "\nSource ---\n{0}", ex.Source ); Console.WriteLine( "\nStackTrace ---\n{0}", ex.StackTrace ); Console.WriteLine( "\nTargetSite ---\n{0}", ex.TargetSite ); } } } mapserver-7.4.3/mapscript/csharp/examples/drawmapWPF.cs000066400000000000000000000077611357574274700232300ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to draw the map directly onto a WPF image. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using System.IO; using System.Diagnostics; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using OSGeo.MapServer; /// /// A C# based mapscript example to draw the map directly onto a WPF image. /// class DrawMap { public static void usage() { Console.WriteLine("usage: DrawMapWPF {mapfile} {outfile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 2) usage(); mapObj map = new mapObj(args[0]); Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name); for (int i = 0; i < map.numlayers; i++) { Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name); } try { WriteableBitmap mapImage = new WriteableBitmap(map.width, map.height, 96, 96, PixelFormats.Bgr32, null); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); using (imageObj image = map.draw()) { // Reserve the back buffer for updates. mapImage.Lock(); try { if (image.getRawPixels(mapImage.BackBuffer) == (int)MS_RETURN_VALUE.MS_FAILURE) { Console.WriteLine("Unable to get image contents"); } // Specify the area of the bitmap that changed. mapImage.AddDirtyRect(new Int32Rect(0, 0, map.width, map.height)); } finally { // Release the back buffer and make it available for display. mapImage.Unlock(); } Console.WriteLine("Rendering time: " + stopwatch.ElapsedMilliseconds + "ms"); // Save the bitmap into a file. using (FileStream stream = new FileStream(args[1], FileMode.Create)) { PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(mapImage)); encoder.Save(stream); } } } catch (Exception ex) { Console.WriteLine( "\nMessage ---\n{0}", ex.Message ); Console.WriteLine( "\nHelpLink ---\n{0}", ex.HelpLink ); Console.WriteLine( "\nSource ---\n{0}", ex.Source ); Console.WriteLine( "\nStackTrace ---\n{0}", ex.StackTrace ); Console.WriteLine( "\nTargetSite ---\n{0}", ex.TargetSite ); } } } mapserver-7.4.3/mapscript/csharp/examples/drawquery.cs000066400000000000000000000146531357574274700232410ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to use the atribute query and * highlight the results. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using OSGeo.MapServer; /// /// A C# based mapscript example to use the arribute query an highlight the results. /// class DrawQuery { public static void usage() { Console.WriteLine("usage: QueryMap {mapfile} {query string} {outfile} {-zoom}"); System.Environment.Exit(-1); } public static void Main(string[] args) { Console.WriteLine(""); if (args.Length < 3 || args.Length > 4) usage(); bool ZoomToResults = (args.Length == 4 && args[3] == "-zoom"); mapObj map = new mapObj(args[0]); Console.WriteLine ("# Map layers " + map.numlayers + "; Map name = " + map.name); QueryByAttribute(args[1], map, ZoomToResults); map.querymap.status = mapscript.MS_ON; map.querymap.color.setRGB(0,0,255,255); map.querymap.style = (int)MS_QUERYMAP_STYLES.MS_HILITE; try { imageObj image = map.drawQuery(); image.save(args[2],map); } catch (Exception ex) { Console.WriteLine( "QueryMap: ", ex.Message ); } } private static bool IsLayerQueryable(layerObj layer) { if ( layer.type == MS_LAYER_TYPE.MS_LAYER_TILEINDEX ) return false; if(layer.template != null && layer.template.Length > 0) return true; for(int i=0; i 0) return true; } return false; } public static void QueryByAttribute(string qstring, mapObj map, bool zoomToResults) { Console.WriteLine("\nPerforming QueryByAttribute:"); try { layerObj layer; rectObj query_bounds = null; for (int i = 0; i < map.numlayers; i++) { layer = map.getLayer(i); if (layer.connection != null && IsLayerQueryable(layer)) { Console.WriteLine("Layer [" + i + "] name: " + layer.name); BuildQuery(layer, qstring); // zoom to the query results using (resultCacheObj results = layer.getResults()) { if (results != null && results.numresults > 0) { // calculating the extent of the results if (query_bounds == null) query_bounds = new rectObj(results.bounds.minx, results.bounds.miny, results.bounds.maxx, results.bounds.maxy,0); else { if (results.bounds.minx < query_bounds.minx) query_bounds.minx = results.bounds.minx; if (results.bounds.miny < query_bounds.miny) query_bounds.miny = results.bounds.miny; if (results.bounds.maxx > query_bounds.maxx) query_bounds.maxx = results.bounds.maxx; if (results.bounds.maxy > query_bounds.maxy) query_bounds.maxy = results.bounds.maxy; } } } } } // setting the map extent to the result bounds if (query_bounds != null) { if (zoomToResults) { map.setExtent(query_bounds.minx, query_bounds.miny, query_bounds.maxx, query_bounds.maxy); map.scaleExtent(1.2, 0, 0); // increasing the visible area Console.WriteLine("Current map scale: 1:" + (int)map.scaledenom); } } else Console.WriteLine("The query returned 0 results ..."); } catch (Exception e) { Console.WriteLine("QueryByAttribute: " + e.Message); } } private static void BuildQuery(layerObj layer, string qstring) { if (layer != null && layer.map != null) { /*layer.open(); string qs = ""; string att = ""; for (int i=0; i < layer.numitems; i++) { if (qs == "") { qs = "("; att = layer.getItem(i); } else { qs += " OR "; } qs += "'[" + layer.getItem(i) + "]'='" + qstring + "'"; } qs += ")"; layer.close();*/ string qs = qstring; string att = null; Console.WriteLine("Query string: " + qs); try { layer.queryByAttributes(layer.map, att, qs, 1); } catch (Exception e) { Console.WriteLine("BuildQuery: " + e.Message); } } } } mapserver-7.4.3/mapscript/csharp/examples/getbytes.cs000066400000000000000000000053271357574274700230420ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based mapscript example to show the usage of * imageObj.getBytes. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using System.Drawing; using System.IO; using OSGeo.MapServer; /// /// A C# based mapscript example to show the usage of imageObj.getBytes. /// class GetBytes { public static void usage() { Console.WriteLine("usage: getbytes {mapfile} {outfile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length < 2) usage(); try { mapObj map = new mapObj(args[0]); using(imageObj image = map.draw()) { // solution 1 Console.WriteLine ("Drawing map: '" + map.name + "' using imageObj.getBytes"); byte[] img = image.getBytes(); using (MemoryStream ms = new MemoryStream(img)) { Image mapimage = Image.FromStream(ms); mapimage.Save(args[1]); } // solution 2 Console.WriteLine ("Drawing map: '" + map.name + "' using imageObj.write"); using (FileStream fs = File.Open("_" + args[1], FileMode.OpenOrCreate, FileAccess.ReadWrite)) { image.write(fs); } } } catch (Exception ex) { Console.WriteLine( "GetBytes: ", ex.Message ); } } } mapserver-7.4.3/mapscript/csharp/examples/inline.cs000066400000000000000000000130131357574274700224610ustar00rootroot00000000000000/****************************************************************************** * $Id: shapeinfo.cs 7418 2008-02-29 00:02:49Z nsavard $ * * Project: MapServer * Purpose: A C# based based mapscript example to dump information from * a shapefile. * Author: Tamas Szekeres, szekerest@gmail.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using System.Collections; using OSGeo.MapServer; /// /// A MapScript application for creating inline layers with annotations. /// class Inline { public static void usage() { Console.WriteLine("usage: inline [outformat] [outfile]"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length < 2) usage(); // creating a new map from scratch mapObj map = new mapObj(null); // adding a layer layerObj layer = new layerObj(map); layer.type = MS_LAYER_TYPE.MS_LAYER_POINT; layer.status = mapscript.MS_ON; layer.connectiontype = MS_CONNECTION_TYPE.MS_INLINE; // define the attribute names from the inline layer layer.addProcessing("ITEMS=attribute1,attribute2,attribute3"); // define the class classObj classobj = new classObj(layer); classobj.template = "query"; // making the layer queryable // setting up the text based on multiple attributes classobj.setText("('Shape:' + '[attribute1]' + ' Color:' + '[attribute2]' + ' Size:' + '[attribute3]')"); // define the label classobj.label.outlinecolor = new colorObj(255, 255, 255, 0); classobj.label.force = mapscript.MS_TRUE; classobj.label.size = (double)MS_BITMAP_FONT_SIZES.MS_MEDIUM; classobj.label.position = (int)MS_POSITIONS_ENUM.MS_LC; classobj.label.wrap = ' '; // set up attribute binding classobj.label.setBinding((int)MS_LABEL_BINDING_ENUM.MS_LABEL_BINDING_COLOR, "attribute2"); // define the style styleObj style = new styleObj(classobj); style.color = new colorObj(0, 255, 255, 0); style.setBinding((int)MS_STYLE_BINDING_ENUM.MS_STYLE_BINDING_COLOR, "attribute2"); style.setBinding((int)MS_STYLE_BINDING_ENUM.MS_STYLE_BINDING_SIZE, "attribute3"); Random rand = new Random((int)DateTime.Now.ToFileTime()); ; // creating the shapes for (int i = 0; i < 10; i++) { shapeObj shape = new shapeObj((int)MS_SHAPE_TYPE.MS_SHAPE_POINT); // setting the shape attributes shape.initValues(4); shape.setValue(0, Convert.ToString(i)); shape.setValue(1, new colorObj(rand.Next(255), rand.Next(255), rand.Next(255), 0).toHex()); shape.setValue(2, Convert.ToString(rand.Next(25) + 5)); lineObj line = new lineObj(); line.add(new pointObj(rand.Next(400) + 25, rand.Next(400) + 25, 0, 0)); shape.add(line); layer.addFeature(shape); } map.width = 500; map.height = 500; map.setExtent(0,0,450,450); map.selectOutputFormat(args[0]); imageObj image = map.draw(); image.save(args[1], map); //perform a query layer.queryByRect(map, new rectObj(0, 0, 450, 450, 0)); resultObj res; shapeObj feature; using (resultCacheObj results = layer.getResults()) { if (results != null && results.numresults > 0) { // extracting the features found layer.open(); for (int j = 0; j < results.numresults; j++) { res = results.getResult(j); feature = layer.getShape(res); if (feature != null) { Console.WriteLine(" Feature: shapeindex=" + res.shapeindex + " tileindex=" + res.tileindex); for (int k = 0; k < layer.numitems; k++) { Console.Write(" " + layer.getItem(k)); Console.Write(" = "); Console.Write(feature.getValue(k)); Console.WriteLine(); } } } layer.close(); } } } }mapserver-7.4.3/mapscript/csharp/examples/shapeinfo.cs000066400000000000000000000047011357574274700231630ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based based mapscript example to dump information from * a shapefile. * Author: Tamas Szekeres, szekerest@gmail.com * Yew K Choo, ykchoo@geozervice.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using System.Collections; using OSGeo.MapServer; /// /// A C# based mapscript mapscript to dump information from a shapefile. /// class ShapeInfo { public static void usage() { Console.WriteLine("usage: shapeinfo {shapefile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length != 1) usage(); Hashtable ht = new Hashtable(); ht.Add(1,"point"); ht.Add(3,"arc"); ht.Add(5,"polygon"); ht.Add(8,"multipoint"); shapefileObj shpObj = new shapefileObj(args[0],-1); Console.WriteLine ("ShapeType = " + ht[shpObj.type]); Console.WriteLine ("Num shapes = " + shpObj.numshapes); Console.WriteLine ("(xmin, ymin) = (" + shpObj.bounds.minx + "," + shpObj.bounds.miny + ") (xmax, ymax) = (" + shpObj.bounds.maxx + "," + shpObj.bounds.maxy + ")"); } }mapserver-7.4.3/mapscript/csharp/examples/shpdump.cs000066400000000000000000000052661357574274700226760ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: A C# based based mapscript example to dump information from * a shapefile. * Author: Tamas Szekeres, szekerest@gmail.com * Yew K Choo, ykchoo@geozervice.com * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ using System; using OSGeo.MapServer; /// /// A C# based mapscript mapscript to dump information from a shapefile. /// class ShapeDump { public static void usage() { Console.WriteLine("usage: shpdump {shapefile}"); System.Environment.Exit(-1); } public static void Main(string[] args) { if (args.Length != 1) usage(); shapefileObj sf_obj = new shapefileObj(args[0],-1); shapeObj s_obj = new shapeObj(-1); for (int i=0; i) install(FILES ${mapscript_files} DESTINATION ${CMAKE_INSTALL_LIBDIR}) mapserver-7.4.3/mapscript/java/README000066400000000000000000000047571357574274700173760ustar00rootroot00000000000000Java mapscript ============== WARNING: Starting with version 6.1 Mapserver (and Mapscript) uses libtool to build the shared libraries. Some files have changed names and the javamapscript.so shared library now depends on libmapserver.so. The easiest way way to handle the dependency is to simply use the 'make install' target. To generate the SWIG wrappers you need swig > 1.3.24. MAPSCRIPT Reference ------------------- The complete reference documentation is available on-line: http://mapserver.gis.umn.edu/docs/reference/mapscript or in the file: ../doc/mapscript.txt SWIG wrappers ------------- MapServer releases, beginning with 4.2.4, contain pre-generated wrapper code (mapscript/java/mapscript_wrap.c) and class files (mapscript/java/edu). Nevertheless it is recommended that you generate your own using the "interface" target in the Java Makefile. Requires swig > 1.3.24. Version above 1.3.28 or 1.3.29 are recommended. Installation ------------ After MapServer is configured and compiled, change directory to the Java mapscript location and execute: $ cd mapscript/java $ make $ make test (recommended) $ make threadtests (optional) $ make install (required as of 6.1) Remember to set the appropriate variable (LD_LIBRARY_PATH, java.library.path or edit /etc/ld.so.conf) to make sure Java can locate and load the libraries. Windows ------- Edit makefile.vc to match your environment. You will need to set JAVA_HOME and SWIG_HOME to the appropriate variables. You will likely need to copy all of the DLLs needed to run MapServer into the mapscript/java directory (including libmap.dll) so the mapscript.dll can see them to run. cd mapscript/java nmake /f makefile.vc nmake /f makefile.vc test International language support ------------------------------ Since May 2006 Java mapscript has complete support for international languages usage in queries and mapscript internals. To document this improvement we have created the examples/QueryByAttributeUnicode.java test program which uses the ISO-8859-15 encoding. http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1753 http://thread.gmane.org/gmane.comp.gis.mapserver.user/19298/focus=19298 http://thread.gmane.org/gmane.comp.gis.mapserver.user/19213/focus=19213 Onlice resources ---------------- Java mapscript related: http://mapserver.gis.umn.edu/docs/howto/javamapscript http://mapserver.gis.umn.edu/docs/howto/java_mapscript_Tomcat_55 http://mapserver.gis.umn.edu/docs/faq/thread_safety General: http://mapserver.gis.umn.edu/docs mapserver-7.4.3/mapscript/java/data/000077500000000000000000000000001357574274700174125ustar00rootroot00000000000000mapserver-7.4.3/mapscript/java/data/emptymap.map000066400000000000000000000001411357574274700217410ustar00rootroot00000000000000MAP NAME "Niedersachsen" EXTENT 3400000 5700000 3700000 6000000 SIZE 500 500 END mapserver-7.4.3/mapscript/java/data/iso-subset.dbf000066400000000000000000000004571357574274700221720ustar00rootroot00000000000000_WKREIS_KENNCKREIS_NAMEC<EWN 07337 Sdliche Weinstrae 109375 07339 Mainz-Bingen 194156mapserver-7.4.3/mapscript/java/data/iso-subset.shp000066400000000000000000002655501357574274700222400ustar00rootroot00000000000000' zp?IAkFTA'J_JAt?,UAt- JAkFTATJA儽TAm }CJ/JAX^/TAպN/JA:L TATN/JA\TA7HSN/JATAX/JA9鸻üTAZ^/JAEVTAj\`/JA◼TAi\/JA琼TAQYrZ/JA^[TA;X/JATAV/JAyTA!V/JAYTAak/JAҮWtv.TA;"0 W/JA斘Q"TAd/JA…%TA<\^Bj/JAۇاTAw/JA<0jTAk~/JA`TAr/JATAѮ{z/JA$q-TA/JAXTA;pc/JA^TAe./JAԧݻTAk/JA|ݒƻTA /JACpTAi ,/JA siTAÔ/JA%TAwĽ/JA|Q_ TAz/JAA֝2TAu>/JAhhIb׺TAE/JA +0=κTA`S/JAҍTAE/JA`6TA|/JA[~TAơ/JA8nTA b/JAe{тVTA#WR0JAM)TA\W0JAݒC$TAhP0JA" TA =/0JA.5TAF/JA&ٹTA+u/JAWTAa k/JAxTwTAc/JA?[TA>- /JA2%`HTA/JA@%TAa /JA2 )TAQݯ/JA,.sTA ./JAAظTA\B/JAĿ^ǸTA!/JATJTA=?n/JAÖ8~TA|(/JA` TA!/JAġdTA/JAnB-TAS/JAlT(TA@dky/JAA; TAcrnc/JAݷTAur/JA|`ٷTAJF,/JA uTA. /JAQ!l㤷TA-v.JAu_#TAg$.JAVZTA֧.JA-MGTA؁.JAjm/!TAO%.JA TA}.JAgTAy.JAs>TA`y%.JA[TAr.JABͶTAI=/JA +TA/JA HTA8.JA TA.JAqcvoTAAh /JA:ϜhTA#Z.JA`ZTA u2.JAkFTA.JAL=PTA{".JA źTTA .JAq|bXTAwi.JAXEYTAŨ.JAq)VTAp?N.JA@&VTAkt.JA[*WTAY.JA4YTAA9.JAp[TA68.JAk&_TA9o.JAX¼dTA/+5.JAsWhTAе.JAumTA?k.JASLmTA\ `.JA94rTAaV[.JA禣xTA';AAl.JA`@yTAk}s.JA)|TA~2i.JA{ݸTAӮ}.JATA)q.JA72#ΙTAp.JATAxas.JARTASy.JAcYDTA>ry.JAwI5TAlj.JA܏ŲTAl0e.JA9UTAѓZ.JAugTA `.JA9|ʶTAh]-K.JA~=޶TAH.JA TAlCH.JAOTAM.JAf`TA=.JAmTA|Z/.JA\eTA<;+.JAWNW>TA-JAJgDTAhK-JAMA]=TAq-JA‰? TA9`-JA(TAf*(-JATA2g-JAg TA^N-JAjmTAlޅ-JAƫTA.rz-JA;{yTAdAx-JA" TAFq-JA՝"TAFki-JA) #TAs_-JAT&TA4BP-JA.TAI-JAi3TApB-JA4:TAr<<-JANqITA/-JArQTAb,-JA:P\TA̖%-JAs\N%cTAuQ#-JAj jTAd-JAw%*pTAn5Je-JA-&vTAo-JA1{TA{-JA{TTASFI-JAʾTAy,JAe%TA`,JA/$TAx?,JATAA,JA@TA;(,JA}JTA)q],JAo TAUv՛,JAhTA(2B,JATA\,JAZ_`TA:\%,JAP1TAx,JAACTA`,JAŷTAڴg,JAu طTA׸O,JAܷTA,=I,JAPv߷TAH,JAÄScTA6?,JA^uTA- ,JAOTA+JA-TAQթ+JAܷTAK4+JAzm۷TA%+JAaI۷TA d+JAN޷TA3T +JATAJ+JA5CvTA܌+JAh¼TA̡+JA>0TA+JABq$yTAґ+JA TA+JAG]TA'o+JA@_(TA`Jj+JAޛTA{+JA.KTAq+JA XTA.p+JAd]TAoC`+JAwܓSTAiT+JAlTAyK+JAJTAC+JA-c|TAP7ѝ8+JAfTA H 3+JA, 1TAY٬4+JA"TTA00?+JA qTA&D+JAQ^TAxH+JAŊTAl[-+JAOTAm%+JAo TAgԷ+JA8GTA+JA]\=TAx+JATAԃ+JA)TA +JAgTA|*JAdTA*JA;0! TA *JA0TAO"U3*JAѥTAn*JA0yTA*JA2sTAY*JAF\_TA:Oꦄ*JA`TA8z*JA`>gTAg*JA̐z!TA ]Q*JA9%TAG*JA.!g+TAz%>*JA8r!,TAq\3*JAXm5TA/*JA ?K~gTAa+Q4)JA\TAm+)JAz[TA7")JA]TA|=D)JA)@cTA {-)JAR2McTAsS )JAi`TA>Y<(JA7bTA;s}(JAm߶`TAs(JA-^TAZ (JA0(ZTAͤE(JA`GW ZTAK(JA7VYTAV[LTAt&JAu%JA/T~ATA?Ө%JABDTAL%JA2lETAB3:,%JANTA7%JARTA9v%JAdJUTAՠ%JAҟVTAiA%JA΅UTA#^%JA5PRTAЋ%JAڟMTAl.d%JA vTA}!o=$JARIwTAd$JAq!|TA`~$JAPod7TABB-$JASˉTA5X$JAZTAX$JAqqTAY`Î$JAI]ՋTAz$JA @HTAFsj$JA?ֱTAa$JAITAD~C$JATA$A6$JA)!TA~:#$JAJ1TA$JALTAQ#JA0'>TA$l#JAZQTA&#JAs~船TAD#JAֿ,TAKMĊ#JAz\yTA_5#JA7STAK+x#JA"~TA%_#JAqh}TAhqV#JAWn{TAx[#JAxTAѹr4#JAZa^wTA0><#JArTA:˒#JACiTAܭ#JAZoTAuм~#JA7 pTAVv#JA%6XmTA@,Sg#JA3dTAXA\#JA26hTA -G#JAJgTAe|RB#JA܆eTA?#JA(d_TA`?#JA5[TA!JATAl !JAaaQTAr!JA6ǃTAH=!JA@J֓TA]Y!JAUuTAI!JA,ᴹTAF!JAõTA-&{!JAR1TASKd!JAE`TASwYK\!JArpŹTA蚫$z!JAJ"ֹTAg>!JA]ӹTAg1Y!JAG8ܹTA(!JATA(5!JA&n_uTAJs!JA~u$TA+go!JATAXio!JA)TAοg!JAbGTA/t\`!JA TAVWe!JATA;)X!JASTAM@QL!JA)TAs~Rf%TA}I!JA=?TA^ilK!JACq+OTAAI!JAGϐWTA;hC!JA@ǰXXTA劓6!JA kVTAFX JABKnKTAǟ' JADU!JTAF_ JAJTḀ JA.מbUTA  JA)cTA JAATAmd. JA}uTA JA@TAYk JAcsɥTAn JA|ѳTAp JAEĺTA{- JAŪ_кTAU/ JAv'غTAa JAu*TAW JA AITA`c JA\TA{^{ JAyXTA\ JAO7 TA6D JAQPTA$z LJAhTA_jJA^ TA$JACTA8YJAep.TAfJATAv:ZTAbR JA#J^TA rJA߅2\^TA}j%JA.hTA|N\JAL,iTAjJAwqTA%|JA=+}tTAoխJAB;TAxJAmTAsJAvXTA tJA`YQTAHt$JA#TA}qJA̻TA|`JA4ػTAyqJAuݻTAlJJATA̺JAs@=TAJA4*TAKpJANn`:.TA|X>JA5TAN?JAֈ@TAF=JA# QTA(JA[s[TA#[IJAbTAܚJAWiTAJATK{TA%40JAvvTA|7JA(ZcTAMK*"JAbTAOqÿJALB]TAɉ$JATAyJ#JA- .TAEzJA<`kTA>qJAgtgTA[1dJAgTATJAO|6TArJJAwTAFJAIӻTAeEkJARfCTA:JA⹝TA"傖JA RüTAm%vJAWYdTATwJA{,TAt[JzJAo^TAFJA7=|TA[JA_@rTAWڅJA)dTA1}JA$ZTA̭)JA<5TA'JAwk TAdJA'|TA3JAsHTAэJAS TAƔJApxѻTA<_JAƻTAۛJA TA5|JA/TAP%JANijTAhJAj4(֙TAoCJA0|MTAKJAr߉TAD)!JAbwTAWoJAƤ6lqTAc|JAxqtkTAzJA[;bTA e0tJA~fUTA3dJAMOETA|GZJAm>TA44cQJA\8X;TA+=|@JAc 7TAм&JA(_3TA6\JA -TANl JA:|'TAktJAH7TA"JA?TAkJAh TAG_mJA|TAL>KJAEpTAN_JAdTA24JA"TA&JAOtTA" JAxTAsoJA8QںTA _JAfߺTA]^WJAh)TAJAi mTAejJAϸTAB2~JATADJA)߲TA_ 1JAq\TA\3ԋJAoHTA򰙍JA'TAJA[ TA#JAWO6,TAG?[JAC4TAٲ-JAZڔCTAJA5LTA GJAUTA/rJAѸneTApJALaTA*JAhZTA &JA`TAFJJA_AYfTAt;hJADpTA}Z7JA`䂻TA)u5JAm;9ьTAW1(JA\DZTAsJAjxTAC]JAE TA |JA2#DTA#@/JAVTA:JAL -TA'JA"NTANJAk#|fTA&JA)`rTA6[JAdzTA+, tJA͆TA?JA~W8TA \*JA>TAR~JA7TAف9]JANOTAJ÷JJAxiJTA^ܸ JArUXTAJA1TA7+JA=, TA$cJAIԖTAK )JACTA=ͭJAԷxXTAϬJA0 J'TA[@qBJA|zTALڎtlJA^~ uTA`e\JA-3tTAcPJAfzTAֵJA]fTA<-o JAË]TAJAJAETA JA뺒ؽTA~OU;JAڔTAP|JAOTAzSJAd";TAْJA<ATAJAg~FTAWJADSTAݵJA VTA JA_&ZTAkXJApFBeTAJA`;kTAQ 5JA9yTAVJAs/lTA{fSJAUmTAj JA=TAׂ$JA UTA{K4JAѾG\TAlq6JAnTA"D+JA4徾TA(JAO¾TA吘*JA`3ɾTA/-+JAܾTAl.1JAuTA92JA2TAG4JAe-TAH7JA<,TA1JAi+d} TA }!JAvTA3bJALTAYJA"!TAQJAT^.TA>+JAH7TA jMJAS([TA yJAlTAje{JA8`TA4UxJA(TAkJAiTAsJAuQȿTAMK%JANTA[m:JAiBTA5?EJApyTA u@mJAquTA`JAfBOATAa JA0 GTAiN΀JAAVLTAJAPTA@JAMWFTTA_fOJA*yYTAJA`TAf)xFtJA cTA{TlJA&3hTA6^JA^Z@xTA*0ߎJAaYVsTA,JAuTA+|.JAƥTA&QJAJCTr\TAIѕJA&fbTADJAhTAm2\JAGATAiA3JA@ZcTAMJAv,0(TA0ُJA~bTAeeJA(vTAbJAxxSTAOpJAoTA4bJAL TAn JA"}TA-xJATAaJA#8'TArq xJA+QTA}JAبpTA8JA!k>TAE?JA*TARKRNJAc!#&JAn0TA@ JAJaVTAmMJA]- %gTA4_JA(;gTA`@isJA78VgTA?PJAl%`TAO"p+JAvڊWTA)hJAlFTAΧRJAYw35TAJAO0TAJA̡n7TA}xaԉJAEVTAm6|JAw~JAT&TAJ,~JA{TA,0}JA4TA6$yJAx&TAGVJAL%]TAO@JA TA~JA'TAuJAM/TAFӔ\JA1R6kTA17JA$ŸTAJAp1TA:JA#-TARV;JAՇiTAnl(JAaTA鶏JA ZrTAnJA LTAe:@JA7NTA:JAKTA]JATAfJAUصTAvXDJA TA2KJA}4,TAcJAiATAL.JAtWOTA|JZJA5T_TAWJADbTAJAkcTA)W JA!eTAV`tJAXiTA?opJAt*kTAPJAxTAHòJAPTA/-oJAdz ҔTA! WJAVڢTA4wJAͱTAl9JAzJ>TADJAemKTAlR*JApN[TAvŽJAFaTAXurYJAsYlTA;JA@t5xTA؇E JAoTAMJA=UdTAڕJAwUTA@YJAwOTAy JAgJTAhlJAo.rHTA5%@JAgETA D^JA!>)TAdDbJA$TA_GVJAgTAqMٌJA4OTAx(5bJA|TATA0AJA(TAêJAcJAu TA$ƵJJA߿TAH';JA4zTA,JATA9i9$JA?TA "JATAmD<JA:HTAC2 "JAfQTAFJAА(TAQJAFdTAԗy6JAۍ^TA؏JATA͋{:JAۜ-TAJAu]/TA˄JA{P4TAӸJA 8TAkPJAs@TAgzx?JANv1TAf6:JAl76TA2!JAYT4TA}"JA*+5TARJAJ\LTALJAgCUZTAv JAT݅WbTAT*JAo4FmTAKW?JAI2XuTAG5UJA/TA_NnJANmTAap~JA$ÎTAa8JAjTAP`|CJAP4lTAJATA3JAM!{TAVJAd `TAJAqTA.ԽJATA/#JA6TA">JAO;TAvVJAf;WTA:JAtTAĵIJAF TA 3P JA4isTA'JA|{TA~&0JA?TAO* JAFmETA6_JA4!7QTAI5/JA>)#\TA"%JAjTAp JA mTALJAg|ETAcڀJA/sw~TA`)_JAlTAf JAeԹTA ֈJATA'v8(#JA^RTAv\/JATAd87JAw`ϯTASFJA TAJAsUaNTAnoqJAO;dTA`ZJAu9TAsg(JAe޳TAyON"JA $ֿTAF/JAnTAz8JATA60JATA58-JA:6_TA2Z*JAm_TATxq@AJAؼTA|k JA@TAMD JABTA/HJA+TApJA3UTA_JAmF,nTAݴwJA^,rTAj3JA9˞TA] JAK\TAx_JA/p{bTA6JA]TAfJA}B7TAwszJAl@TAcb.JA uJTAAUJAdTA<1JAN TA9_JA"Z^ TAkR_JAzGITALJArTA(JAJ7TA}SJAqTAg*JA#c$TA9JA+JTA`uJAܼTADNJAZqTAy6JA0]TAw8JAZ TA)h<JA$)TA9JAJ[TA!JA MDTATPJA||5=TAaJAvhsTAwoJAH TA<`]JAM|=TA?JAIeTA,Y&JA;qPTA ` zJAqTAi^ JA{TAkIR JATA=oJA+3TAm\JACk:TAUk JAF4TA+-?JATA~#JA#TAX@JA"fTA\+JAT TAԷtZJAc4"TAԾmzJA]62TAa_JAaTAq e=JATA+!*JALTAaQ_JATAm$pJATAT}JA[ɆTA׋n,|JA-]TAc \JA2@5TA%AJA黡дTA>$gJA?TAꠦJA{TAHJA3 DTA[:)VJAITAJAUTAJAE ?TAF'JAѳRTAiJATAKf(JA2RTABM/JAwTA`ϓ.JATA%J JA.?S TAz6JA-f.Q'TA,JAN4FTAJAp3QNTAUoJA< VTA*JAZ`TAe JA|qTA"oJANˋ{TA@hJA֧ȉTA&NJAmTA<2JAeTA2j@JA( |TAkzJAFTA8 ƈjJAxo>TAVSJAjEðTA/5:JA !TATtJA0MATA*JA(TA 5JA0ٽTA9JJAg'TAtXJA;TA1OiJA|TA3qJA?tTAN$JA(STAt(JA|qTA/vyaJAwTA/[GJANA(TA@´K"JAl%TAJAud@TA;^>JA$5TA ^`JATAkJA*/U TABlJA?TAK7JAmTAS0JA"TAujJAr'TAs!JA7+TAQJAW?^0TAcEJA 5TA-LEAJA;TAꃾ#JA>TA9JAPGTAoJAL<[TAw.YJA ]bTA:JACUsTAd~JA`h~TAr,rJA;NTAi?,jJA0TA#6[JA TAix+8JA -{TAJA/-lTA@%JAG)eTAECJA,\TAҟvPJAQTA{pJAJM LTA)ZbJAıGTA[JAU 6#DTA{fyTJAx JA\N*TAGr~ JA/#TAq\~ JAk4TAr JA壶TA$L JA'TA# JAu,TAfâ JAJiTAp JA*wTAV JAvDTA> JAy N^TAk󮦠 JAStrTA'3 JAڏTA JA+0LTA} JAZTAPI0 JACtTA JA:sTAw##JAZTAY,JA7~ &TA^TA+vJA)HTA- +JA]TAB#vJAysTAK=JARTATALBJAlTA)&JA0VTA-_9JA9S TAmKJA3> TA @FZJAĺ- TAtJAT}TA'DJARpTA+@JAdo"TA#YlJAU 'TA%JAa+˸TAJA(@TA42 JANO?TAN؛$JAЙmTAB5DJA OTA7rJAAk TAYEJAi+1TA o7JAKTAXD9+JAHxQTA0JAƚyTASsJA]>TAJAufHzTA ieJA$ETA~e$JAv9حTA[(JAԽTA@/JA7TAnb@JAsHTA JAPvTA#?JAj\TAcXJA㛜vTAb:JAf_TA.C=&JAITAnŘ1JA +JTA!DJATA=TJAp1TA GlJAyTA4JAUTAfJAY RTAzNJA?:#TADJAGTAWIYJAæTAڢJAݍTAe#JAxz%TA! JAkTAU]f JAݝqTAإAJA℻TA*'JA9TA͒JAˆTA?̙JA׷߿TAwG JApU(TA[MJASTA VNJA:uVHTA&,#JA/{TA1SJAԢ(TAFTibJATA|JAW̉TAbtJA#nTAspJAzk{TAvnJAhsTA1[oJAǝlTATmtJAyUdTA2vJAduZTABJA(35STAɊJAJITAbɢ JAATA[m ǀJA5TAeJAWTAq40ZJA5hTA(VJAy3TATlWJA^жTAG$OSJA`TAIpFJA(sTAvV"JAFTA@JABKTA! eJA% 5TA7Yg*JA6 TAfmJAj"TA^ٯ;JA{Ǣ TA!/BJA墪TA$JA5~!TA^hJAWTA:tJAB;TAiJAwTAU )JATAgPX}JAjqTA8[yyJATAN{xJA{TA>MyJA:ETAsJACTA?4IkJAslTA^A^JAJgTAΣSL?JA9TA8 (JAK TA5JATAHJA^ KTAxJACTA3wJAۿTAY.rJATA,s+gJAt5TAXJA2?TAGJJA˼GTAJAJATA$5JAׇTTAZzq(JAyUIwTA:*JA3ohTA> 2JArSTA"A=JAsKTAmUJA Th@TAyv:lJA ;9TA5[JAP2TAJA 2,TAkΖJAހTA[JAb TA4JAQ[g6TAǺ JAK$TAP&JA7rTAڊRJAcTA&dJAkTTA!^+JAͯTA0bJA\VDTA̒JA4TAhynJATA3KJA/bTA4JAky[TA  JAQTAS89;JAw@ǻTAFu+uYJAyiTA3cJA-TA*=~mJAOeETAkgJA>pTA䆲JA#LTAm'qJA$!*TAGgYJA\?TAfJA=TAxEJATAA"-JAaheTAAJA|*zTAVJAHTAU&aJA_TA{,SwJATsTA JAK+STA;}UJA,;ݤTAd{JAñqTAz}JAI VTAn+}JA fFTAЯJA-"TAoJA4#TAWJANTAH(JAKTA_/JAQTAW6JA`'TA$/JAݨTAWڔJA)TAڌJAQ@bTA!&g JAaO[TAV@!JA$ @p[TAQZ JAu TApm JApvTA <L JA^TAu٨ JATA&H JA٭TAg0ה JACTA JA8ܾTA!"“ JATA-Ĝ JA|K TA6 JA]TAN+T JAÎTAq JAjo:TA1 JABTA JAyaTA/ة JAuqTAt0 JAwTA̷ JA7[OTAMh JA+TAJEq JA q}TA" JA{PTAw9s JA6zTAmA JATA:O JA鍵TA% JAcѾTA# JA@rTAѯ JAN.UTA'0 JArTA g JAF|TAG JArC3TAI JA*fTAQL JAX-TA7= JAk\TALk JA߳d,TAjY֯ JAϘV5TAu1. JA#=TA6 JAxITA  JA٧PTAT JA}yUTA-C8 JAC7XTAn̺ JA 4\TAcZ JANoaTA{=i JAǂTAB JABKʐTAo JAX6BTAn JAַ?TAn5 JA63TA 2 JA{nTAv JAi TAl$!JAfWTAǡR JA0R#TAF JA+TAֳc JAs0TAX4A JA3nC5TAmg JAcX9TAM>a JACTAr]JAPFTA#JA@TAMHJAmpTArJA0PTAO  eJAM}KTAbQJAO20JTA :JA:ITA6(JAJKOTA6JA) 5MTA nJAMTAD?JACEGTAXH3hJA%jTAaMJAY$TAX*|OJA^ TAOJAw|_@ TArQPJAeTAaNJAvR#TAԦGHJA~ӥ'*TA=N7JADSTA}fJA +kdTAe{JAܢRTAi JA] MTA.JAy"TA@JAv@TA@oJA~}TAۀ3JA;TA#JAA>TA3…JABTA'JA: TA- JA ,(TAH*xJAы,TAJAK`5CTA.aJA(MTA_ݒJAΐ= XTA؊JAeQ]_TA!PJA $hTAZuJAŅuYuTAmJA/]ׁTAJATGTAͻJAKTAz\JAܰpTAm,JAEhTA=JA]ޮTA$IJAq[ضTAujQJA/qTAaŋQJA*QTA-{5KJA'TA!AJA @TAD@֠1JA(TA4,JA1l3TAC.)JAݶTA)JA訽TA++JA-ʮTA'0JAJƞTA7tgIJAu4TAtعLJArq:TALJAGqTA DJA#_!TAR;JA l-TAP~I9JA7TAL+;JA-@TA8DJAA=MTAPJA_%KYTA>SJAYTAeQ>^JA0?XTANJkJAXTAjߥJA\]TA8,JAԱ/^TAxJAG;_TA.V=JAOmaTAJAXcTAd[.JA!klTA8JAMvTARCJA TA_4JAׂcTAMâ@JA7vTA# JA`TAD6JAt1KTAvGJA)TA?SJA:TAIz`[JATAlQyJA0zhTAMXJAMsTA_JAFTAZVїJATAe#GJA* 2TA]JArg^TA?,JA:#>TA PJATA-JAI'mTALJATA>5JATA"5JAvԝTA=_}JA\lTAJAzaTAЮJA~TTASJA0b=TA(JAaCTA3'kJAov#TAifؑ JA{,TA[1$ JA D%TAx;+ JAMTA{eKP3 JAAGxTAj@@ JA.gTAfY JA=JTA  JA8TATǘ׵ JA TAZPû JA2TAU JA4(TAB2 JAn>3TAc! JAD4mTAQ!JATAyA!JAQTA|!JA`q TA.,%!JA.TA:l&!JAp=TAM*!JA%1nATAJ<.!JA|:ETA'7!JAsITA{P@!JAЮKTAL!JA̰MKTAv a!JA9߻ITAi}!JA!JOCTALC!JAى:TA]!JAɺ 7TAo`S!JAr3TA )q!JA@-TA7!JA~+TA,!JA׉8b+TA!JAwg4,TA!JAB/TAgw"JA24TAuf "JAALTAF>"JA2I8XTAT"JA<,wjTA|8Ph"JA-;qTA|Y\"JA܉{TAY_!"JAt%|TA m2"JA8$N^TAu"JApM5TAF"JAῒ3TA ?p"JA*HӪTA-@&#JA>:TAC#JAZ{bTAQ`#JATA0Ej#JAC6ҩTA[(t#JA6[TAR1|#JATAC$#JABTA9rЇ#JAEߔeTA8Bsm#JAH TAV.f#JAF}TAbl_#JATTA~\#JAɻTA!\#JA}iHTA̕^#JA ATA6 $e#JAZTAUoLv#JA*#TA!tM{#JAUTA,#JA5 &TA`#JAۧz TAQ6u#JA,TAz#JA< TA~%#JA',TA#JAf60TA;#JA? s5TAf>[m#JA %;TALpO#JA0O ATAHD#JA`QFTA5B#JA+JTA*C#JAjePTA K#JA6TTAqV'W#JAlSXTA >c#JA꭛iYTAKo#JA¹XTA9X{#JA^VTA+_-#JA"fTAף#JAjTAIb#JAG-D{TA~ #JAz\TAT#JA[hKTA;[#JA(TA>$+$JAITA]$JAn}TA*T)$JAnTA^c2$JAzTAe{A$JAlH]TAkQ$JAc4dTAZ4k$JAE]ҠTAbms$JAFo5TAOy$JAz//TAk#$JA ٙTAϓ$JAׅTA$JATAl$JATA&$JA4gN(JATA6 @)(JA߷LTA&Y(JAATA?'JAc?%STA I'JAIcFTAk'JAdTAw Y'JA=TA-'JAOZTAK*'JA,JA3W~TA),Of,JAowTA|,JA>rTA,JA-kTA:,JAwx^TAӂ΋,JANPTA;0,JA?MTAj:,JAMTACY-JAѭQTA*o -JAxYQTAu0-JA>NTAе?-JAMTAtM-JAВ/LTA!>a-JAP |LTAyl-JA@ДMTA-JA [%XTAC&a-JAYTAI-JA5VTAԨ<.JA?u.JAiВTAO).JA(|!TAƋC.JA{:<"TA!h.JA!TAA.JA I"TANS.JA[3%TA.JAU Q'TA]X.JA_"#TA>/.JA7TA\x#/JAV$TAN~&B+/JAՠ‚$TAYi4/JAQLQ TA01|;/JA0CETAt1(Q/JA5 TAT/JATALZ/JA${TA'-q/JAITA_(!)|/JAbTA? /JA TA͵a)/JATAQV=TA +$2JATA/֡l2JAgG>TA)Fy2JAE =TAls32JA˞:TAn2JAT7TAF2JA_0TAtzd2JA_,TA:8 3JAae TATN3JApgTACiHv3JA7TA{3JAs YTA/В3JA$b~TA(ڬ3JAG TA}3JAX,TAKcD4JA(wTA|gT4JA3TABx4JAfTAx4JAGTAv4JA?TA~J4JAwTA鴅4JATAP4JA8.2lTA~\45JA2$JTA :5JAB=TAM5JA`ݨTA3g5JA%^\TA>A5JA}TAi5JAW.gTAJ.5JAwf\TA(t5JA}MTA+!55JA184>NTA\5JA@RTAf6JA3 j_TA=6JAw:gTA&6JA CkTA>26JA\9oTA):6JA@jXpTAy$B6JAړoTAg L6JAi=iTAu7JA%P`TA|7JA%#`TA 7JA vdTAgSA7JAJsTA4L;>%7JAzTAN=7JAq{TA&I07JA%}TA]7JAM'}TAUi7JAm $|TAD,h7JA 1xTA1$L8JAv/nTAi "8JA.0gTALs>8JA^TA?_C8JA@]TAEH8JAP:ZTA +K'T8JAbnSTAM^8JAk߬OTAZ^g8JA7OGTA3Y8JA=TAќ8JAdl53TA )8JA!I1TA:68JA0TA[8JAS/,TA޷'9JA>:!TA29JAATAgrv79JA!aTA\9JAbTA0ʖ9JA:'FTAW9JA1F"TA-9JAM$TAݖ9JAfr&TAH:JAf2TA+#:JA9y 4TACSK:JA/6TARr^:JA"a7TA~$k:JAJk8TAf":JA 6TA#p:JAB6TAMh:JAX5TA :JA3TAw :JA|oAO2TAi:JApqnITAޱ6H;JAֶTTAb6i;JA[TA.;JANcTA2(;JA\1mTA8F.;JAl[TA$(JA=^TA'E>JA.9bTAvJ>JAքMbTAIT>JAY(dTAg>JArjpTA>JAZkTA!>JAQTA ۖ>JAYCTA0>JA7.TAMyW>JA.x3#TA0ŭ>JAd%TANy?JAP4 TA+7?JA]!TAn '5?JA#.TA?JAl|4TAi.@JA›Y9TA)N@JAkv==TASP@JA+%TAR}~~@JA+TA?'@JAfTA)@JA?KTA\-@JAX5TAl@JArUTAyj@JA> TA0UnAJA#TAߒAJAqxTAơMbBJAjV^TA<JdBJA./:sTAEhBJAobTAE[pBJAcQTArBJAITA:BJA TAOBJAK TAҹ-BJATAڒBJAl)gTAex2ˤBJAM6TAcuBJAӗTA"BJAvTAx1BJAK&;TA'*BJA TAc(BJA TA"BJATA %BJAAowTAABJAepTABJA6(TA|`JBJA*MTAAJA&,TAۓAJATAv:AJA'F TABAJAoZ>{TAŞ0AJA%nTAD0AJAfqwoTAk-BJAT ,pTAQRBJAѫqTA pBJA1iqTAPmBJAkTA34BJAymTA BJA/c1omTA$CJA(oTA :SCJAT~qTA5mCJAxtTA͊CJATAh$CJAiٞoTA5R$ CJA}TA DJAJpVTAVwDJAE)!TA9B#DJA!àTA>DJA VTATAIFТIJA TA4^(4IJA7TA WIJAlpb^TAKeIJAjMTA:SSmIJA {TAgIJADTA4IJA TA sϺIJA*A6TA$aIJAݖTA7IJA̡{TA2vIJAuTA IJAXSTA\ IJA|TAltIJA1SvTAWIJA=RgTAX]tIJAR*5[TA !IJA`[TAIJA {[TA҉ JJA nCiaTA@%JJAnTA'v5JJA.vTAVBJJAL{TAmdeLJJAZR4}TAetYJJAc3~TAzJJA(TAIgJJA ⼂TAP5CJJAXTAolJJAjXTANLJJA bTAJJAETAc KJAPtTA7h4KJA6dnTAY_KJAQnTAKJAoTAR,gKJA21gTAbHKJAl{TA_KJA\ŖTAnXLJA,TA 7LJAQҋTAhqxdLJA2TA M;LJA?WTANzLJA~TAGLJAC.cTA$LJAdTA7SMJA\TA+MJA;\TA䉒"EMJAfTA^zcMJATAP?MJA>TAwMJAAQwSTAIsŵMJAlbTA9MJAd+)mTA MJA,W=TA"<}NJA@@TAڋ%W+NJAnTAͥzTENJA:TAK TXNJA(10TAMbNJABTAʊ NJA* TA`NJAaZTAlNJA(v|TAlNJAω4TA48i?OJARTAEegOJA ^TATshOJA 'TAi$OJA΁,TAߙPJAiqi4TAoUPJA)TA[zRJAavqTA&9SJAL?yWTASJA)LTAmXSJA+cTA3cSJAyrbTAnkSJA cTADuuSJA/N`TAzSJA$[TALLrSJALdATA@AsSJA:TAsSJA@m*TAtsSJA&TA&)oSJAKsTA iroSJA0 TAgBmSJA#bQ TA__kSJABTAuoMeSJAn.&TAubSJA{Q@TALCISJAbTAথFSJATA?SJAVTA7_1?9SJA?TAݕf2SJATA#.SJAҏTA J,SJATAmSJAp/TANSJAnMTAroZ SJA1#TA%eRJAxTAlRJA =TAwWkRJAbkTARLIRJAՙMTARJA04TA?j%MRJAiTAyi RJA&޿TA 㶄RJASкTAxilyRJA TA_GRJA'zTA_#RJAUwTA_RJATAgW!RJAfTAq_RJAՑTA54wQJA!TA(DOQJAAgTA QJA~TAcQJA٠rTAGtĆQJA`v;nTAU]xQJAOPhPJA_kTAԔ7>PJAQ^TA111PJATAD1+PJA#TA}PJATA창OJA!FTA%OJATA:OJA(&TAOJA]\TAcB߱OJAiTA!OJAL˸TAoOJAxTAIa bOJA9TA+rAOJA|BTAm6OJA/i TA$eNJAҺ7TAOq2NJA!TAxNJAYc{TAQޟNJAuTAENJA3TA5NJABETAȍCNJApJiTAGNJAkqTAx?NJA%TA)RNJATAjm|NJA^_STAnqNJACTAcNJA\7TAPM_NJAn:MoTAoT]VNJA/CTAUPdENJAXTA/3$NJAkTA;|MJAk`TAW֨MJAV0TAMJA~5TABMJA>fyTA1-MJAZ/TAmYMJATAHtJˇMJA`TAdPޏMJA&ҼTA6xMJA.eTA{nMJAlTAzg*TMJATAAMJA9FTAIQLJAEEGkTAwLJA>(şTAx LJAO>TA ӀLJA9_?TArS`zLJAeP}TA@lLJA%TAr&WLJA)TAZKLJAATAr*8>LJAJTAR"6LJAjiTAF~D.LJAJ TAi LLJA>uTAN LJAwTAnX7KJAyZTAğFKJAxTAMKJAF̓TAO5KJAeVbTA6zKJA(˫_TA2]KJAWB[TA>KJAQә[TAUZI+KJA•YTA KJATTAbJJAc":C@TAVJJA8ΗO>TAx@MJJA=TA_*5JJA*TA)EJAjh>TAep0CEJA%>TALEJAVDJAceWTA xDJA_TAtv2ˍDJA$?TA?[DJAtBTA\_DJALGTApDJA%CTAeDJA/͕ TA^DJATASDJAk\TA[DJA1*TAמB[DJAdi!MTAWϯDJAzDTA\ "\DJA9aTAU2eDJAeVYOTAl2iDJA*JTA=XDJAG8TA#D_DJAYTAHg{DJAvTAm}DJA#RTAYLDJA_)NTA/`DJA'MTADJAv.MTADJA$h>hJTA0bZؓDJA_?TA-ՏDJA >TAF6VuDJAꌘ>TA<nDJA=TAΈkDJAɢW7TA`qkgDJA|C:TA4iDJAH7b TACqDJA TA #zDJAo TAѶDJAjP TA%4DJAp,TAA$iEJAљlTA t 6EJADIfTA'lEJAk!TAJ5`EJAQDTA1oEJA@ TA'5M!EJA TAj[BqEJA r+&TASE)EJA[PTAEJADTA7*FJAQxTA%43FJARTA!DFJAx/TA1IFJAgxTA kaFJAZTApFJA%TA/BIJAiQ/TAQ IJAfTAIJA>ZTAJ$JJA[TA5r,JJAT{TA0JJAVTAFJABy TAʑ4FJAsTALFJATɿTAHEJA TAU;EJA/'TAfz+EJAxTAIEJAf TABo2EJAv TA\pʣEJAe TA$EJAe)TA~EJAZTAt"~EJAP.BTAg`EJA{9TA#EJAPSTAZHEJA{4TAiEJA|8!25TAULEJAt;TADEJA t9TABp8CEJAMkn5TAC>EJAd<TAk;EJAlDTA 2EJA?TAEJAغTA)DJA)TAo|DJAgi-TAұ\DJA sTANDJALTAhuDJATAeT7yDJA:TAyDJAj!:TAa]DJAUTAeF JDJA"-BTA)DJA\TACJA|TA@y~CJATABijCJA;TAÄeCJAXշTAXjoCJA4TAU` wCJA0TA yCJA\oTAY4CJAElTACJAFҵTAy CJA7TAţ CJA$YTA6?ҏCJAKmtTADdCJA_چ_TAYȗCJA5ZTA7CJArYTACjsCJA-|TA{eCJA'TAZ|GWCJAR~,TAACJAI0TAe"1CJA H.TA[%CJAxa.TAhPCJA~'2TA;cBJA7 p8TAkoBJAQu۵:TA oۘBJAy*qCTA KBJAAATA; ?BJAhATABJA$YkKTA`AJA4ڕgTAVfAJA;kTA&ٷAJAQ(oTAŻAJA@xxTA^uAJA3WqTAAJAbTAcAJA+cTA!~AJACTA43{AJARָTAHYAJAڥTA';q0CAJATAd=AJAjb$TABtzAJA[mTA^Vf@JATAU<@JA7gJTA_߄@JA:[TA#@JA0fTAh1@JAi[JTA/&@JAsarTA@JAePxTAc@JA:!TAx@JANسy'TA2O@JAmD*TAɠ=@JAԼ/TA) <@JAO@TAt&?JA:BwRTA\ ?JA;0hTAeF9Gn?JAChTAEI<>JA[eTA>JA܉gTA?JA?,TA`?JATA?JAITAaH>JA TAhb>JA혳TAW)>JA]2TAL)>JA"2ϯTA’>JAкTA}tL>JA4U=TA;9G>JAa)TAj>JAɓ4TA=kL>JALTAD[h>JANTA8]_SP>JA>_TA7( I>JAֺ+TAHE>JA!^TAoe@>JA6jrTATi4>JA{TAN4(>JAJP TA;@W>JA\"H TAo=JA!N TAX%j=JA2e TA,=JA&TA=JAR TAtw=JAnj#TArY=JA-#TAJI=JA %TA}=JAM&TAJ'=JAs&TA+=JAQDTA P=JA\>TA5Ќ=JAceTA,Xi=JASV TA=JA71TTAKg=JAR@`TA0=JAV2OTA!#Z=JA bTABG=JAi>TAa=JATAv|=JAPTA$g=JAFTARZ=JAIQ3 TAAU=JA` TA8^/=JAPTA'cI.=JA;f>TAN-,=JA$M TA'C!=JAv)TAcs#?Dx9JAi TAV^p9JAB}TA0dg9JA8TA}Z9JA#1+TA1G9JAl(YTA7&39JA[TAQ9JA*TA;8JAJ1@TAj8JA3ETA`8JATA[S8JAaJ TA18JA3 TA08JA^UwTAl8JA" TAZ;8JATA|8JAt TAker8JA6Fl TAy]j8JA Xa"TA^d8JA^5(TAbr%Y8JA].K-TA@O8JAl0TAVHMF8JA/TA?C8JA4TA5* 88JAT:TA&8JA5>TA6>8JAءC/@TAlv8JAR`?TAÊ8JAD:TAyq" 8JAWDTA:T8JA&JTAVz7JA:mbSTA7JA6AbTAv7JACbTA'7JA9~gTA7JAmTADN7JAxoTAN7JASrTA\%7JAqTA厯7JA#A=wTA7JA@J-yTAV_Ţ7JA xTA4k!7JAxTA]7JA!uavTAH27JAr^DuTA?L4|7JAlHwTA,4es7JAn[rzTAed7JAVV|TAX7JA~TA3T7JAWP~TA]L7JA`~TAG8G7JA|PUTA@7JA{TA]07JALTAT"7JAaNTAS 7JA-TA&"7JA.bTAcN7JA4-U[TA M7JAHTA%O7JA>䫺TAѷQ6JA2L^TA_(6JArTA6JA= ֜TAS[6JA'ߞTA!>6JATA[ۚ6JA[TAb]6JA[OTA+q_6JA|>sTA[Y6JA qb^TA!V6JARTA/n U6JA"nU*TA E6JAf7*+TAJ|86JAAt/TAnK6JAb0TAl_6JA7xTAٰ`6JAkTAܮ$q6JAuUTA"*6JANiqTA6n6JA mTAsT6JAM ÉTAO'6JA oyTA񼜣6JA{uTA&u6JA^^TAXW6JA\g.NTAP6JA]gCTAz-6JA#6TARf 6JAYAh)TAotJ5JAwRKt'TA5JA^0+TAZ5JAZ.TA7z5JAv5TA 5JAe TA?:Cc5JAK!sTAn5JAq9TAԷ=4JA1㍓TAq4JA/ѠyTA{4JA2|TAl{zw4JA\GTAs4JA^TAJ7yf4JATAY94JAvcTAv`3JAv4TAW3JA. TAn3JAb[TAsW4JA;TA 4JAV[ZTAP93JATA>C3JA&TAΛ0h3JAW_TAQUF3JAVTAFz3JAVTAme3JAt91TAx\3JAi`$TAf*4JAr5(TA!4JA)VTA6(3JA/TAlI4JATA]4JAQ0TA{# 4JA:8VTA_b3JATA:IYTz3JAb޿TAg\F3JA||!ۿTA> -3JA$>ؿTAA3JAT]տTA2JAaaE˿TAD=2JA~iƿTA'*ߓ2JA2TAEZ2JAhTA;(2JAi⿿TA8An1JAƿTA5%1JA+/nƿTAM#M1JAQwʡƿTA/Oi1JAmړTAa{f1JAܰ?TAOE1JA.#JTA71JA8TAѝ0*1JA,TA6T1JA#rTAT0JAdKTA!r0JAxc TA=0JAN-TA, 0JA' TAiů0JA TAT0JA؉TA=80JA~TA?ʘ0JAϾTA10JA u̾TAFߞ0JA TAD0JAf?TA0JAVpTAٛY0JAh+TAAy/JAd40/TA9B/JA 1TAZ/JA2TARn-.JAHeU7TAMBh.JA*B#JADTA}P>JA=&xTA l>JAe1bTAd>JA9TAP>JAF)7TA5|>JALx(bTAggy>JA*mTArł>JAd4TA\;I>JA#TAuN>JAoTAB>JAgTA>JADTAB>JA"|۝GTA3|>JAa JTAYy>JAV\m}TA>JAQ[/TA>JAWTAd46m>JA)TA=V>JA1*TA 2?JAv;TAx9?JA{W/iTA`?JA^yTAnD>JA `R TAA>JATAp?JA{ {TA+|?JA} TA^;k?JA=&TAˁ8?JAOw-TA (?JAmR(_TA ?JA~TA-V?JAzTA;p ?JA_,TA0 ?JA;O,TA\ M>JAm,TAc>JA5TA!>JA%,4TAo]V>JA`-TA(V=JAV.-TAv=JAy4TA "V=JAJ;e6TAQ>=JAv;{lTA=JAؒ_rTA=JArTAk=JAoTA w=JAFPwTA3=JAPbTAb#=JA}TA?E=JAyTAi}=JA TA=JATAYAd=JAF_ ;TA;=JAq>TA)´=JAZK2/JTA=JA=*NTA]1>JAJ9WTA`BV>JAܶ(aTA>JAJcTA!C>JA!N1^fTAۢ>JA;)kTA>JA+|TA>JATA~P~h>JAe"@TAG>JAJɋTAA_>JATAc >JA"`TAi?JAo7iTAG;n85?JA*OTAėT=?JA>_TAY:P?JAqPTAea?JAPe׿TAXOlh?JAρTA\9x?JACTAGEN?JAxTA ,M?JAKTAױw>JAITAk3 g>JATA`\=JAVSTAg=JAPViTA$(uZ=JA"TAu=JA CTA *NTA \3JArHTAI|ҽ0JAFdRTAהai0JAgRTA&9i0JA͢w!'TA}kri0JA TAA'0JAGTAS ~{0JA+ TAђ0JA TA'y*0JANTATM/JA)tTA;b/JAZTAFI/JASTA{/JAϤTA^;j.JA8'͛TA^o.JA]v5TA.JAI!TAb߽.JA$TAi3.JArjTAAۍ.JA_)TAݥ/.JA+TA&H{f.JAH׋TAebg.JA]6mpTA!;_.JA 4xTAz5.JAnTAo .JA jPTAD-JAm5kLTA[ .JAh+TA<.JAyh'TA4 >$.JATTA36-JAp)V}TA"V<.JAOTA` u-JAf̻TAB.JAxTA@d<.JATAO6.JA$[TA-NG.JAp(HsTAD{lN.JA `TTAR.JA?=TA25Y.JA^ /6TA[9a.JA5T TAUc.JAqTA@.JA>3#TAP4.JAwTABev.JAG,tp +JAGTAVr+JAkoTAjk*JAV"UTAtN9f*JAuFTA Ha*JA$ >|TA*JA@kyTAR*JAo޿ÒTA; )JAVߒTA?)JAVTAHp)JA A_TAgs)JA+kTAlʱ)JA9 TA;I)JATAcMt)JAQHTAQ(JATAѩЮ(JA!TAUũ(JAkTAqJ(JAq;V.TA\mu(JAzTA,#sf(JA&TA6kb(JATA k^f(JA,EvTAB(JA|NY5TAc潃(JA2dtTAvx-Ep(JA+@WTA}޾(JA(VYTA ;(JAd >TAC9C)JA5hTAu/JAbjTA] >Ҟ/JAm" UTAԡ/JAg%TA2{;/JA*R&TA'/JAaTA/JA=|TAi /JAzWTA}ƺ.JA TA[|I.JA5TAPoc.JA<4TA#.JAF ^TAc.JAiTALZ.JATAqf*.JA(wTA$ɸ.JAg?oTAO .JAOLTAw.JA8%ATAWM.JA\)TAtkWs.JA*$TA(Q.JATA.JAdq TAq.JA46TAO-JATA쐧-JA5TA~d-JAxAhTA>-JA*&TA!N=x-JAXɘTAb)]-JASTALv-JA#HTAhM5t-JA6TAAZ$-JABP[6TA-JA 5TA#L-JA|-hTA:|-JAa:TAʦ%-JA،rTA :.JAɍDŽTAΫg-JAqTAy,=a.JAV+\TAU/e.JA>TAh.JA0ҴTAJL.JALMTA?dЅ.JAf5TAgk.JA{Y|TAǨ.JAaxbTAWeo.JAƭ_TAs /JA3ZTA*z^.JA=00/JA89TAmw/JAS-TAvI!0JAd 3TA>V0JA0:TAx0JAӐn1JA>TAs1JA27'=TA>ǐ (2JAn,@TAe_'f2JA<]CTAFT2JAI=TA82JA(MTA 12JAkXTAQ$g2JAküFcTA/Djm2JA{TAaE2JA8TAuSH2JA(TA望!2JAy躭TA46d3JA^CTA@3JAyBTA*]2JAr3JAg]TAy:G3JAn* TAY'4JAY3CTA^4JAnYTA94JAەTA4JAzpTAQbSon4JATA^xo4JAmTA 4JALTA\4JAF8JAʱTA۷-g9JATA|9JAz#TAmK59JASTAc9JAV]TA9JAT% TAC>9JAhhj TATɰ:JAjuTA!:JATAjN^$:JA;5TA&&:JAܓ/#TAN$>):JAR&TA:JA::TA:JArr6>TA/;JA?TAf|G ;JA*j?TAtt+;JABTAbJ@j0;JA`CTAY7<;JA>7FTA=;JA9(BTAaX?;JAZ>TAe_B;JAز6TAvM,H;JA`(TA Q;JA\TA4\;JATA|2d;JAѶ7 TAjFk;JAJAֹlTAk!>JA&|-jTAy?9>JAcTAG3N>JArdk]TAqh>JA2,+OTAmCJ>JASoCJA2/TA"k>JA7(TAjO)>JA?gTA-:>JADTAAhzp?IAGrsxUA'J_JAt?,UA*8&JAMcUA2&JA%t5UAr:&JAGUA S/&JA.9u UA/v&JAౘ(UA)}y&JA UAI&JAbIUAc}&JALtUA&JA UA E]&JAovթUA&JAWUA(&JA#UAؠ6&JAUilUA:&&JAJeUAhDVs&JApu{UA-z!z&JA3}oUA'b&JAlsUA&JAH^~WKUAHO ט&JAB!EUAo&JAW=UA߻&JAyX,UAº&JA;"UA(/&JArUA &JA`jUAA:&JAL 0UA1yAD&JAbeUA?%JA7fUAoj%JAFOTUA?o0V%JA;UAkd%JAEUA~$JAUAҖ$JAg-UA' G$JA5+UA8W?$JAasjUA8$JAUAe"$JA UA9l#JAǬwUA12#JAsUAS:h#JAYԸUAmx#JA);UA#JASFUAƑ#JAnO&UAvQ#JAˆ*2UAIP#JAz ;UA#JA 7\x<UA`#JAuf=UA慓#JA$7UA#JAx'.UAɎˁ#JA~6C*UAJ. #JA֛6UAFd"JApUA en"JAUA"JAOEUA>e[!JA }UAms!JAM UAP!JA&UA4}o!JAg$UAwm!JAx UA JAXUAK!JA~>yUA{N!JA~UA~!JAdsnUA6!JAkUA8XM*!JAPplUAC"!JAޥxUA*8k"JAUA2aq$"JA@0AUA\o"JA0sUAg2"JAe3atUA`"JAk-tUA3W"JA3#}UAj"JAUAyE([l"JA>,UA\db"JA!UAJd"JA%%UA4(Z"JAZ)UAߢɋT"JAFP]UAz="JA@*UA."JA;t9UAi^("JẠUA["JA6-[UAx%?Yn#JAp?UA3##JA匡UAϵ޲"JAUA"JA>UAvsߪ"JADUAϐ^"JAO4UAT4"JAoRUA;="JAUUA H"JAMßYUA,Z"JAXUAv="JAt UAs.!JA)YUAn[y!JAzUA:^!JA]UAFc߅!JAHUAs!JAUAH!JAcdUA"O;!JA"UAC_8Q!JABUAk*]D!JAMUADs4!JA sYUA~] JAoUA9 JArqVUArֽJ{ JA -UAW JAlUA JAIzaUAJARO| $UA6TJA UAJAUA~,gJAWUA$u#JA.RUA\}nJA9/T=UA *ZJA+DUA)UJA)=UA%^9EJA$uUA窆JAۺUA'JAF mUAiJAނUA[__qJAıUA[JA_0UA'JA8UAi_uJAu=UAhJA1CUA(3+|JA#OPUA~JAs2]UAssJAjXlUA7VćJAvtUA(JAOuUA~AwJAd˩UA^I{JA?'UA e;dJAe: UAȂl]JAsUA\JAwUA|SJACIUAp&JA(UAg%JAXUA/M^,JAh)~z!UAm@ίJAt>UA0JA mUAq JAVBUAlJA}ûwUAmaJAUAJAUAtJA UA5_ JAqUAf۲JARGXcUA`خJA46FUAĠJA.`UArJ0JA#tjUAL~JAsImUA~QJAՒyUAe9JAiDUAӱ"]JA )UA&JAUA4JADuIUA{#JAUAOdxJAYP;UAڞmJAv8UA XKJAL0UAv =JA j2UA6B/JA^UAfUhJAʹUAk JA=rUAzJA{6UAT,JAUUAk_JAHUA JA5eUAJA1UA@JAEV,UA,JAJ@UAJAzUA6kJA 1UAs-:JA,MUUAڟkLJAvÃcUA<2QJAkUA}PJAItUA@)DJA#UA~~8JA~*+UA܃(,JABUAɐJJAy2ոUAfJACOʵUA@JA `UA2JAUA@JAcCUAJA}UA:JAjwUAZ3JAݝUAERJABUAMlJA}* UAJAq3UA9JA:UAoעJAx*BUA4{JAx.OLUAGJAUAxUJANUAJASIUAJAџUAxJAͺ"UAұJA9uUA JA2]!UA={c~JAUA68K[JA9pUAؾ.=JA8UAƯ(JA3UAx\!JAJUA,  JAÇUAoJAUA4JAH띦UAffJAFUA^aJAu԰UAۑ(~JAڛ'UAapJAcUA믙\JA5&UA._JAJ҄UAyXJAjUA*#?JAFUAv'"JAQ UACYJA־UAJlJAUADJAh%R UAI JAMǩUAY?aoJAUA>qJA(_UAJAgM#UA4|JAht*UA7tnJAvI+UAJAIA&gUAYJA.2UA+jJAQtbDUA7 dJA5-})UA~P4YJA(7UA<4bJAa9u?UA2s+LJAd#MUA^d 7JACUUAV"JA^UA- 8JAe1hUA+*JAjcqUA2JA+ uUAu3z?JA*k~UAo-JAv\H}UAaJA&LuUA= JAQrUA=zJAs TUAR7JAi,'oUAb0JAggUA' JA ?eUAYؖ JA;7nUAsj JA1UAfg JAUA JAUA4 JAUAlt[ JAUAV淅 JAϕPUA}!A JAƕMUA6 JAUA3A<& JA93UAV JAҞUAϝ JAeUAUa JAbUAF JA]0NuUA JAD9UAÛ"e JA+zUAyQ JAfPUA[@ JA\ OUAz, JA UA{uj JAڕ\UA/ JAUA1 JA] UA(x%JA& UAΫkJA% UAsqJA)w- UAJA5ZMg< UA0'VJA+t> UAv+JAN"m UA$qJAD UANІ5JAL!UAH)JAfL#!UAѓKJADE'!UAK5JA~*!UA|FOJA͍G.!UA܁\JA?g1!UA,dJA55!UA*JAx=ْ8!UA#JA¡;!UABJA-Yw?!UAJAGB!UA5#JAwD5F!UAiY JA[J!UAVJA\>pM!UA"fJA$Q!UAaJA/bT!UAV&JA9+X!UA{5fJAmM[!UA JA i!UAJA l!UAOfZHJA4w!UA9 JA.y!UAd|6JA!UA\⏮JA-w!UAg{JA[!UA{A JAQ!UA_JA{E!UAݔa&vJAʾ'!UAh 'JA.!UA'W7JA5,m$!UA۰JA !UA+N2JA۽P!UA{JA?d!UAW(JA7b@"UAO LJA}"UA]JAMf"UAS\JAJE5"UAl=uJAVC"UAiˎ`JA 6O"UAyXJAI6]"UA-s3bKJA'G}"UAkq'>JARe4"UAu 0JA6֔"UAҿc'JA짘W"UAE) JAb[G"UA֗,JA "UAsyJA%s"UA$#JAp&"UAwDϮJAjc"UAI JA"UA$5cJAt5i"UA6MJA^"UA}ENJAC"UAݦVJA5f"UAJAa"UACJA*"UAȢJA3R##UAYJAb>a #UAqJAX#UAU³(ZJA̕#UAezJA8 #UACJA"#UAJAh #UAMA-JA#UAm#~JA\R@#UA8lJA9 ?#UA%C{<JA!}w;#UA4JA m7#UAW JA; 4#UA}#/JAT2#UAsaJAM(.#UAlԺJA"#UAhJA G'#UADAJAHðYJA"G|#UAɠ}JAp4#UADJAZ#UAn JA)џ#UA*Q>JAjRE#UA:JAYl#UA@մJA#UAc7JAW#UAVxJA7*$UAֿ~hJA$UAf7JA%l]^$UAv"JAl$UAIIA{]$UAzVIA]-0K$UA[vIIAb?Q$UAeCIABOS$UA|,IA1Mw[$UAIAhtm$UA`>IA$UAf—IAU $UA>rIA+_輜$UA͍MIA_ $UA4 IAڱP$UAeIA($UA]\IA$$UAxEfIAn$UA/IIA*$UAD"IAiI$UA&|3%IA+S$UAX4 IA~`$UA8 ^"IAE ,$UAT=Y-IA }$UA~GIAMa%UAKIADZ$UApIAcO$UAl#ɂIA~#%UA5IAF%%UAC9IA"W)%UA%LIA>/%UAIƴIA5#5%UA\IA(IA,ҳZ%UAG@IA#֘^%UAUIA5Rd%UA4SIAFsp%UA^~IA9%UAFvsIABOГ%UAQ1XnIAUG%UA4~nIA,{%UAWYCoIA7M_%UA*uIAҸ%UA\wIAE%UAJuIA/M%UA~rIATK%UA]welIA%UAIFIAZ%UA(IAʿ&UA*tIAv&UA}IAiɼ&UA/JIA}m&UA@ĖwIAt1&UATŠIAL&UALDaIAD\&UAGo#RIA$?`&UA>JIAUFwa&UABIA;몋a&UA/IA]&UA2&IAe&UA< IAh k&UAhEIAQAo&UA"KIAq&UAwIAJ{&UABԍIA&i&UAieIAts&UAT4IdIAW x[&UA!hY]6IA&UAE~IA L&UA)`#IAỹ&UAFyIA 8M&UAA/IATi&UAZRaIAYњ&UA'sIAz8&UA%.IA%8&UAe׽IA؍&UAo`םIA[&UADJIAV;&UA!bIAG:A&UAkMIAbO&UAzp?IA/d&UAi1 BIAR&UAߝˍAIA h&UA9EIAM&UA NIA%m&'UA=\YIA 'UA3ViIA'UA%IAV'UAz0IA:@'UA-LIA'UA;)ثIAȬ~` 'UA(}aIA;!'UA*ŞIAEc%'UA6^IA/9'UADIA0B'UA$IAeI'UA1IAZ\'UA)LIA`'UA<>IAm~b'UA]IAb~f'UAgv IAˇl'UA]IAIc{'UAQIAH'UAr)\2IA'UA_rqIArX'UAe(IA]'UA xIA'UACIAn'UAƹIA9'UA'*IAfe'UA١IA˶'UAk IA2w'UA>rrz IA9A(UA53IAE% (UAN*5DIAem(UA oPIArs(UA]^IAt'%(UAiqIAAN1(UAnIAvC(UAFDIAl0f(UA:IAbl(UAyIIAi1Hs(UA,IAax(UAEIAV=*UA'OIA)@*UA$YfmIAE*UA4זIAViP*UAh2mIAV*UA DsjIAVZ*UA'$IAWԡf*UA.i@"JAm*UAKXeJA0ލk*UAJA*UAJA*UA]GJA}Yj_*UAB*JACny*UAoALJASOt1*UAecJA]Y*UA:!1JAȆ*UA퉦JAY5*UAfJAR"h+UA>oiJAL+UAۓ}JAOT+UAf]ؐJAo+UA<JAA+UAJAJ2+UAJt)JA?+UA7JA`B+UAs@JAHD+UAkSJABK+UAۨJA\^+UAbcJAXve+UASjJAvf+UAJAѻ-i+UAm9 JAl+UAl0JAq+UAJAŹQ+UAJAl+UAJH$JAZɜ+UA&&CVJA6+UAau]JA\+UA-J xJA5έ+UA9ըJAO+UAFJA5y+UA(2JA4+UAVpJA!a+UA/^JA/'J+UADJAt+UAUo^JA9i,UAX[œrJA`,UAK"JAX,UAv^JA;j,UAfwJAe+UA JA!+UA JA5xK+UAiHJA@+UA {&JA0f+UA3JAC+UAxكEJA+UAH, TJA޸,UA'DeJAfR,UAZPJA£J+UAu}JAHV,UA?4JA== ,UAXJA,Z,UAGOJA,UAi4JAn,UAhY!JA#mr,UAK}10JA\0,UAe6JA$_",UA7]>JA8v&,UA[{BJAa',UA~xJAt?,UAAG$JA5,UAj*bǺJAg,UAKfJAco+UA[EpJA\ح+UA;yJAZ<+UAqZTJA{Y+UAJI|JAh1NJ+UAٓ,JAN݅+UA6٥JA+v+UA,ڧJAS0{rj+UAaTUJAK,"[+UAJJAF+UA=JAi-U++UA8JAl|+UAOuJA*UAYǡJA*UAŏJA΂5@*UA!V“JA+o*UAD)JA~*UAĝJAJ%*UA?JAsx*UAJ~JA.`v*UA_JA+ch*UAmxyJA3*UA?z uJA**UAnGpJA(X)UA;^QfJAFk)UAUdJAh|)UAP"heJAM)UA/ijJAĩaE)UAl{uJA3i)UA氛/JAE>y%=)UATPJA)UA4h JA!(UA|b JArѨ{(UA%! JA5Xzv(UAn" JAEJ(UAw JA1'UA| JAsH*'UA_Q1 JAl'UA?m JA.`'UA>|" JA\W`ȇ'UAe}I JA}pw'UAi{5 JA/p'UA0; JAfjj'UAV1C JA=m_'UAI1RzO JAk;V'UA` JA"{I'UA}&t JAX! <'UA=% JAKG2'UA1SZJA\N&UAU XvJA _&UAJAWBe&UA>iJA1C%UA(JAm%UAJA;ӷ_%UA1JA jY%UAi:JA+hG%UAH+JAQ%UA/O_.JA$UA}=JA$UA^؁JAm$UA4 E#JAc^$UA`=JAjL$UASJA9o$UAGJAFy$UAJA1;Q$UA JAe$UA0/v#JAT$UA]ړ/JAR#UA=JA3?#UAp@JAjI#UAen4BJAe#UA1v@HJAA}Gv#UA`KJAՌԵ#UAvKJAm ơ#UAv#IJAVFì#UALJAc#UAN[WJA^ :#UAq_JA fm)#UA,;N=cJA!#UA, :qJA_M#UAݼڅJAΝ"UA JA 7>"UAJAZ"UA86 JAD!UA,ٍJAwB,R!UAg"JAGE!UAz> JAiI1!UA{\JAV(!UA;JA^r!UA?JAZE!UAeهlJAz5C UApvJA UA#JAZh UA!JAC} UAyhWXJA%z UAj8JAA:^ UA5JA_hg+ UAΟ'JAu# UA+!b8JA2d UAXJAfר UA:nJA~ UA|3)EJAMO UA;JA UAbJA=Ȑ UA1=JAv UA|iJA\Pz UA*H JAƶ UArJAZ  UAS.JAA UAe,JAAN4& UA3:JJAHC, UA9lJAI0 UAOYJAAT3 UAZJAW_3; UA UAG LJAA< UAUGJA]a? UApX?JAglF UAZapPJA-yJ UAd* JA`qQ UASUd JA8fQX UA(z JAc.Z UA} JAHK5[ UAء JA$f UANA!JAWx UA1!JAbk- UAsZL4="JA 2W UAt[f"JA\ UAsI"JAţ UAmй#JA:> UAr#JAz˜ UA[ $JA3Vs UAMjWo$JAs^ UA$JA UA;?$JAdl UA/%JA6d\>!UA_&JAѦ'!UAo"SQS'JAP!UA2OE'JAN.!UA4~r(JA1|!UAXL(JA!UAr(JAR!UA@+)JAh)_"UAG/)JA*er "UAErd@G)JA}"UAx4)JAL+("UA*JAnM"UAb{:*JAs'Y"UAc+*JA{"UA!V*JAR"UA&J*JA"UAc5 +JA~"UA+JA'/K"UA@AE+JA"UA1p!,JA"UAg56,JA<]g#UAk,JA##UAsc,JA( #UA-g,JA% *#UA~;,JA8-;#UAv -JA^hHL#UAbE-JAqU#UAבo-JA`yW^#UA,|-JAiog#UAo͌.JApBo#UAKo/JAn~#UA܂/JA#UAs3/JAM!#UAZ)/JAK#UA"|Mz0JA#UA}?&0JAbA#UA>j0JA #UA蘀1JA#UAgq1JA͒#UAuɶ2JAI#UAR2JAȳ#UAO3JAvGdӹ#UA(*3JAB#UA>4JA#/#UAhb4JAG#UAn:܍A5JAPo($$UA25JArH$UAa5JA\U$UAU6r6JA2m.g$UAi6JA$UA(fL7JA<9$UA`7JA !m$UAh07JA`n$UA͆8JA)j6%UA֏G89JA|vP%UAyP9JA]~U%UA l:JAD}%UAh:JA 1B%UApq{:JA%UAX#;JAIyb%UA$r;JAE;*%UA6{'>JAan&UAN>JA&UAKdR?JA>gW&UAԏ?JA&6d&UA]?JANyr&UA#o0H@JAo9&UA)T@JAҸ` &UAS]@JA&UA-8; AJAP&_&UA'^AJA.x&UAAJAHݯ&UAK5b{AJA8z&UA'AJAZ&UA\N;BJA &UA -BJA۳&UAn3+BJA=&UABJAGb&UAO7BJA:k&UAuWBJAU>g&UA ;΋BJAXd&UAIxKBJAp_&UA0BJADiU&UA4BJAWmJ&UA#GCJA A&UA*FpCJA뙅5&UA* DJAI&UADJAO&UApDJA9ɵ&UA:DJA<&UA=DJAT%UAe `RDJA>S%UAU~DJAJj%UAĠDJA ̵%UAoN%UArpBDJA#]hq%UA jDJAμ%UAkDJA`%UA4rDJA-o%UA DJA3k%UAJDJAD9A%UA~'CJAIgd1%UAd)T*CJA+x.,%UA&1CJAƨL%UAM:CJA}%UASONCJA˖n$UA;UCJAg|$UA} CJAy$UA!u~CJA:$UAw~AWCJA],$UAfCJAhQ p$UA CJAndk$UAk^BJA|S$UA- BJAׇ$$UA2BJA$UAnBJA{ $UAEtBJAK$UA1BJAf#UAHBJA9#UA,CBJA$a#UAXB5BJA=#UAz BJAi~+#UA]9AJAxe#UAAJAL#UAAJA+ׄ#UAuC`@JA^+K$Q#UAe'[@JAe7P#UA1&P@JA|``N#UA L@JAo~N#UA @JAVG#UA5?JA͠MD#UA2?JA C#UAv?JAIhhC#UAb]?JA%N}E#UA }u?JA`SwF#UA?JAS~MK#UAT"w{?JA-8FG#UAS?JAgB#UAܥ56?JANA#UAD?JA&5@#UA,>JA=;ʆ?#UAB>JA- <#UAWf>JA_E9#UAc=>JAғH>$#UA%֥>JAQ#UA=JAPr\#UAy)=JA#UARʷ=JA R#UA9A=JA#UA[*J=JA2 #UAV=JAra#UA.T=JA."UAҗn=JA&6"UA7=JAIM"UA@ =JAo "UA/=JAW3(-"UAt\_=JAk̬"UAI{=JAo~"UArQ=JA,V"UAP=JAq#"UAgj=JAͻ"UAE=JAr̩"UAsX>JA7"UAݳ>JAUӗv"UA>=JAʳlg"UAv=JA[Ua"UA͒T+=JAF"UA8=JA?93"UA3G=JA&"UAɰS=JAQ"UAdp=JAr18!UA$j#e=JA!UAf^h=JAC/a!UA ׸y=JAc!UAt^ ݉=JAx<(!UAOC5?=JA0!UAGa =JAIrn}!UA!ʂp=JA](1n!UAdaP!UA);}JA(Ð UA>JAlUA0N>JA×"UA>JAZ C)UAɷ[>JAЕ ^+UAgjB?JA˻7UAL?JA$")9UAkTR?JA9UAa?JARe ;UA1C?JAAUA[?JA7UAa_@JAP;EAUA= 6@JAl?GUAMRu!H@JAd|IUA:s.xp@JALUA?+2@JARU`NUA΁@JAFթNUA֙a@JA#OUA~* AJA~WUA*Hx$AJA^XUAk6AJAOUA\FAJAxBNUAiPAJA+CAJA %&UAtAJAeUA+)(AJAZ TUAAJA!UAK޿AJA42?UAAJApUA+sAJAXUAʿAJArLYUAAJAl ٰUA:(AJAUALUAJA?g$BUANAJAxUAJPBJAɺo;UAd@BJApCUA̯GBJAUAD%P_BJAUAblrBJApWUAS7}BJA/I,UA7BJA `UAU9BJAmc&UABJA1UA(CJAt3@UA\\CJAW)UAvUwCJA('UA띀CJA[?UA 1FCJA经UAoDDJAM .UAGDJA-k 0UA5LDJAm,UAHpPDJAAb*UAkodDJA)ć-UA\lkDJA)-UApcDJAUA3-JDJAKUAs,EJACM,UAÐEJAc:UA^EJA7L7UAۍOEJA?1#UAIEJAp2UA #EJAJw5UApFJAL;h!UAd5mLFJA*+UA^{FJAQp UAqYlFJA=h UA&}ǦFJAgUA{$JhFJAUA]FJA_|UAh8FJAfUAFJAUA'GJAwBvUA$GJA9uUAGJAIUAո RGJA^0UAnGJANz.UA[3GJAz涉UA# "GJAn&UAY3(GJAv5 }UA&4-GJAl}{UA1GJAKyUAHQ19GJA9wUAmn?GJASTtUA]uLGJAFoUA'ʭ]GJAflUAwGJAfaUA?8GJAif[KUADpGJA}DUA)GJA.C?UA)mGJAhJ.UA4 GJAv@UAf:HJAB*CUA{SHJA]$$UAІZHJAEUAuIJAz#LUA|lIJAHpUA0IJAc UAjIJA{UA$`IJAdUAIJAyȖUASIJAfD١UA6JIJA,McMUA@HJA4NMUA瑎IHJAdX|MUA/?HJA=/UA@HHJAҪ$UA/ÜHJAUAHJA;kUApHJA#UAHJA]UALHJA%oUAJBiHJAUAr9UHJA%x`UA &(HJAs#2UAHJA[BUAa(HJAUAc2GJA9tUA zGJA6@UA]-eHJA&OXEUAZlʗHJA$UA1GJAktUAyGJA TUAw.rHJA#mUAiPHJAfpUA},j%HJAUA(HJAŚUA 'HJAUAGr~HJAOrkUAFʲHJA̠IUAqHJA5EUAчWHJAoR@UA+ \^GJA9UAD/PGJAbBUAbWGJAvUAJGJAUAIGJA{SfsUA\ڻGJA@uUAL bGJA`prUA.n~GJAD} 5UA=GJA>q1UAGJA o%UA(hLGJApBUA?/GJAUAGJA Q UARX[HJA_UA꿫dHJA ?EUA@ HJAIkUA Ii$LJAu޷5yUAȣxLJA˗UAmwLJA6UAcLJAyUAJMJA}*DUAz[PMJAlcUAnVMJA UA}~^MJAN5 UAS$dMJA*wJ UA"_MJAaUAhYL5MJA^]UA"F5MJA?\YUAOJA+KiUUAq@w`#OJA 4vUAMB$OJA҃eyUA9=-NJA`rzUA䤟7NJA 5UA2NJAۜOUAYgaNJAwUAfeNJA UA%ONJA$38UA VOJAI>JUA*OJA6cUAOJA)]aUAXOJAptoUA2|OJA,nUA;8OJA[kUAPJASnUA"A= PJA$rUAv9PJA\UA۔yB_PJA1EUA_dPJAamUAG SJAGM&lUA.SJAWITgUA3m4SJAѴgUAy^MSJA@;fUA.}\ESJA-!)QUA6?ORSJA#9`RUA-sSSJAj>WUA SJA"ggUASJAJ.uUAhTJAG UAC+G6TJAi#UAF?FTJARUAUTJAV\UAzITJA77UA}TJA@pUAn UJA<{ζUAFݼUJAVUA(UJAhUATwUJA'AUAĝ;UJAUA׻lUJAeعUAUJAUPUA"UJA<UAUJA\UAUXVJAJ/HUAʷyzVJA@E>,UA5+VJAFiUA/VJA+.(UA-WJA>8_>/UAIYWJA1UAOBuWJA%3UA3yWJA;4UAȣWJA009UAp#WJAKSKUAVf!kEXJAa?UAb}}[fXJA{.]UAc턑XJA>x8UAXJAyN;t,UA8wXJAN#UA`cXJAUAc@YJA qNUAmxhYJA#UAnE}YJAU UA叅YJA&_UAݴfYJAY $UAc;YJA7tUA-a#YJA5UAnHYJAi/UA iYJArwUA/}YJA UAzYJAhAUAXmYJAZm{UA+_YJAxUA #QYJARCUA"4@YJAw֓UAj -YJAYUA]G YJA$hUAFXJABUA|XJASw|0"UAXJAKK5UA C~XJAZUA_aXJA]UA-?XJAXUAI"XJA~fUA2XJA֧p}UAE;XJAP&iUAюWJA)u9UA晋yWJA!UA}HWJAH\JUAVitWJAl UA^ݸWJAUAnWJAC>UAS'WJA[pUA$WJAMtHJUA'`WJAdd2UAgĩWJA(C)UAWJAUAm@+WJA6OUA^vWJA`UAZIWJAUARYJA[1UAYJA~UAkZJAtUA-[P1ZJA!UA}ZJA8 1UA|>0ZJA2!^UAמ[JA{kUAf[[JA=@zUA4[JAWUA>?[JAԈ UAq~[JA}kUA̪ku%\JAWҍUAUn\JA`+UAċ\JAb=uUA \JALUAT%ɽ\JAmϏUAKռ\JA$|UAj]JA=fUAL\J]JACUA.Oj]JA&*)UA1]JAUAvC]JA;UABd]JA͗^UAĻ׽]JA:6LfUAR]JA4wYUA*]JA|/UAP% ]JA_UAng=}]JAFiUA}3]JAz\UA*u&%]JAEUARMI\JA(vIUA]JAj~UAӭ]JAUA`v^JA[bӘUA]h'<^JA 5wUA ee^JA,$][UAM^JAa UAz_JA) UA'J_JA}[` UAo_JA M UAd_`_JAJ#lyA UAp&H>_JA:Ln7 UAQ$_JAjb. UA~F_JAL+% UA__JA>8 UA_r^JA {Ô UA2>^JAM UA;=^JA6} UA3<]JA#hL@ UAN<]JA"Q4 UA}]JA c- UA.p=]JAZ UAJv]JA  UA7\JAl UA \JAL'S UA(9M\JA}&# UA=*;\JA UAz$-\JAC< UA \JA& UAD\JAk UAhp[JAUv( UAER[JAӓ UA0%F1[JA/a UAᣜ[JAi9y UA1 [JA f+g UA7[JA#r&^ UA`ʡ[JA`!' UAIȕ[JAo UAZJA UAn}ZJA'KÓ UA*?ZJAѻt UA6CYJAaFQ UA(!YJA$| UA\>YJASI UA*cYJA4e UAF^YJAo* UAߙ>NYJA%q UALAYJAk UAr5YJAi UAƛ(YJA UA'YJAM UA~mXJA?Qh-& UA2ݕXJAk, UA\(KlXJA;<- UAhWJA( UA>WJAۡw7# UAWJAӻ"# UAWJAB3 # UAWwWJA" UAX’dWJAz[! UA!qPWJA/ UA'pNWJAMb1$ UAFb$NWJAO& UA WJA\& UA VJAO UA&IWJAԳP UA}rWJA w^Y UAvPiVJAܘV UA!VJAQ UA/(VJA\̝Q UA3TJA>S UA TJA7`S UA.|TJAjQ UAEQ7SJAGyW UA)SJA2X UAU%SJAV-rW UAʹ!ztSJAcZ7gK UAc_SJAQQE UAj*USJAvB< UAvASJAw UA;,3SJAKQ UAYRJArr UA~SJA{yZ~ UAöPRJA5 UA ~RJA UA~ĉTRJATLR UAʸRJA[b*: UA=pW+RJAʀ+/ UA "RJA& UA\o-QJAIBD UAXȦbQJAs UArIQJAņ UAQJAR} UAc%5QJAԼ UA5!QJA!X UAQJAk҂ UA4"PJAV@ UA+)PJA, UAM.#PJACQ`~! UA2@PJAhVbUA-PJA4 UA \PJAUA%PJA (UA3PJAUA˫PJAeAUACDZPJA>-DwUA!_%@QJAjSM*UA)8?PJADmUA(OJA\UA;OJAs+TUA?"2OJAGrsxUA}(OJAw]|UAnʆNJA.`UA}QqNJA]b7pUAJPNJAUAi NJAtVaUAf2 NJAWDeuUA|MJAmp{/UAFMJA&mjUA8ɫMJAҧUA7ŇMJAؚUAf3PpMJA=+UAY2ZaMJAFUAr?LJAKmQUAQLJADUA:LJAUAWLKJA|yUAQ|KJA5m> UA1;KJAu~J UA2KJAK UALiIKJAEI UAeJJA_ UAu2JJA)y UANIJAh UACY;IJAnR UAh̲HJA4 UARxHJA i UAOVHJA;[ UAx=AHJAQ80 UA#(8HJA^ = UAeE8HJAیG UA aeHJA- B UAyhwyHJA^1{ UA)?HJAwS UA3HJA8ʳ UAl^*HJATم UAh;*HJA3 UA2dW-*HJA3)B UA@2HJA z UAbӎ7HJA2N~ UAz|:HJAϔ UA$\N1HJA1U UA漲0HJA~'{C UAHJA^2_~ UAIGJAOE UAԋGJA; UAY jGJAZ_ UA/B{GJAJwa UAX0GJA*퓥 UAmGJA(4 UA KqGJA< UA/NңxGJA;A UA^1GJAA3 UAdGJAzUU UA#GJAka UA$־GJAIs. f UAOKGJAʴ UAChKGJAHBړ UA/:HJAvl UA^2HJAcL UA}HAHJA UA3HHJA^S6UAK@DHJA ; CUAO>HJATHЂUAhHJA߉UAsHJA%dUAFUHJA|R$UA\]HJAHUA@X4GJAY4UA5%GJA,UAGJApUA&ֵGJABUAd"HJARMUA"HJA{uuVUA9%HJA?bUAo2HJAD|vUA`OHJAUAZ$HJA|GfUAm HJAZViUA+6GJAX&UAv>uZGJAjۂUA_rGJAXUAnyGJAyyUA`%FGJA AUA&"GJAaUA@FJA:UAAFJAPUA2|EJA*!UA]EJA&ʬUAI:EJA'QUA/êREJAmQEUAm-EJAXĕ{{UAjEJAmr&zUA;DJAyUA4aNDJA$ֲ&xUAknDJA~ztUAݍ#bDJA1.fvUAUc7bBJAQGUAQ!BJAS0UAGHBJAݠQUA>jBJA ,UAUa1BJAڈyUAw,BJAz"UAcBJA,UAdBJA0.UA|BJA$,3UA|j!BJA"A4UAFkBJAVi)8UA[lBJAM.AUA tLOBJABPUAoGBJATUAfABJAtޚYUA NY$>BJA_|_UA*A >BJAUւ hUA:BJAA|UA] gBBJAQh~UA7q9BJA,UALt@BJAZ_UA IC3BJA wUAθ1BJAuUA2lBJA~WUAۻYCJAUA>:CJA ֬UAJCJAյUA^CJA:IpUAsȭ/DJA@zUA[WDJA[gUAazDJA9 UAo=-DJA%? UA[*~DJA-TR9UAv?DJAgEUA{7 EJAo$L^UA F-EJAʕކbUAIdEJA}BeUAXJSEJAI3,sUAd/EJAccUAj{qEJA6ӬUAA!aEJA$fUA<>؃EJAyUA!EJAoUA>дEJAmUA$EJACUAYEJAt$UA.EJA%iUA+AEJA eUA R4EJA9UAsUEJAAUAHgUARA9AJA`xUAi~AJAW3UA9 l}AJAC[UAP|AJA+pUA>ρAJAtjUA^_AJAkhUA|AJARxUAFAJAn 7UAr)AJA$ UA HAJAA;iUA 8AJA"#UAZ[xAJAšo4UA"=uAJA3;UAÝchAJAXAAUAeg`uAJAkGUAR{AJAKUAY[AJAdlUApg PAJAKo mUAykKAJArDmUAkyAJA<:jUA(@JAAzdUA-@JADUAaK@JA WUA5r@JAUA͉d@JA#UA| ^D@JAט{_UAx2@JAUA۳@JA2LUAڹ?JAMߎGUAo6?JAT(UA9?JA- UA$?JASUAػm?JAs`UAзÑ?JAbNUA B?JA7 UA!?JACQ5UAV>JAt‰UA/G@>JA6'UA aMS>JAMNUA9R>JAYUAr#N>JAlAUA)dI>JAڈ UAgx&>JA6UA?Ⱦ(>JA 8vUADm.>JAt&VUA">JAoUUAK=>JAqUTUAww=JATOUANNG0=JA[qKMUA1vUAQ82JAn̄UAi 1JA3OUA\l1JAfwfUAhU;1JA~UAX1JA:SUAE0JAkZ:UA$y)0JAwBUA [0JA=UAY0JA鉬UAlѱ/JA.UAtG/JAs=>UAIA/JAPǡUAI.JApȀ8UAvk.JA:8bUADL.JA6UA}/JAUA"8z/JA<5֘UA0ks/JAIUA|/JA iUA1,/JA|M~UA;0JAzUAAU/JA/~NeUAb{0JAwUA2@0JAsƹUA0JA˧cUA(R@0JAUAH8h/JAyWUA7$x/JAF8UAQ/JA8qUAj//JAiFUUApb|.JAB:UAj)P-JA(^,vUAn-JABUA AJ:-JAUA '-JAsUUAi,JA%UAϏ,JAbUAF`l,JA&rUAٵ,JAXUA$,JAэ|UAEyUAn+JAiUAݧ+JAS^UAX+JA:|VNUA+JA"AGUAz:+JAJ8UA{X'+JADwUA+JAUUABe+JAl%&FUA]w+JAq_UAӨ+JAUAF֨Z+JAD1DUAP׻+JA&dnUAD{+JApUAvf=l+JAVUA~*JAYMCUA2uk*JAUAc+^K*JA~%UA3A*JAJΐUA ;)JA9\ UA.9)JAUAY#)JALUA!X)JAԥUA; W?)JA~UUA=(JAc:UA (JA:-4MUAJr'JAUA)'JAhܘUAa'JA֘rQUA'JA UAbqw'JAMdPUA uHQ'JA UAQft''JAoUA'JA}UA8&JAMcUAmapserver-7.4.3/mapscript/java/data/iso-subset.shx000066400000000000000000000001641357574274700222340ustar00rootroot00000000000000' :zp?IAkFTA'J_JAt?,UA2ttHAhmapserver-7.4.3/mapscript/java/data/subset-umlauts.map000066400000000000000000000012401357574274700231030ustar00rootroot00000000000000# # See http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1753 # # Donated by: Nicol Hermann # Modified by Umberto Nicoletti # MAP NAME test EXTENT 3404414.882766 5429530.647216 3456884.187265 5550332.450907 SIZE 600 600 UNITS METERS LAYER NAME test-iso STATUS DEFAULT TYPE polygon DATA "iso-subset" TEMPLATE "dummy.html" CLASS NAME test COLOR 128 128 0 OUTLINECOLOR 0 0 0 END END LAYER NAME test-utf STATUS DEFAULT TYPE polygon DATA "utf-subset" TEMPLATE "dummy.html" CLASS NAME test COLOR 128 128 0 OUTLINECOLOR 0 0 0 END END END mapserver-7.4.3/mapscript/java/data/utf-subset.dbf000066400000000000000000000005411357574274700221700ustar00rootroot00000000000000_pIDNKREIS_NAMECdKREISN 7337Südliche Weinstraße 100000 0è 10000mapserver-7.4.3/mapscript/java/data/utf-subset.shp000066400000000000000000002655501357574274700222440ustar00rootroot00000000000000' zp?IAkFTA'J_JAt?,UAt- JAkFTATJA儽TAm }CJ/JAX^/TAպN/JA:L TATN/JA\TA7HSN/JATAX/JA9鸻üTAZ^/JAEVTAj\`/JA◼TAi\/JA琼TAQYrZ/JA^[TA;X/JATAV/JAyTA!V/JAYTAak/JAҮWtv.TA;"0 W/JA斘Q"TAd/JA…%TA<\^Bj/JAۇاTAw/JA<0jTAk~/JA`TAr/JATAѮ{z/JA$q-TA/JAXTA;pc/JA^TAe./JAԧݻTAk/JA|ݒƻTA /JACpTAi ,/JA siTAÔ/JA%TAwĽ/JA|Q_ TAz/JAA֝2TAu>/JAhhIb׺TAE/JA +0=κTA`S/JAҍTAE/JA`6TA|/JA[~TAơ/JA8nTA b/JAe{тVTA#WR0JAM)TA\W0JAݒC$TAhP0JA" TA =/0JA.5TAF/JA&ٹTA+u/JAWTAa k/JAxTwTAc/JA?[TA>- /JA2%`HTA/JA@%TAa /JA2 )TAQݯ/JA,.sTA ./JAAظTA\B/JAĿ^ǸTA!/JATJTA=?n/JAÖ8~TA|(/JA` TA!/JAġdTA/JAnB-TAS/JAlT(TA@dky/JAA; TAcrnc/JAݷTAur/JA|`ٷTAJF,/JA uTA. /JAQ!l㤷TA-v.JAu_#TAg$.JAVZTA֧.JA-MGTA؁.JAjm/!TAO%.JA TA}.JAgTAy.JAs>TA`y%.JA[TAr.JABͶTAI=/JA +TA/JA HTA8.JA TA.JAqcvoTAAh /JA:ϜhTA#Z.JA`ZTA u2.JAkFTA.JAL=PTA{".JA źTTA .JAq|bXTAwi.JAXEYTAŨ.JAq)VTAp?N.JA@&VTAkt.JA[*WTAY.JA4YTAA9.JAp[TA68.JAk&_TA9o.JAX¼dTA/+5.JAsWhTAе.JAumTA?k.JASLmTA\ `.JA94rTAaV[.JA禣xTA';AAl.JA`@yTAk}s.JA)|TA~2i.JA{ݸTAӮ}.JATA)q.JA72#ΙTAp.JATAxas.JARTASy.JAcYDTA>ry.JAwI5TAlj.JA܏ŲTAl0e.JA9UTAѓZ.JAugTA `.JA9|ʶTAh]-K.JA~=޶TAH.JA TAlCH.JAOTAM.JAf`TA=.JAmTA|Z/.JA\eTA<;+.JAWNW>TA-JAJgDTAhK-JAMA]=TAq-JA‰? TA9`-JA(TAf*(-JATA2g-JAg TA^N-JAjmTAlޅ-JAƫTA.rz-JA;{yTAdAx-JA" TAFq-JA՝"TAFki-JA) #TAs_-JAT&TA4BP-JA.TAI-JAi3TApB-JA4:TAr<<-JANqITA/-JArQTAb,-JA:P\TA̖%-JAs\N%cTAuQ#-JAj jTAd-JAw%*pTAn5Je-JA-&vTAo-JA1{TA{-JA{TTASFI-JAʾTAy,JAe%TA`,JA/$TAx?,JATAA,JA@TA;(,JA}JTA)q],JAo TAUv՛,JAhTA(2B,JATA\,JAZ_`TA:\%,JAP1TAx,JAACTA`,JAŷTAڴg,JAu طTA׸O,JAܷTA,=I,JAPv߷TAH,JAÄScTA6?,JA^uTA- ,JAOTA+JA-TAQթ+JAܷTAK4+JAzm۷TA%+JAaI۷TA d+JAN޷TA3T +JATAJ+JA5CvTA܌+JAh¼TA̡+JA>0TA+JABq$yTAґ+JA TA+JAG]TA'o+JA@_(TA`Jj+JAޛTA{+JA.KTAq+JA XTA.p+JAd]TAoC`+JAwܓSTAiT+JAlTAyK+JAJTAC+JA-c|TAP7ѝ8+JAfTA H 3+JA, 1TAY٬4+JA"TTA00?+JA qTA&D+JAQ^TAxH+JAŊTAl[-+JAOTAm%+JAo TAgԷ+JA8GTA+JA]\=TAx+JATAԃ+JA)TA +JAgTA|*JAdTA*JA;0! TA *JA0TAO"U3*JAѥTAn*JA0yTA*JA2sTAY*JAF\_TA:Oꦄ*JA`TA8z*JA`>gTAg*JA̐z!TA ]Q*JA9%TAG*JA.!g+TAz%>*JA8r!,TAq\3*JAXm5TA/*JA ?K~gTAa+Q4)JA\TAm+)JAz[TA7")JA]TA|=D)JA)@cTA {-)JAR2McTAsS )JAi`TA>Y<(JA7bTA;s}(JAm߶`TAs(JA-^TAZ (JA0(ZTAͤE(JA`GW ZTAK(JA7VYTAV[LTAt&JAu%JA/T~ATA?Ө%JABDTAL%JA2lETAB3:,%JANTA7%JARTA9v%JAdJUTAՠ%JAҟVTAiA%JA΅UTA#^%JA5PRTAЋ%JAڟMTAl.d%JA vTA}!o=$JARIwTAd$JAq!|TA`~$JAPod7TABB-$JASˉTA5X$JAZTAX$JAqqTAY`Î$JAI]ՋTAz$JA @HTAFsj$JA?ֱTAa$JAITAD~C$JATA$A6$JA)!TA~:#$JAJ1TA$JALTAQ#JA0'>TA$l#JAZQTA&#JAs~船TAD#JAֿ,TAKMĊ#JAz\yTA_5#JA7STAK+x#JA"~TA%_#JAqh}TAhqV#JAWn{TAx[#JAxTAѹr4#JAZa^wTA0><#JArTA:˒#JACiTAܭ#JAZoTAuм~#JA7 pTAVv#JA%6XmTA@,Sg#JA3dTAXA\#JA26hTA -G#JAJgTAe|RB#JA܆eTA?#JA(d_TA`?#JA5[TA!JATAl !JAaaQTAr!JA6ǃTAH=!JA@J֓TA]Y!JAUuTAI!JA,ᴹTAF!JAõTA-&{!JAR1TASKd!JAE`TASwYK\!JArpŹTA蚫$z!JAJ"ֹTAg>!JA]ӹTAg1Y!JAG8ܹTA(!JATA(5!JA&n_uTAJs!JA~u$TA+go!JATAXio!JA)TAοg!JAbGTA/t\`!JA TAVWe!JATA;)X!JASTAM@QL!JA)TAs~Rf%TA}I!JA=?TA^ilK!JACq+OTAAI!JAGϐWTA;hC!JA@ǰXXTA劓6!JA kVTAFX JABKnKTAǟ' JADU!JTAF_ JAJTḀ JA.מbUTA  JA)cTA JAATAmd. JA}uTA JA@TAYk JAcsɥTAn JA|ѳTAp JAEĺTA{- JAŪ_кTAU/ JAv'غTAa JAu*TAW JA AITA`c JA\TA{^{ JAyXTA\ JAO7 TA6D JAQPTA$z LJAhTA_jJA^ TA$JACTA8YJAep.TAfJATAv:ZTAbR JA#J^TA rJA߅2\^TA}j%JA.hTA|N\JAL,iTAjJAwqTA%|JA=+}tTAoխJAB;TAxJAmTAsJAvXTA tJA`YQTAHt$JA#TA}qJA̻TA|`JA4ػTAyqJAuݻTAlJJATA̺JAs@=TAJA4*TAKpJANn`:.TA|X>JA5TAN?JAֈ@TAF=JA# QTA(JA[s[TA#[IJAbTAܚJAWiTAJATK{TA%40JAvvTA|7JA(ZcTAMK*"JAbTAOqÿJALB]TAɉ$JATAyJ#JA- .TAEzJA<`kTA>qJAgtgTA[1dJAgTATJAO|6TArJJAwTAFJAIӻTAeEkJARfCTA:JA⹝TA"傖JA RüTAm%vJAWYdTATwJA{,TAt[JzJAo^TAFJA7=|TA[JA_@rTAWڅJA)dTA1}JA$ZTA̭)JA<5TA'JAwk TAdJA'|TA3JAsHTAэJAS TAƔJApxѻTA<_JAƻTAۛJA TA5|JA/TAP%JANijTAhJAj4(֙TAoCJA0|MTAKJAr߉TAD)!JAbwTAWoJAƤ6lqTAc|JAxqtkTAzJA[;bTA e0tJA~fUTA3dJAMOETA|GZJAm>TA44cQJA\8X;TA+=|@JAc 7TAм&JA(_3TA6\JA -TANl JA:|'TAktJAH7TA"JA?TAkJAh TAG_mJA|TAL>KJAEpTAN_JAdTA24JA"TA&JAOtTA" JAxTAsoJA8QںTA _JAfߺTA]^WJAh)TAJAi mTAejJAϸTAB2~JATADJA)߲TA_ 1JAq\TA\3ԋJAoHTA򰙍JA'TAJA[ TA#JAWO6,TAG?[JAC4TAٲ-JAZڔCTAJA5LTA GJAUTA/rJAѸneTApJALaTA*JAhZTA &JA`TAFJJA_AYfTAt;hJADpTA}Z7JA`䂻TA)u5JAm;9ьTAW1(JA\DZTAsJAjxTAC]JAE TA |JA2#DTA#@/JAVTA:JAL -TA'JA"NTANJAk#|fTA&JA)`rTA6[JAdzTA+, tJA͆TA?JA~W8TA \*JA>TAR~JA7TAف9]JANOTAJ÷JJAxiJTA^ܸ JArUXTAJA1TA7+JA=, TA$cJAIԖTAK )JACTA=ͭJAԷxXTAϬJA0 J'TA[@qBJA|zTALڎtlJA^~ uTA`e\JA-3tTAcPJAfzTAֵJA]fTA<-o JAË]TAJAJAETA JA뺒ؽTA~OU;JAڔTAP|JAOTAzSJAd";TAْJA<ATAJAg~FTAWJADSTAݵJA VTA JA_&ZTAkXJApFBeTAJA`;kTAQ 5JA9yTAVJAs/lTA{fSJAUmTAj JA=TAׂ$JA UTA{K4JAѾG\TAlq6JAnTA"D+JA4徾TA(JAO¾TA吘*JA`3ɾTA/-+JAܾTAl.1JAuTA92JA2TAG4JAe-TAH7JA<,TA1JAi+d} TA }!JAvTA3bJALTAYJA"!TAQJAT^.TA>+JAH7TA jMJAS([TA yJAlTAje{JA8`TA4UxJA(TAkJAiTAsJAuQȿTAMK%JANTA[m:JAiBTA5?EJApyTA u@mJAquTA`JAfBOATAa JA0 GTAiN΀JAAVLTAJAPTA@JAMWFTTA_fOJA*yYTAJA`TAf)xFtJA cTA{TlJA&3hTA6^JA^Z@xTA*0ߎJAaYVsTA,JAuTA+|.JAƥTA&QJAJCTr\TAIѕJA&fbTADJAhTAm2\JAGATAiA3JA@ZcTAMJAv,0(TA0ُJA~bTAeeJA(vTAbJAxxSTAOpJAoTA4bJAL TAn JA"}TA-xJATAaJA#8'TArq xJA+QTA}JAبpTA8JA!k>TAE?JA*TARKRNJAc!#&JAn0TA@ JAJaVTAmMJA]- %gTA4_JA(;gTA`@isJA78VgTA?PJAl%`TAO"p+JAvڊWTA)hJAlFTAΧRJAYw35TAJAO0TAJA̡n7TA}xaԉJAEVTAm6|JAw~JAT&TAJ,~JA{TA,0}JA4TA6$yJAx&TAGVJAL%]TAO@JA TA~JA'TAuJAM/TAFӔ\JA1R6kTA17JA$ŸTAJAp1TA:JA#-TARV;JAՇiTAnl(JAaTA鶏JA ZrTAnJA LTAe:@JA7NTA:JAKTA]JATAfJAUصTAvXDJA TA2KJA}4,TAcJAiATAL.JAtWOTA|JZJA5T_TAWJADbTAJAkcTA)W JA!eTAV`tJAXiTA?opJAt*kTAPJAxTAHòJAPTA/-oJAdz ҔTA! WJAVڢTA4wJAͱTAl9JAzJ>TADJAemKTAlR*JApN[TAvŽJAFaTAXurYJAsYlTA;JA@t5xTA؇E JAoTAMJA=UdTAڕJAwUTA@YJAwOTAy JAgJTAhlJAo.rHTA5%@JAgETA D^JA!>)TAdDbJA$TA_GVJAgTAqMٌJA4OTAx(5bJA|TATA0AJA(TAêJAcJAu TA$ƵJJA߿TAH';JA4zTA,JATA9i9$JA?TA "JATAmD<JA:HTAC2 "JAfQTAFJAА(TAQJAFdTAԗy6JAۍ^TA؏JATA͋{:JAۜ-TAJAu]/TA˄JA{P4TAӸJA 8TAkPJAs@TAgzx?JANv1TAf6:JAl76TA2!JAYT4TA}"JA*+5TARJAJ\LTALJAgCUZTAv JAT݅WbTAT*JAo4FmTAKW?JAI2XuTAG5UJA/TA_NnJANmTAap~JA$ÎTAa8JAjTAP`|CJAP4lTAJATA3JAM!{TAVJAd `TAJAqTA.ԽJATA/#JA6TA">JAO;TAvVJAf;WTA:JAtTAĵIJAF TA 3P JA4isTA'JA|{TA~&0JA?TAO* JAFmETA6_JA4!7QTAI5/JA>)#\TA"%JAjTAp JA mTALJAg|ETAcڀJA/sw~TA`)_JAlTAf JAeԹTA ֈJATA'v8(#JA^RTAv\/JATAd87JAw`ϯTASFJA TAJAsUaNTAnoqJAO;dTA`ZJAu9TAsg(JAe޳TAyON"JA $ֿTAF/JAnTAz8JATA60JATA58-JA:6_TA2Z*JAm_TATxq@AJAؼTA|k JA@TAMD JABTA/HJA+TApJA3UTA_JAmF,nTAݴwJA^,rTAj3JA9˞TA] JAK\TAx_JA/p{bTA6JA]TAfJA}B7TAwszJAl@TAcb.JA uJTAAUJAdTA<1JAN TA9_JA"Z^ TAkR_JAzGITALJArTA(JAJ7TA}SJAqTAg*JA#c$TA9JA+JTA`uJAܼTADNJAZqTAy6JA0]TAw8JAZ TA)h<JA$)TA9JAJ[TA!JA MDTATPJA||5=TAaJAvhsTAwoJAH TA<`]JAM|=TA?JAIeTA,Y&JA;qPTA ` zJAqTAi^ JA{TAkIR JATA=oJA+3TAm\JACk:TAUk JAF4TA+-?JATA~#JA#TAX@JA"fTA\+JAT TAԷtZJAc4"TAԾmzJA]62TAa_JAaTAq e=JATA+!*JALTAaQ_JATAm$pJATAT}JA[ɆTA׋n,|JA-]TAc \JA2@5TA%AJA黡дTA>$gJA?TAꠦJA{TAHJA3 DTA[:)VJAITAJAUTAJAE ?TAF'JAѳRTAiJATAKf(JA2RTABM/JAwTA`ϓ.JATA%J JA.?S TAz6JA-f.Q'TA,JAN4FTAJAp3QNTAUoJA< VTA*JAZ`TAe JA|qTA"oJANˋ{TA@hJA֧ȉTA&NJAmTA<2JAeTA2j@JA( |TAkzJAFTA8 ƈjJAxo>TAVSJAjEðTA/5:JA !TATtJA0MATA*JA(TA 5JA0ٽTA9JJAg'TAtXJA;TA1OiJA|TA3qJA?tTAN$JA(STAt(JA|qTA/vyaJAwTA/[GJANA(TA@´K"JAl%TAJAud@TA;^>JA$5TA ^`JATAkJA*/U TABlJA?TAK7JAmTAS0JA"TAujJAr'TAs!JA7+TAQJAW?^0TAcEJA 5TA-LEAJA;TAꃾ#JA>TA9JAPGTAoJAL<[TAw.YJA ]bTA:JACUsTAd~JA`h~TAr,rJA;NTAi?,jJA0TA#6[JA TAix+8JA -{TAJA/-lTA@%JAG)eTAECJA,\TAҟvPJAQTA{pJAJM LTA)ZbJAıGTA[JAU 6#DTA{fyTJAx JA\N*TAGr~ JA/#TAq\~ JAk4TAr JA壶TA$L JA'TA# JAu,TAfâ JAJiTAp JA*wTAV JAvDTA> JAy N^TAk󮦠 JAStrTA'3 JAڏTA JA+0LTA} JAZTAPI0 JACtTA JA:sTAw##JAZTAY,JA7~ &TA^TA+vJA)HTA- +JA]TAB#vJAysTAK=JARTATALBJAlTA)&JA0VTA-_9JA9S TAmKJA3> TA @FZJAĺ- TAtJAT}TA'DJARpTA+@JAdo"TA#YlJAU 'TA%JAa+˸TAJA(@TA42 JANO?TAN؛$JAЙmTAB5DJA OTA7rJAAk TAYEJAi+1TA o7JAKTAXD9+JAHxQTA0JAƚyTASsJA]>TAJAufHzTA ieJA$ETA~e$JAv9حTA[(JAԽTA@/JA7TAnb@JAsHTA JAPvTA#?JAj\TAcXJA㛜vTAb:JAf_TA.C=&JAITAnŘ1JA +JTA!DJATA=TJAp1TA GlJAyTA4JAUTAfJAY RTAzNJA?:#TADJAGTAWIYJAæTAڢJAݍTAe#JAxz%TA! JAkTAU]f JAݝqTAإAJA℻TA*'JA9TA͒JAˆTA?̙JA׷߿TAwG JApU(TA[MJASTA VNJA:uVHTA&,#JA/{TA1SJAԢ(TAFTibJATA|JAW̉TAbtJA#nTAspJAzk{TAvnJAhsTA1[oJAǝlTATmtJAyUdTA2vJAduZTABJA(35STAɊJAJITAbɢ JAATA[m ǀJA5TAeJAWTAq40ZJA5hTA(VJAy3TATlWJA^жTAG$OSJA`TAIpFJA(sTAvV"JAFTA@JABKTA! eJA% 5TA7Yg*JA6 TAfmJAj"TA^ٯ;JA{Ǣ TA!/BJA墪TA$JA5~!TA^hJAWTA:tJAB;TAiJAwTAU )JATAgPX}JAjqTA8[yyJATAN{xJA{TA>MyJA:ETAsJACTA?4IkJAslTA^A^JAJgTAΣSL?JA9TA8 (JAK TA5JATAHJA^ KTAxJACTA3wJAۿTAY.rJATA,s+gJAt5TAXJA2?TAGJJA˼GTAJAJATA$5JAׇTTAZzq(JAyUIwTA:*JA3ohTA> 2JArSTA"A=JAsKTAmUJA Th@TAyv:lJA ;9TA5[JAP2TAJA 2,TAkΖJAހTA[JAb TA4JAQ[g6TAǺ JAK$TAP&JA7rTAڊRJAcTA&dJAkTTA!^+JAͯTA0bJA\VDTA̒JA4TAhynJATA3KJA/bTA4JAky[TA  JAQTAS89;JAw@ǻTAFu+uYJAyiTA3cJA-TA*=~mJAOeETAkgJA>pTA䆲JA#LTAm'qJA$!*TAGgYJA\?TAfJA=TAxEJATAA"-JAaheTAAJA|*zTAVJAHTAU&aJA_TA{,SwJATsTA JAK+STA;}UJA,;ݤTAd{JAñqTAz}JAI VTAn+}JA fFTAЯJA-"TAoJA4#TAWJANTAH(JAKTA_/JAQTAW6JA`'TA$/JAݨTAWڔJA)TAڌJAQ@bTA!&g JAaO[TAV@!JA$ @p[TAQZ JAu TApm JApvTA <L JA^TAu٨ JATA&H JA٭TAg0ה JACTA JA8ܾTA!"“ JATA-Ĝ JA|K TA6 JA]TAN+T JAÎTAq JAjo:TA1 JABTA JAyaTA/ة JAuqTAt0 JAwTA̷ JA7[OTAMh JA+TAJEq JA q}TA" JA{PTAw9s JA6zTAmA JATA:O JA鍵TA% JAcѾTA# JA@rTAѯ JAN.UTA'0 JArTA g JAF|TAG JArC3TAI JA*fTAQL JAX-TA7= JAk\TALk JA߳d,TAjY֯ JAϘV5TAu1. JA#=TA6 JAxITA  JA٧PTAT JA}yUTA-C8 JAC7XTAn̺ JA 4\TAcZ JANoaTA{=i JAǂTAB JABKʐTAo JAX6BTAn JAַ?TAn5 JA63TA 2 JA{nTAv JAi TAl$!JAfWTAǡR JA0R#TAF JA+TAֳc JAs0TAX4A JA3nC5TAmg JAcX9TAM>a JACTAr]JAPFTA#JA@TAMHJAmpTArJA0PTAO  eJAM}KTAbQJAO20JTA :JA:ITA6(JAJKOTA6JA) 5MTA nJAMTAD?JACEGTAXH3hJA%jTAaMJAY$TAX*|OJA^ TAOJAw|_@ TArQPJAeTAaNJAvR#TAԦGHJA~ӥ'*TA=N7JADSTA}fJA +kdTAe{JAܢRTAi JA] MTA.JAy"TA@JAv@TA@oJA~}TAۀ3JA;TA#JAA>TA3…JABTA'JA: TA- JA ,(TAH*xJAы,TAJAK`5CTA.aJA(MTA_ݒJAΐ= XTA؊JAeQ]_TA!PJA $hTAZuJAŅuYuTAmJA/]ׁTAJATGTAͻJAKTAz\JAܰpTAm,JAEhTA=JA]ޮTA$IJAq[ضTAujQJA/qTAaŋQJA*QTA-{5KJA'TA!AJA @TAD@֠1JA(TA4,JA1l3TAC.)JAݶTA)JA訽TA++JA-ʮTA'0JAJƞTA7tgIJAu4TAtعLJArq:TALJAGqTA DJA#_!TAR;JA l-TAP~I9JA7TAL+;JA-@TA8DJAA=MTAPJA_%KYTA>SJAYTAeQ>^JA0?XTANJkJAXTAjߥJA\]TA8,JAԱ/^TAxJAG;_TA.V=JAOmaTAJAXcTAd[.JA!klTA8JAMvTARCJA TA_4JAׂcTAMâ@JA7vTA# JA`TAD6JAt1KTAvGJA)TA?SJA:TAIz`[JATAlQyJA0zhTAMXJAMsTA_JAFTAZVїJATAe#GJA* 2TA]JArg^TA?,JA:#>TA PJATA-JAI'mTALJATA>5JATA"5JAvԝTA=_}JA\lTAJAzaTAЮJA~TTASJA0b=TA(JAaCTA3'kJAov#TAifؑ JA{,TA[1$ JA D%TAx;+ JAMTA{eKP3 JAAGxTAj@@ JA.gTAfY JA=JTA  JA8TATǘ׵ JA TAZPû JA2TAU JA4(TAB2 JAn>3TAc! JAD4mTAQ!JATAyA!JAQTA|!JA`q TA.,%!JA.TA:l&!JAp=TAM*!JA%1nATAJ<.!JA|:ETA'7!JAsITA{P@!JAЮKTAL!JA̰MKTAv a!JA9߻ITAi}!JA!JOCTALC!JAى:TA]!JAɺ 7TAo`S!JAr3TA )q!JA@-TA7!JA~+TA,!JA׉8b+TA!JAwg4,TA!JAB/TAgw"JA24TAuf "JAALTAF>"JA2I8XTAT"JA<,wjTA|8Ph"JA-;qTA|Y\"JA܉{TAY_!"JAt%|TA m2"JA8$N^TAu"JApM5TAF"JAῒ3TA ?p"JA*HӪTA-@&#JA>:TAC#JAZ{bTAQ`#JATA0Ej#JAC6ҩTA[(t#JA6[TAR1|#JATAC$#JABTA9rЇ#JAEߔeTA8Bsm#JAH TAV.f#JAF}TAbl_#JATTA~\#JAɻTA!\#JA}iHTA̕^#JA ATA6 $e#JAZTAUoLv#JA*#TA!tM{#JAUTA,#JA5 &TA`#JAۧz TAQ6u#JA,TAz#JA< TA~%#JA',TA#JAf60TA;#JA? s5TAf>[m#JA %;TALpO#JA0O ATAHD#JA`QFTA5B#JA+JTA*C#JAjePTA K#JA6TTAqV'W#JAlSXTA >c#JA꭛iYTAKo#JA¹XTA9X{#JA^VTA+_-#JA"fTAף#JAjTAIb#JAG-D{TA~ #JAz\TAT#JA[hKTA;[#JA(TA>$+$JAITA]$JAn}TA*T)$JAnTA^c2$JAzTAe{A$JAlH]TAkQ$JAc4dTAZ4k$JAE]ҠTAbms$JAFo5TAOy$JAz//TAk#$JA ٙTAϓ$JAׅTA$JATAl$JATA&$JA4gN(JATA6 @)(JA߷LTA&Y(JAATA?'JAc?%STA I'JAIcFTAk'JAdTAw Y'JA=TA-'JAOZTAK*'JA,JA3W~TA),Of,JAowTA|,JA>rTA,JA-kTA:,JAwx^TAӂ΋,JANPTA;0,JA?MTAj:,JAMTACY-JAѭQTA*o -JAxYQTAu0-JA>NTAе?-JAMTAtM-JAВ/LTA!>a-JAP |LTAyl-JA@ДMTA-JA [%XTAC&a-JAYTAI-JA5VTAԨ<.JA?u.JAiВTAO).JA(|!TAƋC.JA{:<"TA!h.JA!TAA.JA I"TANS.JA[3%TA.JAU Q'TA]X.JA_"#TA>/.JA7TA\x#/JAV$TAN~&B+/JAՠ‚$TAYi4/JAQLQ TA01|;/JA0CETAt1(Q/JA5 TAT/JATALZ/JA${TA'-q/JAITA_(!)|/JAbTA? /JA TA͵a)/JATAQV=TA +$2JATA/֡l2JAgG>TA)Fy2JAE =TAls32JA˞:TAn2JAT7TAF2JA_0TAtzd2JA_,TA:8 3JAae TATN3JApgTACiHv3JA7TA{3JAs YTA/В3JA$b~TA(ڬ3JAG TA}3JAX,TAKcD4JA(wTA|gT4JA3TABx4JAfTAx4JAGTAv4JA?TA~J4JAwTA鴅4JATAP4JA8.2lTA~\45JA2$JTA :5JAB=TAM5JA`ݨTA3g5JA%^\TA>A5JA}TAi5JAW.gTAJ.5JAwf\TA(t5JA}MTA+!55JA184>NTA\5JA@RTAf6JA3 j_TA=6JAw:gTA&6JA CkTA>26JA\9oTA):6JA@jXpTAy$B6JAړoTAg L6JAi=iTAu7JA%P`TA|7JA%#`TA 7JA vdTAgSA7JAJsTA4L;>%7JAzTAN=7JAq{TA&I07JA%}TA]7JAM'}TAUi7JAm $|TAD,h7JA 1xTA1$L8JAv/nTAi "8JA.0gTALs>8JA^TA?_C8JA@]TAEH8JAP:ZTA +K'T8JAbnSTAM^8JAk߬OTAZ^g8JA7OGTA3Y8JA=TAќ8JAdl53TA )8JA!I1TA:68JA0TA[8JAS/,TA޷'9JA>:!TA29JAATAgrv79JA!aTA\9JAbTA0ʖ9JA:'FTAW9JA1F"TA-9JAM$TAݖ9JAfr&TAH:JAf2TA+#:JA9y 4TACSK:JA/6TARr^:JA"a7TA~$k:JAJk8TAf":JA 6TA#p:JAB6TAMh:JAX5TA :JA3TAw :JA|oAO2TAi:JApqnITAޱ6H;JAֶTTAb6i;JA[TA.;JANcTA2(;JA\1mTA8F.;JAl[TA$(JA=^TA'E>JA.9bTAvJ>JAքMbTAIT>JAY(dTAg>JArjpTA>JAZkTA!>JAQTA ۖ>JAYCTA0>JA7.TAMyW>JA.x3#TA0ŭ>JAd%TANy?JAP4 TA+7?JA]!TAn '5?JA#.TA?JAl|4TAi.@JA›Y9TA)N@JAkv==TASP@JA+%TAR}~~@JA+TA?'@JAfTA)@JA?KTA\-@JAX5TAl@JArUTAyj@JA> TA0UnAJA#TAߒAJAqxTAơMbBJAjV^TA<JdBJA./:sTAEhBJAobTAE[pBJAcQTArBJAITA:BJA TAOBJAK TAҹ-BJATAڒBJAl)gTAex2ˤBJAM6TAcuBJAӗTA"BJAvTAx1BJAK&;TA'*BJA TAc(BJA TA"BJATA %BJAAowTAABJAepTABJA6(TA|`JBJA*MTAAJA&,TAۓAJATAv:AJA'F TABAJAoZ>{TAŞ0AJA%nTAD0AJAfqwoTAk-BJAT ,pTAQRBJAѫqTA pBJA1iqTAPmBJAkTA34BJAymTA BJA/c1omTA$CJA(oTA :SCJAT~qTA5mCJAxtTA͊CJATAh$CJAiٞoTA5R$ CJA}TA DJAJpVTAVwDJAE)!TA9B#DJA!àTA>DJA VTATAIFТIJA TA4^(4IJA7TA WIJAlpb^TAKeIJAjMTA:SSmIJA {TAgIJADTA4IJA TA sϺIJA*A6TA$aIJAݖTA7IJA̡{TA2vIJAuTA IJAXSTA\ IJA|TAltIJA1SvTAWIJA=RgTAX]tIJAR*5[TA !IJA`[TAIJA {[TA҉ JJA nCiaTA@%JJAnTA'v5JJA.vTAVBJJAL{TAmdeLJJAZR4}TAetYJJAc3~TAzJJA(TAIgJJA ⼂TAP5CJJAXTAolJJAjXTANLJJA bTAJJAETAc KJAPtTA7h4KJA6dnTAY_KJAQnTAKJAoTAR,gKJA21gTAbHKJAl{TA_KJA\ŖTAnXLJA,TA 7LJAQҋTAhqxdLJA2TA M;LJA?WTANzLJA~TAGLJAC.cTA$LJAdTA7SMJA\TA+MJA;\TA䉒"EMJAfTA^zcMJATAP?MJA>TAwMJAAQwSTAIsŵMJAlbTA9MJAd+)mTA MJA,W=TA"<}NJA@@TAڋ%W+NJAnTAͥzTENJA:TAK TXNJA(10TAMbNJABTAʊ NJA* TA`NJAaZTAlNJA(v|TAlNJAω4TA48i?OJARTAEegOJA ^TATshOJA 'TAi$OJA΁,TAߙPJAiqi4TAoUPJA)TA[zRJAavqTA&9SJAL?yWTASJA)LTAmXSJA+cTA3cSJAyrbTAnkSJA cTADuuSJA/N`TAzSJA$[TALLrSJALdATA@AsSJA:TAsSJA@m*TAtsSJA&TA&)oSJAKsTA iroSJA0 TAgBmSJA#bQ TA__kSJABTAuoMeSJAn.&TAubSJA{Q@TALCISJAbTAথFSJATA?SJAVTA7_1?9SJA?TAݕf2SJATA#.SJAҏTA J,SJATAmSJAp/TANSJAnMTAroZ SJA1#TA%eRJAxTAlRJA =TAwWkRJAbkTARLIRJAՙMTARJA04TA?j%MRJAiTAyi RJA&޿TA 㶄RJASкTAxilyRJA TA_GRJA'zTA_#RJAUwTA_RJATAgW!RJAfTAq_RJAՑTA54wQJA!TA(DOQJAAgTA QJA~TAcQJA٠rTAGtĆQJA`v;nTAU]xQJAOPhPJA_kTAԔ7>PJAQ^TA111PJATAD1+PJA#TA}PJATA창OJA!FTA%OJATA:OJA(&TAOJA]\TAcB߱OJAiTA!OJAL˸TAoOJAxTAIa bOJA9TA+rAOJA|BTAm6OJA/i TA$eNJAҺ7TAOq2NJA!TAxNJAYc{TAQޟNJAuTAENJA3TA5NJABETAȍCNJApJiTAGNJAkqTAx?NJA%TA)RNJATAjm|NJA^_STAnqNJACTAcNJA\7TAPM_NJAn:MoTAoT]VNJA/CTAUPdENJAXTA/3$NJAkTA;|MJAk`TAW֨MJAV0TAMJA~5TABMJA>fyTA1-MJAZ/TAmYMJATAHtJˇMJA`TAdPޏMJA&ҼTA6xMJA.eTA{nMJAlTAzg*TMJATAAMJA9FTAIQLJAEEGkTAwLJA>(şTAx LJAO>TA ӀLJA9_?TArS`zLJAeP}TA@lLJA%TAr&WLJA)TAZKLJAATAr*8>LJAJTAR"6LJAjiTAF~D.LJAJ TAi LLJA>uTAN LJAwTAnX7KJAyZTAğFKJAxTAMKJAF̓TAO5KJAeVbTA6zKJA(˫_TA2]KJAWB[TA>KJAQә[TAUZI+KJA•YTA KJATTAbJJAc":C@TAVJJA8ΗO>TAx@MJJA=TA_*5JJA*TA)EJAjh>TAep0CEJA%>TALEJAVDJAceWTA xDJA_TAtv2ˍDJA$?TA?[DJAtBTA\_DJALGTApDJA%CTAeDJA/͕ TA^DJATASDJAk\TA[DJA1*TAמB[DJAdi!MTAWϯDJAzDTA\ "\DJA9aTAU2eDJAeVYOTAl2iDJA*JTA=XDJAG8TA#D_DJAYTAHg{DJAvTAm}DJA#RTAYLDJA_)NTA/`DJA'MTADJAv.MTADJA$h>hJTA0bZؓDJA_?TA-ՏDJA >TAF6VuDJAꌘ>TA<nDJA=TAΈkDJAɢW7TA`qkgDJA|C:TA4iDJAH7b TACqDJA TA #zDJAo TAѶDJAjP TA%4DJAp,TAA$iEJAљlTA t 6EJADIfTA'lEJAk!TAJ5`EJAQDTA1oEJA@ TA'5M!EJA TAj[BqEJA r+&TASE)EJA[PTAEJADTA7*FJAQxTA%43FJARTA!DFJAx/TA1IFJAgxTA kaFJAZTApFJA%TA/BIJAiQ/TAQ IJAfTAIJA>ZTAJ$JJA[TA5r,JJAT{TA0JJAVTAFJABy TAʑ4FJAsTALFJATɿTAHEJA TAU;EJA/'TAfz+EJAxTAIEJAf TABo2EJAv TA\pʣEJAe TA$EJAe)TA~EJAZTAt"~EJAP.BTAg`EJA{9TA#EJAPSTAZHEJA{4TAiEJA|8!25TAULEJAt;TADEJA t9TABp8CEJAMkn5TAC>EJAd<TAk;EJAlDTA 2EJA?TAEJAغTA)DJA)TAo|DJAgi-TAұ\DJA sTANDJALTAhuDJATAeT7yDJA:TAyDJAj!:TAa]DJAUTAeF JDJA"-BTA)DJA\TACJA|TA@y~CJATABijCJA;TAÄeCJAXշTAXjoCJA4TAU` wCJA0TA yCJA\oTAY4CJAElTACJAFҵTAy CJA7TAţ CJA$YTA6?ҏCJAKmtTADdCJA_چ_TAYȗCJA5ZTA7CJArYTACjsCJA-|TA{eCJA'TAZ|GWCJAR~,TAACJAI0TAe"1CJA H.TA[%CJAxa.TAhPCJA~'2TA;cBJA7 p8TAkoBJAQu۵:TA oۘBJAy*qCTA KBJAAATA; ?BJAhATABJA$YkKTA`AJA4ڕgTAVfAJA;kTA&ٷAJAQ(oTAŻAJA@xxTA^uAJA3WqTAAJAbTAcAJA+cTA!~AJACTA43{AJARָTAHYAJAڥTA';q0CAJATAd=AJAjb$TABtzAJA[mTA^Vf@JATAU<@JA7gJTA_߄@JA:[TA#@JA0fTAh1@JAi[JTA/&@JAsarTA@JAePxTAc@JA:!TAx@JANسy'TA2O@JAmD*TAɠ=@JAԼ/TA) <@JAO@TAt&?JA:BwRTA\ ?JA;0hTAeF9Gn?JAChTAEI<>JA[eTA>JA܉gTA?JA?,TA`?JATA?JAITAaH>JA TAhb>JA혳TAW)>JA]2TAL)>JA"2ϯTA’>JAкTA}tL>JA4U=TA;9G>JAa)TAj>JAɓ4TA=kL>JALTAD[h>JANTA8]_SP>JA>_TA7( I>JAֺ+TAHE>JA!^TAoe@>JA6jrTATi4>JA{TAN4(>JAJP TA;@W>JA\"H TAo=JA!N TAX%j=JA2e TA,=JA&TA=JAR TAtw=JAnj#TArY=JA-#TAJI=JA %TA}=JAM&TAJ'=JAs&TA+=JAQDTA P=JA\>TA5Ќ=JAceTA,Xi=JASV TA=JA71TTAKg=JAR@`TA0=JAV2OTA!#Z=JA bTABG=JAi>TAa=JATAv|=JAPTA$g=JAFTARZ=JAIQ3 TAAU=JA` TA8^/=JAPTA'cI.=JA;f>TAN-,=JA$M TA'C!=JAv)TAcs#?Dx9JAi TAV^p9JAB}TA0dg9JA8TA}Z9JA#1+TA1G9JAl(YTA7&39JA[TAQ9JA*TA;8JAJ1@TAj8JA3ETA`8JATA[S8JAaJ TA18JA3 TA08JA^UwTAl8JA" TAZ;8JATA|8JAt TAker8JA6Fl TAy]j8JA Xa"TA^d8JA^5(TAbr%Y8JA].K-TA@O8JAl0TAVHMF8JA/TA?C8JA4TA5* 88JAT:TA&8JA5>TA6>8JAءC/@TAlv8JAR`?TAÊ8JAD:TAyq" 8JAWDTA:T8JA&JTAVz7JA:mbSTA7JA6AbTAv7JACbTA'7JA9~gTA7JAmTADN7JAxoTAN7JASrTA\%7JAqTA厯7JA#A=wTA7JA@J-yTAV_Ţ7JA xTA4k!7JAxTA]7JA!uavTAH27JAr^DuTA?L4|7JAlHwTA,4es7JAn[rzTAed7JAVV|TAX7JA~TA3T7JAWP~TA]L7JA`~TAG8G7JA|PUTA@7JA{TA]07JALTAT"7JAaNTAS 7JA-TA&"7JA.bTAcN7JA4-U[TA M7JAHTA%O7JA>䫺TAѷQ6JA2L^TA_(6JArTA6JA= ֜TAS[6JA'ߞTA!>6JATA[ۚ6JA[TAb]6JA[OTA+q_6JA|>sTA[Y6JA qb^TA!V6JARTA/n U6JA"nU*TA E6JAf7*+TAJ|86JAAt/TAnK6JAb0TAl_6JA7xTAٰ`6JAkTAܮ$q6JAuUTA"*6JANiqTA6n6JA mTAsT6JAM ÉTAO'6JA oyTA񼜣6JA{uTA&u6JA^^TAXW6JA\g.NTAP6JA]gCTAz-6JA#6TARf 6JAYAh)TAotJ5JAwRKt'TA5JA^0+TAZ5JAZ.TA7z5JAv5TA 5JAe TA?:Cc5JAK!sTAn5JAq9TAԷ=4JA1㍓TAq4JA/ѠyTA{4JA2|TAl{zw4JA\GTAs4JA^TAJ7yf4JATAY94JAvcTAv`3JAv4TAW3JA. TAn3JAb[TAsW4JA;TA 4JAV[ZTAP93JATA>C3JA&TAΛ0h3JAW_TAQUF3JAVTAFz3JAVTAme3JAt91TAx\3JAi`$TAf*4JAr5(TA!4JA)VTA6(3JA/TAlI4JATA]4JAQ0TA{# 4JA:8VTA_b3JATA:IYTz3JAb޿TAg\F3JA||!ۿTA> -3JA$>ؿTAA3JAT]տTA2JAaaE˿TAD=2JA~iƿTA'*ߓ2JA2TAEZ2JAhTA;(2JAi⿿TA8An1JAƿTA5%1JA+/nƿTAM#M1JAQwʡƿTA/Oi1JAmړTAa{f1JAܰ?TAOE1JA.#JTA71JA8TAѝ0*1JA,TA6T1JA#rTAT0JAdKTA!r0JAxc TA=0JAN-TA, 0JA' TAiů0JA TAT0JA؉TA=80JA~TA?ʘ0JAϾTA10JA u̾TAFߞ0JA TAD0JAf?TA0JAVpTAٛY0JAh+TAAy/JAd40/TA9B/JA 1TAZ/JA2TARn-.JAHeU7TAMBh.JA*B#JADTA}P>JA=&xTA l>JAe1bTAd>JA9TAP>JAF)7TA5|>JALx(bTAggy>JA*mTArł>JAd4TA\;I>JA#TAuN>JAoTAB>JAgTA>JADTAB>JA"|۝GTA3|>JAa JTAYy>JAV\m}TA>JAQ[/TA>JAWTAd46m>JA)TA=V>JA1*TA 2?JAv;TAx9?JA{W/iTA`?JA^yTAnD>JA `R TAA>JATAp?JA{ {TA+|?JA} TA^;k?JA=&TAˁ8?JAOw-TA (?JAmR(_TA ?JA~TA-V?JAzTA;p ?JA_,TA0 ?JA;O,TA\ M>JAm,TAc>JA5TA!>JA%,4TAo]V>JA`-TA(V=JAV.-TAv=JAy4TA "V=JAJ;e6TAQ>=JAv;{lTA=JAؒ_rTA=JArTAk=JAoTA w=JAFPwTA3=JAPbTAb#=JA}TA?E=JAyTAi}=JA TA=JATAYAd=JAF_ ;TA;=JAq>TA)´=JAZK2/JTA=JA=*NTA]1>JAJ9WTA`BV>JAܶ(aTA>JAJcTA!C>JA!N1^fTAۢ>JA;)kTA>JA+|TA>JATA~P~h>JAe"@TAG>JAJɋTAA_>JATAc >JA"`TAi?JAo7iTAG;n85?JA*OTAėT=?JA>_TAY:P?JAqPTAea?JAPe׿TAXOlh?JAρTA\9x?JACTAGEN?JAxTA ,M?JAKTAױw>JAITAk3 g>JATA`\=JAVSTAg=JAPViTA$(uZ=JA"TAu=JA CTA *NTA \3JArHTAI|ҽ0JAFdRTAהai0JAgRTA&9i0JA͢w!'TA}kri0JA TAA'0JAGTAS ~{0JA+ TAђ0JA TA'y*0JANTATM/JA)tTA;b/JAZTAFI/JASTA{/JAϤTA^;j.JA8'͛TA^o.JA]v5TA.JAI!TAb߽.JA$TAi3.JArjTAAۍ.JA_)TAݥ/.JA+TA&H{f.JAH׋TAebg.JA]6mpTA!;_.JA 4xTAz5.JAnTAo .JA jPTAD-JAm5kLTA[ .JAh+TA<.JAyh'TA4 >$.JATTA36-JAp)V}TA"V<.JAOTA` u-JAf̻TAB.JAxTA@d<.JATAO6.JA$[TA-NG.JAp(HsTAD{lN.JA `TTAR.JA?=TA25Y.JA^ /6TA[9a.JA5T TAUc.JAqTA@.JA>3#TAP4.JAwTABev.JAG,tp +JAGTAVr+JAkoTAjk*JAV"UTAtN9f*JAuFTA Ha*JA$ >|TA*JA@kyTAR*JAo޿ÒTA; )JAVߒTA?)JAVTAHp)JA A_TAgs)JA+kTAlʱ)JA9 TA;I)JATAcMt)JAQHTAQ(JATAѩЮ(JA!TAUũ(JAkTAqJ(JAq;V.TA\mu(JAzTA,#sf(JA&TA6kb(JATA k^f(JA,EvTAB(JA|NY5TAc潃(JA2dtTAvx-Ep(JA+@WTA}޾(JA(VYTA ;(JAd >TAC9C)JA5hTAu/JAbjTA] >Ҟ/JAm" UTAԡ/JAg%TA2{;/JA*R&TA'/JAaTA/JA=|TAi /JAzWTA}ƺ.JA TA[|I.JA5TAPoc.JA<4TA#.JAF ^TAc.JAiTALZ.JATAqf*.JA(wTA$ɸ.JAg?oTAO .JAOLTAw.JA8%ATAWM.JA\)TAtkWs.JA*$TA(Q.JATA.JAdq TAq.JA46TAO-JATA쐧-JA5TA~d-JAxAhTA>-JA*&TA!N=x-JAXɘTAb)]-JASTALv-JA#HTAhM5t-JA6TAAZ$-JABP[6TA-JA 5TA#L-JA|-hTA:|-JAa:TAʦ%-JA،rTA :.JAɍDŽTAΫg-JAqTAy,=a.JAV+\TAU/e.JA>TAh.JA0ҴTAJL.JALMTA?dЅ.JAf5TAgk.JA{Y|TAǨ.JAaxbTAWeo.JAƭ_TAs /JA3ZTA*z^.JA=00/JA89TAmw/JAS-TAvI!0JAd 3TA>V0JA0:TAx0JAӐn1JA>TAs1JA27'=TA>ǐ (2JAn,@TAe_'f2JA<]CTAFT2JAI=TA82JA(MTA 12JAkXTAQ$g2JAküFcTA/Djm2JA{TAaE2JA8TAuSH2JA(TA望!2JAy躭TA46d3JA^CTA@3JAyBTA*]2JAr3JAg]TAy:G3JAn* TAY'4JAY3CTA^4JAnYTA94JAەTA4JAzpTAQbSon4JATA^xo4JAmTA 4JALTA\4JAF8JAʱTA۷-g9JATA|9JAz#TAmK59JASTAc9JAV]TA9JAT% TAC>9JAhhj TATɰ:JAjuTA!:JATAjN^$:JA;5TA&&:JAܓ/#TAN$>):JAR&TA:JA::TA:JArr6>TA/;JA?TAf|G ;JA*j?TAtt+;JABTAbJ@j0;JA`CTAY7<;JA>7FTA=;JA9(BTAaX?;JAZ>TAe_B;JAز6TAvM,H;JA`(TA Q;JA\TA4\;JATA|2d;JAѶ7 TAjFk;JAJAֹlTAk!>JA&|-jTAy?9>JAcTAG3N>JArdk]TAqh>JA2,+OTAmCJ>JASoCJA2/TA"k>JA7(TAjO)>JA?gTA-:>JADTAAhzp?IAGrsxUA'J_JAt?,UA*8&JAMcUA2&JA%t5UAr:&JAGUA S/&JA.9u UA/v&JAౘ(UA)}y&JA UAI&JAbIUAc}&JALtUA&JA UA E]&JAovթUA&JAWUA(&JA#UAؠ6&JAUilUA:&&JAJeUAhDVs&JApu{UA-z!z&JA3}oUA'b&JAlsUA&JAH^~WKUAHO ט&JAB!EUAo&JAW=UA߻&JAyX,UAº&JA;"UA(/&JArUA &JA`jUAA:&JAL 0UA1yAD&JAbeUA?%JA7fUAoj%JAFOTUA?o0V%JA;UAkd%JAEUA~$JAUAҖ$JAg-UA' G$JA5+UA8W?$JAasjUA8$JAUAe"$JA UA9l#JAǬwUA12#JAsUAS:h#JAYԸUAmx#JA);UA#JASFUAƑ#JAnO&UAvQ#JAˆ*2UAIP#JAz ;UA#JA 7\x<UA`#JAuf=UA慓#JA$7UA#JAx'.UAɎˁ#JA~6C*UAJ. #JA֛6UAFd"JApUA en"JAUA"JAOEUA>e[!JA }UAms!JAM UAP!JA&UA4}o!JAg$UAwm!JAx UA JAXUAK!JA~>yUA{N!JA~UA~!JAdsnUA6!JAkUA8XM*!JAPplUAC"!JAޥxUA*8k"JAUA2aq$"JA@0AUA\o"JA0sUAg2"JAe3atUA`"JAk-tUA3W"JA3#}UAj"JAUAyE([l"JA>,UA\db"JA!UAJd"JA%%UA4(Z"JAZ)UAߢɋT"JAFP]UAz="JA@*UA."JA;t9UAi^("JẠUA["JA6-[UAx%?Yn#JAp?UA3##JA匡UAϵ޲"JAUA"JA>UAvsߪ"JADUAϐ^"JAO4UAT4"JAoRUA;="JAUUA H"JAMßYUA,Z"JAXUAv="JAt UAs.!JA)YUAn[y!JAzUA:^!JA]UAFc߅!JAHUAs!JAUAH!JAcdUA"O;!JA"UAC_8Q!JABUAk*]D!JAMUADs4!JA sYUA~] JAoUA9 JArqVUArֽJ{ JA -UAW JAlUA JAIzaUAJARO| $UA6TJA UAJAUA~,gJAWUA$u#JA.RUA\}nJA9/T=UA *ZJA+DUA)UJA)=UA%^9EJA$uUA窆JAۺUA'JAF mUAiJAނUA[__qJAıUA[JA_0UA'JA8UAi_uJAu=UAhJA1CUA(3+|JA#OPUA~JAs2]UAssJAjXlUA7VćJAvtUA(JAOuUA~AwJAd˩UA^I{JA?'UA e;dJAe: UAȂl]JAsUA\JAwUA|SJACIUAp&JA(UAg%JAXUA/M^,JAh)~z!UAm@ίJAt>UA0JA mUAq JAVBUAlJA}ûwUAmaJAUAJAUAtJA UA5_ JAqUAf۲JARGXcUA`خJA46FUAĠJA.`UArJ0JA#tjUAL~JAsImUA~QJAՒyUAe9JAiDUAӱ"]JA )UA&JAUA4JADuIUA{#JAUAOdxJAYP;UAڞmJAv8UA XKJAL0UAv =JA j2UA6B/JA^UAfUhJAʹUAk JA=rUAzJA{6UAT,JAUUAk_JAHUA JA5eUAJA1UA@JAEV,UA,JAJ@UAJAzUA6kJA 1UAs-:JA,MUUAڟkLJAvÃcUA<2QJAkUA}PJAItUA@)DJA#UA~~8JA~*+UA܃(,JABUAɐJJAy2ոUAfJACOʵUA@JA `UA2JAUA@JAcCUAJA}UA:JAjwUAZ3JAݝUAERJABUAMlJA}* UAJAq3UA9JA:UAoעJAx*BUA4{JAx.OLUAGJAUAxUJANUAJASIUAJAџUAxJAͺ"UAұJA9uUA JA2]!UA={c~JAUA68K[JA9pUAؾ.=JA8UAƯ(JA3UAx\!JAJUA,  JAÇUAoJAUA4JAH띦UAffJAFUA^aJAu԰UAۑ(~JAڛ'UAapJAcUA믙\JA5&UA._JAJ҄UAyXJAjUA*#?JAFUAv'"JAQ UACYJA־UAJlJAUADJAh%R UAI JAMǩUAY?aoJAUA>qJA(_UAJAgM#UA4|JAht*UA7tnJAvI+UAJAIA&gUAYJA.2UA+jJAQtbDUA7 dJA5-})UA~P4YJA(7UA<4bJAa9u?UA2s+LJAd#MUA^d 7JACUUAV"JA^UA- 8JAe1hUA+*JAjcqUA2JA+ uUAu3z?JA*k~UAo-JAv\H}UAaJA&LuUA= JAQrUA=zJAs TUAR7JAi,'oUAb0JAggUA' JA ?eUAYؖ JA;7nUAsj JA1UAfg JAUA JAUA4 JAUAlt[ JAUAV淅 JAϕPUA}!A JAƕMUA6 JAUA3A<& JA93UAV JAҞUAϝ JAeUAUa JAbUAF JA]0NuUA JAD9UAÛ"e JA+zUAyQ JAfPUA[@ JA\ OUAz, JA UA{uj JAڕ\UA/ JAUA1 JA] UA(x%JA& UAΫkJA% UAsqJA)w- UAJA5ZMg< UA0'VJA+t> UAv+JAN"m UA$qJAD UANІ5JAL!UAH)JAfL#!UAѓKJADE'!UAK5JA~*!UA|FOJA͍G.!UA܁\JA?g1!UA,dJA55!UA*JAx=ْ8!UA#JA¡;!UABJA-Yw?!UAJAGB!UA5#JAwD5F!UAiY JA[J!UAVJA\>pM!UA"fJA$Q!UAaJA/bT!UAV&JA9+X!UA{5fJAmM[!UA JA i!UAJA l!UAOfZHJA4w!UA9 JA.y!UAd|6JA!UA\⏮JA-w!UAg{JA[!UA{A JAQ!UA_JA{E!UAݔa&vJAʾ'!UAh 'JA.!UA'W7JA5,m$!UA۰JA !UA+N2JA۽P!UA{JA?d!UAW(JA7b@"UAO LJA}"UA]JAMf"UAS\JAJE5"UAl=uJAVC"UAiˎ`JA 6O"UAyXJAI6]"UA-s3bKJA'G}"UAkq'>JARe4"UAu 0JA6֔"UAҿc'JA짘W"UAE) JAb[G"UA֗,JA "UAsyJA%s"UA$#JAp&"UAwDϮJAjc"UAI JA"UA$5cJAt5i"UA6MJA^"UA}ENJAC"UAݦVJA5f"UAJAa"UACJA*"UAȢJA3R##UAYJAb>a #UAqJAX#UAU³(ZJA̕#UAezJA8 #UACJA"#UAJAh #UAMA-JA#UAm#~JA\R@#UA8lJA9 ?#UA%C{<JA!}w;#UA4JA m7#UAW JA; 4#UA}#/JAT2#UAsaJAM(.#UAlԺJA"#UAhJA G'#UADAJAHðYJA"G|#UAɠ}JAp4#UADJAZ#UAn JA)џ#UA*Q>JAjRE#UA:JAYl#UA@մJA#UAc7JAW#UAVxJA7*$UAֿ~hJA$UAf7JA%l]^$UAv"JAl$UAIIA{]$UAzVIA]-0K$UA[vIIAb?Q$UAeCIABOS$UA|,IA1Mw[$UAIAhtm$UA`>IA$UAf—IAU $UA>rIA+_輜$UA͍MIA_ $UA4 IAڱP$UAeIA($UA]\IA$$UAxEfIAn$UA/IIA*$UAD"IAiI$UA&|3%IA+S$UAX4 IA~`$UA8 ^"IAE ,$UAT=Y-IA }$UA~GIAMa%UAKIADZ$UApIAcO$UAl#ɂIA~#%UA5IAF%%UAC9IA"W)%UA%LIA>/%UAIƴIA5#5%UA\IA(IA,ҳZ%UAG@IA#֘^%UAUIA5Rd%UA4SIAFsp%UA^~IA9%UAFvsIABOГ%UAQ1XnIAUG%UA4~nIA,{%UAWYCoIA7M_%UA*uIAҸ%UA\wIAE%UAJuIA/M%UA~rIATK%UA]welIA%UAIFIAZ%UA(IAʿ&UA*tIAv&UA}IAiɼ&UA/JIA}m&UA@ĖwIAt1&UATŠIAL&UALDaIAD\&UAGo#RIA$?`&UA>JIAUFwa&UABIA;몋a&UA/IA]&UA2&IAe&UA< IAh k&UAhEIAQAo&UA"KIAq&UAwIAJ{&UABԍIA&i&UAieIAts&UAT4IdIAW x[&UA!hY]6IA&UAE~IA L&UA)`#IAỹ&UAFyIA 8M&UAA/IATi&UAZRaIAYњ&UA'sIAz8&UA%.IA%8&UAe׽IA؍&UAo`םIA[&UADJIAV;&UA!bIAG:A&UAkMIAbO&UAzp?IA/d&UAi1 BIAR&UAߝˍAIA h&UA9EIAM&UA NIA%m&'UA=\YIA 'UA3ViIA'UA%IAV'UAz0IA:@'UA-LIA'UA;)ثIAȬ~` 'UA(}aIA;!'UA*ŞIAEc%'UA6^IA/9'UADIA0B'UA$IAeI'UA1IAZ\'UA)LIA`'UA<>IAm~b'UA]IAb~f'UAgv IAˇl'UA]IAIc{'UAQIAH'UAr)\2IA'UA_rqIArX'UAe(IA]'UA xIA'UACIAn'UAƹIA9'UA'*IAfe'UA١IA˶'UAk IA2w'UA>rrz IA9A(UA53IAE% (UAN*5DIAem(UA oPIArs(UA]^IAt'%(UAiqIAAN1(UAnIAvC(UAFDIAl0f(UA:IAbl(UAyIIAi1Hs(UA,IAax(UAEIAV=*UA'OIA)@*UA$YfmIAE*UA4זIAViP*UAh2mIAV*UA DsjIAVZ*UA'$IAWԡf*UA.i@"JAm*UAKXeJA0ލk*UAJA*UAJA*UA]GJA}Yj_*UAB*JACny*UAoALJASOt1*UAecJA]Y*UA:!1JAȆ*UA퉦JAY5*UAfJAR"h+UA>oiJAL+UAۓ}JAOT+UAf]ؐJAo+UA<JAA+UAJAJ2+UAJt)JA?+UA7JA`B+UAs@JAHD+UAkSJABK+UAۨJA\^+UAbcJAXve+UASjJAvf+UAJAѻ-i+UAm9 JAl+UAl0JAq+UAJAŹQ+UAJAl+UAJH$JAZɜ+UA&&CVJA6+UAau]JA\+UA-J xJA5έ+UA9ըJAO+UAFJA5y+UA(2JA4+UAVpJA!a+UA/^JA/'J+UADJAt+UAUo^JA9i,UAX[œrJA`,UAK"JAX,UAv^JA;j,UAfwJAe+UA JA!+UA JA5xK+UAiHJA@+UA {&JA0f+UA3JAC+UAxكEJA+UAH, TJA޸,UA'DeJAfR,UAZPJA£J+UAu}JAHV,UA?4JA== ,UAXJA,Z,UAGOJA,UAi4JAn,UAhY!JA#mr,UAK}10JA\0,UAe6JA$_",UA7]>JA8v&,UA[{BJAa',UA~xJAt?,UAAG$JA5,UAj*bǺJAg,UAKfJAco+UA[EpJA\ح+UA;yJAZ<+UAqZTJA{Y+UAJI|JAh1NJ+UAٓ,JAN݅+UA6٥JA+v+UA,ڧJAS0{rj+UAaTUJAK,"[+UAJJAF+UA=JAi-U++UA8JAl|+UAOuJA*UAYǡJA*UAŏJA΂5@*UA!V“JA+o*UAD)JA~*UAĝJAJ%*UA?JAsx*UAJ~JA.`v*UA_JA+ch*UAmxyJA3*UA?z uJA**UAnGpJA(X)UA;^QfJAFk)UAUdJAh|)UAP"heJAM)UA/ijJAĩaE)UAl{uJA3i)UA氛/JAE>y%=)UATPJA)UA4h JA!(UA|b JArѨ{(UA%! JA5Xzv(UAn" JAEJ(UAw JA1'UA| JAsH*'UA_Q1 JAl'UA?m JA.`'UA>|" JA\W`ȇ'UAe}I JA}pw'UAi{5 JA/p'UA0; JAfjj'UAV1C JA=m_'UAI1RzO JAk;V'UA` JA"{I'UA}&t JAX! <'UA=% JAKG2'UA1SZJA\N&UAU XvJA _&UAJAWBe&UA>iJA1C%UA(JAm%UAJA;ӷ_%UA1JA jY%UAi:JA+hG%UAH+JAQ%UA/O_.JA$UA}=JA$UA^؁JAm$UA4 E#JAc^$UA`=JAjL$UASJA9o$UAGJAFy$UAJA1;Q$UA JAe$UA0/v#JAT$UA]ړ/JAR#UA=JA3?#UAp@JAjI#UAen4BJAe#UA1v@HJAA}Gv#UA`KJAՌԵ#UAvKJAm ơ#UAv#IJAVFì#UALJAc#UAN[WJA^ :#UAq_JA fm)#UA,;N=cJA!#UA, :qJA_M#UAݼڅJAΝ"UA JA 7>"UAJAZ"UA86 JAD!UA,ٍJAwB,R!UAg"JAGE!UAz> JAiI1!UA{\JAV(!UA;JA^r!UA?JAZE!UAeهlJAz5C UApvJA UA#JAZh UA!JAC} UAyhWXJA%z UAj8JAA:^ UA5JA_hg+ UAΟ'JAu# UA+!b8JA2d UAXJAfר UA:nJA~ UA|3)EJAMO UA;JA UAbJA=Ȑ UA1=JAv UA|iJA\Pz UA*H JAƶ UArJAZ  UAS.JAA UAe,JAAN4& UA3:JJAHC, UA9lJAI0 UAOYJAAT3 UAZJAW_3; UA UAG LJAA< UAUGJA]a? UApX?JAglF UAZapPJA-yJ UAd* JA`qQ UASUd JA8fQX UA(z JAc.Z UA} JAHK5[ UAء JA$f UANA!JAWx UA1!JAbk- UAsZL4="JA 2W UAt[f"JA\ UAsI"JAţ UAmй#JA:> UAr#JAz˜ UA[ $JA3Vs UAMjWo$JAs^ UA$JA UA;?$JAdl UA/%JA6d\>!UA_&JAѦ'!UAo"SQS'JAP!UA2OE'JAN.!UA4~r(JA1|!UAXL(JA!UAr(JAR!UA@+)JAh)_"UAG/)JA*er "UAErd@G)JA}"UAx4)JAL+("UA*JAnM"UAb{:*JAs'Y"UAc+*JA{"UA!V*JAR"UA&J*JA"UAc5 +JA~"UA+JA'/K"UA@AE+JA"UA1p!,JA"UAg56,JA<]g#UAk,JA##UAsc,JA( #UA-g,JA% *#UA~;,JA8-;#UAv -JA^hHL#UAbE-JAqU#UAבo-JA`yW^#UA,|-JAiog#UAo͌.JApBo#UAKo/JAn~#UA܂/JA#UAs3/JAM!#UAZ)/JAK#UA"|Mz0JA#UA}?&0JAbA#UA>j0JA #UA蘀1JA#UAgq1JA͒#UAuɶ2JAI#UAR2JAȳ#UAO3JAvGdӹ#UA(*3JAB#UA>4JA#/#UAhb4JAG#UAn:܍A5JAPo($$UA25JArH$UAa5JA\U$UAU6r6JA2m.g$UAi6JA$UA(fL7JA<9$UA`7JA !m$UAh07JA`n$UA͆8JA)j6%UA֏G89JA|vP%UAyP9JA]~U%UA l:JAD}%UAh:JA 1B%UApq{:JA%UAX#;JAIyb%UA$r;JAE;*%UA6{'>JAan&UAN>JA&UAKdR?JA>gW&UAԏ?JA&6d&UA]?JANyr&UA#o0H@JAo9&UA)T@JAҸ` &UAS]@JA&UA-8; AJAP&_&UA'^AJA.x&UAAJAHݯ&UAK5b{AJA8z&UA'AJAZ&UA\N;BJA &UA -BJA۳&UAn3+BJA=&UABJAGb&UAO7BJA:k&UAuWBJAU>g&UA ;΋BJAXd&UAIxKBJAp_&UA0BJADiU&UA4BJAWmJ&UA#GCJA A&UA*FpCJA뙅5&UA* DJAI&UADJAO&UApDJA9ɵ&UA:DJA<&UA=DJAT%UAe `RDJA>S%UAU~DJAJj%UAĠDJA ̵%UAoN%UArpBDJA#]hq%UA jDJAμ%UAkDJA`%UA4rDJA-o%UA DJA3k%UAJDJAD9A%UA~'CJAIgd1%UAd)T*CJA+x.,%UA&1CJAƨL%UAM:CJA}%UASONCJA˖n$UA;UCJAg|$UA} CJAy$UA!u~CJA:$UAw~AWCJA],$UAfCJAhQ p$UA CJAndk$UAk^BJA|S$UA- BJAׇ$$UA2BJA$UAnBJA{ $UAEtBJAK$UA1BJAf#UAHBJA9#UA,CBJA$a#UAXB5BJA=#UAz BJAi~+#UA]9AJAxe#UAAJAL#UAAJA+ׄ#UAuC`@JA^+K$Q#UAe'[@JAe7P#UA1&P@JA|``N#UA L@JAo~N#UA @JAVG#UA5?JA͠MD#UA2?JA C#UAv?JAIhhC#UAb]?JA%N}E#UA }u?JA`SwF#UA?JAS~MK#UAT"w{?JA-8FG#UAS?JAgB#UAܥ56?JANA#UAD?JA&5@#UA,>JA=;ʆ?#UAB>JA- <#UAWf>JA_E9#UAc=>JAғH>$#UA%֥>JAQ#UA=JAPr\#UAy)=JA#UARʷ=JA R#UA9A=JA#UA[*J=JA2 #UAV=JAra#UA.T=JA."UAҗn=JA&6"UA7=JAIM"UA@ =JAo "UA/=JAW3(-"UAt\_=JAk̬"UAI{=JAo~"UArQ=JA,V"UAP=JAq#"UAgj=JAͻ"UAE=JAr̩"UAsX>JA7"UAݳ>JAUӗv"UA>=JAʳlg"UAv=JA[Ua"UA͒T+=JAF"UA8=JA?93"UA3G=JA&"UAɰS=JAQ"UAdp=JAr18!UA$j#e=JA!UAf^h=JAC/a!UA ׸y=JAc!UAt^ ݉=JAx<(!UAOC5?=JA0!UAGa =JAIrn}!UA!ʂp=JA](1n!UAdaP!UA);}JA(Ð UA>JAlUA0N>JA×"UA>JAZ C)UAɷ[>JAЕ ^+UAgjB?JA˻7UAL?JA$")9UAkTR?JA9UAa?JARe ;UA1C?JAAUA[?JA7UAa_@JAP;EAUA= 6@JAl?GUAMRu!H@JAd|IUA:s.xp@JALUA?+2@JARU`NUA΁@JAFթNUA֙a@JA#OUA~* AJA~WUA*Hx$AJA^XUAk6AJAOUA\FAJAxBNUAiPAJA+CAJA %&UAtAJAeUA+)(AJAZ TUAAJA!UAK޿AJA42?UAAJApUA+sAJAXUAʿAJArLYUAAJAl ٰUA:(AJAUALUAJA?g$BUANAJAxUAJPBJAɺo;UAd@BJApCUA̯GBJAUAD%P_BJAUAblrBJApWUAS7}BJA/I,UA7BJA `UAU9BJAmc&UABJA1UA(CJAt3@UA\\CJAW)UAvUwCJA('UA띀CJA[?UA 1FCJA经UAoDDJAM .UAGDJA-k 0UA5LDJAm,UAHpPDJAAb*UAkodDJA)ć-UA\lkDJA)-UApcDJAUA3-JDJAKUAs,EJACM,UAÐEJAc:UA^EJA7L7UAۍOEJA?1#UAIEJAp2UA #EJAJw5UApFJAL;h!UAd5mLFJA*+UA^{FJAQp UAqYlFJA=h UA&}ǦFJAgUA{$JhFJAUA]FJA_|UAh8FJAfUAFJAUA'GJAwBvUA$GJA9uUAGJAIUAո RGJA^0UAnGJANz.UA[3GJAz涉UA# "GJAn&UAY3(GJAv5 }UA&4-GJAl}{UA1GJAKyUAHQ19GJA9wUAmn?GJASTtUA]uLGJAFoUA'ʭ]GJAflUAwGJAfaUA?8GJAif[KUADpGJA}DUA)GJA.C?UA)mGJAhJ.UA4 GJAv@UAf:HJAB*CUA{SHJA]$$UAІZHJAEUAuIJAz#LUA|lIJAHpUA0IJAc UAjIJA{UA$`IJAdUAIJAyȖUASIJAfD١UA6JIJA,McMUA@HJA4NMUA瑎IHJAdX|MUA/?HJA=/UA@HHJAҪ$UA/ÜHJAUAHJA;kUApHJA#UAHJA]UALHJA%oUAJBiHJAUAr9UHJA%x`UA &(HJAs#2UAHJA[BUAa(HJAUAc2GJA9tUA zGJA6@UA]-eHJA&OXEUAZlʗHJA$UA1GJAktUAyGJA TUAw.rHJA#mUAiPHJAfpUA},j%HJAUA(HJAŚUA 'HJAUAGr~HJAOrkUAFʲHJA̠IUAqHJA5EUAчWHJAoR@UA+ \^GJA9UAD/PGJAbBUAbWGJAvUAJGJAUAIGJA{SfsUA\ڻGJA@uUAL bGJA`prUA.n~GJAD} 5UA=GJA>q1UAGJA o%UA(hLGJApBUA?/GJAUAGJA Q UARX[HJA_UA꿫dHJA ?EUA@ HJAIkUA Ii$LJAu޷5yUAȣxLJA˗UAmwLJA6UAcLJAyUAJMJA}*DUAz[PMJAlcUAnVMJA UA}~^MJAN5 UAS$dMJA*wJ UA"_MJAaUAhYL5MJA^]UA"F5MJA?\YUAOJA+KiUUAq@w`#OJA 4vUAMB$OJA҃eyUA9=-NJA`rzUA䤟7NJA 5UA2NJAۜOUAYgaNJAwUAfeNJA UA%ONJA$38UA VOJAI>JUA*OJA6cUAOJA)]aUAXOJAptoUA2|OJA,nUA;8OJA[kUAPJASnUA"A= PJA$rUAv9PJA\UA۔yB_PJA1EUA_dPJAamUAG SJAGM&lUA.SJAWITgUA3m4SJAѴgUAy^MSJA@;fUA.}\ESJA-!)QUA6?ORSJA#9`RUA-sSSJAj>WUA SJA"ggUASJAJ.uUAhTJAG UAC+G6TJAi#UAF?FTJARUAUTJAV\UAzITJA77UA}TJA@pUAn UJA<{ζUAFݼUJAVUA(UJAhUATwUJA'AUAĝ;UJAUA׻lUJAeعUAUJAUPUA"UJA<UAUJA\UAUXVJAJ/HUAʷyzVJA@E>,UA5+VJAFiUA/VJA+.(UA-WJA>8_>/UAIYWJA1UAOBuWJA%3UA3yWJA;4UAȣWJA009UAp#WJAKSKUAVf!kEXJAa?UAb}}[fXJA{.]UAc턑XJA>x8UAXJAyN;t,UA8wXJAN#UA`cXJAUAc@YJA qNUAmxhYJA#UAnE}YJAU UA叅YJA&_UAݴfYJAY $UAc;YJA7tUA-a#YJA5UAnHYJAi/UA iYJArwUA/}YJA UAzYJAhAUAXmYJAZm{UA+_YJAxUA #QYJARCUA"4@YJAw֓UAj -YJAYUA]G YJA$hUAFXJABUA|XJASw|0"UAXJAKK5UA C~XJAZUA_aXJA]UA-?XJAXUAI"XJA~fUA2XJA֧p}UAE;XJAP&iUAюWJA)u9UA晋yWJA!UA}HWJAH\JUAVitWJAl UA^ݸWJAUAnWJAC>UAS'WJA[pUA$WJAMtHJUA'`WJAdd2UAgĩWJA(C)UAWJAUAm@+WJA6OUA^vWJA`UAZIWJAUARYJA[1UAYJA~UAkZJAtUA-[P1ZJA!UA}ZJA8 1UA|>0ZJA2!^UAמ[JA{kUAf[[JA=@zUA4[JAWUA>?[JAԈ UAq~[JA}kUA̪ku%\JAWҍUAUn\JA`+UAċ\JAb=uUA \JALUAT%ɽ\JAmϏUAKռ\JA$|UAj]JA=fUAL\J]JACUA.Oj]JA&*)UA1]JAUAvC]JA;UABd]JA͗^UAĻ׽]JA:6LfUAR]JA4wYUA*]JA|/UAP% ]JA_UAng=}]JAFiUA}3]JAz\UA*u&%]JAEUARMI\JA(vIUA]JAj~UAӭ]JAUA`v^JA[bӘUA]h'<^JA 5wUA ee^JA,$][UAM^JAa UAz_JA) UA'J_JA}[` UAo_JA M UAd_`_JAJ#lyA UAp&H>_JA:Ln7 UAQ$_JAjb. UA~F_JAL+% UA__JA>8 UA_r^JA {Ô UA2>^JAM UA;=^JA6} UA3<]JA#hL@ UAN<]JA"Q4 UA}]JA c- UA.p=]JAZ UAJv]JA  UA7\JAl UA \JAL'S UA(9M\JA}&# UA=*;\JA UAz$-\JAC< UA \JA& UAD\JAk UAhp[JAUv( UAER[JAӓ UA0%F1[JA/a UAᣜ[JAi9y UA1 [JA f+g UA7[JA#r&^ UA`ʡ[JA`!' UAIȕ[JAo UAZJA UAn}ZJA'KÓ UA*?ZJAѻt UA6CYJAaFQ UA(!YJA$| UA\>YJASI UA*cYJA4e UAF^YJAo* UAߙ>NYJA%q UALAYJAk UAr5YJAi UAƛ(YJA UA'YJAM UA~mXJA?Qh-& UA2ݕXJAk, UA\(KlXJA;<- UAhWJA( UA>WJAۡw7# UAWJAӻ"# UAWJAB3 # UAWwWJA" UAX’dWJAz[! UA!qPWJA/ UA'pNWJAMb1$ UAFb$NWJAO& UA WJA\& UA VJAO UA&IWJAԳP UA}rWJA w^Y UAvPiVJAܘV UA!VJAQ UA/(VJA\̝Q UA3TJA>S UA TJA7`S UA.|TJAjQ UAEQ7SJAGyW UA)SJA2X UAU%SJAV-rW UAʹ!ztSJAcZ7gK UAc_SJAQQE UAj*USJAvB< UAvASJAw UA;,3SJAKQ UAYRJArr UA~SJA{yZ~ UAöPRJA5 UA ~RJA UA~ĉTRJATLR UAʸRJA[b*: UA=pW+RJAʀ+/ UA "RJA& UA\o-QJAIBD UAXȦbQJAs UArIQJAņ UAQJAR} UAc%5QJAԼ UA5!QJA!X UAQJAk҂ UA4"PJAV@ UA+)PJA, UAM.#PJACQ`~! UA2@PJAhVbUA-PJA4 UA \PJAUA%PJA (UA3PJAUA˫PJAeAUACDZPJA>-DwUA!_%@QJAjSM*UA)8?PJADmUA(OJA\UA;OJAs+TUA?"2OJAGrsxUA}(OJAw]|UAnʆNJA.`UA}QqNJA]b7pUAJPNJAUAi NJAtVaUAf2 NJAWDeuUA|MJAmp{/UAFMJA&mjUA8ɫMJAҧUA7ŇMJAؚUAf3PpMJA=+UAY2ZaMJAFUAr?LJAKmQUAQLJADUA:LJAUAWLKJA|yUAQ|KJA5m> UA1;KJAu~J UA2KJAK UALiIKJAEI UAeJJA_ UAu2JJA)y UANIJAh UACY;IJAnR UAh̲HJA4 UARxHJA i UAOVHJA;[ UAx=AHJAQ80 UA#(8HJA^ = UAeE8HJAیG UA aeHJA- B UAyhwyHJA^1{ UA)?HJAwS UA3HJA8ʳ UAl^*HJATم UAh;*HJA3 UA2dW-*HJA3)B UA@2HJA z UAbӎ7HJA2N~ UAz|:HJAϔ UA$\N1HJA1U UA漲0HJA~'{C UAHJA^2_~ UAIGJAOE UAԋGJA; UAY jGJAZ_ UA/B{GJAJwa UAX0GJA*퓥 UAmGJA(4 UA KqGJA< UA/NңxGJA;A UA^1GJAA3 UAdGJAzUU UA#GJAka UA$־GJAIs. f UAOKGJAʴ UAChKGJAHBړ UA/:HJAvl UA^2HJAcL UA}HAHJA UA3HHJA^S6UAK@DHJA ; CUAO>HJATHЂUAhHJA߉UAsHJA%dUAFUHJA|R$UA\]HJAHUA@X4GJAY4UA5%GJA,UAGJApUA&ֵGJABUAd"HJARMUA"HJA{uuVUA9%HJA?bUAo2HJAD|vUA`OHJAUAZ$HJA|GfUAm HJAZViUA+6GJAX&UAv>uZGJAjۂUA_rGJAXUAnyGJAyyUA`%FGJA AUA&"GJAaUA@FJA:UAAFJAPUA2|EJA*!UA]EJA&ʬUAI:EJA'QUA/êREJAmQEUAm-EJAXĕ{{UAjEJAmr&zUA;DJAyUA4aNDJA$ֲ&xUAknDJA~ztUAݍ#bDJA1.fvUAUc7bBJAQGUAQ!BJAS0UAGHBJAݠQUA>jBJA ,UAUa1BJAڈyUAw,BJAz"UAcBJA,UAdBJA0.UA|BJA$,3UA|j!BJA"A4UAFkBJAVi)8UA[lBJAM.AUA tLOBJABPUAoGBJATUAfABJAtޚYUA NY$>BJA_|_UA*A >BJAUւ hUA:BJAA|UA] gBBJAQh~UA7q9BJA,UALt@BJAZ_UA IC3BJA wUAθ1BJAuUA2lBJA~WUAۻYCJAUA>:CJA ֬UAJCJAյUA^CJA:IpUAsȭ/DJA@zUA[WDJA[gUAazDJA9 UAo=-DJA%? UA[*~DJA-TR9UAv?DJAgEUA{7 EJAo$L^UA F-EJAʕކbUAIdEJA}BeUAXJSEJAI3,sUAd/EJAccUAj{qEJA6ӬUAA!aEJA$fUA<>؃EJAyUA!EJAoUA>дEJAmUA$EJACUAYEJAt$UA.EJA%iUA+AEJA eUA R4EJA9UAsUEJAAUAHgUARA9AJA`xUAi~AJAW3UA9 l}AJAC[UAP|AJA+pUA>ρAJAtjUA^_AJAkhUA|AJARxUAFAJAn 7UAr)AJA$ UA HAJAA;iUA 8AJA"#UAZ[xAJAšo4UA"=uAJA3;UAÝchAJAXAAUAeg`uAJAkGUAR{AJAKUAY[AJAdlUApg PAJAKo mUAykKAJArDmUAkyAJA<:jUA(@JAAzdUA-@JADUAaK@JA WUA5r@JAUA͉d@JA#UA| ^D@JAט{_UAx2@JAUA۳@JA2LUAڹ?JAMߎGUAo6?JAT(UA9?JA- UA$?JASUAػm?JAs`UAзÑ?JAbNUA B?JA7 UA!?JACQ5UAV>JAt‰UA/G@>JA6'UA aMS>JAMNUA9R>JAYUAr#N>JAlAUA)dI>JAڈ UAgx&>JA6UA?Ⱦ(>JA 8vUADm.>JAt&VUA">JAoUUAK=>JAqUTUAww=JATOUANNG0=JA[qKMUA1vUAQ82JAn̄UAi 1JA3OUA\l1JAfwfUAhU;1JA~UAX1JA:SUAE0JAkZ:UA$y)0JAwBUA [0JA=UAY0JA鉬UAlѱ/JA.UAtG/JAs=>UAIA/JAPǡUAI.JApȀ8UAvk.JA:8bUADL.JA6UA}/JAUA"8z/JA<5֘UA0ks/JAIUA|/JA iUA1,/JA|M~UA;0JAzUAAU/JA/~NeUAb{0JAwUA2@0JAsƹUA0JA˧cUA(R@0JAUAH8h/JAyWUA7$x/JAF8UAQ/JA8qUAj//JAiFUUApb|.JAB:UAj)P-JA(^,vUAn-JABUA AJ:-JAUA '-JAsUUAi,JA%UAϏ,JAbUAF`l,JA&rUAٵ,JAXUA$,JAэ|UAEyUAn+JAiUAݧ+JAS^UAX+JA:|VNUA+JA"AGUAz:+JAJ8UA{X'+JADwUA+JAUUABe+JAl%&FUA]w+JAq_UAӨ+JAUAF֨Z+JAD1DUAP׻+JA&dnUAD{+JApUAvf=l+JAVUA~*JAYMCUA2uk*JAUAc+^K*JA~%UA3A*JAJΐUA ;)JA9\ UA.9)JAUAY#)JALUA!X)JAԥUA; W?)JA~UUA=(JAc:UA (JA:-4MUAJr'JAUA)'JAhܘUAa'JA֘rQUA'JA UAbqw'JAMdPUA uHQ'JA UAQft''JAoUA'JA}UA8&JAMcUAmapserver-7.4.3/mapscript/java/data/utf-subset.shx000066400000000000000000000001641357574274700222400ustar00rootroot00000000000000' :zp?IAkFTA'J_JAt?,UA2ttHAhmapserver-7.4.3/mapscript/java/examples/000077500000000000000000000000001357574274700203175ustar00rootroot00000000000000mapserver-7.4.3/mapscript/java/examples/ConnPool.java000066400000000000000000000007001357574274700227060ustar00rootroot00000000000000import edu.umn.gis.mapscript.*; /** *

Title: Mapscript conn pool

*

Description: n.a.

* @author Umberto Nicoletti (umberto.nicoletti@gmail.com) * @version 1.0 */ public class ConnPool { public static void main(String[] args) { // at least it shouldn't crash System.out.println("Running mapscript.msConnPoolCloseUnreferenced"); mapscript.msConnPoolCloseUnreferenced(); System.out.println("Finished."); } } mapserver-7.4.3/mapscript/java/examples/DrawMap.java000066400000000000000000000022451357574274700225200ustar00rootroot00000000000000import edu.umn.gis.mapscript.*; /** *

Title: Mapscript shape dump example.

*

Description: A Java based mapscript example to create an image given a mapfile.

* @author Yew K Choo ykchoo@geozervice.com * @version 1.0 */ public class DrawMap { public static void usage() { System.err.println("Usage: DrawMap {mapfile} {outfile}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 2) usage(); mapObj map = new mapObj(args[0]); //map.getImagecolor().setRGB(153, 153, 204); //styleObj st = map.getLayer(1).getClass(0).getStyle(0); //st.getColor().setHex("#000000"); if( map.getLayer(1).getMetaData("hidden") != null ) { System.out.println("Layer 1 is hidden? "+map.getLayer(1).getMetaData("hidden")); } int i=0; //for (i=0; i<100; i++) { imageObj img = map.draw(); System.out.println("Image size is: "+img.getSize()); System.out.println("Image size from getBytes is: "+img.getBytes().length); System.out.println(i+") the map will be drawn to:"+args[1]); img.save(args[1], map); //} img.delete(); map.delete(); //mapscript.msCleanup(); } } mapserver-7.4.3/mapscript/java/examples/DumpShp.java000066400000000000000000000035011357574274700225410ustar00rootroot00000000000000import edu.umn.gis.mapscript.*; /** *

Title: Mapscript shape dump example.

*

Description: A Java based mapscript to dump information from a shapefile.

* @author Yew K Choo (ykchoo@geozervice.com) * @version 1.0 */ public class DumpShp { public static String getShapeType(int type) { switch (type) { case 1: return "point"; case 3: return "arc"; case 5: return "polygon"; case 8: return "multipoint"; default: return "unknown"; } } public static void usage() { System.err.println("Usage: DumpShp {shapefile.shp}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 1) usage(); shapefileObj shapefile = new shapefileObj (args[0],-1); System.out.println ("Shapefile opened (type = " + getShapeType(shapefile.getType()) + " with " + shapefile.getNumshapes() + " shapes)."); shapeObj shape = new shapeObj(-1); for(int i=0; iTitle: Mapscript shape dump example.

*

Description: A Java based mapscript example to create an image given a mapfile.

* @author Yew K Choo ykchoo@geozervice.com * @version 1.0 */ public class Metadata { public static void usage() { System.err.println("Usage: Metadata {mapfile}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 1) usage(); mapObj map = new mapObj(args[0]); for (int i=0; i<100; i++) { System.out.println("Web->key1 ? "+map.getWeb().getMetadata().get("key1",null)); System.out.println("Web->key2 ? "+map.getWeb().getMetadata().get("key2",null)); System.out.println("Web->key3 ? "+map.getWeb().getMetadata().get("key3",null)); System.out.println("Web->key4 ? "+map.getWeb().getMetadata().get("key4",null)); System.out.println("Web->key5 ? "+map.getWeb().getMetadata().get("key5",null)); System.gc(); System.gc(); System.gc(); System.out.println("Web->key1 ? "+map.getWeb().getMetadata().get("key1",null)); } map.delete(); } } mapserver-7.4.3/mapscript/java/examples/OutputFormatList.java000066400000000000000000000014551357574274700244740ustar00rootroot00000000000000import edu.umn.gis.mapscript.*; /** *

Title: Mapscript outputformat dump example.

* @author Umberto Nicoletti umberto.nicoletti@gmail.com * @version 1.0 */ public class OutputFormatList { public static void usage() { System.err.println("Usage: OutputFormatList {mapfile}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 1) usage(); mapObj map = new mapObj(args[0]); for (int i=0; iTitle: Mapscript shapeinfo example.

*

Description: A Java based mapscript example to dump information from a shapefile.

*

Copyright: Copyright (c) 2004

*

Company: GeoZervice

* @author Yew K Choo (ykchoo@geozervice.com) * @version 1.0 */ public class ShapeInfo { public static String getShapeType(int type) { switch (type) { case 1: return "point"; case 3: return "arc"; case 5: return "polygon"; case 8: return "multipoint"; default: return "unknown"; } } public static void usage() { System.err.println("Usage: ShapeInfo {shapefile.shp} {shapefile.dbf}"); System.exit(-1); } public static void main(String[] args) { if (args.length != 2) usage(); shapefileObj shapefile = new shapefileObj (args[0],-1); System.out.println ("Shapefile name = " + args[0]); System.out.println ("Type = " + getShapeType(shapefile.getType())); System.out.println ("Number of features " + shapefile.getNumshapes()); System.out.println("bounds (" + shapefile.getBounds().getMinx() + "," + shapefile.getBounds().getMiny() + ")" + "(" + shapefile.getBounds().getMaxx() + "," + shapefile.getBounds().getMaxy() + ")"); shapefile.delete(); //mapscript.msCleanup(); } } mapserver-7.4.3/mapscript/java/examples/WxSTest.java000066400000000000000000000047521357574274700225530ustar00rootroot00000000000000import edu.umn.gis.mapscript.mapObj; import edu.umn.gis.mapscript.OWSRequest; import edu.umn.gis.mapscript.mapscript; import java.io.*; class WxSTest_thread extends Thread { public String mapName; public byte[] resultBytes; public void run() { mapObj map = new mapObj(mapName); map.setMetaData( "ows_onlineresource", "http://dummy.org/" ); OWSRequest req = new OWSRequest(); req.setParameter( "SERVICE", "WMS" ); req.setParameter( "VERSION", "1.1.0" ); req.setParameter( "REQUEST", "GetCapabilities" ); mapscript.msIO_installStdoutToBuffer(); int owsResult = map.OWSDispatch( req ); if( owsResult != 0 ) System.out.println( "OWSDispatch Result (expect 0): " + owsResult ); // System.out.println( "Document:" ); // System.out.println( mapscript.msIO_getStdoutBufferString() ); resultBytes = mapscript.msIO_getStdoutBufferBytes(); mapscript.msIO_resetHandlers(); } } public class WxSTest { public static void main(String[] args) { try { WxSTest_thread tt[] = new WxSTest_thread[100]; int i; int expectedLength=0, success = 0, failure=0; for( i = 0; i < tt.length; i++ ) { tt[i] = new WxSTest_thread(); tt[i].mapName = args[0]; } for( i = 0; i < tt.length; i++ ) tt[i].start(); for( i = 0; i < tt.length; i++ ) { tt[i].join(); if( i == 0 ) { expectedLength = tt[i].resultBytes.length; System.out.println( "["+i+"] Document Length: " + expectedLength + ", expecting somewhere around 10000 or more." ); } else if( expectedLength != tt[i].resultBytes.length ) { System.out.println( "["+i+"] Document Length:" + tt[i].resultBytes.length + " Expected:" + expectedLength ); failure++; } else success++; // dump test results to fs for post-mortem inspection FileOutputStream fos = new FileOutputStream("/tmp/wxs_test_"+i); fos.write(tt[i].resultBytes); fos.close(); } System.out.println( "Successes: " + success ); System.out.println( "Failures: " + failure ); } catch( Exception e ) { e.printStackTrace(); } } } mapserver-7.4.3/mapscript/java/examples/WxSTestNoThread.java000066400000000000000000000047111357574274700241730ustar00rootroot00000000000000import edu.umn.gis.mapscript.mapObj; import edu.umn.gis.mapscript.OWSRequest; import edu.umn.gis.mapscript.mapscript; import java.io.*; class WxSTest_nothread { public String mapName; public byte[] resultBytes; public void run() { mapObj map = new mapObj(mapName); map.setMetaData( "ows_onlineresource", "http://dummy.org/" ); OWSRequest req = new OWSRequest(); req.setParameter( "SERVICE", "WMS" ); req.setParameter( "VERSION", "1.1.0" ); req.setParameter( "REQUEST", "GetCapabilities" ); mapscript.msIO_installStdoutToBuffer(); int owsResult = map.OWSDispatch( req ); if( owsResult != 0 ) System.out.println( "OWSDispatch Result (expect 0): " + owsResult ); // System.out.println( "Document:" ); // System.out.println( mapscript.msIO_getStdoutBufferString() ); resultBytes = mapscript.msIO_getStdoutBufferBytes(); mapscript.msIO_resetHandlers(); } } public class WxSTestNoThread { public static void main(String[] args) { try { WxSTest_nothread tt[] = new WxSTest_nothread[1]; int i; int expectedLength=0, success = 0, failure=0; for( i = 0; i < tt.length; i++ ) { tt[i] = new WxSTest_nothread(); tt[i].mapName = args[0]; } for( i = 0; i < tt.length; i++ ) tt[i].run(); for( i = 0; i < tt.length; i++ ) { if( i == 0 ) { expectedLength = tt[i].resultBytes.length; System.out.println( "["+i+"] Document Length: " + expectedLength + ", expecting somewhere around 10000 or more." ); } else if( expectedLength != tt[i].resultBytes.length ) { System.out.println( "["+i+"] Document Length:" + tt[i].resultBytes.length + " Expected:" + expectedLength ); failure++; } else success++; // dump test results to fs for post-mortem inspection FileOutputStream fos = new FileOutputStream("/tmp/wxs_test_"+i); fos.write(tt[i].resultBytes); fos.close(); } System.out.println( "Successes: " + success ); System.out.println( "Failures: " + failure ); } catch( Exception e ) { e.printStackTrace(); } } } mapserver-7.4.3/mapscript/java/javaextend.i000066400000000000000000000024741357574274700210130ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Java-specific extensions to MapScript objects * Author: Sean Gillies, sgillies@frii.com * Jerry Pisk, jerry.pisk@gmail.com * *****************************************************************************/ /* =============================================================================== imageObj =============================================================================== */ /* getBytes moved to mapscript/swiginc/image.i */ /* ============================================================================== pointObj ============================================================================== */ %extend pointObj { pointObj(double x, double y, double z, double m) { pointObj *p; p = (pointObj *)calloc(1,sizeof(pointObj)); if (!p) return NULL; p->x = x; p->y = y; #ifdef USE_POINT_Z_M p->z = z; p->m = m; #endif return p; } pointObj(double x, double y, double z) { pointObj *p; p = (pointObj *)calloc(1,sizeof(pointObj)); if (!p) return NULL; p->x = x; p->y = y; #ifdef USE_POINT_Z_M p->z = z; p->m = -2e38; #endif return p; } } mapserver-7.4.3/mapscript/java/javamodule.i000066400000000000000000000133231357574274700210040ustar00rootroot00000000000000 %include arrays_java.i /* Uncomment this if you wish to hace enums wrapped in an interface compatible with that generated by swig 1.3.21 (tests wont compile, though) %include enumsimple.swg */ /* Mapscript library loader */ %pragma(java) jniclasscode=%{ static { String library = System.getProperty("mapserver.library.name", "javamapscript"); System.loadLibrary(library); /* TODO Throw when return value not MS_SUCCESS? */ edu.umn.gis.mapscript.mapscript.msSetup(); } %} %typemap(jni) gdBuffer %{jbyteArray%} %typemap(jtype) gdBuffer %{byte[]%} %typemap(jstype) gdBuffer %{byte[]%} %typemap(out) gdBuffer %{ $result = SWIG_JavaArrayOutSchar(jenv, $1.data, $1.size); if( $1.owns_data ) msFree($1.data); %} %typemap(javain) gdBuffer "$javainput" %typemap(javaout) gdBuffer { return $jnicall; } /* String conversion utility function */ %{ /* These functions taken from: http://java.sun.com/docs/books/jni/html/other.html#26018 Umberto Nicoletti, umberto.nicoletti@gmail.com Fix bug: http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1753 */ void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) { jclass cls = (*env)->FindClass(env, name); /* if cls is NULL, an exception has already been thrown */ if (cls != NULL) { (*env)->ThrowNew(env, cls, msg); } /* free the local ref */ (*env)->DeleteLocalRef(env, cls); } char *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr) { jbyteArray bytes = 0; jthrowable exc; char *result = 0; jclass jcls_str; jmethodID MID_String_getBytes; if (jstr == NULL) { return NULL; } if ((*env)->EnsureLocalCapacity(env, 2) < 0) { return 0; /* out of memory error */ } jcls_str = (*env)->FindClass(env, "java/lang/String"); MID_String_getBytes = (*env)->GetMethodID(env, jcls_str, "getBytes", "()[B"); bytes = (*env)->CallObjectMethod(env, jstr, MID_String_getBytes); exc = (*env)->ExceptionOccurred(env); if (!exc) { jint len = (*env)->GetArrayLength(env, bytes); result = (char *)malloc(len + 1); if (result == 0) { JNU_ThrowByName(env, "java/lang/OutOfMemoryError",0); (*env)->DeleteLocalRef(env, bytes); return 0; } (*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *)result); result[len] = 0; /* NULL-terminate */ } else { (*env)->DeleteLocalRef(env, exc); } (*env)->DeleteLocalRef(env, bytes); return result; } jstring JNU_NewStringNative(JNIEnv *env, const char *str) { jstring result; jbyteArray bytes = 0; int len; jclass jcls_str; jmethodID MID_String_init; if (str == NULL) { return NULL; } if ((*env)->EnsureLocalCapacity(env, 2) < 0) { return NULL; /* out of memory error */ } jcls_str = (*env)->FindClass(env, "java/lang/String"); MID_String_init = (*env)->GetMethodID(env, jcls_str, "", "([B)V"); len = strlen(str); bytes = (*env)->NewByteArray(env, len); if (bytes != NULL) { (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str); result = (*env)->NewObject(env, jcls_str, MID_String_init, bytes); (*env)->DeleteLocalRef(env, bytes); return result; } /* else fall through */ return NULL; } %} %typemap(in) char * { $1 = JNU_GetStringNativeChars(jenv, $input); } /* The default mapping would use ReleaseStringUTFChars to release the memory allocated with JNU_GetStringNativeChars which causes a memory corruption. (#3491) */ %typemap(freearg, noblock=1) char * { if ($1) free($1); } %typemap(out) char * { $result = JNU_NewStringNative(jenv, $1); } /* =============================================================================== RFC-24 implementation follows =============================================================================== Modified constructor according to: - cache population and sync, item 3.2 */ %typemap(javaconstruct) layerObj(mapObj map) %{ { this($imcall, true); if (map != null) { this.map=map; } } %} %typemap(javaconstruct) classObj(layerObj layer) %{ { this($imcall, true); if (layer != null) { this.layer=layer; } } %} %typemap(javaout) int insertLayer { // call the C API int actualIndex=$jnicall; /* Store parent reference, item 3.2 */ layer.map=this; return actualIndex; } %typemap(javaout) layerObj* getLayer { // call the C API long cPtr=$jnicall; layerObj layer = null; if (cPtr != 0) { layer=new layerObj(cPtr, true); /* Store parent reference, item 3.2 */ layer.map=this; } return layer; } %typemap(javaout) layerObj* getLayerByName { // call the C API long cPtr=$jnicall; layerObj layer = null; if (cPtr != 0) { layer=new layerObj(cPtr, true); /* Store parent reference, item 3.2 */ layer.map=this; } return layer; } %typemap(javaout) int insertClass { // call the C API int actualIndex=$jnicall; /* Store parent reference, item 3.2 */ classobj.layer=this; return actualIndex; } %typemap(javaout) classObj* getClass { // call the C API long cPtr=$jnicall; classObj clazz = null; if (cPtr != 0) { clazz=new classObj(cPtr, true); /* Store parent reference, item 3.2 */ clazz.layer=this; } return clazz; } %typemap(javacode) struct layerObj %{ /* parent reference, RFC-24 item 3.2 */ mapObj map=null; %} %typemap(javacode) struct classObj %{ /* parent reference, RFC-24 item 3.2 */ layerObj layer=null; %} mapserver-7.4.3/mapscript/java/makefile.vc000066400000000000000000000053411357574274700206130ustar00rootroot00000000000000 # # SWIG Stuff # #SWIG_HOME="D:\swig\SWIG-1.3.23\" <- should get this from ..\..\nmake.opt #SWIG=$(SWIG_HOME)\swig !INCLUDE ..\..\nmake.opt MS_LIB = mapscript.lib MS_LIB_DLL = mapscript_i.lib # # Java Stuff #JAVA_HOME = "C:\Progra~1\Java\jdk1.5.0" <- should get this from ..\..\nmake.opt JAVADOC=$(JAVA_HOME)\bin\javadoc JAVAC=$(JAVA_HOME)\bin\javac JAVA=$(JAVA_HOME)\bin\java JAR=$(JAVA_HOME)\bin\jar JAVA_INCLUDE=-I$(JAVA_HOME)\include -I$(JAVA_HOME)\include\win32 CC= cl /MD LINK= link MS_DLL = javamapscript.dll BASE_CFLAGS = $(OPTFLAGS) -DWIN32 -D_WIN32 LDFLAGS = /NODEFAULTLIB:"MSVCRTD" /NODEFAULTLIB:libcd /NODEFAULTLIB:libcmtd /NODEFAULTLIB:msvcrtd /NODEFAULTLIB:LIBC /DEBUG all: interface_release mapscript_java mapscript_lib mapscript_jar interface_release: -md edu\umn\gis\mapscript $(SWIG) -java -package edu.umn.gis.mapscript -outdir edu/umn/gis/mapscript -o mapscript_wrap.c ../mapscript.i mapscript_java: $(JAVAC) edu\umn\gis\mapscript\*.java mapscript_wrap: $(CC) $(BASE_CFLAGS) $(MS_CFLAGS) $(JAVA_INCLUDE) /c mapscript_wrap.c /Fomapscript_wrap.obj .c.obj: $(CC) $(BASE_CFLAGS) $(MS_CFLAGS) $(JAVA_INCLUDE) /c $*.c /Fo$*.obj mapscript_lib: mapscript_wrap.obj link /dll /debug \ mapscript_wrap.obj $(EXTERNAL_LIBS) ..\..\mapserver_i.lib $(LDFLAGS) /def:..\..\mapserver.def \ /out:$(MS_DLL) /implib:$(MS_LIB_DLL) if exist $(MS_DLL).manifest mt -manifest $(MS_DLL).manifest -outputresource:$(MS_DLL);2 mapscript_javadoc: $(JAVADOC) -d doc -sourcepath edu/umn/gis/mapscript/*.java mapscript_jar: $(JAR) cf mapscript.jar edu test: $(JAVAC) -classpath ./mapscript.jar -d examples\ examples\*.java $(JAVA) -cp ./;examples/;./mapscript.jar -Djava.library.path=. DumpShp ../../tests/point.shp $(JAVA) -cp ./;examples/;./mapscript.jar -Djava.library.path=. ShapeInfo ..\..\tests\point.shp ..\..\tests\point.dbf $(JAVA) -cp ./;examples/;./mapscript.jar -Djava.library.path=. DrawMap ..\..\tests\test.map .\map.png $(JAVA) -cp ./;examples/;./mapscript.jar -Djava.library.path=. RFC24 ..\..\tests\test.map threadtests: $(JAVAC) -cp ./mapscript.jar -d tests/threadtest/ tests/threadtest/*.java @echo "-------------------------------------------------------------------------" @echo " You can use your own map! Copy the following command in your shell" @echo " and change the file to the map file (the last argument)" @echo "-------------------------------------------------------------------------" $(JAVA) -cp tests/threadtest/;./mapscript.jar -Djava.library.path=. MapTest -t 10 -i 5 ../../tests/test.map clean: -del *.obj -del *.lib -rmdir /s /q edu del $(MS_DLL) del $(MS_DLL).manifest del mapscript_wrap.c del mapscript.jar del *.ilk del *.pdb del *.exp mapserver-7.4.3/mapscript/java/run_test.sh000077500000000000000000000045351357574274700207120ustar00rootroot00000000000000#!/bin/sh -ex JAVA=${JAVA_HOME}/bin/java JAVAC=${JAVA_HOME}/bin/javac ${JAVAC} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -d examples/ examples/RFC24.java examples/ConnPool.java examples/DrawMap.java examples/DumpShp.java examples/MakePoint.java examples/QueryByAttribute.java examples/ShapeInfo.java examples/WxSTest.java examples/Metadata.java examples/RunTimeBuiltWMSClient.java examples/WxSTestNoThread.java ${JAVAC} -encoding utf8 -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -d examples/ examples/QueryByAttributeUnicode.java ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} DumpShp ../../tests/point.shp ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} ShapeInfo ../../tests/point.shp ../../tests/point.dbf ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} DrawMap ../../tests/test.map ./map.png ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} ConnPool ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} QueryByAttribute ../../tests/test.map ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} WxSTest ../../tests/test.map ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} WxSTestNoThread ../../tests/test.map ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} RFC24 ../../tests/test.map LC_ALL=en_US.UTF-8 ${JAVA} -classpath ./:examples/:${JAVA_MAPSCRIPT_SO}/mapscript.jar -Djava.library.path=${JAVA_MAPSCRIPT_SO} QueryByAttributeUnicode data/subset-umlauts.map ${JAVAC} -cp ${JAVA_MAPSCRIPT_SO}/mapscript.jar -d tests/threadtest/ tests/threadtest/*.java #------------------------------------------------------------------------- # You can use your own map! Copy the following command in your shell # and change the file to the map file (the last argument) #------------------------------------------------------------------------- ${JAVA} -Djava.library.path=${JAVA_MAPSCRIPT_SO} -classpath tests/threadtest/:${JAVA_MAPSCRIPT_SO}/mapscript.jar MapTest -t 50 -i 5 ../../tests/test.map mapserver-7.4.3/mapscript/java/tests/000077500000000000000000000000001357574274700176435ustar00rootroot00000000000000mapserver-7.4.3/mapscript/java/tests/threadtest/000077500000000000000000000000001357574274700220125ustar00rootroot00000000000000mapserver-7.4.3/mapscript/java/tests/threadtest/MapTest.java000066400000000000000000000016411357574274700242340ustar00rootroot00000000000000// $Id$ // // See README_THREADTEST.TXT for usage details. // public class MapTest { public static void main(String args[]) { String mapfile = null; Integer threads = null; Integer iterations = null; for( int i = 0; i < args.length; i++ ) { if( "-t".equals(args[i]) ) { i++; threads = new Integer(args[i]); continue; } if( "-i".equals(args[i]) ) { i++; iterations = new Integer(args[i]); continue; } mapfile = args[i]; } Thread[] tpool = new Thread[threads.intValue()]; for( int i = 0; i < tpool.length; i++ ) { tpool[i] = new MapThread(mapfile, iterations.intValue(), i); } for( int i = 0; i < tpool.length; i++ ) { tpool[i].start(); } } } mapserver-7.4.3/mapscript/java/tests/threadtest/MapThread.java000066400000000000000000000053711357574274700245300ustar00rootroot00000000000000// $Id$ // // See README_THREADTEST.TXT for usage details. // import edu.umn.gis.mapscript.*; public class MapThread extends Thread { MapThread(String mapfile, int iterations, int id) { this.mapfile = mapfile; this.iterations = iterations; this.id=id; } public void run() { System.out.println("Thread "+id+" running..."); /* Uncomment this if you need to reschedule threads if (id>=5) { try { sleep(10000); } catch(InterruptedException ie) { ie.printStackTrace(); } } */ for( int i = 0; i < iterations; i++ ) { mapObj map = new mapObj(mapfile); long path=Math.round(Math.random()*10); if ( path > 5 ) { System.out.println("Thread "+id+"-"+i+" querying..."); query(map); } else { System.out.println("Thread "+id+"-"+i+" using geos to create a buffer..."); try { createBuffer(map); } catch(Exception e) { System.out.println("have you enabled GEOS support? "+e.getMessage()); } } // We use this to test swig's memory management code //System.gc(); //map.draw().save("/tmp/mapthread"+id+"-"+i+".png", map); map.draw(); } mapscript.msConnPoolCloseUnreferenced(); System.out.println("Thread "+id+" done."); } public void createBuffer(mapObj map) { layerObj layer = map.getLayer(3); if (layer!=null) { layer.open(); layer.queryByIndex(map,0,-1,mapscriptConstants.MS_FALSE); shapeObj shape=layer.getShape(layer.getResults().getResult(0)); if (shape!=null) { shapeObj buffer=shape.buffer(0.1); if (buffer != null) { layerObj bufferLayer=new layerObj(map); bufferLayer.setStatus(mapscriptConstants.MS_DEFAULT); bufferLayer.setDebug(mapscriptConstants.MS_ON); bufferLayer.setName("BUFFER"); //bufferLayer.setType(mapscriptConstants.MS_LAYER_POLYGON); bufferLayer.setProjection("init=epsg:4326"); bufferLayer.setType(MS_LAYER_TYPE.MS_LAYER_POINT); bufferLayer.setOpacity(50); classObj clazz=new classObj(bufferLayer); clazz.setName("Buffer class"); styleObj style=new styleObj(clazz); colorObj green=new colorObj(0,254,0,255); //green.setRGB(0,254,0); style.setColor(green); bufferLayer.addFeature(buffer); } else { System.out.println("Buffer shape is NULL!"); } } } } public void query(mapObj map) { layerObj layer = map.getLayer(3); if (layer!=null) { layer.setTemplate("template.html"); String filter="A Point"; layer.queryByAttributes(map,"FNAME", filter, mapscriptConstants.MS_MULTIPLE); layer.open(); System.out.println( " numresults: " +layer.getNumResults() ); layer.close(); } } String mapfile; int iterations; int id; } mapserver-7.4.3/mapscript/java/tests/threadtest/README_THREADTEST.TXT000066400000000000000000000107311357574274700251010ustar00rootroot00000000000000----------------------------------- June, 28th 2006 Umberto Nicoletti (umberto.nicoletti@gmail.com) I have added more functionality to the thread test by integrating it in the Makefile so that it can be ran more easily and by adding a query by attribute and a buffer functions. The latter requires GEOS support in mapserver. It is best to run the tests with MALLOC_CHECK_ variable set to 2 so that memory errors are detected and reported (the jvm will crash on the first error so it should be quite noticeable ;-) ). -------- Original Message -------- Subject: [UMN_MAPSERVER-DEV] Multithreaded Mapscript Date: Mon, 6 Jun 2005 19:22:41 -0700 From: Jerry Pisk Reply-To: Jerry Pisk To: MAPSERVER-DEV@LISTS.UMN.EDU Hi everybody, as I mentioned in my previous e-mail I was able to get mapserver to work in a multithreaded program. But the code I covered was just a fraction of mapserver's code, I only tested mapfile load and map drawing from a PostGIS backend. Since I do not have the resources to do extensive testing I decided to share what I've done with the community. I wrote a simple Java program that creates a number of threads and executes map operations on them. It uses Java mapscript to call mapserver. The following assumes a JDK (I used 1.5 but older versions should work as well) is installed and JAVA_HOME points to it. There are two source files: ================ MapTest.java ================ public class MapTest { public static void main(String args[]) { String mapfile = null; Integer threads = null; Integer iterations = null; for( int i = 0; i < args.length; i++ ) { if( "-t".equals(args[i]) ) { i++; threads = new Integer(args[i]); continue; } if( "-i".equals(args[i]) ) { i++; iterations = new Integer(args[i]); continue; } mapfile = args[i]; } Thread[] tpool = new Thread[threads.intValue()]; for( int i = 0; i < tpool.length; i++ ) { tpool[i] = new MapThread(mapfile, iterations.intValue()); } for( int i = 0; i < tpool.length; i++ ) { tpool[i].start(); } } } ================================================ ================ MapThread.java ================ import edu.umn.gis.mapscript.mapObj; public class MapThread extends Thread { MapThread(String mapfile, int iterations) { this.mapfile = mapfile; this.iterations = iterations; } public void run() { mapObj map = new mapObj(mapfile); for( int i = 0; i < iterations; i++ ) { map.draw(); // Add additional test code here } } String mapfile; int iterations; } ================================================ To use these simply compile mapserver and mapscript (for java you may need to run 'make interface' in mapscript/java). Save the two Java files into a directory of your choice. Compile them (point to your mapscript.jar, in mapscript/java/): $JAVA_HOME/bin/javac -cp ./mapscript.jar *.java and execute: $JAVA_HOME/bin/java -Djava.library.path=./ -cp ./:./mapscript.jar MapTest -t -i where is the number of threads to create, is the number of iterations to execute on each thread and is a full path to your map file. Again, make sure you point to your mapscript.jar and point to where libmapscript.so is in that java.library.path definition (I copied those two files into the same directory as the Java code but your setup may differ). There were occasional libgd related errors (Unable to initialize image) but those simply resulted in an exception being thrown, which is in my humble opinion acceptable, as long as the code does not crash. The code does no error checking, feel free to add it but this is really meant to be a developer's troubleshooting tool, not an end user utility. Also if a map drawing fails that thread will simply exit without finishing its number of iterations. The point of all this is to help make mapserver thread safe. The code above is meant as a simple starting point that should help mapserver developers test the code in a multithreaded application. Any comments and thoughts or even module tests (I do not have the resources to test a lot of mapserver's code, especially all the various data back ends) will be appreciated. Jerry Pisk ---------- $Id$ mapserver-7.4.3/mapscript/mapscript.i000066400000000000000000000173361357574274700177460ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for the MapServer mapscript module Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2005 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================================ */ %begin %{ #ifdef _MSC_VER #define SWIG_PYTHON_INTERPRETER_NO_DEBUG #endif %} #ifndef SWIGPHPNG %module mapscript #else %module mapscriptng #endif #ifdef SWIGCSHARP %ignore frompointer; %include swig_csharp_extensions.i #endif #ifdef SWIGJAVA %ignore layerObj::extent; #endif %newobject msLoadMapFromString; %{ #include "../../mapserver.h" #include "../../maptemplate.h" #include "../../mapogcsld.h" #include "../../mapows.h" #include "../../cgiutil.h" #include "../../mapcopy.h" #include "../../maperror.h" #include "../../mapprimitive.h" #include "../../mapshape.h" #if defined(WIN32) && defined(SWIGCSHARP) /* is needed for GetExceptionCode() for unhandled exception */ #include #endif %} /* Problem with SWIG CSHARP typemap for pointers */ #ifndef SWIGCSHARP %include typemaps.i #endif %include constraints.i %include carrays.i %array_class(int, intarray) /* =========================================================================== Supporting 'None' as an argument to attribute accessor functions Typemaps to support NULL in attribute accessor functions provided to Steve Lime by David Beazley and tested for Python only by Sean Gillies. With the use of these typemaps we can execute statements like layer.group = None ============================================================================ */ #ifdef __cplusplus %typemap(memberin) char * { if ($1) delete [] $1; if ($input) { $1 = ($1_type) (new char[strlen($input)+1]); strcpy((char *) $1,$input); } else { $1 = 0; } } %typemap(memberin,warning="451:Setting const char * member may leak memory.") const char * { if ($input) { $1 = ($1_type) (new char[strlen($input)+1]); strcpy((char *) $1,$input); } else { $1 = 0; } } %typemap(globalin) char * { if ($1) delete [] $1; if ($input) { $1 = ($1_type) (new char[strlen($input)+1]); strcpy((char *) $1,$input); } else { $1 = 0; } } %typemap(globalin,warning="451:Setting const char * variable may leak memory.") const char * { if ($input) { $1 = ($1_type) (new char[strlen($input)+1]); strcpy((char *) $1,$input); } else { $1 = 0; } } #else %typemap(memberin) char * { if ($1) free((char*)$1); if ($input) { $1 = ($1_type) malloc(strlen($input)+1); strcpy((char*)$1,$input); } else { $1 = 0; } } %typemap(memberin,warning="451:Setting const char * member may leak memory.") const char * { if ($input) { $1 = ($1_type) malloc(strlen($input)+1); strcpy((char*)$1,$input); } else { $1 = 0; } } %typemap(globalin) char * { if ($1) free((char*)$1); if ($input) { $1 = ($1_type) malloc(strlen($input)+1); strcpy((char*)$1,$input); } else { $1 = 0; } } %typemap(globalin,warning="451:Setting const char * variable may leak memory.") const char * { if ($input) { $1 = ($1_type) malloc(strlen($input)+1); strcpy((char*)$1,$input); } else { $1 = 0; } } #endif /* __cplusplus */ /* GD Buffer Mapping for use with imageObj::getBytes */ %{ #ifdef __cplusplus extern "C" { #endif typedef struct { unsigned char *data; int size; int owns_data; } gdBuffer; #ifdef __cplusplus } #endif %} /* ============================================================================ Exceptions Note: Python exceptions are in pymodule.i ============================================================================ */ #if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGRUBY) || defined(SWIGPHP7) %include "../mserror.i" #endif /* ============================================================================ Language-specific module code ============================================================================ */ /* C# */ #ifdef SWIGCSHARP %include "csmodule.i" #endif /* Java */ #ifdef SWIGJAVA %include "javamodule.i" #endif /* Python */ #ifdef SWIGPYTHON %include "pymodule.i" #endif /* SWIGPYTHON */ /* Ruby */ #ifdef SWIGRUBY %include "rbmodule.i" #endif /* Perl */ #ifdef SWIGPERL5 %include "plmodule.i" #endif /* Tcl */ #ifdef SWIGTCL8 %include "tclmodule.i" #endif /* SWIGTCL8 */ /* PHP7 */ #ifdef SWIGPHP7 %include "php7module.i" #endif /* SWIGPHP7 */ /* ============================================================================= Wrap MapServer structs into mapscript classes ============================================================================= */ %include "../../mapserver.h" %include "../../mapserver-version.h" %include "../../mapprimitive.h" %include "../../mapshape.h" %include "../../mapproject.h" %include "../../mapsymbol.h" %apply Pointer NONNULL { mapObj *map }; %apply Pointer NONNULL { layerObj *layer }; /* ============================================================================= Class extension methods are now included from separate interface files ============================================================================= */ %include "../swiginc/error.i" %include "../swiginc/map.i" %include "../swiginc/mapzoom.i" %include "../swiginc/symbol.i" %include "../swiginc/symbolset.i" %include "../swiginc/layer.i" %include "../swiginc/class.i" %include "../swiginc/cluster.i" %include "../swiginc/style.i" %include "../swiginc/rect.i" %include "../swiginc/image.i" %include "../swiginc/shape.i" %include "../swiginc/point.i" %include "../swiginc/line.i" %include "../swiginc/shapefile.i" %include "../swiginc/outputformat.i" %include "../swiginc/projection.i" %include "../swiginc/dbfinfo.i" %include "../swiginc/labelcache.i" %include "../swiginc/color.i" %include "../swiginc/hashtable.i" %include "../swiginc/resultcache.i" %include "../swiginc/result.i" %include "../swiginc/owsrequest.i" %include "../swiginc/connpool.i" %include "../swiginc/msio.i" %include "../swiginc/web.i" %include "../swiginc/label.i" %include "../swiginc/scalebar.i" %include "../swiginc/legend.i" %include "../swiginc/referencemap.i" %include "../swiginc/querymap.i" /* ============================================================================= Language-specific extensions to mapserver classes are included here ============================================================================= */ /* Java */ #ifdef SWIGJAVA %include "javaextend.i" #endif /* Python */ #ifdef SWIGPYTHON %include "pyextend.i" #endif /* SWIGPYTHON */ /* Ruby */ #ifdef SWIGRUBY %include "rbextend.i" #endif mapserver-7.4.3/mapscript/mserror.i000066400000000000000000000041251357574274700174250ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: MapScript exceptions Author: Umberto Unicoletti, unicoletti@prometeo.it Jerry Pisk, jerry.pisk@gmail.com Sean Gillies, sgillies@frii.com Tamas Szekeres, szekerest@gmail.com Note: Python exceptions are in mapscript/python C# exceptions are redefinied in mapscript/csharp This implementation truncates the error message length to MAX_ERROR_LEN since SWIG_exception does not allow to free memory allocated on the heap easily (szekerest) ============================================================================ */ #define MAX_ERROR_LEN 8192 %include exception.i %exception { errorObj *ms_error; $action ms_error = msGetErrorObj(); if (ms_error!=NULL && ms_error->code != MS_NOERR) { char ms_message[MAX_ERROR_LEN]; char* msg = msGetErrorString(";"); int ms_errorcode = ms_error->code; if (msg) { snprintf(ms_message, MAX_ERROR_LEN, "%s", msg); free(msg); } else sprintf(ms_message, "Unknown message"); msResetErrorList(); switch(ms_errorcode) { case MS_NOTFOUND: break; case -1: break; case MS_IOERR: SWIG_exception(SWIG_IOError ,ms_message); break; case MS_MEMERR: SWIG_exception(SWIG_MemoryError,ms_message); break; case MS_TYPEERR: SWIG_exception(SWIG_TypeError,ms_message); break; case MS_EOFERR: SWIG_exception(SWIG_SyntaxError,ms_message); break; case MS_CHILDERR: SWIG_exception(SWIG_SystemError,ms_message); break; case MS_NULLPARENTERR: SWIG_exception(SWIG_SystemError,ms_message); break; default: SWIG_exception(SWIG_UnknownError,ms_message); break; } } } mapserver-7.4.3/mapscript/perl/000077500000000000000000000000001357574274700165225ustar00rootroot00000000000000mapserver-7.4.3/mapscript/perl/CMakeLists.txt000066400000000000000000000027061357574274700212670ustar00rootroot00000000000000find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) find_package(Perl REQUIRED) find_package(PerlLibs REQUIRED) set(CUSTOM_PERL_SITE_ARCH_DIR ${PERL_SITEARCH} CACHE DIR "Custom installation directory for perl binary extension") include_directories(${PERL_INCLUDE_PATH}) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) add_definitions(${PERL_EXTRA_C_FLAGS}) set(CMAKE_SWIG_FLAGS -shadow -w314) include_directories(${PROJECT_SOURCE_DIR}/mapscript/perl) if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_GREATER 3.7) swig_add_library(perlmapscript TYPE MODULE LANGUAGE perl5 SOURCES ../mapscript.i) else () swig_add_module(perlmapscript perl5 ../mapscript.i) endif () SWIG_LINK_LIBRARIES(perlmapscript ${PERL_LIBRARIES} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(perlmapscript PROPERTIES OUTPUT_NAME mapscript) set_target_properties(perlmapscript PROPERTIES PREFIX "") if(APPLE) set_target_properties(perlmapscript PROPERTIES SUFFIX ".bundle") endif(APPLE) install(FILES $ DESTINATION ${CUSTOM_PERL_SITE_ARCH_DIR}/auto/mapscript) install(FILES $/mapscript.pm DESTINATION ${CUSTOM_PERL_SITE_ARCH_DIR}) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/tests DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/examples DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) mapserver-7.4.3/mapscript/perl/README000066400000000000000000000012151357574274700174010ustar00rootroot00000000000000To build type: perl Makefile.PL make make install MapScript requires Swig version 1.3+. If you must re-SWIG things use a command like: swig -perl5 -shadow -outdir . -o mapscript_wrap.c ../mapscript.i and then follow the sequence of steps to install mapscript. If you need to change the name of the mapscript module (default=mapscript) you need to: 1) edit ../mapscript.i and change the name of the swig module 2) edit Makefile.PL and edit the name 'mapscript' in the WriteMakefile subroutine call 3) edit plmodule.i and change the name 'mapscript' to whatever the new name will be throughout the file and now build as normal. mapserver-7.4.3/mapscript/perl/examples/000077500000000000000000000000001357574274700203405ustar00rootroot00000000000000mapserver-7.4.3/mapscript/perl/examples/RFC24.pl000066400000000000000000000051461357574274700214630ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use mapscript; use Data::Dumper; my $file=$ARGV[0]; # utility sub assertNotNull { my ($o, $test) = @_; if ($o) { print $test . " PASSED\n"; } else { print $test . " FAILED\n"; } } # layerObj sub testGetLayerObj { my $map = new mapscript::mapObj($file); my $layer = $map->getLayer(1); $map = undef; assertNotNull( $layer->{map} , "testGetLayerObj"); #$layer->{map}->draw()->save("/tmp/map.png"); } sub testGetLayerObjByName { my $map = new mapscript::mapObj($file); my $layer = $map->getLayerByName("POLYGON"); $map = undef; assertNotNull( $layer->{map} , "testGetLayerObjByName"); } sub testLayerObj { my $map = new mapscript::mapObj($file); my $layer = new mapscript::layerObj($map); $map = undef; assertNotNull( $layer->{map} , "testLayerObj"); } sub testInsertLayerObj { my $map = new mapscript::mapObj($file); my $layer = new mapscript::layerObj(undef); my $position = $map->insertLayer($layer); $map = undef; assertNotNull( $position == 7 , "testInsertLayerObj position"); assertNotNull( $layer->{map} , "testInsertLayerObj notnull"); } # classObj sub testGetClassObj { #dumpHash(mapscript::getPARENT_PTRS()); my $map = new mapscript::mapObj($file); my $layer = $map->getLayer(1); my $clazz = $layer->getClass(0); #dumpHash(mapscript::getPARENT_PTRS()); #$clazz->{layer}->{map}->draw()->save("/tmp/map1.png"); #print "parent layer=".$clazz->{layer}."\n"; $map = undef; $layer=undef; #print "parent layer=".$clazz->{layer}."\n"; assertNotNull( $clazz->{layer} , "testGetClassObj"); #$clazz->{layer}->{map}->draw()->save("/tmp/map2.png"); #dumpHash(mapscript::getPARENT_PTRS()); } sub testClassObj { my $map = new mapscript::mapObj($file); my $layer = $map->getLayer(1); my $clazz = new mapscript::classObj($layer); $map = undef; $layer=undef; assertNotNull( $clazz->{layer} , "testClassObj"); } sub testInsertClassObj { my $map = new mapscript::mapObj($file); my $layer = $map->getLayer(1); my $clazz = new mapscript::classObj(undef); my $position = $layer->insertClass($clazz); $map = undef; $layer=undef; assertNotNull( $position == 2 , "testInsertClassObj position"); assertNotNull( $clazz->{layer} , "testInsertClassObj notnull"); } if ( ! $file ) { print "Usage: RFC24.pl file.map\n"; exit 1; } testGetLayerObj; testGetLayerObjByName; testLayerObj; testInsertLayerObj; testGetClassObj; testClassObj; testInsertClassObj; my $hashmap = mapscript::getPARENT_PTRS(); assertNotNull( keys( %$hashmap )==0 , "checking that hashmap of parent ptrs is empty"); print "No of keys:".keys( %$hashmap )."\n"; #dumpHash($hashmap); print Dumper( $hashmap ); mapserver-7.4.3/mapscript/perl/examples/buffer.pl000066400000000000000000000031021357574274700221420ustar00rootroot00000000000000#!/usr/bin/perl # # Script : buffer.pl # # Purpose: Applies buffer to shapefile dataset using geos support # buffer units as are per units of data # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; use File::Copy; my ($infile, $outfile, $buffer); GetOptions("input=s", \$infile, "output=s", \$outfile, "buffer=n", \$buffer); if(!$infile or !$outfile or !$buffer) { print "Usage: $0 --input=[filename] --output=[filename] --buffer=[native units]\n"; exit 0; } die "Tolerance must be greater than zero." unless $buffer > 0; # initialize counters for reporting my $incount = 0; my $outcount = 0; # open the input shapefile my $inSHP = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile."; # create the output shapefile unlink "$outfile.shp"; unlink "$outfile.shx"; unlink "$outfile.dbf"; my $outSHP = new mapscript::shapefileObj($outfile, $inSHP->{type}) or die "Unable to create shapefile '$outfile'. $!\n"; copy("$infile.dbf", "$outfile.dbf") or die "Can't copy file $infile.dbf to $outfile.dbf: $!\n"; my $inshape = new mapscript::shapeObj(-1); # something to hold shapes for(my $i=0; $i<$inSHP->{numshapes}; $i++) { $inSHP->get($i, $inshape); my $outshape = new mapscript::shapeObj(-1); print "buffering feature: $i\n"; $outshape = $inshape->buffer($buffer) or die "Unable to buffer feature #$i: $!\n"; # in native map units $outSHP->add($outshape); undef($outshape); # free memory associated with shape } # for each shape $outSHP = ''; # write the file undef $inSHP; undef $outSHP; mapserver-7.4.3/mapscript/perl/examples/distanceToPoint.pl000077500000000000000000000015531357574274700240130ustar00rootroot00000000000000#!/usr/bin/perl # # Script : distanceToPoint.pl # # Purpose: Returns distance between a shape and a point # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; use File::Copy; my ($infile, $infile_shpid, $x, $y, $distance); GetOptions("infile=s", \$infile, "infile_shpid=s", \$infile_shpid, "x=s", \$x, "y=s", \$y); if(!$infile or !$infile_shpid or !$x or !$y) { print "Usage: $0 --infile=[filename] --infile_shpid=[shpid] --x=[x] --y=[y]\n"; exit 0; } # open the first input shapefile my $inshpf = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile."; my $inshape = $inshpf->getShape($infile_shpid); my $inpt = new mapscript::pointObj($x, $y); $distance = $inshape->distanceToPoint($inpt); undef $inshpf; print "Distance between shape $infile/$infile_shpid and point $x $y is $distance\n"; mapserver-7.4.3/mapscript/perl/examples/distanceToShape.pl000077500000000000000000000021621357574274700237570ustar00rootroot00000000000000#!/usr/bin/perl # # Script : distanceToShape.pl # # Purpose: Returns distance between two shapes # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; use File::Copy; my ($infile1, $infile1_shpid, $infile2, $infile2_shpid, $distance); GetOptions("infile1=s", \$infile1, "infile1_shpid=s", \$infile1_shpid, "infile2=s", \$infile2, "infile2_shpid=s", \$infile2_shpid); if(!$infile1 or !$infile1_shpid or !$infile2 or !$infile2_shpid) { print "Usage: $0 --infile1=[filename] --infile1_shpid=[shpid] --infile2=[filename] --infile2_shpid=[shpid]\n"; exit 0; } # open the first input shapefile my $inshpf1 = new mapscript::shapefileObj($infile1, -1) or die "Unable to open shapefile $infile1."; my $inshpf2 = new mapscript::shapefileObj($infile2, -1) or die "Unable to open shapefile $infile2."; my $inshape1 = $inshpf1->getShape($infile1_shpid); my $inshape2 = $inshpf2->getShape($infile2_shpid); $distance = $inshape1->distanceToShape($inshape2); undef $inshpf1; undef $inshpf2; print "Distance between shape $infile1/$infile1_shpid and shape $infile2/$infile2_shpid is $distance units\n"; mapserver-7.4.3/mapscript/perl/examples/dump.pl000077500000000000000000000022251357574274700216460ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use mapscript; use Getopt::Long; my $file; my %types = ( '1' => 'point', '3' => 'arc', '5' => 'polygon', '8' => 'multipoint' ); GetOptions("file=s", \$file); if(!$file) { print "Syntax: dump.pl --file=[filename]\n"; exit 0; } my $shapefile = new mapscript::shapefileObj($file, -1) or die "Unable to open shapefile $file"; print "Shapefile opened (type=". $types{$shapefile->{type}} .") with ". $shapefile->{numshapes} ." shape(s)\n"; my $shape = new mapscript::shapeObj(-1); for(my $i=0; $i<$shapefile->{numshapes}; $i++) { $shapefile->get($i, $shape); print "Shape $i has ". $shape->{numlines} ." part(s) - "; printf "bounds (%f,%f) (%f,%f)\n", $shape->{bounds}->{minx}, $shape->{bounds}->{miny}, $shape->{bounds}->{maxx}, $shape->{bounds}->{maxy}; for(my $j=0; $j<$shape->{numlines}; $j++) { my $part = $shape->get($j); print "Part $j has ". $part->{numpoints} ." point(s)\n"; for(my $k=0; $k<$part->{numpoints}; $k++) { my $point = $part->get($k); print "$k: ". $point->{x} .", ". $point->{y} ."\n"; } } } mapserver-7.4.3/mapscript/perl/examples/shapeprops.pl000077500000000000000000000015511357574274700230660ustar00rootroot00000000000000#!/usr/bin/perl # # Script : shapeprops.pl # # Purpose: Applies area, perimeter and centroid calculations to a shapes # in a shapefile (requires mapserver/mapscript to be built with GEOS) # # $Id$ # use strict; use warnings; use mapscript; @ARGV == 1 or die "Usage: $0 \n"; # open the shapefile my $sf = new mapscript::shapefileObj($ARGV[0], -1) or die "Unable to open shapefile $ARGV[0]: $!\n"; # loop over every shape for(my $i = 0; $i < $sf->{numshapes}; $i++) { # fetch the shape my $s = $sf->getShape($i); # calculate area my $a = $s->getArea(); # calculate length / perimeter my $l = $s->getLength(); # calculate centroid my $c = $s->getCentroid(); print <{x}, $c->{y} END # free shape undef $s; } # free shapefile undef $sf; mapserver-7.4.3/mapscript/perl/examples/shpPoint2GPX.pl000077500000000000000000000062601357574274700231510ustar00rootroot00000000000000#!/usr/bin/perl # # Script : shpPoint2GPX.pl # # Purpose: Converts a Point shapefile to a GPX document # as per http://www.topografix.com/gpx.asp # # $Id$ # use strict; use warnings; use POSIX; use XBase; use mapscript; use Getopt::Long; my ($infile, $outfile, $namecol); GetOptions("input=s", \$infile, "output=s", \$outfile, "namecol=s", \$namecol); if(!$infile or !$outfile or !$namecol) { print "Usage: $0 --input=[filename] --output=[filename] --namecol=[namecol]\n"; exit 0; } # open the input shapefile and dbf my $shapefile = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile: $!\n"; my $table = new XBase "$infile" or die XBase->errstr; if ($shapefile->{type} != 1) { print "input shapefile must be of type point\n"; exit 0; } # unlink and create the output GPX document unlink "$outfile.gpx"; open(GPX, ">$outfile.gpx") or die "Unable to open GPX document $outfile.gpx: $!\n"; # print the GPX header info print < $outfile.gpx Description Name Welcome to MapServer text/html 2007 http://mapserver.gis.umn.edu/License Welcome to MapServer text/html MapServer, mapscript, perl, GPX, GPS END my $shape = new mapscript::shapeObj(-1); # something to hold shapes # print each shape as a waypoint for(my $i=0; $i<$shapefile->{numshapes}; $i++) { $shapefile->get($i, $shape); for(my $j=0; $j<$shape->{numlines}; $j++) { my $part = $shape->get($j); for(my $k=0; $k<$part->{numpoints}; $k++) { my $point = $part->get($k); my %row = $table->get_record_as_hash($j) or die $table->errstr; delete $row{"_DELETED"}; print "\t{y}\" lon=\"$point->{x}\">\n"; if ($row{uc($namecol)}) { print "\t\t$row{$namecol}\n"; } # print out the dbf values as GPX extensions print "\t\t\n"; foreach my $k (keys %row) { print "\t\t\t\n"; } print "\t\t\n\t\n"; } } } # for each shape print < $shapefile->{numshapes} $shapefile->{source} END undef $shapefile; close(GPX); mapserver-7.4.3/mapscript/perl/examples/shp_in_shp.pl000066400000000000000000000023421357574274700230300ustar00rootroot00000000000000#!/usr/bin/perl # # Script : shp_in_shp.pl # # Purpose: Tests whether a shape is within another shape # # $Id$ # use strict; use warnings; use mapscript; use Getopt::Long; use File::Copy; my ($infile1, $infile1_shpid, $infile2, $infile2_shpid, $within); GetOptions("infile1=s", \$infile1, "infile1_shpid=s", \$infile1_shpid, "infile2=s", \$infile2, "infile2_shpid=s", \$infile2_shpid); # shpid can be zero, which looks false, so use defined() if(!$infile1 or !defined($infile1_shpid) or !$infile2 or !defined($infile2_shpid)) { print "Usage: $0 --infile1=[filename] --infile1_shpid=[shpid] --infile2=[filename] --infile2_shpid=[shpid]\n"; exit 0; } # open the first input shapefile my $inshpf1 = new mapscript::shapefileObj($infile1, -1) or die "Unable to open shapefile $infile1."; my $inshpf2 = new mapscript::shapefileObj($infile2, -1) or die "Unable to open shapefile $infile2."; my $inshape1 = $inshpf1->getShape($infile1_shpid); my $inshape2 = $inshpf2->getShape($infile2_shpid); $within = $inshape1->within($inshape2); if ($within == 1) { $within = "WITHIN"; } elsif ($within == 0) { $within = "NOT WITHIN"; } undef $inshpf1; undef $inshpf2; print "Shape $infile1/$infile1_shpid is $within shape $infile2/$infile2_shpid\n"; mapserver-7.4.3/mapscript/perl/examples/shpinfo.pl000077500000000000000000000023041357574274700223450ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use XBase; use mapscript; use Getopt::Long; my $file; my %types = ( '1' => 'point', '3' => 'arc', '5' => 'polygon', '8' => 'multipoint' ); GetOptions("file=s", \$file); if(!$file) { print "Syntax: shpinfo.pl --file=[filename]\n"; exit 0; } my $shapefile = new mapscript::shapefileObj($file, -1) or die "Unable to open shapefile $file."; print "Shapefile $file:\n\n"; print "\ttype: ". $types{$shapefile->{type}} ."\n"; print "\tnumber of features: ". $shapefile->{numshapes} ."\n"; printf "\tbounds: (%f,%f) (%f,%f)\n", $shapefile->{bounds}->{minx}, $shapefile->{bounds}->{miny}, $shapefile->{bounds}->{maxx}, $shapefile->{bounds}->{maxy}; my $table = new XBase $file.'.dbf' or die XBase->errstr; print "\nXbase table $file.dbf:\n\n"; print "\tnumber of records: ". ($table->last_record+1) ."\n"; print "\tnumber of fields: ". ($table->last_field+1) ."\n\n"; print "\tName Type Length Decimals\n"; print "\t---------------- ---- ------ --------\n"; foreach ($table->field_names) { printf "\t%-16s %4s %6d %8d\n", $_, $table->field_type($_), $table->field_length($_), $table->field_decimal($_) } mapserver-7.4.3/mapscript/perl/examples/thin.pl000066400000000000000000000062631357574274700216460ustar00rootroot00000000000000#!/usr/bin/perl # Script : thin.pl # # Purpose: An adaption of the ArcView Avenue example script genfeat.ave. It's # basically the Douglas-Peucker generalization algorithm. # (http://mapserver.gis.umn.edu/community/scripts/thin.pl) # # $Id$ # use strict; use warnings; use mapscript; use Getopt::Long; use File::Copy; my ($infile, $outfile, $tolerance); GetOptions("input=s", \$infile, "output=s", \$outfile, "tolerance=n", \$tolerance); if(!$infile or !$outfile or !$tolerance) { print "Usage: $0 --input=[filename] --output=[filename] --tolerance=[maximum distance between vertices]\n"; exit 0; } die "Tolerance must be greater than zero." unless $tolerance > 0; # initialize counters for reporting my $incount = 0; my $outcount = 0; # open the input shapefile my $inSHP = new mapscript::shapefileObj($infile, -1) or die "Unable to open shapefile $infile."; die "Cannot thin point/multipoint shapefiles." unless ($inSHP->{type} == 5 or $inSHP->{type} == 3); # create the output shapefile unlink "$outfile.shp"; unlink "$outfile.shx"; unlink "$outfile.dbf"; my $outSHP = new mapscript::shapefileObj($outfile, $inSHP->{type}) or die "Unable to create shapefile '$outfile'. $!\n"; copy("$infile.dbf", "$outfile.dbf") or die "Can't copy file $infile.dbf to $outfile.dbf: $!\n"; my $inshape = new mapscript::shapeObj(-1); # something to hold shapes for(my $i=0; $i<$inSHP->{numshapes}; $i++) { $inSHP->get($i, $inshape); my $outshape = new mapscript::shapeObj(-1); for(my $j=0; $j<$inshape->{numlines}; $j++) { my $inpart = $inshape->get($j); my $outpart = new mapscript::lineObj(); my @stack = (); $incount += $inpart->{numpoints}; my $anchor = $inpart->get(0); # save first point $outpart->add($anchor); my $aIndex = 0; my $fIndex = $inpart->{numpoints} - 1; push @stack, $fIndex; # Douglas - Peucker algorithm while(@stack) { $fIndex = $stack[$#stack]; my $fPoint = $inpart->get($fIndex); my $max = $tolerance; # comparison values my $maxIndex = 0; # process middle points for (($aIndex+1) .. ($fIndex-1)) { my $point = $inpart->get($_); #my $dist = $point->distanceToLine($anchor, $fPoint); my $dist = $point->distanceToSegment($anchor, $fPoint); if($dist >= $max) { $max = $dist; $maxIndex = $_; } } if($maxIndex > 0) { push @stack, $maxIndex; } else { $outpart->add($fPoint); $anchor = $inpart->get(pop @stack); $aIndex = $fIndex; } } # check for collapsed polygons, use original data in that case if(($outpart->{numpoints} < 4) and ($inSHP->{type} == 5)) { $outpart = $inpart; } $outcount += $outpart->{numpoints}; $outshape->add($outpart); } # for each part $outSHP->add($outshape); undef($outshape); # free memory associated with shape } # for each shape $outSHP = ''; # write the file undef $inSHP; undef $outSHP; my $reduction = ((($outcount / $incount) * 100) - 100) * -1; print < <xsl:value-of select="wfs:Title"/> =cut my $mapfile = "/tmp/config.map"; # init OWSRequest object my $req = new mapscript::OWSRequest(); # pick up CGI paramters passed $req->loadParams(); # init mapfile my $map = new mapscript::mapObj($mapfile); # if this is a WFS GetCapabilities request, then intercept # what is normally returned, process with an XSLT document # and then return that to the client if ($req->getValueByName('REQUEST') eq "GetCapabilities" && $req->getValueByName('SERVICE') eq "WFS") { # push STDOUT to a buffer and run the incoming request my $io = mapscript::msIO_installStdoutToBuffer(); $dispatch = $map->OWSDispatch($req); # at this point, the client's request is sent # pull out the HTTP headers my $ct = mapscript::msIO_stripStdoutBufferContentType(); # and then pick up the actual content of the response my $content = mapscript::msIO_getStdoutBufferString(); my $xml = XML::LibXML->new(); my $xslt = XML::LibXSLT->new(); # load XML content my $source = $xml->parse_string($content); # load XSLT document my $style_doc = $xml->parse_file($xsltfile); my $stylesheet = $xslt->parse_stylesheet($style_doc); # invoke the XSLT transformation my $results = $stylesheet->transform($source); # print out the result (header + content) print "Content-type: $ct\n\n"; print $stylesheet->output_string($results); } # else process as normal else { $dispatch = $map->OWSDispatch($req); } mapserver-7.4.3/mapscript/perl/plextend.i000066400000000000000000000011571357574274700205230ustar00rootroot00000000000000/****************************************************************************** * * Project: MapServer * Purpose: Perl-specific extensions to MapScript objects * Author: SDL based on Sean's Python conventions * ****************************************************************************** * * Perl-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGPERL is defined (via 'swig -perl5 ...'). * *****************************************************************************/ mapserver-7.4.3/mapscript/perl/plmodule.i000066400000000000000000000122571357574274700205240ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Perl-specific enhancements to MapScript * Author: SDL based on Sean's Python conventions * ****************************************************************************** * * Perl-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGPERL is defined (via 'swig -perl5 ...'). * *****************************************************************************/ /****************************************************************************** * Simple Typemaps *****************************************************************************/ %init %{ if(msSetup() != MS_SUCCESS) { msSetError(MS_MISCERR, "Error initializing MapServer/Mapscript.", "msSetup()"); } %} /* Translate Perl's built-in file object to FILE * */ %typemap(in) FILE * { $1 = PerlIO_exportFILE (IoIFP (sv_2io ($input)), NULL); } /* To support imageObj::getBytes */ %typemap(out) gdBuffer { SV *mysv; mysv = sv_newmortal(); if ($1.data == NULL) sv_setpv(mysv,""); else sv_setpvn(mysv,(const char*)$1.data,$1.size); $result = newRV(mysv); sv_2mortal($result); argvi++; if( $1.owns_data ) msFree($1.data); } %typemap(out) char[ANY] { $result = newSVpvn($1, strlen($1)); argvi++; } /* =============================================================================== RFC-24 implementation follows =============================================================================== Modified constructor according to: - cache population and sync, item 3.2 - reference counter since Perl does not obey %newobject */ %allowexception; %exception layer { /* Accessing layer */ $action; MS_REFCNT_INCR(result); } %exception map { /* Accessing map */ $action; MS_REFCNT_INCR(result); } %feature("shadow") layerObj(mapObj *map) %{ sub new { my $pkg = shift; my $self = mapscriptc::new_layerObj(@_); bless $self, $pkg if defined($self); if (defined($_[0])) { # parent reference mapscript::RFC24_ADD_PARENT_REF( tied(%$self), $_[0]); } return $self; } %} %feature("shadow") getLayer(int i) %{ sub getLayer { my $layer = mapscriptc::mapObj_getLayer(@_); if (defined($layer)) { # parent reference #print "l=$layer,m=$_[0]\n"; mapscript::RFC24_ADD_PARENT_REF( tied(%$layer) , $_[0]); } return $layer; } %} %feature("shadow") getLayerByName(char* name) %{ sub getLayerByName { my $layer = mapscriptc::mapObj_getLayerByName(@_); if (defined($layer)) { # parent reference #print "l=$layer,m=$_[0]\n"; mapscript::RFC24_ADD_PARENT_REF( tied(%$layer) , $_[0]); } return $layer; } %} %feature("shadow") insertLayer %{ sub insertLayer { my $idx = mapscriptc::mapObj_insertLayer(@_); my $layer=$_[1]; # parent reference mapscript::RFC24_ADD_PARENT_REF(tied(%$layer), $_[0]); return $idx; } %} %feature("shadow") ~layerObj() %{ sub DESTROY { return unless $_[0]->isa('HASH'); my $self = tied(%{$_[0]}); return unless defined $self; delete $ITERATORS{$self}; mapscriptc::delete_layerObj($self); # remove parent reference mapscript::RFC24_DEL_PARENT_REF($self); } %} %feature("shadow") classObj(layerObj *layer) %{ sub new { my $pkg = shift; my $self = mapscriptc::new_classObj(@_); bless $self, $pkg if defined($self); if (defined($_[0])) { # parent reference mapscript::RFC24_ADD_PARENT_REF( tied(%$self), $_[0]); } return $self; } %} %feature("shadow") getClass(int i) %{ sub getClass { my $clazz = mapscriptc::layerObj_getClass(@_); if (defined($clazz)) { # parent reference mapscript::RFC24_ADD_PARENT_REF( tied(%$clazz) , $_[0]); } return $clazz; } %} %feature("shadow") insertClass %{ sub insertClass { my $idx = mapscriptc::layerObj_insertClass(@_); my $clazz=$_[1]; # parent reference mapscript::RFC24_ADD_PARENT_REF(tied(%$clazz), $_[0]); return $idx; } %} %feature("shadow") ~classObj() %{ sub DESTROY { return unless $_[0]->isa('HASH'); my $self = tied(%{$_[0]}); return unless defined $self; delete $ITERATORS{$self}; mapscriptc::delete_classObj($self); # remove parent reference mapscript::RFC24_DEL_PARENT_REF($self); } %} %perlcode %{ %PARENT_PTRS=(); sub RFC24_ADD_PARENT_REF { my ($child, $parent)=@_; $PARENT_PTRS{ $$child }=$parent; } sub RFC24_DEL_PARENT_REF { my ($child)=@_; delete $PARENT_PTRS{ $$child }; } # USE THIS function only for debugging! sub getPARENT_PTRS { return \%PARENT_PTRS; } %} mapserver-7.4.3/mapscript/perl/tests/000077500000000000000000000000001357574274700176645ustar00rootroot00000000000000mapserver-7.4.3/mapscript/perl/tests/0-load.t000066400000000000000000000031061357574274700211250ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More tests => 11; # check the mapserver version for keywords sub msHas { my ($mod) = @_; my $ver = mapscript::msGetVersion(); if (index($ver, $mod) > -1) { return 1; } else { return 0; } } require_ok( 'mapscript' ); diag("Testing: " . $INC{'mapscript.pm'}); diag( mapscript::msGetVersion() ); SKIP: { skip "no geos support", 10 unless msHas('SUPPORTS=GEOS'); my @wkt_list = ( 'POINT (5.0000000000000000 7.0000000000000000)', 'LINESTRING (5.0000000000000000 7.0000000000000000, 7.0000000000000000 9.0000000000000000, 9.0000000000000000 -1.0000000000000000)', 'POLYGON ((500.0000000000000000 500.0000000000000000, 3500.0000000000000000 500.0000000000000000, 3500.0000000000000000 2500.0000000000000000, 500.0000000000000000 2500.0000000000000000, 500.0000000000000000 500.0000000000000000), (1000.0000000000000000 1000.0000000000000000, 1000.0000000000000000 1500.0000000000000000, 1500.0000000000000000 1500.0000000000000000, 1500.0000000000000000 1000.0000000000000000, 1000.0000000000000000 1000.0000000000000000))', 'MULTIPOINT (2000.0000000000000000 2000.0000000000000000, 2000.0000000000000000 1900.0000000000000000)', 'MULTILINESTRING ((600.0000000000000000 1500.0000000000000000, 1600.0000000000000000 2500.0000000000000000), (700.0000000000000000 1500.0000000000000000, 1700.0000000000000000 2500.0000000000000000))' ); for my $orig (@wkt_list) { my $shp = mapscript::shapeObj::fromWKT( $orig ); ok( $shp, 'create shapeObj'); my $new_wkt = $shp->toWKT(); ok( $orig eq $new_wkt, 'from WKT <> toWKT' ); } }; mapserver-7.4.3/mapscript/perl/tests/maps.t000066400000000000000000000026231357574274700210140ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use Test::More tests => 10; use mapscript; sub msHas { my ($mod) = @_; my $ver = mapscript::msGetVersion(); if (index($ver, $mod) > -1) { return 1; } else { return 0; } } # we need to search up directories for the test folder my $mapfile = '../../../msautotest/mspython/test_mapio.map'; if (! -e $mapfile) { $mapfile = '../../../../msautotest/mspython/test_mapio.map'; } ok(-e $mapfile, 'mapfile exists'); my $map = new mapscript::mapObj($mapfile); ok($map, 'create mapObj'); mapscript::msIO_installStdoutToBuffer(); my $owreq = new mapscript::OWSRequest(); ok($owreq, 'create OWSRequest'); $owreq->loadParamsFromURL('service=WMS&version=1.1.1&request=GetMap&layers=grey&srs=EPSG:4326&bbox=-180,-90,180,90&format=image/png&width=80&height=40'); ok($owreq->getName(0) eq 'service'); ok($owreq->getValue(0) eq 'WMS'); ok($owreq->getValueByName('request') eq 'GetMap'); my $err = $map->OWSDispatch( $owreq ); ok($err == 0, 'OWSDispatch'); # warn(mapscript::msGetErrorString("\n")); my $h = mapscript::msIO_getAndStripStdoutBufferMimeHeaders(); #my $k = $h->nextKey(); #while ($k) #{ # diag("$k == " . $h->get($k)); # $k = $h->nextKey($k); #} ok($h->get('Cache-Control') eq 'max-age=86400'); ok($h->get('Content-Type') eq 'image/png'); my $x = mapscript::msIO_getStdoutBufferBytes(); #open(F, '>', 'x.png'); #print F $$x; #close(F); ok(substr($$x, 1, 3) eq 'PNG'); mapserver-7.4.3/mapscript/php/000077500000000000000000000000001357574274700163475ustar00rootroot00000000000000mapserver-7.4.3/mapscript/php/CMakeLists.txt000066400000000000000000000027501357574274700211130ustar00rootroot00000000000000FIND_PACKAGE(PHP REQUIRED) INCLUDE_DIRECTORIES(${PHP_INCLUDE_PATH}) if(WIN32) add_definitions(/DWIN32 /DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0) if(NOT CMAKE_CL_64) add_definitions(-D_USE_32BIT_TIME_T) endif(NOT CMAKE_CL_64) if(WITH_THREAD_SAFETY) add_definitions(-DZTS=1) endif(WITH_THREAD_SAFETY) ENDIF(WIN32) IF(APPLE) if(XCODE) SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -undefined dynamic_lookup") SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -undefined dynamic_lookup") else(XCODE) SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -undefined dynamic_lookup") SET(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -undefined dynamic_lookup") endif(XCODE) ENDIF(APPLE) add_definitions(-DCOMPILE_DL=1) add_library(php_mapscript MODULE mapscript_error.c color.c rect.c hashtable.c web.c grid.c error.c referencemap.c querymap.c outputformat.c scalebar.c label.c legend.c symbol.c style.c image.c class.c projection.c line.c shape.c shapefile.c point.c labelleader.c result.c owsrequest.c cluster.c layer.c map.c php_mapscript_util.c php_mapscript.c mapscript_i.c ) if(WIN32) target_link_libraries(php_mapscript ${MAPSERVER_LIBMAPSERVER} ${PHP_LIBRARY}) ELSE(WIN32) target_link_libraries(php_mapscript ${MAPSERVER_LIBMAPSERVER}) ENDIF(WIN32) set_target_properties(php_mapscript PROPERTIES PREFIX "") install(TARGETS php_mapscript DESTINATION ${PHP_EXTENSION_DIR}) mapserver-7.4.3/mapscript/php/Makefile.vc000066400000000000000000000060721357574274700204230ustar00rootroot00000000000000# # makefile.vc - MSVC++ makefile for the PHP/MapScript extension # # This VC++ makefile will build the PHP module PHP_MAPSCRIPT.DLL # # To use the makefile: # - Open a DOS prompt window # - Run the VCVARS32.BAT script to initialize the VC++ environment variables # - Start the build with: nmake /f makefile.vc # # $Id$ # # Flag indicating to the option files that this is the build of PHP/MapScript PHP_BUILD_CALL=TRUE !INCLUDE ../../nmake.opt !INCLUDE nmake.opt PDB_FILE=/Fdphpms.pdb #DZEND_DEBUG=0 was added for #2717 PHP4_FLAGS=/DZEND_WIN32 /DPHP_WIN32 /DPHP4 /DZTS /PHP_COMPILER_ID=VC9 /DZEND_DEBUG=0 #OPTFLAGS = /nologo /Zi $(WARNING_LEVEL) $(DEBUG) $(PDB_FILE) #BASE_CFLAGS = $(OPTFLAGS) -DWIN32 -D_WIN32 $(PHP4_FLAGS) #LDFLAGS = /NODEFAULTLIB:msvcrt /dll $(LDEBUG) #LDFLAGS = /NODEFAULTLIB:libcd /dll $(LDEBUG) # Set flag for Visual Studio > 2003 & PHP < 5.3 # see http://bugs.php.net/bug.php?id=39130 !IF $(MSVC_VER) >= 1400 !IFDEF WIN64 VCFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE !ELSE VCFLAGS = -D_USE_32BIT_TIME_T -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE !ENDIF !ENDIF BASE_CFLAGS = $(OPTFLAGS) -DWIN32 -D_WIN32 $(PHP4_FLAGS) $(VCFLAGS) OPTFLAGS = /nologo /Zi /MD $(WARNING_LEVEL) $(DEBUG) /EHsc LDFLAGS = /NODEFAULTLIB:libc /dll /FORCE:MULTIPLE $(LDEBUG) # # Set PHP_HOME to point to the root of the PHP source tree # PHP_INC = -I$(PHP_HOME) -I$(PHP_HOME)/main -I$(PHP_HOME)/zend -I$(PHP_HOME)/include -I$(PHP_HOME)/tsrm !IFDEF DLLBUILD MS_LIBS = ../../mapserver_i.lib $(EXTERNAL_LIBS) !ELSE MS_LIBS = $(EXTERNAL_LIBS) ../../mapserver.lib !ENDIF # # The rest of the file should not have to be edited... # PHPMS_CLASS_OBJS = mapscript_error.obj color.obj rect.obj hashtable.obj web.obj grid.obj error.obj referencemap.obj querymap.obj outputformat.obj scalebar.obj label.obj legend.obj symbol.obj style.obj image.obj class.obj projection.obj line.obj shape.obj shapefile.obj point.obj labelcache.obj labelleader.obj labelcachemember.obj result.obj owsrequest.obj cluster.obj layer.obj map.obj PHPMS_OBJS = php_mapscript_util.obj $(PHPMS_CLASS_OBJS) php_mapscript.obj mapscript_i.obj PHPPROJ_OBJS = php_mapscript_util.obj php_proj.obj PHPMS_DLL = php_mapscript.dll PHPPROJ_DLL = php_proj.dll CFLAGS = $(BASE_CFLAGS) $(MS_CFLAGS) -I../.. $(PHP_INC) default: all all: $(PHPMS_DLL) mapscript: $(PHPMS_DLL) proj: $(PHPPROJ_DLL) install: all copy $(PHPMS_DLL) $(PHP_INSTALL_DIR)\$(PHP_INSTALL_DLL_NAME) $(PHPMS_DLL): $(PHPMS_OBJS) link $(LDFLAGS) /out:$(PHPMS_DLL) $(PHPMS_OBJS) $(MS_LIBS) \ $(PHP_HOME)\lib\$(PHP_TS_LIB_NAME) if exist $(PHPMS_DLL).manifest mt -manifest $(PHPMS_DLL).manifest -outputresource:$(PHPMS_DLL);2 $(PHPPROJ_DLL): $(PHPPROJ_OBJS) link $(LDFLAGS) /out:$(PHPPROJ_DLL) $(PHPPROJ_OBJS) $(MS_LIBS) \ $(PHP_HOME)\lib\$(PHP_TS_LIB_NAME) $(PHPMS_OBJS): php_mapscript_util.h php_mapscript.h .c.obj: $(CC) $(CFLAGS) /DCOMPILE_DL=1 /c $*.c /Fo$*.obj clean: del *.obj del $(PHPMS_OBJS) del $(PHPPROJ_OBJS) del $(PHPMS_DLL) del $(PHPPROJ_DLL) del *.lib del *.pdb del *.exp del *.ilk del *.manifest mapserver-7.4.3/mapscript/php/README000066400000000000000000000001421357574274700172240ustar00rootroot00000000000000Please see the PHP MapScript documentation at: http://www.mapserver.org/mapscript/php/index.html mapserver-7.4.3/mapscript/php/README.WIN32000066400000000000000000000063301357574274700200320ustar00rootroot00000000000000 PHP/MapScript Mapserver Module ============================== This README covers building PHP-Mapscript on Windows with Visual Studio 2012 Express for PHP-5.6 x86 Thread-Safe. If you already built Mapserver with instructions from ../../README.WIN32, you are only a few steps away from PHP-Mapscript. If not, first build Mapserver as descriped in ../../README.WIN32. -------------------------------------------------------------------- Step 1: Build PHP -------------------------------------------------------------------- Build PHP-5.6 x86 Thread-Safe with Visual Studio 2012 Express as descriped here: https://wiki.php.net/internals/windows/stepbystepbuild Extract the PHP-SDK to C:\dev\work\php-sdk to be able to use the commands, used here. PHP sources and compiled binaries should be in C:\dev\work\php-sdk\phpdev\vc11\x86\php-5.6.28-src now. -------------------------------------------------------------------- Step 2: Build PHP-Mapscript -------------------------------------------------------------------- After step 5 of ../../README.WIN32 you have an open VS2012 x86 Native Tools Shell in build-Directory in your Mapserver sources (C:\dev\work\mapserver\build). If not, open VS2012 x86 Native Tools Shell, add cmake to your PATH (see ../../README.WIN32) and "cd C:\dev\work\mapserver\build". 1. Tell CMake to build Mapscript by entering: cmake .. -DWITH_PHP=1 -DPHP5_EXTENSION_DIR=C:\dev\builds\php-5.6.28-Win32-VC11-x86_mapscript\ext -DPHP5_INCLUDES=C:\dev\work\php-sdk\phpdev\vc11\x86\php-5.6.28-src 2. build: nmake -------------------------------------------------------------------- Step 3: Install PHP3_MAPSCRIPT.DLL/PHP_MAPSCRIPT.DLL -------------------------------------------------------------------- PHP_MAPSCRIPT.DLL is a regular PHP module, you should copy it to the same directory as the other PHP_*.DLL modules that came with PHP. Then the module can be loaded in one of 2 ways: - Adding a "extension=php_mapscript.dll" line to the PHP3.INI file will load it automatically for every PHP page. - The other possibility is to load the module only when needed using the following PHP call: dl("php_mapscript.dll"); // for the PHP4 module You can test that the module is properly loaded by executing the phpinfo() command in a PHP page... the "MapScript" extension should be included in the list of extensions in the phpinfo() report. -------------------------------------------------------------------- Maybe Step 4: Troubleshooting -------------------------------------------------------------------- If you have any problems, getting PHP-MapScript running, add it to php.ini and try to start php from command line. It may tell you, what is missing. PHP-MapScript has the same dependencies as Mapserver itself so you may need to add paths to the dependencies and libmap.dll/mapserver.dll to you systems PATH environment variable. If this all does not help, use tools like SysInternals Process Monitor (https://technet.microsoft.com/de-de/sysinternals/processmonitor.aspx) or Dependency Walker (http://www.dependencywalker.com/) to find, what is missing. Open php_mapscript.dll with Dependency Walker to see missing dependencies. -------------------------- $Id$ -------------------------- mapserver-7.4.3/mapscript/php/class.c000066400000000000000000001013171357574274700176230ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_class; zend_object_handlers mapscript_class_object_handlers; ZEND_BEGIN_ARG_INFO_EX(class___construct_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, class, classObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_addLabel_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, label, labelObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_removeLabel_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_getLabel_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_setExpression_args, 0, 0, 1) ZEND_ARG_INFO(0, expression) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_setText_args, 0, 0, 1) ZEND_ARG_INFO(0, text) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_getStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_insertStyle_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, style, styleObj, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_removeStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_moveStyleUp_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_moveStyleDown_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_deleteStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_getMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_setMetaData_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_removeMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_createLegendIcon_args, 0, 0, 2) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(class_drawLegendIcon_args, 0, 0, 5) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_ARG_INFO(0, dstX) ZEND_ARG_INFO(0, dstY) ZEND_END_ARG_INFO() /* {{{ proto void __construct(layerObj layer [, classObj class]) Create a new class instance in the specified layer.. */ PHP_METHOD(classObj, __construct) { zval *zobj = getThis(); zval *zlayer, *zclass = NULL; classObj *class; php_layer_object *php_layer; php_class_object *php_class, *php_class2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zlayer, mapscript_ce_layer, &zclass, mapscript_ce_class) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); if (zclass) php_class2 = MAPSCRIPT_OBJ_P(php_class_object, zclass); if ((class = classObj_new(php_layer->layer, (zclass ? php_class2->class:NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } php_class->class = class; MAPSCRIPT_MAKE_PARENT(zlayer,NULL); php_class->parent = parent; MAPSCRIPT_ADDREF(parent.val); } /* }}} */ PHP_METHOD(classObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_class_object *php_class; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); IF_GET_STRING("name", php_class->class->name) else IF_GET_STRING("title", php_class->class->title) else IF_GET_LONG("status", php_class->class->status) else IF_GET_DOUBLE("minscaledenom", php_class->class->minscaledenom) else IF_GET_DOUBLE("maxscaledenom", php_class->class->maxscaledenom) else IF_GET_LONG("minfeaturesize", php_class->class->minfeaturesize) else IF_GET_LONG("numlabels", php_class->class->numlabels) else IF_GET_STRING("template", php_class->class->template) else IF_GET_STRING("keyimage", php_class->class->keyimage) else IF_GET_STRING("group", php_class->class->group) else IF_GET_LONG("numstyles", php_class->class->numstyles) else IF_GET_OBJECT("metadata", mapscript_ce_hashtable, php_class->metadata, &php_class->class->metadata) else IF_GET_OBJECT("leader", mapscript_ce_labelleader, php_class->leader, php_class->class->leader) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(classObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_class_object *php_class; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); /* special case for "template" which we want to set to NULL and not an empty string */ if(Z_TYPE_P(value)==IS_NULL && !strcmp(property,"template")) { msFree(php_class->class->template); php_class->class->template = NULL; } else IF_SET_STRING("name", php_class->class->name, value) else IF_SET_STRING("title", php_class->class->title, value) else IF_SET_LONG("status", php_class->class->status, value) else IF_SET_DOUBLE("minscaledenom", php_class->class->minscaledenom, value) else IF_SET_DOUBLE("maxscaledenom", php_class->class->maxscaledenom, value) else IF_SET_LONG("minfeaturesize", php_class->class->minfeaturesize, value) else IF_SET_STRING("template", php_class->class->template, value) else IF_SET_STRING("keyimage", php_class->class->keyimage, value) else IF_SET_STRING("group", php_class->class->group, value) else if ( (STRING_EQUAL("metadata", property)) || (STRING_EQUAL("leader", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if ( (STRING_EQUAL("numstyles", property)) || (STRING_EQUAL("numstyles", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int addLabel(labelObj *label) Add a label to the class. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(classObj, addLabel) { zval *zobj = getThis(); zval *zlabel; php_class_object *php_class; php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zlabel, mapscript_ce_label) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); php_label = MAPSCRIPT_OBJ_P(php_label_object, zlabel); status = classObj_addLabel(php_class->class, php_label->label); php_label->is_ref = 1; RETURN_LONG(status); } /* }}} */ /* {{{ proto int removeLabel(int index) Removes the label indicated and returns a copy, or NULL in the case of a failure. */ PHP_METHOD(classObj, removeLabel) { zval *zobj = getThis(); long index; labelObj *label; php_class_object *php_class; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); if ((label = classObj_removeLabel(php_class->class, index)) == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } /* Return a copy of the class object just removed */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_label(label, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int class.getLabel(int i) Returns a labelObj from the class given an index value (0=first label) */ PHP_METHOD(classObj, getLabel) { zval *zobj = getThis(); long index; labelObj *label = NULL; php_class_object *php_class; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); if ((label = classObj_getLabel(php_class->class, index)) == NULL) { mapscript_throw_exception("Invalid label index." TSRMLS_CC); return; } /* Return class object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_label(label, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int updateFromString(string snippet) Update a class from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(classObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); status = classObj_updateFromString(php_class->class, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the class object to string. */ PHP_METHOD(classObj, convertToString) { zval *zobj = getThis(); php_class_object *php_class; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); value = classObj_convertToString(php_class->class); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setExpression(string exression) Set the expression string for a class object. */ PHP_METHOD(classObj, setExpression) { char *expression; long expression_len = 0; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &expression, &expression_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); status = classObj_setExpression(php_class->class, expression); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string getExpressionString() Get the expression string for a class object. */ PHP_METHOD(classObj, getExpressionString) { zval *zobj = getThis(); php_class_object *php_class; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); value = classObj_getExpressionString(php_class->class); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setText(string text) Set the text string for a class object. */ PHP_METHOD(classObj, setText) { char *text; long text_len = 0; zval *zobj = getThis(); php_class_object *php_class; php_layer_object *php_layer; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); php_layer = MAPSCRIPT_OBJ(php_layer_object, php_class->parent.val); status = classObj_setText(php_class->class, php_layer->layer, text); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string getTextString() Get the text string for a class object. */ PHP_METHOD(classObj, getTextString) { zval *zobj = getThis(); php_class_object *php_class; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); value = classObj_getTextString(php_class->class); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto styleObj getstyle(int index) return the style object. */ PHP_METHOD(classObj, getStyle) { long index; zval *zobj = getThis(); php_class_object *php_class; styleObj *style = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); if (index < 0 || index >= php_class->class->numstyles) { mapscript_throw_exception("Invalid style index." TSRMLS_CC); return; } style = php_class->class->styles[index]; MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int insertStyle(styleObj style) return MS_SUCCESS or MS_FAILURE. */ PHP_METHOD(classObj, insertStyle) { zval *zobj = getThis(); zval *zstyle = NULL; long index = -1; php_class_object *php_class; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &zstyle, mapscript_ce_style, &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); php_style = MAPSCRIPT_OBJ_P(php_style_object, zstyle); RETURN_LONG(msInsertStyle(php_class->class, php_style->style, index)); } /* }}} */ /* {{{ proto styleObj removeStyle(int index) return the styleObj removed. */ PHP_METHOD(classObj, removeStyle) { zval *zobj = getThis(); long index; styleObj *style; php_class_object *php_class; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); style = msRemoveStyle(php_class->class, index); /* Return a copy of the class object just removed */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int moveStyleUp(int index) The style specified by the style index will be moved up into the array of classes. Returns MS_SUCCESS or MS_FAILURE. ex class->movestyleup(1) will have the effect of moving style 1 up to position 0, and the style at position 0 will be moved to position 1. */ PHP_METHOD(classObj, moveStyleUp) { long index; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); status = classObj_moveStyleUp(php_class->class, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int moveStyleDown(int index) The style specified by the style index will be moved down into the array of classes. Returns MS_SUCCESS or MS_FAILURE. ex class->movestyledown(0) will have the effect of moving style 0 up to position 1, and the style at position 1 will be moved to position 0. */ PHP_METHOD(classObj, moveStyleDown) { long index; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); status = classObj_moveStyleDown(php_class->class, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int deleteStyle(int index) Delete the style specified by the style index. If there are any style that follow the deleted style, their index will decrease by 1. */ PHP_METHOD(classObj, deleteStyle) { long index; zval *zobj = getThis(); php_class_object *php_class; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); status = classObj_deleteStyle(php_class->class, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto string getMetaData(string name) Return MetaData entry by name, or empty string if not found. */ PHP_METHOD(classObj, getMetaData) { zval *zname; zval *zobj = getThis(); php_class_object *php_class; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_class->metadata, &php_class->class->metadata); MAPSCRIPT_CALL_METHOD_1(php_class->metadata, "get", retval, zname); #if PHP_VERSION_ID < 70000 RETURN_STRING(Z_STRVAL_P(retval),1); #else RETURN_STRING(Z_STRVAL(retval)); #endif } /* }}} */ /* {{{ proto int setMetaData(string name, string value) Set MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(classObj, setMetaData) { zval *zname, *zvalue; zval *zobj = getThis(); php_class_object *php_class; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zname, &zvalue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_class->metadata, &php_class->class->metadata); MAPSCRIPT_CALL_METHOD_2(php_class->metadata, "set", retval, zname, zvalue); #if PHP_VERSION_ID < 70000 RETURN_LONG(Z_LVAL_P(retval)); #else RETURN_LONG(Z_LVAL(retval)); #endif } /* }}} */ /* {{{ proto int removeMetaData(string name) Remove MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(classObj, removeMetaData) { zval *zname; zval *zobj = getThis(); php_class_object *php_class; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_class->metadata, &php_class->class->metadata); MAPSCRIPT_CALL_METHOD_1(php_class->metadata, "remove", retval, zname); #if PHP_VERSION_ID < 70000 RETURN_LONG(Z_LVAL_P(retval)); #else RETURN_LONG(Z_LVAL(retval)); #endif } /* }}} */ /* {{{ proto imageObj createLegendIcon(int width, int height) Return the legend icon. */ PHP_METHOD(classObj, createLegendIcon) { zval *zobj = getThis(); long width, height; imageObj *image = NULL; php_class_object *php_class; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); php_layer = MAPSCRIPT_OBJ(php_layer_object, php_class->parent.val); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this class object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((image = classObj_createLegendIcon(php_class->class, php_map->map, php_layer->layer, width, height)) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return an image object */ mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int drawLegendIcon(int width, int height, imageObj image, int dstX, int dstY) set the lengend icon in img. */ PHP_METHOD(classObj, drawLegendIcon) { zval *zobj = getThis(); zval *zimage; long width, height, dstX, dstY; int status = MS_FAILURE; php_class_object *php_class; php_image_object *php_image; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llOll", &width, &height, &zimage, mapscript_ce_image, &dstX, &dstY) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); php_layer = MAPSCRIPT_OBJ(php_layer_object, php_class->parent.val); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this class object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if (!MS_RENDERER_PLUGIN(php_image->image->format)) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); mapscript_report_php_error(E_WARNING, "DrawLegendicon function is only available for renderer plugin drivers" TSRMLS_CC); RETURN_LONG(MS_FAILURE); } if ((status = classObj_drawLegendIcon(php_class->class, php_map->map, php_layer->layer, width, height, php_image->image, dstX, dstY)) != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto string free() Free the object */ PHP_METHOD(classObj, free) { zval *zobj = getThis(); php_class_object *php_class; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zobj); MAPSCRIPT_DELREF(php_class->metadata); } /* }}} */ zend_function_entry class_functions[] = { PHP_ME(classObj, __construct, class___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(classObj, __get, class___get_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, __set, class___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(classObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(classObj, addLabel, class_addLabel_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, removeLabel, class_removeLabel_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, getLabel, class_getLabel_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, updateFromString, class_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(classObj, setExpression, class_setExpression_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, getExpressionString, NULL, ZEND_ACC_PUBLIC) PHP_ME(classObj, setText, class_setText_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, getTextString, NULL, ZEND_ACC_PUBLIC) PHP_ME(classObj, getStyle, class_getStyle_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, insertStyle, class_insertStyle_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, removeStyle, class_removeStyle_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, moveStyleUp, class_moveStyleUp_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, moveStyleDown, class_moveStyleDown_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, deleteStyle, class_deleteStyle_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, getMetaData, class_getMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, setMetaData, class_setMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, removeMetaData, class_removeMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, createLegendIcon, class_createLegendIcon_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, drawLegendIcon, class_drawLegendIcon_args, ZEND_ACC_PUBLIC) PHP_ME(classObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_class(classObj *class, parent_object parent, zval *return_value TSRMLS_DC) { php_class_object * php_class; object_init_ex(return_value, mapscript_ce_class); php_class = MAPSCRIPT_OBJ_P(php_class_object, return_value); php_class->class = class; php_class->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_class_create_object(zend_class_entry *ce TSRMLS_DC) { php_class_object *php_class; php_class = ecalloc(1, sizeof(*php_class) + zend_object_properties_size(ce)); zend_object_std_init(&php_class->zobj, ce TSRMLS_CC); object_properties_init(&php_class->zobj, ce); php_class->zobj.handlers = &mapscript_class_object_handlers; MAPSCRIPT_INIT_PARENT(php_class->parent); ZVAL_UNDEF(&php_class->metadata); ZVAL_UNDEF(&php_class->leader); return &php_class->zobj; } static void mapscript_class_free_object(zend_object *object) { php_class_object *php_class; php_class = (php_class_object *)((char *)object - XtOffsetOf(php_class_object, zobj)); MAPSCRIPT_FREE_PARENT(php_class->parent); MAPSCRIPT_DELREF(php_class->metadata); MAPSCRIPT_DELREF(php_class->leader); /* We don't need to free the classObj */ zend_object_std_dtor(object); } static zend_object* mapscript_class_clone_object(zval *zobj) { php_class_object *php_class_old, *php_class_new; php_layer_object *php_layer; zend_object* zobj_new; php_class_old = MAPSCRIPT_OBJ_P(php_class_object, zobj); php_layer = MAPSCRIPT_OBJ(php_layer_object, php_class_old->parent.val); zobj_new = mapscript_class_create_object(mapscript_ce_class); php_class_new = (php_class_object *)((char *)zobj_new - XtOffsetOf(php_class_object, zobj)); zend_objects_clone_members(&php_class_new->zobj, &php_class_old->zobj); php_class_new->class = classObj_clone(php_class_old->class, php_layer->layer); return zobj_new; } PHP_MINIT_FUNCTION(class) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "classObj", class_functions); mapscript_ce_class = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_class->create_object = mapscript_class_create_object; mapscript_ce_class->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_class_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_class_object_handlers)); mapscript_class_object_handlers.free_obj = mapscript_class_free_object; mapscript_class_object_handlers.clone_obj = mapscript_class_clone_object; mapscript_class_object_handlers.offset = XtOffsetOf(php_class_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_class_object_destroy(void *object TSRMLS_DC) { php_class_object *php_class = (php_class_object *)object; MAPSCRIPT_FREE_OBJECT(php_class); MAPSCRIPT_FREE_PARENT(php_class->parent); MAPSCRIPT_DELREF(php_class->metadata); MAPSCRIPT_DELREF(php_class->leader); /* We don't need to free the classObj */ efree(object); } static zend_object_value mapscript_class_object_new_ex(zend_class_entry *ce, php_class_object **ptr TSRMLS_DC) { zend_object_value retval; php_class_object *php_class; MAPSCRIPT_ALLOC_OBJECT(php_class, php_class_object); retval = mapscript_object_new_ex(&php_class->std, ce, &mapscript_class_object_destroy, &mapscript_class_object_handlers TSRMLS_CC); if (ptr) *ptr = php_class; MAPSCRIPT_INIT_PARENT(php_class->parent); php_class->metadata = NULL; php_class->leader = NULL; return retval; } static zend_object_value mapscript_class_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_class_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_class_object_clone(zval *zobj TSRMLS_DC) { php_class_object *php_class_old, *php_class_new; php_layer_object *php_layer; zend_object_value new_ov; php_class_old = MAPSCRIPT_OBJ_P(php_class_object, zobj); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, php_class_old->parent.val); new_ov = mapscript_class_object_new_ex(mapscript_ce_class, &php_class_new TSRMLS_CC); zend_objects_clone_members(&php_class_new->std, new_ov, &php_class_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_class_new->class = classObj_clone(php_class_old->class, php_layer->layer); return new_ov; } PHP_MINIT_FUNCTION(class) { zend_class_entry ce; memcpy(&mapscript_class_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_class_object_handlers.clone_obj = mapscript_class_object_clone; MAPSCRIPT_REGISTER_CLASS("classObj", class_functions, mapscript_ce_class, mapscript_class_object_new); mapscript_ce_class->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/cluster.c000066400000000000000000000277511357574274700202100ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_cluster; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_cluster_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(cluster___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(cluster___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(cluster_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(cluster_setGroup_args, 0, 0, 1) ZEND_ARG_INFO(0, group) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(cluster_setFilter_args, 0, 0, 1) ZEND_ARG_INFO(0, filter) ZEND_END_ARG_INFO() /* {{{ proto outputformat __construct() clusterObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(clusterObj, __construct) { mapscript_throw_exception("clusterObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(clusterObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_cluster_object *php_cluster; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, zobj); IF_GET_DOUBLE("maxdistance", php_cluster->cluster->maxdistance) else IF_GET_DOUBLE("buffer", php_cluster->cluster->buffer) else IF_GET_STRING("region", php_cluster->cluster->region) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(clusterObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_cluster_object *php_cluster; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, zobj); IF_SET_DOUBLE("maxdistance", php_cluster->cluster->maxdistance, value) else IF_SET_DOUBLE("buffer", php_cluster->cluster->buffer, value) else IF_SET_STRING("region", php_cluster->cluster->region, value) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int updateFromString(string snippet) Update a cluster from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(clusterObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_cluster_object *php_cluster; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, zobj); status = clusterObj_updateFromString(php_cluster->cluster, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the cluster object to string. */ PHP_METHOD(clusterObj, convertToString) { zval *zobj = getThis(); php_cluster_object *php_cluster; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, zobj); value = clusterObj_convertToString(php_cluster->cluster); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setGroup(string group) Set the group expression string. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(clusterObj, setGroup) { char *group = NULL; long group_len = 0; zval *zobj = getThis(); php_cluster_object *php_cluster; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &group, &group_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, zobj); if ((status = clusterObj_setGroup(php_cluster->cluster, group)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string cluster.getGroupString() Return the cluster's group expression. Returns NULL on error. */ PHP_METHOD(clusterObj, getGroupString) { zval *zobj = getThis(); char *value = NULL; php_cluster_object *php_cluster; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, zobj); value = clusterObj_getGroupString(php_cluster->cluster); if (value == NULL) { RETURN_NULL(); } MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setFilter(string filter) Set the filter expression string. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(clusterObj, setFilter) { char *filter = NULL; long filter_len = 0; zval *zobj = getThis(); php_cluster_object *php_cluster; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filter, &filter_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, zobj); if ((status = clusterObj_setFilter(php_cluster->cluster, filter)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string cluster.getFilterString() Return the cluster's filter expression. Returns NULL on error. */ PHP_METHOD(clusterObj, getFilterString) { zval *zobj = getThis(); char *value = NULL; php_cluster_object *php_cluster; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, zobj); value = clusterObj_getFilterString(php_cluster->cluster); if (value == NULL) { RETURN_NULL(); } MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ zend_function_entry cluster_functions[] = { PHP_ME(clusterObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(clusterObj, __get, cluster___get_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, __set, cluster___set_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, updateFromString, cluster_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, setGroup, cluster_setGroup_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, getGroupString, NULL, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, setFilter, cluster_setFilter_args, ZEND_ACC_PUBLIC) PHP_ME(clusterObj, getFilterString, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_cluster(clusterObj *cluster, parent_object parent, zval *return_value TSRMLS_DC) { php_cluster_object * php_cluster; object_init_ex(return_value, mapscript_ce_cluster); php_cluster = MAPSCRIPT_OBJ_P(php_cluster_object, return_value); php_cluster->cluster = cluster; if (ZVAL_NOT_UNDEF(parent.val)) php_cluster->is_ref = 1; php_cluster->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_cluster_create_object(zend_class_entry *ce TSRMLS_DC) { php_cluster_object *php_cluster; php_cluster = ecalloc(1, sizeof(*php_cluster) + zend_object_properties_size(ce)); zend_object_std_init(&php_cluster->zobj, ce TSRMLS_CC); object_properties_init(&php_cluster->zobj, ce); php_cluster->zobj.handlers = &mapscript_cluster_object_handlers; MAPSCRIPT_INIT_PARENT(php_cluster->parent); return &php_cluster->zobj; } static void mapscript_cluster_free_object(zend_object *object) { php_cluster_object *php_cluster; php_cluster = (php_cluster_object *)((char *)object - XtOffsetOf(php_cluster_object, zobj)); MAPSCRIPT_FREE_PARENT(php_cluster->parent); /* We don't need to free the clusterObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(cluster) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "clusterObj", cluster_functions); mapscript_ce_cluster = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_cluster->create_object = mapscript_cluster_create_object; mapscript_ce_cluster->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_cluster_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_cluster_object_handlers)); mapscript_cluster_object_handlers.free_obj = mapscript_cluster_free_object; mapscript_cluster_object_handlers.offset = XtOffsetOf(php_cluster_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_cluster_object_destroy(void *object TSRMLS_DC) { php_cluster_object *php_cluster = (php_cluster_object *)object; MAPSCRIPT_FREE_OBJECT(php_cluster); MAPSCRIPT_FREE_PARENT(php_cluster->parent); /* We don't need to free the clusterObj */ efree(object); } static zend_object_value mapscript_cluster_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_cluster_object *php_cluster; MAPSCRIPT_ALLOC_OBJECT(php_cluster, php_cluster_object); retval = mapscript_object_new(&php_cluster->std, ce, &mapscript_cluster_object_destroy TSRMLS_CC); php_cluster->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_cluster->parent) return retval; } PHP_MINIT_FUNCTION(cluster) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("clusterObj", cluster_functions, mapscript_ce_cluster, mapscript_cluster_object_new); mapscript_ce_cluster->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/color.c000066400000000000000000000240531357574274700176350ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_color; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_color_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(color___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(color___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(color_setRGB_args, 0, 0, 3) ZEND_ARG_INFO(0, red) ZEND_ARG_INFO(0, green) ZEND_ARG_INFO(0, blue) ZEND_ARG_INFO(0, alpha) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(color_setHex_args, 0, 0, 1) ZEND_ARG_INFO(0, rgba) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(color_toHex_args, 0, 0, 0) ZEND_END_ARG_INFO() /* {{{ proto void __construct() colorObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(colorObj, __construct) { mapscript_throw_exception("colorObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(colorObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_color_object *php_color; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_color = MAPSCRIPT_OBJ_P(php_color_object, zobj); IF_GET_LONG("red", php_color->color->red) else IF_GET_LONG("green", php_color->color->green) else IF_GET_LONG("blue", php_color->color->blue) else IF_GET_LONG("alpha", php_color->color->alpha) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(colorObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_color_object *php_color; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_color = MAPSCRIPT_OBJ_P(php_color_object, zobj); IF_SET_COLOR("red", php_color->color->red, value) else IF_SET_COLOR("green", php_color->color->green, value) else IF_SET_COLOR("blue", php_color->color->blue, value) else IF_SET_COLOR("alpha", php_color->color->alpha, value) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int color.setRGB(int R, int G, int B, int A = 255) Set new RGB color. */ PHP_METHOD(colorObj, setRGB) { zval *zobj = getThis(); long red, green, blue, alpha = 255; php_color_object *php_color; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll|l", &red, &green, &blue, &alpha) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_color = MAPSCRIPT_OBJ_P(php_color_object, zobj); MS_INIT_COLOR(*(php_color->color), red, green, blue, alpha); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int color.setHex(string hex) Set new RGB(A) color from hex string. */ PHP_METHOD(colorObj, setHex) { zval *zobj = getThis(); char *hex; long hex_len = 0, red, green, blue, alpha = 255; php_color_object *php_color; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &hex, &hex_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((hex_len == 7 || hex_len == 9) && hex[0] == '#') { red = msHexToInt(hex + 1); green = msHexToInt(hex + 3); blue = msHexToInt(hex + 5); if (hex_len == 9) { alpha = msHexToInt(hex + 7); } if (red > 255 || green > 255 || blue > 255 || alpha > 255) { mapscript_throw_exception("Invalid color index." TSRMLS_CC); RETURN_LONG(MS_FAILURE); } php_color = MAPSCRIPT_OBJ_P(php_color_object, zobj); MS_INIT_COLOR(*(php_color->color), red, green, blue, alpha); RETURN_LONG(MS_SUCCESS); } else { mapscript_throw_exception("Invalid hex color string." TSRMLS_CC); RETURN_LONG(MS_FAILURE); } } /* }}} */ /* {{{ proto string color.toHex() Get hex string #rrggbb[aa]. */ PHP_METHOD(colorObj, toHex) { char *hex; zval *zobj = getThis(); php_color_object *php_color; colorObj *color; php_color = MAPSCRIPT_OBJ_P(php_color_object, zobj); color = php_color->color; if (color->red < 0 || color->green < 0 || color->blue < 0) { mapscript_throw_exception("Can't express invalid color as hex." TSRMLS_CC); return; } if (color->alpha == 255) { hex = msSmallMalloc(8); snprintf(hex, 8, "#%02x%02x%02x", color->red, color->green, color->blue); } else if (color->alpha >= 0) { hex = msSmallMalloc(10); snprintf(hex, 10, "#%02x%02x%02x%02x", color->red, color->green, color->blue, color->alpha); } else { mapscript_throw_exception("Can't express color with invalid alpha as hex." TSRMLS_CC); return; } MAPSCRIPT_RETURN_STRINGL(hex, strlen(hex), 0); } /* }}} */ zend_function_entry color_functions[] = { PHP_ME(colorObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(colorObj, __get, color___get_args, ZEND_ACC_PUBLIC) PHP_ME(colorObj, __set, color___set_args, ZEND_ACC_PUBLIC) PHP_ME(colorObj, setRGB, color_setRGB_args, ZEND_ACC_PUBLIC) PHP_ME(colorObj, setHex, color_setHex_args, ZEND_ACC_PUBLIC) PHP_ME(colorObj, toHex, color_toHex_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_color(colorObj *color, parent_object parent, zval *return_value TSRMLS_DC) { php_color_object * php_color; object_init_ex(return_value, mapscript_ce_color); php_color = MAPSCRIPT_OBJ_P(php_color_object, return_value); php_color->color = color; php_color->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_color_create_object(zend_class_entry *ce TSRMLS_DC) { php_color_object *php_color; php_color = ecalloc(1, sizeof(*php_color) + zend_object_properties_size(ce)); zend_object_std_init(&php_color->zobj, ce TSRMLS_CC); object_properties_init(&php_color->zobj, ce); php_color->zobj.handlers = &mapscript_color_object_handlers; MAPSCRIPT_INIT_PARENT(php_color->parent); return &php_color->zobj; } static void mapscript_color_free_object(zend_object *object) { php_color_object *php_color; php_color = (php_color_object *)((char *)object - XtOffsetOf(php_color_object, zobj)); MAPSCRIPT_FREE_PARENT(php_color->parent); /* We don't need to free the colorObj, the mapObj will do it */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(color) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "colorObj", color_functions); mapscript_ce_color = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_color->create_object = mapscript_color_create_object; mapscript_ce_color->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_color_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_color_object_handlers)); mapscript_color_object_handlers.free_obj = mapscript_color_free_object; mapscript_color_object_handlers.offset = XtOffsetOf(php_color_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_color_object_destroy(void *object TSRMLS_DC) { php_color_object *php_color = (php_color_object *)object; MAPSCRIPT_FREE_OBJECT(php_color); MAPSCRIPT_FREE_PARENT(php_color->parent); /* We don't need to free the colorObj, the mapObj will do it */ efree(object); } static zend_object_value mapscript_color_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_color_object *php_color; MAPSCRIPT_ALLOC_OBJECT(php_color, php_color_object); retval = mapscript_object_new(&php_color->std, ce, &mapscript_color_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_color->parent); return retval; } PHP_MINIT_FUNCTION(color) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("colorObj", color_functions, mapscript_ce_color, mapscript_color_object_new); mapscript_ce_color->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/error.c000066400000000000000000000203061357574274700176450ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" #if PHP_VERSION_ID >= 50625 && PHP_VERSION_ID < 70000 #undef ZVAL_STRING #define ZVAL_STRING(z, s, duplicate) do { \ const char *__s=(s); \ zval *__z = (z); \ Z_STRLEN_P(__z) = strlen(__s); \ Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\ Z_TYPE_P(__z) = IS_STRING; \ } while (0) #endif zend_class_entry *mapscript_ce_error; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_error_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(error___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(error___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto error __construct() errorObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(errorObj, __construct) { mapscript_throw_exception("errorObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(errorObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); /* php_error is in PHP7 defined in php.h, so we use php_errobj instead */ php_error_object *php_errobj; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_errobj = MAPSCRIPT_OBJ_P(php_error_object, zobj); IF_GET_LONG("code", php_errobj->error->code) else IF_GET_STRING("routine", php_errobj->error->routine) else IF_GET_STRING("message", php_errobj->error->message) else IF_GET_LONG("isreported", php_errobj->error->isreported) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(errorObj, __set) { char *property; long property_len = 0; zval *value; /* zval *zobj = getThis(); */ /* php_error_object *php_errobj; */ PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); /* php_errobj = MAPSCRIPT_OBJ_P(php_error_object, zobj); */ if ( (STRING_EQUAL("code", property)) || (STRING_EQUAL("routine", property)) || (STRING_EQUAL("isreported", property)) || (STRING_EQUAL("message", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int error.next() Returns a ref to the next errorObj in the list, or NULL if we reached the last one */ PHP_METHOD(errorObj, next) { zval *zobj = getThis(); php_error_object *php_errobj; errorObj *error = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_errobj = MAPSCRIPT_OBJ_P(php_error_object, zobj); if (php_errobj->error->next == NULL) RETURN_NULL(); /* Make sure 'self' is still valid. It may have been deleted by * msResetErrorList() */ error = msGetErrorObj(); while(error != php_errobj->error) { if (error->next == NULL) { mapscript_throw_exception("Trying to access an errorObj that has expired." TSRMLS_CC); return; } error = error->next; } php_errobj->error = php_errobj->error->next; *return_value = *zobj; zval_copy_ctor(return_value); INIT_PZVAL(return_value); } /* }}} */ zend_function_entry error_functions[] = { PHP_ME(errorObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(errorObj, __get, error___get_args, ZEND_ACC_PUBLIC) PHP_ME(errorObj, __set, error___set_args, ZEND_ACC_PUBLIC) PHP_ME(errorObj, next, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_error(errorObj *error, zval *return_value TSRMLS_DC) { php_error_object * php_errobj; object_init_ex(return_value, mapscript_ce_error); php_errobj = MAPSCRIPT_OBJ_P(php_error_object, return_value); php_errobj->error = error; } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_error_create_object(zend_class_entry *ce TSRMLS_DC) { php_error_object *php_errobj; php_errobj = ecalloc(1, sizeof(*php_errobj) + zend_object_properties_size(ce)); zend_object_std_init(&php_errobj->zobj, ce TSRMLS_CC); object_properties_init(&php_errobj->zobj, ce); php_errobj->zobj.handlers = &mapscript_error_object_handlers; return &php_errobj->zobj; } /* static void mapscript_error_free_object(zend_object *object) { php_error_object *php_errobj; php_errobj = (php_error_object *)((char *)object - XtOffsetOf(php_error_object, zobj)); zend_object_std_dtor(object); } */ PHP_MINIT_FUNCTION(error) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "errorObj", error_functions); mapscript_ce_error = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_error->create_object = mapscript_error_create_object; mapscript_ce_error->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_error_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_error_object_handlers)); /* mapscript_error_object_handlers.free_obj = mapscript_error_free_object; // nothing to do here -> use standard handler */ mapscript_error_object_handlers.offset = XtOffsetOf(php_error_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_error_object_destroy(void *object TSRMLS_DC) { php_error_object *php_errobj = (php_error_object *)object; MAPSCRIPT_FREE_OBJECT(php_errobj); /* We don't need to free the errorObj */ efree(object); } static zend_object_value mapscript_error_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_error_object *php_errobj; MAPSCRIPT_ALLOC_OBJECT(php_errobj, php_error_object); retval = mapscript_object_new(&php_errobj->std, ce, &mapscript_error_object_destroy TSRMLS_CC); return retval; } PHP_MINIT_FUNCTION(error) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("errorObj", error_functions, mapscript_ce_error, mapscript_error_object_new); mapscript_ce_error->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/examples/000077500000000000000000000000001357574274700201655ustar00rootroot00000000000000mapserver-7.4.3/mapscript/php/examples/phpinfo_mapscript.phtml000066400000000000000000000007531357574274700247650ustar00rootroot00000000000000 mapserver-7.4.3/mapscript/php/examples/test_draw_legend_icon.phtml000066400000000000000000000035061357574274700255610ustar00rootroot00000000000000

PHP/MapScript module test

numlayers; // phpinfo(); // // RENDER MAIN MAP // // Note: If you get errors with the saveWebImage() call below, then make sure // that the directory specified by IMAGEPATH in the .MAP file exists and is // writable by the httpd user. // $img = $map->draw(); $url = $img->saveWebImage(); printf("\n", $url, $map->width, $map->height); // // LEGEND // $img = $map->drawLegend(); $url = $img->saveWebImage(); printf("

Draw into one picture.
\n", $url); // Draw all legend icon from all class in all layers printf("

Draw each icon seperatly.
"); printf(""); for ($i=0; $i<$map->numlayers; $i++) { $layer = $map->getLayer($i); if ($layer->status != MS_OFF && $layer->type != MS_LAYER_QUERY) for ($j=0; $j<$layer->numclasses; $j++) { $myClass = $layer->GetClass($j); $img = $myClass->createLegendIcon($map->keysizex, $map->keysizey); $url = $img->saveWebImage(); printf("", $url, $myClass->name); } } printf("
%s
"); // // SCALE BAR // $img = $map->drawScaleBar(); $url = $img->saveWebImage(); printf("

\n", $url); ?> mapserver-7.4.3/mapscript/php/examples/test_draw_map.phtml000066400000000000000000000022751357574274700240720ustar00rootroot00000000000000

PHP/MapScript module test

numlayers; // phpinfo(); // // RENDER MAIN MAP // // Note: If you get errors with the saveWebImage() call below, then make sure // that the directory specified by IMAGEPATH in the .MAP file exists and is // writable by the httpd user. // $img = $map->draw(); $url = $img->saveWebImage(); printf("\n", $url, $map->width, $map->height); // // LEGEND // $img = $map->drawLegend(); $url = $img->saveWebImage(); printf("

\n", $url); // // SCALE BAR // $img = $map->drawScaleBar(); $url = $img->saveWebImage(); printf("

\n", $url); ?> mapserver-7.4.3/mapscript/php/examples/test_layer_mask.phtml000066400000000000000000000056571357574274700244360ustar00rootroot00000000000000

PHP/MapScript layer mask test

SelectOutputFormat("PNG"); //////// // Draw the base layers into an imageObj $img1 = $map->prepareimage(); $layer = $map->getLayerByName("bathymetry"); $layer->set("status", 1); $layer->draw($img1); //$img = $map->draw(); $url = $img1->saveWebImage(); echo "

Draw the base layers into an image...

\n"; printf("\n", $url, $map->width, $map->height); ////////////// // Use the parks layer as a mask... we only want to see the base layers // through the area of the park polygons and the rest should be light grey. // Start by creating a new image ... $img2 = $map->prepareimage(); // ... and we'll use a rectObj to draw the opaque mask background $rect = ms_newRectObj(); $rect->setExtent(0, 0, $map->width, $map->height); // We need to create a temporary layer and class to use in drawing the // filled rectangle that will be the opaque part of the mask. $tmplayer = ms_newLayerObj($map); $tmplayer->set("type", MS_LAYER_POLYGON); $tmplayer->set("status", 1); $tmplayer->set("transform", MS_FALSE); $tmpclass = ms_newClassObj($tmplayer); $tmpstyle = ms_newStyleObj($tmpclass); $tmpstyle->color->setRGB(222,222,222); $rect->draw($map, $tmplayer, $img2, 0, ""); // Draw rect with class 0 // Now fetch the park layer and change its only class to use color index 0 // which is the transparent background color... so the parks polygons will // create transparent holes in the mask $layer = $map->getLayerByName("park"); $layer->set("status", 1); $class = $layer->getClass(0); $style = $class->getStyle(0); $style->color->setRGB(12,12,12); $style->outlinecolor->setRGB(12,12,12); $layer->draw($img2); $url = $img2->saveWebImage(); echo "

Draw the mask into another image...

\n"; printf("\n", $url, $map->width, $map->height); //////// // Last step... combine the two images using pasteImage() // echo "

And combine the two with pasteImage()... you see the base layer through the holes in the mask...

\n"; $img1->pasteImage($img2, 0x0c0c0c); $url = $img1->saveWebImage(); printf("\n", $url, $map->width, $map->height); ?> mapserver-7.4.3/mapscript/php/examples/test_writeshape.phtml000066400000000000000000000025431357574274700244510ustar00rootroot00000000000000addXY($x, $y); $oShp->add( $oLine ); $shpFile->addShape($oShp); // Write attribute record dbase_add_record($dbfFile, array($programId)); } $shpFname = "/tmp/shptest"; $shpFile = ms_newShapeFileObj( $shpFname, MS_SHP_POINT); $dbfFile = dbase_create( $shpFname.".dbf", array(array("PROG_ID", "N", 5, 0))); createPoint( 12, 34, 111); createPoint( 22, 14, 222); createPoint( 10, 20, 333); echo "Shapes Created.
"; //---------------------------------------------------------- // done... cleanup //---------------------------------------------------------- $shpFile->free(); echo "Shape File ($shpFname) closed.
"; dbase_close($dbfFile); echo "Dbase file closed.
"; ?> mapserver-7.4.3/mapscript/php/grid.c000066400000000000000000000221141357574274700174400ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_grid; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_grid_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(grid___construct_args, 0, 1, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(grid___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(grid___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto void __construct(layerObj layer) Create a new intance of gridObj. */ PHP_METHOD(gridObj, __construct) { zval *zlayer; php_layer_object *php_layer; php_grid_object *php_grid, *php_old_grid; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zlayer, mapscript_ce_layer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_grid = MAPSCRIPT_OBJ_P(php_grid_object, getThis()); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); php_layer->layer->connectiontype = MS_GRATICULE; if (php_layer->layer->layerinfo != NULL) free(php_layer->layer->layerinfo); php_layer->layer->layerinfo = (graticuleObj *)malloc( sizeof( graticuleObj ) ); initGrid((graticuleObj *)php_layer->layer->layerinfo); php_grid->grid = (graticuleObj *)php_layer->layer->layerinfo; if (ZVAL_NOT_UNDEF(php_layer->grid) && (MAPSCRIPT_TYPE(php_layer->grid) == IS_OBJECT)) { php_old_grid = MAPSCRIPT_OBJ(php_grid_object, php_layer->grid); php_old_grid->parent.child_ptr = NULL; #if PHP_VERSION_ID < 70000 zend_objects_store_del_ref(php_layer->grid TSRMLS_CC); #else /* Z_SET_REFCOUNT(php_layer->grid, 0); _zval_dtor_func_for_ptr(Z_COUNTED(php_layer->grid)); Z_UNDEF(&php_layer->grid); */ MAPSCRIPT_DELREF(php_layer->grid); #endif } MAKE_STD_ZVAL(php_layer->grid); MAPSCRIPT_MAKE_PARENT(zlayer, &php_layer->grid); #if PHP_VERSION_ID < 70000 mapscript_create_grid((graticuleObj *)(php_layer->layer->layerinfo), parent, php_layer->grid TSRMLS_CC); return_value_ptr = &php_layer->grid; #else mapscript_create_grid((graticuleObj *)(php_layer->layer->layerinfo), parent, &php_layer->grid TSRMLS_CC); return_value = &php_layer->grid; #endif } /* }}} */ PHP_METHOD(gridObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_grid_object *php_grid; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_grid = MAPSCRIPT_OBJ_P(php_grid_object, zobj); IF_GET_DOUBLE("minsubdivide", php_grid->grid->minsubdivides) else IF_GET_DOUBLE("maxsubdivide", php_grid->grid->maxsubdivides) else IF_GET_DOUBLE("minarcs", php_grid->grid->minarcs) else IF_GET_DOUBLE("maxarcs", php_grid->grid->maxarcs) else IF_GET_DOUBLE("mininterval", php_grid->grid->minincrement) else IF_GET_DOUBLE("maxinterval", php_grid->grid->maxincrement) else IF_GET_STRING("labelformat", php_grid->grid->labelformat) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(gridObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_grid_object *php_grid; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_grid = MAPSCRIPT_OBJ_P(php_grid_object, zobj); IF_SET_DOUBLE("minsubdivide", php_grid->grid->minsubdivides, value) else IF_SET_DOUBLE("maxsubdivide", php_grid->grid->maxsubdivides, value) else IF_SET_DOUBLE("minarcs", php_grid->grid->minarcs, value) else IF_SET_DOUBLE("maxarcs", php_grid->grid->maxarcs, value) else IF_SET_DOUBLE("mininterval", php_grid->grid->minincrement, value) else IF_SET_DOUBLE("maxinterval", php_grid->grid->maxincrement, value) else IF_SET_STRING("labelformat", php_grid->grid->labelformat, value) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } zend_function_entry grid_functions[] = { PHP_ME(gridObj, __construct, grid___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(gridObj, __get, grid___get_args, ZEND_ACC_PUBLIC) PHP_ME(gridObj, __set, grid___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(gridObj, set, __set, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_grid(graticuleObj *grid, parent_object parent, zval *return_value TSRMLS_DC) { php_grid_object * php_grid; object_init_ex(return_value, mapscript_ce_grid); php_grid = MAPSCRIPT_OBJ_P(php_grid_object, return_value); php_grid->grid = grid; php_grid->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_grid_create_object(zend_class_entry *ce TSRMLS_DC) { php_grid_object *php_grid; php_grid = ecalloc(1, sizeof(*php_grid) + zend_object_properties_size(ce)); zend_object_std_init(&php_grid->zobj, ce TSRMLS_CC); object_properties_init(&php_grid->zobj, ce); php_grid->zobj.handlers = &mapscript_grid_object_handlers; MAPSCRIPT_INIT_PARENT(php_grid->parent); return &php_grid->zobj; } static void mapscript_grid_free_object(zend_object *object) { php_grid_object *php_grid; php_grid = (php_grid_object *)((char *)object - XtOffsetOf(php_grid_object, zobj)); MAPSCRIPT_FREE_PARENT(php_grid->parent); /* We don't need to free the gridObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(grid) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "gridObj", grid_functions); mapscript_ce_grid = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_grid->create_object = mapscript_grid_create_object; mapscript_ce_grid->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_grid_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_grid_object_handlers)); mapscript_grid_object_handlers.free_obj = mapscript_grid_free_object; mapscript_grid_object_handlers.offset = XtOffsetOf(php_grid_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_grid_object_destroy(void *object TSRMLS_DC) { php_grid_object *php_grid = (php_grid_object *)object; MAPSCRIPT_FREE_OBJECT(php_grid); MAPSCRIPT_FREE_PARENT(php_grid->parent); /* We don't need to free the gridObj */ efree(object); } static zend_object_value mapscript_grid_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_grid_object *php_grid; MAPSCRIPT_ALLOC_OBJECT(php_grid, php_grid_object); retval = mapscript_object_new(&php_grid->std, ce, &mapscript_grid_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_grid->parent); return retval; } PHP_MINIT_FUNCTION(grid) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("gridObj", grid_functions, mapscript_ce_grid, mapscript_grid_object_new); mapscript_ce_grid->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/hashtable.c000066400000000000000000000261251357574274700204540ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_hashtable; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_hashtable_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(hashtable___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable_get_args, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable_set_args, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable_remove_args, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(hashtable_nextkey_args, 0, 0, 1) ZEND_ARG_INFO(0, previousKey) ZEND_END_ARG_INFO() /* {{{ proto hashtable __construct() Create a new hashtableObj instance. */ PHP_METHOD(hashtableObj, __construct) { mapscript_throw_exception("hashTableObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(hashtableObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = MAPSCRIPT_OBJ_P(php_hashtable_object, zobj); IF_GET_LONG("numitems", php_hashtable->hashtable->numitems) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(hashtableObj, __set) { char *property; long property_len = 0; zval *value; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ( (STRING_EQUAL("numitems", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int hashtable.get(string key) Get a value from item by its key. Returns empty string if not found. */ PHP_METHOD(hashtableObj, get) { char *key; long key_len = 0; zval *zobj = getThis(); const char *value = NULL; php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = MAPSCRIPT_OBJ_P(php_hashtable_object, zobj); value = hashTableObj_get(php_hashtable->hashtable, key); if (value == NULL) { MAPSCRIPT_RETURN_STRING("",1); } MAPSCRIPT_RETURN_STRING((char *)value, 1); } /* }}} */ /* {{{ proto int hashtable.set(string key, string value) Set a hash item given key and value. Returns MS_FAILURE on error. */ PHP_METHOD(hashtableObj, set) { char *key, *value; long key_len, value_len = 0; zval *zobj = getThis(); int status = MS_FAILURE; php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = MAPSCRIPT_OBJ_P(php_hashtable_object, zobj); if ((status = hashTableObj_set(php_hashtable->hashtable, key, value)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int hashtable.remove(string key) Remove one item from hash table. Returns MS_FAILURE on error. */ PHP_METHOD(hashtableObj, remove) { char *key; long key_len = 0; zval *zobj = getThis(); int status = MS_FAILURE; php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = MAPSCRIPT_OBJ_P(php_hashtable_object, zobj); if ((status = hashTableObj_remove(php_hashtable->hashtable, key)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int hashtable.clear() Clear all items in hash table (to NULL). */ PHP_METHOD(hashtableObj, clear) { zval *zobj = getThis(); php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = MAPSCRIPT_OBJ_P(php_hashtable_object, zobj); hashTableObj_clear(php_hashtable->hashtable); } /* }}} */ /* {{{ proto int hashtable.nextkey(string previousKey) Return the next key or first key if previousKey == NULL. Returns NULL if no item is in the hashTable or end of hashTable reached */ PHP_METHOD(hashtableObj, nextKey) { char *key; long key_len = 0; zval *zobj = getThis(); const char *value = NULL; php_hashtable_object *php_hashtable; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &key, &key_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_hashtable = MAPSCRIPT_OBJ_P(php_hashtable_object, zobj); value = hashTableObj_nextKey(php_hashtable->hashtable, key); if (value == NULL) RETURN_NULL(); MAPSCRIPT_RETURN_STRING(value, 1); } /* }}} */ zend_function_entry hashtable_functions[] = { PHP_ME(hashtableObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(hashtableObj, __get, hashtable___get_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, __set, hashtable___set_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, get, hashtable_get_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, set, hashtable_set_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, remove, hashtable_remove_args, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, clear, NULL, ZEND_ACC_PUBLIC) PHP_ME(hashtableObj, nextKey, hashtable_nextkey_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_hashtable(hashTableObj *hashtable, parent_object parent, zval *return_value TSRMLS_DC) { php_hashtable_object * php_hashtable; object_init_ex(return_value, mapscript_ce_hashtable); php_hashtable = MAPSCRIPT_OBJ_P(php_hashtable_object, return_value); php_hashtable->hashtable = hashtable; php_hashtable->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_hashtable_create_object(zend_class_entry *ce TSRMLS_DC) { php_hashtable_object *php_hashtable; php_hashtable = ecalloc(1, sizeof(*php_hashtable) + zend_object_properties_size(ce)); zend_object_std_init(&php_hashtable->zobj, ce TSRMLS_CC); object_properties_init(&php_hashtable->zobj, ce); php_hashtable->zobj.handlers = &mapscript_hashtable_object_handlers; MAPSCRIPT_INIT_PARENT(php_hashtable->parent); return &php_hashtable->zobj; } static void mapscript_hashtable_free_object(zend_object *object) { php_hashtable_object *php_hashtable; php_hashtable = (php_hashtable_object *)((char *)object - XtOffsetOf(php_hashtable_object, zobj)); MAPSCRIPT_FREE_PARENT(php_hashtable->parent); /* We don't need to free the hashTableObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(hashtable) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "hashTableObj", hashtable_functions); mapscript_ce_hashtable = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_hashtable->create_object = mapscript_hashtable_create_object; mapscript_ce_hashtable->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_hashtable_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_hashtable_object_handlers)); mapscript_hashtable_object_handlers.free_obj = mapscript_hashtable_free_object; mapscript_hashtable_object_handlers.offset = XtOffsetOf(php_hashtable_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_hashtable_object_destroy(void *object TSRMLS_DC) { php_hashtable_object *php_hashtable = (php_hashtable_object *)object; MAPSCRIPT_FREE_OBJECT(php_hashtable); MAPSCRIPT_FREE_PARENT(php_hashtable->parent); /* We don't need to free the hashTableObj */ efree(object); } static zend_object_value mapscript_hashtable_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_hashtable_object *php_hashtable; MAPSCRIPT_ALLOC_OBJECT(php_hashtable, php_hashtable_object); retval = mapscript_object_new(&php_hashtable->std, ce, &mapscript_hashtable_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_hashtable->parent); return retval; } PHP_MINIT_FUNCTION(hashtable) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("hashTableObj", hashtable_functions, mapscript_ce_hashtable, mapscript_hashtable_object_new); mapscript_ce_hashtable->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/image.c000066400000000000000000000347061357574274700176070ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" #include "ext/standard/head.h" #include "main/php_output.h" zend_class_entry *mapscript_ce_image; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_image_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(image___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(image___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(image_pasteImage_args, 0, 0, 2) ZEND_ARG_INFO(0, srcImg) ZEND_ARG_INFO(0, transparentColorHex) ZEND_ARG_INFO(0, dstX) ZEND_ARG_INFO(0, dstY) ZEND_ARG_INFO(0, angle) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(image_saveImage_args, 0, 0, 2) ZEND_ARG_INFO(0, filename) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_END_ARG_INFO() /* {{{ proto image __construct() imageObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(imageObj, __construct) { mapscript_throw_exception("imageObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(imageObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_image = MAPSCRIPT_OBJ_P(php_image_object, zobj); IF_GET_LONG("width", php_image->image->width) else IF_GET_LONG("height", php_image->image->height) else IF_GET_LONG("resolution", php_image->image->resolution) else IF_GET_LONG("resolutionfactor", php_image->image->resolutionfactor) else IF_GET_STRING("imagepath", php_image->image->imagepath) else IF_GET_STRING("imageurl", php_image->image->imageurl) else IF_GET_STRING("imagetype", php_image->image->format->name) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(imageObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_image = MAPSCRIPT_OBJ_P(php_image_object, zobj); IF_SET_STRING("imagepath", php_image->image->imagepath, value) else IF_SET_STRING("imageurl", php_image->image->imageurl, value) else IF_SET_STRING("imagetype", php_image->image->format->name, value) else if ( (STRING_EQUAL("width", property)) || (STRING_EQUAL("resolution", property)) || (STRING_EQUAL("resolutionfactor", property)) || (STRING_EQUAL("height", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int saveWebImage() Writes image to temp directory. Returns image URL. */ PHP_METHOD(imageObj, saveWebImage) { zval *zobj = getThis(); php_image_object *php_image; char *imageFile = NULL; char *imageFilename = NULL; char path[MS_MAXPATHLEN]; char *imageUrlFull = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_image = MAPSCRIPT_OBJ_P(php_image_object, zobj); imageFilename = msTmpFilename(php_image->image->format->extension); imageFile = msBuildPath(path, php_image->image->imagepath, imageFilename); if (msSaveImage(NULL, php_image->image, imageFile) != MS_SUCCESS) { mapscript_throw_mapserver_exception("Failed writing image to %s" TSRMLS_CC, imageFile); return; } imageUrlFull = msBuildPath(path, php_image->image->imageurl, imageFilename); msFree(imageFilename); MAPSCRIPT_RETURN_STRING(imageUrlFull, 1); } /* }}} */ /* {{{ proto void pasteImage(imageObj Src, int transparentColor [[,int dstx, int dsty], int angle]) Pastes another imageObj on top of this imageObj. transparentColor is the color (0xrrggbb) from srcImg that should be considered transparent. Pass transparentColor=-1 if you don't want any transparent color. If optional dstx,dsty are provided then they define the position where the image should be copied (dstx,dsty = top-left corner position). The optional angle is a value between 0 and 360 degrees to rotate the source image counterclockwise. Note that if a rotation is requested then the dstx and dsty coordinates specify the CENTER of the destination area. NOTE : this function only works for 8 bits GD images. */ PHP_METHOD(imageObj, pasteImage) { long transparent=-1, dstx=0, dsty=0, angle=0; zval *zimage; zval *zobj = getThis(); php_image_object *php_image, *php_imageSrc; /*int oldTransparentColor, newTransparentColor=-1, r, g, b;*/ rendererVTableObj *renderer = NULL; rasterBufferObj rb; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|lll", &zimage, mapscript_ce_image, &transparent, &dstx, &dsty, &angle) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if (ZEND_NUM_ARGS() == 3) mapscript_report_php_error(E_WARNING, "dstX parameter given but not dstY" TSRMLS_CC); php_image = MAPSCRIPT_OBJ_P(php_image_object, zobj); php_imageSrc = MAPSCRIPT_OBJ_P(php_image_object, zimage); if (!MS_RENDERER_PLUGIN(php_imageSrc->image->format) || !MS_RENDERER_PLUGIN(php_image->image->format)) { mapscript_throw_exception("PasteImage function should only be used with renderer plugin drivers." TSRMLS_CC); return; } renderer = MS_IMAGE_RENDERER(php_image->image); memset(&rb,0,sizeof(rasterBufferObj)); if(MS_SUCCESS != renderer->getRasterBufferHandle(php_imageSrc->image, &rb)) { mapscript_throw_exception("PasteImage failed to extract rasterbuffer handle" TSRMLS_CC); return; } if(MS_SUCCESS != renderer->mergeRasterBuffer(php_image->image, &rb, 1.0, 0, 0, dstx, dsty, rb.width, rb.height)) { mapscript_throw_exception("PasteImage failed to merge raster buffer" TSRMLS_CC); return; } /* Look for r,g,b in color table and make it transparent. * will return -1 if there is no exact match which will result in * no transparent color in the call to gdImageColorTransparent(). */ /* if (transparent != -1) { r = (transparent / 0x010000) & 0xff; g = (transparent / 0x0100) & 0xff; b = transparent & 0xff; newTransparentColor = gdImageColorExact(php_imageSrc->image->img.gd, r, g, b); } oldTransparentColor = gdImageGetTransparent(php_imageSrc->image->img.gd); gdImageColorTransparent(php_imageSrc->image->img.gd, newTransparentColor); if (!angleSet) gdImageCopy(php_image->image->img.gd, php_imageSrc->image->img.gd, dstx, dsty, 0, 0, php_imageSrc->image->img.gd->sx, php_imageSrc->image->img.gd->sy); else gdImageCopyRotated(php_image->image->img.gd, php_imageSrc->image->img.gd, dstx, dsty, 0, 0, php_imageSrc->image->img.gd->sx, php_imageSrc->image->img.gd->sy, angle); gdImageColorTransparent(php_imageSrc->image->img.gd, oldTransparentColor);*/ RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int saveImage(string filename, mapObj map) Writes image object to specifed filename. If filename is empty then write to stdout. Returns MS_FAILURE on error. Second aregument oMap is not manadatory. It is usful when saving to other formats like GTIFF to get georeference infos.*/ PHP_METHOD(imageObj, saveImage) { zval *zobj = getThis(); zval *zmap = NULL; char *filename = NULL; long filename_len = 0; php_image_object *php_image; php_map_object *php_map; int status = MS_SUCCESS; /* stdout specific vars */ int size=0; void *iptr=NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO", &filename, &filename_len, &zmap, mapscript_ce_map) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_image = MAPSCRIPT_OBJ_P(php_image_object, zobj); if (zmap) php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); if(filename_len > 0) { if ((status = msSaveImage((zmap ? php_map->map:NULL), php_image->image, filename) != MS_SUCCESS)) { mapscript_throw_mapserver_exception("Failed writing image to %s" TSRMLS_CC, filename); return; } RETURN_LONG(status); } /* no filename - read stdout */ /* if there is no output buffer active, set the header */ //handle changes in PHP 5.4.x #if PHP_VERSION_ID < 50399 if (OG(ob_nesting_level)<=0) { php_header(TSRMLS_C); } #else if (php_output_get_level(TSRMLS_C)<=0) { php_header(TSRMLS_C); } #endif if (MS_RENDERER_PLUGIN(php_image->image->format)) { iptr = (void *)msSaveImageBuffer(php_image->image, &size, php_image->image->format); } else if (php_image->image->format->name && (strcasecmp(php_image->image->format->name, "imagemap")==0)) { iptr = php_image->image->img.imagemap; size = strlen(php_image->image->img.imagemap); } if (size == 0) { mapscript_throw_mapserver_exception("Failed writing image to stdout" TSRMLS_CC); return; } else { php_write(iptr, size TSRMLS_CC); status = MS_SUCCESS; /* status = size; why should we return the size ?? */ msFree(iptr); } RETURN_LONG(status); } /* }}} */ zend_function_entry image_functions[] = { PHP_ME(imageObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(imageObj, __get, image___get_args, ZEND_ACC_PUBLIC) PHP_ME(imageObj, __set, image___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(imageObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(imageObj, saveWebImage, NULL, ZEND_ACC_PUBLIC) PHP_ME(imageObj, pasteImage, image_pasteImage_args, ZEND_ACC_PUBLIC) PHP_ME(imageObj, saveImage, image_saveImage_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_image(imageObj *image, zval *return_value TSRMLS_DC) { php_image_object * php_image; object_init_ex(return_value, mapscript_ce_image); php_image = MAPSCRIPT_OBJ_P(php_image_object, return_value); php_image->image = image; } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_image_create_object(zend_class_entry *ce TSRMLS_DC) { php_image_object *php_image; php_image = ecalloc(1, sizeof(*php_image) + zend_object_properties_size(ce)); zend_object_std_init(&php_image->zobj, ce TSRMLS_CC); object_properties_init(&php_image->zobj, ce); php_image->zobj.handlers = &mapscript_image_object_handlers; return &php_image->zobj; } static void mapscript_image_free_object(zend_object *object) { php_image_object *php_image; php_image = (php_image_object *)((char *)object - XtOffsetOf(php_image_object, zobj)); msFreeImage(php_image->image); zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(image) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "imageObj", image_functions); mapscript_ce_image = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_image->create_object = mapscript_image_create_object; mapscript_ce_image->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_image_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_image_object_handlers)); mapscript_image_object_handlers.free_obj = mapscript_image_free_object; mapscript_image_object_handlers.offset = XtOffsetOf(php_image_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_image_object_destroy(void *object TSRMLS_DC) { php_image_object *php_image = (php_image_object *)object; MAPSCRIPT_FREE_OBJECT(php_image); msFreeImage(php_image->image); efree(object); } static zend_object_value mapscript_image_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_image_object *php_image; MAPSCRIPT_ALLOC_OBJECT(php_image, php_image_object); retval = mapscript_object_new(&php_image->std, ce, &mapscript_image_object_destroy TSRMLS_CC); return retval; } PHP_MINIT_FUNCTION(image) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("imageObj", image_functions, mapscript_ce_image, mapscript_image_object_new); mapscript_ce_image->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/label.c000066400000000000000000000742321357574274700176020ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_label; zend_object_handlers mapscript_label_object_handlers; ZEND_BEGIN_ARG_INFO_EX(label___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_setBinding_args, 0, 0, 2) ZEND_ARG_INFO(0, labelBinding) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_getBinding_args, 0, 0, 1) ZEND_ARG_INFO(0, labelBinding) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_removeBinding_args, 0, 0, 1) ZEND_ARG_INFO(0, labelBinding) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_getStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_insertStyle_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, style, styleObj, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_removeStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_moveStyleUp_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_moveStyleDown_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_deleteStyle_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_setExpression_args, 0, 0, 1) ZEND_ARG_INFO(0, expression) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(label_setText_args, 0, 0, 1) ZEND_ARG_INFO(0, text) ZEND_END_ARG_INFO() /* {{{ proto void __construct() Create a new label instance. */ PHP_METHOD(labelObj, __construct) { php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, getThis()); if ((php_label->label = labelObj_new()) == NULL) { mapscript_throw_exception("Unable to construct labelObj." TSRMLS_CC); return; } } /* }}} */ PHP_METHOD(labelObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); IF_GET_STRING("font", php_label->label->font) else IF_GET_STRING("encoding", php_label->label->encoding) else IF_GET_LONG("type", MS_TRUETYPE) else IF_GET_LONG("shadowsizex", php_label->label->shadowsizex) else IF_GET_LONG("shadowsizey", php_label->label->shadowsizey) else IF_GET_DOUBLE("size", php_label->label->size) else IF_GET_DOUBLE("minsize", php_label->label->minsize) else IF_GET_DOUBLE("maxsize", php_label->label->maxsize) else IF_GET_DOUBLE("minscaledenom", php_label->label->minscaledenom) else IF_GET_DOUBLE("maxscaledenom", php_label->label->maxscaledenom) else IF_GET_LONG("position", php_label->label->position) else IF_GET_LONG("offsetx", php_label->label->offsetx) else IF_GET_LONG("offsety", php_label->label->offsety) else IF_GET_DOUBLE("angle", php_label->label->angle) else IF_GET_LONG("anglemode", php_label->label->anglemode) else IF_GET_LONG("buffer", php_label->label->buffer) else IF_GET_LONG("wrap", php_label->label->wrap) else IF_GET_LONG("minfeaturesize", php_label->label->minfeaturesize) else IF_GET_LONG("autominfeaturesize", php_label->label->autominfeaturesize) else IF_GET_LONG("repeatdistance", php_label->label->repeatdistance) else IF_GET_LONG("numstyles", php_label->label->numstyles) else IF_GET_LONG("mindistance", php_label->label->mindistance) else IF_GET_LONG("partials", php_label->label->partials) else IF_GET_LONG("force", php_label->label->force) else IF_GET_LONG("outlinewidth", php_label->label->outlinewidth) else IF_GET_LONG("align", php_label->label->align) else IF_GET_LONG("maxlength", php_label->label->maxlength) else IF_GET_LONG("minlength", php_label->label->minlength) else IF_GET_LONG("maxoverlapangle", php_label->label->maxoverlapangle) else IF_GET_LONG("priority", php_label->label->priority) else IF_GET_OBJECT("color", mapscript_ce_color, php_label->color, &php_label->label->color) else IF_GET_OBJECT("leader", mapscript_ce_labelleader, php_label->leader, php_label->label->leader) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_label->outlinecolor, &php_label->label->outlinecolor) else IF_GET_OBJECT("shadowcolor", mapscript_ce_color, php_label->shadowcolor, &php_label->label->shadowcolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(labelObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); IF_SET_STRING("font", php_label->label->font, value) else IF_SET_STRING("encoding", php_label->label->encoding, value) else IF_SET_LONG("shadowsizex", php_label->label->shadowsizex, value) else IF_SET_LONG("shadowsizey", php_label->label->shadowsizey, value) else IF_SET_DOUBLE("size", php_label->label->size, value) else IF_SET_DOUBLE("minsize", php_label->label->minsize, value) else IF_SET_DOUBLE("maxsize", php_label->label->maxsize, value) else IF_SET_LONG("position", php_label->label->position, value) else IF_SET_LONG("offsetx", php_label->label->offsetx, value) else IF_SET_LONG("offsety", php_label->label->offsety, value) else IF_SET_DOUBLE("angle", php_label->label->angle, value) else IF_SET_LONG("anglemode", php_label->label->anglemode, value) else IF_SET_LONG("buffer", php_label->label->buffer, value) else IF_SET_BYTE("wrap", php_label->label->wrap, value) else IF_SET_LONG("minfeaturesize", php_label->label->minfeaturesize, value) else IF_SET_LONG("autominfeaturesize", php_label->label->autominfeaturesize, value) else IF_SET_LONG("repeatdistance", php_label->label->repeatdistance, value) else IF_SET_LONG("mindistance", php_label->label->mindistance, value) else IF_SET_LONG("partials", php_label->label->partials, value) else IF_SET_LONG("force", php_label->label->force, value) else IF_SET_LONG("outlinewidth", php_label->label->outlinewidth, value) else IF_SET_LONG("align", php_label->label->align, value) else IF_SET_LONG("maxlength", php_label->label->maxlength, value) else IF_SET_LONG("minlength", php_label->label->minlength, value) else IF_SET_LONG("maxoverlapangle", php_label->label->maxoverlapangle, value) else IF_SET_LONG("priority", php_label->label->priority, value) else IF_SET_DOUBLE("maxscaledenom", php_label->label->maxscaledenom, value) else IF_SET_DOUBLE("minscaledenom", php_label->label->minscaledenom, value) else if ( (STRING_EQUAL("color", property)) || (STRING_EQUAL("outlinecolor", property)) || (STRING_EQUAL("leader", property)) || (STRING_EQUAL("shadowcolor", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if (STRING_EQUAL("numstyles", property)) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int label.updateFromString(string snippet) Update a label from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(labelObj, updateFromString) { zval *zobj = getThis(); char *snippet; long snippet_len = 0; int status = MS_FAILURE; php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); if ((status = labelObj_updateFromString(php_label->label, snippet)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the label object to string. */ PHP_METHOD(labelObj, convertToString) { zval *zobj = getThis(); php_label_object *php_label; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); value = labelObj_convertToString(php_label->label); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int label.setbinding(const bindingid, string value) Set the attribute binding for a specfiled label property. Returns MS_SUCCESS on success. */ PHP_METHOD(labelObj, setBinding) { zval *zobj = getThis(); char *value; long value_len = 0; long bindingId; php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &bindingId, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); if (bindingId < 0 || bindingId > MS_LABEL_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if (!value || strlen(value) <= 0) { mapscript_throw_exception("Invalid binding value." TSRMLS_CC); return; } if(php_label->label->bindings[bindingId].item) { msFree(php_label->label->bindings[bindingId].item); php_label->label->bindings[bindingId].index = -1; php_label->label->numbindings--; } php_label->label->bindings[bindingId].item = msStrdup(value); php_label->label->numbindings++; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int label.getbinding(const bindingid) Get the value of a attribute binding for a specfiled label property. Returns the string value if exist, else null. */ PHP_METHOD(labelObj, getBinding) { zval *zobj = getThis(); long bindingId; char *value = NULL; php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bindingId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); if (bindingId < 0 || bindingId > MS_LABEL_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if( (value = php_label->label->bindings[bindingId].item) != NULL) { MAPSCRIPT_RETURN_STRING(value, 1); } RETURN_NULL(); } /* }}} */ /* {{{ proto int label.removebinding(const bindingid) Remove attribute binding for a specfiled label property. Returns MS_SUCCESS on success. */ PHP_METHOD(labelObj, removeBinding) { zval *zobj = getThis(); long bindingId; php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bindingId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); if (bindingId < 0 || bindingId > MS_LABEL_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if(php_label->label->bindings[bindingId].item) { msFree(php_label->label->bindings[bindingId].item); php_label->label->bindings[bindingId].item = NULL; php_label->label->bindings[bindingId].index = -1; php_label->label->numbindings--; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int getstyle(int index) return the style object. */ PHP_METHOD(labelObj, getStyle) { long index; zval *zobj = getThis(); php_label_object *php_label; styleObj *style = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); if (index < 0 || index >= php_label->label->numstyles) { mapscript_throw_exception("Invalid style index." TSRMLS_CC); return; } style = php_label->label->styles[index]; MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int insertStyle(styleObj style) return MS_SUCCESS or MS_FAILURE. */ PHP_METHOD(labelObj, insertStyle) { zval *zobj = getThis(); zval *zstyle = NULL; long index = -1; php_label_object *php_label; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &zstyle, mapscript_ce_style, &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); php_style = MAPSCRIPT_OBJ_P(php_style_object, zstyle); RETURN_LONG(msInsertLabelStyle(php_label->label, php_style->style, index)); } /* }}} */ /* {{{ proto styleObj removeStyle(int index) return the styleObj removed. */ PHP_METHOD(labelObj, removeStyle) { zval *zobj = getThis(); long index; styleObj *style; php_label_object *php_label; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); style = msRemoveLabelStyle(php_label->label, index); /* Return a copy of the class object just removed */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int moveStyleUp(int index) */ PHP_METHOD(labelObj, moveStyleUp) { long index; zval *zobj = getThis(); php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); status = labelObj_moveStyleUp(php_label->label, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int moveStyleDown(int index) */ PHP_METHOD(labelObj, moveStyleDown) { long index; zval *zobj = getThis(); php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); status = labelObj_moveStyleDown(php_label->label, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int deleteStyle(int index) */ PHP_METHOD(labelObj, deleteStyle) { long index; zval *zobj = getThis(); php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); status = labelObj_deleteStyle(php_label->label, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int label.free() Free the object */ PHP_METHOD(labelObj, free) { zval *zobj = getThis(); php_label_object *php_label; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); MAPSCRIPT_DELREF(php_label->color); MAPSCRIPT_DELREF(php_label->outlinecolor); MAPSCRIPT_DELREF(php_label->shadowcolor); } /* }}} */ /* {{{ proto int setExpression(string exression) Set the expression string for a label object. */ PHP_METHOD(labelObj, setExpression) { char *expression; long expression_len; zval *zobj = getThis(); php_label_object *php_label; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &expression, &expression_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); status = labelObj_setExpression(php_label->label, expression); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string getExpressionString() Get the expression string for a label object. */ PHP_METHOD(labelObj, getExpressionString) { zval *zobj = getThis(); php_label_object *php_label; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); value = labelObj_getExpressionString(php_label->label); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int setText(string text) Set the text string for a label object. */ PHP_METHOD(labelObj, setText) { char *text; long text_len; zval *zobj = getThis(); php_label_object *php_label; php_layer_object *php_layer; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); php_layer = MAPSCRIPT_OBJ(php_layer_object, php_label->parent.val); status = labelObj_setText(php_label->label, php_layer->layer, text); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string getTextString() Get the text string for a label object. */ PHP_METHOD(labelObj, getTextString) { zval *zobj = getThis(); php_label_object *php_label; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_label = MAPSCRIPT_OBJ_P(php_label_object, zobj); value = labelObj_getTextString(php_label->label); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ zend_function_entry label_functions[] = { PHP_ME(labelObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(labelObj, __get, label___get_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, __set, label___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(labelObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelObj, updateFromString, label_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelObj, setBinding, label_setBinding_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, getBinding, label_getBinding_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, removeBinding, label_removeBinding_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, getStyle, label_getStyle_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, insertStyle, label_insertStyle_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, removeStyle, label_removeStyle_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, moveStyleUp, label_moveStyleUp_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, moveStyleDown, label_moveStyleDown_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, deleteStyle, label_deleteStyle_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, setExpression, label_setExpression_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, getExpressionString, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelObj, setText, label_setText_args, ZEND_ACC_PUBLIC) PHP_ME(labelObj, getTextString, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_label(labelObj *label, parent_object parent, zval *return_value TSRMLS_DC) { php_label_object * php_label; object_init_ex(return_value, mapscript_ce_label); php_label = MAPSCRIPT_OBJ_P(php_label_object, return_value); php_label->label = label; if(ZVAL_NOT_UNDEF(parent.val)) php_label->is_ref = 1; php_label->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_label_create_object(zend_class_entry *ce TSRMLS_DC) { php_label_object *php_label; php_label = ecalloc(1, sizeof(*php_label) + zend_object_properties_size(ce)); zend_object_std_init(&php_label->zobj, ce TSRMLS_CC); object_properties_init(&php_label->zobj, ce); php_label->zobj.handlers = &mapscript_label_object_handlers; MAPSCRIPT_INIT_PARENT(php_label->parent); php_label->is_ref = 0; ZVAL_UNDEF(&php_label->color); ZVAL_UNDEF(&php_label->outlinecolor); ZVAL_UNDEF(&php_label->shadowcolor); ZVAL_UNDEF(&php_label->leader); return &php_label->zobj; } static void mapscript_label_free_object(zend_object *object) { php_label_object *php_label; php_label = (php_label_object *)((char *)object - XtOffsetOf(php_label_object, zobj)); MAPSCRIPT_FREE_PARENT(php_label->parent); MAPSCRIPT_DELREF(php_label->color); MAPSCRIPT_DELREF(php_label->outlinecolor); MAPSCRIPT_DELREF(php_label->shadowcolor); MAPSCRIPT_DELREF(php_label->leader); if (php_label->label && !php_label->is_ref) { labelObj_destroy(php_label->label); } zend_object_std_dtor(object); } static zend_object* mapscript_label_clone_object(zval *zobj) { php_label_object *php_label_old, *php_label_new; zend_object* zobj_new; php_label_old = MAPSCRIPT_OBJ_P(php_label_object, zobj); zobj_new = mapscript_label_create_object(mapscript_ce_label); php_label_new = (php_label_object *)((char *)zobj_new - XtOffsetOf(php_label_object, zobj)); php_label_new->label = labelObj_clone(php_label_old->label); return zobj_new; } PHP_MINIT_FUNCTION(label) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "labelObj", label_functions); mapscript_ce_label = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_label->create_object = mapscript_label_create_object; mapscript_ce_label->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_label_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_label_object_handlers)); mapscript_label_object_handlers.free_obj = mapscript_label_free_object; mapscript_label_object_handlers.clone_obj = mapscript_label_clone_object; mapscript_label_object_handlers.offset = XtOffsetOf(php_label_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_label_object_destroy(void *object TSRMLS_DC) { php_label_object *php_label = (php_label_object *)object; MAPSCRIPT_FREE_OBJECT(php_label); MAPSCRIPT_FREE_PARENT(php_label->parent); MAPSCRIPT_DELREF(php_label->color); MAPSCRIPT_DELREF(php_label->outlinecolor); MAPSCRIPT_DELREF(php_label->shadowcolor); MAPSCRIPT_DELREF(php_label->leader); if (php_label->label && !php_label->is_ref) { labelObj_destroy(php_label->label); } efree(object); } static zend_object_value mapscript_label_object_new_ex(zend_class_entry *ce, php_label_object **ptr TSRMLS_DC) { zend_object_value retval; php_label_object *php_label; MAPSCRIPT_ALLOC_OBJECT(php_label, php_label_object); retval = mapscript_object_new_ex(&php_label->std, ce, &mapscript_label_object_destroy, &mapscript_label_object_handlers TSRMLS_CC); if (ptr) *ptr = php_label; php_label->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_label->parent); php_label->color = NULL; php_label->outlinecolor = NULL; php_label->shadowcolor = NULL; php_label->leader = NULL; return retval; } static zend_object_value mapscript_label_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_label_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_label_object_clone(zval *zobj TSRMLS_DC) { php_label_object *php_label_old, *php_label_new; zend_object_value new_ov; php_label_old = MAPSCRIPT_OBJ_P(php_label_object, zobj); new_ov = mapscript_label_object_new_ex(mapscript_ce_label, &php_label_new TSRMLS_CC); zend_objects_clone_members(&php_label_new->std, new_ov, &php_label_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_label_new->label = labelObj_clone(php_label_old->label); return new_ov; } PHP_MINIT_FUNCTION(label) { zend_class_entry ce; memcpy(&mapscript_label_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_label_object_handlers.clone_obj = mapscript_label_object_clone; MAPSCRIPT_REGISTER_CLASS("labelObj", label_functions, mapscript_ce_label, mapscript_label_object_new); mapscript_ce_label->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/labelcache.c000066400000000000000000000146431357574274700205660ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_labelcache; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_labelcache_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(labelcache___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(labelcache___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto labelcache __construct() labelCacheObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(labelCacheObj, __construct) { mapscript_throw_exception("labelCacheObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(labelCacheObj, __get) { mapscript_throw_exception("labelCacheObj has no property." TSRMLS_CC); } PHP_METHOD(labelCacheObj, __set) { mapscript_throw_exception("labelCacheObj has no property." TSRMLS_CC); } /* {{{ proto int labelcache->freeCache(() Free the labelcache object in the map. Returns true on success or false if an error occurs. */ PHP_METHOD(labelCacheObj, freeCache) { zval *zobj = getThis(); php_labelcache_object *php_labelcache; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_labelcache = MAPSCRIPT_OBJ_P(php_labelcache_object, zobj); labelCacheObj_freeCache(php_labelcache->labelcache); RETURN_LONG(MS_SUCCESS); } /* }}}} */ zend_function_entry labelcache_functions[] = { PHP_ME(labelCacheObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(labelCacheObj, __get, labelcache___get_args, ZEND_ACC_PUBLIC) PHP_ME(labelCacheObj, __set, labelcache___set_args, ZEND_ACC_PUBLIC) PHP_ME(labelCacheObj, freeCache, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_labelcache(labelCacheObj *labelcache, parent_object parent, zval *return_value TSRMLS_DC) { php_labelcache_object * php_labelcache; object_init_ex(return_value, mapscript_ce_labelcache); php_labelcache = MAPSCRIPT_OBJ_P(php_labelcache_object, return_value); php_labelcache->labelcache = labelcache; php_labelcache->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_labelcache_create_object(zend_class_entry *ce TSRMLS_DC) { php_labelcache_object *php_labelcache; php_labelcache = ecalloc(1, sizeof(*php_labelcache) + zend_object_properties_size(ce)); zend_object_std_init(&php_labelcache->zobj, ce TSRMLS_CC); object_properties_init(&php_labelcache->zobj, ce); php_labelcache->zobj.handlers = &mapscript_labelcache_object_handlers; MAPSCRIPT_INIT_PARENT(php_labelcache->parent); return &php_labelcache->zobj; } static void mapscript_labelcache_free_object(zend_object *object) { php_labelcache_object *php_labelcache; php_labelcache = (php_labelcache_object *)((char *)object - XtOffsetOf(php_labelcache_object, zobj)); MAPSCRIPT_FREE_PARENT(php_labelcache->parent); zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(labelcache) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "labelcacheObj", labelcache_functions); mapscript_ce_labelcache = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_labelcache->create_object = mapscript_labelcache_create_object; mapscript_ce_labelcache->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_labelcache_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_labelcache_object_handlers)); mapscript_labelcache_object_handlers.free_obj = mapscript_labelcache_free_object; mapscript_labelcache_object_handlers.offset = XtOffsetOf(php_labelcache_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_labelcache_object_destroy(void *object TSRMLS_DC) { php_labelcache_object *php_labelcache = (php_labelcache_object *)object; MAPSCRIPT_FREE_OBJECT(php_labelcache); MAPSCRIPT_FREE_PARENT(php_labelcache->parent); /* We don't need to free the labelCacheObj */ efree(object); } static zend_object_value mapscript_labelcache_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_labelcache_object *php_labelcache; MAPSCRIPT_ALLOC_OBJECT(php_labelcache, php_labelcache_object); retval = mapscript_object_new(&php_labelcache->std, ce, &mapscript_labelcache_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_labelcache->parent); return retval; } PHP_MINIT_FUNCTION(labelcache) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("labelCacheObj", labelcache_functions, mapscript_ce_labelcache, mapscript_labelcache_object_new); mapscript_ce_labelcache->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/labelcachemember.c000066400000000000000000000260311357574274700217500ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_labelcachemember; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_labelcachemember_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(labelcachemember___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(labelcachemember___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto void __construct() labelCacheMemberObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(labelCacheMemberObj, __construct) { mapscript_throw_exception("labelCacheMemberObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(labelCacheMemberObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_labelcachemember_object *php_labelcachemember; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_labelcachemember = MAPSCRIPT_OBJ_P(php_labelcachemember_object, zobj); IF_GET_LONG("classindex", php_labelcachemember->labelcachemember->classindex) /* else IF_GET_LONG("featuresize", php_labelcachemember->labelcachemember->featuresize) */ else IF_GET_LONG("layerindex", php_labelcachemember->labelcachemember->layerindex) /* else IF_GET_LONG("numstyles", php_labelcachemember->labelcachemember->numstyles) */ /* else IF_GET_LONG("numlabels", php_labelcachemember->labelcachemember->numlabels) */ /* else IF_GET_LONG("shapeindex", php_labelcachemember->labelcachemember->shapeindex) */ else IF_GET_LONG("status", php_labelcachemember->labelcachemember->status) else IF_GET_LONG("markerid", php_labelcachemember->labelcachemember->markerid) /* else IF_GET_LONG("tileindex", php_labelcachemember->labelcachemember->tileindex) */ else IF_GET_OBJECT("point", mapscript_ce_point, php_labelcachemember->point, &php_labelcachemember->labelcachemember->point) /* else IF_GET_OBJECT("labels", mapscript_ce_label, php_labelcachemember->labels, &php_labelcachemember->labelcachemember->labels) */ /* else IF_GET_OBJECT("styles", mapscript_ce_style, php_labelcachemember->styles, php_labelcachemember->labelcachemember->styles) */ /* else IF_GET_OBJECT("poly", mapscript_ce_shape, php_labelcachemember->poly, php_labelcachemember->labelcachemember->poly) */ else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(labelCacheMemberObj, __set) { char *property; long property_len = 0; zval *value; /* zval *zobj = getThis(); */ /* php_labelcachemember_object *php_labelcachemember; */ PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); /* php_labelcachemember = MAPSCRIPT_OBJ_P(php_labelcachemember_object, zobj); */ if ( (STRING_EQUAL("classindex", property)) || /* (STRING_EQUAL("featuresize", property)) || */ (STRING_EQUAL("layerindex", property)) || /* (STRING_EQUAL("numstyles", property)) || */ /* (STRING_EQUAL("numlabels", property)) || */ /* (STRING_EQUAL("shapeindex", property)) || */ (STRING_EQUAL("status", property)) || (STRING_EQUAL("markerid", property)) || /* (STRING_EQUAL("tileindex", property)) || */ /* (STRING_EQUAL("labels", property)) || */ /* (STRING_EQUAL("styles", property)) || */ /* (STRING_EQUAL("poly", property)) || */ (STRING_EQUAL("point", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* proto void free() Free the object */ PHP_METHOD(labelCacheMemberObj, free) { zval *zobj = getThis(); php_labelcachemember_object *php_labelcachemember; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_labelcachemember = MAPSCRIPT_OBJ_P(php_labelcachemember_object, zobj); MAPSCRIPT_DELREF(php_labelcachemember->point); MAPSCRIPT_DELREF(php_labelcachemember->labels); MAPSCRIPT_DELREF(php_labelcachemember->styles); MAPSCRIPT_DELREF(php_labelcachemember->poly); } /* }}} */ zend_function_entry labelcachemember_functions[] = { PHP_ME(labelCacheMemberObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(labelCacheMemberObj, __get, labelcachemember___get_args, ZEND_ACC_PUBLIC) PHP_ME(labelCacheMemberObj, __set, labelcachemember___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(labelCacheMemberObj, setProperty, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(labelCacheMemberObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_labelcachemember(labelCacheMemberObj *labelcachemember, parent_object parent, zval *return_value TSRMLS_DC) { php_labelcachemember_object * php_labelcachemember; object_init_ex(return_value, mapscript_ce_labelcachemember); php_labelcachemember = MAPSCRIPT_OBJ_P(php_labelcachemember_object, return_value); php_labelcachemember->labelcachemember = labelcachemember; php_labelcachemember->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_labelcachemember_create_object(zend_class_entry *ce TSRMLS_DC) { php_labelcachemember_object *php_labelcachemember; php_labelcachemember = ecalloc(1, sizeof(*php_labelcachemember) + zend_object_properties_size(ce)); zend_object_std_init(&php_labelcachemember->zobj, ce TSRMLS_CC); object_properties_init(&php_labelcachemember->zobj, ce); php_labelcachemember->zobj.handlers = &mapscript_labelcachemember_object_handlers; MAPSCRIPT_INIT_PARENT(php_labelcachemember->parent); ZVAL_UNDEF(&php_labelcachemember->point); ZVAL_UNDEF(&php_labelcachemember->labels); ZVAL_UNDEF(&php_labelcachemember->styles); ZVAL_UNDEF(&php_labelcachemember->poly); return &php_labelcachemember->zobj; } static void mapscript_labelcachemember_free_object(zend_object *object) { php_labelcachemember_object *php_labelcachemember; php_labelcachemember = (php_labelcachemember_object *)((char *)object - XtOffsetOf(php_labelcachemember_object, zobj)); MAPSCRIPT_FREE_PARENT(php_labelcachemember->parent); MAPSCRIPT_DELREF(php_labelcachemember->point); MAPSCRIPT_DELREF(php_labelcachemember->labels); MAPSCRIPT_DELREF(php_labelcachemember->styles); MAPSCRIPT_DELREF(php_labelcachemember->poly); /* We don't need to free the labelCacheMemberObj, the mapObj will do it */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(labelcachemember) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "labelCacheMemberObj", labelcachemember_functions); mapscript_ce_labelcachemember = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_labelcachemember->create_object = mapscript_labelcachemember_create_object; mapscript_ce_labelcachemember->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_labelcachemember_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_labelcachemember_object_handlers)); mapscript_labelcachemember_object_handlers.free_obj = mapscript_labelcachemember_free_object; mapscript_labelcachemember_object_handlers.offset = XtOffsetOf(php_labelcachemember_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_labelcachemember_object_destroy(void *object TSRMLS_DC) { php_labelcachemember_object *php_labelcachemember = (php_labelcachemember_object *)object; MAPSCRIPT_FREE_OBJECT(php_labelcachemember); MAPSCRIPT_FREE_PARENT(php_labelcachemember->parent); MAPSCRIPT_DELREF(php_labelcachemember->point); MAPSCRIPT_DELREF(php_labelcachemember->labels); MAPSCRIPT_DELREF(php_labelcachemember->styles); MAPSCRIPT_DELREF(php_labelcachemember->poly); /* We don't need to free the labelCacheMemberObj, the mapObj will do it */ efree(object); } static zend_object_value mapscript_labelcachemember_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_labelcachemember_object *php_labelcachemember; MAPSCRIPT_ALLOC_OBJECT(php_labelcachemember, php_labelcachemember_object); retval = mapscript_object_new(&php_labelcachemember->std, ce, &mapscript_labelcachemember_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_labelcachemember->parent); php_labelcachemember->point = NULL; php_labelcachemember->labels = NULL; php_labelcachemember->styles = NULL; php_labelcachemember->poly = NULL; return retval; } PHP_MINIT_FUNCTION(labelcachemember) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("labelCacheMemberObj", labelcachemember_functions, mapscript_ce_labelcachemember, mapscript_labelcachemember_object_new); mapscript_ce_labelcachemember->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/labelleader.c000066400000000000000000000160041357574274700207500ustar00rootroot00000000000000/********************************************************************** * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_labelleader; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_labelleader_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(labelleader___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(labelleader___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto labelleader __construct() labelLeaderObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(labelLeaderObj, __construct) { mapscript_throw_exception("labelLeaderObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(labelLeaderObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_labelleader_object *php_labelleader; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_labelleader = MAPSCRIPT_OBJ_P(php_labelleader_object, zobj); IF_GET_LONG("maxdistance", php_labelleader->labelleader->maxdistance) else IF_GET_LONG("gridstep", php_labelleader->labelleader->gridstep) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(labelLeaderObj, __set) { char *property; long property_len = 0; zval *value; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ( (STRING_EQUAL("maxdistance", property)) || (STRING_EQUAL("gridstep", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } zend_function_entry labelleader_functions[] = { PHP_ME(labelLeaderObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(labelLeaderObj, __get, labelleader___get_args, ZEND_ACC_PUBLIC) PHP_ME(labelLeaderObj, __set, labelleader___set_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_labelleader(labelLeaderObj *labelleader, parent_object parent, zval *return_value TSRMLS_DC) { php_labelleader_object * php_labelleader; object_init_ex(return_value, mapscript_ce_labelleader); php_labelleader = MAPSCRIPT_OBJ_P(php_labelleader_object, return_value); php_labelleader->labelleader = labelleader; php_labelleader->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_labelleader_create_object(zend_class_entry *ce TSRMLS_DC) { php_labelleader_object *php_labelleader; php_labelleader = ecalloc(1, sizeof(*php_labelleader) + zend_object_properties_size(ce)); zend_object_std_init(&php_labelleader->zobj, ce TSRMLS_CC); object_properties_init(&php_labelleader->zobj, ce); php_labelleader->zobj.handlers = &mapscript_labelleader_object_handlers; MAPSCRIPT_INIT_PARENT(php_labelleader->parent); return &php_labelleader->zobj; } static void mapscript_labelleader_free_object(zend_object *object) { php_labelleader_object *php_labelleader; php_labelleader = (php_labelleader_object *)((char *)object - XtOffsetOf(php_labelleader_object, zobj)); MAPSCRIPT_FREE_PARENT(php_labelleader->parent); /* We don't need to free the labelLeaderObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(labelleader) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "labelLeaderObj", labelleader_functions); mapscript_ce_labelleader = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_labelleader->create_object = mapscript_labelleader_create_object; mapscript_ce_labelleader->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_labelleader_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_labelleader_object_handlers)); mapscript_labelleader_object_handlers.free_obj = mapscript_labelleader_free_object; mapscript_labelleader_object_handlers.offset = XtOffsetOf(php_labelleader_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_labelleader_object_destroy(void *object TSRMLS_DC) { php_labelleader_object *php_labelleader = (php_labelleader_object *)object; MAPSCRIPT_FREE_OBJECT(php_labelleader); MAPSCRIPT_FREE_PARENT(php_labelleader->parent); /* We don't need to free the labelLeaderObj */ efree(object); } static zend_object_value mapscript_labelleader_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_labelleader_object *php_labelleader; MAPSCRIPT_ALLOC_OBJECT(php_labelleader, php_labelleader_object); retval = mapscript_object_new(&php_labelleader->std, ce, &mapscript_labelleader_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_labelleader->parent); return retval; } PHP_MINIT_FUNCTION(labelleader) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("labelLeaderObj", labelleader_functions, mapscript_ce_labelleader, mapscript_labelleader_object_new); mapscript_ce_labelleader->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/layer.c000066400000000000000000002421051357574274700176330ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_layer; zend_object_handlers mapscript_layer_object_handlers; ZEND_BEGIN_ARG_INFO_EX(layer___construct_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setExtent_args, 0, 0, 4) ZEND_ARG_INFO(0, minx) ZEND_ARG_INFO(0, miny) ZEND_ARG_INFO(0, maxx) ZEND_ARG_INFO(0, maxy) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getClass_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getClassIndex_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_ARG_INFO(0, classGroup) ZEND_ARG_INFO(0, numClasses) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setFilter_args, 0, 0, 1) ZEND_ARG_INFO(0, expression) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, projectionParams) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setWKTProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, projectionParams) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getResult_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_whichShapes_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, extent, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_addFeature_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setMetaData_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_removeMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getWMSFeatureInfoURL_args, 0, 0, 4) ZEND_ARG_INFO(0, clickX) ZEND_ARG_INFO(0, clickY) ZEND_ARG_INFO(0, featureCount) ZEND_ARG_INFO(0, infoFormat) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setProcessing_args, 0, 0, 1) ZEND_ARG_INFO(0, string) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setProcessingKey_args, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_applySLD_args, 0, 0, 2) ZEND_ARG_INFO(0, sldxml) ZEND_ARG_INFO(0, namedLayer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_applySLDURL_args, 0, 0, 2) ZEND_ARG_INFO(0, sldurl) ZEND_ARG_INFO(0, namedLayer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_moveClassUp_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_moveClassDown_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_removeClass_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setConnectionType_args, 0, 0, 2) ZEND_ARG_INFO(0, connectionType) ZEND_ARG_INFO(0, pluginLibrary) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_draw_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_drawQuery_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByPoint_args, 0, 0, 3) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, buffer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByRect_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, rect, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByFeatures_args, 0, 0, 1) ZEND_ARG_INFO(0, slayer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByAttributes_args, 0, 0, 3) ZEND_ARG_INFO(0, item) ZEND_ARG_INFO(0, string) ZEND_ARG_INFO(0, mode) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByFilter_args, 0, 0, 1) ZEND_ARG_INFO(0, string) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_queryByIndex_args, 0, 0, 2) ZEND_ARG_INFO(0, tileindex) ZEND_ARG_INFO(0, shapeindex) ZEND_ARG_INFO(0, addtoquery) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_getShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, record, resultObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(layer_setGeomTransform_args, 0, 0, 1) ZEND_ARG_INFO(0, transform) ZEND_END_ARG_INFO() /* {{{ proto void __construct(mapObj map [, layerObj layer]) Create a new layerObj instance. */ PHP_METHOD(layerObj, __construct) { zval *zobj = getThis(); zval *zmap, *zlayer = NULL; layerObj *layer; int index; php_map_object *php_map; php_layer_object *php_layer, *php_layer2=NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); if (zlayer) php_layer2 = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); if ((layer = layerObj_new(php_map->map)) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } php_layer->layer = layer; php_layer->is_ref = 1; MAPSCRIPT_MAKE_PARENT(zmap, NULL); php_layer->parent = parent; MAPSCRIPT_ADDREF_P(zmap); /* if a layer is passed as argument, copy the layer into the new one */ if (zlayer) { index = layer->index; msCopyLayer(layer, php_layer2->layer); layer->index = index; } if (layer->connectiontype != MS_GRATICULE || layer->layerinfo == NULL) { MAKE_STD_ZVAL(php_layer->grid); #if PHP_VERSION_ID < 70000 ZVAL_NULL(php_layer->grid); #else ZVAL_NULL(&php_layer->grid); #endif } } /* }}} */ PHP_METHOD(layerObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); IF_GET_LONG("numclasses", php_layer->layer->numclasses) else IF_GET_STRING("encoding", php_layer->layer->encoding) else IF_GET_LONG("index", php_layer->layer->index) else IF_GET_LONG("status", php_layer->layer->status) else IF_GET_LONG("debug", php_layer->layer->debug) else IF_GET_STRING("bandsitem", php_layer->layer->bandsitem) else IF_GET_STRING("classitem", php_layer->layer->classitem) else IF_GET_STRING("classgroup", php_layer->layer->classgroup) else IF_GET_STRING("name", php_layer->layer->name) else IF_GET_STRING("group", php_layer->layer->group) else IF_GET_STRING("data", php_layer->layer->data) else IF_GET_LONG("type", php_layer->layer->type) else IF_GET_LONG("dump", php_layer->layer->dump) else IF_GET_DOUBLE("tolerance", php_layer->layer->tolerance) else IF_GET_LONG("toleranceunits", php_layer->layer->toleranceunits) else IF_GET_LONG("sizeunits", php_layer->layer->sizeunits) else IF_GET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom) else IF_GET_LONG("maxclasses", php_layer->layer->maxclasses) else IF_GET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom) else IF_GET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom) else IF_GET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom) else IF_GET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom) else IF_GET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth) else IF_GET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth) else IF_GET_STRING("mask", php_layer->layer->mask) else IF_GET_LONG("minfeaturesize", php_layer->layer->minfeaturesize) else IF_GET_LONG("maxfeatures", php_layer->layer->maxfeatures) else IF_GET_LONG("startindex", php_layer->layer->startindex) else IF_GET_LONG("transform", php_layer->layer->transform) else IF_GET_LONG("labelcache", php_layer->layer->labelcache) else IF_GET_LONG("postlabelcache", php_layer->layer->postlabelcache) else IF_GET_STRING("labelitem", php_layer->layer->labelitem) else IF_GET_STRING("tileitem", php_layer->layer->tileitem) else IF_GET_STRING("tileindex", php_layer->layer->tileindex) else IF_GET_STRING("header", php_layer->layer->header) else IF_GET_STRING("footer", php_layer->layer->footer) else IF_GET_STRING("connection", php_layer->layer->connection) else IF_GET_LONG("connectiontype", php_layer->layer->connectiontype) else IF_GET_STRING("filteritem", php_layer->layer->filteritem) else IF_GET_STRING("template", php_layer->layer->template) else IF_GET_LONG("opacity", (php_layer->layer->compositer?php_layer->layer->compositer->opacity:100)) else IF_GET_STRING("styleitem", php_layer->layer->styleitem) else IF_GET_LONG("numitems", php_layer->layer->numitems) else IF_GET_LONG("numjoins", php_layer->layer->numjoins) else IF_GET_LONG("num_processing", php_layer->layer->numprocessing) else IF_GET_STRING("requires", php_layer->layer->requires) else IF_GET_STRING("labelrequires", php_layer->layer->labelrequires) else IF_GET_OBJECT("offsite", mapscript_ce_color, php_layer->offsite, &php_layer->layer->offsite) else IF_GET_OBJECT("extent", mapscript_ce_rect, php_layer->extent, &php_layer->layer->extent) else IF_GET_OBJECT("grid", mapscript_ce_grid, php_layer->grid, (graticuleObj *)(php_layer->layer->layerinfo)) else IF_GET_OBJECT("metadata", mapscript_ce_hashtable, php_layer->metadata, &php_layer->layer->metadata) else IF_GET_OBJECT("bindvals", mapscript_ce_hashtable, php_layer->bindvals, &php_layer->layer->bindvals) else IF_GET_OBJECT("cluster", mapscript_ce_cluster, php_layer->cluster, &php_layer->layer->cluster) else IF_GET_OBJECT("projection", mapscript_ce_projection, php_layer->projection, &php_layer->layer->projection) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(layerObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); /* special case for "template" which we want to set to NULL and not an empty string */ if(Z_TYPE_P(value)==IS_NULL && !strcmp(property,"template")) { msFree(php_layer->layer->template); php_layer->layer->template = NULL; } else if(!strcmp(property,"opacity")) { msSetLayerOpacity(php_layer->layer,Z_LVAL_P(value)); } else IF_SET_LONG("status", php_layer->layer->status, value) else IF_SET_STRING("encoding", php_layer->layer->encoding, value) else IF_SET_LONG("debug", php_layer->layer->debug, value) else IF_SET_STRING("classitem", php_layer->layer->classitem, value) else IF_SET_STRING("bandsitem", php_layer->layer->bandsitem, value) else IF_SET_STRING("classgroup", php_layer->layer->classgroup, value) else IF_SET_STRING("name", php_layer->layer->name, value) else IF_SET_STRING("group", php_layer->layer->group, value) else IF_SET_STRING("data", php_layer->layer->data, value) else IF_SET_LONG("type", php_layer->layer->type, value) else IF_SET_LONG("dump", php_layer->layer->dump, value) else IF_SET_DOUBLE("tolerance", php_layer->layer->tolerance, value) else IF_SET_LONG("toleranceunits", php_layer->layer->toleranceunits, value) else IF_SET_LONG("sizeunits", php_layer->layer->sizeunits, value) else IF_SET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom, value) else IF_SET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom, value) else IF_SET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom, value) else IF_SET_LONG("minfeaturesize", php_layer->layer->minfeaturesize, value) else IF_SET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom, value) else IF_SET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom, value) else IF_SET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth, value) else IF_SET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth, value) else IF_SET_STRING("mask", php_layer->layer->mask, value) else IF_SET_LONG("maxfeatures", php_layer->layer->maxfeatures, value) else IF_SET_LONG("startindex", php_layer->layer->startindex, value) else IF_SET_LONG("transform", php_layer->layer->transform, value) else IF_SET_LONG("labelcache", php_layer->layer->labelcache, value) else IF_SET_LONG("postlabelcache", php_layer->layer->postlabelcache, value) else IF_SET_STRING("labelitem", php_layer->layer->labelitem, value) else IF_SET_STRING("tileitem", php_layer->layer->tileitem, value) else IF_SET_STRING("tileindex", php_layer->layer->tileindex, value) else IF_SET_STRING("header", php_layer->layer->header, value) else IF_SET_STRING("footer", php_layer->layer->footer, value) else IF_SET_STRING("connection", php_layer->layer->connection, value) else IF_SET_STRING("filteritem", php_layer->layer->filteritem, value) else IF_SET_STRING("template", php_layer->layer->template, value) else IF_SET_STRING("styleitem", php_layer->layer->styleitem, value) else IF_SET_LONG("num_processing", php_layer->layer->numprocessing, value) else IF_SET_STRING("requires", php_layer->layer->requires, value) else IF_SET_STRING("labelrequires", php_layer->layer->labelrequires, value) else if ( (STRING_EQUAL("offsite", property)) || (STRING_EQUAL("grid", property)) || (STRING_EQUAL("metadata", property)) || (STRING_EQUAL("bindvals", property)) || (STRING_EQUAL("projection", property)) || (STRING_EQUAL("maxclasses", property)) || (STRING_EQUAL("numitems", property)) || (STRING_EQUAL("numjoins", property)) || (STRING_EQUAL("extent", property)) || (STRING_EQUAL("cluster", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if ( (STRING_EQUAL("numclasses", property)) || (STRING_EQUAL("index", property)) || (STRING_EQUAL("connectiontype", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int draw(imageObj image) Draw a single layer, add labels to cache if required. Returns MS_FAILURE on error. */ PHP_METHOD(layerObj, draw) { zval *zobj = getThis(); zval *zimage; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_draw(php_layer->layer, php_map->map, php_image->image)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int drawQuery(image img) Draw query results for a layer. */ PHP_METHOD(layerObj, drawQuery) { zval *zobj = getThis(); zval *zimage; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_drawQuery(php_layer->layer, php_map->map, php_image->image)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int queryByPoint(pointObj point, int type, double buffer) Query at point location. */ PHP_METHOD(layerObj, queryByPoint) { zval *zobj = getThis(); zval *zpoint; int status = MS_FAILURE; long mode; double buffer; php_layer_object *php_layer; php_map_object *php_map; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Old", &zpoint, mapscript_ce_point, &mode, &buffer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_point = MAPSCRIPT_OBJ_P(php_point_object, zpoint); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_queryByPoint(php_layer->layer, php_map->map, php_point->point, mode, buffer)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int queryByRect(rectObj rect) Query using rectangular extent. */ PHP_METHOD(layerObj, queryByRect) { zval *zobj = getThis(); zval *zrect; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zrect, mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zrect); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_queryByRect(php_layer->layer, php_map->map, *(php_rect->rect))) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int queryByShape(shapeObj shape) Query using a shape */ PHP_METHOD(layerObj, queryByShape) { zval *zobj = getThis(); zval *zshape; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_queryByShape(php_layer->layer, php_map->map, php_shape->shape)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int queryByFeatures(int slayer) Query on a layer using query object. */ PHP_METHOD(layerObj, queryByFeatures) { zval *zobj = getThis(); long slayer; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &slayer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_queryByFeatures(php_layer->layer, php_map->map, slayer)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.queryAttributes(string item, string string, int mode) Query at point location. */ PHP_METHOD(layerObj, queryByAttributes) { zval *zobj = getThis(); char *item; long item_len = 0; char *string; long string_len = 0; long mode; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &item, &item_len, &string, &string_len, &mode) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_queryByAttributes(php_layer->layer, php_map->map, item, string, mode)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.queryByFilter(string string) Query by filter. */ PHP_METHOD(layerObj, queryByFilter) { zval *zobj = getThis(); char *string; long string_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_queryByFilter(php_layer->layer, php_map->map, string)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.queryByIndex(int tileindex, int shapeindex, int addtoquery) Query by index. */ PHP_METHOD(layerObj, queryByIndex) { zval *zobj = getThis(); long tileindex, shapeindex; long addtoquery=MS_FALSE; int status = MS_FAILURE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|l", &tileindex, &shapeindex, &addtoquery) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((status = layerObj_queryByIndex(php_layer->layer, php_map->map, tileindex, shapeindex, addtoquery)) != MS_SUCCESS) mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.updateFromString(string snippet) Update a layer from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(layerObj, updateFromString) { zval *zobj = getThis(); char *snippet; long snippet_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if ((status = layerObj_updateFromString(php_layer->layer, snippet)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the layer object to string. */ PHP_METHOD(layerObj, convertToString) { zval *zobj = getThis(); php_layer_object *php_layer; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); value = layerObj_convertToString(php_layer->layer); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int layer.getClass(int i) Returns a classObj from the layer given an index value (0=first class) */ PHP_METHOD(layerObj, getClass) { zval *zobj = getThis(); long index; classObj *class = NULL; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if ((class = layerObj_getClass(php_layer->layer, index)) == NULL) { mapscript_throw_exception("Invalid class index." TSRMLS_CC); return; } /* Return class object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_class(class, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.getClassIndex(shapeObj shape [, string classGroup, int numClasses]) Returns the class index for the shape */ PHP_METHOD(layerObj, getClassIndex) { zval *zobj = getThis(); zval *zshape, *zclassgroup = NULL; MAPSCRIPT_ZVAL_P ppzval; int numElements, *classGroups = NULL; int retval = -1, i = 0; long numClasses = 0; HashTable *classgroup_hash = NULL; php_shape_object *php_shape; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|a!l", &zshape, mapscript_ce_shape, &zclassgroup, &numClasses) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if (zclassgroup) { classgroup_hash = Z_ARRVAL_P(zclassgroup); numElements = zend_hash_num_elements(classgroup_hash); classGroups = (int*)malloc(sizeof(int)*numElements); for(zend_hash_internal_pointer_reset(classgroup_hash); zend_hash_has_more_elements(classgroup_hash) == SUCCESS; zend_hash_move_forward(classgroup_hash), ++i) { #if PHP_VERSION_ID < 70000 zend_hash_get_current_data(classgroup_hash, (void **)&ppzval); #else ppzval = zend_hash_get_current_data(classgroup_hash); #endif classGroups[i] = Z_LVAL_PP(ppzval); } } retval = layerObj_getClassIndex(php_layer->layer, php_map->map, php_shape->shape, classGroups, numClasses); if (zclassgroup) free(classGroups); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int layer.setFilter(string filter) Set layer filter expression. Returns 0 on success, -1 in error. */ PHP_METHOD(layerObj, setFilter) { zval *zobj = getThis(); char *expression; long expression_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &expression, &expression_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if ((status = layerObj_setFilter(php_layer->layer, expression)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string layer.getFilterString() Return the layer's filter expression. Returns NULL on error. */ PHP_METHOD(layerObj, getFilterString) { zval *zobj = getThis(); char *value = NULL; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); value = layerObj_getFilter(php_layer->layer); if (value == NULL) { RETURN_NULL(); } MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int layer.setProjection(string projection_params) Set projection and coord. system for the layer. */ PHP_METHOD(layerObj, setProjection) { zval *zobj = getThis(); char *projection; long projection_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; php_projection_object *php_projection=NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &projection, &projection_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_NOT_UNDEF(php_layer->projection)) php_projection = MAPSCRIPT_OBJ(php_projection_object, php_layer->projection); if ((status = layerObj_setProjection(php_layer->layer, projection)) != MS_SUCCESS) { mapscript_report_php_error(E_WARNING, "setProjection failed" TSRMLS_CC); RETURN_LONG(status); } if (ZVAL_NOT_UNDEF(php_layer->projection)) php_projection->projection = &(php_layer->layer->projection); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.getProjection() Return the projection string of the layer. Returns NULL on error. */ PHP_METHOD(layerObj, getProjection) { zval *zobj = getThis(); char *projection = NULL; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); projection = layerObj_getProjection(php_layer->layer); if (projection == NULL) { RETURN_NULL(); } MAPSCRIPT_RETVAL_STRING(projection, 1); free(projection); } /* }}} */ /* {{{ proto int layer.setWKTProjection(string projection_params) Set projection and coord. system for the layer. */ PHP_METHOD(layerObj, setWKTProjection) { zval *zobj = getThis(); char *projection; long projection_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; php_projection_object *php_projection=NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &projection, &projection_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_NOT_UNDEF(php_layer->projection)) php_projection = MAPSCRIPT_OBJ(php_projection_object, php_layer->projection); if ((status = layerObj_setWKTProjection(php_layer->layer, projection)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (ZVAL_NOT_UNDEF(php_layer->projection)) php_projection->projection = &(php_layer->layer->projection); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.getNumResults() Returns the number of results from this layer in the last query. */ PHP_METHOD(layerObj, getNumResults) { zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (!php_layer->layer->resultcache) RETURN_LONG(0); RETURN_LONG(php_layer->layer->resultcache->numresults); } /* }}} */ /* {{{ proto int layer.getResultsBounds() Returns the bounds of results from this layer in the last query. */ PHP_METHOD(layerObj, getResultsBounds) { zval *zobj = getThis(); php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (!php_layer->layer->resultcache) RETURN_NULL(); /* Return result object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_rect(&(php_layer->layer->resultcache->bounds), parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.getResult(int i) Returns a resultObj by index from a layer object.*/ PHP_METHOD(layerObj, getResult) { zval *zobj = getThis(); long index; resultObj *result = NULL; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if ((result = layerObj_getResult(php_layer->layer, index)) == NULL) { mapscript_throw_exception("Invalid result index." TSRMLS_CC); return; } /* Return result object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_result(&(php_layer->layer->resultcache->results[index]), parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.open() Open the layer for use with getShape(). Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(layerObj, open) { zval *zobj = getThis(); int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); status = layerObj_open(php_layer->layer); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(status); } else { msLayerGetItems(php_layer->layer); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.whichshapes(rectObj extent) Returns MS_SUCCESS/MS_FAILURE. */ /* ** Performs a spatial, and optionally an attribute based feature search. The function basically ** prepares things so that candidate features can be accessed by query or drawing functions. For ** OGR and shapefiles this sets an internal bit vector that indicates whether a particular feature ** is to processed. For SDE it executes an SQL statement on the SDE server. Once run the msLayerNextShape ** function should be called to actually access the shapes. ** ** Note that for shapefiles we apply any maxfeatures constraint at this point. That may be the only ** connection type where this is feasible. */ PHP_METHOD(layerObj, whichShapes) { zval *zobj = getThis(); zval *zrect; int status = MS_FAILURE; php_layer_object *php_layer; php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zrect, mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zrect); status = layerObj_whichShapes(php_layer->layer, php_rect->rect); RETURN_LONG(status); } /* }}} */ /* {{{ proto int layer.nextshape() Returns a shape or NULL. */ PHP_METHOD(layerObj, nextShape) { zval *zobj = getThis(); shapeObj *shape = NULL; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); shape = layerObj_nextShape(php_layer->layer); if (!shape) RETURN_NULL(); /* Return valid object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, php_layer, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.close() Close layer previously opened with open(). */ PHP_METHOD(layerObj, close) { zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); layerObj_close(php_layer->layer); } /* }}} */ /* {{{ proto int layer.getExtent() Retrieve or calculate a layer's extents. */ PHP_METHOD(layerObj, getExtent) { zval *zobj = getThis(); rectObj *rect = NULL; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); /* Create a new rectObj to hold the result */ if ((rect = rectObj_new()) == NULL) { mapscript_throw_mapserver_exception("Failed creating new rectObj (out of memory?)" TSRMLS_CC); return; } if (msLayerGetExtent(php_layer->layer, rect) != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } /* Return rectObj */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_rect(rect, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.setExtent(int minx, int miny, int maxx, int maxy) Set the layer extent. */ PHP_METHOD(layerObj, setExtent) { zval *zobj = getThis(); long minx, miny, maxx, maxy; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &minx, &miny, &maxx, &maxy) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (minx > maxx || miny > maxy) { mapscript_throw_mapserver_exception("Invalid min/max values" TSRMLS_CC); return; } RETURN_LONG(msLayerSetExtent(php_layer->layer, minx, miny, maxx, maxy)) } /* }}} */ /* {{{ proto int layer.addFeature(ShapeObj poShape) Add a shape */ PHP_METHOD(layerObj, addFeature) { zval *zobj = getThis(); zval *zshape; int status = MS_FAILURE; php_layer_object *php_layer; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zshape); status = layerObj_addFeature(php_layer->layer, php_shape->shape); RETURN_LONG(status); } /* }}} */ /* {{{ proto string layer.getMetaData(string name) Return MetaData entry by name, or empty string if not found. */ PHP_METHOD(layerObj, getMetaData) { zval *zname; zval *zobj = getThis(); php_layer_object *php_layer; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_layer->metadata, &php_layer->layer->metadata); MAPSCRIPT_CALL_METHOD_1(php_layer->metadata, "get", retval, zname); #if PHP_VERSION_ID < 70000 RETURN_STRING(Z_STRVAL_P(retval),1); #else RETURN_STRING(Z_STRVAL(retval)) #endif } /* }}} */ /* {{{ proto int layer.setMetaData(string name, string value) Set MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(layerObj, setMetaData) { zval *zname, *zvalue; zval *zobj = getThis(); php_layer_object *php_layer; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zname, &zvalue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_layer->metadata, &php_layer->layer->metadata); MAPSCRIPT_CALL_METHOD_2(php_layer->metadata, "set", retval, zname, zvalue); #if PHP_VERSION_ID < 70000 RETURN_LONG(Z_LVAL_P(retval)); #else RETURN_LONG(Z_LVAL(retval)); #endif } /* }}} */ /* {{{ proto int layer.removeMetaData(string name) Remove MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(layerObj, removeMetaData) { zval *zname; zval *zobj = getThis(); php_layer_object *php_layer; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_layer->metadata, &php_layer->layer->metadata); MAPSCRIPT_CALL_METHOD_1(php_layer->metadata, "remove", retval, zname); #if PHP_VERSION_ID < 70000 RETURN_LONG(Z_LVAL_P(retval)); #else RETURN_LONG(Z_LVAL(retval)); #endif } /* }}} */ /* {{{ proto string layer.getWMSFeatureInfoURL(int clickX, int clickY, int featureCount, string infoFormat) Return a WMS GetFeatureInfo URL (only for WMS layers). */ PHP_METHOD(layerObj, getWMSFeatureInfoURL) { zval *zobj = getThis(); long clickx, clicky, featureCount; char *infoFormat = NULL; long infoFormat_len = 0; char *value = NULL; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llls", &clickx, &clicky, &featureCount, &infoFormat, &infoFormat_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); if ((value = layerObj_getWMSFeatureInfoURL(php_layer->layer, php_map->map, clickx, clicky, featureCount, infoFormat)) == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); MAPSCRIPT_RETURN_STRING("", 1); } MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto char** layer.getItems() Return an array containing all the layer items.*/ PHP_METHOD(layerObj, getItems) { zval *zobj = getThis(); int i, status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); array_init(return_value); status = msLayerGetItems(php_layer->layer); if (status != MS_FAILURE && php_layer->layer->numitems > 0) { for (i=0; ilayer->numitems; i++) { /* add a copy of the group name to the PHP array */ mapscript_add_next_index_string(return_value, php_layer->layer->items[i], 1); } } } /* }}} */ /* {{{ boolean layer.setProcessing(string) set a processing string to the layer*/ PHP_METHOD(layerObj, setProcessing) { zval *zobj = getThis(); char *string = NULL; long string_len = 0; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_layer->layer->numprocessing++; if(php_layer->layer->numprocessing == 1) php_layer->layer->processing = (char **) malloc(2*sizeof(char *)); else php_layer->layer->processing = (char **) realloc(php_layer->layer->processing, sizeof(char*) * (php_layer->layer->numprocessing+1)); php_layer->layer->processing[php_layer->layer->numprocessing-1] = msStrdup(string); php_layer->layer->processing[php_layer->layer->numprocessing] = NULL; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ boolean layer.setProcessingKey(string key, string value) set a processing key string to the layer*/ PHP_METHOD(layerObj, setProcessingKey) { zval *zobj = getThis(); char *key = NULL; long key_len = 0; char *value = NULL; long value_len = 0; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); msLayerSetProcessingKey( php_layer->layer, key, value ); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto char** layer.getProcessing() Return an array containing all the processing strings.*/ PHP_METHOD(layerObj, getProcessing) { zval *zobj = getThis(); int i; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); array_init(return_value); if (php_layer->layer->numprocessing > 0) { for (i=0; ilayer->numprocessing; i++) { mapscript_add_next_index_string(return_value, php_layer->layer->processing[i], 1); } } } /* }}} */ /* {{{ boolean layer.clearProcessing() clear the processing strings in the layer*/ PHP_METHOD(layerObj, clearProcessing) { zval *zobj = getThis(); int i; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (php_layer->layer->numprocessing > 0) { for(i=0; ilayer->numprocessing; i++) free(php_layer->layer->processing[i]); php_layer->layer->numprocessing = 0; free(php_layer->layer->processing); } } /* }}} */ /* {{{ string layer.executewfsgetfeature() Executes a GetFeature request on a WFS layer and returns the name of the temporary GML file created. Returns an empty string on error.*/ PHP_METHOD(layerObj, executeWFSGetFeature) { zval *zobj = getThis(); char *value = NULL; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if ((value=layerObj_executeWFSGetFeature(php_layer->layer)) == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int applySLD(string sldxml, string namedlayer) Apply the SLD document to the layer object. The matching between the sld document and the layer will be done using the layer's name. If a namedlayer argument is passed (argument is optional), the NamedLayer in the sld that matchs it will be used to style the layer. */ PHP_METHOD(layerObj, applySLD) { zval *zobj = getThis(); char *sldxml; long sldxml_len = 0; char *namedLayer = NULL; long namedLayer_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &sldxml, &sldxml_len, &namedLayer, &namedLayer_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); status = layerObj_applySLD(php_layer->layer, sldxml, namedLayer); RETURN_LONG(status); } /* }}} */ /* {{{ proto int applySLDURL(string sldurl, string namedlayer) Apply the SLD document pointed by the URL to the layer object. The matching between the sld document and the layer will be done using the layer's name. If a namedlayer argument is passed (argument is optional), the NamedLayer in the sld that matchs it will be used to style the layer. */ PHP_METHOD(layerObj, applySLDURL) { zval *zobj = getThis(); char *sldurl; long sldurl_len = 0; char *namedLayer = NULL; long namedLayer_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &sldurl, &sldurl_len, &namedLayer, &namedLayer_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); status = layerObj_applySLDURL(php_layer->layer, sldurl, namedLayer); RETURN_LONG(status); } /* }}} */ /* {{{ proto string generateSLD() Returns an SLD XML string based on all the classes found in the layers.*/ PHP_METHOD(layerObj, generateSLD) { zval *zobj = getThis(); char *buffer = NULL; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); buffer = layerObj_generateSLD(php_layer->layer); if (buffer) { MAPSCRIPT_RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); MAPSCRIPT_RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto int moveClassUp(int index) The class specified by the class index will be moved up into the array of layers. Returns MS_SUCCESS or MS_FAILURE. */ PHP_METHOD(layerObj, moveClassUp) { zval *zobj = getThis(); long index; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); status = layerObj_moveClassUp(php_layer->layer, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int moveClassDown(int index) The class specified by the class index will be moved down into the array of layers. Returns MS_SUCCESS or MS_FAILURE.*/ PHP_METHOD(layerObj, moveClassDown) { zval *zobj = getThis(); long index; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); status = layerObj_moveClassDown(php_layer->layer, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int removeClass(int index) Removes the class indicated and returns a copy, or NULL in the case of a failure.*/ PHP_METHOD(layerObj, removeClass) { zval *zobj = getThis(); long index; classObj *class; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if ((class = layerObj_removeClass(php_layer->layer, index)) == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } /* Return a copy of the class object just removed */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_class(class, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.isVisible() Returns MS_TRUE/MS_FALSE depending on whether the layer is currently visible in the map (i.e. turned on, in scale, etc.). */ PHP_METHOD(layerObj, isVisible) { zval *zobj = getThis(); int retval = MS_FALSE; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); retval = msLayerIsVisible(php_map->map, php_layer->layer); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int layer.setConnectionType(int connectionType, string pluginLibrary) Set layer connectiontype. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(layerObj, setConnectionType) { zval *zobj = getThis(); long type; char *plugin = ""; long plugin_len = 0; int status = MS_FAILURE; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &type, &plugin, &plugin_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if ((status = layerObj_setConnectionType(php_layer->layer, type, plugin)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_layer->layer->connectiontype != MS_GRATICULE || php_layer->layer->layerinfo == NULL) { if (ZVAL_NOT_UNDEF(php_layer->grid) && MAPSCRIPT_TYPE(php_layer->grid) == IS_OBJECT) { MAPSCRIPT_DELREF(php_layer->grid); MAKE_STD_ZVAL(php_layer->grid); #if PHP_VERSION_ID < 70000 ZVAL_NULL(php_layer->grid); #else ZVAL_NULL(&php_layer->grid); #endif } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int getGridIntersctionCoordinates() Not sure if this function is often used, let it as it is. */ PHP_METHOD(layerObj, getGridIntersectionCoordinates) { zval *zobj = getThis(); graticuleIntersectionObj *values=NULL; MAPSCRIPT_ZVAL tmp_arr1; int i=0; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this layer object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); array_init(return_value); if (php_layer->layer->connectiontype != MS_GRATICULE) { mapscript_throw_exception("Layer is not of graticule type" TSRMLS_CC); return; } values = msGraticuleLayerGetIntersectionPoints(php_map->map, php_layer->layer); if (values == NULL) return; /* empty array is returned */ /*TOP*/ add_assoc_double(return_value, "topnumpoints", values->nTop); MAKE_STD_ZVAL(tmp_arr1); mapscript_array_init(tmp_arr1); for (i=0; inTop; i++) { #if PHP_VERSION_ID < 70000 add_next_index_string(tmp_arr1, values->papszTopLabels[i],1); #else add_next_index_string(&tmp_arr1, values->papszTopLabels[i]); #endif } mapscript_hash_update(Z_ARRVAL_P(return_value), "toplabels", tmp_arr1); MAKE_STD_ZVAL(tmp_arr1); mapscript_array_init(tmp_arr1); for (i=0; inTop; i++) { #if PHP_VERSION_ID < 70000 add_next_index_double(tmp_arr1, values->pasTop[i].x); add_next_index_double(tmp_arr1, values->pasTop[i].y); #else add_next_index_double(&tmp_arr1, values->pasTop[i].x); add_next_index_double(&tmp_arr1, values->pasTop[i].y); #endif } mapscript_hash_update(Z_ARRVAL_P(return_value), "toppoints", tmp_arr1); /*BOTTOM*/ add_assoc_double(return_value, "bottomnumpoints", values->nBottom); MAKE_STD_ZVAL(tmp_arr1); mapscript_array_init(tmp_arr1); for (i=0; inBottom; i++) { #if PHP_VERSION_ID < 70000 add_next_index_string(tmp_arr1, values->papszBottomLabels[i],1); #else add_next_index_string(&tmp_arr1, values->papszBottomLabels[i]); #endif } mapscript_hash_update(Z_ARRVAL_P(return_value), "bottomlabels", tmp_arr1); MAKE_STD_ZVAL(tmp_arr1); mapscript_array_init(tmp_arr1); for (i=0; inBottom; i++) { #if PHP_VERSION_ID < 70000 add_next_index_double(tmp_arr1, values->pasBottom[i].x); add_next_index_double(tmp_arr1, values->pasBottom[i].y); #else add_next_index_double(&tmp_arr1, values->pasBottom[i].x); add_next_index_double(&tmp_arr1, values->pasBottom[i].y); #endif } mapscript_hash_update(Z_ARRVAL_P(return_value), "bottompoints", tmp_arr1); /*LEFT*/ add_assoc_double(return_value, "leftnumpoints", values->nLeft); MAKE_STD_ZVAL(tmp_arr1); mapscript_array_init(tmp_arr1); for (i=0; inLeft; i++) { #if PHP_VERSION_ID < 70000 add_next_index_string(tmp_arr1, values->papszLeftLabels[i],1); #else add_next_index_string(&tmp_arr1, values->papszLeftLabels[i]); #endif } mapscript_hash_update(Z_ARRVAL_P(return_value), "leftlabels", tmp_arr1); MAKE_STD_ZVAL(tmp_arr1); mapscript_array_init(tmp_arr1); for (i=0; inLeft; i++) { #if PHP_VERSION_ID < 70000 add_next_index_double(tmp_arr1, values->pasLeft[i].x); add_next_index_double(tmp_arr1, values->pasLeft[i].y); #else add_next_index_double(&tmp_arr1, values->pasLeft[i].x); add_next_index_double(&tmp_arr1, values->pasLeft[i].y); #endif } mapscript_hash_update(Z_ARRVAL_P(return_value), "leftpoints", tmp_arr1); /*RIGHT*/ add_assoc_double(return_value, "rightnumpoints", values->nRight); MAKE_STD_ZVAL(tmp_arr1); mapscript_array_init(tmp_arr1); for (i=0; inRight; i++) { #if PHP_VERSION_ID < 70000 add_next_index_string(tmp_arr1, values->papszRightLabels[i],1); #else add_next_index_string(&tmp_arr1, values->papszRightLabels[i]); #endif } mapscript_hash_update(Z_ARRVAL_P(return_value), "rightlabels", tmp_arr1); MAKE_STD_ZVAL(tmp_arr1); mapscript_array_init(tmp_arr1); for (i=0; inRight; i++) { #if PHP_VERSION_ID < 70000 add_next_index_double(tmp_arr1, values->pasRight[i].x); add_next_index_double(tmp_arr1, values->pasRight[i].y); #else add_next_index_double(&tmp_arr1, values->pasRight[i].x); add_next_index_double(&tmp_arr1, values->pasRight[i].y); #endif } mapscript_hash_update(Z_ARRVAL_P(return_value), "rightpoints", tmp_arr1); msGraticuleLayerFreeIntersectionPoints(values); } /* }}} */ /* {{{ proto shapeObj layer.getShape(record) Retrieve shapeObj from a resultset by index. */ PHP_METHOD(layerObj, getShape) { zval *zobj = getThis(); zval *zresult; shapeObj *shape = NULL; php_result_object *php_result; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zresult, mapscript_ce_result) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); php_result = MAPSCRIPT_OBJ_P(php_result_object, zresult); /* Create a new shapeObj to hold the result * Note that the type used to create the shape (MS_NULL) does not matter * at this point since it will be set by SHPReadShape(). */ if ((shape = shapeObj_new(MS_SHAPE_NULL)) == NULL) { mapscript_throw_mapserver_exception("Failed creating new shape (out of memory?)" TSRMLS_CC); return; } if (msLayerGetShape(php_layer->layer, shape, php_result->result) != MS_SUCCESS) { shapeObj_destroy(shape); mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return valid object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, php_layer, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int layer.getGeomTransform() return the geometry transform expression */ PHP_METHOD(layerObj, getGeomTransform) { zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); if (php_layer->layer->_geomtransform.type == MS_GEOMTRANSFORM_NONE || !php_layer->layer->_geomtransform.string) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETURN_STRING(php_layer->layer->_geomtransform.string, 1); } /* }}} */ /* {{{ proto int layer.setGeomTransform() set the geometry transform expression */ PHP_METHOD(layerObj, setGeomTransform) { zval *zobj = getThis(); char *transform; long transform_len = 0; php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &transform, &transform_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); msFree(php_layer->layer->_geomtransform.string); if (transform_len > 0) { php_layer->layer->_geomtransform.string = msStrdup(transform); php_layer->layer->_geomtransform.type = MS_GEOMTRANSFORM_EXPRESSION; } else { php_layer->layer->_geomtransform.type = MS_GEOMTRANSFORM_NONE; php_layer->layer->_geomtransform.string = NULL; } RETURN_LONG(MS_SUCCESS); } /* {{{ proto void layer.free() Free the object */ PHP_METHOD(layerObj, free) { zval *zobj = getThis(); php_layer_object *php_layer; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zobj); MAPSCRIPT_DELREF(php_layer->offsite); if (ZVAL_NOT_UNDEF(php_layer->grid) && MAPSCRIPT_TYPE(php_layer->grid) == IS_OBJECT) MAPSCRIPT_DELREF(php_layer->grid); MAPSCRIPT_DELREF(php_layer->metadata); MAPSCRIPT_DELREF(php_layer->bindvals); MAPSCRIPT_DELREF(php_layer->cluster); MAPSCRIPT_DELREF(php_layer->projection); } /* }}} */ zend_function_entry layer_functions[] = { PHP_ME(layerObj, __construct, layer___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(layerObj, __get, layer___get_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, __set, layer___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(layerObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, draw, layer_draw_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, drawQuery, layer_drawQuery_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, updateFromString, layer_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getClass, layer_getClass_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getClassIndex, layer_getClassIndex_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByPoint, layer_queryByPoint_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByRect, layer_queryByRect_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByShape, layer_queryByShape_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByFeatures, layer_queryByFeatures_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByAttributes, layer_queryByAttributes_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByFilter, layer_queryByFilter_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, queryByIndex, layer_queryByIndex_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setFilter, layer_setFilter_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getFilterString, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setProjection, layer_setProjection_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getProjection, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setWKTProjection, layer_setWKTProjection_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getNumResults, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getResultsBounds, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getResult, layer_getResult_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, open, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, whichShapes, layer_whichShapes_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, nextShape, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, close, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getExtent, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setExtent, layer_setExtent_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, addFeature, layer_addFeature_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getMetaData, layer_getMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setMetaData, layer_setMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, removeMetaData, layer_removeMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getWMSFeatureInfoURL, layer_getWMSFeatureInfoURL_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getItems, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setProcessing, layer_setProcessing_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setProcessingKey, layer_setProcessingKey_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getProcessing, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, clearProcessing, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, executeWFSGetFeature, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, applySLD, layer_applySLD_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, applySLDURL, layer_applySLDURL_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, generateSLD, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, moveClassUp, layer_moveClassUp_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, moveClassDown, layer_moveClassDown_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, removeClass, layer_removeClass_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, isVisible, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setConnectionType, layer_setConnectionType_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getGridIntersectionCoordinates, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getShape, layer_getShape_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, getGeomTransform, NULL, ZEND_ACC_PUBLIC) PHP_ME(layerObj, setGeomTransform, layer_setGeomTransform_args, ZEND_ACC_PUBLIC) PHP_ME(layerObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_layer(layerObj *layer, parent_object parent, zval *return_value TSRMLS_DC) { php_layer_object * php_layer; object_init_ex(return_value, mapscript_ce_layer); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, return_value); php_layer->layer = layer; if (layer->connectiontype != MS_GRATICULE || layer->layerinfo == NULL) { MAKE_STD_ZVAL(php_layer->grid); #if PHP_VERSION_ID < 70000 ZVAL_NULL(php_layer->grid); #else ZVAL_NULL(&php_layer->grid); #endif } if(ZVAL_NOT_UNDEF(parent.val)) php_layer->is_ref = 1; php_layer->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_layer_create_object(zend_class_entry *ce TSRMLS_DC) { php_layer_object *php_layer; php_layer = ecalloc(1, sizeof(*php_layer) + zend_object_properties_size(ce)); zend_object_std_init(&php_layer->zobj, ce TSRMLS_CC); object_properties_init(&php_layer->zobj, ce); php_layer->zobj.handlers = &mapscript_layer_object_handlers; php_layer->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_layer->parent); ZVAL_UNDEF(&php_layer->offsite); ZVAL_UNDEF(&php_layer->grid); ZVAL_UNDEF(&php_layer->metadata); ZVAL_UNDEF(&php_layer->bindvals); ZVAL_UNDEF(&php_layer->cluster); ZVAL_UNDEF(&php_layer->projection); ZVAL_UNDEF(&php_layer->extent); return &php_layer->zobj; } static void mapscript_layer_free_object(zend_object *object) { php_layer_object *php_layer; php_layer = (php_layer_object *)((char *)object - XtOffsetOf(php_layer_object, zobj)); MAPSCRIPT_FREE_PARENT(php_layer->parent); MAPSCRIPT_DELREF(php_layer->offsite); if (ZVAL_NOT_UNDEF(php_layer->grid) && MAPSCRIPT_TYPE(php_layer->grid) == IS_OBJECT) MAPSCRIPT_DELREF(php_layer->grid); MAPSCRIPT_DELREF(php_layer->metadata); MAPSCRIPT_DELREF(php_layer->bindvals); MAPSCRIPT_DELREF(php_layer->cluster); MAPSCRIPT_DELREF(php_layer->projection); MAPSCRIPT_DELREF(php_layer->extent); if (php_layer->layer && !php_layer->is_ref) { layerObj_destroy(php_layer->layer); } zend_object_std_dtor(object); } static zend_object* mapscript_layer_clone_object(zval *zobj) { php_layer_object *php_layer_old, *php_layer_new; zend_object* zobj_new; php_layer_old = MAPSCRIPT_OBJ_P(php_layer_object, zobj); zobj_new = mapscript_layer_create_object(mapscript_ce_layer); php_layer_new = (php_layer_object *)((char *)zobj_new - XtOffsetOf(php_layer_object, zobj)); zend_objects_clone_members(&php_layer_new->zobj, &php_layer_old->zobj); php_layer_new->layer = layerObj_clone(php_layer_old->layer); return zobj_new; } PHP_MINIT_FUNCTION(layer) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "layerObj", layer_functions); mapscript_ce_layer = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_layer->create_object = mapscript_layer_create_object; mapscript_ce_layer->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_layer_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_layer_object_handlers)); mapscript_layer_object_handlers.free_obj = mapscript_layer_free_object; mapscript_layer_object_handlers.clone_obj = mapscript_layer_clone_object; mapscript_layer_object_handlers.offset = XtOffsetOf(php_layer_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_layer_object_destroy(void *object TSRMLS_DC) { php_layer_object *php_layer = (php_layer_object *)object; MAPSCRIPT_FREE_OBJECT(php_layer); MAPSCRIPT_FREE_PARENT(php_layer->parent); MAPSCRIPT_DELREF(php_layer->offsite); if (php_layer->grid && Z_TYPE_P(php_layer->grid) == IS_OBJECT) MAPSCRIPT_DELREF(php_layer->grid); MAPSCRIPT_DELREF(php_layer->metadata); MAPSCRIPT_DELREF(php_layer->bindvals); MAPSCRIPT_DELREF(php_layer->cluster); MAPSCRIPT_DELREF(php_layer->projection); MAPSCRIPT_DELREF(php_layer->extent); if (php_layer->layer && !php_layer->is_ref) { layerObj_destroy(php_layer->layer); } efree(object); } static zend_object_value mapscript_layer_object_new_ex(zend_class_entry *ce, php_layer_object **ptr TSRMLS_DC) { zend_object_value retval; php_layer_object *php_layer; MAPSCRIPT_ALLOC_OBJECT(php_layer, php_layer_object); retval = mapscript_object_new_ex(&php_layer->std, ce, &mapscript_layer_object_destroy, &mapscript_layer_object_handlers TSRMLS_CC); if (ptr) *ptr = php_layer; php_layer->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_layer->parent); php_layer->offsite = NULL; php_layer->grid = NULL; php_layer->metadata = NULL; php_layer->bindvals = NULL; php_layer->cluster = NULL; php_layer->projection = NULL; php_layer->extent = NULL; return retval; } static zend_object_value mapscript_layer_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_layer_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_layer_object_clone(zval *zobj TSRMLS_DC) { php_layer_object *php_layer_old, *php_layer_new; zend_object_value new_ov; php_layer_old = MAPSCRIPT_OBJ_P(php_layer_object, zobj); new_ov = mapscript_layer_object_new_ex(mapscript_ce_layer, &php_layer_new TSRMLS_CC); zend_objects_clone_members(&php_layer_new->std, new_ov, &php_layer_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_layer_new->layer = layerObj_clone(php_layer_old->layer); return new_ov; } PHP_MINIT_FUNCTION(layer) { zend_class_entry ce; memcpy(&mapscript_layer_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_layer_object_handlers.clone_obj = mapscript_layer_object_clone; MAPSCRIPT_REGISTER_CLASS("layerObj", layer_functions, mapscript_ce_layer, mapscript_layer_object_new); mapscript_ce_layer->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/legend.c000066400000000000000000000266201357574274700177570ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_legend_object_handlers; #endif zend_class_entry *mapscript_ce_legend; ZEND_BEGIN_ARG_INFO_EX(legend___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(legend___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(legend_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() /* {{{ proto legend __construct() legendObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(legendObj, __construct) { mapscript_throw_exception("legendObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(legendObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_legend_object *php_legend; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = MAPSCRIPT_OBJ_P(php_legend_object, zobj); IF_GET_LONG("height", php_legend->legend->height) else IF_GET_LONG("width", php_legend->legend->width) else IF_GET_LONG("keysizex", php_legend->legend->keysizex) else IF_GET_LONG("keysizey", php_legend->legend->keysizey) else IF_GET_LONG("keyspacingx", php_legend->legend->keyspacingx) else IF_GET_LONG("keyspacingy", php_legend->legend->keyspacingy) else IF_GET_LONG("status", php_legend->legend->status) else IF_GET_LONG("position", php_legend->legend->position) else IF_GET_LONG("postlabelcache", php_legend->legend->postlabelcache) else IF_GET_STRING("template", php_legend->legend->template) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_legend->outlinecolor, &php_legend->legend->outlinecolor) else IF_GET_OBJECT("label", mapscript_ce_label, php_legend->label, &php_legend->legend->label) else IF_GET_OBJECT("imagecolor", mapscript_ce_color, php_legend->imagecolor, &php_legend->legend->imagecolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(legendObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_legend_object *php_legend; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = MAPSCRIPT_OBJ_P(php_legend_object, zobj); IF_SET_LONG("height", php_legend->legend->height, value) else IF_SET_LONG("width", php_legend->legend->width, value) else IF_SET_LONG("keysizex", php_legend->legend->keysizex, value) else IF_SET_LONG("keysizey", php_legend->legend->keysizey, value) else IF_SET_LONG("keyspacingx", php_legend->legend->keyspacingx, value) else IF_SET_LONG("keyspacingy", php_legend->legend->keyspacingy, value) else IF_SET_LONG("status", php_legend->legend->status, value) else IF_SET_LONG("position", php_legend->legend->position, value) else IF_SET_LONG("postlabelcache", php_legend->legend->postlabelcache, value) else IF_SET_STRING("template", php_legend->legend->template, value) else if ( (STRING_EQUAL("outlinecolor", property)) || (STRING_EQUAL("imagecolor", property)) || (STRING_EQUAL("label", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int legend.updateFromString(string snippet) Update a legend from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(legendObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_legend_object *php_legend; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = MAPSCRIPT_OBJ_P(php_legend_object, zobj); status = legendObj_updateFromString(php_legend->legend, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the legend object to string. */ PHP_METHOD(legendObj, convertToString) { zval *zobj = getThis(); php_legend_object *php_legend; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = MAPSCRIPT_OBJ_P(php_legend_object, zobj); value = legendObj_convertToString(php_legend->legend); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int legend.free() Free the object */ PHP_METHOD(legendObj, free) { zval *zobj = getThis(); php_legend_object *php_legend; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_legend = MAPSCRIPT_OBJ_P(php_legend_object, zobj); MAPSCRIPT_DELREF(php_legend->outlinecolor); MAPSCRIPT_DELREF(php_legend->imagecolor); MAPSCRIPT_DELREF(php_legend->label); } /* }}} */ zend_function_entry legend_functions[] = { PHP_ME(legendObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(legendObj, __get, legend___get_args, ZEND_ACC_PUBLIC) PHP_ME(legendObj, __set, legend___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(legendObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(legendObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(legendObj, updateFromString, legend_updateFromString_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_legend(legendObj *legend, parent_object parent, zval *return_value TSRMLS_DC) { php_legend_object * php_legend; object_init_ex(return_value, mapscript_ce_legend); php_legend = MAPSCRIPT_OBJ_P(php_legend_object, return_value); php_legend->legend = legend; php_legend->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_legend_create_object(zend_class_entry *ce TSRMLS_DC) { php_legend_object *php_legend; php_legend = ecalloc(1, sizeof(*php_legend) + zend_object_properties_size(ce)); zend_object_std_init(&php_legend->zobj, ce TSRMLS_CC); object_properties_init(&php_legend->zobj, ce); php_legend->zobj.handlers = &mapscript_legend_object_handlers; MAPSCRIPT_INIT_PARENT(php_legend->parent); ZVAL_UNDEF(&php_legend->outlinecolor); ZVAL_UNDEF(&php_legend->imagecolor); ZVAL_UNDEF(&php_legend->label); return &php_legend->zobj; } static void mapscript_legend_free_object(zend_object *object) { php_legend_object *php_legend; php_legend = (php_legend_object *)((char *)object - XtOffsetOf(php_legend_object, zobj)); MAPSCRIPT_FREE_PARENT(php_legend->parent); MAPSCRIPT_DELREF(php_legend->outlinecolor); MAPSCRIPT_DELREF(php_legend->imagecolor); MAPSCRIPT_DELREF(php_legend->label); /* We don't need to free the legendObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(legend) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "legendObj", legend_functions); mapscript_ce_legend = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_legend->create_object = mapscript_legend_create_object; mapscript_ce_legend->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_legend_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_legend_object_handlers)); mapscript_legend_object_handlers.free_obj = mapscript_legend_free_object; mapscript_legend_object_handlers.offset = XtOffsetOf(php_legend_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_legend_object_destroy(void *object TSRMLS_DC) { php_legend_object *php_legend = (php_legend_object *)object; MAPSCRIPT_FREE_OBJECT(php_legend); MAPSCRIPT_FREE_PARENT(php_legend->parent); MAPSCRIPT_DELREF(php_legend->outlinecolor); MAPSCRIPT_DELREF(php_legend->imagecolor); MAPSCRIPT_DELREF(php_legend->label); /* We don't need to free the legendObj */ efree(object); } static zend_object_value mapscript_legend_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_legend_object *php_legend; MAPSCRIPT_ALLOC_OBJECT(php_legend, php_legend_object); retval = mapscript_object_new(&php_legend->std, ce, &mapscript_legend_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_legend->parent); php_legend->outlinecolor = NULL; php_legend->imagecolor = NULL; php_legend->label = NULL; return retval; } PHP_MINIT_FUNCTION(legend) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("legendObj", legend_functions, mapscript_ce_legend, mapscript_legend_object_new); mapscript_ce_legend->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/line.c000066400000000000000000000350161357574274700174470ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_line; zend_object_handlers mapscript_line_object_handlers; ZEND_BEGIN_ARG_INFO_EX(line___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_add_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_set_args, 0, 0, 2) ZEND_ARG_INFO(0, index) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_addXY_args, 0, 0, 2) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_ARG_INFO(0, m) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_addXYZ_args, 0, 0, 3) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_ARG_INFO(0, z) ZEND_ARG_INFO(0, m) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_project_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, projIn, projectionObj, 0) ZEND_ARG_OBJ_INFO(0, projOut, projectionObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(line_point_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() /* {{{ proto line __construct() Create a new lineObj instance. */ PHP_METHOD(lineObj, __construct) { php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = MAPSCRIPT_OBJ_P(php_line_object, getThis()); if ((php_line->line = lineObj_new()) == NULL) { mapscript_throw_exception("Unable to construct lineObj." TSRMLS_CC); return; } } /* }}} */ PHP_METHOD(lineObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = MAPSCRIPT_OBJ_P(php_line_object, zobj); IF_GET_LONG("numpoints", php_line->line->numpoints) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(lineObj, __set) { char *property; long property_len = 0; zval *value; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if (STRING_EQUAL("numpoints", property)) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int line.add(pointObj point) Adds a point to the end of a line */ PHP_METHOD(lineObj, add) { zval *zobj = getThis(); zval *zobj_point; php_line_object *php_line; php_point_object *php_point; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobj_point, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = MAPSCRIPT_OBJ_P(php_line_object, zobj); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj_point); status = lineObj_add(php_line->line, php_point->point); RETURN_LONG(status); } /* }}} */ /* {{{ proto int line.addXY(double x, double y, double m) 3rd argument m is used for Measured shape files. It is not mandatory. Adds a point to the end of a line */ PHP_METHOD(lineObj, addXY) { zval *zobj = getThis(); pointObj point; double x, y, m = 0; int status = MS_FAILURE; php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|d", &x, &y, &m) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = MAPSCRIPT_OBJ_P(php_line_object, zobj); point.x = x; point.y = y; #ifdef USE_LINE_Z_M point.z = 0; point.m = m; #endif status = lineObj_add(php_line->line, &point); RETURN_LONG(status); } /* }}} */ /* {{{ proto int line.addXYZ(double x, double y, double z, double m) 4th argument m is used for Measured shape files. It is not mandatory. Adds a point to the end of a line */ PHP_METHOD(lineObj, addXYZ) { zval *zobj = getThis(); pointObj point; double x, y, z, m = 0; int status = MS_FAILURE; php_line_object *php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd|d", &x, &y, &z, &m) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = MAPSCRIPT_OBJ_P(php_line_object, zobj); point.x = x; point.y = y; #ifdef USE_LINE_Z_M point.z = z; point.m = m; #endif status = lineObj_add(php_line->line, &point); RETURN_LONG(status); } /* }}} */ /* {{{ proto int line.project(projectionObj in, projectionObj out) Project the point. returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(lineObj, project) { zval *zobj_proj_in, *zobj_proj_out; zval *zobj = getThis(); php_line_object *php_line; php_projection_object *php_proj_in, *php_proj_out; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_proj_in, mapscript_ce_projection, &zobj_proj_out, mapscript_ce_projection) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = MAPSCRIPT_OBJ_P(php_line_object, zobj); php_proj_in = MAPSCRIPT_OBJ_P(php_projection_object, zobj_proj_in); php_proj_out = MAPSCRIPT_OBJ_P(php_projection_object, zobj_proj_out); status = lineObj_project(php_line->line, php_proj_in->projection, php_proj_out->projection); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int line.point(int i) Returns point number i. First point is number 0. */ PHP_METHOD(lineObj, point) { zval *zobj = getThis(); php_line_object *php_line; long index; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = MAPSCRIPT_OBJ_P(php_line_object, zobj); if ( (index < 0) || (index >= php_line->line->numpoints)) { mapscript_throw_exception("Point '%d' does not exist in this object." TSRMLS_CC, index); return; } MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_point(&(php_line->line->point[index]), parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int line.set(int, index, pointObj point) Set the point values at the specified index */ PHP_METHOD(lineObj, set) { zval *zobj = getThis(); zval *zobj_point; long index; php_line_object *php_line; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lO", &index, &zobj_point, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_line = MAPSCRIPT_OBJ_P(php_line_object, zobj); if ( (index < 0) || (index >= php_line->line->numpoints)) { mapscript_throw_exception("Point '%d' does not exist in this object." TSRMLS_CC, index); return; } php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj_point); php_line->line->point[index].x = php_point->point->x; php_line->line->point[index].y = php_point->point->y; RETURN_LONG(MS_SUCCESS); } /* }}} */ zend_function_entry line_functions[] = { PHP_ME(lineObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(lineObj, __get, line___get_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, __set, line___set_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, add, line_add_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, addXY, line_addXY_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, addXYZ, line_addXYZ_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, project, line_project_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, point, line_point_args, ZEND_ACC_PUBLIC) PHP_MALIAS(lineObj, get, point, line_point_args, ZEND_ACC_PUBLIC) PHP_ME(lineObj, set, line_set_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_line(lineObj *line, parent_object parent, zval *return_value TSRMLS_DC) { php_line_object * php_line; object_init_ex(return_value, mapscript_ce_line); php_line = MAPSCRIPT_OBJ_P(php_line_object, return_value); php_line->line = line; if (ZVAL_NOT_UNDEF(parent.val)) php_line->is_ref = 1; php_line->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_line_create_object(zend_class_entry *ce TSRMLS_DC) { php_line_object *php_line; php_line = ecalloc(1, sizeof(*php_line) + zend_object_properties_size(ce)); zend_object_std_init(&php_line->zobj, ce TSRMLS_CC); object_properties_init(&php_line->zobj, ce); php_line->zobj.handlers = &mapscript_line_object_handlers; MAPSCRIPT_INIT_PARENT(php_line->parent); php_line->is_ref = 0; return &php_line->zobj; } static void mapscript_line_free_object(zend_object *object) { php_line_object *php_line; php_line = (php_line_object *)((char *)object - XtOffsetOf(php_line_object, zobj)); MAPSCRIPT_FREE_PARENT(php_line->parent); if (php_line->line && !php_line->is_ref) { lineObj_destroy(php_line->line); } zend_object_std_dtor(object); } static zend_object* mapscript_line_clone_object(zval *zobj) { php_line_object *php_line_old, *php_line_new; zend_object* zobj_new; php_line_old = MAPSCRIPT_OBJ_P(php_line_object, zobj); zobj_new = mapscript_line_create_object(mapscript_ce_line); php_line_new = (php_line_object *)((char *)zobj_new - XtOffsetOf(php_line_object, zobj)); zend_objects_clone_members(&php_line_new->zobj, &php_line_old->zobj); php_line_new->line = lineObj_clone(php_line_old->line); return zobj_new; } PHP_MINIT_FUNCTION(line) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "lineObj", line_functions); mapscript_ce_line = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_line->create_object = mapscript_line_create_object; mapscript_ce_line->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_line_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_line_object_handlers)); mapscript_line_object_handlers.free_obj = mapscript_line_free_object; mapscript_line_object_handlers.clone_obj = mapscript_line_clone_object; mapscript_line_object_handlers.offset = XtOffsetOf(php_line_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_line_object_destroy(void *object TSRMLS_DC) { php_line_object *php_line = (php_line_object *)object; MAPSCRIPT_FREE_OBJECT(php_line); MAPSCRIPT_FREE_PARENT(php_line->parent); if (php_line->line && !php_line->is_ref) { lineObj_destroy(php_line->line); } efree(object); } static zend_object_value mapscript_line_object_new_ex(zend_class_entry *ce, php_line_object **ptr TSRMLS_DC) { zend_object_value retval; php_line_object *php_line; MAPSCRIPT_ALLOC_OBJECT(php_line, php_line_object); retval = mapscript_object_new_ex(&php_line->std, ce, &mapscript_line_object_destroy, &mapscript_line_object_handlers TSRMLS_CC); if (ptr) *ptr = php_line; php_line->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_line->parent); return retval; } static zend_object_value mapscript_line_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_line_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_line_object_clone(zval *zobj TSRMLS_DC) { php_line_object *php_line_old, *php_line_new; zend_object_value new_ov; php_line_old = MAPSCRIPT_OBJ_P(php_line_object, zobj); new_ov = mapscript_line_object_new_ex(mapscript_ce_line, &php_line_new TSRMLS_CC); zend_objects_clone_members(&php_line_new->std, new_ov, &php_line_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_line_new->line = lineObj_clone(php_line_old->line); return new_ov; } PHP_MINIT_FUNCTION(line) { zend_class_entry ce; memcpy(&mapscript_line_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_line_object_handlers.clone_obj = mapscript_line_object_clone; MAPSCRIPT_REGISTER_CLASS("lineObj", line_functions, mapscript_ce_line, mapscript_line_object_new); mapscript_ce_line->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/map.c000066400000000000000000003656641357574274700173140ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_map; zend_object_handlers mapscript_map_object_handlers; static int mapscript_map_setProjection(int isWKTProj, php_map_object *php_map, char *projString, int setUnitsAndExtents TSRMLS_DC); ZEND_BEGIN_ARG_INFO_EX(map___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, mapFileName) ZEND_ARG_INFO(0, newMapPath) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getSymbolByName_args, 0, 0, 1) ZEND_ARG_INFO(0, symbolName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getSymbolObjectById_args, 0, 0, 1) ZEND_ARG_INFO(0, symbolId) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_embedLegend_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_embedScaleBar_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_drawLabelCache_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getLayer_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getLayerByName_args, 0, 0, 1) ZEND_ARG_INFO(0, layerName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getColorByIndex_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setExtent_args, 0, 0, 4) ZEND_ARG_INFO(0, minx) ZEND_ARG_INFO(0, miny) ZEND_ARG_INFO(0, maxx) ZEND_ARG_INFO(0, maxy) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setCenter_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_offsetExtent_args, 0, 0, 2) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_scaleExtent_args, 0, 0, 3) ZEND_ARG_INFO(0, zoomFactor) ZEND_ARG_INFO(0, minScaleDenom) ZEND_ARG_INFO(0, maxScaleDenom) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setRotation_args, 0, 0, 1) ZEND_ARG_INFO(0, angle) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setSize_args, 0, 0, 2) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_zoomPoint_args, 0, 0, 5) ZEND_ARG_INFO(0, zoomFactor) ZEND_ARG_OBJ_INFO(0, pixelPosition, pointObj, 0) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_ARG_OBJ_INFO(0, geoRefExtent, rectObj, 0) ZEND_ARG_OBJ_INFO(0, maxGeoRefExtent, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_zoomRectangle_args, 0, 0, 4) ZEND_ARG_OBJ_INFO(0, pixelExtent, rectObj, 0) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_ARG_OBJ_INFO(0, geoRefExtent, rectObj, 0) ZEND_ARG_OBJ_INFO(0, maxGeoRefExtent, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_zoomScale_args, 0, 0, 5) ZEND_ARG_INFO(0, scaleDenom) ZEND_ARG_OBJ_INFO(0, pixelPosition, pointObj, 0) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_ARG_OBJ_INFO(0, geoRefExtent, rectObj, 0) ZEND_ARG_OBJ_INFO(0, maxGeoRefExtent, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByPoint_args, 0, 0, 3) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_ARG_INFO(0, mode) ZEND_ARG_INFO(0, buffer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByRect_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, rect, rectObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByFeatures_args, 0, 0, 1) ZEND_ARG_INFO(0, slayer) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByIndex_args, 0, 0, 3) ZEND_ARG_INFO(0, layerIndex) ZEND_ARG_INFO(0, tileIndex) ZEND_ARG_INFO(0, shapeIndex) ZEND_ARG_INFO(0, addToQuery) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_queryByFilter_args, 0, 0, 1) ZEND_ARG_INFO(0, string) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_saveQuery_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, results) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_saveQueryAsGML_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, namespace) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_loadQuery_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_freeQuery_args, 0, 0, 1) ZEND_ARG_INFO(0, layerIndex) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_save_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, projectionParams) ZEND_ARG_INFO(0, setUnitsAndExtents) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setWKTProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, projectionParams) ZEND_ARG_INFO(0, setUnitsAndExtents) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setMetaData_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_removeMetaData_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getLayersIndexByGroup_args, 0, 0, 1) ZEND_ARG_INFO(0, groupName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_moveLayerUp_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_moveLayerDown_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setLayersDrawingOrder_args, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, layerIndexes, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_processTemplate_args, 0, 0, 2) ZEND_ARG_ARRAY_INFO(0, params, 0) ZEND_ARG_INFO(0, generateImages) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_processQueryTemplate_args, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, params, 0) ZEND_ARG_INFO(0, generateImages) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_processLegendTemplate_args, 0, 0, 1) ZEND_ARG_ARRAY_INFO(0, params, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setSymbolSet_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setFontSet_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_selectOutputFormat_args, 0, 0, 1) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_appendOutputFormat_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, outputformat, outputFormatObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_removeOutputFormat_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getOutputFormat_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_saveMapContext_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_loadMapContext_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, uniqueLayerName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_applySLD_args, 0, 0, 1) ZEND_ARG_INFO(0, sldxml) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_applySLDURL_args, 0, 0, 1) ZEND_ARG_INFO(0, sldurl) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_getConfigOption_args, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_setConfigOption_args, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_loadOwsParameters_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, request, owsRequestObj, 0) ZEND_ARG_INFO(0, version) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_owsDispatch_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, request, owsRequestObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_insertLayer_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(map_removeLayer_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() #ifdef disabled ZEND_BEGIN_ARG_INFO_EX(map_getLabel_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() #endif /* {{{ proto void __construct(string mapFileName, newMapPath) Create a new mapObj instance. */ PHP_METHOD(mapObj, __construct) { zval *zobj = getThis(); char *filename; long filename_len = 0; char *path = NULL; long path_len = 0; mapObj *map; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &filename, &filename_len, &path, &path_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); map = mapObj_new(filename, path); if (map == NULL) { mapscript_throw_mapserver_exception("Failed to open map file %s" TSRMLS_CC, filename); return; } php_map->map = map; } /* }}} */ PHP_METHOD(mapObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); IF_GET_LONG("numlayers", php_map->map->numlayers) else IF_GET_STRING("name", php_map->map->name) else IF_GET_STRING("mappath", php_map->map->mappath) else IF_GET_STRING("imagetype", php_map->map->imagetype) else IF_GET_LONG("status", php_map->map->status) else IF_GET_LONG("debug", php_map->map->debug) else IF_GET_LONG("width", php_map->map->width) else IF_GET_LONG("height", php_map->map->height) else IF_GET_LONG("maxsize", php_map->map->maxsize) else IF_GET_DOUBLE("resolution", php_map->map->resolution) else IF_GET_DOUBLE("defresolution", php_map->map->defresolution) else IF_GET_DOUBLE("cellsize", php_map->map->cellsize) else IF_GET_LONG("units", php_map->map->units) else IF_GET_DOUBLE("scaledenom", php_map->map->scaledenom) else IF_GET_STRING("shapepath", php_map->map->shapepath) else IF_GET_LONG("keysizex", php_map->map->legend.keysizex) else IF_GET_LONG("keysizey", php_map->map->legend.keysizey) else IF_GET_LONG("keyspacingx", php_map->map->legend.keyspacingx) else IF_GET_LONG("keyspacingy", php_map->map->legend.keyspacingy) else IF_GET_STRING("symbolsetfilename", php_map->map->symbolset.filename) else IF_GET_LONG("numoutputformats", php_map->map->numoutputformats) else IF_GET_STRING("fontsetfilename", php_map->map->fontset.filename) else IF_GET_OBJECT("outputformat", mapscript_ce_outputformat, php_map->outputformat, php_map->map->outputformat) else IF_GET_OBJECT("configoptions", mapscript_ce_hashtable, php_map->configoptions, &php_map->map->configoptions) else IF_GET_OBJECT("extent", mapscript_ce_rect, php_map->extent, &php_map->map->extent) else IF_GET_OBJECT("web", mapscript_ce_web, php_map->web, &php_map->map->web) else IF_GET_OBJECT("reference", mapscript_ce_referencemap, php_map->reference, &php_map->map->reference) else IF_GET_OBJECT("imagecolor", mapscript_ce_color, php_map->imagecolor, &php_map->map->imagecolor) else IF_GET_OBJECT("scalebar", mapscript_ce_scalebar, php_map->scalebar, &php_map->map->scalebar) else IF_GET_OBJECT("legend", mapscript_ce_legend, php_map->legend, &php_map->map->legend) else IF_GET_OBJECT("querymap", mapscript_ce_querymap, php_map->querymap, &php_map->map->querymap) #ifdef disabled else IF_GET_OBJECT("labelcache", mapscript_ce_labelcache, php_map->labelcache, &php_map->map->labelcache) #endif else IF_GET_OBJECT("projection", mapscript_ce_projection, php_map->projection, &php_map->map->projection) else IF_GET_OBJECT("metadata", mapscript_ce_hashtable, php_map->metadata, &php_map->map->web.metadata) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(mapObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); IF_SET_STRING("name", php_map->map->name, value) else IF_SET_LONG("status", php_map->map->status, value) else IF_SET_LONG("debug", php_map->map->debug, value) else IF_SET_LONG("width", php_map->map->width, value) else IF_SET_LONG("height", php_map->map->height, value) else IF_SET_LONG("maxsize", php_map->map->maxsize, value) else IF_SET_DOUBLE("resolution", php_map->map->resolution, value) else IF_SET_DOUBLE("defresolution", php_map->map->defresolution, value) else IF_SET_DOUBLE("cellsize", php_map->map->cellsize, value) else IF_SET_LONG("units", php_map->map->units, value) else IF_SET_DOUBLE("scaledenom", php_map->map->scaledenom, value) else IF_SET_STRING("shapepath", php_map->map->shapepath, value) else IF_SET_LONG("keysizex", php_map->map->legend.keysizex, value) else IF_SET_LONG("keysizey", php_map->map->legend.keysizey, value) else IF_SET_LONG("keyspacingx", php_map->map->legend.keyspacingx, value) else IF_SET_LONG("keyspacingy", php_map->map->legend.keyspacingy, value) else if ( (STRING_EQUAL("outputformat", property)) || (STRING_EQUAL("extent", property)) || (STRING_EQUAL("web", property)) || (STRING_EQUAL("reference", property)) || (STRING_EQUAL("scalebar", property)) || (STRING_EQUAL("legend", property)) || (STRING_EQUAL("querymap", property)) || #ifdef disabled (STRING_EQUAL("labelcache", property)) || #endif (STRING_EQUAL("projection", property)) || (STRING_EQUAL("metadata", property)) || (STRING_EQUAL("configoptions", property)) || (STRING_EQUAL("imagecolor", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if ( (STRING_EQUAL("numlayers", property)) || (STRING_EQUAL("symbolsetfilename", property)) || (STRING_EQUAL("imagetype", property)) || (STRING_EQUAL("numoutputformats", property)) || (STRING_EQUAL("mappath", property)) || (STRING_EQUAL("fontsetfilename", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int map.getSymbolByName(string symbolName) Returns the symbol index using the name. */ PHP_METHOD(mapObj, getSymbolByName) { zval *zobj = getThis(); char *symbolName; long symbolName_len = 0; int symbolId = -1; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &symbolName, &symbolName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); symbolId = mapObj_getSymbolByName(php_map->map, symbolName); RETURN_LONG(symbolId); } /* }}} */ /* {{{ proto symbolObj map.getSymbolObjectById(int symbolId) Returns the symbol object using a symbol id. Refer to the symbol object reference section for more details. */ PHP_METHOD(mapObj, getSymbolObjectById) { zval *zobj = getThis(); long symbolId; symbolObj *symbol = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &symbolId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if ( symbolId < 0 || symbolId >= php_map->map->symbolset.numsymbols) { mapscript_throw_exception("Invalid symbol index." TSRMLS_CC); return; } symbol = php_map->map->symbolset.symbol[symbolId]; /* Return style object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_symbol(symbol, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto void map.prepareQuery() Calculate the scale of the map and assign it to the map->scaledenom */ PHP_METHOD(mapObj, prepareQuery) { zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); mapObj_prepareQuery(php_map->map); } /* }}} */ /* {{{ proto imageObj map.prepareImage() Return handle on blank image object. */ PHP_METHOD(mapObj, prepareImage) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); image = mapObj_prepareImage(php_map->map); if (image == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return an image object */ mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto imageObj map.draw() Render map and return handle on image object. */ PHP_METHOD(mapObj, draw) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); image = mapObj_draw(php_map->map); if (image == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.drawQuery() Renders a query map, returns an image.. */ PHP_METHOD(mapObj, drawQuery) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); image = mapObj_drawQuery(php_map->map); if (image == NULL) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.drawLegend() Render legend and return handle on image object. */ PHP_METHOD(mapObj, drawLegend) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); image = mapObj_drawLegend(php_map->map); if (image == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.drawReferenceMap() Render reference map and return handle on image object. */ PHP_METHOD(mapObj, drawReferenceMap) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); image = mapObj_drawReferenceMap(php_map->map); if (image == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.drawScaleBar() Render scale bar and return handle on image object. */ PHP_METHOD(mapObj, drawScaleBar) { zval *zobj = getThis(); imageObj *image = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); image = mapObj_drawScalebar(php_map->map); if (image == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.embedLegend(image img) Renders the legend within the map. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, embedLegend) { zval *zobj = getThis(); zval *zimage; int retval = MS_FAILURE; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); retval = mapObj_embedLegend(php_map->map, php_image->image); if ( (retval == MS_FAILURE) || (retval == -1) ) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(retval); } /* }}} */ /* {{{ proto int map.embedScalebar(image img) Renders the scalebar within the map. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, embedScaleBar) { zval *zobj = getThis(); zval *zimage; int retval = MS_FAILURE; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); retval = mapObj_embedScalebar(php_map->map, php_image->image); if ( (retval == MS_FAILURE) || (retval == -1) ) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(retval); } /* }}} */ /* {{{ proto layerObj map.drawLabelCache(image img) Renders the labels for a map. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, drawLabelCache) { zval *zobj = getThis(); zval *zimage; int retval = MS_FAILURE; php_map_object *php_map; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); retval = mapObj_drawLabelCache(php_map->map, php_image->image); if ( (retval == MS_FAILURE) || (retval == -1) ) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(retval); } /* }}} */ /* {{{ proto int map.getLayer(int index) Returns a layerObj from the map given an index value (0=first layer, etc.) */ PHP_METHOD(mapObj, getLayer) { zval *zobj = getThis(); long index; layerObj *layer = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); layer = mapObj_getLayer(php_map->map, index); if (layer == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return layer object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_layer(layer, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto layerObj map.getLayerByName(string layerName) Returns a layerObj from the map given a layer name */ PHP_METHOD(mapObj, getLayerByName) { zval *zobj = getThis(); char *layerName; long layerName_len = 0; layerObj *layer = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &layerName, &layerName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); layer = mapObj_getLayerByName(php_map->map, layerName); if (layer == NULL) { mapscript_report_php_error(E_WARNING, "getLayerByName failed for : %s\n" TSRMLS_CC, layerName); RETURN_NULL(); } /* Return layer object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_layer(layer, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto colorObj map.getColorByIndex(int index) Returns a colorObj from the map given a color index */ PHP_METHOD(mapObj, getColorByIndex) { zval *zobj = getThis(); long index; paletteObj palette; colorObj color; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); palette = php_map->map->palette; if (index < palette.numcolors) { color.red = palette.colors[index].red; color.green = palette.colors[index].green; color.blue = palette.colors[index].blue; } else { mapscript_throw_mapserver_exception("Index should not be higher than %d\n" TSRMLS_CC, palette.numcolors-1); return; } /* Return color object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_color(&color, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.setextent(double minx, double miny, double maxx, double maxy) Set map extent property to new value. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, setExtent) { zval *zobj = getThis(); double minx, miny, maxx, maxy; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddd", &minx, &miny, &maxx, &maxy) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = msMapSetExtent( php_map->map, minx, miny, maxx, maxy); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.setCenter(pointObj center) Returns MS_SUCCESS or MS_FAILURE */ PHP_METHOD(mapObj, setCenter) { zval *zobj = getThis(); zval *zpoint; int status = MS_FAILURE; php_map_object *php_map; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_point = MAPSCRIPT_OBJ_P(php_point_object, zpoint); status = mapObj_setCenter(php_map->map, php_point->point); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.offsetExtent(double x, double y) Returns MS_SUCCESS or MS_FAILURE */ PHP_METHOD(mapObj, offsetExtent) { zval *zobj = getThis(); double x, y; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &x, &y) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_offsetExtent(php_map->map, x, y); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.scaleExtent(double zoomfactor, double minscaledenom, double maxscaledenom) Returns MS_SUCCESS or MS_FAILURE */ PHP_METHOD(mapObj, scaleExtent) { zval *zobj = getThis(); double zoomFactor, minScaleDenom, maxScaleDenom; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd", &zoomFactor, &minScaleDenom, &maxScaleDenom) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_scaleExtent(php_map->map, zoomFactor, minScaleDenom, maxScaleDenom); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.setRotation(double angle) Set map rotation angle. The map view rectangle (specified in EXTENTS) will be rotated by the indicated angle in the counter-clockwise direction. Note that this implies the rendered map will be rotated by the angle in the clockwise direction. */ PHP_METHOD(mapObj, setRotation) { zval *zobj = getThis(); double angle; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &angle) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_setRotation(php_map->map, angle); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.setSize(int width, int height) Set map size (width, height) properties to new values and upddate internal geotransform. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, setSize) { zval *zobj = getThis(); long width, height; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = msMapSetSize(php_map->map, width, height); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int zoompoint(int zoomFactor, pointObj pixelPosition, int width, int height, rectObj geoRefExtent, [rectObj mapGeoRefExtent]) Zoom to a given XY postion. */ PHP_METHOD(mapObj, zoomPoint) { zval *zobj = getThis(); zval *zpoint, *zgeoRefExtent, *zmaxGeoRefExtent = NULL; long zoomFactor, width, height; double dfGeoPosX, dfGeoPosY; double dfDeltaX, dfDeltaY; rectObj newGeoRefExtent; double dfNewScale = 0.0; double dfDeltaExt = -1.0; php_point_object *php_pixelPosition; php_rect_object *php_geoRefExtent=NULL, *php_maxGeoRefExtent=NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lOllO|O", &zoomFactor, &zpoint, mapscript_ce_point, &width, &height, &zgeoRefExtent , mapscript_ce_rect, &zmaxGeoRefExtent , mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_pixelPosition = MAPSCRIPT_OBJ_P(php_point_object, zpoint); php_geoRefExtent = MAPSCRIPT_OBJ_P(php_rect_object, zgeoRefExtent); if (zmaxGeoRefExtent) php_maxGeoRefExtent = MAPSCRIPT_OBJ_P(php_rect_object, zmaxGeoRefExtent); /* -------------------------------------------------------------------- */ /* check the validity of the parameters. */ /* -------------------------------------------------------------------- */ if (zoomFactor == 0 || width <= 0 || height <= 0 || php_geoRefExtent->rect == NULL || php_pixelPosition->point == NULL || (zmaxGeoRefExtent && php_maxGeoRefExtent->rect == NULL)) { mapscript_throw_mapserver_exception("Incorrect parameters\n" TSRMLS_CC); return; } /* -------------------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* -------------------------------------------------------------------- */ if (php_geoRefExtent->rect->minx >= php_geoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_geoRefExtent->rect->miny >= php_geoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } if (zmaxGeoRefExtent) { if (php_maxGeoRefExtent->rect->minx >= php_maxGeoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_maxGeoRefExtent->rect->miny >= php_maxGeoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } } dfGeoPosX = Pix2Georef((int)php_pixelPosition->point->x, 0, width, php_geoRefExtent->rect->minx, php_geoRefExtent->rect->maxx, 0); dfGeoPosY = Pix2Georef((int)php_pixelPosition->point->y, 0, height, php_geoRefExtent->rect->miny, php_geoRefExtent->rect->maxy, 1); dfDeltaX = php_geoRefExtent->rect->maxx - php_geoRefExtent->rect->minx; dfDeltaY = php_geoRefExtent->rect->maxy - php_geoRefExtent->rect->miny; /* -------------------------------------------------------------------- */ /* zoom in */ /* -------------------------------------------------------------------- */ if (zoomFactor > 1) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaX/(2*zoomFactor)); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaY/(2*zoomFactor)); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaX/(2*zoomFactor)); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaY/(2*zoomFactor)); } if (zoomFactor < 0) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaX/2)*(abs(zoomFactor)); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaY/2)*(abs(zoomFactor)); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaX/2)*(abs(zoomFactor)); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaY/2)*(abs(zoomFactor)); } if (zoomFactor == 1) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaX/2); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaY/2); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaX/2); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaY/2); } /* -------------------------------------------------------------------- */ /* if the min and max scale are set in the map file, we will */ /* use them to test before zooming. */ /* -------------------------------------------------------------------- */ msAdjustExtent(&newGeoRefExtent, php_map->map->width, php_map->map->height); if (msCalculateScale(newGeoRefExtent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &dfNewScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_map->map->web.maxscaledenom > 0) { if (zoomFactor < 0 && dfNewScale > php_map->map->web.maxscaledenom) { RETURN_LONG(MS_FAILURE); } } /* ==================================================================== */ /* we do a spcial case for zoom in : we try to zoom as much as */ /* possible using the mincale set in the .map. */ /* ==================================================================== */ if (php_map->map->web.minscaledenom > 0 && dfNewScale < php_map->map->web.minscaledenom && zoomFactor > 1) { dfDeltaExt = GetDeltaExtentsUsingScale(php_map->map->web.minscaledenom, php_map->map->units, dfGeoPosY, php_map->map->width, php_map->map->resolution); if (dfDeltaExt > 0.0) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaExt/2); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaExt/2); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaExt/2); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaExt/2); } else RETURN_LONG(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* -------------------------------------------------------------------- */ if (zmaxGeoRefExtent) { dfDeltaX = newGeoRefExtent.maxx - newGeoRefExtent.minx; dfDeltaY = newGeoRefExtent.maxy - newGeoRefExtent.miny; /* Make sure Current georef extents is not bigger than max extents */ if (dfDeltaX > (php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx)) dfDeltaX = php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx; if (dfDeltaY > (php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny)) dfDeltaY = php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny; if (newGeoRefExtent.minx < php_maxGeoRefExtent->rect->minx) { newGeoRefExtent.minx = php_maxGeoRefExtent->rect->minx; newGeoRefExtent.maxx = newGeoRefExtent.minx + dfDeltaX; } if (newGeoRefExtent.maxx > php_maxGeoRefExtent->rect->maxx) { newGeoRefExtent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (newGeoRefExtent.miny < php_maxGeoRefExtent->rect->miny) { newGeoRefExtent.miny = php_maxGeoRefExtent->rect->miny; newGeoRefExtent.maxy = newGeoRefExtent.miny + dfDeltaY; } if (newGeoRefExtent.maxy > php_maxGeoRefExtent->rect->maxy) { newGeoRefExtent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } /* -------------------------------------------------------------------- */ /* set the map extents with new values. */ /* -------------------------------------------------------------------- */ php_map->map->extent.minx = newGeoRefExtent.minx; php_map->map->extent.miny = newGeoRefExtent.miny; php_map->map->extent.maxx = newGeoRefExtent.maxx; php_map->map->extent.maxy = newGeoRefExtent.maxy; php_map->map->cellsize = msAdjustExtent(&(php_map->map->extent), php_map->map->width, php_map->map->height); dfDeltaX = php_map->map->extent.maxx - php_map->map->extent.minx; dfDeltaY = php_map->map->extent.maxy - php_map->map->extent.miny; if (zmaxGeoRefExtent) { if (php_map->map->extent.minx < php_maxGeoRefExtent->rect->minx) { php_map->map->extent.minx = php_maxGeoRefExtent->rect->minx; php_map->map->extent.maxx = php_map->map->extent.minx + dfDeltaX; } if (php_map->map->extent.maxx > php_maxGeoRefExtent->rect->maxx) { php_map->map->extent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (php_map->map->extent.miny < php_maxGeoRefExtent->rect->miny) { php_map->map->extent.miny = php_maxGeoRefExtent->rect->miny; php_map->map->extent.maxy = php_map->map->extent.miny + dfDeltaY; } if (php_map->map->extent.maxy > php_maxGeoRefExtent->rect->maxy) { php_map->map->extent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } if (msCalculateScale(php_map->map->extent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &(php_map->map->scaledenom)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int zoomRectangle(rectObj pixelExtent, int width, int height, rectObj geoRefExtent [, rectObj geoRefExtent]) Set the map extents to a given extents.*/ PHP_METHOD(mapObj, zoomRectangle) { zval *zobj = getThis(); zval *zpixelExtent, *zgeoRefExtent, *zmaxGeoRefExtent = NULL; long width, height; double dfDeltaX, dfDeltaY; rectObj newGeoRefExtent; double dfNewScale = 0.0; double dfDeltaExt = -1.0; double dfMiddleX =0.0; double dfMiddleY =0.0; php_rect_object *php_geoRefExtent=NULL, *php_maxGeoRefExtent=NULL, *php_pixelExtent=NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OllO|O", &zpixelExtent , mapscript_ce_rect, &width, &height, &zgeoRefExtent , mapscript_ce_rect, &zmaxGeoRefExtent , mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_pixelExtent = MAPSCRIPT_OBJ_P(php_rect_object, zpixelExtent); php_geoRefExtent = MAPSCRIPT_OBJ_P(php_rect_object, zgeoRefExtent); if (zmaxGeoRefExtent) php_maxGeoRefExtent = MAPSCRIPT_OBJ_P(php_rect_object, zmaxGeoRefExtent); /* -------------------------------------------------------------------- */ /* check the validity of the parameters. */ /* -------------------------------------------------------------------- */ if (width <= 0 || height <= 0 || php_geoRefExtent->rect == NULL || php_pixelExtent->rect == NULL || (zmaxGeoRefExtent && php_maxGeoRefExtent->rect == NULL)) { mapscript_throw_mapserver_exception("Incorrect parameters\n" TSRMLS_CC); return; } /* -------------------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* -------------------------------------------------------------------- */ if (php_geoRefExtent->rect->minx >= php_geoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_geoRefExtent->rect->miny >= php_geoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } if (zmaxGeoRefExtent) { if (php_maxGeoRefExtent->rect->minx >= php_maxGeoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_maxGeoRefExtent->rect->miny >= php_maxGeoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } } newGeoRefExtent.minx = Pix2Georef((int)php_pixelExtent->rect->minx, 0, width, php_geoRefExtent->rect->minx, php_geoRefExtent->rect->maxx, 0); newGeoRefExtent.maxx = Pix2Georef((int)php_pixelExtent->rect->maxx, 0, width, php_geoRefExtent->rect->minx, php_geoRefExtent->rect->maxx, 0); newGeoRefExtent.miny = Pix2Georef((int)php_pixelExtent->rect->miny, 0, height, php_geoRefExtent->rect->miny, php_geoRefExtent->rect->maxy, 1); newGeoRefExtent.maxy = Pix2Georef((int)php_pixelExtent->rect->maxy, 0, height, php_geoRefExtent->rect->miny, php_geoRefExtent->rect->maxy, 1); msAdjustExtent(&newGeoRefExtent, php_map->map->width, php_map->map->height); /* -------------------------------------------------------------------- */ /* if the min and max scale are set in the map file, we will */ /* use them to test before setting extents. */ /* -------------------------------------------------------------------- */ if (msCalculateScale(newGeoRefExtent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &dfNewScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_map->map->web.maxscaledenom > 0 && dfNewScale > php_map->map->web.maxscaledenom) { RETURN_LONG(MS_FAILURE); } if (php_map->map->web.minscaledenom > 0 && dfNewScale < php_map->map->web.minscaledenom) { dfMiddleX = newGeoRefExtent.minx + ((newGeoRefExtent.maxx - newGeoRefExtent.minx)/2); dfMiddleY = newGeoRefExtent.miny + ((newGeoRefExtent.maxy - newGeoRefExtent.miny)/2); dfDeltaExt = GetDeltaExtentsUsingScale(php_map->map->web.minscaledenom, php_map->map->units, dfMiddleY, php_map->map->width, php_map->map->resolution); if (dfDeltaExt > 0.0) { newGeoRefExtent.minx = dfMiddleX - (dfDeltaExt/2); newGeoRefExtent.miny = dfMiddleY - (dfDeltaExt/2); newGeoRefExtent.maxx = dfMiddleX + (dfDeltaExt/2); newGeoRefExtent.maxy = dfMiddleY + (dfDeltaExt/2); } else RETURN_LONG(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* -------------------------------------------------------------------- */ if (zmaxGeoRefExtent) { dfDeltaX = newGeoRefExtent.maxx - newGeoRefExtent.minx; dfDeltaY = newGeoRefExtent.maxy - newGeoRefExtent.miny; /* Make sure Current georef extents is not bigger than max extents */ if (dfDeltaX > (php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx)) dfDeltaX = php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx; if (dfDeltaY > (php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny)) dfDeltaY = php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny; if (newGeoRefExtent.minx < php_maxGeoRefExtent->rect->minx) { newGeoRefExtent.minx = php_maxGeoRefExtent->rect->minx; newGeoRefExtent.maxx = newGeoRefExtent.minx + dfDeltaX; } if (newGeoRefExtent.maxx > php_maxGeoRefExtent->rect->maxx) { newGeoRefExtent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (newGeoRefExtent.miny < php_maxGeoRefExtent->rect->miny) { newGeoRefExtent.miny = php_maxGeoRefExtent->rect->miny; newGeoRefExtent.maxy = newGeoRefExtent.miny + dfDeltaY; } if (newGeoRefExtent.maxy > php_maxGeoRefExtent->rect->maxy) { newGeoRefExtent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } php_map->map->extent.minx = newGeoRefExtent.minx; php_map->map->extent.miny = newGeoRefExtent.miny; php_map->map->extent.maxx = newGeoRefExtent.maxx; php_map->map->extent.maxy = newGeoRefExtent.maxy; php_map->map->cellsize = msAdjustExtent(&(php_map->map->extent), php_map->map->width, php_map->map->height); dfDeltaX = php_map->map->extent.maxx - php_map->map->extent.minx; dfDeltaY = php_map->map->extent.maxy - php_map->map->extent.miny; if (zmaxGeoRefExtent) { if (php_map->map->extent.minx < php_maxGeoRefExtent->rect->minx) { php_map->map->extent.minx = php_maxGeoRefExtent->rect->minx; php_map->map->extent.maxx = php_map->map->extent.minx + dfDeltaX; } if (php_map->map->extent.maxx > php_maxGeoRefExtent->rect->maxx) { php_map->map->extent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (php_map->map->extent.miny < php_maxGeoRefExtent->rect->miny) { php_map->map->extent.miny = php_maxGeoRefExtent->rect->miny; php_map->map->extent.maxy = php_map->map->extent.miny + dfDeltaY; } if (php_map->map->extent.maxy > php_maxGeoRefExtent->rect->maxy) { php_map->map->extent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } if (msCalculateScale(php_map->map->extent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &(php_map->map->scaledenom)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int zoomScale(int scaleDenom, pointObj pixelPosition, int width, int height, rectObj geoRefExtent, [rectObj mapGeoRefExtent]) Zoom to a given XY postion. */ PHP_METHOD(mapObj, zoomScale) { zval *zobj = getThis(); zval *zpoint, *zgeoRefExtent, *zmaxGeoRefExtent = NULL; long width, height; double scaleDenom; double dfGeoPosX, dfGeoPosY; double dfDeltaX, dfDeltaY; double dfCurrentScale = 0.0; rectObj newGeoRefExtent; double dfNewScale = 0.0; double dfDeltaExt = -1.0; int tmp = 0; php_point_object *php_pixelPosition; php_rect_object *php_geoRefExtent=NULL, *php_maxGeoRefExtent=NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dOllO|O", &scaleDenom, &zpoint, mapscript_ce_point, &width, &height, &zgeoRefExtent , mapscript_ce_rect, &zmaxGeoRefExtent , mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_pixelPosition = MAPSCRIPT_OBJ_P(php_point_object, zpoint); php_geoRefExtent = MAPSCRIPT_OBJ_P(php_rect_object, zgeoRefExtent); if (zmaxGeoRefExtent) php_maxGeoRefExtent = MAPSCRIPT_OBJ_P(php_rect_object, zmaxGeoRefExtent); /* -------------------------------------------------------------------- */ /* check the validity of the parameters. */ /* -------------------------------------------------------------------- */ if (scaleDenom <= 0.0 || width <= 0 || height <= 0 || php_geoRefExtent->rect == NULL || php_pixelPosition->point == NULL || (zmaxGeoRefExtent && php_maxGeoRefExtent->rect == NULL)) { mapscript_throw_mapserver_exception("Incorrect parameters\n" TSRMLS_CC); return; } /* -------------------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* -------------------------------------------------------------------- */ if (php_geoRefExtent->rect->minx >= php_geoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_geoRefExtent->rect->miny >= php_geoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } if (zmaxGeoRefExtent) { if (php_maxGeoRefExtent->rect->minx >= php_maxGeoRefExtent->rect->maxx) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates minx >= maxx\n" TSRMLS_CC); return; } if (php_maxGeoRefExtent->rect->miny >= php_maxGeoRefExtent->rect->maxy) { mapscript_throw_mapserver_exception("Max Georeferenced coordinates miny >= maxy\n" TSRMLS_CC); return; } } dfGeoPosX = Pix2Georef((int)php_pixelPosition->point->x, 0, width, php_geoRefExtent->rect->minx, php_geoRefExtent->rect->maxx, 0); dfGeoPosY = Pix2Georef((int)php_pixelPosition->point->y, 0, height, php_geoRefExtent->rect->miny, php_geoRefExtent->rect->maxy, 1); dfDeltaX = php_geoRefExtent->rect->maxx - php_geoRefExtent->rect->minx; dfDeltaY = php_geoRefExtent->rect->maxy - php_geoRefExtent->rect->miny; /* -------------------------------------------------------------------- */ /* Calculate new extents based on the sacle. */ /* -------------------------------------------------------------------- */ /* ==================================================================== */ /* make sure to take the smallest size because this is the one */ /* that will be used to ajust the scale. */ /* ==================================================================== */ if (php_map->map->width < php_map->map->height) tmp = php_map->map->width; else tmp = php_map->map->height; dfDeltaExt = GetDeltaExtentsUsingScale(scaleDenom, php_map->map->units, dfGeoPosY, tmp, php_map->map->resolution); if (dfDeltaExt > 0.0) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaExt/2); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaExt/2); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaExt/2); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaExt/2); } else RETURN_LONG(MS_FAILURE); /* -------------------------------------------------------------------- */ /* get current scale. */ /* -------------------------------------------------------------------- */ if (msCalculateScale(*php_geoRefExtent->rect, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &dfCurrentScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* -------------------------------------------------------------------- */ /* if the min and max scale are set in the map file, we will */ /* use them to test before zooming. */ /* */ /* This function has the same effect as zoomin or zoom out. If */ /* the current scale is > newscale we zoom in; else it is a */ /* zoom out. */ /* -------------------------------------------------------------------- */ msAdjustExtent(&newGeoRefExtent, php_map->map->width, php_map->map->height); if (msCalculateScale(newGeoRefExtent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &dfNewScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } if (php_map->map->web.maxscaledenom > 0) { if (dfCurrentScale < dfNewScale && dfNewScale > php_map->map->web.maxscaledenom) { RETURN_LONG(MS_FAILURE); } } /* ==================================================================== */ /* we do a special case for zoom in : we try to zoom as much as */ /* possible using the mincale set in the .map. */ /* ==================================================================== */ if (php_map->map->web.minscaledenom > 0 && dfNewScale < php_map->map->web.minscaledenom && dfCurrentScale > dfNewScale) { dfDeltaExt = GetDeltaExtentsUsingScale(php_map->map->web.minscaledenom, php_map->map->units, dfGeoPosY, php_map->map->width, php_map->map->resolution); if (dfDeltaExt > 0.0) { newGeoRefExtent.minx = dfGeoPosX - (dfDeltaExt/2); newGeoRefExtent.miny = dfGeoPosY - (dfDeltaExt/2); newGeoRefExtent.maxx = dfGeoPosX + (dfDeltaExt/2); newGeoRefExtent.maxy = dfGeoPosY + (dfDeltaExt/2); } else RETURN_LONG(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* -------------------------------------------------------------------- */ if (zmaxGeoRefExtent) { dfDeltaX = newGeoRefExtent.maxx - newGeoRefExtent.minx; dfDeltaY = newGeoRefExtent.maxy - newGeoRefExtent.miny; /* Make sure Current georef extents is not bigger than max extents */ if (dfDeltaX > (php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx)) dfDeltaX = php_maxGeoRefExtent->rect->maxx-php_maxGeoRefExtent->rect->minx; if (dfDeltaY > (php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny)) dfDeltaY = php_maxGeoRefExtent->rect->maxy-php_maxGeoRefExtent->rect->miny; if (newGeoRefExtent.minx < php_maxGeoRefExtent->rect->minx) { newGeoRefExtent.minx = php_maxGeoRefExtent->rect->minx; newGeoRefExtent.maxx = newGeoRefExtent.minx + dfDeltaX; } if (newGeoRefExtent.maxx > php_maxGeoRefExtent->rect->maxx) { newGeoRefExtent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (newGeoRefExtent.miny < php_maxGeoRefExtent->rect->miny) { newGeoRefExtent.miny = php_maxGeoRefExtent->rect->miny; newGeoRefExtent.maxy = newGeoRefExtent.miny + dfDeltaY; } if (newGeoRefExtent.maxy > php_maxGeoRefExtent->rect->maxy) { newGeoRefExtent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } /* -------------------------------------------------------------------- */ /* set the map extents with new values. */ /* -------------------------------------------------------------------- */ php_map->map->extent.minx = newGeoRefExtent.minx; php_map->map->extent.miny = newGeoRefExtent.miny; php_map->map->extent.maxx = newGeoRefExtent.maxx; php_map->map->extent.maxy = newGeoRefExtent.maxy; php_map->map->cellsize = msAdjustExtent(&(php_map->map->extent), php_map->map->width, php_map->map->height); dfDeltaX = php_map->map->extent.maxx - php_map->map->extent.minx; dfDeltaY = php_map->map->extent.maxy - php_map->map->extent.miny; if (zmaxGeoRefExtent) { if (php_map->map->extent.minx < php_maxGeoRefExtent->rect->minx) { php_map->map->extent.minx = php_maxGeoRefExtent->rect->minx; php_map->map->extent.maxx = php_map->map->extent.minx + dfDeltaX; } if (php_map->map->extent.maxx > php_maxGeoRefExtent->rect->maxx) { php_map->map->extent.maxx = php_maxGeoRefExtent->rect->maxx; newGeoRefExtent.minx = newGeoRefExtent.maxx - dfDeltaX; } if (php_map->map->extent.miny < php_maxGeoRefExtent->rect->miny) { php_map->map->extent.miny = php_maxGeoRefExtent->rect->miny; php_map->map->extent.maxy = php_map->map->extent.miny + dfDeltaY; } if (php_map->map->extent.maxy > php_maxGeoRefExtent->rect->maxy) { php_map->map->extent.maxy = php_maxGeoRefExtent->rect->maxy; newGeoRefExtent.miny = newGeoRefExtent.maxy - dfDeltaY; } } if (msCalculateScale(php_map->map->extent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &(php_map->map->scaledenom)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /********************************************************************** * map->queryByPoint() * * Type is MS_SINGLE or MS_MULTIPLE depending on number of results * you want. Passing buffer <=0 defaults to tolerances set in the map * file (in pixels) but you can use a constant buffer (specified in * ground units) instead. **********************************************************************/ /* {{{ proto int map.queryByPoint(pointObj point, int mode, double buffer) Query at point location. */ PHP_METHOD(mapObj, queryByPoint) { zval *zobj = getThis(); zval *zpoint; long mode; double buffer; int status = MS_FAILURE; php_point_object *php_point; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Old", &zpoint, mapscript_ce_point, &mode, &buffer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_point = MAPSCRIPT_OBJ_P(php_point_object, zpoint); status = mapObj_queryByPoint(php_map->map, php_point->point, mode, buffer); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.queryByRect(rectObj rect) */ PHP_METHOD(mapObj, queryByRect) { zval *zobj = getThis(); zval *zrect; int status = MS_FAILURE; php_rect_object *php_rect; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zrect, mapscript_ce_rect) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zrect); status = mapObj_queryByRect(php_map->map, *(php_rect->rect)); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /********************************************************************** * map->queryByShape(shape) * * Generates a result set based on a single shape, the shape is * assumed to be a polygon at this point. **********************************************************************/ /* {{{ proto int map.queryByShape(shapeObj poShape) */ PHP_METHOD(mapObj, queryByShape) { zval *zobj = getThis(); zval *zshape; int status = MS_FAILURE; php_shape_object *php_shape; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zshape); status = mapObj_queryByShape(php_map->map, php_shape->shape); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.queryByFeatures(int slayer) */ PHP_METHOD(mapObj, queryByFeatures) { zval *zobj = getThis(); long slayer; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &slayer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_queryByFeatures(php_map->map, slayer); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /********************************************************************** * map->queryByIndex(qlayer, tileindex, shapeindex, bAddtoQuery) * * * Add a shape into the query result on a specific layer. * if bAddtoQuery (not mandatory) isset to true, the sahpe will be added to * the existing query result. Else the query result is cleared before adding * the sahpe (which is the default behavior). **********************************************************************/ /* {{{ proto int map.queryByIndex(int layerIndex, int tileIndex, int shapeIndex, int addToQuery) */ PHP_METHOD(mapObj, queryByIndex) { zval *zobj = getThis(); long layerIndex, tileIndex, shapeIndex, addToQuery = MS_FALSE; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll|l", &layerIndex, &tileIndex, &shapeIndex, &addToQuery) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_queryByIndex(php_map->map, layerIndex, tileIndex, shapeIndex, addToQuery); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.queryByFilter(char string) */ PHP_METHOD(mapObj, queryByFilter) { zval *zobj = getThis(); char *string; long string_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_queryByFilter(php_map->map, string); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.savequery(string filename, int results) Save the current query to a specfied file. Can be used with loadquery */ PHP_METHOD(mapObj, saveQuery) { zval *zobj = getThis(); char *filename; long filename_len = 0; long results = MS_FALSE; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &results) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_saveQuery(php_map->map, filename, results); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.savequeryasgml(string filename, string namespace) Save the current query to a specfied file as GML. */ PHP_METHOD(mapObj, saveQueryAsGML) { zval *zobj = getThis(); char *filename; long filename_len = 0; char *namespace = "GOMF"; long namespace_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &filename, &filename_len, &namespace, &namespace_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = msGMLWriteQuery(php_map->map, filename, namespace); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.loadquery(filename) Load the query from a specfied file. Used with savequery */ PHP_METHOD(mapObj, loadQuery) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_loadQuery(php_map->map, filename); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map->freeQuery(int qlayer) Free the query on a specified layer. If qlayer is set to -1 all queries on all layers will be freed. */ PHP_METHOD(mapObj, freeQuery) { zval *zobj = getThis(); long qlayer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &qlayer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); mapObj_freeQuery(php_map->map, qlayer); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int map.save(string filename) Write map object to a file. */ PHP_METHOD(mapObj, save) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_save(php_map->map, filename); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.setProjection(string projection_params[, int setUnitsAndExtents]) Set projection and coord. system for the map. */ PHP_METHOD(mapObj, setProjection) { zval *zobj = getThis(); char *projection; long projection_len = 0; int status = MS_FAILURE; long setUnitsAndExtents = MS_FALSE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &projection, &projection_len, &setUnitsAndExtents) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapscript_map_setProjection(MS_FALSE, php_map, projection, setUnitsAndExtents TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.getProjection() Return the projection string of the layer. Returns NULL on error. */ PHP_METHOD(mapObj, getProjection) { zval *zobj = getThis(); char *projection = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); projection = mapObj_getProjection(php_map->map); if (projection == NULL) { RETURN_NULL(); } MAPSCRIPT_RETVAL_STRING(projection, 1); free(projection); } /* }}} */ /* {{{ proto int map.setWKTProjection(string projection) Set projection and coord. system for the map. Returns MS_FAILURE on error. */ PHP_METHOD(mapObj, setWKTProjection) { zval *zobj = getThis(); char *projection; long projection_len = 0; int status = MS_FAILURE; long setUnitsAndExtents = MS_FALSE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &projection, &projection_len, &setUnitsAndExtents) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapscript_map_setProjection(MS_TRUE, php_map, projection, setUnitsAndExtents TSRMLS_CC); RETURN_LONG(status); } /* }}} */ /* {{{ proto string map.getMetaData(string name) Return MetaData entry by name, or empty string if not found. */ PHP_METHOD(mapObj, getMetaData) { zval *zname; zval *zobj = getThis(); php_map_object *php_map; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_map->metadata, &php_map->map->web.metadata); MAPSCRIPT_CALL_METHOD_1(php_map->metadata, "get", retval, zname); #if PHP_VERSION_ID < 70000 RETURN_STRING(Z_STRVAL_P(retval),1); #else RETURN_STRING(Z_STRVAL(retval)); #endif } /* }}} */ /* {{{ proto int map.setMetaData(string name, string value) Set MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(mapObj, setMetaData) { zval *zname, *zvalue; zval *zobj = getThis(); php_map_object *php_map; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zname, &zvalue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_map->metadata, &php_map->map->web.metadata); MAPSCRIPT_CALL_METHOD_2(php_map->metadata, "set", retval, zname, zvalue); #if PHP_VERSION_ID < 70000 RETURN_LONG(Z_LVAL_P(retval)); #else RETURN_LONG(Z_LVAL(retval)); #endif } /* }}} */ /* {{{ proto int map.removeMetaData(string name) Remove MetaData entry by name. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(mapObj, removeMetaData) { zval *zname; zval *zobj = getThis(); php_map_object *php_map; MAPSCRIPT_ZVAL retval; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); CHECK_OBJECT(mapscript_ce_hashtable, php_map->metadata, &php_map->map->web.metadata); MAPSCRIPT_CALL_METHOD_1(php_map->metadata, "remove", retval, zname); #if PHP_VERSION_ID < 70000 RETURN_LONG(Z_LVAL_P(retval)); #else RETURN_LONG(Z_LVAL(retval)); #endif } /* }}} */ /* {{{ proto int map.getLayersIndexByGroup(string groupname) Return an array of layer's index given a group name. */ PHP_METHOD(mapObj, getLayersIndexByGroup) { zval *zobj = getThis(); char *groupName; long groupName_len = 0; int *indexes = NULL; int count = 0; int i; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &groupName, &groupName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); array_init(return_value); indexes = mapObj_getLayersIndexByGroup(php_map->map, groupName, &count); if (indexes && count > 0) { for (i=0; imap->numlayers > 0) { groups = msGetAllGroupNames(php_map->map, &numTok); for (i=0; imap->numlayers; for (i=0; imap->layers[i]->name, 1); #else add_next_index_string(return_value, php_map->map->layers[i]->name); #endif } } /* }}} */ /* {{{ proto int map.movelayerup(int index) Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, moveLayerUp) { zval *zobj = getThis(); long index; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_moveLayerup(php_map->map, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.movelayerdown(int index) Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, moveLayerDown) { zval *zobj = getThis(); long index; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_moveLayerdown(php_map->map, index); RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.getLayersDrawingOrder() Return an array containing all the layers index sorted by drawing order. Note : the first element in the array is the one drawn first.*/ PHP_METHOD(mapObj, getLayersDrawingOrder) { zval *zobj = getThis(); int count = 0; int i; int *layerIndexes = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); array_init(return_value); layerIndexes = mapObj_getLayersdrawingOrder(php_map->map); count = php_map->map->numlayers; /* -------------------------------------------------------------------- */ /* Go through the prioriy list and return the layers index. If */ /* the priority list is not set, it will return the layer */ /* indexs as they were at the load time. */ /* -------------------------------------------------------------------- */ for (i=0; imap->numlayers != numElements) { RETURN_LONG(MS_FAILURE); } indexes = (int*)malloc(sizeof(int)*numElements); for(zend_hash_internal_pointer_reset(indexes_hash); zend_hash_has_more_elements(indexes_hash) == SUCCESS; zend_hash_move_forward(indexes_hash), ++i) { #if PHP_VERSION_ID < 70000 zend_hash_get_current_data(indexes_hash, (void **)&ppzval); #else ppzval = zend_hash_get_current_data(indexes_hash); #endif indexes[i] = Z_LVAL_PP(ppzval); } if (!mapObj_setLayersdrawingOrder(php_map->map, indexes)) { free(indexes); RETURN_LONG(MS_FAILURE); } free(indexes); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int map.processTemplate(array params, int generateImages)*/ PHP_METHOD(mapObj, processTemplate) { zval *zobj = getThis(); zval *zindexes; HashTable *indexes_hash = NULL; long generateImages; char *buffer = NULL; int index = 0; int numElements = 0; int i, size; char **papszNameValue = NULL; char **papszName = NULL; char **papszValue = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al", &zindexes, &generateImages) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); indexes_hash = Z_ARRVAL_P(zindexes); /** * Allocate 2 times the number of elements in * the array, since with associative arrays in PHP * keys are not counted. */ numElements = zend_hash_num_elements(indexes_hash); size = (numElements * 2 + 1) * sizeof(char *); papszNameValue = (char **)emalloc(size+1); memset((char *)papszNameValue, 0, size); if (mapscript_extract_associative_array(indexes_hash, papszNameValue)) { papszName = (char **)malloc(sizeof(char *)*numElements); papszValue = (char **)malloc(sizeof(char *)*numElements); for (i=0; imap, generateImages, papszName, papszValue, numElements); msFree(papszName); // The strings inside the array are just refs msFree(papszValue); if (buffer) { MAPSCRIPT_RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); MAPSCRIPT_RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto int map.processQueryTemplate(array params, int generateImages)*/ PHP_METHOD(mapObj, processQueryTemplate) { zval *zobj = getThis(); zval *zindexes; HashTable *indexes_hash = NULL; long generateImages = MS_TRUE; char *buffer = NULL; int index = 0; int numElements = 0; int i, size; char **papszNameValue = NULL; char **papszName = NULL; char **papszValue = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &zindexes, &generateImages) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); indexes_hash = Z_ARRVAL_P(zindexes); /** * Allocate 2 times the number of elements in * the array, since with associative arrays in PHP * keys are not counted. */ numElements = zend_hash_num_elements(indexes_hash); size = (numElements * 2 + 1) * sizeof(char *); papszNameValue = (char **)emalloc(size+1); memset((char *)papszNameValue, 0, size); if (mapscript_extract_associative_array(indexes_hash, papszNameValue)) { papszName = (char **)malloc(sizeof(char *)*numElements); papszValue = (char **)malloc(sizeof(char *)*numElements); for (i=0; imap, generateImages, papszName, papszValue, numElements); msFree(papszName); // The strings inside the array are just refs msFree(papszValue); if (buffer) { MAPSCRIPT_RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); MAPSCRIPT_RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto int map.processLegendTemplate(array params)*/ PHP_METHOD(mapObj, processLegendTemplate) { zval *zobj = getThis(); zval *zindexes; HashTable *indexes_hash = NULL; char *buffer = NULL; int index = 0; int numElements = 0; int i, size; char **papszNameValue = NULL; char **papszName = NULL; char **papszValue = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &zindexes) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); indexes_hash = Z_ARRVAL_P(zindexes); /** * Allocate 2 times the number of elements in * the array, since with associative arrays in PHP * keys are not counted. */ numElements = zend_hash_num_elements(indexes_hash); size = (numElements * 2 + 1) * sizeof(char *); papszNameValue = (char **)emalloc(size+1); memset((char *)papszNameValue, 0, size); if (mapscript_extract_associative_array(indexes_hash, papszNameValue)) { papszName = (char **)malloc(sizeof(char *)*numElements); papszValue = (char **)malloc(sizeof(char *)*numElements); for (i=0; imap, papszName, papszValue, numElements); msFree(papszName); // The strings inside the array are just refs msFree(papszValue); if (buffer) { MAPSCRIPT_RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); MAPSCRIPT_RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto int map.setSymbolSet(fileName)*/ PHP_METHOD(mapObj, setSymbolSet) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if(filename_len > 0) { if ((status = mapObj_setSymbolSet(php_map->map, filename)) != 0) { mapscript_throw_mapserver_exception("Failed loading symbolset from %s" TSRMLS_CC, filename); return; } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.getNumSymbols() Returns the number of sumbols from this map. */ PHP_METHOD(mapObj, getNumSymbols) { zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); RETURN_LONG(php_map->map->symbolset.numsymbols); } /* }}} */ /* {{{ proto int map.setFontName(fileName)*/ PHP_METHOD(mapObj, setFontSet) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if(filename_len > 0) { if ((status = mapObj_setFontSet(php_map->map, filename)) != 0) { mapscript_throw_mapserver_exception("Failed loading fontset from %s" TSRMLS_CC, filename); return; } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int selectOutputFormat(string type) Selects the output format to be used in the map. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, selectOutputFormat) { zval *zobj = getThis(); char *type; long type_len = 0; int status = MS_FAILURE; php_map_object *php_map; php_outputformat_object *php_outputformat = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &type, &type_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if (ZVAL_NOT_UNDEF(php_map->outputformat)) php_outputformat = MAPSCRIPT_OBJ(php_outputformat_object, php_map->outputformat); if ((status = mapObj_selectOutputFormat(php_map->map, type)) != MS_SUCCESS) { mapscript_report_php_error(E_WARNING, "Unable to set output format to '%s'" TSRMLS_CC, type); } else if (ZVAL_NOT_UNDEF(php_map->outputformat)) { php_outputformat->outputformat = php_map->map->outputformat; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int appendOutputFormat(outputFormatObj outputformat) Appends outputformat object in the map object. Returns the new numoutputformats value */ PHP_METHOD(mapObj, appendOutputFormat) { zval *zobj = getThis(); zval *zoutputformat = NULL; int retval = 0; php_map_object *php_map; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zoutputformat, mapscript_ce_outputformat) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zoutputformat); retval = msAppendOutputFormat(php_map->map, php_outputformat->outputformat); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int removeOutputFormat(string name) Remove outputformat from the map. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(mapObj, removeOutputFormat) { zval *zobj = getThis(); char *name; long name_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if ((status = msRemoveOutputFormat(php_map->map, name)) != MS_SUCCESS) { mapscript_report_php_error(E_WARNING, "Unable to remove output format to '%s'" TSRMLS_CC, name); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.getOutputFormat(int index). Return the outputformat at index position. */ PHP_METHOD(mapObj, getOutputFormat) { zval *zobj = getThis(); long index = -1; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if (index < 0 || index >= php_map->map->numoutputformats) { mapscript_throw_mapserver_exception("Invalid outputformat index." TSRMLS_CC); return; } MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_outputformat(php_map->map->outputformatlist[index], parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int map.saveMapContext(fileName) */ PHP_METHOD(mapObj, saveMapContext) { zval *zobj = getThis(); char *filename; long filename_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if(filename_len > 0) { if ((status = mapObj_saveMapContext(php_map->map, filename)) != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); mapscript_report_php_error(E_WARNING, "Failed saving map context from %s" TSRMLS_CC, filename); RETURN_LONG(MS_FAILURE); } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int map.loadMapContext(fileName) */ PHP_METHOD(mapObj, loadMapContext) { zval *zobj = getThis(); char *filename; long filename_len = 0; long unique = MS_FALSE; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &unique) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if(filename_len > 0) { if ((status = mapObj_loadMapContext(php_map->map, filename, unique)) != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); mapscript_report_php_error(E_WARNING, "Failed loading map context from %s" TSRMLS_CC, filename); RETURN_LONG(MS_FAILURE); } } RETURN_LONG(status); } /* }}} */ /* {{{ proto int applySLD(string sldxml) Apply the SLD document to the map file. */ PHP_METHOD(mapObj, applySLD) { zval *zobj = getThis(); char *sldxml; long sldxml_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &sldxml, &sldxml_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_applySLD(php_map->map, sldxml); RETURN_LONG(status); } /* }}} */ /* {{{ proto int applySLDURL(string sldurl) Apply the SLD document pointed by the URL to the map file. */ PHP_METHOD(mapObj, applySLDURL) { zval *zobj = getThis(); char *sldurl; long sldurl_len = 0; int status = MS_FAILURE; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &sldurl, &sldurl_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); status = mapObj_applySLDURL(php_map->map, sldurl); RETURN_LONG(status); } /* }}} */ /* {{{ proto string generateSLD() Generates an sld based on the map layers/class. */ PHP_METHOD(mapObj, generateSLD) { zval *zobj = getThis(); char *buffer = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); buffer = mapObj_generateSLD(php_map->map); if (buffer) { MAPSCRIPT_RETVAL_STRING(buffer, 1); free(buffer); } else { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); MAPSCRIPT_RETURN_STRING("", 1); } } /* }}} */ /* {{{ proto string map.getConfigOption(string key) Returns the configuation value associated with the key passed as argument. Returns an empty string on error. prototype : value = $map->getconfigoption(key) */ PHP_METHOD(mapObj, getConfigOption) { zval *zobj = getThis(); char *key; long key_len = 0; char *value = NULL; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if ((value = (char *)msGetConfigOption(php_map->map, key)) == NULL) { MAPSCRIPT_RETURN_STRING("", 1); } else { MAPSCRIPT_RETURN_STRING(value, 1); } } /* }}} */ /* {{{ proto int map.setConfigOption(string key, string value) Sets a config parameter using the key and the value passed. */ PHP_METHOD(mapObj, setConfigOption) { zval *zobj = getThis(); char *key; long key_len = 0; char *value; long value_len = 0; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); msSetConfigOption(php_map->map, key,value); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int map.applyConfigOptions() Applies the config options set in the map file. */ PHP_METHOD(mapObj, applyConfigOptions) { zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); msApplyMapConfigOptions(php_map->map); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int loadowsparameters(OWSRequestObj request, string version) Load OWS request parameters (BBOX, LAYERS, &c.) into map. Returns MS_SUCCESS or MS_FAILURE */ PHP_METHOD(mapObj, loadOwsParameters) { zval *zobj = getThis(); zval *zrequest; char *version = NULL; long version_len = 0; int isZval = 1; int status = MS_FAILURE; php_owsrequest_object *php_request; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|s", &zrequest, mapscript_ce_owsrequest, &version, &version_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_request = MAPSCRIPT_OBJ_P(php_owsrequest_object, zrequest); if (!version) { version = msStrdup("1.1.1"); isZval = 0; } status = mapObj_loadOWSParameters(php_map->map, php_request->cgirequest, version); if (!isZval) free(version); RETURN_LONG(status); } /* }}} */ /* {{{ proto int owsDispatch(owsrequest request) Processes and executes the passed OpenGIS Web Services request on the map. */ PHP_METHOD(mapObj, owsDispatch) { zval *zobj = getThis(); zval *zrequest; int status = MS_FAILURE; php_owsrequest_object *php_request; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zrequest, mapscript_ce_owsrequest) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_request = MAPSCRIPT_OBJ_P(php_owsrequest_object, zrequest); status = mapObj_OWSDispatch(php_map->map, php_request->cgirequest); RETURN_LONG(status); } /* }}} */ /* {{{ proto int insertLayer(layerObj layer, index) Returns the index where the layer had been inserted*/ PHP_METHOD(mapObj, insertLayer) { zval *zobj = getThis(); zval *zlayer; long index = -1; int retval = -1; php_layer_object *php_layer; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &zlayer, mapscript_ce_layer, &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); if ((retval = mapObj_insertLayer(php_map->map, php_layer->layer, index)) < 0) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* return layer index */ RETURN_LONG(retval); } /* }}} */ /* {{{ proto int removeLayer(int layer_index) Returns layerObj removed on sucesss, else null. */ PHP_METHOD(mapObj, removeLayer) { zval *zobj = getThis(); long index = -1; layerObj *layer = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); if ((layer = mapObj_removeLayer(php_map->map, index)) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* return layer object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_layer(layer, parent, return_value TSRMLS_CC); } /* }}} */ #ifdef disabled /* {{{ proto int map.getLabel(). Return the next label from the map���s labelcache, allowing iteration over labels. Return NULL when the labelcache is empty. */ PHP_METHOD(mapObj, getLabel) { zval *zobj = getThis(); long index = -1; labelCacheMemberObj *labelCacheMember = NULL; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); labelCacheMember=mapObj_getLabel(php_map->map, index); if (labelCacheMember == NULL) RETURN_NULL(); /* Return labelCacheMember object */ MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_labelcachemember(labelCacheMember, parent, return_value TSRMLS_CC); } /* }}} */ #endif /* {{{ proto string convertToString() Convert the map object to string. */ PHP_METHOD(mapObj, convertToString) { zval *zobj = getThis(); php_map_object *php_map; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); value = mapObj_convertToString(php_map->map); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /************************************************************************/ /* php3_ms_map_getLatLongExtent() */ /* */ /* Utility function (not documented) to get the lat/long */ /* extents of the current map. We assume here that the map has */ /* it's projection (ex LCC or UTM defined). */ /* */ /* Available only with PROJ support. */ /************************************************************************/ PHP_METHOD(mapObj, getLatLongExtent) { #ifdef USE_PROJ zval *zobj = getThis(); rectObj geoRefExt; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); geoRefExt.minx = php_map->map->extent.minx; geoRefExt.miny = php_map->map->extent.miny; geoRefExt.maxx = php_map->map->extent.maxx; geoRefExt.maxy = php_map->map->extent.maxy; if (php_map->map->projection.proj != NULL) { msProjectRect(&(php_map->map->projection), NULL, &geoRefExt); } /* Return rectObj */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_rect(&geoRefExt, parent, return_value TSRMLS_CC); #else mapscript_throw_exception("Available only with PROJ.4 support." TSRMLS_CC); return; #endif } /* {{{ proto int map.free(). Free explicitly the map object. Breaks the internal circular references between the map object and its children. */ PHP_METHOD(mapObj, free) { zval *zobj = getThis(); php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zobj); MAPSCRIPT_DELREF(php_map->outputformat); MAPSCRIPT_DELREF(php_map->extent); MAPSCRIPT_DELREF(php_map->web); MAPSCRIPT_DELREF(php_map->reference); MAPSCRIPT_DELREF(php_map->imagecolor); MAPSCRIPT_DELREF(php_map->scalebar); MAPSCRIPT_DELREF(php_map->legend); MAPSCRIPT_DELREF(php_map->querymap); #ifdef disabled MAPSCRIPT_DELREF(php_map->labelcache); #endif MAPSCRIPT_DELREF(php_map->projection); MAPSCRIPT_DELREF(php_map->metadata); } /* }}} */ zend_function_entry map_functions[] = { PHP_ME(mapObj, __construct, map___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(mapObj, __get, map___get_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, __set, map___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(mapObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getSymbolByName, map_getSymbolByName_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getSymbolObjectById, map_getSymbolObjectById_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, prepareQuery, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, prepareImage, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, draw, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawQuery, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawLegend, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawReferenceMap, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawScaleBar, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, embedLegend, map_embedLegend_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, embedScaleBar, map_embedScaleBar_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, drawLabelCache, map_drawLabelCache_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLayer, map_getLayer_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLayerByName, map_getLayerByName_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getColorByIndex, map_getColorByIndex_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setExtent, map_setExtent_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setCenter, map_setCenter_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, offsetExtent, map_offsetExtent_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, scaleExtent, map_scaleExtent_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setRotation, map_setRotation_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setSize, map_setSize_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, zoomPoint, map_zoomPoint_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, zoomRectangle, map_zoomRectangle_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, zoomScale, map_zoomScale_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByPoint, map_queryByPoint_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByRect, map_queryByRect_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByShape, map_queryByShape_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByFeatures, map_queryByFeatures_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByFilter, map_queryByFilter_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, queryByIndex, map_queryByIndex_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, saveQuery, map_saveQuery_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, saveQueryAsGML, map_saveQueryAsGML_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, loadQuery, map_loadQuery_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, freeQuery, map_freeQuery_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, save, map_save_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getProjection, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setProjection, map_setProjection_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setWKTProjection, map_setWKTProjection_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getMetaData, map_getMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setMetaData, map_setMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, removeMetaData, map_removeMetaData_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLayersIndexByGroup, map_getLayersIndexByGroup_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getAllGroupNames, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getAllLayerNames, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, moveLayerUp, map_moveLayerUp_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, moveLayerDown, map_moveLayerDown_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLayersDrawingOrder, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setLayersDrawingOrder, map_setLayersDrawingOrder_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, processTemplate, map_processTemplate_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, processQueryTemplate, map_processQueryTemplate_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, processLegendTemplate, map_processLegendTemplate_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setSymbolSet, map_setSymbolSet_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getNumSymbols, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setFontSet, map_setFontSet_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, selectOutputFormat, map_selectOutputFormat_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, appendOutputFormat, map_appendOutputFormat_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, removeOutputFormat, map_removeOutputFormat_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getOutputFormat, map_getOutputFormat_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, saveMapContext, map_saveMapContext_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, loadMapContext, map_loadMapContext_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, applySLD, map_applySLD_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, applySLDURL, map_applySLDURL_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, generateSLD, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getConfigOption, map_getConfigOption_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, setConfigOption, map_setConfigOption_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, applyConfigOptions, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, loadOwsParameters, map_loadOwsParameters_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, owsDispatch, map_owsDispatch_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, insertLayer, map_insertLayer_args, ZEND_ACC_PUBLIC) PHP_ME(mapObj, removeLayer, map_removeLayer_args, ZEND_ACC_PUBLIC) #ifdef disabled PHP_ME(mapObj, getLabel, map_getLabel_args, ZEND_ACC_PUBLIC) #endif PHP_ME(mapObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, getLatLongExtent, NULL, ZEND_ACC_PUBLIC) PHP_ME(mapObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; static int mapscript_map_setProjection(int isWKTProj, php_map_object *php_map, char *projString, int setUnitsAndExtents TSRMLS_DC) { #ifdef USE_PROJ int status = MS_SUCCESS; int units = MS_METERS; projectionObj in; projectionObj out; rectObj rect; int setNewExtents = 0; php_projection_object *php_projection = NULL; php_rect_object *php_extent = NULL; if (ZVAL_NOT_UNDEF(php_map->projection)) php_projection = MAPSCRIPT_OBJ(php_projection_object, php_map->projection); if (ZVAL_NOT_UNDEF(php_map->extent)) php_extent = MAPSCRIPT_OBJ(php_rect_object, php_map->extent); in = php_map->map->projection; msInitProjection(&out); if (isWKTProj) msOGCWKT2ProjectionObj(projString, &(out),php_map->map->debug); else msLoadProjectionString(&(out), projString); rect = php_map->map->extent; if (in.proj!= NULL && out.proj!=NULL) { if (msProjectionsDiffer(&in, &out)) { if (msProjectRect(&in, &out, &rect) == MS_SUCCESS) setNewExtents =1; } } /* Free the temporary projection object */ msFreeProjection(&out); if (isWKTProj) status = mapObj_setWKTProjection(php_map->map, projString); else status = mapObj_setProjection(php_map->map, projString); if (status == -1) { mapscript_report_php_error(E_WARNING, "setProjection failed" TSRMLS_CC); return MS_FAILURE; } else if (ZVAL_NOT_UNDEF(php_map->projection)) { php_projection->projection = &(php_map->map->projection); } units = GetMapserverUnitUsingProj(&(php_map->map->projection)); if (units != -1 && setUnitsAndExtents) { /* -------------------------------------------------------------------- set the units and php_map->map extents. -------------------------------------------------------------------- */ php_map->map->units = units; if (setNewExtents) { php_map->map->extent = rect; php_map->map->cellsize = msAdjustExtent(&(php_map->map->extent), php_map->map->width, php_map->map->height); msCalculateScale(php_map->map->extent, php_map->map->units, php_map->map->width, php_map->map->height, php_map->map->resolution, &(php_map->map->scaledenom)); if (ZVAL_NOT_UNDEF(php_map->extent)) php_extent->rect = &(php_map->map->extent); } } return MS_SUCCESS; #else mapscript_throw_exception("Available only with PROJ.4 support." TSRMLS_CC); return MS_FAILURE; #endif } void mapscript_create_map(mapObj *map, zval *return_value TSRMLS_DC) { php_map_object * php_map; object_init_ex(return_value, mapscript_ce_map); php_map = MAPSCRIPT_OBJ_P(php_map_object, return_value); php_map->map = map; } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_map_create_object(zend_class_entry *ce TSRMLS_DC) { php_map_object *php_map; php_map = ecalloc(1, sizeof(*php_map) + zend_object_properties_size(ce)); zend_object_std_init(&php_map->zobj, ce TSRMLS_CC); object_properties_init(&php_map->zobj, ce); php_map->zobj.handlers = &mapscript_map_object_handlers; ZVAL_UNDEF(&php_map->outputformat); ZVAL_UNDEF(&php_map->extent); ZVAL_UNDEF(&php_map->web); ZVAL_UNDEF(&php_map->reference); ZVAL_UNDEF(&php_map->imagecolor); ZVAL_UNDEF(&php_map->scalebar); ZVAL_UNDEF(&php_map->legend); ZVAL_UNDEF(&php_map->querymap); #ifdef disabled ZVAL_UNDEF(&php_map->labelcache); #endif ZVAL_UNDEF(&php_map->projection); ZVAL_UNDEF(&php_map->metadata); ZVAL_UNDEF(&php_map->configoptions); return &php_map->zobj; } static void mapscript_map_free_object(zend_object *object) { php_map_object *php_map; php_map = (php_map_object *)((char *)object - XtOffsetOf(php_map_object, zobj)); MAPSCRIPT_DELREF(php_map->outputformat); MAPSCRIPT_DELREF(php_map->extent); MAPSCRIPT_DELREF(php_map->web); MAPSCRIPT_DELREF(php_map->reference); MAPSCRIPT_DELREF(php_map->imagecolor); MAPSCRIPT_DELREF(php_map->scalebar); MAPSCRIPT_DELREF(php_map->legend); MAPSCRIPT_DELREF(php_map->querymap); #ifdef disabled MAPSCRIPT_DELREF(php_map->labelcache); #endif MAPSCRIPT_DELREF(php_map->projection); MAPSCRIPT_DELREF(php_map->metadata); MAPSCRIPT_DELREF(php_map->configoptions); mapObj_destroy(php_map->map); zend_object_std_dtor(object); } static zend_object* mapscript_map_clone_object(zval *zobj) { php_map_object *php_map_old, *php_map_new; zend_object* zobj_new; php_map_old = MAPSCRIPT_OBJ_P(php_map_object, zobj); zobj_new = mapscript_map_create_object(mapscript_ce_map); php_map_new = (php_map_object *)((char *)zobj_new - XtOffsetOf(php_map_object, zobj)); zend_objects_clone_members(&php_map_new->zobj, &php_map_old->zobj); php_map_new->map = mapObj_clone(php_map_old->map); return zobj_new; } PHP_MINIT_FUNCTION(map) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "mapObj", map_functions); mapscript_ce_map = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_map->create_object = mapscript_map_create_object; mapscript_ce_map->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_map_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_map_object_handlers)); mapscript_map_object_handlers.free_obj = mapscript_map_free_object; mapscript_map_object_handlers.clone_obj = mapscript_map_clone_object; mapscript_map_object_handlers.offset = XtOffsetOf(php_map_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_map_object_destroy(void *object TSRMLS_DC) { php_map_object *php_map = (php_map_object *)object; MAPSCRIPT_FREE_OBJECT(php_map); MAPSCRIPT_DELREF(php_map->outputformat); MAPSCRIPT_DELREF(php_map->extent); MAPSCRIPT_DELREF(php_map->web); MAPSCRIPT_DELREF(php_map->reference); MAPSCRIPT_DELREF(php_map->imagecolor); MAPSCRIPT_DELREF(php_map->scalebar); MAPSCRIPT_DELREF(php_map->legend); MAPSCRIPT_DELREF(php_map->querymap); #ifdef disabled MAPSCRIPT_DELREF(php_map->labelcache); #endif MAPSCRIPT_DELREF(php_map->projection); MAPSCRIPT_DELREF(php_map->metadata); MAPSCRIPT_DELREF(php_map->configoptions); mapObj_destroy(php_map->map); efree(object); } static zend_object_value mapscript_map_object_new_ex(zend_class_entry *ce, php_map_object **ptr TSRMLS_DC) { zend_object_value retval; php_map_object *php_map; MAPSCRIPT_ALLOC_OBJECT(php_map, php_map_object); retval = mapscript_object_new_ex(&php_map->std, ce, &mapscript_map_object_destroy, &mapscript_map_object_handlers TSRMLS_CC); if (ptr) *ptr = php_map; php_map->outputformat = NULL; php_map->extent = NULL; php_map->web = NULL; php_map->reference = NULL; php_map->imagecolor = NULL; php_map->scalebar = NULL; php_map->legend = NULL; php_map->querymap = NULL; #ifdef disabled php_map->labelcache = NULL; #endif php_map->projection = NULL; php_map->metadata = NULL; php_map->configoptions = NULL; return retval; } static zend_object_value mapscript_map_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_map_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_map_object_clone(zval *zobj TSRMLS_DC) { php_map_object *php_map_old, *php_map_new; zend_object_value new_ov; php_map_old = MAPSCRIPT_OBJ_P(php_map_object, zobj); new_ov = mapscript_map_object_new_ex(mapscript_ce_map, &php_map_new TSRMLS_CC); zend_objects_clone_members(&php_map_new->std, new_ov, &php_map_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_map_new->map = mapObj_clone(php_map_old->map); return new_ov; } PHP_MINIT_FUNCTION(map) { zend_class_entry ce; memcpy(&mapscript_map_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_map_object_handlers.clone_obj = mapscript_map_object_clone; MAPSCRIPT_REGISTER_CLASS("mapObj", map_functions, mapscript_ce_map, mapscript_map_object_new); mapscript_ce_map->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/mapscript_error.c000066400000000000000000000077151357574274700217400ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" #include "zend_exceptions.h" #include "php_mapscript_util.h" #include #include "../../maperror.h" #define MAX_EXCEPTION_MSG 256 zend_class_entry *mapscript_ce_mapscriptexception; #if PHP_VERSION_ID >= 70000 zend_object* mapscript_throw_exception(char *format TSRMLS_DC, ...) #else zval* mapscript_throw_exception(char *format TSRMLS_DC, ...) #endif { va_list args; char message[MAX_EXCEPTION_MSG]; va_start(args, format); vsprintf(message, format, args); va_end(args); return zend_throw_exception(mapscript_ce_mapscriptexception, message, 0 TSRMLS_CC); } #if PHP_VERSION_ID >= 70000 zend_object* mapscript_throw_mapserver_exception(char *format TSRMLS_DC, ...) #else zval* mapscript_throw_mapserver_exception(char *format TSRMLS_DC, ...) #endif { va_list args; char message[MAX_EXCEPTION_MSG]; errorObj *ms_error; ms_error = msGetErrorObj(); while (ms_error && ms_error->code != MS_NOERR) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "[MapServer Error]: %s: %s\n", ms_error->routine, ms_error->message); ms_error = ms_error->next; } va_start(args, format); vsprintf(message, format, args); va_end(args); return mapscript_throw_exception(message TSRMLS_CC); } void mapscript_report_php_error(int error_type, char *format TSRMLS_DC, ...) { va_list args; char message[MAX_EXCEPTION_MSG]; va_start(args, format); vsprintf(message, format, args); va_end(args); php_error_docref(NULL TSRMLS_CC, error_type, "%s,", message); } void mapscript_report_mapserver_error(int error_type TSRMLS_DC) { errorObj *ms_error; ms_error = msGetErrorObj(); while (ms_error && ms_error->code != MS_NOERR) { php_error_docref(NULL TSRMLS_CC, error_type, "[MapServer Error]: %s: %s\n", ms_error->routine, ms_error->message); ms_error = ms_error->next; } } PHP_MINIT_FUNCTION(mapscript_error) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "MapScriptException", NULL); #if PHP_VERSION_ID >= 70000 mapscript_ce_mapscriptexception = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C)); #else mapscript_ce_mapscriptexception = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), "Exception" TSRMLS_CC); #endif return SUCCESS; } mapserver-7.4.3/mapscript/php/mapscript_i.c000066400000000000000000001423661357574274700210410ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Interface file for MapServer PHP scripting extension * called MapScript. This file was originally based on * the SWIG interface file mapscript.i * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000, 2007, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" /* grab mapserver declarations to wrap */ #include "../../mapserver.h" #include "../../mapows.h" #include "../../maperror.h" #include "../../mapprimitive.h" #include "../../mapsymbol.h" #include "../../mapshape.h" #include "../../mapproject.h" #include "../../maphash.h" /********************************************************************** * class extensions for mapObj **********************************************************************/ mapObj *mapObj_new(char *filename, char *new_path) { if(filename && strlen(filename)) return msLoadMap(filename, new_path); else { /* create an empty map, no layers etc... */ return msNewMapObj(); } } mapObj *mapObj_newFromString(char *map_text, char *new_path) { if(map_text && strlen(map_text)) return msLoadMapFromString(map_text, new_path); else { /* create an empty map, no layers etc... */ return msNewMapObj(); } } void mapObj_destroy(mapObj* self) { msFreeMap(self); } mapObj *mapObj_clone(mapObj* self) { mapObj *dstMap; dstMap = msNewMapObj(); if (msCopyMap(dstMap, self) != MS_SUCCESS) { msFreeMap(dstMap); dstMap = NULL; } return dstMap; } int mapObj_setRotation(mapObj* self, double rotation_angle ) { return msMapSetRotation( self, rotation_angle ); } layerObj *mapObj_getLayer(mapObj* self, int i) { if(i >= 0 && i < self->numlayers) return (self->layers[i]); /* returns an EXISTING layer */ else return NULL; } layerObj *mapObj_getLayerByName(mapObj* self, char *name) { int i; i = msGetLayerIndex(self, name); if(i != -1) return (self->layers[i]); /* returns an EXISTING layer */ else return NULL; } int *mapObj_getLayersIndexByGroup(mapObj* self, char *groupname, int *pnCount) { return msGetLayersIndexByGroup(self, groupname, pnCount); } int mapObj_getSymbolByName(mapObj* self, char *name) { return msGetSymbolIndex(&self->symbolset, name, MS_TRUE); } void mapObj_prepareQuery(mapObj* self) { int status; status = msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &self->scaledenom); if(status != MS_SUCCESS) self->scaledenom = -1; // degenerate extents ok here } imageObj *mapObj_prepareImage(mapObj* self) { return msPrepareImage(self, MS_FALSE); } imageObj *mapObj_draw(mapObj* self) { return msDrawMap(self, MS_FALSE); } imageObj *mapObj_drawQuery(mapObj* self) { return msDrawMap(self, MS_TRUE); } imageObj *mapObj_drawLegend(mapObj* self) { return msDrawLegend(self, MS_FALSE, NULL); } imageObj *mapObj_drawScalebar(mapObj* self) { return msDrawScalebar(self); } imageObj *mapObj_drawReferenceMap(mapObj* self) { return msDrawReferenceMap(self); } //TODO int mapObj_embedScalebar(mapObj* self, imageObj *img) { return msEmbedScalebar(self, img); } //TODO int mapObj_embedLegend(mapObj* self, imageObj *img) { return msEmbedLegend(self, img); } int mapObj_drawLabelCache(mapObj* self, imageObj *img) { return msDrawLabelCache(self, img); } labelCacheMemberObj* mapObj_getLabel(mapObj* self, int i) { msSetError(MS_MISCERR, "LabelCacheMember access is not available", "getLabel()"); return NULL; } int mapObj_queryByPoint(mapObj* self, pointObj *point, int mode, double buffer) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_POINT; self->query.mode = mode; self->query.point = *point; self->query.buffer = buffer; return msQueryByPoint(self); } int mapObj_queryByRect(mapObj* self, rectObj rect) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_RECT; self->query.mode = MS_QUERY_MULTIPLE; self->query.rect = rect; return msQueryByRect(self); } int mapObj_queryByFeatures(mapObj* self, int slayer) { self->query.slayer = slayer; return msQueryByFeatures(self); } int mapObj_queryByFilter(mapObj* self, char *string) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_FILTER; self->query.mode = MS_QUERY_MULTIPLE; self->query.filter.string = msStrdup(string); self->query.filter.type = MS_EXPRESSION; self->query.rect = self->extent; return msQueryByFilter(self); } int mapObj_queryByShape(mapObj *self, shapeObj *shape) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_SHAPE; self->query.mode = MS_QUERY_MULTIPLE; self->query.shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(self->query.shape); msCopyShape(shape, self->query.shape); return msQueryByShape(self); } int mapObj_queryByIndex(mapObj *self, int qlayer, int tileindex, int shapeindex, int bAddToQuery) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_INDEX; self->query.mode = MS_QUERY_SINGLE; self->query.tileindex = tileindex; self->query.shapeindex = shapeindex; self->query.clear_resultcache = !bAddToQuery; self->query.layer = qlayer; return msQueryByIndex(self); } int mapObj_saveQuery(mapObj *self, char *filename, int results) { return msSaveQuery(self, filename, results); } int mapObj_loadQuery(mapObj *self, char *filename) { return msLoadQuery(self, filename); } void mapObj_freeQuery(mapObj *self, int qlayer) { msQueryFree(self, qlayer); } int mapObj_setWKTProjection(mapObj *self, char *string) { return msOGCWKT2ProjectionObj(string, &(self->projection), self->debug); } char *mapObj_getProjection(mapObj* self) { return msGetProjectionString(&self->projection); } int mapObj_setProjection(mapObj* self, char *string) { return(msLoadProjectionString(&(self->projection), string)); } int mapObj_save(mapObj* self, char *filename) { return msSaveMap(self, filename); } char *mapObj_getMetaData(mapObj *self, char *name) { return(msLookupHashTable(&(self->web.metadata), name)); } int mapObj_setMetaData(mapObj *self, char *name, char *value) { if (msInsertHashTable(&(self->web.metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } int mapObj_removeMetaData(mapObj *self, char *name) { return(msRemoveHashTable(&(self->web.metadata), name)); } int mapObj_moveLayerup(mapObj *self, int layerindex) { return msMoveLayerUp(self, layerindex); } int mapObj_moveLayerdown(mapObj *self, int layerindex) { return msMoveLayerDown(self, layerindex); } int *mapObj_getLayersdrawingOrder(mapObj *self) { return self->layerorder; } int mapObj_setLayersdrawingOrder(mapObj *self, int *panIndexes) { return msSetLayersdrawingOrder(self, panIndexes); } char *mapObj_processTemplate(mapObj *self, int bGenerateImages, char **names, char **values, int numentries) { return msProcessTemplate(self, bGenerateImages, names, values, numentries); } char *mapObj_processLegendTemplate(mapObj *self, char **names, char **values, int numentries) { return msProcessLegendTemplate(self, names, values, numentries); } char *mapObj_processQueryTemplate(mapObj *self, int bGenerateImages, char **names, char **values, int numentries) { return msProcessQueryTemplate(self, bGenerateImages, names, values, numentries); } int mapObj_setSymbolSet(mapObj *self, char *szFileName) { msFreeSymbolSet(&self->symbolset); msInitSymbolSet(&self->symbolset); // Set symbolset filename self->symbolset.filename = msStrdup(szFileName); // Symbolset shares same fontset as main mapfile self->symbolset.fontset = &(self->fontset); return msLoadSymbolSet(&self->symbolset, self); } int mapObj_getNumSymbols(mapObj *self) { return self->symbolset.numsymbols; } int mapObj_setFontSet(mapObj *self, char *szFileName) { msFreeFontSet(&(self->fontset)); msInitFontSet(&(self->fontset)); // Set fontset filename self->fontset.filename = msStrdup(szFileName); return msLoadFontSet(&(self->fontset), self); } int mapObj_saveMapContext(mapObj *self, char *szFilename) { return msSaveMapContext(self, szFilename); } int mapObj_loadMapContext(mapObj *self, char *szFilename, int bUniqueLayerName) { return msLoadMapContext(self, szFilename, bUniqueLayerName); } int mapObj_selectOutputFormat(mapObj *self, const char *imagetype) { outputFormatObj *format = NULL; format = msSelectOutputFormat(self, imagetype); if (format) { msApplyOutputFormat( &(self->outputformat), format, self->transparent, self->interlace, self->imagequality ); return(MS_SUCCESS); } return(MS_FAILURE); } int mapObj_applySLD(mapObj *self, char *sld) { return msSLDApplySLD(self, sld, -1, NULL, NULL); } int mapObj_applySLDURL(mapObj *self, char *sld) { return msSLDApplySLDURL(self, sld, -1, NULL, NULL); } char *mapObj_generateSLD(mapObj *self) { return msSLDGenerateSLD(self, -1, NULL); } int mapObj_loadOWSParameters(mapObj *self, cgiRequestObj *request, char *wmtver_string) { return msMapLoadOWSParameters(self, request, wmtver_string); } int mapObj_OWSDispatch(mapObj *self, cgiRequestObj *req ) { return msOWSDispatch( self, req, MS_TRUE); } int mapObj_insertLayer(mapObj *self, layerObj *layer, int index) { if (self && layer) return msInsertLayer(self, layer, index); return -1; } layerObj *mapObj_removeLayer(mapObj *self, int layerindex) { return msRemoveLayer(self, layerindex); } int mapObj_setCenter(mapObj *self, pointObj *center) { return msMapSetCenter(self, center); } int mapObj_offsetExtent(mapObj *self, double x, double y) { return msMapOffsetExtent(self, x, y); } int mapObj_scaleExtent(mapObj *self, double zoomfactor, double minscaledenom, double maxscaledenom) { return msMapScaleExtent(self, zoomfactor, minscaledenom, maxscaledenom); } char *mapObj_convertToString(mapObj *self) { return msWriteMapToString(self); } /********************************************************************** * class extensions for layerObj, always within the context of a map **********************************************************************/ layerObj *layerObj_new(mapObj *map) { if(msGrowMapLayers(map) == NULL) return(NULL); if(initLayer((map->layers[map->numlayers]), map) == -1) return(NULL); map->layers[map->numlayers]->index = map->numlayers; //Update the layer order list with the layer's index. map->layerorder[map->numlayers] = map->numlayers; map->numlayers++; return (map->layers[map->numlayers-1]); } void layerObj_destroy(layerObj *self) { /* if the layer has a parent_map, let's the map object destroy it */ if ((self->map == NULL) && (self->refcount == 1)) { /* if there is no other PHP Object that use this C layer object, delete it */ freeLayer(self); free(self); self = NULL; } else { MS_REFCNT_DECR(self); } return; } layerObj *layerObj_clone(layerObj *layer) { layerObj *dstLayer; dstLayer = (layerObj *)malloc(sizeof(layerObj)); initLayer(dstLayer, layer->map); msCopyLayer(dstLayer, layer); return dstLayer; } int layerObj_updateFromString(layerObj *self, char *snippet) { return msUpdateLayerFromString(self, snippet, MS_FALSE); } char *layerObj_convertToString(layerObj *self) { return msWriteLayerToString(self); } int layerObj_open(layerObj *self) { return msLayerOpen(self); } int layerObj_whichShapes(layerObj *self, rectObj *poRect) { int oldconnectiontype = self->connectiontype; self->connectiontype = MS_INLINE; if(msLayerWhichItems(self, MS_FALSE, NULL) != MS_SUCCESS) { self->connectiontype = oldconnectiontype; return MS_FAILURE; } self->connectiontype = oldconnectiontype; return msLayerWhichShapes(self, *poRect, MS_FALSE); } shapeObj *layerObj_nextShape(layerObj *self) { int status; shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); status = msLayerNextShape(self, shape); if(status != MS_SUCCESS) { msFreeShape(shape); free(shape); return NULL; } else return shape; } void layerObj_close(layerObj *self) { msLayerClose(self); } resultObj *layerObj_getResult(layerObj *self, int i) { if(!self->resultcache) return NULL; if(i >= 0 && i < self->resultcache->numresults) return &self->resultcache->results[i]; else return NULL; } classObj *layerObj_getClass(layerObj *self, int i) // returns an EXISTING class { if(i >= 0 && i < self->numclasses) return (self->class[i]); else return(NULL); } int layerObj_getClassIndex(layerObj *self, mapObj *map, shapeObj *shape, int *classgroup, int numclasses) { return msShapeGetClass(self, map, shape, classgroup, numclasses); } int layerObj_draw(layerObj *self, mapObj *map, imageObj *img) { return msDrawLayer(map, self, img); } int layerObj_drawQuery(layerObj *self, mapObj *map, imageObj *img) { return msDrawQueryLayer(map, self, img); } int layerObj_queryByAttributes(layerObj *self, mapObj *map, char *qitem, char *qstring, int mode) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_FILTER; map->query.mode = mode; if(qitem) map->query.filteritem = msStrdup(qitem); if(qstring) { msInitExpression(&map->query.filter); msLoadExpressionString(&map->query.filter, qstring); } map->query.layer = self->index; map->query.rect = map->extent; status = self->status; self->status = MS_ON; retval = msQueryByFilter(map); self->status = status; return retval; } int layerObj_queryByPoint(layerObj *self, mapObj *map, pointObj *point, int mode, double buffer) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_POINT; map->query.mode = mode; map->query.point = *point; map->query.buffer = buffer; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByPoint(map); self->status = status; return retval; } int layerObj_queryByRect(layerObj *self, mapObj *map, rectObj rect) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.rect = rect; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByRect(map); self->status = status; return retval; } int layerObj_queryByFeatures(layerObj *self, mapObj *map, int slayer) { int status; int retval; map->query.slayer = slayer; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByFeatures(map); self->status = status; return retval; } int layerObj_queryByShape(layerObj *self, mapObj *map, shapeObj *shape) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_SHAPE; map->query.mode = MS_QUERY_MULTIPLE; map->query.shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(map->query.shape); msCopyShape(shape, map->query.shape); map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByShape(map); self->status = status; return retval; } int layerObj_queryByFilter(layerObj *self, mapObj *map, char *string) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_FILTER; map->query.mode = MS_QUERY_MULTIPLE; map->query.filter.string = msStrdup(string); map->query.filter.type = MS_EXPRESSION; map->query.layer = self->index; map->query.rect = map->extent; status = self->status; self->status = MS_ON; retval = msQueryByFilter(map); self->status = status; return retval; } int layerObj_queryByIndex(layerObj *self, mapObj *map, int tileindex, int shapeindex, int addtoquery) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_INDEX; map->query.mode = MS_QUERY_SINGLE; map->query.tileindex = tileindex; map->query.shapeindex = shapeindex; map->query.clear_resultcache = !addtoquery; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByIndex(map); self->status = status; return retval; } int layerObj_setFilter(layerObj *self, char *string) { if (!string || strlen(string) == 0) { msFreeExpression(&self->filter); return MS_SUCCESS; } else return msLoadExpressionString(&self->filter, string); } char *layerObj_getFilter(layerObj *self) { return msGetExpressionString(&(self->filter)); } int layerObj_setWKTProjection(layerObj *self, char *string) { self->project = MS_TRUE; return msOGCWKT2ProjectionObj(string, &(self->projection), self->debug); } char *layerObj_getProjection(layerObj* self) { return msGetProjectionString(&self->projection); } int layerObj_setProjection(layerObj *self, char *string) { int nReturn; nReturn = msLoadProjectionString(&(self->projection), string); if (nReturn == MS_SUCCESS) self->project = MS_TRUE; return nReturn; } int layerObj_addFeature(layerObj *self, shapeObj *shape) { if(self->features != NULL && self->features->tailifhead != NULL) shape->index = self->features->tailifhead->shape.index + 1; else shape->index = 0; if(insertFeatureList(&(self->features), shape) == NULL) return MS_FAILURE; else return MS_SUCCESS; } char *layerObj_getMetaData(layerObj *self, char *name) { return(msLookupHashTable(&(self->metadata), name)); } int layerObj_setMetaData(layerObj *self, char *name, char *value) { if (msInsertHashTable(&(self->metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } int layerObj_removeMetaData(layerObj *self, char *name) { return(msRemoveHashTable(&(self->metadata), name)); } char *layerObj_getWMSFeatureInfoURL(layerObj *self, mapObj *map, int click_x, int click_y, int feature_count, char *info_format) { // NOTE: the returned string should be freed by the caller but right // now we're leaking it. return(msWMSGetFeatureInfoURL(map, self, click_x, click_y, feature_count, info_format)); } char *layerObj_executeWFSGetFeature(layerObj *self) { return (msWFSExecuteGetFeature(self)); } int layerObj_applySLD(layerObj *self, char *sld, char *stylelayer) { return msSLDApplySLD(self->map, sld, self->index, stylelayer, NULL); } int layerObj_applySLDURL(layerObj *self, char *sld, char *stylelayer) { return msSLDApplySLDURL(self->map, sld, self->index, stylelayer, NULL); } char *layerObj_generateSLD(layerObj *self) { return msSLDGenerateSLD(self->map, self->index, NULL); } int layerObj_moveClassUp(layerObj *self, int index) { return msMoveClassUp(self, index); } int layerObj_moveClassDown(layerObj *self, int index) { return msMoveClassDown(self, index); } classObj *layerObj_removeClass(layerObj *self, int index) { return msRemoveClass(self, index); } int layerObj_setConnectionType(layerObj *self, int connectiontype, const char *library_str) { /* Caller is responsible to close previous layer correctly before calling * msConnectLayer() */ if (msLayerIsOpen(self)) msLayerClose(self); return msConnectLayer(self, connectiontype, library_str); } /********************************************************************** * class extensions for labelObj **********************************************************************/ labelObj *labelObj_new() { labelObj *label; label = (labelObj *)malloc(sizeof(labelObj)); if(!label) return(NULL); initLabel(label); return label; } void labelObj_destroy(labelObj *self) { if (freeLabel(self) == MS_SUCCESS) free(self); } labelObj *labelObj_clone(labelObj *label) { labelObj *dstLabel; dstLabel = (labelObj *)malloc(sizeof(labelObj)); initLabel(dstLabel); dstLabel->font = NULL; msCopyLabel(dstLabel, label); return dstLabel; } int labelObj_updateFromString(labelObj *self, char *snippet) { return msUpdateLabelFromString(self, snippet, MS_FALSE); } char *labelObj_convertToString(labelObj *self) { return msWriteLabelToString(self); } int labelObj_moveStyleUp(labelObj *self, int index) { return msMoveLabelStyleUp(self, index); } int labelObj_moveStyleDown(labelObj *self, int index) { return msMoveLabelStyleDown(self, index); } int labelObj_deleteStyle(labelObj *self, int index) { return msDeleteLabelStyle(self, index); } int labelObj_setExpression(labelObj *self, char *string) { if (!string || strlen(string) == 0) { msFreeExpression(&self->expression); return MS_SUCCESS; } else return msLoadExpressionString(&self->expression, string); } char *labelObj_getExpressionString(labelObj *self) { return msGetExpressionString(&(self->expression)); } int labelObj_setText(labelObj *self, layerObj *layer, char *string) { if (!string || strlen(string) == 0) { msFreeExpression(&self->text); return MS_SUCCESS; } return msLoadExpressionString(&self->text, string); } char *labelObj_getTextString(labelObj *self) { return msGetExpressionString(&(self->text)); } /********************************************************************** * class extensions for legendObj **********************************************************************/ int legendObj_updateFromString(legendObj *self, char *snippet) { return msUpdateLegendFromString(self, snippet, MS_FALSE); } char *legendObj_convertToString(legendObj *self) { return msWriteLegendToString(self); } /********************************************************************** * class extensions for queryMapObj **********************************************************************/ int queryMapObj_updateFromString(queryMapObj *self, char *snippet) { return msUpdateQueryMapFromString(self, snippet, MS_FALSE); } char *queryMapObj_convertToString(queryMapObj *self) { return msWriteQueryMapToString(self); } /********************************************************************** * class extensions for referenceMapObj **********************************************************************/ int referenceMapObj_updateFromString(referenceMapObj *self, char *snippet) { return msUpdateReferenceMapFromString(self, snippet, MS_FALSE); } char *referenceMapObj_convertToString(referenceMapObj *self) { return msWriteReferenceMapToString(self); } /********************************************************************** * class extensions for scaleBarObj **********************************************************************/ int scalebarObj_updateFromString(scalebarObj *self, char *snippet) { return msUpdateScalebarFromString(self, snippet, MS_FALSE); } char *scalebarObj_convertToString(scalebarObj *self) { return msWriteScalebarToString(self); } /********************************************************************** * class extensions for webObj **********************************************************************/ int webObj_updateFromString(webObj *self, char *snippet) { return msUpdateWebFromString(self, snippet, MS_FALSE); } char *webObj_convertToString(webObj *self) { return msWriteWebToString(self); } /********************************************************************** * class extensions for classObj, always within the context of a layer **********************************************************************/ classObj *classObj_new(layerObj *layer, classObj *class) { if(msGrowLayerClasses(layer) == NULL) return NULL; if(initClass((layer->class[layer->numclasses])) == -1) return NULL; if (class) { msCopyClass((layer->class[layer->numclasses]), class, layer); layer->class[layer->numclasses]->layer = layer; } layer->class[layer->numclasses]->layer = layer; layer->numclasses++; return (layer->class[layer->numclasses-1]); } int classObj_addLabel(classObj *self, labelObj *label) { return msAddLabelToClass(self, label); } labelObj *classObj_removeLabel(classObj *self, int index) { return msRemoveLabelFromClass(self, index); } labelObj *classObj_getLabel(classObj *self, int i) // returns an EXISTING label { if(i >= 0 && i < self->numlabels) return (self->labels[i]); else return(NULL); } int classObj_updateFromString(classObj *self, char *snippet) { return msUpdateClassFromString(self, snippet, MS_FALSE); } char *classObj_convertToString(classObj *self) { return msWriteClassToString(self); } void classObj_destroy(classObj *self) { return; /* do nothing, map deconstrutor takes care of it all */ } int classObj_setExpression(classObj *self, char *string) { if (!string || strlen(string) == 0) { msFreeExpression(&self->expression); return MS_SUCCESS; } else return msLoadExpressionString(&self->expression, string); } char *classObj_getExpressionString(classObj *self) { return msGetExpressionString(&(self->expression)); } int classObj_setText(classObj *self, layerObj *layer, char *string) { if (!string || strlen(string) == 0) { msFreeExpression(&self->text); return MS_SUCCESS; } return msLoadExpressionString(&self->text, string); } char *classObj_getTextString(classObj *self) { return msGetExpressionString(&(self->text)); } int classObj_drawLegendIcon(classObj *self, mapObj *map, layerObj *layer, int width, int height, imageObj *dstImg, int dstX, int dstY) { #ifdef USE_GD msClearLayerPenValues(layer); // just in case the mapfile has already been processed #endif return msDrawLegendIcon(map, layer, self, width, height, dstImg, dstX, dstY, MS_TRUE, NULL); } imageObj *classObj_createLegendIcon(classObj *self, mapObj *map, layerObj *layer, int width, int height) { return msCreateLegendIcon(map, layer, self, width, height, MS_TRUE); } int classObj_setSymbolByName(classObj *self, mapObj *map, char* pszSymbolName) { /* self->symbol = msGetSymbolIndex(&map->symbolset, pszSymbolName, MS_TRUE); return self->symbol; */ return -1; } int classObj_setOverlaySymbolByName(classObj *self, mapObj *map, char* pszOverlaySymbolName) { /* self->overlaysymbol = msGetSymbolIndex(&map->symbolset, pszOverlaySymbolName, MS_TRUE); return self->overlaysymbol; */ return -1; } classObj *classObj_clone(classObj *class, layerObj *layer) { classObj *dstClass; dstClass = (classObj *)malloc(sizeof(classObj)); initClass(dstClass); msCopyClass(dstClass, class, layer); return dstClass; } int classObj_moveStyleUp(classObj *self, int index) { return msMoveStyleUp(self, index); } int classObj_moveStyleDown(classObj *self, int index) { return msMoveStyleDown(self, index); } int classObj_deleteStyle(classObj *self, int index) { return msDeleteStyle(self, index); } /********************************************************************** * class extensions for pointObj, useful many places **********************************************************************/ pointObj *pointObj_new() { return (pointObj *)malloc(sizeof(pointObj)); } void pointObj_destroy(pointObj *self) { free(self); } int pointObj_project(pointObj *self, projectionObj *in, projectionObj *out) { return msProjectPoint(in, out, self); } int pointObj_draw(pointObj *self, mapObj *map, layerObj *layer, imageObj *img, int class_index, char *label_string) { return msDrawPoint(map, layer, self, img, class_index, label_string); } double pointObj_distanceToPoint(pointObj *self, pointObj *point) { return msDistancePointToPoint(self, point); } double pointObj_distanceToLine(pointObj *self, pointObj *a, pointObj *b) { return msDistancePointToSegment(self, a, b); } double pointObj_distanceToShape(pointObj *self, shapeObj *shape) { return msDistancePointToShape(self, shape); } /********************************************************************** * class extensions for lineObj (eg. a line or group of points), * useful many places **********************************************************************/ lineObj *lineObj_new() { lineObj *line; line = (lineObj *)malloc(sizeof(lineObj)); if(!line) return(NULL); line->numpoints=0; line->point=NULL; return line; } void lineObj_destroy(lineObj *self) { free(self->point); free(self); } lineObj *lineObj_clone(lineObj *line) { lineObj *dstLine; dstLine = (lineObj *)malloc(sizeof(lineObj)); dstLine->numpoints= line->numpoints; dstLine->point = (pointObj *)malloc(sizeof(pointObj)*(dstLine->numpoints)); msCopyLine(dstLine, line); return dstLine; } int lineObj_project(lineObj *self, projectionObj *in, projectionObj *out) { return msProjectLine(in, out, self); } pointObj *lineObj_get(lineObj *self, int i) { if(i<0 || i>=self->numpoints) return NULL; else return &(self->point[i]); } int lineObj_add(lineObj *self, pointObj *p) { if(self->numpoints == 0) { /* new */ self->point = (pointObj *)malloc(sizeof(pointObj)); if(!self->point) return MS_FAILURE; } else { /* extend array */ self->point = (pointObj *)realloc(self->point, sizeof(pointObj)*(self->numpoints+1)); if(!self->point) return MS_FAILURE; } self->point[self->numpoints].x = p->x; self->point[self->numpoints].y = p->y; #ifdef USE_POINT_Z_M self->point[self->numpoints].m = p->m; #endif self->numpoints++; return MS_SUCCESS; } /********************************************************************** * class extensions for shapeObj **********************************************************************/ shapeObj *shapeObj_new(int type) { shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if(!shape) return NULL; msInitShape(shape); shape->type = type; return shape; } void shapeObj_destroy(shapeObj *self) { msFreeShape(self); free(self); } int shapeObj_project(shapeObj *self, projectionObj *in, projectionObj *out) { return msProjectShape(in, out, self); } lineObj *shapeObj_get(shapeObj *self, int i) { if(i<0 || i>=self->numlines) return NULL; else return &(self->line[i]); } int shapeObj_add(shapeObj *self, lineObj *line) { return msAddLine(self, line); } int shapeObj_draw(shapeObj *self, mapObj *map, layerObj *layer, imageObj *img) { return msDrawShape(map, layer, self, img, -1, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS); } void shapeObj_setBounds(shapeObj *self) { int i, j; self->bounds.minx = self->bounds.maxx = self->line[0].point[0].x; self->bounds.miny = self->bounds.maxy = self->line[0].point[0].y; for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { self->bounds.minx = MS_MIN(self->bounds.minx, self->line[i].point[j].x); self->bounds.maxx = MS_MAX(self->bounds.maxx, self->line[i].point[j].x); self->bounds.miny = MS_MIN(self->bounds.miny, self->line[i].point[j].y); self->bounds.maxy = MS_MAX(self->bounds.maxy, self->line[i].point[j].y); } } return; } int shapeObj_copy(shapeObj *self, shapeObj *dest) { return(msCopyShape(self, dest)); } int shapeObj_contains(shapeObj *self, pointObj *point) { if(self->type == MS_SHAPE_POLYGON) return msIntersectPointPolygon(point, self); return -1; } int shapeObj_intersects(shapeObj *self, shapeObj *shape) { switch(self->type) { case(MS_SHAPE_LINE): switch(shape->type) { case(MS_SHAPE_LINE): return msIntersectPolylines(self, shape); case(MS_SHAPE_POLYGON): return msIntersectPolylinePolygon(self, shape); } break; case(MS_SHAPE_POLYGON): switch(shape->type) { case(MS_SHAPE_LINE): return msIntersectPolylinePolygon(shape, self); case(MS_SHAPE_POLYGON): return msIntersectPolygons(self, shape); } break; } return -1; } pointObj *shapeObj_getpointusingmeasure(shapeObj *self, double m) { if (self) return msGetPointUsingMeasure(self, m); return NULL; } pointObj *shapeObj_getmeasureusingpoint(shapeObj *self, pointObj *point) { if (self) return msGetMeasureUsingPoint(self, point); return NULL; } shapeObj *shapeObj_buffer(shapeObj *self, double width) { return msGEOSBuffer(self, width); } shapeObj *shapeObj_simplify(shapeObj *self, double tolerance) { return msGEOSSimplify(self, tolerance); } shapeObj *shapeObj_topologypreservingsimplify(shapeObj *self, double tolerance) { return msGEOSTopologyPreservingSimplify(self, tolerance); } shapeObj *shapeObj_convexHull(shapeObj *self) { return msGEOSConvexHull(self); } shapeObj *shapeObj_boundary(shapeObj *self) { return msGEOSBoundary(self); } int shapeObj_contains_geos(shapeObj *self, shapeObj *shape) { return msGEOSContains(self, shape); } shapeObj *shapeObj_Union(shapeObj *self, shapeObj *shape) { return msGEOSUnion(self, shape); } shapeObj *shapeObj_intersection(shapeObj *self, shapeObj *shape) { return msGEOSIntersection(self, shape); } shapeObj *shapeObj_difference(shapeObj *self, shapeObj *shape) { return msGEOSDifference(self, shape); } shapeObj *shapeObj_symdifference(shapeObj *self, shapeObj *shape) { return msGEOSSymDifference(self, shape); } int shapeObj_overlaps(shapeObj *self, shapeObj *shape) { return msGEOSOverlaps(self, shape); } int shapeObj_within(shapeObj *self, shapeObj *shape) { return msGEOSWithin(self, shape); } int shapeObj_crosses(shapeObj *self, shapeObj *shape) { return msGEOSCrosses(self, shape); } int shapeObj_touches(shapeObj *self, shapeObj *shape) { return msGEOSTouches(self, shape); } int shapeObj_equals(shapeObj *self, shapeObj *shape) { return msGEOSEquals(self, shape); } int shapeObj_disjoint(shapeObj *self, shapeObj *shape) { return msGEOSDisjoint(self, shape); } pointObj *shapeObj_getcentroid(shapeObj *self) { return msGEOSGetCentroid(self); } double shapeObj_getarea(shapeObj *self) { return msGEOSArea(self); } double shapeObj_getlength(shapeObj *self) { return msGEOSLength(self); } pointObj *shapeObj_getLabelPoint(shapeObj *self) { pointObj *point = (pointObj *)calloc(1, sizeof(pointObj)); if (point == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for point", "getLabelPoint()"); return NULL; } if(self->type == MS_SHAPE_POLYGON && msPolygonLabelPoint(self, point, -1) == MS_SUCCESS) return point; free(point); return NULL; } /********************************************************************** * class extensions for rectObj **********************************************************************/ rectObj *rectObj_new() { rectObj *rect; rect = (rectObj *)calloc(1, sizeof(rectObj)); if(!rect) return(NULL); rect->minx = -1; rect->miny = -1; rect->maxx = -1; rect->maxy = -1; return(rect); } void rectObj_destroy(rectObj *self) { free(self); } int rectObj_project(rectObj *self, projectionObj *in, projectionObj *out) { return msProjectRect(in, out, self); } double rectObj_fit(rectObj *self, int width, int height) { return msAdjustExtent(self, width, height); } int rectObj_draw(rectObj *self, mapObj *map, layerObj *layer, imageObj *img, int classindex, char *text) { shapeObj shape; msInitShape(&shape); msRectToPolygon(*self, &shape); shape.classindex = classindex; if(text && layer->class[classindex]->numlabels > 0) { shape.text = msStrdup(text); } if(MS_SUCCESS != msDrawShape(map, layer, &shape, img, -1, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS)) { /* error message has been set already */ } msFreeShape(&shape); return 0; } /********************************************************************** * class extensions for shapefileObj **********************************************************************/ shapefileObj *shapefileObj_new(char *filename, int type) { shapefileObj *shapefile; int status; shapefile = (shapefileObj *)calloc(1,sizeof(shapefileObj)); if(!shapefile) return NULL; if(type == -1) status = msShapefileOpen(shapefile, "rb", filename, MS_TRUE); else if (type == -2) status = msShapefileOpen(shapefile, "rb+", filename, MS_TRUE); else status = msShapefileCreate(shapefile, filename, type); if(status == -1) { msShapefileClose(shapefile); free(shapefile); return NULL; } return(shapefile); } void shapefileObj_destroy(shapefileObj *self) { msShapefileClose(self); free(self); } int shapefileObj_get(shapefileObj *self, int i, shapeObj *shape) { if(i<0 || i>=self->numshapes) return -1; msFreeShape(shape); /* frees all lines and points before re-filling */ msSHPReadShape(self->hSHP, i, shape); self->lastshape = i; return MS_SUCCESS; } int shapefileObj_getPoint(shapefileObj *self, int i, pointObj *point) { if(i<0 || i>=self->numshapes) return -1; return msSHPReadPoint(self->hSHP, i, point); } int shapefileObj_getTransformed(shapefileObj *self, mapObj *map, int i, shapeObj *shape) { if(i<0 || i>=self->numshapes) return -1; msFreeShape(shape); /* frees all lines and points before re-filling */ msSHPReadShape(self->hSHP, i, shape); msTransformShapeSimplify(shape, map->extent, map->cellsize); return 0; } void shapefileObj_getExtent(shapefileObj *self, int i, rectObj *rect) { msSHPReadBounds(self->hSHP, i, rect); } int shapefileObj_add(shapefileObj *self, shapeObj *shape) { return msSHPWriteShape(self->hSHP, shape); } int shapefileObj_addPoint(shapefileObj *self, pointObj *point) { return msSHPWritePoint(self->hSHP, point); } /********************************************************************** * class extensions for projectionObj **********************************************************************/ projectionObj *projectionObj_new(char *string) { int status; projectionObj *proj=NULL; proj = (projectionObj *)malloc(sizeof(projectionObj)); if(!proj) return NULL; msInitProjection(proj); status = msLoadProjectionString(proj, string); if(status == -1) { msFreeProjection(proj); free(proj); return NULL; } return proj; } int projectionObj_getUnits(projectionObj *self) { return GetMapserverUnitUsingProj(self); } void projectionObj_destroy(projectionObj *self) { msFreeProjection(self); free(self); } projectionObj *projectionObj_clone(projectionObj *projection) { projectionObj *dstProjection; dstProjection = (projectionObj *)malloc(sizeof(projectionObj)); msInitProjection(dstProjection); msCopyProjection(dstProjection, projection); return dstProjection; } /********************************************************************** * class extensions for labelCacheObj - TP mods **********************************************************************/ void labelCacheObj_freeCache(labelCacheObj *self) { msFreeLabelCache(self); } /********************************************************************** * class extensions for DBFInfo - TP mods **********************************************************************/ char *DBFInfo_getFieldName(DBFInfo *self, int iField) { static char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pszFieldName; } int DBFInfo_getFieldWidth(DBFInfo *self, int iField) { char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pnWidth; } int DBFInfo_getFieldDecimals(DBFInfo *self, int iField) { char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pnDecimals; } DBFFieldType DBFInfo_getFieldType(DBFInfo *self, int iField) { return msDBFGetFieldInfo(self, iField, NULL, NULL, NULL); } /********************************************************************** * class extensions for styleObj, always within the context of a class **********************************************************************/ styleObj *styleObj_new(classObj *class, styleObj *style) { if(msGrowClassStyles(class) == NULL) return NULL; if(initStyle(class->styles[class->numstyles]) == -1) return NULL; if (style) msCopyStyle(class->styles[class->numstyles], style); class->numstyles++; return class->styles[class->numstyles-1]; } styleObj *styleObj_label_new(labelObj *label, styleObj *style) { if(msGrowLabelStyles(label) == NULL) return NULL; if(initStyle(label->styles[label->numstyles]) == -1) return NULL; if (style) msCopyStyle(label->styles[label->numstyles], style); label->numstyles++; return label->styles[label->numstyles-1]; } int styleObj_updateFromString(styleObj *self, char *snippet) { return msUpdateStyleFromString(self, snippet, MS_FALSE); } char *styleObj_convertToString(styleObj *self) { return msWriteStyleToString(self); } int styleObj_setSymbolByName(styleObj *self, mapObj *map, char* pszSymbolName) { self->symbol = msGetSymbolIndex(&map->symbolset, pszSymbolName, MS_TRUE); return self->symbol; } styleObj *styleObj_clone(styleObj *style) { styleObj *newstyle = NULL; if (!style) return NULL; newstyle = (styleObj *)malloc(sizeof(styleObj)); initStyle(newstyle); msCopyStyle(newstyle, style); return newstyle; } void styleObj_setGeomTransform(styleObj *style, char *transform) { if (!style) return; msStyleSetGeomTransform(style, transform); } cgiRequestObj *cgirequestObj_new() { cgiRequestObj *request; request = msAllocCgiObj(); return request; } int cgirequestObj_loadParams(cgiRequestObj *self, char* (*getenv2)(const char*, void* thread_context), char *raw_post_data, ms_uint32 raw_post_data_length, void* thread_context) { self->NumParams = loadParams(self, getenv2, raw_post_data, raw_post_data_length, thread_context); return self->NumParams; } void cgirequestObj_setParameter(cgiRequestObj *self, char *name, char *value) { int i; if (self->NumParams == MS_DEFAULT_CGI_PARAMS) { msSetError(MS_CHILDERR, "Maximum number of items, %d, has been reached", "setItem()", MS_DEFAULT_CGI_PARAMS); } for (i=0; iNumParams; i++) { if (strcasecmp(self->ParamNames[i], name) == 0) { free(self->ParamValues[i]); self->ParamValues[i] = msStrdup(value); break; } } if (i == self->NumParams) { self->ParamNames[self->NumParams] = msStrdup(name); self->ParamValues[self->NumParams] = msStrdup(value); self->NumParams++; } } void cgirequestObj_addParameter(cgiRequestObj *self, char *name, char *value) { if (self->NumParams == MS_DEFAULT_CGI_PARAMS) { msSetError(MS_CHILDERR, "Maximum number of items, %d, has been reached", "addParameter()", MS_DEFAULT_CGI_PARAMS); } self->ParamNames[self->NumParams] = msStrdup(name); self->ParamValues[self->NumParams] = msStrdup(value); self->NumParams++; } char *cgirequestObj_getName(cgiRequestObj *self, int index) { if (index < 0 || index >= self->NumParams) { msSetError(MS_CHILDERR, "Invalid index, valid range is [0, %d]", "getName()", self->NumParams-1); return NULL; } return self->ParamNames[index]; } char *cgirequestObj_getValue(cgiRequestObj *self, int index) { if (index < 0 || index >= self->NumParams) { msSetError(MS_CHILDERR, "Invalid index, valid range is [0, %d]", "getValue()", self->NumParams-1); return NULL; } return self->ParamValues[index]; } char *cgirequestObj_getValueByName(cgiRequestObj *self, const char *name) { int i; for (i=0; iNumParams; i++) { if (strcasecmp(self->ParamNames[i], name) == 0) { return self->ParamValues[i]; } } return NULL; } void cgirequestObj_destroy(cgiRequestObj *self) { free(self); } /********************************************************************** * class extensions hashTableObj **********************************************************************/ // New instance hashTableObj *hashTableObj_new() { return msCreateHashTable(); } // set a hash item given key and value int hashTableObj_set(hashTableObj *self, const char *key, const char *value) { if (msInsertHashTable(self, key, value) == NULL) { return MS_FAILURE; } return MS_SUCCESS; } // get value from item by its key const char *hashTableObj_get(hashTableObj *self, const char *key) { return (msLookupHashTable(self, key)); } // Remove one item from hash table int hashTableObj_remove(hashTableObj *self, const char *key) { return (msRemoveHashTable(self, key)); } // Clear all items in hash table (to NULL) void hashTableObj_clear(hashTableObj *self) { msFreeHashItems(self); initHashTable(self); } // Return the next key or first key if previousKey == NULL char *hashTableObj_nextKey(hashTableObj *self, const char *previousKey) { return ((char *)msNextKeyFromHashTable(self, previousKey)); } resultObj *resultObj_new() { resultObj *r = (resultObj *) msSmallMalloc(sizeof(resultObj)); r->tileindex = -1; r->shapeindex = -1; r->resultindex = -1; return r; } /********************************************************************** * class extensions clusterObj **********************************************************************/ int clusterObj_updateFromString(clusterObj *self, char *snippet) { return msUpdateClusterFromString(self, snippet); } char *clusterObj_convertToString(clusterObj *self) { return msWriteClusterToString(self); } int clusterObj_setGroup(clusterObj *self, char *string) { if (!string || strlen(string) == 0) { msFreeExpression(&self->group); return MS_SUCCESS; } else return msLoadExpressionString(&self->group, string); } char *clusterObj_getGroupString(clusterObj *self) { return msGetExpressionString(&(self->group)); } int clusterObj_setFilter(clusterObj *self, char *string) { if (!string || strlen(string) == 0) { msFreeExpression(&self->filter); return MS_SUCCESS; } else return msLoadExpressionString(&self->filter, string); } char *clusterObj_getFilterString(clusterObj *self) { return msGetExpressionString(&(self->filter)); } outputFormatObj* outputFormatObj_new(const char *driver, char *name) { outputFormatObj *format; format = msCreateDefaultOutputFormat(NULL, driver, name); /* in the case of unsupported formats, msCreateDefaultOutputFormat should return NULL */ if (!format) { msSetError(MS_MISCERR, "Unsupported format driver: %s", "outputFormatObj()", driver); return NULL; } msInitializeRendererVTable(format); /* Else, continue */ format->refcount++; format->inmapfile = MS_TRUE; return format; } void outputFormatObj_destroy(outputFormatObj* self) { if ( --self->refcount < 1 ) msFreeOutputFormat( self ); } imageObj *symbolObj_getImage(symbolObj *self, outputFormatObj *input_format) { imageObj *image = NULL; outputFormatObj *format = NULL; rendererVTableObj *renderer = NULL; int retval; if (self->type != MS_SYMBOL_PIXMAP) { msSetError(MS_SYMERR, "Can't return image from non-pixmap symbol", "getImage()"); return NULL; } if (input_format) { format = input_format; } else { format = msCreateDefaultOutputFormat(NULL, "AGG/PNG", "png"); if (format) msInitializeRendererVTable(format); } if (format == NULL) { msSetError(MS_IMGERR, "Could not create output format", "getImage()"); return NULL; } renderer = format->vtable; msPreloadImageSymbol(renderer, self); if (self->pixmap_buffer) { image = msImageCreate(self->pixmap_buffer->width, self->pixmap_buffer->height, format, NULL, NULL, MS_DEFAULT_RESOLUTION, MS_DEFAULT_RESOLUTION, NULL); if(!image) { return NULL; } retval = renderer->mergeRasterBuffer(image, self->pixmap_buffer, 1.0, 0, 0, 0, 0, self->pixmap_buffer->width, self->pixmap_buffer->height); if(retval != MS_SUCCESS) { msFreeImage(image); return NULL; } } return image; } int symbolObj_setImage(symbolObj *self, imageObj *image) { rendererVTableObj *renderer = NULL; renderer = image->format->vtable; if (self->pixmap_buffer) { msFreeRasterBuffer(self->pixmap_buffer); free(self->pixmap_buffer); } self->pixmap_buffer = (rasterBufferObj*)malloc(sizeof(rasterBufferObj)); if (!self->pixmap_buffer) { msSetError(MS_MEMERR, NULL, "setImage()"); return MS_FAILURE; } self->type = MS_SYMBOL_PIXMAP; if(renderer->getRasterBufferCopy(image, self->pixmap_buffer) != MS_SUCCESS) return MS_FAILURE; return MS_SUCCESS; } mapserver-7.4.3/mapscript/php/outputformat.c000066400000000000000000000331221357574274700212650ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_outputformat; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_outputformat_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(outputformat___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, driver) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat_setOption_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat_getOption_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(outputformat_getOptionByIndex_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() /* {{{ proto outputformat __construct() instanciate outputFormatObj */ PHP_METHOD(outputFormatObj, __construct) { zval *zobj = getThis(); php_outputformat_object *php_outputformat; char *driver; long driver_len = 0; char *name = NULL; long name_len = 0; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &driver, &driver_len, &name, &name_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zobj); if ((php_outputformat->outputformat = outputFormatObj_new(driver, name)) == NULL) { mapscript_throw_exception("Unable to construct outputFormatObj." TSRMLS_CC); return; } } /* }}} */ PHP_METHOD(outputFormatObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zobj); IF_GET_STRING("name", php_outputformat->outputformat->name) else IF_GET_STRING("mimetype", php_outputformat->outputformat->mimetype) else IF_GET_STRING("driver", php_outputformat->outputformat->driver) else IF_GET_STRING("extension", php_outputformat->outputformat->extension) else IF_GET_LONG("renderer", php_outputformat->outputformat->renderer) else IF_GET_LONG("imagemode", php_outputformat->outputformat->imagemode) else IF_GET_LONG("transparent", php_outputformat->outputformat->transparent) else IF_GET_LONG("bands", php_outputformat->outputformat->bands) else IF_GET_LONG("numformatoptions", php_outputformat->outputformat->numformatoptions) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(outputFormatObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zobj); IF_SET_STRING("name", php_outputformat->outputformat->name, value) else IF_SET_STRING("mimetype", php_outputformat->outputformat->mimetype, value) else IF_SET_STRING("driver", php_outputformat->outputformat->driver, value) else IF_SET_STRING("extension", php_outputformat->outputformat->extension, value) else IF_SET_LONG("renderer", php_outputformat->outputformat->renderer, value) else IF_SET_LONG("imagemode", php_outputformat->outputformat->imagemode, value) else IF_SET_LONG("transparent", php_outputformat->outputformat->transparent, value) else if ( (STRING_EQUAL("bands", property)) || (STRING_EQUAL("numformatoptions", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int outputFormat.setOption(string property_name, new_value) Add or Modify the format option list. return true on success.*/ PHP_METHOD(outputFormatObj, setOption) { char *property; long property_len = 0; char *value; long value_len = 0; zval *zobj = getThis(); php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &property, &property_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zobj); msSetOutputFormatOption(php_outputformat->outputformat, property, value); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto string outputFormat.getOption(string property_name) Returns the associated value for the format option property passed as argument. Returns an empty string if property not found.*/ PHP_METHOD(outputFormatObj, getOption) { char *property; long property_len = 0; zval *zobj = getThis(); const char *value = NULL; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zobj); value = msGetOutputFormatOption(php_outputformat->outputformat, property, ""); MAPSCRIPT_RETURN_STRING((char*)value,1); } /* }}} */ /* {{{ proto int outputFormat.validate() Checks some internal consistency issues, and returns MS_SUCCESS if things are OK and MS_FAILURE if there are problems. Some problems are fixed up internally. May produce debug output if issues encountered.*/ PHP_METHOD(outputFormatObj, validate) { zval *zobj = getThis(); int status = MS_FALSE; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zobj); status = msOutputFormatValidate(php_outputformat->outputformat, MS_TRUE); if (status != MS_TRUE) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_LONG(MS_FAILURE); } else RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int outputformat.getOptionByIndex(int index). Return the option at index position. */ PHP_METHOD(outputFormatObj, getOptionByIndex) { zval *zobj = getThis(); long index = -1; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zobj); if (index < 0 || index >= php_outputformat->outputformat->numformatoptions) { mapscript_throw_mapserver_exception("Invalid format option index." TSRMLS_CC); return; } MAPSCRIPT_RETURN_STRING(php_outputformat->outputformat->formatoptions[index],1); } /* }}} */ zend_function_entry outputformat_functions[] = { PHP_ME(outputFormatObj, __construct, outputformat___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(outputFormatObj, __get, outputformat___get_args, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, __set, outputformat___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(outputFormatObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, setOption, outputformat_setOption_args, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, getOption, outputformat_getOption_args, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, getOptionByIndex, outputformat_getOptionByIndex_args, ZEND_ACC_PUBLIC) PHP_ME(outputFormatObj, validate, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_outputformat(outputFormatObj *outputformat, parent_object parent, zval *return_value TSRMLS_DC) { php_outputformat_object * php_outputformat; object_init_ex(return_value, mapscript_ce_outputformat); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, return_value); php_outputformat->outputformat = outputformat; if(ZVAL_NOT_UNDEF(parent.val)) php_outputformat->is_ref = 1; php_outputformat->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_outputformat_create_object(zend_class_entry *ce TSRMLS_DC) { php_outputformat_object *php_outputformat; php_outputformat = ecalloc(1, sizeof(*php_outputformat) + zend_object_properties_size(ce)); zend_object_std_init(&php_outputformat->zobj, ce TSRMLS_CC); object_properties_init(&php_outputformat->zobj, ce); php_outputformat->zobj.handlers = &mapscript_outputformat_object_handlers; MAPSCRIPT_INIT_PARENT(php_outputformat->parent); php_outputformat->is_ref = 0; return &php_outputformat->zobj; } static void mapscript_outputformat_free_object(zend_object *object) { php_outputformat_object *php_outputformat; php_outputformat = (php_outputformat_object *)((char *)object - XtOffsetOf(php_outputformat_object, zobj)); MAPSCRIPT_FREE_PARENT(php_outputformat->parent); if (php_outputformat->outputformat && !php_outputformat->is_ref) { outputFormatObj_destroy(php_outputformat->outputformat); } zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(outputformat) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "outputFormatObj", outputformat_functions); mapscript_ce_outputformat = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_outputformat->create_object = mapscript_outputformat_create_object; mapscript_ce_outputformat->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_outputformat_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_outputformat_object_handlers)); mapscript_outputformat_object_handlers.free_obj = mapscript_outputformat_free_object; mapscript_outputformat_object_handlers.offset = XtOffsetOf(php_outputformat_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_outputformat_object_destroy(void *object TSRMLS_DC) { php_outputformat_object *php_outputformat = (php_outputformat_object *)object; MAPSCRIPT_FREE_OBJECT(php_outputformat); MAPSCRIPT_FREE_PARENT(php_outputformat->parent); if (php_outputformat->outputformat && !php_outputformat->is_ref) { outputFormatObj_destroy(php_outputformat->outputformat); } efree(object); } static zend_object_value mapscript_outputformat_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_outputformat_object *php_outputformat; MAPSCRIPT_ALLOC_OBJECT(php_outputformat, php_outputformat_object); retval = mapscript_object_new(&php_outputformat->std, ce, &mapscript_outputformat_object_destroy TSRMLS_CC); php_outputformat->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_outputformat->parent); return retval; } PHP_MINIT_FUNCTION(outputformat) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("outputFormatObj", outputformat_functions, mapscript_ce_outputformat, mapscript_outputformat_object_new); mapscript_ce_outputformat->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/owsrequest.c000066400000000000000000000454461357574274700207510ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" #include "SAPI.h" #include "php_variables.h" #if PHP_VERSION_ID >= 50600 #include "php_streams.h" #endif char *owsrequest_getenv(const char *name, void *thread_context); zend_class_entry *mapscript_ce_owsrequest; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_owsrequest_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(owsrequest___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_setParameter_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_addParameter_args, 0, 0, 2) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_getName_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_getValue_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(owsrequest_getValueByName_args, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() /* {{{ proto owsrequest __construct() Create a new OWSRequestObj instance. */ PHP_METHOD(OWSRequestObj, __construct) { zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; cgiRequestObj *request; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, zobj); if ((request = cgirequestObj_new()) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } php_owsrequest->cgirequest = request; } /* }}} */ PHP_METHOD(OWSRequestObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, zobj); IF_GET_LONG("numparams", php_owsrequest->cgirequest->NumParams) else IF_GET_STRING("contenttype", php_owsrequest->cgirequest->contenttype) else IF_GET_STRING("postrequest", php_owsrequest->cgirequest->postrequest) else IF_GET_STRING("httpcookiedata", php_owsrequest->cgirequest->httpcookiedata) else IF_GET_LONG("type", php_owsrequest->cgirequest->type) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(OWSRequestObj, __set) { char *property; long property_len = 0; zval *value; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ( (STRING_EQUAL("numparams", property)) || (STRING_EQUAL("type", property)) || (STRING_EQUAL("contenttype", property)) || (STRING_EQUAL("postrequest", property)) || (STRING_EQUAL("httpcookiedata", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int owsrequest.loadParams() Initializes the OWSRequest object from the cgi environment variables REQUEST_METHOD, QUERY_STRING and HTTP_COOKIE. Returns the number of name/value pairs collected. */ PHP_METHOD(OWSRequestObj, loadParams) { zval *zobj = getThis(); MAPSCRIPT_ZVAL_P val; php_owsrequest_object *php_owsrequest; void *thread_context; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); thread_context = NULL; php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, zobj); if ( (STRING_EQUAL(sapi_module.name,"cli")) || (STRING_EQUAL(sapi_module.name,"cgi")) || (STRING_EQUAL(sapi_module.name,"cgi-fcgi")) ) { cgirequestObj_loadParams(php_owsrequest->cgirequest, NULL, NULL, 0, thread_context); } else { // check if we have input data for GET method if (SG(request_info).request_method && STRING_EQUAL(SG(request_info).request_method, "GET")) { #if PHP_VERSION_ID >= 70000 zend_is_auto_global_str("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); if ( !Z_ISUNDEF(PG(http_globals)[TRACK_VARS_SERVER]) && ((val = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "QUERY_STRING", sizeof("QUERY_STRING")-1)) != NULL) && (Z_TYPE_P(val) == IS_STRING) && (Z_STRLEN_P(val) > 0) ) { cgirequestObj_loadParams(php_owsrequest->cgirequest, owsrequest_getenv, NULL, 0, thread_context); } #else zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); if ( PG(http_globals)[TRACK_VARS_SERVER] && (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "QUERY_STRING", sizeof("QUERY_STRING"), (void **) &val) == SUCCESS) && (Z_TYPE_PP(val) == IS_STRING) && (Z_STRLEN_PP(val) > 0) ) { cgirequestObj_loadParams(php_owsrequest->cgirequest, owsrequest_getenv, NULL, 0, thread_context); } #endif } else { #if PHP_VERSION_ID >= 50600 php_stream *s = php_stream_temp_new(); php_stream *input = php_stream_open_wrapper("php://input", "r", 0, NULL); #if PHP_VERSION_ID >= 70000 zend_string *raw_post_data = NULL; #else char *raw_post_data = NULL; long raw_post_data_length = 0; #endif /* php://input does not support stat */ php_stream_copy_to_stream_ex(input, s, -1, NULL); php_stream_close(input); php_stream_rewind(s); #if PHP_VERSION_ID >= 70000 raw_post_data = php_stream_copy_to_mem(s, -1, 0); cgirequestObj_loadParams(php_owsrequest->cgirequest, owsrequest_getenv, ZSTR_VAL(raw_post_data), ZSTR_LEN(raw_post_data), thread_context); if(raw_post_data) zend_string_free(raw_post_data); #else raw_post_data_length = php_stream_copy_to_mem(s, raw_post_data, -1, 0); cgirequestObj_loadParams(php_owsrequest->cgirequest, owsrequest_getenv, raw_post_data, raw_post_data_length, thread_context); #endif #else cgirequestObj_loadParams(php_owsrequest->cgirequest, owsrequest_getenv, SG(request_info).raw_post_data, SG(request_info).raw_post_data_length, thread_context); #endif } } RETURN_LONG(php_owsrequest->cgirequest->NumParams); } /* }}} */ /* {{{ proto int owsrequest.setParameter(string name, string value) Set a request parameter. */ PHP_METHOD(OWSRequestObj, setParameter) { char *name; long name_len = 0; char *value; long value_len = 0; zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, zobj); cgirequestObj_setParameter(php_owsrequest->cgirequest, name, value); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int owsrequest.addParameter(string name, string value) Add a request parameter. */ PHP_METHOD(OWSRequestObj, addParameter) { char *name; long name_len = 0; char *value; long value_len = 0; zval *zobj = getThis(); php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, zobj); cgirequestObj_addParameter(php_owsrequest->cgirequest, name, value); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto string owsrequest.getName(int index) Return the name of the parameter at index in the request's array of parameter names. */ PHP_METHOD(OWSRequestObj, getName) { long index; zval *zobj = getThis(); char *value = NULL; php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, zobj); value = cgirequestObj_getName(php_owsrequest->cgirequest, index); if (!value) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETURN_STRING(value,1); } /* }}} */ /* {{{ proto string owsrequest.getValue(int index) Return the value of the parameter at index in the request’s array of parameter values.*/ PHP_METHOD(OWSRequestObj, getValue) { long index; zval *zobj = getThis(); char *value = NULL; php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, zobj); value = cgirequestObj_getValue(php_owsrequest->cgirequest, index); if (!value) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETURN_STRING(value,1); } /* }}} */ /* {{{ proto string owsrequest.getValueByName(string name) Return the value associated with the parameter name.*/ PHP_METHOD(OWSRequestObj, getValueByName) { char *name; long name_len = 0; zval *zobj = getThis(); char *value = NULL; php_owsrequest_object *php_owsrequest; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, zobj); value = cgirequestObj_getValueByName(php_owsrequest->cgirequest, name); if (!value) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETURN_STRING(value,1); } /* }}} */ zend_function_entry owsrequest_functions[] = { PHP_ME(OWSRequestObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(OWSRequestObj, __get, owsrequest___get_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, __set, owsrequest___set_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, loadParams, NULL, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, setParameter, owsrequest_setParameter_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, addParameter, owsrequest_addParameter_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, getName, owsrequest_getName_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, getValue, owsrequest_getValue_args, ZEND_ACC_PUBLIC) PHP_ME(OWSRequestObj, getValueByName, owsrequest_getValueByName_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; #if PHP_VERSION_ID < 70000 char *owsrequest_getenv(const char *name, void *thread_context) { zval **val, **ppzval; zval *cookie_result, *key; HashTable *cookies; char *string_key = NULL, *cookie_tmp; ulong num_key; int i = 0; TSRMLS_FETCH_FROM_CTX(thread_context); if (STRING_EQUAL(name, "HTTP_COOKIE")) { cookies = PG(http_globals)[TRACK_VARS_COOKIE]->value.ht; MAKE_STD_ZVAL(cookie_result); ZVAL_STRING(cookie_result, "",1); for(zend_hash_internal_pointer_reset(cookies); zend_hash_has_more_elements(cookies) == SUCCESS; zend_hash_move_forward(cookies), ++i) { zend_hash_get_current_data(cookies, (void **)&ppzval); zend_hash_get_current_key(cookies, &string_key, &num_key, 1); cookie_tmp = malloc((strlen(string_key)+Z_STRLEN_PP(ppzval)+3) * sizeof(char)); sprintf(cookie_tmp, "%s=%s;",string_key,Z_STRVAL_PP(ppzval)); MAKE_STD_ZVAL(key); ZVAL_STRING(key, cookie_tmp,1); add_string_to_string(cookie_result,cookie_result, key); zval_dtor(key); free(cookie_tmp); } return Z_STRVAL_P(cookie_result); } else { zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); if ( PG(http_globals)[TRACK_VARS_SERVER] && (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, name, strlen(name)+1, (void **) &val) == SUCCESS) && (Z_TYPE_PP(val) == IS_STRING)) { return Z_STRVAL_PP(val); } } return NULL; } #else /* PHP7 - Modification by Bjoern Boldt */ char *owsrequest_getenv(const char *name, void *thread_context) { zval *val, *ppzval; zval cookie_result; HashTable *cookies; zend_string *string_key; zend_string *result = NULL; zend_ulong num_key; size_t len, sum = 0; int i = 0; TSRMLS_FETCH_FROM_CTX(thread_context); if (STRING_EQUAL(name, "HTTP_COOKIE")) { cookies = Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]); for(zend_hash_internal_pointer_reset(cookies); zend_hash_has_more_elements(cookies) == SUCCESS; zend_hash_move_forward(cookies), ++i) { ppzval = zend_hash_get_current_data(cookies); zend_hash_get_current_key(cookies, &string_key, &num_key); len = (ZSTR_LEN(string_key)+Z_STRLEN_P(ppzval)+2) * sizeof(char); if(!result) result = zend_string_alloc(len, 1); else result = zend_string_extend(result, sum + len, 1); sprintf(&result->val[sum], "%s=%s;",ZSTR_VAL(string_key),Z_STRVAL_P(ppzval)); sum += len; } if (result){ ZVAL_STRINGL(&cookie_result, ZSTR_VAL(result), ZSTR_LEN(result)); zend_string_free(result); return Z_STRVAL(cookie_result); /* this string will stay in memory until php-script exit */ } else return ""; } else { zend_is_auto_global_str("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); if ( (!Z_ISUNDEF(PG(http_globals)[TRACK_VARS_SERVER])) && ((val = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), name, strlen(name))) != NULL) && (Z_TYPE_P(val) == IS_STRING)) { return Z_STRVAL_P(val); } } return NULL; } #endif void mapscript_create_owsrequest(cgiRequestObj *cgirequest, zval *return_value TSRMLS_DC) { php_owsrequest_object * php_owsrequest; object_init_ex(return_value, mapscript_ce_owsrequest); php_owsrequest = MAPSCRIPT_OBJ_P(php_owsrequest_object, return_value); php_owsrequest->cgirequest = cgirequest; } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_owsrequest_create_object(zend_class_entry *ce TSRMLS_DC) { php_owsrequest_object *php_owsrequest; php_owsrequest = ecalloc(1, sizeof(*php_owsrequest) + zend_object_properties_size(ce)); zend_object_std_init(&php_owsrequest->zobj, ce TSRMLS_CC); object_properties_init(&php_owsrequest->zobj, ce); php_owsrequest->zobj.handlers = &mapscript_owsrequest_object_handlers; return &php_owsrequest->zobj; } static void mapscript_owsrequest_free_object(zend_object *object) { php_owsrequest_object *php_owsrequest; php_owsrequest = (php_owsrequest_object *)((char *)object - XtOffsetOf(php_owsrequest_object, zobj)); cgirequestObj_destroy(php_owsrequest->cgirequest); zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(owsrequest) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "OWSRequestObj", owsrequest_functions); mapscript_ce_owsrequest = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_owsrequest->create_object = mapscript_owsrequest_create_object; mapscript_ce_owsrequest->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_owsrequest_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_owsrequest_object_handlers)); mapscript_owsrequest_object_handlers.free_obj = mapscript_owsrequest_free_object; mapscript_owsrequest_object_handlers.offset = XtOffsetOf(php_owsrequest_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_owsrequest_object_destroy(void *object TSRMLS_DC) { php_owsrequest_object *php_owsrequest = (php_owsrequest_object *)object; MAPSCRIPT_FREE_OBJECT(php_owsrequest); cgirequestObj_destroy(php_owsrequest->cgirequest); efree(object); } static zend_object_value mapscript_owsrequest_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_owsrequest_object *php_owsrequest; MAPSCRIPT_ALLOC_OBJECT(php_owsrequest, php_owsrequest_object); retval = mapscript_object_new(&php_owsrequest->std, ce, &mapscript_owsrequest_object_destroy TSRMLS_CC); return retval; } PHP_MINIT_FUNCTION(owsrequest) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("OWSRequestObj", owsrequest_functions, mapscript_ce_owsrequest, mapscript_owsrequest_object_new); mapscript_ce_owsrequest->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/php_mapscript.c000066400000000000000000001422531357574274700213730ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000-2005, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" #include "php_mapscript_util.h" #include "php.h" #include "php_globals.h" #include "SAPI.h" #include "ext/standard/info.h" #include "ext/standard/head.h" #include "../../maperror.h" #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #else #include #endif /* All gd functions used in this extension (if they are renamed in the "main/php_compat.h" file of php source) should be added here too for compatibility reasons: when php compiles gd as a shared extention */ #if defined(HAVE_GD_BUNDLED) #undef gdImageColorExact #undef gdImageColorTransparent #undef gdImageCopy #endif #ifndef DLEXPORT #define DLEXPORT ZEND_DLEXPORT #endif //#if defined(_WIN32) && !defined(__CYGWIN__) //void ***tsrm_ls; //#endif zend_object_handlers mapscript_std_object_handlers; ZEND_BEGIN_ARG_INFO_EX(ms_newShapeObj_args, 0, 0, 1) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_shapeObjFromWkt_args, 0, 0, 1) ZEND_ARG_INFO(0, wkt) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newShapeFileObj_args, 0, 0, 2) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newMapObj_args, 0, 0, 1) ZEND_ARG_INFO(0, mapFileName) ZEND_ARG_INFO(0, newMapPath) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newMapObjFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, mapFileString) ZEND_ARG_INFO(0, newMapPath) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newLayerObj_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newProjectionObj_args, 0, 0, 1) ZEND_ARG_INFO(0, projString) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newStyleObj_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, class, classObj, 0) ZEND_ARG_OBJ_INFO(0, style, styleObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newClassObj_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, class, classObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newSymbolObj_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_INFO(0, symbolName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(ms_newGridObj_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_END_ARG_INFO() /* {{{ proto mapObj ms_newMapObj(string mapFileName, newMapPath) Create a new mapObj instance. */ PHP_FUNCTION(ms_newMapObj) { char *filename; long filename_len = 0; char *path = NULL; long path_len = 0; mapObj *map = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &filename, &filename_len, &path, &path_len) == FAILURE) { return; PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); map = mapObj_new(filename, path); if (map == NULL) { mapscript_throw_mapserver_exception("Failed to open map file \"%s\", or map file error." TSRMLS_CC, filename); return; } mapscript_create_map(map, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto mapObj ms_newMapObj(string mapFileString, newMapPath) Create a new mapObj instance. */ PHP_FUNCTION(ms_newMapObjFromString) { char *string; long string_len = 0; char *path = NULL; long path_len = 0; mapObj *map = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &string, &string_len, &path, &path_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); map = mapObj_newFromString(string, path); if (map == NULL) { mapscript_throw_mapserver_exception("Error while loading map file from string." TSRMLS_CC); return; } mapscript_create_map(map, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto layerObj ms_newLayerObj(mapObj map [, layerObj layer]) Create a new layerObj instance. */ PHP_FUNCTION(ms_newLayerObj) { zval *zmap, *zlayer = NULL; layerObj *layer; int index; php_map_object *php_map; php_layer_object *php_layer; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); if (zlayer) php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); if ((layer = layerObj_new(php_map->map)) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* if a layer is passed as argument, copy the layer into the new one */ if (zlayer) { index = layer->index; msCopyLayer(layer, php_layer->layer); layer->index = index; } MAPSCRIPT_MAKE_PARENT(zmap, NULL); mapscript_create_layer(layer, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto projectionObj ms_newProjectionObj(string projString) Create a new projectionObj instance. */ PHP_FUNCTION(ms_newProjectionObj) { char *projString; long projString_len = 0; projectionObj *projection = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &projString, &projString_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((projection = projectionObj_new(projString)) == NULL) { mapscript_throw_mapserver_exception("Unable to construct projectionObj." TSRMLS_CC); return; } MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_projection(projection, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto rectObj ms_newRectObj() Create a new rectObj instance. */ PHP_FUNCTION(ms_newRectObj) { php_rect_object * php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); object_init_ex(return_value, mapscript_ce_rect); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, return_value); if ((php_rect->rect = rectObj_new()) == NULL) { mapscript_throw_exception("Unable to construct rectObj." TSRMLS_CC); return; } } /* }}} */ /* {{{ proto pointObj ms_newPointObj() Create a new pointObj instance. */ PHP_FUNCTION(ms_newPointObj) { pointObj *point = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((point = pointObj_new()) == NULL) { mapscript_throw_mapserver_exception("Unable to construct pointObj." TSRMLS_CC); return; } point->x = 0; point->y = 0; #ifdef USE_POINT_Z_M point->z = 0; point->m = 0; #endif /* Return point object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* {{{ proto lineObj ms_newLineObj() Create a new lineObj instance. */ PHP_FUNCTION(ms_newLineObj) { php_line_object * php_line; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); object_init_ex(return_value, mapscript_ce_line); php_line = MAPSCRIPT_OBJ_P(php_line_object, return_value); if ((php_line->line = lineObj_new()) == NULL) { mapscript_throw_exception("Unable to construct lineObj." TSRMLS_CC); return; } } /* }}} */ /* {{{ proto styleObj __construct(classObj class [, styleObj style]) Create a new styleObj instance */ PHP_FUNCTION(ms_newStyleObj) { zval *zclass, *zstyle = NULL; styleObj *style; php_class_object *php_class; php_style_object *php_style; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zclass, mapscript_ce_class, &zstyle, mapscript_ce_style) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_class = MAPSCRIPT_OBJ_P(php_class_object, zclass); if (zstyle) php_style = MAPSCRIPT_OBJ_P(php_style_object, zstyle); if ((style = styleObj_new(php_class->class, (zstyle ? php_style->style : NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return point object */ MAPSCRIPT_MAKE_PARENT(zclass, NULL); mapscript_create_style(style, parent, return_value TSRMLS_CC); } /* {{{ proto classObj ms_newClassObj(layerObj layer [, classObj class]) Create a new class instance in the specified layer.. */ PHP_FUNCTION(ms_newClassObj) { zval *zlayer, *zclass = NULL; classObj *class; php_layer_object *php_layer; php_class_object *php_class; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|O", &zlayer, mapscript_ce_layer, &zclass, mapscript_ce_class) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); if (zclass) php_class = MAPSCRIPT_OBJ_P(php_class_object, zclass); if ((class = classObj_new(php_layer->layer, (zclass ? php_class->class:NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } MAPSCRIPT_MAKE_PARENT(zlayer, NULL); mapscript_create_class(class, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int ms_newSymbolObj(mapObj map, string symbolName) Create a new symbolObj instance and return its index. */ PHP_FUNCTION(ms_newSymbolObj) { zval *zmap; char *symbolName; long symbolName_len = 0; int retval = 0; php_map_object *php_map; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zmap, mapscript_ce_map, &symbolName, &symbolName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); retval = msAddNewSymbol(php_map->map, symbolName); RETURN_LONG(retval); } /* }}} */ /* {{{ proto shapeObj ms_newShapeObj(int type) Create a new shapeObj instance. */ PHP_FUNCTION(ms_newShapeObj) { php_shape_object * php_shape; long type; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); object_init_ex(return_value, mapscript_ce_shape); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, return_value); if ((php_shape->shape = shapeObj_new(type)) == NULL) { mapscript_throw_exception("Unable to construct shapeObj." TSRMLS_CC); return; } MAKE_STD_ZVAL(php_shape->values); mapscript_array_init(php_shape->values); } /* }}} */ /* {{{ proto shapeObj shapeObjFromWkt(string type) Creates new shape object from WKT string. */ PHP_FUNCTION(ms_shapeObjFromWkt) { php_shape_object * php_shape; char *wkt; long str_len = 0; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &wkt, &str_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); object_init_ex(return_value, mapscript_ce_shape); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, return_value); if ((php_shape->shape = msShapeFromWKT(wkt)) == NULL) { mapscript_throw_exception("Unable to construct shapeObj." TSRMLS_CC); return; } MAKE_STD_ZVAL(php_shape->values); mapscript_array_init(php_shape->values); } /* }}} */ /* {{{ proto shapefile ms_newShapeFileObj(string filename, int type) Create a new shapeFileObj instance. */ PHP_FUNCTION(ms_newShapeFileObj) { char *filename; long filename_len = 0; long type; shapefileObj *shapefile; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &filename, &filename_len, &type) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); shapefile = shapefileObj_new(filename, type); if (shapefile == NULL) { mapscript_throw_mapserver_exception("Failed to open shapefile %s" TSRMLS_CC, filename); return; } mapscript_create_shapefile(shapefile, return_value TSRMLS_CC); } /* }}} */ PHP_FUNCTION(ms_newOWSRequestObj) { cgiRequestObj *request; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((request = cgirequestObj_new()) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return owsrequest object */ mapscript_create_owsrequest(request, return_value TSRMLS_CC); } /* {{{ proto gridObj ms_newGridObj(layerObj layer) Create a new intance of gridObj. */ PHP_FUNCTION(ms_newGridObj) { zval *zlayer; php_layer_object *php_layer; php_grid_object *php_grid; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zlayer, mapscript_ce_layer) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); php_layer->layer->connectiontype = MS_GRATICULE; if (php_layer->layer->grid != NULL) { freeGrid(php_layer->layer->grid); free(php_layer->layer->grid); } php_layer->layer->grid = (graticuleObj *)malloc( sizeof( graticuleObj ) ); initGrid(php_layer->layer->grid); if (ZVAL_NOT_UNDEF(php_layer->grid) && (MAPSCRIPT_TYPE(php_layer->grid) == IS_OBJECT)) { php_grid = MAPSCRIPT_OBJ(php_grid_object, php_layer->grid); php_grid->parent.child_ptr = NULL; #if PHP_VERSION_ID < 70000 zend_objects_store_del_ref(php_layer->grid TSRMLS_CC); #else MAPSCRIPT_DELREF(php_layer->grid); #endif } MAKE_STD_ZVAL(php_layer->grid); MAPSCRIPT_MAKE_PARENT(zlayer, &php_layer->grid); #if PHP_VERSION_ID < 70000 mapscript_create_grid((graticuleObj *)(php_layer->layer->grid), parent, php_layer->grid TSRMLS_CC); zend_objects_store_add_ref(php_layer->grid TSRMLS_CC); *return_value = *(php_layer->grid); #else mapscript_create_grid((graticuleObj *)(php_layer->layer->grid), parent, &php_layer->grid TSRMLS_CC); ZVAL_COPY_VALUE(return_value, &php_layer->grid); #endif } /* }}} */ /* {{{ proto errorObj ms_GetErrorObj() Return the head of the MapServer errorObj list. */ PHP_FUNCTION(ms_GetErrorObj) { errorObj *error; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((error = msGetErrorObj()) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* Return error object */ mapscript_create_error(error, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto errorObj ms_ResetErrorList() Clear the MapServer errorObj list. */ PHP_FUNCTION(ms_ResetErrorList) { msResetErrorList(); } /* }} */ /*===================================================================== * PHP function wrappers *====================================================================*/ /************************************************************************/ /* ms_VetVersion() */ /* */ /* Returns a string with MapServer version and configuration */ /* params. */ /************************************************************************/ PHP_FUNCTION(ms_GetVersion) { PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); MAPSCRIPT_RETURN_STRING(msGetVersion(), 1); } /************************************************************************/ /* ms_GetVersionInt() */ /* */ /* Returns the MapServer version in int format. */ /* Given version x.y.z, returns x*0x10000+y*0x100+z */ /************************************************************************/ PHP_FUNCTION(ms_GetVersionInt) { PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); RETURN_LONG(msGetVersionInt()); } /* ==================================================================== */ /* utility functions related to msio */ /* ==================================================================== */ PHP_FUNCTION(ms_ioInstallStdoutToBuffer) { msIO_installStdoutToBuffer(); RETURN_TRUE; } PHP_FUNCTION(ms_ioResetHandlers) { msIO_resetHandlers(); RETURN_TRUE; } PHP_FUNCTION(ms_ioInstallStdinFromBuffer) { msIO_installStdinFromBuffer(); RETURN_TRUE; } PHP_FUNCTION(ms_ioGetStdoutBufferString) { char *buffer; msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; if(ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { php_error(E_ERROR, "Can't identify msIO buffer"); RETURN_FALSE; } buf = (msIOBuffer *) ctx->cbData; /* write one zero byte and backtrack if it isn't already there */ if( buf->data_len == 0 || buf->data[buf->data_offset] != '\0' ) { msIO_bufferWrite( buf, "", 1 ); buf->data_offset--; } buffer = (char *) (buf->data); MAPSCRIPT_RETURN_STRINGL(buffer, buf->data_offset, 1); } typedef struct { unsigned char *data; int size; int owns_data; } gdBuffer; PHP_FUNCTION(ms_ioGetStdoutBufferBytes) { msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; gdBuffer gdBuf; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { php_error(E_ERROR, "Can't identify msIO buffer"); RETURN_FALSE; } buf = (msIOBuffer *) ctx->cbData; gdBuf.data = buf->data; gdBuf.size = buf->data_offset; gdBuf.owns_data = MS_FALSE; /* we are seizing ownership of the buffer contents */ buf->data_offset = 0; buf->data_len = 0; buf->data = NULL; php_write(gdBuf.data, gdBuf.size TSRMLS_CC); /* return the gdBuf.size, which is the "really used length" of the msIOBuffer */ RETURN_LONG(gdBuf.size); } PHP_FUNCTION(ms_ioStripStdoutBufferContentType) { const char *buf = NULL; buf = msIO_stripStdoutBufferContentType(); if (buf) { MAPSCRIPT_RETURN_STRING((char *)buf, 1); } else { RETURN_FALSE; } } PHP_FUNCTION(ms_ioGetAndStripStdoutBufferMimeHeaders) { hashTableObj *hashtable; char *value, *key = NULL; if((hashtable = msIO_getAndStripStdoutBufferMimeHeaders())) { array_init(return_value); while((key = hashTableObj_nextKey(hashtable, key))) { value = (char *) hashTableObj_get(hashtable, key); #if PHP_VERSION_ID < 70000 add_assoc_string(return_value, key, value, 1); #else add_assoc_string(return_value, key, value); #endif } free(hashtable); } else RETURN_FALSE; } PHP_FUNCTION(ms_ioStripStdoutBufferContentHeaders) { msIO_stripStdoutBufferContentHeaders(); } /* ==================================================================== */ /* utility functions */ /* ==================================================================== */ /************************************************************************/ /* void ms_getcwd */ /* */ /* This function is a copy of the */ /* vod php3_posix_getcwd(INTERNAL_FUNCTION_PARAMETERS) */ /* (./php/functions/posix.c). */ /* */ /* Since posix functions seems to not be standard in php, It has been*/ /* added here. */ /************************************************************************/ /* OS/2's gcc defines _POSIX_PATH_MAX but not PATH_MAX */ #if !defined(PATH_MAX) && defined(_POSIX_PATH_MAX) #define PATH_MAX _POSIX_PATH_MAX #endif #if !defined(PATH_MAX) && defined(MAX_PATH) #define PATH_MAX MAX_PATH #endif #if !defined(PATH_MAX) #define PATH_MAX 512 #endif PHP_FUNCTION(ms_getCwd) { char buffer[PATH_MAX]; char *p; p = getcwd(buffer, PATH_MAX); if (!p) { //php3_error(E_WARNING, "posix_getcwd() failed with '%s'", // strerror(errno)); RETURN_FALSE; } MAPSCRIPT_RETURN_STRING(buffer, 1); } PHP_FUNCTION(ms_getPid) { RETURN_LONG(getpid()); } /************************************************************************/ /* DLEXPORT void php3_ms_getscale(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Utility function to get the scale based on the width/height */ /* of the pixmap, the georeference and the units of the data. */ /* */ /* Parameters are : */ /* */ /* - Georefernce extents (rectObj) */ /* - Width : width in pixel */ /* - Height : Height in pixel */ /* - Units of the data (int) */ /* */ /* */ /************************************************************************/ PHP_FUNCTION(ms_getScale) { zval *zgeoRefExt = NULL; long width, height,unit; double resolution; php_rect_object *php_geoRefExt; double dfScale = 0.0; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ollld", &zgeoRefExt, mapscript_ce_rect, &width, &height, &unit, &resolution) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_geoRefExt = MAPSCRIPT_OBJ_P(php_rect_object, zgeoRefExt); if (msCalculateScale(*(php_geoRefExt->rect), unit, width, height, resolution, &dfScale) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_DOUBLE(dfScale); } /********************************************************************** * ms_tokenizeMap() * * Preparse mapfile and return an array containg one item for each * token in the map. **********************************************************************/ /* {{{ proto array ms_tokenizeMap(string filename) Preparse mapfile and return an array containg one item for each token in the map.*/ PHP_FUNCTION(ms_tokenizeMap) { char *filename; long filename_len = 0; char **tokens; int i, numtokens=0; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ((tokens = msTokenizeMap(filename, &numtokens)) == NULL) { mapscript_throw_mapserver_exception("Failed tokenizing map file %s" TSRMLS_CC, filename); return; } else { array_init(return_value); for (i=0; i #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #else #include #endif #include "../../mapserver.h" #include "../../mapregex.h" #endif /* USE_PHP_REGEX */ #include "../../maptemplate.h" #include "../../mapogcsld.h" #include "../../mapows.h" #define MAPSCRIPT_VERSION "($Revision$ $Date$)" #define MAPSCRIPT_VERSION "($Revision$ $Date$)" #if PHP_VERSION_ID >= 70000 #define MAPSCRIPT_ZVAL zval #define MAPSCRIPT_ZVAL_P zval* #define Z_DVAL_PP(zv) Z_DVAL_P(zv) #define Z_LVAL_PP(zv) Z_LVAL_P(zv) #define Z_STRVAL_PP(zv) Z_STRVAL_P(zv) #define MAPSCRIPT_OBJ_P(t, o) (t *)((char *)(Z_OBJ_P(o)) - XtOffsetOf(t, zobj)) #define MAPSCRIPT_OBJ(t, o) (t *)((char *)(Z_OBJ(o)) - XtOffsetOf(t, zobj)) #define MAPSCRIPT_RETURN_STRINGL(a, b, c) RETURN_STRINGL(a, b) #define MAPSCRIPT_RETURN_STRING(a, b) RETURN_STRING(a) #define MAPSCRIPT_RETVAL_STRING(a, b) RETVAL_STRING(a) #define MAPSCRIPT_RETURN_STRINGL(a, b, c) RETURN_STRINGL(a, b) #define MAPSCRIPT_ZVAL_STRING(a, b, c) ZVAL_STRING(a, b) #define mapscript_is_auto_global(s, l) zend_is_auto_global_str(s, l) #define mapscript_array_init(zv) array_init(&zv) #define mapscript_add_next_index_string(a, b, c) add_next_index_string(a, b) #define mapscript_add_assoc_string(zv, b, c, d) add_assoc_string(&zv, b, c) #define mapscript_hash_get_current_key(a, b, c, d) zend_hash_get_current_key(a, b, c) #define mapscript_hash_update(ht, keyname, data) \ zend_hash_str_update(ht, keyname, strlen(keyname)+1, &data); #define MAPSCRIPT_TYPE(zv) Z_TYPE(zv) #define MAPSCRIPT_OBJCE(zv) Z_OBJCE(zv) #define MAKE_STD_ZVAL(zv) ZVAL_UNDEF(&zv) #define ZVAL_NOT_UNDEF(zv) !(Z_ISUNDEF(zv)) #define ZVAL_IS_UNDEF(zv) (Z_ISUNDEF(zv)) #define ZVAL_SET_UNDEF(zv) ZVAL_UNDEF(&zv) #define INIT_ZVAL(zv) #define INIT_PZVAL(a) #else #define MAPSCRIPT_ZVAL zval* #define MAPSCRIPT_ZVAL_P zval** #define MAPSCRIPT_OBJ_P(t, o) (t *) zend_object_store_get_object(o TSRMLS_CC) #define MAPSCRIPT_OBJ(t, o) (t *) zend_object_store_get_object(o TSRMLS_CC) #define MAPSCRIPT_RETURN_STRINGL(a, b, c) RETURN_STRINGL(a, b, c) #define MAPSCRIPT_RETURN_STRING(a, b) RETURN_STRING(a, b) #define MAPSCRIPT_RETVAL_STRING(a, b) RETVAL_STRING(a, b) #define MAPSCRIPT_RETVAL_STRINGL(a, b, c) RETURN_STRINGL(a, b, c) #define MAPSCRIPT_ZVAL_STRING(a, b, c) ZVAL_STRING(a, b, c) #define mapscript_is_auto_global(s, l) zend_is_auto_global(s, l) #define mapscript_array_init(zv) array_init(zv) #define mapscript_add_next_index_string(a, b, c) add_next_index_string(a, b, c) #define mapscript_add_assoc_string(a, b, c, d) add_assoc_string(a, b, c, d) #define mapscript_hash_get_current_key(a, b, c, d) zend_hash_get_current_key(a, b, c, d) #define mapscript_hash_update(ht, key, data) \ zend_hash_update(Z_ARRVAL_P(return_value), key, strlen(key)+1, &data, sizeof(data), NULL) #define MAPSCRIPT_TYPE(zv) Z_TYPE_P(zv) #define MAPSCRIPT_OBJCE(zv) Z_OBJCE_P(zv) #define ZVAL_NOT_UNDEF(zv) (zv != NULL) #define ZVAL_IS_UNDEF(zv) (zv == NULL) #define ZVAL_SET_UNDEF(zv) zv = NULL #endif extern zend_module_entry mapscript_module_entry; #define phpext_mapscript_ptr &mapscript_module_entry #ifndef zend_parse_parameters_none #define zend_parse_parameters_none() \ zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") #endif /* it looks like that macro is not always defined: ticket #3926 */ #ifndef TRUE #define TRUE 1 #endif /* Taken from the CAIRO php extension */ /* turn error handling to exception mode and restore */ #if defined(PHP_VERSION_ID) && PHP_VERSION_ID >= 50300 /* 5.3 version of the macros */ #define PHP_MAPSCRIPT_ERROR_HANDLING(force_exceptions) \ zend_error_handling error_handling; \ if(force_exceptions || getThis()) { \ zend_replace_error_handling(EH_THROW, mapscript_ce_mapscriptexception, &error_handling TSRMLS_CC); \ } #define PHP_MAPSCRIPT_RESTORE_ERRORS(force_exceptions) \ if(force_exceptions || getThis()) { \ zend_restore_error_handling(&error_handling TSRMLS_CC); \ } #else /* 5.2 versions of the macros */ #define PHP_MAPSCRIPT_ERROR_HANDLING(force_exceptions) \ if(force_exceptions || getThis()) { \ php_set_error_handling(EH_THROW, mapscript_ce_mapscriptexception TSRMLS_CC); \ } #define PHP_MAPSCRIPT_RESTORE_ERRORS(force_exceptions) \ if(force_exceptions || getThis()) { \ php_std_error_handling(); \ } #endif /* MapScript objects */ #if PHP_VERSION_ID >= 70000 typedef struct _parent_object { zval val; // the zval of the parent zval *child_ptr; // a ptr to a parent property, which is the zval of the child object. // should be set to NULL when the child is destroyed } parent_object; typedef struct _php_color_object { parent_object parent; colorObj *color; zend_object zobj; } php_color_object; typedef struct _php_rect_object { parent_object parent; int is_ref; rectObj *rect; zend_object zobj; } php_rect_object; typedef struct _php_hashtable_object { parent_object parent; hashTableObj *hashtable; zend_object zobj; } php_hashtable_object; typedef struct _php_symbol_object { parent_object parent; symbolObj *symbol; zend_object zobj; } php_symbol_object; typedef struct _php_class_object { parent_object parent; //old layer zval metadata; zval leader; classObj *class; zend_object zobj; } php_class_object; typedef struct _php_image_object { imageObj *image; zend_object zobj; } php_image_object; typedef struct _php_web_object { parent_object parent; zval extent; zval metadata; zval validation; webObj *web; zend_object zobj; } php_web_object; typedef struct _php_legend_object { parent_object parent; zval outlinecolor; zval label; zval imagecolor; legendObj *legend; zend_object zobj; } php_legend_object; typedef struct _php_outputformat_object { parent_object parent; int is_ref; outputFormatObj *outputformat; zend_object zobj; } php_outputformat_object; typedef struct _php_querymap_object { parent_object parent; zval color; queryMapObj *querymap; zend_object zobj; } php_querymap_object; typedef struct _php_grid_object { parent_object parent; graticuleObj *grid; zend_object zobj; } php_grid_object; typedef struct _php_error_object { errorObj *error; zend_object zobj; } php_error_object; typedef struct _php_referencemap_object { parent_object parent; zval extent; zval color; zval outlinecolor; referenceMapObj *referencemap; zend_object zobj; } php_referencemap_object; typedef struct _php_label_object { parent_object parent; int is_ref; zval color; zval outlinecolor; zval shadowcolor; zval backgroundcolor; zval backgroundshadowcolor; zval leader; labelObj *label; zend_object zobj; } php_label_object; typedef struct _php_style_object { parent_object parent; zval color; zval outlinecolor; zval backgroundcolor; zval mincolor; zval maxcolor; styleObj *style; zend_object zobj; } php_style_object; typedef struct _php_projection_object { parent_object parent; int is_ref; projectionObj *projection; zend_object zobj; } php_projection_object; typedef struct _php_point_object { parent_object parent; int is_ref; pointObj *point; zend_object zobj; } php_point_object; typedef struct _php_line_object { parent_object parent; int is_ref; lineObj *line; zend_object zobj; } php_line_object; typedef struct _php_shape_object { parent_object parent; zval bounds; zval values; int is_ref; shapeObj *shape; zend_object zobj; } php_shape_object; typedef struct _php_shapefile_object { zval bounds; shapefileObj *shapefile; zend_object zobj; } php_shapefile_object; #ifdef disabled typedef struct _php_labelcache_object { parent_object parent; labelCacheObj *labelcache; zend_object zobj; } php_labelcache_object; #endif typedef struct _php_labelleader_object { parent_object parent; labelLeaderObj *labelleader; zend_object zobj; } php_labelleader_object; #ifdef disabled typedef struct _php_labelcachemember_object { parent_object parent; zval labels; /* should be immutable */ zval point; /* should be immutable */ zval styles; /* should be immutable */ zval poly; /* should be immutable */ labelCacheMemberObj *labelcachemember; zend_object zobj; } php_labelcachemember_object; #endif typedef struct _php_result_object { parent_object parent; resultObj *result; zend_object zobj; } php_result_object; typedef struct _php_scalebar_object { parent_object parent; zval color; zval backgroundcolor; zval outlinecolor; zval label; zval imagecolor; scalebarObj *scalebar; zend_object zobj; } php_scalebar_object; typedef struct _php_owsrequest_object { cgiRequestObj *cgirequest; zend_object zobj; } php_owsrequest_object; typedef struct _php_layer_object { parent_object parent; //old map zval offsite; zval grid; zval metadata; zval bindvals; zval projection; zval cluster; zval extent; int is_ref; layerObj *layer; zend_object zobj; } php_layer_object; typedef struct _php_map_object { zval outputformat; zval extent; zval web; zval reference; zval imagecolor; zval scalebar; zval legend; zval querymap; #ifdef disabled zval labelcache; #endif zval projection; zval metadata; zval configoptions; mapObj *map; zend_object zobj; } php_map_object; typedef struct _php_cluster_object { parent_object parent; int is_ref; clusterObj *cluster; zend_object zobj; } php_cluster_object; #else /* PHP5 object structs */ typedef struct _parent_object { zval *val; // the zval of the parent zval **child_ptr; // a ptr to a parent property, which point to the child object. // should be set to NULL when the child is destroyed } parent_object; typedef struct _php_color_object { zend_object std; parent_object parent; colorObj *color; } php_color_object; typedef struct _php_rect_object { zend_object std; parent_object parent; int is_ref; rectObj *rect; } php_rect_object; typedef struct _php_hashtable_object { zend_object std; parent_object parent; hashTableObj *hashtable; } php_hashtable_object; typedef struct _php_symbol_object { zend_object std; parent_object parent; symbolObj *symbol; } php_symbol_object; typedef struct _php_class_object { zend_object std; parent_object parent; //old layer zval *metadata; zval *leader; classObj *class; } php_class_object; typedef struct _php_image_object { zend_object std; imageObj *image; } php_image_object; typedef struct _php_web_object { zend_object std; parent_object parent; zval *extent; zval *metadata; zval *validation; webObj *web; } php_web_object; typedef struct _php_legend_object { zend_object std; parent_object parent; zval *outlinecolor; zval *label; zval *imagecolor; legendObj *legend; } php_legend_object; typedef struct _php_outputformat_object { zend_object std; parent_object parent; int is_ref; outputFormatObj *outputformat; } php_outputformat_object; typedef struct _php_querymap_object { zend_object std; parent_object parent; zval *color; queryMapObj *querymap; } php_querymap_object; typedef struct _php_grid_object { zend_object std; parent_object parent; graticuleObj *grid; } php_grid_object; typedef struct _php_error_object { zend_object std; errorObj *error; } php_error_object; typedef struct _php_referencemap_object { zend_object std; parent_object parent; zval *extent; zval *color; zval *outlinecolor; referenceMapObj *referencemap; } php_referencemap_object; typedef struct _php_label_object { zend_object std; parent_object parent; int is_ref; zval *color; zval *outlinecolor; zval *shadowcolor; zval *backgroundcolor; zval *backgroundshadowcolor; zval *leader; labelObj *label; } php_label_object; typedef struct _php_style_object { zend_object std; parent_object parent; zval *color; zval *outlinecolor; zval *backgroundcolor; zval *mincolor; zval *maxcolor; styleObj *style; } php_style_object; typedef struct _php_projection_object { zend_object std; parent_object parent; int is_ref; projectionObj *projection; } php_projection_object; typedef struct _php_point_object { zend_object std; parent_object parent; int is_ref; pointObj *point; } php_point_object; typedef struct _php_line_object { zend_object std; parent_object parent; int is_ref; lineObj *line; } php_line_object; typedef struct _php_shape_object { zend_object std; parent_object parent; zval *bounds; zval *values; int is_ref; shapeObj *shape; } php_shape_object; typedef struct _php_shapefile_object { zend_object std; zval *bounds; shapefileObj *shapefile; } php_shapefile_object; #ifdef disabled typedef struct _php_labelcache_object { zend_object std; parent_object parent; labelCacheObj *labelcache; } php_labelcache_object; #endif typedef struct _php_labelleader_object { zend_object std; parent_object parent; labelLeaderObj *labelleader; } php_labelleader_object; #ifdef disabled typedef struct _php_labelcachemember_object { zend_object std; parent_object parent; zval *labels; /* should be immutable */ zval *point; /* should be immutable */ zval *styles; /* should be immutable */ zval *poly; /* should be immutable */ labelCacheMemberObj *labelcachemember; } php_labelcachemember_object; #endif typedef struct _php_result_object { zend_object std; parent_object parent; resultObj *result; } php_result_object; typedef struct _php_scalebar_object { zend_object std; parent_object parent; zval *color; zval *backgroundcolor; zval *outlinecolor; zval *label; zval *imagecolor; scalebarObj *scalebar; } php_scalebar_object; typedef struct _php_owsrequest_object { zend_object std; cgiRequestObj *cgirequest; } php_owsrequest_object; typedef struct _php_layer_object { zend_object std; parent_object parent; //old map zval *offsite; zval *grid; zval *metadata; zval *bindvals; zval *projection; zval *cluster; zval *extent; int is_ref; layerObj *layer; } php_layer_object; typedef struct _php_map_object { zend_object std; zval *outputformat; zval *extent; zval *web; zval *reference; zval *imagecolor; zval *scalebar; zval *legend; zval *querymap; #ifdef disabled zval *labelcache; #endif zval *projection; zval *metadata; zval *configoptions; mapObj *map; } php_map_object; typedef struct _php_cluster_object { zend_object std; parent_object parent; int is_ref; clusterObj *cluster; } php_cluster_object; #endif /* Lifecyle functions*/ PHP_MINIT_FUNCTION(mapscript); PHP_MINFO_FUNCTION(mapscript); PHP_MSHUTDOWN_FUNCTION(mapscript); PHP_RINIT_FUNCTION(mapscript); PHP_RSHUTDOWN_FUNCTION(mapscript); PHP_MINIT_FUNCTION(mapscript_error); PHP_MINIT_FUNCTION(color); PHP_MINIT_FUNCTION(label); PHP_MINIT_FUNCTION(style); PHP_MINIT_FUNCTION(symbol); PHP_MINIT_FUNCTION(image); PHP_MINIT_FUNCTION(web); PHP_MINIT_FUNCTION(legend); PHP_MINIT_FUNCTION(outputformat); PHP_MINIT_FUNCTION(querymap); PHP_MINIT_FUNCTION(grid); PHP_MINIT_FUNCTION(error); PHP_MINIT_FUNCTION(referencemap); PHP_MINIT_FUNCTION(class); PHP_MINIT_FUNCTION(projection); #ifdef disabled PHP_MINIT_FUNCTION(labelcachemember); PHP_MINIT_FUNCTION(labelcache); #endif PHP_MINIT_FUNCTION(labelleader); PHP_MINIT_FUNCTION(result); PHP_MINIT_FUNCTION(scalebar); PHP_MINIT_FUNCTION(owsrequest); PHP_MINIT_FUNCTION(point); PHP_MINIT_FUNCTION(rect); PHP_MINIT_FUNCTION(hashtable); PHP_MINIT_FUNCTION(line); PHP_MINIT_FUNCTION(shape); PHP_MINIT_FUNCTION(shapefile); PHP_MINIT_FUNCTION(layer); PHP_MINIT_FUNCTION(map); PHP_MINIT_FUNCTION(cluster); /* mapscript functions */ PHP_FUNCTION(ms_GetVersion); PHP_FUNCTION(ms_GetVersionInt); PHP_FUNCTION(ms_GetErrorObj); PHP_FUNCTION(ms_ResetErrorList); PHP_FUNCTION(ms_getCwd); PHP_FUNCTION(ms_getPid); PHP_FUNCTION(ms_getScale); PHP_FUNCTION(ms_tokenizeMap); PHP_FUNCTION(ms_ioInstallStdoutToBuffer); PHP_FUNCTION(ms_ioInstallStdinFromBuffer); PHP_FUNCTION(ms_ioGetStdoutBufferString); PHP_FUNCTION(ms_ioResetHandlers); PHP_FUNCTION(ms_ioStripStdoutBufferContentType); PHP_FUNCTION(ms_ioStripStdoutBufferContentHeaders); PHP_FUNCTION(ms_ioGetAndStripStdoutBufferMimeHeaders); PHP_FUNCTION(ms_ioGetStdoutBufferBytes); /* object constructors */ PHP_FUNCTION(ms_newLineObj); PHP_FUNCTION(ms_newRectObj); PHP_FUNCTION(ms_newShapeObj); PHP_FUNCTION(ms_shapeObjFromWkt); PHP_FUNCTION(ms_newOWSRequestObj); PHP_FUNCTION(ms_newShapeFileObj); PHP_FUNCTION(ms_newMapObj); PHP_FUNCTION(ms_newMapObjFromString); PHP_FUNCTION(ms_newLayerObj); PHP_FUNCTION(ms_newPointObj); PHP_FUNCTION(ms_newProjectionObj); PHP_FUNCTION(ms_newStyleObj); PHP_FUNCTION(ms_newSymbolObj); PHP_FUNCTION(ms_newClassObj); PHP_FUNCTION(ms_newGridObj); /* mapscript zend class entries */ extern zend_object_handlers mapscript_std_object_handlers; extern zend_class_entry *mapscript_ce_mapscriptexception; extern zend_class_entry *mapscript_ce_color; extern zend_class_entry *mapscript_ce_label; extern zend_class_entry *mapscript_ce_projection; extern zend_class_entry *mapscript_ce_point; extern zend_class_entry *mapscript_ce_rect; extern zend_class_entry *mapscript_ce_hashtable; extern zend_class_entry *mapscript_ce_style; extern zend_class_entry *mapscript_ce_class; extern zend_class_entry *mapscript_ce_symbol; extern zend_class_entry *mapscript_ce_image; extern zend_class_entry *mapscript_ce_web; extern zend_class_entry *mapscript_ce_legend; extern zend_class_entry *mapscript_ce_outputformat; extern zend_class_entry *mapscript_ce_querymap; extern zend_class_entry *mapscript_ce_grid; extern zend_class_entry *mapscript_ce_error; extern zend_class_entry *mapscript_ce_referencemap; extern zend_class_entry *mapscript_ce_line; extern zend_class_entry *mapscript_ce_shape; extern zend_class_entry *mapscript_ce_shapefile; #ifdef disabled extern zend_class_entry *mapscript_ce_labelcachemember; extern zend_class_entry *mapscript_ce_labelcache; #endif extern zend_class_entry *mapscript_ce_labelleader; extern zend_class_entry *mapscript_ce_result; extern zend_class_entry *mapscript_ce_scalebar; extern zend_class_entry *mapscript_ce_owsrequest; extern zend_class_entry *mapscript_ce_layer; extern zend_class_entry *mapscript_ce_map; extern zend_class_entry *mapscript_ce_cluster; #if PHP_VERSION_ID < 70000 /* PHP Object constructors */ extern zend_object_value mapscript_object_new(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object) TSRMLS_DC); extern zend_object_value mapscript_object_new_ex(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object), zend_object_handlers *object_handlers TSRMLS_DC); #endif /* PHP_VERSION_ID < 70000 */ extern void mapscript_fetch_object(zend_class_entry *ce, zval* zval_parent, php_layer_object* layer, void *internal_object, MAPSCRIPT_ZVAL_P php_object_storage TSRMLS_DC); extern void mapscript_create_color(colorObj *color, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_rect(rectObj *rect, parent_object php_parent, zval *return_value TSRMLS_DC); extern void mapscript_create_hashtable(hashTableObj *hashtable, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_label(labelObj *label, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_style(styleObj *style, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_symbol(symbolObj *symbol, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_class(classObj *class, parent_object parent, zval *return_value TSRMLS_DC); #ifdef disabled extern void mapscript_create_labelcachemember(labelCacheMemberObj *labelcachemember, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_labelcache(labelCacheObj *labelcache, parent_object parent, zval *return_value TSRMLS_DC); #endif extern void mapscript_create_labelleader(labelLeaderObj *labelleader, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_result(resultObj *result, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_scalebar(scalebarObj *scalebar, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_owsrequest(cgiRequestObj *cgirequest, zval *return_value TSRMLS_DC); extern void mapscript_create_image(imageObj *image, zval *return_value TSRMLS_DC); extern void mapscript_create_web(webObj *web, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_legend(legendObj *legend, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_outputformat(outputFormatObj *outputformat, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_querymap(queryMapObj *querymap, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_grid(graticuleObj *grid, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_error(errorObj *error, zval *return_value TSRMLS_DC); extern void mapscript_create_referencemap(referenceMapObj *referenceMap, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_point(pointObj *point, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_projection(projectionObj *projection, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_line(lineObj *line, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_shape(shapeObj *shape, parent_object parent, php_layer_object *php_layer, zval *return_value TSRMLS_DC); extern void mapscript_create_shapefile(shapefileObj *shapefile, zval *return_value TSRMLS_DC); extern void mapscript_create_layer(layerObj *layer, parent_object parent, zval *return_value TSRMLS_DC); extern void mapscript_create_map(mapObj *map, zval *return_value TSRMLS_DC); extern void mapscript_create_cluster(clusterObj *cluster, parent_object php_parent, zval *return_value TSRMLS_DC); /* Exported functions for PHP Mapscript API */ /* throw a MapScriptException */ #if PHP_VERSION_ID >= 70000 extern zend_object * mapscript_throw_exception(char *format TSRMLS_DC, ...); #else extern zval * mapscript_throw_exception(char *format TSRMLS_DC, ...); #endif /* print all MapServer errors (as Warning) and throw a MapScriptException */ #if PHP_VERSION_ID >= 70000 extern zend_object* mapscript_throw_mapserver_exception(char *format TSRMLS_DC, ...); #else extern zval* mapscript_throw_mapserver_exception(char *format TSRMLS_DC, ...); #endif extern void mapscript_report_mapserver_error(int error_type TSRMLS_DC); extern void mapscript_report_php_error(int error_type, char *format TSRMLS_DC, ...); /*===================================================================== * Internal functions from mapscript_i.c *====================================================================*/ mapObj *mapObj_new(char *filename, char *new_path); mapObj *mapObj_newFromString(char *map_text, char *new_path); void mapObj_destroy(mapObj* self); mapObj *mapObj_clone(mapObj* self); int mapObj_setRotation(mapObj* self, double rotation_angle ); layerObj *mapObj_getLayer(mapObj* self, int i); layerObj *mapObj_getLayerByName(mapObj* self, char *name); int *mapObj_getLayersIndexByGroup(mapObj* self, char *groupname, int *pnCount); int mapObj_getSymbolByName(mapObj* self, char *name); void mapObj_prepareQuery(mapObj* self); imageObj *mapObj_prepareImage(mapObj* self); imageObj *mapObj_draw(mapObj* self); imageObj *mapObj_drawQuery(mapObj* self); imageObj *mapObj_drawLegend(mapObj* self); imageObj *mapObj_drawScalebar(mapObj* self); imageObj *mapObj_drawReferenceMap(mapObj* self); int mapObj_embedScalebar(mapObj* self, imageObj *img); int mapObj_embedLegend(mapObj* self, imageObj *img); int mapObj_drawLabelCache(mapObj* self, imageObj *img); #ifdef disabled labelCacheMemberObj *mapObj_getLabel(mapObj* self, int i); #endif int mapObj_queryByPoint(mapObj* self, pointObj *point, int mode, double buffer); int mapObj_queryByRect(mapObj* self, rectObj rect); int mapObj_queryByFeatures(mapObj* self, int slayer); int mapObj_queryByShape(mapObj *self, shapeObj *shape); int mapObj_queryByIndex(mapObj *self, int qlayer, int tileindex, int shapeindex, int bAddToQuery); int mapObj_queryByFilter(mapObj* self, char *string); int mapObj_saveQuery(mapObj *self, char *filename, int results); int mapObj_loadQuery(mapObj *self, char *filename); int mapObj_setWKTProjection(mapObj *self, char *string); char* mapObj_getProjection(mapObj* self); int mapObj_setProjection(mapObj* self, char *string); int mapObj_save(mapObj* self, char *filename); char *mapObj_getMetaData(mapObj *self, char *name); int mapObj_setMetaData(mapObj *self, char *name, char *value); int mapObj_removeMetaData(mapObj *self, char *name); void mapObj_freeQuery(mapObj *self, int qlayer); int mapObj_moveLayerup(mapObj *self, int layerindex); int mapObj_moveLayerdown(mapObj *self, int layerindex); int *mapObj_getLayersdrawingOrder(mapObj *self); int mapObj_setLayersdrawingOrder(mapObj *self, int *panIndexes); char *mapObj_processTemplate(mapObj *self, int bGenerateImages, char **names, char **values, int numentries); char *mapObj_processLegendTemplate(mapObj *self, char **names, char **values, int numentries); char *mapObj_processQueryTemplate(mapObj *self, int bGenerateImages, char **names, char **values, int numentries); int mapObj_setSymbolSet(mapObj *self, char *szFileName); int mapObj_getNumSymbols(mapObj *self); int mapObj_setFontSet(mapObj *self, char *szFileName); int mapObj_saveMapContext(mapObj *self, char *szFileName); int mapObj_loadMapContext(mapObj *self, char *szFileName, int bUniqueLayerName); int mapObj_selectOutputFormat(mapObj *self, const char *imagetype); int mapObj_applySLD(mapObj *self, char *sld); int mapObj_applySLDURL(mapObj *self, char *sld); char *mapObj_generateSLD(mapObj *self); int mapObj_loadOWSParameters(mapObj *self, cgiRequestObj *request, char *wmtver_string); int mapObj_OWSDispatch(mapObj *self, cgiRequestObj *req ); int mapObj_insertLayer(mapObj *self, layerObj *layer, int index); layerObj *mapObj_removeLayer(mapObj *self, int layerindex); int mapObj_setCenter(mapObj *self, pointObj *center); int mapObj_offsetExtent(mapObj *self, double x, double y); int mapObj_scaleExtent(mapObj *self, double zoomfactor, double minscaledenom, double maxscaledenom); char *mapObj_convertToString(mapObj *self); layerObj *layerObj_new(mapObj *map); void layerObj_destroy(layerObj* self); int layerObj_updateFromString(layerObj *self, char *snippet); char *layerObj_convertToString(layerObj *self); int layerObj_open(layerObj *self); int layerObj_whichShapes(layerObj *self, rectObj *poRect); shapeObj *layerObj_nextShape(layerObj *self); void layerObj_close(layerObj *self); int layerObj_getShape(layerObj *self, shapeObj *shape, int tileindex, int shapeindex); resultObj *layerObj_getResult(layerObj *self, int i); classObj *layerObj_getClass(layerObj *self, int i); int layerObj_getClassIndex(layerObj *self, mapObj *map, shapeObj *shape, int *classgroup, int numclasses); int layerObj_draw(layerObj *self, mapObj *map, imageObj *img); int layerObj_drawQuery(layerObj *self, mapObj *map, imageObj *img); int layerObj_queryByAttributes(layerObj *self, mapObj *map, char *qitem, char *qstring, int mode); int layerObj_queryByPoint(layerObj *self, mapObj *map, pointObj *point, int mode, double buffer); int layerObj_queryByRect(layerObj *self, mapObj *map,rectObj rect); int layerObj_queryByFeatures(layerObj *self, mapObj *map, int slayer); int layerObj_queryByShape(layerObj *self, mapObj *map, shapeObj *shape); int layerObj_queryByFilter(layerObj *self, mapObj *map, char *string); int layerObj_queryByIndex(layerObj *self, mapObj *map, int tileindex, int shapeindex, int addtoquery); int layerObj_setFilter(layerObj *self, char *string); char* layerObj_getFilter(layerObj *self); int layerObj_setWKTProjection(layerObj *self, char *string); char* layerObj_getProjection(layerObj *self); int layerObj_setProjection(layerObj *self, char *string); int layerObj_addFeature(layerObj *self, shapeObj *shape); char *layerObj_getMetaData(layerObj *self, char *name); int layerObj_setMetaData(layerObj *self, char *name, char *value); int layerObj_removeMetaData(layerObj *self, char *name); char *layerObj_getWMSFeatureInfoURL(layerObj *self, mapObj *map, int click_x, int click_y, int feature_count, char *info_format); char *layerObj_executeWFSGetFeature(layerObj *self); int layerObj_applySLD(layerObj *self, char *sld, char *stylelayer); int layerObj_applySLDURL(layerObj *self, char *sld, char *stylelayer); char *layerObj_generateSLD(layerObj *self); int layerObj_moveClassUp(layerObj *self, int index); int layerObj_moveClassDown(layerObj *self, int index); classObj *layerObj_removeClass(layerObj *self, int index); int layerObj_setConnectionType(layerObj *self, int connectiontype, const char *library_str) ; layerObj *layerObj_clone(layerObj *layer); labelObj *labelObj_new(); int labelObj_updateFromString(labelObj *self, char *snippet); char *labelObj_convertToString(labelObj *self); void labelObj_destroy(labelObj *self); int labelObj_moveStyleUp(labelObj *self, int index); int labelObj_moveStyleDown(labelObj *self, int index); int labelObj_deleteStyle(labelObj *self, int index); labelObj *labelObj_clone(labelObj *label); int labelObj_setExpression(labelObj *self, char *string); char *labelObj_getExpressionString(labelObj *self); int labelObj_setText(labelObj *self,layerObj *layer,char *string); char *labelObj_getTextString(labelObj *self); int legendObj_updateFromString(legendObj *self, char *snippet); char *legendObj_convertToString(legendObj *self); int queryMapObj_updateFromString(queryMapObj *self, char *snippet); char *queryMapObj_convertToString(queryMapObj *self); int referenceMapObj_updateFromString(referenceMapObj *self, char *snippet); char *referenceMapObj_convertToString(referenceMapObj *self); int scalebarObj_updateFromString(scalebarObj *self, char *snippet); char *scalebarObj_convertToString(scalebarObj *self); int webObj_updateFromString(webObj *self, char *snippet); char *webObj_convertToString(webObj *self); classObj *classObj_new(layerObj *layer, classObj *class); labelObj *classObj_getLabel(classObj *self, int i); int classObj_addLabel(classObj *self, labelObj *label); labelObj *classObj_removeLabel(classObj *self, int index); int classObj_updateFromString(classObj *self, char *snippet); char *classObj_convertToString(classObj *self); void classObj_destroy(classObj* self); int classObj_setExpression(classObj *self, char *string); char *classObj_getExpressionString(classObj *self); int classObj_setText(classObj *self,layerObj *layer,char *string); char *classObj_getTextString(classObj *self); int classObj_drawLegendIcon(classObj *self, mapObj *map, layerObj *layer, int width, int height, imageObj *im, int dstX, int dstY); imageObj *classObj_createLegendIcon(classObj *self, mapObj *map, layerObj *layer, int width, int height); int classObj_setSymbolByName(classObj *self, mapObj *map, char *pszSymbolName); int classObj_setOverlaySymbolByName(classObj *self, mapObj *map, char *pszOverlaySymbolName); classObj *classObj_clone(classObj *class, layerObj *layer); int classObj_moveStyleUp(classObj *self, int index); int classObj_moveStyleDown(classObj *self, int index); int classObj_deleteStyle(classObj *self, int index); char *classObj_getMetaData(classObj *self, char *name); int classObj_setMetaData(classObj *self, char *name, char *value); int classObj_removeMetaData(classObj *self, char *name); pointObj *pointObj_new(); void pointObj_destroy(pointObj *self); int pointObj_project(pointObj *self, projectionObj *in, projectionObj *out); int pointObj_draw(pointObj *self, mapObj *map, layerObj *layer, imageObj *img, int class_index, char *label_string); double pointObj_distanceToPoint(pointObj *self, pointObj *point); double pointObj_distanceToLine(pointObj *self, pointObj *a, pointObj *b); double pointObj_distanceToShape(pointObj *self, shapeObj *shape); lineObj *lineObj_new(); void lineObj_destroy(lineObj *self); lineObj *lineObj_clone(lineObj *line); int lineObj_project(lineObj *self, projectionObj *in, projectionObj *out); pointObj *lineObj_get(lineObj *self, int i); int lineObj_add(lineObj *self, pointObj *p); shapeObj *shapeObj_new(int type); void shapeObj_destroy(shapeObj *self); int shapeObj_project(shapeObj *self, projectionObj *in, projectionObj *out); lineObj *shapeObj_get(shapeObj *self, int i); int shapeObj_add(shapeObj *self, lineObj *line); int shapeObj_draw(shapeObj *self, mapObj *map, layerObj *layer, imageObj *img); void shapeObj_setBounds(shapeObj *self); int shapeObj_copy(shapeObj *self, shapeObj *dest); int shapeObj_contains(shapeObj *self, pointObj *point); int shapeObj_intersects(shapeObj *self, shapeObj *shape); pointObj *shapeObj_getpointusingmeasure(shapeObj *self, double m); pointObj *shapeObj_getmeasureusingpoint(shapeObj *self, pointObj *point); shapeObj *shapeObj_buffer(shapeObj *self, double width); shapeObj *shapeObj_simplify(shapeObj *self, double tolerance); shapeObj *shapeObj_topologypreservingsimplify(shapeObj *self, double tolerance); shapeObj *shapeObj_convexHull(shapeObj *self); shapeObj *shapeObj_boundary(shapeObj *self); int shapeObj_contains_geos(shapeObj *self, shapeObj *poshape); shapeObj *shapeObj_Union(shapeObj *self, shapeObj *poshape); shapeObj *shapeObj_intersection(shapeObj *self, shapeObj *poshape); shapeObj *shapeObj_difference(shapeObj *self, shapeObj *poshape); shapeObj *shapeObj_symdifference(shapeObj *self, shapeObj *poshape); int shapeObj_overlaps(shapeObj *self, shapeObj *shape); int shapeObj_within(shapeObj *self, shapeObj *shape); int shapeObj_crosses(shapeObj *self, shapeObj *shape); int shapeObj_touches(shapeObj *self, shapeObj *shape); int shapeObj_equals(shapeObj *self, shapeObj *shape); int shapeObj_disjoint(shapeObj *self, shapeObj *shape); pointObj *shapeObj_getcentroid(shapeObj *self); double shapeObj_getarea(shapeObj *self); double shapeObj_getlength(shapeObj *self); pointObj *shapeObj_getLabelPoint(shapeObj *self); rectObj *rectObj_new(); void rectObj_destroy(rectObj *self); int rectObj_project(rectObj *self, projectionObj *in, projectionObj *out); double rectObj_fit(rectObj *self, int width, int height); int rectObj_draw(rectObj *self, mapObj *map, layerObj *layer, imageObj *img, int classindex, char *text); shapefileObj *shapefileObj_new(char *filename, int type); void shapefileObj_destroy(shapefileObj *self); int shapefileObj_get(shapefileObj *self, int i, shapeObj *shape); int shapefileObj_getPoint(shapefileObj *self, int i, pointObj *point); int shapefileObj_getTransformed(shapefileObj *self, mapObj *map, int i, shapeObj *shape); void shapefileObj_getExtent(shapefileObj *self, int i, rectObj *rect); int shapefileObj_add(shapefileObj *self, shapeObj *shape); int shapefileObj_addPoint(shapefileObj *self, pointObj *point); projectionObj *projectionObj_new(char *string); projectionObj *projectionObj_clone(projectionObj *projection); int projectionObj_getUnits(projectionObj *self); void projectionObj_destroy(projectionObj *self); #ifdef disabled void labelCacheObj_freeCache(labelCacheObj *self); #endif char *DBFInfo_getFieldName(DBFInfo *self, int iField); int DBFInfo_getFieldWidth(DBFInfo *self, int iField); int DBFInfo_getFieldDecimals(DBFInfo *self, int iField); DBFFieldType DBFInfo_getFieldType(DBFInfo *self, int iField); styleObj *styleObj_new(classObj *class, styleObj *style); styleObj *styleObj_label_new(labelObj *label, styleObj *style); int styleObj_updateFromString(styleObj *self, char *snippet); char *styleObj_convertToString(styleObj *self); int styleObj_setSymbolByName(styleObj *self, mapObj *map, char* pszSymbolName); styleObj *styleObj_clone(styleObj *style); void styleObj_setGeomTransform(styleObj *style, char *transform); hashTableObj *hashTableObj_new(); int hashTableObj_set(hashTableObj *self, const char *key, const char *value); const char *hashTableObj_get(hashTableObj *self, const char *key); int hashTableObj_remove(hashTableObj *self, const char *key); void hashTableObj_clear(hashTableObj *self); char *hashTableObj_nextKey(hashTableObj *self, const char *prevkey); cgiRequestObj *cgirequestObj_new(); int cgirequestObj_loadParams(cgiRequestObj *self, char* (*getenv2)(const char*, void* thread_context), char *raw_post_data, ms_uint32 raw_post_data_length, void* thread_context); void cgirequestObj_setParameter(cgiRequestObj *self, char *name, char *value); void cgirequestObj_addParameter(cgiRequestObj *self, char *name, char *value); char *cgirequestObj_getName(cgiRequestObj *self, int index); char *cgirequestObj_getValue(cgiRequestObj *self, int index); char *cgirequestObj_getValueByName(cgiRequestObj *self, const char *name); void cgirequestObj_destroy(cgiRequestObj *self); resultObj *resultObj_new(); int clusterObj_updateFromString(clusterObj *self, char *snippet); char *clusterObj_convertToString(clusterObj *self); int clusterObj_setGroup(clusterObj *self, char *string); char *clusterObj_getGroupString(clusterObj *self); int clusterObj_setFilter(clusterObj *self, char *string); char *clusterObj_getFilterString(clusterObj *self); outputFormatObj *outputFormatObj_new(const char *driver, char *name); void outputFormatObj_destroy(outputFormatObj* self); int symbolObj_setImage(symbolObj *self, imageObj *image); imageObj *symbolObj_getImage(symbolObj *self, outputFormatObj *input_format); #endif /* PHP_MAPSCRIPT_H */ mapserver-7.4.3/mapscript/php/php_mapscript_util.c000066400000000000000000000204361357574274700224260ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer : Utility functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000-2005, DM Solutions Group * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript_util.h" #include "../../maperror.h" #if PHP_VERSION_ID < 70000 zend_object_value mapscript_object_new(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object) TSRMLS_DC) { zend_object_value retval; #if PHP_VERSION_ID < 50399 zval *temp; #endif zobj->ce = ce; ALLOC_HASHTABLE(zobj->properties); zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0); //handle changes in PHP 5.4.x #if PHP_VERSION_ID < 50399 zend_hash_copy(zobj->properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &temp, sizeof(zval *)); #else object_properties_init(zobj, ce); #endif retval.handle = zend_objects_store_put(zobj, NULL, (zend_objects_free_object_storage_t)zend_objects_free_object, NULL TSRMLS_CC); retval.handlers = &mapscript_std_object_handlers; return retval; } zend_object_value mapscript_object_new_ex(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object), zend_object_handlers *object_handlers TSRMLS_DC) { zend_object_value retval; #if PHP_VERSION_ID < 50399 zval *temp; #endif zobj->ce = ce; ALLOC_HASHTABLE(zobj->properties); zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0); //handle changes in PHP 5.4.x #if PHP_VERSION_ID < 50399 zend_hash_copy(zobj->properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &temp, sizeof(zval *)); #else object_properties_init(zobj, ce); #endif retval.handle = zend_objects_store_put(zobj, NULL, (zend_objects_free_object_storage_t)zend_objects_free_object, NULL TSRMLS_CC); retval.handlers = object_handlers; return retval; } #endif /* PHP_VERSION_ID < 70000 */ int mapscript_extract_associative_array(HashTable *php, char **array) { MAPSCRIPT_ZVAL_P value; #if PHP_VERSION_ID < 70000 char *string_key = NULL; ulong num_key; #else zend_string *string_key = NULL; zend_ulong num_key; #endif int i = 0; for(zend_hash_internal_pointer_reset(php); zend_hash_has_more_elements(php) == SUCCESS; zend_hash_move_forward(php)) { #if PHP_VERSION_ID < 70000 zend_hash_get_current_data(php, (void **)&value); #else value = zend_hash_get_current_data(php); #endif switch (mapscript_hash_get_current_key(php, &string_key, &num_key, 1)) { case HASH_KEY_IS_STRING: #if PHP_VERSION_ID < 70000 array[i++] = string_key; #else array[i++] = ZSTR_VAL(string_key); #endif array[i++] = Z_STRVAL_PP(value); break; } } array[i++] = NULL; return 1; } /* This method returns an object property of a php class. If the object exists, it returns a reference to it, otherwise it creates it */ void mapscript_fetch_object(zend_class_entry *ce, zval* zval_parent, php_layer_object* layer, void *internal_object, MAPSCRIPT_ZVAL_P php_object_storage TSRMLS_DC) { parent_object p; // create the parent struct #if PHP_VERSION_ID < 70000 p.val = zval_parent; #define mapscript_fetch_object_return_value *php_object_storage #else p.val = *zval_parent; #define mapscript_fetch_object_return_value php_object_storage #endif p.child_ptr = &*php_object_storage; MAKE_STD_ZVAL(*php_object_storage); if (ce == mapscript_ce_outputformat) mapscript_create_outputformat((outputFormatObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_color) mapscript_create_color((colorObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_rect) mapscript_create_rect((rectObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_class) mapscript_create_class((classObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_hashtable) mapscript_create_hashtable((hashTableObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_label) mapscript_create_label((labelObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_style) mapscript_create_style((styleObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_symbol) mapscript_create_symbol((symbolObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); #ifdef disabled else if (ce == mapscript_ce_labelcachemember) mapscript_create_labelcachemember((labelCacheMemberObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_labelcache) mapscript_create_labelcache((labelCacheObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); #endif else if (ce == mapscript_ce_result) mapscript_create_result((resultObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_scalebar) mapscript_create_scalebar((scalebarObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_web) mapscript_create_web((webObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_legend) mapscript_create_legend((legendObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_querymap) mapscript_create_querymap((queryMapObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_grid) mapscript_create_grid((graticuleObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_referencemap) mapscript_create_referencemap((referenceMapObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_point) mapscript_create_point((pointObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_projection) mapscript_create_projection((projectionObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_line) mapscript_create_line((lineObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_shape) mapscript_create_shape((shapeObj*)internal_object, p, layer, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_layer) mapscript_create_layer((layerObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_cluster) mapscript_create_cluster((clusterObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); else if (ce == mapscript_ce_labelleader) mapscript_create_labelleader((labelLeaderObj*)internal_object, p, mapscript_fetch_object_return_value TSRMLS_CC); } mapserver-7.4.3/mapscript/php/php_mapscript_util.h000066400000000000000000000311621357574274700224310ustar00rootroot00000000000000/********************************************************************** * $Id$ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer : Utility functions * Header - macros * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * ********************************************************************** * Copyright (c) 2000, 2001, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #ifndef PHP_MAPSCRIPT_UTIL_H #define PHP_MAPSCRIPT_UTIL_H #include "php.h" #include "php_globals.h" #include "php_mapscript.h" #if PHP_VERSION_ID < 70000 #if ZEND_MODULE_API_NO < 20010901 #define TSRMLS_D void #define TSRMLS_DC #define TSRMLS_C #define TSRMLS_CC #endif /* Add pseudo refcount macros for PHP version < 5.3 */ #ifndef Z_REFCOUNT_PP #define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz)) #define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc) #define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz)) #define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz)) #define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz)) #define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz)) #define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz)) #define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref) #define Z_REFCOUNT_P(pz) zval_refcount_p(pz) #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc) #define Z_ADDREF_P(pz) zval_addref_p(pz) #define Z_DELREF_P(pz) zval_delref_p(pz) #define Z_ISREF_P(pz) zval_isref_p(pz) #define Z_SET_ISREF_P(pz) zval_set_isref_p(pz) #define Z_UNSET_ISREF_P(pz) zval_unset_isref_p(pz) #define Z_SET_ISREF_TO_P(pz, isref) zval_set_isref_to_p(pz, isref) #define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z)) #define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc) #define Z_ADDREF(z) Z_ADDREF_P(&(z)) #define Z_DELREF(z) Z_DELREF_P(&(z)) #define Z_ISREF(z) Z_ISREF_P(&(z)) #define Z_SET_ISREF(z) Z_SET_ISREF_P(&(z)) #define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z)) #define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref) #if defined(__GNUC__) #define zend_always_inline inline __attribute__((always_inline)) #elif defined(_MSC_VER) #define zend_always_inline __forceinline #else #define zend_always_inline inline #endif static zend_always_inline zend_uint zval_refcount_p(zval* pz) { return pz->refcount; } static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc) { return pz->refcount = rc; } static zend_always_inline zend_uint zval_addref_p(zval* pz) { return ++pz->refcount; } static zend_always_inline zend_uint zval_delref_p(zval* pz) { return --pz->refcount; } static zend_always_inline zend_bool zval_isref_p(zval* pz) { return pz->is_ref; } static zend_always_inline zend_bool zval_set_isref_p(zval* pz) { return pz->is_ref = 1; } static zend_always_inline zend_bool zval_unset_isref_p(zval* pz) { return pz->is_ref = 0; } static zend_always_inline zend_bool zval_set_isref_to_p(zval* pz, zend_bool isref) { return pz->is_ref = isref; } #endif /* PHP >=5.3 replaced ZVAL_DELREF by Z_DELREF_P */ #if ZEND_MODULE_API_NO >= 20090626 #define ZVAL_DELREF Z_DELREF_P #define ZVAL_ADDREF Z_ADDREF_P #endif #define MAPSCRIPT_REGISTER_CLASS(name, functions, class_entry, constructor) \ INIT_CLASS_ENTRY(ce, name, functions); \ class_entry = zend_register_internal_class(&ce TSRMLS_CC); \ class_entry->create_object = constructor; #define MAPSCRIPT_ALLOC_OBJECT(zobj, object_type) \ zobj = ecalloc(1, sizeof(object_type)); #define MAPSCRIPT_FREE_OBJECT(zobj) \ zend_hash_destroy(zobj->std.properties); \ FREE_HASHTABLE(zobj->std.properties); #endif /* PHP_VERSION_ID < 70000 */ #if PHP_VERSION_ID >= 70300 #define MAPSCRIPT_ADDREF(zv) if(!Z_ISUNDEF(zv)) GC_ADDREF(Z_COUNTED(zv)) #define MAPSCRIPT_ADDREF_P(p) if(!Z_ISUNDEF(*p)) GC_ADDREF(Z_COUNTED_P(p)) #else #if PHP_VERSION_ID >= 70000 #define MAPSCRIPT_ADDREF(zv) if(!(Z_ISUNDEF(zv))) GC_REFCOUNT(Z_COUNTED(zv))++; #define MAPSCRIPT_ADDREF_P(zv) if(!(Z_ISUNDEF(*zv))) GC_REFCOUNT(Z_COUNTED_P(zv))++; #else #define MAPSCRIPT_ADDREF(zobj) if (zobj) Z_ADDREF_P(zobj) #define MAPSCRIPT_ADDREF_P(zv) MAPSCRIPT_ADDREF(zv) #endif /* PHP_VERSION_ID >= 70000 */ #endif /* PHP_VERSION_ID >= 70300 */ #if PHP_VERSION_ID >= 70300 #define MAPSCRIPT_DELREF(zv) \ if (!(Z_ISUNDEF(zv))) \ { \ zend_refcounted *_gc = Z_COUNTED(zv); \ GC_DELREF(_gc); \ if(GC_REFCOUNT(_gc) == 0) \ rc_dtor_func(_gc); \ ZVAL_UNDEF(&zv); \ } #else #if PHP_VERSION_ID >= 70000 #if PHP_VERSION_ID >= 70100 #define _zval_dtor_func_for_ptr _zval_dtor_func #endif /* PHP_VERSION_ID >= 70100 */ #define MAPSCRIPT_DELREF(zv) \ if (!(Z_ISUNDEF(zv))) \ { \ zend_refcounted *_gc = Z_COUNTED_P(&zv); \ if(--GC_REFCOUNT(_gc) == 0) \ _zval_dtor_func_for_ptr(_gc); \ ZVAL_UNDEF(&zv); \ } #else #define MAPSCRIPT_DELREF(zobj) \ if (zobj) \ { \ if (Z_REFCOUNT_P(zobj) == 1) { \ zval_ptr_dtor(&zobj); \ } \ else { \ Z_DELREF_P(zobj); \ } \ zobj = NULL; \ } #endif /* PHP_VERSION_ID >= 70000 */ #endif /* PHP_VERSION_ID >= 70300 */ #if PHP_VERSION_ID >= 70000 #define MAPSCRIPT_FREE_PARENT(parent) \ if (parent.child_ptr) \ ZVAL_UNDEF(parent.child_ptr); \ MAPSCRIPT_DELREF(parent.val); #define MAPSCRIPT_MAKE_PARENT(zobj, ptr) \ if(zobj == NULL) \ ZVAL_UNDEF(&parent.val); \ else \ ZVAL_COPY_VALUE(&parent.val, zobj); \ parent.child_ptr = ptr; #define MAPSCRIPT_INIT_PARENT(parent) \ ZVAL_UNDEF(&parent.val); \ parent.child_ptr = NULL; #else #define MAPSCRIPT_FREE_PARENT(parent) \ if (parent.child_ptr) \ *parent.child_ptr = NULL; \ MAPSCRIPT_DELREF(parent.val); #define MAPSCRIPT_MAKE_PARENT(zobj, ptr) \ parent.val = zobj; \ parent.child_ptr = ptr; #define MAPSCRIPT_INIT_PARENT(parent) \ parent.val = NULL; \ parent.child_ptr = NULL; #endif #if PHP_VERSION_ID >= 70000 #define MAPSCRIPT_CALL_METHOD_1(zobj, function_name, retval, arg1) \ zend_call_method_with_1_params(&zobj, Z_OBJCE(zobj), NULL, function_name, &retval, arg1); #define MAPSCRIPT_CALL_METHOD_2(zobj, function_name, retval, arg1, arg2) \ zend_call_method_with_2_params(&zobj, Z_OBJCE(zobj), NULL, function_name, &retval, arg1, arg2); #define MAPSCRIPT_CALL_METHOD_2_P(zobj, function_name, retval, arg1, arg2) \ zend_call_method_with_2_params(zobj, Z_OBJCE_P(zobj), NULL, function_name, &retval, arg1, arg2); #else #define MAPSCRIPT_CALL_METHOD_1(zobj, function_name, retval, arg1) \ zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), NULL, function_name, &retval, arg1); #define MAPSCRIPT_CALL_METHOD_2(zobj, function_name, retval, arg1, arg2) \ zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj), NULL, function_name, &retval, arg1, arg2); #define MAPSCRIPT_CALL_METHOD_2_P(zobj, function_name, retval, arg1, arg2) \ MAPSCRIPT_CALL_METHOD_2(zobj, function_name, retval, arg1, arg2) #endif /* PHP_VERSION_ID */ #define STRING_EQUAL(string1, string2) \ strcmp(string1, string2) == 0 /* helpers for getters */ #define IF_GET_STRING(property_name, value) \ if (strcmp(property, property_name)==0) \ { \ MAPSCRIPT_RETVAL_STRING( (value ? value:"") , 1); \ } \ #define IF_GET_LONG(property_name, value) \ if (strcmp(property, property_name)==0) \ { \ RETVAL_LONG(value); \ } \ #define IF_GET_DOUBLE(property_name, value) \ if (strcmp(property, property_name)==0) \ { \ RETVAL_DOUBLE(value); \ } \ #if PHP_VERSION_ID >= 70000 #define IF_GET_OBJECT(property_name, mapscript_ce, php_object_storage, internal_object) \ if (strcmp(property, property_name)==0) \ { \ if (Z_ISUNDEF(php_object_storage)) { \ mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \ &php_object_storage TSRMLS_CC); \ } \ RETURN_ZVAL(&php_object_storage, 1, 0); \ } #else #define IF_GET_OBJECT(property_name, mapscript_ce, php_object_storage, internal_object) \ if (strcmp(property, property_name)==0) \ { \ if (!php_object_storage) { \ mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \ &php_object_storage TSRMLS_CC); \ } \ RETURN_ZVAL(php_object_storage, 1, 0); \ } #endif #if PHP_VERSION_ID >= 70000 #define CHECK_OBJECT(mapscript_ce, php_object_storage, internal_object) \ if (Z_ISUNDEF(php_object_storage)) { \ mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \ &php_object_storage TSRMLS_CC); \ } #else #define CHECK_OBJECT(mapscript_ce, php_object_storage, internal_object) \ if (!php_object_storage) { \ mapscript_fetch_object(mapscript_ce, zobj, NULL, (void*)internal_object, \ &php_object_storage TSRMLS_CC); \ } #endif /* helpers for setters */ #define IF_SET_STRING(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_string(value); \ if (internal) free(internal); \ if (Z_STRVAL_P(value)) \ internal = msStrdup(Z_STRVAL_P(value)); \ } #define IF_SET_LONG(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_long(value); \ internal = Z_LVAL_P(value); \ } #define IF_SET_DOUBLE(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_double(value); \ internal = Z_DVAL_P(value); \ } #define IF_SET_BYTE(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_long(value); \ internal = (unsigned char)Z_LVAL_P(value); \ } #define IF_SET_COLOR(property_name, internal, value) \ if (strcmp(property, property_name)==0) \ { \ convert_to_long(value); \ /* validate the color value */ \ if (Z_LVAL_P(value) < 0 || Z_LVAL_P(value) > 255) { \ mapscript_throw_exception("Invalid color value. It must be between 0 and 255." TSRMLS_CC); \ return; \ } \ internal = Z_LVAL_P(value); \ } #if PHP_VERSION_ID < 70000 zend_object_value mapscript_object_new(zend_object *zobj, zend_class_entry *ce, void (*zend_objects_free_object) TSRMLS_DC); #endif /* PHP_VERSION_ID < 70000 */ int mapscript_extract_associative_array(HashTable *php, char **array); #endif /* PHP_MAPSCRIPT_UTIL_H */ mapserver-7.4.3/mapscript/php/php_regex.c000066400000000000000000000062231357574274700204770ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Regex wrapper * Author: Bill Binko * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** * * $Log$ * Revision 1.2 2005/05/27 15:00:12 dan * New regex wrappers to solve issues with previous version (bug 1354) * */ /* we can't include mapserver.h, so we need our own basics */ #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #else #include #endif /*Need to specify this so that mapregex.h doesn't defined constants and doesn't #define away our ms_*/ #define BUILDING_REGEX_PROXY 1 #include "../../mapregex.h" /* regex_extra.h doesn't exist in PHP >=5.3 */ #include "php.h" #if ZEND_MODULE_API_NO < 20090626 #include "regex/regex_extra.h" #include "regex/regex.h" #else #include "php_regex.h" #endif MS_API_EXPORT(int) ms_regcomp(ms_regex_t *regex, const char *expr, int cflags) { /* Must free in regfree() */ regex_t* sys_regex = (regex_t*) malloc(sizeof(regex_t)); regex->sys_regex = (void*) sys_regex; return regcomp(sys_regex, expr, cflags); } MS_API_EXPORT(size_t) ms_regerror(int errcode, const ms_regex_t *regex, char *errbuf, size_t errbuf_size) { return regerror(errcode, (regex_t*)(regex->sys_regex), errbuf, errbuf_size); } MS_API_EXPORT(int) ms_regexec(const ms_regex_t *regex, const char *string, size_t nmatch, ms_regmatch_t pmatch[], int eflags) { /*This next line only works because we know that regmatch_t and ms_regmatch_t are exactly alike (POSIX STANDARD)*/ return regexec((const regex_t*)(regex->sys_regex), string, nmatch, (regmatch_t*) pmatch, eflags); } MS_API_EXPORT(void) ms_regfree(ms_regex_t *regex) { regfree((regex_t*)(regex->sys_regex)); free(regex->sys_regex); return; } mapserver-7.4.3/mapscript/php/point.c000066400000000000000000000406641357574274700176560ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_point; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_point_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(point___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_setXY_args, 0, 0, 2) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_ARG_INFO(0, m) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_setXYZ_args, 0, 0, 3) ZEND_ARG_INFO(0, x) ZEND_ARG_INFO(0, y) ZEND_ARG_INFO(0, z) ZEND_ARG_INFO(0, m) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_project_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, projIn, projectionObj, 0) ZEND_ARG_OBJ_INFO(0, projOut, projectionObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_distanceToPoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_distanceToLine_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_ARG_OBJ_INFO(0, point2, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_distanceToShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(point_draw_args, 0, 0, 5) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_ARG_INFO(0, classIndex) ZEND_ARG_INFO(0, text) ZEND_END_ARG_INFO() /* {{{ proto point __construct() Create a new pointObj instance. */ PHP_METHOD(pointObj, __construct) { php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, getThis()); if ((php_point->point = pointObj_new()) == NULL) { mapscript_throw_exception("Unable to construct pointObj." TSRMLS_CC); return; } php_point->point->x = 0; php_point->point->y = 0; #ifdef USE_POINT_Z_M php_point->point->z = 0; php_point->point->m = 0; #endif } /* }}} */ PHP_METHOD(pointObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); IF_GET_DOUBLE("x", php_point->point->x) else IF_GET_DOUBLE("y", php_point->point->y) #ifdef USE_POINT_Z_M else IF_GET_DOUBLE("z", php_point->point->z) else IF_GET_DOUBLE("m", php_point->point->m) #endif else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(pointObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); IF_SET_DOUBLE("x", php_point->point->x, value) else IF_SET_DOUBLE("y", php_point->point->y, value) #ifdef USE_POINT_Z_M else IF_SET_DOUBLE("z", php_point->point->z, value) else IF_SET_DOUBLE("m", php_point->point->m, value) #endif else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int point.setXY(double x, double y, double m) 3rd argument m is used for Measured shape files. It is not mandatory. Set new point. Returns MS_FAILURE on error. */ PHP_METHOD(pointObj, setXY) { double x, y, m; zval *zobj = getThis(); php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd|d", &x, &y, &m) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); php_point->point->x = x; php_point->point->y = y; #ifdef USE_POINT_Z_M if (ZEND_NUM_ARGS() == 3) { php_point->point->m = m; } #endif RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int point.setXYZ(double x, double y, double z, double m) 4th argument m is used for Measured shape files. It is not mandatory. Set new point. Returns MS_FAILURE on error. */ PHP_METHOD(pointObj, setXYZ) { double x, y, z, m; zval *zobj = getThis(); php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddd|d", &x, &y, &z, &m) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); php_point->point->x = x; php_point->point->y = y; #ifdef USE_POINT_Z_M php_point->point->z = z; if (ZEND_NUM_ARGS() == 4) { php_point->point->m = m; } #endif RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int point.project(projectionObj in, projectionObj out) Project the point. returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(pointObj, project) { zval *zobj_proj_in, *zobj_proj_out; zval *zobj = getThis(); php_point_object *php_point; php_projection_object *php_proj_in, *php_proj_out; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_proj_in, mapscript_ce_projection, &zobj_proj_out, mapscript_ce_projection) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); php_proj_in = MAPSCRIPT_OBJ_P(php_projection_object, zobj_proj_in); php_proj_out = MAPSCRIPT_OBJ_P(php_projection_object, zobj_proj_out); status = pointObj_project(php_point->point, php_proj_in->projection, php_proj_out->projection); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int point.distanceToPoint(pointObj) Calculates distance between two points. */ PHP_METHOD(pointObj, distanceToPoint) { zval *zobj_point2; zval *zobj = getThis(); php_point_object *php_point, *php_point2; double distance = -1; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobj_point2, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); php_point2 = MAPSCRIPT_OBJ_P(php_point_object, zobj_point2); distance = pointObj_distanceToPoint(php_point->point, php_point2->point); RETURN_DOUBLE(distance); } /* }}} */ /* {{{ proto int point.distanceToLine(pointObj line_point, pointObj line_point2) Calculates distance between a point and a lined defined by the two points passed in argument. */ PHP_METHOD(pointObj, distanceToLine) { zval *zobj = getThis(); zval *zobj_line_point, *zobj_line_point2; php_point_object *php_point, *php_line_point, *php_line_point2; double distance = -1; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_line_point, mapscript_ce_point, &zobj_line_point2, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); php_line_point = MAPSCRIPT_OBJ_P(php_point_object, zobj_line_point); php_line_point2 = MAPSCRIPT_OBJ_P(php_point_object, zobj_line_point2); distance = pointObj_distanceToLine(php_point->point, php_line_point->point, php_line_point2->point); RETURN_DOUBLE(distance); } /* }}} */ /* {{{ proto int distanceToShape(shapeObj shape) Calculates the minimum distance between a point and a shape. */ PHP_METHOD(pointObj, distanceToShape) { zval *zobj = getThis(); zval *zshape; php_point_object *php_point; php_shape_object *php_shape; double distance = -1; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zshape); distance = pointObj_distanceToShape(php_point->point, php_shape->shape); RETURN_DOUBLE(distance); } /* }}} */ /* {{{ proto int point.draw(mapObj map, layerObj layer, imageObj img, string class_name, string text) Draws the individual point using layer. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(pointObj, draw) { zval *zobj = getThis(); zval *zmap, *zlayer, *zimage; char *text = NULL; long text_len = 0; long classIndex; int status = MS_FAILURE; php_point_object *php_point; php_map_object *php_map; php_layer_object *php_layer; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOOl|s", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer, &zimage, mapscript_ce_image, &classIndex, &text, &text_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_point = MAPSCRIPT_OBJ_P(php_point_object, zobj); php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); if ((status = pointObj_draw(php_point->point, php_map->map, php_layer->layer, php_image->image, classIndex, text)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ zend_function_entry point_functions[] = { PHP_ME(pointObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(pointObj, __get, point___get_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, __set, point___set_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, setXY, point_setXY_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, setXYZ, point_setXYZ_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, project, point_project_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, distanceToPoint, point_distanceToPoint_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, distanceToLine, point_distanceToLine_args, ZEND_ACC_PUBLIC) PHP_MALIAS(pointObj, distanceToSegment, distanceToLine, point_distanceToLine_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, distanceToShape, point_distanceToShape_args, ZEND_ACC_PUBLIC) PHP_ME(pointObj, draw, point_draw_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_point(pointObj *point, parent_object parent, zval *return_value TSRMLS_DC) { php_point_object * php_point; object_init_ex(return_value, mapscript_ce_point); php_point = MAPSCRIPT_OBJ_P(php_point_object, return_value); php_point->point = point; if (ZVAL_NOT_UNDEF(parent.val)) php_point->is_ref = 1; php_point->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_point_create_object(zend_class_entry *ce TSRMLS_DC) { php_point_object *php_point; php_point = ecalloc(1, sizeof(*php_point) + zend_object_properties_size(ce)); zend_object_std_init(&php_point->zobj, ce TSRMLS_CC); object_properties_init(&php_point->zobj, ce); php_point->zobj.handlers = &mapscript_point_object_handlers; php_point->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_point->parent); return &php_point->zobj; } static void mapscript_point_free_object(zend_object *object) { php_point_object *php_point; php_point = (php_point_object *)((char *)object - XtOffsetOf(php_point_object, zobj)); MAPSCRIPT_FREE_PARENT(php_point->parent); if (php_point->point && !php_point->is_ref) { pointObj_destroy(php_point->point); } zend_object_std_dtor(object); } static zend_object* mapscript_point_clone_object(zval *zobj) { php_point_object *php_point_old, *php_point_new; zend_object* zobj_new; php_point_old = MAPSCRIPT_OBJ_P(php_point_object, zobj); zobj_new = mapscript_point_create_object(mapscript_ce_point); php_point_new = (php_point_object *)((char *)zobj_new - XtOffsetOf(php_point_object, zobj)); zend_objects_clone_members(&php_point_new->zobj, &php_point_old->zobj); if ((php_point_new->point = pointObj_new()) == NULL) { mapscript_throw_exception("Unable to construct pointObj." TSRMLS_CC); return NULL; } memcpy(php_point_new->point, php_point_old->point, sizeof(pointObj)); return zobj_new; } PHP_MINIT_FUNCTION(point) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "pointObj", point_functions); mapscript_ce_point = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_point->create_object = mapscript_point_create_object; mapscript_ce_point->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_point_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_point_object_handlers)); mapscript_point_object_handlers.free_obj = mapscript_point_free_object; mapscript_point_object_handlers.clone_obj = mapscript_point_clone_object; mapscript_point_object_handlers.offset = XtOffsetOf(php_point_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_point_object_destroy(void *object TSRMLS_DC) { php_point_object *php_point = (php_point_object *)object; MAPSCRIPT_FREE_OBJECT(php_point); MAPSCRIPT_FREE_PARENT(php_point->parent); if (php_point->point && !php_point->is_ref) { pointObj_destroy(php_point->point); } efree(object); } static zend_object_value mapscript_point_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_point_object *php_point; MAPSCRIPT_ALLOC_OBJECT(php_point, php_point_object); retval = mapscript_object_new(&php_point->std, ce, &mapscript_point_object_destroy TSRMLS_CC); php_point->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_point->parent); return retval; } PHP_MINIT_FUNCTION(point) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("pointObj", point_functions, mapscript_ce_point, mapscript_point_object_new); mapscript_ce_point->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/projection.c000066400000000000000000000223241357574274700206720ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_projection; zend_object_handlers mapscript_projection_object_handlers; ZEND_BEGIN_ARG_INFO_EX(projection___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, projString) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(projection_setWKTProjection_args, 0, 0, 1) ZEND_ARG_INFO(0, wkt) ZEND_END_ARG_INFO() /* {{{ proto projectionObj __construct(string projString) Create a new projectionObj instance. */ PHP_METHOD(projectionObj, __construct) { char *projString; long projString_len = 0; php_projection_object *php_projection; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &projString, &projString_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_projection = MAPSCRIPT_OBJ_P(php_projection_object, getThis()); if ((php_projection->projection = projectionObj_new(projString)) == NULL) { mapscript_throw_mapserver_exception("Unable to construct projectionObj." TSRMLS_CC); return; } } /* }}} */ /* {{{ proto projectionObj setWKTProjection(string wkt) Set the wkt projection. Return MS_SUCCESS or MS_FAILURE .*/ PHP_METHOD(projectionObj, setWKTProjection) { char *wkt; long wkt_len = 0; php_projection_object *php_projection; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &wkt, &wkt_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_projection = MAPSCRIPT_OBJ_P(php_projection_object, getThis()); RETURN_LONG(msOGCWKT2ProjectionObj(wkt, php_projection->projection, MS_FALSE)); } /* }}} */ /* {{{ proto int projectionObj.getunits() Returns the units of a projection object */ PHP_METHOD(projectionObj, getUnits) { php_projection_object *php_projection; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_projection = MAPSCRIPT_OBJ_P(php_projection_object, getThis()); RETURN_LONG(projectionObj_getUnits(php_projection->projection)); } /* }}} */ zend_function_entry projection_functions[] = { PHP_ME(projectionObj, __construct, projection___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(projectionObj, setWKTProjection, projection_setWKTProjection_args, ZEND_ACC_PUBLIC) PHP_ME(projectionObj, getUnits, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_projection(projectionObj *projection, parent_object parent, zval *return_value TSRMLS_DC) { php_projection_object * php_projection; object_init_ex(return_value, mapscript_ce_projection); php_projection = MAPSCRIPT_OBJ_P(php_projection_object, return_value); php_projection->projection = projection; if (ZVAL_NOT_UNDEF(parent.val)) php_projection->is_ref = 1; php_projection->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_projection_create_object(zend_class_entry *ce TSRMLS_DC) { php_projection_object *php_projection; php_projection = ecalloc(1, sizeof(*php_projection) + zend_object_properties_size(ce)); zend_object_std_init(&php_projection->zobj, ce TSRMLS_CC); object_properties_init(&php_projection->zobj, ce); php_projection->zobj.handlers = &mapscript_projection_object_handlers; MAPSCRIPT_INIT_PARENT(php_projection->parent); php_projection->is_ref = 0; return &php_projection->zobj; } static void mapscript_projection_free_object(zend_object *object) { php_projection_object *php_projection; php_projection = (php_projection_object *)((char *)object - XtOffsetOf(php_projection_object, zobj)); MAPSCRIPT_FREE_PARENT(php_projection->parent); if (php_projection->projection && !php_projection->is_ref) { projectionObj_destroy(php_projection->projection); } zend_object_std_dtor(object); } static zend_object* mapscript_projection_clone_object(zval *zobj) { php_projection_object *php_projection_old, *php_projection_new; zend_object* zobj_new; php_projection_old = MAPSCRIPT_OBJ_P(php_projection_object, zobj); zobj_new = mapscript_projection_create_object(mapscript_ce_projection); php_projection_new = (php_projection_object *)((char *)zobj_new - XtOffsetOf(php_projection_object, zobj)); zend_objects_clone_members(&php_projection_new->zobj, &php_projection_old->zobj); php_projection_new->projection = projectionObj_clone(php_projection_old->projection); return zobj_new; } PHP_MINIT_FUNCTION(projection) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "projectionObj", projection_functions); mapscript_ce_projection = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_projection->create_object = mapscript_projection_create_object; mapscript_ce_projection->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_projection_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_projection_object_handlers)); mapscript_projection_object_handlers.free_obj = mapscript_projection_free_object; mapscript_projection_object_handlers.clone_obj = mapscript_projection_clone_object; mapscript_projection_object_handlers.offset = XtOffsetOf(php_projection_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_projection_object_destroy(void *object TSRMLS_DC) { php_projection_object *php_projection = (php_projection_object *)object; MAPSCRIPT_FREE_OBJECT(php_projection); MAPSCRIPT_FREE_PARENT(php_projection->parent); if (php_projection->projection && !php_projection->is_ref) { projectionObj_destroy(php_projection->projection); } efree(object); } static zend_object_value mapscript_projection_object_new_ex(zend_class_entry *ce, php_projection_object **ptr TSRMLS_DC) { zend_object_value retval; php_projection_object *php_projection; MAPSCRIPT_ALLOC_OBJECT(php_projection, php_projection_object); retval = mapscript_object_new_ex(&php_projection->std, ce, &mapscript_projection_object_destroy, &mapscript_projection_object_handlers TSRMLS_CC); if (ptr) *ptr = php_projection; php_projection->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_projection->parent); return retval; } static zend_object_value mapscript_projection_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_projection_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_projection_object_clone(zval *zobj TSRMLS_DC) { php_projection_object *php_projection_old, *php_projection_new; zend_object_value new_ov; php_projection_old = MAPSCRIPT_OBJ_P(php_projection_object, zobj); new_ov = mapscript_projection_object_new_ex(mapscript_ce_projection, &php_projection_new TSRMLS_CC); zend_objects_clone_members(&php_projection_new->std, new_ov, &php_projection_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_projection_new->projection = projectionObj_clone(php_projection_old->projection); return new_ov; } PHP_MINIT_FUNCTION(projection) { zend_class_entry ce; memcpy(&mapscript_projection_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_projection_object_handlers.clone_obj = mapscript_projection_object_clone; MAPSCRIPT_REGISTER_CLASS("projectionObj", projection_functions, mapscript_ce_projection, mapscript_projection_object_new); mapscript_ce_projection->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/querymap.c000066400000000000000000000236131357574274700203630ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_querymap; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_querymap_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(querymap___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(querymap___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(querymap_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() /* {{{ proto querymap __construct() queryMapObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(queryMapObj, __construct) { mapscript_throw_exception("queryMapObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(queryMapObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_querymap_object *php_querymap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = MAPSCRIPT_OBJ_P(php_querymap_object, zobj); IF_GET_LONG("width", php_querymap->querymap->width) else IF_GET_LONG("height", php_querymap->querymap->height) else IF_GET_LONG("style", php_querymap->querymap->style) else IF_GET_LONG("status", php_querymap->querymap->status) else IF_GET_OBJECT("color", mapscript_ce_color, php_querymap->color, &php_querymap->querymap->color) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(queryMapObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_querymap_object *php_querymap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = MAPSCRIPT_OBJ_P(php_querymap_object, zobj); IF_SET_LONG("width", php_querymap->querymap->width, value) else IF_SET_LONG("height", php_querymap->querymap->height, value) else IF_SET_LONG("style", php_querymap->querymap->style, value) else IF_SET_LONG("status", php_querymap->querymap->status, value) else if ( (STRING_EQUAL("color", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int querymap.updateFromString(string snippet) Update a querymap from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(queryMapObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_querymap_object *php_querymap; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = MAPSCRIPT_OBJ_P(php_querymap_object, zobj); status = queryMapObj_updateFromString(php_querymap->querymap, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the querymap object to string. */ PHP_METHOD(queryMapObj, convertToString) { zval *zobj = getThis(); php_querymap_object *php_querymap; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = MAPSCRIPT_OBJ_P(php_querymap_object, zobj); value = queryMapObj_convertToString(php_querymap->querymap); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int querymap.free() Free the object */ PHP_METHOD(queryMapObj, free) { zval *zobj = getThis(); php_querymap_object *php_querymap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_querymap = MAPSCRIPT_OBJ_P(php_querymap_object, zobj); MAPSCRIPT_DELREF(php_querymap->color); } /* }}} */ zend_function_entry querymap_functions[] = { PHP_ME(queryMapObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(queryMapObj, __get, querymap___get_args, ZEND_ACC_PUBLIC) PHP_ME(queryMapObj, __set, querymap___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(queryMapObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(queryMapObj, updateFromString, querymap_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(queryMapObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(queryMapObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_querymap(queryMapObj *querymap, parent_object parent, zval *return_value TSRMLS_DC) { php_querymap_object * php_querymap; object_init_ex(return_value, mapscript_ce_querymap); php_querymap = MAPSCRIPT_OBJ_P(php_querymap_object, return_value); php_querymap->querymap = querymap; php_querymap->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_querymap_create_object(zend_class_entry *ce TSRMLS_DC) { php_querymap_object *php_querymap; php_querymap = ecalloc(1, sizeof(*php_querymap) + zend_object_properties_size(ce)); zend_object_std_init(&php_querymap->zobj, ce TSRMLS_CC); object_properties_init(&php_querymap->zobj, ce); php_querymap->zobj.handlers = &mapscript_querymap_object_handlers; MAPSCRIPT_INIT_PARENT(php_querymap->parent); ZVAL_UNDEF(&php_querymap->color); return &php_querymap->zobj; } static void mapscript_querymap_free_object(zend_object *object) { php_querymap_object *php_querymap; php_querymap = (php_querymap_object *)((char *)object - XtOffsetOf(php_querymap_object, zobj)); MAPSCRIPT_FREE_PARENT(php_querymap->parent); MAPSCRIPT_FREE_PARENT(php_querymap->parent); MAPSCRIPT_DELREF(php_querymap->color); /* We don't need to free the queryMapObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(querymap) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "queryMapObj", querymap_functions); mapscript_ce_querymap = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_querymap->create_object = mapscript_querymap_create_object; mapscript_ce_querymap->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_querymap_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_querymap_object_handlers)); mapscript_querymap_object_handlers.free_obj = mapscript_querymap_free_object; mapscript_querymap_object_handlers.offset = XtOffsetOf(php_querymap_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_querymap_object_destroy(void *object TSRMLS_DC) { php_querymap_object *php_querymap = (php_querymap_object *)object; MAPSCRIPT_FREE_OBJECT(php_querymap); MAPSCRIPT_FREE_PARENT(php_querymap->parent); MAPSCRIPT_DELREF(php_querymap->color); /* We don't need to free the queryMapObj */ efree(object); } static zend_object_value mapscript_querymap_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_querymap_object *php_querymap; MAPSCRIPT_ALLOC_OBJECT(php_querymap, php_querymap_object); retval = mapscript_object_new(&php_querymap->std, ce, &mapscript_querymap_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_querymap->parent); php_querymap->color = NULL; return retval; } PHP_MINIT_FUNCTION(querymap) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("queryMapObj", querymap_functions, mapscript_ce_querymap, mapscript_querymap_object_new); mapscript_ce_querymap->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/rect.c000066400000000000000000000330151357574274700174520ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_rect; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_rect_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(rect___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect_draw_args, 0, 0, 5) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_ARG_INFO(0, classIndex) ZEND_ARG_INFO(0, text) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect_project_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, projIn, projectionObj, 0) ZEND_ARG_OBJ_INFO(0, projOut, projectionObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect_setExtent_args, 0, 0, 4) ZEND_ARG_INFO(0, minx) ZEND_ARG_INFO(0, miny) ZEND_ARG_INFO(0, maxx) ZEND_ARG_INFO(0, maxy) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(rect_fit_args, 0, 0, 2) ZEND_ARG_INFO(0, width) ZEND_ARG_INFO(0, height) ZEND_END_ARG_INFO() /* {{{ proto rect __construct() Create a new rectObj instance. */ PHP_METHOD(rectObj, __construct) { php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, getThis()); if ((php_rect->rect = rectObj_new()) == NULL) { mapscript_throw_exception("Unable to construct rectObj." TSRMLS_CC); return; } } /* }}} */ PHP_METHOD(rectObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zobj); IF_GET_DOUBLE("minx", php_rect->rect->minx) else IF_GET_DOUBLE("miny", php_rect->rect->miny) else IF_GET_DOUBLE("maxx", php_rect->rect->maxx) else IF_GET_DOUBLE("maxy", php_rect->rect->maxy) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int draw(mapObj map, layerObj layer, imageObj img, string class_name, string text) Draws the individual rect using layer. Returns MS_SUCCESS/MS_FAILURE. */ PHP_METHOD(rectObj, draw) { zval *zobj = getThis(); zval *zmap, *zlayer, *zimage; char *text = NULL; long text_len = 0; long classIndex; int status = MS_FAILURE; php_rect_object *php_rect; php_map_object *php_map; php_layer_object *php_layer; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOOl|s", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer, &zimage, mapscript_ce_image, &classIndex, &text, &text_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zobj); php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); if ((status = rectObj_draw(php_rect->rect, php_map->map, php_layer->layer, php_image->image, classIndex, text)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ PHP_METHOD(rectObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zobj); IF_SET_DOUBLE("minx", php_rect->rect->minx, value) else IF_SET_DOUBLE("miny", php_rect->rect->miny, value) else IF_SET_DOUBLE("maxx", php_rect->rect->maxx, value) else IF_SET_DOUBLE("maxy", php_rect->rect->maxy, value) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int rect.project(projectionObj in, projectionObj out) Project a Rect object Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(rectObj, project) { zval *zobj_proj_in, *zobj_proj_out; zval *zobj = getThis(); php_rect_object *php_rect; php_projection_object *php_proj_in, *php_proj_out; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_proj_in, mapscript_ce_projection, &zobj_proj_out, mapscript_ce_projection) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zobj); php_proj_in = MAPSCRIPT_OBJ_P(php_projection_object, zobj_proj_in); php_proj_out = MAPSCRIPT_OBJ_P(php_projection_object, zobj_proj_out); status = rectObj_project(php_rect->rect, php_proj_in->projection, php_proj_out->projection); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int rect.setextent(xmin, ymin, xmax, ymax) Set object property using four values. */ PHP_METHOD(rectObj, setExtent) { zval *zobj = getThis(); double minx, miny, maxx, maxy; php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dddd", &minx, &miny, &maxx, &maxy) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zobj); php_rect->rect->minx = minx; php_rect->rect->miny = miny; php_rect->rect->maxx = maxx; php_rect->rect->maxy = maxy; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int rect.fit(int nWidth, int nHeight) Adjust extents of the rectangle to fit the width/height specified. */ PHP_METHOD(rectObj, fit) { zval *zobj = getThis(); long width, height; double retval=0.0; php_rect_object *php_rect; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, zobj); retval = rectObj_fit(php_rect->rect, width, height); RETURN_DOUBLE(retval); } /* }}} */ /* {{{ proto rect getCenter() Get center point of the extent. */ PHP_METHOD(rectObj, getCenter) { php_rect_object *php_rect; pointObj *center; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, getThis()); center = (pointObj *)calloc(1, sizeof(pointObj)); if (!center) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); RETURN_NULL(); } center->x = (php_rect->rect->minx + php_rect->rect->maxx)/2; center->y = (php_rect->rect->miny + php_rect->rect->maxy)/2; /* Return result object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(center, parent, return_value TSRMLS_CC); } /* }}} */ zend_function_entry rect_functions[] = { PHP_ME(rectObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(rectObj, getCenter, NULL, ZEND_ACC_PUBLIC) PHP_ME(rectObj, __get, rect___get_args, ZEND_ACC_PUBLIC) PHP_ME(rectObj, __set, rect___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(rectObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(rectObj, draw, rect_draw_args, ZEND_ACC_PUBLIC) PHP_ME(rectObj, project, rect_project_args, ZEND_ACC_PUBLIC) PHP_ME(rectObj, setExtent, rect_setExtent_args, ZEND_ACC_PUBLIC) PHP_ME(rectObj, fit, rect_fit_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_rect(rectObj *rect, parent_object parent, zval *return_value TSRMLS_DC) { php_rect_object * php_rect; object_init_ex(return_value, mapscript_ce_rect); php_rect = MAPSCRIPT_OBJ_P(php_rect_object, return_value); php_rect->rect = rect; if(ZVAL_NOT_UNDEF(parent.val)) php_rect->is_ref = 1; php_rect->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_rect_create_object(zend_class_entry *ce TSRMLS_DC) { php_rect_object *php_rect; php_rect = ecalloc(1, sizeof(*php_rect) + zend_object_properties_size(ce)); zend_object_std_init(&php_rect->zobj, ce TSRMLS_CC); object_properties_init(&php_rect->zobj, ce); php_rect->zobj.handlers = &mapscript_rect_object_handlers; MAPSCRIPT_INIT_PARENT(php_rect->parent); php_rect->is_ref = 0; return &php_rect->zobj; } static void mapscript_rect_free_object(zend_object *object) { php_rect_object *php_rect; php_rect = (php_rect_object *)((char *)object - XtOffsetOf(php_rect_object, zobj)); MAPSCRIPT_FREE_PARENT(php_rect->parent); if (php_rect->rect && !php_rect->is_ref) { rectObj_destroy(php_rect->rect); } zend_object_std_dtor(object); } static zend_object* mapscript_rect_clone_object(zval *zobj) { php_rect_object *php_rect_old, *php_rect_new; zend_object* zobj_new; php_rect_old = MAPSCRIPT_OBJ_P(php_rect_object, zobj); zobj_new = mapscript_rect_create_object(mapscript_ce_rect); php_rect_new = (php_rect_object *)((char *)zobj_new - XtOffsetOf(php_rect_object, zobj)); zend_objects_clone_members(&php_rect_new->zobj, &php_rect_old->zobj); if ((php_rect_new->rect = rectObj_new()) == NULL) { mapscript_throw_exception("Unable to construct rectObj." TSRMLS_CC); return NULL; } memcpy(php_rect_new->rect, php_rect_old->rect, sizeof(rectObj)); return zobj_new; } PHP_MINIT_FUNCTION(rect) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "rectObj", rect_functions); mapscript_ce_rect = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_rect->create_object = mapscript_rect_create_object; mapscript_ce_rect->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_rect_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_rect_object_handlers)); mapscript_rect_object_handlers.free_obj = mapscript_rect_free_object; mapscript_rect_object_handlers.clone_obj = mapscript_rect_clone_object; mapscript_rect_object_handlers.offset = XtOffsetOf(php_rect_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_rect_object_destroy(void *object TSRMLS_DC) { php_rect_object *php_rect = (php_rect_object *)object; MAPSCRIPT_FREE_OBJECT(php_rect); MAPSCRIPT_FREE_PARENT(php_rect->parent); if (php_rect->rect && !php_rect->is_ref) { rectObj_destroy(php_rect->rect); } efree(object); } static zend_object_value mapscript_rect_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_rect_object *php_rect; MAPSCRIPT_ALLOC_OBJECT(php_rect, php_rect_object); retval = mapscript_object_new(&php_rect->std, ce, &mapscript_rect_object_destroy TSRMLS_CC); php_rect->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_rect->parent) return retval; } PHP_MINIT_FUNCTION(rect) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("rectObj", rect_functions, mapscript_ce_rect, mapscript_rect_object_new); mapscript_ce_rect->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/referencemap.c000066400000000000000000000303741357574274700211560ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_referencemap; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_referencemap_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(referenceMap___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(referenceMap___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(referenceMap_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() /* {{{ proto referenceMapObj __construct() referenceMapObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(referenceMapObj, __construct) { mapscript_throw_exception("referenceMapObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(referenceMapObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_referencemap_object *php_referencemap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = MAPSCRIPT_OBJ_P(php_referencemap_object, zobj); IF_GET_STRING("image", php_referencemap->referencemap->image) else IF_GET_LONG("width", php_referencemap->referencemap->width) else IF_GET_LONG("height", php_referencemap->referencemap->height) else IF_GET_LONG("status", php_referencemap->referencemap->status) else IF_GET_LONG("marker", php_referencemap->referencemap->marker) else IF_GET_STRING("markername", php_referencemap->referencemap->markername) else IF_GET_LONG("markersize", php_referencemap->referencemap->markersize) else IF_GET_LONG("maxboxsize", php_referencemap->referencemap->maxboxsize) else IF_GET_LONG("minboxsize", php_referencemap->referencemap->minboxsize) else IF_GET_OBJECT("extent", mapscript_ce_rect, php_referencemap->extent, &php_referencemap->referencemap->extent) else IF_GET_OBJECT("color", mapscript_ce_color, php_referencemap->color, &php_referencemap->referencemap->color) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_referencemap->outlinecolor, &php_referencemap->referencemap->outlinecolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(referenceMapObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_referencemap_object *php_referencemap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = MAPSCRIPT_OBJ_P(php_referencemap_object, zobj); IF_SET_STRING("image", php_referencemap->referencemap->image, value) else IF_SET_LONG("width", php_referencemap->referencemap->width, value) else IF_SET_LONG("height", php_referencemap->referencemap->height, value) else IF_SET_LONG("status", php_referencemap->referencemap->status, value) else IF_SET_LONG("marker", php_referencemap->referencemap->marker, value) else IF_SET_STRING("markername", php_referencemap->referencemap->markername, value) else IF_SET_LONG("markersize", php_referencemap->referencemap->markersize, value) else IF_SET_LONG("maxboxsize", php_referencemap->referencemap->maxboxsize, value) else IF_SET_LONG("minboxsize", php_referencemap->referencemap->minboxsize, value) else if ( (STRING_EQUAL("extent", property)) || (STRING_EQUAL("color", property)) || (STRING_EQUAL("outlinecolor", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int referencemap.updateFromString(string snippet) Update a referencemap from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(referenceMapObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_referencemap_object *php_referencemap; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = MAPSCRIPT_OBJ_P(php_referencemap_object, zobj); status = referenceMapObj_updateFromString(php_referencemap->referencemap, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the referencemap object to string. */ PHP_METHOD(referenceMapObj, convertToString) { zval *zobj = getThis(); php_referencemap_object *php_referencemap; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = MAPSCRIPT_OBJ_P(php_referencemap_object, zobj); value = referenceMapObj_convertToString(php_referencemap->referencemap); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int referencemap.free() Free the object. */ PHP_METHOD(referenceMapObj, free) { zval *zobj = getThis(); php_referencemap_object *php_referencemap; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_referencemap = MAPSCRIPT_OBJ_P(php_referencemap_object, zobj); MAPSCRIPT_DELREF(php_referencemap->extent); MAPSCRIPT_DELREF(php_referencemap->color); MAPSCRIPT_DELREF(php_referencemap->outlinecolor); } /* }}} */ zend_function_entry referencemap_functions[] = { PHP_ME(referenceMapObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(referenceMapObj, __get, referenceMap___get_args, ZEND_ACC_PUBLIC) PHP_ME(referenceMapObj, __set, referenceMap___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(referenceMapObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(referenceMapObj, updateFromString, referenceMap_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(referenceMapObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(referenceMapObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_referencemap(referenceMapObj *referencemap, parent_object parent, zval *return_value TSRMLS_DC) { php_referencemap_object * php_referencemap; object_init_ex(return_value, mapscript_ce_referencemap); php_referencemap = MAPSCRIPT_OBJ_P(php_referencemap_object, return_value); php_referencemap->referencemap = referencemap; php_referencemap->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_referencemap_create_object(zend_class_entry *ce TSRMLS_DC) { php_referencemap_object *php_referencemap; php_referencemap = ecalloc(1, sizeof(*php_referencemap) + zend_object_properties_size(ce)); zend_object_std_init(&php_referencemap->zobj, ce TSRMLS_CC); object_properties_init(&php_referencemap->zobj, ce); php_referencemap->zobj.handlers = &mapscript_referencemap_object_handlers; MAPSCRIPT_INIT_PARENT(php_referencemap->parent); ZVAL_UNDEF(&php_referencemap->extent); ZVAL_UNDEF(&php_referencemap->color); ZVAL_UNDEF(&php_referencemap->outlinecolor); return &php_referencemap->zobj; } static void mapscript_referencemap_free_object(zend_object *object) { php_referencemap_object *php_referencemap; php_referencemap = (php_referencemap_object *)((char *)object - XtOffsetOf(php_referencemap_object, zobj)); MAPSCRIPT_FREE_PARENT(php_referencemap->parent); MAPSCRIPT_DELREF(php_referencemap->extent); MAPSCRIPT_DELREF(php_referencemap->color); MAPSCRIPT_DELREF(php_referencemap->outlinecolor); /* We don't need to free the referenceMapObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(referencemap) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "referenceMapObj", referencemap_functions); mapscript_ce_referencemap = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_referencemap->create_object = mapscript_referencemap_create_object; mapscript_ce_referencemap->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_referencemap_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_referencemap_object_handlers)); mapscript_referencemap_object_handlers.free_obj = mapscript_referencemap_free_object; mapscript_referencemap_object_handlers.offset = XtOffsetOf(php_referencemap_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_referencemap_object_destroy(void *object TSRMLS_DC) { php_referencemap_object *php_referencemap = (php_referencemap_object *)object; MAPSCRIPT_FREE_OBJECT(php_referencemap); MAPSCRIPT_FREE_PARENT(php_referencemap->parent); MAPSCRIPT_DELREF(php_referencemap->extent); MAPSCRIPT_DELREF(php_referencemap->color); MAPSCRIPT_DELREF(php_referencemap->outlinecolor); /* We don't need to free the referenceMapObj */ efree(object); } static zend_object_value mapscript_referencemap_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_referencemap_object *php_referencemap; MAPSCRIPT_ALLOC_OBJECT(php_referencemap, php_referencemap_object); retval = mapscript_object_new(&php_referencemap->std, ce, &mapscript_referencemap_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_referencemap->parent); php_referencemap->extent = NULL; php_referencemap->color = NULL; php_referencemap->outlinecolor = NULL; return retval; } PHP_MINIT_FUNCTION(referencemap) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("referenceMapObj", referencemap_functions, mapscript_ce_referencemap, mapscript_referencemap_object_new); mapscript_ce_referencemap->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/result.c000066400000000000000000000167731357574274700200470ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_result_object_handlers; #endif zend_class_entry *mapscript_ce_result; ZEND_BEGIN_ARG_INFO_EX(result___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, shapeindex) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(result___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(result___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() /* {{{ proto resultObj __construct() Create a new resultObj instance */ PHP_METHOD(resultObj, __construct) { long shapeindex; php_result_object *php_result; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &shapeindex) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_result = MAPSCRIPT_OBJ_P(php_result_object, getThis()); if ((php_result->result = resultObj_new()) == NULL) { mapscript_throw_exception("Unable to construct resultObj." TSRMLS_CC); return; } php_result->result->shapeindex = shapeindex; } /* }}} */ PHP_METHOD(resultObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_result_object *php_result; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_result = MAPSCRIPT_OBJ_P(php_result_object, zobj); IF_GET_LONG("shapeindex", php_result->result->shapeindex) else IF_GET_LONG("tileindex", php_result->result->tileindex) else IF_GET_LONG("classindex", php_result->result->classindex) else IF_GET_LONG("resultindex", php_result->result->resultindex) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(resultObj, __set) { char *property; long property_len = 0; zval *value; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ( (STRING_EQUAL("shapeindex", property)) || (STRING_EQUAL("tileindex", property)) || (STRING_EQUAL("resultindex", property)) || (STRING_EQUAL("classindex", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } zend_function_entry result_functions[] = { PHP_ME(resultObj, __construct, result___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(resultObj, __get, result___get_args, ZEND_ACC_PUBLIC) PHP_ME(resultObj, __set, result___set_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_result(resultObj *result, parent_object parent, zval *return_value TSRMLS_DC) { php_result_object * php_result; object_init_ex(return_value, mapscript_ce_result); php_result = MAPSCRIPT_OBJ_P(php_result_object, return_value); php_result->result = result; php_result->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_result_create_object(zend_class_entry *ce TSRMLS_DC) { php_result_object *php_result; php_result = ecalloc(1, sizeof(*php_result) + zend_object_properties_size(ce)); zend_object_std_init(&php_result->zobj, ce TSRMLS_CC); object_properties_init(&php_result->zobj, ce); php_result->zobj.handlers = &mapscript_result_object_handlers; MAPSCRIPT_INIT_PARENT(php_result->parent); return &php_result->zobj; } static void mapscript_result_free_object(zend_object *object) { php_result_object *php_result; php_result = (php_result_object *)((char *)object - XtOffsetOf(php_result_object, zobj)); MAPSCRIPT_FREE_PARENT(php_result->parent); /* We don't need to free the resultObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(result) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "resultObj", result_functions); mapscript_ce_result = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_result->create_object = mapscript_result_create_object; mapscript_ce_result->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_result_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_result_object_handlers)); mapscript_result_object_handlers.free_obj = mapscript_result_free_object; mapscript_result_object_handlers.offset = XtOffsetOf(php_result_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_result_object_destroy(void *object TSRMLS_DC) { php_result_object *php_result = (php_result_object *)object; MAPSCRIPT_FREE_OBJECT(php_result); MAPSCRIPT_FREE_PARENT(php_result->parent); /* We don't need to free the resultObj */ efree(object); } static zend_object_value mapscript_result_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_result_object *php_result; MAPSCRIPT_ALLOC_OBJECT(php_result, php_result_object); retval = mapscript_object_new(&php_result->std, ce, &mapscript_result_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_result->parent); return retval; } PHP_MINIT_FUNCTION(result) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("resultObj", result_functions, mapscript_ce_result, mapscript_result_object_new); mapscript_ce_result->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/scalebar.c000066400000000000000000000327701357574274700203000ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_scalebar; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_scalebar_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(scalebar___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(scalebar___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(scalebar_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(scalebar_setImageColor_args, 0, 0, 3) ZEND_ARG_INFO(0, red) ZEND_ARG_INFO(0, green) ZEND_ARG_INFO(0, blue) ZEND_END_ARG_INFO() /* {{{ proto scalebar __construct() scalebarObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(scalebarObj, __construct) { mapscript_throw_exception("scalebarObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(scalebarObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_scalebar_object *php_scalebar; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = MAPSCRIPT_OBJ_P(php_scalebar_object, zobj); IF_GET_LONG("height", php_scalebar->scalebar->height) else IF_GET_LONG("width", php_scalebar->scalebar->width) else IF_GET_LONG("style", php_scalebar->scalebar->style) else IF_GET_LONG("intervals", php_scalebar->scalebar->intervals) else IF_GET_LONG("units", php_scalebar->scalebar->units) else IF_GET_LONG("status", php_scalebar->scalebar->status) else IF_GET_LONG("position", php_scalebar->scalebar->position) else IF_GET_LONG("postlabelcache", php_scalebar->scalebar->postlabelcache) else IF_GET_LONG("align", php_scalebar->scalebar->align) else IF_GET_OBJECT("color", mapscript_ce_color, php_scalebar->color, &php_scalebar->scalebar->color) else IF_GET_OBJECT("backgroundcolor", mapscript_ce_color, php_scalebar->backgroundcolor, &php_scalebar->scalebar->backgroundcolor) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_scalebar->outlinecolor, &php_scalebar->scalebar->outlinecolor) else IF_GET_OBJECT("label", mapscript_ce_label, php_scalebar->label, &php_scalebar->scalebar->label) else IF_GET_OBJECT("imagecolor", mapscript_ce_color, php_scalebar->imagecolor, &php_scalebar->scalebar->imagecolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(scalebarObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_scalebar_object *php_scalebar; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = MAPSCRIPT_OBJ_P(php_scalebar_object, zobj); IF_SET_LONG("height", php_scalebar->scalebar->height, value) else IF_SET_LONG("width", php_scalebar->scalebar->width, value) else IF_SET_LONG("style", php_scalebar->scalebar->style, value) else IF_SET_LONG("intervals", php_scalebar->scalebar->intervals, value) else IF_SET_LONG("units", php_scalebar->scalebar->units, value) else IF_SET_LONG("status", php_scalebar->scalebar->status, value) else IF_SET_LONG("position", php_scalebar->scalebar->position, value) else IF_SET_LONG("postlabelcache", php_scalebar->scalebar->postlabelcache, value) else IF_SET_LONG("align", php_scalebar->scalebar->align, value) else if ( (STRING_EQUAL("color", property)) || (STRING_EQUAL("backgroundcolor", property)) || (STRING_EQUAL("outlinecolor", property)) || (STRING_EQUAL("label", property)) || (STRING_EQUAL("imagecolor", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int scalebar.updateFromString(string snippet) Update a scalebar from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(scalebarObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_scalebar_object *php_scalebar; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = MAPSCRIPT_OBJ_P(php_scalebar_object, zobj); status = scalebarObj_updateFromString(php_scalebar->scalebar, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the scalebar object to string. */ PHP_METHOD(scalebarObj, convertToString) { zval *zobj = getThis(); php_scalebar_object *php_scalebar; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = MAPSCRIPT_OBJ_P(php_scalebar_object, zobj); value = scalebarObj_convertToString(php_scalebar->scalebar); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int scalebar.setImageColor(int red, int green, int blue) Set the imagecolor property of the scalebar. Returns -1 on error. */ PHP_METHOD(scalebarObj, setImageColor) { zval *zobj = getThis(); long red, green, blue; php_scalebar_object *php_scalebar; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &red, &green, &blue) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = MAPSCRIPT_OBJ_P(php_scalebar_object, zobj); if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) RETURN_LONG(MS_FAILURE); php_scalebar->scalebar->imagecolor.red = red; php_scalebar->scalebar->imagecolor.green = green; php_scalebar->scalebar->imagecolor.blue = blue; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int scalebar.free() Free the object */ PHP_METHOD(scalebarObj, free) { zval *zobj = getThis(); php_scalebar_object *php_scalebar; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_scalebar = MAPSCRIPT_OBJ_P(php_scalebar_object, zobj); MAPSCRIPT_DELREF(php_scalebar->color); MAPSCRIPT_DELREF(php_scalebar->backgroundcolor); MAPSCRIPT_DELREF(php_scalebar->outlinecolor); MAPSCRIPT_DELREF(php_scalebar->imagecolor); MAPSCRIPT_DELREF(php_scalebar->label); } /* }}} */ zend_function_entry scalebar_functions[] = { PHP_ME(scalebarObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(scalebarObj, __get, scalebar___get_args, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, __set, scalebar___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(scalebarObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, updateFromString, scalebar_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, setImageColor, scalebar_setImageColor_args, ZEND_ACC_PUBLIC) PHP_ME(scalebarObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_scalebar(scalebarObj *scalebar, parent_object parent, zval *return_value TSRMLS_DC) { php_scalebar_object * php_scalebar; object_init_ex(return_value, mapscript_ce_scalebar); php_scalebar = MAPSCRIPT_OBJ_P(php_scalebar_object, return_value); php_scalebar->scalebar = scalebar; php_scalebar->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_scalebar_create_object(zend_class_entry *ce TSRMLS_DC) { php_scalebar_object *php_scalebar; php_scalebar = ecalloc(1, sizeof(*php_scalebar) + zend_object_properties_size(ce)); zend_object_std_init(&php_scalebar->zobj, ce TSRMLS_CC); object_properties_init(&php_scalebar->zobj, ce); php_scalebar->zobj.handlers = &mapscript_scalebar_object_handlers; MAPSCRIPT_INIT_PARENT(php_scalebar->parent); ZVAL_UNDEF(&php_scalebar->color); ZVAL_UNDEF(&php_scalebar->backgroundcolor); ZVAL_UNDEF(&php_scalebar->outlinecolor); ZVAL_UNDEF(&php_scalebar->imagecolor); ZVAL_UNDEF(&php_scalebar->label); return &php_scalebar->zobj; } static void mapscript_scalebar_free_object(zend_object *object) { php_scalebar_object *php_scalebar; php_scalebar = (php_scalebar_object *)((char *)object - XtOffsetOf(php_scalebar_object, zobj)); MAPSCRIPT_FREE_PARENT(php_scalebar->parent); MAPSCRIPT_DELREF(php_scalebar->color); MAPSCRIPT_DELREF(php_scalebar->backgroundcolor); MAPSCRIPT_DELREF(php_scalebar->outlinecolor); MAPSCRIPT_DELREF(php_scalebar->imagecolor); MAPSCRIPT_DELREF(php_scalebar->label); /* We don't need to free the scalebarObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(scalebar) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "scalebarObj", scalebar_functions); mapscript_ce_scalebar = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_scalebar->create_object = mapscript_scalebar_create_object; mapscript_ce_scalebar->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_scalebar_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_scalebar_object_handlers)); mapscript_scalebar_object_handlers.free_obj = mapscript_scalebar_free_object; mapscript_scalebar_object_handlers.offset = XtOffsetOf(php_scalebar_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_scalebar_object_destroy(void *object TSRMLS_DC) { php_scalebar_object *php_scalebar = (php_scalebar_object *)object; MAPSCRIPT_FREE_OBJECT(php_scalebar); MAPSCRIPT_FREE_PARENT(php_scalebar->parent); MAPSCRIPT_DELREF(php_scalebar->color); MAPSCRIPT_DELREF(php_scalebar->backgroundcolor); MAPSCRIPT_DELREF(php_scalebar->outlinecolor); MAPSCRIPT_DELREF(php_scalebar->imagecolor); MAPSCRIPT_DELREF(php_scalebar->label); /* We don't need to free the scalebarObj */ efree(object); } static zend_object_value mapscript_scalebar_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_scalebar_object *php_scalebar; MAPSCRIPT_ALLOC_OBJECT(php_scalebar, php_scalebar_object); retval = mapscript_object_new(&php_scalebar->std, ce, &mapscript_scalebar_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_scalebar->parent); php_scalebar->color = NULL; php_scalebar->backgroundcolor = NULL; php_scalebar->outlinecolor = NULL; php_scalebar->imagecolor = NULL; php_scalebar->label = NULL; return retval; } PHP_MINIT_FUNCTION(scalebar) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("scalebarObj", scalebar_functions, mapscript_ce_scalebar, mapscript_scalebar_object_new); mapscript_ce_scalebar->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/shape.c000066400000000000000000001221621357574274700176170ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_shape; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_shape_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(shape___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_project_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, projIn, projectionObj, 0) ZEND_ARG_OBJ_INFO(0, projOut, projectionObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_add_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, line, lineObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_line_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_contains_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_intersects_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_getPointUsingMeasure_args, 0, 0, 1) ZEND_ARG_INFO(0, measure) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_getMeasureUsingPoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_getValue_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_INFO(0, fieldName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_buffer_args, 0, 0, 1) ZEND_ARG_INFO(0, width) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_containsShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_union_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_intersection_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_difference_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_symdifference_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_overlaps_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_within_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_crosses_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_touches_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_equals_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_disjoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_simplify_args, 0, 0, 1) ZEND_ARG_INFO(0, tolerance) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_topologyPreservingSimplify_args, 0, 0, 1) ZEND_ARG_INFO(0, tolerance) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_draw_args, 0, 0, 3) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_OBJ_INFO(0, layer, layerObj, 0) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_distanceToPoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shape_distanceToShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() /* {{{ proto shape __construct(int type) Create a new shapeObj instance. */ PHP_METHOD(shapeObj, __construct) { zval *zobj = getThis(); php_shape_object *php_shape; long type; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); if ((php_shape->shape = shapeObj_new(type)) == NULL) { mapscript_throw_exception("Unable to construct shapeObj." TSRMLS_CC); return; } MAKE_STD_ZVAL(php_shape->values); mapscript_array_init(php_shape->values); } /* }}} */ PHP_METHOD(shapeObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); IF_GET_STRING("text", php_shape->shape->text) else IF_GET_LONG("classindex", php_shape->shape->classindex) else IF_GET_LONG("index", php_shape->shape->index) else IF_GET_LONG("tileindex", php_shape->shape->tileindex) else IF_GET_LONG("resultindex", php_shape->shape->resultindex) else IF_GET_LONG("numlines", php_shape->shape->numlines) else IF_GET_LONG("numvalues", php_shape->shape->numvalues) else IF_GET_LONG("type", php_shape->shape->type) else IF_GET_OBJECT("bounds", mapscript_ce_rect, php_shape->bounds, &php_shape->shape->bounds) else IF_GET_OBJECT("values", NULL, php_shape->values, NULL) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(shapeObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); IF_SET_STRING("text", php_shape->shape->text, value) else IF_SET_LONG("classindex", php_shape->shape->classindex, value) else IF_SET_LONG("index", php_shape->shape->index, value) else if ( (STRING_EQUAL("type", property)) || (STRING_EQUAL("numlines", property)) || (STRING_EQUAL("tileindex", property)) || (STRING_EQUAL("resultindex", property)) || (STRING_EQUAL("bounds", property)) || (STRING_EQUAL("values", property)) || (STRING_EQUAL("numvalues", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int shape.add(lineObj line) Adds a line (i.e. a part) to a shape */ PHP_METHOD(shapeObj, add) { zval *zobj = getThis(); zval *zline; php_shape_object *php_shape; php_line_object *php_line; int retval = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zline, mapscript_ce_line) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_line = MAPSCRIPT_OBJ_P(php_line_object, zline); retval = shapeObj_add(php_shape->shape, php_line->line); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int shape.line(int i) Returns line (part) number i. First line is number 0. */ PHP_METHOD(shapeObj, line) { zval *zobj = getThis(); long index; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); if (index < 0 || index >= php_shape->shape->numlines) { mapscript_throw_exception("Line '%d' does not exist in this object." TSRMLS_CC, index); return; } MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_line(&(php_shape->shape->line[index]), parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.contains(pointObj point) Returns true or false if the the point is in a polygone shape.*/ PHP_METHOD(shapeObj, contains) { zval *zobj = getThis(); zval *zpoint; php_shape_object *php_shape; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_point = MAPSCRIPT_OBJ_P(php_point_object, zpoint); if (!shapeObj_contains(php_shape->shape, php_point->point)) RETURN_FALSE; RETURN_TRUE; } /* }}} */ /* {{{ proto int shape.intersects(shapeObj shape) Returns true if the two shapes intersect. Else false.*/ PHP_METHOD(shapeObj, intersects) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (!shapeObj_intersects(php_shape->shape, php_shape2->shape)) RETURN_FALSE; RETURN_TRUE; } /* }}} */ /* {{{ proto int shape.project(projectionObj in, projectionObj out) Project a Shape. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(shapeObj, project) { zval *zobj_proj_in, *zobj_proj_out; zval *zobj = getThis(); php_shape_object *php_shape; php_projection_object *php_proj_in, *php_proj_out; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zobj_proj_in, mapscript_ce_projection, &zobj_proj_out, mapscript_ce_projection) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_proj_in = MAPSCRIPT_OBJ_P(php_projection_object, zobj_proj_in); php_proj_out = MAPSCRIPT_OBJ_P(php_projection_object, zobj_proj_out); status = shapeObj_project(php_shape->shape, php_proj_in->projection, php_proj_out->projection); if (status != MS_SUCCESS) { mapscript_report_mapserver_error(E_WARNING TSRMLS_CC); } RETURN_LONG(status); } /* }}} */ /* {{{ proto int shape.getpointusingmeasure(double measure) Given a shape and a mesure, return a point object containing the XY location corresponding to the measure */ PHP_METHOD(shapeObj, getPointUsingMeasure) { zval *zobj = getThis(); double measure; pointObj *point = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &measure) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); point = shapeObj_getpointusingmeasure(php_shape->shape, measure); if (point == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(zobj, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.getpointusingmeasure(pointObj point) Given a shape and a point object, return a point object containing the XY location of the intersection between the point and the shape. The point return contains also the extrapolated M value at the intersection. */ PHP_METHOD(shapeObj, getMeasureUsingPoint) { zval *zobj = getThis(); zval *zpoint; pointObj *intersection = NULL; php_shape_object *php_shape; php_point_object *php_point; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_point = MAPSCRIPT_OBJ_P(php_point_object, zpoint); intersection = shapeObj_getmeasureusingpoint(php_shape->shape, php_point->point); if (intersection == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(intersection, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto string shape.getValue(layerObj layer, string fieldName) Returns value for specified field name. */ PHP_METHOD(shapeObj, getValue) { zval *zobj = getThis(); zval *zlayer; char *fieldName; long fieldName_len = 0; int i; php_layer_object *php_layer; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zlayer, mapscript_ce_layer, &fieldName, &fieldName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); if (php_shape->shape->numvalues != php_layer->layer->numitems) MAPSCRIPT_RETURN_STRING("", 1); for(i=0; ilayer->numitems; i++) { if (strcasecmp(php_layer->layer->items[i], fieldName)==0) { MAPSCRIPT_RETURN_STRING(php_shape->shape->values[i], 1); } } } /* }}} */ /* {{{ proto int shape.buffer(double width) Given a shape and a width, return a shape object with a buffer using underlying GEOS library*/ PHP_METHOD(shapeObj, buffer) { zval *zobj = getThis(); double width; shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &width) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); shape = shapeObj_buffer(php_shape->shape, width); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.convexhull() Given a shape, return a shape representing the convex hull using underlying GEOS library */ PHP_METHOD(shapeObj, convexhull) { zval *zobj = getThis(); shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); shape = shapeObj_convexHull(php_shape->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.boundary() Returns the boundary of the shape. Only available if php/mapscript is built with GEOS library.*/ PHP_METHOD(shapeObj, boundary) { zval *zobj = getThis(); shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); shape = shapeObj_boundary(php_shape->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.contains(shapeobj shape) Return true or false if the given shape in argument 1 is contained in the shape. Use3d underlying msGEOSContains GEOS library*/ PHP_METHOD(shapeObj, containsShape) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (shapeObj_contains_geos(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.Union(shapeobj shape) Return a shape which is the union of the current shape and the one given in argument 1 . Uses underlying GEOS library*/ PHP_METHOD(shapeObj, union) { zval *zobj = getThis(); zval *zshape; shapeObj *shape; php_shape_object *php_shape, *php_shape2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); shape = shapeObj_Union(php_shape->shape, php_shape2->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.intersection(shapeobj shape) Return a shape which is the intersection of the current shape and the one given in argument 1 . Uses underlying GEOS library*/ PHP_METHOD(shapeObj, intersection) { zval *zobj = getThis(); zval *zshape; shapeObj *shape; php_shape_object *php_shape, *php_shape2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); shape = shapeObj_intersection(php_shape->shape, php_shape2->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.difference(shapeobj shape) Return a shape which is the difference of the current shape and the one given in argument 1 . Uses underlying GEOS library*/ PHP_METHOD(shapeObj, difference) { zval *zobj = getThis(); zval *zshape; shapeObj *shape; php_shape_object *php_shape, *php_shape2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); shape = shapeObj_difference(php_shape->shape, php_shape2->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.symdifference(shapeobj shape) Return a shape which is the symetrical difference of the current shape and the one given in argument 1 . Uses underlying GEOS library*/ PHP_METHOD(shapeObj, symdifference) { zval *zobj = getThis(); zval *zshape; shapeObj *shape; php_shape_object *php_shape, *php_shape2; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); shape = shapeObj_symdifference(php_shape->shape, php_shape2->shape); if (shape == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.overlaps(shapeobj shape) Return true if the given shape in argument 1 overlaps the shape. Else return false. */ PHP_METHOD(shapeObj, overlaps) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (shapeObj_overlaps(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.within(shapeobj shape) Return true if the given shape in argument 1 is within the shape. Else return false. */ PHP_METHOD(shapeObj, within) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (shapeObj_within(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.crosses(shapeobj shape) Return true if the given shape in argument 1 crosses the shape. Else return false. */ PHP_METHOD(shapeObj, crosses) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (shapeObj_crosses(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.touches(shapeobj shape) Return true if the given shape in argument 1 touches the shape. Else return false. */ PHP_METHOD(shapeObj, touches) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (shapeObj_touches(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.equals(shapeobj shape) Return true if the given shape in argument 1 is equal to the shape. Else return false. */ PHP_METHOD(shapeObj, equals) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (shapeObj_equals(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.disjoint(shapeobj shape) Return true if the given shape in argument 1 is disjoint to the shape. Else return false. */ PHP_METHOD(shapeObj, disjoint) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape, *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); if (shapeObj_disjoint(php_shape->shape, php_shape2->shape)) { RETURN_TRUE; } else RETURN_FALSE; } /* }}} */ /* {{{ proto int shape.getcentroid() Given a shape, return a point object representing the centroid */ PHP_METHOD(shapeObj, getCentroid) { zval *zobj = getThis(); pointObj *point; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); point = shapeObj_getcentroid(php_shape->shape); if (point == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.getarea() Returns the area of the shape */ PHP_METHOD(shapeObj, getArea) { zval *zobj = getThis(); double area = 0; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); area = shapeObj_getarea(php_shape->shape); RETURN_DOUBLE(area); } /* }}} */ /* {{{ proto int shape.getlength() Returns the length of the shape */ PHP_METHOD(shapeObj, getLength) { zval *zobj = getThis(); double length = 0; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); length = shapeObj_getlength(php_shape->shape); RETURN_DOUBLE(length); } /* }}} */ /* {{{ proto int shape.getlabelpoint() Given a shape, return a point object suitable for labelling it */ PHP_METHOD(shapeObj, getLabelPoint) { zval *zobj = getThis(); pointObj *point; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); point = shapeObj_getLabelPoint(php_shape->shape); if (point == NULL) RETURN_FALSE; MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto string shape.toWkt() Returns WKT representation of geometry. */ PHP_METHOD(shapeObj, toWkt) { zval *zobj = getThis(); char *wkt = NULL; php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); wkt = msShapeToWKT(php_shape->shape); if (wkt) { MAPSCRIPT_RETVAL_STRING(wkt, 1); msFree(wkt); return; } MAPSCRIPT_RETURN_STRING("", 1); } /* }}} */ /* {{{ proto int shape.setBounds() Updates the bounds property of the shape. Must be called to calculate new bounding box after new parts have been added. Returns true if successful, else return false.*/ PHP_METHOD(shapeObj, setBounds) { zval *zobj = getThis(); php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); shapeObj_setBounds(php_shape->shape); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int shape.simplify(double tolerance) Given a shape and a tolerance, return a simplified shape object using underlying GEOS library */ PHP_METHOD(shapeObj, simplify) { zval *zobj = getThis(); double tolerance; shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &tolerance) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); shape = shapeObj_simplify(php_shape->shape, tolerance); if (shape == NULL) RETURN_NULL(); MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.topologypreservingsimplify(double tolerance) Given a shape and a tolerance, return a simplified shape object using underlying GEOS library */ PHP_METHOD(shapeObj, topologyPreservingSimplify) { zval *zobj = getThis(); double tolerance; shapeObj *shape = NULL; php_shape_object *php_shape; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &tolerance) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); shape = shapeObj_topologypreservingsimplify(php_shape->shape, tolerance); if (shape == NULL) RETURN_NULL(); MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shape.draw(mapObj map, layerObj layer, imageObj img) Draws the individual shape using layer. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(shapeObj, draw) { zval *zobj = getThis(); zval *zmap, *zlayer, *zimage; int status = MS_FAILURE; php_shape_object *php_shape; php_map_object *php_map; php_layer_object *php_layer; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOO", &zmap, mapscript_ce_map, &zlayer, mapscript_ce_layer, &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); php_layer = MAPSCRIPT_OBJ_P(php_layer_object, zlayer); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); if ((status = shapeObj_draw(php_shape->shape, php_map->map, php_layer->layer, php_image->image)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto void shape.free() Free the object */ PHP_METHOD(shapeObj, free) { zval *zobj = getThis(); php_shape_object *php_shape; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); MAPSCRIPT_DELREF(php_shape->bounds); } /* }}} */ /* {{{ proto int shape.distanceToPoint(pointObj point) Returns the distance from the point to shape. */ PHP_METHOD(shapeObj, distanceToPoint) { zval *zobj = getThis(); zval *zpoint; php_shape_object *php_shape; php_point_object *php_point; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_point = MAPSCRIPT_OBJ_P(php_point_object, zpoint); RETURN_DOUBLE(msDistancePointToShape(php_point->point, php_shape->shape)); } /* }}} */ /* {{{ proto int shape.distanceToShape(shapeObj shape) Returns the distance from the shape to shape2. */ PHP_METHOD(shapeObj, distanceToShape) { zval *zobj = getThis(); zval *zshape; php_shape_object *php_shape; php_shape_object *php_shape2; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zobj); php_shape2 = MAPSCRIPT_OBJ_P(php_shape_object, zshape); RETURN_DOUBLE(msGEOSDistance(php_shape->shape, php_shape2->shape)); } /* }}} */ zend_function_entry shape_functions[] = { PHP_ME(shapeObj, __construct, shape___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(shapeObj, __get, shape___get_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, __set, shape___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(shapeObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, project, shape_project_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, add, shape_add_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, line, shape_line_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, contains, shape_contains_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, intersects, shape_intersects_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getPointUsingMeasure, shape_getPointUsingMeasure_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getMeasureUsingPoint, shape_getMeasureUsingPoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getValue, shape_getValue_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, buffer, shape_buffer_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, convexhull, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, boundary, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, containsShape, shape_containsShape_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, union, shape_union_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, intersection, shape_intersection_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, difference, shape_difference_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, symdifference, shape_symdifference_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, overlaps, shape_overlaps_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, within, shape_within_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, crosses, shape_crosses_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, touches, shape_touches_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, equals, shape_equals_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, disjoint, shape_disjoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getCentroid, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getArea, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getLength, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, getLabelPoint, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, toWkt, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, setBounds, NULL, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, simplify, shape_simplify_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, topologyPreservingSimplify, shape_topologyPreservingSimplify_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, draw, shape_draw_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, distanceToPoint, shape_distanceToPoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, distanceToShape, shape_distanceToShape_args, ZEND_ACC_PUBLIC) PHP_ME(shapeObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_shape(shapeObj *shape, parent_object parent, php_layer_object *php_layer, zval *return_value TSRMLS_DC) { php_shape_object *php_shape; int i; object_init_ex(return_value, mapscript_ce_shape); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, return_value); php_shape->shape = shape; MAKE_STD_ZVAL(php_shape->values); mapscript_array_init(php_shape->values); if (php_layer) { if ((php_shape->shape->numvalues == php_layer->layer->numitems) || (php_shape->shape->numvalues == 0 && php_layer->layer->numitems == -1)) { for(i=0; ishape->numvalues; i++) { mapscript_add_assoc_string(php_shape->values, php_layer->layer->items[i], php_shape->shape->values[i], 1); } } else { mapscript_throw_exception("Assertion failed, Could not set shape values: %d, %d" TSRMLS_CC, php_shape->shape->numvalues, php_layer->layer->numitems); return; } } if (ZVAL_NOT_UNDEF(parent.val)) php_shape->is_ref = 1; php_shape->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_shape_create_object(zend_class_entry *ce TSRMLS_DC) { php_shape_object *php_shape; php_shape = ecalloc(1, sizeof(*php_shape) + zend_object_properties_size(ce)); zend_object_std_init(&php_shape->zobj, ce TSRMLS_CC); object_properties_init(&php_shape->zobj, ce); php_shape->zobj.handlers = &mapscript_shape_object_handlers; php_shape->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_shape->parent); ZVAL_UNDEF(&php_shape->bounds); ZVAL_UNDEF(&php_shape->values); return &php_shape->zobj; } static void mapscript_shape_free_object(zend_object *object) { php_shape_object *php_shape; php_shape = (php_shape_object *)((char *)object - XtOffsetOf(php_shape_object, zobj)); MAPSCRIPT_FREE_PARENT(php_shape->parent); MAPSCRIPT_DELREF(php_shape->bounds); MAPSCRIPT_DELREF(php_shape->values); if (php_shape->shape && !php_shape->is_ref) { shapeObj_destroy(php_shape->shape); } zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(shape) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "shapeObj", shape_functions); mapscript_ce_shape = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_shape->create_object = mapscript_shape_create_object; mapscript_ce_shape->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_shape_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_shape_object_handlers)); mapscript_shape_object_handlers.free_obj = mapscript_shape_free_object; mapscript_shape_object_handlers.offset = XtOffsetOf(php_shape_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_shape_object_destroy(void *object TSRMLS_DC) { php_shape_object *php_shape = (php_shape_object *)object; MAPSCRIPT_FREE_OBJECT(php_shape); MAPSCRIPT_FREE_PARENT(php_shape->parent); MAPSCRIPT_DELREF(php_shape->bounds); MAPSCRIPT_DELREF(php_shape->values); if (php_shape->shape && !php_shape->is_ref) { shapeObj_destroy(php_shape->shape); } efree(object); } static zend_object_value mapscript_shape_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_shape_object *php_shape; MAPSCRIPT_ALLOC_OBJECT(php_shape, php_shape_object); retval = mapscript_object_new(&php_shape->std, ce, &mapscript_shape_object_destroy TSRMLS_CC); php_shape->is_ref = 0; MAPSCRIPT_INIT_PARENT(php_shape->parent); php_shape->bounds = NULL; php_shape->values = NULL; return retval; } PHP_MINIT_FUNCTION(shape) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("shapeObj", shape_functions, mapscript_ce_shape, mapscript_shape_object_new); mapscript_ce_shape->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/shapefile.c000066400000000000000000000401261357574274700204560ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_shapefile; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_shapefile_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(shapefile___construct_args, 0, 0, 2) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_getShape_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_getPoint_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_getExtent_args, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_addShape_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, shape, shapeObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_addPoint_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, point, pointObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(shapefile_getTransformed_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() /* {{{ proto shapefile __construct(string filename, int type) Create a new shapeFileObj instance. */ PHP_METHOD(shapeFileObj, __construct) { zval *zobj = getThis(); php_shapefile_object *php_shapefile; char *filename; long filename_len = 0; long type; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &filename, &filename_len, &type) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); php_shapefile->shapefile = shapefileObj_new(filename, type); if (php_shapefile->shapefile == NULL) { mapscript_throw_mapserver_exception("Failed to open shapefile %s" TSRMLS_CC, filename); return; } } /* }}} */ PHP_METHOD(shapeFileObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_shapefile_object *php_shapefile; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); IF_GET_LONG("numshapes", php_shapefile->shapefile->numshapes) else IF_GET_LONG("type", php_shapefile->shapefile->type) else IF_GET_LONG("isopen", php_shapefile->shapefile->isopen) else IF_GET_LONG("lastshape", php_shapefile->shapefile->lastshape) else IF_GET_STRING("source", php_shapefile->shapefile->source) else IF_GET_OBJECT("bounds", mapscript_ce_rect, php_shapefile->bounds, &php_shapefile->shapefile->bounds) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(shapeFileObj, __set) { char *property; long property_len = 0; zval *value; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); if ( (STRING_EQUAL("numshapes", property)) || (STRING_EQUAL("type", property)) || (STRING_EQUAL("source", property)) || (STRING_EQUAL("isopen", property)) || (STRING_EQUAL("lastshape", property)) || (STRING_EQUAL("bounds", property)) ) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int shapefile.getShape(int i) Retrieve shape by index. */ PHP_METHOD(shapeFileObj, getShape) { zval *zobj = getThis(); long index; shapeObj *shape; php_shapefile_object *php_shapefile; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); /* Create a new shapeObj to hold the result * Note that the type used to create the shape (MS_NULL) does not matter * at this point since it will be set by SHPReadShape(). */ if ((shape = shapeObj_new(MS_SHAPE_NULL)) == NULL) { mapscript_throw_mapserver_exception("Failed creating new shape (out of memory?)" TSRMLS_CC); return; } if (shapefileObj_get(php_shapefile->shapefile, index, shape) != MS_SUCCESS) { shapeObj_destroy(shape); mapscript_throw_mapserver_exception("Failed reading shape %ld." TSRMLS_CC, index); return; } MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shapefile.getPoint(int i) Retrieve a point by index. */ PHP_METHOD(shapeFileObj, getPoint) { zval *zobj = getThis(); long index; pointObj *point; php_shapefile_object *php_shapefile; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); /* Create a new shapeObj to hold the result * Note that the type used to create the shape (MS_NULL) does not matter * at this point since it will be set by SHPReadShape(). */ /* Create a new PointObj to hold the result */ if ((point = pointObj_new()) == NULL) { mapscript_throw_mapserver_exception("Failed creating new point (out of memory?)" TSRMLS_CC); return; } /* Read from the file */ if (shapefileObj_getPoint(php_shapefile->shapefile, index, point) != MS_SUCCESS) { pointObj_destroy(point); mapscript_throw_mapserver_exception("Failed reading point %ld." TSRMLS_CC, index); return; } MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_point(point, parent, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shapefile.getExtent(int i) Retrieve a shape's bounding box by index. */ PHP_METHOD(shapeFileObj, getExtent) { zval *zobj = getThis(); long index; rectObj *rect; php_shapefile_object *php_shapefile; parent_object p; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); /* Create a new rectObj to hold the result */ if ((rect = rectObj_new()) == NULL) { mapscript_throw_mapserver_exception("Failed creating new rectObj (out of memory?)" TSRMLS_CC); return; } /* Read from the file * shapefileObj_getExtent() has no return value! How do we catch errors? */ shapefileObj_getExtent(php_shapefile->shapefile, index, rect); /* Return rectObj */ MAPSCRIPT_INIT_PARENT(p); mapscript_create_rect(rect, p, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto int shapefile.addShape(shapeObj shape) Appends a shape to an open shapefile. */ PHP_METHOD(shapeFileObj, addShape) { zval *zobj = getThis(); zval *zshape; php_shapefile_object *php_shapefile; php_shape_object *php_shape; int retval = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zshape, mapscript_ce_shape) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); php_shape = MAPSCRIPT_OBJ_P(php_shape_object, zshape); retval = shapefileObj_add(php_shapefile->shapefile, php_shape->shape); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int shapefile.addPoint(pointObj point) Appends a point to a poin layer. */ PHP_METHOD(shapeFileObj, addPoint) { zval *zobj = getThis(); zval *zpoint; php_shapefile_object *php_shapefile; php_point_object *php_point; int retval = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpoint, mapscript_ce_point) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); php_point = MAPSCRIPT_OBJ_P(php_point_object, zpoint); retval = shapefileObj_addPoint(php_shapefile->shapefile, php_point->point); RETURN_LONG(retval); } /* }}} */ /* {{{ proto int shapefile.getTransformed(mapObj map, int index) Retrieve shape by index. */ PHP_METHOD(shapeFileObj, getTransformed) { zval *zobj = getThis(); zval *zmap; long index; php_shapefile_object *php_shapefile; php_map_object *php_map; shapeObj *shape = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &zmap, mapscript_ce_map, &index) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); /* Create a new shapeObj to hold the result * Note that the type used to create the shape (MS_NULL) does not matter * at this point since it will be set by SHPReadShape(). */ if ((shape = shapeObj_new(MS_SHAPE_NULL)) == NULL) { mapscript_throw_mapserver_exception("Failed creating new shape (out of memory?)" TSRMLS_CC); return; } /* Read from the file */ if (shapefileObj_getTransformed(php_shapefile->shapefile, php_map->map, index, shape) != MS_SUCCESS) { shapeObj_destroy(shape); mapscript_throw_mapserver_exception("Failed reading shape %ld." TSRMLS_CC, index); return; } /* Return shape object */ MAPSCRIPT_MAKE_PARENT(NULL, NULL); mapscript_create_shape(shape, parent, NULL, return_value TSRMLS_CC); } /* }}} */ /* {{{ proto void shapefile.free() Free the object */ PHP_METHOD(shapeFileObj, free) { zval *zobj = getThis(); php_shapefile_object *php_shapefile; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, zobj); MAPSCRIPT_DELREF(php_shapefile->bounds); } /* }}} */ zend_function_entry shapefile_functions[] = { PHP_ME(shapeFileObj, __construct, shapefile___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(shapeFileObj, __get, shapefile___get_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, __set, shapefile___set_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, getShape, shapefile_getShape_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, getPoint, shapefile_getPoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, getExtent, shapefile_getExtent_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, addShape, shapefile_addShape_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, addPoint, shapefile_addPoint_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, getTransformed, shapefile_getTransformed_args, ZEND_ACC_PUBLIC) PHP_ME(shapeFileObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_shapefile(shapefileObj *shapefile, zval *return_value TSRMLS_DC) { php_shapefile_object * php_shapefile; object_init_ex(return_value, mapscript_ce_shapefile); php_shapefile = MAPSCRIPT_OBJ_P(php_shapefile_object, return_value); php_shapefile->shapefile = shapefile; } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_shapefile_create_object(zend_class_entry *ce TSRMLS_DC) { php_shapefile_object *php_shapefile; php_shapefile = ecalloc(1, sizeof(*php_shapefile) + zend_object_properties_size(ce)); zend_object_std_init(&php_shapefile->zobj, ce TSRMLS_CC); object_properties_init(&php_shapefile->zobj, ce); php_shapefile->zobj.handlers = &mapscript_shapefile_object_handlers; ZVAL_UNDEF(&php_shapefile->bounds); return &php_shapefile->zobj; } static void mapscript_shapefile_free_object(zend_object *object) { php_shapefile_object *php_shapefile; php_shapefile = (php_shapefile_object *)((char *)object - XtOffsetOf(php_shapefile_object, zobj)); MAPSCRIPT_DELREF(php_shapefile->bounds); shapefileObj_destroy(php_shapefile->shapefile); zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(shapefile) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "shapefileObj", shapefile_functions); mapscript_ce_shapefile = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_shapefile->create_object = mapscript_shapefile_create_object; mapscript_ce_shapefile->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_shapefile_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_shapefile_object_handlers)); mapscript_shapefile_object_handlers.free_obj = mapscript_shapefile_free_object; mapscript_shapefile_object_handlers.offset = XtOffsetOf(php_shapefile_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_shapefile_object_destroy(void *object TSRMLS_DC) { php_shapefile_object *php_shapefile = (php_shapefile_object *)object; MAPSCRIPT_FREE_OBJECT(php_shapefile); MAPSCRIPT_DELREF(php_shapefile->bounds); shapefileObj_destroy(php_shapefile->shapefile); efree(object); } static zend_object_value mapscript_shapefile_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_shapefile_object *php_shapefile; MAPSCRIPT_ALLOC_OBJECT(php_shapefile, php_shapefile_object); retval = mapscript_object_new(&php_shapefile->std, ce, &mapscript_shapefile_object_destroy TSRMLS_CC); php_shapefile->bounds = NULL; return retval; } PHP_MINIT_FUNCTION(shapefile) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("shapeFileObj", shapefile_functions, mapscript_ce_shapefile, mapscript_shapefile_object_new); mapscript_ce_shapefile->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/style.c000066400000000000000000001000731357574274700176540ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_style; zend_object_handlers mapscript_style_object_handlers; ZEND_BEGIN_ARG_INFO_EX(style___construct_args, 0, 0, 1) ZEND_ARG_INFO(0, parent) ZEND_ARG_OBJ_INFO(0, style, styleObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_setBinding_args, 0, 0, 2) ZEND_ARG_INFO(0, styleBinding) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_getBinding_args, 0, 0, 1) ZEND_ARG_INFO(0, styleBinding) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_removeBinding_args, 0, 0, 1) ZEND_ARG_INFO(0, styleBinding) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_setGeomTransform_args, 0, 0, 1) ZEND_ARG_INFO(0, transform) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(style_setPattern_args, 0, 0, 1) ZEND_ARG_INFO(0, pattern) ZEND_END_ARG_INFO() /* {{{ proto void __construct(parent [, styleObj style]) Create a new styleObj instance. parent has to be a classObj or labelObj. */ PHP_METHOD(styleObj, __construct) { zval *zobj = getThis(); zval *zparent, *zstyle = NULL; styleObj *style; php_class_object *php_class = NULL; php_label_object *php_label = NULL; php_style_object *php_style, *php_style2 = NULL; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|O", &zparent, &zstyle, mapscript_ce_style) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); if (Z_TYPE_P(zparent) == IS_OBJECT && Z_OBJCE_P(zparent) == mapscript_ce_class) php_class = MAPSCRIPT_OBJ_P(php_class_object, zparent); else if (Z_TYPE_P(zparent) == IS_OBJECT && Z_OBJCE_P(zparent) == mapscript_ce_label) php_label = MAPSCRIPT_OBJ_P(php_label_object, zparent); else { mapscript_throw_mapserver_exception("Invalid argument 1: should be a classObj or labelObj" TSRMLS_CC); return; } if (zstyle) php_style2 = MAPSCRIPT_OBJ_P(php_style_object, zstyle); if (php_class) { if ((style = styleObj_new(php_class->class, (zstyle ? php_style2->style : NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } } else { if ((style = styleObj_label_new(php_label->label, (zstyle ? php_style2->style : NULL))) == NULL) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } } php_style->style = style; MAPSCRIPT_MAKE_PARENT(zparent, NULL); php_style->parent = parent; MAPSCRIPT_ADDREF_P(zparent); } /* }}} */ PHP_METHOD(styleObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); IF_GET_LONG("symbol", php_style->style->symbol) else IF_GET_STRING("symbolname", php_style->style->symbolname) else IF_GET_DOUBLE("size", php_style->style->size) else IF_GET_DOUBLE("minsize", php_style->style->minsize) else IF_GET_DOUBLE("maxsize", php_style->style->maxsize) else IF_GET_DOUBLE("width", php_style->style->width) else IF_GET_DOUBLE("outlinewidth", php_style->style->outlinewidth) else IF_GET_DOUBLE("minwidth", php_style->style->minwidth) else IF_GET_DOUBLE("maxwidth", php_style->style->maxwidth) else IF_GET_LONG("offsetx", php_style->style->offsetx) else IF_GET_LONG("offsety", php_style->style->offsety) else IF_GET_LONG("polaroffsetpixel", php_style->style->polaroffsetpixel) else IF_GET_LONG("polaroffsetangle", php_style->style->polaroffsetangle) else IF_GET_DOUBLE("angle", php_style->style->angle) else IF_GET_DOUBLE("minvalue", php_style->style->minvalue) else IF_GET_DOUBLE("maxvalue", php_style->style->maxvalue) else IF_GET_STRING("rangeitem", php_style->style->rangeitem) else IF_GET_LONG("rangeitemindex", php_style->style->rangeitemindex) else IF_GET_DOUBLE("gap", php_style->style->gap) else IF_GET_DOUBLE("initialgap", php_style->style->initialgap) else IF_GET_DOUBLE("maxscaledenom", php_style->style->maxscaledenom) else IF_GET_DOUBLE("minscaledenom", php_style->style->minscaledenom) else IF_GET_LONG("patternlength", php_style->style->patternlength) else IF_GET_LONG("position", php_style->style->position) else IF_GET_LONG("linecap", php_style->style->linecap) else IF_GET_LONG("linejoin", php_style->style->linejoin) else IF_GET_LONG("linejoinmaxsize", php_style->style->linejoinmaxsize) else IF_GET_DOUBLE("angle", php_style->style->angle) else IF_GET_LONG("autoangle", php_style->style->autoangle) else IF_GET_LONG("opacity", php_style->style->opacity) else IF_GET_OBJECT("color", mapscript_ce_color, php_style->color, &php_style->style->color) else IF_GET_OBJECT("outlinecolor", mapscript_ce_color, php_style->outlinecolor, &php_style->style->outlinecolor) else IF_GET_OBJECT("backgroundcolor", mapscript_ce_color, php_style->backgroundcolor, &php_style->style->backgroundcolor) else IF_GET_OBJECT("mincolor", mapscript_ce_color, php_style->mincolor, &php_style->style->mincolor) else IF_GET_OBJECT("maxcolor", mapscript_ce_color, php_style->maxcolor, &php_style->style->maxcolor) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(styleObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_style_object *php_style; php_map_object *php_map = NULL; php_class_object *php_class; php_layer_object *php_layer; #ifdef disabled php_labelcachemember_object *php_labelcachemember; #endif PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); IF_SET_LONG("symbol", php_style->style->symbol, value) else IF_SET_DOUBLE("size", php_style->style->size, value) else IF_SET_DOUBLE("minsize", php_style->style->minsize, value) else IF_SET_DOUBLE("maxsize", php_style->style->maxsize, value) else IF_SET_DOUBLE("width", php_style->style->width, value) else IF_SET_DOUBLE("outlinewidth", php_style->style->outlinewidth, value) else IF_SET_DOUBLE("minwidth", php_style->style->minwidth, value) else IF_SET_DOUBLE("maxwidth", php_style->style->maxwidth, value) else IF_SET_LONG("offsetx", php_style->style->offsetx, value) else IF_SET_LONG("offsety", php_style->style->offsety, value) else IF_SET_LONG("polaroffsetpixel", php_style->style->polaroffsetpixel, value) else IF_SET_LONG("polaroffsetangle", php_style->style->polaroffsetangle, value) else IF_SET_DOUBLE("angle", php_style->style->angle, value) else IF_SET_DOUBLE("minvalue", php_style->style->minvalue, value) else IF_SET_DOUBLE("maxvalue", php_style->style->maxvalue, value) else IF_SET_DOUBLE("minscaledenom", php_style->style->minscaledenom, value) else IF_SET_DOUBLE("maxscaledenom", php_style->style->maxscaledenom, value) else IF_SET_STRING("rangeitem", php_style->style->rangeitem, value) else IF_SET_LONG("rangeitemindex", php_style->style->rangeitemindex, value) else IF_SET_DOUBLE("gap", php_style->style->gap, value) else IF_SET_DOUBLE("initialgap", php_style->style->initialgap, value) else IF_SET_LONG("position", php_style->style->position, value) else IF_SET_LONG("linecap", php_style->style->linecap, value) else IF_SET_LONG("linejoin", php_style->style->linejoin, value) else IF_SET_LONG("linejoinmaxsize", php_style->style->linejoinmaxsize, value) else IF_SET_DOUBLE("angle", php_style->style->angle, value) else IF_SET_LONG("autoangle", php_style->style->autoangle, value) else if (STRING_EQUAL("opacity", property)) { int alpha; convert_to_long(value); php_style->style->opacity = Z_LVAL_P(value); /* apply opacity as the alpha channel color(s) */ if(php_style->style->opacity < 100) alpha = MS_NINT(php_style->style->opacity*2.55); else alpha = 255; php_style->style->color.alpha = alpha; php_style->style->outlinecolor.alpha = alpha; php_style->style->backgroundcolor.alpha = alpha; php_style->style->mincolor.alpha = alpha; php_style->style->maxcolor.alpha = alpha; } else if (STRING_EQUAL("symbolname", property)) { convert_to_string(value); if (php_style->style->symbolname) free(php_style->style->symbolname); if (Z_STRVAL_P(value)) php_style->style->symbolname = msStrdup(Z_STRVAL_P(value)); /* The parent can be a classObj or a labelCacheMemberObj */ if (MAPSCRIPT_OBJCE(php_style->parent.val) == mapscript_ce_class) { php_class = MAPSCRIPT_OBJ(php_class_object, php_style->parent.val); /* Can a class have no layer object ? */ php_layer = MAPSCRIPT_OBJ(php_layer_object, php_class->parent.val); if (ZVAL_IS_UNDEF(php_layer->parent.val)) { mapscript_throw_exception("No map object associated with this style object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_layer->parent.val); #ifdef disabled } else if (MAPSCRIPT_OBJCE(php_style->parent.val) == mapscript_ce_labelcachemember) { /* The parent is always a map */ php_labelcachemember = MAPSCRIPT_OBJ(php_labelcachemember_object, php_style->parent.val); if (ZVAL_NOT_UNDEF(php_labelcachemember->parent.val)) { mapscript_throw_exception("No map object associated with this style object." TSRMLS_CC); return; } php_map = MAPSCRIPT_OBJ(php_map_object, php_labelcachemember->parent.val); #endif } if (styleObj_setSymbolByName(php_style->style, php_map->map, php_style->style->symbolname) == -1) { mapscript_throw_exception("Symbol not found." TSRMLS_CC); return; } } else if ( (STRING_EQUAL("color", property)) || (STRING_EQUAL("outlinecolor", property)) || (STRING_EQUAL("backgroundcolor", property)) || (STRING_EQUAL("maxcolor", property)) || (STRING_EQUAL("mincolor", property))) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else if ( (STRING_EQUAL("patternlength", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int style.updateFromString(string snippet) Update a style from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(styleObj, updateFromString) { zval *zobj = getThis(); char *snippet; long snippet_len = 0; int status = MS_FAILURE; MAPSCRIPT_ZVAL retval; zval property_name, value; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); if ((status = styleObj_updateFromString(php_style->style, snippet)) != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } /* verify the symbol if needed */ if (php_style->style->symbolname) { INIT_ZVAL(property_name); INIT_ZVAL(value); MAPSCRIPT_ZVAL_STRING(&property_name, "symbolname", 1); MAPSCRIPT_ZVAL_STRING(&value, php_style->style->symbolname, 1); MAPSCRIPT_CALL_METHOD_2_P(zobj, "__set", retval, &property_name, &value); } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the style object to string. */ PHP_METHOD(styleObj, convertToString) { zval *zobj = getThis(); php_style_object *php_style; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); value = styleObj_convertToString(php_style->style); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int style.setbinding(const bindingid, string value) Set the attribute binding for a specfiled style property. Returns MS_SUCCESS on success. */ PHP_METHOD(styleObj, setBinding) { zval *zobj = getThis(); char *value; long value_len = 0; long bindingId; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &bindingId, &value, &value_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); if (bindingId < 0 || bindingId > MS_STYLE_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if (!value || strlen(value) <= 0) { mapscript_throw_exception("Invalid binding value." TSRMLS_CC); return; } if(php_style->style->bindings[bindingId].item) { msFree(php_style->style->bindings[bindingId].item); php_style->style->bindings[bindingId].index = -1; php_style->style->numbindings--; } php_style->style->bindings[bindingId].item = msStrdup(value); php_style->style->numbindings++; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int style.getbinding(const bindingid) Get the value of a attribute binding for a specfiled style property. Returns the string value if exist, else null. */ PHP_METHOD(styleObj, getBinding) { zval *zobj = getThis(); long bindingId; char *value = NULL; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bindingId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); if (bindingId < 0 || bindingId > MS_STYLE_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if( (value = php_style->style->bindings[bindingId].item) != NULL) { MAPSCRIPT_RETURN_STRING(value, 1); } RETURN_NULL(); } /* }}} */ /* {{{ proto int style.removebinding(const bindingid) Remove attribute binding for a specfiled style property. Returns MS_SUCCESS on success. */ PHP_METHOD(styleObj, removeBinding) { zval *zobj = getThis(); long bindingId; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bindingId) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); if (bindingId < 0 || bindingId > MS_STYLE_BINDING_LENGTH) { mapscript_throw_exception("Invalid binding id." TSRMLS_CC); return; } if(php_style->style->bindings[bindingId].item) { msFree(php_style->style->bindings[bindingId].item); php_style->style->bindings[bindingId].item = NULL; php_style->style->bindings[bindingId].index = -1; php_style->style->numbindings--; } RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int style.free() Free the object */ PHP_METHOD(styleObj, free) { zval *zobj = getThis(); php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); MAPSCRIPT_DELREF(php_style->color); MAPSCRIPT_DELREF(php_style->outlinecolor); MAPSCRIPT_DELREF(php_style->backgroundcolor); } /* }}} */ /* {{{ proto int style.getGeomTransform() return the geometry transform expression */ PHP_METHOD(styleObj, getGeomTransform) { zval *zobj = getThis(); php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); if (php_style->style->_geomtransform.type == MS_GEOMTRANSFORM_NONE || !php_style->style->_geomtransform.string) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETURN_STRING(php_style->style->_geomtransform.string, 1); } /* }}} */ /* {{{ proto int style.setGeomTransform() set the geometry transform expression */ PHP_METHOD(styleObj, setGeomTransform) { zval *zobj = getThis(); char *transform; long transform_len = 0; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &transform, &transform_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); styleObj_setGeomTransform(php_style->style, transform); } /* }}} */ /* {{{ proto int style.setpattern(array points) Set the pattern of the style ) */ PHP_METHOD(styleObj, setPattern) { zval *zpattern; MAPSCRIPT_ZVAL_P ppzval; HashTable *pattern_hash = NULL; zval *zobj = getThis(); int index = 0, numelements = 0; php_style_object *php_style; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &zpattern) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); pattern_hash = Z_ARRVAL_P(zpattern); numelements = zend_hash_num_elements(pattern_hash); if (numelements == 0) { mapscript_report_php_error(E_WARNING, "style->setpoints : invalid array of %d element(s) as parameter." TSRMLS_CC, numelements); RETURN_LONG(MS_FAILURE); } for(zend_hash_internal_pointer_reset(pattern_hash); zend_hash_has_more_elements(pattern_hash) == SUCCESS; zend_hash_move_forward(pattern_hash)) { #if PHP_VERSION_ID < 70000 zend_hash_get_current_data(pattern_hash, (void **)&ppzval); if (Z_TYPE_PP(ppzval) != IS_LONG) convert_to_long(*ppzval); #else ppzval = zend_hash_get_current_data(pattern_hash); if (Z_TYPE_P(ppzval) != IS_DOUBLE) convert_to_double(ppzval); #endif php_style->style->pattern[index] = Z_LVAL_PP(ppzval); index++; } php_style->style->patternlength = numelements; RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int style.getPatternArray() Returns an array containing the pattern.*/ PHP_METHOD(styleObj, getPatternArray) { zval *zobj = getThis(); php_style_object *php_style; int index; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_style = MAPSCRIPT_OBJ_P(php_style_object, zobj); array_init(return_value); if (php_style->style->patternlength > 0) { for (index=0; index < php_style->style->patternlength; index++) { add_next_index_long(return_value, php_style->style->pattern[index]); } } } /* }}} */ zend_function_entry style_functions[] = { PHP_ME(styleObj, __construct, style___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(styleObj, __get, style___get_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, __set, style___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(styleObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(styleObj, updateFromString, style_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(styleObj, setBinding, style_setBinding_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, getBinding, style_getBinding_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, removeBinding, style_removeBinding_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, getGeomTransform, NULL, ZEND_ACC_PUBLIC) PHP_ME(styleObj, setGeomTransform, style_setGeomTransform_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, setPattern, style_setPattern_args, ZEND_ACC_PUBLIC) PHP_ME(styleObj, getPatternArray, NULL, ZEND_ACC_PUBLIC) PHP_ME(styleObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_style(styleObj *style, parent_object parent, zval *return_value TSRMLS_DC) { php_style_object * php_style; object_init_ex(return_value, mapscript_ce_style); php_style = MAPSCRIPT_OBJ_P(php_style_object, return_value); php_style->style = style; php_style->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_style_create_object(zend_class_entry *ce TSRMLS_DC) { php_style_object *php_style; php_style = ecalloc(1, sizeof(*php_style) + zend_object_properties_size(ce)); zend_object_std_init(&php_style->zobj, ce TSRMLS_CC); object_properties_init(&php_style->zobj, ce); php_style->zobj.handlers = &mapscript_style_object_handlers; MAPSCRIPT_INIT_PARENT(php_style->parent); ZVAL_UNDEF(&php_style->color); ZVAL_UNDEF(&php_style->outlinecolor); ZVAL_UNDEF(&php_style->backgroundcolor); return &php_style->zobj; } static void mapscript_style_free_object(zend_object *object) { php_style_object *php_style; php_style = (php_style_object *)((char *)object - XtOffsetOf(php_style_object, zobj)); MAPSCRIPT_FREE_PARENT(php_style->parent); MAPSCRIPT_DELREF(php_style->color); MAPSCRIPT_DELREF(php_style->outlinecolor); MAPSCRIPT_DELREF(php_style->backgroundcolor); /* We don't need to free the styleObj, the mapObj will do it */ zend_object_std_dtor(object); } static zend_object* mapscript_style_clone_object(zval *zobj) { php_style_object *php_style_old, *php_style_new; zend_object* zobj_new; php_style_old = MAPSCRIPT_OBJ_P(php_style_object, zobj); zobj_new = mapscript_style_create_object(mapscript_ce_style); php_style_new = (php_style_object *)((char *)zobj_new - XtOffsetOf(php_style_object, zobj)); zend_objects_clone_members(&php_style_new->zobj, &php_style_old->zobj); php_style_new->style = styleObj_clone(php_style_old->style); return zobj_new; } PHP_MINIT_FUNCTION(style) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "styleObj", style_functions); mapscript_ce_style = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_style->create_object = mapscript_style_create_object; mapscript_ce_style->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_style_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_style_object_handlers)); mapscript_style_object_handlers.free_obj = mapscript_style_free_object; mapscript_style_object_handlers.clone_obj = mapscript_style_clone_object; mapscript_style_object_handlers.offset = XtOffsetOf(php_style_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_style_object_destroy(void *object TSRMLS_DC) { php_style_object *php_style = (php_style_object *)object; MAPSCRIPT_FREE_OBJECT(php_style); MAPSCRIPT_FREE_PARENT(php_style->parent); MAPSCRIPT_DELREF(php_style->color); MAPSCRIPT_DELREF(php_style->outlinecolor); MAPSCRIPT_DELREF(php_style->backgroundcolor); /* We don't need to free the styleObj, the mapObj will do it */ efree(object); } static zend_object_value mapscript_style_object_new_ex(zend_class_entry *ce, php_style_object **ptr TSRMLS_DC) { zend_object_value retval; php_style_object *php_style; MAPSCRIPT_ALLOC_OBJECT(php_style, php_style_object); retval = mapscript_object_new_ex(&php_style->std, ce, &mapscript_style_object_destroy, &mapscript_style_object_handlers TSRMLS_CC); if (ptr) *ptr = php_style; MAPSCRIPT_INIT_PARENT(php_style->parent); php_style->color = NULL; php_style->outlinecolor = NULL; php_style->backgroundcolor = NULL; return retval; } static zend_object_value mapscript_style_object_new(zend_class_entry *ce TSRMLS_DC) { return mapscript_style_object_new_ex(ce, NULL TSRMLS_CC); } static zend_object_value mapscript_style_object_clone(zval *zobj TSRMLS_DC) { php_style_object *php_style_old, *php_style_new; zend_object_value new_ov; php_style_old = MAPSCRIPT_OBJ_P(php_style_object, zobj); new_ov = mapscript_style_object_new_ex(mapscript_ce_style, &php_style_new TSRMLS_CC); zend_objects_clone_members(&php_style_new->std, new_ov, &php_style_old->std, Z_OBJ_HANDLE_P(zobj) TSRMLS_CC); php_style_new->style = styleObj_clone(php_style_old->style); return new_ov; } PHP_MINIT_FUNCTION(style) { zend_class_entry ce; memcpy(&mapscript_style_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); mapscript_style_object_handlers.clone_obj = mapscript_style_object_clone; MAPSCRIPT_REGISTER_CLASS("styleObj", style_functions, mapscript_ce_style, mapscript_style_object_new); mapscript_ce_style->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/symbol.c000066400000000000000000000414451357574274700200300ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_symbol; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_symbol_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(symbol___construct_args, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, map, mapObj, 0) ZEND_ARG_INFO(0, symbolName) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol_setPoints_args, 0, 0, 1) ZEND_ARG_INFO(0, points) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol_setImagePath_args, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol_setImage_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, image, imageObj, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(symbol_getImage_args, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, outputformat, outputFormatObj, 0) ZEND_END_ARG_INFO() /* {{{ proto void __construct(mapObj map, string symbolname) Create a new symbolObj instance. */ PHP_METHOD(symbolObj, __construct) { zval *zmap; char *symbolName; long symbolName_len = 0; int symbolId = -1; php_symbol_object *php_symbol; php_map_object *php_map; parent_object parent; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &zmap, mapscript_ce_map, &symbolName, &symbolName_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, getThis()); php_map = MAPSCRIPT_OBJ_P(php_map_object, zmap); symbolId = msAddNewSymbol(php_map->map, symbolName); if (symbolId == -1) { mapscript_throw_mapserver_exception("Unable to construct symbolObj" TSRMLS_CC); return; } php_symbol->symbol = php_map->map->symbolset.symbol[symbolId]; MAPSCRIPT_MAKE_PARENT(zmap, NULL); php_symbol->parent = parent; MAPSCRIPT_ADDREF_P(zmap); } /* }}} */ PHP_METHOD(symbolObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_symbol_object *php_symbol; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, zobj); IF_GET_STRING("name", php_symbol->symbol->name) else IF_GET_LONG("type", php_symbol->symbol->type) else IF_GET_LONG("inmapfile", php_symbol->symbol->inmapfile) else IF_GET_DOUBLE("sizex", php_symbol->symbol->sizex) else IF_GET_DOUBLE("sizey", php_symbol->symbol->sizey) else IF_GET_LONG("numpoints", php_symbol->symbol->numpoints) else IF_GET_LONG("filled", php_symbol->symbol->filled) else IF_GET_STRING("imagepath", php_symbol->symbol->imagepath) else IF_GET_LONG("transparent", php_symbol->symbol->transparent) else IF_GET_LONG("transparentcolor", php_symbol->symbol->transparentcolor) else IF_GET_STRING("character", php_symbol->symbol->character) else IF_GET_DOUBLE("anchorpoint_y", php_symbol->symbol->anchorpoint_y) else IF_GET_DOUBLE("anchorpoint_x", php_symbol->symbol->anchorpoint_x) else IF_GET_DOUBLE("maxx", php_symbol->symbol->maxx) else IF_GET_DOUBLE("minx", php_symbol->symbol->minx) else IF_GET_DOUBLE("miny", php_symbol->symbol->miny) else IF_GET_DOUBLE("maxy", php_symbol->symbol->maxy) else IF_GET_STRING("font", php_symbol->symbol->font) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(symbolObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_symbol_object *php_symbol; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, zobj); IF_SET_STRING("name", php_symbol->symbol->name, value) else IF_SET_LONG("type", php_symbol->symbol->type, value) else IF_SET_LONG("inmapfile", php_symbol->symbol->inmapfile, value) else IF_SET_DOUBLE("sizex", php_symbol->symbol->sizex, value) else IF_SET_DOUBLE("sizey", php_symbol->symbol->sizey, value) else IF_SET_LONG("filled", php_symbol->symbol->filled, value) else IF_SET_LONG("transparent", php_symbol->symbol->transparent, value) else IF_SET_LONG("transparentcolor", php_symbol->symbol->transparentcolor, value) else IF_SET_STRING("character", php_symbol->symbol->character, value) else IF_SET_STRING("font", php_symbol->symbol->font, value) else IF_SET_DOUBLE("anchorpoint_y", php_symbol->symbol->anchorpoint_y, value) else IF_SET_DOUBLE("anchorpoint_x", php_symbol->symbol->anchorpoint_x, value) else IF_SET_DOUBLE("maxx", php_symbol->symbol->maxx, value) else IF_SET_DOUBLE("maxy", php_symbol->symbol->maxy, value) else IF_SET_DOUBLE("minx", php_symbol->symbol->minx, value) else IF_SET_DOUBLE("miny", php_symbol->symbol->miny, value) else if ( (STRING_EQUAL("numpoints", property)) || (STRING_EQUAL("imagepath", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int symbol.setpoints(array points) Set the points of the symbol ) */ PHP_METHOD(symbolObj, setPoints) { zval *zpoints; MAPSCRIPT_ZVAL_P ppzval; HashTable *points_hash = NULL; zval *zobj = getThis(); int index = 0, flag = 0, numelements = 0; php_symbol_object *php_symbol; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &zpoints) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, zobj); points_hash = Z_ARRVAL_P(zpoints); numelements = zend_hash_num_elements(points_hash); if ((numelements == 0) || (numelements % 2 != 0)) { mapscript_report_php_error(E_WARNING, "symbol->setpoints : invalid array of %d element(s) as parameter." TSRMLS_CC, numelements); RETURN_LONG(MS_FAILURE); } for(zend_hash_internal_pointer_reset(points_hash); zend_hash_has_more_elements(points_hash) == SUCCESS; zend_hash_move_forward(points_hash)) { #if PHP_VERSION_ID < 70000 zend_hash_get_current_data(points_hash, (void **)&ppzval); if (Z_TYPE_PP(ppzval) != IS_DOUBLE) convert_to_double(*ppzval); #else ppzval = zend_hash_get_current_data(points_hash); if (Z_TYPE_P(ppzval) != IS_DOUBLE) convert_to_double(ppzval); #endif if (!flag) { php_symbol->symbol->points[index].x = Z_DVAL_PP(ppzval); php_symbol->symbol->sizex = MS_MAX(php_symbol->symbol->sizex, php_symbol->symbol->points[index].x); } else { php_symbol->symbol->points[index].y = Z_DVAL_PP(ppzval); php_symbol->symbol->sizey = MS_MAX(php_symbol->symbol->sizey, php_symbol->symbol->points[index].y); index++; } flag = !flag; } php_symbol->symbol->numpoints = (numelements/2); RETURN_LONG(MS_SUCCESS); } /* }}} */ /* {{{ proto int symbol.getPointsArray() Returns an array containing the points of the symbol. Refer to setpoints to see how the array should be interpreted. */ PHP_METHOD(symbolObj, getPointsArray) { zval *zobj = getThis(); php_symbol_object *php_symbol; int index; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, zobj); array_init(return_value); if (php_symbol->symbol->numpoints > 0) { for (index=0; index < php_symbol->symbol->numpoints; index++) { add_next_index_double(return_value, php_symbol->symbol->points[index].x); add_next_index_double(return_value, php_symbol->symbol->points[index].y); } } } /* }}} */ /* {{{ proto int symbol.setimagepath(char *imagefile) loads a new symbol image ) */ PHP_METHOD(symbolObj, setImagePath) { zval *zobj = getThis(); php_symbol_object *php_symbol; char *filename; long filename_len = 0; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, zobj); status = msLoadImageSymbol(php_symbol->symbol, filename); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto int setImage(imageObj image) Set image pixmap symbol */ PHP_METHOD(symbolObj, setImage) { zval *zimage; php_symbol_object *php_symbol; php_image_object *php_image; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zimage, mapscript_ce_image) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, getThis()); php_image = MAPSCRIPT_OBJ_P(php_image_object, zimage); RETURN_LONG(symbolObj_setImage(php_symbol->symbol, php_image->image)); } /* }}} */ /* {{{ proto imageObj getImage(outputFormatObj outputformat) Get the symbol image */ PHP_METHOD(symbolObj, getImage) { zval *zoutputformat; imageObj *image = NULL; php_map_object *php_map; php_symbol_object *php_symbol; php_outputformat_object *php_outputformat; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zoutputformat, mapscript_ce_outputformat) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, getThis()); php_map = MAPSCRIPT_OBJ(php_map_object, php_symbol->parent.val); php_outputformat = MAPSCRIPT_OBJ_P(php_outputformat_object, zoutputformat); image = symbolObj_getImage(php_symbol->symbol, php_outputformat->outputformat); if (image == NULL) { mapscript_throw_exception("Unable to get the symbol image" TSRMLS_CC); return; } /* the outputformat HAS to be added to the map, since the renderer is now used by the current symbol */ if (msGetOutputFormatIndex(php_map->map, php_outputformat->outputformat->name) == -1) msAppendOutputFormat(php_map->map, php_outputformat->outputformat); mapscript_create_image(image, return_value TSRMLS_CC); } /* }}} */ zend_function_entry symbol_functions[] = { PHP_ME(symbolObj, __construct, symbol___construct_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(symbolObj, __get, symbol___get_args, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, __set, symbol___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(symbolObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, setPoints, symbol_setPoints_args, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, getPointsArray, NULL, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, setImage, symbol_setImage_args, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, getImage, symbol_getImage_args, ZEND_ACC_PUBLIC) PHP_ME(symbolObj, setImagePath, symbol_setImagePath_args, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_symbol(symbolObj *symbol, parent_object parent, zval *return_value TSRMLS_DC) { php_symbol_object * php_symbol; object_init_ex(return_value, mapscript_ce_symbol); php_symbol = MAPSCRIPT_OBJ_P(php_symbol_object, return_value); php_symbol->symbol = symbol; php_symbol->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_symbol_create_object(zend_class_entry *ce TSRMLS_DC) { php_symbol_object *php_symbol; php_symbol = ecalloc(1, sizeof(*php_symbol) + zend_object_properties_size(ce)); zend_object_std_init(&php_symbol->zobj, ce TSRMLS_CC); object_properties_init(&php_symbol->zobj, ce); php_symbol->zobj.handlers = &mapscript_symbol_object_handlers; MAPSCRIPT_INIT_PARENT(php_symbol->parent); return &php_symbol->zobj; } static void mapscript_symbol_free_object(zend_object *object) { php_symbol_object *php_symbol; php_symbol = (php_symbol_object *)((char *)object - XtOffsetOf(php_symbol_object, zobj)); MAPSCRIPT_FREE_PARENT(php_symbol->parent); /* We don't need to free the symbolObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(symbol) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "symbolObj", symbol_functions); mapscript_ce_symbol = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_symbol->create_object = mapscript_symbol_create_object; mapscript_ce_symbol->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_symbol_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_symbol_object_handlers)); mapscript_symbol_object_handlers.free_obj = mapscript_symbol_free_object; mapscript_symbol_object_handlers.offset = XtOffsetOf(php_symbol_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_symbol_object_destroy(void *object TSRMLS_DC) { php_symbol_object *php_symbol = (php_symbol_object *)object; MAPSCRIPT_FREE_OBJECT(php_symbol); MAPSCRIPT_FREE_PARENT(php_symbol->parent); /* We don't need to free the symbolObj */ efree(object); } static zend_object_value mapscript_symbol_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_symbol_object *php_symbol; MAPSCRIPT_ALLOC_OBJECT(php_symbol, php_symbol_object); retval = mapscript_object_new(&php_symbol->std, ce, &mapscript_symbol_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_symbol->parent); return retval; } PHP_MINIT_FUNCTION(symbol) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("symbolObj", symbol_functions, mapscript_ce_symbol, mapscript_symbol_object_new); mapscript_ce_symbol->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/php/web.c000066400000000000000000000302421357574274700172710ustar00rootroot00000000000000/********************************************************************** * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $ * * Project: MapServer * Purpose: PHP/MapScript extension for MapServer. External interface * functions * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca) * Alan Boudreault, Mapgears * ********************************************************************** * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "php_mapscript.h" zend_class_entry *mapscript_ce_web; #if PHP_VERSION_ID >= 70000 zend_object_handlers mapscript_web_object_handlers; #endif ZEND_BEGIN_ARG_INFO_EX(web___get_args, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(web___set_args, 0, 0, 2) ZEND_ARG_INFO(0, property) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(web_updateFromString_args, 0, 0, 1) ZEND_ARG_INFO(0, snippet) ZEND_END_ARG_INFO() /* {{{ proto web __construct() webObj CANNOT be instanciated, this will throw an exception on use */ PHP_METHOD(webObj, __construct) { mapscript_throw_exception("webObj cannot be constructed" TSRMLS_CC); } /* }}} */ PHP_METHOD(webObj, __get) { char *property; long property_len = 0; zval *zobj = getThis(); php_web_object *php_web; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &property, &property_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = MAPSCRIPT_OBJ_P(php_web_object, zobj); IF_GET_STRING("log", php_web->web->log) else IF_GET_STRING("imagepath", php_web->web->imagepath) else IF_GET_STRING("template", php_web->web->template) else IF_GET_STRING("imageurl", php_web->web->imageurl) else IF_GET_STRING("temppath", php_web->web->temppath) else IF_GET_STRING("header", php_web->web->header) else IF_GET_STRING("footer", php_web->web->footer) else IF_GET_STRING("empty", php_web->web->empty) else IF_GET_STRING("error", php_web->web->error) else IF_GET_STRING("mintemplate", php_web->web->mintemplate) else IF_GET_STRING("maxtemplate", php_web->web->maxtemplate) else IF_GET_DOUBLE("minscaledenom", php_web->web->minscaledenom) else IF_GET_DOUBLE("maxscaledenom", php_web->web->maxscaledenom) else IF_GET_STRING("queryformat", php_web->web->queryformat) else IF_GET_STRING("legendformat", php_web->web->legendformat) else IF_GET_STRING("browseformat", php_web->web->browseformat) else IF_GET_OBJECT("extent", mapscript_ce_rect, php_web->extent, &php_web->web->extent) else IF_GET_OBJECT("metadata", mapscript_ce_hashtable, php_web->metadata, &php_web->web->metadata) else IF_GET_OBJECT("validation", mapscript_ce_hashtable, php_web->validation, &php_web->web->validation) else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } PHP_METHOD(webObj, __set) { char *property; long property_len = 0; zval *value; zval *zobj = getThis(); php_web_object *php_web; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &property, &property_len, &value) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = MAPSCRIPT_OBJ_P(php_web_object, zobj); IF_SET_STRING("log", php_web->web->log, value) else IF_SET_STRING("imagepath", php_web->web->imagepath, value) else IF_SET_STRING("template", php_web->web->template, value) else IF_SET_STRING("imageurl", php_web->web->imageurl, value) else IF_SET_STRING("temppath", php_web->web->temppath, value) else IF_SET_STRING("header", php_web->web->header, value) else IF_SET_STRING("footer", php_web->web->footer, value) else IF_SET_STRING("mintemplate", php_web->web->mintemplate, value) else IF_SET_STRING("maxtemplate", php_web->web->maxtemplate, value) else IF_SET_DOUBLE("minscaledenom", php_web->web->minscaledenom, value) else IF_SET_DOUBLE("maxscaledenom", php_web->web->maxscaledenom, value) else IF_SET_STRING("queryformat", php_web->web->queryformat, value) else IF_SET_STRING("legendformat", php_web->web->legendformat, value) else IF_SET_STRING("browseformat", php_web->web->browseformat, value) else if ( (STRING_EQUAL("empty", property)) || (STRING_EQUAL("error", property)) || (STRING_EQUAL("extent", property))) { mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property); } else if ( (STRING_EQUAL("metadata", property)) || (STRING_EQUAL("validation", property)) ) { mapscript_throw_exception("Property '%s' is an object and can only be modified through its accessors." TSRMLS_CC, property); } else { mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property); } } /* {{{ proto int web.updateFromString(string snippet) Update a web from a string snippet. Returns MS_SUCCESS/MS_FAILURE */ PHP_METHOD(webObj, updateFromString) { char *snippet; long snippet_len = 0; zval *zobj = getThis(); php_web_object *php_web; int status = MS_FAILURE; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snippet, &snippet_len) == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = MAPSCRIPT_OBJ_P(php_web_object, zobj); status = webObj_updateFromString(php_web->web, snippet); if (status != MS_SUCCESS) { mapscript_throw_mapserver_exception("" TSRMLS_CC); return; } RETURN_LONG(status); } /* }}} */ /* {{{ proto string convertToString() Convert the web object to string. */ PHP_METHOD(webObj, convertToString) { zval *zobj = getThis(); php_web_object *php_web; char *value = NULL; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = MAPSCRIPT_OBJ_P(php_web_object, zobj); value = webObj_convertToString(php_web->web); if (value == NULL) MAPSCRIPT_RETURN_STRING("", 1); MAPSCRIPT_RETVAL_STRING(value, 1); free(value); } /* }}} */ /* {{{ proto int web.free() Free the object. */ PHP_METHOD(webObj, free) { zval *zobj = getThis(); php_web_object *php_web; PHP_MAPSCRIPT_ERROR_HANDLING(TRUE); if (zend_parse_parameters_none() == FAILURE) { PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); return; } PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE); php_web = MAPSCRIPT_OBJ_P(php_web_object, zobj); MAPSCRIPT_DELREF(php_web->extent); MAPSCRIPT_DELREF(php_web->metadata); MAPSCRIPT_DELREF(php_web->validation); } /* }}} */ zend_function_entry web_functions[] = { PHP_ME(webObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(webObj, __get, web___get_args, ZEND_ACC_PUBLIC) PHP_ME(webObj, __set, web___set_args, ZEND_ACC_PUBLIC) PHP_MALIAS(webObj, set, __set, NULL, ZEND_ACC_PUBLIC) PHP_ME(webObj, updateFromString, web_updateFromString_args, ZEND_ACC_PUBLIC) PHP_ME(webObj, convertToString, NULL, ZEND_ACC_PUBLIC) PHP_ME(webObj, free, NULL, ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; void mapscript_create_web(webObj *web, parent_object parent, zval *return_value TSRMLS_DC) { php_web_object * php_web; object_init_ex(return_value, mapscript_ce_web); php_web = MAPSCRIPT_OBJ_P(php_web_object, return_value); php_web->web = web; php_web->parent = parent; MAPSCRIPT_ADDREF(parent.val); } #if PHP_VERSION_ID >= 70000 /* PHP7 - Modification by Bjoern Boldt */ static zend_object *mapscript_web_create_object(zend_class_entry *ce TSRMLS_DC) { php_web_object *php_web; php_web = ecalloc(1, sizeof(*php_web) + zend_object_properties_size(ce)); zend_object_std_init(&php_web->zobj, ce TSRMLS_CC); object_properties_init(&php_web->zobj, ce); php_web->zobj.handlers = &mapscript_web_object_handlers; MAPSCRIPT_INIT_PARENT(php_web->parent); ZVAL_UNDEF(&php_web->extent); ZVAL_UNDEF(&php_web->metadata); ZVAL_UNDEF(&php_web->validation); return &php_web->zobj; } static void mapscript_web_free_object(zend_object *object) { php_web_object *php_web; php_web = (php_web_object *)((char *)object - XtOffsetOf(php_web_object, zobj)); MAPSCRIPT_FREE_PARENT(php_web->parent); MAPSCRIPT_DELREF(php_web->extent); MAPSCRIPT_DELREF(php_web->metadata); MAPSCRIPT_DELREF(php_web->validation); /* We don't need to free the webObj */ zend_object_std_dtor(object); } PHP_MINIT_FUNCTION(web) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "webObj", web_functions); mapscript_ce_web = zend_register_internal_class(&ce TSRMLS_CC); mapscript_ce_web->create_object = mapscript_web_create_object; mapscript_ce_web->ce_flags |= ZEND_ACC_FINAL; memcpy(&mapscript_web_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_web_object_handlers)); mapscript_web_object_handlers.free_obj = mapscript_web_free_object; mapscript_web_object_handlers.offset = XtOffsetOf(php_web_object, zobj); return SUCCESS; } #else /* PHP5 */ static void mapscript_web_object_destroy(void *object TSRMLS_DC) { php_web_object *php_web = (php_web_object *)object; MAPSCRIPT_FREE_OBJECT(php_web); MAPSCRIPT_FREE_PARENT(php_web->parent); MAPSCRIPT_DELREF(php_web->extent); MAPSCRIPT_DELREF(php_web->metadata); MAPSCRIPT_DELREF(php_web->validation); /* We don't need to free the webObj */ efree(object); } static zend_object_value mapscript_web_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; php_web_object *php_web; MAPSCRIPT_ALLOC_OBJECT(php_web, php_web_object); retval = mapscript_object_new(&php_web->std, ce, &mapscript_web_object_destroy TSRMLS_CC); MAPSCRIPT_INIT_PARENT(php_web->parent); php_web->extent = NULL; php_web->metadata = NULL; php_web->validation = NULL; return retval; } PHP_MINIT_FUNCTION(web) { zend_class_entry ce; MAPSCRIPT_REGISTER_CLASS("webObj", web_functions, mapscript_ce_web, mapscript_web_object_new); mapscript_ce_web->ce_flags |= ZEND_ACC_FINAL_CLASS; return SUCCESS; } #endif mapserver-7.4.3/mapscript/phpng/000077500000000000000000000000001357574274700166745ustar00rootroot00000000000000mapserver-7.4.3/mapscript/phpng/CMakeLists.txt000066400000000000000000000057041357574274700214420ustar00rootroot00000000000000find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) if(WIN32 AND (${CMAKE_VERSION} EQUAL "3.12.0") OR (${CMAKE_VERSION} EQUAL "3.12.1") OR (${CMAKE_VERSION} EQUAL "3.12.2") OR (${CMAKE_VERSION} EQUAL "3.12.3")) message(FATAL_ERROR "Building with CMAKE ${CMAKE_VERSION} will not work. Please downgrade to 3.11.x or update to a higher version than 3.12.3") endif() if(WIN32) FIND_PACKAGE(SWIG 3.0.11 REQUIRED) if(WITH_THREAD_SAFETY) FIND_PACKAGE(SWIG 4.0.0 REQUIRED) endif(WITH_THREAD_SAFETY) endif(WIN32) FIND_PACKAGE(PHP REQUIRED) INCLUDE(UseSWIG) if(WIN32) add_definitions(/DWIN32 /DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0) if(NOT CMAKE_CL_64) add_definitions(-D_USE_32BIT_TIME_T) endif(NOT CMAKE_CL_64) if(WITH_THREAD_SAFETY) add_definitions(-DZTS=1) endif(WITH_THREAD_SAFETY) endif(WIN32) include_directories(${PHP_INCLUDE_PATH}) message(STATUS "PHP Include Path: ${PHP_INCLUDE_PATH}") include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) include_directories(${PROJECT_SOURCE_DIR}/mapscript/phpng) include_directories(${CMAKE_CURRENT_BINARY_DIR}) # make sure mapscriptPHP7_wrap.c is found if(WIN32) include_directories(${PHP_INCLUDE_PATH}/win32) endif(WIN32) IF(PHP_VERSION LESS 5) MESSAGE(FATAL_ERROR "PHP version is not 5 or later") ENDIF(PHP_VERSION LESS 5) IF(PHP_VERSION LESS 7) if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_GREATER 3.7) SWIG_ADD_LIBRARY(php_mapscriptng TYPE MODULE LANGUAGE php SOURCES ../mapscript.i) else () swig_add_module(php_mapscriptng php ../mapscript.i) endif () ELSE() if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_GREATER 3.7) SWIG_ADD_LIBRARY(php_mapscriptng TYPE MODULE LANGUAGE php7 SOURCES ../mapscript.i) else () swig_add_module(php_mapscriptng php7 ../mapscript.i) endif () ENDIF(PHP_VERSION LESS 7) if(WIN32) target_compile_options(php_mapscriptng PRIVATE /DWIN32 /DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0) if(WITH_THREAD_SAFETY) target_compile_options(php_mapscriptng PRIVATE /DZTS=1) endif(WITH_THREAD_SAFETY) SWIG_LINK_LIBRARIES(php_mapscriptng ${PHP_LIBRARY}) endif(WIN32) IF(APPLE) if(XCODE) SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -undefined dynamic_lookup") SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -undefined dynamic_lookup") else(XCODE) SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -undefined dynamic_lookup") SET(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -undefined dynamic_lookup") endif(XCODE) ENDIF(APPLE) # hide "defined but not used" warnings target_compile_options(php_mapscriptng PRIVATE -Wno-unused-label) target_link_libraries(php_mapscriptng mapserver) set_target_properties(${SWIG_MODULE_mapscript_REAL_NAME} PROPERTIES PREFIX "") if(NOT WIN32) install(TARGETS php_mapscriptng DESTINATION ${PHP_EXTENSION_DIR}) endif() mapserver-7.4.3/mapscript/phpng/README.WIN32000066400000000000000000000076041357574274700203640ustar00rootroot00000000000000This readme covers building Mapserver from scatch on Windows. We will download current development state of php. If you need MapscriptNG for a different version of php, you have to fit the commands below. For the first time, it is a good idea to build as shown below and after you have a working state, you can change whatever you want, knowing there is a working state you can return to. All you need is Visual Studio 2017 Express (latest Version, check for updates) and GIT installed. To begin, start x64 or x86 Native Tools Command Prompt for VS 2017 and just execute all Commands listed below. Please always stay inside PHP-SDK-Shell to have wget and unzip available. rem -------------------------------------------------------------------- rem Step 1: Create Directories rem -------------------------------------------------------------------- mkdir C:\projects mkdir C:\projects\mapserver%VSCMD_ARG_TGT_ARCH% rem -------------------------------------------------------------------- rem Step 2: Build PHP rem -------------------------------------------------------------------- cd C:\projects\mapserver%VSCMD_ARG_TGT_ARCH% git clone https://github.com/Microsoft/php-sdk-binary-tools.git php-sdk cd C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\php-sdk set VS_VERSION=%VSCMD_VER:~0,2% phpsdk-vc%VS_VERSION%-%VSCMD_ARG_TGT_ARCH%.bat phpsdk_buildtree phpmaster git clone https://github.com/php/php-src.git cd php-src phpsdk_deps --update --branch master buildconf configure --enable-snapshot-build nmake snap rem -------------------------------------------------------------------- rem Step 3: Get GISInternals SDK rem -------------------------------------------------------------------- cd C:\projects\mapserver%VSCMD_ARG_TGT_ARCH% mkdir packages mkdir packages\gisinternals%VSCMD_ARG_TGT_ARCH%\ mkdir gisinternals%VSCMD_ARG_TGT_ARCH% set GISInternalsArchitecture=- if %VSCMD_ARG_TGT_ARCH% == x64 set GISInternalsArchitecture=-%VSCMD_ARG_TGT_ARCH%- wget -O packages\gisinternals%VSCMD_ARG_TGT_ARCH%\release-1911%GISInternalsArchitecture%dev.zip http://download.gisinternals.com/sdk/downloads/release-1911%GISInternalsArchitecture%dev.zip unzip -q -o packages\gisinternals%VSCMD_ARG_TGT_ARCH%\release-1911%GISInternalsArchitecture%dev.zip -d gisinternals%VSCMD_ARG_TGT_ARCH% rem -------------------------------------------------------------------- rem Step 4: Other Dependencies rem -------------------------------------------------------------------- rem ### SWIG ### cd C:\projects\mapserver%VSCMD_ARG_TGT_ARCH% git clone https://github.com/AlexanderGabriel/swig mkdir swig\build cd swig\build cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release cmake --build . move swig.exe .. rem ### gnulib ### cd C:\projects\mapserver%VSCMD_ARG_TGT_ARCH% git clone git://git.savannah.gnu.org/gnulib.git -------------------------------------------------------------------- Step 5: Build Mapserver with php_mapscriptng -------------------------------------------------------------------- cd C:\projects\mapserver%VSCMD_ARG_TGT_ARCH% git clone https://github.com/mapserver/mapserver cd mapserver mkdir build cd build cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -Wno-dev -DCMAKE_PREFIX_PATH=C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\gisinternals%VSCMD_ARG_TGT_ARCH%\release-1911-%VSCMD_ARG_TGT_ARCH%;C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\gnulib\lib;C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\gnulib\include;C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\gisinternals%VSCMD_ARG_TGT_ARCH%\release-1911-%VSCMD_ARG_TGT_ARCH%\lib;C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\gisinternals%VSCMD_ARG_TGT_ARCH%\release-1911-%VSCMD_ARG_TGT_ARCH%\include -DREGEX_DIR=C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\gisinternals%VSCMD_ARG_TGT_ARCH%\regex-0.12 -DWITH_POSTGIS=0 -DWITH_PROTOBUFC=0 -DWITH_THREAD_SAFETY=1 -DWITH_PHPNG=1 -DSWIG_EXECUTABLE=C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\swig\swig.exe -DSWIG_DIR=C:\projects\mapserver%VSCMD_ARG_TGT_ARCH%\swig cmake --build . mapserver-7.4.3/mapscript/phpng/php7module.i000066400000000000000000000011171357574274700211320ustar00rootroot00000000000000%pragma(php) phpinfo=" php_info_print_table_start(); php_info_print_table_row(2, \"MapServer Version\", msGetVersion()); php_info_print_table_end(); " /* To support imageObj::getBytes */ %typemap(out) gdBuffer { RETVAL_STRINGL((const char*)$1.data, $1.size); if( $1.owns_data ) msFree($1.data); } /* Module initialization: call msSetup() and register msCleanup() */ %init %{ if (msSetup() != MS_SUCCESS) { msSetError(MS_MISCERR, "Failed to set up threads and font cache", "msSetup()"); } %} %mshutdown { msCleanup(); } mapserver-7.4.3/mapscript/python/000077500000000000000000000000001357574274700171015ustar00rootroot00000000000000mapserver-7.4.3/mapscript/python/CMakeLists.txt000066400000000000000000000170051357574274700216440ustar00rootroot00000000000000find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) find_package(PythonInterp) find_python_module(setuptools REQUIRED) # Python library/header finding doesn't seem to honor the python # interpreter that was found beforehand, and defaults to the system # python. We first try to find python.h and libpython.so ourselves # from the hints given by distutils and sys execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_inc; print(get_python_inc(True))" OUTPUT_VARIABLE PYTHON_INC OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "import sys; print(sys.prefix)" OUTPUT_VARIABLE PYTHON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True))" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) find_path(PYTHON_INCLUDE_PATH Python.h HINTS ${PYTHON_INC} ) find_library(PYTHON_LIBRARIES NAMES python${PYTHON_VERSION_STRING} python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} python HINTS ${PYTHON_PREFIX}/lib ) #if that failed, fall back to the default cmake method of finding python dev files if(NOT PYTHON_INCLUDE_PATH OR NOT PYTHON_LIBRARIES) find_package(PythonLibs) endif() include_directories(${PYTHON_INCLUDE_PATH}) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) include_directories(${PROJECT_SOURCE_DIR}/mapscript/python) if (${PYTHON_VERSION_MAJOR} VERSION_GREATER 2) set_property(SOURCE ../mapscript.i PROPERTY SWIG_FLAGS "-py3") endif () if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_GREATER 3.7) swig_add_library(pythonmapscript TYPE MODULE LANGUAGE python SOURCES ../mapscript.i) else () swig_add_module(pythonmapscript python ../mapscript.i) endif () swig_link_libraries(pythonmapscript ${PYTHON_LIBRARIES} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(${SWIG_MODULE_pythonmapscript_REAL_NAME} PROPERTIES PREFIX "") set_target_properties(${SWIG_MODULE_pythonmapscript_REAL_NAME} PROPERTIES OUTPUT_NAME _mapscript) set(SETUP_PY_IN "${PROJECT_SOURCE_DIR}/mapscript/python/setup.py.in") set(SETUP_PY_TEMP "${CMAKE_CURRENT_BINARY_DIR}/setup.py.temp") configure_file(${SETUP_PY_IN} ${SETUP_PY_TEMP} @ONLY) file(READ ${SETUP_PY_TEMP} SETUP_CONTENT) # each target (e.g. Debug, Release etc.) will have a copy of setup.py file(GENERATE OUTPUT $/setup.py INPUT ${SETUP_PY_TEMP}) if(MSVC) set(OUTPUT_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}) else() # for non-Windows builds there are no build type subfolders (e.g. Release, Debug etc.) set(OUTPUT_FOLDER ${CMAKE_CURRENT_BINARY_DIR}) endif() if(WIN32) # Windows venv binaries are in a different location than Linux set(PYTHON_VENV_SCRIPTS ${OUTPUT_FOLDER}/mapscriptvenv/Scripts) else() set(PYTHON_VENV_SCRIPTS ${OUTPUT_FOLDER}/mapscriptvenv/bin) endif() add_custom_target( pythonmapscript-wheel DEPENDS mapscripttests.stamp ) add_custom_command( DEPENDS ${SWIG_MODULE_pythonmapscript_REAL_NAME} OUTPUT mapscriptvenv.stamp WORKING_DIRECTORY ${OUTPUT_FOLDER} COMMAND ${PYTHON_EXECUTABLE} -m pip install virtualenv COMMAND ${PYTHON_EXECUTABLE} -m virtualenv mapscriptvenv COMMAND ${PYTHON_VENV_SCRIPTS}/python -m pip install pip --upgrade --force-reinstall > pip_update.log COMMAND ${PYTHON_VENV_SCRIPTS}/pip install -r ${PROJECT_SOURCE_DIR}/mapscript/python/requirements-dev.txt > requires.log COMMENT "Creating a Python virtual environment and installing the required packages" ) add_custom_command( DEPENDS mapscriptvenv.stamp OUTPUT mapscriptlinting.stamp WORKING_DIRECTORY ${OUTPUT_FOLDER} COMMAND ${PYTHON_VENV_SCRIPTS}/flake8 $/mapscript/tests --max-line-length=120 COMMAND ${PYTHON_VENV_SCRIPTS}/flake8 $/mapscript/examples --max-line-length=120 COMMENT "Linting test suite and examples with flake8" # note only one comment is output per custom command block ) add_custom_command( DEPENDS mapscriptlinting.stamp OUTPUT mapscriptwheel.stamp WORKING_DIRECTORY ${OUTPUT_FOLDER} COMMAND ${PYTHON_VENV_SCRIPTS}/python setup.py bdist_wheel > wheel_build.log COMMENT "Building the mapscript Python wheel" ) add_custom_command( WORKING_DIRECTORY ${PYTHON_VENV_SCRIPTS} # make sure scripts aren't run when from the same folder as mapscript.py DEPENDS mapscriptwheel.stamp OUTPUT mapscripttests.stamp COMMAND ${PYTHON_VENV_SCRIPTS}/pip install --no-index --find-links=${OUTPUT_FOLDER}/dist mapscript COMMAND ${PYTHON_VENV_SCRIPTS}/pytest --pyargs mapscript.tests COMMAND ${PYTHON_VENV_SCRIPTS}/python -m mapscript.examples.project_csv ${PROJECT_SOURCE_DIR}/tests/cities.csv 2 1 EPSG:4326 EPSG:3857 > test.csv COMMAND ${PYTHON_VENV_SCRIPTS}/python -m mapscript.examples.shpdump ${PROJECT_SOURCE_DIR}/tests/polygon.shp > shpdump.txt COMMAND ${PYTHON_VENV_SCRIPTS}/python -m mapscript.examples.shpinfo ${PROJECT_SOURCE_DIR}/tests/polygon.shp > shpinfo.txt COMMAND ${PYTHON_VENV_SCRIPTS}/python -m mapscript.examples.wxs ${PROJECT_SOURCE_DIR}/tests/test.map > response.xml COMMENT "Installing the Python wheel and testing it in the virtual environment, then running tests and examples" ) add_custom_command( TARGET _pythonmapscript WORKING_DIRECTORY ${OUTPUT_FOLDER} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/mapscript/python/mapscript/__init__.py" $/mapscript/__init__.py COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/mapscript.py" $/mapscript/mapscript.py COMMAND ${CMAKE_COMMAND} -E copy "$" "$/mapscript/$" COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/mapscript/python/README.rst" $/README.rst COMMAND ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/mapscript/python/tests/cases" $/mapscript/tests COMMAND ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/tests" $/mapscript/tests/data COMMAND ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/mapscript/python/examples" $/mapscript/examples COMMENT "Copying files required to build Mapscript" ) install( CODE " SET(ENV{PYTHONPATH} \${PYTHON_SITE_PACKAGES}:\$ENV{PYTHONPATH}) if(DEFINED ENV{DESTDIR}) SET(PYTHON_ROOT \"--root=\$ENV{DESTDIR}\") endif() if(DEFINED CMAKE_INSTALL_PREFIX) SET(PYTHON_PREFIX \"--prefix=\${CMAKE_INSTALL_PREFIX}\") endif() execute_process( COMMAND ${PYTHON_EXECUTABLE} setup.py install \${PYTHON_ROOT} \${PYTHON_PREFIX} WORKING_DIRECTORY ${OUTPUT_FOLDER} ) " ) message(STATUS "CMake Version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}") message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") message(STATUS "Python MapScript output directory: ${OUTPUT_FOLDER}") message(STATUS "Python Executable: ${PYTHON_EXECUTABLE}") message(STATUS "Python site packages: ${PYTHON_SITE_PACKAGES}") mapserver-7.4.3/mapscript/python/README.rst000066400000000000000000000241621357574274700205750ustar00rootroot00000000000000Python MapScript for MapServer 7.4.0 README =========================================== :Author: MapServer Team :Last Updated: 2019-06-04 Introduction ------------ The Python mapscript module provides users an interface to `MapServer `_ classes on any platform, and has been tested on Python versions 2.7 and 3.5+. The Python mapscript module is created using `SWIG `_ the the Simplified Wrapper and Interface Generator. This is used to create MapServer bindings in many different programming languages. + Language agnostic documentation is available at http://mapserver.org/mapscript/introduction.html + Python specific documentation is available at http://mapserver.org/mapscript/python.html For working with Mapfiles in Python the `mappyfile `_ project is also available, this allows creating, parsing, formatting, and validating Mapfiles without any dependencies on MapServer. Wheels and PyPI --------------- Python `wheels `_ have been created for Windows and uploaded to `PyPI `_ - the Python Package Index. Note - MapServer binaries still need to be installed on the system, and are not included in the wheel itself, see the *Installation* section below. Advantages of ready-made wheels on PyPI include: + easy installation using `pip `_ + mapscript can be added as a dependency to `Requirements Files `_ + mapscript can be easily added to a Python `Virtual Environment `_ + Python2 or Python3 versions of mapscript can be installed and work with a single installation of MapServer Currently the following wheels are built: + Python 2.7 x64 for MapServer 7.4.0 + Python 3.6 x64 for MapServer 7.4.0 The mapscript wheels have been compiled using Visual Studio 2017 version 15.3 (``MSVC++ 14.11 _MSC_VER == 1911``). Linux wheels are also planned, using the `manylinux `_ project. No source distributions will be provided on PyPI - to build from source requires the full MapServer source code, in which case it is easiest to take a copy of the full MapServer project and run the CMake process detailed below. The wheels contain a full test suite and sample data that can be run to check that the installed MapServer is running correctly. .. py3 SWIG flag adds type annotations Installation on Windows ----------------------- To use mapscript you will need to add the MapServer binaries to your system path. On Windows you can use the following, replacing ``C:\MapServer\bin`` with the location of your MapServer binaries. .. code-block:: bat SET PATH=C:\MapServer\bin;%PATH% Windows binary packages can be downloaded from `GIS Internals `_. To ensure compatibility with the wheels, please use identical release packages, e.g. ``release-1911-x64-gdal-2-3-mapserver-7-4`` for mapscript 7.4. When using these packages the MapServer path will be similar to ``C:\release-1911-x64-gdal-2-3-mapserver-7-2\bin``. Prior to installing mapscript it is recommended to update pip to the latest version with the following command: .. code-block:: bat python -m pip install --upgrade pip If there are binary wheels available for your system, mapscript can be installed using: .. code-block:: bat pip install mapscript If you already have mapscript installed and wish to upgrade it to a newer version you can use: .. code-block:: bat pip install mapscript --upgrade Now you should be able to import mapscript: .. code-block:: python python -c "import mapscript;print(mapscript.msGetVersion())" MapServer version 7.4.0 OUTPUT=PNG OUTPUT=JPEG OUTPUT=KML SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=CAIRO SUPPORTS=SVG_SYMBOLS SUPPORTS=SVGCAIRO SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=SOS_SERVER SUPPORTS=FASTCGI SUPPORTS=THREADS SUPPORTS=GEOS SUPPORTS=PBF INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE If you failed to add the MapServer binaries to your system path you may see one of the following errors: .. code-block:: python ImportError: No module named _mapscript # Python 2.x ModuleNotFoundError: No module named '_mapscript' # Python 3.x If your version of mapscript does not match your version of MapServer you may instead one of the following messages: .. code-block:: python ImportError: DLL load failed: The specified module could not be found. ImportError: DLL load failed: The specified procedure could not be found. Installation on Unix -------------------- For Unix users there are two approaches to installing mapscript. The first is to install the ``python-mapscript`` package using a package manager. For example on Ubuntu the following command can be used: .. code-block:: bat sudo apt-get install python-mapscript The second approach is to build and install the Python mapscript module from source. Full details on compiling MapServer from source are detailed on the `Compiling on Unix `_ page. To make sure Python mapscript is built alongside MapServer the following flag needs to be set: .. code-block:: bat -DWITH_PYTHON=ON To configure the path of the mapscript installation location ``-DCMAKE_INSTALL_PREFIX`` can be set, e.g. .. code-block:: bat sudo cmake .. -DCMAKE_INSTALL_PREFIX=/usr When installing the `DESTDIR `_ variable can be set (note ``DESTDIR`` is not used on Windows) to install mapscript to a non-default location. E.g. .. code-block:: bat make install DESTDIR=/tmp In summary the ``install`` target runs the ``setup.py install`` command using custom paths (when set) similar to below: python setup.py install --root=${DESTDIR} --prefix={CMAKE_INSTALL_PREFIX} Quickstart ---------- Some basic examples of what can be done with mapscript are shown below. Note - before running any scripts using mapscript, you will need to add the MapServer binaries to your system path, see the *Installation* section above. To open an existing Mapfile: .. code-block:: python >>> import mapscript >>> test_map = mapscript.mapObj(r"C:\Maps\mymap.map") >>> extent = test_map.extent Create a layer from a string: .. code-block:: python >>> import mapscript >>> layer = mapscript.fromstring("""LAYER NAME "test" TYPE POINT END""") >>> layer >>> layer.name 'test' >>> layer.type == mapscript.MS_LAYER_POINT True Building the Mapscript Module ----------------------------- The mapscript module is built as part of the MapServer CMake build process. This is configured using the ``mapserver/mapscript/CMakeLists.txt`` file. Before the switch to CMake MapServer mapscript was built using distutils and ``setup.py``. Now the ``setup.py.in`` file is used as a template that is filled with the MapServer version number and used to created wheel files for distribution, or install mapscript directly on the build machine. The build process works as follows. + CMake runs SWIG. This uses the SWIG interface files to create a ``mapscriptPYTHON_wrap.c`` file, and a ``mapscript.py`` file containing the Python wrapper to the mapscript binary module. + CMake then uses the appropriate compiler on the system to compile the ``mapscriptPYTHON_wrap.c`` file into a Python binary module - ``_mapscript.pyd`` file on Windows, and a ``_mapscript.so`` file on Unix. ``CMakeLists.txt`` is configured with a ``pythonmapscript-wheel`` target that copies all the required files to the output build folder where they are then packaged into a Python wheel. The wheel can be built using the following command: .. code-block:: bat cmake --build . --target pythonmapscript-wheel The ``pythonmapscript-wheel`` target creates a virtual environment, creates the Python wheel, installs it to the virtual environment and finally runs the test suite. This process runs commands similar to the following: .. code-block:: bat python -m pip install virtualenv virtualenv mapscriptvenv python -m pip install --upgrade pip pip install -r requirements-dev.txt python setup.py bdist_wheel pip install --no-index --find-links=dist mapscript python -m pytest --pyargs mapscript.tests SWIG can also be run manually, without using CMake. This may allow further optimizations and control on the output. .. code-block:: bat cd C:\Projects\mapserver\build SET PATH=C:\MapServerBuild\swigwin-3.0.12;%PATH% swig -python -shadow -o mapscript_wrap.c ../mapscript.i SWIG has several command line options to control the output, examples of which are shown below: .. code-block:: bat swig -python -shadow -modern -templatereduce -fastdispatch -fvirtual -fastproxy -modernargs -castmode -dirvtable -fastinit -fastquery -noproxydel -nobuildnone -o mapscript_wrap.c ../mapscript.i Testing ------- The mapscript module includes a test suite and a small sample dataset to check the output and MapServer installation. It is recommended `pytest `_ is used to run the tests. This can be installed using: .. code-block:: bat pip install pytest Make sure the MapServer binaries are on the system path, and that the PROJ_LIB variable has been set as this is required for many of the tests. .. code-block:: bat SET PATH=C:\release-1911-x64-gdal-2-3-mapserver-7-4\bin;%PATH% SET PROJ_LIB=C:\release-1911-x64-gdal-2-3-mapserver-7-4\bin\proj\SHARE Finally run the command below to run the test suite: .. code-block:: bat pytest --pyargs mapscript.tests Credits ------- + Steve Lime (developer) + Sean Gillies (developer) + Frank Warmerdam (developer) + Howard Butler (developer) + Norman Vine (cygwin and distutils guru) + Tim Cera (install) + Michael Schultz (documentation) + Thomas Bonfort (developer) + Even Rouault (developer) + Seth Girvin (Python3 migration, documentation and builds) + Claude Paroz (Python3 migration) mapserver-7.4.3/mapscript/python/examples/000077500000000000000000000000001357574274700207175ustar00rootroot00000000000000mapserver-7.4.3/mapscript/python/examples/__init__.py000066400000000000000000000000001357574274700230160ustar00rootroot00000000000000mapserver-7.4.3/mapscript/python/examples/project_csv.py000077500000000000000000000032061357574274700236160ustar00rootroot00000000000000#!/usr/bin/env python """ Simple example to read a csv file and reproject point x/y data Usage: project_csv.py cities.csv 2 1 EPSG:4326 EPSG:3857 """ import sys import csv from io import open import mapscript def main(input_file, x_field_idx, y_field_idx, input_proj, output_proj): # set input and output projections proj_in = mapscript.projectionObj(input_proj) proj_out = mapscript.projectionObj(output_proj) # open file with open(input_file, encoding='utf-8') as f: # read csv csv_in = csv.reader(f) headers = next(csv_in) # setup output csv_out = csv.writer(sys.stdout) csv_out.writerow(headers) for row in csv_in: # set pointObj point = mapscript.pointObj(float(row[x_field_idx]), float(row[y_field_idx])) # project point.project(proj_in, proj_out) # update with reprojected coordinates row[x_field_idx] = point.x row[y_field_idx] = point.y csv_out.writerow(row) def usage(): """ Display usage if program is used incorrectly """ print("Syntax: %s " % sys.argv[0]) sys.exit(2) # check input parameters if (len(sys.argv) != 6): usage() input_file = sys.argv[1] # set x and y indices x_field_idx = int(sys.argv[2]) y_field_idx = int(sys.argv[3]) # get projection codes input_proj = "init="+sys.argv[4].lower() output_proj = "init="+sys.argv[5].lower() main(input_file, x_field_idx, y_field_idx, input_proj, output_proj) mapserver-7.4.3/mapscript/python/examples/shpdump.py000077500000000000000000000040321357574274700227530ustar00rootroot00000000000000#!/usr/bin/env python """ Dump the contents of the passed in Shapefile Usage: python shpdump.py polygon.shp """ import mapscript import sys import os def plural(x): """ Returns an 's' if plural Useful in print statements to avoid something like 'point(s)' """ if x > 1: return 's' return '' def get_shapefile_object(sf_path): # make sure can access .shp file, create shapefileObj if os.access(sf_path, os.F_OK): sf_obj = mapscript.shapefileObj(sf_path, -1) else: print("Can't access {}".format(sf_path)) sys.exit(2) return sf_obj def main(sf_path): if not sf_path.lower().endswith(".shp"): sf_path += ".shp" sf_obj = get_shapefile_object(sf_path) # create an empty Shapefile object s_obj = mapscript.shapeObj() # loop through each shape in the original Shapefile for i in range(sf_obj.numshapes): # get the object at index i sf_obj.get(i, s_obj) print("Shape %i has %i part%s" % (i, s_obj.numlines, plural(s_obj.numlines))) print("Bounds (%f, %f) (%f, %f)" % (s_obj.bounds.minx, s_obj.bounds.miny, s_obj.bounds.maxx, s_obj.bounds.maxy)) # loop through parts of each shape for j in range(s_obj.numlines): # get the jth part of the ith object part = s_obj.get(j) print("Part %i has %i point%s" % (j, part.numpoints, plural(part.numpoints))) # loop through points in each part for k in range(part.numpoints): # get the kth point of the jth part of the ith shape point = part.get(k) print("%i: %f, %f" % (k, point.x, point.y)) def usage(): """ Display usage if program is used incorrectly """ print("Syntax: %s " % sys.argv[0]) sys.exit(2) # make sure passing in filename argument if len(sys.argv) != 2: usage() sf_path = sys.argv[1] main(sf_path) mapserver-7.4.3/mapscript/python/examples/shpinfo.py000077500000000000000000000055351357574274700227520ustar00rootroot00000000000000#!/usr/bin/env python """ Extracts basic descriptive information from a Shapefile Usage: python shpinfo.py point.shp """ import mapscript import sys import os def get_shapefile_object(sf_path): # make sure can access .shp file, create shapefileObj if os.access(sf_path, os.F_OK): sf_obj = mapscript.shapefileObj(sf_path) else: print("Can't access {}".format(sf_path)) sys.exit(2) return sf_obj def get_shapefile_details(sf_obj): # dictionary of shapefile types types = { mapscript.MS_SHAPEFILE_POINT: 'Point', mapscript.MS_SHAPEFILE_ARC: 'Line', mapscript.MS_SHAPEFILE_POLYGON: 'Polygon', mapscript.MS_SHAPEFILE_MULTIPOINT: 'Multipoint', mapscript.MS_SHP_POINTZ: 'PointZ', mapscript.MS_SHP_ARCZ: 'LineZ', mapscript.MS_SHP_POLYGONZ: 'PolygonZ', mapscript.MS_SHP_MULTIPOINTZ: 'MultipointZ', mapscript.MS_SHP_POINTM: 'Multipoint', mapscript.MS_SHP_ARCM: 'LineM', mapscript.MS_SHP_POLYGONM: 'PolygonM', mapscript.MS_SHP_MULTIPOINTM: 'MultipointM' } # print out basic information that is part of the shapefile object print("\tType: %s" % types[sf_obj.type]) print("\tBounds: (%f, %f) (%f, %f)" % (sf_obj.bounds.minx, sf_obj.bounds.miny, sf_obj.bounds.maxx, sf_obj.bounds.maxy)) print("\tNumber of features: %i" % sf_obj.numshapes) def get_dbf_details(sf_obj): # get DBF object dbf_obj = sf_obj.getDBF() # print out table characteristics print("\tNumber of records in DBF: %i" % dbf_obj.nRecords) print("\tNumber of fields: %i" % dbf_obj.nFields) print("") print("\t%-20s %12s %8s %10s" % ("Name", "Type", "Length", "Decimals")) print("\t-----------------------------------------------------") # print out field characteristics for idx in range(0, dbf_obj.nFields): print("\t%-20s %12s %8d %10d" % (dbf_obj.getFieldName(idx), dbf_obj.getFieldType(idx), dbf_obj.getFieldWidth(idx), dbf_obj.getFieldDecimals(idx))) def main(sf_path): if not sf_path.lower().endswith(".shp"): sf_path += ".shp" sf_obj = get_shapefile_object(sf_path) print("Shapefile %s:" % sf_path) print("") get_shapefile_details(sf_obj) get_dbf_details(sf_obj) def usage(): """ Display usage if program is used incorrectly """ print("Syntax: %s " % sys.argv[0]) sys.exit(2) # make sure a filename argument is provided if len(sys.argv) != 2: usage() main(sys.argv[1]) mapserver-7.4.3/mapscript/python/examples/wxs.py000066400000000000000000000030121357574274700221060ustar00rootroot00000000000000#!/usr/bin/env python """ Output WMS GetCapabilities response for a Mapfile Usage: python wxs.py test.map """ import sys import xml.dom.minidom import mapscript def main(map_file): map = mapscript.mapObj(map_file) map.setMetaData("ows_onlineresource", "http://dummy.org/") ows_req = mapscript.OWSRequest() ows_req.type = mapscript.MS_GET_REQUEST ows_req.setParameter("SERVICE", "WMS") ows_req.setParameter("VERSION", "1.1.0") ows_req.setParameter("REQUEST", "GetCapabilities") mapscript.msIO_installStdoutToBuffer() dispatch_status = map.OWSDispatch(ows_req) if dispatch_status != mapscript.MS_SUCCESS: print("An error occurred") content_type = mapscript.msIO_stripStdoutBufferContentType() mapscript.msIO_stripStdoutBufferContentHeaders() result = mapscript.msIO_getStdoutBufferBytes() # [('Content-Type', 'application/vnd.ogc.wms_xml; charset=UTF-8'), ('Content-Length', '11385')] response_headers = [('Content-Type', content_type), ('Content-Length', str(len(result)))] assert int(response_headers[1][1]) > 0 dom = xml.dom.minidom.parseString(result) print(dom.toprettyxml(indent="", newl="")) def usage(): """ Display usage if program is used incorrectly """ print("Syntax: %s " % sys.argv[0]) sys.exit(2) # make sure a filename argument is provided if len(sys.argv) != 2: usage() map_file = sys.argv[1] main(map_file) mapserver-7.4.3/mapscript/python/mapscript/000077500000000000000000000000001357574274700211035ustar00rootroot00000000000000mapserver-7.4.3/mapscript/python/mapscript/__init__.py000066400000000000000000000000301357574274700232050ustar00rootroot00000000000000from .mapscript import *mapserver-7.4.3/mapscript/python/pyextend.i000066400000000000000000000347561357574274700211320ustar00rootroot00000000000000/****************************************************************************** * Project: MapServer * Purpose: Python-specific extensions to MapScript objects * Author: Sean Gillies, sgillies@frii.com * Author: Seth Girvin, sethg@geographika.co.uk * ****************************************************************************** * * Python-specific mapscript code has been moved into this * SWIG interface file to improve the readability of the main * interface file. The main mapscript.i file includes this * file when SWIGPYTHON is defined (via 'swig -python ...'). * *****************************************************************************/ /* fromstring: Factory for mapfile objects */ %pythoncode %{ def fromstring(data, mappath=None): """Creates map objects from mapfile strings. Parameters ========== data : string Mapfile in a string. mappath : string Optional root map path, enabling relative paths in mapfile. Example ======= >>> mo = fromstring("MAP\nNAME 'test'\nEND") >>> mo.name 'test' """ import re if re.search(r"^\s*MAP", data, re.I): return msLoadMapFromString(data, mappath) elif re.search(r"^\s*LAYER", data, re.I): ob = layerObj() ob.updateFromString(data) return ob elif re.search(r"^\s*CLASS", data, re.I): ob = classObj() ob.updateFromString(data) return ob elif re.search(r"^\s*STYLE", data, re.I): ob = styleObj() ob.updateFromString(data) return ob else: raise ValueError("No map, layer, class, or style found. Can not load from provided string") %} /* =========================================================================== Python rectObj extensions ======================================================================== */ %extend rectObj { %pythoncode %{ def __str__(self): return self.toString() def __contains__(self, item): item_type = item.__class__.__name__ if item_type == "pointObj": if item.x >= self.minx and item.x <= self.maxx \ and item.y >= self.miny and item.y <= self.maxy: return True else: return False else: raise TypeError('__contains__ does not yet handle %s' % (item_type)) %} } /* =========================================================================== Python pointObj extensions ======================================================================== */ %extend pointObj { %pythoncode %{ def __str__(self): return self.toString() @property def __geo_interface__(self): if hasattr(self, "z"): coords = (self.x, self.y, self.z) else: coords = (self.x, self.y) return {"type": "Point", "coordinates": coords} %} } /* =========================================================================== Python lineObj extensions ======================================================================== */ %extend lineObj { %pythoncode %{ @property def __geo_interface__(self): coords = [] for idx in range(0, self.numpoints): pt = self.get(idx) geom = pt.__geo_interface__ coords.append(geom["coordinates"]) return {"type": "LineString", "coordinates": coords} %} } /* =========================================================================== Python shapeObj extensions ======================================================================== */ %extend shapeObj { %pythoncode %{ def _convert_item_values(self, property_values, property_types): """ **Python MapScript only** Convert an item value, which is always stored as a string, into a Python type, based on an attributes GML metadata type. These can be one of the following: ``Integer|Long|Real|Character|Date|Boolean`` """ typed_values = [] for value, type_ in zip(property_values, property_types): try: if type_.lower() == "integer": value = int(value) elif type_.lower() == "long": value = long(value) elif type_.lower() == "real": value = float(value) else: pass except ValueError: pass typed_values.append(value) return typed_values @property def __geo_interface__(self): bounds = self.bounds ms_geom_type = self.type # see https://tools.ietf.org/html/rfc7946 for GeoJSON types if ms_geom_type == MS_SHAPE_POINT or ms_geom_type == MS_SHP_POINTZ or ms_geom_type == MS_SHP_POINTM: geom_type = "Point" elif ms_geom_type == MS_SHP_MULTIPOINTZ or ms_geom_type == MS_SHP_MULTIPOINTM: geom_type = "MultiPoint" elif ms_geom_type == MS_SHAPE_LINE or ms_geom_type == MS_SHP_ARCZ or ms_geom_type == MS_SHP_ARCM: if self.numlines == 1: geom_type = "LineString" else: geom_type = "MultiLineString" elif ms_geom_type == MS_SHAPE_POLYGON or ms_geom_type == MS_SHP_POLYGONZ or ms_geom_type == MS_SHP_POLYGONM: if self.numlines == 1: geom_type = "Polygon" else: geom_type = "MultiPolygon" elif ms_geom_type == MS_SHAPE_NULL: return None else: raise TypeError("Shape type {} not supported".format(geom_type)) properties = {} coords = [] # property names are stored at the layer level # https://github.com/mapserver/mapserver/issues/130 property_values = [self.getValue(idx) for idx in range(0, self.numvalues)] if hasattr(self, "_item_definitions"): property_names, property_types = zip(*self._item_definitions) property_values = self._convert_item_values(property_values, property_types) else: property_names = [str(idx) for idx in range(0, self.numvalues)] properties = dict(zip(property_names, property_values)) for idx in range(0, self.numlines): line = self.get(idx) geom = line.__geo_interface__ coords.append(geom["coordinates"]) return { "type": "Feature", "bbox": (bounds.minx, bounds.miny, bounds.maxx, bounds.maxy), "properties": properties, "geometry": { "type": geom_type, "coordinates": coords } } def getItemDefinitions(self): return self._item_definitions def setItemDefinitions(self, item_definitions): self._item_definitions = item_definitions __swig_getmethods__["itemdefinitions"] = getItemDefinitions __swig_setmethods__["itemdefinitions"] = setItemDefinitions %} } /****************************************************************************** * Extensions to mapObj *****************************************************************************/ %extend mapObj { /* getLayerOrder() extension returns the map layerorder as a native sequence */ PyObject *getLayerOrder() { int i; PyObject *order; order = PyTuple_New(self->numlayers); for (i = 0; i < self->numlayers; i++) { PyTuple_SetItem(order,i,PyInt_FromLong((long)self->layerorder[i])); } return order; } int setLayerOrder(PyObject *order) { int i, size; size = PyTuple_Size(order); for (i = 0; i < size; i++) { self->layerorder[i] = (int)PyInt_AsLong(PyTuple_GetItem(order, i)); } return MS_SUCCESS; } PyObject* getSize() { PyObject* output ; output = PyTuple_New(2); PyTuple_SetItem(output,0,PyInt_FromLong((long)self->width)); PyTuple_SetItem(output,1,PyInt_FromLong((long)self->height)); return output; } %pythoncode %{ def get_height(self): return self.getSize()[1] # <-- second member is the height def get_width(self): return self.getSize()[0] # <-- first member is the width def set_height(self, value): return self.setSize(self.getSize()[0], value) def set_width(self, value): return self.setSize(value, self.getSize()[1]) width = property(get_width, set_width) height = property(get_height, set_height) %} } /****************************************************************************** * Extensions to layerObj *****************************************************************************/ %extend layerObj { %pythoncode %{ def getItemDefinitions(self): """ **Python MapScript only** Return item (field) names and their types if available. Field types are specified using GML metadata and can be one of the following: ``Integer|Long|Real|Character|Date|Boolean`` """ item_names = [self.getItem(idx) for idx in range(0, self.numitems)] item_types = [self.getItemType(idx) for idx in range(0, self.numitems)] return zip(item_names, item_types) %} } /****************************************************************************** * Extensions to imageObj *****************************************************************************/ %extend imageObj { /* ====================================================================== write() Write image data to an open Python file or file-like object. Overrides extension method in mapscript/swiginc/image.i. Intended to replace saveToString. ====================================================================== */ int write( PyObject *file=Py_None ) { unsigned char *imgbuffer=NULL; int imgsize; PyObject *noerr; int retval=MS_FAILURE; rendererVTableObj *renderer = NULL; /* Return immediately if image driver is not GD */ if ( !MS_RENDERER_PLUGIN(self->format) ) { msSetError(MS_IMGERR, "Writing of %s format not implemented", "imageObj::write", self->format->driver); return MS_FAILURE; } if (file == Py_None) /* write to stdout */ retval = msSaveImage(NULL, self, NULL); else /* presume a Python file-like object */ { imgbuffer = msSaveImageBuffer(self, &imgsize, self->format); if (imgsize == 0) { msSetError(MS_IMGERR, "failed to get image buffer", "write()"); return MS_FAILURE; } %#if PY_MAJOR_VERSION >= 3 // https://docs.python.org/3/c-api/arg.html noerr = PyObject_CallMethod(file, "write", "y#", imgbuffer, imgsize); %#else // https://docs.python.org/2/c-api/arg.html noerr = PyObject_CallMethod(file, "write", "s#", imgbuffer, imgsize); %#endif free(imgbuffer); if (noerr == NULL) return MS_FAILURE; else Py_DECREF(noerr); retval = MS_SUCCESS; } return retval; } /* Deprecated */ PyObject *saveToString() { int size=0; unsigned char *imgbytes; PyObject *imgstring; imgbytes = msSaveImageBuffer(self, &size, self->format); if (size == 0) { msSetError(MS_IMGERR, "failed to get image buffer", "saveToString()"); return NULL; } imgstring = PyBytes_FromStringAndSize((const char*) imgbytes, size); free(imgbytes); return imgstring; } } /****************************************************************************** * Extensions to styleObj *****************************************************************************/ %extend styleObj { void pattern_set(int nListSize, double* pListValues) { if( nListSize < 2 ) { msSetError(MS_SYMERR, "Not enough pattern elements. A minimum of 2 are required", "pattern_set()"); return; } if( nListSize > MS_MAXPATTERNLENGTH ) { msSetError(MS_MISCERR, "Too many elements", "pattern_set()"); return; } memcpy( self->pattern, pListValues, sizeof(double) * nListSize); self->patternlength = nListSize; } void pattern_get(double** argout, int* pnListSize) { *pnListSize = self->patternlength; *argout = (double*) malloc(sizeof(double) * *pnListSize); memcpy( *argout, self->pattern, sizeof(double) * *pnListSize); } void patternlength_set2(int patternlength) { msSetError(MS_MISCERR, "pattern is read-only", "patternlength_set()"); } %pythoncode %{ __swig_setmethods__["patternlength"] = _mapscript.styleObj_patternlength_set2 __swig_getmethods__["patternlength"] = _mapscript.styleObj_patternlength_get if _newclass:patternlength = _swig_property(_mapscript.styleObj_patternlength_get, _mapscript.styleObj_patternlength_set2) __swig_setmethods__["pattern"] = _mapscript.styleObj_pattern_set __swig_getmethods__["pattern"] = _mapscript.styleObj_pattern_get if _newclass:pattern = _swig_property(_mapscript.styleObj_pattern_get, _mapscript.styleObj_pattern_set) %} } /****************************************************************************** * Extensions to hashTableObj - add dict methods *****************************************************************************/ %extend hashTableObj{ %pythoncode %{ def __getitem__(self, key): return self.get(key) def __setitem__(self, key, value): return self.set(key, value) def __delitem__(self, key) : return self.remove(key) def __contains__(self, key): return key.lower() in [k.lower() for k in self.keys()] def __len__(self): return self.numitems def keys(self): keys = [] k = None while True : k = self.nextKey(k) if k : keys.append(k) else : break return keys %} } mapserver-7.4.3/mapscript/python/pymodule.i000066400000000000000000000200471357574274700211140ustar00rootroot00000000000000/****************************************************************************** * Project: MapServer * Purpose: Python-specific enhancements to MapScript * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * * Python-specific mapscript code has been moved into this * SWIG interface file to improve the readability of the main * interface file. The main mapscript.i file includes this * file when SWIGPYTHON is defined (via 'swig -python ...'). * *****************************************************************************/ /****************************************************************************** * Simple Typemaps *****************************************************************************/ /* Translates Python None to C NULL for strings */ %typemap(in,parse="z") char * ""; /* To support imageObj::getBytes */ %typemap(out) gdBuffer { $result = PyBytes_FromStringAndSize((const char*)$1.data, $1.size); if( $1.owns_data ) msFree($1.data); } /* * Typemap for counted arrays of doubles <- PySequence */ %typemap(in,numinputs=1) (int nListSize, double* pListValues) { int i; /* %typemap(in,numinputs=1) (int nListSize, double* pListValues)*/ /* check if is List */ if ( !PySequence_Check($input) ) { PyErr_SetString(PyExc_TypeError, "not a sequence"); SWIG_fail; } $1 = PySequence_Size($input); $2 = (double*) malloc($1*sizeof(double)); for( i = 0; i<$1; i++ ) { PyObject *o = PySequence_GetItem($input,i); if ( !PyArg_Parse(o,"d",&$2[i]) ) { PyErr_SetString(PyExc_TypeError, "not a number"); Py_DECREF(o); SWIG_fail; } Py_DECREF(o); } } %fragment("CreateTupleFromDoubleArray","header") %{ static PyObject * CreateTupleFromDoubleArray( double *first, unsigned int size ) { unsigned int i; PyObject *out = PyTuple_New( size ); for( i=0; i * has been updated by Sean Gillies to use * PyErr_SetString, %exception and $action for SWIG 1.3, do the most * obvious mapping of MapServer errors to Python exceptions and map all * others to a new 'MapServerError' exception which can be caught like this: * * from mapscript import * * empty_map = mapObj('') * try: * img = empty_map.draw() * except MapServerError, msg: * print "Caught MapServerError:", msg * *************************************************************************/ %{ PyObject *MSExc_MapServerError; PyObject *MSExc_MapServerChildError; %} /* Module initialization: call msSetup() and register msCleanup() */ %init %{ /* See bug 1203 for discussion of race condition with GD font cache */ if (msSetup() != MS_SUCCESS) { msSetError(MS_MISCERR, "Failed to set up threads and font cache", "msSetup()"); } Py_AtExit(msCleanup); /* Define Generic MapServer error */ MSExc_MapServerError=PyErr_NewException("_mapscript.MapServerError",NULL,NULL); if (MSExc_MapServerError != NULL) PyDict_SetItemString(d, "MapServerError", MSExc_MapServerError); /* Define MapServer MS_CHILD error */ MSExc_MapServerChildError = PyErr_NewException("_mapscript.MapServerChildError", NULL, NULL); if (MSExc_MapServerChildError != NULL) PyDict_SetItemString(d, "MapServerChildError", MSExc_MapServerChildError); %} %{ static void _raise_ms_exception( void ); static void _raise_ms_exception() { int errcode; errorObj *ms_error; char *errmsg; ms_error = msGetErrorObj(); errcode = ms_error->code; errmsg = msGetErrorString("\n"); switch (errcode) { case MS_IOERR: PyErr_SetString(PyExc_IOError, errmsg); break; case MS_MEMERR: PyErr_SetString(PyExc_MemoryError, errmsg); break; case MS_TYPEERR: PyErr_SetString(PyExc_TypeError, errmsg); break; case MS_EOFERR: PyErr_SetString(PyExc_EOFError, errmsg); break; case MS_CHILDERR: PyErr_SetString(MSExc_MapServerChildError, errmsg); break; default: PyErr_SetString(MSExc_MapServerError, errmsg); break; } free(errmsg); } %} %exception { $action { errorObj *ms_error = msGetErrorObj(); switch(ms_error->code) { case MS_NOERR: break; case MS_NOTFOUND: msResetErrorList(); break; case -1: break; case MS_IOERR: if (strcmp(ms_error->routine, "msSearchDiskTree()") != 0) { _raise_ms_exception(); msResetErrorList(); return NULL; } default: _raise_ms_exception(); msResetErrorList(); return NULL; } } } %pythoncode %{ MapServerError = _mapscript.MapServerError MapServerChildError = _mapscript.MapServerChildError %} /* The bogus "if 1:" is to introduce a new scope to work around indentation handling with pythonappend in different versions. (#3180) */ %feature("pythonappend") layerObj %{if 1: self.p_map=None try: # python 2.5 if args and len(args)!=0: self.p_map=args[0] except NameError: # python 2.6 if map: self.p_map=map %} /* The bogus "if 1:" is to introduce a new scope to work around indentation handling with pythonappend in different versions. (#3180) */ %feature("pythonappend") classObj %{if 1: self.p_layer =None try: # python 2.5 if args and len(args)!=0: self.p_layer=args[0] except NameError: # python 2.6 if layer: self.p_layer=layer %} %feature("shadow") insertClass %{ def insertClass(*args): actualIndex=$action(*args) args[1].p_layer=args[0] return actualIndex%} %feature("shadow") getClass %{ def getClass(*args): clazz = $action(*args) if clazz: if args and len(args)!=0: clazz.p_layer=args[0] else: clazz.p_layer=None return clazz%} %feature("shadow") insertLayer %{ def insertLayer(*args): actualIndex=$action(*args) args[1].p_map=args[0] return actualIndex%} %feature("shadow") getLayer %{ def getLayer(*args): layer = $action(*args) if layer: if args and len(args)!=0: layer.p_map=args[0] else: layer.p_map=None return layer%} %feature("shadow") getLayerByName %{ def getLayerByName(*args): layer = $action(*args) if layer: if args and len(args)!=0: layer.p_map=args[0] else: layer.p_map=None return layer%} mapserver-7.4.3/mapscript/python/requirements-dev.txt000066400000000000000000000000651357574274700231420ustar00rootroot00000000000000pytest pillow wheel>=0.31.1 setuptools>=40.2.0 flake8mapserver-7.4.3/mapscript/python/setup.py.in000066400000000000000000000033171357574274700212240ustar00rootroot00000000000000from io import open from setuptools import setup, find_packages, Distribution class BinaryDistribution(Distribution): """ Distribution which always forces a binary package with platform name See http://lucumr.pocoo.org/2014/1/27/python-on-wheels/ and https://stackoverflow.com/questions/24071491/how-can-i-make-a-python-wheel-from-an-existing-native-library """ def has_ext_modules(foo): return True def is_pure(self): return False def readme(): with open('README.rst', "r", encoding="utf-8") as f: return f.read() setup( name="mapscript", description = "MapServer Python MapScript bindings", long_description=readme(), classifiers = [ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'Intended Audience :: Science/Research', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: C', 'Programming Language :: C++', 'Topic :: Scientific/Engineering :: GIS', 'Topic :: Scientific/Engineering :: Information Analysis', ], author = "Steve Lime", license = "MIT", url="http://www.mapserver.org", version="@MapServer_VERSION_MAJOR@.@MapServer_VERSION_MINOR@.@MapServer_VERSION_REVISION@", packages=find_packages(), package_data={ # list the files to include starting with the most deeply nested folder or they are overwritten 'mapscript': ['tests/data/vera/*.*', 'tests/data/*.*', '$'] }, distclass=BinaryDistribution )mapserver-7.4.3/mapscript/python/tests/000077500000000000000000000000001357574274700202435ustar00rootroot00000000000000mapserver-7.4.3/mapscript/python/tests/TESTING.txt000066400000000000000000000020541357574274700221220ustar00rootroot00000000000000.. $Id$ Python MapScript Unit Tests ======================================== Authors: Sean Gillies, sgillies@frii.com Howard Butler, hobu@iastate.edu Running the tests ----------------- To run all of the tests, change directory to cases and execute :: $ cd cases $ python runalltests.py -v This runs all tests found in every TestCase derived class defined in any module named "cases/*test.py". The tests cannot be run properly from another path. The unit test script will insert the local build directory produced by Python distutils into the head of the Python PATH. This allows us to run the unit tests before installing the mapscript module. The unit tests use a map config file, symbolset file, fontset file, and data located in the 'tests' directory of the mapserver distribution. If you encounter any errors, please create a new issue in the MapServer bug tracker http://mapserver.gis.umn.edu/bugs/enter_bug.cgi under the SWIG-MapScript component. Copy the relevant error messages and we'll get to the bug ASAP. Thanks! mapserver-7.4.3/mapscript/python/tests/cases/000077500000000000000000000000001357574274700213415ustar00rootroot00000000000000mapserver-7.4.3/mapscript/python/tests/cases/__init__.py000066400000000000000000000000001357574274700234400ustar00rootroot00000000000000mapserver-7.4.3/mapscript/python/tests/cases/class_test.py000066400000000000000000000073551357574274700240710ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of classObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase class ClassObjTestCase(unittest.TestCase): def testConstructorNoArg(self): c = mapscript.classObj() assert c.thisown == 1 assert c.layer is None assert c.numstyles == 0 def testConstructorWithArg(self): lyr = mapscript.layerObj() lyr.name = 'foo' c = mapscript.classObj(lyr) assert c.thisown == 1 assert c.layer.name == lyr.name assert c.numstyles == 0 class ClassCloningTestCase(unittest.TestCase): def testCloneClass(self): """check attributes of a cloned class""" c = mapscript.classObj() c.minscaledenom = 5.0 clone = c.clone() assert clone.thisown == 1 assert clone.minscaledenom == 5.0 class ClassIconTestCase(MapTestCase): """testing for bug 1250""" def testAlphaTransparentPixmap(self): lo = self.map.getLayerByName('INLINE-PIXMAP-RGBA') co = lo.getClass(0) self.map.selectOutputFormat('PNG') im = co.createLegendIcon(self.map, lo, 48, 48) im.save('testAlphaTransparentPixmapIcon.png') def testAlphaTransparentPixmapPNG24(self): lo = self.map.getLayerByName('INLINE-PIXMAP-RGBA') co = lo.getClass(0) self.map.selectOutputFormat('PNG24') im = co.createLegendIcon(self.map, lo, 48, 48) im.save('testAlphaTransparentPixmapIcon24.png') def testAlphaTransparentPixmapJPG(self): lo = self.map.getLayerByName('INLINE-PIXMAP-RGBA') co = lo.getClass(0) self.map.selectOutputFormat('JPEG') im = co.createLegendIcon(self.map, lo, 48, 48) im.save('testAlphaTransparentPixmapIcon.jpg') def testIndexedTransparentPixmap(self): lo = self.map.getLayerByName('INLINE-PIXMAP-PCT') lo.type = mapscript.MS_LAYER_POINT co = lo.getClass(0) self.map.selectOutputFormat('PNG') im = co.createLegendIcon(self.map, lo, 32, 32) im.save('testIndexedTransparentPixmapIcon.png') def testIndexedTransparentPixmapJPG(self): lo = self.map.getLayerByName('INLINE-PIXMAP-PCT') lo.type = mapscript.MS_LAYER_POINT co = lo.getClass(0) self.map.selectOutputFormat('JPEG') im = co.createLegendIcon(self.map, lo, 32, 32) im.save('testIndexedTransparentPixmapIcon.jpg') if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/clone_test.py000066400000000000000000000075671357574274700240710ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of map cloning # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import TESTMAPFILE class MapCloneTestCase(unittest.TestCase): """Base class for testing with a map fixture""" def setUp(self): self.mapobj_orig = mapscript.mapObj(TESTMAPFILE) self.mapobj_clone = self.mapobj_orig.clone() def tearDown(self): self.mapobj_orig = None self.mapobj_clone = None class MapCloningTestCase(MapCloneTestCase): def testClonedName(self): """MapCloningTestCase.testClonedName: the name of a cloned map equals the original""" assert self.mapobj_clone.name == self.mapobj_orig.name def testClonedLayers(self): """MapCloningTestCase.testClonedLayers: the layers of a cloned map equal the original""" assert self.mapobj_clone.numlayers == self.mapobj_orig.numlayers assert self.mapobj_clone.getLayer(0).data \ == self.mapobj_orig.getLayer(0).data def testSetFontSet(self): """MapCloningTestCase.testSetFontSet: the number of fonts in a cloned map equal original""" assert self.mapobj_clone.fontset.numfonts == 2 def testSetSymbolSet(self): """MapCloningTestCase.testSetSymbolSet: the number of symbols in a cloned map equal original""" num = self.mapobj_clone.symbolset.numsymbols assert num == 5, num def testDrawClone(self): """drawing a cloned map works properly""" msimg = self.mapobj_clone.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testClone.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testDrawCloneJPEG(self): """drawing a cloned map works properly""" self.mapobj_clone.selectOutputFormat('JPEG') self.mapobj_clone.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON msimg = self.mapobj_clone.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testClone.jpg' fh = open(filename, 'wb') fh.write(data) fh.close() def testDrawClonePNG24(self): """drawing a cloned map works properly""" self.mapobj_clone.selectOutputFormat('PNG24') self.mapobj_clone.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON msimg = self.mapobj_clone.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testClonePNG24.png' fh = open(filename, 'wb') fh.write(data) fh.close() if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/color_test.py000066400000000000000000000061361357574274700240760ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of colorObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript class ColorObjTestCase(unittest.TestCase): def testColorObjConstructorNoArgs(self): """a color can be initialized with no arguments""" c = mapscript.colorObj() assert (c.red, c.green, c.blue, c.alpha) == (0, 0, 0, 255) def testColorObjConstructorArgs(self): """a color can be initialized with arguments""" c = mapscript.colorObj(1, 2, 3, 4) assert (c.red, c.green, c.blue, c.alpha) == (1, 2, 3, 4) def testColorObjToHex(self): """a color can be outputted as hex""" c = mapscript.colorObj(255, 255, 255) assert c.toHex() == '#ffffff' def testColorObjToHexBadly(self): """raise an error in the case of an undefined color""" c = mapscript.colorObj(-1, -1, -1) self.assertRaises(mapscript.MapServerError, c.toHex) def testColorObjSetRGB(self): """a color can be set using setRGB method""" c = mapscript.colorObj() c.setRGB(255, 255, 255, 100) assert (c.red, c.green, c.blue, c.alpha) == (255, 255, 255, 100) def testColorObjSetHexLower(self): """a color can be set using lower case hex""" c = mapscript.colorObj() c.setHex('#ffffff64') assert (c.red, c.green, c.blue, c.alpha) == (255, 255, 255, 100) def testColorObjSetHexUpper(self): """a color can be set using upper case hex""" c = mapscript.colorObj() c.setHex('#FFFFFF') assert (c.red, c.green, c.blue) == (255, 255, 255) def testColorObjSetHexBadly(self): """invalid hex color string raises proper error""" c = mapscript.colorObj() self.assertRaises(mapscript.MapServerError, c.setHex, '#fffffg') if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/font_test.py000066400000000000000000000055651357574274700237330ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of hashTableObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import os import unittest import mapscript from .testing import TESTS_PATH class FontTestCase(unittest.TestCase): def testSettingFonts(self): mo = mapscript.mapObj() assert mo.fontset.numfonts == 0 mo.fontset.fonts.set('Vera', os.path.join(TESTS_PATH, 'vera', 'Vera.ttf')) # NB: this does *not* increment the fonset.numfonts -- new bug mo.setSize(300, 300) mo.setExtent(-1.0, -1.0, 1.0, 1.0) lo = mapscript.layerObj() lo.type = mapscript.MS_LAYER_POINT lo.connectiontype = mapscript.MS_INLINE lo.status = mapscript.MS_DEFAULT co = mapscript.classObj() lbl = mapscript.labelObj() lbl.type = mapscript.MS_TRUETYPE lbl.font = 'Vera' lbl.size = 10 lbl.color.setHex('#000000') co.addLabel(lbl) so = mapscript.styleObj() so.symbol = 0 so.color.setHex('#000000') co.insertStyle(so) lo.insertClass(co) li = mo.insertLayer(lo) lo = mo.getLayer(li) point = mapscript.pointObj(0, 0) line = mapscript.lineObj() line.add(point) shape = mapscript.shapeObj(lo.type) shape.add(line) shape.setBounds() shape.text = 'Foo' shape.classindex = 0 lo.addFeature(shape) im = mo.draw() # im = mo.prepareImage() # shape.draw(mo, lo, im) im.save('testSettingFonts.png') if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/hash_test.py000066400000000000000000000125041357574274700236770ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of hashTableObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase # =========================================================================== # Base class for hashtable tests. Derived classes use these tests, but # defined different values for self.table. class HashTableBaseTestCase(object): keys = ['key1', 'key2', 'key3', 'key4'] values = ['value1', 'value2', 'value3', 'value4'] def testUseNonExistentKey(self): assert self.table.get('bogus') is None def testUseNonExistentKeyWithDefault(self): assert self.table.get('bogus', 'default') == 'default' def testGetValue(self): for key, value in zip(self.keys, self.values): assert self.table.get(key) == value assert self.table.get(key.upper()) == value assert self.table.get(key.capitalize()) == value def testGetValueWithDefault(self): for key, value in zip(self.keys, self.values): assert self.table.get(key, 'foo') == value assert self.table.get(key.upper(), 'foo') == value assert self.table.get(key.capitalize(), 'foo') == value def testClear(self): self.table.clear() for key in self.keys: assert self.table.get(key) is None def testRemoveItem(self): key = self.keys[0] self.table.remove(key) assert self.table.get(key) is None def testNextKey(self): key = self.table.nextKey() assert key == self.keys[0], key for i in range(1, len(self.keys)): key = self.table.nextKey(key) assert key == self.keys[i], key # We're at the end, next should be None key = self.table.nextKey(key) assert key is None, key # tests using the Python dictionary access methods def testDictKeys(self): assert sorted(self.keys) == sorted(self.table.keys()) def testDictItems(self): assert len(self.keys) == len(self.table) def testCheckDictContains(self): for key in self.keys: assert key in self.table.keys() def testGetDictValue(self): for key, value in zip(self.keys, self.values): assert self.table[key] == value assert self.table[key.upper()] == value assert self.table[key.capitalize()] == value def testRemoveDictItem(self): key = self.keys[0] del self.table[key] assert self.table[key] is None # =========================================================================== # Test begins now # =========================================================================== # HashTable test case # class HashTableTestCase(unittest.TestCase, HashTableBaseTestCase): """Tests of the MapServer HashTable object""" def setUp(self): "our fixture is a HashTable with two items" self.table = mapscript.hashTableObj() for key, value in zip(self.keys, self.values): self.table.set(key, value) def tearDown(self): self.table = None def testConstructor(self): table = mapscript.hashTableObj() assert table.__class__.__name__ == "hashTableObj", table # ============================================================================== # following tests use the tests/test.map fixture class WebMetadataTestCase(MapTestCase, HashTableBaseTestCase): def setUp(self): MapTestCase.setUp(self) self.table = self.map.web.metadata self.keys = ['key1', 'key2', 'key3', 'key4', 'ows_enable_request'] self.values = ['value1', 'value2', 'value3', 'value4', '*'] def tearDown(self): MapTestCase.tearDown(self) self.table = None class LayerMetadataTestCase(WebMetadataTestCase): def setUp(self): MapTestCase.setUp(self) self.table = self.map.getLayer(1).metadata class ClassMetadataTestCase(WebMetadataTestCase): def setUp(self): MapTestCase.setUp(self) self.table = self.map.getLayer(1).getClass(0).metadata if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/image_test.py000066400000000000000000000136761357574274700240510ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of map cloning # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest from io import BytesIO import urllib import mapscript from .testing import TEST_IMAGE as test_image from .testing import MapTestCase have_image = 0 try: from PIL import Image have_image = 1 except ImportError: pass class SaveToStringTestCase(MapTestCase): def testSaveToString(self): """test that an image can be saved as a string""" msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testSaveToString.png' fh = open(filename, 'wb') fh.write(data) fh.close() if have_image: pyimg = Image.open(filename) assert pyimg.format == 'PNG' assert pyimg.size == (200, 200) assert pyimg.mode == 'RGB' else: assert 1 class ImageObjTestCase(unittest.TestCase): def testConstructor(self): """imageObj constructor works""" imgobj = mapscript.imageObj(10, 10) assert imgobj.thisown == 1 assert imgobj.height == 10 assert imgobj.width == 10 def testConstructorWithFormat(self): """imageObj with an optional driver works""" driver = 'AGG/PNG' format = mapscript.outputFormatObj(driver) imgobj = mapscript.imageObj(10, 10, format) assert imgobj.thisown == 1 assert imgobj.format.driver == driver assert imgobj.height == 10 assert imgobj.width == 10 def xtestConstructorFilename(self): """imageObj with a filename works""" imgobj = mapscript.imageObj(test_image) assert imgobj.thisown == 1 assert imgobj.height == 200 assert imgobj.width == 200 imgobj.save('testConstructorFilename.png') def xtestConstructorFilenameDriver(self): """imageObj with a filename and a driver works""" imgobj = mapscript.imageObj(test_image) assert imgobj.thisown == 1 assert imgobj.height == 200 assert imgobj.width == 200 imgobj.save('testConstructorFilenameDriver.png') def xtestConstructorStream(self): """imageObj with a file stream works""" f = open(test_image, 'rb') imgobj = mapscript.imageObj(f) f.close() assert imgobj.thisown == 1 assert imgobj.height == 200 assert imgobj.width == 200 def xtestConstructorBytesIO(self): """imageObj with a BytesIO works""" with open(test_image, 'rb') as f: data = f.read() s = BytesIO(data) imgobj = mapscript.imageObj(s) assert imgobj.thisown == 1 assert imgobj.height == 200 assert imgobj.width == 200 def xtestConstructorUrlStream(self): """imageObj with a URL stream works""" url = urllib.urlopen('http://mapserver.org/_static/banner.png') imgobj = mapscript.imageObj(url, 'AGG/JPEG') assert imgobj.thisown == 1 assert imgobj.height == 68 assert imgobj.width == 439 imgobj.save('testConstructorUrlStream.jpg') class ImageWriteTestCase(MapTestCase): def testImageWrite(self): """image writes data to an open filehandle""" image = self.map.draw() assert image.thisown == 1 filename = 'testImageWrite.png' fh = open(filename, 'wb') image.write(fh) fh.close() if have_image: pyimg = Image.open(filename) assert pyimg.format == 'PNG' assert pyimg.size == (200, 200) assert pyimg.mode == 'RGB' else: assert 1 def testImageWriteBytesIO(self): """image writes data to a BytesIO instance""" image = self.map.draw() assert image.thisown == 1 s = BytesIO() image.write(s) filename = 'testImageWriteBytesIO.png' with open(filename, 'wb') as fh: fh.write(s.getvalue()) if have_image: pyimg = Image.open(filename) assert pyimg.format == 'PNG' assert pyimg.size == (200, 200) assert pyimg.mode == 'RGB' else: assert 1 def testImageGetBytes(self): """image returns bytes""" image = self.map.draw() assert image.thisown == 1 s = BytesIO(image.getBytes()) filename = 'testImageGetBytes.png' with open(filename, 'wb') as fh: fh.write(s.getvalue()) if have_image: pyimg = Image.open(filename) assert pyimg.format == 'PNG' assert pyimg.size == (200, 200) assert pyimg.mode == 'RGB' else: assert 1 if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/label_test.py000066400000000000000000000045171357574274700240400ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Map # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase class NewLabelsTestCase(MapTestCase): def testLabelBinding(self): """attribute binding can be set and get""" new_label = mapscript.labelObj() assert (not new_label.getBinding(mapscript.MS_LABEL_BINDING_COLOR)) new_label.setBinding(mapscript.MS_LABEL_BINDING_COLOR, "NEW_BINDING") assert (new_label.getBinding(mapscript.MS_LABEL_BINDING_COLOR) == "NEW_BINDING") class LabelCacheMemberTestCase(MapTestCase): def testCacheMemberText(self): """string attribute has been renamed to 'text' (bug 852)""" lo = self.map.getLayerByName('POINT') lo.status = mapscript.MS_ON img = self.map.draw() assert img is not None assert self.map.labelcache.num_rendered_members == 1, self.map.labelcache.num_rendered_members # label = self.map.nextLabel() # assert label.text == 'A Point', label.text if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/layer_test.py000066400000000000000000000421101357574274700240640ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Layer # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest from random import random import mapscript from .testing import MapTestCase class MapLayerTestCase(MapTestCase): def setUp(self): MapTestCase.setUp(self) self.layer = self.map.getLayer(1) class LayerConstructorTestCase(MapLayerTestCase): def testLayerConstructorNoArg(self): """test layer constructor with no argument""" layer = mapscript.layerObj() assert layer.__class__.__name__ == "layerObj" assert layer.thisown == 1 assert layer.index == -1 assert layer.map is None, layer.map def testLayerConstructorMapArg(self): """test layer constructor with map argument""" layer = mapscript.layerObj(self.map) assert layer.__class__.__name__ == "layerObj" assert layer.thisown == 1 lyr = self.map.getLayer(self.map.numlayers-1) assert lyr is not None # assert str(layer) == str(lyr) # TODO - check why these are not equal assert layer.map is not None, layer.map class LayerItemDefinitionTestCase(MapLayerTestCase): def setUp(self): MapTestCase.setUp(self) self.layer = self.map.getLayerByName('POINT') self.layer.open() def tearDown(self): self.layer.close() def testLayerGetItemType(self): """test getting layer item information for the first item""" item_type = self.layer.getItemType(0) assert item_type == "Integer" def testLayerGetItemDefinition2(self): """test getting layer item information for the second item""" item_type = self.layer.getItemType(1) assert item_type == "Character" def testLayerGetMissingItemType(self): """test getting item information for a non-existent index""" item_type = self.layer.getItemType(100) assert item_type is None def testLayerGetItemTypeClosedLayer(self): """item definition will be None for a closed layer""" self.layer.close() item_type = self.layer.getItemType(0) assert item_type is None def testLayerGetNonDefinedItemType(self): """test getting layer item information for a layer with gml_types auto""" layer = self.map.getLayerByName('POLYGON') layer.open() item_type = layer.getItemType(0) assert item_type == "" layer.close() class LayerCloningTestCase(MapLayerTestCase): def testLayerCloning(self): """check attributes of a cloned layer""" clone = self.layer.clone() assert clone.thisown == 1 assert str(clone) != str(self.layer) assert clone.name == self.layer.name assert clone.numclasses == self.layer.numclasses assert clone.map is None, clone.map assert clone.data == self.layer.data class LayerExtentTestCase(MapTestCase): def setUp(self): MapTestCase.setUp(self) self.layer = self.map.getLayerByName('POLYGON') def testPolygonExtent(self): """retrieve the extent of a polygon layer""" e = mapscript.rectObj() self.assertRectsEqual(e, self.layer.extent) def testPolygonGetExtent(self): """retrieve the extent of a polygon layer""" e = mapscript.rectObj(-0.25, 51.227222, 0.25, 51.727222) self.assertRectsEqual(e, self.layer.getExtent()) def testGetPresetExtent(self): """test layer.setExtent() and layer.getExtent() to return preset instead of calculating extents""" r = mapscript.rectObj(1.0, 1.0, 3.0, 3.0) self.layer.setExtent(r.minx, r.miny, r.maxx, r.maxy) rect = self.layer.extent assert r.minx == rect.minx, rect assert r.miny == rect.miny, rect.miny assert r.maxx == rect.maxx, rect.maxx assert r.maxy == rect.maxy, rect.maxy def testResetLayerExtent(self): """test resetting a layer's extent""" layer = self.map.getLayerByName('POLYGON') layer.setExtent() self.assertRectsEqual(layer.extent, mapscript.rectObj()) def testDirectExtentAccess(self): """direct access to a layer's extent works properly""" pt_layer = self.map.getLayerByName('POINT') rect = pt_layer.extent assert str(pt_layer.extent) == str(rect), (pt_layer.extent, rect) e = mapscript.rectObj(-0.5, 51.0, 0.5, 52.0) self.assertRectsEqual(e, rect) class LayerRasterProcessingTestCase(MapLayerTestCase): def testSetProcessing(self): """setting a layer's processing directive works""" self.layer.setProcessing('directive0=foo') assert self.layer.numprocessing == 1, self.layer.numprocessing self.layer.setProcessing('directive1=bar') assert self.layer.numprocessing == 2, self.layer.numprocessing directives = [self.layer.getProcessing(i) for i in range(self.layer.numprocessing)] assert directives == ['directive0=foo', 'directive1=bar'] def testClearProcessing(self): """clearing a self.layer's processing directive works""" self.layer.setProcessing('directive0=foo') assert self.layer.numprocessing == 1, self.layer.numprocessing self.layer.setProcessing('directive1=bar') assert self.layer.numprocessing == 2, self.layer.numprocessing assert self.layer.clearProcessing() == mapscript.MS_SUCCESS class RemoveClassTestCase(MapLayerTestCase): def testRemoveClass1NumClasses(self): """RemoveClassTestCase.testRemoveClass1NumClasses: removing the layer's first class by index leaves one class left""" c = self.layer.removeClass(0) assert c.thisown == 1 assert self.layer.numclasses == 1 def testRemoveClass1ClassName(self): """RemoveClassTestCase.testRemoveClass1ClassName: confirm removing the layer's first class reverts the name of the second class""" c2name = self.layer.getClass(1).name c = self.layer.removeClass(0) assert c is not None assert self.layer.getClass(0).name == c2name def testRemoveClass2NumClasses(self): """RemoveClassTestCase.testRemoveClass2NumClasses: removing the layer's second class by index leaves one class left""" c = self.layer.removeClass(1) assert c is not None assert self.layer.numclasses == 1 def testRemoveClass2ClassName(self): """RemoveClassTestCase.testRemoveClass2ClassName: confirm removing the layer's second class reverts the name of the first class""" c1name = self.layer.getClass(0).name c = self.layer.removeClass(1) assert c is not None assert self.layer.getClass(0).name == c1name class InsertClassTestCase(MapLayerTestCase): def testLayerInsertClass(self): """insert class at default index""" n = self.layer.numclasses new_class = mapscript.classObj() new_class.name = 'foo' new_index = self.layer.insertClass(new_class) assert new_index == n assert self.layer.numclasses == n + 1 c = self.layer.getClass(new_index) assert c.thisown == 1 assert c.name == new_class.name def testLayerInsertClassAtZero(self): """insert class at index 0""" n = self.layer.numclasses new_class = mapscript.classObj() new_class.name = 'foo' new_index = self.layer.insertClass(new_class, 0) assert new_index == 0 assert self.layer.numclasses == n + 1 c = self.layer.getClass(new_index) assert c.thisown == 1 assert c.name == new_class.name def testInsertNULLClass(self): """inserting NULL class should raise an error""" self.assertRaises(mapscript.MapServerChildError, self.layer.insertClass, None) class LayerTestCase(MapTestCase): def testLayerConstructorOwnership(self): """LayerTestCase.testLayerConstructorOwnership: newly constructed layer has proper ownership""" layer = mapscript.layerObj(self.map) assert layer.thisown == 1 def testGetLayerOrder(self): """LayerTestCase.testGetLayerOrder: get layer drawing order""" order = self.map.getLayerOrder() assert order == tuple(range(7)), order def testSetLayerOrder(self): """LayerTestCase.testSetLayerOrder: set layer drawing order""" ord = (1, 0, 2, 3, 4, 5, 6) self.map.setLayerOrder(ord) order = self.map.getLayerOrder() assert order == ord, order # Layer removal tests class RemoveLayerTestCase(MapTestCase): def testRemoveLayer1NumLayers(self): """removing the first layer by index from the mapfile leaves three""" self.map.removeLayer(0) assert self.map.numlayers == 6 def testRemoveLayer1LayerName(self): """removing first layer reverts it to the second layer's name""" l2name = self.map.getLayer(1).name self.map.removeLayer(0) assert self.map.getLayer(0).name == l2name def testRemoveLayer2NumLayers(self): """removing second layer by index from mapfile leaves three layers""" self.map.removeLayer(1) assert self.map.numlayers == 6 def testRemoveLayer2LayerName(self): """removing of the second layer reverts it to the first layer's name""" l1name = self.map.getLayer(0).name self.map.removeLayer(1) assert self.map.getLayer(0).name == l1name class ExpressionTestCase(MapLayerTestCase): def testClearExpression(self): """layer expression can be properly cleared""" self.layer.setFilter('') fs = self.layer.getFilterString() assert fs is None, fs def testSetStringExpression(self): """layer expression can be set to string""" self.layer.setFilter('foo') fs = self.layer.getFilterString() self.layer.filteritem = 'fid' assert fs == '"foo"', fs self.map.draw() def testSetQuotedStringExpression(self): """layer expression string can be quoted""" self.layer.setFilter('"foo"') fs = self.layer.getFilterString() self.layer.filteritem = 'fid' assert fs == '"foo"', fs self.map.draw() def testSetRegularExpression(self): """layer expression can be regular expression""" self.layer.setFilter('/foo/') self.layer.filteritem = 'fid' fs = self.layer.getFilterString() assert fs == '/foo/', fs self.map.draw() def testSetLogicalExpression(self): """layer expression can be logical expression""" self.layer.setFilter('([fid] >= 2)') fs = self.layer.getFilterString() assert fs == '([fid] >= 2)', fs self.map.draw() def testSetCompoundLogicalExpression(self): """layer expression can be a compound logical expression""" # filter = '( ([fid] >= 2) AND (\'[fname]\' == \'A Polygon\' ))' flt = """( ([fid] >= 2) AND ("[fname]" == 'A Polygon' ))""" excode = self.layer.setFilter(flt) assert excode == mapscript.MS_SUCCESS, excode fs = self.layer.getFilterString() assert fs == flt, fs self.map.draw() class LayerQueryTestCase(MapLayerTestCase): def setUp(self): MapLayerTestCase.setUp(self) self.layer = self.map.getLayerByName('POINT') self.layer.template = 'foo' class SpatialLayerQueryTestCase(LayerQueryTestCase): def testRectQuery(self): qrect = mapscript.rectObj(-10.0, 45.0, 10.0, 55.0) self.layer.queryByRect(self.map, qrect) assert self.layer.getNumResults() == 1 def testShapeQuery(self): qrect = mapscript.rectObj(-10.0, 45.0, 10.0, 55.0) qshape = qrect.toPolygon() self.layer.queryByShape(self.map, qshape) assert self.layer.getNumResults() == 1 def testPointQuery(self): qpoint = mapscript.pointObj(0.0, 51.5) self.layer.queryByPoint(self.map, qpoint, mapscript.MS_MULTIPLE, 2.0) assert self.layer.getNumResults() == 1 def testRectQueryNoResults(self): qrect = mapscript.rectObj(-101.0, 0.0, -100.0, 1.0) self.layer.queryByRect(self.map, qrect) assert self.layer.getNumResults() == 0 def testShapeQueryNoResults(self): qrect = mapscript.rectObj(-101.0, 0.0, -100.0, 1.0) qshape = qrect.toPolygon() self.layer.queryByShape(self.map, qshape) assert self.layer.getNumResults() == 0 def testPointQueryNoResults(self): qpoint = mapscript.pointObj(-100.0, 51.5) self.layer.queryByPoint(self.map, qpoint, mapscript.MS_MULTIPLE, 2.0) assert self.layer.getNumResults() == 0 class AttributeLayerQueryTestCase(LayerQueryTestCase): def testAttributeQuery(self): self.layer.queryByAttributes(self.map, "FNAME", '"A Point"', mapscript.MS_MULTIPLE) assert self.layer.getNumResults() == 1 def testLogicalAttributeQuery(self): self.layer.queryByAttributes(self.map, None, '("[FNAME]" == "A Point")', mapscript.MS_MULTIPLE) assert self.layer.getNumResults() == 1 def testAttributeQueryNoResults(self): self.layer.queryByAttributes(self.map, "FNAME", '"Bogus Point"', mapscript.MS_MULTIPLE) assert self.layer.getNumResults() == 0 class LayerVisibilityTestCase(MapLayerTestCase): def setUp(self): MapLayerTestCase.setUp(self) self.layer.minscaledenom = 1000 self.layer.maxscaledenom = 2000 self.layer.status = mapscript.MS_ON self.map.zoomScale(1500, mapscript.pointObj(100, 100), 200, 200, self.map.extent, None) def testInitialVisibility(self): """expect visibility""" assert self.layer.isVisible() == mapscript.MS_TRUE def testStatusOffVisibility(self): """expect false visibility after switching status off""" self.layer.status = mapscript.MS_OFF assert self.layer.isVisible() == mapscript.MS_FALSE def testZoomOutVisibility(self): """expect false visibility after zooming out beyond maximum""" self.map.zoomScale(2500, mapscript.pointObj(100, 100), 200, 200, self.map.extent, None) assert self.layer.isVisible() == mapscript.MS_FALSE class InlineLayerTestCase(unittest.TestCase): def setUp(self): # Inline feature layer self.ilayer = mapscript.layerObj() self.ilayer.type = mapscript.MS_LAYER_POLYGON self.ilayer.status = mapscript.MS_DEFAULT self.ilayer.connectiontype = mapscript.MS_INLINE cs = 'f7fcfd, e5f5f9, ccece6, 99d8c9, 66c2a4, 41ae76, 238b45, 006d2c, 00441b' colors = ['#' + h for h in cs.split(', ')] for i in range(9): # Make a class for feature ci = self.ilayer.insertClass(mapscript.classObj()) co = self.ilayer.getClass(ci) si = co.insertStyle(mapscript.styleObj()) so = co.getStyle(si) so.color.setHex(colors[i]) li = co.addLabel(mapscript.labelObj()) lbl = co.getLabel(li) lbl.color.setHex('#000000') lbl.outlinecolor.setHex('#FFFFFF') lbl.type = mapscript.MS_BITMAP lbl.size = mapscript.MS_SMALL # The shape to add is randomly generated xc = 4.0*(random() - 0.5) yc = 4.0*(random() - 0.5) r = mapscript.rectObj(xc-0.25, yc-0.25, xc+0.25, yc+0.25) s = r.toPolygon() # Classify s.classindex = i s.text = "F%d" % (i) # Add to inline feature layer self.ilayer.addFeature(s) def testExternalClassification(self): mo = mapscript.mapObj() mo.setSize(400, 400) mo.setExtent(-2.5, -2.5, 2.5, 2.5) mo.selectOutputFormat('image/png') mo.insertLayer(self.ilayer) im = mo.draw() im.save('testExternalClassification.png') if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/line_test.py000066400000000000000000000063551357574274700237120ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Map "zooming" # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapPrimitivesTestCase class LineObjTestCase(MapPrimitivesTestCase): """Testing the lineObj class in stand-alone mode""" def setUp(self): """The test fixture is a line with two points""" self.points = (mapscript.pointObj(0.0, 1.0), mapscript.pointObj(2.0, 3.0)) self.line = mapscript.lineObj() self.addPointToLine(self.line, self.points[0]) self.addPointToLine(self.line, self.points[1]) def testCreateLine(self): """created line has the correct number of points""" assert self.line.numpoints == 2 def testGetPointsFromLine(self): """points in the line share are the same that were input""" for i in range(len(self.points)): got_point = self.getPointFromLine(self.line, i) self.assertPointsEqual(got_point, self.points[i]) def testAddPointToLine(self): """adding a point to a line behaves correctly""" new_point = mapscript.pointObj(4.0, 5.0) self.addPointToLine(self.line, new_point) assert self.line.numpoints == 3 def xtestAlterNumPoints(self): """ numpoints is immutable, this should raise error """ # The following works locally but fails on Appveyor (error is not raised) # with self.assertRaises(AttributeError): # self.line.numpoints = 3 # the following approach also fails on appveyor error_thrown = False try: self.line.numpoints = 3 except AttributeError: error_thrown = True assert error_thrown is True def testLineGeoInterface(self): """return line using the __geo_interface__ protocol""" assert self.line.__geo_interface__ == {"type": "LineString", "coordinates": [(0.0, 1.0), (2.0, 3.0)]} if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/map_test.py000066400000000000000000000332421357574274700235330ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Map # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase, TESTMAPFILE class MapConstructorTestCase(unittest.TestCase): def testMapConstructorNoArg(self): """MapConstructorTestCase.testMapConstructorNoArg: test map constructor with no argument""" test_map = mapscript.mapObj() assert test_map.__class__.__name__ == "mapObj" assert test_map.thisown == 1 def testMapConstructorEmptyStringArg(self): """MapConstructorTestCase.testMapConstructorEmptyStringArg: test map constructor with old-style empty string argument""" test_map = mapscript.mapObj('') assert test_map.__class__.__name__ == "mapObj" assert test_map.thisown == 1 def testMapConstructorFilenameArg(self): """MapConstructorTestCasetest.testMapConstructorEmptyStringArg: map constructor with filename argument""" test_map = mapscript.mapObj(TESTMAPFILE) assert test_map.__class__.__name__ == "mapObj" assert test_map.thisown == 1 class MapExtentTestCase(MapTestCase): def testSetExtent(self): """MapExtentTestCase.testSetExtent: test the setting of a mapObj's extent""" test_map = mapscript.mapObj(TESTMAPFILE) e = test_map.extent result = test_map.setExtent(e.minx, e.miny, e.maxx, e.maxy) self.assertAlmostEqual(test_map.scaledenom, 14.24445829) assert result == mapscript.MS_SUCCESS, result def testSetExtentBadly(self): """MapExtentTestCase.testSetExtentBadly: test that mapscript raises an error for an invalid mapObj extent""" test_map = mapscript.mapObj(TESTMAPFILE) self.assertRaises(mapscript.MapServerError, test_map.setExtent, 1.0, -2.0, -3.0, 4.0) def testReBindingExtent(self): """test the rebinding of a map's extent""" test_map = mapscript.mapObj(TESTMAPFILE) rect1 = mapscript.rectObj(-10.0, -10.0, 10.0, 10.0) rect2 = mapscript.rectObj(-10.0, -10.0, 10.0, 10.0) test_map.extent = rect1 assert repr(test_map.extent) != repr(rect1), (test_map.extent, rect1) del rect1 self.assertRectsEqual(test_map.extent, rect2) class MapLayersTestCase(MapTestCase): def testMapInsertLayer(self): """MapLayersTestCase.testMapInsertLayer: test insertion of a new layer at default (last) index""" n = self.map.numlayers layer = mapscript.layerObj() layer.name = 'new' assert layer.map is None, layer.map index = self.map.insertLayer(layer) assert layer.map is not None, layer.map assert index == n, index assert self.map.numlayers == n + 1 names = [self.map.getLayer(i).name for i in range(self.map.numlayers)] assert names == ['RASTER', 'POLYGON', 'LINE', 'POINT', 'INLINE', 'INLINE-PIXMAP-RGBA', 'INLINE-PIXMAP-PCT', 'new'] order = self.map.getLayerOrder() assert order == (0, 1, 2, 3, 4, 5, 6, 7), order def testMapInsertLayerAtZero(self): """MapLayersTestCase.testMapInsertLayerAtZero: test insertion of a new layer at first index""" n = self.map.numlayers layer = mapscript.layerObj() layer.name = 'new' assert layer.map is None, layer.map index = self.map.insertLayer(layer, 0) assert layer.map is not None, layer.map assert index == 0, index assert self.map.numlayers == n + 1 names = [self.map.getLayer(i).name for i in range(self.map.numlayers)] assert names == ['new', 'RASTER', 'POLYGON', 'LINE', 'POINT', 'INLINE', 'INLINE-PIXMAP-RGBA', 'INLINE-PIXMAP-PCT'], names order = self.map.getLayerOrder() assert order == (0, 1, 2, 3, 4, 5, 6, 7), order def testMapInsertLayerDrawingOrder(self): """MapLayersTestCase.testMapInsertLayerDrawingOrder: test affect of insertion of a new layer at index 1 on drawing order""" n = self.map.numlayers assert n == 7 # reverse layer drawing order o_start = (6, 5, 4, 3, 2, 1, 0) self.map.setLayerOrder(o_start) # insert Layer layer = mapscript.layerObj() layer.name = 'new' index = self.map.insertLayer(layer, 1) assert index == 1, index # We expect our new layer to be at index 1 in drawing order as well order = self.map.getLayerOrder() assert order == (7, 1, 6, 5, 4, 3, 2, 0), order def testMapInsertLayerBadIndex(self): """MapLayersTestCase.testMapInsertLayerBadIndex: expect an exception when index is too large""" layer = mapscript.layerObj() self.assertRaises(mapscript.MapServerChildError, self.map.insertLayer, layer, 1000) def testMapInsertNULLLayer(self): """expect an exception on attempt to insert a NULL Layer""" self.assertRaises(mapscript.MapServerChildError, self.map.insertLayer, None) def testMapRemoveLayerAtTail(self): """removal of highest index (tail) layer""" n = self.map.numlayers layer = self.map.removeLayer(n-1) assert self.map.numlayers == n-1 assert layer.name == 'INLINE-PIXMAP-PCT' assert layer.thisown == 1 del layer order = self.map.getLayerOrder() assert order == (0, 1, 2, 3, 4, 5), order def testMapRemoveLayerAtZero(self): """removal of lowest index (0) layer""" n = self.map.numlayers layer = self.map.removeLayer(0) assert self.map.numlayers == n-1 assert layer.name == 'RASTER' order = self.map.getLayerOrder() assert order == (0, 1, 2, 3, 4, 5), order def testMapRemoveLayerDrawingOrder(self): """test affect of layer removal on drawing order""" n = self.map.numlayers # reverse layer drawing order o_start = (6, 5, 4, 3, 2, 1, 0) self.map.setLayerOrder(o_start) layer = self.map.removeLayer(1) assert self.map.numlayers == n-1 assert layer.name == 'POLYGON' order = self.map.getLayerOrder() assert order == (5, 4, 3, 2, 1, 0), order names = [self.map.getLayer(i).name for i in range(self.map.numlayers)] assert names == ['RASTER', 'LINE', 'POINT', 'INLINE', 'INLINE-PIXMAP-RGBA', 'INLINE-PIXMAP-PCT'], names class MapExceptionTestCase(MapTestCase): def testDrawBadData(self): """MapExceptionTestCase.testDrawBadData: a bad data descriptor in a layer returns proper error""" self.map.getLayerByName('POLYGON').data = 'foo' self.assertRaises(mapscript.MapServerError, self.map.draw) class EmptyMapExceptionTestCase(unittest.TestCase): def setUp(self): self.map = mapscript.mapObj('') def tearDown(self): self.map = None def testDrawEmptyMap(self): """EmptyMapExceptionTestCase.testDrawEmptyMap: drawing an empty map returns proper error""" self.assertRaises(mapscript.MapServerError, self.map.draw) class MapMetaDataTestCase(MapTestCase): def testInvalidKeyAccess(self): """MapMetaDataTestCase.testInvalidKeyAccess: an invalid map metadata key returns proper error""" self.assertRaises(mapscript.MapServerError, self.map.getMetaData, 'foo') def testFirstKeyAccess(self): """MapMetaDataTestCase.testFirstKeyAccess: first metadata key is correct value""" key = self.map.getFirstMetaDataKey() assert key == 'key1' val = self.map.getMetaData(key) assert val == 'value1' def testLastKeyAccess(self): """MapMetaDataTestCase.testLastKeyAccess: last metadata key is correct value""" key = self.map.getFirstMetaDataKey() for i in range(4): key = self.map.getNextMetaDataKey(key) assert key is not None key = self.map.getNextMetaDataKey(key) assert key is None def testMapMetaData(self): """MapMetaDataTestCase.testMapMetaData: map metadata keys are correct values""" keys = [] key = self.map.getFirstMetaDataKey() if key is not None: keys.append(key) while 1: key = self.map.getNextMetaDataKey(key) if not key: break keys.append(key) assert keys == ['key1', 'key2', 'key3', 'key4', 'ows_enable_request'], keys def testLayerMetaData(self): """MapMetaDataTestCase.testLayerMetaData: layer metadata keys are correct values""" keys = [] key = self.map.getLayer(1).getFirstMetaDataKey() if key is not None: keys.append(key) while 1: key = self.map.getLayer(1).getNextMetaDataKey(key) if not key: break keys.append(key) assert keys == ['key1', 'key2', 'key3', 'key4'], keys def testClassMetaData(self): """MapMetaDataTestCase.testClassMetaData: class metadata keys are correct values""" keys = [] key = self.map.getLayer(1).getClass(0).getFirstMetaDataKey() if key is not None: keys.append(key) while 1: key = self.map.getLayer(1).getClass(0).getNextMetaDataKey(key) if not key: break keys.append(key) assert keys == ['key1', 'key2', 'key3', 'key4'], keys class NoFontSetTestCase(unittest.TestCase): def testNoGetFontSetFile(self): """an empty map should have fontset filename == None""" self.map = mapscript.mapObj() assert self.map.fontset.filename is None class MapFontSetTestCase(MapTestCase): def testGetFontSetFile(self): """expect fontset file to be 'fonts.txt'""" file = self.map.fontset.filename assert file == 'fonts.txt', file class MapSizeTestCase(MapTestCase): def testDefaultSize(self): assert self.map.width == 200 assert self.map.height == 200 def testSetSize(self): retval = self.map.setSize(480, 480) assert retval == mapscript.MS_SUCCESS, retval assert self.map.width == 480 assert self.map.height == 480 class MapSetWKTTestCase(MapTestCase): def testOGCWKT(self): self.map.setWKTProjection('''PROJCS["unnamed",GEOGCS["WGS 84",DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563]], PRIMEM["Greenwich",0], UNIT["Degree",0.0174532925199433]], PROJECTION["Albers_Conic_Equal_Area"], PARAMETER["standard_parallel_1", 65], PARAMETER["standard_parallel_2", 55], PARAMETER["latitude_of_center", 0], PARAMETER["longitude_of_center", -153], PARAMETER["false_easting", -4943910.68], PARAMETER["false_northing", 0], UNIT["metre",1.0] ]''') proj4 = self.map.getProjection() assert proj4.find('+proj=aea') != -1 assert proj4.find('+datum=WGS84') != -1 assert mapscript.projectionObj(proj4).getUnits() != mapscript.MS_DD def testESRIWKT(self): self.map.setWKTProjection('ESRI::PROJCS["Pulkovo_1995_GK_Zone_2", GEOGCS["GCS_Pulkovo_1995", ' 'DATUM["D_Pulkovo_1995", SPHEROID["Krasovsky_1940", 6378245, 298.3]], ' 'PRIMEM["Greenwich", 0], ' 'UNIT["Degree", 0.017453292519943295]], PROJECTION["Gauss_Kruger"], ' 'PARAMETER["False_Easting", 2500000], ' 'PARAMETER["False_Northing", 0], PARAMETER["Central_Meridian", 9], ' 'PARAMETER["Scale_Factor", 1], ' 'PARAMETER["Latitude_Of_Origin", 0], UNIT["Meter", 1]]') proj4 = self.map.getProjection() assert proj4.find('+proj=tmerc') != -1 assert proj4.find('+ellps=krass') != -1 assert (mapscript.projectionObj(proj4)).getUnits() != mapscript.MS_DD def testWellKnownGEOGCS(self): self.map.setWKTProjection('WGS84') proj4 = self.map.getProjection() assert proj4.find('+proj=longlat') != -1, proj4 assert proj4.find('+datum=WGS84') != -1, proj4 assert (mapscript.projectionObj(proj4)).getUnits() != mapscript.MS_METERS if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/outputformat_test.py000066400000000000000000000112771357574274700255330ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of outputFormatObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase class OutputFormatTestCase(unittest.TestCase): """http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=511""" def testOutputFormatConstructor(self): new_format = mapscript.outputFormatObj('GDAL/GTiff', 'gtiff') # assert new_format.refcount == 1, new_format.refcount assert new_format.name == 'gtiff' assert new_format.mimetype == 'image/tiff' class MapOutputFormatTestCase(MapTestCase): def testAppendNewOutputFormat(self): """test that a new output format can be created on-the-fly""" num = self.map.numoutputformats new_format = mapscript.outputFormatObj('GDAL/GTiff', 'gtiffx') # assert new_format.refcount == 1, new_format.refcount self.map.appendOutputFormat(new_format) assert self.map.numoutputformats == num + 1 # assert new_format.refcount == 2, new_format.refcount self.map.selectOutputFormat('gtiffx') self.map.save('testAppendNewOutputFormat.map') self.map.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON imgobj = self.map.draw() filename = 'testAppendNewOutputFormat.tif' imgobj.save(filename) def testRemoveOutputFormat(self): """testRemoveOutputFormat may fail depending on GD options""" num = self.map.numoutputformats new_format = mapscript.outputFormatObj('GDAL/GTiff', 'gtiffx') self.map.appendOutputFormat(new_format) assert self.map.numoutputformats == num + 1 # assert new_format.refcount == 2, new_format.refcount assert self.map.removeOutputFormat('gtiffx') == mapscript.MS_SUCCESS # assert new_format.refcount == 1, new_format.refcount assert self.map.numoutputformats == num self.assertRaises(mapscript.MapServerError, self.map.selectOutputFormat, 'gtiffx') self.map.selectOutputFormat('GTiff') assert self.map.outputformat.mimetype == 'image/tiff' def testBuiltInPNG24Format(self): """test built in PNG RGB format""" self.map.selectOutputFormat('PNG24') assert self.map.outputformat.mimetype == 'image/png' self.map.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON img = self.map.draw() assert img.format.mimetype == 'image/png' filename = 'testBuiltInPNG24Format.png' img.save(filename) def testBuiltInJPEGFormat(self): """test built in JPEG format""" self.map.selectOutputFormat('JPEG') assert self.map.outputformat.mimetype == 'image/jpeg' self.map.getLayerByName('INLINE-PIXMAP-RGBA').status = mapscript.MS_ON img = self.map.draw() assert img.format.mimetype == 'image/jpeg' filename = 'testBuiltInJPEGFormat.jpg' img.save(filename) def testSelectBuiltInJPEGFormat(self): """test selection of built-in JPEG format""" self.map.selectOutputFormat('JPEG') assert self.map.outputformat.mimetype == 'image/jpeg' class UnsupportedFormatTestCase(unittest.TestCase): """I (Sean) don't ever configure for PDF, so this is the unsupported format.""" def testCreateUnsupported(self): self.assertRaises(mapscript.MapServerError, mapscript.outputFormatObj, 'PDF') if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/ows_test.py000066400000000000000000000100201357574274700235530ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of OWS Requests # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase class OWSRequestTestCase(MapTestCase): def testInit(self): """OWSRequestTestCase.testInit: OWS initializer works right""" request = mapscript.OWSRequest() request.setParameter("BBOX", "-0.3, 51.2, 0.3, 51.8") assert request.NumParams == 1 assert request.getName(0) == "BBOX" assert request.getValue(0) == "-0.3, 51.2, 0.3, 51.8" def testGetParameter(self): """OWSRequestTestCase.testGetParameter: OWS can get request parameters by index""" request = mapscript.OWSRequest() request.setParameter('foo', 'bar') assert request.getValue(0) == 'bar' def testGetParameterByName(self): """OWSRequestTestCase.testGetParameterByName: OWS can get request parameters by name""" request = mapscript.OWSRequest() request.setParameter('foo', 'bar') assert request.getValueByName('Foo') == 'bar' def testResetParam(self): """OWSRequestTestCase.testResetParam: OWS can reset parameters by name""" request = mapscript.OWSRequest() request.setParameter('foo', 'bar') assert request.NumParams == 1 request.setParameter('Foo', 'bra') assert request.NumParams == 1 assert request.getValue(0) == 'bra' def testLoadWMSRequest(self): """OWSRequestTestCase.testLoadWMSRequest: OWS can load a WMS request""" request = mapscript.OWSRequest() request.setParameter("REQUEST", "GetMap") request.setParameter("VERSION", "1.1.0") request.setParameter("FORMAT", "image/png") request.setParameter("LAYERS", "POINT") request.setParameter("BBOX", "-0.30, 51.20, 0.30, 51.80") request.setParameter("SRS", "EPSG:4326") request.setParameter("HEIGHT", "60") request.setParameter("WIDTH", "60") request.setParameter("STYLES", "") for i in range(self.map.numlayers): self.map.getLayer(i).status = mapscript.MS_ON status = self.map.loadOWSParameters(request) assert status == mapscript.MS_SUCCESS, status self.assertEqual(self.map.height, 60) self.assertEqual(self.map.width, 60) self.assertEqual(self.map.getProjection(), "+init=epsg:4326") # MapServer extents are from middle of the pixel self.assertAlmostEqual(self.map.extent.minx, -0.295) self.assertAlmostEqual(self.map.extent.miny, 51.205) self.assertAlmostEqual(self.map.extent.maxx, 0.295) self.assertAlmostEqual(self.map.extent.maxy, 51.795) img = self.map.draw() img.save("test_load_ows_request.png") if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/parentreference_test.py000066400000000000000000000101171357574274700261220ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Map # Author: Umberto Nicoletti, unicoletti@prometeo.it # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import gc import unittest import mapscript from .testing import TESTMAPFILE class ParentReferenceTestCase(unittest.TestCase): def initMap(self): self.map = mapscript.mapObj(TESTMAPFILE) def testGetLayerObj(self): self.initMap() layer = self.map.getLayer(1) self.map = None assert str(layer.p_map).find('mapscript.mapObj') != -1 gc.collect() assert layer.map is not None, layer.map def testGetLayerObjByName(self): self.initMap() layer = self.map.getLayerByName('POLYGON') self.map = None assert str(layer.p_map).find('mapscript.mapObj') != -1 gc.collect() assert layer.map is not None, layer.map def testLayerObj(self): self.initMap() layer = mapscript.layerObj(self.map) self.map = None assert str(layer.p_map).find('mapscript.mapObj') != -1 gc.collect() assert layer.map is not None, layer.map def testInsertLayerObj(self): self.initMap() layer = mapscript.layerObj() self.map.insertLayer(layer) self.map = None assert str(layer.p_map).find('mapscript.mapObj') != -1 gc.collect() assert layer.map is not None, layer.map def testGetClassObj(self): self.initMap() layer = self.map.getLayer(1) clazz = layer.getClass(0) self.map = None layer = None assert str(clazz.p_layer).find('mapscript.layerObj') != -1 gc.collect() assert clazz.layer is not None, clazz.layer def testClassObj(self): self.initMap() layer = mapscript.layerObj(self.map) clazz = mapscript.classObj(layer) self.map = None layer = None assert str(clazz.p_layer).find('mapscript.layerObj') != -1 gc.collect() assert clazz.layer is not None, clazz.layer def testInsertClassObj(self): self.initMap() layer = mapscript.layerObj() clazz = mapscript.classObj() layer.insertClass(clazz) self.map = None layer = None assert str(clazz.p_layer).find('mapscript.layerObj') != -1 gc.collect() assert clazz.layer is not None, clazz.layer def testRemoveClassObj(self): self.initMap() layer = self.map.getLayer(1) clazz = layer.removeClass(0) if hasattr(clazz, 'p_layer'): assert clazz.p_layer is None, clazz.p_layer assert clazz.layer is None, clazz.layer self.initMap() position = self.map.getLayer(0).insertClass(clazz) assert position == 0, position assert clazz.p_layer is not None, clazz.p_layer assert clazz.layer is not None, clazz.layer if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/pgtest.py000066400000000000000000000113201357574274700232160ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of PostGIS Layer # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/cases/pgtest.py -v # # NOTE: these tests use a fixture included in mapserver/tests. To produce # the testing database, follow these steps: # # $ cd mapserver/tests # $ shp2pgsql -s 4326 -I polygon.shp postgis.polygon > polygon.sql # $ su postgres # $ make -f makefile_postgis # # =========================================================================== import unittest import mapscript PG_CONNECTION_STRING = "dbname=mapserver_test user=postgres" class TableTest(unittest.TestCase): def setUp(self): self.mo = mapscript.mapObj() lo = mapscript.layerObj() lo.name = 'pg_layer' lo.type = mapscript.MS_LAYER_POLYGON lo.connectiontype = mapscript.MS_POSTGIS lo.connection = PG_CONNECTION_STRING lo.data = "the_geom from polygon" li = self.mo.insertLayer(lo) self.lo = self.mo.getLayer(li) def test_getfeature(self): self.lo.open() f = self.lo.getFeature(1, -1) atts = [f.getValue(i) for i in range(self.lo.numitems)] self.lo.close() self.assertEqual(atts, ['1', '1', 'A Polygon'], atts) class ViewTest(unittest.TestCase): def setUp(self): self.mo = mapscript.mapObj() lo = mapscript.layerObj() lo.name = 'pg_sub_layer' lo.type = mapscript.MS_LAYER_POLYGON lo.connectiontype = mapscript.MS_POSTGIS lo.connection = PG_CONNECTION_STRING lo.data = "the_geom from polygon_v using unique gid using srid=4326" li = self.mo.insertLayer(lo) self.lo = self.mo.getLayer(li) def test_getfeature(self): self.lo.open() f = self.lo.getFeature(1, -1) atts = [f.getValue(i) for i in range(self.lo.numitems)] self.lo.close() self.assertEqual(atts, ['1', '1', 'A Polygon'], atts) class SubSelectTest(unittest.TestCase): def setUp(self): self.mo = mapscript.mapObj() lo = mapscript.layerObj() lo.name = 'pg_sub_layer' lo.type = mapscript.MS_LAYER_POLYGON lo.connectiontype = mapscript.MS_POSTGIS lo.connection = PG_CONNECTION_STRING lo.data = "the_geom from (select * from polygon) as foo using unique gid using srid=4326" li = self.mo.insertLayer(lo) self.lo = self.mo.getLayer(li) def test_getfeature(self): self.lo.open() f = self.lo.getFeature(1, -1) atts = [f.getValue(i) for i in range(self.lo.numitems)] self.lo.close() self.assertEqual(atts, ['1', '1', 'A Polygon'], atts) class SubSelectNoSRIDTest(unittest.TestCase): """SRID should be diagnosed from the selection""" def setUp(self): self.mo = mapscript.mapObj() lo = mapscript.layerObj() lo.name = 'pg_sub_layer' lo.type = mapscript.MS_LAYER_POLYGON lo.connectiontype = mapscript.MS_POSTGIS lo.connection = PG_CONNECTION_STRING lo.data = "the_geom from (select * from polygon) as foo using unique gid" li = self.mo.insertLayer(lo) self.lo = self.mo.getLayer(li) def test_getfeature(self): self.lo.open() f = self.lo.getFeature(1, -1) atts = [f.getValue(i) for i in range(self.lo.numitems)] self.lo.close() self.assertEqual(atts, ['1', '1', 'A Polygon'], atts) if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/point_test.py000066400000000000000000000077471357574274700241220ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Point # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript class PointObjTestCase(unittest.TestCase): def testPointObjConstructorNoArgs(self): """point can be created with no arguments""" p = mapscript.pointObj() self.assertAlmostEqual(p.x, 0.0) self.assertAlmostEqual(p.y, 0.0) def testPointObjConstructorArgs(self): """point can be created with arguments""" p = mapscript.pointObj(1.0, 1.0) self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 1.0) def testSetXY(self): """point can have its x and y reset""" p = mapscript.pointObj() p.setXY(1.0, 1.0) self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 1.0) if hasattr(p, 'm'): self.assertAlmostEqual(p.m, -2e38) def testSetXYM(self): """point can have its x and y reset (with m value)""" p = mapscript.pointObj() p.setXY(1.0, 1.0, 1.0) self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 1.0) if hasattr(p, 'm'): self.assertAlmostEqual(p.m, 1.0) def testSetXYZ(self): """point can have its x, y, z reset (with m value)""" p = mapscript.pointObj() p.setXYZ(1.0, 2.0, 3.0, 4.0) self.assertAlmostEqual(p.x, 1.0) self.assertAlmostEqual(p.y, 2.0) if hasattr(p, 'z') and hasattr(p, 'm'): self.assertAlmostEqual(p.z, 3.0) self.assertAlmostEqual(p.m, 4.0) def testPoint__str__(self): """return properly formatted string""" p = mapscript.pointObj(1.0, 1.0) if hasattr(p, 'z'): p_str = "{ 'x': %.16g, 'y': %.16g, 'z': %.16g }" % (p.x, p.y, p.z) else: p_str = "{ 'x': %.16g, 'y': %.16g }" % (p.x, p.y) assert str(p) == p_str, str(p) def testPointToString(self): """return properly formatted string in toString()""" p = mapscript.pointObj(1.0, 1.0, 0.002, 15.0) if hasattr(p, 'z') and hasattr(p, 'm'): p_str = "{ 'x': %.16g, 'y': %.16g, 'z': %.16g, 'm': %.16g }" \ % (p.x, p.y, p.z, p.m) else: p_str = "{ 'x': %.16g, 'y': %.16g }" % (p.x, p.y) assert p.toString() == p_str, p.toString() def testPointGeoInterface(self): """return point using the __geo_interface__ protocol""" p = mapscript.pointObj(1.0, 1.0, 0.002, 15.0) if hasattr(p, 'z'): assert p.__geo_interface__ == {"type": "Point", "coordinates": (1.0, 1.0, 0.002)} else: assert p.__geo_interface__ == {"type": "Point", "coordinates": (1.0, 1.0)} if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/rect_test.py000066400000000000000000000123451357574274700237140ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of rectObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapPrimitivesTestCase class RectObjTestCase(MapPrimitivesTestCase): def testRectObjConstructorNoArgs(self): """a rect can be initialized with no args""" r = mapscript.rectObj() self.assertAlmostEqual(r.minx, -1.0) self.assertAlmostEqual(r.miny, -1.0) self.assertAlmostEqual(r.maxx, -1.0) self.assertAlmostEqual(r.maxy, -1.0) def testRectObjConstructorArgs(self): """a rect can be initialized with arguments""" r = mapscript.rectObj(-1.0, -2.0, 3.0, 4.0) self.assertAlmostEqual(r.minx, -1.0) self.assertAlmostEqual(r.miny, -2.0) self.assertAlmostEqual(r.maxx, 3.0) self.assertAlmostEqual(r.maxy, 4.0) def testRectObjConstructorBadXCoords(self): """an invalid extent raises proper error (x direction)""" self.assertRaises(mapscript.MapServerError, mapscript.rectObj, 1.0, -2.0, -3.0, 4.0) def testRectObjConstructorBadYCoords(self): """an invalid extent raises proper error (y direction)""" self.assertRaises(mapscript.MapServerError, mapscript.rectObj, -1.0, 2.0, 3.0, -2.0) def testRectObjToPolygon(self): """a rect can be converted into a MS_POLYGON shape""" r = mapscript.rectObj(-1.0, -2.0, 3.0, 4.0) s = r.toPolygon() assert s.numlines == 1, s.numlines line = self.getLineFromShape(s, 0) assert line.numpoints == 5, line.numpoints point = self.getPointFromLine(line, 0) self.assertAlmostEqual(point.x, -1.0) self.assertAlmostEqual(point.y, -2.0) def testExceptionMessage(self): """test formatted error message""" try: r = mapscript.rectObj(1.0, -2.0, -3.0, 4.0) print(r) except mapscript.MapServerError as msg: assert str(msg) == "rectObj(): Invalid rectangle. { 'minx': 1.000000 , " \ "'miny': -2.000000 , 'maxx': -3.000000 , 'maxy': 4.000000 }", msg def testRect__str__(self): """__str__ returns properly formatted string""" r = mapscript.rectObj(-1.0, -2.0, 3.0001, 4.0) r_str = str(r) assert r_str == "{ 'minx': -1 , 'miny': -2 , 'maxx': 3.0001 , 'maxy': 4 }", r_str r2 = eval(r_str) self.assertAlmostEqual(r2['minx'], r.minx) self.assertAlmostEqual(r2['miny'], r.miny) self.assertAlmostEqual(r2['maxx'], r.maxx) self.assertAlmostEqual(r2['maxy'], r.maxy) def testRectToString(self): """return properly formatted string""" r = mapscript.rectObj(-1.0, -2.0, 3.0001, 4.0) r_str = r.toString() assert r_str == "{ 'minx': -1 , 'miny': -2 , 'maxx': 3.0001 , 'maxy': 4 }", r_str def testRectContainsPoint(self): """point is contained (spatially) in rectangle""" r = mapscript.rectObj(-1.0, -2.0, 3.0, 4.0) p = mapscript.pointObj(0.0, 0.0) assert p in r, (p.x, p.y, r) def testRectContainsPointNot(self): """point is not contained (spatially) in rectangle""" r = mapscript.rectObj(-1.0, -2.0, 3.0, 4.0) p = mapscript.pointObj(3.00001, 0.0) assert p not in r, (p.x, p.y, r) class ImageRectObjTestCase(MapPrimitivesTestCase): def testRectObjConstructorArgs(self): """create a rect in image units""" r = mapscript.rectObj(-1.0, 2.0, 3.0, 0.0, mapscript.MS_TRUE) self.assertAlmostEqual(r.minx, -1.0) self.assertAlmostEqual(r.miny, 2.0) self.assertAlmostEqual(r.maxx, 3.0) self.assertAlmostEqual(r.maxy, 0.0) def testRectObjConstructorBadYCoords(self): """in image units miny should be greater than maxy""" self.assertRaises(mapscript.MapServerError, mapscript.rectObj, -1.0, 0.0, 3.0, 2.0, mapscript.MS_TRUE) if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/refcount_test.py000066400000000000000000000274211357574274700246050ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Map # Author: Umberto Nicoletti, unicoletti@prometeo.it # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import TESTMAPFILE class ReferenceCountingTestCase(unittest.TestCase): def initMap(self): self.map = mapscript.mapObj(TESTMAPFILE) def testMap(self): """ReferenceCountingTestCase.testMap: test map constructor with no argument""" test_map = mapscript.mapObj() assert test_map.__class__.__name__ == "mapObj" assert test_map.thisown == 1 assert test_map.refcount == 1 def testMapWithDefaultMap(self): """ReferenceCountingTestCase.testTestMap: test map constructor with default map file""" test_map = mapscript.mapObj(TESTMAPFILE) assert test_map.__class__.__name__ == "mapObj" assert test_map.thisown == 1 assert test_map.refcount == 1 assert test_map.getLayer(0).refcount == 2 def testMapLayersCounting(self): """ReferenceCountingTestCase.testTestMap: test map constructor with default map file""" self.initMap() layerRef1 = self.map.getLayer(0) assert layerRef1.refcount == 2 layerRef2 = self.map.getLayer(0) assert layerRef2.refcount == 3 def testMapInsertedLayer(self): """MapLayersTestCase.testMapInsertedLayer: test insertion of a new layer at default (last) index""" self.initMap() n = self.map.numlayers layer = mapscript.layerObj() layer.name = 'new' assert layer.refcount == 1 assert layer.thisown == 1 index = self.map.insertLayer(layer) assert index == n, index assert self.map.numlayers == n + 1 assert layer.refcount == 2 assert layer.thisown == 1 assert self.map.getLayer(index).refcount == 3 assert self.map.getLayer(index).thisown == 1 assert layer.refcount == 2 assert layer.thisown == 1 def testMapInsertedLayerWithIndex(self): """MapLayersTestCase.testMapInsertedLayerWithIndex: test insertion of a new layer at index 0""" self.initMap() n = self.map.numlayers layer = mapscript.layerObj() layer.name = 'new' assert layer.refcount == 1 assert layer.thisown == 1 index = self.map.insertLayer(layer, 0) assert index == 0, index assert self.map.numlayers == n + 1 assert layer.refcount == 2 assert layer.thisown == 1 assert self.map.getLayer(index).refcount == 3 assert self.map.getLayer(index).thisown == 1 assert layer.refcount == 2 assert layer.thisown == 1 def testMapRemovedLayerAtTail(self): """removal of highest index (tail) layer""" self.initMap() n = self.map.numlayers layer = self.map.removeLayer(n-1) assert self.map.numlayers == n-1 assert layer.name == 'INLINE-PIXMAP-PCT' assert layer.thisown == 1 assert layer.refcount == 1, layer.refcount self.map.draw() def testMapRemovedLayerAtZero(self): """removal of lowest index (0) layer""" self.initMap() n = self.map.numlayers layer = self.map.removeLayer(0) assert self.map.numlayers == n-1 assert layer.name == 'RASTER' assert layer.thisown == 1 assert layer.refcount == 1, layer.refcount self.map.draw() def testBehaveWhenParentIsNull(self): """behave when parent (map) is null""" self.initMap() layer = mapscript.layerObj() layer.name = 'new' index = self.map.insertLayer(layer, 0) assert index == 0, index self.map = None assert layer.map is not None, layer.map exception = None try: layer.open() except Exception: # must fail because the new layer is missing information assert True exception = True assert exception is True def testLayerClone(self): """Clone a layer""" layer = mapscript.layerObj() layer.name = 'sample' copy = layer.clone() assert layer.refcount == 1, layer.refcount assert copy.refcount == 1, copy.refcount assert layer.name == copy.name assert copy.map is None def testMapGetLayerByName(self): """behave when parent (map) is null""" self.initMap() layer = self.map.getLayerByName("RASTER") assert layer.refcount == 2, layer.refcount assert layer.thisown == 1, layer.thisown def testBehaveWhenParentIsNotNull(self): """behave when parent (map) is not null""" self.initMap() layer = mapscript.layerObj(self.map) layer.name = 'new' assert layer.refcount == 2, layer.refcount def testDummyClass(self): """basic refcounting for classObj""" clazz = mapscript.classObj() assert clazz.refcount == 1, clazz.refcount def testClassWithArgument(self): """classObj constructor with not null layer""" self.initMap() clazz = mapscript.classObj(self.map.getLayer(0)) assert clazz.refcount == 2, clazz.refcount def testClassGetter(self): """classObj getter""" self.initMap() clazz = self.map.getLayer(1).getClass(0) assert clazz.refcount == 2, clazz.refcount def testClassClone(self): """classObj clone""" self.initMap() clazz = self.map.getLayer(1).getClass(0) assert clazz.refcount == 2, clazz.refcount clone = clazz.clone() assert clone.refcount == 1, clone.refcount def testClassInsert(self): """classObj insert at end""" self.initMap() clazz = mapscript.classObj() clazz.minscaledenom = 666 assert clazz.refcount == 1, clazz.refcount idx = self.map.getLayer(1).insertClass(clazz) assert clazz.refcount == 2, clazz.refcount assert self.map.getLayer(1).getClass(idx).refcount == 3, self.map.getLayer(1).getClass(idx).refcount assert self.map.getLayer(1).getClass(idx).minscaledenom == 666, self.map.getLayer(1).getClass(idx).minscaledenom def testClassInsertAtMiddle(self): """classObj insert at pos. 1""" self.initMap() clazz = mapscript.classObj() clazz.minscaledenom = 666 assert clazz.refcount == 1, clazz.refcount idx = self.map.getLayer(1).insertClass(clazz, 1) assert idx == 1, idx assert clazz.refcount == 2, clazz.refcount assert self.map.getLayer(1).getClass(idx).refcount == 3, self.map.getLayer(1).getClass(idx).refcount assert self.map.getLayer(1).getClass(idx).thisown, self.map.getLayer(1).getClass(idx).thisown assert self.map.getLayer(1).getClass(idx).minscaledenom == 666, self.map.getLayer(1).getClass(idx).minscaledenom def testRemoveFirstClass(self): """removal of first class""" self.initMap() clazz = self.map.getLayerByName("POLYGON").removeClass(0) assert clazz is not None assert clazz.thisown == 1 assert clazz.refcount == 1, clazz.refcount self.map.draw() def testMapClone(self): """cloning a mapObj""" self.initMap() clone = self.map.clone() assert clone.refcount == 1, clone.refcount def testStyleGetter(self): """styleObj getter""" self.initMap() style = self.map.getLayer(1).getClass(0).getStyle(0) assert style.refcount == 2, style.refcount assert style.thisown == 1, style.thisown def testStyleConstructor(self): """styleObj Constructor""" self.initMap() style = mapscript.styleObj(self.map.getLayer(1).getClass(0)) assert style.refcount == 2, style.refcount assert style.thisown == 1, style.thisown style = mapscript.styleObj() assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown def testRemoveStyleAtBeginning(self): """styleObj remove first one""" self.initMap() style = mapscript.styleObj() assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown self.map.getLayer(1).getClass(0).insertStyle(style) assert style.refcount == 2, style.refcount assert style.thisown == 1, style.thisown style = self.map.getLayer(1).getClass(0).removeStyle(0) assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown def testInsertStyle(self): """styleObj Insert""" self.initMap() style = mapscript.styleObj() assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown self.map.getLayer(1).getClass(0).insertStyle(style) assert style.refcount == 2, style.refcount assert style.thisown == 1, style.thisown def testCloneStyle(self): """styleObj Clone""" self.initMap() style = mapscript.styleObj() assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown clone = style.clone() assert clone.refcount == 1, clone.refcount assert clone.thisown == 1, clone.thisown assert style.refcount == 1, style.refcount assert style.thisown == 1, style.thisown style = self.map.getLayer(1).getClass(0).getStyle(0) clone = style.clone() assert clone.refcount == 1, clone.refcount assert clone.thisown == 1, clone.thisown def testBasicSymbolRefcounting(self): """symbolObj refcounting """ self.initMap() symb = self.map.symbolset.getSymbol(0) assert symb.refcount == 2, symb.refcount assert symb.thisown == 1, symb.thisown symb = self.map.symbolset.getSymbolByName("home-png") assert symb.refcount == 2, symb.refcount assert symb.thisown == 1, symb.thisown symb2 = self.map.symbolset.getSymbolByName("home-png") assert symb2.refcount == 3, symb2.refcount assert symb2.thisown == 1, symb2.thisown def testSymbolAppendRemove(self): """appendSymbolObj refcounting """ self.initMap() symb = mapscript.symbolObj("ANEWSYMBOL") assert symb.refcount == 1, symb.refcount assert symb.thisown == 1, symb.thisown idx = self.map.symbolset.appendSymbol(symb) assert symb.refcount == 2, symb.refcount assert symb.thisown == 1, symb.thisown symb = self.map.symbolset.removeSymbol(idx) assert symb.refcount == 1, symb.refcount assert symb.thisown == 1, symb.thisown if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/resultcache_test.py000066400000000000000000000123451357574274700252610ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of ResultCache # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase class LayerQueryTestCase(MapTestCase): def setUp(self): MapTestCase.setUp(self) self.layer = self.map.getLayer(1) self.layer.template = 'some day i will fix this!' def pointquery(self): p = mapscript.pointObj(0.0, 51.5) self.layer.queryByPoint(self.map, p, mapscript.MS_MULTIPLE, -1) return self.layer.getResults() def indexquery(self): self.layer.queryByIndex(self.map, -1, 0, mapscript.MS_TRUE) return self.layer.getResults() class ResultCacheTestCase(LayerQueryTestCase): def testNoDirectAccess(self): """denying direct access to layer's resultcache""" self.assertRaises(AttributeError, getattr, self.layer, 'resultcache') def testNullResultCache(self): """before a query layer's resultcache should be NULL""" results = self.layer.getResults() assert results is None class PointQueryResultsTestCase(LayerQueryTestCase): def testCacheAfterQuery(self): """simple point query returns one result""" results = self.pointquery() assert results.numresults == 1 def testCacheAfterFailedQuery(self): """point query with no results returns NULL""" p = mapscript.pointObj(0.0, 0.0) self.layer.queryByPoint(self.map, p, mapscript.MS_MULTIPLE, -1) results = self.layer.getResults() assert results is None def testDeletionOfResults(self): """deleting results should not harm the layer""" results = self.pointquery() assert results.thisown == 0 del results results = self.layer.getResults() assert results.numresults == 1 def testQueryResultBounds(self): """result bounds should equal layer bounds""" results = self.pointquery() e = self.layer.getExtent() self.assertRectsEqual(results.bounds, e) def testQueryResultMembers(self): """get the single result member""" results = self.pointquery() self.layer.open() res = results.getResult(0) feature = self.layer.getShape(res) self.layer.close() self.assertRectsEqual(results.bounds, feature.bounds) assert feature.getValue(1) == 'A Polygon' def testQueryResultsListComp(self): """get all results using list comprehension""" results = self.pointquery() result_list = [results.getResult(i) for i in range(results.numresults)] assert len(result_list) == 1 assert result_list[0].shapeindex == 0 def testQueryByIndex(self): """pop a result into the result set""" self.layer.queryByIndex(self.map, -1, 0, mapscript.MS_FALSE) results = self.layer.getResults() assert results.numresults == 1 self.layer.queryByIndex(self.map, -1, 0, mapscript.MS_TRUE) results = self.layer.getResults() assert results.numresults == 2 class DumpAndLoadTestCase(LayerQueryTestCase): def testSaveAndLoadQuery(self): """test saving query to a file""" results = self.pointquery() self.map.saveQuery('test.qy') self.map.freeQuery() results = self.layer.getResults() assert results is None self.map.loadQuery('test.qy') results = self.layer.getResults() assert results is not None class LayerOffQueryTestCase(LayerQueryTestCase): def testPointQueryOffLayer(self): """simple point query returns one result, even if layer is off""" self.layer.status = mapscript.MS_OFF results = self.pointquery() assert results.numresults == 1 def testIndexQueryOffLayer(self): """simple index query returns one result, even if layer is off""" self.layer.status = mapscript.MS_OFF results = self.indexquery() assert results.numresults == 1 if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/shape_test.py000066400000000000000000000152741357574274700240630ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Shape # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase, ShapeObjTestCase class ShapePointTestCase(ShapeObjTestCase): """Test point type shapeObj in stand-alone mode""" def setUp(self): """The test fixture is a shape of one point""" self.points = (mapscript.pointObj(0.0, 1.0), ) self.lines = (mapscript.lineObj(), ) self.addPointToLine(self.lines[0], self.points[0]) self.shape = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) self.addLineToShape(self.shape, self.lines[0]) def testCreateShape(self): """the number of lines is correct""" assert self.shape.numlines == 1 def testShapeClone(self): """test shape can be copied""" s = self.shape.clone() self.assertShapesEqual(self.shape, s) class InlineFeatureTestCase(MapTestCase): """tests for issue http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=562""" def testAddPointFeature(self): """adding a point to an inline feature works correctly""" inline_layer = self.map.getLayerByName('INLINE') assert inline_layer.connectiontype == mapscript.MS_INLINE p = mapscript.pointObj(0.2, 51.5) lyr = mapscript.lineObj() self.addPointToLine(lyr, p) shape = mapscript.shapeObj(inline_layer.type) shape.classindex = 0 self.addLineToShape(shape, lyr) inline_layer.addFeature(shape) msimg = self.map.draw() filename = 'testAddPointFeature.png' msimg.save(filename) def testGetShape(self): """returning the shape from an inline feature works""" inline_layer = self.map.getLayerByName('INLINE') inline_layer.open() inline_layer.template = "FAKE" inline_layer.queryByIndex(self.map, -1, 0) res = inline_layer.getResult(0) s = inline_layer.getShape(res) lyr = self.getLineFromShape(s, 0) p = self.getPointFromLine(lyr, 0) self.assertAlmostEqual(p.x, -0.2) self.assertAlmostEqual(p.y, 51.5) def testGetNumFeatures(self): """the number of features in the inline layer is correct""" inline_layer = self.map.getLayerByName('INLINE') assert inline_layer.getNumFeatures() == 1 def testShapeGeoInterface(self): """return the shape using the __geo_interface__ protocol with no attribute names""" layer = self.map.getLayerByName('POLYGON') layer.open() layer.template = "FAKE" layer.queryByIndex(self.map, -1, 0) res = layer.getResult(0) s = layer.getShape(res) assert s.__geo_interface__ == { 'geometry': { 'type': 'Polygon', 'coordinates': [[(-0.25, 51.227222), (-0.25, 51.727222), (0.25, 51.727222), (0.25, 51.227222), (-0.25, 51.227222)]] }, 'type': 'Feature', 'bbox': (-0.25, 51.227222, 0.25, 51.727222), 'properties': {'1': 'A Polygon', '0': '1'} } layer.close() def testShapeGeoInterfaceWithFields(self): """return the shape using the __geo_interface__ protocol with attribute names""" layer = self.map.getLayerByName('POINT') layer.open() layer.template = "FAKE" layer.queryByIndex(self.map, -1, 0) res = layer.getResult(0) s = layer.getShape(res) s.itemdefinitions = layer.getItemDefinitions() assert s.__geo_interface__ == { 'geometry': { 'type': 'Point', 'coordinates': [[(0.0, 51.477222)]] }, 'type': 'Feature', 'bbox': (0.0, 51.477222, 0.0, 51.477222), 'properties': {'FNAME': 'A Point', 'FID': 1} } layer.close() class ShapeValuesTestCase(unittest.TestCase): def testNullValue(self): so = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) assert so.numvalues == 0 assert so.getValue(0) is None def testSetValue(self): so = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) so.initValues(4) so.setValue(0, 'Foo') assert so.numvalues == 4 assert so.getValue(0) == 'Foo' assert so.getValue(1) == '' # New class for testing the WKT stuff of RFC-2 class ShapeWKTTestCase(unittest.TestCase): # define a pair of coords, and WKT as class data point_xy = (-105.5000000000000000, 40.0000000000000000) point_wkt = 'POINT (-105.5000000000000000 40.0000000000000000)' def testSetPointWKT(self): # Create new instance and set/init from WKT so = mapscript.shapeObj.fromWKT(self.point_wkt) # expect one line with one point self.assertTrue(so.numlines == 1, so.numlines) self.assertTrue(so.get(0).numpoints == 1, so.get(0).numpoints) # expect shape's x and y values to be correct po = so.get(0).get(0) self.assertAlmostEqual(po.x, self.point_xy[0]) self.assertAlmostEqual(po.y, self.point_xy[1]) def testGetPointWKT(self): # Create new instance from class data po = mapscript.pointObj(self.point_xy[0], self.point_xy[1]) lo = mapscript.lineObj() lo.add(po) so = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) so.add(lo) # test output WKT wkt = so.toWKT() self.assertTrue(wkt == self.point_wkt, wkt) if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/shapefile_test.py000066400000000000000000000044101357574274700247110ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of shapefileObj # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import os import mapscript from .testing import TESTS_PATH class AddShapeTestCase(unittest.TestCase): def testAddEmpty(self): """expect an error rather than segfault when adding an empty shape""" # See bug 1201 sf = mapscript.shapefileObj('testAddDud.shp', 1) so = mapscript.shapeObj(mapscript.MS_SHAPE_POINT) self.assertRaises(mapscript.MapServerError, sf.add, so) def testGetDBFInfo(self): """Fetch dbf information from shapefile""" pth = os.path.join(TESTS_PATH, "polygon.shp") sf = mapscript.shapefileObj(pth) assert sf.getDBF() is not None, sf.getDBF() assert sf.getDBF().nFields == 2, sf.getDBF().nFields assert sf.getDBF().getFieldName(0) == 'FID', sf.getDBF().getFieldName(0) assert sf.getDBF().getFieldName(1) == 'FNAME', sf.getDBF().getFieldName(1) if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/style_test.py000066400000000000000000000206741357574274700241230ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Map Styles # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapTestCase class DrawProgrammedStylesTestCase(MapTestCase): def testDrawPoints(self): """DrawProgrammedStylesTestCase.testDrawPoints: point drawing with styles works as advertised""" points = [mapscript.pointObj(-0.2, 51.6), mapscript.pointObj(0.0, 51.2), mapscript.pointObj(0.2, 51.6)] colors = [mapscript.colorObj(255, 0, 0), mapscript.colorObj(0, 255, 0), mapscript.colorObj(0, 0, 255)] img = self.map.prepareImage() layer = self.map.getLayerByName('POINT') # layer.draw(self.map, img) class0 = layer.getClass(0) for i in range(len(points)): style0 = class0.getStyle(0) style0.color = colors[i] # style0.color.pen = -4 assert style0.color.toHex() == colors[i].toHex() points[i].draw(self.map, layer, img, 0, "foo") img.save('test_draw_points.png') class NewStylesTestCase(MapTestCase): def testStyleConstructor(self): """a new style is properly initialized""" new_style = mapscript.styleObj() assert new_style.color.red == -1 assert new_style.color.green == -1 assert new_style.color.blue == -1 def testCloneStyle(self): """check attributes of a cloned style""" new_style = mapscript.styleObj() new_style.color.setHex('#808080') clone = new_style.clone() assert clone.thisown == 1 assert clone.color.toHex() == '#808080' def testStyleColorSettable(self): """a style can be set with a color tuple""" new_style = mapscript.styleObj() new_style.color.setRGB(1, 2, 3) assert new_style.color.red == 1 assert new_style.color.green == 2 assert new_style.color.blue == 3 def testStyleBinding(self): """attribute binding can be set and get""" new_style = mapscript.styleObj() assert (not new_style.getBinding(mapscript.MS_STYLE_BINDING_COLOR)) new_style.setBinding(mapscript.MS_STYLE_BINDING_COLOR, "NEW_BINDING") assert (new_style.getBinding(mapscript.MS_STYLE_BINDING_COLOR) == "NEW_BINDING") def testAppendNewStyle(self): """a new style can be appended properly""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) assert class0.numstyles == 2, class0.numstyles new_style = mapscript.styleObj() new_style.color.setRGB(0, 0, 0) new_style.symbol = 1 new_style.size = 3 index = class0.insertStyle(new_style) assert index == 2, index assert class0.numstyles == 3, class0.numstyles msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testAppendNewStyle.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testAppendNewStyleOldWay(self): """NewStylesTestCase.testAppendNewStyleOldWay: a new style can be appended properly using old method""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) assert class0.numstyles == 2, class0.numstyles new_style = mapscript.styleObj(class0) assert new_style.thisown == 1, new_style.thisown new_style.color.setRGB(0, 0, 0) new_style.symbol = 1 new_style.size = 3 msimg = self.map.draw() data = msimg.saveToString() filename = 'testAppendNewStyleOldWay.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testInsertNewStyleAtIndex0(self): """NewStylesTestCase.testInsertNewStyleAtIndex0: a new style can be inserted ahead of all others""" l_layer = self.map.getLayerByName('LINE') class0 = l_layer.getClass(0) new_style = mapscript.styleObj() new_style.color.setRGB(255, 255, 0) new_style.symbol = 1 new_style.size = 7 index = class0.insertStyle(new_style, 0) assert index == 0, index assert class0.numstyles == 2, class0.numstyles msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testInsertNewStyleAtIndex0.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testRemovePointStyle(self): """NewStylesTestCase.testRemovePointStyle: a point style can be properly removed""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) rem_style = class0.removeStyle(1) assert rem_style is not None assert class0.numstyles == 1, class0.numstyles msimg = self.map.draw() filename = 'testRemovePointStyle.png' msimg.save(filename) def testModifyMultipleStyle(self): """NewStylesTestCase.testModifyMultipleStyle: multiple styles can be modified""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) style1 = class0.getStyle(1) style1.color.setRGB(255, 255, 0) msimg = self.map.draw() filename = 'testModifyMutiplePointStyle.png' msimg.save(filename) def testInsertStylePastEnd(self): """NewStylesTestCase.testInsertStylePastEnd: inserting a style past the end of the list raises the proper error""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) new_style = mapscript.styleObj() self.assertRaises(mapscript.MapServerChildError, class0.insertStyle, new_style, 6) def testInsertNULLStyle(self): """attempt to insert a NULL style should raise error""" p_layer = self.map.getLayerByName('POINT') class0 = p_layer.getClass(0) self.assertRaises(mapscript.MapServerChildError, class0.insertStyle, None) class BrushCachingTestCase(MapTestCase): def testDrawMapWithSecondPolygon(self): """draw a blue polygon and a red polygon""" p = self.map.getLayerByName('POLYGON') ip = mapscript.layerObj(self.map) ip.type = mapscript.MS_LAYER_POLYGON ip.status = mapscript.MS_DEFAULT c0 = mapscript.classObj(ip) # turn off first polygon layer's color p.getClass(0).getStyle(0).color.setRGB(-1, -1, -1) # copy this style to inline polygon layer, then change outlinecolor c0.insertStyle(p.getClass(0).getStyle(0)) st0 = c0.getStyle(0) st0.outlinecolor.setRGB(255, 0, 0) # pull out the first feature from polygon layer, shift it # and use this as an inline feature in new layer p.open() p.template = "FAKE" # set a template so the layer can be queried p.queryByIndex(self.map, -1, 0, mapscript.MS_TRUE) res = p.getResult(0) s0 = p.getShape(res) p.close() r0 = s0.bounds r1 = mapscript.rectObj(r0.minx-0.1, r0.miny-0.1, r0.maxx-0.1, r0.maxy-0.1) s1 = r1.toPolygon() ip.addFeature(s1) img = self.map.draw() img.save('test_drawmapw2ndpolygon.png') if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/symbol_test.py000066400000000000000000000147361357574274700242720ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Symbol # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest from io import BytesIO import mapscript from .testing import MapTestCase, XMARKS_IMAGE, HOME_IMAGE class SymbolTestCase(unittest.TestCase): def testConstructor(self): """create new instance of symbolObj""" symbol = mapscript.symbolObj('test') assert symbol.name == 'test' assert symbol.thisown == 1 def testConstructorImage(self): """create new instance of symbolObj from an image""" symbol = mapscript.symbolObj('xmarks', XMARKS_IMAGE) assert symbol.name == 'xmarks' assert symbol.type == mapscript.MS_SYMBOL_VECTOR # was MS_SYMBOL_PIXMAP! format = mapscript.outputFormatObj('AGG/PNG') img = symbol.getImage(format) img.save('sym-%s.%s' % (symbol.name, img.format.extension)) class DynamicGraphicSymbolTestCase(): def setUp(self): MapTestCase.setUp(self) with open(HOME_IMAGE, 'rb') as fh: s = BytesIO(fh.read()) symb_img = mapscript.imageObj(s) self.h_symbol = mapscript.symbolObj('house') self.h_symbol.type = mapscript.MS_SYMBOL_PIXMAP self.h_symbol.setImage(symb_img) with open(XMARKS_IMAGE, 'rb') as fh: s = BytesIO(fh.read()) symb_img = mapscript.imageObj(s) self.x_symbol = mapscript.symbolObj('xmarks') self.x_symbol.type = mapscript.MS_SYMBOL_PIXMAP self.x_symbol.setImage(symb_img) def testSetPCTImage(self): """set image of new symbolObj""" assert self.h_symbol.name == 'house' assert self.h_symbol.type == mapscript.MS_SYMBOL_PIXMAP format = mapscript.outputFormatObj('AGG/PNG') format.transparent = mapscript.MS_ON img = self.h_symbol.getImage(format) img.save('set-%s.%s' % (self.h_symbol.name, img.format.extension)) def testDrawSetPCTImage(self): """draw a map using the set image symbol""" symbol_index = self.map.symbolset.appendSymbol(self.h_symbol) assert symbol_index == 4, symbol_index num = self.map.symbolset.numsymbols assert num == 5, num inline_layer = self.map.getLayerByName('INLINE') s = inline_layer.getClass(0).getStyle(0) s.symbol = symbol_index s.size = -1 # pixmap's own size img = self.map.draw() img.save('testDrawSetPCTImage.%s' % (img.format.extension)) def testSetRGBAImage(self): """set image of new symbolObj""" assert self.x_symbol.name == 'xmarks' assert self.x_symbol.type == mapscript.MS_SYMBOL_PIXMAP format = mapscript.outputFormatObj('AGG/PNG') img = self.x_symbol.getImage(format) img.save('set-%s.%s' % (self.x_symbol.name, img.format.extension)) def testDrawSetRGBAImage(self): """draw a map using the set image symbol""" symbol_index = self.map.symbolset.appendSymbol(self.x_symbol) inline_layer = self.map.getLayerByName('INLINE') s = inline_layer.getClass(0).getStyle(0) s.symbol = symbol_index s.size = -1 # pixmap's own size self.map.selectOutputFormat('PNG24') img = self.map.draw() img.save('testDrawSetRGBAImage.%s' % (img.format.extension)) class MapSymbolTestCase(MapTestCase): def testGetPoints(self): """get symbol points as line and test coords""" symbol = self.map.symbolset.getSymbol(1) assert symbol.name == 'circle' line = symbol.getPoints() assert line.numpoints == 1, line.numpoints pt = self.getPointFromLine(line, 0) self.assertPointsEqual(pt, mapscript.pointObj(1.0, 1.0)) def testSetPoints(self): """add lines of points to an existing symbol""" symbol = self.map.symbolset.getSymbol(1) assert symbol.name == 'circle' line = mapscript.lineObj() self.addPointToLine(line, mapscript.pointObj(2.0, 2.0)) self.addPointToLine(line, mapscript.pointObj(3.0, 3.0)) assert symbol.setPoints(line) == 2 assert symbol.numpoints == 2 line = symbol.getPoints() assert line.numpoints == 2, line.numpoints pt = self.getPointFromLine(line, 1) self.assertPointsEqual(pt, mapscript.pointObj(3.0, 3.0)) def testSetStyle(self): """expect success after setting an existing symbol's style""" symbol = self.map.symbolset.getSymbol(1) # default MapScript API setPattern has been extended to allow lists # assert symbol.setPattern(0, 1) == mapscript.MS_SUCCESS symbol.pattern = [0, 1] assert symbol.pattern == [0, 1] def testRGBASymbolInPNG24(self): """draw a RGBA PNG pixmap on PNG canvas""" self.map.setImageType('PNG24') # self.map.getLayerByName('INLINE-PIXMAP-RGBA').status \ # == mapscript.MS_DEFAULT img = self.map.draw() img.save('pixmap-rgba-24.png') def testRGBASymbolInJPEG(self): """draw a RGBA PNG pixmap on JPEG canvas""" self.map.setImageType('JPEG') # self.map.getLayerByName('INLINE-PIXMAP-RGBA').status \ # == mapscript.MS_DEFAULT img = self.map.draw() img.save('pixmap-rgba.jpg') if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/symbolset_test.py000066400000000000000000000134701357574274700250000ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of SymbolSet # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import os import unittest import mapscript from .testing import MapTestCase, XMARKS_IMAGE, TESTS_PATH SYMBOLSET = os.path.join(TESTS_PATH, "symbols.txt") class SymbolSetTestCase(unittest.TestCase): def testConstructorNoArgs(self): """new instance of symbolSetObj should have one symbol""" symbolset = mapscript.symbolSetObj() num = symbolset.numsymbols assert num == 1, num def testConstructorFile(self): """new instance of symbolSetObj from symbols.txt""" symbolset = mapscript.symbolSetObj(SYMBOLSET) num = symbolset.numsymbols assert num == 4, num def testAddSymbolToNewSymbolSet(self): """add two new symbols to a SymbolSet""" symbolset = mapscript.symbolSetObj(SYMBOLSET) symbola = mapscript.symbolObj('testa') symbolb = mapscript.symbolObj('testb') symbolset.appendSymbol(symbola) symbolset.appendSymbol(symbolb) num = symbolset.numsymbols assert num == 6, num names = [None, 'circle', 'xmarks-png', 'home-png', 'testa', 'testb'] for i in range(symbolset.numsymbols): symbol = symbolset.getSymbol(i) assert symbol.name == names[i], symbol.name def testRemoveSymbolFromNewSymbolSet(self): """after removing a symbol, expect numsymbols -= 1""" symbolset = mapscript.symbolSetObj(SYMBOLSET) symbolset.removeSymbol(1) num = symbolset.numsymbols assert num == 3, num def testSaveNewSymbolSet(self): """save a new SymbolSet to disk""" symbolset = mapscript.symbolSetObj(SYMBOLSET) symbola = mapscript.symbolObj('testa') symbolb = mapscript.symbolObj('testb') symbolset.appendSymbol(symbola) symbolset.appendSymbol(symbolb) assert symbolset.save('new_symbols.txt') == mapscript.MS_SUCCESS def testError(self): symbolset = mapscript.symbolSetObj(SYMBOLSET) symbola = mapscript.symbolObj('testa') symbolb = mapscript.symbolObj('testb') symbolset.appendSymbol(symbola) symbolset.appendSymbol(symbolb) self.assertRaises(mapscript.MapServerError, symbolset.save, '/bogus/new_symbols.txt') class MapSymbolSetTestCase(MapTestCase): def testGetNumSymbols(self): """expect getNumSymbols == 2 from test fixture test.map""" num = self.map.getNumSymbols() assert num == 4, num def testSymbolSetNumsymbols(self): """expect numsymbols == 2 from test fixture test.map""" num = self.map.symbolset.numsymbols assert num == 4, num def testSymbolSetSymbolNames(self): """test names of symbols in test fixture's symbolset""" set = self.map.symbolset names = [None, 'circle', 'xmarks-png', 'home-png'] for i in range(set.numsymbols): symbol = set.getSymbol(i) assert symbol.name == names[i], symbol.name def testSymbolIndex(self): """expect index of 'circle' symbol to be 1 in test fixture symbolset""" i = self.map.symbolset.index('circle') assert i == 1, i def testBug1962(self): """resetting imagepath doesn't cause segfault""" layer = self.map.getLayerByName('POINT') style0 = layer.getClass(0).getStyle(0) sym0 = style0.symbol sym1 = self.map.symbolset.getSymbol(sym0) sym2 = mapscript.symbolObj('xxx') assert sym2 is not None sym1.setImagepath(XMARKS_IMAGE) # self.assertRaises(IOError, sym1.setImagepath, '/bogus/new_symbols.txt') msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.getBytes() filename = 'testBug1962.png' fh = open(filename, 'wb') fh.write(data) fh.close() def testDrawNewSymbol(self): """draw using a new symbol added to the fixture""" symbol = mapscript.symbolObj('xmarks', XMARKS_IMAGE) symbol_index = self.map.symbolset.appendSymbol(symbol) assert symbol_index == 4, symbol_index num = self.map.symbolset.numsymbols assert num == 5, num inline_layer = self.map.getLayerByName('INLINE') s = inline_layer.getClass(0).getStyle(0) s.symbol = symbol_index # s.size = 24 msimg = self.map.draw() assert msimg.thisown == 1 data = msimg.saveToString() filename = 'testDrawNewSymbol.png' fh = open(filename, 'wb') fh.write(data) fh.close() if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/testing.py000066400000000000000000000130031357574274700233650ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript testing utilities # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== # # Purpose of this module is to export the locally built mapscript module # prior to installation, do some name normalization that allows testing of # the so-called next generation class names, and define some classes # useful to many test cases. # # =========================================================================== import os import unittest import tempfile import mapscript # define the path to mapserver test data TESTS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) TESTMAPFILE = os.path.join(TESTS_PATH, 'test.map') XMARKS_IMAGE = os.path.join(TESTS_PATH, 'xmarks.png') HOME_IMAGE = os.path.join(TESTS_PATH, 'home.png') TEST_IMAGE = os.path.join(TESTS_PATH, 'test.png') INCOMING = tempfile.mkdtemp(prefix="mapscript") # ========================================================================== # Base testing classes class MapPrimitivesTestCase(unittest.TestCase): """Base class for testing primitives (points, lines, shapes) in stand-alone mode""" def addPointToLine(self, line, point): """Using either the standard or next_generation_api""" try: line.add(point) except AttributeError: # next_generation_api line.addPoint(point) except Exception: raise def getPointFromLine(self, line, index): """Using either the standard or next_generation_api""" try: point = line.get(index) return point except AttributeError: # next_generation_api point = line.getPoint(index) return point except Exception: raise def addLineToShape(self, shape, line): """Using either the standard or next_generation_api""" try: shape.add(line) except AttributeError: # next_generation_api shape.addLine(line) except Exception: raise def getLineFromShape(self, shape, index): """Using either the standard or next_generation_api""" try: line = shape.get(index) return line except AttributeError: # next_generation_api line = shape.getLine(index) return line except Exception: raise def assertPointsEqual(self, first, second): self.assertAlmostEqual(first.x, second.x) self.assertAlmostEqual(first.y, second.y) def assertLinesEqual(self, first, second): assert first.numpoints == second.numpoints for i in range(first.numpoints): point_first = self.getPointFromLine(first, i) point_second = self.getPointFromLine(second, i) self.assertPointsEqual(point_first, point_second) def assertShapesEqual(self, first, second): assert first.numlines == second.numlines for i in range(first.numlines): line_first = self.getLineFromShape(first, i) line_second = self.getLineFromShape(second, i) self.assertLinesEqual(line_first, line_second) def assertRectsEqual(self, first, second): self.assertAlmostEqual(first.minx, second.minx) self.assertAlmostEqual(first.miny, second.miny) self.assertAlmostEqual(first.maxx, second.maxx) self.assertAlmostEqual(first.maxy, second.maxy) class MapTestCase(MapPrimitivesTestCase): """Base class for testing with a map fixture""" def setUp(self): self.map = mapscript.mapObj(TESTMAPFILE) # self.xmarks_image = xmarks_image # self.test_image = test_image def tearDown(self): self.map = None class MapZoomTestCase(MapPrimitivesTestCase): "Testing new zoom* methods that we are adapting from the PHP MapScript" def setUp(self): self.mapobj1 = mapscript.mapObj(TESTMAPFILE) # Change the extent for purposes of zoom testing rect = mapscript.rectObj() rect.minx, rect.miny, rect.maxx, rect.maxy = (-50.0, -50.0, 50.0, 50.0) self.mapobj1.extent = rect # Change height/width as well self.mapobj1.width, self.mapobj1.height = (100, 100) def tearDown(self): self.mapobj1 = None class ShapeObjTestCase(MapPrimitivesTestCase): """Base class for shapeObj tests""" pass mapserver-7.4.3/mapscript/python/tests/cases/thread_test.py000066400000000000000000000142541357574274700242270ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript test of multi-threading # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import os import unittest import threading import mapscript from .testing import TESTMAPFILE, INCOMING def draw_map(name, save=0): # print("making map in thread %s" % (name)) mo = mapscript.mapObj(TESTMAPFILE) im = mo.draw() if save: im.save('threadtest_%s.png' % (name)) def trigger_exception(name): # print("triggering exception in thread %s" % (name)) mo = mapscript.mapObj(TESTMAPFILE) try: mo.setExtent(1, 50, -1, 51) raise Exception("We expected a MapServer exception") except mapscript.MapServerError: pass class MultipleThreadsTestCase(unittest.TestCase): def testDrawMultiThreads(self): """map drawing with multiple threads""" workers = [] for i in range(10): name = 'd%d' % (i) thread = threading.Thread(target=draw_map, name=name, args=(name, 1)) workers.append(thread) thread.start() def testExceptionsMultiThreads(self): """mapserver exceptions behave with multiple threads""" workers = [] for i in range(10): name = 'e%d' % (i) thread = threading.Thread(target=trigger_exception, name=name, args=(name,)) workers.append(thread) thread.start() def testExceptionContainmentMultiThreads(self): """mapserver exceptions should be contained to a thread""" num = 100 workers = [] # Trigger an exception in the first started thread for i in range(0, 1): name = 'c%d' % (i) thread = threading.Thread(target=trigger_exception, name=name, args=(name,)) workers.append(thread) # Draw normally for i in range(1, num): name = 'c%d' % (i) thread = threading.Thread(target=draw_map, name=name, args=(name,)) workers.append(thread) # Start all threads for i in range(num): workers[i].start() def draw_map_wfs(name, save=0): # print("making map in thread %s" % (name)) mo = mapscript.mapObj(TESTMAPFILE) # WFS layer lo = mapscript.layerObj() lo.name = 'cheapo_wfs' lo.setProjection('+init=epsg:4326') lo.connectiontype = mapscript.MS_WFS lo.connection = 'http://zcologia.com:9001/mapserver/members/features.rpy?' lo.metadata.set('wfs_service', 'WFS') lo.metadata.set('wfs_typename', 'users') lo.metadata.set('wfs_version', '1.0.0') lo.type = mapscript.MS_LAYER_POINT lo.status = mapscript.MS_DEFAULT lo.labelitem = 'zco:mid' so1 = mapscript.styleObj() so1.color.setHex('#FFFFFF') so1.size = 9 so1.symbol = 1 # mo.symbolset.index('circle') so2 = mapscript.styleObj() so2.color.setHex('#333333') so2.size = 7 so2.symbol = 1 # mo.symbolset.index('circle') co = mapscript.classObj() co.label.type = mapscript.MS_BITMAP co.label.size = mapscript.MS_SMALL co.label.color.setHex('#000000') co.label.outlinecolor.setHex('#FFFFFF') co.label.position = mapscript.MS_AUTO co.insertStyle(so1) co.insertStyle(so2) lo.insertClass(co) mo.insertLayer(lo) if not mo.web.imagepath: mo.web.imagepath = os.environ.get('TEMP', None) or INCOMING mo.debug = mapscript.MS_ON im = mo.draw() if save: im.save('threadtest_wfs_%s.png' % (name)) def draw_map_wms(name, save=0): # print("making map in thread %s" % (name)) mo = mapscript.mapObj(TESTMAPFILE) # WFS layer lo = mapscript.layerObj() lo.name = 'jpl_wms' lo.setProjection('+init=epsg:4326') lo.connectiontype = mapscript.MS_WMS lo.connection = 'http://vmap0.tiles.osgeo.org/wms/vmap0?' lo.metadata.set('wms_service', 'WMS') lo.metadata.set('wms_server_version', '1.1.1') lo.metadata.set('wms_name', 'basic') lo.metadata.set('wms_style', 'visual') lo.metadata.set('wms_format', 'image/jpeg') lo.type = mapscript.MS_LAYER_RASTER lo.status = mapscript.MS_DEFAULT lo.debug = mapscript.MS_ON mo.insertLayer(lo) if not mo.web.imagepath: mo.web.imagepath = os.environ.get('TEMP', None) or INCOMING mo.debug = mapscript.MS_ON mo.selectOutputFormat('image/jpeg') im = mo.draw() if save: im.save('threadtest_wms_%s.jpg' % (name)) class OWSRequestTestCase(unittest.TestCase): # def testDrawWFS(self): # workers = [] # for i in range(10): # name = 'd%d' % (i) # thread = threading.Thread(target=draw_map_wfs, name=name, args=(name, 1)) # workers.append(thread) # thread.start() def testDrawWMS(self): workers = [] for i in range(10): name = 'd%d' % (i) thread = threading.Thread(target=draw_map_wms, name=name, args=(name, 1)) workers.append(thread) thread.start() if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/cases/zoom_test.py000066400000000000000000000177641357574274700237550ustar00rootroot00000000000000# Project: MapServer # Purpose: xUnit style Python mapscript tests of Map "zooming" # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== import unittest import mapscript from .testing import MapZoomTestCase class ZoomPointTestCase(MapZoomTestCase): def testRecenter(self): """ZoomPointTestCase.testRecenter: recentering the map with a point returns the same extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj(50.0, 50.0) extent = self.mapobj1.extent self.mapobj1.zoomPoint(1, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-50, -50, 50, 50)) def testZoomInPoint(self): """ZoomPointTestCase.testZoomInPoint: zooming in by a power of 2 returns the proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj(50.0, 50.0) extent = self.mapobj1.extent self.mapobj1.zoomPoint(2, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-25, -25, 25, 25)) def testZoomOutPoint(self): """ZoomPointTestCase.testZoomOutPoint: zooming out by a power of 2 returns the proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent self.mapobj1.zoomPoint(-2, p, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-100, -100, 100, 100)) def testZoomOutPointConstrained(self): """ZoomPointTestCase.testZoomOutPointConstrained: zooming out to a constrained extent returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) max = mapscript.rectObj() max.minx, max.miny, max.maxx, max.maxy = (-100.0, -100.0, 100.0, 100.0) p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent self.mapobj1.zoomPoint(-4, p, w, h, extent, max) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, max) def testZoomBadSize(self): """ZoomPointTestCase.testZoomBadSize: zooming to a bad size raises proper error""" p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent w = 0 h = -1 self.assertRaises(mapscript.MapServerError, self.mapobj1.zoomPoint, -2, p, w, h, extent, None) def testZoomBadExtent(self): """ZoomPointTestCase.testZoomBadExtent: zooming to a bad extent raises proper error""" p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent extent.maxx = extent.maxx - 1000000 w = 100 h = 100 self.assertRaises(mapscript.MapServerError, self.mapobj1.zoomPoint, -2, p, w, h, extent, None) class ZoomRectangleTestCase(MapZoomTestCase): def testZoomRectangle(self): """ZoomRectangleTestCase.testZoomRectangle: zooming to an extent returns proper map extent""" w, h = (self.mapobj1.width, self.mapobj1.height) r = mapscript.rectObj(1, 26, 26, 1, 1) extent = self.mapobj1.extent self.mapobj1.zoomRectangle(r, w, h, extent, None) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, mapscript.rectObj(-49, 24, -24, 49)) def testZoomRectangleConstrained(self): """ZoomRectangleTestCase.testZoomRectangleConstrained: zooming to a constrained extent returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) max = mapscript.rectObj(-100.0, -100.0, 100.0, 100.0) r = mapscript.rectObj(0, 200, 200, 0, 1) extent = self.mapobj1.extent self.mapobj1.zoomRectangle(r, w, h, extent, max) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, max) def testZoomRectangleBadly(self): """zooming into an invalid extent raises proper error""" w, h = (self.mapobj1.width, self.mapobj1.height) r = mapscript.rectObj(0, 0, 200, 200) extent = self.mapobj1.extent self.assertRaises(mapscript.MapServerError, self.mapobj1.zoomRectangle, r, w, h, extent, None) class ZoomScaleTestCase(MapZoomTestCase): def testRecenter(self): """ZoomScaleTestCase.testRecenter: recentering map returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) # 100 by 100 p = mapscript.pointObj() p.x, p.y = (50, 50) scale = 2834.6472 extent = self.mapobj1.extent self.mapobj1.zoomScale(scale, p, w, h, extent, None) assert self.mapobj1.scaledenom == scale new_extent = self.mapobj1.extent # self.assertRectsEqual(new_extent, mapscript.rectObj(-50, -50, 50, 50)) # old values self.assertRectsEqual(new_extent, mapscript.rectObj(-49.5, -49.5, 49.5, 49.5)) def testZoomInScale(self): """ZoomScaleTestCase.testZoomInScale: zooming in to a specified scale returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj() p.x, p.y = (50, 50) scale = 1417.3236 extent = self.mapobj1.extent self.mapobj1.zoomScale(scale, p, w, h, extent, None) new_extent = self.mapobj1.extent # self.assertRectsEqual(new_extent, mapscript.rectObj(-25, -25, 25, 25)) # old values self.assertRectsEqual(new_extent, mapscript.rectObj(-24.75, -24.75, 24.75, 24.75)) def testZoomOutScale(self): """ZoomScaleTestCase.testZoomOutScale: zooming out to a specified scale returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) p = mapscript.pointObj() p.x, p.y = (50, 50) scale = 5669.2944 extent = self.mapobj1.extent self.mapobj1.zoomScale(scale, p, w, h, extent, None) new_extent = self.mapobj1.extent # self.assertRectsEqual(new_extent, mapscript.rectObj(-100, -100, 100, 100)) # old values self.assertRectsEqual(new_extent, mapscript.rectObj(-99, -99, 99, 99)) def testZoomOutPointConstrained(self): """ZoomScaleTestCase.testZoomOutPointConstrained: zooming out to a constrained extent returns proper extent""" w, h = (self.mapobj1.width, self.mapobj1.height) max = mapscript.rectObj() max.minx, max.miny, max.maxx, max.maxy = (-100.0, -100.0, 100.0, 100.0) p = mapscript.pointObj() p.x, p.y = (50, 50) extent = self.mapobj1.extent scale = 10000 self.mapobj1.zoomScale(scale, p, w, h, extent, max) new_extent = self.mapobj1.extent self.assertRectsEqual(new_extent, max) if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/fragments.txt000066400000000000000000000042251357574274700227750ustar00rootroot00000000000000Functional tests of mapfile fragment loading ============================================ Setup ----- Use pkg_resources to maintain sanity with setuptools develop builds >>> try: ... import pkg_resources ... msg = pkg_resources.require('mapscript') ... except: ... pass Loading a MAP string -------------------- Empty map >>> import mapscript >>> mo = mapscript.fromstring("""MAP\nNAME "test"\nEND""") >>> mo # doctest: +ELLIPSIS >>> mo.name 'test' >>> del mo With map path Read in the standard mapserver fixture, and verify quickly >>> import os >>> mapfile = os.path.abspath('../../../tests/test.map') >>> maproot = os.path.abspath("%s/.." % mapfile) >>> f = file(mapfile, 'rb') >>> mapstring = f.read() >>> f.close() >>> mapstring.startswith('MAP') True >>> mo = mapscript.fromstring(mapstring, maproot) >>> mo # doctest: +ELLIPSIS >>> mo.name 'Testing' >>> mo.numlayers 7 # Delete so next tests get a clean slate >>> del mo Without map map Massage the mapfile to use absolute paths to resources >>> absmapstr = mapstring.replace('FONTSET "', 'FONTSET "%s/' % maproot) >>> absmapstr = absmapstr.replace('SYMBOLSET "', 'SYMBOLSET "%s/' % maproot) >>> absmapstr = absmapstr.replace('DATA "', 'DATA "%s/' % maproot) >>> mo = mapscript.fromstring(absmapstr) >>> mo # doctest: +ELLIPSIS >>> mo.name 'Testing' >>> mo.numlayers 7 Layers ------ >>> lo = mapscript.fromstring("""LAYER NAME "test" TYPE POINT END""") >>> lo #doctest: +ELLIPSIS >>> lo.name 'test' >>> lo.type == mapscript.MS_LAYER_POINT True Classes ------- >>> co = mapscript.fromstring("""CLASS TITLE "test" END""") >>> co #doctest: +ELLIPSIS >>> co.title 'test' Styles ------ >>> so = mapscript.fromstring("""STYLE END""") >>> so #doctest: +ELLIPSIS mapserver-7.4.3/mapscript/python/tests/runalldoctests.py000066400000000000000000000012671357574274700236710ustar00rootroot00000000000000import doctest import getopt import glob import sys try: import pkg_resources pkg_resources.require('mapscript') except (ImportError, pkg_resources.DistributionNotFound): pass def run(pattern): if pattern is None: testfiles = glob.glob('*.txt') else: testfiles = glob.glob(pattern) for file in testfiles: doctest.testfile(file) if __name__ == "__main__": try: opts, args = getopt.getopt(sys.argv[1:], "t:v") except getopt.GetoptError: print("Usage: python runalldoctests.py [-t GLOB_PATTERN]") sys.exit(2) pattern = None for o, a in opts: if o == '-t': pattern = a run(pattern) mapserver-7.4.3/mapscript/python/tests/rundoctests.dist000077500000000000000000000001161357574274700235060ustar00rootroot00000000000000#!/bin/sh #export PYTHONPATH="YOUR_DEV_PYTHON_PATH" python runalldoctests.py mapserver-7.4.3/mapscript/python/tests/runtests.py000066400000000000000000000126031357574274700225060ustar00rootroot00000000000000# $Id$ # # Project: MapServer # Purpose: Comprehensive xUnit style Python mapscript test suite # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== # # Execute this module as a script from mapserver/mapscript/python # # python tests/runtests.py -v # # =========================================================================== import unittest # Import test cases import cases from cases.recttest import RectObjTestCase from cases.hashtest import HashTableTestCase, WebMetadataTestCase from cases.hashtest import LayerMetadataTestCase, ClassMetadataTestCase from cases.owstest import OWSRequestTestCase from cases.clonetest import MapCloningTestCase from cases.imagetest import ImageObjTestCase, ImageWriteTestCase from cases.imagetest import SaveToStringTestCase from cases.maptest import MapConstructorTestCase from cases.maptest import MapLayersTestCase from cases.maptest import MapExtentTestCase from cases.maptest import MapExceptionTestCase from cases.maptest import EmptyMapExceptionTestCase from cases.maptest import MapMetaDataTestCase from cases.maptest import MapSizeTestCase from cases.layertest import LayerConstructorTestCase from cases.layertest import LayerExtentTestCase from cases.layertest import LayerRasterProcessingTestCase from cases.layertest import LayerTestCase from cases.layertest import RemoveLayerTestCase from cases.zoomtest import ZoomPointTestCase from cases.zoomtest import ZoomRectangleTestCase from cases.zoomtest import ZoomScaleTestCase from cases.linetest import LineObjTestCase from cases.shapetest import ShapePointTestCase from cases.pointtest import PointObjTestCase from cases.shapetest import InlineFeatureTestCase from cases.styletest import DrawProgrammedStylesTestCase from cases.styletest import NewStylesTestCase from cases.styletest import BrushCachingTestCase from cases.colortest import ColorObjTestCase from cases.symboltest import SymbolTestCase from cases.symboltest import MapSymbolTestCase from cases.symbolsettest import SymbolSetTestCase from cases.symbolsettest import MapSymbolSetTestCase from cases.outputformattest import OutputFormatTestCase from cases.outputformattest import MapOutputFormatTestCase from cases.labeltest import LabelCacheMemberTestCase from cases.resultcachetest import ResultCacheTestCase from cases.resultcachetest import PointQueryResultsTestCase from cases.resultcachetest import DumpAndLoadTestCase # Create a test suite suite = unittest.TestSuite() # Add tests to the suite suite.addTests([RectObjTestCase()]) suite.addTests([HashTableTestCase(), WebMetadataTestCase(), LayerMetadataTestCase(), ClassMetadataTestCase()]) suite.addTests([MapCloningTestCase()]) suite.addTests([OWSRequestTestCase()]) suite.addTests([ImageObjTestCase(), ImageWriteTestCase(), SaveToStringTestCase()]) suite.addTests([MapConstructorTestCase(), MapLayersTestCase(), MapExtentTestCase(), MapExceptionTestCase(), EmptyMapExceptionTestCase(), MapMetaDataTestCase()]) suite.addTests([LayerConstructorTestCase(), LayerExtentTestCase(), LayerRasterProcessingTestCase(), RemoveLayerTestCase()]) suite.addTests([LineObjTestCase(), ShapePointTestCase(), PointObjTestCase(), InlineFeatureTestCase()]) suite.addTests([DrawProgrammedStylesTestCase(), NewStylesTestCase(), BrushCachingTestCase(), ColorObjTestCase()]) suite.addTests([SymbolTestCase(), MapSymbolTestCase()]) suite.addTests([SymbolSetTestCase(), MapSymbolSetTestCase()]) suite.addTests([ZoomPointTestCase(), ZoomRectangleTestCase(), ZoomScaleTestCase()]) suite.addTests([OutputFormatTestCase(), MapOutputFormatTestCase()]) suite.addTest(LabelCacheMemberTestCase()) suite.addTests([ResultCacheTestCase(), PointQueryResultsTestCase(), DumpAndLoadTestCase()]) # ============================================================================ # If module is run as a script, execute every test case in the suite if __name__ == '__main__': unittest.main() mapserver-7.4.3/mapscript/python/tests/timing/000077500000000000000000000000001357574274700215325ustar00rootroot00000000000000mapserver-7.4.3/mapscript/python/tests/timing/clonemaps.py000066400000000000000000000037371357574274700240770ustar00rootroot00000000000000# $Id$ # # Timing tests of mapfile parsing vs map cloning import os from shutil import copyfile import timeit from .testing import TESTMAPFILE, mapscript # =========================================================================== # Test 1A: New maps from mapfile # # reloading the mapfile each time print("Test 1A: reloading maps from mapfile") s = """\ m = mapscript.mapObj(TESTMAPFILE) """ t = timeit.Timer(stmt=s, setup='from __main__ import mapscript, TESTMAPFILE') print("%.2f usec/pass" % (1000000 * t.timeit(number=100)/100)) # =========================================================================== # Test 1B: Cloning # # Cloning instead of reloading print("Test 1B: cloning maps instead of reloading") m = mapscript.mapObj(TESTMAPFILE) s = """\ c = m.clone() """ t = timeit.Timer(stmt=s, setup='from __main__ import m') print("%.2f usec/pass" % (1000000 * t.timeit(number=100)/100)) # =========================================================================== # Test 2: Add 20 dups of the POLYGON layer to see how results scale timing_map = mapscript.mapObj(TESTMAPFILE) polygon_layer = timing_map.getLayerByName('POLYGON') # duplicate POLYGON layer 20 times for i in range(20): timing_map.insertLayer(polygon_layer) assert timing_map.numlayers == 24 TIMINGMAPFILE = os.path.join(os.getcwd(), 'timing.map') timing_map.save(TIMINGMAPFILE) copyfile('../../tests/fonts.txt', os.path.join(os.getcwd(), 'fonts.txt')) copyfile('../../tests/symbols.txt', os.path.join(os.getcwd(), 'symbols.txt')) # Test 2A: reloading mapfile print("Test 2A: reloading inflated mapfile") s = """\ m = mapscript.mapObj(TIMINGMAPFILE) """ t = timeit.Timer(stmt=s, setup='from __main__ import mapscript, TIMINGMAPFILE') print("%.2f usec/pass" % (1000000 * t.timeit(number=100)/100)) print("Test 2B: cloning inflated mapfile") m = mapscript.mapObj(TIMINGMAPFILE) s = """\ c = m.clone() """ t = timeit.Timer(stmt=s, setup='from __main__ import m') print("%.2f usec/pass" % (1000000 * t.timeit(number=100)/100)) mapserver-7.4.3/mapscript/python/tests/timing/drawshapes.py000066400000000000000000000055131357574274700242510ustar00rootroot00000000000000# $Id$ # # Timing tests of feature drawing -- map.draw vs drawing features # shape by shape. import getopt import os import sys import timeit from random import random from .testing import mapscript # Get Number of shapes from the command line try: opts, args = getopt.getopt(sys.argv[1:], 'n:') except getopt.GetoptError: sys.exit(2) numshapes = 100 # default to 100 for o, a in opts: if o == '-n': numshapes = int(a) # The shapefileObj shpfile = mapscript.shapefileObj('timing.shp', mapscript.MS_SHAPEFILE_POLYGON) # Inline feature layer ilayer = mapscript.layerObj() ilayer.type = mapscript.MS_LAYER_POLYGON ilayer.setProjection('init=epsg:4326') ilayer.status = mapscript.MS_DEFAULT ilayer.connectiontype = mapscript.MS_INLINE print(numshapes, "shapes") i = 0 while i < numshapes: # The shape to add is randomly generated xc = 4.0*(random() - 0.5) yc = 4.0*(random() - 0.5) r = mapscript.rectObj(xc-0.25, yc-0.25, xc+0.25, yc+0.25) s = r.toPolygon() # Add to shapefile shpfile.add(s) # Add to inline feature layer ilayer.addFeature(s) i = i + 1 del shpfile # closes up the file # Prepare the testing fixture m = mapscript.mapObj('timing.map') l = m.getLayerByName('POLYGON') l.data = os.path.join(os.getcwd(), 'timing') # Save three map images to check afterwards img = m.draw() img.save('timing.png') shpfile = mapscript.shapefileObj('timing.shp') img = m.prepareImage() for i in range(shpfile.numshapes): s = shpfile.getShape(i) s.classindex = 0 s.draw(m, l, img) img.save('timing-shapes.png') class0 = mapscript.classObj(ilayer) class0.insertStyle(l.getClass(0).getStyle(0)) img = m.prepareImage() ilayer.draw(m, img) img.save('timing-inline.png') # ========================================================================= # Test 1A: Draw all shapes at once using map.draw() print("Test 1A: draw map, all shapes at once") s = """\ img = m.draw() """ t = timeit.Timer(stmt=s, setup='from __main__ import m') print("%.2f usec/pass" % (1000000 * t.timeit(number=100)/100)) # ========================================================================= # Test 1B: Draw shape by shape from the shapefileObj print("Test 1B: draw shapes one at a time") s = """\ img = m.prepareImage() for i in range(shpfile.numshapes): s = shpfile.getShape(i) s.classindex = 0 s.draw(m, l, img) """ t = timeit.Timer(stmt=s, setup='from __main__ import m, l, shpfile') print("%.2f usec/pass" % (1000000 * t.timeit(number=100)/100)) # ========================================================================= # Test 1C: Draw shapes after pushing them into an inline layer print("Test 1C: draw inline layer shapes") s = """\ img = m.prepareImage() ilayer.draw(m, img) """ t = timeit.Timer(stmt=s, setup='from __main__ import m, ilayer') print("%.2f usec/pass" % (1000000 * t.timeit(number=100)/100)) mapserver-7.4.3/mapscript/python/tests/timing/testing.py000066400000000000000000000057361357574274700235740ustar00rootroot00000000000000# $Id$ # # Project: MapServer # Purpose: xUnit style Python mapscript testing utilities # Author: Sean Gillies, sgillies@frii.com # # =========================================================================== # Copyright (c) 2004, Sean Gillies # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # =========================================================================== # # Purpose of this module is to export the locally built mapscript module # prior to installation, do some name normalization that allows testing of # the so-called next generation class names, and define some classes # useful to many test cases. # # All test case modules should import mapscript from testing # # from .testing import mapscript # # =========================================================================== import os import sys import distutils.util import unittest # define the path to mapserver test data TESTS_PATH = '../../tests' TESTMAPFILE = os.path.join(TESTS_PATH, 'test.map') XMARKS_IMAGE = os.path.join(TESTS_PATH, 'xmarks.png') TEST_IMAGE = os.path.join(TESTS_PATH, 'test.png') # Put local build directory on head of python path platformdir = '-'.join((distutils.util.get_platform(), '.'.join(map(str, sys.version_info[0:2])))) sys.path.insert(0, os.path.join('build', 'lib.' + platformdir)) # import mapscript from the local build directory import mapscript # normalize names, allows testing of module that uses the experimental # next generation names classnames = [ 'mapObj', 'layerObj', 'classObj', 'styleObj', 'shapeObj', 'lineObj', 'pointObj', 'rectObj', 'outputFormatObj', 'symbolObj', 'symbolSetObj', 'colorObj', 'imageObj', 'shapefileObj', 'projectionObj', 'fontSetObj', 'hashTableObj' ] for name in classnames: try: new_name = name.replace('Obj', '') new_name = new_name.capitalize() new_object = getattr(mapscript, new_name) setattr(mapscript, name, new_object) except AttributeError: pass mapserver-7.4.3/mapscript/python/tests/timing/timing.map000066400000000000000000000013431357574274700235210ustar00rootroot00000000000000MAP NAME "Testing" EXTENT -2 -2 2 2 IMAGETYPE PNG IMAGECOLOR 254 254 254 STATUS ON SIZE 800 800 PROJECTION "init=epsg:4326" END SYMBOL TYPE PIXMAP NAME 'home-png' IMAGE '../../../../tests/home.png' END SYMBOL TYPE PIXMAP NAME 'xmarks-png' IMAGE '../../../../tests/xmarks.png' END LAYER NAME "POLYGON" TYPE POLYGON PROJECTION "init=epsg:4326" END STATUS DEFAULT DATA "timing.shp" CLASS STYLE COLOR 0 0 204 #OUTLINECOLOR 0 0 204 END END END LAYER NAME "POINT" TYPE POINT PROJECTION "init=epsg:4326" END STATUS OFF CLASS STYLE SYMBOL 2 END END END END mapserver-7.4.3/mapscript/ruby/000077500000000000000000000000001357574274700165415ustar00rootroot00000000000000mapserver-7.4.3/mapscript/ruby/CMakeLists.txt000066400000000000000000000022671357574274700213100ustar00rootroot00000000000000find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) find_package(Ruby REQUIRED) include_directories(${RUBY_INCLUDE_DIRS}) include_directories(${PROJECT_SOURCE_DIR}/mapscript/swiginc) include_directories(${PROJECT_SOURCE_DIR}/mapscript/) include_directories(${PROJECT_SOURCE_DIR}/mapscript/ruby) if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} VERSION_GREATER 3.7) swig_add_library(rubymapscript TYPE MODULE LANGUAGE ruby SOURCES ../mapscript.i) else () swig_add_module(rubymapscript ruby ../mapscript.i) endif () swig_link_libraries(rubymapscript ${RUBY_LIBRARY} ${MAPSERVER_LIBMAPSERVER}) set_target_properties(${SWIG_MODULE_rubymapscript_REAL_NAME} PROPERTIES PREFIX "") set_target_properties(${SWIG_MODULE_rubymapscript_REAL_NAME} PROPERTIES OUTPUT_NAME mapscript) if(APPLE) set_target_properties(${SWIG_MODULE_rubymapscript_REAL_NAME} PROPERTIES SUFFIX ".bundle") endif(APPLE) set(mapscript_files $) execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "puts RbConfig::CONFIG['sitearchdir']" OUTPUT_VARIABLE RUBY_SITEARCHDIR OUTPUT_STRIP_TRAILING_WHITESPACE) install(FILES ${mapscript_files} DESTINATION ${RUBY_SITEARCHDIR}) mapserver-7.4.3/mapscript/ruby/README000066400000000000000000000022671357574274700174300ustar00rootroot00000000000000Ruby MapScript Interface ------------------------ BUILD ----- The files that are required to create the library 'mapscript.so' : mapscript.i extconf.rb Be sure that you have installed SWIG version 1.3a5 or greater. The installation is tested with ruby version 1.6 and 1.8. To build type : # ruby extconf.rb # make INSTALL ------- If you don't want to install the library, you have to add the library path as argument to the command (ruby -I[path/to/the/library] ...). To install type as 'root' user : # make install EXAMPLES -------- To run the examples: Go to the directory of the examples # cd examples Run the example to receive information about a shape file # ruby shpinfo.rb [path/shapefile.shp] or if you don't have executed 'make install' # ruby -I[path/to/mapscript.so] shpinfo.rb [path/shapefile.shp] e.g.: # ruby -I.. shpinfo.rb lake2spy.shp Run the example to create a PNG file from a shape file. The output will be in the file [shapefile].png. # ruby shp2img.rb [path/shapefile.shp] or # ruby -I[path/to/mapscript.so] shp2img.rb [path/shapefile.shp] e.g.: # ruby -I.. shp2img.rb lake2spy.shp AUTHOR ------ Markus Schnider msr@sourcepole.ch http://www.sourcepole.com mapserver-7.4.3/mapscript/ruby/examples/000077500000000000000000000000001357574274700203575ustar00rootroot00000000000000mapserver-7.4.3/mapscript/ruby/examples/shp2img.rb000077500000000000000000000015721357574274700222650ustar00rootroot00000000000000#!/usr/bin/env ruby require "mapscript" include Mapscript filename = ARGV[0] shapefile = ShapefileObj.new(filename, -1) shapepath = File.dirname(filename) shapename = File.basename(filename, "....") map = MapObj.new('') map.shapepath = shapepath map.height = 200 map.width = 200 map.extent = shapefile.bounds $shapetypes = { MS_SHAPEFILE_POINT => MS_LAYER_POINT, MS_SHAPEFILE_ARC => MS_LAYER_LINE, MS_SHAPEFILE_POLYGON => MS_LAYER_POLYGON, MS_SHAPEFILE_MULTIPOINT => MS_LAYER_LINE } layer = LayerObj.new(map) layer.name = shapename layer.type = $shapetypes[shapefile.type] layer.status = MS_ON layer.data = shapename cls = ClassObj.new(layer) style = StyleObj.new() color = ColorObj.new() color.red = 107 color.green = 158 color.blue = 160 style.color = color cls.insertStyle(style) #map.save(shapename+'.map') img = map.draw img.save(shapename+'.png') mapserver-7.4.3/mapscript/ruby/extconf.rb000077500000000000000000000022651357574274700205440ustar00rootroot00000000000000#!/usr/bin/env ruby require 'mkmf' require 'pathname' mapscriptvars = File.open("../../mapscriptvars") make_home = mapscriptvars.gets.chomp make_define = mapscriptvars.gets.chomp make_inc = mapscriptvars.gets.chomp make_libs = mapscriptvars.gets.chomp make_static_libs = mapscriptvars.gets.chomp mapscriptvars.close MAPSERVER_LOCAL_LIBS=Pathname.new(File.dirname(__FILE__) + '/../../.libs').realpath # $CFLAGS works only with 1.8 ??? -> the -Wall argument is not needed !!! $CFLAGS = "" $CPPFLAGS = make_inc + " -idirafter $(rubylibdir)/$(arch) " + make_define $LDFLAGS += " -fPIC -Wl,-rpath,#{MAPSERVER_LOCAL_LIBS}" #$LOCAL_LIBS += " -L../../.libs/ " + " -lmapserver " + make_static_libs $LOCAL_LIBS += " -L#{MAPSERVER_LOCAL_LIBS} " + " -lmapserver " # if the source file 'mapscript_wrap.c' is missing nothing works # this is a workaround !! if !FileTest.exist?("mapscript_wrap.c") $objs = [] $objs.push("mapscript_wrap.o") end #CONFIG['LDSHARED'] = "LD_RUN_PATH=#{MAPSERVER_LOCAL_LIBS} " + CONFIG['LDSHARED'] create_makefile("mapscript") make_file = File.open("Makefile", "a") make_file << "\nmapscript_wrap.c: ../mapscript.i\n\tswig -ruby -o mapscript_wrap.c ../mapscript.i" make_file.close mapserver-7.4.3/mapscript/ruby/rbextend.i000066400000000000000000000011171357574274700205260ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Ruby-specific extensions to MapScript objects * Author: * ****************************************************************************** * * Ruby-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGRUBY is defined (via 'swig -ruby ...'). * *****************************************************************************/ mapserver-7.4.3/mapscript/ruby/rbmodule.i000066400000000000000000000101411357574274700205210ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Ruby-specific enhancements to MapScript * Author: * ****************************************************************************** * * Ruby-specific mapscript code has been moved into this * SWIG interface file to improve the readibility of the main * interface file. The main mapscript.i file includes this * file when SWIGRUBY is defined (via 'swig -ruby ...'). * *****************************************************************************/ /****************************************************************************** * Simple Typemaps *****************************************************************************/ /* To support imageObj::getBytes */ %typemap(out) gdBuffer { $result = rb_str_new($1.data, $1.size); msFree($1.data); } /************************************************************************** * MapServer Errors and Ruby Exceptions ************************************************************************** * * Translation of errors reported via the ms_error structure into * Ruby exceptions. Generally copied from Python MapScript by Jim Klassen. * Follows original code by Chris Chamberlin as updated * updated by Sean Gillies . * Uses rb_raise, %exception and $action for SWIG 1.3, do the most * obvious mapping of MapServer errors to Ruby exceptions and map all * others to a new 'MapServerError' exception which can be caught like * this: * * require 'mapscript' * empty_map = Mapscript.MapObj.new('') * begin: * img = empty_map.draw() * rescue Mapscript::MapServerError => msg * print "Caught MapServerError:", msg.to_s * end * *************************************************************************/ %{ VALUE MSExc_MapServerError; VALUE MSExc_MapServerChildError; %} /* Module initialization: call msSetup() and register msCleanup() */ %init %{ /* Copied from pymodule.i to fix #3619 */ if (msSetup() != MS_SUCCESS) { msSetError(MS_MISCERR, "Failed to set up threads and font cache", "msSetup()"); } /* Is there a place to hook to call msCleanup()? */ VALUE exceptionClass = rb_eval_string("Exception"); VALUE mapscriptModule = rb_eval_string("Mapscript"); MSExc_MapServerError = rb_define_class_under(mapscriptModule, "MapserverError", exceptionClass); MSExc_MapServerChildError = rb_define_class_under(mapscriptModule, "MapserverChildErrorError", exceptionClass); %} %{ static void _raise_ms_exception( void ); static void _raise_ms_exception() { int errcode; errorObj *ms_error; char *errmsg; ms_error = msGetErrorObj(); errcode = ms_error->code; errmsg = msGetErrorString("\n"); switch (errcode) { case MS_IOERR: rb_raise(rb_eIOError, errmsg, "%s"); break; case MS_MEMERR: rb_raise(rb_eNoMemError, errmsg, "%s"); break; case MS_TYPEERR: rb_raise(rb_eTypeError, errmsg, "%s"); break; case MS_EOFERR: rb_raise(rb_eEOFError, errmsg, "%s"); break; case MS_CHILDERR: rb_raise(MSExc_MapServerChildError, errmsg, "%s"); break; default: rb_raise(MSExc_MapServerError, errmsg, "%s"); break; } free(errmsg); } %} %exception { msResetErrorList(); $action { errorObj *ms_error = msGetErrorObj(); switch(ms_error->code) { case MS_NOERR: break; case MS_NOTFOUND: msResetErrorList(); break; case -1: break; case MS_IOERR: if (strncmp(ms_error->routine, "msSearchDiskTree()", 20) != 0) { _raise_ms_exception(); msResetErrorList(); return NULL; } default: _raise_ms_exception(); msResetErrorList(); return NULL; } } } mapserver-7.4.3/mapscript/swiginc/000077500000000000000000000000001357574274700172235ustar00rootroot00000000000000mapserver-7.4.3/mapscript/swiginc/class.i000066400000000000000000000167011357574274700205070ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript classObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend classObj { classObj(layerObj *layer=NULL) { classObj *new_class=NULL; if (!layer) { new_class = (classObj *) malloc(sizeof(classObj)); if (!new_class) { msSetError(MS_MEMERR, "Could not allocate memory for new classObj instance", "classObj()"); return NULL; } if (initClass(new_class) == -1) return NULL; new_class->layer = NULL; return new_class; } else { if(msGrowLayerClasses(layer) == NULL) return NULL; if (initClass(layer->class[layer->numclasses]) == -1) return NULL; layer->class[layer->numclasses]->layer = layer; MS_REFCNT_INCR(layer->class[layer->numclasses]); layer->numclasses++; return (layer->class[layer->numclasses-1]); } return NULL; } ~classObj() { if (self) { if (freeClass(self)==MS_SUCCESS) { free(self); self=NULL; } } } int updateFromString(char *snippet) { return msUpdateClassFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteClassToString(self); } #if defined (SWIGJAVA) || defined (SWIGPHP) %newobject cloneClass; classObj *cloneClass() #else %newobject clone; classObj *clone() #endif { classObj *new_class; new_class = (classObj *) malloc(sizeof(classObj)); if (!new_class) { msSetError(MS_MEMERR, "Could not allocate memory for new classObj instance", "clone()"); return NULL; } if (initClass(new_class) == -1) { msSetError(MS_MEMERR, "Failed to initialize Class", "clone()"); return NULL; } new_class->layer = NULL; if (msCopyClass(new_class, self, self->layer) != MS_SUCCESS) { freeClass(new_class); free(new_class); new_class = NULL; } return new_class; } int setExpression(char *expression) { if (!expression || strlen(expression) == 0) { msFreeExpression(&self->expression); return MS_SUCCESS; } else return msLoadExpressionString(&self->expression, expression); } %newobject getExpressionString; char *getExpressionString() { return msGetExpressionString(&(self->expression)); } int setText(char *text) { if (!text || strlen(text) == 0) { msFreeExpression(&self->text); return MS_SUCCESS; } else return msLoadExpressionString(&self->text, text); } %newobject getTextString; char *getTextString() { return msGetExpressionString(&(self->text)); } char *getMetaData(char *name) { char *value = NULL; if (!name) { msSetError(MS_HASHERR, "NULL key", "getMetaData"); } value = (char *) msLookupHashTable(&(self->metadata), name); if (!value) { msSetError(MS_HASHERR, "Key %s does not exist", "getMetaData", name); return NULL; } return value; } int setMetaData(char *name, char *value) { if (msInsertHashTable(&(self->metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } char *getFirstMetaDataKey() { return (char *) msFirstKeyFromHashTable(&(self->metadata)); } char *getNextMetaDataKey(char *lastkey) { return (char *) msNextKeyFromHashTable(&(self->metadata), lastkey); } int drawLegendIcon(mapObj *map, layerObj *layer, int width, int height, imageObj *dstImage, int dstX, int dstY) { if(layer->sizeunits != MS_PIXELS) { map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height); layer->scalefactor = (msInchesPerUnit(layer->sizeunits,0)/msInchesPerUnit(map->units,0)) / map->cellsize; } else layer->scalefactor = map->resolution/map->defresolution; return msDrawLegendIcon(map, layer, self, width, height, dstImage, dstX, dstY, MS_TRUE, NULL); } %newobject createLegendIcon; imageObj *createLegendIcon(mapObj *map, layerObj *layer, int width, int height) { return msCreateLegendIcon(map, layer, self, width, height, MS_TRUE); } %newobject getLabel; labelObj *getLabel(int i) { if (i >= 0 && i < self->numlabels) { MS_REFCNT_INCR(self->labels[i]); return self->labels[i]; } else { msSetError(MS_CHILDERR, "Invalid index: %d.", "getLabel()", i); return NULL; } } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {labelObj *label}; #endif int addLabel(labelObj *label) { return msAddLabelToClass(self, label); } #ifdef SWIGCSHARP %clear labelObj *label; #endif %newobject removeLabel; labelObj *removeLabel(int index) { labelObj* label = (labelObj *) msRemoveLabelFromClass(self, index); if (label) MS_REFCNT_INCR(label); return label; } /* See Bugzilla issue 548 for more details about the *Style methods */ %newobject getStyle; styleObj *getStyle(int i) { if (i >= 0 && i < self->numstyles) { MS_REFCNT_INCR(self->styles[i]); return self->styles[i]; } else { msSetError(MS_CHILDERR, "Invalid index: %d", "getStyle()", i); return NULL; } } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {styleObj *style}; #endif int insertStyle(styleObj *style, int index=-1) { return msInsertStyle(self, style, index); } #ifdef SWIGCSHARP %clear styleObj *style; #endif %newobject removeStyle; styleObj *removeStyle(int index) { styleObj* style = (styleObj *) msRemoveStyle(self, index); if (style) MS_REFCNT_INCR(style); return style; } int moveStyleUp(int index) { return msMoveStyleUp(self, index); } int moveStyleDown(int index) { return msMoveStyleDown(self, index); } } mapserver-7.4.3/mapscript/swiginc/cluster.i000066400000000000000000000045231357574274700210620ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript clusterObj extensions Author: Tamas Szekeres =========================================================================== Copyright (c) 1996-2007 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend clusterObj { int updateFromString(char *snippet) { return msUpdateClusterFromString(self, snippet); } %newobject convertToString; char* convertToString() { return msWriteClusterToString(self); } int setGroup(char *group) { if (!group || strlen(group) == 0) { msFreeExpression(&self->group); return MS_SUCCESS; } else return msLoadExpressionString(&self->group, group); } %newobject getGroupString; char *getGroupString() { return msGetExpressionString(&(self->group)); } int setFilter(char *filter) { if (!filter || strlen(filter) == 0) { msFreeExpression(&self->filter); return MS_SUCCESS; } else return msLoadExpressionString(&self->filter, filter); } %newobject getFilterString; char *getFilterString() { return msGetExpressionString(&(self->filter)); } } mapserver-7.4.3/mapscript/swiginc/color.i000066400000000000000000000106541357574274700205210ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript colorObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %{ #include "../../mapserver.h" %} %extend colorObj { colorObj(int red=0, int green=0, int blue=0, int alpha=255) { colorObj *color; /* Check colors */ if (red > 255 || green > 255 || blue > 255 || alpha>255 || red<-1 || green<-1 || blue<-1 || alpha<0 ) { msSetError(MS_MISCERR, "Invalid color", "colorObj()"); return NULL; } color = (colorObj *)calloc(1, sizeof(colorObj)); if (!color) return(NULL); MS_INIT_COLOR(*color, red, green, blue, alpha); return(color); } ~colorObj() { free(self); } int setRGB(int red, int green, int blue, int alpha = 255) { /* Check colors */ if (red > 255 || green > 255 || blue > 255 || alpha > 255) { msSetError(MS_MISCERR, "Invalid color index.", "setRGB()"); return MS_FAILURE; } MS_INIT_COLOR(*self, red, green, blue, alpha); return MS_SUCCESS; } int setHex(char *psHexColor) { int red, green, blue, alpha = 255; if (psHexColor && (strlen(psHexColor) == 7 || strlen(psHexColor) == 9) && psHexColor[0] == '#') { red = msHexToInt(psHexColor+1); green = msHexToInt(psHexColor+3); blue= msHexToInt(psHexColor+5); if (strlen(psHexColor) == 9) { alpha = msHexToInt(psHexColor+7); } if (red > 255 || green > 255 || blue > 255 || alpha > 255) { msSetError(MS_MISCERR, "Invalid color index.", "setHex()"); return MS_FAILURE; } MS_INIT_COLOR(*self, red, green, blue, alpha); return MS_SUCCESS; } else { msSetError(MS_MISCERR, "Invalid hex color.", "setHex()"); return MS_FAILURE; } } %newobject toHex; char *toHex() { char *hexcolor; if (!self) { msSetError(MS_MISCERR, "Can't express NULL color as hex", "toHex()"); return NULL; } if (self->red < 0 || self->green < 0 || self->blue < 0) { msSetError(MS_MISCERR, "Can't express invalid color as hex", "toHex()"); return NULL; } if (self->alpha == 255) { hexcolor = msSmallMalloc(8); snprintf(hexcolor, 8, "#%02x%02x%02x", self->red, self->green, self->blue); } else if (self->alpha >= 0) { hexcolor = msSmallMalloc(10); snprintf(hexcolor, 10, "#%02x%02x%02x%02x", self->red, self->green, self->blue, self->alpha); } else { msSetError(MS_MISCERR, "Can't express color with invalid alpha as hex", "toHex()"); return NULL; } return hexcolor; } } mapserver-7.4.3/mapscript/swiginc/connpool.i000066400000000000000000000030621357574274700212250ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for connection pool management Author: Umberto Nicoletti, unicoletti@prometeo.it =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ void msConnPoolCloseUnreferenced(); mapserver-7.4.3/mapscript/swiginc/dbfinfo.i000066400000000000000000000047111357574274700210070ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript DBFInfo extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ /* class extensions for DBFInfo - TP mods */ %extend DBFInfo { char *getFieldName(int iField) { static char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pszFieldName; } int getFieldWidth(int iField) { char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pnWidth; } int getFieldDecimals(int iField) { char pszFieldName[1000]; int pnWidth; int pnDecimals; msDBFGetFieldInfo(self, iField, &pszFieldName[0], &pnWidth, &pnDecimals); return pnDecimals; } int getFieldType(int iField) { return msDBFGetFieldInfo(self, iField, NULL, NULL, NULL); } } mapserver-7.4.3/mapscript/swiginc/error.i000066400000000000000000000043271357574274700205340ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript errorObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ /* wrap the errorObj and a few functions */ %include "../../maperror.h" /* A few things neccessary for automatically wrapped functions */ %newobject msGetErrorString; %extend errorObj { errorObj() { return msGetErrorObj(); } ~errorObj() {} errorObj *next() { errorObj *ep; if (self == NULL || self->next == NULL) return NULL; ep = msGetErrorObj(); while (ep != self) { /* We reached end of list of active errorObj and didn't find the errorObj... this is bad! */ if (ep->next == NULL) return NULL; ep = ep->next; } return ep->next; } } mapserver-7.4.3/mapscript/swiginc/hashtable.i000066400000000000000000000065561357574274700213440ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript hashTableObj extensions Author: Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %{ #include "../../maphash.h" %} /* ======================================================================== * Include maphash header, first stating declarations to ignore * ======================================================================== */ /* ignore the hashObj struct */ %ignore hashObj; /* ignore items and make numitems immutable */ %ignore items; %immutable numitems; %include "../../maphash.h" /* ======================================================================== * Extension methods * ======================================================================== */ %extend hashTableObj { /* New instance */ #if defined(SWIGJAVA) || defined(SWIGCSHARP) hashTableObj() { #else hashTableObj(void) { #endif return msCreateHashTable(); } /* Destroy instance */ ~hashTableObj() { msFreeHashTable(self); } /* set a hash item given key and value */ int set(char *key, char *value) { if (msInsertHashTable(self, key, value) == NULL) { return MS_FAILURE; } return MS_SUCCESS; } /* get value from item by its key */ char *get(char *key, char *default_value=NULL) { char *value = NULL; if (!key) { msSetError(MS_HASHERR, "NULL key", "get"); } value = (char *) msLookupHashTable(self, key); if (!value) { return default_value; } return value; } /* Remove one item from hash table */ int remove(char *key) { return msRemoveHashTable(self, key); } /* Clear all items in hash table (to NULL) */ void clear(void) { msFreeHashItems(self); initHashTable(self); } /* Return the next key or first key if prevkey == NULL */ const char *nextKey(char *prevkey=NULL) { return msNextKeyFromHashTable(self, (const char *) prevkey); } } mapserver-7.4.3/mapscript/swiginc/image.i000066400000000000000000000141501357574274700204600ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript imageObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================*/ %extend imageObj { /* imageObj constructor now takes filename as an optional argument. */ imageObj(int width, int height, outputFormatObj *input_format=NULL, const char *file=NULL, double resolution=MS_DEFAULT_RESOLUTION, double defresolution=MS_DEFAULT_RESOLUTION) { imageObj *image=NULL; outputFormatObj *format; rendererVTableObj *renderer = NULL; rasterBufferObj *rb = NULL; if (input_format) { format = input_format; } else { format = msCreateDefaultOutputFormat(NULL, "AGG/PNG", "aggpng"); if (format) msInitializeRendererVTable(format); } if (format == NULL) { msSetError(MS_IMGERR, "Could not create output format", "imageObj()"); return NULL; } if (file) { renderer = format->vtable; rb = (rasterBufferObj*) malloc(sizeof(rasterBufferObj)); if (!rb) { msSetError(MS_MEMERR, NULL, "imageObj()"); return NULL; } if ( (renderer->loadImageFromFile((char *)file, rb)) == MS_FAILURE) { msFreeRasterBuffer(rb); free(rb); return NULL; } image = msImageCreate(rb->width, rb->height, format, NULL, NULL, resolution, defresolution, NULL); if (! image) { msFreeRasterBuffer(rb); free(rb); return NULL; } if(renderer->mergeRasterBuffer(image, rb, 1.0, 0, 0, 0, 0, rb->width, rb->height) != MS_SUCCESS) { msFreeImage(image); image = NULL; } msFreeRasterBuffer(rb); free(rb); return image; } image = msImageCreate(width, height, format, NULL, NULL, resolution, defresolution, NULL); return image; } ~imageObj() { msFreeImage(self); } /* saveGeo - see Bugzilla issue 549 */ void save(char *filename, mapObj *map=NULL) { msSaveImage(map, self, filename ); } /* ====================================================================== write() Write image data to an open file handle. Intended to replace saveToString. See python/pyextend.i for the Python specific version of this method. ====================================================================== */ #ifndef SWIGPYTHON int write( FILE *file=NULL ) { int retval=MS_FAILURE; rendererVTableObj *renderer = NULL; if (MS_RENDERER_PLUGIN(self->format)) { if (file) { renderer = self->format->vtable; /* FIXME? as an improvement, pass a map argument instead of the NULL (see #4216) */ retval = renderer->saveImage(self, NULL, file, self->format); } else { retval = msSaveImage(NULL, self, NULL); } } else { msSetError(MS_IMGERR, "Writing of %s format not implemented", "imageObj::write", self->format->name); } return retval; } #endif /* ------------------------------------------------------------------------- getBytes returns a gdBuffer structure (defined in mapscript.i) which must be typemapped to an object appropriate to the target language. This typemap must also msFree the data member of the gdBuffer. See the type- maps in java/javamodule.i and python/pymodule.i for examples. contributed by Jerry Pisk, jerry.pisk@gmail.com ------------------------------------------------------------------------- */ gdBuffer getBytes() { gdBuffer buffer; buffer.owns_data = MS_TRUE; buffer.data = msSaveImageBuffer(self, &buffer.size, self->format); if( buffer.data == NULL || buffer.size == 0 ) { buffer.data = NULL; msSetError(MS_MISCERR, "Failed to get image buffer", "getBytes"); return buffer; } return buffer; } int getSize() { gdBuffer buffer; int size=0; buffer.data = msSaveImageBuffer(self, &buffer.size, self->format); size = buffer.size; if( buffer.data == NULL || buffer.size == 0 ) { buffer.data = NULL; msSetError(MS_MISCERR, "Failed to get image buffer size", "getSize"); } free(buffer.data); return size; } } mapserver-7.4.3/mapscript/swiginc/label.i000066400000000000000000000107271357574274700204630ustar00rootroot00000000000000/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript labelObj extensions Author: Steve Lime =========================================================================== Copyright (c) 1996-2007 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend labelObj { labelObj() { labelObj *label; label = (labelObj *)calloc(1, sizeof(labelObj)); if (!label) return(NULL); initLabel(label); return(label); } ~labelObj() { freeLabel(self); } int updateFromString(char *snippet) { return msUpdateLabelFromString(self, snippet,MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteLabelToString(self); } int removeBinding(int binding) { if(binding < 0 || binding >= MS_LABEL_BINDING_LENGTH) return MS_FAILURE; if(self->bindings[binding].item) { free(self->bindings[binding].item); self->bindings[binding].item = NULL; self->bindings[binding].index = -1; self->numbindings--; } return MS_SUCCESS; } char *getBinding(int binding) { if(binding < 0 || binding >= MS_LABEL_BINDING_LENGTH) return NULL; return self->bindings[binding].item; } int setBinding(int binding, char *item) { if(!item) return MS_FAILURE; if(binding < 0 || binding >= MS_LABEL_BINDING_LENGTH) return MS_FAILURE; if(self->bindings[binding].item) { free(self->bindings[binding].item); self->bindings[binding].item = NULL; self->bindings[binding].index = -1; self->numbindings--; } self->bindings[binding].item = msStrdup(item); self->numbindings++; return MS_SUCCESS; } int setExpression(char *expression) { if (!expression || strlen(expression) == 0) { msFreeExpression(&self->expression); return MS_SUCCESS; } else return msLoadExpressionString(&self->expression, expression); } %newobject getExpressionString; char *getExpressionString() { return msGetExpressionString(&(self->expression)); } int setText(char *text) { if (!text || strlen(text) == 0) { msFreeExpression(&self->text); return MS_SUCCESS; } else return msLoadExpressionString(&self->text, text); } %newobject getTextString; char *getTextString() { return msGetExpressionString(&(self->text)); } %newobject getStyle; styleObj *getStyle(int i) { if (i >= 0 && i < self->numstyles) { MS_REFCNT_INCR(self->styles[i]); return self->styles[i]; } else { msSetError(MS_CHILDERR, "Invalid index: %d", "getStyle()", i); return NULL; } } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {styleObj *style}; #endif int insertStyle(styleObj *style, int index=-1) { return msInsertLabelStyle(self, style, index); } #ifdef SWIGCSHARP %clear styleObj *style; #endif %newobject removeStyle; styleObj *removeStyle(int index) { styleObj* style = (styleObj *) msRemoveLabelStyle(self, index); if (style) MS_REFCNT_INCR(style); return style; } int moveStyleUp(int index) { return msMoveLabelStyleUp(self, index); } int moveStyleDown(int index) { return msMoveLabelStyleDown(self, index); } } mapserver-7.4.3/mapscript/swiginc/labelcache.i000066400000000000000000000032141357574274700214400ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript labelCacheObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend labelCacheObj { void freeCache() { msFreeLabelCache(self); } } mapserver-7.4.3/mapscript/swiginc/layer.i000066400000000000000000000453231357574274700205200ustar00rootroot00000000000000 /* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript layerObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend layerObj { layerObj(mapObj *map=NULL) { layerObj *layer; int result; if (!map) { layer = (layerObj *) malloc(sizeof(layerObj)); if (!layer) { msSetError(MS_MEMERR, "Failed to initialize Layer", "layerObj()"); return NULL; } result = initLayer(layer, NULL); if (result == MS_SUCCESS) { layer->index = -1; return layer; } else { msSetError(MS_MEMERR, "Failed to initialize Layer", "layerObj()"); return NULL; } } else { if(msGrowMapLayers(map) == NULL) return(NULL); if (initLayer((map->layers[map->numlayers]), map) == -1) return(NULL); map->layers[map->numlayers]->index = map->numlayers; map->layerorder[map->numlayers] = map->numlayers; map->numlayers++; MS_REFCNT_INCR(map->layers[map->numlayers-1]); return (map->layers[map->numlayers-1]); } } void setOpacity(int opacity) { msSetLayerOpacity(self, opacity); } int getOpacity() { if(self->compositer) return (self->compositer->opacity); return (100); } ~layerObj() { /*if (!self->map) {*/ if (self) { if(freeLayer(self)==MS_SUCCESS) { free(self); } } } #if defined (SWIGJAVA) || defined(SWIGPHP) %newobject cloneLayer; layerObj *cloneLayer() #else %newobject clone; layerObj *clone() #endif { layerObj *layer; int result; layer = (layerObj *) malloc(sizeof(layerObj)); if (!layer) { msSetError(MS_MEMERR, "Failed to initialize Layer", "layerObj()"); return NULL; } result = initLayer(layer, NULL); if (result != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to initialize Layer", "layerObj()"); return NULL; } if (msCopyLayer(layer, self) != MS_SUCCESS) { freeLayer(layer); free(layer); layer = NULL; } layer->map = NULL; layer->index = -1; return layer; } int updateFromString(char *snippet) { return msUpdateLayerFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteLayerToString(self); } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {classObj *classobj}; #endif int insertClass(classObj *classobj, int index=-1) { return msInsertClass(self, classobj, index); } #ifdef SWIGCSHARP %clear classObj *classobj; #endif /* removeClass() */ %newobject removeClass; classObj *removeClass(int index) { classObj* c = msRemoveClass(self, index); if (c != NULL) { MS_REFCNT_INCR(c); } return c; } int open() { int status; status = msLayerOpen(self); if (status == MS_SUCCESS) { return msLayerGetItems(self); } return status; } int whichShapes(rectObj rect) { int oldconnectiontype = self->connectiontype; self->connectiontype = MS_INLINE; if(msLayerWhichItems(self, MS_TRUE, NULL) != MS_SUCCESS) { self->connectiontype = oldconnectiontype; return MS_FAILURE; } self->connectiontype = oldconnectiontype; return msLayerWhichShapes(self, rect, MS_FALSE); } %newobject nextShape; shapeObj *nextShape() { int status; shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); status = msLayerNextShape(self, shape); if(status != MS_SUCCESS) { msFreeShape(shape); free(shape); return NULL; } else return shape; } void close() { msLayerClose(self); } %newobject getShape; shapeObj *getShape(resultObj *record) { int retval; shapeObj *shape; if (!record) return NULL; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); shape->type = self->type; /* is this right? */ retval = msLayerGetShape(self, shape, record); if(retval != MS_SUCCESS) { msFreeShape(shape); free(shape); return NULL; } else return shape; } int getNumResults() { if (!self->resultcache) return 0; return self->resultcache->numresults; } %newobject getResultsBounds; rectObj *getResultsBounds() { rectObj *bounds; if (!self->resultcache) return NULL; bounds = (rectObj *) malloc(sizeof(rectObj)); MS_COPYRECT(bounds, &self->resultcache->bounds); return bounds; } resultObj *getResult(int i) { if (!self->resultcache) return NULL; if (i >= 0 && i < self->resultcache->numresults) return &self->resultcache->results[i]; else return NULL; } %newobject getClass; classObj *getClass(int i) { classObj *result=NULL; if (i >= 0 && i < self->numclasses) { result=self->class[i]; MS_REFCNT_INCR(result); } return result; } char *getItem(int i) { if (i >= 0 && i < self->numitems) return (char *) (self->items[i]); else return NULL; } int setItems(char **items, int numitems) { return msLayerSetItems(self, items, numitems); } int draw(mapObj *map, imageObj *image) { return msDrawLayer(map, self, image); } int drawQuery(mapObj *map, imageObj *image) { return msDrawQueryLayer(map, self, image); } /* For querying, we switch layer status ON and then back to original value before returning. */ int queryByFilter(mapObj *map, char *string) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_FILTER; map->query.mode = MS_QUERY_MULTIPLE; map->query.filter.string = msStrdup(string); map->query.filter.type = MS_EXPRESSION; map->query.layer = self->index; map->query.rect = map->extent; status = self->status; self->status = MS_ON; retval = msQueryByFilter(map); self->status = status; return retval; } int queryByAttributes(mapObj *map, char *qitem, char *qstring, int mode) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_FILTER; map->query.mode = mode; if(qitem) map->query.filteritem = msStrdup(qitem); if(qstring) { msInitExpression(&map->query.filter); msLoadExpressionString(&map->query.filter, qstring); } map->query.layer = self->index; map->query.rect = map->extent; status = self->status; self->status = MS_ON; retval = msQueryByFilter(map); self->status = status; return retval; } int queryByPoint(mapObj *map, pointObj *point, int mode, double buffer) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_POINT; map->query.mode = mode; map->query.point = *point; map->query.buffer = buffer; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByPoint(map); self->status = status; return retval; } int queryByRect(mapObj *map, rectObj rect) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_RECT; map->query.mode = MS_QUERY_MULTIPLE; map->query.rect = rect; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByRect(map); self->status = status; return retval; } int queryByFeatures(mapObj *map, int slayer) { int status; int retval; map->query.slayer = slayer; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByFeatures(map); self->status = status; return retval; } int queryByShape(mapObj *map, shapeObj *shape) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_SHAPE; map->query.mode = MS_QUERY_MULTIPLE; map->query.shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(map->query.shape); msCopyShape(shape, map->query.shape); map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByShape(map); self->status = status; return retval; } int queryByIndex(mapObj *map, int tileindex, int shapeindex, int bAddToQuery=MS_FALSE) { int status; int retval; msInitQuery(&(map->query)); map->query.type = MS_QUERY_BY_INDEX; map->query.mode = MS_QUERY_SINGLE; map->query.tileindex = tileindex; map->query.shapeindex = shapeindex; map->query.clear_resultcache = !bAddToQuery; map->query.layer = self->index; status = self->status; self->status = MS_ON; retval = msQueryByIndex(map); self->status = status; return retval; } resultCacheObj *getResults(void) { return self->resultcache; } int setFilter(char *filter) { if (!filter || strlen(filter) == 0) { msFreeExpression(&self->filter); return MS_SUCCESS; } else return msLoadExpressionString(&self->filter, filter); } %newobject getFilterString; char *getFilterString() { return msGetExpressionString(&(self->filter)); } int setWKTProjection(char *wkt) { self->project = MS_TRUE; return msOGCWKT2ProjectionObj(wkt, &(self->projection), self->debug); } %newobject getProjection; char *getProjection() { return (char *) msGetProjectionString(&(self->projection)); } int setProjection(char *proj4) { self->project = MS_TRUE; return msLoadProjectionString(&(self->projection), proj4); } int addFeature(shapeObj *shape) { self->connectiontype = MS_INLINE; if(self->features != NULL && self->features->tailifhead != NULL) shape->index = self->features->tailifhead->shape.index + 1; else shape->index = 0; if (insertFeatureList(&(self->features), shape) == NULL) return MS_FAILURE; return MS_SUCCESS; } /* Returns the number of inline feature of a layer */ int getNumFeatures() { return msLayerGetNumFeatures(self); } %newobject getExtent; rectObj *getExtent() { rectObj *extent; extent = (rectObj *) malloc(sizeof(rectObj)); msLayerGetExtent(self, extent); return extent; } int setExtent(double minx=-1.0, double miny=-1.0, double maxx=-1.0, double maxy=-1.0) { if (minx > maxx || miny > maxy) { msSetError(MS_RECTERR, "{ 'minx': %f , 'miny': %f , 'maxx': %f , 'maxy': %f }", "layerObj::setExtent()", minx, miny, maxx, maxy); return MS_FAILURE; } return msLayerSetExtent(self, minx, miny, maxx, maxy); } /* The following metadata methods are no longer needed since we have promoted the metadata member of layerObj to a first-class mapscript object. See hashtable.i. Not yet scheduled for deprecation but perhaps in the next major release? --SG */ char *getMetaData(char *name) { char *value = NULL; if (!name) { msSetError(MS_HASHERR, "NULL key", "getMetaData"); } value = (char *) msLookupHashTable(&(self->metadata), name); /* Umberto, 05/17/2006 Exceptions should be reserved for situations when a serious error occurred and normal program flow must be interrupted. In this case returning null should be more that enough. */ #ifndef SWIGJAVA if (!value) { msSetError(MS_HASHERR, "Key %s does not exist", "getMetaData", name); return NULL; } #endif return value; } int setMetaData(char *name, char *value) { if (msInsertHashTable(&(self->metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } int removeMetaData(char *name) { return(msRemoveHashTable(&(self->metadata), name)); } char *getFirstMetaDataKey() { return (char *) msFirstKeyFromHashTable(&(self->metadata)); } char *getNextMetaDataKey(char *lastkey) { return (char *) msNextKeyFromHashTable(&(self->metadata), lastkey); } %newobject getWMSFeatureInfoURL; char *getWMSFeatureInfoURL(mapObj *map, int click_x, int click_y, int feature_count, char *info_format) { return (char *) msWMSGetFeatureInfoURL(map, self, click_x, click_y, feature_count, info_format); } %newobject executeWFSGetFeature; char *executeWFSGetFeature(layerObj *layer) { return (char *) msWFSExecuteGetFeature(layer); } int applySLD(char *sld, char *stylelayer) { return msSLDApplySLD(self->map, sld, self->index, stylelayer, NULL); } int applySLDURL(char *sld, char *stylelayer) { return msSLDApplySLDURL(self->map, sld, self->index, stylelayer, NULL); } %newobject generateSLD; char *generateSLD() { return (char *) msSLDGenerateSLD(self->map, self->index, NULL); } int isVisible() { if (!self->map) { msSetError(MS_MISCERR, "visibility has no meaning outside of a map context", "isVisible()"); return MS_FAILURE; } return msLayerIsVisible(self->map, self); } int moveClassUp(int index) { return msMoveClassUp(self, index); } int moveClassDown(int index) { return msMoveClassDown(self, index); } void setProcessingKey(const char *key, const char *value) { msLayerSetProcessingKey( self, key, value ); } /* this method is deprecated ... should use addProcessing() */ void setProcessing(const char *directive ) { msLayerAddProcessing( self, directive ); } void addProcessing(const char *directive ) { msLayerAddProcessing( self, directive ); } char *getProcessing(int index) { return (char *) msLayerGetProcessing(self, index); } char *getProcessingKey(const char *key) { return (char *) msLayerGetProcessingKey(self, key); } int clearProcessing() { return msLayerClearProcessing(self); } int setConnectionType(int connectiontype, const char *library_str) { /* Caller is responsible to close previous layer correctly before * calling msConnectLayer() */ if (msLayerIsOpen(self)) msLayerClose(self); return msConnectLayer(self, connectiontype, library_str); } int getClassIndex(mapObj *map, shapeObj *shape, int *classgroup=NULL, int numclasses=0) { return msShapeGetClass(self, map, shape, classgroup, numclasses); } char *getGeomTransform() { return self->_geomtransform.string; } void setGeomTransform(char *transform) { msFree(self->_geomtransform.string); if (!transform || strlen(transform) > 0) { self->_geomtransform.string = msStrdup(transform); self->_geomtransform.type = MS_GEOMTRANSFORM_EXPRESSION; } else { self->_geomtransform.type = MS_GEOMTRANSFORM_NONE; self->_geomtransform.string = NULL; } } %feature("autodoc", "3"); %feature("docstring") "Returns the requested item's field type. A layer must be open to retrieve the item definition. Pass in the attribute index to retrieve the type. The layer's numitems property contains the number of items available, and the first item is index zero." char *getItemType(int i) { char *itemType = NULL; if (i >= 0 && i < self->numitems) { gmlItemListObj *item_list; item_list = msGMLGetItems(self, "G"); if (item_list != NULL) { gmlItemObj *item = item_list->items + i; itemType = msStrdup(item->type); msGMLFreeItems(item_list); // destroy the original list } } return itemType; } } mapserver-7.4.3/mapscript/swiginc/legend.i000066400000000000000000000033151357574274700206350ustar00rootroot00000000000000/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript legendObj extensions Author: Steve Lime =========================================================================== Copyright (c) 1996-2007 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend legendObj { int updateFromString(char *snippet) { return msUpdateLegendFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteLegendToString(self); } } mapserver-7.4.3/mapscript/swiginc/line.i000066400000000000000000000056511357574274700203330ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript lineObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend lineObj { lineObj() { lineObj *line; line = (lineObj *)malloc(sizeof(lineObj)); if (!line) return(NULL); line->numpoints=0; line->point=NULL; return line; } ~lineObj() { free(self->point); free(self); } int project(projectionObj *projin, projectionObj *projout) { return msProjectLine(projin, projout, self); } pointObj *get(int i) { if (i<0 || i>=self->numpoints) return NULL; else return &(self->point[i]); } int add(pointObj *p) { if (self->numpoints == 0) { /* new */ self->point = (pointObj *)malloc(sizeof(pointObj)); if (!self->point) return MS_FAILURE; } else { /* extend array */ self->point = (pointObj *)realloc(self->point, sizeof(pointObj)*(self->numpoints+1)); if (!self->point) return MS_FAILURE; } self->point[self->numpoints].x = p->x; self->point[self->numpoints].y = p->y; self->numpoints++; return MS_SUCCESS; } int set(int i, pointObj *p) { if (i<0 || i>=self->numpoints) return MS_FAILURE; self->point[i].x = p->x; self->point[i].y = p->y; return MS_SUCCESS; } } mapserver-7.4.3/mapscript/swiginc/map.i000066400000000000000000000334501357574274700201570ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript mapObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend mapObj { mapObj(char *filename="") { if (filename && strlen(filename)) return msLoadMap(filename, NULL); else { /* create an empty map, no layers etc... */ return msNewMapObj(); } } #ifdef SWIGCSHARP mapObj(char *mapText, int isMapText /*used as signature only to differentiate this constructor from default constructor*/ ) { return msLoadMapFromString(mapText, NULL); } #endif ~mapObj() { msFreeMap(self); } #if defined (SWIGJAVA) || defined (SWIGPHP) %newobject cloneMap; mapObj *cloneMap() #else %newobject clone; mapObj *clone() #endif { mapObj *dstMap; dstMap = msNewMapObj(); if (msCopyMap(dstMap, self) != MS_SUCCESS) { msFreeMap(dstMap); dstMap = NULL; } return dstMap; } #ifdef SWIGCSHARP %apply SWIGTYPE *SETREFERENCE {layerObj *layer}; #endif int insertLayer(layerObj *layer, int index=-1) { return msInsertLayer(self, layer, index); } #ifdef SWIGCSHARP %clear layerObj *layer; #endif %newobject removeLayer; layerObj *removeLayer(int index) { layerObj *layer=msRemoveLayer(self, index); MS_REFCNT_INCR(layer); return layer; } int setExtent(double minx, double miny, double maxx, double maxy) { return msMapSetExtent( self, minx, miny, maxx, maxy ); } int offsetExtent(double x, double y) { return msMapOffsetExtent( self, x, y ); } int scaleExtent(double zoomfactor, double minscaledenom, double maxscaledenom) { return msMapScaleExtent( self, zoomfactor, minscaledenom, maxscaledenom ); } int setCenter(pointObj *center) { return msMapSetCenter( self, center ); } /* recent rotation work makes setSize the only reliable method for changing the image size. direct access is deprecated. */ int setSize(int width, int height) { return msMapSetSize(self, width, height); } int setRotation( double rotation_angle ) { return msMapSetRotation( self, rotation_angle ); } %newobject getLayer; layerObj *getLayer(int i) { if(i >= 0 && i < self->numlayers) { MS_REFCNT_INCR(self->layers[i]); return (self->layers[i]); /* returns an EXISTING layer */ } else { return NULL; } } %newobject getLayerByName; layerObj *getLayerByName(char *name) { int i; i = msGetLayerIndex(self, name); if(i != -1) { MS_REFCNT_INCR(self->layers[i]); return (self->layers[i]); /* returns an EXISTING layer */ } else return NULL; } int getSymbolByName(char *name) { return msGetSymbolIndex(&self->symbolset, name, MS_TRUE); } void prepareQuery() { int status; status = msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &self->scaledenom); if(status != MS_SUCCESS) self->scaledenom = -1; } %newobject prepareImage; imageObj *prepareImage() { return msPrepareImage(self, MS_FALSE); } void setImageType( char * imagetype ) { outputFormatObj *format; format = msSelectOutputFormat( self, imagetype ); if( format == NULL ) msSetError(MS_MISCERR, "Unable to find IMAGETYPE '%s'.", "setImageType()", imagetype ); else { msFree( self->imagetype ); self->imagetype = msStrdup(imagetype); msApplyOutputFormat( &(self->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } } void selectOutputFormat( char *imagetype ) { outputFormatObj *format; format = msSelectOutputFormat( self, imagetype ); if ( format == NULL ) msSetError(MS_MISCERR, "Unable to find IMAGETYPE '%s'.", "setImageType()", imagetype ); else { msFree( self->imagetype ); self->imagetype = msStrdup(imagetype); msApplyOutputFormat( &(self->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } } %newobject getOutputFormat; outputFormatObj *getOutputFormat(int i) { if(i >= 0 && i < self->numoutputformats) { MS_REFCNT_INCR(self->outputformatlist[i]); return (self->outputformatlist[i]); } else { return NULL; } } void setOutputFormat( outputFormatObj *format ) { msApplyOutputFormat( &(self->outputformat), format, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE ); } %newobject draw; imageObj *draw() { #if defined(WIN32) && defined(SWIGCSHARP) __try { return msDrawMap(self, MS_FALSE); } __except(1 /*EXCEPTION_EXECUTE_HANDLER, catch every exception so it doesn't crash IIS*/) { msSetError(MS_IMGERR, "Unhandled exception in drawing map image 0x%08x", "msDrawMap()", GetExceptionCode()); } #else return msDrawMap(self, MS_FALSE); #endif } %newobject drawQuery; imageObj *drawQuery() { return msDrawMap(self, MS_TRUE); } %newobject drawLegend; imageObj *drawLegend() { return msDrawLegend(self, MS_FALSE, NULL); } %newobject drawScalebar; imageObj *drawScalebar() { return msDrawScalebar(self); } %newobject drawReferenceMap; imageObj *drawReferenceMap() { return msDrawReferenceMap(self); } int embedScalebar(imageObj *image) { return msEmbedScalebar(self, image); } int embedLegend(imageObj *image) { return msEmbedLegend(self, image); } int drawLabelCache(imageObj *image) { return msDrawLabelCache(self,image); } int queryByFilter(char *string) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_FILTER; self->query.mode = MS_QUERY_MULTIPLE; self->query.filter.string = msStrdup(string); self->query.filter.type = MS_EXPRESSION; self->query.rect = self->extent; return msQueryByFilter(self); } int queryByPoint(pointObj *point, int mode, double buffer) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_POINT; self->query.mode = mode; self->query.point = *point; self->query.buffer = buffer; return msQueryByPoint(self); } int queryByRect(rectObj rect) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_RECT; self->query.mode = MS_QUERY_MULTIPLE; self->query.rect = rect; return msQueryByRect(self); } int queryByFeatures(int slayer) { self->query.slayer = slayer; return msQueryByFeatures(self); } int queryByShape(shapeObj *shape) { msInitQuery(&(self->query)); self->query.type = MS_QUERY_BY_SHAPE; self->query.mode = MS_QUERY_MULTIPLE; self->query.shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(self->query.shape); msCopyShape(shape, self->query.shape); return msQueryByShape(self); } int setWKTProjection(char *wkt) { return msOGCWKT2ProjectionObj(wkt, &(self->projection), self->debug); } %newobject getProjection; char *getProjection() { return msGetProjectionString(&(self->projection)); } int setProjection(char *proj4) { return msLoadProjectionString(&(self->projection), proj4); } int save(char *filename) { return msSaveMap(self, filename); } int saveQuery(char *filename, int results=MS_FALSE) { return msSaveQuery(self, filename, results); } int loadQuery(char *filename) { return msLoadQuery(self, filename); } void freeQuery(int qlayer=-1) { msQueryFree(self, qlayer); } int saveQueryAsGML(char *filename, const char *ns="GOMF") { return msGMLWriteQuery(self, filename, ns); } char *getMetaData(char *name) { char *value = NULL; if (!name) { msSetError(MS_HASHERR, "NULL key", "getMetaData"); } value = (char *) msLookupHashTable(&(self->web.metadata), name); if (!value) { msSetError(MS_HASHERR, "Key %s does not exist", "getMetaData", name); return NULL; } return value; } int setMetaData(char *name, char *value) { if (msInsertHashTable(&(self->web.metadata), name, value) == NULL) return MS_FAILURE; return MS_SUCCESS; } int removeMetaData(char *name) { return(msRemoveHashTable(&(self->web.metadata), name)); } char *getFirstMetaDataKey() { return (char *) msFirstKeyFromHashTable(&(self->web.metadata)); } char *getNextMetaDataKey(char *lastkey) { return (char *) msNextKeyFromHashTable(&(self->web.metadata), lastkey); } int setSymbolSet(char *szFileName) { msFreeSymbolSet(&self->symbolset); msInitSymbolSet(&self->symbolset); self->symbolset.filename = msStrdup(szFileName); /* Symbolset shares same fontset as main mapfile */ self->symbolset.fontset = &(self->fontset); return msLoadSymbolSet(&self->symbolset, self); } int getNumSymbols() { return self->symbolset.numsymbols; } int setFontSet(char *filename) { msFreeFontSet(&(self->fontset)); msInitFontSet(&(self->fontset)); self->fontset.filename = msStrdup(filename); return msLoadFontSet(&(self->fontset), self); } /* I removed a method to get the fonset filename. Instead I updated mapserver.h to allow SWIG access to the fonset, although the numfonts and filename members are read-only. Use the setFontSet method to actually change the fontset. To get the filename do $map->{fontset}->{filename}; -- SG */ int saveMapContext(char *szFileName) { return msSaveMapContext(self, szFileName); } int loadMapContext(char *szFileName, int useUniqueNames=MS_FALSE) { return msLoadMapContext(self, szFileName, useUniqueNames); } int moveLayerUp(int layerindex) { return msMoveLayerUp(self, layerindex); } int moveLayerDown(int layerindex) { return msMoveLayerDown(self, layerindex); } %newobject getLayersDrawingOrder; intarray *getLayersDrawingOrder() { int i; intarray *order; order = new_intarray(self->numlayers); for (i=0; inumlayers; i++) #if (defined(SWIGPYTHON) || defined(SWIGRUBY) ) && SWIG_VERSION >= 0x010328 /* 1.3.28 */ intarray___setitem__(order, i, self->layerorder[i]); #else intarray_setitem(order, i, self->layerorder[i]); #endif return order; } int setLayersDrawingOrder(int *panIndexes) { return msSetLayersdrawingOrder(self, panIndexes); } void setConfigOption(char *key, char *value) { msSetConfigOption(self,key,value); } char *getConfigOption(char *key) { return (char *) msGetConfigOption(self,key); } void applyConfigOptions() { msApplyMapConfigOptions( self ); } /* SLD */ int applySLD(char *sld) { return msSLDApplySLD(self, sld, -1, NULL, NULL); } int applySLDURL(char *sld) { return msSLDApplySLDURL(self, sld, -1, NULL, NULL); } %newobject generateSLD; char *generateSLD() { return (char *) msSLDGenerateSLD(self, -1, NULL); } %newobject processTemplate; char *processTemplate(int bGenerateImages, char **names, char **values, int numentries) { return msProcessTemplate(self, bGenerateImages, names, values, numentries); } %newobject processLegendTemplate; char *processLegendTemplate(char **names, char **values, int numentries) { return msProcessLegendTemplate(self, names, values, numentries); } %newobject processQueryTemplate; char *processQueryTemplate(char **names, char **values, int numentries) { return msProcessQueryTemplate(self, 1, names, values, numentries); } outputFormatObj *getOutputFormatByName(char *name) { return msSelectOutputFormat(self, name); } int appendOutputFormat(outputFormatObj *format) { return msAppendOutputFormat(self, format); } int removeOutputFormat(char *name) { return msRemoveOutputFormat(self, name); } int loadOWSParameters(cgiRequestObj *request, char *wmtver_string="1.1.1") { return msMapLoadOWSParameters(self, request, wmtver_string); } int OWSDispatch( cgiRequestObj *req ) { return msOWSDispatch( self, req, MS_TRUE ); } %newobject convertToString; char* convertToString() { return msWriteMapToString(self); } } mapserver-7.4.3/mapscript/swiginc/mapzoom.i000066400000000000000000000643701357574274700210710ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Map zooming convenience methods for MapScript * Author: Sean Gillies, sgillies@frii.com * ****************************************************************************** * * These functions are adapted from the code in php_mapscript.c. * *****************************************************************************/ %extend mapObj { /* ----------------------------------------------------------------------- Zoom by the given factor to a pixel position within the width and height bounds. If max_extent is not NULL, the zoom is constrained to the max_extents ----------------------------------------------------------------------- */ int zoomPoint(int zoomfactor, pointObj *poPixPos, int width, int height, rectObj *poGeorefExt, rectObj *poMaxGeorefExt) { double dfGeoPosX, dfGeoPosY; double dfDeltaX, dfDeltaY; rectObj oNewGeorefExt; double dfNewScale; int bMaxExtSet; double dfDeltaExt; double dX, dY; dfNewScale = 0.0; bMaxExtSet = 0; dfDeltaExt = -1.0; if (poMaxGeorefExt != NULL) { bMaxExtSet = 1; } /* ----------------------------------------------------------- */ /* check the validity of the parameters. */ /* ----------------------------------------------------------- */ if (zoomfactor == 0 || width <= 0 || height <= 0 || poGeorefExt == NULL || poPixPos == NULL) { msSetError(MS_MISCERR, "Incorrect arguments", "mapscript::mapObj::zoomPoint()"); return MS_FAILURE; } /* ----------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* ----------------------------------------------------------- */ if (poGeorefExt->minx >= poGeorefExt->maxx) { msSetError(MS_MISCERR, "Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomPoint()"); return MS_FAILURE; } if (poGeorefExt->miny >= poGeorefExt->maxy) { msSetError(MS_MISCERR, "Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomPoint()"); return MS_FAILURE; } if (bMaxExtSet == 1) { if (poMaxGeorefExt->minx >= poMaxGeorefExt->maxx) { msSetError(MS_MISCERR, "Max Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomPoint()"); return MS_FAILURE; } if (poMaxGeorefExt->miny >= poMaxGeorefExt->maxy) { msSetError(MS_MISCERR, "Max Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomPoint()"); } } dfDeltaX = poGeorefExt->maxx - poGeorefExt->minx; dfDeltaY = poGeorefExt->maxy - poGeorefExt->miny; dX = dfDeltaX/((double)width); dY = dfDeltaY/((double)height); dfGeoPosX = poGeorefExt->minx + dX * (double)poPixPos->x; dfGeoPosY = poGeorefExt->maxy - dY * (double)poPixPos->y; /* --- -------------------------------------------------------- */ /* zoom in */ /* ------------------------------------------------------------ */ if (zoomfactor > 1) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaX/(2*zoomfactor)); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaY/(2*zoomfactor)); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaX/(2*zoomfactor)); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaY/(2*zoomfactor)); } if (zoomfactor < 0) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaX/2)*(abs(zoomfactor)); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaY/2)*(abs(zoomfactor)); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaX/2)*(abs(zoomfactor)); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaY/2)*(abs(zoomfactor)); } if (zoomfactor == 1) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaX/2); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaY/2); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaX/2); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaY/2); } /* ------------------------------------------------------------ */ /* if the min and max scale are set in the map file, we will */ /* use them to test before zooming. */ /* ------------------------------------------------------------ */ msAdjustExtent(&oNewGeorefExt, self->width, self->height); msCalculateScale(oNewGeorefExt, self->units, self->width, self->height, self->resolution, &dfNewScale); if (self->web.maxscaledenom > 0) { if (zoomfactor < 0 && dfNewScale > self->web.maxscaledenom) { return MS_FAILURE; } } /* ============================================================ */ /* we do a spcial case for zoom in : we try to zoom as much as */ /* possible using the mincale set in the .map. */ /* ============================================================ */ if (self->web.minscaledenom > 0 && dfNewScale < self->web.minscaledenom && zoomfactor > 1) { /* To be consistent in swig mapscript and PHP mapscript, use the same function to calculate the delta extents. */ dfDeltaExt = GetDeltaExtentsUsingScale(self->web.minscaledenom, self->units, dfGeoPosY, self->width, self->resolution); if (dfDeltaExt > 0.0) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaExt/2); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaExt/2); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaExt/2); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaExt/2); } else return MS_FAILURE; } /* ------------------------------------------------------------ */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* ------------------------------------------------------------ */ if (bMaxExtSet) { dfDeltaX = oNewGeorefExt.maxx - oNewGeorefExt.minx; dfDeltaY = oNewGeorefExt.maxy - oNewGeorefExt.miny; /* Make sure Current georef extents is not bigger than * max extents */ if (dfDeltaX > (poMaxGeorefExt->maxx-poMaxGeorefExt->minx)) dfDeltaX = poMaxGeorefExt->maxx-poMaxGeorefExt->minx; if (dfDeltaY > (poMaxGeorefExt->maxy-poMaxGeorefExt->miny)) dfDeltaY = poMaxGeorefExt->maxy-poMaxGeorefExt->miny; if (oNewGeorefExt.minx < poMaxGeorefExt->minx) { oNewGeorefExt.minx = poMaxGeorefExt->minx; oNewGeorefExt.maxx = oNewGeorefExt.minx + dfDeltaX; } if (oNewGeorefExt.maxx > poMaxGeorefExt->maxx) { oNewGeorefExt.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (oNewGeorefExt.miny < poMaxGeorefExt->miny) { oNewGeorefExt.miny = poMaxGeorefExt->miny; oNewGeorefExt.maxy = oNewGeorefExt.miny + dfDeltaY; } if (oNewGeorefExt.maxy > poMaxGeorefExt->maxy) { oNewGeorefExt.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } /* ------------------------------------------------------------ */ /* set the map extents with new values. */ /* ------------------------------------------------------------ */ self->extent.minx = oNewGeorefExt.minx; self->extent.miny = oNewGeorefExt.miny; self->extent.maxx = oNewGeorefExt.maxx; self->extent.maxy = oNewGeorefExt.maxy; self->cellsize = msAdjustExtent(&(self->extent), self->width, self->height); dfDeltaX = self->extent.maxx - self->extent.minx; dfDeltaY = self->extent.maxy - self->extent.miny; if (bMaxExtSet) { if (self->extent.minx < poMaxGeorefExt->minx) { self->extent.minx = poMaxGeorefExt->minx; self->extent.maxx = self->extent.minx + dfDeltaX; } if (self->extent.maxx > poMaxGeorefExt->maxx) { self->extent.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (self->extent.miny < poMaxGeorefExt->miny) { self->extent.miny = poMaxGeorefExt->miny; self->extent.maxy = self->extent.miny + dfDeltaY; } if (self->extent.maxy > poMaxGeorefExt->maxy) { self->extent.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &(self->scaledenom)); return MS_SUCCESS; } int zoomRectangle(rectObj *poPixRect, int width, int height, rectObj *poGeorefExt, rectObj *poMaxGeorefExt) { double dfDeltaX, dfDeltaY; rectObj oNewGeorefExt; double dfNewScale; double dfDeltaExt; double dfMiddleX, dfMiddleY; int bMaxExtSet; bMaxExtSet = 0; dfNewScale = 0.0; dfDeltaExt = -1.0; if (poMaxGeorefExt != NULL) bMaxExtSet = 1; /* ----------------------------------------------------------- */ /* check the validity of the parameters. */ /* ----------------------------------------------------------- */ if (poPixRect == 0 || width <= 0 || height <= 0 || poGeorefExt == NULL) { msSetError(MS_MISCERR, "Incorrect arguments", "mapscript::mapObj::zoomRectangle"); return MS_FAILURE; } /* ----------------------------------------------------------- */ /* check if the values passed are consistent min <= max. */ /* ----------------------------------------------------------- */ if (poPixRect->minx >= poPixRect->maxx) { msSetError(MS_MISCERR, "image rectangle minx >= maxx", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } /* This is not a typo: "maxx >= minx". For historical reason, we * keep this as it is. See documentation for more info about this check. */ if (poPixRect->maxy >= poPixRect->miny) { msSetError(MS_MISCERR, "image rectangle maxy >= miny", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } if (poGeorefExt->minx >= poGeorefExt->maxx) { msSetError(MS_MISCERR, "Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } if (poGeorefExt->miny >= poGeorefExt->maxy) { msSetError(MS_MISCERR, "Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } if (bMaxExtSet == 1) { if (poMaxGeorefExt->minx >= poMaxGeorefExt->maxx) { msSetError(MS_MISCERR, "Max Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } if (poMaxGeorefExt->miny >= poMaxGeorefExt->maxy) { msSetError(MS_MISCERR, "Max Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomRectangle()"); return MS_FAILURE; } } /* ----------------------------------------------------------- */ /* Convert pixel rectangle to georeferenced rectangle */ /* ----------------------------------------------------------- */ dfDeltaX = poGeorefExt->maxx - poGeorefExt->minx; dfDeltaY = poGeorefExt->maxy - poGeorefExt->miny; oNewGeorefExt.minx = Pix2Georef((int)poPixRect->minx, 0, width, poGeorefExt->minx, poGeorefExt->maxx, 0); oNewGeorefExt.maxx = Pix2Georef((int)poPixRect->maxx, 0, width, poGeorefExt->minx, poGeorefExt->maxx, 0); oNewGeorefExt.miny = Pix2Georef((int)poPixRect->miny, 0, height, poGeorefExt->miny, poGeorefExt->maxy, 1); oNewGeorefExt.maxy = Pix2Georef((int)poPixRect->maxy, 0, height, poGeorefExt->miny, poGeorefExt->maxy, 1); msAdjustExtent(&oNewGeorefExt, self->width, self->height); /* ------------------------------------------------------------ */ /* if the min and max scale are set in the map file, we will */ /* use them to test before setting extents. */ /* ------------------------------------------------------------ */ msCalculateScale(oNewGeorefExt, self->units, self->width, self->height, self->resolution, &dfNewScale); if (self->web.maxscaledenom > 0 && dfNewScale > self->web.maxscaledenom) return MS_FAILURE; if (self->web.minscaledenom > 0 && dfNewScale < self->web.minscaledenom) { dfMiddleX = oNewGeorefExt.minx + ((oNewGeorefExt.maxx - oNewGeorefExt.minx)/2); dfMiddleY = oNewGeorefExt.miny + ((oNewGeorefExt.maxy - oNewGeorefExt.miny)/2); /* To be consistent in swig mapscript and PHP mapscript, use the same function to calculate the delta extents. */ dfDeltaExt = GetDeltaExtentsUsingScale(self->web.minscaledenom, self->units, dfMiddleY, self->width, self->resolution); if (dfDeltaExt > 0.0) { oNewGeorefExt.minx = dfMiddleX - (dfDeltaExt/2); oNewGeorefExt.miny = dfMiddleY - (dfDeltaExt/2); oNewGeorefExt.maxx = dfMiddleX + (dfDeltaExt/2); oNewGeorefExt.maxy = dfMiddleY + (dfDeltaExt/2); } else return MS_FAILURE; } /* ------------------------------------------------------------ */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* ------------------------------------------------------------ */ if (bMaxExtSet) { dfDeltaX = oNewGeorefExt.maxx - oNewGeorefExt.minx; dfDeltaY = oNewGeorefExt.maxy - oNewGeorefExt.miny; /* Make sure Current georef extents is not bigger * than max extents */ if (dfDeltaX > (poMaxGeorefExt->maxx-poMaxGeorefExt->minx)) dfDeltaX = poMaxGeorefExt->maxx-poMaxGeorefExt->minx; if (dfDeltaY > (poMaxGeorefExt->maxy-poMaxGeorefExt->miny)) dfDeltaY = poMaxGeorefExt->maxy-poMaxGeorefExt->miny; if (oNewGeorefExt.minx < poMaxGeorefExt->minx) { oNewGeorefExt.minx = poMaxGeorefExt->minx; oNewGeorefExt.maxx = oNewGeorefExt.minx + dfDeltaX; } if (oNewGeorefExt.maxx > poMaxGeorefExt->maxx) { oNewGeorefExt.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (oNewGeorefExt.miny < poMaxGeorefExt->miny) { oNewGeorefExt.miny = poMaxGeorefExt->miny; oNewGeorefExt.maxy = oNewGeorefExt.miny + dfDeltaY; } if (oNewGeorefExt.maxy > poMaxGeorefExt->maxy) { oNewGeorefExt.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } self->extent.minx = oNewGeorefExt.minx; self->extent.miny = oNewGeorefExt.miny; self->extent.maxx = oNewGeorefExt.maxx; self->extent.maxy = oNewGeorefExt.maxy; self->cellsize = msAdjustExtent(&(self->extent), self->width, self->height); dfDeltaX = self->extent.maxx - self->extent.minx; dfDeltaY = self->extent.maxy - self->extent.miny; if (bMaxExtSet) { if (self->extent.minx < poMaxGeorefExt->minx) { self->extent.minx = poMaxGeorefExt->minx; self->extent.maxx = self->extent.minx + dfDeltaX; } if (self->extent.maxx > poMaxGeorefExt->maxx) { self->extent.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (self->extent.miny < poMaxGeorefExt->miny) { self->extent.miny = poMaxGeorefExt->miny; self->extent.maxy = self->extent.miny + dfDeltaY; } if (self->extent.maxy > poMaxGeorefExt->maxy) { self->extent.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &(self->scaledenom)); return MS_SUCCESS; } /* ------------------------------------------------------------------- Zoom by the given factor to a pixel position within the width and height bounds. If max_extent is not NULL, the zoom is constrained to the max_extents ------------------------------------------------------------------- */ int zoomScale(double scale, pointObj *poPixPos, int width, int height, rectObj *poGeorefExt, rectObj *poMaxGeorefExt) { double dfGeoPosX, dfGeoPosY; double dfDeltaX, dfDeltaY; rectObj oNewGeorefExt; double dfNewScale, dfCurrentScale; int bMaxExtSet; int nTmp; double dfDeltaExt; double dX, dY; dfNewScale = 0.0; dfCurrentScale = 0.0; nTmp = 0; bMaxExtSet = 0; dfDeltaExt = -1.0; if (poMaxGeorefExt != NULL) { bMaxExtSet = 1; } /* ----------------------------------------------------------- */ /* check the validity of the parameters. */ /* ----------------------------------------------------------- */ if (scale <= 0.0 || width <= 0 || height <= 0 || poGeorefExt == NULL || poPixPos == NULL ) { msSetError(MS_MISCERR, "Incorrect arguments", "mapscript::mapObj::zoomScale"); return MS_FAILURE; } /* ----------------------------------------------------------- */ /* check if the values passed are consistent min > max. */ /* ----------------------------------------------------------- */ if (poGeorefExt->minx >= poGeorefExt->maxx) { msSetError(MS_MISCERR, "Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomScale()"); return MS_FAILURE; } if (poGeorefExt->miny >= poGeorefExt->maxy) { msSetError(MS_MISCERR, "Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomScale()"); return MS_FAILURE; } if (bMaxExtSet == 1) { if (poMaxGeorefExt->minx >= poMaxGeorefExt->maxx) { msSetError(MS_MISCERR, "Max Georeferenced coordinates minx >= maxx", "mapscript::mapObj::zoomScale()"); return MS_FAILURE; } if (poMaxGeorefExt->miny >= poMaxGeorefExt->maxy) { msSetError(MS_MISCERR, "Max Georeferenced coordinates miny >= maxy", "mapscript::mapObj::zoomScale()"); } } dfDeltaX = poGeorefExt->maxx - poGeorefExt->minx; dfDeltaY = poGeorefExt->maxy - poGeorefExt->miny; dX = dfDeltaX/((double)width); dY = dfDeltaY/((double)height); dfGeoPosX = poGeorefExt->minx + dX * (double)poPixPos->x; dfGeoPosY = poGeorefExt->maxy - dY * (double)poPixPos->y; /* ------------------------------------------------------------ */ /* Calculate new extents based on the scale. */ /* ------------------------------------------------------------ */ /* ============================================================ */ /* make sure to take the smallest size because this is the one */ /* that will be used to ajust the scale. */ /* ============================================================ */ if (self->width < self->height) nTmp = self->width; else nTmp = self->height; /* To be consistent in swig mapscript and PHP mapscript, use the same function to calculate the delta extents. */ dfDeltaExt = GetDeltaExtentsUsingScale(scale, self->units, dfGeoPosY, nTmp, self->resolution); if (dfDeltaExt > 0.0) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaExt/2); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaExt/2); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaExt/2); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaExt/2); } else return MS_FAILURE; /* ------------------------------------------------------------ */ /* get current scale. */ /* ------------------------------------------------------------ */ msCalculateScale(*poGeorefExt, self->units, self->width, self->height, self->resolution, &dfCurrentScale); /* ------------------------------------------------------------ * * if the min and max scale are set in the map file, we will * * use them to test before zooming. * * * * This function has the same effect as zoomin or zoom out. * If the current scale is > newscale we zoom in; else it is * a zoom out. * ------------------------------------------------------------ */ msAdjustExtent(&oNewGeorefExt, self->width, self->height); msCalculateScale(oNewGeorefExt, self->units, self->width, self->height, self->resolution, &dfNewScale); if (self->web.maxscaledenom > 0) { if (dfCurrentScale < dfNewScale && dfNewScale > self->web.maxscaledenom) { return MS_FAILURE; } } /* ============================================================ */ /* we do a special case for zoom in : we try to zoom as much as */ /* possible using the mincale set in the .map. */ /* ============================================================ */ if (self->web.minscaledenom > 0 && dfNewScale < self->web.minscaledenom && dfCurrentScale > dfNewScale) { /* To be consistent in swig mapscript and PHP mapscript, use the same function to calculate the delta extents. */ dfDeltaExt = GetDeltaExtentsUsingScale(scale, self->units, dfGeoPosY, nTmp, self->resolution); if (dfDeltaExt > 0.0) { oNewGeorefExt.minx = dfGeoPosX - (dfDeltaExt/2); oNewGeorefExt.miny = dfGeoPosY - (dfDeltaExt/2); oNewGeorefExt.maxx = dfGeoPosX + (dfDeltaExt/2); oNewGeorefExt.maxy = dfGeoPosY + (dfDeltaExt/2); } else return MS_FAILURE; } /* ------------------------------------------------------------ */ /* If the buffer is set, make sure that the extents do not go */ /* beyond the buffer. */ /* ------------------------------------------------------------ */ if (bMaxExtSet) { dfDeltaX = oNewGeorefExt.maxx - oNewGeorefExt.minx; dfDeltaY = oNewGeorefExt.maxy - oNewGeorefExt.miny; /* Make sure Current georef extents is not bigger * than max extents */ if (dfDeltaX > (poMaxGeorefExt->maxx-poMaxGeorefExt->minx)) dfDeltaX = poMaxGeorefExt->maxx-poMaxGeorefExt->minx; if (dfDeltaY > (poMaxGeorefExt->maxy-poMaxGeorefExt->miny)) dfDeltaY = poMaxGeorefExt->maxy-poMaxGeorefExt->miny; if (oNewGeorefExt.minx < poMaxGeorefExt->minx) { oNewGeorefExt.minx = poMaxGeorefExt->minx; oNewGeorefExt.maxx = oNewGeorefExt.minx + dfDeltaX; } if (oNewGeorefExt.maxx > poMaxGeorefExt->maxx) { oNewGeorefExt.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (oNewGeorefExt.miny < poMaxGeorefExt->miny) { oNewGeorefExt.miny = poMaxGeorefExt->miny; oNewGeorefExt.maxy = oNewGeorefExt.miny + dfDeltaY; } if (oNewGeorefExt.maxy > poMaxGeorefExt->maxy) { oNewGeorefExt.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } self->extent.minx = oNewGeorefExt.minx; self->extent.miny = oNewGeorefExt.miny; self->extent.maxx = oNewGeorefExt.maxx; self->extent.maxy = oNewGeorefExt.maxy; self->cellsize = msAdjustExtent(&(self->extent), self->width, self->height); dfDeltaX = self->extent.maxx - self->extent.minx; dfDeltaY = self->extent.maxy - self->extent.miny; if (bMaxExtSet) { if (self->extent.minx < poMaxGeorefExt->minx) { self->extent.minx = poMaxGeorefExt->minx; self->extent.maxx = self->extent.minx + dfDeltaX; } if (self->extent.maxx > poMaxGeorefExt->maxx) { self->extent.maxx = poMaxGeorefExt->maxx; oNewGeorefExt.minx = oNewGeorefExt.maxx - dfDeltaX; } if (self->extent.miny < poMaxGeorefExt->miny) { self->extent.miny = poMaxGeorefExt->miny; self->extent.maxy = self->extent.miny + dfDeltaY; } if (self->extent.maxy > poMaxGeorefExt->maxy) { self->extent.maxy = poMaxGeorefExt->maxy; oNewGeorefExt.miny = oNewGeorefExt.maxy - dfDeltaY; } } msCalculateScale(self->extent, self->units, self->width, self->height, self->resolution, &(self->scaledenom)); return MS_SUCCESS; } } mapserver-7.4.3/mapscript/swiginc/msio.i000066400000000000000000000067011357574274700203500ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Definitions for MapServer IO redirection capability. * Author: Frank Warmerdam, warmerdam@pobox.com * * Note: * copied from mapio.h to avoid to much #ifdef swigging * ****************************************************************************** * Copyright (c) 2004, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* $Id$ */ void msIO_resetHandlers(void); void msIO_installStdoutToBuffer(void); void msIO_installStdinFromBuffer(void); %newobject msIO_stripStdoutBufferContentType; const char *msIO_stripStdoutBufferContentType(); void msIO_stripStdoutBufferContentHeaders(void); /* mapscript only extensions */ const char *msIO_getStdoutBufferString(void); gdBuffer msIO_getStdoutBufferBytes(void); %newobject msIO_getAndStripStdoutBufferMimeHeaders; hashTableObj* msIO_getAndStripStdoutBufferMimeHeaders(void); %{ const char *msIO_getStdoutBufferString() { msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_getStdoutBufferString" ); return ""; } buf = (msIOBuffer *) ctx->cbData; /* write one zero byte and backtrack if it isn't already there */ if( buf->data_len == 0 || buf->data[buf->data_offset] != '\0' ) { msIO_bufferWrite( buf, "", 1 ); buf->data_offset--; } return (const char *) (buf->data); } gdBuffer msIO_getStdoutBufferBytes() { msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" ); msIOBuffer *buf; gdBuffer gdBuf; if( ctx == NULL || ctx->write_channel == MS_FALSE || strcmp(ctx->label,"buffer") != 0 ) { msSetError( MS_MISCERR, "Can't identify msIO buffer.", "msIO_getStdoutBufferString" ); gdBuf.data = (unsigned char*)""; gdBuf.size = 0; gdBuf.owns_data = MS_FALSE; return gdBuf; } buf = (msIOBuffer *) ctx->cbData; gdBuf.data = buf->data; gdBuf.size = buf->data_offset; gdBuf.owns_data = MS_TRUE; /* we are seizing ownership of the buffer contents */ buf->data_offset = 0; buf->data_len = 0; buf->data = NULL; return gdBuf; } %} mapserver-7.4.3/mapscript/swiginc/outputformat.i000066400000000000000000000063001357574274700221450ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript outputFormatObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend outputFormatObj { outputFormatObj(const char *driver, char *name=NULL) { outputFormatObj *format; format = msCreateDefaultOutputFormat(NULL, driver, name); /* in the case of unsupported formats, msCreateDefaultOutputFormat should return NULL */ if (!format) { msSetError(MS_MISCERR, "Unsupported format driver: %s", "outputFormatObj()", driver); return NULL; } msInitializeRendererVTable(format); MS_REFCNT_INIT(format); format->inmapfile = MS_TRUE; return format; } ~outputFormatObj() { msFreeOutputFormat( self ); } #ifndef SWIGJAVA void setExtension( const char *extension ) { msFree( self->extension ); self->extension = msStrdup(extension); } void setMimetype( const char *mimetype ) { msFree( self->mimetype ); self->mimetype = msStrdup(mimetype); } #endif void setOption( const char *key, const char *value ) { msSetOutputFormatOption( self, key, value ); } int validate() { return msOutputFormatValidate( self, MS_FALSE ); } %newobject getOption; char *getOption(const char *key, const char *value="") { return msStrdup(msGetOutputFormatOption(self, key, value)); } %newobject getOptionAt; char* getOptionAt(int i) { if( i >= 0 && i < self->numformatoptions ) { return msStrdup(self->formatoptions[i]); } return NULL; } void attachDevice( void *device ) { self->device = device; } } mapserver-7.4.3/mapscript/swiginc/owsrequest.i000066400000000000000000000110161357574274700216150ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for manipulating OGC request stuff via mapscript. Author: Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 2004 Sean Gillies Copyright (c) 2006 Frank Warmerdam Copyright (c) 1996-2007 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %{ static char *msGetEnvURL( const char *key, void *thread_context ) { if( strcmp(key,"REQUEST_METHOD") == 0 ) return "GET"; if( strcmp(key,"QUERY_STRING") == 0 ) return (char *) thread_context; return NULL; } %} %rename(OWSRequest) cgiRequestObj; %include "../../cgiutil.h" /* Class for programming OWS services - SG */ %extend cgiRequestObj { cgiRequestObj() { cgiRequestObj *request; request = msAllocCgiObj(); if (!request) { msSetError(MS_CGIERR, "Failed to initialize object","OWSRequest()"); return NULL; } return request; } ~cgiRequestObj() { msFreeCgiObj(self); } int loadParams() { self->NumParams = loadParams( self, NULL, NULL, 0, NULL); return self->NumParams; } int loadParamsFromURL( const char *url ) { self->NumParams = loadParams( self, msGetEnvURL, NULL, 0, (void*)url ); return self->NumParams; } void setParameter(char *name, char *value) { int i; if (self->NumParams == MS_DEFAULT_CGI_PARAMS) { msSetError(MS_CHILDERR, "Maximum number of items, %d, has been reached", "setItem()", MS_DEFAULT_CGI_PARAMS); } for (i=0; iNumParams; i++) { if (strcasecmp(self->ParamNames[i], name) == 0) { free(self->ParamValues[i]); self->ParamValues[i] = msStrdup(value); break; } } if (i == self->NumParams) { self->ParamNames[self->NumParams] = msStrdup(name); self->ParamValues[self->NumParams] = msStrdup(value); self->NumParams++; } } void addParameter(char *name, char *value) { if (self->NumParams == MS_DEFAULT_CGI_PARAMS) { msSetError(MS_CHILDERR, "Maximum number of items, %d, has been reached", "addParameter()", MS_DEFAULT_CGI_PARAMS); } self->ParamNames[self->NumParams] = msStrdup(name); self->ParamValues[self->NumParams] = msStrdup(value); self->NumParams++; } char *getName(int index) { if (index < 0 || index >= self->NumParams) { msSetError(MS_CHILDERR, "Invalid index, valid range is [0, %d]", "getName()", self->NumParams-1); return NULL; } return self->ParamNames[index]; } char *getValue(int index) { if (index < 0 || index >= self->NumParams) { msSetError(MS_CHILDERR, "Invalid index, valid range is [0, %d]", "getValue()", self->NumParams-1); return NULL; } return self->ParamValues[index]; } char *getValueByName(const char *name) { int i; for (i=0; iNumParams; i++) { if (strcasecmp(self->ParamNames[i], name) == 0) { return self->ParamValues[i]; } } return NULL; } } mapserver-7.4.3/mapscript/swiginc/point.i000066400000000000000000000106001357574274700205230ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript pointObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend pointObj { /* Java pointObj constructors are in java/javaextend.i (bug 1106) */ #ifndef SWIGJAVA pointObj(double x=0.0, double y=0.0, double z=0.0, double m=-2e38) { pointObj *p; p = (pointObj *)calloc(1,sizeof(pointObj)); if (!p) return NULL; p->x = x; p->y = y; #ifdef USE_POINT_Z_M p->z = z; p->m = m; #endif /* USE_POINT_Z_M */ return p; } #endif ~pointObj() { free(self); } int project(projectionObj *projin, projectionObj *projout) { return msProjectPoint(projin, projout, self); } int draw(mapObj *map, layerObj *layer, imageObj *image, int classindex, char *text) { return msDrawPoint(map, layer, self, image, classindex, text); } double distanceToPoint(pointObj *point) { return msDistancePointToPoint(self, point); } double distanceToSegment(pointObj *a, pointObj *b) { return msDistancePointToSegment(self, a, b); } double distanceToShape(shapeObj *shape) { return msDistancePointToShape(self, shape); } int setXY(double x, double y, double m=-2e38) { self->x = x; self->y = y; #ifdef USE_POINT_Z_M self->z = 0.0; self->m = m; #endif /* USE_POINT_Z_M */ return MS_SUCCESS; } int setXYZ(double x, double y, double z, double m=-2e38) { self->x = x; self->y = y; #ifdef USE_POINT_Z_M self->z = z; self->m = m; #endif /* USE_POINT_Z_M */ return MS_SUCCESS; } int setXYZM(double x, double y, double z, double m) { self->x = x; self->y = y; #ifdef USE_POINT_Z_M self->z = z; self->m = m; #endif /* USE_POINT_Z_M */ return MS_SUCCESS; } %newobject toString; char *toString() { char buffer[256]; const char *fmt; #ifdef USE_POINT_Z_M if( self->m < -1e38 ) fmt = "{ 'x': %.16g, 'y': %.16g, 'z': %.16g }"; else fmt = "{ 'x': %.16g, 'y': %.16g, 'z': %.16g, 'm': %.16g }"; #else fmt = "{ 'x': %.16g, 'y': %.16g }"; #endif /* USE_POINT_Z_M */ msPointToFormattedString(self, fmt, (char *) &buffer, 256); return msStrdup(buffer); } %newobject toShape; shapeObj *toShape() { shapeObj *shape; shape = (shapeObj *) malloc(sizeof(shapeObj)); msInitShape(shape); shape->type = MS_SHAPE_POINT; shape->line = (lineObj *) malloc(sizeof(lineObj)); shape->numlines = 1; shape->line[0].point = (pointObj *) malloc(sizeof(pointObj)); shape->line[0].numpoints = 1; shape->line[0].point[0].x = self->x; shape->line[0].point[0].y = self->y; #ifdef USE_POINT_Z_M shape->line[0].point[0].z = self->z; shape->line[0].point[0].m = self->m; #endif /* USE_POINT_Z_M */ return shape; } } mapserver-7.4.3/mapscript/swiginc/projection.i000066400000000000000000000044351357574274700215570ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript projectionObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend projectionObj { projectionObj(char *proj4) { int status; projectionObj *proj=NULL; proj = (projectionObj *)malloc(sizeof(projectionObj)); if (!proj) return NULL; msInitProjection(proj); status = msLoadProjectionString(proj, proj4); if (status == -1) { msFreeProjection(proj); free(proj); return NULL; } return proj; } ~projectionObj() { msFreeProjection(self); free(self); } int setWKTProjection(char* wkt) { /* no debug output here */ return msOGCWKT2ProjectionObj(wkt, self, MS_FALSE); } int getUnits() { return GetMapserverUnitUsingProj(self); } } mapserver-7.4.3/mapscript/swiginc/querymap.i000066400000000000000000000033251357574274700212430ustar00rootroot00000000000000/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript queryMapObj extensions Author: Steve Lime =========================================================================== Copyright (c) 1996-2007 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend queryMapObj { int updateFromString(char *snippet) { return msUpdateQueryMapFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteQueryMapToString(self); } } mapserver-7.4.3/mapscript/swiginc/rect.i000066400000000000000000000117201357574274700203330ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript rectObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend rectObj { rectObj(double minx=-1.0, double miny=-1.0, double maxx=-1.0, double maxy=-1.0, int imageunits=MS_FALSE) { rectObj *rect; if (imageunits == MS_FALSE) { if (minx > maxx || miny > maxy) { msSetError(MS_RECTERR, "{ 'minx': %f , 'miny': %f , 'maxx': %f , 'maxy': %f }", "rectObj()", minx, miny, maxx, maxy); return NULL; } } else { if (minx > maxx || maxy > miny) { msSetError(MS_RECTERR, "image (pixel/line) units { 'minx': %f , 'miny': %f , 'maxx': %f , 'maxy': %f }", "rectObj()", minx, miny, maxx, maxy); return NULL; } } rect = (rectObj *)calloc(1, sizeof(rectObj)); if (!rect) return(NULL); rect->minx = minx; rect->miny = miny; rect->maxx = maxx; rect->maxy = maxy; return(rect); } ~rectObj() { free(self); } int project(projectionObj *projin, projectionObj *projout) { return msProjectRect(projin, projout, self); } double fit(int width, int height) { return msAdjustExtent(self, width, height); } int draw(mapObj *map, layerObj *layer, imageObj *image, int classindex, char *text) { shapeObj shape; int ret; msInitShape(&shape); msRectToPolygon(*self, &shape); shape.classindex = classindex; if(text && layer->class[classindex]->numlabels > 0) { shape.text = msStrdup(text); } ret = msDrawShape(map, layer, &shape, image, -1, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS); msFreeShape(&shape); return ret; } %newobject getCenter; pointObj *getCenter() { pointObj *center; center = (pointObj *)calloc(1, sizeof(pointObj)); if (!center) { msSetError(2, "Failed to allocate memory for point", "getCenter()"); return NULL; } center->x = (self->minx + self->maxx)/2; center->y = (self->miny + self->maxy)/2; return center; } %newobject toPolygon; shapeObj *toPolygon() { lineObj line = {0,NULL}; shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); shape->type = MS_SHAPE_POLYGON; line.point = (pointObj *)malloc(sizeof(pointObj)*5); line.point[0].x = self->minx; line.point[0].y = self->miny; line.point[1].x = self->minx; line.point[1].y = self->maxy; line.point[2].x = self->maxx; line.point[2].y = self->maxy; line.point[3].x = self->maxx; line.point[3].y = self->miny; line.point[4].x = line.point[0].x; line.point[4].y = line.point[0].y; line.numpoints = 5; msAddLine(shape, &line); msComputeBounds(shape); free(line.point); return shape; } %newobject toString; char *toString() { char buffer[256]; char fmt[]="{ 'minx': %.16g , 'miny': %.16g , 'maxx': %.16g , 'maxy': %.16g }"; msRectToFormattedString(self, (char *) &fmt, (char *) &buffer, 256); return msStrdup(buffer); } } mapserver-7.4.3/mapscript/swiginc/referencemap.i000066400000000000000000000033451357574274700220360ustar00rootroot00000000000000/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript referenceMapObj extensions Author: Steve Lime =========================================================================== Copyright (c) 1996-2007 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend referenceMapObj { int updateFromString(char *snippet) { return msUpdateReferenceMapFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteReferenceMapToString(self); } } mapserver-7.4.3/mapscript/swiginc/result.i000066400000000000000000000036351357574274700207220ustar00rootroot00000000000000/* =========================================================================== $Id: shape.i 9558 2009-11-20 18:11:50Z sdlime $ Project: MapServer Purpose: SWIG interface file for mapscript shapeObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend resultObj { resultObj(long shapeindex) { resultObj *result = (resultObj *) msSmallMalloc(sizeof(resultObj)); result->tileindex = -1; result->resultindex = -1; result->shapeindex = shapeindex; return result; } ~resultObj() { free(self); } } mapserver-7.4.3/mapscript/swiginc/resultcache.i000066400000000000000000000033201357574274700216750ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript resultCacheObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend resultCacheObj { resultObj *getResult(int i) { if (i >= 0 && i < self->numresults) { return &self->results[i]; } return NULL; } } mapserver-7.4.3/mapscript/swiginc/scalebar.i000066400000000000000000000033251357574274700211540ustar00rootroot00000000000000/* =========================================================================== $Id: $ Project: MapServer Purpose: SWIG interface file for mapscript scalebarObj extensions Author: Steve Lime =========================================================================== Copyright (c) 1996-2007 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend scalebarObj { int updateFromString(char *snippet) { return msUpdateScalebarFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteScalebarToString(self); } } mapserver-7.4.3/mapscript/swiginc/shape.i000066400000000000000000000167461357574274700205130ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript shapeObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend shapeObj { shapeObj(int type=MS_SHAPE_NULL) { shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); if(type >= 0) shape->type = type; return shape; } ~shapeObj() { msFreeShape(self); free(self); } %newobject fromWKT; static shapeObj *fromWKT(char *wkt) { shapeObj *shape; if(!wkt) return NULL; shape = msShapeFromWKT(wkt); if(!shape) return NULL; return shape; } int project(projectionObj *projin, projectionObj *projout) { return msProjectShape(projin, projout, self); } lineObj *get(int i) { if (i<0 || i>=self->numlines) return NULL; else return &(self->line[i]); } int add(lineObj *line) { return msAddLine(self, line); } int draw(mapObj *map, layerObj *layer, imageObj *image) { return msDrawShape(map, layer, self, image, -1, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS); } void setBounds() { msComputeBounds(self); return; } #if defined (SWIGJAVA) || defined (SWIGPHP) %newobject cloneShape; shapeObj *cloneShape() #else %newobject clone; shapeObj *clone() #endif { shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); shape->type = self->type; msCopyShape(self, shape); return shape; } int copy(shapeObj *dest) { return(msCopyShape(self, dest)); } %newobject toWKT; char *toWKT() { return msShapeToWKT(self); } %newobject buffer; shapeObj *buffer(double width) { return msGEOSBuffer(self, width); } %newobject simplify; shapeObj *simplify(double tolerance) { return msGEOSSimplify(self, tolerance); } %newobject topologyPreservingSimplify; shapeObj *topologyPreservingSimplify(double tolerance) { return msGEOSTopologyPreservingSimplify(self, tolerance); } %newobject convexHull; shapeObj *convexHull() { return msGEOSConvexHull(self); } %newobject boundary; shapeObj *boundary() { return msGEOSBoundary(self); } %newobject getCentroid; pointObj *getCentroid() { return msGEOSGetCentroid(self); } %newobject Union; shapeObj *Union(shapeObj *shape) { return msGEOSUnion(self, shape); } %newobject intersection; shapeObj *intersection(shapeObj *shape) { return msGEOSIntersection(self, shape); } %newobject difference; shapeObj *difference(shapeObj *shape) { return msGEOSDifference(self, shape); } %newobject symDifference; shapeObj *symDifference(shapeObj *shape) { return msGEOSSymDifference(self, shape); } int contains(shapeObj *shape) { return msGEOSContains(self, shape); } int overlaps(shapeObj *shape) { return msGEOSOverlaps(self, shape); } int within(shapeObj *shape) { return msGEOSWithin(self, shape); } int crosses(shapeObj *shape) { return msGEOSCrosses(self, shape); } int intersects(shapeObj *shape) { return msGEOSIntersects(self, shape); } /* if GEOS is not present an alternative computation is provided, see mapgeos.c */ int touches(shapeObj *shape) { return msGEOSTouches(self, shape); } int equals(shapeObj *shape) { return msGEOSEquals(self, shape); } int disjoint(shapeObj *shape) { return msGEOSDisjoint(self, shape); } double getArea() { return msGEOSArea(self); } double getLength() { return msGEOSLength(self); } char *getValue(int i) { if (i >= 0 && i < self->numvalues && self->values) return (self->values[i]); else return NULL; } int contains(pointObj *point) { if (self->type == MS_SHAPE_POLYGON) return msIntersectPointPolygon(point, self); return -1; } double distanceToPoint(pointObj *point) { return msDistancePointToShape(point, self); /* should there be a GEOS version of this? */ } double distanceToShape(shapeObj *shape) { return msGEOSDistance(self, shape); /* note this calls msDistanceShapeToShape() if GEOS support is not present */ } %newobject getLabelPoint; pointObj *getLabelPoint() { pointObj *point = (pointObj *)calloc(1, sizeof(pointObj)); if (point == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for point", "labelPoint()"); return NULL; } if(self->type == MS_SHAPE_POLYGON && msPolygonLabelPoint(self, point, -1) == MS_SUCCESS) return point; free(point); return NULL; } int setValue(int i, char *value) { if (!self->values || !value) { msSetError(MS_SHPERR, "Can't set value", "setValue()"); return MS_FAILURE; } if (i >= 0 && i < self->numvalues) { msFree(self->values[i]); self->values[i] = msStrdup(value); if (!self->values[i]) { return MS_FAILURE; } else return MS_SUCCESS; } else { msSetError(MS_SHPERR, "Invalid value index", "setValue()"); return MS_FAILURE; } } void initValues(int numvalues) { int i; if(self->values) msFreeCharArray(self->values, self->numvalues); self->values = NULL; self->numvalues = 0; /* Allocate memory for the values */ if (numvalues > 0) { if ((self->values = (char **)malloc(sizeof(char *)*numvalues)) == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for values", "shapeObj()"); return; } else { for (i=0; ivalues[i] = msStrdup(""); } self->numvalues = numvalues; } } } mapserver-7.4.3/mapscript/swiginc/shapefile.i000066400000000000000000000102441357574274700213360ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript shapefileObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend shapefileObj { shapefileObj(char *filename, int type=-1) { shapefileObj *shapefile; int status; shapefile = (shapefileObj *)malloc(sizeof(shapefileObj)); if (!shapefile) return NULL; if (type == -1) status = msShapefileOpen(shapefile, "rb", filename, MS_TRUE); else if (type == -2) status = msShapefileOpen(shapefile, "rb+", filename, MS_TRUE); else status = msShapefileCreate(shapefile, filename, type); if (status == -1) { msShapefileClose(shapefile); free(shapefile); return NULL; } return(shapefile); } ~shapefileObj() { msShapefileClose(self); free(self); } int get(int i, shapeObj *shape) { if (i<0 || i>=self->numshapes) return MS_FAILURE; msFreeShape(shape); /* frees all lines and points before re-filling */ msSHPReadShape(self->hSHP, i, shape); return MS_SUCCESS; } %newobject getShape; shapeObj *getShape(int i) { shapeObj *shape; shape = (shapeObj *)malloc(sizeof(shapeObj)); if (!shape) return NULL; msInitShape(shape); shape->type = self->type; msSHPReadShape(self->hSHP, i, shape); return shape; } int getPoint(int i, pointObj *point) { if (i<0 || i>=self->numshapes) return MS_FAILURE; msSHPReadPoint(self->hSHP, i, point); return MS_SUCCESS; } int getTransformed(mapObj *map, int i, shapeObj *shape) { if (i<0 || i>=self->numshapes) return MS_FAILURE; msFreeShape(shape); /* frees all lines and points before re-filling */ msSHPReadShape(self->hSHP, i, shape); msTransformShapeSimplify(shape, map->extent, map->cellsize); return MS_SUCCESS; } void getExtent(int i, rectObj *rect) { msSHPReadBounds(self->hSHP, i, rect); } int add(shapeObj *shape) { /* Trap NULL or empty shapes -- bug 1201 */ if (!shape) { msSetError(MS_SHPERR, "Can't add NULL shape", "shapefileObj::add"); return MS_FAILURE; } else if (!shape->line) { msSetError(MS_SHPERR, "Can't add empty shape", "shapefileObj::add"); return MS_FAILURE; } return msSHPWriteShape(self->hSHP, shape); } int addPoint(pointObj *point) { return msSHPWritePoint(self->hSHP, point); } DBFInfo *getDBF() { return self->hDBF; } } mapserver-7.4.3/mapscript/swiginc/style.i000066400000000000000000000124271357574274700205430ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript styleObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== See Bugzilla issue 548 about work on styleObj and classObj */ %extend styleObj { styleObj(classObj *parent_class=NULL) { styleObj *style = NULL; if (parent_class!=NULL) { if ((style = msGrowClassStyles(parent_class)) == NULL) return NULL; if ( initStyle(style) == MS_FAILURE ) { msSetError(MS_MISCERR, "Failed to init new styleObj instance", "initStyle()"); } parent_class->numstyles++; MS_REFCNT_INCR(style); } else { style = (styleObj *) malloc(sizeof(styleObj)); if (!style) { msSetError(MS_MEMERR, "Failed to allocate memory for new styleObj instance", "styleObj()"); return NULL; } if ( initStyle(style) == MS_FAILURE ) { msSetError(MS_MISCERR, "Failed to init new styleObj instance", "initStyle()"); msFree(style); return NULL; } } return style; } ~styleObj() { if (self) { if ( freeStyle(self) == MS_SUCCESS ) { free(self); self=NULL; } } } int updateFromString(char *snippet) { return msUpdateStyleFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteStyleToString(self); } #if defined (SWIGJAVA) || defined (SWIGPHP) %newobject cloneStyle; styleObj *cloneStyle() #else %newobject clone; styleObj *clone() #endif { styleObj *style; style = (styleObj *) malloc(sizeof(styleObj)); if (!style) { msSetError(MS_MEMERR, "Could not allocate memory for new styleObj instance", "clone()"); return NULL; } if (initStyle(style) == -1) { msSetError(MS_MEMERR, "Failed to initialize Style", "clone()"); return NULL; } if (msCopyStyle(style, self) != MS_SUCCESS) { free(style); return NULL; } return style; } int setSymbolByName(mapObj *map, char* symbolname) { self->symbol = msGetSymbolIndex(&map->symbolset, symbolname, MS_TRUE); if (self->symbolname) free((char*)self->symbolname); if (symbolname) self->symbolname = msStrdup(symbolname); else self->symbolname = 0; return self->symbol; } int removeBinding(int binding) { if(binding < 0 || binding >= MS_STYLE_BINDING_LENGTH) return MS_FAILURE; if(self->bindings[binding].item) { free(self->bindings[binding].item); self->bindings[binding].item = NULL; self->bindings[binding].index = -1; self->numbindings--; } return MS_SUCCESS; } int setBinding(int binding, char *item) { if(!item) return MS_FAILURE; if(binding < 0 || binding >= MS_STYLE_BINDING_LENGTH) return MS_FAILURE; if(self->bindings[binding].item) { free(self->bindings[binding].item); self->bindings[binding].item = NULL; self->bindings[binding].index = -1; self->numbindings--; } self->bindings[binding].item = msStrdup(item); self->numbindings++; return MS_SUCCESS; } char *getBinding(int binding) { if(binding < 0 || binding >= MS_STYLE_BINDING_LENGTH) return NULL; return self->bindings[binding].item; } char *getGeomTransform() { return self->_geomtransform.string; } void setGeomTransform(char *transform) { msStyleSetGeomTransform(self, transform); } } mapserver-7.4.3/mapscript/swiginc/symbol.i000066400000000000000000000125561357574274700207130ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript symbolObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %include "../../mapsymbol.h" /* Full support for symbols and addition of them to the map symbolset is done to resolve MapServer bug 579 http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=579 */ %extend symbolObj { symbolObj(char *symbolname, const char *imagefile=NULL) { symbolObj *symbol; symbol = (symbolObj *) malloc(sizeof(symbolObj)); initSymbol(symbol); symbol->name = msStrdup(symbolname); if (imagefile) { msLoadImageSymbol(symbol, imagefile); } return symbol; } ~symbolObj() { if (self) { if (msFreeSymbol(self)==MS_SUCCESS) { free(self); self=NULL; } } } int setImagepath(const char *imagefile) { return msLoadImageSymbol(self, imagefile); } int setPoints(lineObj *line) { int i; self->sizex = 0; self->sizey = 0; for (i=0; inumpoints; i++) { MS_COPYPOINT(&(self->points[i]), &(line->point[i])); self->sizex = MS_MAX(self->sizex, self->points[i].x); self->sizey = MS_MAX(self->sizey, self->points[i].y); } self->numpoints = line->numpoints; return self->numpoints; } %newobject getPoints; lineObj *getPoints() { int i; lineObj *line; line = (lineObj *) malloc(sizeof(lineObj)); line->point = (pointObj *) malloc(sizeof(pointObj)*(self->numpoints)); for (i=0; inumpoints; i++) { line->point[i].x = self->points[i].x; line->point[i].y = self->points[i].y; } line->numpoints = self->numpoints; return line; } %newobject getImage; imageObj *getImage(outputFormatObj *input_format) { imageObj *image = NULL; outputFormatObj *format = NULL; rendererVTableObj *renderer = NULL; if (input_format) { format = input_format; } else { format = msCreateDefaultOutputFormat(NULL, "AGG/PNG", "aggpng"); if (format) msInitializeRendererVTable(format); } if (format == NULL) { msSetError(MS_IMGERR, "Could not create output format", "getImage()"); return NULL; } renderer = format->vtable; msPreloadImageSymbol(renderer, self); if (self->pixmap_buffer) { image = msImageCreate(self->pixmap_buffer->width, self->pixmap_buffer->height, format, NULL, NULL, MS_DEFAULT_RESOLUTION, MS_DEFAULT_RESOLUTION, NULL); if(!image) { msSetError(MS_IMGERR, "Could not create image", "getImage()"); return NULL; } if(MS_SUCCESS != renderer->mergeRasterBuffer(image, self->pixmap_buffer, 1.0, 0, 0, 0, 0, self->pixmap_buffer->width, self->pixmap_buffer->height)) { msSetError(MS_IMGERR, "Could not merge symbol image", "getImage()"); msFreeImage(image); return NULL; } } return image; } int setImage(imageObj *image) { rendererVTableObj *renderer = NULL; renderer = image->format->vtable; if (self->pixmap_buffer) { msFreeRasterBuffer(self->pixmap_buffer); free(self->pixmap_buffer); } self->pixmap_buffer = (rasterBufferObj*)malloc(sizeof(rasterBufferObj)); if (!self->pixmap_buffer) { msSetError(MS_MEMERR, NULL, "setImage()"); return MS_FAILURE; } self->type = MS_SYMBOL_PIXMAP; return renderer->getRasterBufferCopy(image, self->pixmap_buffer); } } mapserver-7.4.3/mapscript/swiginc/symbolset.i000066400000000000000000000063351357574274700214250ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript symbolSetObj extensions Author: Steve Lime Sean Gillies, sgillies@frii.com =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %extend symbolSetObj { symbolSetObj(const char *symbolfile=NULL) { symbolSetObj *symbolset; mapObj *temp_map=NULL; symbolset = (symbolSetObj *) malloc(sizeof(symbolSetObj)); msInitSymbolSet(symbolset); if (symbolfile) { symbolset->filename = msStrdup(symbolfile); temp_map = msNewMapObj(); msLoadSymbolSet(symbolset, temp_map); symbolset->map = NULL; msFreeMap(temp_map); } return symbolset; } ~symbolSetObj() { msFreeSymbolSet(self); if (self->filename) free(self->filename); free(self); } %newobject getSymbol; symbolObj *getSymbol(int i) { if (i >= 0 && i < self->numsymbols) { symbolObj *s=self->symbol[i]; MS_REFCNT_INCR(s); return s; } else return NULL; } %newobject getSymbolByName; symbolObj *getSymbolByName(char *symbolname) { int i; if (!symbolname) return NULL; i = msGetSymbolIndex(self, symbolname, MS_TRUE); if (i == -1) return NULL; else { MS_REFCNT_INCR(self->symbol[i]); return self->symbol[i]; } } int index(char *symbolname) { return msGetSymbolIndex(self, symbolname, MS_TRUE); } int appendSymbol(symbolObj *symbol) { return msAppendSymbol(self, symbol); } %newobject removeSymbol; symbolObj *removeSymbol(int index) { symbolObj *s=msRemoveSymbol(self, index); if (s!=NULL) { MS_REFCNT_INCR(s); } return s; } int save(const char *filename) { return msSaveSymbolSet(self, filename); } } mapserver-7.4.3/mapscript/swiginc/web.i000066400000000000000000000042241357574274700201540ustar00rootroot00000000000000/* =========================================================================== $Id$ Project: MapServer Purpose: SWIG interface file for mapscript webObj extensions Author: Steve Lime Umberto Nicoletti unicoletti@prometeo.it =========================================================================== Copyright (c) 1996-2001 Regents of the University of Minnesota. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =========================================================================== */ %include "../../mapserver.h" /* Constructor and destructor for webObj http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=579 */ %extend webObj { webObj() { webObj *web; web = (webObj *) malloc(sizeof(webObj)); initWeb(web); return web; } ~webObj() { if (!self) return; freeWeb(self); free(self); } int updateFromString(char *snippet) { return msUpdateWebFromString(self, snippet, MS_FALSE); } %newobject convertToString; char* convertToString() { return msWriteWebToString(self); } } mapserver-7.4.3/mapscript/tcl/000077500000000000000000000000001357574274700163425ustar00rootroot00000000000000mapserver-7.4.3/mapscript/tcl/Makefile.in000066400000000000000000000060161357574274700204120ustar00rootroot00000000000000# # Makefile.in for mapscript Tcl interface # Tom Poindexter, tpoindex@nyx.net # DLTARGET = libMapscript11 PACKAGEDIR = MapscriptTcl1.1 # Note: also change 'package provide' version in pkgIndex.tcl !! SWIGINC = -I@SWIGDIR@/include SWIGLIB = -L@SWIGDIR@/lib SWIGLIB_SPEC = -lswig TCL_PREFIX = @TCL_PREFIX@ TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@ TCL_CC = @TCL_CC@ TCL_DEFS = @TCL_DEFS@ TCL_SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@ TCL_SHLIB_CFLAGS = @TCL_SHLIB_CFLAGS@ TCL_LD_SEARCH_FLAGS = @TCL_LD_SEARCH_FLAGS@ TCL_SHLIB_LD = @TCL_SHLIB_LD@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_LIBS = @TCL_LIBS@ LIBS = @TCL_LIBS@ TCL_DBGX = @TCL_DBGX@ LIB_RUNTIME_DIR = @TCL_EXEC_PREFIX@/lib:@TCL_EXEC_PREFIX@/lib/$(PACKAGEDIR):@TCL_PREFIX@/lib:@MAPSERVERHOME@ MAPSERVERHOME = @MAPSERVERHOME@ MAPSERVERDEFS = @MAPSERVERDEFS@ MAPSERVERINCS = @MAPSERVERINCS@ MAPSERVERLIBS = @MAPSERVERLIBS@ # ugly alert! # see the README for this hack SWIG_STUB_HACK = -DUSE_TCL_STUBS -DITCL_NAMESPACES -DItcl_Namespace=int \ -D"spaceId=spcid;Tcl_InitStubs(interp,\"8.1\",0)" all: stublib stublib: mapscript_wrap.c $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) \ -I$(TCL_PREFIX)/include \ $(MAPSERVERDEFS) $(MAPSERVERINCS) \ $(SWIG_STUB_HACK) \ mapscript_wrap.c $(TCL_SHLIB_LD) -o $(DLTARGET)$(TCL_SHLIB_SUFFIX) mapscript_wrap.o \ $(TCL_LD_SEARCH_FLAGS) \ $(TCL_STUB_LIB_SPEC) \ $(TCL_LIBS) \ -L$(MAPSERVERHOME) $(MAPSERVERLIBS) mapscript_wrap.c: swig -tcl8 -dhtml -namespace $(MAPSERVERDEFS) $(MAPSERVERINCS) \ mapscript.i nostublib: mapscript_wrap.c $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) \ -I$(TCL_PREFIX)/include \ $(MAPSERVERDEFS) $(MAPSERVERINCS) \ mapscript_wrap.c $(TCL_SHLIB_LD) -o $(DLTARGET)$(TCL_SHLIB_SUFFIX) mapscript_wrap.o \ $(TCL_LD_SEARCH_FLAGS) \ $(TCL_LIB_SPEC) \ $(TCL_LIBS) \ -L$(MAPSERVERHOME) $(MAPSERVERLIBS) $(DLTARGET)$(TCL_SHLIB_SUFFIX): mapscript_wrap.o install: $(DLTARGET)$(TCL_SHLIB_SUFFIX) -mkdir $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) cp $(DLTARGET)$(TCL_SHLIB_SUFFIX) $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) chmod +x \ $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR)/$(DLTARGET)$(TCL_SHLIB_SUFFIX) cp pkgIndex.tcl $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) cp mapscriptsupp.tcl $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) cp mapscriptsupp.html $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) cp mapscript_wrap.html $(TCL_EXEC_PREFIX)/lib/$(PACKAGEDIR) useprebuilt: gunzip -c mapscript_wrap.c.gz >mapscript_wrap.c prebuilt: mapscript_wrap.c gzip -cf mapscript_wrap.c >mapscript_wrap.c.gz tar: if test ! -f mapscript_wrap.c.gz ; then \ gzip -cf mapscript_wrap.c >mapscript_wrap.c.gz; fi rm -f mapscript_wrap.c (cd ..; tar cf mapscript-tcl.tar tcl ) gzip -f ../mapscript-tcl.tar clean: rm -f *.o core *.so distclean: clean rm -f Makefile reallyclean: distclean rm -f mapscript_wrap.* mapserver-7.4.3/mapscript/tcl/README000066400000000000000000000146701357574274700172320ustar00rootroot00000000000000Mapscript Tcl Interface WHAT It's a Tcl interface for Mapserver. You can write Tcl scripts to generate maps, read/write shapefiles, etc. VERSION Mapscript 1.1 is built for Mapserver 3.5 + INSTALL A simple 'configure' script and Makefile is included. The configure is hand built, rather than being derived from GNU autoconf. Normally you can just type: configure make make install to build and install the interface. Three configure options are supported: configure --with-tcl=[dir] --with-swig=[dir] --with-linker-cc --with-tcl=[dir] specify the directory where you installed Tcl, the default is /usr/local. 'configure' looks for $dir/lib/tclConfig.sh for Tcl configure info. --with-swig=[dir] specify the directory where you installed Swig, the default is /usr/local. 'configure' looks for $dir/include/swig.h and $dir/lib/libswig.a. --with-linker-cc use the compiler command as the front-end for linking, if not already so. See 'COMPILE PROBLEMS' below. ** Mapserver source code is presumed to be two directory levels above this directory, and uses various .h files from Mapscript, along with ../mapscript.i. ** Mapscript/Tcl normally builds as a Tcl stubbed dynamic library. The makefile includes a target 'nostublib' if you want to build with a Tcl version dependent library (not recommended). ** Tested with Tcl/Tk version 8.3.2, and Swig version 1.1-883 REQUIREMENTS You must have Tcl (tcl.sourceforge.net) installed and optionally, Swig installed also (www.swig.org). The current mapscript.i Swig interface definition file is designed for Swig 1.1 versions. Newer versions of Swig may require mapscript.i changes. You should have Tcl 8.3 or greater installed, as the Makefile normally builds with the Tcl dynamic stubs library. Tcl 8.3.2 (or current release) is recommended. Additionally, you may want the Img Tcl extension to support upcoming Mapserver images (PNG, JPG, etc.) See the NOTES section below for more information. COMPILE PROBLEMS Some users have reported link or runtime errors, most notably when mapscript_wrap.c is compiled with gcc, but using ld to link the shared library. If you experience this problem, try re-running the configure script, adding the '--with-linker-cc' option to the configure command line. For users without Swig installed, a pre-built mapscript_wrap.c is available. 'make useprebuilt' will unpack the pre-built mapscript_wrap.c. If you get runtime errors reporting missing symbols, check the Mapscript/Tcl shared library for shared libraries it may be dependent upon. In Linux, Solaris (and possibly other unix systems) try this: ldd libMapscript*.* Note which libraries are unresolved. Find the directories which contain the libraries that are unresolved, and add those directories to your LD_LIBRARY_PATH environment variable, or whichever environment variable is appropriate for your system: $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/other/required/dirs Add this to your .profile or .cshrc so you won't have to set this each time you login. On some systems (Linux, et.al), a /etc/ld.so.conf file and 'ldconfig' program will set system-wide default library directory paths. WINDOWS See the ./win directory. You should first install Tcl 8.3.2. Then, run the 'setup.tcl' file to install Mapscript/Tcl. You can double-click on the 'setup.tcl' file from Windows explorer, or 'start setup.tcl' from a DOS box. To rebuild the DLL, see the file 'README.ms-mingw' and 'ms-mingw.tar.gz'. The DLL provided was built with the Mingw compiler, as a cross compiler hosted on Linux. You should be able to rebuild the DLL on any Unix box, or with a little work, using Mingw or Cygwin compiler & tools on Windows. No Microsoft or Borland makefiles are provided. Feel free to donate one(s). You can use the popular 'WinZip' program to unpack tar.gz files on Windows (http://www.winzip.com), or use gunzip and tar from the Cygwin tools (http://sources.redhat.com/cygwin/). DOCS Swig generated documentation, plus and additional doc page for Tcl coded helper functions are available as HTML. EXAMPLES See the ./examples directory. shpinfo.tcl - print rudimentary info about a shape file. MAPSERVER WORKBENCH MapServer Workbench is a set of tools written in Tcl/Tk with the Mapscript/Tcl extension, and is available separately. The Workbench currently consists of: msappwiz.tcl -wizard to create mapserver application mapfiles msedit.tcl -tree-structured mapfile editor msexplorer.tcl -view, zoom, and query mapfiles msshapex.tcl -view shapefile information and .dbf attributes MapServer Workbench tools run under Unix or Windows. For more information and to download MapServer Workbench: http://msworkbench.sourceforge.net http://sourceforge.net/projects/msworkbench/ http://www.nyx.net/~tpoindex/gis NOTES e.g., the "SWIG_STUB_HACK" Building Tcl extensions that are not dependent on a particular version of Tcl is the preferred method. Prior to Tcl 8.1, an extension had to be linked against a version dependent Tcl libarary. Extensions had to be recompiled and relinked when newer versions of Tcl were installed. Beginning with Tcl 8.1, the 'stub' library was introduced to facilitate version independent extensions. The stub library is a table of pointers to Tcl functions, that are initialized at run time, so extensions compiled for one version of Tcl don't have to be recompiled. A call to Tcl_InitStubs() is required before using any Tcl function in an extension, and we link to libtclstub8.3.a, instead of the entire Tcl library. Swig 1.1-883 doesn't initialize the stub table by calling Tcl_InitStubs(), so we must do it ourselves. Normally, we use the Swig directive '%init' to include the call to Tcl_InitStubs. However, we also prefer that the new Mapscript commands reside in their own namespace, by using the Swig option '-namespace'. Unfortunately, Swig generates a call to Tcl_Eval() before the %init code is included in the wrapped .c file. We work around this problem for Mapscript by some crusty use of the C preprocessor. Just before the Tcl_Eval call in the wrapped .c file, Swig also includes an bit of code that allows use the [incr Tcl] object system. The makefile passes command line C preprocessor defines to subvert this bit of code for our use. Thus, we are able to call the Tcl_InitStub function before Tcl_Eval is called. See the Makefile macro "SWIG_STUB_HACK". WHO Tom Poindexter tpoindex@nyx.net http://www.nyx.net/~tpoindex/ mapserver-7.4.3/mapscript/tcl/configure000077500000000000000000000107621357574274700202570ustar00rootroot00000000000000#!/bin/sh # not a normal autoconf configure script # grab the file ../../perlvars that mapserver made for the perl mapscript # build, and use gcc and ld flags if [ ! -f ../../perlvars ] ; then echo "you must build MapServer first." exit fi MAPSERVERHOME=`head -1 ../../mapscriptvars | tail -1` MAPSERVERDEFS=`head -2 ../../mapscriptvars | tail -1` MAPSERVERINCS=`head -3 ../../mapscriptvars | tail -1` MAPSERVERLIBS=`head -4 ../../mapscriptvars | tail -1` # make sure link to mapscript.i exists if [ ! -f mapscript.i ] ; then ln -s ../mapscript.i mapscript.i fi # check for --with-tcl= and/or --with-swig= with_tcl=/usr/local with_swig=/usr/local with_linker_cc=no for arg in $* do case $arg in --help) echo "mapscript tcl configure options:" echo "--with-tcl=dir where to find tcl (lib/tclConfig.sh)" echo "--with-swig=dir where to find swig (include/swig.h)" echo "--with-linker-cc use the compiler as linker front-end \ (see README)" exit ;; --with-tcl=*) save_if=$IFS IFS== set -- $arg with_tcl=$2 IFS=$save_ifs ;; --with-swig=*) save_if=$IFS IFS== set -- $arg with_swig=$2 IFS=$save_ifs ;; --with-linker-cc) with_linker_cc=yes ;; esac done # look for Tcl configs echo "looking for Tcl in $with_tcl" if [ ! -f $with_tcl/lib/tclConfig.sh ] ; then echo "can not find tclConfig.sh in $with_tcl" exit fi echo " found lib/tclConfig.sh in $with_tcl" # look for swig echo "looking for Swig in $with_swig" if [ ! -f $with_swig/include/swig.h ] ; then echo "can not find swig.h in $with_swig/include" echo "using pre-built swig tcl interface" # mapscript_wrap.c included in package else echo " found include/swig.h in $with_swig" fi SWIGDIR=$with_swig # source the tcl Configs . $with_tcl/lib/tclConfig.sh echo "tcl version = $TCL_VERSION" # if --with-linker-cc option set, then change ld command to use TCL_CC if test "$with_linker_cc" = "yes" ; then # get cc command, without any options that may be present eval set -- $TCL_CC cc="$1" # get any linker command options eval set -- $TCL_SHLIB_LD shift # build the new command using cc and linker options TCL_SHLIB_LD="$cc $*" fi # ugh. Tcl's tclConfig.sh only provides TCL_LD_SEARCH_FLAGS appropriate for # use with 'cc'. if 'ld' is the shared library loader, the flags # might be wrong, try to fix. this problem is often found on # Solaris, HP-UX, IRIX, {Free,Open,Net}BSD, OSF, Dec/Compaq Unix # first, get the shared lib loader command, should be ld or *cc eval set -- $TCL_SHLIB_LD ldcmd=`basename $1` if test "$ldcmd" = "ld" ; then # this machine uses ld, now see if a flag begins with -Wl newarg="" eval set -- $TCL_LD_SEARCH_FLAGS space="" for arg in $* do case $TCL_LD_SEARCH_FLAGS in -Wl*) # yep, here's our problem child # strip off first arg, change "," to " " via sh set hack IFSsave="$IFS" IFS="," eval set -- $arg IFS="$IFSsave" shift arg="$*" ;; *) newarg="$newarg$space$arg" ;; esac space=" " done TCL_LD_SEARCH_FLAGS="$newarg" fi # also check for Solaris loader flags '-z text', which causes unresolved # link errors, because we're mixing -fPIC code (mapscript_wrap.o) with # non -fPIC code (libmap.a, etc.) the resulting libMapscript.so will be # mixed, so don't cause the link to fail. TCL_SHLIB_LD=`echo $TCL_SHLIB_LD | sed -e 's/-z text//'` # fix up LIB_RUNTIME_DIR for those systems that leave it out if test -z "$LIB_RUNTIME_DIR" ; then LIB_RUNTIME_DIR=$with_tcl/lib fi # create our Makefile echo "creating Makefile" sed -e "s%@MAPSERVERHOME@%$MAPSERVERHOME%g" \ -e "s%@MAPSERVERDEFS@%$MAPSERVERDEFS%g" \ -e "s%@MAPSERVERINCS@%$MAPSERVERINCS%g" \ -e "s%@MAPSERVERLIBS@%$MAPSERVERLIBS%g" \ -e "s%@TCL_PREFIX@%$TCL_PREFIX%g" \ -e "s%@TCL_EXEC_PREFIX@%$TCL_EXEC_PREFIX%g" \ -e "s%@TCL_CC@%$TCL_CC%g" \ -e "s%@TCL_DEFS@%$TCL_DEFS%g" \ -e "s%@TCL_SHLIB_SUFFIX@%$TCL_SHLIB_SUFFIX%g" \ -e "s%@TCL_SHLIB_CFLAGS@%$TCL_SHLIB_CFLAGS%g" \ -e "s%@TCL_LD_SEARCH_FLAGS@%$TCL_LD_SEARCH_FLAGS%g" \ -e "s%@TCL_SHLIB_LD@%$TCL_SHLIB_LD%g" \ -e "s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g" \ -e "s%@TCL_STUB_LIB_SPEC@%$TCL_STUB_LIB_SPEC%g" \ -e "s%@TCL_LIBS@%$TCL_LIBS%g" \ -e "s%@LIB_RUNTIME_DIR@%$LIB_RUNTIME_DIR%g" \ -e "s%@TCL_DBGX@%$TCL_DBGX%g" \ -e "s%@SWIGDIR@%$SWIGDIR%g" \ Makefile mapserver-7.4.3/mapscript/tcl/examples/000077500000000000000000000000001357574274700201605ustar00rootroot00000000000000mapserver-7.4.3/mapscript/tcl/examples/shpinfo.tcl000077500000000000000000000013621357574274700223370ustar00rootroot00000000000000#!/usr/local/bin/tclsh8.3 # if running a test before install, include directory to find package lappend auto_path [pwd]/.. package require Mapscript array set types { 1 point 3 arc 5 polygon 8 multipoint } set file $argv if {! [file isfile $file.shp]} { puts "shapefile \"$file\" not found" puts "usage: $argv0 " exit } mapscript::shapefileObj shp1 $file -1 puts "\nShapefile $file:\n" puts "\ttype: $types([shp1 cget -type])" puts "\tnumber of features: [shp1 cget -numshapes]" set rectPtr [shp1 cget -bounds] puts "\tbounds: ([mapscript::rectObjRef $rectPtr cget -minx],[mapscript::rectObjRef $rectPtr cget -miny]) ([mapscript::rectObjRef $rectPtr cget -maxx],[mapscript::rectObjRef $rectPtr cget -maxy])" mapserver-7.4.3/mapscript/tcl/mapscript_wrap.html000066400000000000000000001352361357574274700222750ustar00rootroot00000000000000 mapscript_wrap.c

mapscript_wrap.c


Contents

mapscript::MS_VERSION = 3.4 (pre-release)

[ Constant : char * ]
logical control variables

mapscript::MS_TRUE = 1

[ Constant : int ]

mapscript::MS_FALSE = 0

[ Constant : int ]

mapscript::MS_ON = 1

[ Constant : int ]

mapscript::MS_OFF = 0

[ Constant : int ]

mapscript::MS_DEFAULT = 2

[ Constant : int ]

mapscript::MS_QUERY = 3

[ Constant : int ]

mapscript::MS_EMBED = 4

[ Constant : int ]

mapscript::MS_YES = 1

[ Constant : int ]

mapscript::MS_NO = 0

[ Constant : int ]
modes for searching (spatial/database)

mapscript::MS_SINGLE = 0

[ Constant : int ]

mapscript::MS_MULTIPLE = 1

[ Constant : int ]
General defines, not wrapable

mapscript::MS_FILE_MAP = MS_FILE_MAP

[ Constant : int ]

mapscript::MS_FILE_SYMBOL = MS_FILE_SYMBOL

[ Constant : int ]

mapscript::MS_INCHES = MS_INCHES

[ Constant : int ]

mapscript::MS_FEET = MS_FEET

[ Constant : int ]

mapscript::MS_MILES = MS_MILES

[ Constant : int ]

mapscript::MS_METERS = MS_METERS

[ Constant : int ]

mapscript::MS_NAUTICALMILES = MS_NAUTICALMILES

[ Constant : int ]

mapscript::MS_KILOMETERS = MS_KILOMETERS

[ Constant : int ]

mapscript::MS_DD = MS_DD

[ Constant : int ]

mapscript::MS_PIXELS = MS_PIXELS

[ Constant : int ]

mapscript::MS_POINT = MS_POINT

[ Constant : int ]

mapscript::MS_LINE = MS_LINE

[ Constant : int ]

mapscript::MS_POLYGON = MS_POLYGON

[ Constant : int ]

mapscript::MS_POLYLINE = MS_POLYLINE

[ Constant : int ]

mapscript::MS_RASTER = MS_RASTER

[ Constant : int ]

mapscript::MS_ANNOTATION = MS_ANNOTATION

[ Constant : int ]

mapscript::MS_NULL = MS_NULL

[ Constant : int ]

mapscript::MS_TRUETYPE = MS_TRUETYPE

[ Constant : int ]

mapscript::MS_BITMAP = MS_BITMAP

[ Constant : int ]

mapscript::MS_UL = MS_UL

[ Constant : int ]

mapscript::MS_LR = MS_LR

[ Constant : int ]

mapscript::MS_UR = MS_UR

[ Constant : int ]

mapscript::MS_LL = MS_LL

[ Constant : int ]

mapscript::MS_CR = MS_CR

[ Constant : int ]

mapscript::MS_CL = MS_CL

[ Constant : int ]

mapscript::MS_UC = MS_UC

[ Constant : int ]

mapscript::MS_LC = MS_LC

[ Constant : int ]

mapscript::MS_CC = MS_CC

[ Constant : int ]

mapscript::MS_AUTO = MS_AUTO

[ Constant : int ]

mapscript::MS_XY = MS_XY

[ Constant : int ]
arrangement matters for auto placement

mapscript::MS_TINY = MS_TINY

[ Constant : int ]

mapscript::MS_SMALL = MS_SMALL

[ Constant : int ]

mapscript::MS_MEDIUM = MS_MEDIUM

[ Constant : int ]

mapscript::MS_LARGE = MS_LARGE

[ Constant : int ]

mapscript::MS_GIANT = MS_GIANT

[ Constant : int ]

mapscript::MS_NORMAL = MS_NORMAL

[ Constant : int ]

mapscript::MS_HILITE = MS_HILITE

[ Constant : int ]

mapscript::MS_SELECTED = MS_SELECTED

[ Constant : int ]

mapscript::MS_INVERTED = MS_INVERTED

[ Constant : int ]

mapscript::MS_LOCAL = MS_LOCAL

[ Constant : int ]

mapscript::MS_SDE = MS_SDE

[ Constant : int ]

mapscript::MS_OGR = MS_OGR

[ Constant : int ]

mapscript::MS_GIF = MS_GIF

[ Constant : int ]

mapscript::MS_PNG = MS_PNG

[ Constant : int ]

mapscript::MS_JPEG = MS_JPEG

[ Constant : int ]

mapscript::MS_WBMP = MS_WBMP

[ Constant : int ]

mapscript::MS_FILE_DEFAULT = (MS_FILE_MAP)

[ Constant : int ]

1. class featureListNodeObj

[ created from struct featureListNodeObj ]

-shape

[ Member data: returns shapeObj * ]

-next

[ Member data: returns struct listNode * ]

2. class colorObj

[ created from struct colorObj ]

-red

[ Member data: returns int ]

-green

[ Member data: returns int ]

-blue

[ Member data: returns int ]

3. class queryObj

[ created from struct queryObj ]

-expression

[ Member data: returns expressionObj * ]
the expression to be matched

-template

[ Member data: returns char * ]

queryObj name layer

[ Constructor: returns queryObj * ]

rename obj {}

[ Destructor: returns void ]

setExpression string

[ Member : returns int ]

4. class shapeResultObj

[ created from struct shapeResultObj ]

-layer

[ Member data: returns int ]

-tile

[ Member data: returns int ]

-shape

[ Member data: returns int ]

-query

[ Member data: returns int ]

5. class queryResultObj

[ created from struct queryResultObj ]

-numlayers

[ Member data: returns int ]

-numresults

[ Member data: returns int ]

-numquerylayers

[ Member data: returns int ]

-currentlayer

[ Member data: returns int ]

-currenttile

[ Member data: returns int ]

-currentshape

[ Member data: returns int ]
allows for cursors-like access to results

queryResultObj name filename

[ Constructor: returns queryResultObj * ]

rename obj {}

[ Destructor: returns void ]

free

[ Member : returns void ]

save filename

[ Member : returns int ]

next

[ Member : returns shapeResultObj ]

6. class queryMapObj

[ created from struct queryMapObj ]

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-status

[ Member data: returns int ]

-style

[ Member data: returns int ]
HILITE, SELECTED or NORMAL

-color

[ Member data: returns int ]

7. class labelObj

[ created from struct labelObj ]

-font

[ Member data: returns char * ]

-type

[ Member data: returns enum MS_FONT_TYPE ]

-color

[ Member data: returns int ]

-outlinecolor

[ Member data: returns int ]

-shadowcolor

[ Member data: returns int ]

-shadowsizex

[ Member data: returns int ]

-shadowsizey

[ Member data: returns int ]

-backgroundcolor

[ Member data: returns int ]

-backgroundshadowcolor

[ Member data: returns int ]

-backgroundshadowsizex

[ Member data: returns int ]

-backgroundshadowsizey

[ Member data: returns int ]

-size

[ Member data: returns int ]

-sizescaled

[ Member data: returns int ]

-minsize

[ Member data: returns int ]

-maxsize

[ Member data: returns int ]

-position

[ Member data: returns int ]

-offsetx

[ Member data: returns int ]

-offsety

[ Member data: returns int ]

-angle

[ Member data: returns double ]

-autoangle

[ Member data: returns int ]
true or false

-buffer

[ Member data: returns int ]
space to reserve around a label

-antialias

[ Member data: returns int ]

-wrap

[ Member data: returns char ]

-minfeaturesize

[ Member data: returns int ]
minimum feature size (in pixels) to label

-autominfeaturesize

[ Member data: returns int ]
true or false

-mindistance

[ Member data: returns int ]

-partials

[ Member data: returns int ]
can labels run of an image

-force

[ Member data: returns int ]
labels *must* be drawn

8. class webObj

[ created from struct webObj ]

-log

[ Member data: returns char * ]

-imagepath

[ Member data: returns char * ]

-imageurl

[ Member data: returns char * ]

-template

[ Member data: returns char * ]

-header

[ Member data: returns char * ]

-footer

[ Member data: returns char * ]

-empty

[ Member data: returns char * ]

-error

[ Member data: returns char * ]
error handling

-extent

[ Member data: returns rectObj * ]
clipping extent

-minscale

[ Member data: returns double ]

-maxscale

[ Member data: returns double ]

-mintemplate

[ Member data: returns char * ]

-maxtemplate

[ Member data: returns char * ]

9. class classObj

[ created from struct classObj ]

-color

[ Member data: returns int ]

-backgroundcolor

[ Member data: returns int ]

-outlinecolor

[ Member data: returns int ]

-overlaycolor

[ Member data: returns int ]

-overlaybackgroundcolor

[ Member data: returns int ]

-overlayoutlinecolor

[ Member data: returns int ]

-symbol

[ Member data: returns int ]

-symbolname

[ Member data: returns char * ]

-overlaysymbol

[ Member data: returns int ]

-overlaysymbolname

[ Member data: returns char * ]

-size

[ Member data: returns int ]

-sizescaled

[ Member data: returns int ]

-minsize

[ Member data: returns int ]

-maxsize

[ Member data: returns int ]

-overlaysize

[ Member data: returns int ]

-overlaysizescaled

[ Member data: returns int ]

-overlayminsize

[ Member data: returns int ]

-overlaymaxsize

[ Member data: returns int ]

-label

[ Member data: returns labelObj * ]

-name

[ Member data: returns char * ]
used for legend labeling

classObj name layer

[ Constructor: returns classObj * ]

rename obj {}

[ Destructor: returns void ]

setExpression string

[ Member : returns int ]

setText layer string

[ Member : returns int ]

10. class labelCacheMemberObj

[ created from struct labelCacheMemberObj ]

-size

[ Member data: returns int ]
parameters that can vary for each label/feature

-angle

[ Member data: returns double ]

-string

[ Member data: returns char * ]

-featuresize

[ Member data: returns double ]

-layeridx

[ Member data: returns int ]
indexes

-classidx

[ Member data: returns int ]

-tileidx

[ Member data: returns int ]

-shapeidx

[ Member data: returns int ]

-point

[ Member data: returns pointObj * ]
label point

-poly

[ Member data: returns shapeObj * ]
label bounding box

-status

[ Member data: returns int ]
has this label been drawn or not

11. class markerCacheMemberObj

[ created from struct markerCacheMemberObj ]

-id

[ Member data: returns int ]
corresponding label

-poly

[ Member data: returns shapeObj * ]
marker bounding box (POINT layers only)

12. class labelCacheObj

[ created from struct labelCacheObj ]

-labels

[ Member data: returns labelCacheMemberObj * ]

-numlabels

[ Member data: returns int ]

-cachesize

[ Member data: returns int ]

-markers

[ Member data: returns markerCacheMemberObj * ]

-nummarkers

[ Member data: returns int ]

-markercachesize

[ Member data: returns int ]

freeCache

[ Member : returns void ]

13. class symbolSetObj

[ created from struct symbolSetObj ]

-filename

[ Member data: returns char * ]

-fontset

[ Member data: returns fontSetObj * ]
a pointer to the main mapObj version

-numsymbols

[ Member data: returns int ]

-symbol

[ Member data: returns symbolObj * ]

-imagecache

[ Member data: returns struct imageCacheObj * ]

-imagecachesize

[ Member data: returns int ]

14. class referenceMapObj

[ created from struct referenceMapObj ]

-extent

[ Member data: returns rectObj * ]

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-color

[ Member data: returns colorObj * ]

-outlinecolor

[ Member data: returns colorObj * ]

-image

[ Member data: returns char * ]

-status

[ Member data: returns int ]

15. class scalebarObj

[ created from struct scalebarObj ]

-imagecolor

[ Member data: returns colorObj * ]

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-style

[ Member data: returns int ]

-intervals

[ Member data: returns int ]

-label

[ Member data: returns labelObj * ]

-color

[ Member data: returns int ]

-backgroundcolor

[ Member data: returns int ]

-outlinecolor

[ Member data: returns int ]

-units

[ Member data: returns int ]

-status

[ Member data: returns int ]
ON, OFF or EMBED

-position

[ Member data: returns int ]
for embeded scalebars

-transparent

[ Member data: returns int ]

-interlace

[ Member data: returns int ]

-postlabelcache

[ Member data: returns int ]

16. class legendObj

[ created from struct legendObj ]

-imagecolor

[ Member data: returns colorObj * ]

-label

[ Member data: returns labelObj * ]

-keysizex

[ Member data: returns int ]

-keysizey

[ Member data: returns int ]

-keyspacingx

[ Member data: returns int ]

-keyspacingy

[ Member data: returns int ]

-outlinecolor

[ Member data: returns int ]
Color of outline of box, -1 for no outline

-status

[ Member data: returns int ]
ON, OFF or EMBED

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-position

[ Member data: returns int ]
for embeded legends

-transparent

[ Member data: returns int ]

-interlace

[ Member data: returns int ]

-postlabelcache

[ Member data: returns int ]

17. class layerObj

[ created from struct layerObj ]

-index

[ Member data: returns int ]

-classitem

[ Member data: returns char * ]
.DBF item to be used for symbol lookup

-class

[ Member data: returns classObj * ]
always at least 1 class

-numclasses

[ Member data: returns int ]

-name

[ Member data: returns char * ]
layer name, must be unique

-group

[ Member data: returns char * ]

-description

[ Member data: returns char * ]
layer title or description

-legend

[ Member data: returns char * ]
legend graphic

-status

[ Member data: returns int ]
layer status, either ON or OFF

-data

[ Member data: returns char * ]
layer data filename, including path

-type

[ Member data: returns enum MS_FEATURE_TYPE ]

-tolerance

[ Member data: returns double ]
search buffer for point and line queries (in toleranceunits)

-toleranceunits

[ Member data: returns int ]

-symbolscale

[ Member data: returns double ]
scale at which symbols are default size

-maxscale

[ Member data: returns double ]
layer is active only BELOW this scale value (<=)

-minscale

[ Member data: returns double ]
layer is active only ABOVE this scale value (>)

-labelminscale

[ Member data: returns double ]
annotation is active only BELOW this scale value (<=)

-labelmaxscale

[ Member data: returns double ]
annotation is active only ABOVE this scale value (>)

-maxfeatures

[ Member data: returns int ]

-offsite

[ Member data: returns int ]
offsite value for raster images

-transform

[ Member data: returns int ]
does this layer have to be transformed to file coordinates

-labelcache

[ Member data: returns int ]
on or off

-postlabelcache

[ Member data: returns int ]

-labelitem

[ Member data: returns char * ]
.DBF item to be used for text

-labelsizeitem

[ Member data: returns char * ]

-labelangleitem

[ Member data: returns char * ]

-tileitem

[ Member data: returns char * ]

-tileindex

[ Member data: returns char * ]
layer index file for tiling support

-projection

[ Member data: returns projectionObj * ]
projection information for the layer

-features

[ Member data: returns featureListNodeObjPtr ]
linked list so we don't need a counter

-connection

[ Member data: returns char * ]

-connectiontype

[ Member data: returns enum MS_CONNECTION_TYPE ]

layerObj name map

[ Constructor: returns layerObj * ]

rename obj {}

[ Destructor: returns void ]

getClass i

[ Member : returns classObj * ]

draw map img

[ Member : returns int ]

queryUsingPoint map point mode buffer

[ Member : returns queryResultObj * ]

queryUsingRect map rect

[ Member : returns queryResultObj * ]

queryUsingFeatures map results

[ Member : returns int ]

queryUsingShape map shape

[ Member : returns queryResultObj * ]

setProjection string

[ Member : returns int ]

addFeature shape

[ Member : returns int ]

classify string

[ Member : returns int ]

18. class mapObj

[ created from struct mapObj ]
structure for a map

-name

[ Member data: returns char * ]
small identifier for naming etc.

-status

[ Member data: returns int ]
is map creation on or off

-height

[ Member data: returns int ]

-width

[ Member data: returns int ]

-layers

[ Member data: returns layerObj * ]

-numlayers

[ Member data: returns int ]
number of layers in mapfile

-labelcache

[ Member data: returns labelCacheObj * ]
we need this here so multiple feature processors can access it

-transparent

[ Member data: returns int ]

-interlace

[ Member data: returns int ]

-extent

[ Member data: returns rectObj * ]
map extent array

-cellsize

[ Member data: returns double ]
in map units

-units

[ Member data: returns enum MS_UNITS ]
units of the projection

-scale

[ Member data: returns double ]
scale of the output image

-shapepath

[ Member data: returns char * ]
where are the shape files located

-tile

[ Member data: returns char * ]
an optional tile name to use as well

-palette

[ Member data: returns paletteObj * ]
holds a map palette

-imagecolor

[ Member data: returns colorObj * ]
holds the initial image color value

-imagetype

[ Member data: returns int ]

-imagequality

[ Member data: returns int ]

-projection

[ Member data: returns projectionObj * ]
projection information for output map

-reference

[ Member data: returns referenceMapObj * ]

-scalebar

[ Member data: returns scalebarObj * ]

-legend

[ Member data: returns legendObj * ]

-web

[ Member data: returns webObj * ]

mapObj name filename

[ Constructor: returns mapObj * ]

rename obj {}

[ Destructor: returns void ]

getLayer i

[ Member : returns layerObj * ]

getLayerByName name

[ Member : returns layerObj * ]

addColor r g b

[ Member : returns int ]

getSymbolByName type name

[ Member : returns int ]

prepareQuery

[ Member : returns void ]

prepareImage

[ Member : returns gdImagePtr ]

draw

[ Member : returns gdImagePtr ]

drawQueryMap results

[ Member : returns gdImagePtr ]

drawLegend

[ Member : returns gdImagePtr ]

drawScalebar

[ Member : returns gdImagePtr ]

drawReferenceMap

[ Member : returns gdImagePtr ]

embedScalebar img

[ Member : returns int ]

embedLegend img

[ Member : returns int ]

drawLabelCache img

[ Member : returns int ]

nextLabel

[ Member : returns labelCacheMemberObj * ]

queryUsingPoint point mode buffer

[ Member : returns queryResultObj * ]

queryUsingRect rect

[ Member : returns queryResultObj * ]

queryUsingFeatures results

[ Member : returns int ]

queryUsingShape map shape

[ Member : returns queryResultObj * ]

setProjection string

[ Member : returns int ]

save filename

[ Member : returns int ]

mapscript::msSaveImage img filename transparent interlace

[ returns int ]

mapscript::msFreeImage img

[ returns void ]

mapscript::MS_NOERR = 0

[ Constant : int ]

mapscript::MS_IOERR = 1

[ Constant : int ]

mapscript::MS_MEMERR = 2

[ Constant : int ]

mapscript::MS_TYPEERR = 3

[ Constant : int ]

mapscript::MS_SYMERR = 4

[ Constant : int ]

mapscript::MS_REGEXERR = 5

[ Constant : int ]

mapscript::MS_TTFERR = 6

[ Constant : int ]

mapscript::MS_DBFERR = 7

[ Constant : int ]

mapscript::MS_GDERR = 8

[ Constant : int ]

mapscript::MS_IDENTERR = 9

[ Constant : int ]

mapscript::MS_EOFERR = 10

[ Constant : int ]

mapscript::MS_PROJERR = 11

[ Constant : int ]

mapscript::MS_MISCERR = 12

[ Constant : int ]

mapscript::MS_CGIERR = 13

[ Constant : int ]

mapscript::MS_WEBERR = 14

[ Constant : int ]

mapscript::MS_IMGERR = 15

[ Constant : int ]

mapscript::MS_HASHERR = 16

[ Constant : int ]

mapscript::MS_JOINERR = 17

[ Constant : int ]
empty search results

mapscript::MS_NOTFOUND = 18

[ Constant : int ]

mapscript::MS_SHPERR = 19

[ Constant : int ]

mapscript::MS_PARSEERR = 20

[ Constant : int ]

mapscript::MS_SDEERR = 21

[ Constant : int ]

mapscript::MS_OGRERR = 22

[ Constant : int ]

mapscript::MS_NUMERRORCODES = 23

[ Constant : int ]

mapscript::MESSAGELENGTH = 2048

[ Constant : int ]

mapscript::ROUTINELENGTH = 64

[ Constant : int ]

19. class errorObj

[ created from struct errorObj ]

-code

[ Member data: returns int ]

-routine

[ Member data: returns char * ]

-message

[ Member data: returns char * ]

mapscript::ms_error_set { errorObj * } mapscript::ms_error_get

[ Global : errorObj ms_error ]

mapscript::msSetError code message routine

[ returns void ]

mapscript::msWriteError stream

[ returns void ]

20. class rectObj

[ created from struct rectObj ]

-minx

[ Member data: returns double ]

-miny

[ Member data: returns double ]

-maxx

[ Member data: returns double ]

-maxy

[ Member data: returns double ]

rectObj name

[ Constructor: returns rectObj * ]

rename obj {}

[ Destructor: returns void ]

fit width height

[ Member : returns double ]

draw map layer img class_string label_string

[ Member : returns int ]

21. class pointObj

[ created from struct pointObj ]

-x

[ Member data: returns double ]

-y

[ Member data: returns double ]

pointObj name

[ Constructor: returns pointObj * ]

rename obj {}

[ Destructor: returns void ]

draw map layer img class_string label_string

[ Member : returns int ]

distanceToPoint point

[ Member : returns double ]

distanceToLine a b

[ Member : returns double ]

distanceToShape shape

[ Member : returns double ]

22. class lineObj

[ created from struct lineObj ]

-numpoints

[ Member data: returns int ]

-point

[ Member data: returns pointObj * ]

lineObj name

[ Constructor: returns lineObj * ]

rename obj {}

[ Destructor: returns void ]

get i

[ Member : returns pointObj * ]

add p

[ Member : returns int ]

23. class shapeObj

[ created from struct shapeObj ]

-numlines

[ Member data: returns int ]

-line

[ Member data: returns lineObj * ]

-bounds

[ Member data: returns rectObj * ]

-type

[ Member data: returns int ]

-classindex

[ Member data: returns int ]

-queryindex

[ Member data: returns int ]

-text

[ Member data: returns char * ]

shapeObj name type

[ Constructor: returns shapeObj * ]

rename obj {}

[ Destructor: returns void ]

get i

[ Member : returns lineObj * ]

add line

[ Member : returns int ]

draw map layer img class_string label_string

[ Member : returns int ]

setBounds

[ Member : returns void ]

copy dest

[ Member : returns int ]

contains point

[ Member : returns int ]

intersects shape

[ Member : returns int ]

mapscript::MS_SHP_POINT = 1

[ Constant : int ]

mapscript::MS_SHP_ARC = 3

[ Constant : int ]

mapscript::MS_SHP_POLYGON = 5

[ Constant : int ]

mapscript::MS_SHP_MULTIPOINT = 8

[ Constant : int ]

24. class DBFInfo

[ created from struct DBFInfo ]

-fp

[ Member data: returns FILE * ]

-nRecords

[ Member data: returns int ]

-nRecordLength

[ Member data: returns int ]

-nHeaderLength

[ Member data: returns int ]

-nFields

[ Member data: returns int ]

-panFieldOffset

[ Member data: returns int * ]

-panFieldSize

[ Member data: returns int * ]

-panFieldDecimals

[ Member data: returns int * ]

-pachFieldType

[ Member data: returns char * ]

-pszHeader

[ Member data: returns char * ]

-nCurrentRecord

[ Member data: returns int ]

-bCurrentRecordModified

[ Member data: returns int ]

-pszCurrentRecord

[ Member data: returns char * ]

-bNoHeader

[ Member data: returns int ]

-bUpdated

[ Member data: returns int ]

getFieldName iField

[ Member : returns char * ]

getFieldWidth iField

[ Member : returns int ]

getFieldDecimals iField

[ Member : returns int ]

getFieldType iField

[ Member : returns DBFFieldType ]

mapscript::FTString = FTString

[ Constant : int ]

mapscript::FTInteger = FTInteger

[ Constant : int ]

mapscript::FTDouble = FTDouble

[ Constant : int ]

mapscript::FTInvalid = FTInvalid

[ Constant : int ]

25. class shapefileObj

[ created from struct shapefileObj ]

-source

[ Member data: returns char * ]
full path to the shapefile data

-hSHP

[ Member data: returns SHPHandle * ]
.SHP/.SHX file pointer

-type

[ Member data: returns int ]
shape type

-numshapes

[ Member data: returns int ]
number of shapes

-bounds

[ Member data: returns rectObj * ]
shape extent

-hDBF

[ Member data: returns DBFHandle ]
.DBF file pointer

shapefileObj name filename type

[ Constructor: returns shapefileObj * ]

rename obj {}

[ Destructor: returns void ]

get i shape

[ Member : returns int ]

getTransformed map i shape

[ Member : returns int ]

getExtent i rect

[ Member : returns void ]

add shape

[ Member : returns int ]

mapscript::DBFOpen pszDBFFile pszAccess

[ returns DBFHandle ]

mapscript::DBFCreate pszDBFFile

[ returns DBFHandle ]

mapscript::DBFGetFieldCount psDBF

[ returns int ]

mapscript::DBFGetRecordCount psDBF

[ returns int ]

mapscript::DBFAddField hDBF pszFieldName eType nWidth nDecimals

[ returns int ]

mapscript::DBFGetFieldInfo psDBF iField pszFieldName pnWidth pnDecimals

[ returns DBFFieldType ]

mapscript::DBFReadIntegerAttribute hDBF iShape iField

[ returns int ]

mapscript::DBFReadDoubleAttribute hDBF iShape iField

[ returns double ]

mapscript::DBFReadStringAttribute hDBF iShape iField

[ returns char * ]

mapscript::DBFWriteIntegerAttribute hDBF iShape iField nFieldValue

[ returns int ]

mapscript::DBFWriteDoubleAttribute hDBF iShape iField dFieldValue

[ returns int ]

mapscript::DBFWriteStringAttribute hDBF iShape iField pszFieldValue

[ returns int ]

mapscript::DBFClose hDBF

[ returns void ]
mapserver-7.4.3/mapscript/tcl/mapscriptsupp.html000066400000000000000000000075401357574274700221500ustar00rootroot00000000000000 mapscript_supp.c

mapscriptsupp.tcl


Mapscript Supplemental Procedures

  • 1. proc mapscript::classObjRef
  • 2. proc mapscript::colorObjRef
  • 3. proc mapscript::errorObjRef
  • 4. proc mapscript::featureListNodeObjRef
  • 5. proc mapscript::itemObjRef
  • 6. proc mapscript::labelCacheMemberObjRef
  • 7. proc mapscript::labelCacheObjRef
  • 8. proc mapscript::labelObjRef
  • 9. proc mapscript::layerObjRef
  • 10. proc mapscript::legendObjRef
  • 11. proc mapscript::lineObjRef
  • 12. proc mapscript::mapObjRef
  • 13. proc mapscript::markerCacheMemberObjRef
  • 14. proc mapscript::pointObjRef
  • 15. proc mapscript::projectionObjRef
  • 16. proc mapscript::queryMapObjRef
  • 17. proc mapscript::rectObjRef
  • 18. proc mapscript::referenceMapObjRef
  • 19. proc mapscript::resultCacheMemberObjRef
  • 20. proc mapscript::resultCacheObjRef
  • 21. proc mapscript::scalebarObjRef
  • 22. proc mapscript::shapeObjRef
  • 23. proc mapscript::shapefileObjRef
  • 24. proc mapscript::symbolSetObjRef
  • 25. proc mapscript::webObjRef
  • 26. proc mapscript::DBFInfoRef

Usage

These procedures allow methods to be invoked on object references (i.e., pointers), without having to convert a reference into an object. A valid object reference is required; procedures check for valid object types.

General syntax:

objectRefProc $objectPtr args

Sample:

set map [mapscript::mapObj -args $mapFile]
set rectPtr [$map cget -extent]
set minx [mapscript::rectObjRef $rectPtr cget -minx]
set miny [mapscript::rectObjRef $rectPtr cget -miny]

Notes: each of the objectRef procedures is just a shortcut to invoke a SWIG generated method name. Method names of:

  • cget
  • configure
  • delete
invoke that object's cget, configure, and delete method respectively.

Example:

mapscript::rectObjRef $rectPtr cget -minx
is equivalent to:
mapscript::rectObj_minx_get $rectPtr

Mapscript Convenience Procedures

  • 1. proc mapscript::getDBFNames
  • 2. proc mapscript::getDBFTypes
  • 3. proc mapscript::getDBFValues
  • 4. proc mapscript::getQueryInfo

Usage

mapscript::getDBFNames DBFInfo_handle
getDBFNames returns a list of field names from a DBF file handle. The DBFInfo_handle must be a valid DBFInfo handle returned from the DBFInfo constructor.

mapscript::getDBFTypes DBFInfo_handle
getDBFTypes returns a list of field types and lengths from a DBF file handle. The DBFInfo_handle must be a valid DBFInfo handle returned from the DBFInfo constructor. Each list element is itself a list of field type and field length. Valid field types are returned as: string, integer, and double.

mapscript::getDBFValues DBFInfo_handle record_number
getDBFValues returns a list of field values from a DBF file handle. The DBFInfo_handle must be a valid DBFInfo handle returned from the DBFInfo constructor. Record_number is the record number of the row to fetch.

mapscript::getQueryInfo mapObj_pointer layerObj_pointer
getQueryInfo returns a list of name-value pairs from a layer that map query has generated. mapObj_pointer and queryObj_pointer must be valid mapObj and layerObj pointers.


See also

See mapscript_wrap.html for the full Mapscript Tcl interface.

Note also that the Mapscript objects described in mapscript_wrap.html are defined in the mapscript namespace.

Tom Poindexter
tpoindex@nyx.net
mapserver-7.4.3/mapscript/tcl/mapscriptsupp.tcl000066400000000000000000000114201357574274700217560ustar00rootroot00000000000000# mapscriptsupp.tcl # # define procs to invoke object methods using an object pointer # tom poindexter, nov 2000, tpoindex@nyx.net # # e.g. shapeObj method arg arg ... # can be invoked on a shapeObj pointer as: # shapeObjRef $shapeObjPointer method arg arg ... # # convenience procedures: # getDBFNames $DBFHandle :returns list of field names # getDBFTypes $DBFHandle :returns list of field types # getDBFValues $DBFHandle $rec :returns list of field values # getQueryInfo $mapPtr $layerPtr :return "field value" from query # fix SWIG error # some swig versions don't handle namespaces when generating shadow objects # mapscript just has one - ms_error # if {![string length [info commands ::mapscript::ms_error]]} { catch { ::mapscript::errorObj ::mapscript::ms_error -this [::mapscript::ms_error_get] } } # # now define object helper procs # namespace eval ::mapscript { proc _mapscript_init_ {} { set code { proc OBJECTRef {ptr method args} { # check ptr for correct object type #if {! [regexp {_[^_]*_OBJECT_p} $ptr]} { # error "OBJECTRef pointer \"$ptr\" has wrong object class" #} # check for configure/cget/delete commands set member "" set delete "" switch -- $method { configure { set command _set set member _[string range [lindex $args 0] 1 end] set args [lrange $args 1 end] } cget { set command _get set member _[string range [lindex $args 0] 1 end] set args "" } delete { set delete delete_ set command "" set args "" } default { set command _$method } } # check of existence of command if {! [string length \ [info command ::mapscript::${delete}OBJECT${member}${command}]]} { error "OBJECT does not have method named \"$method\", or \ a member named \"$member\"" } # invoke command return [uplevel "::mapscript::${delete}OBJECT${member}${command} \ $ptr $args"] } } foreach obj {classObj colorObj errorObj featureListNodeObj itemObj \ labelCacheMemberObj labelCacheObj labelObj layerObj \ legendObj lineObj mapObj markerCacheMemberObj pointObj \ projectionObj queryMapObj rectObj referenceMapObj \ resultCacheMemberObj resultCacheObj scalebarObj shapeObj \ shapefileObj symbolSetObj webObj \ DBFInfo} { regsub -all OBJECT $code $obj proc_code eval $proc_code } } # run the help proc initialization, then get rid of it _mapscript_init_ rename _mapscript_init_ {} # # now create convenience procs # proc getDBFNames {dbf} { set n [msDBFGetFieldCount $dbf] set names "" for {set i 0} {$i < $n} {incr i} { lappend names [DBFInfoRef $dbf getFieldName $i] } return $names } proc getDBFTypes {dbf} { set n [msDBFGetFieldCount $dbf] set types "" for {set i 0} {$i < $n} {incr i} { set t [DBFInfoRef $dbf getFieldType $i] switch $t \ $::mapscript::FTString {set t string} \ $::mapscript::FTInteger {set t integer} \ $::mapscript::FTDouble {set t double} \ default {set t invalid} lappend t [DBFInfoRef $dbf getFieldWidth $i] lappend types $t } return $types } proc getDBFValues {dbf rec} { set n [msDBFGetFieldCount $dbf] set r [msDBFGetRecordCount $dbf] if {$rec >= $r || $rec < -1} {return ""} set values "" for {set i 0} {$i < $n} {incr i} { switch [DBFInfoRef $dbf getFieldType $i] \ $::mapscript::FTString { set t [msDBFReadStringAttribute $dbf $rec $i] } \ $::mapscript::FTInteger { set t [msDBFReadIntegerAttribute $dbf $rec $i] } \ $::mapscript::FTDouble { set t [msDBFReadDoubleAttribute $dbf $rec $i] } \ default {set t ""} lappend values $t } return $values } proc getQueryInfo {mapPtr layerPtr} { layerObjRef $layerPtr open [mapObjRef $mapPtr cget -shapepath] set rescachePtr [layerObjRef $layerPtr cget -resultcache] set numResults [resultCacheObjRef $rescachePtr cget -numresults] for {set i 0} {$i < $numResults} {incr i} { set resmemPtr [layerObjRef $layerPtr getResult $i] set shpIdx [resultCacheMemberObjRef $resmemPtr cget -shapeindex] set tileIdx [resultCacheMemberObjRef $resmemPtr cget -tileindex] set shpPtr [shapeObj -args $mapscript::MS_SHAPE_NULL] set rc [layerObjRef $layerPtr getShape $shpPtr $tileIdx $shpIdx] set numValues [shapeObjRef $shpPtr cget -numvalues] set pairs "" for {set j 0} {$j < $numValues} {incr j} { lappend pairs [layerObjRef $layerPtr getItem $j] \ [shapeObjRef $shpPtr getValue $j] } # delete the temporary shpPtr catch {rename $shpPtr {}} } layerObjRef $layerPtr close return $pairs } } ;#end of namespace command mapserver-7.4.3/mapscript/tcl/pkgIndex.tcl000066400000000000000000000005401357574274700206160ustar00rootroot00000000000000# pkgIndex.tcl for mapscript # # load shared library, and source supplementaly ref procs package ifneeded Mapscript 1.1 " load [list [file join $dir libMapscript11[info sharedlibextension]]] # source the object reference helpers and convenience procs source [list [file join $dir mapscriptsupp.tcl]] package provide Mapscript 1.1 " mapserver-7.4.3/mapscript/tcl/win/000077500000000000000000000000001357574274700171375ustar00rootroot00000000000000mapserver-7.4.3/mapscript/tcl/win/README.ms-mingw000066400000000000000000000105001357574274700215500ustar00rootroot00000000000000Mapserver and Mapscript/Tcl for Windows These are the steps I have made to compile Mapserver and Mapscript/Tcl for Windows. My build environment is the Mingw (Minimalist GNU for Windows) compiler and toolchain, hosted on Linux/Unix. You probably want to use the pre-compiled DLL, if at all possible. Things get ugly after this...... First, make a new directory to hold everthing we will need. mkdir ms_win cd ms_win Unpack the ms-mingw.tar.gz in that directory: gunzip -c ../ms-mingw.tar.gz | tar xf - Next, you'll need the Mingw compiler and toolchain, compiled as a cross compiler, hosted on your Linux or Unix platform. Mo DeJong has written a shell script to download, compile, and install *all* of the compiler, toolchain, and Mingw libraries. The script is in ms-mingw/mingw-xcc.sh I have set the script to install the tools into /opt/mingw. If you want to change this, you'll need to also change the 'build' shell script. The mingw-xcc.sh script uses the 'wget' program to fetch files via ftp (ftp://ftp.gnu.org/gnu/wget/). cd ms-mingw sh mingw-xcc.sh cd .. Next, get *fresh* sources of all of the required MapServer packages, and unpack in the ms_win directory. Your 'ms_win' directory should look like this after unpacking all of the sources: README.ms-mingw install ms-mingw/ tcl8.3.2/ build jpeg-6b/ proj-4.4.2/ tiff-v3.5.5/ freetype-1.3.1/ mapserver/ regex-0.12/ zlib-1.1.3/ The 'ms-mingw' directory contains directories for each of the components we will be building. Each directory consists of a Makefile for Mingw as a cross compiler, and a 'build' script to copy the Makefile into the source directories (as above), and make the libraries. Software locations: mingw: http://www.mingw.org The mingw-xcc.sh script will grab things for you. There's a lot of info on the Mingw compiler and its use as a cross compiler at the site. proj: http://www.remotesensing.org/proj/ Get version 4.4.2 zlib: http://www.info-zip.org/pub/infozip/zlib/ Get version 1.1.3 jpeg: ftp://ftp.uu.net/graphics/jpeg/ Get version 6b. tiff: http://www.libtiff.org/ Get version 3.5.5 freetype: http://www.freetype.org Get version 1.3.1 NOTE!!! I have found the the freetype-1.3.1.tar.gz file contains source files with dos style end of line characters (cr-lf). This will likely confuse gcc. The easy way to convert into normal unix-style text files is to get the freetype-1.3.1.zip, and use 'unzip -a freetype-1.3.1' to unpack it, converting the files to use lf only. Rename the 'freetype' directory to 'freetype-1.3.1'. regex: ftp://ftp.gnu.org/pub/gnu/regex/regex-0.12.tar.gz mapserver: http://mapserver.gis.umn.edu/dload.html Get the 'nightly' CVS builds for 3.4 (beta), nightly.tar.gz. We will also use the GD 1.2 and GDFT libraries that come with Mapserver. As a side effect, we will also build an executable, mapserv.exe. tcl: http://dev.scriptics.com Get version 8.3.2 We will only be building 'libtclstub83.a', not the entire Tcl library. Also get 'tcl832.exe' and install it on your Windows machine(s) if you don't already have it. For best results, let the installer place Tcl in 'C:\Program Files\Tcl'. Build everything: Use the build script in this directory. (change the values of 'mingwbin' and 'mingwxcc' if needed.) sh build Install: You probably have to be root to write into /c. sh install Or, you can ftp the files over to your windows box and use the 'setup.tcl' installer. Notes: Building for Windows is a royal pain in the ***! The biggest problem is building the various libraries the 'right' way, i.e, as DLL files. This requires a majic Windows macro to export the symbols for the DLL, but another majic macro for code that uses the symbols in a DLL. For software originally not designed to be portable across Unix and Windows, this requires changing alot of source files. Examples of software that is written for portability: zlib, tcl Examples of software that is not: proj, mapserver The alternative: compile the source library code, and bundling it into a standard library file, e.g., libz.a, libjpeg.a, libttf.a, etc. We then take all of the libraries and create our final DLL, libMapscript.dll. The downside is that we're not allowing any reuse of the libaries, but the upside is we don't have to change much exisiting code. I do this method. mapserver-7.4.3/mapscript/tcl/win/ms-mingw.tar000066400000000000000000002400001357574274700214010ustar00rootroot00000000000000README.ms-mingw0100644000421500037440000001050007225405766013601 0ustar tpoindexsybcipsMapserver and Mapscript/Tcl for Windows These are the steps I have made to compile Mapserver and Mapscript/Tcl for Windows. My build environment is the Mingw (Minimalist GNU for Windows) compiler and toolchain, hosted on Linux/Unix. You probably want to use the pre-compiled DLL, if at all possible. Things get ugly after this...... First, make a new directory to hold everthing we will need. mkdir ms_win cd ms_win Unpack the ms-mingw.tar.gz in that directory: gunzip -c ../ms-mingw.tar.gz | tar xf - Next, you'll need the Mingw compiler and toolchain, compiled as a cross compiler, hosted on your Linux or Unix platform. Mo DeJong has written a shell script to download, compile, and install *all* of the compiler, toolchain, and Mingw libraries. The script is in ms-mingw/mingw-xcc.sh I have set the script to install the tools into /opt/mingw. If you want to change this, you'll need to also change the 'build' shell script. The mingw-xcc.sh script uses the 'wget' program to fetch files via ftp (ftp://ftp.gnu.org/gnu/wget/). cd ms-mingw sh mingw-xcc.sh cd .. Next, get *fresh* sources of all of the required MapServer packages, and unpack in the ms_win directory. Your 'ms_win' directory should look like this after unpacking all of the sources: README.ms-mingw install ms-mingw/ tcl8.3.2/ build jpeg-6b/ proj-4.4.2/ tiff-v3.5.5/ freetype-1.3.1/ mapserver/ regex-0.12/ zlib-1.1.3/ The 'ms-mingw' directory contains directories for each of the components we will be building. Each directory consists of a Makefile for Mingw as a cross compiler, and a 'build' script to copy the Makefile into the source directories (as above), and make the libraries. Software locations: mingw: http://www.mingw.org The mingw-xcc.sh script will grab things for you. There's a lot of info on the Mingw compiler and its use as a cross compiler at the site. proj: http://www.remotesensing.org/proj/ Get version 4.4.2 zlib: http://www.info-zip.org/pub/infozip/zlib/ Get version 1.1.3 jpeg: ftp://ftp.uu.net/graphics/jpeg/ Get version 6b. tiff: http://www.libtiff.org/ Get version 3.5.5 freetype: http://www.freetype.org Get version 1.3.1 NOTE!!! I have found the the freetype-1.3.1.tar.gz file contains source files with dos style end of line characters (cr-lf). This will likely confuse gcc. The easy way to convert into normal unix-style text files is to get the freetype-1.3.1.zip, and use 'unzip -a freetype-1.3.1' to unpack it, converting the files to use lf only. Rename the 'freetype' directory to 'freetype-1.3.1'. regex: ftp://ftp.gnu.org/pub/gnu/regex/regex-0.12.tar.gz mapserver: http://mapserver.gis.umn.edu/dload.html Get the 'nightly' CVS builds for 3.4 (beta), nightly.tar.gz. We will also use the GD 1.2 and GDFT libraries that come with Mapserver. As a side effect, we will also build an executable, mapserv.exe. tcl: http://dev.scriptics.com Get version 8.3.2 We will only be building 'libtclstub83.a', not the entire Tcl library. Also get 'tcl832.exe' and install it on your Windows machine(s) if you don't already have it. For best results, let the installer place Tcl in 'C:\Program Files\Tcl'. Build everything: Use the build script in this directory. (change the values of 'mingwbin' and 'mingwxcc' if needed.) sh build Install: You probably have to be root to write into /c. sh install Or, you can ftp the files over to your windows box and use the 'setup.tcl' installer. Notes: Building for Windows is a royal pain in the ***! The biggest problem is building the various libraries the 'right' way, i.e, as DLL files. This requires a majic Windows macro to export the symbols for the DLL, but another majic macro for code that uses the symbols in a DLL. For software originally not designed to be portable across Unix and Windows, this requires changing alot of source files. Examples of software that is written for portability: zlib, tcl Examples of software that is not: proj, mapserver The alternative: compile the source library code, and bundling it into a standard library file, e.g., libz.a, libjpeg.a, libttf.a, etc. We then take all of the libraries and create our final DLL, libMapscript.dll. The downside is that we're not allowing any reuse of the libaries, but the upside is we don't have to change much exisiting code. I do this method. build0100644000421500037440000000113207225404613012175 0ustar tpoindexsybcips # change these two defs if your Mingw cross compiler is somewhere else mingwbin=/opt/mingw/bin mingwxcc=i386-mingw32msvc- export mingwbin mingwxcc (cd ms-mingw/zlib-1.1.3 ; sh build) (cd ms-mingw/jpeg-6b ; sh build) (cd ms-mingw/tiff-v3.5.5 ; sh build) (cd ms-mingw/freetype-1.3.1 ; sh build) (cd ms-mingw/gd-1.2 ; sh build) (cd ms-mingw/gdft ; sh build) (cd ms-mingw/proj-4.4.2 ; sh build) (cd ms-mingw/regex-0.12 ; sh build) (cd ms-mingw/mapserver ; sh build) (cd ms-mingw/tcl-8.3.2 ; sh build) (cd ms-mingw/mapscripttcl ; sh build) install0100644000421500037440000000045007225156531012551 0ustar tpoindexsybcips#!/bin/sh destdir=/c/progra~1/tcl/lib/MapscriptTcl1.0 if [ ! -d $destdir ] ; then mkdir $destdir fi cd mapserver/mapscript/tcl cp libMapscript.dll $destdir cp mapscriptsupp.tcl $destdir cp pkgIndex.tcl $destdir cp mapscript_wrap.html $destdir cp mapscriptsupp.html $destdir ms-mingw/0040755000421500037440000000000007225406434012722 5ustar tpoindexsybcipsms-mingw/gd-1.2/0040755000421500037440000000000007225405166013613 5ustar tpoindexsybcipsms-mingw/gd-1.2/build0100644000421500037440000000020307225405157014625 0ustar tpoindexsybcipscp Makefile.MinXCC ../../mapserver/gd-1.2 cd ../../mapserver/gd-1.2 make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/gd-1.2/Makefile.MinXCC0100644000421500037440000000266307220263750016333 0ustar tpoindexsybcips#Depending on your system, you will need to modify this makefile. #If you do not have gcc, change the setting for CC, but you must #use an ANSI standard C compiler (NOT the old SunOS 4.1.3 cc #compiler; get gcc if you are still using it). #If the ar command fails on your system, consult the ar manpage #for your system. MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool CFLAGS = -O LIBS = -L./ -lgd -lm all: libgd.a old: libgd.a gddemo giftogd webgif gddemo: gddemo.o libgd.a gd.h gdfonts.h gdfontl.h $(CC) gddemo.o -o gddemo $(LIBS) giftogd: giftogd.o libgd.a gd.h $(CC) giftogd.o -o giftogd $(LIBS) libgd.a: gd.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \ gd.h gdfontt.h gdfonts.h gdfontmb.h gdfontl.h gdfontg.h rm -f libgd.a $(AR) rc libgd.a gd.o gdfontt.o gdfonts.o gdfontmb.o \ gdfontl.o gdfontg.o gd.dll: gd.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \ gd.h gdfontt.h gdfonts.h gdfontmb.h gdfontl.h gdfontg.h $(DLLWRAP) --output-lib=libgd.a --dllname=gd.dll --output-def=gd.def \ --dlltool=$(DLLTOOL) --export-all-symbols --driver-name=$(CC) \ gd.o gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o webgif: webgif.o libgd.a gd.h $(CC) webgif.o -o webgif $(LIBS) clean: rm -f *.o *.a gddemo giftogd webgif ms-mingw/freetype-1.3.1/0040755000421500037440000000000007225405132015175 5ustar tpoindexsybcipsms-mingw/freetype-1.3.1/Makefile.MinXCC0100644000421500037440000000470507220311561017715 0ustar tpoindexsybcips# This file is part of the FreeType project. # # It builds the library for MinGW32 gcc under Win9x. # # You will need a port of GNU make; the MinGW32 port works. # # Use this file while in the lib directory with the following statement: # # make -f arch/win32/Makefile.Min # # # When compared to the other Makefiles for gcc, there is a difference # here, because COMMAND.COM on Win 9x is not able to process more than # 126 characters. So the command line for ar use the * shell character. # # This is not as safe as normal, because unnecessary files may be # included by mistake in the library. # The normal behaviour can be restored by defining NON_LIMITED_SHELL=1 ARCH = arch/win32 FT_MAKEFILE = $(ARCH)/Makefile.MinXCC MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool ifdef DEBUG CFLAGS = -Wall -O2 -g -ansi -pedantic -I$(ARCH) -I. -Iextend else CFLAGS = -Wall -ansi -pedantic -O2 -s -I$(ARCH) -I. -Iextend endif TTF_DEFS = -D__WIN32__ -D__WIN32DLL__ -DWIN32 -D_WIN32 -D_MT -D_DLL TTFILE = ./ttfile.c TTMEMORY = ./ttmemory.c TTMUTEX = ./ttmutex.c PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ extend/ftxgsub.c extend/ftxgpos.c extend/ftxgdef.c \ extend/ftxopen.c extend/ftxerr18.c OBJS_X = $(SRC_X:.c=.o) SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ ttgload.c ttinterp.c ttload.c ttobjs.c \ ttraster.c ttextend.c $(PORT) OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) SRC_S = $(ARCH)/freetype.c OBJ_S = $(SRC_S:.c=.o) OBJS_S = $(OBJ_S) $(OBJS_X) %.o: %.c $(CC) $(CFLAGS) $(TTF_DEFS) -c -o $@ $< .PHONY: all debug clean distclean depend all: $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=$(OBJS_S) OBJ_LOC=$(ARCH) libttf.a libttf.a: $(LIB_FILES) rm -f libttf.a $(AR) cr libttf.a $(OBJS_S) ttf.dll: $(LIB_FILES) $(DLLWRAP) --output-lib=libttf.a --dllname=ttf.dll \ --def=ttf.def \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ $^ $(OBJ_S): $(SRC_S) $(SRC_M) clean: -rm *.o -rm extend\*.o -rm $(subst /,\,$(ARCH)\*.o) -rm response distclean: clean -rm dep.end -rm libttf.a depend: $(SRS_S) $(SRC_M) $(SRC_X) $(CC) -E -M $^ > dep.end ifeq (dep.end,$(wildcard dep.end)) include dep.end endif # end of Makefile.Min ms-mingw/freetype-1.3.1/build0100644000421500037440000000023507225405130016212 0ustar tpoindexsybcipscp Makefile.MinXCC ../../freetype-1.3.1/lib/arch/win32 cd ../../freetype-1.3.1/lib make -f arch/win32/Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/mingw-xcc.sh0100755000421500037440000000700707225406434015156 0ustar tpoindexsybcips#!/bin/sh # This is a buildscript for a cross mingwin compiler. # You should be able to just run it once you set # the correct src, build, and install dirs #SRCDIR=${HOME}/project/Xmingwin #BUILDDIR=${HOME}/project/build/Xmingwin #PREFIX=${HOME}/project/install/Xmingwin SRCDIR=/opt/mingw/src BUILDDIR=/opt/mingw/build PREFIX=/opt/mingw #TARGET=i386-pc-mingw32 # Mumit suggested changing this target name to i386-mingw32msvc TARGET=i386-mingw32msvc TARGET_ALIAS=i386-mingw32msvc # The install location's bin dir must be on the path PATH=$PREFIX/bin:$PATH BASE_URL=ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/snapshots/gcc-2.95.2-1 BINUTILS=binutils-19990818 BINUTILS_TAR=${BINUTILS}-1-src.tar.gz GCC=gcc-2.95.2 GCC_TAR=${GCC}-1-src.tar.gz MINGWSRC_ZIP=mingw-20000203.zip MSVCRT_ZIP=mingw-msvcrt-20000203.zip # If the files are not in the src directory, download them now mkdir -p $SRCDIR cd $SRCDIR for f in $BINUTILS_TAR $GCC_TAR $MINGWSRC_ZIP $MSVCRT_ZIP; do if test ! -f ${f} ; then echo "wget ${BASE_URL}/${f}" wget ${BASE_URL}/${f} if test ! -f ${f} ; then echo "Could not download ${BASE_URL}/${f}" exit 1 fi else echo "Found ${f} in the srcdir $SRCDIR" fi done echo "--- install binary cross libs and includes" mkdir -p $PREFIX cd $PREFIX if test ! -d $TARGET_ALIAS ; then unzip -o $SRCDIR/$MSVCRT_ZIP fi if test ! -d $TARGET_ALIAS ; then echo "error extracting $MSVCRT_ZIP, target alias dir $SRCDIR/$TARGET_ALIAS not found" exit 1 fi if test $TARGET_ALIAS != $TARGET ; then ln -s $TARGET_ALIAS $TARGET fi echo "--- compile and install binutils" cd $SRCDIR if test ! -d $BINUTILS ; then echo "extracting $BINUTILS_TAR in $SRCDIR" tar -xzf $BINUTILS_TAR if test ! -d $BINUTILS ; then echo "error extracting $BINUTILS_TAR, could not find $SRCDIR/$BINUTILS dir" exit 1 fi fi mkdir -p $BUILDDIR/binutils-$TARGET cd $BUILDDIR/binutils-$TARGET if test ! -f Makefile ; then echo "running ./configure for binutils, output saved in configure.log" $SRCDIR/$BINUTILS/configure -v --prefix=$PREFIX --target=$TARGET \ &> configure.log fi echo "running \"make\" for binutils, output saved in make.log" make all &> make.log echo "running \"make install\" for binutils, output saved in make_install.log" make install &> make_install.log echo "--- compile and install gcc" cd $SRCDIR if test ! -d $GCC ; then echo "extracting $GCC_TAR in $SRCDIR" tar -xzf $GCC_TAR if test ! -d $GCC ; then echo "error extracting $GCC_TAR, could not find $SRCDIR/$GCC dir" exit 1 fi fi mkdir -p $BUILDDIR/gcc-$TARGET cd $BUILDDIR/gcc-$TARGET if test ! -f Makefile ; then echo "running ./configure for gcc, output saved in configure.log" $SRCDIR/$GCC/configure -v --prefix=$PREFIX --target=$TARGET \ --with-gnu-as --with-gnu-ld \ &> configure.log fi # work around gcc bug? #cd gcc ; make installdirs ; cd - #echo "running \"make cross\" for gcc, output saved in make.log" echo "running \"make\" for gcc, output saved in make.log" #NOTE: We seem to need to run make cross not make all here #make cross &> make.log #FIXME: we seem to need to run make 2 times, not sure where the bug is. make all &> make1.log make all &> make2.log echo "running \"make install\" for gcc, output saved in make_install.log" make install &> make_install.log echo "Done!" echo "" echo "Your mingwin cross compilers are installed in $PREFIX" echo "The c++ compiler is called $TARGET-c++ or $TARGET-g++" echo "The c compiler is called $TARGET-gcc" echo "You may need to add $PREFIX/bin to your PATH" ms-mingw/tiff-v3.5.5/0040755000421500037440000000000007225405345014506 5ustar tpoindexsybcipsms-mingw/tiff-v3.5.5/Makefile.MinXCC0100644000421500037440000000722707220312242017217 0ustar tpoindexsybcips# $Header: /cvsroot/osrs/libtiff/libtiff/Makefile.lcc,v 1.1.1.1 1999/07/27 21:50:27 mike Exp $ # # Tag Image File Format Library # # Copyright (c) 1988-1997 Sam Leffler # Copyright (c) 1991-1997 Silicon Graphics, Inc. # # Permission to use, copy, modify, distribute, and sell this software and # its documentation for any purpose is hereby granted without fee, provided # that (i) the above copyright notices and this permission notice appear in # all copies of the software and related documentation, and (ii) the names of # Sam Leffler and Silicon Graphics may not be used in any advertising or # publicity relating to the software without the specific, prior written # permission of Stanford and Silicon Graphics. # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # DESTDIR=. # INSTALL=install NULL= MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool NATIVE_CC = gcc IPATH= -I. -I../../jpeg-6b -I../../zlib-1.1.3 ILIBS= -L../../jpeg-6b -ljpeg -L../../zlib-1.1.3 -lz CONF_LIBRARY=\ ${NULL} COPTS= -O6 -DNDEBUG -DJPEG_SUPPORT CFLAGS= ${COPTS} ${IPATH} ${CONF_LIBRARY} # INCS= tiff.h tiffio.h SRCS= tif_fax3.c \ fax3sm_winnt.c \ tif_aux.c \ tif_close.c \ tif_codec.c \ tif_compress.c \ tif_dir.c \ tif_dirinfo.c \ tif_dirread.c \ tif_dirwrite.c \ tif_dumpmode.c \ tif_error.c \ tif_getimage.c \ tif_jpeg.c \ tif_flush.c \ tif_luv.c \ tif_lzw.c \ tif_next.c \ tif_open.c \ tif_packbits.c \ tif_predict.c \ tif_print.c \ tif_read.c \ tif_swab.c \ tif_strip.c \ tif_thunder.c \ tif_tile.c \ tif_version.c \ tif_warning.c \ tif_win32.c \ tif_write.c \ tif_zip.c \ ${NULL} OBJS= tif_fax3.o \ fax3sm_winnt.o \ tif_aux.o \ tif_close.o \ tif_codec.o \ tif_compress.o \ tif_dir.o \ tif_dirinfo.o \ tif_dirread.o \ tif_dirwrite.o \ tif_dumpmode.o \ tif_error.o \ tif_getimage.o \ tif_jpeg.o \ tif_flush.o \ tif_luv.o \ tif_lzw.o \ tif_next.o \ tif_open.o \ tif_packbits.o \ tif_predict.o \ tif_print.o \ tif_read.o \ tif_swab.o \ tif_strip.o \ tif_thunder.o \ tif_tile.o \ tif_version.o \ tif_warning.o \ tif_win32.o \ tif_write.o \ tif_zip.o \ ${NULL} ALL= tiffrnb.lib all: version.h libtiff.a tiff.dll: version.h ${OBJS} $(DLLWRAP) --output-lib=libtiff.a --dllname=tiff.dll \ --output-def=tiff.def --def=libtiff.def \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ ${OBJS} ${ILIBS} libtiff.a: ${OBJS} rm -f libtiff.a ${AR} cr libtiff.a $(OBJS) ${OBJS}: tiffio.h tiff.h tiffcomp.h tiffiop.h tiffconf.h tif_fax3.o: tif_fax3.c fax3sm_winnt.c t4.h tif_fax3.h version.h: ${NATIVE_CC} -o mkversion ${CFLAGS} mkversion.c rm -f version.h; ./mkversion version.h install: all installh -for i in ${ALL}; do \ ${INSTALL} -c -m 644 $$i ${DESTDIR}/lib/$$i; \ done installh: ${INCS} -for i in ${INCS}; do \ h=`basename $$i`; \ cmp -s $$i ${DESTDIR}/include/$$h || \ ${INSTALL} -c -m 444 $$i ${DESTDIR}/include/$$h; \ done clean: rm -f ${ALL} ${OBJS} mkg3states mkg3states.o g3states.h tags: ${SRCS} ${CTAGS} ${SRCS} ms-mingw/tiff-v3.5.5/build0100644000421500037440000000021107225405344015516 0ustar tpoindexsybcipscp Makefile.MinXCC ../../tiff-v3.5.5/libtiff cd ../../tiff-v3.5.5/libtiff make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/gdft/0040755000421500037440000000000007225405172013644 5ustar tpoindexsybcipsms-mingw/gdft/Makefile.MinXCC0100644000421500037440000000247707220264436016374 0ustar tpoindexsybcips#Depending on your system, you will need to modify this makefile. #If you do not have gcc, change the setting for CC, but you must #use an ANSI standard C compiler (NOT the old SunOS 4.1.3 cc #compiler; get gcc if you are still using it). #If the ar command fails on your system, consult the ar manpage #for your system. MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool GD_INC = -I../gd-1.2 GD_LIB = -L../gd-1.2 -lgd GD = -DUSE_GD_1_3 TTF_INC = -I../../freetype-1.3.1/lib TTF_LIB = -L../../freetype-1.3.1/lib -lttf TTF = -DUSE_TTF LEX = flex XTRALIBS = -lm CFLAGS = -O2 $(GD) $(GD_INC) $(TTF) $(TTF_INC) LDFLAGS = $(XTRALIBS) $(GD_LIB) $(TTF_LIB) RM= /bin/rm -f OBJS= gdkanji.o gdcache.o gdttf.o # # --- You shouldn't have to edit anything else. --- # .c.o: $(CC) -c $(CFLAGS) $< all: libgdft.a gdft.dll: $(OBJS) $(DLLWRAP) --output-lib=libgdft.a --dllname=gdft.dll \ --output-def=gdft.def \ --dlltool=$(DLLTOOL) --export-all-symbols --driver-name=$(CC) \ $(OBJS) $(TTF_LIB) lib: libgdft.a libgdft: libgfft.a libgdft.a: $(OBJS) rm -f libgdft.a $(AR) cr libgdft.a $(OBJS) clean: rm -f libgdft.a *.o ms-mingw/gdft/build0100644000421500037440000000017707225405171014667 0ustar tpoindexsybcipscp Makefile.MinXCC ../../mapserver/gdft cd ../../mapserver/gdft make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/jpeg-6b/0040755000421500037440000000000007225405176014156 5ustar tpoindexsybcipsms-mingw/jpeg-6b/Makefile.MinXCC0100644000421500037440000002755507220264452016704 0ustar tpoindexsybcips# Makefile for Independent JPEG Group's software # This makefile is suitable for Unix-like systems with ANSI-capable compilers. # If you have a non-ANSI compiler, makefile.unix is a better starting point. # Read installation instructions before saying "make" !! # The name of your C compiler: MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool # You may need to adjust these cc options: CFLAGS= -O6 # Generally, we recommend defining any configuration symbols in jconfig.h, # NOT via -D switches here. # Link-time cc options: LDFLAGS= # To link any special libraries, add the necessary -l commands here. LDLIBS= # Put here the object file name for the correct system-dependent memory # manager file. For Unix this is usually jmemnobs.o, but you may want # to use jmemansi.o or jmemname.o if you have limited swap space. SYSDEPMEM= jmemnobs.o # miscellaneous OS-dependent stuff # linker LN= $(CC) # file deletion command RM= rm -f # library (.a) file creation command # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ jquant2.c jutils.c jmemmgr.c # memmgr back ends: compile only one of these into a working library SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c # source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ coderules.doc filelist.doc change.log MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ makvms.opt CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ jconfig.vms CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ testimgp.jpg DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapimin.o jcapistd.o jctrans.o jcparam.o jdatadst.o jcinit.o \ jcmaster.o jcmarker.o jcmainct.o jcprepct.o jccoefct.o jccolor.o \ jcsample.o jchuff.o jcphuff.o jcdctmgr.o jfdctfst.o jfdctflt.o \ jfdctint.o # decompression library object files DLIBOBJECTS= jdapimin.o jdapistd.o jdtrans.o jdatasrc.o jdmaster.o \ jdinput.o jdmarker.o jdhuff.o jdphuff.o jdmainct.o jdcoefct.o \ jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o jidctred.o \ jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o # These objectfiles are included in libjpeg.a LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for sample applications (excluding library files) COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o rdrle.o rdbmp.o rdswitch.o \ cdjpeg.o DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o wrrle.o wrbmp.o rdcolmap.o \ cdjpeg.o TROBJECTS= jpegtran.o rdswitch.o cdjpeg.o transupp.o all: libjpeg.a jpeg.dll: $(LIBOBJECTS) $(DLLWRAP) --output-lib=libjpeg.a --dllname=jpeg.dll \ --output-def=jpeg.def \ --dlltool=$(DLLTOOL) --export-all-symbols --driver-name=$(CC) \ $(LIBOBJECTS) allold: libjpeg.a cjpeg djpeg jpegtran rdjpgcom wrjpgcom libjpeg.a: $(LIBOBJECTS) $(RM) libjpeg.a $(AR) cr libjpeg.a $(LIBOBJECTS) cjpeg: $(COBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.a $(LDLIBS) djpeg: $(DOBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.a $(LDLIBS) jpegtran: $(TROBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o jpegtran $(TROBJECTS) libjpeg.a $(LDLIBS) rdjpgcom: rdjpgcom.o $(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.o $(LDLIBS) wrjpgcom: wrjpgcom.o $(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.o $(LDLIBS) jconfig.h: jconfig.doc echo You must prepare a system-dependent jconfig.h file. echo Please read the installation directions in install.doc. exit 1 clean: $(RM) *.o cjpeg djpeg jpegtran libjpeg.a rdjpgcom wrjpgcom $(RM) core testout* test: cjpeg djpeg jpegtran $(RM) testout* ./djpeg -dct int -ppm -outfile testout.ppm testorig.jpg ./djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg ./cjpeg -dct int -outfile testout.jpg testimg.ppm ./djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg ./cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm ./jpegtran -outfile testoutt.jpg testprog.jpg cmp testimg.ppm testout.ppm cmp testimg.bmp testout.bmp cmp testimg.jpg testout.jpg cmp testimg.ppm testoutp.ppm cmp testimgp.jpg testoutp.jpg cmp testorig.jpg testoutt.jpg jcapimin.o: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcapistd.o: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.o: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.o: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.o: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jchuff.o: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h jcinit.o: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.o: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.o: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.o: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.o: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.o: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcphuff.o: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h jcprepct.o: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.o: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jctrans.o: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapimin.o: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapistd.o: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatadst.o: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatasrc.o: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.o: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.o: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.o: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h jdinput.o: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.o: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.o: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.o: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmerge.o: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdphuff.o: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h jdpostct.o: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.o: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdtrans.o: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jerror.o: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h jfdctflt.o: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jfdctfst.o: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jfdctint.o: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctflt.o: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctfst.o: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctint.o: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctred.o: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.o: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.o: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jutils.o: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemmgr.o: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemansi.o: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemname.o: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemnobs.o: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemdos.o: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemmac.o: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h cjpeg.o: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h djpeg.o: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h jpegtran.o: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h rdjpgcom.o: rdjpgcom.c jinclude.h jconfig.h wrjpgcom.o: wrjpgcom.c jinclude.h jconfig.h cdjpeg.o: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdcolmap.o: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdswitch.o: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.o: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h rdppm.o: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrppm.o: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdgif.o: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrgif.o: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdtarga.o: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrtarga.o: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdbmp.o: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrbmp.o: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdrle.o: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrrle.o: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h ms-mingw/jpeg-6b/build0100644000421500037440000000021107225405175015166 0ustar tpoindexsybcipscp Makefile.MinXCC ../../jpeg-6b cd ../../jpeg-6b cp jconfig.vc jconfig.h make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/mapserver/0040755000421500037440000000000007225405211014716 5ustar tpoindexsybcipsms-mingw/mapserver/Makefile.MinXCC0100755000421500037440000001521707220445065017452 0ustar tpoindexsybcips# Run ./configure in the main MapServer directory to turn this Makefile.in # into a proper Makefile # # mpatrol runtime memory debugger # MPATROL= MPATROL_INC= MPATROL_LIB= # # If you want to ignore missing datafile errors uncomment the following # line. This is especially useful with large tiled datasets that may not # have complete data for each tile. # #IGNORE_MISSING_DATA=-DIGNORE_MISSING_DATA IGNORE_MISSING_DATA = -DIGNORE_MISSING_DATA # # Apparently these aren't as commonplace as I'd hoped. Edit the # following line to reflect the missing functions on your platform. # # STRINGS=-DNEED_STRCASECMP -DNEED_STRNCASECMP -DNEED_STRDUP STRINGS= # Freetype distribution (TrueType font support). Available at http://www.freetype.org/. (RECOMMENDED) TTF_LIB= -Lgdft -lgdft -L../freetype-1.3.1/lib -lttf TTF_INC= -Igdft -I../freetype-1.3.1/lib TTF= -DUSE_TTF MAKE_GDFT= MAKE_GDFT_CLEAN= # Proj.4 distribution (cartographic projection routines). Not required for normal use. (EXPERIMENTAL) PROJ_INC= -I../proj-4.4.2/src PROJ_LIB= -L../proj-4.4.2/src -lproj PROJ= -DUSE_PROJ # GD distribution (graphics library GIF and/or PNG support). (REQUIRED) # # - Version 1.2 is included and writes LZW GIF (-DUSE_GD_1_2). # - Versions 1.3 to 1.5 write non-LZW GIF (-DUSE_GD_1_3). # - Versions 1.6 and greater write PNG (-DUSE_GD_1_6). Add -lpng -lz to GD_LIB line. # # If you're not using the 1.2 version included in the MapServer distribution # then comment out the MAKE_GD and MAKE_GD_CLEAN entries. # GDFONT_OBJ=gd-1.2/gdfontt.o gd-1.2/gdfonts.o gd-1.2/gdfontmb.o gd-1.2/gdfontl.o gd-1.2/gdfontg.o GD_INC= -Igd-1.2 GD_LIB= -Lgd-1.2 -lgd GD= -DUSE_GD_1_2 MAKE_GD= MAKE_GD_CLEAN = # TIFF distribution (raster support for TIFF and GEOTIFF imagery). (RECOMMENDED) TIFF_INC= -I../tiff-v3.5.5/libtiff TIFF_LIB= -L../tiff-v3.5.5/libtiff -ltiff TIFF= -DUSE_TIF # JPEG distribution (raster support for grayscale JPEG images, INPUT ONLY). JPEG_INC= -I../jpeg-6b JPEG_LIB= -L../jpeg-6b -ljpeg JPEG= -DUSE_JPEG # EPPL7 Support (this activates ERDAS as well) Included in the distribution. Probably the best raster alternative if # you've got EPPL7 laying around. See http://www.lmic.state.mn.us/ for more information. (RECOMMENDED) EPPL= -DUSE_EPPL EPPL_OBJ= epplib.o # ESRI SDE Support. You MUST have the SDE Client libraries and include files # on your system someplace. The actual SDE server you wish to connect to can # be elsewhere. SDE= SDE_LIB= SDE_INC= # Optional OGR Support. OGC Simple Feature inspired interface for vector # formats. See http://gdal.velocet.ca/projects/opengis/ OGR= OGR_LIB= OGR_INC= # # UofMN GIS/Image Processing Extension (very experimental) # #EGIS=-DUSE_EGIS #EGIS_INC=-I./egis/errLog -I./egis/imgSrc -I./egis #EGIS_LIB=-L./egis/errLog -lerrLog -L./egis/imgSrc -limgGEN -L./egis -legis #MAKE_EGIS=egis #MAKE_EGIS_CLEAN=egis_clean # # IMPORTANT NOTE ABOUT REGEX FOR PHP_MAPSCRIPT USERS: # # In order to compile the PHP_MAPSCRIPT module, we have to make MapServer # uses the same version of the REGEX library that PHP was compiled with: # REGEX_OBJ= ../regex-0.12/regex.o REGEX_INC= -I../regex-0.12 # # Pick a compiler, etc. Flex and bison are only required if you need to modify the mapserver lexer (maplexer.l) or expression parser (mapparser.y). # MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar cr DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool CXX = $(CC) RANLIB= true LEX= flex YACC= bison XTRALIBS= -lm RUNPATHS= CFLAGS= -O2 $(IGNORE_MISSING_DATA) $(STRINGS) $(EPPL) $(PROJ) $(TTF) \ $(TIFF) $(JPEG) $(GD) $(SDE) $(OGR) $(MPATROL) $(GD_INC) $(PROJ_INC) $(TTF_INC) \ $(TIFF_INC) $(JPEG_INC) $(EGIS_INC) $(SDE_INC) $(REGEX_INC) $(MPATROL_INC) LDFLAGS= $(RUNPATHS) -L. -lmap $(GD_LIB) $(TTF_LIB) $(TIFF_LIB) $(PROJ_LIB) \ $(JPEG_LIB) $(EGIS_LIB) $(SDE_LIB) $(OGR_LIB) $(MPATROL_LIB) $(XTRALIBS) RM= /bin/rm -f OBJS= mapbits.o maphash.o mapshape.o mapxbase.o mapparser.o maplexer.o maptree.o mapsearch.o mapstring.o mapsymbol.o mapfile.o maplegend.o maputil.o mapscale.o mapquery.o maplabel.o maperror.o mapprimitive.o mapproject.o mapraster.o mapsde.o mapogr.o $(EPPL_OBJ) $(REGEX_OBJ) # # --- You shouldn't have to edit anything else. --- # .c.o: $(CC) -c $(CFLAGS) $< -o $@ all: $(MAKE_GD) $(MAKE_EGIS) $(MAKE_GDFT) libmap.a shp2img legend \ mapserv shptree shptreevis shptreetst scalebar sortshp perlvars gd:: cd gd-1.2; make; cd .. gdft:: cd gdft; make; cd .. egis:: cd egis/errLog; make; cd .. cd egis/imgSrc; make; cd .. cd egis; make; cd .. php3_mapscript:: cd mapscript/php3; make; cd ../.. maplexer.o: maplexer.c map.h mapfile.h maplexer.c: maplexer.l $(LEX) -Pmsyy -i -omaplexer.c maplexer.l mapparser.o: mapparser.c map.h mapparser.c: mapparser.y $(YACC) -p msyy -d -omapparser.c mapparser.y mapogr.o: mapogr.cpp $(CXX) -c $(CFLAGS) $(OGR_INC) mapogr.cpp -o mapogr.o lib: libmap.a libmap: libmap.a libmap.a: map.h $(OBJS) map.h $(AR) libmap.a $(OBJS) $(RANLIB) libmap.a shp2img: libmap.a shp2img.o map.h $(CC) $(CFLAGS) shp2img.o $(LDFLAGS) -o shp2img sym2img: libmap.a sym2img.o map.h $(CC) $(CFLAGS) sym2img.o $(LDFLAGS) -o sym2img legend: libmap.a legend.o map.h $(CC) $(CFLAGS) legend.o $(LDFLAGS) -o legend scalebar: libmap.a scalebar.o map.h $(CC) $(CFLAGS) scalebar.o $(LDFLAGS) -o scalebar mapserv: mapserv.h libmap.a mapserv.o cgiutil.o map.h $(CC) $(CFLAGS) mapserv.o cgiutil.o $(LDFLAGS) -o mapserv shpindex: libmap.a shpindex.o map.h $(CC) $(CFLAGS) shpindex.o $(LDFLAGS) -o shpindex shptree: libmap.a shptree.o map.h $(CC) $(CFLAGS) shptree.o $(LDFLAGS) -o shptree shptreevis: libmap.a shptreevis.o map.h $(CC) $(CFLAGS) shptreevis.o $(LDFLAGS) -o shptreevis shptreetst: libmap.a shptreetst.o map.h $(CC) $(CFLAGS) shptreetst.o $(LDFLAGS) -o shptreetst sortshp: sortshp.o $(CC) $(CFLAGS) sortshp.o $(LDFLAGS) -o sortshp perlvars: touch perlvars pwd > perlvars echo $(IGNORE_MISSING_DATA) $(STRINGS) $(EPPL) $(PROJ) $(TTF) $(TIFF) $(JPEG) $(GD) $(SDE) $(OGR) >> perlvars echo -I. $(PROJ_INC) $(GD_INC) $(TTF_INC) $(TIFF_INC) $(JPEG_INC) $(SDE_INC) $(OGR_INC) >> perlvars echo $(LDFLAGS) >> perlvars gd_clean: cd gd-1.2; make clean; cd .. gdft_clean: cd gdft; make clean; cd .. egis_clean: cd egis/errLog; make clean; cd .. cd egis/imgSrc; make clean; cd .. cd egis; make clean; cd .. php3_mapscript_clean:: cd mapscript/php3; make clean; cd ../.. clean: $(MAKE_GD_CLEAN) $(MAKE_GDFT_CLEAN) $(MAKE_EGIS_CLEAN) rm -f libmap.a *.o shp2img mapserv legend shptree shptreevis shptreetst scalebar sortshp perlvars sorta-clean: rm -f *.o ms-mingw/mapserver/build0100644000421500037440000000016407225405211015736 0ustar tpoindexsybcipscp Makefile.MinXCC ../../mapserver cd ../../mapserver make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/zlib-1.1.3/0040755000421500037440000000000007225405353014317 5ustar tpoindexsybcipsms-mingw/zlib-1.1.3/Makefile.MinXCC0100644000421500037440000001302507220422642017030 0ustar tpoindexsybcips# Makefile for zlib # Copyright (C) 1995-1998 Jean-loup Gailly. # For conditions of distribution and use, see copyright notice in zlib.h # To compile and test, type: # ./configure; make test # The call of configure is optional if you don't have special requirements # If you wish to build zlib as a shared library, use: ./configure -s # To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: # make install # To install in $HOME instead of /usr/local, use: # make install prefix=$HOME MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool CFLAGS=-O #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 #CFLAGS=-g -DDEBUG #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ # -Wstrict-prototypes -Wmissing-prototypes LDFLAGS=-L. -lz LDSHARED=$(CC) CPP=$(CC) -E VER=1.1.3 LIBS=libz.a SHAREDLIB=libz.so RANLIB=true TAR=tar SHELL=/bin/sh prefix = /usr/local exec_prefix = ${prefix} libdir = ${exec_prefix}/lib includedir = ${prefix}/include OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o OBJA = # to use the asm code: make OBJA=match.o TEST_OBJS = example.o minigzip.o DISTFILES = README FAQ INDEX ChangeLog configure Make*[a-z0-9] *.[ch] *.mms \ algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ nt/Make*[a-z0-9] nt/zlib.dnt amiga/Make*.??? os2/M*.os2 os2/zlib.def \ contrib/RE*.contrib contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \ contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/asm[56]86/*.?86 \ contrib/asm[56]86/*.S contrib/iostream/*.cpp \ contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \ contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]?? \ contrib/delphi*/*.??? all: libz.a z.dll: $(OBJS) $(DLLWRAP) --output-lib=libz.a --dllname=z.dll \ --output-def=z.def --export-all-symbols \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ $(OBJS) allold: example minigzip test: all @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ echo hello world | ./minigzip | ./minigzip -d || \ echo ' *** minigzip test FAILED ***' ; \ if ./example; then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; \ fi libz.a: $(OBJS) $(OBJA) rm -f libz.a $(AR) cr libz.a $(OBJS) $(OBJA) match.o: match.S $(CPP) match.S > _match.s $(CC) -c _match.s mv _match.o match.o rm -f _match.s $(SHAREDLIB).$(VER): $(OBJS) $(LDSHARED) -o $@ $(OBJS) rm -f $(SHAREDLIB) $(SHAREDLIB).1 ln -s $@ $(SHAREDLIB) ln -s $@ $(SHAREDLIB).1 example: example.o $(LIBS) $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) minigzip: minigzip.o $(LIBS) $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) install: $(LIBS) -@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi -@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi cp zlib.h zconf.h $(includedir) chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h cp $(LIBS) $(libdir) cd $(libdir); chmod 755 $(LIBS) -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1 cd $(libdir); if test -f $(SHAREDLIB).$(VER); then \ rm -f $(SHAREDLIB) $(SHAREDLIB).1; \ ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \ ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \ (ldconfig || true) >/dev/null 2>&1; \ fi # The ranlib in install is needed on NeXTSTEP which checks file times # ldconfig is for Linux uninstall: cd $(includedir); \ v=$(VER); \ if test -f zlib.h; then \ v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \ rm -f zlib.h zconf.h; \ fi; \ cd $(libdir); rm -f libz.a; \ if test -f $(SHAREDLIB).$$v; then \ rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \ fi clean: rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \ _match.s maketree distclean: clean zip: mv Makefile Makefile~; cp -p Makefile.in Makefile rm -f test.c ztest*.c contrib/minizip/test.zip v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ zip -ul9 zlib$$v $(DISTFILES) mv Makefile~ Makefile dist: mv Makefile Makefile~; cp -p Makefile.in Makefile rm -f test.c ztest*.c contrib/minizip/test.zip d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ rm -f $$d.tar.gz; \ if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ files=""; \ for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ cd ..; \ GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ if test ! -d $$d; then rm -f $$d; fi mv Makefile~ Makefile tags: etags *.[ch] depend: makedepend -- $(CFLAGS) -- *.[ch] # DO NOT DELETE THIS LINE -- make depend depends on it. adler32.o: zlib.h zconf.h compress.o: zlib.h zconf.h crc32.o: zlib.h zconf.h deflate.o: deflate.h zutil.h zlib.h zconf.h example.o: zlib.h zconf.h gzio.o: zutil.h zlib.h zconf.h infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h infcodes.o: zutil.h zlib.h zconf.h infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h inffast.o: zutil.h zlib.h zconf.h inftrees.h inffast.o: infblock.h infcodes.h infutil.h inffast.h inflate.o: zutil.h zlib.h zconf.h infblock.h inftrees.o: zutil.h zlib.h zconf.h inftrees.h infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h minigzip.o: zlib.h zconf.h trees.o: deflate.h zutil.h zlib.h zconf.h trees.h uncompr.o: zlib.h zconf.h zutil.o: zutil.h zlib.h zconf.h ms-mingw/zlib-1.1.3/build0100644000421500037440000000016607225405350015336 0ustar tpoindexsybcipscp Makefile.MinXCC ../../zlib-1.1.3 cd ../../zlib-1.1.3 make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/proj-4.4.2/0040755000421500037440000000000007225405220014327 5ustar tpoindexsybcipsms-mingw/proj-4.4.2/Makefile.MinXCC0100644000421500037440000000443407220430037017050 0ustar tpoindexsybcips MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool azimuthal = \ PJ_aeqd.o PJ_gnom.o PJ_laea.o PJ_mod_ster.o \ PJ_nsper.o PJ_nzmg.o PJ_ortho.o PJ_stere.o conic = \ PJ_aea.o PJ_bipc.o PJ_bonne.o PJ_eqdc.o \ PJ_imw_p.o PJ_lcc.o PJ_mpoly.o PJ_poly.o \ PJ_rpoly.o PJ_sconics.o cylinder = \ PJ_cass.o PJ_cc.o PJ_cea.o PJ_eqc.o \ PJ_gall.o PJ_labrd.o PJ_lsat.o PJ_merc.o \ PJ_mill.o PJ_ocea.o PJ_omerc.o PJ_somerc.o \ PJ_tcc.o PJ_tcea.o PJ_tmerc.o misc = \ PJ_airy.o PJ_aitoff.o PJ_august.o PJ_bacon.o \ PJ_chamb.o PJ_hammer.o PJ_lagrng.o PJ_larr.o \ PJ_lask.o PJ_nocol.o PJ_ob_tran.o PJ_oea.o \ PJ_tpeqd.o PJ_vandg.o PJ_vandg2.o PJ_vandg4.o \ PJ_wag7.o pj_latlong.o pseudo = \ PJ_boggs.o PJ_collg.o PJ_crast.o PJ_denoy.o \ PJ_eck1.o PJ_eck2.o PJ_eck3.o PJ_eck4.o \ PJ_eck5.o PJ_fahey.o PJ_fouc_s.o PJ_gins8.o \ PJ_gn_sinu.o PJ_goode.o PJ_hatano.o PJ_loxim.o \ PJ_mbt_fps.o PJ_mbtfpp.o PJ_mbtfpq.o PJ_moll.o \ PJ_nell.o PJ_nell_h.o PJ_putp2.o PJ_putp3.o \ PJ_putp4p.o PJ_putp5.o PJ_putp6.o PJ_robin.o \ PJ_sts.o PJ_urm5.o PJ_urmfps.o PJ_wag2.o \ PJ_wag3.o PJ_wink1.o PJ_wink2.o support = \ aasincos.o adjlon.o bch2bps.o bchgen.o \ biveval.o dmstor.o mk_cheby.o pj_auth.o \ pj_deriv.o pj_ell_set.o pj_ellps.o pj_errno.o \ pj_factors.o pj_fwd.o pj_init.o pj_inv.o \ pj_list.o pj_malloc.o pj_mlfn.o pj_msfn.o \ pj_open_lib.o pj_param.o pj_phi2.o pj_pr_list.o \ pj_qsfn.o pj_strerrno.o pj_tsfn.o pj_units.o \ pj_zpoly1.o rtodms.o vector1.o pj_release.o \ geocent.o pj_transform.o pj_datum_set.o pj_datums.o \ pj_apply_gridshift.o emess.o nad_cvt.o nad_init.o \ nad_intr.o LIBOBJ = $(support) $(pseudo) $(azimuthal) $(conic) $(cylinder) $(misc) EXESRC = proj.c gen_cheb.c p_series.c CFLAGS = -I. -O6 all: libproj.a proj.exe proj.dll: $(LIBOBJ) $(DLLWRAP) --output-lib=libproj.a --dllname=proj.dll \ --output-def=proj.def --export-all-symbols \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ $(LIBOBJ) -lm libproj.a: $(LIBOBJ) rm -f libproj.a $(AR) cr libproj.a $(LIBOBJ) proj.exe: $(EXESRC) libproj.a $(CC) -I. -o proj.exe -mwindows -mconsole $(EXESRC) -L. -lproj -lm clean: rm *.o *.a *.dll ms-mingw/proj-4.4.2/build0100644000421500037440000000017607225405217015360 0ustar tpoindexsybcipscp Makefile.MinXCC ../../proj-4.4.2/src cd ../../proj-4.4.2/src make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/tcl-8.3.2/0040755000421500037440000000000007225406576014161 5ustar tpoindexsybcipsms-mingw/tcl-8.3.2/build0100644000421500037440000000043507225406576015202 0ustar tpoindexsybcips# make gcc tcl stub lib # now configure and build the stub lib to .a format cd ../../tcl8.3.2/win CC=$mingwbin/${mingwxcc}gcc ./configure --enable-gcc make MINGWBIN=$mingwbin MINGWXCC=$mingwxcc AR=$mingwbin/${mingwxcc}ar \ RANLIB=$mingwbin/${mingwxcc}ranlib libtclstub83.a ms-mingw/regex-0.12/0040755000421500037440000000000007225405223014405 5ustar tpoindexsybcipsms-mingw/regex-0.12/Makefile.MinXCC0100644000421500037440000000061007220432746017124 0ustar tpoindexsybcipsMINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool CFLAGS=-O6 -DHAVE_STRING_H OBJS = regex.o all: libregex.a libregex.a: $(OBJS) rm -f libregex.a $(AR) cr libregex.a $(OBJS) clean: rm -f *.o *.a ms-mingw/regex-0.12/build0100644000421500037440000000016707225405223015430 0ustar tpoindexsybcipscp Makefile.MinXCC ../../regex-0.12 cd ../../regex-0.12 make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc ms-mingw/mapscripttcl/0040755000421500037440000000000007225410213015415 5ustar tpoindexsybcipsms-mingw/mapscripttcl/Makefile.MinXCC0100644000421500037440000000574107225410213020141 0ustar tpoindexsybcips# # Makefile.MinXCC for mapscript Tcl interface # Tom Poindexter, tpoindex@nyx.net # # The name of your C compiler: MINGWBIN = /opt/mingw/bin MINGWXCC = i386-mingw32msvc- CC = $(MINGWBIN)/$(MINGWXCC)gcc AR = $(MINGWBIN)/$(MINGWXCC)ar DLLWRAP = $(MINGWBIN)/$(MINGWXCC)dllwrap DLLTOOL = $(MINGWBIN)/$(MINGWXCC)dlltool DLTARGET = libMapscript PACKAGEDIR = MapscriptTcl1.0 TCL_PREFIX = /c/progra~1/tcl TCL_EXEC_PREFIX = $(TCL_PREFIX)/lib TCL_CC = $(CC) TCL_SHLIB_SUFFIX = .dll TCL_SHLIB_CFLAGS = -D_MSC_VER -D_WIN32 -D__WIN32__ -DWIN32 -D_WINDOWS \ -mno-cygwin TCL_LIB_SPEC = -L../../../tcl8.3.2/win -ltcl83 TCL_SHLIB_LD = $(DLLWRAP) TCL_LD_SEARCH_FLAGS = TCL_STUB_LIB_SPEC = -L../../../tcl8.3.2/win -ltclstub83 TCL_LIBS = TCL_DBGX = LIB_RUNTIME_DIR = MAPSERVERHOME = ../.. MAPSERVERDEFS = -DIGNORE_MISSING_DATA -DUSE_EPPL -DUSE_PROJ -DUSE_TTF \ -DUSE_TIF -DUSE_JPEG -DUSE_GD_1_2 MAPSERVERINCS = -I../.. -I../../../proj-4.4.2/src -I../../gd-1.2 \ -I../../gdft -I../../../freetype-1.3.1/lib \ -I../../../tiff-v3.5.5/libtiff -I../../../jpeg-6b \ -I../../../regex-0.12 MAPSERVERLIBS = -L../.. -lmap \ -L../../gdft -lgdft \ -L../../gd-1.2 -lgd \ -L../../../freetype-1.3.1/lib -lttf \ -L../../../tiff-v3.5.5/libtiff -ltiff \ -L../../../jpeg-6b -ljpeg \ -L../../../proj-4.4.2/src -lproj \ -L../../../regex-0.12 -lregex \ -lm SWIG_STUB_HACK = -DUSE_TCL_STUBS -DITCL_NAMESPACES -DItcl_Namespace=int \ -D"spaceId=ISPCID;Tcl_InitStubs(interp,\"8.1\",0)" all: stublib stublib: mapscript_wrap.o dllEntry.o mapscripttcl.def $(DLLWRAP) -s -mwindows -Wl,-e,_DllMain@12 -mno-cygwin \ --dllname=$(DLTARGET)$(TCL_SHLIB_SUFFIX) \ --def=mapscripttcl.def \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ dllEntry.o mapscript_wrap.o \ $(TCL_STUB_LIB_SPEC) $(MAPSERVERLIBS) $(TCL_LIBS) mapscript_wrap.o: mapscript_wrap.c $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) \ -I$(TCL_PREFIX)/include \ $(MAPSERVERDEFS) $(MAPSERVERINCS) \ $(SWIG_STUB_HACK) \ mapscript_wrap.c dllEntry.o: dllEntry.c $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) dllEntry.c mapscripttcl.def: dllEntry.o mapscript_wrap.o $(DLLTOOL) --export-all --exclude-symbols DllMain@12 --output-def $@ \ dllEntry.o mapscript_wrap.o nostublib: mapscripttcl.def mapscript_wrap.o dllEntry.o $(TCL_CC) -c $(TCL_DEFS) $(TCL_SHLIB_CFLAGS) \ -I$(TCL_PREFIX)/include \ $(MAPSERVERDEFS) $(MAPSERVERINCS) \ mapscript_wrap.c $(DLLWRAP) -s -mwindows -Wl,-e,_DllMain@12 -mno-cygwin \ --dllname=$(DLTARGET)$(TCL_SHLIB_SUFFIX) \ --def=mapscripttcl.def \ --dlltool=$(DLLTOOL) --driver-name=$(CC) \ dllEntry.o mapscript_wrap.o \ $(TCL_LIB_SPEC) $(MAPSERVERLIBS) $(TCL_LIBS) mapscript_wrap.c: swig -tcl8 -dnone -namespace $(MAPSERVERDEFS) $(MAPSERVERINCS) \ mapscript.i clean: rm -f *.o *.so *.dll *.a ms-mingw/mapscripttcl/dllEntry.c0100644000421500037440000000133407220672620017363 0ustar tpoindexsybcips/* * dllEntry.c -- * * This procedure provides the entry point for the dll * */ #include #if defined(_MSC_VER) || defined(__GNUC__) #define DllEntryPoint DllMain #endif /* *---------------------------------------------------------------------- * * DllEntryPoint -- * * This routine is called by gcc, VC++ or Borland to invoke the * initialization code for Tcl. * * Results: * TRUE. * * Side effects: * None. * *---------------------------------------------------------------------- */ BOOL APIENTRY DllEntryPoint ( HINSTANCE hInst, /* Library instance handle. */ DWORD reason, /* Reason this function is being called. */ LPVOID reserved) /* Not used. */ { return TRUE; } ms-mingw/mapscripttcl/build0100644000421500037440000000030107225405204016432 0ustar tpoindexsybcipscp Makefile.MinXCC ../../mapserver/mapscript/tcl cp dllEntry.c ../../mapserver/mapscript/tcl cd ../../mapserver/mapscript/tcl make -f Makefile.MinXCC MINGWBIN=$mingwbin MINGWXCC=$mingwxcc mapserver-7.4.3/mapscript/tcl/win/setup.tcl000066400000000000000000000011021357574274700207750ustar00rootroot00000000000000# install mapscript/tcl set tclhome [file dirname $tcl_library] set mslib $tclhome/MapscriptTcl1.0 if {! [file isdirectory $mslib]} { file mkdir $mslib } file copy -force libMapscript.dll $mslib file copy -force ../pkgIndex.tcl $mslib file copy -force ../mapscriptsupp.tcl $mslib catch {file copy -force ../mapscriptsupp.html $mslib} catch {file copy -force ../mapscript_wrap.html $mslib} wm title . "Mapscript/Tcl Installer" label .l -text "Mapscript/Tcl Installation is complete." button .b -text Ok -command exit pack .l .b -side top -padx 30 -pady 30 mapserver-7.4.3/mapscript/v8/000077500000000000000000000000001357574274700161155ustar00rootroot00000000000000mapserver-7.4.3/mapscript/v8/line.cpp000066400000000000000000000155201357574274700175530ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "mapserver-config.h" #ifdef USE_V8_MAPSCRIPT #include "v8_mapscript.h" using namespace v8; Persistent Line::constructor; void Line::Initialize(Handle target) { HandleScope scope; Handle c = FunctionTemplate::New(Line::New); c->InstanceTemplate()->SetInternalFieldCount(1); c->SetClassName(String::NewSymbol("lineObj")); SET_ATTRIBUTE_RO(c, "numpoints", getProp); NODE_SET_PROTOTYPE_METHOD(c, "point", getPoint); NODE_SET_PROTOTYPE_METHOD(c, "addXY", addXY); NODE_SET_PROTOTYPE_METHOD(c, "addXYZ", addXYZ); NODE_SET_PROTOTYPE_METHOD(c, "add", addPoint); target->Set(String::NewSymbol("lineObj"), c->GetFunction()); constructor.Reset(Isolate::GetCurrent(), c); } void Line::Dispose() { Line::constructor.Dispose(); Line::constructor.Clear(); } Line::~Line() { if (this->freeInternal) { msFree(this->this_->point); msFree(this->this_); } } Handle Line::Constructor() { return (*Line::constructor)->GetFunction(); } void Line::New(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args[0]->IsExternal()) { Local ext = Local::Cast(args[0]); void *ptr = ext->Value(); Line *line = static_cast(ptr); Handle self = args.Holder(); line->Wrap(self); if (line->parent_) { self->SetHiddenValue(String::New("__parent__"), line->parent_->handle()); line->disableMemoryHandler(); } } else { lineObj *l = (lineObj *)msSmallMalloc(sizeof(lineObj)); l->numpoints=0; l->point=NULL; Line *line = new Line(l); line->Wrap(args.Holder()); } } Line::Line(lineObj *l, ObjectWrap *p): ObjectWrap() { this->this_ = l; this->parent_ = p; this->freeInternal = true; } void Line::getProp(Local property, const PropertyCallbackInfo& info) { HandleScope scope; Line* l = ObjectWrap::Unwrap(info.Holder()); std::string name = TOSTR(property); Handle value = Undefined(); if (name == "numpoints") value = Integer::New(l->get()->numpoints); info.GetReturnValue().Set(value); } void Line::getPoint(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 1 || !args[0]->IsInt32()) { ThrowException(String::New("Invalid argument")); return; } Line* l = ObjectWrap::Unwrap(args.Holder()); lineObj* line = l->get(); int index = args[0]->Int32Value(); if (index < 0 || index >= line->numpoints) { ThrowException(String::New("Invalid point index.")); return; } Point *point = new Point(&line->point[index], l); Handle ext = External::New(point); args.GetReturnValue().Set(Point::Constructor()->NewInstance(1, &ext)); } void Line::addXY(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) { ThrowException(String::New("Invalid argument")); return; } Line* l = ObjectWrap::Unwrap(args.Holder()); lineObj* line = l->get(); if(line->numpoints == 0) /* new */ line->point = (pointObj *)msSmallMalloc(sizeof(pointObj)); else /* extend array */ line->point = (pointObj *)msSmallRealloc(line->point, sizeof(pointObj)*(line->numpoints+1)); line->point[line->numpoints].x = args[0]->NumberValue(); line->point[line->numpoints].y = args[1]->NumberValue(); #ifdef USE_POINT_Z_M if (args.Length() > 2 && args[2]->IsNumber()) line->point[line->numpoints].m = args[2]->NumberValue(); #endif line->numpoints++; } void Line::addXYZ(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 3 || !args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { ThrowException(String::New("Invalid argument")); return; } Line* l = ObjectWrap::Unwrap(args.Holder()); lineObj* line = l->get(); if(line->numpoints == 0) /* new */ line->point = (pointObj *)msSmallMalloc(sizeof(pointObj)); else /* extend array */ line->point = (pointObj *)msSmallRealloc(line->point, sizeof(pointObj)*(line->numpoints+1)); line->point[line->numpoints].x = args[0]->NumberValue(); line->point[line->numpoints].y = args[1]->NumberValue(); #ifdef USE_POINT_Z_M line->point[line->numpoints].z = args[2]->NumberValue(); if (args.Length() > 3 && args[3]->IsNumber()) line->point[line->numpoints].m = args[3]->NumberValue(); #endif line->numpoints++; } void Line::addPoint(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 1 || !args[0]->IsObject() || !args[0]->ToObject()->GetConstructorName()->Equals(String::New("pointObj"))) { ThrowException(String::New("Invalid argument")); return; } Line* l = ObjectWrap::Unwrap(args.Holder()); lineObj* line = l->get(); Point* p = ObjectWrap::Unwrap(args[0]->ToObject()); pointObj* point = p->get(); if(line->numpoints == 0) /* new */ line->point = (pointObj *)msSmallMalloc(sizeof(pointObj)); else /* extend array */ line->point = (pointObj *)msSmallRealloc(line->point, sizeof(pointObj)*(line->numpoints+1)); line->point[line->numpoints].x = point->x; line->point[line->numpoints].y = point->y; #ifdef USE_POINT_Z_M line->point[line->numpoints].z = point->z; if (args.Length() > 3 && args[3]->IsNumber()) line->point[line->numpoints].m = point->m; #endif line->numpoints++; } #endif mapserver-7.4.3/mapscript/v8/line.hpp000066400000000000000000000050611357574274700175570ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #ifndef LINE_H_ #define LINE_H_ #include using namespace v8; class Line: public ObjectWrap { public: static void Initialize(Handle target); static void New(const v8::FunctionCallbackInfo& args); static void Dispose(); static Handle Constructor(); Line(lineObj *l, ObjectWrap *p = NULL); ~Line(); inline lineObj* get() { return this_; } inline void disableMemoryHandler() { this->freeInternal = false; } static void getProp(Local property, const PropertyCallbackInfo& info); static void setProp(Local property, Local value, const PropertyCallbackInfo& info); static void getPoint(const v8::FunctionCallbackInfo& args); static void addXY(const v8::FunctionCallbackInfo& args); static void addXYZ(const v8::FunctionCallbackInfo& args); static void addPoint(const v8::FunctionCallbackInfo& args); private: static Persistent constructor; lineObj *this_; ObjectWrap *parent_; bool freeInternal; }; #endif mapserver-7.4.3/mapscript/v8/point.cpp000066400000000000000000000130541357574274700177550ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "mapserver-config.h" #ifdef USE_V8_MAPSCRIPT #include "v8_mapscript.h" using namespace v8; Persistent Point::constructor; void Point::Initialize(Handle target) { HandleScope scope; Handle c = FunctionTemplate::New(Point::New); c->InstanceTemplate()->SetInternalFieldCount(1); c->SetClassName(String::NewSymbol("pointObj")); SET_ATTRIBUTE(c, "x", getProp, setProp); SET_ATTRIBUTE(c, "y", getProp, setProp); #ifdef USE_POINT_Z_M SET_ATTRIBUTE(c, "z", getProp, setProp); SET_ATTRIBUTE(c, "m", getProp, setProp); #endif NODE_SET_PROTOTYPE_METHOD(c, "setXY", setXY); NODE_SET_PROTOTYPE_METHOD(c, "setXYZ", setXYZ); target->Set(String::NewSymbol("pointObj"), c->GetFunction()); constructor.Reset(Isolate::GetCurrent(), c); } void Point::Dispose() { Point::constructor.Dispose(); Point::constructor.Clear(); } Point::~Point() { if (this->freeInternal) { msFree(this->get()); } } Handle Point::Constructor() { return (*Point::constructor)->GetFunction(); } void Point::New(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args[0]->IsExternal()) { Local ext = Local::Cast(args[0]); void *ptr = ext->Value(); Point *point = static_cast(ptr); Handle self = args.Holder(); point->Wrap(self); if (point->parent_) { self->SetHiddenValue(String::New("__parent__"), point->parent_->handle()); point->disableMemoryHandler(); } } else { pointObj *p = (pointObj *)msSmallMalloc(sizeof(pointObj)); p->x = 0; p->y = 0; #ifdef USE_POINT_Z_M p->z = 0; p->m = 0; #endif Point *point = new Point(p); point->Wrap(args.Holder()); } } Point::Point(pointObj *p, ObjectWrap *pa): ObjectWrap() { this->this_ = p; this->parent_ = pa; this->freeInternal = true; } void Point::getProp(Local property, const PropertyCallbackInfo& info) { HandleScope scope; Point* p = ObjectWrap::Unwrap(info.Holder()); std::string name = TOSTR(property); Handle value = Undefined(); if (name == "x") value = Number::New(p->get()->x); else if (name == "y") value = Number::New(p->get()->y); #ifdef USE_POINT_Z_M else if (name == "z") value = Number::New(p->get()->z); else if (name == "m") value = Number::New(p->get()->m); #endif info.GetReturnValue().Set(value); } void Point::setProp(Local property, Local value, const PropertyCallbackInfo& info) { HandleScope scope; Point* p = ObjectWrap::Unwrap(info.Holder()); std::string name = TOSTR(property); if (!value->IsNumber()) ThrowException(Exception::TypeError( String::New("point value must be a number"))); if (name == "x") { p->get()->x = value->NumberValue(); } else if (name == "y") { p->get()->y = value->NumberValue(); } #ifdef USE_POINT_Z_M else if (name == "z") { p->get()->z = value->NumberValue(); } else if (name == "m") { p->get()->m = value->NumberValue(); } #endif } void Point::setXY(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsNumber()) { ThrowException(String::New("Invalid argument")); return; } Point* p = ObjectWrap::Unwrap(args.Holder()); p->get()->x = args[0]->NumberValue(); p->get()->y = args[1]->NumberValue(); } void Point::setXYZ(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 3 || !args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { ThrowException(String::New("Invalid argument")); return; } Point* p = ObjectWrap::Unwrap(args.Holder()); p->get()->x = args[0]->NumberValue(); p->get()->y = args[1]->NumberValue(); #ifdef USE_POINT_Z_M p->get()->z = args[2]->NumberValue(); if (args.Length() > 3 && args[3]->IsNumber()) { p->get()->m = args[3]->NumberValue(); } #endif } #endif mapserver-7.4.3/mapscript/v8/point.hpp000066400000000000000000000046701357574274700177660ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #ifndef POINT_H_ #define POINT_H_ #include using namespace v8; class Point: public ObjectWrap { public: static void Initialize(Handle target); static void New(const v8::FunctionCallbackInfo& args); static void Dispose(); static Handle Constructor(); Point(pointObj *p, ObjectWrap *pa = NULL); ~Point(); inline pointObj* get() { return this_; } inline void disableMemoryHandler() { this->freeInternal = false; } static void getProp(Local property, const PropertyCallbackInfo& info); static void setProp(Local property, Local value, const PropertyCallbackInfo& info); static void setXY(const v8::FunctionCallbackInfo& args); static void setXYZ(const v8::FunctionCallbackInfo& args); private: static Persistent constructor; pointObj *this_; ObjectWrap *parent_; bool freeInternal; }; #endif mapserver-7.4.3/mapscript/v8/shape.cpp000066400000000000000000000260701357574274700177260ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "mapserver-config.h" #ifdef USE_V8_MAPSCRIPT #include "v8_mapscript.h" #include using namespace v8; using std::map; using std::string; Persistent Shape::constructor; void Shape::Initialize(Handle target) { HandleScope scope; Handle c = FunctionTemplate::New(Shape::New); c->InstanceTemplate()->SetInternalFieldCount(1); c->SetClassName(String::NewSymbol("shapeObj")); SET_ATTRIBUTE_RO(c, "numvalues", getProp); SET_ATTRIBUTE_RO(c, "numlines", getProp); SET_ATTRIBUTE_RO(c, "index", getProp); SET_ATTRIBUTE_RO(c, "type", getProp); SET_ATTRIBUTE_RO(c, "tileindex", getProp); SET_ATTRIBUTE_RO(c, "classindex", getProp); SET_ATTRIBUTE(c, "text", getProp, setProp); NODE_SET_PROTOTYPE_METHOD(c, "clone", clone); NODE_SET_PROTOTYPE_METHOD(c, "line", getLine); NODE_SET_PROTOTYPE_METHOD(c, "add", addLine); NODE_SET_PROTOTYPE_METHOD(c, "setGeometry", setGeometry); NODE_DEFINE_CONSTANT(c->GetFunction(), "Point",MS_SHAPE_POINT); NODE_DEFINE_CONSTANT(c->GetFunction(), "Line",MS_SHAPE_LINE); NODE_DEFINE_CONSTANT(c->GetFunction(), "Polygon",MS_SHAPE_POLYGON); NODE_DEFINE_CONSTANT(c->GetFunction(), "Null",MS_SHAPE_NULL); target->Set(String::NewSymbol("shapeObj"), c->GetFunction()); constructor.Reset(Isolate::GetCurrent(), c); } void Shape::Dispose() { Shape::constructor.Dispose(); Shape::constructor.Clear(); } Shape::~Shape() { /* this is set to false if the shapeObj is owned by mapserver and not v8 */ if (freeInternal) { msFreeShape(this->get()); msFree(this->get()); } } Handle Shape::Constructor() { return (*Shape::constructor)->GetFunction(); } void Shape::New(const v8::FunctionCallbackInfo& args) { HandleScope scope; Handle self = args.Holder(); Shape *shape; if (args[0]->IsExternal()) { Local ext = Local::Cast(args[0]); void *ptr = ext->Value(); shape = static_cast(ptr); shape->Wrap(args.Holder()); } else { shapeObj *s = (shapeObj *)msSmallMalloc(sizeof(shapeObj)); msInitShape(s); if(args.Length() >= 1) { s->type = args[0]->Int32Value(); } else { s->type = MS_SHAPE_NULL; } shape = new Shape(s); shape->Wrap(self); } /* create the attribute template. should use ObjectWrap in future */ Handle attributes_templ = ObjectTemplate::New(); attributes_templ->SetInternalFieldCount(2); attributes_templ->SetNamedPropertyHandler(attributeGetValue, attributeSetValue); Handle attributes = attributes_templ->NewInstance(); map *attributes_map = new map(); attributes->SetInternalField(0, External::New(attributes_map)); attributes->SetInternalField(1, External::New(shape->get()->values)); attributes->SetHiddenValue(String::New("__parent__"), self); if (shape->layer) { for (int i=0; ilayer->numitems; ++i) { (*attributes_map)[string(shape->layer->items[i])] = i; } } Persistent pattributes; pattributes.Reset(Isolate::GetCurrent(), attributes); pattributes.MakeWeak(attributes_map, attributeWeakCallback); pattributes.MarkIndependent(); self->Set(String::New("attributes"), attributes); } Shape::Shape(shapeObj *s): ObjectWrap() { this->this_ = s; this->layer = NULL; this->freeInternal = true; } void Shape::getProp(Local property, const PropertyCallbackInfo& info) { HandleScope scope; Shape* s = ObjectWrap::Unwrap(info.Holder()); std::string name = TOSTR(property); Handle value = Undefined(); if (name == "numvalues") value = Integer::New(s->get()->numvalues); else if (name == "numlines") value = Integer::New(s->get()->numlines); else if (name == "index") value = Number::New(s->get()->index); else if (name == "type") value = Integer::New(s->get()->type); else if (name == "tileindex") value = Integer::New(s->get()->tileindex); else if (name == "classindex") value = Integer::New(s->get()->classindex); else if (name == "text") value = String::New(s->get()->text); info.GetReturnValue().Set(value); } void Shape::setProp(Local property, Local value, const PropertyCallbackInfo& info) { HandleScope scope; Shape* s = ObjectWrap::Unwrap(info.Holder()); std::string name = TOSTR(property); if (name == "text") { if (s->get()->text) msFree(s->get()->text); s->get()->text = getStringValue(value); } } void Shape::clone(const v8::FunctionCallbackInfo& args) { HandleScope scope; Shape* s = ObjectWrap::Unwrap(args.Holder()); shapeObj *shape = s->get(); shapeObj *new_shape = (shapeObj *)msSmallMalloc(sizeof(shapeObj)); msInitShape(new_shape); msCopyShape(shape, new_shape); Shape *ns = new Shape(new_shape); Handle ext = External::New(ns); Handle clone = Shape::Constructor()->NewInstance(1, &ext); /* we need this to copy shape attributes */ Handle self = s->handle(); Handle self_attributes = self->Get(String::New("attributes"))->ToObject(); Local wrap = Local::Cast(self_attributes->GetInternalField(0)); void *ptr = wrap->Value(); map *self_attributes_map = static_cast *>(ptr); Handle clone_attributes = clone->Get(String::New("attributes"))->ToObject(); wrap = Local::Cast(clone_attributes->GetInternalField(0)); ptr = wrap->Value(); map *clone_attributes_map = static_cast *>(ptr); clone_attributes_map->insert(self_attributes_map->begin(), self_attributes_map->end()); args.GetReturnValue().Set(clone); } void Shape::getLine(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 1 || !args[0]->IsInt32()) { ThrowException(String::New("Invalid argument")); return; } int index = args[0]->Int32Value(); Shape* s = ObjectWrap::Unwrap(args.Holder()); shapeObj *shape = s->get(); if (index < 0 || index >= shape->numlines) { ThrowException(String::New("Invalid line index.")); return; } Line *line = new Line(&shape->line[index], s); Handle ext = External::New(line); args.GetReturnValue().Set(Line::Constructor()->NewInstance(1, &ext)); } void Shape::addLine(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 1 || !args[0]->IsObject() || !args[0]->ToObject()->GetConstructorName()->Equals(String::New("lineObj"))) { ThrowException(String::New("Invalid argument")); return; } Shape* s = ObjectWrap::Unwrap(args.Holder()); shapeObj *shape = s->get(); Line* l = ObjectWrap::Unwrap(args[0]->ToObject()); lineObj *line = l->get(); msAddLine(shape, line); } void Shape::setGeometry(const v8::FunctionCallbackInfo& args) { HandleScope scope; if (args.Length() < 1 || !args[0]->IsObject() || !args[0]->ToObject()->GetConstructorName()->Equals(String::New("shapeObj"))) { ThrowException(String::New("Invalid argument")); return; } Shape* s = ObjectWrap::Unwrap(args.Holder()); shapeObj *shape = s->get(); Shape* ns = ObjectWrap::Unwrap(args[0]->ToObject()); shapeObj *new_shape = ns->get(); /* clean current shape */ for (int i = 0; i < shape->numlines; i++) { free(shape->line[i].point); } if (shape->line) free(shape->line); shape->line = NULL; shape->numlines = 0; for (int i = 0; i < new_shape->numlines; i++) { msAddLine(shape, &(new_shape->line[i])); } return; } void Shape::attributeWeakCallback(v8::Isolate* isolate, v8::Persistent* pobj, map *map) { v8::HandleScope scope(isolate); pobj->Dispose(); pobj->Clear(); delete map; } void Shape::attributeGetValue(Local name, const PropertyCallbackInfo &info) { Local self = info.Holder(); Local wrap = Local::Cast(self->GetInternalField(0)); void *ptr = wrap->Value(); map *indexes = static_cast *>(ptr); wrap = Local::Cast(self->GetInternalField(1)); ptr = wrap->Value(); char **values = static_cast(ptr); String::Utf8Value utf8_value(name); string key = string(*utf8_value); map::iterator iter = indexes->find(key); if (iter != indexes->end()) { const int &index = (*iter).second; info.GetReturnValue().Set(String::New(values[index])); } } void Shape::attributeSetValue(Local name, Local value, const PropertyCallbackInfo &info) { Local self = info.Holder(); Local wrap = Local::Cast(self->GetInternalField(0)); void *ptr = wrap->Value(); map *indexes = static_cast *>(ptr); wrap = Local::Cast(self->GetInternalField(1)); ptr = wrap->Value(); char **values = static_cast(ptr); String::Utf8Value utf8_name(name), utf8_value(value); string key = string(*utf8_name); map::iterator iter = indexes->find(key); if (iter == indexes->end()) { ThrowException(String::New("Invalid value name.")); } else { const int &index = (*iter).second; msFree(values[index]); values[index] = msStrdup(*utf8_value); } } #endif mapserver-7.4.3/mapscript/v8/shape.hpp000066400000000000000000000066431357574274700177370ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #ifndef SHAPE_H_ #define SHAPE_H_ #include #include #include using namespace v8; using std::map; using std::string; class Shape: public ObjectWrap { public: static void Initialize(Handle target); static void New(const v8::FunctionCallbackInfo& args); static void Dispose(); static Handle Constructor(); Shape(shapeObj *p); ~Shape(); inline shapeObj* get() { return this_; } inline void disableMemoryHandler() { this->freeInternal = false; } inline void setLayer(layerObj *layer) { this->layer = layer; }; static void getProp(Local property, const PropertyCallbackInfo& info); static void setProp(Local property, Local value, const PropertyCallbackInfo& info); static void clone(const v8::FunctionCallbackInfo& args); static void getLine(const v8::FunctionCallbackInfo& args); static void addLine(const v8::FunctionCallbackInfo& args); static void setGeometry(const v8::FunctionCallbackInfo& args); /* This could be generic in the future.. */ static void attributeWeakCallback(v8::Isolate* isolate, v8::Persistent* pobj, map *map); static void attributeGetValue(Local name, const PropertyCallbackInfo &info); static void attributeSetValue(Local name, Local value, const PropertyCallbackInfo &info); static void attributeMapDestroy(Isolate *isolate, Persistent *object, map *map); private: static Persistent constructor; bool freeInternal; layerObj *layer; /* for attributes names */ shapeObj *this_; }; #endif mapserver-7.4.3/mapscript/v8/v8_mapscript.cpp000066400000000000000000000036001357574274700212370ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "mapserver-config.h" #ifdef USE_V8_MAPSCRIPT #include "mapserver.h" #include "v8_mapscript.h" char* getStringValue(Local value, const char *fallback) { if (value->IsString()) { String::AsciiValue string(value); char *str = (char *) malloc(string.length() + 1); strcpy(str, *string); return str; } char *str = (char *) malloc(strlen(fallback) + 1); strcpy(str, fallback); return str; } #endif mapserver-7.4.3/mapscript/v8/v8_mapscript.h000066400000000000000000000076121357574274700207130ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #ifndef V8_MAPSCRIPT_H #define V8_MAPSCRIPT_H #include "mapserver-config.h" #ifdef USE_V8_MAPSCRIPT /* This need should be removed in future v8 version */ #define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR 1 #define V8_USE_UNSAFE_HANDLES 1 #include "mapserver.h" #include #include #include #include #include "v8_object_wrap.hpp" #include "point.hpp" #include "line.hpp" #include "shape.hpp" using namespace v8; using std::string; using std::stack; using std::map; class V8Context { public: V8Context(Isolate *isolate) : isolate(isolate) {} Isolate *isolate; stack paths; /* for relative paths and the require function */ map > scripts; Persistent context; layerObj *layer; /* current layer, used in geomtransform */ }; #define V8CONTEXT(map) ((V8Context*) (map)->v8context) inline void NODE_SET_PROTOTYPE_METHOD(v8::Handle recv, const char* name, v8::FunctionCallback callback) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handle_scope(isolate); v8::Local t = v8::FunctionTemplate::New(callback); recv->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, name), t->GetFunction()); } #define NODE_SET_PROTOTYPE_METHOD NODE_SET_PROTOTYPE_METHOD #define TOSTR(obj) (*String::Utf8Value((obj)->ToString())) #define SET(target, name, value) \ (target)->PrototypeTemplate()->Set(String::NewSymbol(name), value); #define SET_ATTRIBUTE(t, name, get, set) \ t->InstanceTemplate()->SetAccessor(String::NewSymbol(name), get, set) #define SET_ATTRIBUTE_RO(t, name, get) \ t->InstanceTemplate()->SetAccessor( \ String::NewSymbol(name), \ get, 0, \ Handle(), \ DEFAULT, \ static_cast( \ ReadOnly|DontDelete)) #define NODE_DEFINE_CONSTANT(target, name, constant) \ (target)->Set(String::NewSymbol(name), \ Integer::New(constant), \ static_cast( \ ReadOnly|DontDelete)); char* getStringValue(Local value, const char *fallback=""); #endif #endif mapserver-7.4.3/mapscript/v8/v8_object_wrap.hpp000066400000000000000000000074621357574274700215530ustar00rootroot00000000000000// Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef V8_OBJECT_WRAP_H_ #define V8_OBJECT_WRAP_H_ #include "v8.h" #include class ObjectWrap { public: ObjectWrap() { refs_ = 0; } virtual ~ObjectWrap() { if (persistent().IsEmpty()) return; assert(persistent().IsNearDeath()); persistent().ClearWeak(); persistent().Dispose(); } template static inline T* Unwrap(v8::Handle handle) { assert(!handle.IsEmpty()); assert(handle->InternalFieldCount() > 0); // Cast to ObjectWrap before casting to T. A direct cast from void // to T won't work right when T has more than one base class. void* ptr = handle->GetAlignedPointerFromInternalField(0); ObjectWrap* wrap = static_cast(ptr); return static_cast(wrap); } inline v8::Local handle() { return handle(v8::Isolate::GetCurrent()); } inline v8::Local handle(v8::Isolate* isolate) { return v8::Local::New(isolate, persistent()); } inline v8::Persistent& persistent() { return handle_; } protected: inline void Wrap(v8::Handle handle) { assert(persistent().IsEmpty()); assert(handle->InternalFieldCount() > 0); handle->SetAlignedPointerInInternalField(0, this); persistent().Reset(v8::Isolate::GetCurrent(), handle); MakeWeak(); } inline void MakeWeak(void) { persistent().MakeWeak(this, WeakCallback); persistent().MarkIndependent(); } /* Ref() marks the object as being attached to an event loop. * Refed objects will not be garbage collected, even if * all references are lost. */ virtual void Ref() { assert(!persistent().IsEmpty()); persistent().ClearWeak(); refs_++; } /* Unref() marks an object as detached from the event loop. This is its * default state. When an object with a "weak" reference changes from * attached to detached state it will be freed. Be careful not to access * the object after making this call as it might be gone! * (A "weak reference" means an object that only has a * persistant handle.) * * DO NOT CALL THIS FROM DESTRUCTOR */ virtual void Unref() { assert(!persistent().IsEmpty()); assert(!persistent().IsWeak()); assert(refs_ > 0); if (--refs_ == 0) MakeWeak(); } int refs_; // ro private: static void WeakCallback(v8::Isolate* isolate, v8::Persistent* pobj, ObjectWrap* wrap) { v8::HandleScope scope(isolate); assert(wrap->refs_ == 0); assert(*pobj == wrap->persistent()); assert((*pobj).IsNearDeath()); delete wrap; } v8::Persistent handle_; }; #endif // v8_OBJECT_WRAP_H_ mapserver-7.4.3/mapsearch.c000066400000000000000000000545631357574274700157020ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Various geospatial search operations. * Author: Steve Lime and the MapServer team. * * Notes: For information on point in polygon function please see: * * http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html * * The appropriate copyright notice accompanies the funtion definition. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #define LASTVERT(v,n) ((v) == 0 ? n-2 : v-1) #define NEXTVERT(v,n) ((v) == n-2 ? 0 : v+1) /* ** Returns MS_TRUE if rectangles a and b overlap */ int msRectOverlap(const rectObj *a, const rectObj *b) { if(a->minx > b->maxx) return(MS_FALSE); if(a->maxx < b->minx) return(MS_FALSE); if(a->miny > b->maxy) return(MS_FALSE); if(a->maxy < b->miny) return(MS_FALSE); return(MS_TRUE); } /* ** Computes the intersection of two rectangles, updating the first ** to be only the intersection of the two. Returns MS_FALSE if ** the intersection is empty. */ int msRectIntersect( rectObj *a, const rectObj *b ) { if( a->maxx > b->maxx ) a->maxx = b->maxx; if( a->minx < b->minx ) a->minx = b->minx; if( a->maxy > b->maxy ) a->maxy = b->maxy; if( a->miny < b->miny ) a->miny = b->miny; if( a->maxx < a->minx || b->maxx < b->minx ) return MS_FALSE; else return MS_TRUE; } /* ** Returns MS_TRUE if rectangle a is contained in rectangle b */ int msRectContained(const rectObj *a, const rectObj *b) { if(a->minx >= b->minx && a->maxx <= b->maxx) if(a->miny >= b->miny && a->maxy <= b->maxy) return(MS_TRUE); return(MS_FALSE); } /* ** Merges rect b into rect a. Rect a changes, b does not. */ void msMergeRect(rectObj *a, rectObj *b) { a->minx = MS_MIN(a->minx, b->minx); a->maxx = MS_MAX(a->maxx, b->maxx); a->miny = MS_MIN(a->miny, b->miny); a->maxy = MS_MAX(a->maxy, b->maxy); } int msPointInRect(const pointObj *p, const rectObj *rect) { if(p->x < rect->minx) return(MS_FALSE); if(p->x > rect->maxx) return(MS_FALSE); if(p->y < rect->miny) return(MS_FALSE); if(p->y > rect->maxy) return(MS_FALSE); return(MS_TRUE); } int msPolygonDirection(lineObj *c) { double mx, my, area; int i, v=0, lv, nv; /* first find lowest, rightmost point of polygon */ mx = c->point[0].x; my = c->point[0].y; for(i=0; inumpoints-1; i++) { if((c->point[i].y < my) || ((c->point[i].y == my) && (c->point[i].x > mx))) { v = i; mx = c->point[i].x; my = c->point[i].y; } } lv = LASTVERT(v,c->numpoints); nv = NEXTVERT(v,c->numpoints); area = c->point[lv].x*c->point[v].y - c->point[lv].y*c->point[v].x + c->point[lv].y*c->point[nv].x - c->point[lv].x*c->point[nv].y + c->point[v].x*c->point[nv].y - c->point[nv].x*c->point[v].y; if(area > 0) return(1); /* counter clockwise orientation */ else if(area < 0) /* clockwise orientation */ return(-1); else return(0); /* shouldn't happen unless the polygon is self intersecting */ } /* ** Copyright (c) 1970-2003, Wm. Randolph Franklin ** ** Permission is hereby granted, free of charge, to any person obtaining a copy of this software and ** associated documentation files (the "Software"), to deal in the Software without restriction, including ** without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ** copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the ** following conditions: ** ** 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the ** following disclaimers. ** 2. Redistributions in binary form must reproduce the above copyright notice in the documentation and/or ** other materials provided with the distribution. ** 3. The name of W. Randolph Franklin may not be used to endorse or promote products derived from this ** Software without specific prior written permission. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT ** LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN ** NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ int msPointInPolygon(pointObj *p, lineObj *c) { int i, j, status = MS_FALSE; for (i = 0, j = c->numpoints-1; i < c->numpoints; j = i++) { if ((((c->point[i].y<=p->y) && (p->ypoint[j].y)) || ((c->point[j].y<=p->y) && (p->ypoint[i].y))) && (p->x < (c->point[j].x - c->point[i].x) * (p->y - c->point[i].y) / (c->point[j].y - c->point[i].y) + c->point[i].x)) status = !status; } return status; } /* ** Note: the following functions are brute force implementations. Some fancy ** computational geometry algorithms would speed things up nicely in many ** cases. In due time... -SDL- */ int msIntersectSegments(const pointObj *a, const pointObj *b, const pointObj *c, const pointObj *d) /* from comp.graphics.alogorithms FAQ */ { double r, s; double denominator, numerator; numerator = ((a->y-c->y)*(d->x-c->x) - (a->x-c->x)*(d->y-c->y)); denominator = ((b->x-a->x)*(d->y-c->y) - (b->y-a->y)*(d->x-c->x)); if((denominator == 0) && (numerator == 0)) { /* lines are coincident, intersection is a line segement if it exists */ if(a->y == c->y) { /* coincident horizontally, check x's */ if(((a->x >= MS_MIN(c->x,d->x)) && (a->x <= MS_MAX(c->x,d->x))) || ((b->x >= MS_MIN(c->x,d->x)) && (b->x <= MS_MAX(c->x,d->x)))) return(MS_TRUE); else return(MS_FALSE); } else { /* test for y's will work fine for remaining cases */ if(((a->y >= MS_MIN(c->y,d->y)) && (a->y <= MS_MAX(c->y,d->y))) || ((b->y >= MS_MIN(c->y,d->y)) && (b->y <= MS_MAX(c->y,d->y)))) return(MS_TRUE); else return(MS_FALSE); } } if(denominator == 0) /* lines are parallel, can't intersect */ return(MS_FALSE); r = numerator/denominator; if((r<0) || (r>1)) return(MS_FALSE); /* no intersection */ numerator = ((a->y-c->y)*(b->x-a->x) - (a->x-c->x)*(b->y-a->y)); s = numerator/denominator; if((s<0) || (s>1)) return(MS_FALSE); /* no intersection */ return(MS_TRUE); } /* ** Instead of using ring orientation we count the number of parts the ** point falls in. If odd the point is in the polygon, if 0 or even ** then the point is in a hole or completely outside. */ int msIntersectPointPolygon(pointObj *point, shapeObj *poly) { int i; int status=MS_FALSE; for(i=0; inumlines; i++) { if(msPointInPolygon(point, &poly->line[i]) == MS_TRUE) /* ok, the point is in a line */ status = !status; } return(status); } int msIntersectMultipointPolygon(shapeObj *multipoint, shapeObj *poly) { int i,j; /* The change to loop through all the lines has been made for ticket * #2443 but is no more needed since ticket #2762. PostGIS now put all * points into a single line. */ for(i=0; inumlines; i++ ) { lineObj points = multipoint->line[i]; for(j=0; jnumlines; c1++) for(v1=1; v1line[c1].numpoints; v1++) for(c2=0; c2numlines; c2++) for(v2=1; v2line[c2].numpoints; v2++) if(msIntersectSegments(&(line1->line[c1].point[v1-1]), &(line1->line[c1].point[v1]), &(line2->line[c2].point[v2-1]), &(line2->line[c2].point[v2])) == MS_TRUE) return(MS_TRUE); return(MS_FALSE); } int msIntersectPolylinePolygon(shapeObj *line, shapeObj *poly) { int i; /* STEP 1: polygon might competely contain the polyline or one of it's parts (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(line->line[i].point[0]), poly) == MS_TRUE) /* this considers holes and multiple parts */ return(MS_TRUE); } /* STEP 2: look for intersecting line segments */ if (msIntersectPolylines(line, poly) == MS_TRUE) return (MS_TRUE); return(MS_FALSE); } int msIntersectPolygons(shapeObj *p1, shapeObj *p2) { int i; /* STEP 1: polygon 1 completely contains 2 (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(p2->line[i].point[0]), p1) == MS_TRUE) /* this considers holes and multiple parts */ return(MS_TRUE); } /* STEP 2: polygon 2 completely contains 1 (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(p1->line[i].point[0]), p2) == MS_TRUE) /* this considers holes and multiple parts */ return(MS_TRUE); } /* STEP 3: look for intersecting line segments */ if (msIntersectPolylines(p1, p2) == MS_TRUE) return(MS_TRUE); /* ** At this point we know there are are no intersections between edges. There may be other tests necessary ** but I haven't run into any cases that require them. */ return(MS_FALSE); } /* ** Distance computations */ double msDistancePointToPoint(pointObj *a, pointObj *b) { double d; d = sqrt(msSquareDistancePointToPoint(a, b)); return(d); } /* ** Quickly compute the square of the distance; avoids expensive sqrt() call on each invocation */ double msSquareDistancePointToPoint(pointObj *a, pointObj *b) { double dx, dy; dx = a->x - b->x; dy = a->y - b->y; return(dx*dx + dy*dy); } double msDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b) { return (sqrt(msSquareDistancePointToSegment(p, a, b))); } double msSquareDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b) { double l_squared; /* squared length of line ab */ double r,s; l_squared = msSquareDistancePointToPoint(a,b); if(l_squared == 0.0) /* a = b */ return(msSquareDistancePointToPoint(a,p)); r = ((a->y - p->y)*(a->y - b->y) - (a->x - p->x)*(b->x - a->x))/(l_squared); if(r > 1) /* perpendicular projection of P is on the forward extention of AB */ return(MS_MIN(msSquareDistancePointToPoint(p, b),msSquareDistancePointToPoint(p, a))); if(r < 0) /* perpendicular projection of P is on the backward extention of AB */ return(MS_MIN(msSquareDistancePointToPoint(p, b),msSquareDistancePointToPoint(p, a))); s = ((a->y - p->y)*(b->x - a->x) - (a->x - p->x)*(b->y - a->y))/l_squared; return(fabs(s*s*l_squared)); } #define SMALL_NUMBER 0.00000001 #define dot(u,v) ((u).x *(v).x + (u).y *(v).y) /* vector dot product */ #define norm(v) sqrt(dot(v,v)) #define slope(a,b) (((a)->y - (b)->y)/((a)->x - (b)->x)) /* Segment to segment distance code is a modified version of that found at: */ /* */ /* http://www.geometryalgorithms.com/Archive/algorithm_0106/algorithm_0106.htm */ /* */ /* Copyright 2001, softSurfer (www.softsurfer.com) */ /* This code may be freely used and modified for any purpose */ /* providing that this copyright notice is included with it. */ /* SoftSurfer makes no warranty for this code, and cannot be held */ /* liable for any real or imagined damage resulting from its use. */ /* Users of this code must verify correctness for their application. */ double msDistanceSegmentToSegment(pointObj *pa, pointObj *pb, pointObj *pc, pointObj *pd) { vectorObj dP; vectorObj u, v, w; double a, b, c, d, e; double D; double sc, sN, sD; /* N=numerator, D=demoninator */ double tc, tN, tD; /* check for strictly parallel segments first */ /* if(((pa->x == pb->x) && (pc->x == pd->x)) || (slope(pa,pb) == slope(pc,pd))) { // vertical (infinite slope) || otherwise parallel */ /* D = msDistancePointToSegment(pa, pc, pd); */ /* D = MS_MIN(D, msDistancePointToSegment(pb, pc, pd)); */ /* D = MS_MIN(D, msDistancePointToSegment(pc, pa, pb)); */ /* return(MS_MIN(D, msDistancePointToSegment(pd, pa, pb))); */ /* } */ u.x = pb->x - pa->x; /* u = pb - pa */ u.y = pb->y - pa->y; v.x = pd->x - pc->x; /* v = pd - pc */ v.y = pd->y - pc->y; w.x = pa->x - pc->x; /* w = pa - pc */ w.y = pa->y - pc->y; a = dot(u,u); b = dot(u,v); c = dot(v,v); d = dot(u,w); e = dot(v,w); D = a*c - b*b; sc = sN = sD = D; tc = tN = tD = D; /* compute the line parameters of the two closest points */ if(D < SMALL_NUMBER) { /* lines are parallel or almost parallel */ sN = 0.0; sD = 1.0; tN = e; tD = c; } else { /* get the closest points on the infinite lines */ sN = b*e - c*d; tN = a*e - b*d; if(sN < 0) { sN = 0.0; tN = e; tD = c; } else if(sN > sD) { sN = sD; tN = e + b; tD = c; } } if(tN < 0) { tN = 0.0; if(-d < 0) sN = 0.0; else if(-d > a) sN = sD; else { sN = -d; sD = a; } } else if(tN > tD) { tN = tD; if((-d + b) < 0) sN = 0.0; else if((-d + b) > a) sN = sD; else { sN = (-d + b); sD = a; } } /* finally do the division to get sc and tc */ sc = sN/sD; tc = tN/tD; dP.x = w.x + (sc*u.x) - (tc*v.x); dP.y = w.y + (sc*u.y) - (tc*v.y); return(norm(dP)); } double msDistancePointToShape(pointObj *point, shapeObj *shape) { double d; d = msSquareDistancePointToShape(point, shape); return(sqrt(d)); } /* ** As msDistancePointToShape; avoid expensive sqrt calls */ double msSquareDistancePointToShape(pointObj *point, shapeObj *shape) { int i, j; double dist, minDist=-1; switch(shape->type) { case(MS_SHAPE_POINT): for(j=0; jnumlines; j++) { for(i=0; iline[j].numpoints; i++) { dist = msSquareDistancePointToPoint(point, &(shape->line[j].point[i])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } break; case(MS_SHAPE_LINE): for(j=0; jnumlines; j++) { for(i=1; iline[j].numpoints; i++) { dist = msSquareDistancePointToSegment(point, &(shape->line[j].point[i-1]), &(shape->line[j].point[i])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } break; case(MS_SHAPE_POLYGON): if(msIntersectPointPolygon(point, shape)) minDist = 0; /* point is IN the shape */ else { /* treat shape just like a line */ for(j=0; jnumlines; j++) { for(i=1; iline[j].numpoints; i++) { dist = msSquareDistancePointToSegment(point, &(shape->line[j].point[i-1]), &(shape->line[j].point[i])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } break; default: break; } return(minDist); } double msDistanceShapeToShape(shapeObj *shape1, shapeObj *shape2) { int i,j,k,l; double dist, minDist=-1; switch(shape1->type) { case(MS_SHAPE_POINT): /* shape1 */ for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { dist = msSquareDistancePointToShape(&(shape1->line[i].point[j]), shape2); if((dist < minDist) || (minDist < 0)) minDist = dist; } } minDist = sqrt(minDist); break; case(MS_SHAPE_LINE): /* shape1 */ switch(shape2->type) { case(MS_SHAPE_POINT): for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { dist = msSquareDistancePointToShape(&(shape2->line[i].point[j]), shape1); if((dist < minDist) || (minDist < 0)) minDist = dist; } } minDist = sqrt(minDist); break; case(MS_SHAPE_LINE): for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { for(k=0; knumlines; k++) { for(l=1; lline[k].numpoints; l++) { /* check intersection (i.e. dist=0) */ if(msIntersectSegments(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])) == MS_TRUE) return(0); /* no intersection, compute distance */ dist = msDistanceSegmentToSegment(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } } break; case(MS_SHAPE_POLYGON): /* shape2 (the polygon) could contain shape1 or one of it's parts */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(shape1->line[0].point[0]), shape2) == MS_TRUE) /* this considers holes and multiple parts */ return(0); } /* check segment intersection and, if necessary, distance between segments */ for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { for(k=0; knumlines; k++) { for(l=1; lline[k].numpoints; l++) { /* check intersection (i.e. dist=0) */ if(msIntersectSegments(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])) == MS_TRUE) return(0); /* no intersection, compute distance */ dist = msDistanceSegmentToSegment(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } } break; } break; case(MS_SHAPE_POLYGON): /* shape1 */ switch(shape2->type) { case(MS_SHAPE_POINT): for(i=0; inumlines; i++) { for(j=0; jline[i].numpoints; j++) { dist = msSquareDistancePointToShape(&(shape2->line[i].point[j]), shape1); if((dist < minDist) || (minDist < 0)) minDist = dist; } } minDist = sqrt(minDist); break; case(MS_SHAPE_LINE): /* shape1 (the polygon) could contain shape2 or one of it's parts */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(shape2->line[i].point[0]), shape1) == MS_TRUE) /* this considers holes and multiple parts */ return(0); } /* check segment intersection and, if necessary, distance between segments */ for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { for(k=0; knumlines; k++) { for(l=1; lline[k].numpoints; l++) { /* check intersection (i.e. dist=0) */ if(msIntersectSegments(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])) == MS_TRUE) return(0); /* no intersection, compute distance */ dist = msDistanceSegmentToSegment(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } } break; case(MS_SHAPE_POLYGON): /* shape1 completely contains shape2 (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(shape2->line[i].point[0]), shape1) == MS_TRUE) /* this considers holes and multiple parts */ return(0); } /* shape2 completely contains shape1 (only need to check one point from each part) */ for(i=0; inumlines; i++) { if(msIntersectPointPolygon(&(shape1->line[i].point[0]), shape2) == MS_TRUE) /* this considers holes and multiple parts */ return(0); } /* check segment intersection and, if necessary, distance between segments */ for(i=0; inumlines; i++) { for(j=1; jline[i].numpoints; j++) { for(k=0; knumlines; k++) { for(l=1; lline[k].numpoints; l++) { /* check intersection (i.e. dist=0) */ if(msIntersectSegments(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])) == MS_TRUE) return(0); /* no intersection, compute distance */ dist = msDistanceSegmentToSegment(&(shape1->line[i].point[j-1]), &(shape1->line[i].point[j]), &(shape2->line[k].point[l-1]), &(shape2->line[k].point[l])); if((dist < minDist) || (minDist < 0)) minDist = dist; } } } } break; } break; } return(minDist); } mapserver-7.4.3/mapserv.c000066400000000000000000000263521357574274700154070ustar00rootroot00000000000000/****************************************************************************** * $id: mapserv.c 9470 2009-10-16 16:09:31Z sdlime $ * * Project: MapServer * Purpose: MapServer CGI mainline. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver-config.h" #ifdef USE_FASTCGI #define NO_FCGI_DEFINES #include "fcgi_stdio.h" #endif #include "mapserv.h" #include "mapio.h" #include "maptime.h" #ifndef WIN32 #include #endif /************************************************************************/ /* FastCGI cleanup functions. */ /************************************************************************/ #ifndef WIN32 void msCleanupOnSignal( int nInData ) { /* For some reason, the fastcgi message code does not seem to work */ /* from within the signal handler on Unix. So we force output through */ /* normal stdio functions. */ msIO_installHandlers( NULL, NULL, NULL ); #ifndef NDEBUG msIO_fprintf( stderr, "In msCleanupOnSignal.\n" ); #endif msCleanup(); exit(0); } #endif #ifdef WIN32 void msCleanupOnExit( void ) { /* note that stderr and stdout seem to be non-functional in the */ /* fastcgi/win32 case. If you really want to check functioning do */ /* some sort of hack logging like below ... otherwise just trust it! */ #ifdef notdef FILE *fp_out = fopen( "D:\\temp\\mapserv.log", "w" ); fprintf( fp_out, "In msCleanupOnExit\n" ); fclose( fp_out ); #endif msCleanup(1); } #endif #ifdef USE_FASTCGI /************************************************************************/ /* msIO_fcgiRead() */ /* */ /* This is the default implementation via stdio. */ /************************************************************************/ static int msIO_fcgiRead( void *cbData, void *data, int byteCount ) { return FCGI_fread( data, 1, byteCount, (FCGI_FILE *) cbData ); } /************************************************************************/ /* msIO_fcgiWrite() */ /* */ /* This is the default implementation via stdio. */ /************************************************************************/ static int msIO_fcgiWrite( void *cbData, void *data, int byteCount ) { return FCGI_fwrite( data, 1, byteCount, (FCGI_FILE *) cbData ); } /************************************************************************/ /* msIO_installFastCGIRedirect() */ /************************************************************************/ static int msIO_installFastCGIRedirect() { msIOContext stdin_ctx, stdout_ctx, stderr_ctx; stdin_ctx.label = "fcgi"; stdin_ctx.write_channel = MS_FALSE; stdin_ctx.readWriteFunc = msIO_fcgiRead; stdin_ctx.cbData = (void *) FCGI_stdin; stdout_ctx.label = "fcgi"; stdout_ctx.write_channel = MS_TRUE; stdout_ctx.readWriteFunc = msIO_fcgiWrite; stdout_ctx.cbData = (void *) FCGI_stdout; stderr_ctx.label = "fcgi"; stderr_ctx.write_channel = MS_TRUE; stderr_ctx.readWriteFunc = msIO_fcgiWrite; stderr_ctx.cbData = (void *) FCGI_stderr; msIO_installHandlers( &stdin_ctx, &stdout_ctx, &stderr_ctx ); return MS_TRUE; } #endif /************************************************************************/ /* main() */ /************************************************************************/ int main(int argc, char *argv[]) { int iArg; int sendheaders = MS_TRUE; struct mstimeval execstarttime, execendtime; struct mstimeval requeststarttime, requestendtime; mapservObj* mapserv = NULL; /* -------------------------------------------------------------------- */ /* Initialize mapserver. This sets up threads, GD and GEOS as */ /* well as using MS_ERRORFILE and MS_DEBUGLEVEL env vars if set. */ /* -------------------------------------------------------------------- */ if( msSetup() != MS_SUCCESS ) { msCGIWriteError(mapserv); msCleanup(); exit(0); } if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&execstarttime, NULL); /* -------------------------------------------------------------------- */ /* Process arguments. In normal use as a cgi-bin there are no */ /* commandline switches, but we provide a few for test/debug */ /* purposes, and to query the version info. */ /* -------------------------------------------------------------------- */ for( iArg = 1; iArg < argc; iArg++ ) { /* Keep only "-v", "-nh" and "QUERY_STRING=..." enabled by default. * The others will require an explicit -DMS_ENABLE_CGI_CL_DEBUG_ARGS * at compile time. Do *NOT* enable them since they can cause security * problems : https://github.com/mapserver/mapserver/issues/3485 */ if( strcmp(argv[iArg],"-v") == 0 ) { printf("%s\n", msGetVersion()); fflush(stdout); exit(0); } else if(strcmp(argv[iArg], "-nh") == 0) { sendheaders = MS_FALSE; msIO_setHeaderEnabled( MS_FALSE ); } else if( strncmp(argv[iArg], "QUERY_STRING=", 13) == 0 ) { /* Debugging hook... pass "QUERY_STRING=..." on the command-line */ putenv( "REQUEST_METHOD=GET" ); putenv( argv[iArg] ); } else if (strcmp(argv[iArg], "--h") == 0 || strcmp(argv[iArg], "--help") == 0) { printf("Usage: mapserv [--help] [-v] [-nh] [QUERY_STRING=value]\n"); #ifdef MS_ENABLE_CGI_CL_DEBUG_ARGS printf(" [-tmpbase dirname] [-t mapfilename] [MS_ERRORFILE=value] [MS_DEBUGLEVEL=value]\n"); #endif printf("\n"); printf("Options :\n"); printf(" -h, --help Display this help message.\n"); printf(" -v Display version and exit.\n"); printf(" -nh Suppress HTTP headers in CGI mode.\n"); printf(" QUERY_STRING=value Set the QUERY_STRING in GET request mode.\n"); #ifdef MS_ENABLE_CGI_CL_DEBUG_ARGS printf(" -tmpbase dirname Define a forced temporary directory.\n"); printf(" -t mapfilename Display the tokens of the mapfile after parsing.\n"); printf(" MS_ERRORFILE=filename Set error file.\n"); printf(" MS_DEBUGLEVEL=value Set debug level.\n"); #endif exit(0); } #ifdef MS_ENABLE_CGI_CL_DEBUG_ARGS else if( iArg < argc-1 && strcmp(argv[iArg], "-tmpbase") == 0) { msForceTmpFileBase( argv[++iArg] ); } else if( iArg < argc-1 && strcmp(argv[iArg], "-t") == 0) { char **tokens; int numtokens=0; if((tokens=msTokenizeMap(argv[iArg+1], &numtokens)) != NULL) { int i; for(i=0; imap && mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&requestendtime, NULL); msDebug("mapserv request processing time (msLoadMap not incl.): %.3fs\n", (requestendtime.tv_sec+requestendtime.tv_usec/1.0e6)- (requeststarttime.tv_sec+requeststarttime.tv_usec/1.0e6) ); } msCGIWriteLog(mapserv,MS_FALSE); msFreeMapServObj(mapserv); #ifdef USE_FASTCGI /* FCGI_ --- return to top of loop */ msResetErrorList(); continue; } /* end fastcgi loop */ #endif /* normal case, processing is complete */ if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&execendtime, NULL); msDebug("mapserv total execution time: %.3fs\n", (execendtime.tv_sec+execendtime.tv_usec/1.0e6)- (execstarttime.tv_sec+execstarttime.tv_usec/1.0e6) ); } msCleanup(); #ifdef _WIN32 /* flush pending writes to stdout */ fflush(stdout); #endif exit( 0 ); } mapserver-7.4.3/mapserv.h000066400000000000000000000052161357574274700154100ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Declarations supporting mapserv.c. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPSERV_H #define MAPSERV_H #if defined(_WIN32) && !defined(__CYGWIN__) #include #endif #include #include #include "maptemplate.h" #include "maptile.h" #include "cgiutil.h" /* ** Defines */ #define NUMEXP "[-]?(([0-9]+)|([0-9]*[.][0-9]+)([eE][-+]?[0-9]+)?)" #define EXTENT_PADDING .05 /* ** Macros */ #define TEMPLATE_TYPE(s) (((strncmp("http://", s, 7) == 0) || (strncmp("https://", s, 8) == 0) || (strncmp("ftp://", s, 6)) == 0) ? MS_URL : MS_FILE) MS_DLL_EXPORT int msCGIWriteLog(mapservObj *mapserv, int show_error); MS_DLL_EXPORT void msCGIWriteError(mapservObj *mapserv); MS_DLL_EXPORT mapObj *msCGILoadMap(mapservObj *mapserv); int msCGISetMode(mapservObj *mapserv); int msCGILoadForm(mapservObj *mapserv); int msCGIDispatchBrowseRequest(mapservObj *mapserv); int msCGIDispatchCoordinateRequest(mapservObj *mapserv); int msCGIDispatchQueryRequest(mapservObj *mapserv); int msCGIDispatchImageRequest(mapservObj *mapserv); int msCGIDispatchLegendRequest(mapservObj *mapserv); int msCGIDispatchLegendIconRequest(mapservObj *mapserv); MS_DLL_EXPORT int msCGIDispatchRequest(mapservObj *mapserv); #endif /* MAPSERV_H */ mapserver-7.4.3/mapserver-api.c000066400000000000000000000007331357574274700165000ustar00rootroot00000000000000#include "mapserver.h" mapObj* umnms_new_map(char *filename) { mapObj *map = NULL; if(filename) { map = msLoadMap(filename,NULL); } else { map = (mapObj *)msSmallCalloc(sizeof(mapObj),1); if(initMap(map) == -1) { free(map); return NULL; } } return map; } layerObj* umnms_new_layer(mapObj *map); classObj* umnms_new_class(layerObj *layer); styleObj* umnms_new_style(classObj *theclass); labelObj* umnms_new_label(classObj *theclass); mapserver-7.4.3/mapserver-api.h000066400000000000000000000013371357574274700165060ustar00rootroot00000000000000/* * File: mapserver-api.h * Author: tbonfort * * Created on March 14, 2013, 1:12 PM */ #ifndef MAPSERVER_API_H #define MAPSERVER_API_H #include "mapserver-version.h" #ifdef __cplusplus extern "C" { #endif typedef struct mapObj mapObj; typedef struct layerObj layerObj; typedef struct classObj classObj; typedef struct styleObj styleObj; typedef struct labelObj labelObj; typedef struct symbolObj symbolObj; typedef struct imageObj imageObj; mapObj* umnms_new_map(char *filename); layerObj* umnms_new_layer(mapObj *map); classObj* umnms_new_class(layerObj *layer); styleObj* umnms_new_style(classObj *theclass); labelObj* umnms_new_label(classObj *theclass); #ifdef __cplusplus } #endif #endif /* MAPSERVER_API_H */ mapserver-7.4.3/mapserver-config-version.cmake.in000066400000000000000000000006041357574274700221170ustar00rootroot00000000000000set(PACKAGE_VERSION "@MapServer_VERSION_STRING@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") set(PACKAGE_VERSION_EXACT TRUE) endif() endif() mapserver-7.4.3/mapserver-config.cmake.in000066400000000000000000000014471357574274700204420ustar00rootroot00000000000000# - Config file for the mapserver package # It defines the following variables # MAPSERVER_INCLUDE_DIRS - include directories for mapserver # MAPSERVER_LIBRARIES - libraries to link against # MAPSERVER_EXECUTABLES - executables build for mapserver # Compute paths get_filename_component(MAPSERVER_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) set(MAPSERVER_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") # Our library dependencies (contains definitions for IMPORTED targets) if(NOT TARGET mapserver AND NOT MapServer_BINARY_DIR) include("${MAPSERVER_CMAKE_DIR}/mapserverTargets.cmake") endif() # These are IMPORTED targets created by mapserverTargets.cmake set(MAPSERVER_LIBRARIES mapserver) set(MAPSERVER_EXECUTABLES sortshp shptree shptreevis msencrypt legend scalebar tile4ms shptreetst shp2img mapserv) mapserver-7.4.3/mapserver-config.h.in000066400000000000000000000030701357574274700176030ustar00rootroot00000000000000#ifndef _MAPSERVER_CONFIG_H #define _MAPSERVER_CONFIG_H #cmakedefine USE_PROJ 1 #cmakedefine USE_PBF 1 #cmakedefine USE_POSTGIS 1 #cmakedefine USE_GDAL 1 #cmakedefine USE_PIXMAN 1 #cmakedefine USE_OGR 1 #cmakedefine USE_WMS_SVR 1 #cmakedefine USE_WCS_SVR 1 #cmakedefine USE_WFS_SVR 1 #cmakedefine USE_SOS_SVR 1 #cmakedefine USE_WFS_LYR 1 #cmakedefine USE_WMS_LYR 1 #cmakedefine USE_CURL 1 #cmakedefine USE_CAIRO 1 #cmakedefine USE_GEOS 1 #cmakedefine USE_GIF 1 #cmakedefine USE_JPEG 1 #cmakedefine USE_PNG 1 #cmakedefine USE_ICONV 1 #cmakedefine USE_FRIBIDI 1 #cmakedefine USE_HARFBUZZ 1 #cmakedefine USE_LIBXML2 1 #cmakedefine USE_FASTCGI 1 #cmakedefine USE_MYSQL 1 #cmakedefine USE_THREAD 1 #cmakedefine USE_KML 1 #cmakedefine USE_POINT_Z_M 1 #cmakedefine USE_ORACLESPATIAL 1 #cmakedefine USE_EXEMPI 1 #cmakedefine USE_XMLMAPFILE 1 #cmakedefine USE_GENERIC_MS_NINT 1 #cmakedefine POSTGIS_HAS_SERVER_VERSION 1 #cmakedefine USE_SVG_CAIRO 1 #cmakedefine USE_RSVG 1 #cmakedefine USE_SDE 1 #cmakedefine SDE64 1 #cmakedefine USE_EXTENDED_DEBUG 1 #cmakedefine USE_V8_MAPSCRIPT 1 /*windows specific hacks*/ #if defined(_WIN32) #cmakedefine REGEX_MALLOC 1 #cmakedefine USE_GENERIC_MS_NINT 1 #endif #cmakedefine HAVE_STRRSTR 1 #cmakedefine HAVE_STRCASECMP 1 #cmakedefine HAVE_STRCASESTR 1 #cmakedefine HAVE_STRDUP 1 #cmakedefine HAVE_STRLCAT 1 #cmakedefine HAVE_STRLCPY 1 #cmakedefine HAVE_STRLEN 1 #cmakedefine HAVE_STRNCASECMP 1 #cmakedefine HAVE_VSNPRINTF 1 #cmakedefine HAVE_DLFCN_H 1 #cmakedefine HAVE_LRINTF 1 #cmakedefine HAVE_LRINT 1 #cmakedefine HAVE_SYNC_FETCH_AND_ADD 1 #endif mapserver-7.4.3/mapserver-version.h.in000066400000000000000000000004771357574274700200330ustar00rootroot00000000000000#ifndef _MAPSERVER_VERSION_H #define _MAPSERVER_VERSION_H #define MS_VERSION_MAJOR @MapServer_VERSION_MAJOR@ #define MS_VERSION_MINOR @MapServer_VERSION_MINOR@ #define MS_VERSION_REV @MapServer_VERSION_REVISION@ #define MS_VERSION "@MapServer_VERSION_STRING@" #define MS_VERSION_NUM @MapServer_VERSION_NUM@ #endif mapserver-7.4.3/mapserver.h000066400000000000000000003773311357574274700157510ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Primary MapServer include file. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #ifndef MAP_H #define MAP_H #include "mapserver-config.h" /* ** Main includes. If a particular header was needed by several .c files then ** I just put it here. What the hell, it works and it's all right here. -SDL- */ #if defined(HAVE_STRCASESTR) && !defined(_GNU_SOURCE) #define _GNU_SOURCE /* Required for strcasestr() defn */ #endif #include #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #include #include #else #include #endif #if defined(_WIN32) && !defined(__CYGWIN__) # define MS_DLL_EXPORT __declspec(dllexport) #define USE_MSFREE #else #define MS_DLL_EXPORT #endif #if defined(__GNUC__) #define WARN_UNUSED __attribute__((warn_unused_result)) #define LIKELY(x) __builtin_expect((x),1) #define UNLIKELY(x) __builtin_expect((x),0) #else #define WARN_UNUSED #define LIKELY(x) (x) #define UNLIKELY(x) (x) #endif /* definition of ms_int32/ms_uint32 */ #include #ifndef _WIN32 #include #endif #ifdef _WIN32 #ifndef SIZE_MAX #ifdef _WIN64 #define SIZE_MAX _UI64_MAX #else #define SIZE_MAX UINT_MAX #endif #endif #endif #if ULONG_MAX == 0xffffffff typedef long ms_int32; typedef unsigned long ms_uint32; #elif UINT_MAX == 0xffffffff typedef int ms_int32; typedef unsigned int ms_uint32; #else typedef int32_t ms_int32; typedef uint32_t ms_uint32; #endif #if defined(_WIN32) && !defined(__CYGWIN__) /* Need to use _vsnprintf() with VS2003 */ #define vsnprintf _vsnprintf #endif #include "mapserver-api.h" #ifndef SWIG /*forward declaration of rendering object*/ typedef struct rendererVTableObj rendererVTableObj; typedef struct tileCacheObj tileCacheObj; typedef struct textPathObj textPathObj; typedef struct textRunObj textRunObj; typedef struct glyph_element glyph_element; typedef struct face_element face_element; #endif /* ms_bitarray is used by the bit mask in mapbit.c */ typedef ms_uint32 * ms_bitarray; typedef const ms_uint32 *ms_const_bitarray; #include "maperror.h" #include "mapprimitive.h" #include "mapshape.h" #include "mapsymbol.h" #include "maptree.h" /* quadtree spatial index */ #include "maphash.h" #include "mapio.h" #include #include "mapproject.h" #include "cgiutil.h" #include /* regular expression support */ /* The regex lib from the system and the regex lib from PHP needs to * be separated here. We separate here via its directory location. */ #include "mapregex.h" #ifdef USE_OGR #define CPL_SUPRESS_CPLUSPLUS #include "ogr_api.h" #endif /* EQUAL and EQUALN are defined in cpl_port.h, so add them in here if ogr was not included */ #ifndef EQUAL #if defined(WIN32) || defined(WIN32CE) # define EQUAL(a,b) (stricmp(a,b)==0) #else # define EQUAL(a,b) (strcasecmp(a,b)==0) #endif #endif #ifndef EQUALN #if defined(WIN32) || defined(WIN32CE) # define EQUALN(a,b,n) (strnicmp(a,b,n)==0) #else # define EQUALN(a,b,n) (strncasecmp(a,b,n)==0) #endif #endif #if defined(_WIN32) && !defined(__CYGWIN__) #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || !defined(_MSC_VER) #define snprintf _snprintf #endif #endif #ifdef __cplusplus extern "C" { #endif // hide from swig or ruby will choke on the __FUNCTION__ name #ifndef SWIG /* Memory allocation check utility */ #ifndef __FUNCTION__ # define __FUNCTION__ "MapServer" #endif #endif #define MS_CHECK_ALLOC(var, size, retval) \ if (!var) { \ msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", __FUNCTION__, \ __FILE__, __LINE__, (unsigned int)(size)); \ return retval; \ } #define MS_CHECK_ALLOC_NO_RET(var, size) \ if (!var) { \ msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", __FUNCTION__, \ __FILE__, __LINE__, (unsigned int)(size)); \ return; \ } /* General defines, wrapable */ #define MS_TRUE 1 /* logical control variables */ #define MS_FALSE 0 #define MS_UNKNOWN -1 #define MS_ON 1 #define MS_OFF 0 #define MS_DEFAULT 2 #define MS_EMBED 3 #define MS_DELETE 4 #define MS_YES 1 #define MS_NO 0 /* Number of layer, class and style ptrs to alloc at once in the corresponding msGrow...() functions. Replaces former MS_MAXLAYERS, MS_MAXCLASSES and MS_MAXSTYLES with dynamic allocation (see RFC-17). */ #define MS_LAYER_ALLOCSIZE 64 #define MS_CLASS_ALLOCSIZE 8 #define MS_STYLE_ALLOCSIZE 4 #define MS_LABEL_ALLOCSIZE 2 /* not too common */ #define MS_MAX_LABEL_PRIORITY 10 #define MS_MAX_LABEL_FONTS 5 #define MS_DEFAULT_LABEL_PRIORITY 1 #define MS_LABEL_FORCE_GROUP 2 /* other values are MS_ON/MS_OFF */ /* General defines, not wrapable */ #ifndef SWIG #ifdef USE_XMLMAPFILE #define MS_DEFAULT_MAPFILE_PATTERN "\\.(map|xml)$" #define MS_DEFAULT_XMLMAPFILE_PATTERN "\\.xml$" #else #define MS_DEFAULT_MAPFILE_PATTERN "\\.map$" #endif #define MS_TEMPLATE_MAGIC_STRING "MapServer Template" #define MS_TEMPLATE_EXPR "\\.(xml|wml|html|htm|svg|kml|gml|js|tmpl)$" #define MS_INDEX_EXTENSION ".qix" #define MS_QUERY_RESULTS_MAGIC_STRING "MapServer Query Results" #define MS_QUERY_PARAMS_MAGIC_STRING "MapServer Query Params" #define MS_QUERY_EXTENSION ".qy" #define MS_DEG_TO_RAD .0174532925199432958 #define MS_RAD_TO_DEG 57.29577951 #define MS_DEFAULT_RESOLUTION 72 #define MS_RED 0 #define MS_GREEN 1 #define MS_BLUE 2 #define MS_MAXCOLORS 256 #define MS_MISSING_DATA_IGNORE 0 #define MS_MISSING_DATA_FAIL 1 #define MS_MISSING_DATA_LOG 2 #define MS_BUFFER_LENGTH 2048 /* maximum input line length */ #define MS_URL_LENGTH 1024 #define MS_MAXPATHLEN 1024 #define MS_MAXIMAGESIZE_DEFAULT 4096 #define MS_MAXPROJARGS 20 #define MS_MAXJOINS 20 #define MS_ITEMNAMELEN 32 #define MS_NAMELEN 20 #define MS_MINSYMBOLSIZE 0 /* in pixels */ #define MS_MAXSYMBOLSIZE 500 #define MS_MINSYMBOLWIDTH 0 /* in pixels */ #define MS_MAXSYMBOLWIDTH 32 #define MS_URL 0 /* template types */ #define MS_FILE 1 #define MS_MINFONTSIZE 4 #define MS_MAXFONTSIZE 256 #define MS_LABELCACHEINITSIZE 100 #define MS_LABELCACHEINCREMENT 10 #define MS_RESULTCACHEINITSIZE 10 #define MS_RESULTCACHEINCREMENT 10 #define MS_FEATUREINITSIZE 10 /* how many points initially can a feature have */ #define MS_FEATUREINCREMENT 10 #define MS_EXPRESSION 2000 /* todo: make this an enum */ #define MS_REGEX 2001 #define MS_STRING 2002 #define MS_NUMBER 2003 #define MS_COMMENT 2004 #define MS_IREGEX 2005 #define MS_ISTRING 2006 #define MS_BINDING 2007 #define MS_LIST 2008 /* string split flags */ #define MS_HONOURSTRINGS 0x0001 #define MS_ALLOWEMPTYTOKENS 0x0002 #define MS_PRESERVEQUOTES 0x0004 #define MS_PRESERVEESCAPES 0x0008 #define MS_STRIPLEADSPACES 0x0010 #define MS_STRIPENDSPACES 0x0020 /* boolean options for the expression object. */ #define MS_EXP_INSENSITIVE 1 /* General macro definitions */ #define MS_MIN(a,b) (((a)<(b))?(a):(b)) #define MS_MAX(a,b) (((a)>(b))?(a):(b)) #define MS_ABS(a) (((a)<0) ? -(a) : (a)) #define MS_SGN(a) (((a)<0) ? -1 : 1) #define MS_STRING_IS_NULL_OR_EMPTY(s) ((!s || s[0] == '\0') ? MS_TRUE:MS_FALSE) #define MS_NINT_GENERIC(x) ((x) >= 0.0 ? ((long) ((x)+.5)) : ((long) ((x)-.5))) #ifdef _MSC_VER #define msIsNan(x) _isnan(x) #else #define msIsNan(x) isnan(x) #endif /* see http://mega-nerd.com/FPcast/ for some discussion of fast conversion to nearest int. We avoid lrint() for now because it would be hard to include math.h "properly". */ #if defined(HAVE_LRINT) && !defined(USE_GENERIC_MS_NINT) # define MS_NINT(x) lrint(x) /*# define MS_NINT(x) lround(x) */ /* note that lrint rounds .5 to the nearest *even* integer, i.e. lrint(0.5)=0,lrint(1.5)=2 */ #elif defined(_MSC_VER) && defined(_WIN32) && !defined(USE_GENERIC_MS_NINT) static __inline long int MS_NINT (double flt) { int intgr; _asm { fld flt fistp intgr } ; return intgr ; } #elif defined(i386) && defined(__GNUC_PREREQ) && !defined(USE_GENERIC_MS_NINT) static __inline long int MS_NINT( double __x ) { long int __lrintres; __asm__ __volatile__ ("fistpl %0" : "=m" (__lrintres) : "t" (__x) : "st"); return __lrintres; } #else # define MS_NINT(x) MS_NINT_GENERIC(x) #endif /* #define MS_VALID_EXTENT(minx, miny, maxx, maxy) (((minxmimetype ? format->mimetype : "unknown") #define MS_IMAGE_EXTENSION(format) (format->extension ? format->extension : "unknown") #define MS_DRIVER_SWF(format) (strncasecmp((format)->driver,"swf",3)==0) #define MS_DRIVER_GDAL(format) (strncasecmp((format)->driver,"gdal/",5)==0) #define MS_DRIVER_IMAGEMAP(format) (strncasecmp((format)->driver,"imagemap",8)==0) #define MS_DRIVER_AGG(format) (strncasecmp((format)->driver,"agg/",4)==0) #define MS_DRIVER_MVT(format) (strncasecmp((format)->driver,"mvt",3)==0) #define MS_DRIVER_CAIRO(format) (strncasecmp((format)->driver,"cairo/",6)==0) #define MS_DRIVER_OGL(format) (strncasecmp((format)->driver,"ogl/",4)==0) #define MS_DRIVER_TEMPLATE(format) (strncasecmp((format)->driver,"template",8)==0) #endif /*SWIG*/ #define MS_RENDER_WITH_SWF 2 #define MS_RENDER_WITH_RAWDATA 3 #define MS_RENDER_WITH_IMAGEMAP 5 #define MS_RENDER_WITH_TEMPLATE 8 /* query results only */ #define MS_RENDER_WITH_OGR 16 #define MS_RENDER_WITH_PLUGIN 100 #define MS_RENDER_WITH_CAIRO_RASTER 101 #define MS_RENDER_WITH_CAIRO_PDF 102 #define MS_RENDER_WITH_CAIRO_SVG 103 #define MS_RENDER_WITH_OGL 104 #define MS_RENDER_WITH_AGG 105 #define MS_RENDER_WITH_KML 106 #define MS_RENDER_WITH_UTFGRID 107 #define MS_RENDER_WITH_MVT 108 #ifndef SWIG #define MS_RENDERER_SWF(format) ((format)->renderer == MS_RENDER_WITH_SWF) #define MS_RENDERER_RAWDATA(format) ((format)->renderer == MS_RENDER_WITH_RAWDATA) #define MS_RENDERER_IMAGEMAP(format) ((format)->renderer == MS_RENDER_WITH_IMAGEMAP) #define MS_RENDERER_TEMPLATE(format) ((format)->renderer == MS_RENDER_WITH_TEMPLATE) #define MS_RENDERER_KML(format) ((format)->renderer == MS_RENDER_WITH_KML) #define MS_RENDERER_OGR(format) ((format)->renderer == MS_RENDER_WITH_OGR) #define MS_RENDERER_MVT(format) ((format)->renderer == MS_RENDER_WITH_MVT) #define MS_RENDERER_PLUGIN(format) ((format)->renderer > MS_RENDER_WITH_PLUGIN) #define MS_CELLSIZE(min,max,d) (((max) - (min))/((d)-1)) /* where min/max are from an MapServer pixel center-to-pixel center extent */ #define MS_OWS_CELLSIZE(min,max,d) (((max) - (min))/(d)) /* where min/max are from an OGC pixel outside edge-to-pixel outside edge extent */ #define MS_MAP2IMAGE_X(x,minx,cx) (MS_NINT(((x) - (minx))/(cx))) #define MS_MAP2IMAGE_Y(y,maxy,cy) (MS_NINT(((maxy) - (y))/(cy))) #define MS_IMAGE2MAP_X(x,minx,cx) ((minx) + (cx)*(x)) #define MS_IMAGE2MAP_Y(y,maxy,cy) ((maxy) - (cy)*(y)) /* these versions of MS_MAP2IMAGE takes 1/cellsize and is much faster */ #define MS_MAP2IMAGE_X_IC(x,minx,icx) (MS_NINT(((x) - (minx))*(icx))) #define MS_MAP2IMAGE_Y_IC(y,maxy,icy) (MS_NINT(((maxy) - (y))*(icy))) #define MS_MAP2IMAGE_XCELL_IC(x,minx,icx) ((int)(((x) - (minx))*(icx))) #define MS_MAP2IMAGE_YCELL_IC(y,maxy,icy) ((int)(((maxy) - (y))*(icy))) #define MS_MAP2IMAGE_X_IC_DBL(x,minx,icx) (((x) - (minx))*(icx)) #define MS_MAP2IMAGE_Y_IC_DBL(y,maxy,icy) (((maxy) - (y))*(icy)) #define MS_MAP2IMAGE_X_IC_SNAP(x,minx,icx,res) ((MS_NINT(((x) - (minx))*(icx)*(res)))/(res)) #define MS_MAP2IMAGE_Y_IC_SNAP(y,maxy,icy,res) ((MS_NINT(((maxy) - (y))*(icy)*(res)))/(res)) /* For CARTO symbols */ #define MS_PI 3.14159265358979323846 #define MS_PI2 1.57079632679489661923 /* (MS_PI / 2) */ #define MS_3PI2 4.71238898038468985769 /* (3 * MS_PI2) */ #define MS_2PI 6.28318530717958647693 /* (2 * MS_PI) */ #define MS_ENCRYPTION_KEY_SIZE 16 /* Key size: 128 bits = 16 bytes */ #define GET_LAYER(map, pos) map->layers[pos] #define GET_CLASS(map, lid, cid) map->layers[lid]->class[cid] #ifdef USE_THREAD #if defined(HAVE_SYNC_FETCH_AND_ADD) #define MS_REFCNT_INCR(obj) __sync_fetch_and_add(&obj->refcount, +1) #define MS_REFCNT_DECR(obj) __sync_sub_and_fetch(&obj->refcount, +1) #define MS_REFCNT_INIT(obj) obj->refcount=1, __sync_synchronize() #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) #pragma intrinsic (_InterlockedExchangeAdd) #if defined(_MSC_VER) && (_MSC_VER <= 1200) #define MS_REFCNT_INCR(obj) ( _InterlockedExchangeAdd((long*)(&obj->refcount), (long)(+1)) +1 ) #define MS_REFCNT_DECR(obj) ( _InterlockedExchangeAdd((long*)(&obj->refcount), (long)(-1)) -1 ) #define MS_REFCNT_INIT(obj) obj->refcount=1 #else #define MS_REFCNT_INCR(obj) ( _InterlockedExchangeAdd((volatile long*)(&obj->refcount), (long)(+1)) +1 ) #define MS_REFCNT_DECR(obj) ( _InterlockedExchangeAdd((volatile long*)(&obj->refcount), (long)(-1)) -1 ) #define MS_REFCNT_INIT(obj) obj->refcount=1 #endif #elif defined(__MINGW32__) && defined(__i386__) #define MS_REFCNT_INCR(obj) ( InterlockedExchangeAdd((long*)(&obj->refcount), (long)(+1)) +1 ) #define MS_REFCNT_DECR(obj) ( InterlockedExchangeAdd((long*)(&obj->refcount), (long)(-1)) -1 ) #define MS_REFCNT_INIT(obj) obj->refcount=1 #else // unsafe fallback #define MS_REFCNT_INCR(obj) obj->refcount++ #define MS_REFCNT_DECR(obj) (--(obj->refcount)) #define MS_REFCNT_INIT(obj) obj->refcount=1 #endif // close if defined(_MSC.. #else /*USE_THREAD*/ #define MS_REFCNT_INCR(obj) obj->refcount++ #define MS_REFCNT_DECR(obj) (--(obj->refcount)) #define MS_REFCNT_INIT(obj) obj->refcount=1 #endif /*USE_THREAD*/ #define MS_REFCNT_DECR_IS_NOT_ZERO(obj) (MS_REFCNT_DECR(obj))>0 #define MS_REFCNT_DECR_IS_ZERO(obj) (MS_REFCNT_DECR(obj))<=0 #define MS_IS_VALID_ARRAY_INDEX(index, size) ((index<0 || index>=size)?MS_FALSE:MS_TRUE) #define MS_CONVERT_UNIT(src_unit, dst_unit, value) (value * msInchesPerUnit(src_unit,0) / msInchesPerUnit(dst_unit,0)) #define MS_INIT_INVALID_RECT { -1e300, -1e300, 1e300, 1e300 } #endif /* General enumerated types - needed by scripts */ enum MS_FILE_TYPE {MS_FILE_MAP, MS_FILE_SYMBOL}; enum MS_UNITS {MS_INCHES, MS_FEET, MS_MILES, MS_METERS, MS_KILOMETERS, MS_DD, MS_PIXELS, MS_PERCENTAGES, MS_NAUTICALMILES}; enum MS_SHAPE_TYPE {MS_SHAPE_POINT, MS_SHAPE_LINE, MS_SHAPE_POLYGON, MS_SHAPE_NULL}; enum MS_LAYER_TYPE {MS_LAYER_POINT, MS_LAYER_LINE, MS_LAYER_POLYGON, MS_LAYER_RASTER, MS_LAYER_ANNOTATION /* only used for parser backwards compatibility */, MS_LAYER_QUERY, MS_LAYER_CIRCLE, MS_LAYER_TILEINDEX, MS_LAYER_CHART}; enum MS_FONT_TYPE {MS_TRUETYPE, MS_BITMAP}; #define MS_POSITIONS_LENGTH 14 enum MS_POSITIONS_ENUM {MS_UL=101, MS_LR, MS_UR, MS_LL, MS_CR, MS_CL, MS_UC, MS_LC, MS_CC, MS_AUTO, MS_XY, MS_NONE, MS_AUTO2,MS_FOLLOW}; #define MS_TINY 5 #define MS_SMALL 7 #define MS_MEDIUM 10 #define MS_LARGE 13 #define MS_GIANT 16 enum MS_QUERYMAP_STYLES {MS_NORMAL, MS_HILITE, MS_SELECTED}; enum MS_CONNECTION_TYPE {MS_INLINE, MS_SHAPEFILE, MS_TILED_SHAPEFILE, MS_UNUSED_2, MS_OGR, MS_UNUSED_1, MS_POSTGIS, MS_WMS, MS_ORACLESPATIAL, MS_WFS, MS_GRATICULE, MS_MYSQL, MS_RASTER, MS_PLUGIN, MS_UNION, MS_UVRASTER, MS_CONTOUR, MS_KERNELDENSITY }; #define IS_THIRDPARTY_LAYER_CONNECTIONTYPE(type) ((type) == MS_UNION || (type) == MS_KERNELDENSITY) enum MS_JOIN_CONNECTION_TYPE {MS_DB_XBASE, MS_DB_CSV, MS_DB_MYSQL, MS_DB_ORACLE, MS_DB_POSTGRES}; enum MS_JOIN_TYPE {MS_JOIN_ONE_TO_ONE, MS_JOIN_ONE_TO_MANY}; #define MS_SINGLE 0 /* modes for searching (spatial/database) */ #define MS_MULTIPLE 1 enum MS_QUERY_MODE {MS_QUERY_SINGLE, MS_QUERY_MULTIPLE}; enum MS_QUERY_TYPE {MS_QUERY_IS_NULL, MS_QUERY_BY_POINT, MS_QUERY_BY_RECT, MS_QUERY_BY_SHAPE, MS_QUERY_BY_ATTRIBUTE, MS_QUERY_BY_INDEX, MS_QUERY_BY_FILTER}; enum MS_ALIGN_VALUE {MS_ALIGN_DEFAULT, MS_ALIGN_LEFT, MS_ALIGN_CENTER, MS_ALIGN_RIGHT}; enum MS_CAPS_JOINS_AND_CORNERS {MS_CJC_NONE, MS_CJC_BEVEL, MS_CJC_BUTT, MS_CJC_MITER, MS_CJC_ROUND, MS_CJC_SQUARE, MS_CJC_TRIANGLE}; #define MS_CJC_DEFAULT_CAPS MS_CJC_ROUND #define MS_CJC_DEFAULT_JOINS MS_CJC_NONE #define MS_CJC_DEFAULT_JOIN_MAXSIZE 3 enum MS_RETURN_VALUE {MS_SUCCESS, MS_FAILURE, MS_DONE}; enum MS_IMAGEMODE { MS_IMAGEMODE_PC256, MS_IMAGEMODE_RGB, MS_IMAGEMODE_RGBA, MS_IMAGEMODE_INT16, MS_IMAGEMODE_FLOAT32, MS_IMAGEMODE_BYTE, MS_IMAGEMODE_FEATURE, MS_IMAGEMODE_NULL }; enum MS_GEOS_OPERATOR {MS_GEOS_EQUALS, MS_GEOS_DISJOINT, MS_GEOS_TOUCHES, MS_GEOS_OVERLAPS, MS_GEOS_CROSSES, MS_GEOS_INTERSECTS, MS_GEOS_WITHIN, MS_GEOS_CONTAINS, MS_GEOS_BEYOND, MS_GEOS_DWITHIN}; #define MS_FILE_DEFAULT MS_FILE_MAP #if defined(_MSC_VER) && (_MSC_VER <= 1310) #define MS_DEBUG msDebug2 #else #ifdef USE_EXTENDED_DEBUG #define MS_DEBUG(level,elt,fmt, ...) if((elt)->debug >= (level)) msDebug(fmt,##__VA_ARGS__) #else #define MS_DEBUG(level,elt,fmt, ...) /* no-op */ #endif #endif /* coordinate to pixel simplification modes, used in msTransformShape */ enum MS_TRANSFORM_MODE { MS_TRANSFORM_NONE, /* no geographic to pixel transformation */ MS_TRANSFORM_ROUND, /* round to integer, might create degenerate geometries (used for GD)*/ MS_TRANSFORM_SNAPTOGRID, /* snap to a grid, should be user configurable in the future*/ MS_TRANSFORM_FULLRESOLUTION, /* keep full resolution */ MS_TRANSFORM_SIMPLIFY /* keep full resolution */ }; typedef enum { MS_COMPOP_CLEAR, MS_COMPOP_SRC, MS_COMPOP_DST, MS_COMPOP_SRC_OVER, MS_COMPOP_DST_OVER, MS_COMPOP_SRC_IN, MS_COMPOP_DST_IN, MS_COMPOP_SRC_OUT, MS_COMPOP_DST_OUT, MS_COMPOP_SRC_ATOP, MS_COMPOP_DST_ATOP, MS_COMPOP_XOR, MS_COMPOP_PLUS, MS_COMPOP_MINUS, MS_COMPOP_MULTIPLY, MS_COMPOP_SCREEN, MS_COMPOP_OVERLAY, MS_COMPOP_DARKEN, MS_COMPOP_LIGHTEN, MS_COMPOP_COLOR_DODGE, MS_COMPOP_COLOR_BURN, MS_COMPOP_HARD_LIGHT, MS_COMPOP_SOFT_LIGHT, MS_COMPOP_DIFFERENCE, MS_COMPOP_EXCLUSION, MS_COMPOP_CONTRAST, MS_COMPOP_INVERT, MS_COMPOP_INVERT_RGB } CompositingOperation; typedef struct _CompositingFilter{ char *filter; struct _CompositingFilter *next; } CompositingFilter; typedef struct _LayerCompositer{ CompositingOperation comp_op; int opacity; CompositingFilter *filter; struct _LayerCompositer *next; } LayerCompositer; #ifndef SWIG /* Filter object */ typedef enum { FILTER_NODE_TYPE_UNDEFINED = -1, FILTER_NODE_TYPE_LOGICAL = 0, FILTER_NODE_TYPE_SPATIAL = 1, FILTER_NODE_TYPE_COMPARISON = 2, FILTER_NODE_TYPE_PROPERTYNAME = 3, FILTER_NODE_TYPE_BBOX = 4, FILTER_NODE_TYPE_LITERAL = 5, FILTER_NODE_TYPE_BOUNDARY = 6, FILTER_NODE_TYPE_GEOMETRY_POINT = 7, FILTER_NODE_TYPE_GEOMETRY_LINE = 8, FILTER_NODE_TYPE_GEOMETRY_POLYGON = 9, FILTER_NODE_TYPE_FEATUREID = 10, FILTER_NODE_TYPE_TEMPORAL = 11, FILTER_NODE_TYPE_TIME_PERIOD = 12 } FilterNodeType; /************************************************************************/ /* FilterEncodingNode */ /************************************************************************/ typedef struct _FilterNode { FilterNodeType eType; char *pszValue; void *pOther; char *pszSRS; struct _FilterNode *psLeftNode; struct _FilterNode *psRightNode; } FilterEncodingNode; #endif /*SWIG*/ /* Define supported bindings here (only covers existing bindings at first). Not accessible directly using MapScript. */ #define MS_STYLE_BINDING_LENGTH 12 enum MS_STYLE_BINDING_ENUM { MS_STYLE_BINDING_SIZE, MS_STYLE_BINDING_WIDTH, MS_STYLE_BINDING_ANGLE, MS_STYLE_BINDING_COLOR, MS_STYLE_BINDING_OUTLINECOLOR, MS_STYLE_BINDING_SYMBOL, MS_STYLE_BINDING_OUTLINEWIDTH, MS_STYLE_BINDING_OPACITY, MS_STYLE_BINDING_OFFSET_X, MS_STYLE_BINDING_OFFSET_Y, MS_STYLE_BINDING_POLAROFFSET_PIXEL, MS_STYLE_BINDING_POLAROFFSET_ANGLE }; #define MS_LABEL_BINDING_LENGTH 9 enum MS_LABEL_BINDING_ENUM { MS_LABEL_BINDING_SIZE, MS_LABEL_BINDING_ANGLE, MS_LABEL_BINDING_COLOR, MS_LABEL_BINDING_OUTLINECOLOR, MS_LABEL_BINDING_FONT, MS_LABEL_BINDING_PRIORITY, MS_LABEL_BINDING_POSITION, MS_LABEL_BINDING_SHADOWSIZEX, MS_LABEL_BINDING_SHADOWSIZEY }; /************************************************************************/ /* attributeBindingObj */ /************************************************************************/ #ifndef SWIG typedef struct { char *item; int index; } attributeBindingObj; #endif /*SWIG*/ /************************************************************************/ /* labelPathObj */ /* */ /* Label path object - used to hold path and bounds of curved */ /* labels - Bug #1620 implementation. */ /************************************************************************/ #ifndef SWIG typedef struct { multipointObj path; shapeObj bounds; double *angles; } labelPathObj; #endif /*SWIG*/ /************************************************************************/ /* fontSetObj */ /* */ /* used to hold aliases for TRUETYPE fonts */ /************************************************************************/ typedef struct { #ifdef SWIG %immutable; #endif char *filename; int numfonts; hashTableObj fonts; #ifdef SWIG %mutable; #endif #ifndef SWIG struct mapObj *map; #endif } fontSetObj; /************************************************************************/ /* featureListNodeObj */ /* */ /* for inline features, shape caches and queries */ /************************************************************************/ #ifndef SWIG typedef struct listNode { shapeObj shape; struct listNode *next; struct listNode *tailifhead; /* this is the tail node in the list, if this is the head element, otherwise NULL */ } featureListNodeObj; typedef featureListNodeObj * featureListNodeObjPtr; #endif /************************************************************************/ /* paletteObj */ /* */ /* used to hold colors while a map file is read */ /************************************************************************/ #ifndef SWIG typedef struct { colorObj colors[MS_MAXCOLORS-1]; int colorvalue[MS_MAXCOLORS-1]; int numcolors; } paletteObj; #endif /************************************************************************/ /* expressionObj & tokenObj */ /************************************************************************/ enum MS_TOKEN_LOGICAL_ENUM { MS_TOKEN_LOGICAL_AND=300, MS_TOKEN_LOGICAL_OR, MS_TOKEN_LOGICAL_NOT }; enum MS_TOKEN_LITERAL_ENUM { MS_TOKEN_LITERAL_NUMBER=310, MS_TOKEN_LITERAL_STRING, MS_TOKEN_LITERAL_TIME, MS_TOKEN_LITERAL_SHAPE, MS_TOKEN_LITERAL_BOOLEAN }; enum MS_TOKEN_COMPARISON_ENUM { MS_TOKEN_COMPARISON_EQ=320, MS_TOKEN_COMPARISON_NE, MS_TOKEN_COMPARISON_GT, MS_TOKEN_COMPARISON_LT, MS_TOKEN_COMPARISON_LE, MS_TOKEN_COMPARISON_GE, MS_TOKEN_COMPARISON_IEQ, MS_TOKEN_COMPARISON_RE, MS_TOKEN_COMPARISON_IRE, MS_TOKEN_COMPARISON_IN, MS_TOKEN_COMPARISON_LIKE, MS_TOKEN_COMPARISON_INTERSECTS, MS_TOKEN_COMPARISON_DISJOINT, MS_TOKEN_COMPARISON_TOUCHES, MS_TOKEN_COMPARISON_OVERLAPS, MS_TOKEN_COMPARISON_CROSSES, MS_TOKEN_COMPARISON_WITHIN, MS_TOKEN_COMPARISON_CONTAINS, MS_TOKEN_COMPARISON_EQUALS, MS_TOKEN_COMPARISON_BEYOND, MS_TOKEN_COMPARISON_DWITHIN }; enum MS_TOKEN_FUNCTION_ENUM { MS_TOKEN_FUNCTION_LENGTH=350, MS_TOKEN_FUNCTION_TOSTRING, MS_TOKEN_FUNCTION_COMMIFY, MS_TOKEN_FUNCTION_AREA, MS_TOKEN_FUNCTION_ROUND, MS_TOKEN_FUNCTION_FROMTEXT, MS_TOKEN_FUNCTION_BUFFER, MS_TOKEN_FUNCTION_DIFFERENCE, MS_TOKEN_FUNCTION_SIMPLIFY, MS_TOKEN_FUNCTION_SIMPLIFYPT, MS_TOKEN_FUNCTION_GENERALIZE, MS_TOKEN_FUNCTION_SMOOTHSIA, MS_TOKEN_FUNCTION_JAVASCRIPT, MS_TOKEN_FUNCTION_UPPER, MS_TOKEN_FUNCTION_LOWER, MS_TOKEN_FUNCTION_INITCAP, MS_TOKEN_FUNCTION_FIRSTCAP }; enum MS_TOKEN_BINDING_ENUM { MS_TOKEN_BINDING_DOUBLE=370, MS_TOKEN_BINDING_INTEGER, MS_TOKEN_BINDING_STRING, MS_TOKEN_BINDING_TIME, MS_TOKEN_BINDING_SHAPE, MS_TOKEN_BINDING_MAP_CELLSIZE, MS_TOKEN_BINDING_DATA_CELLSIZE }; enum MS_PARSE_TYPE_ENUM { MS_PARSE_TYPE_BOOLEAN, MS_PARSE_TYPE_STRING, MS_PARSE_TYPE_SHAPE }; #ifndef SWIG typedef union { int intval; char *strval; shapeObj *shpval; } parseResultObj; typedef union { double dblval; int intval; char *strval; struct tm tmval; shapeObj *shpval; attributeBindingObj bindval; } tokenValueObj; typedef struct tokenListNode { int token; tokenValueObj tokenval; char *tokensrc; /* on occassion we may want to access to the original source string (e.g. date/time) */ struct tokenListNode *next; struct tokenListNode *tailifhead; /* this is the tail node in the list if this is the head element, otherwise NULL */ } tokenListNodeObj; typedef tokenListNodeObj * tokenListNodeObjPtr; typedef struct { char *string; int type; /* container for expression options such as case-insensitiveness */ /* This is a boolean container. */ int flags; /* logical expression options */ tokenListNodeObjPtr tokens; tokenListNodeObjPtr curtoken; /* regular expression options */ ms_regex_t regex; /* compiled regular expression to be matched */ int compiled; char *native_string; /* RFC 91 */ } expressionObj; typedef struct { colorObj *pixel; /* for raster layers */ shapeObj *shape; /* for vector layers */ double dblval; /* for map cellsize used by simplify */ double dblval2; /* for data cellsize */ expressionObj *expr; /* expression to be evaluated (contains tokens) */ int type; /* type of parse: boolean, string/text or shape/geometry */ parseResultObj result; /* parse result */ } parseObj; #endif /* MS RFC 69*/ typedef struct { double maxdistance; /* max distance between clusters */ double buffer; /* the buffer size around the selection area */ char* region; /* type of the cluster region (rectangle or ellipse) */ #ifndef SWIG expressionObj group; /* expression to identify the groups */ expressionObj filter; /* expression for filtering the shapes */ #endif } clusterObj; /************************************************************************/ /* joinObj */ /* */ /* simple way to access other XBase files, one-to-one or */ /* one-to-many supported */ /************************************************************************/ #ifndef SWIG typedef struct { char *name; char **items, **values; /* items/values (process 1 record at a time) */ int numitems; char *table; char *from, *to; /* item names */ void *joininfo; /* vendor specific (i.e. XBase, MySQL, etc.) stuff to allow for persistant access */ char *header, *footer; #ifndef __cplusplus char *template; #else char *_template; #endif enum MS_JOIN_TYPE type; char *connection; enum MS_JOIN_CONNECTION_TYPE connectiontype; } joinObj; #endif /************************************************************************/ /* outputFormatObj */ /* */ /* see mapoutput.c for most related code. */ /************************************************************************/ typedef struct { #ifndef SWIG int refcount; char **formatoptions; #endif /* SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ int numformatoptions; #ifdef SWIG %mutable; #endif /* SWIG */ char *name; char *mimetype; char *driver; char *extension; int renderer; /* MS_RENDER_WITH_* */ int imagemode; /* MS_IMAGEMODE_* value. */ int transparent; int bands; int inmapfile; /* boolean value for writing */ #ifndef SWIG rendererVTableObj *vtable; void *device; /* for supporting direct rendering onto a device context */ #endif } outputFormatObj; /* The following is used for "don't care" values in transparent, interlace and imagequality values. */ #define MS_NOOVERRIDE -1111 /************************************************************************/ /* queryObj */ /* */ /* encapsulates the information necessary to perform a query */ /************************************************************************/ #ifndef SWIG typedef struct { int type; /* MS_QUERY_TYPE */ int mode; /* MS_QUERY_MODE */ int layer; pointObj point; /* by point */ double buffer; int maxresults; rectObj rect; /* by rect */ shapeObj *shape; /* by shape & operator (OGC filter) */ long shapeindex; /* by index */ long tileindex; int clear_resultcache; int maxfeatures; /* global maxfeatures */ int startindex; int only_cache_result_count; /* set to 1 sometimes by WFS 2.0 GetFeature request */ expressionObj filter; /* by filter */ char *filteritem; int slayer; /* selection layer, used for msQueryByFeatures() (note this is not a query mode per se) */ int cache_shapes; /* whether to cache shapes in resultCacheObj */ int max_cached_shape_count; /* maximum number of shapes cached in the total number of resultCacheObj */ int max_cached_shape_ram_amount; /* maximum number of bytes taken by shapes cached in the total number of resultCacheObj */ } queryObj; #endif /************************************************************************/ /* queryMapObj */ /* */ /* used to visualize query results */ /************************************************************************/ typedef struct { int height, width; int status; int style; /* HILITE, SELECTED or NORMAL */ colorObj color; } queryMapObj; /************************************************************************/ /* webObj */ /* */ /* holds parameters for a mapserver/mapscript interface */ /************************************************************************/ typedef struct { char *log; char *imagepath, *imageurl, *temppath; #ifdef SWIG %immutable; #endif /* SWIG */ struct mapObj *map; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef __cplusplus char *template; #else char *_template; #endif char *header, *footer; char *empty, *error; /* error handling */ rectObj extent; /* clipping extent */ double minscaledenom, maxscaledenom; char *mintemplate, *maxtemplate; char *queryformat; /* what format is the query to be returned, given as a MIME type */ char *legendformat; char *browseformat; #ifdef SWIG %immutable; #endif /* SWIG */ hashTableObj metadata; hashTableObj validation; #ifdef SWIG %mutable; #endif /* SWIG */ } webObj; /************************************************************************/ /* styleObj */ /* */ /* holds parameters for symbolization, multiple styles may be */ /* applied within a classObj */ /************************************************************************/ struct styleObj{ #ifdef SWIG %immutable; #endif /* SWIG */ int refcount; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG /* private vars for rfc 48 & 64 */ expressionObj _geomtransform; #endif /*should an angle be automatically computed*/ int autoangle; colorObj color; colorObj backgroundcolor; colorObj outlinecolor; int opacity; /* Stuff to handle Color Range Styles */ colorObj mincolor; colorObj maxcolor; double minvalue; double maxvalue; char *rangeitem; int rangeitemindex; int symbol; char *symbolname; double size; double minsize, maxsize; #if defined(SWIG) && defined(SWIGPYTHON) /* would probably make sense to mark it immutable for other binding languages than Python */ %immutable; #endif int patternlength; /*moved from symbolObj in version 6.0*/ #if defined(SWIG) && defined(SWIGPYTHON) %mutable; #endif #if !(defined(SWIG) && defined(SWIGPYTHON)) /* in Python we use a special typemap for this */ double pattern[MS_MAXPATTERNLENGTH]; /*moved from symbolObj in version 6.0*/ #endif double gap; /*moved from symbolObj in version 6.0*/ double initialgap; int position; /*moved from symbolObj in version 6.0*/ int linecap, linejoin; /*moved from symbolObj in version 6.0*/ double linejoinmaxsize; /*moved from symbolObj in version 6.0*/ double width; double outlinewidth; double minwidth, maxwidth; double offsetx, offsety; /* for shadows, hollow symbols, etc... */ double polaroffsetpixel, polaroffsetangle; double angle; double minscaledenom, maxscaledenom; #ifndef SWIG attributeBindingObj bindings[MS_STYLE_BINDING_LENGTH]; int numbindings; #endif }; #define MS_STYLE_SINGLE_SIDED_OFFSET -99 #define MS_STYLE_DOUBLE_SIDED_OFFSET -999 #define IS_PARALLEL_OFFSET(offsety) ((offsety) == MS_STYLE_SINGLE_SIDED_OFFSET || (offsety) == MS_STYLE_DOUBLE_SIDED_OFFSET) /********************************************************************/ /* labelLeaderObj */ /* */ /* parameters defining how a label or a group of labels may be */ /* offsetted from its original position */ /********************************************************************/ typedef struct { int maxdistance; int gridstep; #ifndef SWIG styleObj **styles; int maxstyles; #endif #ifdef SWIG %immutable; #endif int numstyles; #ifdef SWIG %mutable; #endif } labelLeaderObj; /************************************************************************/ /* labelObj */ /* */ /* parameters needed to annotate a layer, legend or scalebar */ /************************************************************************/ struct labelObj{ #ifdef SWIG %immutable; #endif /* SWIG */ int refcount; #ifdef SWIG %mutable; #endif /* SWIG */ char *font; colorObj color; colorObj outlinecolor; int outlinewidth; colorObj shadowcolor; int shadowsizex, shadowsizey; int size; int minsize, maxsize; int position; int offsetx, offsety; double angle; enum MS_POSITIONS_ENUM anglemode; int buffer; /* space to reserve around a label */ int align; char wrap; int maxlength; int minlength; double space_size_10; /*cached size of a single space character used for label text alignment of rfc40 */ int minfeaturesize; /* minimum feature size (in pixels) to label */ int autominfeaturesize; /* true or false */ double minscaledenom, maxscaledenom; int mindistance; int repeatdistance; double maxoverlapangle; int partials; /* can labels run of an image */ int force; /* labels *must* be drawn */ char *encoding; int priority; /* Priority level 1 to MS_MAX_LABEL_PRIORITY, default=1 */ #ifndef SWIG expressionObj expression; expressionObj text; #endif #ifndef SWIG styleObj **styles; int maxstyles; #endif int numstyles; #ifndef SWIG attributeBindingObj bindings[MS_LABEL_BINDING_LENGTH]; int numbindings; #endif labelLeaderObj *leader; }; #ifdef SWIG #ifdef __cplusplus extern "C" { #endif typedef struct labelObj labelObj; #ifdef __cplusplus } #endif #endif #ifndef SWIG /* lightweight structure containing information to render a labelObj */ typedef struct { lineObj *poly; rectObj bbox; } label_bounds; typedef struct { labelObj *label; char *annotext; double scalefactor,resolutionfactor; pointObj annopoint; double rotation; textPathObj *textpath; //rectObj bbox; label_bounds **style_bounds; } textSymbolObj; #endif #define MS_LABEL_PERPENDICULAR_OFFSET -99 #define MS_LABEL_PERPENDICULAR_TOP_OFFSET 99 #define IS_PERPENDICULAR_OFFSET(offsety) ((offsety) == MS_LABEL_PERPENDICULAR_OFFSET || (offsety) == MS_LABEL_PERPENDICULAR_TOP_OFFSET) /************************************************************************/ /* classObj */ /* */ /* basic symbolization and classification information */ /************************************************************************/ struct classObj { #ifndef SWIG expressionObj expression; /* the expression to be matched */ #endif int status; #ifndef SWIG styleObj **styles; int maxstyles; #endif #ifdef SWIG %immutable; #endif int numstyles; #ifdef SWIG %mutable; #endif #ifndef SWIG labelObj **labels; int maxlabels; #endif int numlabels; /* should be immutable */ char *name; /* should be unique within a layer */ char *title; /* used for legend labeling */ #ifndef SWIG expressionObj text; #endif /* not SWIG */ #ifndef __cplusplus char *template; #else /* __cplusplus */ char *_template; #endif /* __cplusplus */ #ifdef SWIG %immutable; #endif /* SWIG */ hashTableObj metadata; hashTableObj validation; #ifdef SWIG %mutable; #endif /* SWIG */ double minscaledenom, maxscaledenom; int minfeaturesize; /* minimum feature size (in pixels) to shape */ #ifdef SWIG %immutable; #endif /* SWIG */ int refcount; struct layerObj *layer; #ifdef SWIG %mutable; #endif /* SWIG */ int debug; char *keyimage; char *group; labelLeaderObj *leader; }; /************************************************************************/ /* labelCacheMemberObj */ /* */ /* structures to implement label caching and collision */ /* avoidance etc */ /* */ /* Note: These are scriptable, but are read only. */ /************************************************************************/ #ifdef SWIG %immutable; #endif /* SWIG */ typedef struct { #ifdef include_deprecated styleObj *styles; /* copied from the classObj, only present if there is a marker to be drawn */ int numstyles; #endif textSymbolObj **textsymbols; int numtextsymbols; int layerindex; /* indexes */ int classindex; #ifdef include_deprecated int shapetype; /* source geometry type, can be removed once annotation layers are dropped */ #endif pointObj point; /* label point */ rectObj bbox; /* bounds of the whole cachePtr. Individual text and symbol sub bounds are found in the textsymbols */ int status; /* has this label been drawn or not */ int markerid; /* corresponding marker (POINT layers only) */ lineObj *leaderline; rectObj *leaderbbox; } labelCacheMemberObj; /************************************************************************/ /* markerCacheMemberObj */ /************************************************************************/ typedef struct { int id; /* corresponding label */ rectObj bounds; } markerCacheMemberObj; /************************************************************************/ /* labelCacheSlotObj */ /************************************************************************/ typedef struct { labelCacheMemberObj *labels; int numlabels; int cachesize; markerCacheMemberObj *markers; int nummarkers; int markercachesize; } labelCacheSlotObj; /************************************************************************/ /* labelCacheObj */ /************************************************************************/ typedef struct { /* One labelCacheSlotObj for each priority level */ labelCacheSlotObj slots[MS_MAX_LABEL_PRIORITY]; int gutter; /* space in pixels around the image where labels cannot be placed */ labelCacheMemberObj **rendered_text_symbols; int num_allocated_rendered_members; int num_rendered_members; } labelCacheObj; /************************************************************************/ /* resultObj */ /************************************************************************/ typedef struct { long shapeindex; int tileindex; int resultindex; int classindex; #ifndef SWIG shapeObj* shape; #endif } resultObj; #ifdef SWIG %mutable; #endif /* SWIG */ /************************************************************************/ /* resultCacheObj */ /************************************************************************/ typedef struct { #ifndef SWIG resultObj *results; int cachesize; #endif /* not SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ int numresults; rectObj bounds; #ifndef SWIG rectObj previousBounds; /* bounds at previous iteration */ #endif #ifdef SWIG %mutable; #endif /* SWIG */ /* TODO: remove for 6.0, confirm with Assefa */ /*used to force the result retreiving to use getshape instead of resultgetshape*/ int usegetshape; } resultCacheObj; /************************************************************************/ /* symbolSetObj */ /************************************************************************/ typedef struct { char *filename; int imagecachesize; #ifdef SWIG %immutable; #endif /* SWIG */ int numsymbols; int maxsymbols; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG int refcount; symbolObj** symbol; struct mapObj *map; fontSetObj *fontset; /* a pointer to the main mapObj version */ struct imageCacheObj *imagecache; #endif /* not SWIG */ } symbolSetObj; /************************************************************************/ /* referenceMapObj */ /************************************************************************/ typedef struct { rectObj extent; int height, width; colorObj color; colorObj outlinecolor; char *image; int status; int marker; char *markername; int markersize; int minboxsize; int maxboxsize; #ifdef SWIG %immutable; #endif /* SWIG */ struct mapObj *map; #ifdef SWIG %mutable; #endif /* SWIG */ } referenceMapObj; /************************************************************************/ /* scalebarObj */ /************************************************************************/ typedef struct { colorObj imagecolor; int height, width; int style; int intervals; labelObj label; colorObj color; colorObj backgroundcolor; colorObj outlinecolor; int units; int status; /* ON, OFF or EMBED */ int position; /* for embeded scalebars */ #ifndef SWIG int transparent; int interlace; #endif /* not SWIG */ int postlabelcache; int align; int offsetx; int offsety; } scalebarObj; /************************************************************************/ /* legendObj */ /************************************************************************/ typedef struct { colorObj imagecolor; #ifdef SWIG %immutable; #endif labelObj label; #ifdef SWIG %mutable; #endif int keysizex, keysizey; int keyspacingx, keyspacingy; colorObj outlinecolor; /* Color of outline of box, -1 for no outline */ int status; /* ON, OFF or EMBED */ int height, width; int position; /* for embeded legends */ #ifndef SWIG int transparent; int interlace; #endif /* not SWIG */ int postlabelcache; #ifndef __cplusplus char *template; #else /* __cplusplus */ char *_template; #endif /* __cplusplus */ #ifdef SWIG %immutable; #endif /* SWIG */ struct mapObj *map; #ifdef SWIG %mutable; #endif /* SWIG */ } legendObj; /************************************************************************/ /* graticuleObj */ /************************************************************************/ #ifndef SWIG typedef struct { double dwhichlatitude; double dwhichlongitude; double dstartlatitude; double dstartlongitude; double dendlatitude; double dendlongitude; double dincrementlatitude; double dincrementlongitude; double minarcs; double maxarcs; double minincrement; double maxincrement; double minsubdivides; double maxsubdivides; int bvertical; int blabelaxes; int ilabelstate; int ilabeltype; rectObj extent; lineObj *pboundinglines; pointObj *pboundingpoints; char *labelformat; } graticuleObj; typedef struct { int nTop; pointObj *pasTop; char **papszTopLabels; int nBottom; pointObj *pasBottom; char **papszBottomLabels; int nLeft; pointObj *pasLeft; char **papszLeftLabels; int nRight; pointObj *pasRight; char **papszRightLabels; } graticuleIntersectionObj; struct layerVTable; typedef struct layerVTable layerVTableObj; #endif /*SWIG*/ /************************************************************************/ /* imageObj */ /* */ /* A wrapper for GD and other images. */ /************************************************************************/ struct imageObj{ #ifdef SWIG %immutable; #endif int width, height; double resolution; double resolutionfactor; char *imagepath, *imageurl; outputFormatObj *format; #ifndef SWIG tileCacheObj *tilecache; int ntiles; #endif #ifdef SWIG %mutable; #endif #ifndef SWIG int size; #endif #ifndef SWIG union { void *plugin; char *imagemap; short *raw_16bit; float *raw_float; unsigned char *raw_byte; } img; ms_bitarray img_mask; pointObj refpt; mapObj *map; #endif }; /************************************************************************/ /* layerObj */ /* */ /* base unit of a map. */ /************************************************************************/ typedef struct { double minscale; double maxscale; char *value; } scaleTokenEntryObj; typedef struct { char *name; int n_entries; scaleTokenEntryObj *tokens; } scaleTokenObj; #ifndef SWIG typedef enum { SORT_ASC, SORT_DESC } sortOrderEnum; typedef struct { char* item; sortOrderEnum sortOrder; } sortByProperties; typedef struct { int nProperties; sortByProperties* properties; } sortByClause; typedef struct { /* The following store original members if they have been modified at runtime by a rfc86 scaletoken */ char *data; char *tileitem; char *tileindex; char *filteritem; char *filter; char **processing; int *processing_idx; int n_processing; } originalScaleTokenStrings; #endif struct layerObj { char *classitem; /* .DBF item to be used for symbol lookup */ #ifndef SWIG int classitemindex; resultCacheObj *resultcache; /* holds the results of a query against this layer */ double scalefactor; /* computed, not set */ #ifndef __cplusplus classObj **class; /* always at least 1 class */ #else /* __cplusplus */ classObj **_class; #endif /* __cplusplus */ #endif /* not SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ /* reference counting, RFC24 */ int refcount; int numclasses; int maxclasses; int index; struct mapObj *map; #ifdef SWIG %mutable; #endif /* SWIG */ char *header, *footer; /* only used with multi result queries */ #ifndef __cplusplus char *template; /* global template, used across all classes */ #else /* __cplusplus */ char *_template; #endif /* __cplusplus */ char *name; /* should be unique */ char *group; /* shouldn't be unique it's supposed to be a group right? */ int status; /* on or off */ #ifndef SWIG /* RFC86 Scale-dependent token replacements */ scaleTokenObj *scaletokens; int numscaletokens; originalScaleTokenStrings *orig_st; #endif char *data; /* filename, can be relative or full path */ enum MS_LAYER_TYPE type; double tolerance; /* search buffer for point and line queries (in toleranceunits) */ int toleranceunits; double symbolscaledenom; /* scale at which symbols are default size */ double minscaledenom, maxscaledenom; int minfeaturesize; /* minimum feature size (in pixels) to shape */ double labelminscaledenom, labelmaxscaledenom; double mingeowidth, maxgeowidth; /* map width (in map units) at which the layer should be drawn */ int sizeunits; /* applies to all classes */ int maxfeatures; int startindex; colorObj offsite; /* transparent pixel value for raster images */ int transform; /* does this layer have to be transformed to file coordinates */ int labelcache, postlabelcache; /* on or off */ char *labelitem; #ifndef SWIG int labelitemindex; #endif /* not SWIG */ char *tileitem; char *tileindex; /* layer index file for tiling support */ char *tilesrs; #ifndef SWIG int tileitemindex; projectionObj projection; /* projection information for the layer */ int project; /* boolean variable, do we need to project this layer or not */ #endif /* not SWIG */ int units; /* units of the projection */ #ifndef SWIG featureListNodeObjPtr features; /* linked list so we don't need a counter */ featureListNodeObjPtr currentfeature; /* pointer to the current feature */ #endif /* SWIG */ char *connection; char *plugin_library; char *plugin_library_original; /* this is needed for mapfile writing */ enum MS_CONNECTION_TYPE connectiontype; #ifndef SWIG layerVTableObj *vtable; /* SDL has converted OracleSpatial, SDE, Graticules */ void *layerinfo; /* all connection types should use this generic pointer to a vendor specific structure */ void *wfslayerinfo; /* For WFS layers, will contain a msWFSLayerInfo struct */ #endif /* not SWIG */ /* attribute/classification handling components */ #ifdef SWIG %immutable; #endif /* SWIG */ int numitems; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG char **items; void *iteminfo; /* connection specific information necessary to retrieve values */ expressionObj filter; /* connection specific attribute filter */ int bandsitemindex; int filteritemindex; int styleitemindex; #endif /* not SWIG */ char *bandsitem; /* which item in a tile contains bands to use (tiled raster data only) */ char *filteritem; char *styleitem; /* item to be used for style lookup - can also be 'AUTO' */ char *requires; /* context expressions, simple enough to not use expressionObj */ char *labelrequires; #ifdef SWIG %immutable; #endif /* SWIG */ hashTableObj metadata; hashTableObj validation; hashTableObj bindvals; clusterObj cluster; #ifdef SWIG %mutable; #endif /* SWIG */ int dump; int debug; #ifndef SWIG char **processing; joinObj *joins; #endif /* not SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ rectObj extent; int numprocessing; int numjoins; #ifdef SWIG %mutable; #endif /* SWIG */ char *classgroup; #ifndef SWIG imageObj *maskimage; graticuleObj* grid; #endif char *mask; #ifndef SWIG expressionObj _geomtransform; #endif char *encoding; /* for iconving shape attributes. ignored if NULL or "utf-8" */ /* RFC93 UTFGrid support */ char *utfitem; int utfitemindex; expressionObj utfdata; #ifndef SWIG sortByClause sortBy; #endif LayerCompositer *compositer; }; #ifndef SWIG void msFontCacheSetup(); void msFontCacheCleanup(); typedef struct { double minx,miny,maxx,maxy,advance; } glyph_metrics; typedef struct { glyph_element *glyph; face_element *face; pointObj pnt; double rot; } glyphObj; struct textPathObj{ int numglyphs; int numlines; int line_height; int glyph_size; int absolute; /* are the glyph positions absolutely placed, or relative to the origin */ glyphObj *glyphs; label_bounds bounds; }; typedef enum { duplicate_never, duplicate_always, duplicate_if_needed } label_cache_mode; void initTextPath(textPathObj *tp); int WARN_UNUSED msComputeTextPath(mapObj *map, textSymbolObj *ts); void msCopyTextPath(textPathObj *dst, textPathObj *src); void freeTextPath(textPathObj *tp); void initTextSymbol(textSymbolObj *ts); void freeTextSymbol(textSymbolObj *ts); void msCopyTextSymbol(textSymbolObj *dst, textSymbolObj *src); void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char *string, double scalefactor, double resolutionfactor, label_cache_mode cache); #endif /* SWIG */ /************************************************************************/ /* mapObj */ /* */ /* encompasses everything used in an Internet mapping */ /* application. */ /************************************************************************/ /* MAP OBJECT - */ struct mapObj { /* structure for a map */ char *name; /* small identifier for naming etc. */ int status; /* is map creation on or off */ int height, width; int maxsize; #ifndef SWIG layerObj **layers; #endif /* SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ /* reference counting, RFC24 */ int refcount; int numlayers; /* number of layers in mapfile */ int maxlayers; /* allocated size of layers[] array */ symbolSetObj symbolset; fontSetObj fontset; labelCacheObj labelcache; /* we need this here so multiple feature processors can access it */ #ifdef SWIG %mutable; #endif /* SWIG */ int transparent; /* TODO - Deprecated */ int interlace; /* TODO - Deprecated */ int imagequality; /* TODO - Deprecated */ rectObj extent; /* map extent array */ double cellsize; /* in map units */ #ifndef SWIG geotransformObj gt; /* rotation / geotransform */ rectObj saved_extent; #endif /*SWIG*/ enum MS_UNITS units; /* units of the projection */ double scaledenom; /* scale of the output image */ double resolution; double defresolution; /* default resolution: used for calculate the scalefactor */ char *shapepath; /* where are the shape files located */ char *mappath; /* path of the mapfile, all path are relative to this path */ #ifndef SWIG paletteObj palette; /* holds a map palette */ #endif /*SWIG*/ colorObj imagecolor; /* holds the initial image color value */ #ifdef SWIG %immutable; #endif /* SWIG */ int numoutputformats; #ifndef SWIG outputFormatObj **outputformatlist; #endif /*SWIG*/ outputFormatObj *outputformat; char *imagetype; /* name of current outputformat */ #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG projectionObj projection; /* projection information for output map */ projectionObj latlon; /* geographic projection definition */ #endif /* not SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ referenceMapObj reference; scalebarObj scalebar; legendObj legend; queryMapObj querymap; webObj web; #ifdef SWIG %mutable; #endif /* SWIG */ int *layerorder; int debug; char *datapattern, *templatepattern; /* depricated, use VALIDATION ... END block instead */ #ifdef SWIG %immutable; #endif /* SWIG */ hashTableObj configoptions; #ifdef SWIG %mutable; #endif /* SWIG */ #ifndef SWIG /* Private encryption key information - see mapcrypto.c */ int encryption_key_loaded; /* MS_TRUE once key has been loaded */ unsigned char encryption_key[MS_ENCRYPTION_KEY_SIZE]; /* 128bits encryption key */ queryObj query; #endif #ifdef USE_V8_MAPSCRIPT void *v8context; #endif }; /************************************************************************/ /* layerVTable */ /* */ /* contains function pointers to the layer operations. If you */ /* add new functions to here, remember to update */ /* populateVirtualTable in maplayer.c */ /************************************************************************/ #ifndef SWIG struct layerVTable { int (*LayerTranslateFilter)(layerObj *layer, expressionObj *filter, char *filteritem); int (*LayerSupportsCommonFilters)(layerObj *layer); int (*LayerInitItemInfo)(layerObj *layer); void (*LayerFreeItemInfo)(layerObj *layer); int (*LayerOpen)(layerObj *layer); int (*LayerIsOpen)(layerObj *layer); int (*LayerWhichShapes)(layerObj *layer, rectObj rect, int isQuery); int (*LayerNextShape)(layerObj *layer, shapeObj *shape); int (*LayerGetShape)(layerObj *layer, shapeObj *shape, resultObj *record); int (*LayerGetShapeCount)(layerObj *layer, rectObj rect, projectionObj *rectProjection); int (*LayerClose)(layerObj *layer); int (*LayerGetItems)(layerObj *layer); int (*LayerGetExtent)(layerObj *layer, rectObj *extent); int (*LayerGetAutoStyle)(mapObj *map, layerObj *layer, classObj *c, shapeObj *shape); int (*LayerCloseConnection)(layerObj *layer); int (*LayerSetTimeFilter)(layerObj *layer, const char *timestring, const char *timefield); int (*LayerApplyFilterToLayer)(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); int (*LayerCreateItems)(layerObj *layer, int nt); int (*LayerGetNumFeatures)(layerObj *layer); int (*LayerGetAutoProjection)(layerObj *layer, projectionObj *projection); char* (*LayerEscapeSQLParam)(layerObj *layer, const char* pszString); char* (*LayerEscapePropertyName)(layerObj *layer, const char* pszString); void (*LayerEnablePaging)(layerObj *layer, int value); int (*LayerGetPaging)(layerObj *layer); }; #endif /*SWIG*/ /* Function prototypes, wrapable */ MS_DLL_EXPORT int msSaveImage(mapObj *map, imageObj *img, const char *filename); MS_DLL_EXPORT void msFreeImage(imageObj *img); MS_DLL_EXPORT int msSetup(void); MS_DLL_EXPORT void msCleanup(void); MS_DLL_EXPORT mapObj *msLoadMapFromString(char *buffer, char *new_mappath); /* Function prototypes, not wrapable */ #ifndef SWIG /* ** helper functions not part of the general API but needed in ** a few other places (like mapscript)... found in mapfile.c */ int getString(char **s); int getDouble(double *d); int getInteger(int *i); int getSymbol(int n, ...); int getCharacter(char *c); int msBuildPluginLibraryPath(char **dest, const char *lib_str, mapObj *map); MS_DLL_EXPORT int hex2int(char *hex); MS_DLL_EXPORT void initJoin(joinObj *join); MS_DLL_EXPORT void initSymbol(symbolObj *s); MS_DLL_EXPORT int initMap(mapObj *map); MS_DLL_EXPORT layerObj *msGrowMapLayers( mapObj *map ); MS_DLL_EXPORT int initLayer(layerObj *layer, mapObj *map); MS_DLL_EXPORT int freeLayer( layerObj * ); MS_DLL_EXPORT classObj *msGrowLayerClasses( layerObj *layer ); MS_DLL_EXPORT scaleTokenObj *msGrowLayerScaletokens( layerObj *layer ); MS_DLL_EXPORT int initScaleToken(scaleTokenObj *scaleToken); MS_DLL_EXPORT int initClass(classObj *_class); MS_DLL_EXPORT int freeClass( classObj * ); MS_DLL_EXPORT styleObj *msGrowClassStyles( classObj *_class ); MS_DLL_EXPORT labelObj *msGrowClassLabels( classObj *_class ); MS_DLL_EXPORT styleObj *msGrowLabelStyles( labelObj *label ); MS_DLL_EXPORT styleObj *msGrowLeaderStyles( labelLeaderObj *leader ); MS_DLL_EXPORT int msMaybeAllocateClassStyle(classObj* c, int idx); MS_DLL_EXPORT void initLabel(labelObj *label); MS_DLL_EXPORT int freeLabel(labelObj *label); MS_DLL_EXPORT int freeLabelLeader(labelLeaderObj *leader); MS_DLL_EXPORT void resetClassStyle(classObj *_class); MS_DLL_EXPORT int initStyle(styleObj *style); MS_DLL_EXPORT int freeStyle(styleObj *style); MS_DLL_EXPORT void initReferenceMap(referenceMapObj *ref); MS_DLL_EXPORT void initScalebar(scalebarObj *scalebar); MS_DLL_EXPORT void initGrid( graticuleObj *pGraticule ); MS_DLL_EXPORT void initWeb(webObj *web); MS_DLL_EXPORT void freeWeb(webObj *web); MS_DLL_EXPORT void initResultCache(resultCacheObj *resultcache); void cleanupResultCache(resultCacheObj *resultcache); MS_DLL_EXPORT int initLayerCompositer(LayerCompositer *compositer); MS_DLL_EXPORT void initLeader(labelLeaderObj *leader); MS_DLL_EXPORT void freeGrid( graticuleObj *pGraticule); MS_DLL_EXPORT featureListNodeObjPtr insertFeatureList(featureListNodeObjPtr *list, shapeObj *shape); MS_DLL_EXPORT void freeFeatureList(featureListNodeObjPtr list); /* To be used *only* within the mapfile loading phase */ MS_DLL_EXPORT int loadExpressionString(expressionObj *exp, char *value); /* Use this next, thread safe wrapper, function everywhere else */ MS_DLL_EXPORT int msLoadExpressionString(expressionObj *exp, char *value); MS_DLL_EXPORT char *msGetExpressionString(expressionObj *exp); MS_DLL_EXPORT void msInitExpression(expressionObj *exp); MS_DLL_EXPORT void msFreeExpressionTokens(expressionObj *exp); MS_DLL_EXPORT void msFreeExpression(expressionObj *exp); MS_DLL_EXPORT void msApplySubstitutions(mapObj *map, char **names, char **values, int npairs); MS_DLL_EXPORT void msApplyDefaultSubstitutions(mapObj *map); MS_DLL_EXPORT int getClassIndex(layerObj *layer, char *str); /* For maplabel */ int intersectLabelPolygons(lineObj *p1, rectObj *r1, lineObj *p2, rectObj *r2); int intersectTextSymbol(textSymbolObj *ts, label_bounds *lb); pointObj get_metrics(pointObj *p, int position, textPathObj *tp, int ox, int oy, double rotation, int buffer, label_bounds *metrics); double dist(pointObj a, pointObj b); void fastComputeBounds(lineObj *line, rectObj *bounds); /* ** Main API Functions */ /* mapobject.c */ MS_DLL_EXPORT void msFreeMap(mapObj *map); MS_DLL_EXPORT mapObj *msNewMapObj(void); MS_DLL_EXPORT const char *msGetConfigOption( mapObj *map, const char *key); MS_DLL_EXPORT int msSetConfigOption( mapObj *map, const char *key, const char *value); MS_DLL_EXPORT int msTestConfigOption( mapObj *map, const char *key, int default_result ); MS_DLL_EXPORT void msApplyMapConfigOptions( mapObj *map ); MS_DLL_EXPORT int msMapComputeGeotransform( mapObj *map ); MS_DLL_EXPORT void msMapPixelToGeoref( mapObj *map, double *x, double *y ); MS_DLL_EXPORT void msMapGeorefToPixel( mapObj *map, double *x, double *y ); MS_DLL_EXPORT int msMapSetExtent(mapObj *map, double minx, double miny, double maxx, double maxy); MS_DLL_EXPORT int msMapOffsetExtent( mapObj *map, double x, double y); MS_DLL_EXPORT int msMapScaleExtent( mapObj *map, double zoomfactor, double minscaledenom, double maxscaledenom); MS_DLL_EXPORT int msMapSetCenter( mapObj *map, pointObj *center); MS_DLL_EXPORT int msMapSetRotation( mapObj *map, double rotation_angle ); MS_DLL_EXPORT int msMapSetSize( mapObj *map, int width, int height ); MS_DLL_EXPORT int msMapSetSize( mapObj *map, int width, int height ); MS_DLL_EXPORT int msMapSetFakedExtent( mapObj *map ); MS_DLL_EXPORT int msMapRestoreRealExtent( mapObj *map ); MS_DLL_EXPORT int msMapLoadOWSParameters( mapObj *map, cgiRequestObj *request, const char *wmtver_string ); MS_DLL_EXPORT int msMapIgnoreMissingData( mapObj *map ); /* mapfile.c */ MS_DLL_EXPORT int msValidateParameter(const char *value, const char *pattern1, const char *pattern2, const char *pattern3, const char *pattern4); MS_DLL_EXPORT int msGetLayerIndex(mapObj *map, const char *name); MS_DLL_EXPORT int msGetSymbolIndex(symbolSetObj *set, char *name, int try_addimage_if_notfound); MS_DLL_EXPORT mapObj *msLoadMap(char *filename, char *new_mappath); MS_DLL_EXPORT int msTransformXmlMapfile(const char *stylesheet, const char *xmlMapfile, FILE *tmpfile); MS_DLL_EXPORT int msSaveMap(mapObj *map, char *filename); MS_DLL_EXPORT void msFreeCharArray(char **array, int num_items); MS_DLL_EXPORT int msUpdateScalebarFromString(scalebarObj *scalebar, char *string, int url_string); MS_DLL_EXPORT int msUpdateQueryMapFromString(queryMapObj *querymap, char *string, int url_string); MS_DLL_EXPORT int msUpdateLabelFromString(labelObj *label, char *string, int url_string); MS_DLL_EXPORT int msUpdateClusterFromString(clusterObj *cluster, char *string); MS_DLL_EXPORT int msUpdateReferenceMapFromString(referenceMapObj *ref, char *string, int url_string); MS_DLL_EXPORT int msUpdateLegendFromString(legendObj *legend, char *string, int url_string); MS_DLL_EXPORT int msUpdateWebFromString(webObj *web, char *string, int url_string); MS_DLL_EXPORT int msUpdateStyleFromString(styleObj *style, char *string, int url_string); MS_DLL_EXPORT int msUpdateClassFromString(classObj *_class, char *string, int url_string); MS_DLL_EXPORT int msUpdateLayerFromString(layerObj *layer, char *string, int url_string); MS_DLL_EXPORT int msUpdateMapFromURL(mapObj *map, char *variable, char *string); MS_DLL_EXPORT char *msWriteLayerToString(layerObj *layer); MS_DLL_EXPORT char *msWriteMapToString(mapObj *map); MS_DLL_EXPORT char *msWriteClassToString(classObj *_class); MS_DLL_EXPORT char *msWriteStyleToString(styleObj *style); MS_DLL_EXPORT char *msWriteLabelToString(labelObj *label); MS_DLL_EXPORT char *msWriteWebToString(webObj *web); MS_DLL_EXPORT char *msWriteScalebarToString(scalebarObj *scalebar); MS_DLL_EXPORT char *msWriteQueryMapToString(queryMapObj *querymap); MS_DLL_EXPORT char *msWriteReferenceMapToString(referenceMapObj *ref); MS_DLL_EXPORT char *msWriteLegendToString(legendObj *legend); MS_DLL_EXPORT char *msWriteClusterToString(clusterObj *cluster); MS_DLL_EXPORT int msEvalRegex(const char *e, const char *s); #ifdef USE_MSFREE MS_DLL_EXPORT void msFree(void *p); #else #define msFree free #endif MS_DLL_EXPORT char **msTokenizeMap(char *filename, int *numtokens); MS_DLL_EXPORT int msInitLabelCache(labelCacheObj *cache); MS_DLL_EXPORT int msFreeLabelCache(labelCacheObj *cache); MS_DLL_EXPORT int msCheckConnection(layerObj * layer); /* connection pooling functions (mapfile.c) */ MS_DLL_EXPORT void msCloseConnections(mapObj *map); MS_DLL_EXPORT void msOGRInitialize(void); MS_DLL_EXPORT void msOGRCleanup(void); MS_DLL_EXPORT void msGDALCleanup(void); MS_DLL_EXPORT void msGDALInitialize(void); MS_DLL_EXPORT imageObj *msDrawScalebar(mapObj *map); /* in mapscale.c */ MS_DLL_EXPORT int msCalculateScale(rectObj extent, int units, int width, int height, double resolution, double *scaledenom); MS_DLL_EXPORT double GetDeltaExtentsUsingScale(double scale, int units, double centerLat, int width, double resolution); MS_DLL_EXPORT double Pix2Georef(int nPixPos, int nPixMin, int nPixMax, double dfGeoMin, double dfGeoMax, int bULisYOrig); MS_DLL_EXPORT double Pix2LayerGeoref(mapObj *map, layerObj *layer, int value); MS_DLL_EXPORT double msInchesPerUnit(int units, double center_lat); MS_DLL_EXPORT int msEmbedScalebar(mapObj *map, imageObj *img); MS_DLL_EXPORT int msPointInRect(const pointObj *p, const rectObj *rect); /* in mapsearch.c */ MS_DLL_EXPORT int msRectOverlap(const rectObj *a, const rectObj *b); MS_DLL_EXPORT int msRectContained(const rectObj *a, const rectObj *b); MS_DLL_EXPORT int msRectIntersect(rectObj *a, const rectObj *b); MS_DLL_EXPORT void msRectToFormattedString(rectObj *rect, char *format, char *buffer, int buffer_length); MS_DLL_EXPORT void msPointToFormattedString(pointObj *point, const char*format, char *buffer, int buffer_length); MS_DLL_EXPORT int msIsDegenerateShape(shapeObj *shape); MS_DLL_EXPORT void msMergeRect(rectObj *a, rectObj *b); MS_DLL_EXPORT double msDistancePointToPoint(pointObj *a, pointObj *b); MS_DLL_EXPORT double msSquareDistancePointToPoint(pointObj *a, pointObj *b); MS_DLL_EXPORT double msDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b); MS_DLL_EXPORT double msSquareDistancePointToSegment(pointObj *p, pointObj *a, pointObj *b); MS_DLL_EXPORT double msDistancePointToShape(pointObj *p, shapeObj *shape); MS_DLL_EXPORT double msSquareDistancePointToShape(pointObj *p, shapeObj *shape); MS_DLL_EXPORT double msDistanceSegmentToSegment(pointObj *pa, pointObj *pb, pointObj *pc, pointObj *pd); MS_DLL_EXPORT double msDistanceShapeToShape(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msIntersectSegments(const pointObj *a, const pointObj *b, const pointObj *c, const pointObj *d); MS_DLL_EXPORT int msPointInPolygon(pointObj *p, lineObj *c); MS_DLL_EXPORT int msIntersectMultipointPolygon(shapeObj *multipoint, shapeObj *polygon); MS_DLL_EXPORT int msIntersectPointPolygon(pointObj *p, shapeObj *polygon); MS_DLL_EXPORT int msIntersectPolylinePolygon(shapeObj *line, shapeObj *poly); MS_DLL_EXPORT int msIntersectPolygons(shapeObj *p1, shapeObj *p2); MS_DLL_EXPORT int msIntersectPolylines(shapeObj *line1, shapeObj *line2); MS_DLL_EXPORT int msInitQuery(queryObj *query); /* in mapquery.c */ MS_DLL_EXPORT void msFreeQuery(queryObj *query); MS_DLL_EXPORT int msSaveQuery(mapObj *map, char *filename, int results); MS_DLL_EXPORT int msLoadQuery(mapObj *map, char *filename); MS_DLL_EXPORT int msExecuteQuery(mapObj *map); MS_DLL_EXPORT int msQueryByIndex(mapObj *map); /* various query methods, all rely on the queryObj hung off the mapObj */ MS_DLL_EXPORT int msQueryByAttributes(mapObj *map); MS_DLL_EXPORT int msQueryByPoint(mapObj *map); MS_DLL_EXPORT int msQueryByRect(mapObj *map); MS_DLL_EXPORT int msQueryByFeatures(mapObj *map); MS_DLL_EXPORT int msQueryByShape(mapObj *map); MS_DLL_EXPORT int msQueryByFilter(mapObj *map); MS_DLL_EXPORT int msGetQueryResultBounds(mapObj *map, rectObj *bounds); MS_DLL_EXPORT int msIsLayerQueryable(layerObj *lp); MS_DLL_EXPORT void msQueryFree(mapObj *map, int qlayer); /* todo: rename */ MS_DLL_EXPORT int msRasterQueryByShape(mapObj *map, layerObj *layer, shapeObj *selectshape); MS_DLL_EXPORT int msRasterQueryByRect(mapObj *map, layerObj *layer, rectObj queryRect); MS_DLL_EXPORT int msRasterQueryByPoint(mapObj *map, layerObj *layer, int mode, pointObj p, double buffer, int maxresults ); /* in mapstring.c */ MS_DLL_EXPORT void msStringTrim(char *str); MS_DLL_EXPORT void msStringTrimBlanks(char *string); MS_DLL_EXPORT char *msStringTrimLeft(char *string); MS_DLL_EXPORT char *msStringChop(char *string); MS_DLL_EXPORT void msStringTrimEOL(char *string); MS_DLL_EXPORT char *msReplaceSubstring(char *str, const char *old, const char *sznew); MS_DLL_EXPORT void msReplaceChar(char *str, char old, char sznew); MS_DLL_EXPORT char *msCaseReplaceSubstring(char *str, const char *old, const char *sznew); MS_DLL_EXPORT char *msStripPath(char *fn); MS_DLL_EXPORT char *msGetPath(char *fn); MS_DLL_EXPORT char *msBuildPath(char *pszReturnPath, const char *abs_path, const char *path); MS_DLL_EXPORT char *msBuildPath3(char *pszReturnPath, const char *abs_path, const char *path1, const char *path2); MS_DLL_EXPORT char *msTryBuildPath(char *szReturnPath, const char *abs_path, const char *path); MS_DLL_EXPORT char *msTryBuildPath3(char *szReturnPath, const char *abs_path, const char *path1, const char *path2); MS_DLL_EXPORT char **msStringSplit(const char *string, char cd, int *num_tokens); MS_DLL_EXPORT char ** msStringSplitComplex( const char * pszString, const char * pszDelimiters, int *num_tokens, int nFlags); MS_DLL_EXPORT int msStringArrayContains(char **array, const char *element, int numElements); MS_DLL_EXPORT char **msStringTokenize( const char *pszLine, const char *pszDelim, int *num_tokens, int preserve_quote); MS_DLL_EXPORT int msCountChars(char *str, char ch); MS_DLL_EXPORT char *msLongToString(long value); MS_DLL_EXPORT char *msDoubleToString(double value, int force_f); MS_DLL_EXPORT char *msIntToString(int value); MS_DLL_EXPORT void msStringToUpper(char *string); MS_DLL_EXPORT void msStringToLower(char *string); MS_DLL_EXPORT void msStringInitCap(char *string); MS_DLL_EXPORT void msStringFirstCap(char *string); MS_DLL_EXPORT int msEncodeChar(const char); MS_DLL_EXPORT char *msEncodeUrlExcept(const char*, const char); MS_DLL_EXPORT char *msEncodeUrl(const char*); MS_DLL_EXPORT char *msEscapeJSonString(const char* pszJSonString); MS_DLL_EXPORT char *msEncodeHTMLEntities(const char *string); MS_DLL_EXPORT void msDecodeHTMLEntities(const char *string); MS_DLL_EXPORT int msIsXMLTagValid(const char *string); MS_DLL_EXPORT char *msStringConcatenate(char *pszDest, const char *pszSrc); MS_DLL_EXPORT char *msJoinStrings(char **array, int arrayLength, const char *delimeter); MS_DLL_EXPORT char *msHashString(const char *pszStr); MS_DLL_EXPORT char *msCommifyString(char *str); MS_DLL_EXPORT int msHexToInt(char *hex); MS_DLL_EXPORT char *msGetEncodedString(const char *string, const char *encoding); MS_DLL_EXPORT char *msConvertWideStringToUTF8 (const wchar_t* string, const char* encoding); MS_DLL_EXPORT int msGetNextGlyph(const char **in_ptr, char *out_string); MS_DLL_EXPORT int msGetNumGlyphs(const char *in_ptr); MS_DLL_EXPORT int msGetUnicodeEntity(const char *inptr, unsigned int *unicode); MS_DLL_EXPORT int msStringIsInteger(const char *string); MS_DLL_EXPORT int msUTF8ToUniChar(const char *str, unsigned int *chPtr); /* maptclutf.c */ MS_DLL_EXPORT char* msStringEscape( const char * pszString ); MS_DLL_EXPORT int msStringInArray( const char * pszString, char **array, int numelements); #ifndef HAVE_STRRSTR MS_DLL_EXPORT char *strrstr(const char *string, const char *find); #endif /* NEED_STRRSTR */ #ifndef HAVE_STRCASESTR MS_DLL_EXPORT char *strcasestr(const char *s, const char *find); #endif /* NEED_STRCASESTR */ #ifndef HAVE_STRNCASECMP MS_DLL_EXPORT int strncasecmp(const char *s1, const char *s2, int len); #endif /* NEED_STRNCASECMP */ #ifndef HAVE_STRCASECMP MS_DLL_EXPORT int strcasecmp(const char *s1, const char *s2); #endif /* NEED_STRCASECMP */ #ifndef HAVE_STRLCAT MS_DLL_EXPORT size_t strlcat(char *dst, const char *src, size_t siz); #endif /* NEED_STRLCAT */ #ifndef HAVE_STRLCPY MS_DLL_EXPORT size_t strlcpy(char *dst, const char *src, size_t siz); #endif /* NEED_STRLCAT */ MS_DLL_EXPORT char *msStrdup( const char * pszString ); #include "hittest.h" /* in mapsymbol.c */ /* Use this function *only* with mapfile loading phase */ MS_DLL_EXPORT int loadSymbolSet(symbolSetObj *symbolset, mapObj *map); /* Use this threadsafe wrapper everywhere else */ MS_DLL_EXPORT int msLoadSymbolSet(symbolSetObj *symbolset, mapObj *map); MS_DLL_EXPORT int msCopySymbol(symbolObj *dst, symbolObj *src, mapObj *map); MS_DLL_EXPORT int msCopySymbolSet(symbolSetObj *dst, symbolSetObj *src, mapObj *map); MS_DLL_EXPORT int msCopyHashTable(hashTableObj *dst, hashTableObj *src); MS_DLL_EXPORT void msInitSymbolSet(symbolSetObj *symbolset); MS_DLL_EXPORT symbolObj *msGrowSymbolSet( symbolSetObj *symbolset ); MS_DLL_EXPORT int msAddImageSymbol(symbolSetObj *symbolset, char *filename); MS_DLL_EXPORT int msFreeSymbolSet(symbolSetObj *symbolset); MS_DLL_EXPORT int msFreeSymbol(symbolObj *symbol); MS_DLL_EXPORT int msAddNewSymbol(mapObj *map, char *name); MS_DLL_EXPORT int msAppendSymbol(symbolSetObj *symbolset, symbolObj *symbol); MS_DLL_EXPORT symbolObj *msRemoveSymbol(symbolSetObj *symbolset, int index); MS_DLL_EXPORT int msSaveSymbolSet(symbolSetObj *symbolset, const char *filename); MS_DLL_EXPORT int msLoadImageSymbol(symbolObj *symbol, const char *filename); MS_DLL_EXPORT int msPreloadImageSymbol(rendererVTableObj *renderer, symbolObj *symbol); MS_DLL_EXPORT int msPreloadSVGSymbol(symbolObj *symbol); MS_DLL_EXPORT symbolObj *msRotateSymbol(symbolObj *symbol, double angle); MS_DLL_EXPORT int WARN_UNUSED msGetCharacterSize(mapObj *map, char* font, int size, char *character, rectObj *r); MS_DLL_EXPORT int WARN_UNUSED msGetMarkerSize(mapObj *map, styleObj *style, double *width, double *height, double scalefactor); /* MS_DLL_EXPORT int msGetCharacterSize(char *character, int size, char *font, rectObj *rect); */ MS_DLL_EXPORT double msSymbolGetDefaultSize(symbolObj *s); MS_DLL_EXPORT void freeImageCache(struct imageCacheObj *ic); MS_DLL_EXPORT imageObj WARN_UNUSED *msDrawLegend(mapObj *map, int scale_independent, map_hittest *hittest); /* in maplegend.c */ MS_DLL_EXPORT int WARN_UNUSED msLegendCalcSize(mapObj *map, int scale_independent, int *size_x, int *size_y, int *alayers, int numl_ayer, map_hittest *hittest, double resolutionfactor); MS_DLL_EXPORT int WARN_UNUSED msEmbedLegend(mapObj *map, imageObj *img); MS_DLL_EXPORT int WARN_UNUSED msDrawLegendIcon(mapObj* map, layerObj* lp, classObj* myClass, int width, int height, imageObj *img, int dstX, int dstY, int scale_independant, class_hittest *hittest); MS_DLL_EXPORT imageObj WARN_UNUSED *msCreateLegendIcon(mapObj* map, layerObj* lp, classObj* myClass, int width, int height, int scale_independant); MS_DLL_EXPORT int msLoadFontSet(fontSetObj *fontSet, mapObj *map); /* in maplabel.c */ MS_DLL_EXPORT int msInitFontSet(fontSetObj *fontset); MS_DLL_EXPORT int msFreeFontSet(fontSetObj *fontset); MS_DLL_EXPORT int WARN_UNUSED msGetTextSymbolSize(mapObj *map, textSymbolObj *ts, rectObj *r); MS_DLL_EXPORT int WARN_UNUSED msGetStringSize(mapObj *map, labelObj *label, int size, char *string, rectObj *r); MS_DLL_EXPORT int WARN_UNUSED msAddLabel(mapObj *map, imageObj *image, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize, textSymbolObj *ts); MS_DLL_EXPORT int WARN_UNUSED msAddLabelGroup(mapObj *map, imageObj *image, layerObj *layer, int classindex, shapeObj *shape, pointObj *point, double featuresize); MS_DLL_EXPORT void insertRenderedLabelMember(mapObj *map, labelCacheMemberObj *cachePtr); MS_DLL_EXPORT int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, label_bounds *lb, int current_priority, int current_label); MS_DLL_EXPORT int msTestLabelCacheLeaderCollision(mapObj *map, pointObj *lp1, pointObj *lp2); MS_DLL_EXPORT labelCacheMemberObj *msGetLabelCacheMember(labelCacheObj *labelcache, int i); MS_DLL_EXPORT void msFreeShape(shapeObj *shape); /* in mapprimitive.c */ int msGetShapeRAMSize(shapeObj* shape); /* in mapprimitive.c */ MS_DLL_EXPORT void msFreeLabelPathObj(labelPathObj *path); MS_DLL_EXPORT shapeObj *msShapeFromWKT(const char *string); MS_DLL_EXPORT char *msShapeToWKT(shapeObj *shape); MS_DLL_EXPORT void msInitShape(shapeObj *shape); MS_DLL_EXPORT void msShapeDeleteLine( shapeObj *shape, int line ); MS_DLL_EXPORT int msCopyShape(shapeObj *from, shapeObj *to); MS_DLL_EXPORT int msIsOuterRing(shapeObj *shape, int r); MS_DLL_EXPORT int *msGetOuterList(shapeObj *shape); MS_DLL_EXPORT int *msGetInnerList(shapeObj *shape, int r, int *outerlist); MS_DLL_EXPORT void msComputeBounds(shapeObj *shape); MS_DLL_EXPORT void msRectToPolygon(rectObj rect, shapeObj *poly); MS_DLL_EXPORT void msClipPolylineRect(shapeObj *shape, rectObj rect); MS_DLL_EXPORT void msClipPolygonRect(shapeObj *shape, rectObj rect); MS_DLL_EXPORT void msTransformShape(shapeObj *shape, rectObj extent, double cellsize, imageObj *image); MS_DLL_EXPORT void msTransformPoint(pointObj *point, rectObj *extent, double cellsize, imageObj *image); MS_DLL_EXPORT void msOffsetPointRelativeTo(pointObj *point, layerObj *layer); MS_DLL_EXPORT void msOffsetShapeRelativeTo(shapeObj *shape, layerObj *layer); MS_DLL_EXPORT void msTransformShapeSimplify(shapeObj *shape, rectObj extent, double cellsize); MS_DLL_EXPORT void msTransformShapeToPixelSnapToGrid(shapeObj *shape, rectObj extent, double cellsize, double grid_resolution); MS_DLL_EXPORT void msTransformShapeToPixelRound(shapeObj *shape, rectObj extent, double cellsize); MS_DLL_EXPORT void msTransformShapeToPixelDoublePrecision(shapeObj *shape, rectObj extent, double cellsize); #ifndef SWIG struct line_lengths { double *segment_lengths; double total_length; int longest_segment_index; }; struct polyline_lengths { struct line_lengths *ll; double total_length; int longest_line_index; int longest_segment_line_index, longest_segment_point_index; }; struct label_auto_result { pointObj *label_points; double *angles; int num_label_points; }; struct label_follow_result { textSymbolObj **follow_labels; int num_follow_labels; struct label_auto_result lar; }; #endif MS_DLL_EXPORT void msTransformPixelToShape(shapeObj *shape, rectObj extent, double cellsize); MS_DLL_EXPORT void msPolylineComputeLineSegments(shapeObj *shape, struct polyline_lengths *pll); MS_DLL_EXPORT int msPolylineLabelPath(mapObj *map, imageObj *image, shapeObj *p, textSymbolObj *ts, labelObj *label, struct label_follow_result *lfr); MS_DLL_EXPORT int WARN_UNUSED msPolylineLabelPoint(mapObj *map, shapeObj *p, textSymbolObj *ts, labelObj *label, struct label_auto_result *lar, double resolutionfactor); MS_DLL_EXPORT int WARN_UNUSED msLineLabelPath(mapObj *map, imageObj *img, lineObj *p, textSymbolObj *ts, struct line_lengths *ll, struct label_follow_result *lfr, labelObj *lbl); MS_DLL_EXPORT int WARN_UNUSED msLineLabelPoint(mapObj *map, lineObj *p, textSymbolObj *ts, struct line_lengths *ll, struct label_auto_result *lar, labelObj *lbl, double resolutionfactor); MS_DLL_EXPORT int msPolygonLabelPoint(shapeObj *p, pointObj *lp, double min_dimension); MS_DLL_EXPORT int msAddLine(shapeObj *p, lineObj *new_line); MS_DLL_EXPORT int msAddLineDirectly(shapeObj *p, lineObj *new_line); MS_DLL_EXPORT int msAddPointToLine(lineObj *line, pointObj *point ); MS_DLL_EXPORT double msGetPolygonArea(shapeObj *p); MS_DLL_EXPORT int msGetPolygonCentroid(shapeObj *p, pointObj *lp, double *miny, double *maxy); MS_DLL_EXPORT int msDrawRasterLayer(mapObj *map, layerObj *layer, imageObj *image); /* in mapraster.c */ MS_DLL_EXPORT imageObj *msDrawReferenceMap(mapObj *map); /* mapbits.c - bit array handling functions and macros */ #define MS_ARRAY_BIT 32 #define MS_GET_BIT(array,i) (array[i>>5] & (1 <<(i & 0x3f))) #define MS_SET_BIT(array,i) {array[i>>5] |= (1 <<(i & 0x3f));} #define MS_CLR_BIT(array,i) {array[i>>5] &= (~(1 <<(i & 0x3f)));} MS_DLL_EXPORT size_t msGetBitArraySize(int numbits); /* in mapbits.c */ MS_DLL_EXPORT ms_bitarray msAllocBitArray(int numbits); MS_DLL_EXPORT int msGetBit(ms_const_bitarray array, int index); MS_DLL_EXPORT void msSetBit(ms_bitarray array, int index, int value); MS_DLL_EXPORT void msSetAllBits(ms_bitarray array, int index, int value); MS_DLL_EXPORT void msFlipBit(ms_bitarray array, int index); MS_DLL_EXPORT int msGetNextBit(ms_const_bitarray array, int index, int size); /* maplayer.c - layerObj api */ MS_DLL_EXPORT int msLayerInitItemInfo(layerObj *layer); MS_DLL_EXPORT void msLayerFreeItemInfo(layerObj *layer); MS_DLL_EXPORT int msLayerOpen(layerObj *layer); /* in maplayer.c */ MS_DLL_EXPORT int msLayerApplyScaletokens(layerObj *layer, double scale); MS_DLL_EXPORT int msLayerRestoreFromScaletokens(layerObj *layer); MS_DLL_EXPORT int msClusterLayerOpen(layerObj *layer); /* in mapcluster.c */ MS_DLL_EXPORT int msLayerIsOpen(layerObj *layer); MS_DLL_EXPORT void msLayerClose(layerObj *layer); MS_DLL_EXPORT void msLayerFreeExpressions(layerObj *layer); MS_DLL_EXPORT int msLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery); MS_DLL_EXPORT int msLayerGetItemIndex(layerObj *layer, char *item); MS_DLL_EXPORT int msLayerWhichItems(layerObj *layer, int get_all, const char *metadata); MS_DLL_EXPORT int msLayerNextShape(layerObj *layer, shapeObj *shape); MS_DLL_EXPORT int msLayerGetItems(layerObj *layer); MS_DLL_EXPORT int msLayerSetItems(layerObj *layer, char **items, int numitems); MS_DLL_EXPORT int msLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record); MS_DLL_EXPORT int msLayerGetShapeCount(layerObj *layer, rectObj rect, projectionObj *rectProjection); MS_DLL_EXPORT int msLayerGetExtent(layerObj *layer, rectObj *extent); MS_DLL_EXPORT int msLayerSetExtent( layerObj *layer, double minx, double miny, double maxx, double maxy); MS_DLL_EXPORT int msLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape); MS_DLL_EXPORT int msLayerGetFeatureStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape); MS_DLL_EXPORT void msLayerAddProcessing( layerObj *layer, const char *directive ); MS_DLL_EXPORT void msLayerSetProcessingKey( layerObj *layer, const char *key, const char *value); MS_DLL_EXPORT char *msLayerGetProcessing( layerObj *layer, int proc_index); MS_DLL_EXPORT char *msLayerGetProcessingKey( layerObj *layer, const char *); MS_DLL_EXPORT int msLayerClearProcessing( layerObj *layer ); MS_DLL_EXPORT void msLayerSubstituteProcessing( layerObj *layer, const char *from, const char *to ); MS_DLL_EXPORT char *msLayerGetFilterString( layerObj *layer ); MS_DLL_EXPORT int msLayerEncodeShapeAttributes( layerObj *layer, shapeObj *shape); MS_DLL_EXPORT int msLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem); MS_DLL_EXPORT int msLayerSupportsCommonFilters(layerObj *layer); MS_DLL_EXPORT const char *msExpressionTokenToString(int token); MS_DLL_EXPORT int msTokenizeExpression(expressionObj *expression, char **list, int *listsize); MS_DLL_EXPORT int msLayerSetTimeFilter(layerObj *lp, const char *timestring, const char *timefield); MS_DLL_EXPORT int msLayerMakeBackticsTimeFilter(layerObj *lp, const char *timestring, const char *timefield); MS_DLL_EXPORT int msLayerMakePlainTimeFilter(layerObj *lp, const char *timestring, const char *timefield); MS_DLL_EXPORT int msLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); MS_DLL_EXPORT int msLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex); /* maplayer.c */ MS_DLL_EXPORT int msLayerGetNumFeatures(layerObj *layer); MS_DLL_EXPORT int msLayerSupportsPaging(layerObj *layer); MS_DLL_EXPORT void msLayerEnablePaging(layerObj *layer, int value); MS_DLL_EXPORT int msLayerGetPaging(layerObj *layer); MS_DLL_EXPORT int msLayerGetMaxFeaturesToDraw(layerObj *layer, outputFormatObj *format); MS_DLL_EXPORT char *msLayerEscapeSQLParam(layerObj *layer, const char* pszString); MS_DLL_EXPORT char *msLayerEscapePropertyName(layerObj *layer, const char* pszString); int msLayerSupportsSorting(layerObj *layer); void msLayerSetSort(layerObj *layer, const sortByClause* sortBy); MS_DLL_EXPORT char* msLayerBuildSQLOrderBy(layerObj *layer); /* These are special because SWF is using these */ int msOGRLayerNextShape(layerObj *layer, shapeObj *shape); int msOGRLayerGetItems(layerObj *layer); void msOGRLayerFreeItemInfo(layerObj *layer); int msOGRLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record); int msOGRLayerGetExtent(layerObj *layer, rectObj *extent); #ifdef USE_OGR MS_DLL_EXPORT int msOGRGeometryToShape(OGRGeometryH hGeometry, shapeObj *shape, OGRwkbGeometryType type); #endif /* USE_OGR */ MS_DLL_EXPORT int msInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msConnectLayer(layerObj *layer, const int connectiontype, const char *library_str); MS_DLL_EXPORT int msINLINELayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msSHPLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msTiledSHPLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msOGRLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msPostGISLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msOracleSpatialLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msWFSLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msGraticuleLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msRASTERLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msUVRASTERLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msContourLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msPluginLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT int msUnionLayerInitializeVirtualTable(layerObj *layer); MS_DLL_EXPORT void msPluginFreeVirtualTableFactory(void); int LayerDefaultGetShapeCount(layerObj *layer, rectObj rect, projectionObj *rectProjection); void msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes(layerObj* layer, mapObj* map); /* ==================================================================== */ /* Prototypes for functions in mapdraw.c */ /* ==================================================================== */ MS_DLL_EXPORT imageObj *msPrepareImage(mapObj *map, int allow_nonsquare); MS_DLL_EXPORT imageObj *msDrawMap(mapObj *map, int querymap); MS_DLL_EXPORT int msLayerIsVisible(mapObj *map, layerObj *layer); MS_DLL_EXPORT int msDrawLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msDrawWMSLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msDrawWFSLayer(mapObj *map, layerObj *layer, imageObj *image); #define MS_DRAWMODE_FEATURES 0x00001 #define MS_DRAW_FEATURES(mode) (MS_DRAWMODE_FEATURES&(mode)) #define MS_DRAWMODE_LABELS 0x00002 #define MS_DRAW_LABELS(mode) (MS_DRAWMODE_LABELS&(mode)) #define MS_DRAWMODE_SINGLESTYLE 0x00004 #define MS_DRAW_SINGLESTYLE(mode) (MS_DRAWMODE_SINGLESTYLE&(mode)) #define MS_DRAWMODE_QUERY 0x00008 #define MS_DRAW_QUERY(mode) (MS_DRAWMODE_QUERY&(mode)) #define MS_DRAWMODE_UNCLIPPEDLABELS 0x00010 #define MS_DRAW_UNCLIPPED_LABELS(mode) (MS_DRAWMODE_UNCLIPPEDLABELS&(mode)) #define MS_DRAWMODE_UNCLIPPEDLINES 0x00020 #define MS_DRAW_UNCLIPPED_LINES(mode) (MS_DRAWMODE_UNCLIPPEDLINES&(mode)) MS_DLL_EXPORT int WARN_UNUSED msDrawShape(mapObj *map, layerObj *layer, shapeObj *shape, imageObj *image, int style, int mode); MS_DLL_EXPORT int WARN_UNUSED msDrawPoint(mapObj *map, layerObj *layer, pointObj *point, imageObj *image, int classindex, char *labeltext); /*Range Support*/ typedef enum { MS_COLORSPACE_RGB, MS_COLORSPACE_HSL } colorspace; MS_DLL_EXPORT int msShapeToRange(styleObj *style, shapeObj *shape); MS_DLL_EXPORT int msValueToRange(styleObj *style, double fieldVal, colorspace cs); MS_DLL_EXPORT int WARN_UNUSED msDrawMarkerSymbol(mapObj *map, imageObj *image, pointObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT int WARN_UNUSED msDrawLineSymbol(mapObj *map, imageObj *image, shapeObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT int WARN_UNUSED msDrawShadeSymbol(mapObj *map, imageObj *image, shapeObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT int WARN_UNUSED msCircleDrawLineSymbol(mapObj *map, imageObj *image, pointObj *p, double r, styleObj *style, double scalefactor); MS_DLL_EXPORT int WARN_UNUSED msCircleDrawShadeSymbol(mapObj *map, imageObj *image, pointObj *p, double r, styleObj *style, double scalefactor); MS_DLL_EXPORT int WARN_UNUSED msDrawPieSlice(mapObj *map, imageObj *image, pointObj *p, styleObj *style, double radius, double start, double end); MS_DLL_EXPORT int WARN_UNUSED msDrawLabelBounds(mapObj *map, imageObj *image, label_bounds *bnds, styleObj *style, double scalefactor); MS_DLL_EXPORT void msOutlineRenderingPrepareStyle(styleObj *pStyle, mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT void msOutlineRenderingRestoreStyle(styleObj *pStyle, mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int WARN_UNUSED msDrawLabel(mapObj *map, imageObj *image, pointObj labelPnt, char *string, labelObj *label, double scalefactor); MS_DLL_EXPORT int WARN_UNUSED msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbolObj *ts); MS_DLL_EXPORT int WARN_UNUSED msDrawLabelCache(mapObj *map, imageObj *image); MS_DLL_EXPORT void msImageStartLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT void msImageEndLayer(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT void msDrawStartShape(mapObj *map, layerObj *layer, imageObj *image, shapeObj *shape); MS_DLL_EXPORT void msDrawEndShape(mapObj *map, layerObj *layer, imageObj *image, shapeObj *shape); /* ==================================================================== */ /* End of Prototypes for functions in mapdraw.c */ /* ==================================================================== */ /* ==================================================================== */ /* Prototypes for functions in mapgeomutil.cpp */ /* ==================================================================== */ MS_DLL_EXPORT shapeObj *msRasterizeArc(double x0, double y0, double radius, double startAngle, double endAngle, int isSlice); MS_DLL_EXPORT int msHatchPolygon(imageObj *img, shapeObj *poly, double spacing, double width, double *pattern, int patternlength, double angle, colorObj *color); /* ==================================================================== */ /* Prototypes for functions in mapimagemap.c */ /* ==================================================================== */ MS_DLL_EXPORT imageObj *msImageCreateIM(int width, int height, outputFormatObj *format, char *imagepath, char *imageurl, double resolution, double defresolution); MS_DLL_EXPORT void msImageStartLayerIM(mapObj *map, layerObj *layer, imageObj *image); MS_DLL_EXPORT int msSaveImageIM(imageObj* img, const char *filename, outputFormatObj *format); MS_DLL_EXPORT void msFreeImageIM(imageObj* img); MS_DLL_EXPORT void msDrawMarkerSymbolIM(mapObj *map, imageObj* img, pointObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT void msDrawLineSymbolIM(mapObj *map, imageObj* img, shapeObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT void msDrawShadeSymbolIM(mapObj *map, imageObj* img, shapeObj *p, styleObj *style, double scalefactor); MS_DLL_EXPORT int msDrawTextIM(mapObj *map, imageObj* img, pointObj labelPnt, char *string, labelObj *label, double scalefactor); /* ==================================================================== */ /* End of Prototypes for functions in mapimagemap.c */ /* ==================================================================== */ /* various JOIN functions (in mapjoin.c) */ MS_DLL_EXPORT int msJoinConnect(layerObj *layer, joinObj *join); MS_DLL_EXPORT int msJoinPrepare(joinObj *join, shapeObj *shape); MS_DLL_EXPORT int msJoinNext(joinObj *join); MS_DLL_EXPORT int msJoinClose(joinObj *join); /*in mapraster.c */ int msDrawRasterLayerLowCheckIfMustDraw(mapObj *map, layerObj *layer); void* msDrawRasterLayerLowOpenDataset(mapObj *map, layerObj *layer, const char* filename, char szPath[MS_MAXPATHLEN], char** p_decrypted_path); void msDrawRasterLayerLowCloseDataset(layerObj *layer, void* hDataset); int msDrawRasterLayerLowWithDataset(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void* hDatasetIn ); MS_DLL_EXPORT int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb ); MS_DLL_EXPORT int msGetClass(layerObj *layer, colorObj *color, int colormap_index); MS_DLL_EXPORT int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue ); int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry ); /* in mapdrawgdal.c */ MS_DLL_EXPORT int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void *hDSVoid ); MS_DLL_EXPORT int msGetGDALGeoTransform(void *hDS, mapObj *map, layerObj *layer, double *padfGeoTransform ); MS_DLL_EXPORT int *msGetGDALBandList( layerObj *layer, void *hDS, int max_bands, int *band_count ); MS_DLL_EXPORT double msGetGDALNoDataValue( layerObj *layer, void *hBand, int *pbGotNoData ); /* in interpolation.c */ MS_DLL_EXPORT int msComputeKernelDensityDataset(mapObj *map, imageObj *image, layerObj *layer, void **hDSvoid, void **cleanup_ptr); MS_DLL_EXPORT int msCleanupKernelDensityDataset(mapObj *map, imageObj *image, layerObj *layer, void *cleanup_ptr); /* in mapchart.c */ MS_DLL_EXPORT int msDrawChartLayer(mapObj *map, layerObj *layer, imageObj *image); /* ==================================================================== */ /* End of prototypes for functions in mapgd.c */ /* ==================================================================== */ /* ==================================================================== */ /* Prototypes for functions in maputil.c */ /* ==================================================================== */ MS_DLL_EXPORT int msScaleInBounds(double scale, double minscale, double maxscale); MS_DLL_EXPORT void *msSmallMalloc( size_t nSize ); MS_DLL_EXPORT void * msSmallRealloc( void * pData, size_t nNewSize ); MS_DLL_EXPORT void *msSmallCalloc( size_t nCount, size_t nSize ); MS_DLL_EXPORT int msIntegerInArray(const int value, int *array, int numelements); MS_DLL_EXPORT int msExtentsOverlap(mapObj *map, layerObj *layer); MS_DLL_EXPORT char *msBuildOnlineResource(mapObj *map, cgiRequestObj *req); /* For mapswf */ MS_DLL_EXPORT int getRgbColor(mapObj *map,int i,int *r,int *g,int *b); /* maputil.c */ MS_DLL_EXPORT int msBindLayerToShape(layerObj *layer, shapeObj *shape, int querymapMode); MS_DLL_EXPORT int msValidateContexts(mapObj *map); MS_DLL_EXPORT int msEvalContext(mapObj *map, layerObj *layer, char *context); MS_DLL_EXPORT int msEvalExpression(layerObj *layer, shapeObj *shape, expressionObj *expression, int itemindex); MS_DLL_EXPORT int msShapeGetClass(layerObj *layer, mapObj *map, shapeObj *shape, int *classgroup, int numclasses); MS_DLL_EXPORT int msShapeCheckSize(shapeObj *shape, double minfeaturesize); MS_DLL_EXPORT char* msShapeGetLabelAnnotation(layerObj *layer, shapeObj *shape, labelObj *lbl); MS_DLL_EXPORT int msGetLabelStatus(mapObj *map, layerObj *layer, shapeObj *shape, labelObj *lbl); MS_DLL_EXPORT int msAdjustImage(rectObj rect, int *width, int *height); MS_DLL_EXPORT char *msEvalTextExpression(expressionObj *expr, shapeObj *shape); MS_DLL_EXPORT char *msEvalTextExpressionJSonEscape(expressionObj *expr, shapeObj *shape); MS_DLL_EXPORT double msAdjustExtent(rectObj *rect, int width, int height); MS_DLL_EXPORT int msConstrainExtent(rectObj *bounds, rectObj *rect, double overlay); MS_DLL_EXPORT int *msGetLayersIndexByGroup(mapObj *map, char *groupname, int *nCount); MS_DLL_EXPORT unsigned char *msSaveImageBuffer(imageObj* image, int *size_ptr, outputFormatObj *format); MS_DLL_EXPORT shapeObj* msOffsetPolyline(shapeObj* shape, double offsetx, double offsety); MS_DLL_EXPORT int msMapSetLayerProjections(mapObj* map); /* Functions to chnage the drawing order of the layers. */ /* Defined in mapobject.c */ MS_DLL_EXPORT int msMoveLayerUp(mapObj *map, int nLayerIndex); MS_DLL_EXPORT int msMoveLayerDown(mapObj *map, int nLayerIndex); MS_DLL_EXPORT int msSetLayersdrawingOrder(mapObj *self, int *panIndexes); MS_DLL_EXPORT int msInsertLayer(mapObj *map, layerObj *layer, int nIndex); MS_DLL_EXPORT layerObj *msRemoveLayer(mapObj *map, int nIndex); /* Defined in layerobject.c */ MS_DLL_EXPORT int msInsertClass(layerObj *layer,classObj *classobj,int nIndex); MS_DLL_EXPORT classObj *msRemoveClass(layerObj *layer, int nIndex); MS_DLL_EXPORT int msMoveClassUp(layerObj *layer, int nClassIndex); MS_DLL_EXPORT int msMoveClassDown(layerObj *layer, int nClassIndex); /* classobject.c */ MS_DLL_EXPORT int msAddLabelToClass(classObj *classo, labelObj *label); MS_DLL_EXPORT labelObj *msRemoveLabelFromClass(classObj *classo, int nLabelIndex); MS_DLL_EXPORT int msMoveStyleUp(classObj *classo, int nStyleIndex); MS_DLL_EXPORT int msMoveStyleDown(classObj *classo, int nStyleIndex); MS_DLL_EXPORT int msDeleteStyle(classObj *classo, int nStyleIndex); MS_DLL_EXPORT int msInsertStyle(classObj *classo, styleObj *style, int nStyleIndex); MS_DLL_EXPORT styleObj *msRemoveStyle(classObj *classo, int index); /* maplabel.c */ MS_DLL_EXPORT int msInsertLabelStyle(labelObj *label, styleObj *style, int nStyleIndex); MS_DLL_EXPORT int msMoveLabelStyleUp(labelObj *label, int nStyleIndex); MS_DLL_EXPORT int msMoveLabelStyleDown(labelObj *label, int nStyleIndex); MS_DLL_EXPORT int msDeleteLabelStyle(labelObj *label, int nStyleIndex); MS_DLL_EXPORT styleObj *msRemoveLabelStyle(labelObj *label, int nStyleIndex); /* Measured shape utility functions. */ MS_DLL_EXPORT pointObj *msGetPointUsingMeasure(shapeObj *shape, double m); MS_DLL_EXPORT pointObj *msGetMeasureUsingPoint(shapeObj *shape, pointObj *point); MS_DLL_EXPORT char **msGetAllGroupNames(mapObj* map, int *numTok); MS_DLL_EXPORT char *msTmpFile(mapObj *map, const char *mappath, const char *tmppath, const char *ext); MS_DLL_EXPORT char *msTmpPath(mapObj *map, const char *mappath, const char *tmppath); MS_DLL_EXPORT char *msTmpFilename(const char *ext); MS_DLL_EXPORT void msForceTmpFileBase( const char *new_base ); MS_DLL_EXPORT imageObj *msImageCreate(int width, int height, outputFormatObj *format, char *imagepath, char *imageurl, double resolution, double defresolution, colorObj *bg); MS_DLL_EXPORT void msAlphaBlend( unsigned char red_src, unsigned char green_src, unsigned char blue_src, unsigned char alpha_src, unsigned char *red_dst, unsigned char *green_dst, unsigned char *blue_dst, unsigned char *alpha_dst ); MS_DLL_EXPORT void msAlphaBlendPM( unsigned char red_src, unsigned char green_src, unsigned char blue_src, unsigned char alpha_src, unsigned char *red_dst, unsigned char *green_dst, unsigned char *blue_dst, unsigned char *alpha_dst ); MS_DLL_EXPORT void msRGBtoHSL(colorObj *rgb, double *h, double *s, double *l); MS_DLL_EXPORT void msHSLtoRGB(double h, double s, double l, colorObj *rgb); MS_DLL_EXPORT int msCheckParentPointer(void* p, char* objname); MS_DLL_EXPORT int *msAllocateValidClassGroups(layerObj *lp, int *nclasses); MS_DLL_EXPORT void msFreeRasterBuffer(rasterBufferObj *b); MS_DLL_EXPORT void msSetLayerOpacity(layerObj *layer, int opacity); void msMapSetLanguageSpecificConnection(mapObj* map, const char* validated_language); MS_DLL_EXPORT shapeObj* msGeneralize(shapeObj * shape, double tolerance); /* ==================================================================== */ /* End of prototypes for functions in maputil.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapoutput.c */ /* ==================================================================== */ MS_DLL_EXPORT void msApplyDefaultOutputFormats( mapObj * ); MS_DLL_EXPORT void msFreeOutputFormat( outputFormatObj * ); MS_DLL_EXPORT int msGetOutputFormatIndex(mapObj *map, const char *imagetype); MS_DLL_EXPORT int msRemoveOutputFormat(mapObj *map, const char *imagetype); MS_DLL_EXPORT int msAppendOutputFormat(mapObj *map, outputFormatObj *format); MS_DLL_EXPORT outputFormatObj *msSelectOutputFormat( mapObj *map, const char *imagetype ); MS_DLL_EXPORT void msApplyOutputFormat( outputFormatObj **target, outputFormatObj *format, int transparent, int interlaced, int imagequality ); MS_DLL_EXPORT const char *msGetOutputFormatOption( outputFormatObj *format, const char *optionkey, const char *defaultresult ); MS_DLL_EXPORT outputFormatObj *msCreateDefaultOutputFormat( mapObj *map, const char *driver, const char *name ); MS_DLL_EXPORT int msPostMapParseOutputFormatSetup( mapObj *map ); MS_DLL_EXPORT void msSetOutputFormatOption( outputFormatObj *format, const char *key, const char *value ); MS_DLL_EXPORT void msGetOutputFormatMimeList( mapObj *map, char **mime_list, int max_mime ); MS_DLL_EXPORT void msGetOutputFormatMimeListImg( mapObj *map, char **mime_list, int max_mime ); MS_DLL_EXPORT void msGetOutputFormatMimeListWMS( mapObj *map, char **mime_list, int max_mime ); MS_DLL_EXPORT outputFormatObj *msCloneOutputFormat( outputFormatObj *format ); MS_DLL_EXPORT int msOutputFormatValidate( outputFormatObj *format, int issue_error ); void msOutputFormatResolveFromImage( mapObj *map, imageObj* img ); /* ==================================================================== */ /* End of prototypes for functions in mapoutput.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapgdal.c */ /* ==================================================================== */ MS_DLL_EXPORT int msSaveImageGDAL( mapObj *map, imageObj *image, const char *filename ); MS_DLL_EXPORT int msInitDefaultGDALOutputFormat( outputFormatObj *format ); #ifdef USE_GDAL void msCleanVSIDir( const char *pszDir ); #endif /* ==================================================================== */ /* prototypes for functions in mapogroutput.c */ /* ==================================================================== */ MS_DLL_EXPORT int msInitDefaultOGROutputFormat( outputFormatObj *format ); MS_DLL_EXPORT int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders ); /* ==================================================================== */ /* Public prototype for mapogr.cpp functions. */ /* ==================================================================== */ int MS_DLL_EXPORT msOGRLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery); int MS_DLL_EXPORT msOGRLayerOpen(layerObj *layer, const char *pszOverrideConnection); /* in mapogr.cpp */ int MS_DLL_EXPORT msOGRLayerClose(layerObj *layer); char MS_DLL_EXPORT *msOGRShapeToWKT(shapeObj *shape); shapeObj MS_DLL_EXPORT *msOGRShapeFromWKT(const char *string); int msOGRUpdateStyleFromString(mapObj *map, layerObj *layer, classObj *c, const char *stylestring); /* ==================================================================== */ /* prototypes for functions in mapcopy */ /* ==================================================================== */ MS_DLL_EXPORT int msCopyMap(mapObj *dst, mapObj *src); MS_DLL_EXPORT int msCopyLayer(layerObj *dst, layerObj *src); MS_DLL_EXPORT int msCopyScaleToken(scaleTokenObj *src, scaleTokenObj *dst); MS_DLL_EXPORT int msCopyPoint(pointObj *dst, pointObj *src); MS_DLL_EXPORT int msCopyFontSet(fontSetObj *dst, fontSetObj *src, mapObj *map); MS_DLL_EXPORT void copyProperty(void *dst, void *src, int size); MS_DLL_EXPORT char *copyStringProperty(char **dst, char *src); MS_DLL_EXPORT int msCopyClass(classObj *dst, classObj *src, layerObj *layer); MS_DLL_EXPORT int msCopyStyle(styleObj *dst, styleObj *src); MS_DLL_EXPORT int msCopyLabel(labelObj *dst, labelObj *src); MS_DLL_EXPORT int msCopyLabelLeader(labelLeaderObj *dst, labelLeaderObj *src); MS_DLL_EXPORT int msCopyLine(lineObj *dst, lineObj *src); MS_DLL_EXPORT int msCopyProjection(projectionObj *dst, projectionObj *src); MS_DLL_EXPORT int msCopyProjectionExtended(projectionObj *dst, projectionObj *src, char ** args, int num_args); int msCopyExpression(expressionObj *dst, expressionObj *src); int msCopyProjection(projectionObj *dst, projectionObj *src); MS_DLL_EXPORT int msCopyRasterBuffer(rasterBufferObj *dst, const rasterBufferObj *src); /* ==================================================================== */ /* end prototypes for functions in mapcopy */ /* ==================================================================== */ /* ==================================================================== */ /* mappool.c: connection pooling API. */ /* ==================================================================== */ MS_DLL_EXPORT void *msConnPoolRequest( layerObj *layer ); MS_DLL_EXPORT void msConnPoolRelease( layerObj *layer, void * ); MS_DLL_EXPORT void msConnPoolRegister( layerObj *layer, void *conn_handle, void (*close)( void * ) ); MS_DLL_EXPORT void msConnPoolCloseUnreferenced( void ); MS_DLL_EXPORT void msConnPoolFinalCleanup( void ); /* ==================================================================== */ /* prototypes for functions in mapcpl.c */ /* ==================================================================== */ MS_DLL_EXPORT const char *msGetBasename( const char *pszFullFilename ); MS_DLL_EXPORT void *msGetSymbol(const char *pszLibrary, const char *pszEntryPoint); /* ==================================================================== */ /* prototypes for functions in mapgeos.c */ /* ==================================================================== */ MS_DLL_EXPORT void msGEOSSetup(void); MS_DLL_EXPORT void msGEOSCleanup(void); MS_DLL_EXPORT void msGEOSFreeGeometry(shapeObj *shape); MS_DLL_EXPORT shapeObj *msGEOSShapeFromWKT(const char *string); MS_DLL_EXPORT char *msGEOSShapeToWKT(shapeObj *shape); MS_DLL_EXPORT void msGEOSFreeWKT(char* pszGEOSWKT); MS_DLL_EXPORT shapeObj *msGEOSBuffer(shapeObj *shape, double width); MS_DLL_EXPORT shapeObj *msGEOSSimplify(shapeObj *shape, double tolerance); MS_DLL_EXPORT shapeObj *msGEOSTopologyPreservingSimplify(shapeObj *shape, double tolerance); MS_DLL_EXPORT shapeObj *msGEOSConvexHull(shapeObj *shape); MS_DLL_EXPORT shapeObj *msGEOSBoundary(shapeObj *shape); MS_DLL_EXPORT pointObj *msGEOSGetCentroid(shapeObj *shape); MS_DLL_EXPORT shapeObj *msGEOSUnion(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT shapeObj *msGEOSIntersection(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT shapeObj *msGEOSDifference(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT shapeObj *msGEOSSymDifference(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT shapeObj *msGEOSOffsetCurve(shapeObj *p, double offset); MS_DLL_EXPORT int msGEOSContains(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSOverlaps(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSWithin(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSCrosses(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSIntersects(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSTouches(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSEquals(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT int msGEOSDisjoint(shapeObj *shape1, shapeObj *shape2); MS_DLL_EXPORT double msGEOSArea(shapeObj *shape); MS_DLL_EXPORT double msGEOSLength(shapeObj *shape); MS_DLL_EXPORT double msGEOSDistance(shapeObj *shape1, shapeObj *shape2); /* ==================================================================== */ /* prototypes for functions in mapcrypto.c */ /* ==================================================================== */ MS_DLL_EXPORT int msGenerateEncryptionKey(unsigned char *k); MS_DLL_EXPORT int msReadEncryptionKeyFromFile(const char *keyfile, unsigned char *k); MS_DLL_EXPORT void msEncryptStringWithKey(const unsigned char *key, const char *in, char *out); MS_DLL_EXPORT void msDecryptStringWithKey(const unsigned char *key, const char *in, char *out); MS_DLL_EXPORT char *msDecryptStringTokens(mapObj *map, const char *in); MS_DLL_EXPORT void msHexEncode(const unsigned char *in, char *out, int numbytes); MS_DLL_EXPORT int msHexDecode(const char *in, unsigned char *out, int numchars); /* ==================================================================== */ /* prototypes for functions in mapxmp.c */ /* ==================================================================== */ MS_DLL_EXPORT int msXmpPresent(mapObj *map); MS_DLL_EXPORT int msXmpWrite(mapObj *map, const char *filename); /* ==================================================================== */ /* prototypes for functions in mapgeomtransform.c */ /* ==================================================================== */ enum MS_GEOMTRANSFORM_TYPE { MS_GEOMTRANSFORM_NONE, MS_GEOMTRANSFORM_EXPRESSION, MS_GEOMTRANSFORM_START, MS_GEOMTRANSFORM_END, MS_GEOMTRANSFORM_VERTICES, MS_GEOMTRANSFORM_BBOX, MS_GEOMTRANSFORM_CENTROID, MS_GEOMTRANSFORM_BUFFER, MS_GEOMTRANSFORM_CONVEXHULL, MS_GEOMTRANSFORM_LABELPOINT, MS_GEOMTRANSFORM_LABELPOLY, MS_GEOMTRANSFORM_LABELCENTER }; MS_DLL_EXPORT int msDrawTransformedShape(mapObj *map, imageObj *image, shapeObj *shape, styleObj *style, double scalefactor); MS_DLL_EXPORT void msStyleSetGeomTransform(styleObj *s, char *transform); MS_DLL_EXPORT char *msStyleGetGeomTransform(styleObj *style); MS_DLL_EXPORT int msGeomTransformShape(mapObj *map, layerObj *layer, shapeObj *shape); /* ==================================================================== */ /* end of prototypes for functions in mapgeomtransform.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapgraticule.c */ /* ==================================================================== */ MS_DLL_EXPORT graticuleIntersectionObj *msGraticuleLayerGetIntersectionPoints(mapObj *map, layerObj *layer); MS_DLL_EXPORT void msGraticuleLayerFreeIntersectionPoints( graticuleIntersectionObj *psValue); /* ==================================================================== */ /* end of prototypes for functions in mapgraticule.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapsmoothing.c */ /* ==================================================================== */ MS_DLL_EXPORT shapeObj* msSmoothShapeSIA(shapeObj *shape, int ss, int si, char *preprocessing); /* ==================================================================== */ /* end of prototypes for functions in mapsmoothing.c */ /* ==================================================================== */ /* ==================================================================== */ /* prototypes for functions in mapv8.cpp */ /* ==================================================================== */ #ifdef USE_V8_MAPSCRIPT MS_DLL_EXPORT void msV8CreateContext(mapObj *map); MS_DLL_EXPORT void msV8ContextSetLayer(mapObj *map, layerObj *layer); MS_DLL_EXPORT void msV8FreeContext(mapObj *map); MS_DLL_EXPORT char* msV8GetFeatureStyle(mapObj *map, const char *filename, layerObj *layer, shapeObj *shape); MS_DLL_EXPORT shapeObj *msV8TransformShape(shapeObj *shape, const char* filename); #endif /* ==================================================================== */ /* end of prototypes for functions in mapv8.cpp */ /* ==================================================================== */ #endif #ifndef SWIG /* * strokeStyleObj */ typedef struct { double width; /* line width in pixels */ /* line pattern, e.g. dots, dashes, etc.. */ int patternlength; double pattern[MS_MAXPATTERNLENGTH]; double patternoffset; /* must be a valid color if not NULL */ /* color.alpha must be used if supported by the renderer */ colorObj *color; int linecap; /* MS_CJC_TRIANGLE, MS_CJC_SQUARE, MS_CJC_ROUND, MS_CJC_BUTT */ int linejoin; /* MS_CJC_BEVEL MS_CJC_ROUND MS_CJC_MITER */ double linejoinmaxsize; } strokeStyleObj; #define INIT_STROKE_STYLE(s) { (s).width=0; (s).patternlength=0; (s).color=NULL; (s).linecap=MS_CJC_ROUND; (s).linejoin=MS_CJC_ROUND; (s).linejoinmaxsize=0;} /* * symbolStyleObj */ typedef struct { /* must be valid colors if not NULL */ /* color.alpha must be used if supported by the renderer */ colorObj *color; colorObj *backgroundcolor; double outlinewidth; colorObj *outlinecolor; /* scalefactor to be applied on the tile or symbol*/ double scale; /* rotation to apply on the symbol (and the tile?) * in radians */ double rotation; /* the gap to space symbols appart when used as a polygon tile */ double gap; /* style object, necessary for vector type renderers to be able * to render symbols through other renders such as cairo/agg */ styleObj *style; } symbolStyleObj; #define INIT_SYMBOL_STYLE(s) {(s).color=NULL; (s).backgroundcolor=NULL; (s).outlinewidth=0; (s).outlinecolor=NULL; (s).scale=1.0; (s).rotation=0; (s).style=NULL;} struct tileCacheObj { symbolObj *symbol; int width; int height; colorObj color, outlinecolor, backgroundcolor; double outlinewidth, rotation,scale; imageObj *image; tileCacheObj *next; }; /* * labelStyleObj */ typedef struct { /* full paths to truetype font file */ char* fonts[MS_MAX_LABEL_FONTS]; int numfonts; double size; double rotation; colorObj *color; double outlinewidth; colorObj *outlinecolor; } labelStyleObj; #define INIT_LABEL_STYLE(s) {memset(&(s),'\0',sizeof(labelStyleObj));} #endif #ifndef SWIG MS_DLL_EXPORT int msInitializeDummyRenderer(rendererVTableObj *vtable); MS_DLL_EXPORT int msInitializeRendererVTable(outputFormatObj *outputformat); MS_DLL_EXPORT int msPopulateRendererVTableCairoRaster( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableCairoSVG( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableCairoPDF( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableOGL( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableAGG( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableUTFGrid( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableKML( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableOGR( rendererVTableObj *renderer ); MS_DLL_EXPORT int msPopulateRendererVTableMVT( rendererVTableObj *renderer ); MS_DLL_EXPORT int msMVTWriteTile( mapObj *map, int sendheaders ); #ifdef USE_CAIRO MS_DLL_EXPORT void msCairoCleanup(void); #endif /* allocate 50k for starters */ #define MS_DEFAULT_BUFFER_ALLOC 50000 typedef struct _autobuffer { unsigned char *data; size_t size; size_t available; size_t _next_allocation_size; } bufferObj; /* in mapimageio.c */ int msQuantizeRasterBuffer(rasterBufferObj *rb, unsigned int *reqcolors, rgbaPixel *palette, rgbaPixel *forced_palette, int num_forced_palette_entries, unsigned int *palette_scaling_maxval); int msClassifyRasterBuffer(rasterBufferObj *rb, rasterBufferObj *qrb); int msSaveRasterBuffer(mapObj *map, rasterBufferObj *data, FILE *stream, outputFormatObj *format); int msSaveRasterBufferToBuffer(rasterBufferObj *data, bufferObj *buffer, outputFormatObj *format); int msLoadMSRasterBufferFromFile(char *path, rasterBufferObj *rb); /* in mapagg.cpp */ void msApplyBlurringCompositingFilter(rasterBufferObj *rb, unsigned int radius); int WARN_UNUSED msApplyCompositingFilter(mapObj *map, rasterBufferObj *rb, CompositingFilter *filter); void msBufferInit(bufferObj *buffer); void msBufferResize(bufferObj *buffer, size_t target_size); MS_DLL_EXPORT void msBufferFree(bufferObj *buffer); MS_DLL_EXPORT void msBufferAppend(bufferObj *buffer, void *data, size_t length); typedef struct { int charWidth, charHeight; } fontMetrics; struct rendererVTableObj { int supports_pixel_buffer; int supports_clipping; int supports_svg; int use_imagecache; enum MS_TRANSFORM_MODE default_transform_mode; enum MS_TRANSFORM_MODE transform_mode; double default_approximation_scale; double approximation_scale; void *renderer_data; int WARN_UNUSED (*renderLine)(imageObj *img, shapeObj *p, strokeStyleObj *style); int WARN_UNUSED (*renderPolygon)(imageObj *img, shapeObj *p, colorObj *color); int WARN_UNUSED (*renderPolygonTiled)(imageObj *img, shapeObj *p, imageObj *tile); int WARN_UNUSED (*renderLineTiled)(imageObj *img, shapeObj *p, imageObj *tile); int WARN_UNUSED (*renderGlyphs)(imageObj *img, textPathObj *tp, colorObj *clr, colorObj *olcolor, int olwidth); int WARN_UNUSED (*renderText)(imageObj *img, pointObj *labelpnt, char *text, double angle, colorObj *clr, colorObj *olcolor, int olwidth); int WARN_UNUSED (*renderVectorSymbol)(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); int WARN_UNUSED (*renderPixmapSymbol)(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); int WARN_UNUSED (*renderEllipseSymbol)(imageObj *image, double x, double y, symbolObj *symbol, symbolStyleObj *style); int WARN_UNUSED (*renderSVGSymbol)(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); int WARN_UNUSED (*renderTile)(imageObj *img, imageObj *tile, double x, double y); int WARN_UNUSED (*loadImageFromFile)(char *path, rasterBufferObj *rb); int WARN_UNUSED (*getRasterBufferHandle)(imageObj *img, rasterBufferObj *rb); int WARN_UNUSED (*getRasterBufferCopy)(imageObj *img, rasterBufferObj *rb); int WARN_UNUSED (*initializeRasterBuffer)(rasterBufferObj *rb, int width, int height, int mode); int WARN_UNUSED (*mergeRasterBuffer)(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height); int WARN_UNUSED (*compositeRasterBuffer)(imageObj *dest, rasterBufferObj *overlay, CompositingOperation comp_op, int opacity); /* image i/o */ imageObj* WARN_UNUSED (*createImage)(int width, int height, outputFormatObj *format, colorObj* bg); int WARN_UNUSED (*saveImage)(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format); unsigned char* WARN_UNUSED (*saveImageBuffer)(imageObj *img, int *size_ptr, outputFormatObj *format); /*...*/ int (*startLayer)(imageObj *img, mapObj *map, layerObj *layer); int (*endLayer)(imageObj *img, mapObj *map, layerObj *layer); int (*startShape)(imageObj *img, shapeObj *shape); int (*endShape)(imageObj *img, shapeObj *shape); int (*setClip)(imageObj *img, rectObj clipRect); int (*resetClip)(imageObj *img); int (*freeImage)(imageObj *image); int (*freeSymbol)(symbolObj *symbol); int (*cleanup)(void *renderer_data); } ; MS_DLL_EXPORT int msRenderRasterizedSVGSymbol(imageObj* img, double x, double y, symbolObj* symbol, symbolStyleObj* style); #define MS_IMAGE_RENDERER(im) ((im)->format->vtable) #define MS_RENDERER_CACHE(renderer) ((renderer)->renderer_data) #define MS_IMAGE_RENDERER_CACHE(im) MS_RENDERER_CACHE(MS_IMAGE_RENDERER((im))) #define MS_MAP_RENDERER(map) ((map)->outputformat->vtable) shapeObj *msOffsetCurve(shapeObj *p, double offset); #if defined USE_GEOS && (GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 3)) shapeObj *msGEOSOffsetCurve(shapeObj *p, double offset); #endif int msOGRIsSpatialite(layerObj* layer); #endif /* SWIG */ #ifdef __cplusplus } #endif #endif /* MAP_H */ mapserver-7.4.3/mapservutil.c000066400000000000000000002214161357574274700163030ustar00rootroot00000000000000/****************************************************************************** * $id$ * * Project: MapServer * Purpose: MapServer CGI utility functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "mapserv.h" #include "maptime.h" #include "mapows.h" /* ** Enumerated types, keep the query modes in sequence and at the end of the enumeration (mode enumeration is in maptemplate.h). */ static int numModes = 23; static char *modeStrings[23] = {"BROWSE","ZOOMIN","ZOOMOUT","MAP","LEGEND","LEGENDICON","REFERENCE","SCALEBAR","COORDINATE", "QUERY","NQUERY","ITEMQUERY","ITEMNQUERY", "FEATUREQUERY","FEATURENQUERY","ITEMFEATUREQUERY","ITEMFEATURENQUERY", "INDEXQUERY","TILE","OWS", "WFS", "MAPLEGEND", "MAPLEGENDICON" }; int msCGIWriteLog(mapservObj *mapserv, int show_error) { FILE *stream; int i; time_t t; char szPath[MS_MAXPATHLEN]; if(!mapserv) return(MS_SUCCESS); if(!mapserv->map) return(MS_SUCCESS); if(!mapserv->map->web.log) return(MS_SUCCESS); if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, mapserv->map->web.log),"a")) == NULL) { msSetError(MS_IOERR, "%s", "msCGIWriteLog()", mapserv->map->web.log); return(MS_FAILURE); } t = time(NULL); fprintf(stream,"%s,",msStringChop(ctime(&t))); fprintf(stream,"%d,",(int)getpid()); if(getenv("REMOTE_ADDR") != NULL) fprintf(stream,"%s,",getenv("REMOTE_ADDR")); else fprintf(stream,"NULL,"); fprintf(stream,"%s,",mapserv->map->name); fprintf(stream,"%d,",mapserv->Mode); fprintf(stream,"%f %f %f %f,", mapserv->map->extent.minx, mapserv->map->extent.miny, mapserv->map->extent.maxx, mapserv->map->extent.maxy); fprintf(stream,"%f %f,", mapserv->mappnt.x, mapserv->mappnt.y); for(i=0; iNumLayers; i++) fprintf(stream, "%s ", mapserv->Layers[i]); fprintf(stream,","); if(show_error == MS_TRUE) msWriteError(stream); else fprintf(stream, "normal execution"); fprintf(stream,"\n"); fclose(stream); return(MS_SUCCESS); } void msCGIWriteError(mapservObj *mapserv) { errorObj *ms_error = msGetErrorObj(); if(!ms_error || ms_error->code == MS_NOERR || ms_error->isreported) { /* either we have no error, or it was already reported by other means */ return; } msCGIWriteLog(mapserv,MS_TRUE); if(!mapserv || !mapserv->map) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("\n"); msIO_printf("MapServer Message\n"); msIO_printf("\n", msGetVersion()); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf(""); return; } if((ms_error->code == MS_NOTFOUND) && (mapserv->map->web.empty)) { /* msRedirect(mapserv->map->web.empty); */ if(msReturnURL(mapserv, mapserv->map->web.empty, BROWSE) != MS_SUCCESS) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("\n"); msIO_printf("MapServer Message\n"); msIO_printf("\n", msGetVersion()); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf(""); } } else { if(mapserv->map->web.error) { /* msRedirect(mapserv->map->web.error); */ if(msReturnURL(mapserv, mapserv->map->web.error, BROWSE) != MS_SUCCESS) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("\n"); msIO_printf("MapServer Message\n"); msIO_printf("\n", msGetVersion()); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf(""); } } else { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("\n"); msIO_printf("MapServer Message\n"); msIO_printf("\n", msGetVersion()); msIO_printf("\n"); msWriteErrorXML(stdout); msIO_printf(""); } } } /* ** Converts a string (e.g. form parameter) to a double, first checking the format against ** a regular expression. returns an error if the format test fails. */ #define GET_NUMERIC(string,dbl) do { \ dbl = strtod((string), &strtoderr);\ if (*strtoderr) {\ msSetError(MS_TYPEERR, NULL, "GET_NUMERIC()");\ return MS_FAILURE;\ }\ } while (0) #define GET_NUMERIC_NO_ERROR(string,dbl) dbl = strtod((string), &strtoderr); #define FREE_TOKENS_ON_ERROR(ntok) if(!strtoderr) {\ msSetError(MS_TYPEERR, "invalid number", "msCGILoadForm()");\ msFreeCharArray(tokens,(ntok));\ return MS_FAILURE;\ } static void setClassGroup(layerObj *layer, char *classgroup) { int i; if(!layer || !classgroup) return; for(i=0; inumclasses; i++) { if(layer->class[i]->group && strcmp(layer->class[i]->group, classgroup) == 0) { msFree(layer->classgroup); layer->classgroup = msStrdup(classgroup); return; /* bail */ } } } /* ** Extract Map File name from params and load it. ** Returns map object or NULL on error. */ mapObj *msCGILoadMap(mapservObj *mapserv) { int i, j; mapObj *map = NULL; for(i=0; irequest->NumParams; i++) /* find the mapfile parameter first */ if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break; if(i == mapserv->request->NumParams) { char *ms_mapfile = getenv("MS_MAPFILE"); if(ms_mapfile) { map = msLoadMap(ms_mapfile,NULL); } else { msSetError(MS_WEBERR, "CGI variable \"map\" is not set.", "msCGILoadMap()"); /* no default, outta here */ return NULL; } } else { if(getenv(mapserv->request->ParamValues[i])) /* an environment variable references the actual file to use */ map = msLoadMap(getenv(mapserv->request->ParamValues[i]), NULL); else { /* by here we know the request isn't for something in an environment variable */ if(getenv("MS_MAP_NO_PATH")) { msSetError(MS_WEBERR, "Mapfile not found in environment variables and this server is not configured for full paths.", "msCGILoadMap()"); return NULL; } if(getenv("MS_MAP_PATTERN") && msEvalRegex(getenv("MS_MAP_PATTERN"), mapserv->request->ParamValues[i]) != MS_TRUE) { msSetError(MS_WEBERR, "Parameter 'map' value fails to validate.", "msCGILoadMap()"); return NULL; } /* ok to try to load now */ map = msLoadMap(mapserv->request->ParamValues[i], NULL); } } if(!map) return NULL; if(!msLookupHashTable(&(map->web.validation), "immutable")) { /* check for any %variable% substitutions here, also do any map_ changes, we do this here so WMS/WFS */ /* services can take advantage of these "vendor specific" extensions */ for(i=0; irequest->NumParams; i++) { /* ** a few CGI variables should be skipped altogether ** ** qstring: there is separate per layer validation for attribute queries and the substitution checks ** below conflict with that so we avoid it here */ if(strncasecmp(mapserv->request->ParamNames[i],"qstring",7) == 0) continue; /* check to see if there are any additions to the mapfile */ if(strncasecmp(mapserv->request->ParamNames[i],"map_",4) == 0 || strncasecmp(mapserv->request->ParamNames[i],"map.",4) == 0) { if(msUpdateMapFromURL(map, mapserv->request->ParamNames[i], mapserv->request->ParamValues[i]) != MS_SUCCESS) { msFreeMap(map); return NULL; } continue; } if(strncasecmp(mapserv->request->ParamNames[i],"classgroup",10) == 0) { /* #4207 */ for(j=0; jnumlayers; j++) { setClassGroup(GET_LAYER(map, j), mapserv->request->ParamValues[i]); } continue; } } msApplySubstitutions(map, mapserv->request->ParamNames, mapserv->request->ParamValues, mapserv->request->NumParams); msApplyDefaultSubstitutions(map); /* check to see if a ogc map context is passed as argument. if there */ /* is one load it */ for(i=0; irequest->NumParams; i++) { if(strcasecmp(mapserv->request->ParamNames[i],"context") == 0) { if(mapserv->request->ParamValues[i] && strlen(mapserv->request->ParamValues[i]) > 0) { if(strncasecmp(mapserv->request->ParamValues[i],"http",4) == 0) { if(msGetConfigOption(map, "CGI_CONTEXT_URL")) msLoadMapContextURL(map, mapserv->request->ParamValues[i], MS_FALSE); } else msLoadMapContext(map, mapserv->request->ParamValues[i], MS_FALSE); } } } } /* * RFC-42 HTTP Cookie Forwarding * Here we set the http_cookie_data metadata to handle the * HTTP Cookie Forwarding. The content of this metadata is the cookie * content. In the future, this metadata will probably be replaced * by an object that is part of the mapObject that would contain * information on the application status (such as cookie). */ if( mapserv->request->httpcookiedata != NULL ) { msInsertHashTable( &(map->web.metadata), "http_cookie_data", mapserv->request->httpcookiedata ); } return map; } /* ** Set operation mode. First look in MS_MODE env. var. as a ** default value that can be overridden by the mode=... CGI param. ** Returns silently, leaving mapserv->Mode unchanged if mode param not set. */ int msCGISetMode(mapservObj *mapserv) { const char *mode = NULL; int i, j; mode = getenv("MS_MODE"); for( i=0; irequest->NumParams; i++ ) { if(strcasecmp(mapserv->request->ParamNames[i], "mode") == 0) { mode = mapserv->request->ParamValues[i]; break; } } if (mode) { for(j=0; jMode = j; break; } } if(j == numModes) { msSetError(MS_WEBERR, "Invalid mode.", "msCGISetMode()"); return MS_FAILURE; } } if (mapserv->Mode >= 0) { int disabled = MS_FALSE; const char* enable_modes = msLookupHashTable(&mapserv->map->web.metadata, "ms_enable_modes"); if (!msOWSParseRequestMetadata(enable_modes, mode, &disabled) && disabled) { /* the current mode is disabled */ msSetError(MS_WEBERR, "The specified mode '%s' is not supported by the current map configuration", "msCGISetMode()", mode); return MS_FAILURE; } } return MS_SUCCESS; } /* ** Process CGI parameters. */ int msCGILoadForm(mapservObj *mapserv) { int i,n; char **tokens=NULL; int rosa_type=0; double tmpval; char *strtoderr; for(i=0; irequest->NumParams; i++) { /* now process the rest of the form variables */ if(strlen(mapserv->request->ParamValues[i]) == 0) continue; if(strcasecmp(mapserv->request->ParamNames[i],"icon") == 0) { mapserv->icon = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"queryfile") == 0) { mapserv->QueryFile = msStrdup(mapserv->request->ParamValues[i]); if(msValidateParameter(mapserv->QueryFile, msLookupHashTable(&(mapserv->map->web.validation), "queryfile"), NULL, NULL, NULL) != MS_SUCCESS) { msSetError(MS_WEBERR, "Parameter 'queryfile' value fails to validate.", "mapserv()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"savequery") == 0) { mapserv->savequery = MS_TRUE; continue; } /* Insecure as implemented, need to save someplace non accessible by everyone in the universe if(strcasecmp(mapserv->request->ParamNames[i],"savemap") == 0) { mapserv->savemap = MS_TRUE; continue; } */ if(strcasecmp(mapserv->request->ParamNames[i],"zoom") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->Zoom); if((mapserv->Zoom > MAXZOOM) || (mapserv->Zoom < MINZOOM)) { msSetError(MS_WEBERR, "Zoom value out of range.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"zoomdir") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],tmpval); mapserv->ZoomDirection = (int)tmpval; if((mapserv->ZoomDirection != -1) && (mapserv->ZoomDirection != 1) && (mapserv->ZoomDirection != 0)) { msSetError(MS_WEBERR, "Zoom direction must be 1, 0 or -1.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"zoomsize") == 0) { /* absolute zoom magnitude */ GET_NUMERIC(mapserv->request->ParamValues[i],tmpval); mapserv->ZoomSize = (int)tmpval; if((mapserv->ZoomSize > MAXZOOM) || (mapserv->ZoomSize < 1)) { msSetError(MS_WEBERR, "Invalid zoom size.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"imgext") == 0) { /* extent of an existing image in a web application */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 4) { msSetError(MS_WEBERR, "Not enough arguments for imgext.", "msCGILoadForm()"); msFreeCharArray(tokens,n); return MS_FAILURE; } GET_NUMERIC_NO_ERROR(tokens[0],mapserv->ImgExt.minx); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[1],mapserv->ImgExt.miny); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[2],mapserv->ImgExt.maxx); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[3],mapserv->ImgExt.maxy); FREE_TOKENS_ON_ERROR(4); msFreeCharArray(tokens, 4); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"searchmap") == 0) { mapserv->SearchMap = MS_TRUE; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"id") == 0) { if(msEvalRegex(IDPATTERN, mapserv->request->ParamValues[i]) == MS_FALSE) { msSetError(MS_WEBERR, "Parameter 'id' value fails to validate.", "msCGILoadForm()"); return MS_FAILURE; } strlcpy(mapserv->Id, mapserv->request->ParamValues[i], IDSIZE); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"mapext") == 0) { /* extent of the new map or query */ if(strncasecmp(mapserv->request->ParamValues[i],"shape",5) == 0) mapserv->UseShapes = MS_TRUE; else { tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 4) { msSetError(MS_WEBERR, "Not enough arguments for mapext.", "msCGILoadForm()"); msFreeCharArray(tokens,n); return MS_FAILURE; } GET_NUMERIC_NO_ERROR(tokens[0],mapserv->map->extent.minx); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[1],mapserv->map->extent.miny); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[2],mapserv->map->extent.maxx); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[3],mapserv->map->extent.maxy); FREE_TOKENS_ON_ERROR(4); msFreeCharArray(tokens, 4); #ifdef USE_PROJ /* * If there is a projection in the map file, and it is not lon/lat, and the * extents "look like" they *are* lon/lat, based on their size, * then convert the extents to the map file projection. * * DANGER: If the extents are legitimately in the mapfile projection * and coincidentally fall in the lon/lat range, bad things * will ensue. */ if(mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj) && (mapserv->map->extent.minx >= -180.0 && mapserv->map->extent.minx <= 180.0) && (mapserv->map->extent.miny >= -90.0 && mapserv->map->extent.miny <= 90.0) && (mapserv->map->extent.maxx >= -180.0 && mapserv->map->extent.maxx <= 180.0) && (mapserv->map->extent.maxy >= -90.0 && mapserv->map->extent.maxy <= 90.0)) { msProjectRect(&(mapserv->map->latlon), &(mapserv->map->projection), &(mapserv->map->extent)); /* extent is a in lat/lon */ } #endif if((mapserv->map->extent.minx != mapserv->map->extent.maxx) && (mapserv->map->extent.miny != mapserv->map->extent.maxy)) { /* extent seems ok */ mapserv->CoordSource = FROMUSERBOX; mapserv->QueryCoordSource = FROMUSERBOX; } } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"minx") == 0) { /* extent of the new map, in pieces */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.minx); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"maxx") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.maxx); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"miny") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.miny); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"maxy") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->map->extent.maxy); mapserv->CoordSource = FROMUSERBOX; mapserv->QueryCoordSource = FROMUSERBOX; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"mapxy") == 0) { /* user map coordinate */ if(strncasecmp(mapserv->request->ParamValues[i],"shape",5) == 0) { mapserv->UseShapes = MS_TRUE; } else { tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for mapxy.", "msCGILoadForm()"); msFreeCharArray(tokens,n); return MS_FAILURE; } GET_NUMERIC_NO_ERROR(tokens[0],mapserv->mappnt.x ); FREE_TOKENS_ON_ERROR(2); GET_NUMERIC_NO_ERROR(tokens[1],mapserv->mappnt.y ); FREE_TOKENS_ON_ERROR(2); msFreeCharArray(tokens, 2); #ifdef USE_PROJ if(mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj) && (mapserv->mappnt.x >= -180.0 && mapserv->mappnt.x <= 180.0) && (mapserv->mappnt.y >= -90.0 && mapserv->mappnt.y <= 90.0)) { msProjectPoint(&(mapserv->map->latlon), &(mapserv->map->projection), &mapserv->mappnt); /* point is a in lat/lon */ } #endif if(mapserv->CoordSource == NONE) { /* don't override previous settings (i.e. buffer or scale ) */ mapserv->CoordSource = FROMUSERPNT; mapserv->QueryCoordSource = FROMUSERPNT; } } continue; } /* ** Query shape consisting of map or image coordinates. It's almost identical processing so we'll do either in this block... */ if(strcasecmp(mapserv->request->ParamNames[i], "mapshape") == 0 || strcasecmp(mapserv->request->ParamNames[i], "imgshape") == 0) { if(strcasecmp(mapserv->request->ParamNames[i],"mapshape") == 0) mapserv->QueryCoordSource = FROMUSERSHAPE; else mapserv->QueryCoordSource = FROMIMGSHAPE; if(strchr(mapserv->request->ParamValues[i], '(') != NULL) { /* try WKT */ if((mapserv->map->query.shape = msShapeFromWKT(mapserv->request->ParamValues[i])) == NULL) { msSetError(MS_WEBERR, "WKT parse failed for mapshape/imgshape.", "msCGILoadForm()"); return MS_FAILURE; } } else { lineObj line= {0,NULL}; char **tmp=NULL; int n, j; tmp = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(n%2 != 0 || n<8) { /* n must be even and be at least 8 */ msSetError(MS_WEBERR, "Malformed polygon geometry for mapshape/imgshape.", "msCGILoadForm()"); msFreeCharArray(tmp,n); return MS_FAILURE; } line.numpoints = n/2; line.point = (pointObj *)msSmallMalloc(sizeof(pointObj)*line.numpoints); mapserv->map->query.shape = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(mapserv->map->query.shape); mapserv->map->query.shape->type = MS_SHAPE_POLYGON; for(j=0; jQueryCoordSource == FROMUSERSHAPE && mapserv->map->projection.proj && !pj_is_latlong(mapserv->map->projection.proj) && (line.point[j].x >= -180.0 && line.point[j].x <= 180.0) && (line.point[j].y >= -90.0 && line.point[j].y <= 90.0)) { msProjectPoint(&(mapserv->map->latlon), &(mapserv->map->projection), &line.point[j]); /* point is a in lat/lon */ } #endif } if(msAddLine(mapserv->map->query.shape, &line) == -1) { msFree(line.point); msFreeCharArray(tmp, n); return MS_FAILURE; } msFree(line.point); msFreeCharArray(tmp, n); } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"img.x") == 0) { /* mouse click, in pieces */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ImgPnt.x); if((mapserv->ImgPnt.x > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.x < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"img.y") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ImgPnt.y); if((mapserv->ImgPnt.y > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"imgxy") == 0) { /* mouse click, single variable */ if(mapserv->CoordSource == FROMIMGPNT) continue; tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for imgxy.", "msCGILoadForm()"); msFreeCharArray(tokens,n); return MS_FAILURE; } GET_NUMERIC_NO_ERROR(tokens[0],mapserv->ImgPnt.x ); FREE_TOKENS_ON_ERROR(2); GET_NUMERIC_NO_ERROR(tokens[1],mapserv->ImgPnt.y ); FREE_TOKENS_ON_ERROR(2); msFreeCharArray(tokens, 2); if((mapserv->ImgPnt.x > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.x < (-2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y > (2*mapserv->map->maxsize)) || (mapserv->ImgPnt.y < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Reference map coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } if(mapserv->CoordSource == NONE) { /* override nothing since this parameter is usually used to hold a default value */ mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"imgbox") == 0) { /* selection box (eg. mouse drag) */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 4) { msSetError(MS_WEBERR, "Not enough arguments for imgbox.", "msCGILoadForm()"); msFreeCharArray(tokens,n); return MS_FAILURE; } GET_NUMERIC_NO_ERROR(tokens[0],mapserv->ImgBox.minx); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[1],mapserv->ImgBox.miny); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[2],mapserv->ImgBox.maxx); FREE_TOKENS_ON_ERROR(4); GET_NUMERIC_NO_ERROR(tokens[3],mapserv->ImgBox.maxy); FREE_TOKENS_ON_ERROR(4); msFreeCharArray(tokens, 4); if((mapserv->ImgBox.minx != mapserv->ImgBox.maxx) && (mapserv->ImgBox.miny != mapserv->ImgBox.maxy)) { /* must not degenerate into a point */ mapserv->CoordSource = FROMIMGBOX; mapserv->QueryCoordSource = FROMIMGBOX; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"ref.x") == 0) { /* mouse click in reference image, in pieces */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->RefPnt.x); if((mapserv->RefPnt.x > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.x < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMREFPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"ref.y") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->RefPnt.y); if((mapserv->RefPnt.y > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.y < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMREFPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"refxy") == 0) { /* mouse click in reference image, single variable */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for imgxy.", "msCGILoadForm()"); msFreeCharArray(tokens,n); return MS_FAILURE; } GET_NUMERIC_NO_ERROR(tokens[0],mapserv->RefPnt.x); FREE_TOKENS_ON_ERROR(2); GET_NUMERIC_NO_ERROR(tokens[1],mapserv->RefPnt.y); FREE_TOKENS_ON_ERROR(2); msFreeCharArray(tokens, 2); if((mapserv->RefPnt.x > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.x < (-2*mapserv->map->maxsize)) || (mapserv->RefPnt.y > (2*mapserv->map->maxsize)) || (mapserv->RefPnt.y < (-2*mapserv->map->maxsize))) { msSetError(MS_WEBERR, "Reference map coordinate out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMREFPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"buffer") == 0) { /* radius (map units), actually 1/2 square side */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->Buffer); mapserv->CoordSource = FROMBUF; mapserv->QueryCoordSource = FROMUSERPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"scale") == 0 || strcasecmp(mapserv->request->ParamNames[i],"scaledenom") == 0) { /* scale for new map */ GET_NUMERIC(mapserv->request->ParamValues[i],mapserv->ScaleDenom); if(mapserv->ScaleDenom <= 0) { msSetError(MS_WEBERR, "Scale out of range.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMSCALE; mapserv->QueryCoordSource = FROMUSERPNT; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"imgsize") == 0) { /* size of existing image (pixels) */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for imgsize.", "msCGILoadForm()"); msFreeCharArray(tokens,n); return MS_FAILURE; } GET_NUMERIC_NO_ERROR(tokens[0],tmpval); FREE_TOKENS_ON_ERROR(2); mapserv->ImgCols = (int)tmpval; GET_NUMERIC_NO_ERROR(tokens[1],tmpval); FREE_TOKENS_ON_ERROR(2); mapserv->ImgRows = (int)tmpval; msFreeCharArray(tokens, 2); if(mapserv->ImgCols > mapserv->map->maxsize || mapserv->ImgRows > mapserv->map->maxsize || mapserv->ImgCols <= 0 || mapserv->ImgRows <= 0) { msSetError(MS_WEBERR, "Image size out of range.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"mapsize") == 0) { /* size of new map (pixels) */ tokens = msStringSplit(mapserv->request->ParamValues[i], ' ', &n); if(!tokens) { msSetError(MS_MEMERR, NULL, "msCGILoadForm()"); return MS_FAILURE; } if(n != 2) { msSetError(MS_WEBERR, "Not enough arguments for mapsize.", "msCGILoadForm()"); msFreeCharArray(tokens,n); return MS_FAILURE; } GET_NUMERIC_NO_ERROR(tokens[0],tmpval); FREE_TOKENS_ON_ERROR(2); mapserv->map->width = (int)tmpval; GET_NUMERIC_NO_ERROR(tokens[1],tmpval); FREE_TOKENS_ON_ERROR(2); mapserv->map->height = (int)tmpval; msFreeCharArray(tokens, 2); if(mapserv->map->width > mapserv->map->maxsize || mapserv->map->height > mapserv->map->maxsize || mapserv->map->width <= 0 || mapserv->map->height <= 0) { msSetError(MS_WEBERR, "Image size out of range.", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strncasecmp(mapserv->request->ParamNames[i],"layers", 6) == 0) { /* turn a set of layers, delimited by spaces, on */ /* If layers=all then turn on all layers */ if (strcasecmp(mapserv->request->ParamValues[i], "all") == 0) { int l; /* Reset NumLayers=0. If individual layers were already selected then free the previous values. */ for(l=0; lNumLayers; l++) msFree(mapserv->Layers[l]); mapserv->NumLayers=0; for(mapserv->NumLayers=0; mapserv->NumLayers < mapserv->map->numlayers; mapserv->NumLayers++) { if(msGrowMapservLayers(mapserv) == MS_FAILURE) return MS_FAILURE; if(GET_LAYER(mapserv->map, mapserv->NumLayers)->name) { mapserv->Layers[mapserv->NumLayers] = msStrdup(GET_LAYER(mapserv->map, mapserv->NumLayers)->name); } else { mapserv->Layers[mapserv->NumLayers] = msStrdup(""); } } } else { int num_layers=0, l; char **layers=NULL; layers = msStringSplit(mapserv->request->ParamValues[i], ' ', &(num_layers)); for(l=0; lLayers[mapserv->NumLayers++] = msStrdup(layers[l]); } msFreeCharArray(layers, num_layers); num_layers = 0; } continue; } if(strncasecmp(mapserv->request->ParamNames[i],"layer", 5) == 0) { /* turn a single layer/group on */ if(msGrowMapservLayers(mapserv) == MS_FAILURE) return MS_FAILURE; mapserv->Layers[mapserv->NumLayers] = msStrdup(mapserv->request->ParamValues[i]); mapserv->NumLayers++; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"qlayer") == 0) { /* layer to query (i.e search) */ mapserv->QueryLayer = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"qitem") == 0) { /* attribute to query on (optional) */ mapserv->QueryItem = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"qstring") == 0) { /* attribute query string */ mapserv->QueryString = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"qformat") == 0) { /* format to apply to query results (shortcut instead of having to use "map.web=QUERYFORMAT+foo") */ if(mapserv->map->web.queryformat) free(mapserv->map->web.queryformat); /* avoid leak */ mapserv->map->web.queryformat = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"slayer") == 0) { /* layer to select (for feature based search) */ mapserv->SelectLayer = msStrdup(mapserv->request->ParamValues[i]); continue; } if(strcasecmp(mapserv->request->ParamNames[i],"shapeindex") == 0) { /* used for index queries */ GET_NUMERIC(mapserv->request->ParamValues[i],tmpval); mapserv->ShapeIndex = (int)tmpval; continue; } if(strcasecmp(mapserv->request->ParamNames[i],"tileindex") == 0) { GET_NUMERIC(mapserv->request->ParamValues[i],tmpval); mapserv->TileIndex = (int)tmpval; continue; } /* -------------------------------------------------------------------- * The following code is used to support mode=tile * -------------------------------------------------------------------- */ if(strcasecmp(mapserv->request->ParamNames[i], "tilemode") == 0) { /* currently, only valid tilemode is "spheremerc" */ if( strcasecmp(mapserv->request->ParamValues[i], "gmap") == 0) { mapserv->TileMode = TILE_GMAP; } else if ( strcasecmp(mapserv->request->ParamValues[i], "ve") == 0 ) { mapserv->TileMode = TILE_VE; } else { msSetError(MS_WEBERR, "Invalid tilemode. Use one of: gmap, ve", "msCGILoadForm()"); return MS_FAILURE; } continue; } if(strcasecmp(mapserv->request->ParamNames[i],"tile") == 0) { if( strlen(mapserv->request->ParamValues[i]) < 1 ) { msSetError(MS_WEBERR, "Empty tile parameter.", "msCGILoadForm()"); return MS_FAILURE; } mapserv->CoordSource = FROMTILE; mapserv->TileCoords = msStrdup(mapserv->request->ParamValues[i]); continue; } /* -------------------------------------------------------------------- */ /* The following code is used to support the rosa applet (for */ /* more information on Rosa, please consult : */ /* http://www.maptools.org/rosa/) . */ /* This code was provided by Tim.Mackey@agso.gov.au. */ /* */ /* For Application using it can be seen at : */ /* http://www.agso.gov.au/map/pilbara/ */ /* */ /* -------------------------------------------------------------------- */ if(strcasecmp(mapserv->request->ParamNames[i],"INPUT_TYPE") == 0) { /* Rosa input type */ if(strcasecmp(mapserv->request->ParamValues[i],"auto_rect") == 0) { rosa_type=1; /* rectangle */ continue; } if(strcasecmp(mapserv->request->ParamValues[i],"auto_point") == 0) { rosa_type=2; /* point */ continue; } } if(strcasecmp(mapserv->request->ParamNames[i],"INPUT_COORD") == 0) { /* Rosa coordinates */ switch(rosa_type) { case 1: sscanf(mapserv->request->ParamValues[i],"%lf,%lf;%lf,%lf", &mapserv->ImgBox.minx,&mapserv->ImgBox.miny,&mapserv->ImgBox.maxx, &mapserv->ImgBox.maxy); if((mapserv->ImgBox.minx != mapserv->ImgBox.maxx) && (mapserv->ImgBox.miny != mapserv->ImgBox.maxy)) { mapserv->CoordSource = FROMIMGBOX; mapserv->QueryCoordSource = FROMIMGBOX; } else { mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; mapserv->ImgPnt.x=mapserv->ImgBox.minx; mapserv->ImgPnt.y=mapserv->ImgBox.miny; } break; case 2: sscanf(mapserv->request->ParamValues[i],"%lf,%lf",&mapserv->ImgPnt.x, &mapserv->ImgPnt.y); mapserv->CoordSource = FROMIMGPNT; mapserv->QueryCoordSource = FROMIMGPNT; break; } continue; } /* -------------------------------------------------------------------- */ /* end of code for Rosa support. */ /* -------------------------------------------------------------------- */ } /* next parameter */ if(mapserv->Mode == ZOOMIN) { mapserv->ZoomDirection = 1; mapserv->Mode = BROWSE; } if(mapserv->Mode == ZOOMOUT) { mapserv->ZoomDirection = -1; mapserv->Mode = BROWSE; } if(mapserv->ZoomSize != 0) { /* use direction and magnitude to calculate zoom */ if(mapserv->ZoomDirection == 0) { mapserv->fZoom = 1; } else { mapserv->fZoom = mapserv->ZoomSize*mapserv->ZoomDirection; if(mapserv->fZoom < 0) mapserv->fZoom = 1.0/MS_ABS(mapserv->fZoom); } } else { /* use single value for zoom */ if((mapserv->Zoom >= -1) && (mapserv->Zoom <= 1)) { mapserv->fZoom = 1; /* pan */ } else { if(mapserv->Zoom < 0) mapserv->fZoom = 1.0/MS_ABS(mapserv->Zoom); else mapserv->fZoom = mapserv->Zoom; } } if(mapserv->ImgRows == -1) mapserv->ImgRows = mapserv->map->height; if(mapserv->ImgCols == -1) mapserv->ImgCols = mapserv->map->width; if(mapserv->map->height == -1) mapserv->map->height = mapserv->ImgRows; if(mapserv->map->width == -1) mapserv->map->width = mapserv->ImgCols; return MS_SUCCESS; } int setExtentFromShapes(mapservObj *mapserv) { double dx, dy, cellsize; rectObj tmpext= {-1.0,-1.0,-1.0,-1.0}; pointObj tmppnt= {-1.0,-1.0}; msGetQueryResultBounds(mapserv->map, &(tmpext)); dx = tmpext.maxx - tmpext.minx; dy = tmpext.maxy - tmpext.miny; tmppnt.x = (tmpext.maxx + tmpext.minx)/2; tmppnt.y = (tmpext.maxy + tmpext.miny)/2; tmpext.minx -= dx*EXTENT_PADDING/2.0; tmpext.maxx += dx*EXTENT_PADDING/2.0; tmpext.miny -= dy*EXTENT_PADDING/2.0; tmpext.maxy += dy*EXTENT_PADDING/2.0; if(mapserv->ScaleDenom != 0) { /* apply the scale around the center point (tmppnt) */ cellsize = (mapserv->ScaleDenom/mapserv->map->resolution)/msInchesPerUnit(mapserv->map->units,0); /* user supplied a point and a scale */ tmpext.minx = tmppnt.x - cellsize*mapserv->map->width/2.0; tmpext.miny = tmppnt.y - cellsize*mapserv->map->height/2.0; tmpext.maxx = tmppnt.x + cellsize*mapserv->map->width/2.0; tmpext.maxy = tmppnt.y + cellsize*mapserv->map->height/2.0; } else if(mapserv->Buffer != 0) { /* apply the buffer around the center point (tmppnt) */ tmpext.minx = tmppnt.x - mapserv->Buffer; tmpext.miny = tmppnt.y - mapserv->Buffer; tmpext.maxx = tmppnt.x + mapserv->Buffer; tmpext.maxy = tmppnt.y + mapserv->Buffer; } /* in case we don't get usable extent at this point (i.e. single point result) */ if(!MS_VALID_EXTENT(tmpext)) { if(mapserv->map->web.minscaledenom > 0) { /* try web object minscale first */ cellsize = (mapserv->map->web.minscaledenom/mapserv->map->resolution)/msInchesPerUnit(mapserv->map->units,0); /* user supplied a point and a scale */ tmpext.minx = tmppnt.x - cellsize*mapserv->map->width/2.0; tmpext.miny = tmppnt.y - cellsize*mapserv->map->height/2.0; tmpext.maxx = tmppnt.x + cellsize*mapserv->map->width/2.0; tmpext.maxy = tmppnt.y + cellsize*mapserv->map->height/2.0; } else { msSetError(MS_WEBERR, "No way to generate a valid map extent from selected shapes.", "mapserv()"); return MS_FAILURE; } } mapserv->mappnt = tmppnt; mapserv->map->extent = mapserv->RawExt = tmpext; /* save unadjusted extent */ return MS_SUCCESS; } /* FIX: NEED ERROR CHECKING HERE FOR IMGPNT or MAPPNT */ void setCoordinate(mapservObj *mapserv) { double cellx,celly; cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows); mapserv->mappnt.x = MS_IMAGE2MAP_X(mapserv->ImgPnt.x, mapserv->ImgExt.minx, cellx); mapserv->mappnt.y = MS_IMAGE2MAP_Y(mapserv->ImgPnt.y, mapserv->ImgExt.maxy, celly); return; } int msCGIDispatchBrowseRequest(mapservObj *mapserv) { char *template = NULL; int i,status; for(i=0; irequest->NumParams; i++) /* find the template param value */ if (strcasecmp(mapserv->request->ParamNames[i], "template") == 0) template = mapserv->request->ParamValues[i]; if ( (!mapserv->map->web.template) && (template==NULL || (strcasecmp(template, "openlayers")!=0)) ) { msSetError(MS_WEBERR, "Traditional BROWSE mode requires a TEMPLATE in the WEB section, but none was provided.", "mapserv()"); return MS_FAILURE; } if(mapserv->QueryFile) { status = msLoadQuery(mapserv->map, mapserv->QueryFile); if(status != MS_SUCCESS) return MS_FAILURE; } status = setExtent(mapserv); if(status != MS_SUCCESS) return MS_FAILURE; status = checkWebScale(mapserv); if(status != MS_SUCCESS) return MS_FAILURE; /* -------------------------------------------------------------------- */ /* generate map, legend, scalebar and refernce images. */ /* -------------------------------------------------------------------- */ if(msGenerateImages(mapserv, MS_FALSE, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; if ( (template != NULL) && (strcasecmp(template, "openlayers")==0) ) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); if (msReturnOpenLayersPage(mapserv) != MS_SUCCESS) return MS_FAILURE; } else if(mapserv->QueryFile) { if(msReturnTemplateQuery(mapserv, mapserv->map->web.queryformat, NULL) != MS_SUCCESS) return MS_FAILURE; } else { if(TEMPLATE_TYPE(mapserv->map->web.template) == MS_FILE) { /* if thers's an html template, then use it */ if(mapserv->sendheaders) { msIO_setHeader("Content-Type","%s", mapserv->map->web.browseformat); /* write MIME header */ msIO_sendHeaders(); } if(msReturnPage(mapserv, mapserv->map->web.template, BROWSE, NULL) != MS_SUCCESS) return MS_FAILURE; } else { if(msReturnURL(mapserv, mapserv->map->web.template, BROWSE) != MS_SUCCESS) return MS_FAILURE; } } return MS_SUCCESS; } int msCGIDispatchCoordinateRequest(mapservObj *mapserv) { setCoordinate(mapserv); /* mouse click => map coord */ msIO_printf("Your \"click\" corresponds to (approximately): (%g, %g).", mapserv->mappnt.x, mapserv->mappnt.y); #ifdef USE_PROJ if(mapserv->map->projection.proj != NULL && !pj_is_latlong(mapserv->map->projection.proj) ) { pointObj p=mapserv->mappnt; msProjectPoint(&(mapserv->map->projection), &(mapserv->map->latlon), &p); msIO_printf("Computed lat/lon value is (%g, %g).\n",p.x, p.y); } #endif return MS_SUCCESS; } int msCGIDispatchQueryRequest(mapservObj *mapserv) { int status,i,j; char buffer[1024]; if(mapserv->QueryFile) { /* already got a completed query */ status = msLoadQuery(mapserv->map, mapserv->QueryFile); if(status != MS_SUCCESS) return MS_FAILURE; } else { if((mapserv->QueryLayerIndex = msGetLayerIndex(mapserv->map, mapserv->QueryLayer)) != -1) /* force the query layer on */ GET_LAYER(mapserv->map, mapserv->QueryLayerIndex)->status = MS_ON; switch(mapserv->Mode) { case ITEMFEATUREQUERY: case ITEMFEATURENQUERY: if((mapserv->SelectLayerIndex = msGetLayerIndex(mapserv->map, mapserv->SelectLayer)) == -1) { /* force the selection layer on */ msSetError(MS_WEBERR, "Selection layer not set or references an invalid layer.", "mapserv()"); return MS_FAILURE; } GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->status = MS_ON; /* validate the qstring parameter */ if(msValidateParameter(mapserv->QueryString, msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->validation), "qstring"), msLookupHashTable(&(mapserv->map->web.validation), "qstring"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_WEBERR, "Parameter 'qstring' value fails to validate.", "mapserv()"); return MS_FAILURE; } if(mapserv->QueryCoordSource != NONE && !mapserv->UseShapes) if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */ return MS_FAILURE; mapserv->map->query.type = MS_QUERY_BY_FILTER; if(mapserv->QueryItem) mapserv->map->query.filteritem = msStrdup(mapserv->QueryItem); if(mapserv->QueryString) { msInitExpression(&mapserv->map->query.filter); msLoadExpressionString(&mapserv->map->query.filter, mapserv->QueryString); } mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.mode = MS_QUERY_MULTIPLE; if(mapserv->Mode == ITEMFEATUREQUERY) mapserv->map->query.mode = MS_QUERY_SINGLE; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.slayer = mapserv->SelectLayerIndex; /* this will trigger the feature query eventually */ break; case FEATUREQUERY: case FEATURENQUERY: if((mapserv->SelectLayerIndex = msGetLayerIndex(mapserv->map, mapserv->SelectLayer)) == -1) { /* force the selection layer on */ msSetError(MS_WEBERR, "Selection layer not set or references an invalid layer.", "mapserv()"); return MS_FAILURE; } GET_LAYER(mapserv->map, mapserv->SelectLayerIndex)->status = MS_ON; if(mapserv->Mode == FEATUREQUERY) { switch(mapserv->QueryCoordSource) { case FROMIMGPNT: mapserv->map->extent = mapserv->ImgExt; /* use the existing map extent */ setCoordinate(mapserv); break; case FROMUSERPNT: break; default: msSetError(MS_WEBERR, "No way to perform the initial search, not enough information.", "mapserv()"); return MS_FAILURE; break; } mapserv->map->query.type = MS_QUERY_BY_POINT; mapserv->map->query.mode = MS_QUERY_SINGLE; mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.buffer = mapserv->Buffer; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.slayer = mapserv->SelectLayerIndex; /* this will trigger the feature query eventually */ } else { /* FEATURENQUERY */ switch(mapserv->QueryCoordSource) { case FROMIMGPNT: mapserv->map->extent = mapserv->ImgExt; /* use the existing map extent */ setCoordinate(mapserv); mapserv->map->query.type = MS_QUERY_BY_POINT; break; case FROMIMGBOX: /* TODO: this option was present but with no code to leverage the image box... */ break; case FROMUSERPNT: mapserv->map->query.type = MS_QUERY_BY_POINT; break; default: if(MS_SUCCESS != setExtent(mapserv)) { return MS_FAILURE; } mapserv->map->query.type = MS_QUERY_BY_RECT; break; } } mapserv->map->query.mode = MS_QUERY_MULTIPLE; mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.buffer = mapserv->Buffer; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.slayer = mapserv->SelectLayerIndex; break; case ITEMQUERY: case ITEMNQUERY: if(mapserv->QueryLayerIndex < 0 || mapserv->QueryLayerIndex >= mapserv->map->numlayers) { msSetError(MS_WEBERR, "Query layer not set or references an invalid layer.", "mapserv()"); return MS_FAILURE; } /* validate the qstring parameter */ if(msValidateParameter(mapserv->QueryString, msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->QueryLayerIndex)->validation), "qstring"), msLookupHashTable(&(mapserv->map->web.validation), "qstring"), NULL, NULL) != MS_SUCCESS) { msSetError(MS_WEBERR, "Parameter 'qstring' value fails to validate.", "mapserv()"); return MS_FAILURE; } if(mapserv->QueryCoordSource != NONE && !mapserv->UseShapes) if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */ return MS_FAILURE; mapserv->map->query.type = MS_QUERY_BY_FILTER; mapserv->map->query.layer = mapserv->QueryLayerIndex; if(mapserv->QueryItem) mapserv->map->query.filteritem = msStrdup(mapserv->QueryItem); if(mapserv->QueryString) { msInitExpression(&mapserv->map->query.filter); msLoadExpressionString(&mapserv->map->query.filter, mapserv->QueryString); } mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.mode = MS_QUERY_MULTIPLE; if(mapserv->Mode == ITEMQUERY) mapserv->map->query.mode = MS_QUERY_SINGLE; break; case NQUERY: mapserv->map->query.mode = MS_QUERY_MULTIPLE; /* all of these cases return multiple results */ mapserv->map->query.layer = mapserv->QueryLayerIndex; switch(mapserv->QueryCoordSource) { case FROMIMGPNT: setCoordinate(mapserv); if(mapserv->SearchMap) { /* compute new extent, pan etc then search that extent */ if(MS_SUCCESS != setExtent(mapserv)) /* set user area of interest */ return MS_FAILURE; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.type = MS_QUERY_BY_RECT; } else { mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */ mapserv->map->width = mapserv->ImgCols; mapserv->map->height = mapserv->ImgRows; if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.type = MS_QUERY_BY_POINT; } break; case FROMIMGBOX: if(mapserv->SearchMap) { /* compute new extent, pan etc then search that extent */ setExtent(mapserv); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.type = MS_QUERY_BY_RECT; } else { double cellx, celly; mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */ mapserv->map->width = mapserv->ImgCols; mapserv->map->height = mapserv->ImgRows; if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); /* calculate the new search extent */ celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows); mapserv->RawExt.minx = MS_IMAGE2MAP_X(mapserv->ImgBox.minx, mapserv->ImgExt.minx, cellx); mapserv->RawExt.maxx = MS_IMAGE2MAP_X(mapserv->ImgBox.maxx, mapserv->ImgExt.minx, cellx); mapserv->RawExt.maxy = MS_IMAGE2MAP_Y(mapserv->ImgBox.miny, mapserv->ImgExt.maxy, celly); /* y's are flip flopped because img/map coordinate systems are */ mapserv->RawExt.miny = MS_IMAGE2MAP_Y(mapserv->ImgBox.maxy, mapserv->ImgExt.maxy, celly); mapserv->map->query.rect = mapserv->RawExt; mapserv->map->query.type = MS_QUERY_BY_RECT; } break; case FROMIMGSHAPE: mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */ mapserv->map->width = mapserv->ImgCols; mapserv->map->height = mapserv->ImgRows; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; /* convert from image to map coordinates here (see setCoordinate) */ for(i=0; imap->query.shape->numlines; i++) { for(j=0; jmap->query.shape->line[i].numpoints; j++) { mapserv->map->query.shape->line[i].point[j].x = MS_IMAGE2MAP_X(mapserv->map->query.shape->line[i].point[j].x, mapserv->map->extent.minx, mapserv->map->cellsize); mapserv->map->query.shape->line[i].point[j].y = MS_IMAGE2MAP_Y(mapserv->map->query.shape->line[i].point[j].y, mapserv->map->extent.maxy, mapserv->map->cellsize); } } mapserv->map->query.type = MS_QUERY_BY_SHAPE; break; case FROMUSERPNT: if(mapserv->Buffer == 0) { /* do a *pure* point query */ mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.type = MS_QUERY_BY_POINT; setExtent(mapserv); } else { setExtent(mapserv); if(mapserv->SearchMap) { /* the extent should be tied to a map, so we need to "adjust" it */ if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); } mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.type = MS_QUERY_BY_RECT; } break; case FROMUSERSHAPE: setExtent(mapserv); mapserv->map->query.type = MS_QUERY_BY_SHAPE; break; default: /* from an extent of some sort */ setExtent(mapserv); if(mapserv->SearchMap) { /* the extent should be tied to a map, so we need to "adjust" it */ if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); } mapserv->map->query.rect = mapserv->map->extent; mapserv->map->query.type = MS_QUERY_BY_RECT; break; } break; case QUERY: switch(mapserv->QueryCoordSource) { case FROMIMGPNT: setCoordinate(mapserv); mapserv->map->extent = mapserv->ImgExt; /* use the existing image parameters */ mapserv->map->width = mapserv->ImgCols; mapserv->map->height = mapserv->ImgRows; if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return MS_FAILURE; break; case FROMUSERPNT: /* only a buffer makes sense, DOES IT? */ if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE; break; default: msSetError(MS_WEBERR, "Query mode needs a point, imgxy and mapxy are not set.", "mapserv()"); return MS_FAILURE; break; } mapserv->map->query.type = MS_QUERY_BY_POINT; mapserv->map->query.mode = MS_QUERY_SINGLE; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.point = mapserv->mappnt; mapserv->map->query.buffer = mapserv->Buffer; break; case INDEXQUERY: mapserv->map->query.type = MS_QUERY_BY_INDEX; mapserv->map->query.mode = MS_QUERY_SINGLE; mapserv->map->query.layer = mapserv->QueryLayerIndex; mapserv->map->query.shapeindex = mapserv->ShapeIndex; mapserv->map->query.tileindex = mapserv->TileIndex; break; } /* end mode switch */ /* finally execute the query */ if((status = msExecuteQuery(mapserv->map)) != MS_SUCCESS) return MS_FAILURE; } if(mapserv->map->querymap.width != -1) mapserv->map->width = mapserv->map->querymap.width; /* make sure we use the right size */ if(mapserv->map->querymap.height != -1) mapserv->map->height = mapserv->map->querymap.height; if(mapserv->UseShapes) if(MS_SUCCESS != setExtentFromShapes(mapserv)) return MS_FAILURE; if(msReturnTemplateQuery(mapserv, mapserv->map->web.queryformat, NULL) != MS_SUCCESS) return MS_FAILURE; if(mapserv->savequery) { snprintf(buffer, sizeof(buffer), "%s%s%s%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_QUERY_EXTENSION); if((status = msSaveQuery(mapserv->map, buffer, MS_FALSE)) != MS_SUCCESS) return status; } return MS_SUCCESS; } int msCGIDispatchImageRequest(mapservObj *mapserv) { int status; imageObj *img = NULL; switch(mapserv->Mode) { case MAP: if(mapserv->QueryFile) { status = msLoadQuery(mapserv->map, mapserv->QueryFile); if(status != MS_SUCCESS) return MS_FAILURE; img = msDrawMap(mapserv->map, MS_TRUE); } else img = msDrawMap(mapserv->map, MS_FALSE); break; case REFERENCE: mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); img = msDrawReferenceMap(mapserv->map); break; case SCALEBAR: img = msDrawScalebar(mapserv->map); break; case TILE: msTileSetExtent(mapserv); if(!strcmp(MS_IMAGE_MIME_TYPE(mapserv->map->outputformat), "application/x-protobuf")) { if((status = msMVTWriteTile(mapserv->map, mapserv->sendheaders)) != MS_SUCCESS) return MS_FAILURE; return MS_SUCCESS; } img = msTileDraw(mapserv); break; case LEGEND: case MAPLEGEND: img = msDrawLegend(mapserv->map, MS_FALSE, mapserv->hittest); break; default: msSetError(MS_CGIERR,"Invalid CGI mode", "msCGIDispatchImageRequest()"); break; } if(!img) return MS_FAILURE; /* ** Set the Cache control headers if the option is set. */ if( mapserv->sendheaders && msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age") ) { msIO_setHeader("Cache-Control","max-age=%s", msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age")); } if(mapserv->sendheaders) { const char *attachment = msGetOutputFormatOption(mapserv->map->outputformat, "ATTACHMENT", NULL ); if(attachment) msIO_setHeader("Content-disposition","attachment; filename=%s", attachment); if(!strcmp(MS_IMAGE_MIME_TYPE(mapserv->map->outputformat), "application/json")) { msIO_setHeader("Content-Type","application/json; charset=utf-8"); } else { msIO_setHeader("Content-Type","%s", MS_IMAGE_MIME_TYPE(mapserv->map->outputformat)); } msIO_sendHeaders(); } if( mapserv->Mode == MAP || mapserv->Mode == TILE ) status = msSaveImage(mapserv->map, img, NULL); else status = msSaveImage(NULL,img, NULL); if(status != MS_SUCCESS) return MS_FAILURE; msFreeImage(img); return MS_SUCCESS; } int msCGIDispatchLegendRequest(mapservObj *mapserv) { int status; if(mapserv->Mode == MAPLEGEND) { if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE; if(checkWebScale(mapserv) != MS_SUCCESS) return MS_FAILURE; mapserv->hittest = msSmallMalloc(sizeof(map_hittest)); initMapHitTests(mapserv->map,mapserv->hittest); status = msHitTestMap(mapserv->map,mapserv->hittest); if(status != MS_SUCCESS) return MS_FAILURE; } if(mapserv->map->legend.template) { char *legendTemplate; legendTemplate = generateLegendTemplate(mapserv); if(legendTemplate) { if(mapserv->sendheaders) { msIO_setHeader("Content-Type","%s",mapserv->map->web.legendformat); msIO_sendHeaders(); } msIO_fwrite(legendTemplate, strlen(legendTemplate), 1, stdout); free(legendTemplate); return MS_SUCCESS; } else {/* error already generated by (generateLegendTemplate()) */ return MS_FAILURE; } } else { return msCGIDispatchImageRequest(mapserv); } } int msCGIDispatchLegendIconRequest(mapservObj *mapserv) { char **tokens = NULL; int numtokens=0; int layerindex=-1, classindex=0, status; outputFormatObj *format = NULL; imageObj *img = NULL; /* TODO: do we want to set scale here? */ /* do we have enough information */ if(!mapserv->icon) { msSetError(MS_WEBERR, "Mode=LEGENDICON requires an icon parameter.", "mapserv()"); return MS_FAILURE; } /* process the icon definition */ tokens = msStringSplit(mapserv->icon, ',', &numtokens); if(numtokens != 1 && numtokens != 2) { msSetError(MS_WEBERR, "%d Malformed icon parameter, should be 'layer,class' or just 'layer' if the layer has only 1 class defined.", "mapserv()", numtokens); status = MS_FAILURE; goto li_cleanup; } if((layerindex = msGetLayerIndex(mapserv->map, tokens[0])) == -1) { msSetError(MS_WEBERR, "Icon layer=%s not found in mapfile.", "mapserv()", tokens[0]); status = MS_FAILURE; goto li_cleanup; } if(numtokens == 2) { /* check the class index */ classindex = atoi(tokens[1]); if(classindex >= GET_LAYER(mapserv->map, layerindex)->numclasses) { msSetError(MS_WEBERR, "Icon class=%d not found in layer=%s.", "mapserv()", classindex, GET_LAYER(mapserv->map, layerindex)->name); status = MS_FAILURE; goto li_cleanup; } } if(mapserv->Mode == MAPLEGENDICON) { if(setExtent(mapserv) != MS_SUCCESS) { status=MS_FAILURE; goto li_cleanup; } if(checkWebScale(mapserv) != MS_SUCCESS) { status=MS_FAILURE; goto li_cleanup; } mapserv->hittest = msSmallMalloc(sizeof(map_hittest)); initMapHitTests(mapserv->map,mapserv->hittest); status = msHitTestLayer(mapserv->map, GET_LAYER(mapserv->map,layerindex),&mapserv->hittest->layerhits[layerindex]); if(status != MS_SUCCESS) goto li_cleanup; } /* ensure we have an image format representing the options for the legend. */ msApplyOutputFormat(&format, mapserv->map->outputformat, mapserv->map->legend.transparent, mapserv->map->legend.interlace, MS_NOOVERRIDE); /* initialize the legend image */ if( ! MS_RENDERER_PLUGIN(format) ) { msSetError(MS_RENDERERERR, "unsupported renderer for legend icon", "mapserv main()"); status = MS_FAILURE; goto li_cleanup; } img = msImageCreate(mapserv->map->legend.keysizex, mapserv->map->legend.keysizey, format, mapserv->map->web.imagepath, mapserv->map->web.imageurl, mapserv->map->resolution, mapserv->map->defresolution, &(mapserv->map->legend.imagecolor)); if(!img) { status = MS_FAILURE; goto li_cleanup; } img->map = mapserv->map; /* drop this reference to output format */ msApplyOutputFormat(&format, NULL, MS_NOOVERRIDE, MS_NOOVERRIDE, MS_NOOVERRIDE); if(msDrawLegendIcon(mapserv->map, GET_LAYER(mapserv->map, layerindex), GET_LAYER(mapserv->map, layerindex)->class[classindex], mapserv->map->legend.keysizex, mapserv->map->legend.keysizey, img, 0, 0, MS_TRUE, ((mapserv->hittest)?(&mapserv->hittest->layerhits[layerindex].classhits[classindex]):(NULL))) != MS_SUCCESS) { status = MS_FAILURE; goto li_cleanup; } if(mapserv->sendheaders) { msIO_setHeader("Content-Type","%s",MS_IMAGE_MIME_TYPE(mapserv->map->outputformat)); msIO_sendHeaders(); } /* ** Set the Cache control headers if the option is set. */ if( mapserv->sendheaders && msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age") ) { msIO_printf("Cache-Control: max-age=%s%c", msLookupHashTable(&(mapserv->map->web.metadata), "http_max_age"), 10); } status = msSaveImage(NULL, img, NULL); li_cleanup: msFreeCharArray(tokens, numtokens); msFreeImage(img); return status; } int msCGIDispatchRequest(mapservObj *mapserv) { int i; int status; /* ** Determine 'mode': Check for MS_MODE env. var. and mode=... CGI param */ mapserv->Mode = -1; /* Not set */ if( msCGISetMode(mapserv) != MS_SUCCESS) { return MS_FAILURE; } /* ** Start by calling the WMS/WFS/WCS Dispatchers. If they fail then we'll ** process this as a regular MapServer request. */ if((mapserv->Mode == -1 || mapserv->Mode == OWS || mapserv->Mode == WFS) && (status = msOWSDispatch(mapserv->map, mapserv->request, mapserv->Mode)) != MS_DONE ) { /* ** OWSDispatch returned either MS_SUCCESS or MS_FAILURE */ if( status == MS_FAILURE ) { return MS_FAILURE; } if (status == MS_SUCCESS && strcasecmp(mapserv->map->imagetype, "application/openlayers")==0) { char *service = NULL; for( i=0; irequest->NumParams; i++) { if(strcasecmp(mapserv->request->ParamNames[i], "SERVICE") == 0) { service = mapserv->request->ParamValues[i]; break; } } if (service && strcasecmp(service,"WMS")==0) { if(mapserv->sendheaders) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); } if (msReturnOpenLayersPage(mapserv) != MS_SUCCESS) return MS_FAILURE; } } return MS_SUCCESS; } /* done OGC/OWS case */ /* ** Do "traditional" mode processing. */ if (mapserv->Mode == -1) mapserv->Mode = BROWSE; if(MS_SUCCESS != msCGILoadForm(mapserv)) { return MS_FAILURE; } /* Insecure as implemented, need to save someplace non accessible by everyone in the universe if(mapserv->savemap) { snprintf(buffer, sizeof(buffer), "%s%s%s.map", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id); if(msSaveMap(mapserv->map, buffer) == -1) return MS_FAILURE; } */ if((mapserv->CoordSource == FROMIMGPNT) || (mapserv->CoordSource == FROMIMGBOX)) /* make sure extent of existing image matches shape of image */ mapserv->map->cellsize = msAdjustExtent(&mapserv->ImgExt, mapserv->ImgCols, mapserv->ImgRows); /* ** For each layer let's set layer status */ for(i=0; imap->numlayers; i++) { if((GET_LAYER(mapserv->map, i)->status != MS_DEFAULT)) { if(isOn(mapserv, GET_LAYER(mapserv->map, i)->name, GET_LAYER(mapserv->map, i)->group) == MS_TRUE) /* Set layer status */ GET_LAYER(mapserv->map, i)->status = MS_ON; else GET_LAYER(mapserv->map, i)->status = MS_OFF; } } if(mapserv->CoordSource == FROMREFPNT) /* force browse mode if the reference coords are set */ mapserv->Mode = BROWSE; if(mapserv->Mode == TILE) { /* ** Tile mode: ** Set the projection up and test the parameters for legality. */ if( msTileSetup(mapserv) != MS_SUCCESS ) { return MS_FAILURE; } } if(mapserv->Mode == BROWSE) { return msCGIDispatchBrowseRequest(mapserv); } else if(mapserv->Mode == MAP || mapserv->Mode == SCALEBAR || mapserv->Mode == REFERENCE || mapserv->Mode == TILE) { /* "image" only modes */ /* tile, map, scalebar and reference all need the extent to be set up correctly */ if(setExtent(mapserv) != MS_SUCCESS) return MS_FAILURE; if(checkWebScale(mapserv) != MS_SUCCESS) return MS_FAILURE; return msCGIDispatchImageRequest(mapserv); } else if(mapserv->Mode == LEGEND || mapserv->Mode == MAPLEGEND) { return msCGIDispatchLegendRequest(mapserv); } else if(mapserv->Mode == LEGENDICON || mapserv->Mode == MAPLEGENDICON) { return msCGIDispatchLegendIconRequest(mapserv); } else if(mapserv->Mode >= QUERY) { return msCGIDispatchQueryRequest(mapserv); } else if(mapserv->Mode == COORDINATE) { return msCGIDispatchCoordinateRequest(mapserv); } else { msSetError(MS_WEBERR, "Bug: unsupported mode", "msDispatchRequest"); return MS_FAILURE; } } int msCGIHandler(const char *query_string, void **out_buffer, size_t *buffer_length) { int x,m=0; struct mstimeval execstarttime, execendtime; struct mstimeval requeststarttime, requestendtime; mapservObj* mapserv = NULL; char *queryString = NULL; int maxParams = MS_DEFAULT_CGI_PARAMS; msIOContext *ctx; msIOBuffer *buf; msIO_installStdoutToBuffer(); /* Use PROJ_LIB env vars if set */ msProjLibInitFromEnv(); /* Use MS_ERRORFILE and MS_DEBUGLEVEL env vars if set */ if( msDebugInitFromEnv() != MS_SUCCESS ) { msCGIWriteError(mapserv); goto end_request; } if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&execstarttime, NULL); if(!query_string || !*query_string) { msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); msIO_printf("No query information to decode. QUERY_STRING not set.\n"); goto end_request; } mapserv = msAllocMapServObj(); mapserv->request->type = MS_GET_REQUEST; /* don't modify the string */ queryString = msStrdup(query_string); for(x=0; queryString[0] != '\0'; x++) { if(m >= maxParams) { maxParams *= 2; mapserv->request->ParamNames = (char **) realloc(mapserv->request->ParamNames,sizeof(char *) * maxParams); if (mapserv->request->ParamNames == NULL) { msIO_printf("Out of memory trying to allocate name/value pairs.\n"); goto end_request; } mapserv->request->ParamValues = (char **) realloc(mapserv->request->ParamValues,sizeof(char *) * maxParams); if (mapserv->request->ParamValues == NULL) { msIO_printf("Out of memory trying to allocate name/value pairs.\n"); goto end_request; } } mapserv->request->ParamValues[m] = makeword(queryString,'&'); plustospace(mapserv->request->ParamValues[m]); unescape_url(mapserv->request->ParamValues[m]); mapserv->request->ParamNames[m] = makeword(mapserv->request->ParamValues[m],'='); m++; } mapserv->request->NumParams = m; if( mapserv->request->NumParams == 0 ) { msCGIWriteError(mapserv); goto end_request; } mapserv->map = msCGILoadMap(mapserv); if(!mapserv->map) { msCGIWriteError(mapserv); goto end_request; } if( mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&requeststarttime, NULL); if(msCGIDispatchRequest(mapserv) != MS_SUCCESS) { msCGIWriteError(mapserv); goto end_request; } end_request: if(mapserv) { if(mapserv->map && mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&requestendtime, NULL); msDebug("mapserv request processing time (msLoadMap not incl.): %.3fs\n", (requestendtime.tv_sec+requestendtime.tv_usec/1.0e6)- (requeststarttime.tv_sec+requeststarttime.tv_usec/1.0e6) ); } msCGIWriteLog(mapserv,MS_FALSE); msFreeMapServObj(mapserv); } /* normal case, processing is complete */ if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&execendtime, NULL); msDebug("mapserv total execution time: %.3fs\n", (execendtime.tv_sec+execendtime.tv_usec/1.0e6)- (execstarttime.tv_sec+execstarttime.tv_usec/1.0e6) ); } ctx = msIO_getHandler( (FILE *) "stdout" ); buf = (msIOBuffer *) ctx->cbData; *out_buffer = buf->data; *buffer_length = buf->data_offset; free(queryString); return 0; } mapserver-7.4.3/mapshape.c000066400000000000000000003071131357574274700155250ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implements support for shapefile access. * Authors: Steve Lime and Frank Warmerdam * * Note: * This code is entirely based on the previous work of Frank Warmerdam. It is * essentially shapelib 1.1.5. However, there were enough changes that it was * incorporated into the MapServer source to avoid confusion. Relicensed with * permission of Frank Warmerdam (shapelib author). See the README * for licence details. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include #include "mapserver.h" #include "mapows.h" #if defined(USE_GDAL) || defined(USE_OGR) #include #include #endif /* Only use this macro on 32-bit integers! */ #define SWAP_FOUR_BYTES(data) \ ( ((data >> 24) & 0x000000FF) | ((data >> 8) & 0x0000FF00) | \ ((data << 8) & 0x00FF0000) | ((data << 24) & 0xFF000000) ) #define ByteCopy( a, b, c ) memcpy( b, a, c ) static int bBigEndian; /************************************************************************/ /* SwapWord() */ /* */ /* Swap a 2, 4 or 8 byte word. */ /************************************************************************/ static void SwapWord( int length, void * wordP ) { int i; uchar temp; for( i=0; i < length/2; i++ ) { temp = ((uchar *) wordP)[i]; ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1]; ((uchar *) wordP)[length-i-1] = temp; } } /************************************************************************/ /* SfRealloc() */ /* */ /* A realloc cover function that will access a NULL pointer as */ /* a valid input. */ /************************************************************************/ static void * SfRealloc( void * pMem, int nNewSize ) { return realloc(pMem, nNewSize); } /************************************************************************/ /* writeHeader() */ /* */ /* Write out a header for the .shp and .shx files as well as the */ /* contents of the index (.shx) file. */ /************************************************************************/ static void writeHeader( SHPHandle psSHP ) { uchar abyHeader[100]; int i; ms_int32 i32; double dValue; ms_int32 *panSHX; /* -------------------------------------------------------------------- */ /* Prepare header block for .shp file. */ /* -------------------------------------------------------------------- */ for( i = 0; i < 100; i++ ) abyHeader[i] = 0; abyHeader[2] = 0x27; /* magic cookie */ abyHeader[3] = 0x0a; i32 = psSHP->nFileSize/2; /* file size */ ByteCopy( &i32, abyHeader+24, 4 ); if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); i32 = 1000; /* version */ ByteCopy( &i32, abyHeader+28, 4 ); if( bBigEndian ) SwapWord( 4, abyHeader+28 ); i32 = psSHP->nShapeType; /* shape type */ ByteCopy( &i32, abyHeader+32, 4 ); if( bBigEndian ) SwapWord( 4, abyHeader+32 ); dValue = psSHP->adBoundsMin[0]; /* set bounds */ ByteCopy( &dValue, abyHeader+36, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+36 ); dValue = psSHP->adBoundsMin[1]; ByteCopy( &dValue, abyHeader+44, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+44 ); dValue = psSHP->adBoundsMax[0]; ByteCopy( &dValue, abyHeader+52, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+52 ); dValue = psSHP->adBoundsMax[1]; ByteCopy( &dValue, abyHeader+60, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+60 ); dValue = psSHP->adBoundsMin[2]; /* z */ ByteCopy( &dValue, abyHeader+68, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+68 ); dValue = psSHP->adBoundsMax[2]; ByteCopy( &dValue, abyHeader+76, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+76 ); dValue = psSHP->adBoundsMin[3]; /* m */ ByteCopy( &dValue, abyHeader+84, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+84 ); dValue = psSHP->adBoundsMax[3]; ByteCopy( &dValue, abyHeader+92, 8 ); if( bBigEndian ) SwapWord( 8, abyHeader+92 ); /* -------------------------------------------------------------------- */ /* Write .shp file header. */ /* -------------------------------------------------------------------- */ fseek( psSHP->fpSHP, 0, 0 ); fwrite( abyHeader, 100, 1, psSHP->fpSHP ); /* -------------------------------------------------------------------- */ /* Prepare, and write .shx file header. */ /* -------------------------------------------------------------------- */ i32 = (psSHP->nRecords * 2 * sizeof(ms_int32) + 100)/2; /* file size */ ByteCopy( &i32, abyHeader+24, 4 ); if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); fseek( psSHP->fpSHX, 0, 0 ); fwrite( abyHeader, 100, 1, psSHP->fpSHX ); /* -------------------------------------------------------------------- */ /* Write out the .shx contents. */ /* -------------------------------------------------------------------- */ panSHX = (ms_int32 *) msSmallMalloc(sizeof(ms_int32) * 2 * psSHP->nRecords); for( i = 0; i < psSHP->nRecords; i++ ) { panSHX[i*2 ] = psSHP->panRecOffset[i]/2; panSHX[i*2+1] = psSHP->panRecSize[i]/2; if( !bBigEndian ) { *(panSHX+i*2) = SWAP_FOUR_BYTES(*(panSHX+i*2)); *(panSHX+i*2+1) = SWAP_FOUR_BYTES(*(panSHX+i*2+1)); } } fwrite( panSHX, sizeof(ms_int32) * 2, psSHP->nRecords, psSHP->fpSHX ); free( panSHX ); } /************************************************************************/ /* msSHPOpen() */ /* */ /* Open the .shp and .shx files based on the basename of the */ /* files or either file name. */ /************************************************************************/ SHPHandle msSHPOpen( const char * pszLayer, const char * pszAccess ) { char *pszFullname, *pszBasename; SHPHandle psSHP; uchar *pabyBuf; int i; double dValue; /* -------------------------------------------------------------------- */ /* Ensure the access string is one of the legal ones. We */ /* ensure the result string indicates binary to avoid common */ /* problems on Windows. */ /* -------------------------------------------------------------------- */ if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0 || strcmp(pszAccess,"r+") == 0 ) pszAccess = "r+b"; else pszAccess = "rb"; /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) bBigEndian = MS_FALSE; else bBigEndian = MS_TRUE; /* -------------------------------------------------------------------- */ /* Initialize the info structure. */ /* -------------------------------------------------------------------- */ psSHP = (SHPHandle) msSmallMalloc(sizeof(SHPInfo)); psSHP->bUpdated = MS_FALSE; psSHP->pabyRec = NULL; psSHP->panParts = NULL; psSHP->nBufSize = psSHP->nPartMax = 0; /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(pszLayer)+5); strcpy( pszBasename, pszLayer ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s.shp", pszBasename ); psSHP->fpSHP = fopen(pszFullname, pszAccess ); if( psSHP->fpSHP == NULL ) { sprintf( pszFullname, "%s.SHP", pszBasename ); psSHP->fpSHP = fopen(pszFullname, pszAccess ); } if( psSHP->fpSHP == NULL ) { msFree(pszBasename); msFree(pszFullname); msFree(psSHP); return( NULL ); } sprintf( pszFullname, "%s.shx", pszBasename ); psSHP->fpSHX = fopen(pszFullname, pszAccess ); if( psSHP->fpSHX == NULL ) { sprintf( pszFullname, "%s.SHX", pszBasename ); psSHP->fpSHX = fopen(pszFullname, pszAccess ); } if( psSHP->fpSHX == NULL ) { fclose(psSHP->fpSHP); msFree(pszBasename); msFree(pszFullname); msFree(psSHP); return( NULL ); } free( pszFullname ); free( pszBasename ); /* -------------------------------------------------------------------- */ /* Read the file size from the SHP file. */ /* -------------------------------------------------------------------- */ pabyBuf = (uchar *) msSmallMalloc(100); if(1 != fread( pabyBuf, 100, 1, psSHP->fpSHP )) { fclose( psSHP->fpSHP ); fclose( psSHP->fpSHX ); free( psSHP ); free(pabyBuf); return( NULL ); } psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256 + pabyBuf[25] * 256 * 256 + pabyBuf[26] * 256 + pabyBuf[27]) * 2; /* -------------------------------------------------------------------- */ /* Read SHX file Header info */ /* -------------------------------------------------------------------- */ if(1 != fread( pabyBuf, 100, 1, psSHP->fpSHX )) { msSetError(MS_SHPERR, "Corrupted .shx file", "msSHPOpen()"); fclose( psSHP->fpSHP ); fclose( psSHP->fpSHX ); free( psSHP ); free(pabyBuf); return( NULL ); } if( pabyBuf[0] != 0 || pabyBuf[1] != 0 || pabyBuf[2] != 0x27 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) ) { msSetError(MS_SHPERR, "Corrupted .shp file", "msSHPOpen()"); fclose( psSHP->fpSHP ); fclose( psSHP->fpSHX ); free( psSHP ); free(pabyBuf); return( NULL ); } psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256 + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256; if (psSHP->nRecords != 0) psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8; if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 ) { msSetError(MS_SHPERR, "Corrupted .shp file : nRecords = %d.", "msSHPOpen()", psSHP->nRecords); fclose( psSHP->fpSHP ); fclose( psSHP->fpSHX ); free( psSHP ); free(pabyBuf); return( NULL ); } psSHP->nShapeType = pabyBuf[32]; if( bBigEndian ) SwapWord( 8, pabyBuf+36 ); memcpy( &dValue, pabyBuf+36, 8 ); psSHP->adBoundsMin[0] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+44 ); memcpy( &dValue, pabyBuf+44, 8 ); psSHP->adBoundsMin[1] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+52 ); memcpy( &dValue, pabyBuf+52, 8 ); psSHP->adBoundsMax[0] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+60 ); memcpy( &dValue, pabyBuf+60, 8 ); psSHP->adBoundsMax[1] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */ memcpy( &dValue, pabyBuf+68, 8 ); psSHP->adBoundsMin[2] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+76 ); memcpy( &dValue, pabyBuf+76, 8 ); psSHP->adBoundsMax[2] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* m */ memcpy( &dValue, pabyBuf+84, 8 ); psSHP->adBoundsMin[3] = dValue; if( bBigEndian ) SwapWord( 8, pabyBuf+92 ); memcpy( &dValue, pabyBuf+92, 8 ); psSHP->adBoundsMax[3] = dValue; free( pabyBuf ); /* -------------------------------------------------------------------- */ /* Read the .shx file to get the offsets to each record in */ /* the .shp file. */ /* -------------------------------------------------------------------- */ psSHP->nMaxRecords = psSHP->nRecords; /* Our in-memory cache of offset information */ psSHP->panRecOffset = (int *) malloc(sizeof(int) * psSHP->nMaxRecords ); /* Our in-memory cache of size information */ psSHP->panRecSize = (int *) malloc(sizeof(int) * psSHP->nMaxRecords ); /* The completeness information for our in-memory cache */ psSHP->panRecLoaded = msAllocBitArray( 1 + (psSHP->nMaxRecords / SHX_BUFFER_PAGE) ) ; /* Is our in-memory cache completely populated? */ psSHP->panRecAllLoaded = 0; /* malloc failed? clean up and shut down */ if (psSHP->panRecOffset == NULL || psSHP->panRecSize == NULL || psSHP->panRecLoaded == NULL) { free(psSHP->panRecOffset); free(psSHP->panRecSize); free(psSHP->panRecLoaded); fclose( psSHP->fpSHP ); fclose( psSHP->fpSHX ); free( psSHP ); msSetError(MS_MEMERR, "Out of memory", "msSHPOpen()"); return( NULL ); } return( psSHP ); } /************************************************************************/ /* msSHPClose() */ /* */ /* Close the .shp and .shx files. */ /************************************************************************/ void msSHPClose(SHPHandle psSHP ) { /* -------------------------------------------------------------------- */ /* Update the header if we have modified anything. */ /* -------------------------------------------------------------------- */ if( psSHP->bUpdated ) writeHeader( psSHP ); /* -------------------------------------------------------------------- */ /* Free all resources, and close files. */ /* -------------------------------------------------------------------- */ free( psSHP->panRecOffset ); free( psSHP->panRecSize ); free( psSHP->panRecLoaded ); free(psSHP->pabyRec); free(psSHP->panParts); fclose( psSHP->fpSHX ); fclose( psSHP->fpSHP ); free( psSHP ); } /************************************************************************/ /* msSHPGetInfo() */ /* */ /* Fetch general information about the shape file. */ /************************************************************************/ void msSHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType ) { if( pnEntities ) *pnEntities = psSHP->nRecords; if( pnShapeType ) *pnShapeType = psSHP->nShapeType; } /************************************************************************/ /* msSHPCreate() */ /* */ /* Create a new shape file and return a handle to the open */ /* shape file with read/write access. */ /************************************************************************/ SHPHandle msSHPCreate( const char * pszLayer, int nShapeType ) { char *pszBasename, *pszFullname; int i; FILE *fpSHP, *fpSHX; uchar abyHeader[100]; ms_int32 i32; double dValue; #ifndef USE_POINT_Z_M if( nShapeType == SHP_POLYGONZ || nShapeType == SHP_POLYGONM || nShapeType == SHP_ARCZ || nShapeType == SHP_ARCM || nShapeType == SHP_POINTZ || nShapeType == SHP_POINTM || nShapeType == SHP_MULTIPOINTZ || nShapeType == SHP_MULTIPOINTM ) { msSetError( MS_SHPERR, "Attempt to create M/Z shapefile but without having enabled Z/M support.", "msSHPCreate()" ); return NULL; } #endif /* -------------------------------------------------------------------- */ /* Establish the byte order on this system. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) bBigEndian = MS_FALSE; else bBigEndian = MS_TRUE; /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(pszLayer)+5); strcpy( pszBasename, pszLayer ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the two files so we can write their headers. */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s.shp", pszBasename ); fpSHP = fopen(pszFullname, "wb" ); if( fpSHP == NULL ) { free( pszFullname ); free(pszBasename); return( NULL ); } sprintf( pszFullname, "%s.shx", pszBasename ); fpSHX = fopen(pszFullname, "wb" ); if( fpSHX == NULL ) { fclose(fpSHP); free( pszFullname ); free(pszBasename); return( NULL ); } free( pszFullname ); free(pszBasename); /* -------------------------------------------------------------------- */ /* Prepare header block for .shp file. */ /* -------------------------------------------------------------------- */ for( i = 0; i < 100; i++ ) abyHeader[i] = 0; abyHeader[2] = 0x27; /* magic cookie */ abyHeader[3] = 0x0a; i32 = 50; /* file size */ ByteCopy( &i32, abyHeader+24, 4 ); if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); i32 = 1000; /* version */ ByteCopy( &i32, abyHeader+28, 4 ); if( bBigEndian ) SwapWord( 4, abyHeader+28 ); i32 = nShapeType; /* shape type */ ByteCopy( &i32, abyHeader+32, 4 ); if( bBigEndian ) SwapWord( 4, abyHeader+32 ); dValue = 0.0; /* set bounds */ ByteCopy( &dValue, abyHeader+36, 8 ); ByteCopy( &dValue, abyHeader+44, 8 ); ByteCopy( &dValue, abyHeader+52, 8 ); ByteCopy( &dValue, abyHeader+60, 8 ); /* -------------------------------------------------------------------- */ /* Write .shp file header. */ /* -------------------------------------------------------------------- */ fwrite( abyHeader, 100, 1, fpSHP ); /* -------------------------------------------------------------------- */ /* Prepare, and write .shx file header. */ /* -------------------------------------------------------------------- */ i32 = 50; /* file size */ ByteCopy( &i32, abyHeader+24, 4 ); if( !bBigEndian ) SwapWord( 4, abyHeader+24 ); fwrite( abyHeader, 100, 1, fpSHX ); /* -------------------------------------------------------------------- */ /* Close the files, and then open them as regular existing files. */ /* -------------------------------------------------------------------- */ fclose( fpSHP ); fclose( fpSHX ); return( msSHPOpen( pszLayer, "rb+" ) ); } /************************************************************************/ /* writeBounds() */ /* */ /* Compute a bounds rectangle for a shape, and set it into the */ /* indicated location in the record. */ /************************************************************************/ static void writeBounds( uchar * pabyRec, shapeObj *shape, int nVCount ) { double dXMin, dXMax, dYMin, dYMax; int i, j; if( nVCount == 0 ) { dXMin = dYMin = dXMax = dYMax = 0.0; } else { dXMin = dXMax = shape->line[0].point[0].x; dYMin = dYMax = shape->line[0].point[0].y; for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { dXMin = MS_MIN(dXMin, shape->line[i].point[j].x); dXMax = MS_MAX(dXMax, shape->line[i].point[j].x); dYMin = MS_MIN(dYMin, shape->line[i].point[j].y); dYMax = MS_MAX(dYMax, shape->line[i].point[j].y); } } } if( bBigEndian ) { SwapWord( 8, &dXMin ); SwapWord( 8, &dYMin ); SwapWord( 8, &dXMax ); SwapWord( 8, &dYMax ); } ByteCopy( &dXMin, pabyRec + 0, 8 ); ByteCopy( &dYMin, pabyRec + 8, 8 ); ByteCopy( &dXMax, pabyRec + 16, 8 ); ByteCopy( &dYMax, pabyRec + 24, 8 ); } int msSHPWritePoint(SHPHandle psSHP, pointObj *point ) { int nRecordOffset, nRecordSize=0; uchar *pabyRec; ms_int32 i32, nPoints, nParts; if( psSHP->nShapeType != SHP_POINT) return(-1); psSHP->bUpdated = MS_TRUE; /* Fill the SHX buffer if it is not already full. */ if( ! psSHP->panRecAllLoaded ) msSHXLoadAll( psSHP ); /* -------------------------------------------------------------------- */ /* Add the new entity to the in memory index. */ /* -------------------------------------------------------------------- */ psSHP->nRecords++; if( psSHP->nRecords > psSHP->nMaxRecords ) { psSHP->nMaxRecords = (int) (psSHP->nMaxRecords * 1.3 + 100); psSHP->panRecOffset = (int *) SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords ); psSHP->panRecSize = (int *) SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords ); } /* -------------------------------------------------------------------- */ /* Compute a few things. */ /* -------------------------------------------------------------------- */ nPoints = 1; nParts = 1; /* -------------------------------------------------------------------- */ /* Initialize record. */ /* -------------------------------------------------------------------- */ psSHP->panRecOffset[psSHP->nRecords-1] = nRecordOffset = psSHP->nFileSize; pabyRec = (uchar *) msSmallMalloc(nPoints * 2 * sizeof(double) + nParts * 4 + 128); /* -------------------------------------------------------------------- */ /* Write vertices for a point. */ /* -------------------------------------------------------------------- */ ByteCopy( &(point->x), pabyRec + 12, 8 ); ByteCopy( &(point->y), pabyRec + 20, 8 ); if( bBigEndian ) { SwapWord( 8, pabyRec + 12 ); SwapWord( 8, pabyRec + 20 ); } nRecordSize = 20; /* -------------------------------------------------------------------- */ /* Set the shape type, record number, and record size. */ /* -------------------------------------------------------------------- */ i32 = psSHP->nRecords-1+1; /* record # */ if( !bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec, 4 ); i32 = nRecordSize/2; /* record size */ if( !bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec + 4, 4 ); i32 = psSHP->nShapeType; /* shape type */ if( bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec + 8, 4 ); /* -------------------------------------------------------------------- */ /* Write out record. */ /* -------------------------------------------------------------------- */ if(fseek( psSHP->fpSHP, nRecordOffset, 0 ) == 0) { fwrite( pabyRec, nRecordSize+8, 1, psSHP->fpSHP ); psSHP->panRecSize[psSHP->nRecords-1] = nRecordSize; psSHP->nFileSize += nRecordSize + 8; /* -------------------------------------------------------------------- */ /* Expand file wide bounds based on this shape. */ /* -------------------------------------------------------------------- */ if( psSHP->nRecords == 1 ) { psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = point->x; psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = point->y; } else { psSHP->adBoundsMin[0] = MS_MIN(psSHP->adBoundsMin[0], point->x); psSHP->adBoundsMin[1] = MS_MIN(psSHP->adBoundsMin[1], point->y); psSHP->adBoundsMax[0] = MS_MAX(psSHP->adBoundsMax[0], point->x); psSHP->adBoundsMax[1] = MS_MAX(psSHP->adBoundsMax[1], point->y); } } else { psSHP->nRecords -- ; } free( pabyRec ); return( psSHP->nRecords - 1 ); } int msSHPWriteShape(SHPHandle psSHP, shapeObj *shape ) { int nRecordOffset, i, j, k, nRecordSize=0; uchar *pabyRec; int nShapeType; ms_int32 i32, nPoints, nParts; #ifdef USE_POINT_Z_M double dfMMin, dfMMax = 0; #endif psSHP->bUpdated = MS_TRUE; /* Fill the SHX buffer if it is not already full. */ if( ! psSHP->panRecAllLoaded ) msSHXLoadAll( psSHP ); /* -------------------------------------------------------------------- */ /* Add the new entity to the in memory index. */ /* -------------------------------------------------------------------- */ psSHP->nRecords++; if( psSHP->nRecords > psSHP->nMaxRecords ) { psSHP->nMaxRecords = (int) (psSHP->nMaxRecords * 1.3 + 100); psSHP->panRecOffset = (int *) SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords ); psSHP->panRecSize = (int *) SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords ); } /* -------------------------------------------------------------------- */ /* Compute a few things. */ /* -------------------------------------------------------------------- */ nPoints = 0; for(i=0; inumlines; i++) nPoints += shape->line[i].numpoints; nParts = shape->numlines; /* -------------------------------------------------------------------- */ /* Initialize record. */ /* -------------------------------------------------------------------- */ psSHP->panRecOffset[psSHP->nRecords-1] = nRecordOffset = psSHP->nFileSize; pabyRec = (uchar *) msSmallMalloc(nPoints * 4 * sizeof(double) + nParts * 8 + 128); nShapeType = psSHP->nShapeType; if (shape->type == MS_SHAPE_NULL) { nShapeType = 0; nRecordSize = 12; } /* -------------------------------------------------------------------- */ /* Write vertices for a Polygon or Arc. */ /* -------------------------------------------------------------------- */ else if(psSHP->nShapeType == SHP_POLYGON || psSHP->nShapeType == SHP_ARC || psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM || psSHP->nShapeType == SHP_ARCZ || psSHP->nShapeType == SHP_POLYGONZ) { ms_int32 t_nParts, t_nPoints, partSize; t_nParts = nParts; t_nPoints = nPoints; writeBounds( pabyRec + 12, shape, t_nPoints ); if( bBigEndian ) { nPoints = SWAP_FOUR_BYTES(nPoints); nParts = SWAP_FOUR_BYTES(nParts); } ByteCopy( &nPoints, pabyRec + 40 + 8, 4 ); ByteCopy( &nParts, pabyRec + 36 + 8, 4 ); partSize = 0; /* first part always starts at 0 */ ByteCopy( &partSize, pabyRec + 44 + 8 + 4*0, 4 ); if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*0); for( i = 1; i < t_nParts; i++ ) { partSize += shape->line[i-1].numpoints; ByteCopy( &partSize, pabyRec + 44 + 8 + 4*i, 4 ); if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i); } k = 0; /* overall point counter */ for( i = 0; i < shape->numlines; i++ ) { for( j = 0; j < shape->line[i].numpoints; j++ ) { ByteCopy( &(shape->line[i].point[j].x), pabyRec + 44 + 4*t_nParts + 8 + k * 16, 8 ); ByteCopy( &(shape->line[i].point[j].y), pabyRec + 44 + 4*t_nParts + 8 + k * 16 + 8, 8 ); if( bBigEndian ) { SwapWord( 8, pabyRec + 44+4*t_nParts+8+k*16 ); SwapWord( 8, pabyRec + 44+4*t_nParts+8+k*16+8 ); } k++; } } nRecordSize = 44 + 4*t_nParts + 16 * t_nPoints; #ifdef USE_POINT_Z_M /* -------------------------------------------------------------------- */ /* measured shape : polygon and arc. */ /* -------------------------------------------------------------------- */ if(psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM) { dfMMin = shape->line[0].point[0].m; dfMMax = shape->line[shape->numlines-1].point[shape->line[shape->numlines-1].numpoints-1].m; nRecordSize = 44 + 4*t_nParts + 8 + (t_nPoints* 16); ByteCopy( &(dfMMin), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; ByteCopy( &(dfMMax), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; for( i = 0; i < shape->numlines; i++ ) { for( j = 0; j < shape->line[i].numpoints; j++ ) { ByteCopy( &(shape->line[i].point[j].m), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } } } /* -------------------------------------------------------------------- */ /* Polygon. Arc with Z */ /* -------------------------------------------------------------------- */ if (psSHP->nShapeType == SHP_POLYGONZ || psSHP->nShapeType == SHP_ARCZ || psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM) { dfMMin = shape->line[0].point[0].z; dfMMax = shape->line[shape->numlines-1].point[shape->line[shape->numlines-1].numpoints-1].z; nRecordSize = 44 + 4*t_nParts + 8 + (t_nPoints* 16); ByteCopy( &(dfMMin), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; ByteCopy( &(dfMMax), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; for( i = 0; i < shape->numlines; i++ ) { for( j = 0; j < shape->line[i].numpoints; j++ ) { ByteCopy( &(shape->line[i].point[j].z), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } } } #endif /* def USE_POINT_Z_M */ } /* -------------------------------------------------------------------- */ /* Write vertices for a MultiPoint. */ /* -------------------------------------------------------------------- */ else if( psSHP->nShapeType == SHP_MULTIPOINT || psSHP->nShapeType == SHP_MULTIPOINTM || psSHP->nShapeType == SHP_MULTIPOINTZ) { ms_int32 t_nPoints; t_nPoints = nPoints; writeBounds( pabyRec + 12, shape, nPoints ); if( bBigEndian ) nPoints = SWAP_FOUR_BYTES(nPoints); ByteCopy( &nPoints, pabyRec + 44, 4 ); for( i = 0; i < shape->line[0].numpoints; i++ ) { ByteCopy( &(shape->line[0].point[i].x), pabyRec + 48 + i*16, 8 ); ByteCopy( &(shape->line[0].point[i].y), pabyRec + 48 + i*16 + 8, 8 ); if( bBigEndian ) { SwapWord( 8, pabyRec + 48 + i*16 ); SwapWord( 8, pabyRec + 48 + i*16 + 8 ); } } nRecordSize = 40 + 16 * t_nPoints; #ifdef USE_POINT_Z_M if (psSHP->nShapeType == SHP_MULTIPOINTM) { dfMMin = shape->line[0].point[0].m; dfMMax = shape->line[0].point[shape->line[0].numpoints-1].m; ByteCopy( &(dfMMin), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; ByteCopy( &(dfMMax), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; for( i = 0; i < shape->line[0].numpoints; i++ ) { ByteCopy( &(shape->line[0].point[i].m), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } } if (psSHP->nShapeType == SHP_MULTIPOINTZ) { dfMMin = shape->line[0].point[0].z; dfMMax = shape->line[0].point[shape->line[0].numpoints-1].z; ByteCopy( &(dfMMin), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; ByteCopy( &(dfMMax), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; for( i = 0; i < shape->line[0].numpoints; i++ ) { ByteCopy( &(shape->line[0].point[i].z), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } } #endif /* USE_POINT_Z_M */ } /* -------------------------------------------------------------------- */ /* Write vertices for a point. */ /* -------------------------------------------------------------------- */ else if( psSHP->nShapeType == SHP_POINT || psSHP->nShapeType == SHP_POINTM || psSHP->nShapeType == SHP_POINTZ) { ByteCopy( &(shape->line[0].point[0].x), pabyRec + 12, 8 ); ByteCopy( &(shape->line[0].point[0].y), pabyRec + 20, 8 ); if( bBigEndian ) { SwapWord( 8, pabyRec + 12 ); SwapWord( 8, pabyRec + 20 ); } nRecordSize = 20; #ifdef USE_POINT_Z_M if (psSHP->nShapeType == SHP_POINTM) { ByteCopy( &(shape->line[0].point[0].m), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } if (psSHP->nShapeType == SHP_POINTZ) { ByteCopy( &(shape->line[0].point[0].z), pabyRec + nRecordSize, 8 ); if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize ); nRecordSize += 8; } #endif /* USE_POINT_Z_M */ } /* -------------------------------------------------------------------- */ /* Set the shape type, record number, and record size. */ /* -------------------------------------------------------------------- */ i32 = psSHP->nRecords-1+1; /* record # */ if( !bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec, 4 ); i32 = nRecordSize/2; /* record size */ if( !bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec + 4, 4 ); i32 = nShapeType; /* shape type */ if( bBigEndian ) i32 = SWAP_FOUR_BYTES(i32); ByteCopy( &i32, pabyRec + 8, 4 ); /* -------------------------------------------------------------------- */ /* Write out record. */ /* -------------------------------------------------------------------- */ if(fseek( psSHP->fpSHP, nRecordOffset, 0 ) == 0) { fwrite( pabyRec, nRecordSize+8, 1, psSHP->fpSHP ); psSHP->panRecSize[psSHP->nRecords-1] = nRecordSize; psSHP->nFileSize += nRecordSize + 8; /* -------------------------------------------------------------------- */ /* Expand file wide bounds based on this shape. */ /* -------------------------------------------------------------------- */ if( psSHP->nRecords == 1 ) { psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = shape->line[0].point[0].x; psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = shape->line[0].point[0].y; #ifdef USE_POINT_Z_M psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = shape->line[0].point[0].z; psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = shape->line[0].point[0].m; #endif } for( i=0; inumlines; i++ ) { for( j=0; jline[i].numpoints; j++ ) { psSHP->adBoundsMin[0] = MS_MIN(psSHP->adBoundsMin[0], shape->line[i].point[j].x); psSHP->adBoundsMin[1] = MS_MIN(psSHP->adBoundsMin[1], shape->line[i].point[j].y); #ifdef USE_POINT_Z_M psSHP->adBoundsMin[2] = MS_MIN(psSHP->adBoundsMin[2], shape->line[i].point[j].z); psSHP->adBoundsMin[3] = MS_MIN(psSHP->adBoundsMin[3], shape->line[i].point[j].m); #endif psSHP->adBoundsMax[0] = MS_MAX(psSHP->adBoundsMax[0], shape->line[i].point[j].x); psSHP->adBoundsMax[1] = MS_MAX(psSHP->adBoundsMax[1], shape->line[i].point[j].y); #ifdef USE_POINT_Z_M psSHP->adBoundsMax[2] = MS_MAX(psSHP->adBoundsMax[2], shape->line[i].point[j].z); psSHP->adBoundsMax[3] = MS_MAX(psSHP->adBoundsMax[3], shape->line[i].point[j].m); #endif } } } else { psSHP->nRecords --; /* there was an error writing the record */ } free( pabyRec ); return( psSHP->nRecords - 1 ); } /* ** msSHPReadAllocateBuffer() - Ensure our record buffer is large enough. */ static int msSHPReadAllocateBuffer( SHPHandle psSHP, int hEntity, const char* pszCallingFunction) { int nEntitySize = msSHXReadSize(psSHP, hEntity) + 8; /* -------------------------------------------------------------------- */ /* Ensure our record buffer is large enough. */ /* -------------------------------------------------------------------- */ if( nEntitySize > psSHP->nBufSize ) { psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize); if (psSHP->pabyRec == NULL) { /* Reallocate previous successfull size for following features */ psSHP->pabyRec = msSmallMalloc(psSHP->nBufSize); msSetError(MS_MEMERR, "Out of memory. Cannot allocate %d bytes. Probably broken shapefile at feature %d", pszCallingFunction, nEntitySize, hEntity); return(MS_FAILURE); } psSHP->nBufSize = nEntitySize; } if (psSHP->pabyRec == NULL) { msSetError(MS_MEMERR, "Out of memory", pszCallingFunction); return(MS_FAILURE); } return MS_SUCCESS; } /* ** msSHPReadPoint() - Reads a single point from a POINT shape file. */ int msSHPReadPoint( SHPHandle psSHP, int hEntity, pointObj *point ) { int nEntitySize; /* -------------------------------------------------------------------- */ /* Only valid for point shapefiles */ /* -------------------------------------------------------------------- */ if( psSHP->nShapeType != SHP_POINT ) { msSetError(MS_SHPERR, "msSHPReadPoint only operates on point shapefiles.", "msSHPReadPoint()"); return(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* Validate the record/entity number. */ /* -------------------------------------------------------------------- */ if( hEntity < 0 || hEntity >= psSHP->nRecords ) { msSetError(MS_SHPERR, "Record index out of bounds.", "msSHPReadPoint()"); return(MS_FAILURE); } nEntitySize = msSHXReadSize( psSHP, hEntity) + 8; if( msSHXReadSize( psSHP, hEntity) == 4 ) { msSetError(MS_SHPERR, "NULL feature encountered.", "msSHPReadPoint()"); return(MS_FAILURE); } else if ( nEntitySize < 28 ) { msSetError(MS_SHPERR, "Corrupted feature encountered. hEntity=%d, nEntitySize=%d", "msSHPReadPoint()", hEntity, nEntitySize); return(MS_FAILURE); } if (msSHPReadAllocateBuffer(psSHP, hEntity, "msSHPReadPoint()") == MS_FAILURE) { return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Read the record. */ /* -------------------------------------------------------------------- */ if( 0 != fseek( psSHP->fpSHP, msSHXReadOffset( psSHP, hEntity), 0 )) { msSetError(MS_IOERR, "failed to seek offset", "msSHPReadPoint()"); return(MS_FAILURE); } if( 1 != fread( psSHP->pabyRec, nEntitySize, 1, psSHP->fpSHP )) { msSetError(MS_IOERR, "failed to fread record", "msSHPReadPoint()"); return(MS_FAILURE); } memcpy( &(point->x), psSHP->pabyRec + 12, 8 ); memcpy( &(point->y), psSHP->pabyRec + 20, 8 ); if( bBigEndian ) { SwapWord( 8, &(point->x)); SwapWord( 8, &(point->y)); } return(MS_SUCCESS); } /* ** msSHXLoadPage() ** ** The SHX tells us what the byte offsets of the shapes in the SHP file are. ** We read the SHX file in ~8K pages and store those pages in memory for ** successive accesses during the reading cycle (first bounds are read, ** then entire shapes). Each time we read a page, we mark it as read. */ int msSHXLoadPage( SHPHandle psSHP, int shxBufferPage ) { int i; /* Each SHX record is 8 bytes long (two ints), hence our buffer size. */ char buffer[SHX_BUFFER_PAGE * 8]; /* Validate the page number. */ if( shxBufferPage < 0 ) return(MS_FAILURE); if( 0 != fseek( psSHP->fpSHX, 100 + shxBufferPage * SHX_BUFFER_PAGE * 8, 0 )) { /* * msSetError(MS_IOERR, "failed to seek offset", "msSHXLoadPage()"); * return(MS_FAILURE); */ } if( SHX_BUFFER_PAGE != fread( buffer, 8, SHX_BUFFER_PAGE, psSHP->fpSHX )) { /* * msSetError(MS_IOERR, "failed to fread SHX record", "msSHXLoadPage()"); * return(MS_FAILURE); */ } /* Copy the buffer contents out into the working arrays. */ for( i = 0; i < SHX_BUFFER_PAGE; i++ ) { int tmpOffset, tmpSize; /* Don't write information past the end of the arrays, please. */ if(psSHP->nRecords <= (shxBufferPage * SHX_BUFFER_PAGE + i) ) break; memcpy( &tmpOffset, (buffer + (8*i)), 4); memcpy( &tmpSize, (buffer + (8*i) + 4), 4); /* SHX uses big endian numbers for the offsets, so we have to flip them */ /* if we are a little endian machine. */ if( !bBigEndian ) { tmpOffset = SWAP_FOUR_BYTES(tmpOffset); tmpSize = SWAP_FOUR_BYTES(tmpSize); } /* SHX stores the offsets in 2 byte units, so we double them to get */ /* an offset in bytes. */ tmpOffset = tmpOffset * 2; tmpSize = tmpSize * 2; /* Write the answer into the working arrays on the SHPHandle */ psSHP->panRecOffset[shxBufferPage * SHX_BUFFER_PAGE + i] = tmpOffset; psSHP->panRecSize[shxBufferPage * SHX_BUFFER_PAGE + i] = tmpSize; } msSetBit(psSHP->panRecLoaded, shxBufferPage, 1); return(MS_SUCCESS); } int msSHXLoadAll( SHPHandle psSHP ) { int i; uchar *pabyBuf; pabyBuf = (uchar *) msSmallMalloc(8 * psSHP->nRecords ); if(psSHP->nRecords != fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX )) { msSetError(MS_IOERR, "failed to read shx records", "msSHXLoadAll()"); free(pabyBuf); return MS_FAILURE; } for( i = 0; i < psSHP->nRecords; i++ ) { ms_int32 nOffset, nLength; memcpy( &nOffset, pabyBuf + i * 8, 4 ); memcpy( &nLength, pabyBuf + i * 8 + 4, 4 ); if( !bBigEndian ) { nOffset = SWAP_FOUR_BYTES( nOffset ); nLength = SWAP_FOUR_BYTES( nLength ); } psSHP->panRecOffset[i] = nOffset*2; psSHP->panRecSize[i] = nLength*2; } free(pabyBuf); psSHP->panRecAllLoaded = 1; return(MS_SUCCESS); } int msSHXReadOffset( SHPHandle psSHP, int hEntity ) { int shxBufferPage = hEntity / SHX_BUFFER_PAGE; /* Validate the record/entity number. */ if( hEntity < 0 || hEntity >= psSHP->nRecords ) return(MS_FAILURE); if( ! (psSHP->panRecAllLoaded || msGetBit(psSHP->panRecLoaded, shxBufferPage)) ) { msSHXLoadPage( psSHP, shxBufferPage ); } return psSHP->panRecOffset[hEntity]; } int msSHXReadSize( SHPHandle psSHP, int hEntity ) { int shxBufferPage = hEntity / SHX_BUFFER_PAGE; /* Validate the record/entity number. */ if( hEntity < 0 || hEntity >= psSHP->nRecords ) return(MS_FAILURE); if( ! (psSHP->panRecAllLoaded || msGetBit(psSHP->panRecLoaded, shxBufferPage)) ) { msSHXLoadPage( psSHP, shxBufferPage ); } return psSHP->panRecSize[hEntity]; } /* ** msSHPReadShape() - Reads the vertices for one shape from a shape file. */ void msSHPReadShape( SHPHandle psSHP, int hEntity, shapeObj *shape ) { int i, j, k; #ifdef USE_POINT_Z_M int nOffset = 0; #endif int nEntitySize, nRequiredSize; msInitShape(shape); /* initialize the shape */ /* -------------------------------------------------------------------- */ /* Validate the record/entity number. */ /* -------------------------------------------------------------------- */ if( hEntity < 0 || hEntity >= psSHP->nRecords ) return; if( msSHXReadSize(psSHP, hEntity) == 4 ) { shape->type = MS_SHAPE_NULL; return; } nEntitySize = msSHXReadSize(psSHP, hEntity) + 8; if (msSHPReadAllocateBuffer(psSHP, hEntity, "msSHPReadShape()") == MS_FAILURE) { shape->type = MS_SHAPE_NULL; return; } /* -------------------------------------------------------------------- */ /* Read the record. */ /* -------------------------------------------------------------------- */ if( 0 != fseek( psSHP->fpSHP, msSHXReadOffset( psSHP, hEntity), 0 )) { msSetError(MS_IOERR, "failed to seek offset", "msSHPReadShape()"); shape->type = MS_SHAPE_NULL; return; } if( 1 != fread( psSHP->pabyRec, nEntitySize, 1, psSHP->fpSHP )) { msSetError(MS_IOERR, "failed to fread record", "msSHPReadPoint()"); shape->type = MS_SHAPE_NULL; return; } /* -------------------------------------------------------------------- */ /* Extract vertices for a Polygon or Arc. */ /* -------------------------------------------------------------------- */ if( psSHP->nShapeType == SHP_POLYGON || psSHP->nShapeType == SHP_ARC || psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM || psSHP->nShapeType == SHP_POLYGONZ || psSHP->nShapeType == SHP_ARCZ) { ms_int32 nPoints, nParts; if (nEntitySize < 40 + 8 + 4) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted feature encountered. hEntity = %d, nEntitySize=%d", "msSHPReadShape()", hEntity, nEntitySize); return; } /* copy the bounding box */ memcpy( &shape->bounds.minx, psSHP->pabyRec + 8 + 4, 8 ); memcpy( &shape->bounds.miny, psSHP->pabyRec + 8 + 12, 8 ); memcpy( &shape->bounds.maxx, psSHP->pabyRec + 8 + 20, 8 ); memcpy( &shape->bounds.maxy, psSHP->pabyRec + 8 + 28, 8 ); if( bBigEndian ) { SwapWord( 8, &shape->bounds.minx); SwapWord( 8, &shape->bounds.miny); SwapWord( 8, &shape->bounds.maxx); SwapWord( 8, &shape->bounds.maxy); } memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 ); memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 ); if( bBigEndian ) { nPoints = SWAP_FOUR_BYTES(nPoints); nParts = SWAP_FOUR_BYTES(nParts); } if (nPoints < 0 || nParts < 0 || nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted feature encountered. hEntity = %d, nPoints =%d, nParts = %d", "msSHPReadShape()", hEntity, nPoints, nParts); return; } /* -------------------------------------------------------------------- */ /* Copy out the part array from the record. */ /* -------------------------------------------------------------------- */ if( psSHP->nPartMax < nParts ) { psSHP->panParts = (int *) SfRealloc(psSHP->panParts, nParts * sizeof(int) ); if (psSHP->panParts == NULL) { /* Reallocate previous successfull size for following features */ psSHP->panParts = (int *) msSmallMalloc(psSHP->nPartMax * sizeof(int) ); shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory. Cannot allocate %d bytes. Probably broken shapefile at feature %d", "msSHPReadShape()", (int)(nParts * sizeof(int)), hEntity); return; } psSHP->nPartMax = nParts; } if (psSHP->panParts == NULL) { shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory", "msSHPReadShape()"); return; } /* With the previous checks on nPoints and nParts, */ /* we should not overflow here and after */ /* since 50 M * (16 + 8 + 8) = 1 600 MB */ if (44 + 8 + 4 * nParts + 16 * nPoints > nEntitySize) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.", "msSHPReadShape()", hEntity, nPoints, nParts); return; } memcpy( psSHP->panParts, psSHP->pabyRec + 44 + 8, 4 * nParts ); if( bBigEndian ) { for( i = 0; i < nParts; i++ ) { *(psSHP->panParts+i) = SWAP_FOUR_BYTES(*(psSHP->panParts+i)); } } /* -------------------------------------------------------------------- */ /* Fill the shape structure. */ /* -------------------------------------------------------------------- */ shape->line = (lineObj *)malloc(sizeof(lineObj)*nParts); MS_CHECK_ALLOC_NO_RET(shape->line, sizeof(lineObj)*nParts); shape->numlines = nParts; k = 0; /* overall point counter */ for( i = 0; i < nParts; i++) { if( i == nParts-1) shape->line[i].numpoints = nPoints - psSHP->panParts[i]; else shape->line[i].numpoints = psSHP->panParts[i+1] - psSHP->panParts[i]; if (shape->line[i].numpoints <= 0) { msSetError(MS_SHPERR, "Corrupted .shp file : shape %d, shape->line[%d].numpoints=%d", "msSHPReadShape()", hEntity, i, shape->line[i].numpoints); while(--i >= 0) free(shape->line[i].point); free(shape->line); shape->line = NULL; shape->numlines = 0; shape->type = MS_SHAPE_NULL; return; } if( (shape->line[i].point = (pointObj *)malloc(sizeof(pointObj)*shape->line[i].numpoints)) == NULL ) { while(--i >= 0) free(shape->line[i].point); free(shape->line); shape->numlines = 0; shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory", "msSHPReadShape()"); return; } /* nOffset = 44 + 8 + 4*nParts; */ for( j = 0; j < shape->line[i].numpoints; j++ ) { memcpy(&(shape->line[i].point[j].x), psSHP->pabyRec + 44 + 4*nParts + 8 + k * 16, 8 ); memcpy(&(shape->line[i].point[j].y), psSHP->pabyRec + 44 + 4*nParts + 8 + k * 16 + 8, 8 ); if( bBigEndian ) { SwapWord( 8, &(shape->line[i].point[j].x) ); SwapWord( 8, &(shape->line[i].point[j].y) ); } #ifdef USE_POINT_Z_M /* -------------------------------------------------------------------- */ /* Polygon, Arc with Z values. */ /* -------------------------------------------------------------------- */ shape->line[i].point[j].z = 0.0; /* initialize */ if (psSHP->nShapeType == SHP_POLYGONZ || psSHP->nShapeType == SHP_ARCZ) { nOffset = 44 + 8 + (4*nParts) + (16*nPoints) ; if( nEntitySize >= nOffset + 16 + 8*nPoints ) { memcpy(&(shape->line[i].point[j].z), psSHP->pabyRec + nOffset + 16 + k*8, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[i].point[j].z) ); } } /* -------------------------------------------------------------------- */ /* Measured arc and polygon support. */ /* -------------------------------------------------------------------- */ shape->line[i].point[j].m = 0; /* initialize */ if (psSHP->nShapeType == SHP_POLYGONM || psSHP->nShapeType == SHP_ARCM) { nOffset = 44 + 8 + (4*nParts) + (16*nPoints) ; if( nEntitySize >= nOffset + 16 + 8*nPoints ) { memcpy(&(shape->line[i].point[j].m), psSHP->pabyRec + nOffset + 16 + k*8, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[i].point[j].m) ); } } #endif /* USE_POINT_Z_M */ k++; } } if(psSHP->nShapeType == SHP_POLYGON || psSHP->nShapeType == SHP_POLYGONZ || psSHP->nShapeType == SHP_POLYGONM) shape->type = MS_SHAPE_POLYGON; else shape->type = MS_SHAPE_LINE; } /* -------------------------------------------------------------------- */ /* Extract a MultiPoint. */ /* -------------------------------------------------------------------- */ else if( psSHP->nShapeType == SHP_MULTIPOINT || psSHP->nShapeType == SHP_MULTIPOINTM || psSHP->nShapeType == SHP_MULTIPOINTZ) { ms_int32 nPoints; if (nEntitySize < 44 + 4) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted feature encountered. recSize of feature %d=%d", "msSHPReadShape()", hEntity, msSHXReadSize(psSHP, hEntity)); return; } /* copy the bounding box */ memcpy( &shape->bounds.minx, psSHP->pabyRec + 8 + 4, 8 ); memcpy( &shape->bounds.miny, psSHP->pabyRec + 8 + 12, 8 ); memcpy( &shape->bounds.maxx, psSHP->pabyRec + 8 + 20, 8 ); memcpy( &shape->bounds.maxy, psSHP->pabyRec + 8 + 28, 8 ); if( bBigEndian ) { SwapWord( 8, &shape->bounds.minx); SwapWord( 8, &shape->bounds.miny); SwapWord( 8, &shape->bounds.maxx); SwapWord( 8, &shape->bounds.maxy); } memcpy( &nPoints, psSHP->pabyRec + 44, 4 ); if( bBigEndian ) nPoints = SWAP_FOUR_BYTES(nPoints); /* -------------------------------------------------------------------- */ /* Fill the shape structure. */ /* -------------------------------------------------------------------- */ if( (shape->line = (lineObj *)malloc(sizeof(lineObj))) == NULL ) { shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory", "msSHPReadShape()"); return; } if (nPoints < 0 || nPoints > 50 * 1000 * 1000) { free(shape->line); shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted .shp file : shape %d, nPoints=%d.", "msSHPReadShape()", hEntity, nPoints); return; } nRequiredSize = 48 + nPoints * 16; if (psSHP->nShapeType == SHP_MULTIPOINTZ || psSHP->nShapeType == SHP_MULTIPOINTM) nRequiredSize += 16 + nPoints * 8; if (nRequiredSize > nEntitySize) { free(shape->line); shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d", "msSHPReadShape()", hEntity, nPoints, nEntitySize); return; } shape->numlines = 1; shape->line[0].numpoints = nPoints; shape->line[0].point = (pointObj *) malloc( nPoints * sizeof(pointObj) ); if (shape->line[0].point == NULL) { free(shape->line); shape->numlines = 0; shape->type = MS_SHAPE_NULL; msSetError(MS_MEMERR, "Out of memory", "msSHPReadShape()"); return; } for( i = 0; i < nPoints; i++ ) { memcpy(&(shape->line[0].point[i].x), psSHP->pabyRec + 48 + 16 * i, 8 ); memcpy(&(shape->line[0].point[i].y), psSHP->pabyRec + 48 + 16 * i + 8, 8 ); if( bBigEndian ) { SwapWord( 8, &(shape->line[0].point[i].x) ); SwapWord( 8, &(shape->line[0].point[i].y) ); } #ifdef USE_POINT_Z_M /* -------------------------------------------------------------------- */ /* MulipointZ */ /* -------------------------------------------------------------------- */ shape->line[0].point[i].z = 0; /* initialize */ if (psSHP->nShapeType == SHP_MULTIPOINTZ) { nOffset = 48 + 16*nPoints; memcpy(&(shape->line[0].point[i].z), psSHP->pabyRec + nOffset + 16 + i*8, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[0].point[i].z)); } /* -------------------------------------------------------------------- */ /* Measured shape : multipont. */ /* -------------------------------------------------------------------- */ shape->line[0].point[i].m = 0; /* initialize */ if (psSHP->nShapeType == SHP_MULTIPOINTM) { nOffset = 48 + 16*nPoints; memcpy(&(shape->line[0].point[i].m), psSHP->pabyRec + nOffset + 16 + i*8, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[0].point[i].m)); } #endif /* USE_POINT_Z_M */ } shape->type = MS_SHAPE_POINT; } /* -------------------------------------------------------------------- */ /* Extract a Point. */ /* -------------------------------------------------------------------- */ else if(psSHP->nShapeType == SHP_POINT || psSHP->nShapeType == SHP_POINTM || psSHP->nShapeType == SHP_POINTZ) { if (nEntitySize < 20 + 8) { shape->type = MS_SHAPE_NULL; msSetError(MS_SHPERR, "Corrupted feature encountered. recSize of feature %d=%d", "msSHPReadShape()", hEntity, msSHXReadSize(psSHP, hEntity)); return; } /* -------------------------------------------------------------------- */ /* Fill the shape structure. */ /* -------------------------------------------------------------------- */ shape->line = (lineObj *)malloc(sizeof(lineObj)); MS_CHECK_ALLOC_NO_RET(shape->line, sizeof(lineObj)); shape->numlines = 1; shape->line[0].numpoints = 1; shape->line[0].point = (pointObj *) msSmallMalloc(sizeof(pointObj)); memcpy( &(shape->line[0].point[0].x), psSHP->pabyRec + 12, 8 ); memcpy( &(shape->line[0].point[0].y), psSHP->pabyRec + 20, 8 ); if( bBigEndian ) { SwapWord( 8, &(shape->line[0].point[0].x)); SwapWord( 8, &(shape->line[0].point[0].y)); } #ifdef USE_POINT_Z_M /* -------------------------------------------------------------------- */ /* PointZ */ /* -------------------------------------------------------------------- */ shape->line[0].point[0].z = 0; /* initialize */ if (psSHP->nShapeType == SHP_POINTZ) { nOffset = 20 + 8; if( nEntitySize >= nOffset + 8 ) { memcpy(&(shape->line[0].point[0].z), psSHP->pabyRec + nOffset, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[0].point[0].z)); } } /* -------------------------------------------------------------------- */ /* Measured support : point. */ /* -------------------------------------------------------------------- */ shape->line[0].point[0].m = 0; /* initialize */ if (psSHP->nShapeType == SHP_POINTM) { nOffset = 20 + 8; if( nEntitySize >= nOffset + 8 ) { memcpy(&(shape->line[0].point[0].m), psSHP->pabyRec + nOffset, 8 ); if( bBigEndian ) SwapWord( 8, &(shape->line[0].point[0].m)); } } #endif /* USE_POINT_Z_M */ /* set the bounding box to the point */ shape->bounds.minx = shape->bounds.maxx = shape->line[0].point[0].x; shape->bounds.miny = shape->bounds.maxy = shape->line[0].point[0].y; shape->type = MS_SHAPE_POINT; } shape->index = hEntity; return; } int msSHPReadBounds( SHPHandle psSHP, int hEntity, rectObj *padBounds) { /* -------------------------------------------------------------------- */ /* Validate the record/entity number. */ /* -------------------------------------------------------------------- */ if( psSHP->nRecords <= 0 || hEntity < -1 || hEntity >= psSHP->nRecords ) { padBounds->minx = padBounds->miny = padBounds->maxx = padBounds->maxy = 0.0; return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* If the entity is -1 we fetch the bounds for the whole file. */ /* -------------------------------------------------------------------- */ if( hEntity == -1 ) { padBounds->minx = psSHP->adBoundsMin[0]; padBounds->miny = psSHP->adBoundsMin[1]; padBounds->maxx = psSHP->adBoundsMax[0]; padBounds->maxy = psSHP->adBoundsMax[1]; } else { if( msSHXReadSize(psSHP, hEntity) == 4 ) { /* NULL shape */ padBounds->minx = padBounds->miny = padBounds->maxx = padBounds->maxy = 0.0; return MS_FAILURE; } if( psSHP->nShapeType != SHP_POINT && psSHP->nShapeType != SHP_POINTZ && psSHP->nShapeType != SHP_POINTM) { if( 0 != fseek( psSHP->fpSHP, msSHXReadOffset( psSHP, hEntity) + 12, 0 )) { msSetError(MS_IOERR, "failed to seek offset", "msSHPReadBounds()"); return(MS_FAILURE); } if( 1 != fread( padBounds, sizeof(double)*4, 1, psSHP->fpSHP )) { msSetError(MS_IOERR, "failed to fread record", "msSHPReadBounds()"); return(MS_FAILURE); } if( bBigEndian ) { SwapWord( 8, &(padBounds->minx) ); SwapWord( 8, &(padBounds->miny) ); SwapWord( 8, &(padBounds->maxx) ); SwapWord( 8, &(padBounds->maxy) ); } if(msIsNan(padBounds->minx)) { /* empty shape */ padBounds->minx = padBounds->miny = padBounds->maxx = padBounds->maxy = 0.0; return MS_FAILURE; } } else { /* -------------------------------------------------------------------- */ /* For points we fetch the point, and duplicate it as the */ /* minimum and maximum bound. */ /* -------------------------------------------------------------------- */ if( 0 != fseek( psSHP->fpSHP, msSHXReadOffset( psSHP, hEntity) + 12, 0 )) { msSetError(MS_IOERR, "failed to seek offset", "msSHPReadBounds()"); return(MS_FAILURE); } if( 1 != fread( padBounds, sizeof(double)*2, 1, psSHP->fpSHP )) { msSetError(MS_IOERR, "failed to fread record", "msSHPReadBounds()"); return(MS_FAILURE); } if( bBigEndian ) { SwapWord( 8, &(padBounds->minx) ); SwapWord( 8, &(padBounds->miny) ); } padBounds->maxx = padBounds->minx; padBounds->maxy = padBounds->miny; } } return MS_SUCCESS; } int msShapefileOpen(shapefileObj *shpfile, const char *mode, const char *filename, int log_failures) { int i; char *dbfFilename; size_t bufferSize = 0; if(!filename) { if( log_failures ) msSetError(MS_IOERR, "No (NULL) filename provided.", "msShapefileOpen()"); return(-1); } /* initialize a few things */ shpfile->status = NULL; shpfile->lastshape = -1; shpfile->isopen = MS_FALSE; /* open the shapefile file (appending ok) and get basic info */ if(!mode) shpfile->hSHP = msSHPOpen( filename, "rb"); else shpfile->hSHP = msSHPOpen( filename, mode); if(!shpfile->hSHP) { if( log_failures ) msSetError(MS_IOERR, "(%s)", "msShapefileOpen()", filename); return(-1); } strlcpy(shpfile->source, filename, sizeof(shpfile->source)); /* load some information about this shapefile */ msSHPGetInfo( shpfile->hSHP, &shpfile->numshapes, &shpfile->type); msSHPReadBounds( shpfile->hSHP, -1, &(shpfile->bounds)); bufferSize = strlen(filename)+5; dbfFilename = (char *)msSmallMalloc(bufferSize); dbfFilename[0] = '\0'; strcpy(dbfFilename, filename); /* clean off any extention the filename might have */ for (i = strlen(dbfFilename) - 1; i > 0 && dbfFilename[i] != '.' && dbfFilename[i] != '/' && dbfFilename[i] != '\\'; i-- ) {} if( dbfFilename[i] == '.' ) dbfFilename[i] = '\0'; strlcat(dbfFilename, ".dbf", bufferSize); shpfile->hDBF = msDBFOpen(dbfFilename, "rb"); if(!shpfile->hDBF) { if( log_failures ) msSetError(MS_IOERR, "(%s)", "msShapefileOpen()", dbfFilename); free(dbfFilename); return(-1); } free(dbfFilename); shpfile->isopen = MS_TRUE; return(0); /* all o.k. */ } /* Creates a new shapefile */ int msShapefileCreate(shapefileObj *shpfile, char *filename, int type) { if(type != SHP_POINT && type != SHP_MULTIPOINT && type != SHP_ARC && type != SHP_POLYGON && type != SHP_POINTM && type != SHP_MULTIPOINTM && type != SHP_ARCM && type != SHP_POLYGONM && type != SHP_POINTZ && type != SHP_MULTIPOINTZ && type != SHP_ARCZ && type != SHP_POLYGONZ) { msSetError(MS_SHPERR, "Invalid shape type.", "msNewSHPFile()"); return(-1); } /* create the spatial portion */ shpfile->hSHP = msSHPCreate(filename, type); if(!shpfile->hSHP) { msSetError(MS_IOERR, "(%s)", "msNewSHPFile()",filename); return(-1); } /* retrieve a few things about this shapefile */ msSHPGetInfo( shpfile->hSHP, &shpfile->numshapes, &shpfile->type); msSHPReadBounds( shpfile->hSHP, -1, &(shpfile->bounds)); /* initialize a few other things */ shpfile->status = NULL; shpfile->lastshape = -1; shpfile->isopen = MS_TRUE; shpfile->hDBF = NULL; /* XBase file is NOT created here... */ return(0); } void msShapefileClose(shapefileObj *shpfile) { if (shpfile && shpfile->isopen == MS_TRUE) { /* Silently return if called with NULL shpfile by freeLayer() */ if(shpfile->hSHP) msSHPClose(shpfile->hSHP); if(shpfile->hDBF) msDBFClose(shpfile->hDBF); free(shpfile->status); shpfile->isopen = MS_FALSE; } } /* status array lives in the shpfile, can return MS_SUCCESS/MS_FAILURE/MS_DONE */ int msShapefileWhichShapes(shapefileObj *shpfile, rectObj rect, int debug) { int i; rectObj shaperect; char *filename; char *sourcename = 0; /* shape file source string from map file */ char *s = 0; /* pointer to start of '.shp' in source string */ free(shpfile->status); shpfile->status = NULL; /* rect and shapefile DON'T overlap... */ if(msRectOverlap(&shpfile->bounds, &rect) != MS_TRUE) return(MS_DONE); if(msRectContained(&shpfile->bounds, &rect) == MS_TRUE) { shpfile->status = msAllocBitArray(shpfile->numshapes); if(!shpfile->status) { msSetError(MS_MEMERR, NULL, "msShapefileWhichShapes()"); return(MS_FAILURE); } msSetAllBits(shpfile->status, shpfile->numshapes, 1); } else { /* deal with case where sourcename is of the form 'file.shp' */ sourcename = msStrdup(shpfile->source); s = strstr(sourcename, ".shp"); if( s ) *s = '\0'; else { s = strstr(sourcename, ".SHP"); if( s ) *s = '\0'; } filename = (char *)malloc(strlen(sourcename)+strlen(MS_INDEX_EXTENSION)+1); MS_CHECK_ALLOC(filename, strlen(sourcename)+strlen(MS_INDEX_EXTENSION)+1, MS_FAILURE); sprintf(filename, "%s%s", sourcename, MS_INDEX_EXTENSION); shpfile->status = msSearchDiskTree(filename, rect, debug, shpfile->numshapes); free(filename); free(sourcename); if(shpfile->status) { /* index */ msFilterTreeSearch(shpfile, shpfile->status, rect); } else { /* no index */ shpfile->status = msAllocBitArray(shpfile->numshapes); if(!shpfile->status) { msSetError(MS_MEMERR, NULL, "msShapefileWhichShapes()"); return(MS_FAILURE); } for(i=0; inumshapes; i++) { if(msSHPReadBounds(shpfile->hSHP, i, &shaperect) == MS_SUCCESS) if(msRectOverlap(&shaperect, &rect) == MS_TRUE) msSetBit(shpfile->status, i, 1); } } } shpfile->lastshape = -1; return(MS_SUCCESS); /* success */ } /* Return the absolute path to the given layer's tileindex file's directory */ void msTileIndexAbsoluteDir(char *tiFileAbsDir, layerObj *layer) { char tiFileAbsPath[MS_MAXPATHLEN]; char *tiFileAbsDirTmp=NULL; msBuildPath(tiFileAbsPath, layer->map->mappath, layer->tileindex); /* absolute path to tileindex file */ tiFileAbsDirTmp = msGetPath(tiFileAbsPath); /* tileindex file's directory */ strlcpy(tiFileAbsDir, tiFileAbsDirTmp, MS_MAXPATHLEN); free(tiFileAbsDirTmp); } /* ** Build possible paths we might find the tile file at: ** map dir + shape path + filename? ** tile dir + shape path + filename? ** map dir + filename? ** ** Returns ** MS_SUCCESS - found a file ** MS_FAILURE - no file, and map is configured to fail on missing ** MS_DONE - no file, and map is configured to continue on missing */ static int msTiledSHPTryOpen(shapefileObj *shpfile, layerObj *layer, char *tiFileAbsDir, const char *filename) { char szPath[MS_MAXPATHLEN]; int ignore_missing = msMapIgnoreMissingData(layer->map); int log_failures = MS_TRUE; if( ignore_missing == MS_MISSING_DATA_IGNORE ) log_failures = MS_FALSE; if(msShapefileOpen(shpfile, "rb", msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, filename), log_failures) == -1) { if(msShapefileOpen(shpfile, "rb", msBuildPath3(szPath, tiFileAbsDir, layer->map->shapepath, filename), log_failures) == -1) { if(msShapefileOpen(shpfile, "rb", msBuildPath(szPath, layer->map->mappath, filename), log_failures) == -1) { if(ignore_missing == MS_MISSING_DATA_FAIL) { msSetError(MS_IOERR, "Unable to open shapefile '%s' for layer '%s' ... fatal error.", "msTiledSHPTryOpen()", filename, layer->name); return(MS_FAILURE); } else if( ignore_missing == MS_MISSING_DATA_LOG ) { if( layer->debug || layer->map->debug ) { msDebug( "Unable to open shapefile '%s' for layer '%s' ... ignoring this missing data.\n", szPath, layer->name ); } return(MS_DONE); } else if( ignore_missing == MS_MISSING_DATA_IGNORE ) { return(MS_DONE); } else { /* never get here */ msSetError(MS_IOERR, "msIgnoreMissingData returned unexpected value.", "msTiledSHPTryOpen()"); return(MS_FAILURE); } } } } return(MS_SUCCESS); } static const char* msTiledSHPLoadEntry(layerObj *layer, int i, char* tilename, size_t tilenamesize) { const char* filename; msTiledSHPLayerInfo *tSHP= layer->layerinfo; msFreeProjection(&(tSHP->sTileProj)); if( layer->tilesrs != NULL ) { int idx = msDBFGetItemIndex(tSHP->tileshpfile->hDBF, layer->tilesrs); const char* pszWKT = msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, idx); msOGCWKT2ProjectionObj(pszWKT, &(tSHP->sTileProj), layer->debug ); } if(!layer->data) /* assume whole filename is in attribute field */ filename =msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, layer->tileitemindex); else { snprintf(tilename, tilenamesize, "%s/%s", msDBFReadStringAttribute(tSHP->tileshpfile->hDBF, i, layer->tileitemindex) , layer->data); filename = tilename; } return filename; } static int msTiledSHPOpenFile(layerObj *layer) { int i; const char *filename; char tilename[MS_MAXPATHLEN], szPath[MS_MAXPATHLEN]; char tiFileAbsDir[MS_MAXPATHLEN]; msTiledSHPLayerInfo *tSHP=NULL; if (layer->layerinfo != NULL) { return MS_SUCCESS; // Nothing to do... layer is already opened } if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; /* allocate space for a shapefileObj using layer->layerinfo */ tSHP = (msTiledSHPLayerInfo *) malloc(sizeof(msTiledSHPLayerInfo)); MS_CHECK_ALLOC(tSHP, sizeof(msTiledSHPLayerInfo), MS_FAILURE); msInitProjection(&(tSHP->sTileProj)); tSHP->shpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); if (tSHP->shpfile == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msTiledSHPOpenFile()", __FILE__, __LINE__, (unsigned int)sizeof(shapefileObj)); msFreeProjection(&(tSHP->sTileProj)); free(tSHP); return MS_FAILURE; } tSHP->shpfile->isopen = MS_FALSE; /* in case of error: do not try to close the shpfile */ tSHP->tileshpfile = NULL; /* may need this if not using a tile layer, look for malloc later */ layer->layerinfo = tSHP; tSHP->tilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); if(tSHP->tilelayerindex != -1) { /* does the tileindex reference another layer */ int status; layerObj *tlp; tlp = (GET_LAYER(layer->map, tSHP->tilelayerindex)); if(tlp->connectiontype != MS_SHAPEFILE) { msSetError(MS_SHPERR, "Tileindex layer must be a shapefile.", "msTiledSHPOpenFile()"); return(MS_FAILURE); } status = msLayerOpen(tlp); if(status != MS_SUCCESS) return(MS_FAILURE); /* build item list */ status = msLayerWhichItems(tlp, MS_FALSE, NULL); if(status != MS_SUCCESS) return(MS_FAILURE); tSHP->tileshpfile = (shapefileObj *) tlp->layerinfo; /* shapefiles use layerinfo to point to a shapefileObj */ } else { /* or reference a shapefile directly */ /* we need tSHP->tileshpfile if we're not working with a layer */ tSHP->tileshpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); if (tSHP->tileshpfile == NULL) { msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msTiledSHPOpenFile()", __FILE__, __LINE__, (unsigned int)sizeof(shapefileObj)); free(tSHP->shpfile); msFreeProjection(&(tSHP->sTileProj)); free(tSHP); layer->layerinfo = NULL; return MS_FAILURE; } if(msShapefileOpen(tSHP->tileshpfile, "rb", msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, layer->tileindex), MS_TRUE) == -1) if(msShapefileOpen(tSHP->tileshpfile, "rb", msBuildPath(szPath, layer->map->mappath, layer->tileindex), MS_TRUE) == -1) return(MS_FAILURE); } if((layer->tileitemindex = msDBFGetItemIndex(tSHP->tileshpfile->hDBF, layer->tileitem)) == -1) return(MS_FAILURE); if( layer->tilesrs != NULL && msDBFGetItemIndex(tSHP->tileshpfile->hDBF, layer->tilesrs) < 0 ) { msSetError(MS_SHPERR, "Cannot identify TILESRS field.", "msTiledSHPOpenFile()"); return MS_FAILURE; } if( layer->tilesrs != NULL && layer->projection.numargs == 0 ) { msSetError(MS_SHPERR, "A layer with TILESRS set in TILEINDEX `%s' must have a " "projection set on itself.", "msOGRLayerOpen()", layer->tileindex ); return MS_FAILURE; } msTileIndexAbsoluteDir(tiFileAbsDir, layer); /* position the source at the FIRST tile to use as a template, this is so the functions that fill the iteminfo array have something to work from */ for(i=0; itileshpfile->numshapes; i++) { int try_open; filename = msTiledSHPLoadEntry(layer, i, tilename, sizeof(tilename)); if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); return(MS_SUCCESS); /* found a template, ok to proceed */ } msSetError(MS_SHPERR, "Unable to open a single tile to use as a template in layer %s.", "msTiledSHPOpenFile()", layer->name?layer->name:"(null)"); return(MS_FAILURE); } static int msTiledSHPWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int i, status; const char *filename; char tilename[MS_MAXPATHLEN]; char tiFileAbsDir[MS_MAXPATHLEN]; msTiledSHPLayerInfo *tSHP=NULL; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPWhichShapes()"); return(MS_FAILURE); } msShapefileClose(tSHP->shpfile); /* close previously opened files */ tSHP->searchrect = rect; /* save the search extent */ if(tSHP->tilelayerindex != -1) { /* does the tileindex reference another layer */ layerObj *tlp; shapeObj tshape; tlp = (GET_LAYER(layer->map, tSHP->tilelayerindex)); status= msLayerWhichShapes(tlp, rect, isQuery); if(status != MS_SUCCESS) return(status); /* could be MS_DONE or MS_FAILURE */ msTileIndexAbsoluteDir(tiFileAbsDir, layer); msInitShape(&tshape); while((status = msLayerNextShape(tlp, &tshape)) == MS_SUCCESS) { int try_open; rectObj rectTile = rect; filename = msTiledSHPLoadEntry(layer, tshape.index, tilename, sizeof(tilename)); if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); #ifdef USE_PROJ if( tSHP->sTileProj.numargs > 0 ) { msProjectRect(&(layer->projection), &(tSHP->sTileProj), &rectTile); } #endif status = msShapefileWhichShapes(tSHP->shpfile, rectTile, layer->debug); if(status == MS_DONE) { /* Close and continue to next tile */ msShapefileClose(tSHP->shpfile); continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); return(MS_FAILURE); } /* the layer functions keeps track of this */ /* tSHP->tileshpfile->lastshape = tshape.index; */ break; } return(status); /* if we reach here we either 1) ran out of tiles or 2) had an error reading a tile */ } else { /* or reference a shapefile directly */ int try_open; status = msShapefileWhichShapes(tSHP->tileshpfile, rect, layer->debug); if(status != MS_SUCCESS) return(status); /* could be MS_DONE or MS_FAILURE */ msTileIndexAbsoluteDir(tiFileAbsDir, layer); /* position the source at the FIRST shapefile */ for(i=0; itileshpfile->numshapes; i++) { rectObj rectTile = rect; if(msGetBit(tSHP->tileshpfile->status,i)) { filename = msTiledSHPLoadEntry(layer, i, tilename, sizeof(tilename)); if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); #ifdef USE_PROJ if( tSHP->sTileProj.numargs > 0 ) { msProjectRect(&(layer->projection), &(tSHP->sTileProj), &rectTile); } #endif status = msShapefileWhichShapes(tSHP->shpfile, rectTile, layer->debug); if(status == MS_DONE) { /* Close and continue to next tile */ msShapefileClose(tSHP->shpfile); continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); return(MS_FAILURE); } tSHP->tileshpfile->lastshape = i; break; } } if(i == tSHP->tileshpfile->numshapes) return(MS_DONE); /* no more tiles */ else return(MS_SUCCESS); } return(MS_FAILURE); /* should *never* get here */ } static int msTiledSHPNextShape(layerObj *layer, shapeObj *shape) { int i, status, filter_passed = MS_FALSE; const char *filename; char tilename[MS_MAXPATHLEN]; char tiFileAbsDir[MS_MAXPATHLEN]; msTiledSHPLayerInfo *tSHP=NULL; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPNextShape()"); return(MS_FAILURE); } msTileIndexAbsoluteDir(tiFileAbsDir, layer); do { i = tSHP->shpfile->lastshape + 1; while(ishpfile->numshapes && !msGetBit(tSHP->shpfile->status,i)) i++; /* next "in" shape */ if(i == tSHP->shpfile->numshapes) { /* done with this tile, need a new one */ msShapefileClose(tSHP->shpfile); /* clean up */ /* position the source to the NEXT shapefile based on the tileindex */ if(tSHP->tilelayerindex != -1) { /* does the tileindex reference another layer */ layerObj *tlp; shapeObj tshape; int try_open; tlp = (GET_LAYER(layer->map, tSHP->tilelayerindex)); msInitShape(&tshape); while((status = msLayerNextShape(tlp, &tshape)) == MS_SUCCESS) { rectObj rectTile = tSHP->searchrect; filename = msTiledSHPLoadEntry(layer, tshape.index, tilename, sizeof(tilename)); if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); #ifdef USE_PROJ if( tSHP->sTileProj.numargs > 0 ) { msProjectRect(&(layer->projection), &(tSHP->sTileProj), &rectTile); } #endif status = msShapefileWhichShapes(tSHP->shpfile, rectTile, layer->debug); if(status == MS_DONE) { /* Close and continue to next tile */ msShapefileClose(tSHP->shpfile); continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); tSHP->tileshpfile->lastshape = -1; return(MS_FAILURE); } /* the layer functions keeps track of this */ /* tSHP->tileshpfile->lastshape = tshape.index; */ break; } if(status == MS_DONE) { tSHP->tileshpfile->lastshape = -1; return(MS_DONE); /* no more tiles */ } else { msFreeShape(&tshape); continue; /* we've got shapes */ } } else { /* or reference a shapefile directly */ for(i=(tSHP->tileshpfile->lastshape + 1); itileshpfile->numshapes; i++) { if(msGetBit(tSHP->tileshpfile->status,i)) { rectObj rectTile = tSHP->searchrect; int try_open; filename = msTiledSHPLoadEntry(layer, i, tilename, sizeof(tilename)); if(strlen(filename) == 0) continue; /* check again */ try_open = msTiledSHPTryOpen(tSHP->shpfile, layer, tiFileAbsDir, filename); if( try_open == MS_DONE ) continue; else if (try_open == MS_FAILURE ) return(MS_FAILURE); #ifdef USE_PROJ if( tSHP->sTileProj.numargs > 0 ) { msProjectRect(&(layer->projection), &(tSHP->sTileProj), &rectTile); } #endif status = msShapefileWhichShapes(tSHP->shpfile, rectTile, layer->debug); if(status == MS_DONE) { /* Close and continue to next tile */ msShapefileClose(tSHP->shpfile); continue; } else if(status != MS_SUCCESS) { msShapefileClose(tSHP->shpfile); tSHP->tileshpfile->lastshape = -1; return(MS_FAILURE); } tSHP->tileshpfile->lastshape = i; break; } } /* end for loop */ if(i == tSHP->tileshpfile->numshapes) { tSHP->tileshpfile->lastshape = -1; return(MS_DONE); /* no more tiles */ } else continue; /* we've got shapes */ } } tSHP->shpfile->lastshape = i; msSHPReadShape(tSHP->shpfile->hSHP, i, shape); if(shape->type == MS_SHAPE_NULL) { msFreeShape(shape); continue; /* skip NULL shapes */ } #ifdef USE_PROJ if( tSHP->sTileProj.numargs > 0 ) { msProjectShape( &(tSHP->sTileProj), &(layer->projection), shape); } #endif shape->tileindex = tSHP->tileshpfile->lastshape; shape->numvalues = layer->numitems; shape->values = msDBFGetValueList(tSHP->shpfile->hDBF, i, layer->iteminfo, layer->numitems); if(!shape->values) shape->numvalues = 0; filter_passed = MS_TRUE; /* By default accept ANY shape */ if(layer->numitems > 0 && layer->iteminfo) { filter_passed = msEvalExpression(layer, shape, &(layer->filter), layer->filteritemindex); } if(!filter_passed) msFreeShape(shape); /* free's values as well */ } while(!filter_passed); /* Loop until both spatial and attribute filters match */ return(MS_SUCCESS); } static int msTiledSHPGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { const char *filename; char tilename[MS_MAXPATHLEN], szPath[MS_MAXPATHLEN]; msTiledSHPLayerInfo *tSHP=NULL; char tiFileAbsDir[MS_MAXPATHLEN]; long shapeindex = record->shapeindex; int tileindex = record->tileindex; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPGetShape()"); return(MS_FAILURE); } msTileIndexAbsoluteDir(tiFileAbsDir, layer); if((tileindex < 0) || (tileindex >= tSHP->tileshpfile->numshapes)) return(MS_FAILURE); /* invalid tile id */ if(tileindex != tSHP->tileshpfile->lastshape) { /* correct tile is not currenly open so open the correct tile */ msShapefileClose(tSHP->shpfile); /* close current tile */ filename = msTiledSHPLoadEntry(layer, tileindex, tilename, sizeof(tilename)); /* open the shapefile, since a specific tile was request an error should be generated if that tile does not exist */ if(strlen(filename) == 0) return(MS_FAILURE); if(msShapefileOpen(tSHP->shpfile, "rb", msBuildPath3(szPath, tiFileAbsDir, layer->map->shapepath, filename), MS_TRUE) == -1) { if(msShapefileOpen(tSHP->shpfile, "rb", msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, filename), MS_TRUE) == -1) { if(msShapefileOpen(tSHP->shpfile, "rb", msBuildPath(szPath, layer->map->mappath, filename), MS_TRUE) == -1) { return(MS_FAILURE); } } } } if((shapeindex < 0) || (shapeindex >= tSHP->shpfile->numshapes)) return(MS_FAILURE); msSHPReadShape(tSHP->shpfile->hSHP, shapeindex, shape); tSHP->shpfile->lastshape = shapeindex; tSHP->tileshpfile->lastshape = tileindex; #ifdef USE_PROJ if( tSHP->sTileProj.numargs > 0 ) { msProjectShape( &(tSHP->sTileProj), &(layer->projection), shape); } #endif if(layer->numitems > 0 && layer->iteminfo) { shape->numvalues = layer->numitems; shape->values = msDBFGetValueList(tSHP->shpfile->hDBF, shapeindex, layer->iteminfo, layer->numitems); if(!shape->values) return(MS_FAILURE); } shape->tileindex = tileindex; return(MS_SUCCESS); } static void msTiledSHPClose(layerObj *layer) { msTiledSHPLayerInfo *tSHP=NULL; tSHP = layer->layerinfo; if(tSHP) { msShapefileClose(tSHP->shpfile); free(tSHP->shpfile); if(tSHP->tilelayerindex != -1) { layerObj *tlp; if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return; tlp = (GET_LAYER(layer->map, tSHP->tilelayerindex)); msLayerClose(tlp); } else { msShapefileClose(tSHP->tileshpfile); free(tSHP->tileshpfile); } msFreeProjection(&(tSHP->sTileProj)); free(tSHP); } layer->layerinfo = NULL; } /************************************************************************/ /* msTiledSHPClose() */ /* Overloaded version of msTiledSHPClose for virtual table architecture */ /************************************************************************/ int msTiledSHPCloseVT(layerObj *layer) { msTiledSHPClose(layer); return MS_SUCCESS; } void msTiledSHPLayerFreeItemInfo(layerObj *layer) { if(layer->iteminfo) { free(layer->iteminfo); layer->iteminfo = NULL; } } int msTiledSHPLayerInitItemInfo(layerObj *layer) { msTiledSHPLayerInfo *tSHP=NULL; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPLayerInitItemInfo()"); return MS_FAILURE; } msTiledSHPLayerFreeItemInfo(layer); layer->iteminfo = (int *) msDBFGetItemIndexes(tSHP->shpfile->hDBF, layer->items, layer->numitems); if(!layer->iteminfo) return(MS_FAILURE); return MS_SUCCESS; } static void msSHPPassThroughFieldDefinitions( layerObj *layer, DBFHandle hDBF ) { int numitems, i; numitems = msDBFGetFieldCount( hDBF ); for(i=0; imetadata), "G", "type") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_type ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", item ); if( strlen(gml_width) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_width ); snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",item ); if( strlen(gml_precision) > 0 && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL ) msInsertHashTable(&(layer->metadata), md_item_name, gml_precision ); } } int msTiledSHPLayerGetItems(layerObj *layer) { msTiledSHPLayerInfo *tSHP=NULL; const char *value; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPLayerGetItems()"); return MS_FAILURE; } layer->numitems = msDBFGetFieldCount(tSHP->shpfile->hDBF); layer->items = msDBFGetItems(tSHP->shpfile->hDBF); if(!layer->items) return MS_FAILURE; /* -------------------------------------------------------------------- */ /* consider populating the field definitions in metadata. */ /* -------------------------------------------------------------------- */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) msSHPPassThroughFieldDefinitions( layer, tSHP->shpfile->hDBF ); return msTiledSHPLayerInitItemInfo(layer); } int msTiledSHPLayerGetExtent(layerObj *layer, rectObj *extent) { msTiledSHPLayerInfo *tSHP=NULL; tSHP = layer->layerinfo; if(!tSHP) { msSetError(MS_SHPERR, "Tiled shapefile layer has not been opened.", "msTiledSHPLayerGetExtent()"); return MS_FAILURE; } *extent = tSHP->tileshpfile->bounds; return MS_SUCCESS; } int msTiledSHPLayerIsOpen(layerObj *layer) { if(layer->layerinfo) return MS_TRUE; else return MS_FALSE; } int msTiledSHPLayerSupportsCommonFilters(layerObj *layer) { return MS_TRUE; } int msTiledSHPLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerSupportsCommonFilters = msTiledSHPLayerSupportsCommonFilters; layer->vtable->LayerInitItemInfo = msTiledSHPLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msTiledSHPLayerFreeItemInfo; layer->vtable->LayerOpen = msTiledSHPOpenFile; layer->vtable->LayerIsOpen = msTiledSHPLayerIsOpen; layer->vtable->LayerWhichShapes = msTiledSHPWhichShapes; layer->vtable->LayerNextShape = msTiledSHPNextShape; /* no special version, use ...GetShape() */ /* layer->vtable->LayerResultsGetShape = msTiledSHPGetShape; */ layer->vtable->LayerGetShape = msTiledSHPGetShape; layer->vtable->LayerClose = msTiledSHPCloseVT; layer->vtable->LayerGetItems = msTiledSHPLayerGetItems; layer->vtable->LayerGetExtent = msTiledSHPLayerGetExtent; /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerCloseConnection, use default */; layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ /* layer->vtable->LayerGetAutoProjection, use defaut*/ return MS_SUCCESS; } /* SHAPEFILE Layer virtual table functions */ void msSHPLayerFreeItemInfo(layerObj *layer) { if(layer->iteminfo) { free(layer->iteminfo); layer->iteminfo = NULL; } } int msSHPLayerInitItemInfo(layerObj *layer) { shapefileObj *shpfile = layer->layerinfo; if( ! shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerInitItemInfo()"); return MS_FAILURE; } /* iteminfo needs to be a bit more complex, a list of indexes plus the length of the list */ msSHPLayerFreeItemInfo(layer); layer->iteminfo = (int *) msDBFGetItemIndexes(shpfile->hDBF, layer->items, layer->numitems); if( ! layer->iteminfo) { return MS_FAILURE; } return MS_SUCCESS; } int msSHPLayerOpen(layerObj *layer) { char szPath[MS_MAXPATHLEN]; shapefileObj *shpfile; if(layer->layerinfo) return MS_SUCCESS; /* layer already open */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; /* allocate space for a shapefileObj using layer->layerinfo */ shpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); MS_CHECK_ALLOC(shpfile, sizeof(shapefileObj), MS_FAILURE); layer->layerinfo = shpfile; if(msShapefileOpen(shpfile, "rb", msBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, layer->data), MS_TRUE) == -1) { if(msShapefileOpen(shpfile, "rb", msBuildPath(szPath, layer->map->mappath, layer->data), MS_TRUE) == -1) { layer->layerinfo = NULL; free(shpfile); return MS_FAILURE; } } if (layer->projection.numargs > 0 && EQUAL(layer->projection.args[0], "auto")) { #if defined(USE_GDAL) || defined(USE_OGR) const char* pszPRJFilename = CPLResetExtension(szPath, "prj"); int bOK = MS_FALSE; FILE* fp = fopen(pszPRJFilename, "rb"); if( fp != NULL ) { char szPRJ[2048]; OGRSpatialReferenceH hSRS; int nRead; nRead = (int)fread(szPRJ, 1, sizeof(szPRJ) - 1, fp); szPRJ[nRead] = '\0'; hSRS = OSRNewSpatialReference(szPRJ); if( hSRS != NULL ) { if( OSRMorphFromESRI( hSRS ) == OGRERR_NONE ) { char* pszWKT = NULL; if( OSRExportToWkt( hSRS, &pszWKT ) == OGRERR_NONE ) { if( msOGCWKT2ProjectionObj(pszWKT, &(layer->projection), layer->debug ) == MS_SUCCESS ) { bOK = MS_TRUE; } } CPLFree(pszWKT); } OSRDestroySpatialReference(hSRS); } fclose(fp); } if( bOK != MS_TRUE ) { if( layer->debug || layer->map->debug ) { msDebug( "Unable to get SRS from shapefile '%s' for layer '%s'.\n", szPath, layer->name ); } } #else /* !(defined(USE_GDAL) || defined(USE_OGR)) */ if( layer->debug || layer->map->debug ) { msDebug( "Unable to get SRS from shapefile '%s' for layer '%s'. GDAL or OGR support needed\n", szPath, layer->name ); } #endif /* defined(USE_GDAL) || defined(USE_OGR) */ } return MS_SUCCESS; } int msSHPLayerIsOpen(layerObj *layer) { if(layer->layerinfo) return MS_TRUE; else return MS_FALSE; } int msSHPLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int status; shapefileObj *shpfile; shpfile = layer->layerinfo; if(!shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerWhichShapes()"); return MS_FAILURE; } status = msShapefileWhichShapes(shpfile, rect, layer->debug); if(status != MS_SUCCESS) { return status; } return MS_SUCCESS; } int msSHPLayerNextShape(layerObj *layer, shapeObj *shape) { int i; shapefileObj *shpfile; shpfile = layer->layerinfo; if(!shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerNextShape()"); return MS_FAILURE; } i = msGetNextBit(shpfile->status, shpfile->lastshape + 1, shpfile->numshapes); shpfile->lastshape = i; if(i == -1) return(MS_DONE); /* nothing else to read */ msSHPReadShape(shpfile->hSHP, i, shape); if(shape->type == MS_SHAPE_NULL) { msFreeShape(shape); return msSHPLayerNextShape(layer, shape); /* skip NULL shapes */ } shape->numvalues = layer->numitems; shape->values = msDBFGetValueList(shpfile->hDBF, i, layer->iteminfo, layer->numitems); if(!shape->values) shape->numvalues = 0; return MS_SUCCESS; } int msSHPLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { shapefileObj *shpfile; long shapeindex; shpfile = layer->layerinfo; shapeindex = record->shapeindex; if(!shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerGetShape()"); return MS_FAILURE; } /* msSHPReadShape *should* return success or failure so we don't have to test here */ if(shapeindex < 0 || shapeindex >= shpfile->numshapes) { msSetError(MS_MISCERR, "Invalid feature id.", "msSHPLayerGetShape()"); return MS_FAILURE; } msSHPReadShape(shpfile->hSHP, shapeindex, shape); if(layer->numitems > 0 && layer->iteminfo) { shape->numvalues = layer->numitems; shape->values = msDBFGetValueList(shpfile->hDBF, shapeindex, layer->iteminfo, layer->numitems); if(!shape->values) return MS_FAILURE; } shpfile->lastshape = shapeindex; return MS_SUCCESS; } int msSHPLayerClose(layerObj *layer) { shapefileObj *shpfile; shpfile = layer->layerinfo; if(!shpfile) return MS_SUCCESS; /* nothing to do */ msShapefileClose(shpfile); free(layer->layerinfo); layer->layerinfo = NULL; return MS_SUCCESS; } int msSHPLayerGetItems(layerObj *layer) { shapefileObj *shpfile; const char *value; shpfile = layer->layerinfo; if(!shpfile) { msSetError(MS_SHPERR, "Shapefile layer has not been opened.", "msSHPLayerGetItems()"); return MS_FAILURE; } layer->numitems = msDBFGetFieldCount(shpfile->hDBF); layer->items = msDBFGetItems(shpfile->hDBF); if(layer->numitems == 0) return MS_SUCCESS; /* No items is a valid case (#3147) */ if(!layer->items) return MS_FAILURE; /* -------------------------------------------------------------------- */ /* consider populating the field definitions in metadata. */ /* -------------------------------------------------------------------- */ if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL && strcasecmp(value,"auto") == 0 ) msSHPPassThroughFieldDefinitions( layer, shpfile->hDBF ); return msLayerInitItemInfo(layer); } int msSHPLayerGetExtent(layerObj *layer, rectObj *extent) { *extent = ((shapefileObj*)layer->layerinfo)->bounds; return MS_SUCCESS; } int msSHPLayerSupportsCommonFilters(layerObj *layer) { return MS_TRUE; } int msSHPLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerSupportsCommonFilters = msSHPLayerSupportsCommonFilters; layer->vtable->LayerInitItemInfo = msSHPLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msSHPLayerFreeItemInfo; layer->vtable->LayerOpen = msSHPLayerOpen; layer->vtable->LayerIsOpen = msSHPLayerIsOpen; layer->vtable->LayerWhichShapes = msSHPLayerWhichShapes; layer->vtable->LayerNextShape = msSHPLayerNextShape; layer->vtable->LayerGetShape = msSHPLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerClose = msSHPLayerClose; layer->vtable->LayerGetItems = msSHPLayerGetItems; layer->vtable->LayerGetExtent = msSHPLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerCloseConnection, use default */ layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter; /* layer->vtable->LayerTranslateFilter, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } mapserver-7.4.3/mapshape.h000066400000000000000000000166711357574274700155400ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Shapefile access API * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPSHAPE_H #define MAPSHAPE_H #include #include "mapprimitive.h" #include "mapproject.h" #ifdef __cplusplus extern "C" { #endif #define SHX_BUFFER_PAGE 1024 #ifndef SWIG #define MS_PATH_LENGTH 1024 /* Shapefile types */ #define SHP_POINT 1 #define SHP_ARC 3 #define SHP_POLYGON 5 #define SHP_MULTIPOINT 8 #define SHP_POINTZ 11 #define SHP_ARCZ 13 #define SHP_POLYGONZ 15 #define SHP_MULTIPOINTZ 18 #define SHP_POINTM 21 #define SHP_ARCM 23 #define SHP_POLYGONM 25 #define SHP_MULTIPOINTM 28 #endif #define MS_SHAPEFILE_POINT 1 #define MS_SHAPEFILE_ARC 3 #define MS_SHAPEFILE_POLYGON 5 #define MS_SHAPEFILE_MULTIPOINT 8 #define MS_SHP_POINTZ 11 #define MS_SHP_ARCZ 13 #define MS_SHP_POLYGONZ 15 #define MS_SHP_MULTIPOINTZ 18 #define MS_SHP_POINTM 21 #define MS_SHP_ARCM 23 #define MS_SHP_POLYGONM 25 #define MS_SHP_MULTIPOINTM 28 #ifndef SWIG typedef unsigned char uchar; typedef struct { FILE *fpSHP; FILE *fpSHX; int nShapeType; /* SHPT_* */ int nFileSize; /* SHP file */ int nRecords; int nMaxRecords; int *panRecOffset; int *panRecSize; ms_bitarray panRecLoaded; int panRecAllLoaded; double adBoundsMin[4]; double adBoundsMax[4]; int bUpdated; int nBufSize; /* these used static vars in shape readers, moved to be thread-safe */ uchar *pabyRec; int nPartMax; int *panParts; } SHPInfo; typedef SHPInfo * SHPHandle; #endif typedef struct { #ifdef SWIG %immutable; #endif FILE *fp; int nRecords; unsigned int nRecordLength; int nHeaderLength; int nFields; int *panFieldOffset; int *panFieldSize; int *panFieldDecimals; char *pachFieldType; char *pszHeader; int nCurrentRecord; int bCurrentRecordModified; char *pszCurrentRecord; int bNoHeader; int bUpdated; char *pszStringField; int nStringFieldLen; #ifdef SWIG %mutable; #endif } DBFInfo; typedef DBFInfo * DBFHandle; typedef enum {FTString, FTInteger, FTDouble, FTInvalid} DBFFieldType; /* Shapefile object, no write access via scripts */ typedef struct { #ifdef SWIG %immutable; #endif char source[MS_PATH_LENGTH]; /* full path to this file data */ #ifndef SWIG SHPHandle hSHP; /* SHP/SHX file pointer */ #endif int type; /* shapefile type */ int numshapes; /* number of shapes */ rectObj bounds; /* shape extent */ #ifndef SWIG DBFHandle hDBF; /* DBF file pointer */ #endif int lastshape; ms_bitarray status; int isopen; #ifdef SWIG %mutable; #endif } shapefileObj; #ifndef SWIG /* layerInfo structure for tiled shapefiles */ typedef struct { shapefileObj *shpfile; shapefileObj *tileshpfile; int tilelayerindex; projectionObj sTileProj; rectObj searchrect; } msTiledSHPLayerInfo; /* shapefileObj function prototypes */ MS_DLL_EXPORT int msShapefileOpen(shapefileObj *shpfile, const char *mode, const char *filename, int log_failures); MS_DLL_EXPORT int msShapefileCreate(shapefileObj *shpfile, char *filename, int type); MS_DLL_EXPORT void msShapefileClose(shapefileObj *shpfile); MS_DLL_EXPORT int msShapefileWhichShapes(shapefileObj *shpfile, rectObj rect, int debug); /* SHP/SHX function prototypes */ MS_DLL_EXPORT SHPHandle msSHPOpen( const char * pszShapeFile, const char * pszAccess ); MS_DLL_EXPORT SHPHandle msSHPCreate( const char * pszShapeFile, int nShapeType ); MS_DLL_EXPORT void msSHPClose( SHPHandle hSHP ); MS_DLL_EXPORT void msSHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType ); MS_DLL_EXPORT int msSHPReadBounds( SHPHandle psSHP, int hEntity, rectObj *padBounds ); MS_DLL_EXPORT void msSHPReadShape( SHPHandle psSHP, int hEntity, shapeObj *shape ); MS_DLL_EXPORT int msSHPReadPoint(SHPHandle psSHP, int hEntity, pointObj *point ); MS_DLL_EXPORT int msSHPWriteShape( SHPHandle psSHP, shapeObj *shape ); MS_DLL_EXPORT int msSHPWritePoint(SHPHandle psSHP, pointObj *point ); /* SHX reading */ MS_DLL_EXPORT int msSHXLoadAll( SHPHandle psSHP ); MS_DLL_EXPORT int msSHXLoadPage( SHPHandle psSHP, int shxBufferPage ); MS_DLL_EXPORT int msSHXReadOffset( SHPHandle psSHP, int hEntity ); MS_DLL_EXPORT int msSHXReadSize( SHPHandle psSHP, int hEntity ); /* tiledShapefileObj function prototypes are in mapserver.h */ /* XBase function prototypes */ MS_DLL_EXPORT DBFHandle msDBFOpen( const char * pszDBFFile, const char * pszAccess ); MS_DLL_EXPORT void msDBFClose( DBFHandle hDBF ); MS_DLL_EXPORT DBFHandle msDBFCreate( const char * pszDBFFile ); MS_DLL_EXPORT int msDBFGetFieldCount( DBFHandle psDBF ); MS_DLL_EXPORT int msDBFGetRecordCount( DBFHandle psDBF ); MS_DLL_EXPORT int msDBFAddField( DBFHandle hDBF, const char * pszFieldName, DBFFieldType eType, int nWidth, int nDecimals ); MS_DLL_EXPORT DBFFieldType msDBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName, int * pnWidth, int * pnDecimals ); MS_DLL_EXPORT int msDBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField ); MS_DLL_EXPORT double msDBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField ); MS_DLL_EXPORT const char *msDBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField ); MS_DLL_EXPORT int msDBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, int nFieldValue ); MS_DLL_EXPORT int msDBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField, double dFieldValue ); MS_DLL_EXPORT int msDBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField, const char * pszFieldValue ); MS_DLL_EXPORT char **msDBFGetItems(DBFHandle dbffile); MS_DLL_EXPORT char **msDBFGetValues(DBFHandle dbffile, int record); MS_DLL_EXPORT char **msDBFGetValueList(DBFHandle dbffile, int record, int *itemindexes, int numitems); MS_DLL_EXPORT int *msDBFGetItemIndexes(DBFHandle dbffile, char **items, int numitems); MS_DLL_EXPORT int msDBFGetItemIndex(DBFHandle dbffile, char *name); #endif #ifdef __cplusplus } #endif #endif /* MAPSHAPE_H */ mapserver-7.4.3/mapsmoothing.c000066400000000000000000000212741357574274700164350ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: RFC94 Shape smoothing * Author: Alan Boudreault (aboudreault@mapgears.com) * Author: Daniel Morissette (dmorissette@mapgears.com) * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #define FP_EPSILON 1e-12 #define FP_EQ(a, b) (fabs((a)-(b)) < FP_EPSILON) /* Internal Use, represent a line window (points) */ typedef struct { int pos; /* current point position in line */ int size; int index; /* index of the current point in points array */ lineObj *line; int lineIsRing; /* closed ring? */ pointObj **points; } lineWindow; static void initLineWindow(lineWindow *lw, lineObj *line, int size) { lw->pos = -1; lw->lineIsRing = MS_FALSE; lw->size = size; lw->line = line; lw->index = floor(lw->size/2); /* index of current position in points array */ lw->points = (pointObj**)msSmallMalloc(sizeof(pointObj*)*size); if ( (line->numpoints >= 2) && ((FP_EQ(line->point[0].x, line->point[line->numpoints-1].x)) && (FP_EQ(line->point[0].y, line->point[line->numpoints-1].y))) ) { lw->lineIsRing = 1; } } static void freeLineWindow(lineWindow *lw) { free(lw->points); } static int nextLineWindow(lineWindow *lw) { int i; if (++lw->pos >= lw->line->numpoints) return MS_DONE; lw->points[lw->index] = &lw->line->point[lw->pos]; for (i=0;iindex;++i) { int r, l; r = lw->pos-(i+1); l = lw->pos+(i+1); /* adjust values */ if ((r < 0) && lw->lineIsRing) r = lw->line->numpoints-(i+2); if ((l >= lw->line->numpoints) && lw->lineIsRing) l = 1+(l-lw->line->numpoints); /* return if the window in not valid.. */ if (r<0 || l>=lw->line->numpoints) return MS_FALSE; lw->points[lw->index-(i+1)] = &lw->line->point[r]; lw->points[lw->index+(i+1)] = &lw->line->point[l]; } return MS_TRUE; } /* Calculates the distance ratio between the total distance of a path and the distance between the first and last point (to detect a loop). */ static double computePathDistanceRatio(pointObj **points, int len) { double sum; int i; for (sum=0,i=1;inumlines; i++) free(newShape->line[i].point); newShape->numlines = 0; if (newShape->line) free(newShape->line); for (i=0;inumlines;++i) { const int windowSize = 5; int res; lineWindow lw; lineObj line = {0, NULL}; initLineWindow(&lw, &shape->line[i], windowSize); msAddLine(newShape, &line); while ((res = nextLineWindow(&lw)) != MS_DONE) { double ratio = 0; pointObj point; if (lw.lineIsRing && lw.pos==lw.line->numpoints-1) { point = newShape->line[i].point[0]; msAddPointToLine(&newShape->line[i], &point); continue; } if (res == MS_FALSE) { /* invalid window */ msAddPointToLine(&newShape->line[i], lw.points[lw.index]); continue; } if (!force) ratio = computePathDistanceRatio(lw.points, windowSize); if (force || (ratio > 1.3)) { point.x = (lw.line->point[lw.pos].x + lw.points[lw.index-1]->x)/2; point.y = (lw.line->point[lw.pos].y + lw.points[lw.index-1]->y)/2; msAddPointToLine(&newShape->line[i], &point); } point = lw.line->point[lw.pos]; msAddPointToLine(&newShape->line[i], &point); if (force || (ratio > 1.3)) { point.x = (lw.line->point[lw.pos].x + lw.points[lw.index+1]->x)/2; point.y = (lw.line->point[lw.pos].y + lw.points[lw.index+1]->y)/2; msAddPointToLine(&newShape->line[i], &point); } } freeLineWindow(&lw); } msFreeShape(shape); return MS_SUCCESS; } shapeObj* msSmoothShapeSIA(shapeObj *shape, int ss, int si, char *preprocessing) { int i, j; pointObj *p; double *coeff; shapeObj *newShape; newShape = (shapeObj *) msSmallMalloc(sizeof (shapeObj)); msInitShape(newShape); if (ss < 3) ss = 3; if (si < 1) si = 1; /* Apply preprocessing */ if (preprocessing) { if (strcasecmp(preprocessing, "all") == 0) processShapePathDistance(shape, MS_TRUE); else if (strcasecmp(preprocessing, "angle") == 0) processShapePathDistance(shape, MS_FALSE); } p = (pointObj *) msSmallMalloc(ss*sizeof(pointObj)); coeff = (double *) msSmallMalloc(ss*sizeof (double)); for (i=0;i 1 && i>0) { msInitShape(&initialShape); msCopyShape(shape, &initialShape); /* Clean our shape object */ for (j=0; j < newShape->numlines; ++j) free(newShape->line[j].point); newShape->numlines = 0; if (newShape->line) { free(newShape->line); newShape->line = NULL; } shape = &initialShape; } for (j=0;jnumlines;++j) { int k, ws, res; lineObj newLine = {0,NULL}; lineWindow lw; /* determine if we can use the ss for this line */ ws = ss; if (ws >= shape->line[j].numpoints) { ws = shape->line[j].numpoints-1; } if (ws%2==0) ws-=1; initLineWindow(&lw, &shape->line[j], ws); msAddLine(newShape, &newLine); coeff[lw.index] = 1; for (k=0;kline[j], lw.points[lw.index]); continue; } /* Apply Coefficient */ p[lw.index] = *lw.points[lw.index]; for (k=0; kline[j], &point); } freeLineWindow(&lw); } if (i>0) { msFreeShape(shape); shape = newShape; } } free(p); free(coeff); return newShape; } mapserver-7.4.3/mapstring.c000066400000000000000000001674131357574274700157420ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Various string handling functions. * Author: Steve Lime and the MapServer team. * * Notes: A couple of string handling functions (strrstr, strlcat) were taken from * other sources. Copyright notices accompany those functions below. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * Copyright (c) 1998 Todd C. Miller * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "mapthread.h" #include #include #include /* * Find the first occurrence of find in s, ignore case. */ #ifdef USE_FRIBIDI #if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(HAVE_FRIBIDI2) #include "fribidi.h" #else #include #endif #define MAX_STR_LEN 65000 #endif #ifdef USE_ICONV #include #include #endif #include "mapentities.h" #ifndef HAVE_STRRSTR /* ** Copyright (c) 2000-2004 University of Illinois Board of Trustees ** Copyright (c) 2000-2005 Mark D. Roth ** All rights reserved. ** ** Developed by: Campus Information Technologies and Educational Services, ** University of Illinois at Urbana-Champaign ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the ** ``Software''), to deal with the Software without restriction, including ** without limitation the rights to use, copy, modify, merge, publish, ** distribute, sublicense, and/or sell copies of the Software, and to ** permit persons to whom the Software is furnished to do so, subject to ** the following conditions: ** ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimers. ** ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimers in the ** documentation and/or other materials provided with the distribution. ** ** * Neither the names of Campus Information Technologies and Educational ** Services, University of Illinois at Urbana-Champaign, nor the names ** of its contributors may be used to endorse or promote products derived ** from this Software without specific prior written permission. ** ** THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ** IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ** ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE ** OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. */ char *strrstr(const char *string, const char *find) { size_t stringlen, findlen; const char *cp; findlen = strlen(find); stringlen = strlen(string); if (findlen > stringlen) return NULL; for (cp = string + stringlen - findlen; cp >= string; cp--) if (strncmp(cp, find, findlen) == 0) return (char*) cp; return NULL; } #endif #ifndef HAVE_STRLCAT /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MS_MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src));/* count does not include NUL */ } #endif #ifndef HAVE_STRLCPY /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif #ifndef HAVE_STRCASESTR /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ char *strcasestr(const char *s, const char *find) { char c, sc; size_t len; if ((c = *find++) != 0) { c = tolower((unsigned char)c); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); } while ((char)tolower((unsigned char)sc) != c); } while (strncasecmp(s, find, len) != 0); s--; } return ((char *)s); } #endif #ifndef HAVE_STRNCASECMP int strncasecmp(const char *s1, const char *s2, int len) { register const char *cp1, *cp2; int cmp = 0; cp1 = s1; cp2 = s2; if(len == 0) return(0); if (!*cp1) return -1; else if (!*cp2) return 1; while(*cp1 && *cp2 && len) { if((cmp = (toupper(*cp1) - toupper(*cp2))) != 0) return(cmp); cp1++; cp2++; len--; } if(len == 0) { return(0); } if(*cp1 || *cp2) { if (*cp1) return(1); else return (-1); } return(0); } #endif #ifndef HAVE_STRCASECMP int strcasecmp(const char *s1, const char *s2) { register const char *cp1, *cp2; int cmp = 0; cp1 = s1; cp2 = s2; if ((!cp1) || (!cp2 )) { return (0); } while(*cp1 && *cp2) { if((cmp = (toupper(*cp1) - toupper(*cp2))) != 0) return(cmp); cp1++; cp2++; } if(*cp1 || *cp2) { if (*cp1) return(1); else return (-1); } return(0); } #endif char *msLongToString(long value) { size_t bufferSize = 256; char *buffer = (char*)msSmallMalloc(bufferSize); snprintf(buffer, bufferSize, "%ld", value); return(buffer); } char *msDoubleToString(double value, int force_f) { size_t bufferSize = 256; char *buffer = (char*)msSmallMalloc(bufferSize); if (force_f == MS_TRUE) snprintf(buffer, bufferSize, "%f", value); else snprintf(buffer, bufferSize, "%g", value); return(buffer); } char *msIntToString(int value) { size_t bufferSize = 256; char *buffer = (char*)msSmallMalloc(bufferSize); snprintf(buffer, bufferSize, "%i", value); return(buffer); } void msStringToUpper(char *string) { int i; if (string != NULL) { for (i = 0; i < strlen(string); i++) { string[i] = toupper(string[i]); } return; } } void msStringToLower(char *string) { int i; if (string != NULL) { for (i = 0; i < strlen(string); i++) { string[i] = tolower(string[i]); } return; } } /** * Force the first character to uppercase and the rest of the characters to * lower case for EACH word in the string. */ void msStringInitCap(char *string) { int i; int start = 1; if (string != NULL) { for (i = 0; i < (int)strlen(string); i++) { if (string[i] == ' ') start = 1; else if (start) { string[i] = toupper(string[i]); start = 0; } else { string[i] = tolower(string[i]); } } } } /** * Force the first character to uppercase for the FIRST word in the string * and the rest of the characters to lower case. */ void msStringFirstCap(char *string) { int i; int start = 1; if (string != NULL) { for (i = 0; i < (int)strlen(string); i++) { if (string[i] != ' ') { if (start) { string[i] = toupper(string[i]); start = 0; } else string[i] = tolower(string[i]); } } } } char *msStringChop(char *string) { int n; n = strlen(string); if(n>0) string[n-1] = '\0'; return(string); } /* ** Trim leading and trailing white space. */ void msStringTrim(char *str) { int i; /* Send nulls home without supper. */ if( ! str ) return; /* Move non-white string to the front. */ i = strspn(str, " "); if(i) { memmove(str, str + i, strlen(str) - i + 1); } /* Nothing left? Exit. */ if(strlen(str) == 0) { return; } /* Null-terminate end of non-white string. */ for(i=strlen(str)-1; i>=0; i--) { /* step backwards from end */ if(str[i] != ' ') { str[i+1] = '\0'; return; } } return; } /* ** Remove leading white spaces and shift everything to the left. */ char *msStringTrimLeft(char *string) { char *read, *write; int i, length; if (string && strlen(string) > 0) { length = strlen(string); read = string; write = string; for (i=0; i write) { while (*read) { *write = *read; read++; write++; } *write = '\0'; } } return string; } /* ------------------------------------------------------------------------------- */ /* Trims trailing blanks from a string */ /* ------------------------------------------------------------------------------- */ void msStringTrimBlanks(char *string) { int i,n; n = strlen(string); for(i=n-1; i>=0; i--) { /* step backwards through the string */ if(string[i] != ' ') { string[i+1] = '\0'; return; } } } /* ------------------------------------------------------------------------------- */ /* Trims end-of-line marker from a string */ /* Usefull in conjunction with fgets() calls */ /* ------------------------------------------------------------------------------- */ void msStringTrimEOL(char *string) { int i; for(i=0 ; string[i] != '\0'; i++) { if(string[i] == '\n') { string[i] = '\0'; /* Terminate the string at the newline */ return; } } } /* ------------------------------------------------------------------------------- */ /* Replace all occurances of old with new in str. */ /* It is assumed that str was dynamically created using malloc. */ /* ------------------------------------------------------------------------------- */ char *msReplaceSubstring(char *str, const char *old, const char *new) { size_t str_len, old_len, new_len, tmp_offset; char *tmp_ptr; if(new == NULL) new = ""; /* ** If old is not found then leave str alone */ if( (tmp_ptr = strstr(str, old)) == NULL) return(str); /* ** Grab some info about incoming strings */ str_len = strlen(str); old_len = strlen(old); new_len = strlen(new); /* ** Now loop until old is NOT found in new */ while( tmp_ptr != NULL ) { /* ** re-allocate memory for buf assuming 1 replacement of old with new ** don't bother reallocating if old is larger than new) */ if (old_len < new_len) { tmp_offset = tmp_ptr - str; str_len = str_len - old_len + new_len; str = (char *)msSmallRealloc(str, (str_len + 1)); /* make new space for a copy */ tmp_ptr = str + tmp_offset; } /* ** Move the trailing part of str to make some room unless old_len == new_len */ if (old_len != new_len) { memmove(tmp_ptr+new_len, tmp_ptr+old_len, strlen(tmp_ptr)-old_len+1); } /* ** Now copy new over old */ memcpy(tmp_ptr, new, new_len); /* ** And look for more matches in the rest of the string */ tmp_ptr = strstr(tmp_ptr + new_len, old); } return(str); } /* * same goal as msReplaceSubstring, but for the known case * when we won't have to do reallocs etc * used to replace the wrap characetr by a newline for labels */ void msReplaceChar(char *str, char old, char new) { while(*(str++)) if(*str==old) *str=new; } /* ** how many times does ch occur in str */ int msCountChars(char *str, char ch) { int i, l, n=0; l = strlen(str); for(i=0; i=0; i--) { /* step backwards through the string */ if((str[i] == '/') || (str[i] == '\\')) { str[i+1] = '\0'; break; } } if(strcmp(str, fn) == 0) { msFree(str); #if defined(_WIN32) && !defined(__CYGWIN__) str = msStrdup(".\\"); #else str= msStrdup("./"); #endif } return(str); } /* ** Returns a *path* built from abs_path and path. ** The pszReturnPath must be declared by the caller function as an array ** of MS_MAXPATHLEN char */ char *msBuildPath(char *pszReturnPath, const char *abs_path, const char *path) { int abslen = 0; int pathlen = 0; if(path == NULL) { msSetError(MS_IOERR, NULL, "msBuildPath"); return NULL; } pathlen = strlen(path); if (abs_path) abslen = strlen(abs_path); if((pathlen + abslen + 2) > MS_MAXPATHLEN) { msSetError(MS_IOERR, "Path is too long. Check server logs.", "msBuildPath()"); msDebug("msBuildPath(): (%s%s): path is too long.\n", abs_path, path); return NULL; } /* Check if path is absolute */ if((abs_path == NULL) || (abslen == 0) || (path[0] == '\\') || (path[0] == '/') || (pathlen > 1 && (path[1] == ':'))) { strlcpy(pszReturnPath, path, MS_MAXPATHLEN); return(pszReturnPath); } /* else return abs_path/path */ if((abs_path[abslen-1] == '/') || (abs_path[abslen-1] == '\\')) { snprintf(pszReturnPath, MS_MAXPATHLEN, "%s%s", abs_path, path); } else { snprintf(pszReturnPath, MS_MAXPATHLEN, "%s/%s", abs_path, path); } return(pszReturnPath); } /* ** Returns a *path* built from abs_path, path1 and path2. ** abs_path/path1/path2 ** The pszReturnPath must be declared by the caller function as an array ** of MS_MAXPATHLEN char */ char *msBuildPath3(char *pszReturnPath, const char *abs_path, const char *path1,const char *path2) { char szPath[MS_MAXPATHLEN]; return msBuildPath(pszReturnPath, abs_path, msBuildPath(szPath, path1, path2)); } /* ** Similar to msBuildPath(), but the input path is only qualified by the ** absolute path if this will result in it pointing to a readable file. ** ** Returns NULL if the resulting path doesn't point to a readable file. */ char *msTryBuildPath(char *szReturnPath, const char *abs_path, const char *path) { FILE *fp; if( msBuildPath( szReturnPath, abs_path, path ) == NULL ) return NULL; fp = fopen( szReturnPath, "r" ); if( fp == NULL ) { strlcpy( szReturnPath, path, MS_MAXPATHLEN); return NULL; } else fclose( fp ); return szReturnPath; } /* ** Similar to msBuildPath3(), but the input path is only qualified by the ** absolute path if this will result in it pointing to a readable file. ** ** Returns NULL if the resulting path doesn't point to a readable file. */ char *msTryBuildPath3(char *szReturnPath, const char *abs_path, const char *path1, const char *path2) { FILE *fp; if( msBuildPath3( szReturnPath, abs_path, path1, path2 ) == NULL ) return NULL; fp = fopen( szReturnPath, "r" ); if( fp == NULL ) { strlcpy( szReturnPath, path2, MS_MAXPATHLEN); return NULL; } else fclose( fp ); return szReturnPath; } /* ** Splits a string into multiple strings based on ch. Consecutive ch's are ignored. */ char **msStringSplit(const char *string, char ch, int *num_tokens) { int i,j,k; int length,n; char **token; char last_ch='\0'; n = 1; /* always at least 1 token, the string itself */ length = strlen(string); for(i=0; i= nTokenMax-3 ) { nTokenMax = nTokenMax * 2 + 10; pszToken = (char *) msSmallRealloc(pszToken, sizeof(char)*nTokenMax); } pszToken[nTokenLen] = *pszString; nTokenLen++; } /* * Strip spaces at the token end if requested. */ if ( !bInString && bStripEndSpaces ) { while ( nTokenLen && isspace((unsigned char)pszToken[nTokenLen - 1]) ) nTokenLen--; } pszToken[nTokenLen] = '\0'; /* * Add the token. */ if( pszToken[0] != '\0' || bAllowEmptyTokens ) { if( nRetLen >= nRetMax - 1 ) { nRetMax = nRetMax * 2 + 10; papszRetList = (char **) msSmallRealloc(papszRetList, sizeof(char*)*nRetMax); } papszRetList[nRetLen++] = msStrdup( pszToken ); papszRetList[nRetLen] = NULL; } } /* * If the last token was empty, then we need to capture * it now, as the loop would skip it. */ if( *pszString == '\0' && bAllowEmptyTokens && nRetLen > 0 && strchr(pszDelimiters,*(pszString-1)) != NULL ) { if( nRetLen >= nRetMax - 1 ) { nRetMax = nRetMax * 2 + 10; papszRetList = (char **) msSmallRealloc(papszRetList, sizeof(char*)*nRetMax); } papszRetList[nRetLen++] = msStrdup(""); papszRetList[nRetLen] = NULL; } if( papszRetList == NULL ) papszRetList = (char **) msSmallMalloc(sizeof(char *)*1); *num_tokens = nRetLen; free(pszToken); return papszRetList; } /* This method is similar to msStringSplit but support quoted strings. It also support multi-characters delimiter and allows to preserve quotes */ char **msStringTokenize( const char *pszLine, const char *pszDelim, int *num_tokens, int preserve_quote ) { char **papszResult = NULL; int n = 1, iChar, nLength = strlen(pszLine), iTokenChar = 0, bInQuotes = MS_FALSE; char *pszToken = (char *) msSmallMalloc(sizeof(char)*(nLength+1)); int nDelimLen = strlen(pszDelim); /* Compute the number of tokens */ for( iChar = 0; pszLine[iChar] != '\0'; iChar++ ) { if( bInQuotes && pszLine[iChar] == '"' && pszLine[iChar+1] == '"' ) { iChar++; } else if( pszLine[iChar] == '"' ) { bInQuotes = !bInQuotes; } else if ( !bInQuotes && strncmp(pszLine+iChar,pszDelim,nDelimLen) == 0 ) { iChar += nDelimLen - 1; n++; } } papszResult = (char **) msSmallMalloc(sizeof(char *)*n); n = iTokenChar = bInQuotes = 0; for( iChar = 0; pszLine[iChar] != '\0'; iChar++ ) { if( bInQuotes && pszLine[iChar] == '"' && pszLine[iChar+1] == '"' ) { if (preserve_quote == MS_TRUE) pszToken[iTokenChar++] = '"'; pszToken[iTokenChar++] = '"'; iChar++; } else if( pszLine[iChar] == '"' ) { if (preserve_quote == MS_TRUE) pszToken[iTokenChar++] = '"'; bInQuotes = !bInQuotes; } else if( !bInQuotes && strncmp(pszLine+iChar,pszDelim,nDelimLen) == 0 ) { pszToken[iTokenChar++] = '\0'; papszResult[n] = pszToken; pszToken = (char *) msSmallMalloc(sizeof(char)*(nLength+1)); iChar += nDelimLen - 1; iTokenChar = 0; n++; } else { pszToken[iTokenChar++] = pszLine[iChar]; } } pszToken[iTokenChar++] = '\0'; papszResult[n] = pszToken; *num_tokens = n+1; return papszResult; } /********************************************************************** * msEncodeChar() * * Return 1 if the character argument should be encoded for safety * in URL use and 0 otherwise. Specific character map taken from * http://www.ietf.org/rfc/rfc2396.txt * **********************************************************************/ int msEncodeChar(const char c) { if ( (c >= 0x61 && c <= 0x7A ) || /* Letters a-z */ (c >= 0x41 && c <= 0x5A ) || /* Letters A-Z */ (c >= 0x30 && c <= 0x39 ) || /* Numbers 0-9 */ (c >= 0x27 && c <= 0x2A ) || /* * ' ( ) */ (c >= 0x2D && c <= 0x2E ) || /* - . */ (c == 0x5F ) || /* _ */ (c == 0x21 ) || /* ! */ (c == 0x7E ) ) { /* ~ */ return(0); } else { return(1); } } char *msEncodeUrl(const char *data) { /* * Delegate to msEncodeUrlExcept, with a null second argument * to render the except handling moot. */ return(msEncodeUrlExcept(data, '\0')); } /********************************************************************** * msEncodeCharExcept() * * URL encoding, applies RFP2396 encoding to all characters * except the one exception character. An exception character * of '\0' implies no exception handling. * **********************************************************************/ char *msEncodeUrlExcept(const char *data, const char except) { static const char *hex = "0123456789ABCDEF"; const char *i; char *j, *code; int inc; unsigned char ch; for (inc=0, i=data; *i!='\0'; i++) if (msEncodeChar(*i)) inc += 2; code = (char*)msSmallMalloc(strlen(data)+inc+1); for (j=code, i=data; *i!='\0'; i++, j++) { if ( except != '\0' && *i == except ) { *j = except; } else if (msEncodeChar(*i)) { ch = *i; *j++ = '%'; *j++ = hex[ch/16]; *j = hex[ch%16]; } else *j = *i; } *j = '\0'; return code; } /************************************************************************/ /* msEscapeJSonString() */ /************************************************************************/ /* The input (and output) string are not supposed to start/end with double */ /* quote characters. It is the responsibility of the caller to do that. */ char* msEscapeJSonString(const char* pszJSonString) { /* Worst case is one character to become \uABCD so 6 characters */ char* pszRet; int i = 0, j = 0; static const char* pszHex = "0123456789ABCDEF"; pszRet = (char*) msSmallMalloc(strlen(pszJSonString) * 6 + 1); /* From http://www.json.org/ */ for(i = 0; pszJSonString[i] != '\0'; i++) { unsigned char ch = pszJSonString[i]; if( ch == '\b' ) { pszRet[j++] = '\\'; pszRet[j++] = 'b'; } else if( ch == '\f' ) { pszRet[j++] = '\\'; pszRet[j++] = 'f'; } else if( ch == '\n' ) { pszRet[j++] = '\\'; pszRet[j++] = 'n'; } else if( ch == '\r' ) { pszRet[j++] = '\\'; pszRet[j++] = 'r'; } else if( ch == '\t' ) { pszRet[j++] = '\\'; pszRet[j++] = 't'; } else if( ch < 32 ) { pszRet[j++] = '\\'; pszRet[j++] = 'u'; pszRet[j++] = '0'; pszRet[j++] = '0'; pszRet[j++] = pszHex[ch / 16]; pszRet[j++] = pszHex[ch % 16]; } else if( ch == '"' ) { pszRet[j++] = '\\'; pszRet[j++] = '"'; } else if( ch == '\\' ) { pszRet[j++] = '\\'; pszRet[j++] = '\\'; } else { pszRet[j++] = ch; } } pszRet[j] = '\0'; return pszRet; } /* msEncodeHTMLEntities() ** ** Return a copy of string after replacing some problematic chars with their ** HTML entity equivalents. ** ** The replacements performed are: ** '&' -> "&", '"' -> """, '<' -> "<" and '>' -> ">" **/ char *msEncodeHTMLEntities(const char *string) { int buflen, i; char *newstring; const char *c; if(string == NULL) return NULL; /* Start with 100 extra chars for replacements... */ /* should be good enough for most cases */ buflen = strlen(string) + 100; newstring = (char*)malloc(buflen+1); MS_CHECK_ALLOC(newstring, buflen+1, NULL); for(i=0, c=string; *c != '\0'; c++) { /* Need to realloc buffer? */ if (i+6 > buflen) { /* If we had to realloc then this string must contain several */ /* entities... so let's go with twice the previous buffer size */ buflen *= 2; newstring = (char*)realloc(newstring, buflen+1); MS_CHECK_ALLOC(newstring, buflen+1, NULL); } switch(*c) { case '&': strcpy(newstring+i, "&"); i += 5; break; case '<': strcpy(newstring+i, "<"); i += 4; break; case '>': strcpy(newstring+i, ">"); i += 4; break; case '"': strcpy(newstring+i, """); i += 6; break; case '\'': strcpy(newstring+i, "'"); /* changed from ' and i += 6 (bug 1040) */ i += 5; break; default: newstring[i++] = *c; } } newstring[i++] = '\0'; return newstring; } /* msDecodeHTMLEntities() ** ** Modify the string to replace encoded characters by their true value ** ** The replacements performed are: ** "&" -> '&', """ -> '"', "<" -> '<' and ">" -> '>' **/ void msDecodeHTMLEntities(const char *string) { char *pszAmp=NULL, *pszSemiColon=NULL, *pszReplace=NULL, *pszEnd=NULL; char *pszBuffer=NULL; size_t bufferSize = 0; if(string == NULL) return; else pszBuffer = (char*)string; bufferSize = strlen(pszBuffer); pszReplace = (char*) msSmallMalloc(bufferSize+1); pszEnd = (char*) msSmallMalloc(bufferSize+1); while((pszAmp = strchr(pszBuffer, '&')) != NULL) { /* Get the &...; */ strlcpy(pszReplace, pszAmp, bufferSize); pszSemiColon = strchr(pszReplace, ';'); if(pszSemiColon == NULL) break; else pszSemiColon++; /* Get everything after the &...; */ strlcpy(pszEnd, pszSemiColon, bufferSize); pszReplace[pszSemiColon-pszReplace] = '\0'; /* Replace the &...; */ if(strcasecmp(pszReplace, "&") == 0) { pszBuffer[pszAmp - pszBuffer] = '&'; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } else if(strcasecmp(pszReplace, "<") == 0) { pszBuffer[pszAmp - pszBuffer] = '<'; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } else if(strcasecmp(pszReplace, ">") == 0) { pszBuffer[pszAmp - pszBuffer] = '>'; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } else if(strcasecmp(pszReplace, """) == 0) { pszBuffer[pszAmp - pszBuffer] = '"'; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } else if(strcasecmp(pszReplace, "'") == 0) { pszBuffer[pszAmp - pszBuffer] = '\''; pszBuffer[pszAmp - pszBuffer + 1] = '\0'; strcat(pszBuffer, pszEnd); } pszBuffer = pszAmp + 1; } free(pszReplace); free(pszEnd); return; } /* ** msIsXMLValid ** ** Check if the string is an XML valid string. It should contains only ** A-Z, a-z, 0-9, '_', '-', '.', and ':' ** Return MS_TRUE or MS_FALSE */ int msIsXMLTagValid(const char *string) { int i, nLen; nLen = strlen(string); for(i=0; i= 'A' && string[i] <= 'Z' ) && !( string[i] >= 'a' && string[i] <= 'z' ) && !( string[i] >= '0' && string[i] <= '9' ) && string[i] != '-' && string[i] != '.' && string[i] != ':' && string[i] != '_' ) return MS_FALSE; } return MS_TRUE; } /* * Concatenate pszSrc to pszDest and reallocate memory if necessary. */ char *msStringConcatenate(char *pszDest, const char *pszSrc) { int nLen; if (pszSrc == NULL) return pszDest; /* if destination is null, allocate memory */ if (pszDest == NULL) { pszDest = msStrdup(pszSrc); } else { /* if dest is not null, reallocate memory */ char *pszTemp; nLen = strlen(pszDest) + strlen(pszSrc); pszTemp = (char*)realloc(pszDest, nLen + 1); if (pszTemp) { pszDest = pszTemp; strcat(pszDest, pszSrc); pszDest[nLen] = '\0'; } else { msSetError(MS_MEMERR, "Error while reallocating memory.", "msStringConcatenate()"); return NULL; } } return pszDest; } char *msJoinStrings(char **array, int arrayLength, const char *delimeter) { char *string; int stringLength=0; int delimeterLength; int i; if(!array || arrayLength <= 0 || !delimeter) return NULL; delimeterLength = strlen(delimeter); for(i=0; i 1) return str; old_length = strlen(str); if(num_decimal_points == 0) { num_commas = floor((old_length - 1)/3); add_commas=1; /* add commas right away */ } else { num_commas = floor(((old_length - strlen(strchr(str, decimal_point))) - 1)/3); add_commas=0; /* wait until after the decimal point */ } if(num_commas < 1) return str; /* nothing to add */ new_length = old_length + num_commas; str = (char *) msSmallRealloc(str, new_length+1); str[new_length] = '\0'; j = 0; for(i=new_length-1; i>=0; i--) { /* step backwards through the string */ if(num_decimal_points == 1 && add_commas == 0) { /* to the right of the decimal point, no commas */ str[i] = str[i-num_commas]; if(str[i] == decimal_point) add_commas = 1; } else if(add_commas == 1 && j>2) { /* need a comma */ str[i] = comma; num_commas--; /* need one fewer now */ j = 0; /* reset */ } else { str[i] = str[i-num_commas]; /* shift to the right */ j++; } if(num_commas == 0) break; /* done, rest of string is ok "as is" */ } return str; } /* ------------------------------------------------------------------------------- */ /* Replace all occurances of old with new in str. */ /* It is assumed that str was dynamically created using malloc. */ /* Same function as msReplaceSubstring but this is case incensitive */ /* ------------------------------------------------------------------------------- */ char *msCaseReplaceSubstring(char *str, const char *old, const char *new) { size_t str_len, old_len, new_len, tmp_offset; char *tmp_ptr; /* ** If old is not found then leave str alone */ if( (tmp_ptr = (char *) strcasestr(str, old)) == NULL) return(str); if(new == NULL) new = ""; /* ** Grab some info about incoming strings */ str_len = strlen(str); old_len = strlen(old); new_len = strlen(new); /* ** Now loop until old is NOT found in new */ while( tmp_ptr != NULL ) { /* ** re-allocate memory for buf assuming 1 replacement of old with new ** don't bother reallocating if old is larger than new) */ if (old_len < new_len) { tmp_offset = tmp_ptr - str; str_len = str_len - old_len + new_len; str = (char *)msSmallRealloc(str, (str_len + 1)); /* make new space for a copy */ tmp_ptr = str + tmp_offset; } /* ** Move the trailing part of str to make some room unless old_len == new_len */ if (old_len != new_len) { memmove(tmp_ptr+new_len, tmp_ptr+old_len, strlen(tmp_ptr)-old_len+1); } /* ** Now copy new over old */ memcpy(tmp_ptr, new, new_len); /* ** And look for more matches in the rest of the string */ tmp_ptr = (char *) strcasestr(tmp_ptr + new_len, old); } return(str); } /* ** Converts a 2 character hexidecimal string to an integer. */ int msHexToInt(char *hex) { int number; number = (hex[0] >= 'A' ? ((hex[0] & 0xdf) - 'A')+10 : (hex[0] - '0')); number *= 16; number += (hex[1] >= 'A' ? ((hex[1] & 0xdf) - 'A')+10 : (hex[1] - '0')); return(number); } /* ** Use FRIBIDI to encode the string. ** The return value must be freed by the caller. */ #ifdef USE_FRIBIDI char *msGetFriBidiEncodedString(const char *string, const char *encoding) { FriBidiChar logical[MAX_STR_LEN]; FriBidiParType base; size_t len; #ifdef FRIBIDI_NO_CHARSETS iconv_t to_ucs4, from_ucs4; #else int to_char_set_num; int from_char_set_num; #endif len = strlen(string); #ifdef FRIBIDI_NO_CHARSETS to_ucs4 = iconv_open ("WCHAR_T", encoding); from_ucs4 = iconv_open ("UTF-8", "WCHAR_T"); #else to_char_set_num = fribidi_parse_charset ((char*)encoding); from_char_set_num = fribidi_parse_charset ("UTF-8"); #endif #ifdef FRIBIDI_NO_CHARSETS if (to_ucs4 == (iconv_t) (-1) || from_ucs4 == (iconv_t) (-1)) #else if (!to_char_set_num || !from_char_set_num) #endif { msSetError(MS_IDENTERR, "Encoding not supported (%s).", "msGetFriBidiEncodedString()", encoding); return NULL; } #ifdef FRIBIDI_NO_CHARSETS { char *st = string, *ust = (char *) logical; int in_len = (int) len; len = sizeof logical; iconv (to_ucs4, &st, &in_len, &ust, (int *) &len); len = (FriBidiChar *) ust - logical; } #else len = fribidi_charset_to_unicode (to_char_set_num, (char*)string, len, logical); #endif { FriBidiChar *visual; char outstring[MAX_STR_LEN]; FriBidiStrIndex *ltov, *vtol; FriBidiLevel *levels; FriBidiStrIndex new_len; fribidi_boolean log2vis; int i, j; visual = (FriBidiChar *) msSmallMalloc (sizeof (FriBidiChar) * (len + 1)); ltov = NULL; vtol = NULL; levels = NULL; /* Create a bidi string. */ log2vis = fribidi_log2vis (logical, len, &base, /* output */ visual, ltov, vtol, levels); if (!log2vis) { msSetError(MS_IDENTERR, "Failed to create bidi string.", "msGetFriBidiEncodedString()"); return NULL; } new_len = len; /* Convert it to utf-8 for display. */ #ifdef FRIBIDI_NO_CHARSETS { char *str = outstring, *ust = (char *) visual; int in_len = len * sizeof visual[0]; new_len = sizeof outstring; iconv (from_ucs4, &ust, &in_len, &str, (int *) &new_len); *str = '\0'; new_len = str - outstring; } #else new_len = fribidi_unicode_to_charset (from_char_set_num, visual, len, outstring); /* scan str and compress out FRIBIDI_CHAR_FILL UTF8 characters */ for (i=0, j=0; i 0) { iconv_status = iconv(cd, (char**)&inp, &len, &outp, &bufleft); if(iconv_status == -1) { msFree(out); iconv_close(cd); return msStrdup(string); } } out[bufsize - bufleft] = '\0'; iconv_close(cd); return out; #else if (*string == '\0' || (encoding && strcasecmp(encoding, "UTF-8")==0)) return msStrdup(string); /* Nothing to do: string already in UTF-8 */ msSetError(MS_MISCERR, "Not implemeted since Iconv is not enabled.", "msGetEncodedString()"); return NULL; #endif } char* msConvertWideStringToUTF8 (const wchar_t* string, const char* encoding) { #ifdef USE_ICONV char* output = NULL; char* errormessage = NULL; iconv_t cd = NULL; size_t nStr; size_t nInSize; size_t nOutSize; size_t iconv_status = -1; size_t nBufferSize; char* pszUTF8 = NULL; const wchar_t* pwszWide = NULL; if (string != NULL) { nStr = wcslen (string); nBufferSize = ((nStr * 6) + 1); output = (char*) msSmallMalloc (nBufferSize); if (nStr == 0) { /* return an empty 8 byte string */ output[0] = '\0'; return output; } cd = iconv_open("UTF-8", encoding); nOutSize = nBufferSize; if ((iconv_t)-1 != cd) { nInSize = sizeof (wchar_t)*nStr; pszUTF8 = output; pwszWide = string; iconv_status = iconv(cd, (char **)&pwszWide, &nInSize, &pszUTF8, &nOutSize); if ((size_t)-1 == iconv_status) { switch (errno) { case E2BIG: errormessage = "There is not sufficient room in buffer"; break; case EILSEQ: errormessage = "An invalid multibyte sequence has been encountered in the input"; break; case EINVAL: errormessage = "An incomplete multibyte sequence has been encountered in the input"; break; default: errormessage = "Unknown"; break; } msSetError(MS_MISCERR, "Unable to convert string in encoding '%s' to UTF8 %s", "msConvertWideStringToUTF8()", encoding,errormessage); iconv_close(cd); msFree(output); return NULL; } iconv_close(cd); } else { msSetError(MS_MISCERR, "Encoding not supported by libiconv (%s).", "msConvertWideStringToUTF8()", encoding); msFree(output); return NULL; } } else { /* we were given a NULL wide string, nothing we can do here */ return NULL; } /* NULL-terminate the output string */ output[nBufferSize - nOutSize] = '\0'; return output; #else msSetError(MS_MISCERR, "Not implemented since Iconv is not enabled.", "msConvertWideStringToUTF8()"); return NULL; #endif } /* ** Returns the next glyph in string and advances *in_ptr to the next ** character. ** ** If out_string is not NULL then the character (bytes) is copied to this ** buffer and null-terminated. out_string must be a pre-allocated buffer of ** at least 11 bytes. ** ** The function returns the number of bytes in this glyph. ** ** This function treats 3 types of glyph encodings: * - as an html entity, for example { , Ư , or é * - as an utf8 encoded character * - if utf8 decoding fails, as a raw character * ** This function mimics the character decoding function used in gdft.c of * libGD. It is necessary to have the same behaviour, as input strings must be * split into the same glyphs as what gd does. ** ** In UTF-8, the number of leading 1 bits in the first byte specifies the ** number of bytes in the entire sequence. ** Source: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 ** ** U-00000000 U-0000007F: 0xxxxxxx ** U-00000080 U-000007FF: 110xxxxx 10xxxxxx ** U-00000800 U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx ** U-00010000 U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx ** U-00200000 U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx ** U-04000000 U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ int msGetNextGlyph(const char **in_ptr, char *out_string) { unsigned char in; int numbytes=0; unsigned int unicode; int i; in = (unsigned char)**in_ptr; if (in == 0) return -1; /* Empty string */ if((numbytes=msGetUnicodeEntity(*in_ptr,&unicode))>0) { if(out_string) { for(i=0; iname, en2->name); } /* * this function tests if the string pointed by inptr represents * an HTML entity, in decimal form ( e.g. Å), in hexadecimal * form ( e.g. 水 ), or from html 4.0 spec ( e.g. é ) * - returns returns 0 if the string doesn't represent such an entity. * - if the string does start with such entity,it returns the number of * bytes occupied by said entity, and stores the unicode value in *unicode */ int msGetUnicodeEntity(const char *inptr, unsigned int *unicode) { unsigned char *in = (unsigned char*)inptr; int l,val=0; if(*in=='&') { in++; if(*in=='#') { in++; if(*in=='x'||*in=='X') { in++; for(l=3; l<8; l++) { char byte; if(*in>='0'&&*in<='9') byte = *in - '0'; else if(*in>='a'&&*in<='f') byte = *in - 'a' + 10; else if(*in>='A'&&*in<='F') byte = *in - 'A' + 10; else break; in++; val = (val * 16) + byte; } if(*in==';' && l>3 ) { *unicode=val; return ++l; } } else { for(l=2; l<8; l++) { if(*in>='0'&&*in<='9') { val = val*10+*in-'0'; in++; } else break; } if(*in==';' && l>2 ) { *unicode=val; return ++l; } } } else { char entity_name_buf[MAP_ENTITY_NAME_LENGTH_MAX+1]; char *p; struct mapentities_s key, *res; key.name = p = entity_name_buf; for (l = 1; l <= MAP_ENTITY_NAME_LENGTH_MAX+1; l++) { if (*in == '\0') /*end of string before possible entity: return*/ break; if (*in == ';') { /*possible end of entity: do a lookup*/ *p++ = '\0'; res = bsearch(&key, mapentities, MAP_NR_OF_ENTITIES, sizeof(mapentities[0]), *cmp_entities); if (res) { *unicode = res->value; return ++l; } break; /*the string was of the form of an entity but didn't correspond to an existing one: return*/ } *p++ = *in; in++; } } } return 0; } /** * msStringIsInteger() * * determines whether a given string is an integer * * @param string the string to be tested * * @return MS_SUCCESS or MS_FAILURE */ int msStringIsInteger(const char *string) { int length, i; length = strlen(string); if (length == 0) return MS_FAILURE; for(i=0; iencoding || !*layer->encoding || !strcasecmp(layer->encoding, "UTF-8")) return MS_SUCCESS; cd = iconv_open("UTF-8", layer->encoding); if(cd == (iconv_t)-1) { msSetError(MS_IDENTERR, "Encoding not supported by libiconv (%s).", "msGetEncodedString()", layer->encoding); return MS_FAILURE; } for(i=0;i numvalues; i++) { if(!shape->values[i] || (len = strlen(shape->values[i]))==0) { continue; /* Nothing to do */ } bufsize = len * 6 + 1; /* Each UTF-8 char can be up to 6 bytes */ inp = shape->values[i]; out = (char*) msSmallMalloc(bufsize); strlcpy(out, shape->values[i], bufsize); outp = out; bufleft = bufsize; iconv_status = -1; while (len > 0) { iconv_status = iconv(cd, (char**)&inp, &len, &outp, &bufleft); if(iconv_status == -1) { msFree(out); continue; /* silently ignore failed conversions */ } } out[bufsize - bufleft] = '\0'; msFree(shape->values[i]); shape->values[i] = out; } iconv_close(cd); return MS_SUCCESS; #else if( !layer->encoding || !*layer->encoding || !strcasecmp(layer->encoding, "UTF-8")) return MS_SUCCESS; msSetError(MS_MISCERR, "Not implemented since Iconv is not enabled.", "msGetEncodedString()"); return MS_FAILURE; #endif } mapserver-7.4.3/mapsymbol.c000066400000000000000000001027141357574274700157320ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: symbolObj related functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include /* variable number of function arguments support */ #include /* since the parser handles time/date we need this */ #include "mapserver.h" #include "mapfile.h" #include "mapcopy.h" #include "mapthread.h" #include "fontcache.h" #include "mapows.h" extern int msyylex(void); /* lexer globals */ extern void msyyrestart(FILE *); extern double msyynumber; extern char *msyystring_buffer; extern int msyylineno; extern FILE *msyyin; extern int msyystate; static const unsigned char PNGsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; /* 89 50 4E 47 0D 0A 1A 0A hex */ static const unsigned char JPEGsig[3] = {255, 216, 255}; /* FF D8 FF hex */ void freeImageCache(struct imageCacheObj *ic) { if(ic) { freeImageCache(ic->next); /* free any children */ msFreeRasterBuffer(&(ic->img)); free(ic); } return; } /* ** msSymbolGetDefaultSize() ** ** Return the default size of a symbol. ** Note: The size of a symbol is the height. Everywhere in the code, the width ** is adjusted to the size that becomes the height. ** See mapgd.c // size ~ height in pixels */ double msSymbolGetDefaultSize(symbolObj *s) { double size; if(s == NULL) return 1; switch(s->type) { case(MS_SYMBOL_TRUETYPE): size = 1; break; case(MS_SYMBOL_PIXMAP): assert(s->pixmap_buffer != NULL); if(s->pixmap_buffer == NULL) return 1; /* FIXME */ size = (double)s->pixmap_buffer->height; break; case(MS_SYMBOL_SVG): size = 1; #if defined(USE_SVG_CAIRO) || defined (USE_RSVG) assert(s->renderer_cache != NULL); size = s->sizey; #endif break; default: /* vector and ellipses, scalable */ size = (s->sizey<=0)?s->sizex:s->sizey; break; } if(size <= 0) return 1; return size; } void initSymbol(symbolObj *s) { MS_REFCNT_INIT(s); s->type = MS_SYMBOL_VECTOR; s->transparent = MS_FALSE; s->transparentcolor = 0; s->sizex = 1; s->sizey = 1; s->filled = MS_FALSE; s->numpoints=0; s->renderer=NULL; s->renderer_free_func = NULL; s->renderer_cache = NULL; s->pixmap_buffer=NULL; s->imagepath = NULL; s->name = NULL; s->inmapfile = MS_FALSE; s->font = NULL; s->full_pixmap_path = NULL; s->character = NULL; s->anchorpoint_x = s->anchorpoint_y = 0.5; } int msFreeSymbol(symbolObj *s) { if(!s) return MS_FAILURE; if( MS_REFCNT_DECR_IS_NOT_ZERO(s) ) { return MS_FAILURE; } if(s->name) free(s->name); if(s->renderer_free_func) { s->renderer_free_func(s); } else { if(s->renderer!=NULL) { s->renderer->freeSymbol(s); } } if(s->pixmap_buffer) { msFreeRasterBuffer(s->pixmap_buffer); free(s->pixmap_buffer); } if(s->font) free(s->font); msFree(s->full_pixmap_path); if(s->imagepath) free(s->imagepath); if(s->character) free(s->character); return MS_SUCCESS; } int loadSymbol(symbolObj *s, char *symbolpath) { int done=MS_FALSE; char szPath[MS_MAXPATHLEN]; initSymbol(s); for(;;) { switch(msyylex()) { case(ANCHORPOINT): if(getDouble(&(s->anchorpoint_x)) == -1) return MS_FAILURE; if(getDouble(&(s->anchorpoint_y)) == -1) return MS_FAILURE; if(s->anchorpoint_x<0 || s->anchorpoint_x>1 || s->anchorpoint_y<0 || s->anchorpoint_y>1) { msSetError(MS_SYMERR, "ANCHORPOINT must be between 0 and 1", "loadSymbol()"); return(-1); } break; case(ANTIALIAS): /*ignore*/ msyylex(); break; case(CHARACTER): if(getString(&s->character) == MS_FAILURE) return(-1); break; case(END): /* do some error checking */ if((s->type == MS_SYMBOL_SVG) && (s->imagepath == NULL)) { msSetError(MS_SYMERR, "Symbol of type SVG has no file path specified.", "loadSymbol()"); return(-1); } if((s->type == MS_SYMBOL_PIXMAP) && (s->full_pixmap_path == NULL)) { msSetError(MS_SYMERR, "Symbol of type PIXMAP has no image data.", "loadSymbol()"); return(-1); } if(((s->type == MS_SYMBOL_ELLIPSE) || (s->type == MS_SYMBOL_VECTOR)) && (s->numpoints == 0)) { msSetError(MS_SYMERR, "Symbol of type VECTOR or ELLIPSE has no point data.", "loadSymbol()"); return(-1); } if(s->type == MS_SYMBOL_VECTOR) { double minx = s->points[0].x; double miny = s->points[0].y; /* should only negative points be shifted? (#4116)*/ int shiftpositive = ((s->anchorpoint_x!=0.5)||(s->anchorpoint_y!=0.5)); int i; for(i=1; inumpoints; i++) { if(s->points[i].x != -99 && s->points[i].y != -99) { if(s->points[i].xpoints[i].x; if(s->points[i].ypoints[i].y; } } if(minx<0 || miny<0 || (shiftpositive && (minx!=0 || miny!=0))) { for(i=0; inumpoints; i++) { if(s->points[i].x != -99 && s->points[i].y != -99) { s->points[i].x -= minx; s->points[i].y -= miny; } } s->sizex -= minx; s->sizey -= miny; } } return(0); break; case(EOF): msSetError(MS_EOFERR, NULL, "loadSymbol()"); return(-1); break; case(FILLED): if((s->filled = getSymbol(2,MS_TRUE,MS_FALSE)) == -1) return(-1); break; case(FONT): if(getString(&s->font) == MS_FAILURE) return(-1); break; case(IMAGE): if(msyylex() != MS_STRING) { /* get image location from next token */ msSetError(MS_TYPEERR, "Parsing error near (%s):(line %d)", "loadSymbol()", msyystring_buffer, msyylineno); return(-1); } s->full_pixmap_path = msStrdup(msBuildPath(szPath, symbolpath, msyystring_buffer)); /* Set imagepath */ s->imagepath = msStrdup(msyystring_buffer); break; case(NAME): if(getString(&s->name) == MS_FAILURE) return(-1); break; case(POINTS): done = MS_FALSE; s->sizex = 0; s->sizey = 0; for(;;) { switch(msyylex()) { case(END): done = MS_TRUE; break; case(MS_NUMBER): s->points[s->numpoints].x = atof(msyystring_buffer); /* grab the x */ if(getDouble(&(s->points[s->numpoints].y)) == -1) return(-1); /* grab the y */ if(s->points[s->numpoints].x!=-99) { s->sizex = MS_MAX(s->sizex, s->points[s->numpoints].x); s->sizey = MS_MAX(s->sizey, s->points[s->numpoints].y); } s->numpoints++; break; default: msSetError(MS_TYPEERR, "Parsing error near (%s):(line %d)", "loadSymbol()", msyystring_buffer, msyylineno); return(-1); } if(done == MS_TRUE) break; } break; case(TRANSPARENT): s->transparent = MS_TRUE; if(getInteger(&(s->transparentcolor)) == -1) return(-1); break; case(TYPE): if((s->type = getSymbol(8,MS_SYMBOL_VECTOR,MS_SYMBOL_ELLIPSE,MS_SYMBOL_PIXMAP,MS_SYMBOL_SIMPLE,MS_TRUETYPE,MS_SYMBOL_HATCH,MS_SYMBOL_SVG)) == -1) return(-1); if(s->type == MS_TRUETYPE) /* TrueType keyword is valid several place in map files and symbol files, this simplifies the lexer */ s->type = MS_SYMBOL_TRUETYPE; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadSymbol()", msyystring_buffer, msyylineno); return(-1); } /* end switch */ } /* end for */ return done; } void writeSymbol(symbolObj *s, FILE *stream) { int i; msIO_fprintf(stream, " SYMBOL\n"); if(s->name != NULL) msIO_fprintf(stream, " NAME \"%s\"\n", s->name); switch (s->type) { case(MS_SYMBOL_HATCH): msIO_fprintf(stream, " TYPE HATCH\n"); break; case(MS_SYMBOL_PIXMAP): msIO_fprintf(stream, " TYPE PIXMAP\n"); if(s->imagepath != NULL) msIO_fprintf(stream, " IMAGE \"%s\"\n", s->imagepath); if(s->anchorpoint_y!=0.5 || s->anchorpoint_x!=0.5) { msIO_fprintf(stream, " ANCHORPOINT %g %g\n", s->anchorpoint_x, s->anchorpoint_y); } msIO_fprintf(stream, " TRANSPARENT %d\n", s->transparentcolor); break; case(MS_SYMBOL_TRUETYPE): msIO_fprintf(stream, " TYPE TRUETYPE\n"); if (s->character != NULL) msIO_fprintf(stream, " CHARACTER \"%s\"\n", s->character); if (s->font != NULL) msIO_fprintf(stream, " FONT \"%s\"\n", s->font); if(s->anchorpoint_y!=0.5 || s->anchorpoint_x!=0.5) { msIO_fprintf(stream, " ANCHORPOINT %g %g\n", s->anchorpoint_x, s->anchorpoint_y); } break; default: if(s->type == MS_SYMBOL_ELLIPSE) msIO_fprintf(stream, " TYPE ELLIPSE\n"); else if(s->type == MS_SYMBOL_VECTOR) msIO_fprintf(stream, " TYPE VECTOR\n"); else if(s->type == MS_SYMBOL_SVG) msIO_fprintf(stream, " TYPE SVG\n"); else msIO_fprintf(stream, " TYPE SIMPLE\n"); if(s->filled == MS_TRUE) msIO_fprintf(stream, " FILLED TRUE\n"); if(s->imagepath != NULL) msIO_fprintf(stream, " IMAGE \"%s\"\n", s->imagepath); if(s->anchorpoint_y!=0.5 || s->anchorpoint_x!=0.5) { msIO_fprintf(stream, " ANCHORPOINT %g %g\n", s->anchorpoint_x, s->anchorpoint_y); } /* POINTS */ if(s->numpoints != 0) { msIO_fprintf(stream, " POINTS\n"); for(i=0; inumpoints; i++) { msIO_fprintf(stream, " %g %g\n", s->points[i].x, s->points[i].y); } msIO_fprintf(stream, " END\n"); } break; } msIO_fprintf(stream, " END\n\n"); } /* ** Little helper function to allow us to build symbol files on-the-fly ** from just a file name. ** ** Returns the symbol index or -1 if it could not be added. */ int msAddImageSymbol(symbolSetObj *symbolset, char *filename) { char szPath[MS_MAXPATHLEN]; symbolObj *symbol=NULL; char *extension=NULL; int symbolidx; if(!symbolset) { msSetError(MS_SYMERR, "Symbol structure unallocated.", "msAddImageSymbol()"); return(-1); } if(!filename || strlen(filename) == 0) return(-1); /* Allocate/init memory for new symbol if needed */ if (msGrowSymbolSet(symbolset) == NULL) return -1; symbolidx = symbolset->numsymbols; symbolset->numsymbols++; symbol = symbolset->symbol[symbolidx]; /* check if svg checking extension otherwise assume it's a pixmap */ extension = strrchr(filename, '.'); if (extension == NULL) extension = ""; if (strncasecmp(extension, ".svg", 4) == 0) { symbol->type = MS_SYMBOL_SVG; } else { symbol->type = MS_SYMBOL_PIXMAP; } #ifdef USE_CURL if (strncasecmp(filename, "http", 4) == 0) { char *tmpfullfilename = NULL; char *tmpfilename = NULL; char *tmppath = NULL; int status = 0; char szPath[MS_MAXPATHLEN]; int bCheckLocalCache = MS_TRUE; tmppath = msTmpPath(NULL, NULL, NULL); if (tmppath) { tmpfilename = msEncodeUrl(filename); tmpfullfilename = msBuildPath(szPath, tmppath, tmpfilename); if (tmpfullfilename) { /*use the url for now as a caching mechanism*/ if (msHTTPGetFile(filename, tmpfullfilename, &status, -1, bCheckLocalCache, 0, 1024*1024 /* 1 MegaByte */) == MS_SUCCESS) { symbol->imagepath = msStrdup(tmpfullfilename); symbol->full_pixmap_path = msStrdup(tmpfullfilename); } else { unlink(tmpfullfilename); msFree(tmpfilename); msFree(tmppath); return MS_FAILURE; } } msFree(tmpfilename); msFree(tmppath); } } #endif /*if the http did not work, allow it to be treated as a file*/ if (!symbol->full_pixmap_path) { if(symbolset->map) { symbol->full_pixmap_path = msStrdup(msBuildPath(szPath, symbolset->map->mappath, filename)); } else { symbol->full_pixmap_path = msStrdup(msBuildPath(szPath, NULL, filename)); } symbol->imagepath = msStrdup(filename); } symbol->name = msStrdup(filename); return symbolidx; } int msFreeSymbolSet(symbolSetObj *symbolset) { int i; freeImageCache(symbolset->imagecache); for(i=0; inumsymbols; i++) { if (symbolset->symbol[i]!=NULL) { if ( msFreeSymbol((symbolset->symbol[i])) == MS_SUCCESS ) { msFree(symbolset->symbol[i]); symbolset->symbol[i]=NULL; } } } msFree(symbolset->symbol); /* no need to deal with fontset, it's a pointer */ return MS_SUCCESS; } void msInitSymbolSet(symbolSetObj *symbolset) { symbolset->filename = NULL; symbolset->imagecache = NULL; symbolset->imagecachesize = 0; /* 0 symbols in the cache */ symbolset->fontset = NULL; symbolset->map = NULL; symbolset->numsymbols = 0; symbolset->maxsymbols = 0; symbolset->symbol = NULL; /* Alloc symbol[] array and ensure there is at least 1 symbol: * symbol 0 which is the default symbol with all default params. */ if (msGrowSymbolSet(symbolset) == NULL) return; /* alloc failed */ symbolset->symbol[0]->type = MS_SYMBOL_ELLIPSE; symbolset->symbol[0]->filled = MS_TRUE; symbolset->symbol[0]->numpoints = 1; symbolset->symbol[0]->points[0].x = 1; symbolset->symbol[0]->points[0].y = 1; /* Just increment numsymbols to reserve symbol 0. * initSymbol() has already been called */ symbolset->numsymbols = 1; } /* ** Ensure there is at least one free entry in the symbol array of this ** symbolSetObj. Grow the allocated symbol[] array if necessary and ** allocate a new symbol for symbol[numsymbols] if there is not already one ** and call initSymbol() on it. ** ** This function is safe to use for the initial allocation of the symbol[] ** array as well (i.e. when maxsymbols==0 and symbol==NULL) ** ** Returns a reference to the new symbolObj on success, NULL on error. */ symbolObj *msGrowSymbolSet( symbolSetObj *symbolset ) { /* Do we need to increase the size of symbol[] by MS_SYMBOL_ALLOCSIZE? */ if (symbolset->numsymbols == symbolset->maxsymbols) { int i; if (symbolset->maxsymbols == 0) { /* Initial allocation of array */ symbolset->maxsymbols += MS_SYMBOL_ALLOCSIZE; symbolset->numsymbols = 0; symbolset->symbol = (symbolObj**)malloc(symbolset->maxsymbols*sizeof(symbolObj*)); } else { /* realloc existing array */ symbolset->maxsymbols += MS_SYMBOL_ALLOCSIZE; symbolset->symbol = (symbolObj**)realloc(symbolset->symbol, symbolset->maxsymbols*sizeof(symbolObj*)); } if (symbolset->symbol == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for symbol array.", "msGrowSymbolSet()"); return NULL; } for(i=symbolset->numsymbols; imaxsymbols; i++) symbolset->symbol[i] = NULL; } if (symbolset->symbol[symbolset->numsymbols]==NULL) { symbolset->symbol[symbolset->numsymbols]=(symbolObj*)malloc(sizeof(symbolObj)); if (symbolset->symbol[symbolset->numsymbols]==NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for a symbolObj", "msGrowSymbolSet()"); return NULL; } } /* Always call initSymbol() even if we didn't allocate a new symbolObj * Since it's possible to dynamically remove/reuse symbols */ initSymbol(symbolset->symbol[symbolset->numsymbols]); return symbolset->symbol[symbolset->numsymbols]; } /* --------------------------------------------------------------------------- msLoadSymbolSet and loadSymbolSet msLoadSymbolSet wraps calls to loadSymbolSet with mutex acquisition and release. It should be used everywhere outside the mapfile loading phase of an application. loadSymbolSet should only be used when a mutex exists. It does not check for existence of a mutex! See bug 339 for more details -- SG. ------------------------------------------------------------------------ */ int msLoadSymbolSet(symbolSetObj *symbolset, mapObj *map) { int retval = MS_FAILURE; msAcquireLock( TLOCK_PARSER ); retval = loadSymbolSet( symbolset, map ); msReleaseLock( TLOCK_PARSER ); return retval; } int loadSymbolSet(symbolSetObj *symbolset, mapObj *map) { int status=1; char szPath[MS_MAXPATHLEN], *pszSymbolPath=NULL; int foundSymbolSetToken=MS_FALSE; int token; if(!symbolset) { msSetError(MS_SYMERR, "Symbol structure unallocated.", "loadSymbolSet()"); return(-1); } symbolset->map = (mapObj *)map; if(!symbolset->filename) return(0); /* ** Open the file */ if((msyyin = fopen(msBuildPath(szPath, symbolset->map->mappath, symbolset->filename), "r")) == NULL) { msSetError(MS_IOERR, "(%s)", "loadSymbolSet()", symbolset->filename); return(-1); } pszSymbolPath = msGetPath(szPath); msyystate = MS_TOKENIZE_FILE; /* restore lexer state to INITIAL, and do return comments */ msyylex(); /* sets things up, but doesn't process any tokens */ msyylineno = 0; /* reset line counter */ msyyrestart(msyyin); /* flush the scanner - there's a better way but this works for now */ /* ** Read the symbol file */ for(;;) { token = msyylex(); if(!foundSymbolSetToken && token != SYMBOLSET) { msSetError(MS_IDENTERR, "First token must be SYMBOLSET, this doesn't look like a symbol file.", "msLoadSymbolSet()"); return(-1); } switch(token) { case(END): case(EOF): status = 0; break; case(SYMBOL): /* Allocate/init memory for new symbol if needed */ if (msGrowSymbolSet(symbolset) == NULL) { status = -1; } else if((loadSymbol((symbolset->symbol[symbolset->numsymbols]), pszSymbolPath) == -1)) status = -1; else symbolset->numsymbols++; break; case(SYMBOLSET): foundSymbolSetToken = MS_TRUE; break; default: msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadSymbolSet()", msyystring_buffer, msyylineno); status = -1; } /* end switch */ if(status != 1) break; } /* end for */ fclose(msyyin); msyyin = NULL; free(pszSymbolPath); return(status); } int msGetCharacterSize(mapObj *map, char* font, int size, char *character, rectObj *r) { unsigned int unicode, codepoint; glyph_element *glyph; face_element *face = msGetFontFace(font, &map->fontset); if(UNLIKELY(!face)) return MS_FAILURE; msUTF8ToUniChar(character, &unicode); codepoint = msGetGlyphIndex(face,unicode); glyph = msGetGlyphByIndex(face,size,codepoint); if(UNLIKELY(!glyph)) return MS_FAILURE; if(glyph) { r->minx = glyph->metrics.minx; r->maxx = glyph->metrics.maxx; r->miny = - glyph->metrics.maxy; r->maxy = - glyph->metrics.miny; } return MS_SUCCESS; } /* ** Returns the size, in pixels, of a marker symbol defined by a specific style and scalefactor. Used for annotation ** layer collision avoidance. A marker is made up of a number of styles so the calling code must either do the looping ** itself or call this function for the bottom style which should be the largest. */ int msGetMarkerSize(mapObj *map, styleObj *style, double *width, double *height, double scalefactor) { int size; symbolObj *symbol; *width = *height = 0; /* set a starting value */ if(style->symbol > map->symbolset.numsymbols || style->symbol < 0) return(MS_FAILURE); /* no such symbol, 0 is OK */ if(style->symbol == 0) { /* single point */ *width = 1; *height = 1; return(MS_SUCCESS); } symbol = map->symbolset.symbol[style->symbol]; if (symbol->type == MS_SYMBOL_PIXMAP && !symbol->pixmap_buffer) { if (MS_SUCCESS != msPreloadImageSymbol(MS_MAP_RENDERER(map), symbol)) return MS_FAILURE; } if(symbol->type == MS_SYMBOL_SVG && !symbol->renderer_cache) { #if defined(USE_SVG_CAIRO) || defined (USE_RSVG) if(MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msGetMarkerSize()"); return MS_FAILURE; #endif } if(style->size == -1) { size = ( msSymbolGetDefaultSize(symbol) * scalefactor ); } else size = (style->size*scalefactor); size = MS_MAX(size, style->minsize); size = MS_MIN(size, style->maxsize); switch(symbol->type) { case(MS_SYMBOL_TRUETYPE): { rectObj gbounds; if(UNLIKELY(MS_FAILURE == msGetCharacterSize(map,symbol->font,size,symbol->character, &gbounds))) return MS_FAILURE; *width = MS_MAX(*width, (gbounds.maxx-gbounds.minx)); *height = MS_MAX(*height, (gbounds.maxy-gbounds.miny)); } break; case(MS_SYMBOL_PIXMAP): if(size == 1) { *width = MS_MAX(*width, symbol->pixmap_buffer->width); *height = MS_MAX(*height, symbol->pixmap_buffer->height); } else { *width = MS_MAX(*width, (((double)size/(double)symbol->pixmap_buffer->height) * symbol->pixmap_buffer->width)); *height = MS_MAX(*height, size); } break; default: /* vector and ellipses, scalable */ if(style->size > 0) { *width = MS_MAX(*width, ((size/symbol->sizey) * symbol->sizex)); *height = MS_MAX(*height, size); } else { /* use symbol defaults */ *width = MS_MAX(*width, symbol->sizex); *height = MS_MAX(*height, symbol->sizey); } break; } return(MS_SUCCESS); } /* * Add a default new symbol. If the symbol name exists * return the id of the symbol. */ int msAddNewSymbol(mapObj *map, char *name) { int i = 0; if (!map || !name) return -1; i = msGetSymbolIndex(&map->symbolset, name, MS_TRUE); if (i >= 0) return i; /* Allocate memory for new symbol if needed */ if (msGrowSymbolSet(&(map->symbolset)) == NULL) return -1; i = map->symbolset.numsymbols; map->symbolset.symbol[i]->name = msStrdup(name); map->symbolset.numsymbols++; return i; } /* msAppendSymbol and msRemoveSymbol are part of the work to resolve * MapServer bug 579. * http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=579 */ int msAppendSymbol(symbolSetObj *symbolset, symbolObj *symbol) { /* Allocate memory for new symbol if needed */ if (msGrowSymbolSet(symbolset) == NULL) return -1; /* we need to free the symbolObj that was already allocated as we are going to replace it with the provided symbolObj*. Not the most efficient technique, but this function should be rarely called, and in any case only by mapscript. Another option could be to use msCopySymbol(), in which case the call to MS_REFCNT_INCR(symbol) should be removed.*/ if(symbolset->symbol[symbolset->numsymbols]) { msFreeSymbol(symbolset->symbol[symbolset->numsymbols]); msFree(symbolset->symbol[symbolset->numsymbols]); } symbolset->symbol[symbolset->numsymbols]=symbol; MS_REFCNT_INCR(symbol); return symbolset->numsymbols++; } symbolObj *msRemoveSymbol(symbolSetObj *symbolset, int nSymbolIndex) { int i; symbolObj *symbol; if (symbolset->numsymbols == 1) { msSetError(MS_CHILDERR, "Cannot remove a symbolset's sole symbol", "removeSymbol()"); return NULL; } else if (nSymbolIndex < 0 || nSymbolIndex >= symbolset->numsymbols) { msSetError(MS_CHILDERR, "Cannot remove symbol, invalid nSymbolIndex %d", "removeSymbol()", nSymbolIndex); return NULL; } else { symbol=symbolset->symbol[nSymbolIndex]; for (i=nSymbolIndex+1; inumsymbols; i++) { symbolset->symbol[i-1] = symbolset->symbol[i]; } symbolset->symbol[i-1]=NULL; symbolset->numsymbols--; MS_REFCNT_DECR(symbol); /* update symbol references in the map */ if (symbolset->map) { int l,c,s,lb; layerObj *layer; classObj *cl; styleObj *style; labelObj *label; for (l = 0; l < symbolset->map->numlayers; l++) { layer = GET_LAYER(symbolset->map, l); for (c = 0; c < layer->numclasses; c++) { cl = layer->class[c]; for (s = 0; s < cl->numstyles; s++) { style = cl->styles[s]; if (style->symbol >= nSymbolIndex) --style->symbol; } for (lb = 0; lb < cl->numlabels; lb++) { label = cl->labels[lb]; for (s = 0; s < label->numstyles; s++) { style = label->styles[s]; if (style->symbol >= nSymbolIndex) --style->symbol; } } } } /* Update symbol references in labelcache */ for(c = 0; c < MS_MAX_LABEL_PRIORITY; c++) { labelCacheSlotObj *cacheslot = &(symbolset->map->labelcache.slots[c]); for(l = 0; l < cacheslot->numlabels; l++) { labelCacheMemberObj *cachePtr = &(cacheslot->labels[l]); for(lb = 0; lb < cachePtr->numtextsymbols; lb++) { label = cachePtr->textsymbols[lb]->label; for (s = 0; s < label->numstyles; s++) { style = label->styles[s]; if (style->symbol >= nSymbolIndex) --style->symbol; } } } } } return symbol; } } int msSaveSymbolSetStream(symbolSetObj *symbolset, FILE *stream) { int i; if (!symbolset || !stream) { msSetError(MS_SYMERR, "Cannot save symbolset.", "msSaveSymbolSetStream()"); return MS_FAILURE; } /* Don't ever write out the default symbol at index 0 */ for (i=1; inumsymbols; i++) { if(!symbolset->symbol[i]->inmapfile) writeSymbol((symbolset->symbol[i]), stream); } return MS_SUCCESS; } int msSaveSymbolSet(symbolSetObj *symbolset, const char *filename) { FILE *stream; int retval; if (!filename || strlen(filename) == 0) { msSetError(MS_SYMERR, "Invalid filename.", "msSaveSymbolSet()"); return MS_FAILURE; } stream = fopen(filename, "w"); if (stream) { fprintf(stream, "SYMBOLSET\n"); retval = msSaveSymbolSetStream(symbolset, stream); fprintf(stream, "END\n"); fclose(stream); } else { msSetError(MS_SYMERR, "Could not write to %s", "msSaveSymbolSet()", filename); retval = MS_FAILURE; } return retval; } int msLoadImageSymbol(symbolObj *symbol, const char *filename) { msFree(symbol->full_pixmap_path); symbol->full_pixmap_path = msStrdup(filename); return MS_SUCCESS; } int msPreloadImageSymbol(rendererVTableObj *renderer, symbolObj *symbol) { if(symbol->pixmap_buffer && symbol->renderer == renderer) return MS_SUCCESS; if(symbol->pixmap_buffer) { /* other renderer was used, start again */ msFreeRasterBuffer(symbol->pixmap_buffer); } else { symbol->pixmap_buffer = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); } if(MS_SUCCESS != renderer->loadImageFromFile(symbol->full_pixmap_path, symbol->pixmap_buffer)) { /* Free pixmap_buffer already allocated */ free(symbol->pixmap_buffer); symbol->pixmap_buffer = NULL; return MS_FAILURE; } symbol->renderer = renderer; symbol->sizex = symbol->pixmap_buffer->width; symbol->sizey = symbol->pixmap_buffer->height; return MS_SUCCESS; } /*********************************************************************** * msCopySymbol() * * * * Copy a symbolObj, using mapfile.c:initSymbol(), msCopyPoint() * * gdImageCreate(), gdImageCopy() * **********************************************************************/ int msCopySymbol(symbolObj *dst, symbolObj *src, mapObj *map) { int i; initSymbol(dst); MS_COPYSTRING(dst->name, src->name); MS_COPYSTELEM(type); MS_COPYSTELEM(inmapfile); /* map is a special case */ dst->map = map; MS_COPYSTELEM(sizex); MS_COPYSTELEM(sizey); MS_COPYSTELEM(anchorpoint_x); MS_COPYSTELEM(anchorpoint_y); for (i=0; i < src->numpoints; i++) { MS_COPYPOINT(&(dst->points[i]), &(src->points[i])); } MS_COPYSTELEM(numpoints); MS_COPYSTELEM(filled); MS_COPYSTRING(dst->imagepath, src->imagepath); MS_COPYSTELEM(transparent); MS_COPYSTELEM(transparentcolor); MS_COPYSTRING(dst->character, src->character); MS_COPYSTRING(dst->font, src->font); MS_COPYSTRING(dst->full_pixmap_path,src->full_pixmap_path); return(MS_SUCCESS); } /*********************************************************************** * msCopySymbolSet() * * * * Copy a symbolSetObj using msCopyFontSet(), msCopySymbol() * **********************************************************************/ int msCopySymbolSet(symbolSetObj *dst, symbolSetObj *src, mapObj *map) { int i, return_value; MS_COPYSTRING(dst->filename, src->filename); dst->map = map; dst->fontset = &(map->fontset); /* Copy child symbols */ for (i = 0; i < src->numsymbols; i++) { if (msGrowSymbolSet(dst) == NULL) return MS_FAILURE; return_value = msCopySymbol(dst->symbol[i], src->symbol[i], map); if (return_value != MS_SUCCESS) { msSetError(MS_MEMERR,"Failed to copy symbol.","msCopySymbolSet()"); return(MS_FAILURE); } dst->numsymbols++; } /* MS_COPYSTELEM(imagecachesize); */ /* I have a feeling that the code below is not quite right - Sean */ /*copyProperty(&(dst->imagecache), &(src->imagecache), sizeof(struct imageCacheObj)); */ dst->imagecachesize = 0; /* since we are not copying the cache set the cache to NUNLL and the size to 0 (bug 1521) */ dst->imagecache = NULL; return(MS_SUCCESS); } static void get_bbox(pointObj *poiList, int numpoints, double *minx, double *miny, double *maxx, double *maxy) { int j; *minx = *maxx = poiList[0].x; *miny = *maxy = poiList[0].y; for(j=1; jtype == MS_SYMBOL_VECTOR); */ newSymbol = (symbolObj *) malloc(sizeof(symbolObj)); msCopySymbol(newSymbol, symbol, NULL); /* TODO: do we really want to do this for all symbol types? */ angle_rad = (MS_DEG_TO_RAD*angle); sin_a = sin(angle_rad); cos_a = cos(angle_rad); dp_x = symbol->sizex * .5; /* get the shift vector at 0,0 */ dp_y = symbol->sizey * .5; /* center at 0,0 and rotate; then move back */ for( i=0; i < symbol->numpoints; i++) { /* don't rotate PENUP commands (TODO: should use a constant here) */ if ((symbol->points[i].x == -99.0) && (symbol->points[i].y == -99.0) ) { newSymbol->points[i].x = -99.0; newSymbol->points[i].y = -99.0; continue; } newSymbol->points[i].x = dp_x + ((symbol->points[i].x-dp_x)*cos_a - (symbol->points[i].y-dp_y)*sin_a); newSymbol->points[i].y = dp_y + ((symbol->points[i].x-dp_x)*sin_a + (symbol->points[i].y-dp_y)*cos_a); } /* get the new bbox of the symbol, because we need it to get the new dimensions of the new symbol */ get_bbox(newSymbol->points, newSymbol->numpoints, &minx, &miny, &maxx, &maxy); if ( (fabs(minx)>TOL) || (fabs(miny)>TOL) ) { xcor = minx*-1.0; /* symbols always start at 0,0 so get the shift vector */ ycor = miny*-1.0; for( i=0; i < newSymbol->numpoints; i++) { if ((newSymbol->points[i].x == -99.0) && (newSymbol->points[i].y == -99.0)) continue; newSymbol->points[i].x = newSymbol->points[i].x + xcor; newSymbol->points[i].y = newSymbol->points[i].y + ycor; } /* update the bbox to get the final dimension values for the symbol */ get_bbox(newSymbol->points, newSymbol->numpoints, &minx, &miny, &maxx, &maxy); } newSymbol->sizex = maxx; newSymbol->sizey = maxy; return newSymbol; } mapserver-7.4.3/mapsymbol.h000066400000000000000000000133241357574274700157350ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: symbolObj related declarations. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPSYMBOL_H #define MAPSYMBOL_H #include "mapserver-api.h" #include enum MS_SYMBOL_TYPE {MS_SYMBOL_SIMPLE=1000, MS_SYMBOL_VECTOR, MS_SYMBOL_ELLIPSE, MS_SYMBOL_PIXMAP, MS_SYMBOL_TRUETYPE, MS_SYMBOL_HATCH, MS_SYMBOL_SVG}; #define MS_SYMBOL_ALLOCSIZE 64 /* number of symbolObj ptrs to allocate for a symbolset at once */ #define MS_MAXVECTORPOINTS 100 /* shade, marker and line symbol parameters */ #define MS_MAXPATTERNLENGTH 10 #define MS_IMAGECACHESIZE 6 /* COLOR OBJECT */ typedef struct { int red; int green; int blue; int alpha; } colorObj; #ifndef SWIG enum MS_RASTER_BUFFER_TYPE { MS_BUFFER_NONE=2000, MS_BUFFER_BYTE_RGBA, MS_BUFFER_BYTE_PALETTE }; typedef struct { unsigned char *pixels; unsigned int pixel_step, row_step; unsigned char *a,*r,*g,*b; } rgbaArrayObj; typedef struct { unsigned char b,g,r,a; } rgbaPixel; typedef struct { unsigned char r,g,b; } rgbPixel; typedef struct { unsigned char *pixels; /*stores the actual pixel indexes*/ rgbaPixel *palette; /*rgba palette entries*/ unsigned int num_entries; /*number of palette entries*/ unsigned int scaling_maxval; } paletteArrayObj; typedef struct { int type; unsigned int width,height; union { rgbaArrayObj rgba; paletteArrayObj palette; } data; } rasterBufferObj; /* NOTE: RB_SET_PIXEL() will premultiply by alpha, inputs should not be premultiplied */ #define RB_SET_PIXEL(rb,x,y,red,green,blue,alpha) \ { \ int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \ if( !(rb)->data.rgba.a ) { \ (rb)->data.rgba.r[_rb_off] = red; \ (rb)->data.rgba.g[_rb_off] = green; \ (rb)->data.rgba.b[_rb_off] = blue; \ } else { \ double a = alpha/255.0; \ (rb)->data.rgba.r[_rb_off] = red * a; \ (rb)->data.rgba.g[_rb_off] = green * a; \ (rb)->data.rgba.b[_rb_off] = blue * a; \ (rb)->data.rgba.a[_rb_off] = alpha; \ } \ } /* This versions receives an input red/green/blue that is already premultiplied with alpha */ #define RB_SET_PIXEL_PM(rb,x,y,red,green,blue,alpha) \ { \ int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \ (rb)->data.rgba.r[_rb_off] = red; \ (rb)->data.rgba.g[_rb_off] = green; \ (rb)->data.rgba.b[_rb_off] = blue; \ if( rb->data.rgba.a ) { \ (rb)->data.rgba.a[_rb_off] = alpha; \ } \ } /* NOTE: RB_MIX_PIXEL() will premultiply by alpha, inputs should not be premultiplied */ #define RB_MIX_PIXEL(rb,x,y,red,green,blue,alpha) \ { \ int _rb_off = (x) * (rb)->data.rgba.pixel_step + (y) * (rb)->data.rgba.row_step; \ \ msAlphaBlend( red, green, blue, alpha, \ (rb)->data.rgba.r + _rb_off, \ (rb)->data.rgba.g + _rb_off, \ (rb)->data.rgba.b + _rb_off, \ ((rb)->data.rgba.a == NULL ) ? NULL : (rb)->data.rgba.a + _rb_off ); \ } struct imageCacheObj { int symbol; int size; colorObj color; colorObj outlinecolor; colorObj backgroundcolor; rasterBufferObj img; struct imageCacheObj *next; }; #endif /* SWIG */ struct symbolObj{ char *name; int type; int inmapfile; /* boolean value for writing */ #ifndef SWIG /* ** Pointer to his map */ struct mapObj *map; #endif /* SWIG */ /* ** MS_SYMBOL_VECTOR and MS_SYMBOL_ELLIPSE options */ double sizex, sizey; double minx,miny,maxx,maxy; #ifndef SWIG pointObj points[MS_MAXVECTORPOINTS]; #endif #ifdef SWIG %immutable; #endif /* SWIG */ int refcount; int numpoints; #ifdef SWIG %mutable; #endif /* SWIG */ int filled; double anchorpoint_x, anchorpoint_y; /* ** MS_SYMBOL_PIXMAP options */ #ifndef SWIG rendererVTableObj *renderer; void (*renderer_free_func)(symbolObj *self); rasterBufferObj *pixmap_buffer; void *renderer_cache; char *full_pixmap_path; #endif /* SWIG */ #ifdef SWIG %immutable; #endif /* SWIG */ char *imagepath; #ifdef SWIG %mutable; #endif /* SWIG */ int transparent; int transparentcolor; /* ** MS_SYMBOL_TRUETYPE options */ char *character; char *font; } ; #endif /* MAPSYMBOL_H */ mapserver-7.4.3/maptclutf.c000066400000000000000000000273631357574274700157340ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of msUTF8ToUniChar() * Author: Daniel Morissette, Thomas Bonfort * * Note: * The source code of Tcl_UtfToUniChar() was borrowed from tclUtf.c * from the Tcl/Tk project. * * Website: http://www.tcl.tk/software/tcltk/ * Source download: http://prdownloads.sourceforge.net/tcl/tcl8.4.15-src.tar.gz * * See copyright and license terms below the standard MapServer license. * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * Copyright (c) 1997-1998 Sun Microsystems, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /* * tclUtf.c -- * * Routines for manipulating UTF-8 strings. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * * This software is copyrighted by the Regents of the University of * California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState * Corporation and other parties. The following terms apply to all files * associated with the software unless explicitly disclaimed in * individual files. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS. * * GOVERNMENT USE: If you are acquiring this software on behalf of the * U.S. government, the Government shall have only "Restricted Rights" * in the software and related documentation as defined in the Federal * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you * are acquiring the software on behalf of the Department of Defense, the * software shall be classified as "Commercial Computer Software" and the * Government shall have only "Restricted Rights" as defined in Clause * 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the * authors grant the U.S. Government and others acting in its behalf * permission to use and distribute the software in accordance with the * terms specified in this license. */ #include "mapserver.h" /* The source code of Tcl_UtfToUniChar() was borrowed from tclUtf.c * from the Tcl/Tk project: * Website: * http://www.tcl.tk/software/tcltk/ * Source download: * http://prdownloads.sourceforge.net/tcl/tcl8.4.15-src.tar.gz * Original License info follows below. */ /* * tclUtf.c -- * * Routines for manipulating UTF-8 strings. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Id: tclUtf.c,v 1.30.2.3 2005/09/07 14:35:56 dgp Exp */ /******************* Tcl license.terms ********************* This software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. ***********************************************************/ #define TCL_UTF_MAX 6 /* * The following structures are used when mapping between Unicode (UCS-2) * and UTF-8. */ static const unsigned char totalBytes[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, #if TCL_UTF_MAX > 3 4,4,4,4,4,4,4,4, #else 1,1,1,1,1,1,1,1, #endif #if TCL_UTF_MAX > 4 5,5,5,5, #else 1,1,1,1, #endif #if TCL_UTF_MAX > 5 6,6,6,6 #else 1,1,1,1 #endif }; /* *--------------------------------------------------------------------------- * * Tcl_UtfToUniChar -- * * Extract the Tcl_UniChar represented by the UTF-8 string. Bad * UTF-8 sequences are converted to valid Tcl_UniChars and processing * continues. Equivalent to Plan 9 chartorune(). * * The caller must ensure that the source buffer is long enough that * this routine does not run off the end and dereference non-existent * memory looking for trail bytes. If the source buffer is known to * be '\0' terminated, this cannot happen. Otherwise, the caller * should call Tcl_UtfCharComplete() before calling this routine to * ensure that enough bytes remain in the string. * * Results: * *chPtr is filled with the Tcl_UniChar, and the return value is the * number of bytes from the UTF-8 string that were consumed. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int ms_Tcl_UtfToUniChar(register const char *str, register unsigned int *chPtr) { register int byte; /* * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones. */ byte = *((unsigned char *) str); if (byte < 0xC0) { /* * Handles properly formed UTF-8 characters between 0x01 and 0x7F. * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid * characters representing themselves. */ *chPtr = byte; return 1; } else if (byte < 0xE0) { if ((str[1] & 0xC0) == 0x80) { /* * Two-byte-character lead-byte followed by a trail-byte. */ *chPtr = (((byte & 0x1F) << 6) | (str[1] & 0x3F)); return 2; } /* * A two-byte-character lead-byte not followed by trail-byte * represents itself. */ *chPtr = byte; return 1; } else if (byte < 0xF0) { if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) { /* * Three-byte-character lead byte followed by two trail bytes. */ *chPtr = (((byte & 0x0F) << 12) | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F)); return 3; } /* * A three-byte-character lead-byte not followed by two trail-bytes * represents itself. */ *chPtr = byte; return 1; } #if TCL_UTF_MAX > 3 else { int ch, total, trail; total = totalBytes[byte]; trail = total - 1; if (trail > 0) { ch = byte & (0x3F >> trail); do { str++; if ((*str & 0xC0) != 0x80) { *chPtr = byte; return 1; } ch <<= 6; ch |= (*str & 0x3F); trail--; } while (trail > 0); *chPtr = ch; return total; } } #endif *chPtr = byte; return 1; } /* msUTF8ToUniChar() * * Extract the Unicode Char represented by the UTF-8 string. Bad * UTF-8 sequences are converted to valid Unicode Chars and processing * continues. * * The caller must ensure that the source buffer is long enough that * this routine does not run off the end and dereference non-existent * memory looking for trail bytes. If the source buffer is known to * be '\0' terminated, this cannot happen. * * Results: * *chPtr is filled with the Unicode Char value, and the return value * is the number of bytes from the UTF-8 string that were consumed. ** **/ int msUTF8ToUniChar(const char *str, /* The UTF-8 string. */ unsigned int *chPtr) /* Filled with the Unicode Char represented * by the UTF-8 string. */ { /*check if the string is an html entity (eg { or Ī)*/ int entitylgth; if(*str == '&' && (entitylgth=msGetUnicodeEntity(str, chPtr))>0) return entitylgth; return ms_Tcl_UtfToUniChar(str, chPtr); } mapserver-7.4.3/maptemplate.c000066400000000000000000005056361357574274700162520ustar00rootroot00000000000000/****************************************************************************** * $id: maptemplate.c 7725 2008-06-21 15:56:58Z sdlime $ * * Project: MapServer * Purpose: Various template processing functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2008 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "maptemplate.h" #include "maphash.h" #include "mapserver.h" #include "maptile.h" #include "mapows.h" #include #include #include #include static inline void IGUR_sizet(size_t ignored) { (void)ignored; } /* Ignore GCC Unused Result */ static inline void IGUR_voidp(void* ignored) { (void)ignored; } /* Ignore GCC Unused Result */ static char *olUrl = "//www.mapserver.org/lib/OpenLayers-ms60.js"; static char *olTemplate = \ "\n" "\n" " MapServer Simple Viewer\n" " \n" " \n" " \n" "
\n" " \n" "\n" ""; static char *olLayerMapServerTag = \ "var mslayer = new OpenLayers.Layer.MapServer( \"MapServer Layer\",\n" " \"[mapserv_onlineresource]\",\n" " {layers: '[layers]'},\n" " {singleTile: \"true\", ratio:1} )"; static char *olLayerWMSTag = \ "var mslayer = new OpenLayers.Layer.WMS('MapServer Simple Viewer\',\n" " '[mapserv_onlineresource]',\n" " {layers: '[LAYERS]',\n" " bbox: '[minx],[miny],[maxx],[maxy]',\n" " width: [mapwidth], height: [mapheight], version: '[VERSION]', format:'[openlayers_format]'}," " {singleTile: \"true\", ratio:1, projection: '[openlayers_projection]'});\n"; static char *processLine(mapservObj *mapserv, char *instr, FILE *stream, int mode); static int isValidTemplate(FILE *stream, const char *filename) { char buffer[MS_BUFFER_LENGTH]; if(fgets(buffer, MS_BUFFER_LENGTH, stream) != NULL) { if(!strcasestr(buffer, MS_TEMPLATE_MAGIC_STRING)) { msSetError(MS_WEBERR, "Missing magic string, %s doesn't look like a MapServer template.", "isValidTemplate()", filename); return MS_FALSE; } } return MS_TRUE; } /* * Redirect to (only use in CGI) * */ int msRedirect(char *url) { msIO_setHeader("Status","302 Found"); msIO_setHeader("Uri","%s",url); msIO_setHeader("Location","%s",url); msIO_setHeader("Content-Type","text/html"); msIO_sendHeaders(); return MS_SUCCESS; } /* ** Sets the map extent under a variety of scenarios. */ int setExtent(mapservObj *mapserv) { double cellx,celly,cellsize; if(mapserv->Mode == TILE) { if(MS_SUCCESS != msTileSetExtent(mapserv)) { return MS_FAILURE; } } switch(mapserv->CoordSource) { case FROMUSERBOX: /* user passed in a map extent */ break; case FROMIMGBOX: /* fully interactive web, most likely with java front end */ cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows); mapserv->map->extent.minx = MS_IMAGE2MAP_X(mapserv->ImgBox.minx, mapserv->ImgExt.minx, cellx); mapserv->map->extent.maxx = MS_IMAGE2MAP_X(mapserv->ImgBox.maxx, mapserv->ImgExt.minx, cellx); mapserv->map->extent.maxy = MS_IMAGE2MAP_Y(mapserv->ImgBox.miny, mapserv->ImgExt.maxy, celly); /* y's are flip flopped because img/map coordinate systems are */ mapserv->map->extent.miny = MS_IMAGE2MAP_Y(mapserv->ImgBox.maxy, mapserv->ImgExt.maxy, celly); break; case FROMIMGPNT: cellx = MS_CELLSIZE(mapserv->ImgExt.minx, mapserv->ImgExt.maxx, mapserv->ImgCols); celly = MS_CELLSIZE(mapserv->ImgExt.miny, mapserv->ImgExt.maxy, mapserv->ImgRows); mapserv->mappnt.x = MS_IMAGE2MAP_X(mapserv->ImgPnt.x, mapserv->ImgExt.minx, cellx); mapserv->mappnt.y = MS_IMAGE2MAP_Y(mapserv->ImgPnt.y, mapserv->ImgExt.maxy, celly); mapserv->map->extent.minx = mapserv->mappnt.x - .5*((mapserv->ImgExt.maxx - mapserv->ImgExt.minx)/mapserv->fZoom); /* create an extent around that point */ mapserv->map->extent.miny = mapserv->mappnt.y - .5*((mapserv->ImgExt.maxy - mapserv->ImgExt.miny)/mapserv->fZoom); mapserv->map->extent.maxx = mapserv->mappnt.x + .5*((mapserv->ImgExt.maxx - mapserv->ImgExt.minx)/mapserv->fZoom); mapserv->map->extent.maxy = mapserv->mappnt.y + .5*((mapserv->ImgExt.maxy - mapserv->ImgExt.miny)/mapserv->fZoom); break; case FROMREFPNT: cellx = MS_CELLSIZE(mapserv->map->reference.extent.minx, mapserv->map->reference.extent.maxx, mapserv->map->reference.width); celly = MS_CELLSIZE(mapserv->map->reference.extent.miny, mapserv->map->reference.extent.maxy, mapserv->map->reference.height); mapserv->mappnt.x = MS_IMAGE2MAP_X(mapserv->RefPnt.x, mapserv->map->reference.extent.minx, cellx); mapserv->mappnt.y = MS_IMAGE2MAP_Y(mapserv->RefPnt.y, mapserv->map->reference.extent.maxy, celly); mapserv->map->extent.minx = mapserv->mappnt.x - .5*(mapserv->ImgExt.maxx - mapserv->ImgExt.minx); /* create an extent around that point */ mapserv->map->extent.miny = mapserv->mappnt.y - .5*(mapserv->ImgExt.maxy - mapserv->ImgExt.miny); mapserv->map->extent.maxx = mapserv->mappnt.x + .5*(mapserv->ImgExt.maxx - mapserv->ImgExt.minx); mapserv->map->extent.maxy = mapserv->mappnt.y + .5*(mapserv->ImgExt.maxy - mapserv->ImgExt.miny); break; case FROMBUF: mapserv->map->extent.minx = mapserv->mappnt.x - mapserv->Buffer; /* create an extent around that point, using the buffer */ mapserv->map->extent.miny = mapserv->mappnt.y - mapserv->Buffer; mapserv->map->extent.maxx = mapserv->mappnt.x + mapserv->Buffer; mapserv->map->extent.maxy = mapserv->mappnt.y + mapserv->Buffer; break; case FROMSCALE: cellsize = (mapserv->ScaleDenom/mapserv->map->resolution)/msInchesPerUnit(mapserv->map->units,0); /* user supplied a point and a scale denominator */ mapserv->map->extent.minx = mapserv->mappnt.x - cellsize*(mapserv->map->width-1)/2.0; mapserv->map->extent.miny = mapserv->mappnt.y - cellsize*(mapserv->map->height-1)/2.0; mapserv->map->extent.maxx = mapserv->mappnt.x + cellsize*(mapserv->map->width-1)/2.0; mapserv->map->extent.maxy = mapserv->mappnt.y + cellsize*(mapserv->map->height-1)/2.0; break; default: /* use the default in the mapfile if it exists */ if((mapserv->map->extent.minx == mapserv->map->extent.maxx) && (mapserv->map->extent.miny == mapserv->map->extent.maxy)) { msSetError(MS_WEBERR, "No way to generate map extent.", "mapserv()"); return MS_FAILURE; } } mapserv->RawExt = mapserv->map->extent; /* save unaltered extent */ return MS_SUCCESS; } int checkWebExtent(mapservObj *mapserv) { return MS_SUCCESS; } int checkWebScale(mapservObj *mapserv) { int status; rectObj work_extent = mapserv->map->extent; mapserv->map->cellsize = msAdjustExtent(&(work_extent), mapserv->map->width, mapserv->map->height); /* we do this cause we need a scale */ if((status = msCalculateScale(work_extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return status; if((mapserv->map->scaledenom < mapserv->map->web.minscaledenom) && (mapserv->map->web.minscaledenom > 0)) { if(mapserv->map->web.mintemplate) { /* use the template provided */ if(TEMPLATE_TYPE(mapserv->map->web.mintemplate) == MS_FILE) { if((status = msReturnPage(mapserv, mapserv->map->web.mintemplate, BROWSE, NULL)) != MS_SUCCESS) return status; } else { if((status = msReturnURL(mapserv, mapserv->map->web.mintemplate, BROWSE)) != MS_SUCCESS) return status; } } else { /* force zoom = 1 (i.e. pan) */ mapserv->fZoom = mapserv->Zoom = 1; mapserv->ZoomDirection = 0; mapserv->CoordSource = FROMSCALE; mapserv->ScaleDenom = mapserv->map->web.minscaledenom; mapserv->mappnt.x = (mapserv->map->extent.maxx + mapserv->map->extent.minx)/2; /* use center of bad extent */ mapserv->mappnt.y = (mapserv->map->extent.maxy + mapserv->map->extent.miny)/2; setExtent(mapserv); mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return status; } } else { if((mapserv->map->scaledenom > mapserv->map->web.maxscaledenom) && (mapserv->map->web.maxscaledenom > 0)) { if(mapserv->map->web.maxtemplate) { /* use the template provided */ if(TEMPLATE_TYPE(mapserv->map->web.maxtemplate) == MS_FILE) { if((status = msReturnPage(mapserv, mapserv->map->web.maxtemplate, BROWSE, NULL)) != MS_SUCCESS) return status; } else { if((status = msReturnURL(mapserv, mapserv->map->web.maxtemplate, BROWSE)) != MS_SUCCESS) return status; } } else { /* force zoom = 1 (i.e. pan) */ mapserv->fZoom = mapserv->Zoom = 1; mapserv->ZoomDirection = 0; mapserv->CoordSource = FROMSCALE; mapserv->ScaleDenom = mapserv->map->web.maxscaledenom; mapserv->mappnt.x = (mapserv->map->extent.maxx + mapserv->map->extent.minx)/2; /* use center of bad extent */ mapserv->mappnt.y = (mapserv->map->extent.maxy + mapserv->map->extent.miny)/2; setExtent(mapserv); mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if((status = msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom)) != MS_SUCCESS) return status; } } } return MS_SUCCESS; } int msReturnTemplateQuery(mapservObj *mapserv, char *queryFormat, char **papszBuffer) { imageObj *img = NULL; int i, status; outputFormatObj *outputFormat=NULL; mapObj *map = mapserv->map; if(!queryFormat) { msSetError(MS_WEBERR, "Return format/mime-type not specified.", "msReturnTemplateQuery()"); return MS_FAILURE; } msApplyDefaultOutputFormats(map); i = msGetOutputFormatIndex(map, queryFormat); /* queryFormat can be a mime-type or name */ if(i >= 0) outputFormat = map->outputformatlist[i]; if(outputFormat) { if( MS_RENDERER_PLUGIN(outputFormat) ) { msInitializeRendererVTable(outputFormat); } /* if( MS_RENDERER_MVT(outputFormat) ) { if( mapserv != NULL ) checkWebScale(mapserv); status = msMVTWriteFromQuery(map, outputFormat, mapserv->sendheaders); return status; } */ if( MS_RENDERER_OGR(outputFormat) ) { if( mapserv != NULL ) checkWebScale(mapserv); status = msOGRWriteFromQuery(map, outputFormat, mapserv->sendheaders); return status; } if( !MS_RENDERER_TEMPLATE(outputFormat) ) { /* got an image format, return the query results that way */ outputFormatObj *tempOutputFormat = map->outputformat; /* save format */ if( mapserv != NULL ) checkWebScale(mapserv); map->outputformat = outputFormat; /* override what was given for IMAGETYPE */ img = msDrawMap(map, MS_TRUE); if(!img) return MS_FAILURE; map->outputformat = tempOutputFormat; /* restore format */ if(mapserv == NULL || mapserv->sendheaders) { msIO_setHeader("Content-Type", "%s", MS_IMAGE_MIME_TYPE(outputFormat)); msIO_sendHeaders(); } status = msSaveImage(map, img, NULL); msFreeImage(img); return status; } } /* ** At this point we know we have a template of some sort, either the new style that references a or the old ** style made up of external files slammed together. Either way we may have to compute a query map and other ** images. We only create support images IF the querymap has status=MS_ON. */ if(map->querymap.status && mapserv != NULL ) { checkWebScale(mapserv); if(msGenerateImages(mapserv, MS_TRUE, MS_TRUE) != MS_SUCCESS) return MS_FAILURE; } if(outputFormat) { const char *file = msGetOutputFormatOption( outputFormat, "FILE", NULL ); if(!file) { msSetError(MS_WEBERR, "Template driver requires \"FILE\" format option be set.", "msReturnTemplateQuery()"); return MS_FAILURE; } if(mapserv == NULL || mapserv->sendheaders) { const char *attachment = msGetOutputFormatOption( outputFormat, "ATTACHMENT", NULL ); if(attachment) msIO_setHeader("Content-disposition","attachment; filename=%s", attachment); msIO_setHeader("Content-Type", "%s", outputFormat->mimetype); msIO_sendHeaders(); } if((status = msReturnPage(mapserv, (char *) file, BROWSE, papszBuffer)) != MS_SUCCESS) return status; } else { if((status = msReturnNestedTemplateQuery(mapserv, queryFormat, papszBuffer)) != MS_SUCCESS) return status; } return MS_SUCCESS; } /* ** Is a particular layer or group on, that is was it requested explicitly by the user. */ int isOn(mapservObj *mapserv, char *name, char *group) { int i; for(i=0; iNumLayers; i++) { if(name && strcmp(mapserv->Layers[i], name) == 0) return(MS_TRUE); if(group && strcmp(mapserv->Layers[i], group) == 0) return(MS_TRUE); } return(MS_FALSE); } /************************************************************************/ /* int sortLayerByOrder(mapObj *map, char* pszOrder) */ /* */ /* sorth the displaying in ascending or descending order. */ /************************************************************************/ int sortLayerByOrder(mapObj *map, const char* pszOrder) { int *panCurrentOrder = NULL; int i = 0; if(!map) { msSetError(MS_WEBERR, "Invalid pointer.", "sortLayerByOrder()"); return MS_FAILURE; } /* ==================================================================== */ /* The flag "ascending" is in fact not useful since the */ /* default ordering is ascending. */ /* ==================================================================== */ /* -------------------------------------------------------------------- */ /* the map->layerorder should be set at this point in the */ /* sortLayerByMetadata. */ /* -------------------------------------------------------------------- */ if(map->layerorder) { panCurrentOrder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); for (i=0; inumlayers ; i++) panCurrentOrder[i] = map->layerorder[i]; if(strcasecmp(pszOrder, "DESCENDING") == 0) { for (i=0; inumlayers; i++) map->layerorder[i] = panCurrentOrder[map->numlayers-1-i]; } free(panCurrentOrder); } return MS_SUCCESS; } /*! * This function set the map->layerorder * index order by the metadata collumn name */ static int sortLayerByMetadata(mapObj *map, const char* pszMetadata) { int nLegendOrder1; int nLegendOrder2; int i, j; int tmp; if(!map) { msSetError(MS_WEBERR, "Invalid pointer.", "sortLayerByMetadata()"); return MS_FAILURE; } /* * Initiate to default order (Reverse mapfile order) */ if(map->layerorder) { int *pnLayerOrder; /* Backup the original layer order to be able to reverse it */ pnLayerOrder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); for (i=0; inumlayers ; i++) pnLayerOrder[i] = map->layerorder[i]; /* Get a new layerorder array */ free(map->layerorder); map->layerorder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); /* Reverse the layerorder array */ for (i=0; inumlayers ; i++) map->layerorder[i] = pnLayerOrder[map->numlayers - i - 1]; free(pnLayerOrder); } else { map->layerorder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); for (i=0; inumlayers ; i++) map->layerorder[i] = map->numlayers - i - 1; } if(!pszMetadata) return MS_SUCCESS; /* * Bubble sort algo (not very efficient) * should implement a kind of quick sort * alog instead */ for (i=0; inumlayers-1; i++) { for (j=0; jnumlayers-1-i; j++) { const char* pszLegendOrder1 = msLookupHashTable(&(GET_LAYER(map, map->layerorder[j+1])->metadata), pszMetadata); const char* pszLegendOrder2 = msLookupHashTable(&(GET_LAYER(map, map->layerorder[j])->metadata), pszMetadata); if(!pszLegendOrder1 || !pszLegendOrder2) continue; nLegendOrder1 = atoi(pszLegendOrder1); nLegendOrder2 = atoi(pszLegendOrder2); if(nLegendOrder1 < nLegendOrder2) { /* compare the two neighbors */ tmp = map->layerorder[j]; /* swap a[j] and a[j+1] */ map->layerorder[j] = map->layerorder[j+1]; map->layerorder[j+1] = tmp; } } } return MS_SUCCESS; } /* ** This function return a pointer ** at the begining of the first occurence ** of pszTag in pszInstr. ** ** Tag can be [TAG] or [TAG something] */ char *findTag(char *pszInstr, char *pszTag) { char *pszTag1, *pszStart=NULL; char *pszTemp; int done=MS_FALSE; int length; if(!pszInstr || !pszTag) { msSetError(MS_WEBERR, "Invalid pointer.", "findTag()"); return NULL; } length = strlen(pszTag) + 1; /* adding [ character to the beginning */ pszTag1 = (char*) msSmallMalloc(length+1); strcpy(pszTag1, "["); strcat(pszTag1, pszTag); pszTemp = pszInstr; while(!done) { pszStart = strstr(pszTemp, pszTag1); if(pszStart == NULL) done = MS_TRUE; /* tag not found */ else if((*(pszStart+length) == ']' || *(pszStart+length) == ' ')) done = MS_TRUE; /* valid tag */ else pszTemp += length; /* skip ahead and start over */ } free(pszTag1); return pszStart; } /* ** This function return a pointer ** to the end of the tag in pszTag ** ** The end of a tag is the next ** non-quoted ']' character. ** Return NULL if not found. */ char *findTagEnd(const char *pszTag) { char *pszEnd = NULL, *pszTmp = (char*)pszTag; while (pszTmp != NULL) { if (*pszTmp == '"') pszTmp = strchr(pszTmp+1,'"'); if ((pszTmp == NULL) || (*pszTmp == ']')) { pszEnd = pszTmp; pszTmp = NULL; } else pszTmp++; } return pszEnd; } /* ** Return a hashtableobj from instr of all ** arguments. hashtable must be freed by caller. */ int getTagArgs(char* pszTag, char* pszInstr, hashTableObj **ppoHashTable) { char *pszStart, *pszEnd, *pszArgs; int nLength; char **papszArgs, **papszVarVal; int nArgs, nDummy; int i; if(!pszTag || !pszInstr) { msSetError(MS_WEBERR, "Invalid pointer.", "getTagArgs()"); return MS_FAILURE; } /* set position to the begining of tag */ pszStart = findTag(pszInstr, pszTag); if(pszStart) { /* find ending position */ pszEnd = findTagEnd(pszStart); if(pszEnd) { /* skip the tag name */ pszStart = pszStart + strlen(pszTag) + 1; /* get length of all args */ nLength = pszEnd - pszStart; if(nLength > 0) { /* is there arguments ? */ pszArgs = (char*)msSmallMalloc(nLength + 1); strlcpy(pszArgs, pszStart, nLength+1); if(!(*ppoHashTable)) *ppoHashTable = msCreateHashTable(); /* put all arguments seperate by space in a hash table */ papszArgs = msStringTokenize(pszArgs, " ", &nArgs, MS_TRUE); /* msReturnTemplateQuerycheck all argument if they have values */ for (i=0; i 0) { *pszResult = (char*)msSmallMalloc(nLength + 1); /* copy string beetween start and end tag */ strlcpy(*pszResult, pszStart, nLength+1); (*pszResult)[nLength] = '\0'; } } else { msSetError(MS_WEBERR, "Malformed [%s] tag.", "getInlineTag()", pszTag); return MS_FAILURE; } } msFree(pszEndTag); return MS_SUCCESS; } /*! * this function process all if tag in pszInstr. * this function return a modified pszInstr. * ht mus contain all variables needed by the function * to interpret if expression. * * If bLastPass is true then all tests for 'null' values will be * considered true if the corresponding value is not set. */ int processIfTag(char **pszInstr, hashTableObj *ht, int bLastPass) { /* char *pszNextInstr = pszInstr; */ char *pszStart, *pszEnd=NULL; const char *pszName, *pszValue, *pszOperator, *pszHTValue; char *pszThen=NULL; char *pszIfTag; char *pszPatIn=NULL, *pszPatOut=NULL, *pszTmp; int nInst = 0; int bEmpty = 0; int nLength; hashTableObj *ifArgs=NULL; if(!*pszInstr) { msSetError(MS_WEBERR, "Invalid pointer.", "processIfTag()"); return MS_FAILURE; } /* find the if start tag */ pszStart = findTag(*pszInstr, "if"); while (pszStart) { pszPatIn = findTag(pszStart, "if"); pszPatOut = strstr(pszStart, "[/if]"); pszTmp = pszPatIn; do { if(pszPatIn && pszPatIn < pszPatOut) { nInst++; pszTmp = pszPatIn; } if(pszPatOut && ((pszPatIn == NULL) || pszPatOut < pszPatIn)) { pszEnd = pszPatOut; nInst--; pszTmp = pszPatOut; } pszPatIn = findTag(pszTmp+1, "if"); pszPatOut = strstr(pszTmp+1, "[/if]"); } while (pszTmp != NULL && nInst > 0); /* get the then string (if expression is true) */ if(getInlineTag("if", pszStart, &pszThen) != MS_SUCCESS) { msSetError(MS_WEBERR, "Malformed then if tag.", "processIfTag()"); return MS_FAILURE; } /* retrieve if tag args */ if(getTagArgs("if", pszStart, &ifArgs) != MS_SUCCESS) { msSetError(MS_WEBERR, "Malformed args if tag.", "processIfTag()"); return MS_FAILURE; } pszName = msLookupHashTable(ifArgs, "name"); pszValue = msLookupHashTable(ifArgs, "value"); pszOperator = msLookupHashTable(ifArgs, "oper"); if(pszOperator == NULL) /* Default operator if not set is "eq" */ pszOperator = "eq"; bEmpty = 0; if(pszName) { /* build the complete if tag ([if all_args]then string[/if]) */ /* to replace if by then string if expression is true */ /* or by a white space if not. */ nLength = pszEnd - pszStart; pszIfTag = (char*)msSmallMalloc(nLength + 6); strlcpy(pszIfTag, pszStart, nLength+1); pszIfTag[nLength] = '\0'; strcat(pszIfTag, "[/if]"); pszHTValue = msLookupHashTable(ht, pszName); if(strcmp(pszOperator, "neq") == 0) { if(pszValue && pszHTValue && strcasecmp(pszValue, pszHTValue) != 0) { *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, pszThen); } else if(pszHTValue) { *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, ""); bEmpty = 1; } } else if(strcmp(pszOperator, "eq") == 0) { if(pszValue && pszHTValue && strcasecmp(pszValue, pszHTValue) == 0) { *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, pszThen); } else if(pszHTValue) { *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, ""); bEmpty = 1; } } else if(strcmp(pszOperator, "isnull") == 0) { if(pszHTValue != NULL) { /* We met a non-null value... condition is false */ *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, ""); bEmpty = 1; } else if(bLastPass) { /* On last pass, if value is still null then condition is true */ *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, pszThen); } } else if(strcmp(pszOperator, "isset") == 0) { if(pszHTValue != NULL) { /* Found a non-null value... condition is true */ *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, pszThen); } else if(bLastPass) { /* On last pass, if value still not set then condition is false */ *pszInstr = msReplaceSubstring(*pszInstr, pszIfTag, ""); bEmpty = 1; } } else { msSetError(MS_WEBERR, "Unsupported operator (%s) in if tag.", "processIfTag()", pszOperator); return MS_FAILURE; } if(pszIfTag) free(pszIfTag); pszIfTag = NULL; } if(pszThen) free (pszThen); pszThen=NULL; msFreeHashTable(ifArgs); ifArgs=NULL; /* find the if start tag */ if(bEmpty) pszStart = findTag(pszStart, "if"); else pszStart = findTag(pszStart + 1, "if"); } return MS_SUCCESS; } /* Helper function to return the text before the supplied string2 in string1. */ static char *getPreTagText(const char *string1, const char *string2) { int n; char *result, *tmpstr; if((tmpstr = strstr(string1, string2)) == NULL) return msStrdup(""); /* return an empty string */ n = strlen(string1) - strlen(tmpstr); result = (char *) msSmallMalloc(n + 1); strlcpy(result, string1, n+1); return result; } /* Helper function to retunr the text after the supplied string2 in string1. */ static char *getPostTagText(const char *string1, const char *string2) { char *tmpstr; if((tmpstr = strstr(string1, string2)) == NULL) return msStrdup(""); /* return an empty string */ tmpstr += strlen(string2); /* skip string2 */ return msStrdup(tmpstr); } /* ** Function to process a [feature ...] tag. This tag can *only* be found within ** a [resultset ...][/resultset] block. */ static int processFeatureTag(mapservObj *mapserv, char **line, layerObj *layer) { char *preTag, *postTag; /* text before and after the tag */ const char *argValue; char *tag, *tagInstance, *tagStart; hashTableObj *tagArgs=NULL; int limit=-1; const char *trimLast=NULL; int i, j, status; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processFeatureTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "feature"); if(!tagStart) return(MS_SUCCESS); /* OK, just return; */ /* check for any tag arguments */ if(getTagArgs("feature", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "limit"); if(argValue) limit = atoi(argValue); argValue = msLookupHashTable(tagArgs, "trimlast"); if(argValue) trimLast = argValue; } if(strstr(*line, "[/feature]") == NULL) { /* we know the closing tag must be here, if not throw an error */ msSetError(MS_WEBERR, "[feature] tag found without closing [/feature].", "processFeatureTag()"); msFreeHashTable(tagArgs); return(MS_FAILURE); } if(getInlineTag("feature", *line, &tag) != MS_SUCCESS) { msSetError(MS_WEBERR, "Malformed feature tag.", "processFeatureTag()"); msFreeHashTable(tagArgs); return MS_FAILURE; } preTag = getPreTagText(*line, "[feature"); postTag = getPostTagText(*line, "[/feature]"); /* start rebuilding **line */ free(*line); *line = preTag; /* we know the layer has query results or we wouldn't be in this code */ #if 0 status = msLayerOpen(layer); /* open the layer */ if(status != MS_SUCCESS) return status; status = msLayerGetItems(layer); /* retrieve all the item names */ if(status != MS_SUCCESS) return status; #endif if(layer->numjoins > 0) { /* initialize necessary JOINs here */ for(j=0; jnumjoins; j++) { status = msJoinConnect(layer, &(layer->joins[j])); if(status != MS_SUCCESS) { msFreeHashTable(tagArgs); msFree(postTag); msFree(tag); return status; } } } mapserv->LRN = 1; /* layer result counter */ mapserv->resultlayer = layer; msInitShape(&(mapserv->resultshape)); if(limit == -1) /* return all */ limit = layer->resultcache->numresults; else limit = MS_MIN(limit, layer->resultcache->numresults); for(i=0; iresultshape), &(layer->resultcache->results[i])); if(status != MS_SUCCESS) { msFreeHashTable(tagArgs); msFree(postTag); msFree(tag); return status; } mapserv->resultshape.classindex = msShapeGetClass(layer, layer->map, &mapserv->resultshape, NULL, -1); /* prepare any necessary JOINs here (one-to-one only) */ if(layer->numjoins > 0) { for(j=0; jnumjoins; j++) { if(layer->joins[j].type == MS_JOIN_ONE_TO_ONE) { msJoinPrepare(&(layer->joins[j]), &(mapserv->resultshape)); msJoinNext(&(layer->joins[j])); /* fetch the first row */ } } } /* ** if necessary trim a few characters off the end of the tag */ if(trimLast && (i == limit-1)) { char *ptr; if((ptr = strrstr(tag, trimLast)) != NULL) *ptr = '\0'; } /* process the tag */ tagInstance = processLine(mapserv, tag, NULL, QUERY); /* do substitutions */ *line = msStringConcatenate(*line, tagInstance); /* grow the line */ free(tagInstance); msFreeShape(&(mapserv->resultshape)); /* init too */ mapserv->RN++; /* increment counters */ mapserv->LRN++; } /* msLayerClose(layer); */ mapserv->resultlayer = NULL; /* necessary? */ *line = msStringConcatenate(*line, postTag); /* ** clean up */ free(postTag); free(tag); msFreeHashTable(tagArgs); return(MS_SUCCESS); } /* ** Function to process a [resultset ...] tag. */ static int processResultSetTag(mapservObj *mapserv, char **line, FILE *stream) { char lineBuffer[MS_BUFFER_LENGTH]; int foundTagEnd; char *preTag, *postTag; /* text before and after the tag */ char *tag, *tagStart; hashTableObj *tagArgs=NULL; const char *layerName=NULL; const char *nodata=NULL; int layerIndex=-1; layerObj *lp; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processResultSetTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "resultset"); if(!tagStart) return(MS_SUCCESS); /* OK, just return; */ while (tagStart) { /* initialize the tag arguments */ layerName = NULL; /* check for any tag arguments */ if(getTagArgs("resultset", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { layerName = msLookupHashTable(tagArgs, "layer"); nodata = msLookupHashTable(tagArgs, "nodata"); } if(!layerName) { msSetError(MS_WEBERR, "[resultset] tag missing required 'layer' argument.", "processResultSetTag()"); msFreeHashTable(tagArgs); return(MS_FAILURE); } layerIndex = msGetLayerIndex(mapserv->map, layerName); if(layerIndex>=mapserv->map->numlayers || layerIndex<0) { msSetError(MS_MISCERR, "Layer named '%s' does not exist.", "processResultSetTag()", layerName); msFreeHashTable(tagArgs); return MS_FAILURE; } lp = GET_LAYER(mapserv->map, layerIndex); if(strstr(*line, "[/resultset]") == NULL) { /* read ahead */ if(!stream) { msSetError(MS_WEBERR, "Invalid file pointer.", "processResultSetTag()"); msFreeHashTable(tagArgs); return(MS_FAILURE); } foundTagEnd = MS_FALSE; while(!foundTagEnd) { if(fgets(lineBuffer, MS_BUFFER_LENGTH, stream) != NULL) { *line = msStringConcatenate(*line, lineBuffer); if(strstr(*line, "[/resultset]") != NULL) foundTagEnd = MS_TRUE; } else break; /* ran out of file */ } if(foundTagEnd == MS_FALSE) { msSetError(MS_WEBERR, "[resultset] tag found without closing [/resultset].", "processResultSetTag()"); msFreeHashTable(tagArgs); return(MS_FAILURE); } } if(getInlineTag("resultset", *line, &tag) != MS_SUCCESS) { msSetError(MS_WEBERR, "Malformed resultset tag.", "processResultSetTag()"); msFreeHashTable(tagArgs); return MS_FAILURE; } preTag = getPreTagText(*line, "[resultset"); /* TODO: need to handle tags in these */ postTag = getPostTagText(*line, "[/resultset]"); /* start rebuilding **line */ free(*line); *line = preTag; if(lp->resultcache && lp->resultcache->numresults > 0) { /* probably will need a while-loop here to handle multiple instances of [feature ...] tags */ if(processFeatureTag(mapserv, &tag, lp) != MS_SUCCESS) { msFreeHashTable(tagArgs); return(MS_FAILURE); /* TODO: how to handle */ } *line = msStringConcatenate(*line, tag); } else if(nodata) { *line = msStringConcatenate(*line, nodata); } *line = msStringConcatenate(*line, postTag); /* clean up */ free(postTag); free(tag); tagStart = findTag(*line, "resultset"); } msFreeHashTable(tagArgs); return(MS_SUCCESS); } /* ** Function process a [include src="..."] tag. ** ** TODO's: ** - allow URLs */ static int processIncludeTag(mapservObj *mapserv, char **line, FILE *stream, int mode) { char *tag, *tagStart, *tagEnd; hashTableObj *tagArgs=NULL; int tagOffset, tagLength; char *content=NULL, *processedContent=NULL; const char *src=NULL; FILE *includeStream; char buffer[MS_BUFFER_LENGTH], path[MS_MAXPATHLEN]; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processIncludeTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "include"); /* It is OK to have no include tags, just return. */ if( !tagStart ) return MS_SUCCESS; while( tagStart ) { tagOffset = tagStart - *line; /* check for any tag arguments */ if(getTagArgs("include", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { src = msLookupHashTable(tagArgs, "src"); } if(!src) return(MS_SUCCESS); /* don't process the tag, could be something else so return MS_SUCCESS */ if((includeStream = fopen(msBuildPath(path, mapserv->map->mappath, src), "r")) == NULL) { msSetError(MS_IOERR, "%s", "processIncludeTag()", src); return MS_FAILURE; } if(isValidTemplate(includeStream, src) != MS_TRUE) { fclose(includeStream); return MS_FAILURE; } while(fgets(buffer, MS_BUFFER_LENGTH, includeStream) != NULL) content = msStringConcatenate(content, buffer); /* done with included file handle */ fclose(includeStream); /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* process any other tags in the content */ processedContent = processLine(mapserv, content, stream, mode); /* do the replacement */ *line = msReplaceSubstring(*line, tag, processedContent); /* clean up */ free(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; free(content); free(processedContent); if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, "include"); else tagStart = NULL; } return(MS_SUCCESS); } /* ** Function to process an [item ...] tag: line contains the tag, shape holds the attributes. */ enum ITEM_ESCAPING {ESCAPE_HTML, ESCAPE_URL, ESCAPE_JSON, ESCAPE_NONE}; static int processItemTag(layerObj *layer, char **line, shapeObj *shape) { int i, j; char *tag, *tagStart, *tagEnd; hashTableObj *tagArgs=NULL; int tagLength; char *encodedTagValue=NULL, *tagValue=NULL; const char *argValue=NULL; const char *name=NULL, *pattern=NULL; const char *format=NULL, *nullFormat=NULL; int precision; int uc, lc, commify; int escape; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processItemTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "item"); if(!tagStart) return(MS_SUCCESS); /* OK, just return; */ while (tagStart) { format = "$value"; /* initialize the tag arguments */ nullFormat = ""; precision=-1; name = pattern = NULL; uc = lc = commify = MS_FALSE; escape=ESCAPE_HTML; /* check for any tag arguments */ if(getTagArgs("item", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "name"); if(argValue) name = argValue; argValue = msLookupHashTable(tagArgs, "pattern"); if(argValue) pattern = argValue; argValue = msLookupHashTable(tagArgs, "precision"); if(argValue) precision = atoi(argValue); argValue = msLookupHashTable(tagArgs, "format"); if(argValue) format = argValue; argValue = msLookupHashTable(tagArgs, "nullformat"); if(argValue) nullFormat = argValue; argValue = msLookupHashTable(tagArgs, "uc"); if(argValue && strcasecmp(argValue, "true") == 0) uc = MS_TRUE; argValue = msLookupHashTable(tagArgs, "lc"); if(argValue && strcasecmp(argValue, "true") == 0) lc = MS_TRUE; argValue = msLookupHashTable(tagArgs, "commify"); if(argValue && strcasecmp(argValue, "true") == 0) commify = MS_TRUE; argValue = msLookupHashTable(tagArgs, "escape"); if(argValue && strcasecmp(argValue, "url") == 0) escape = ESCAPE_URL; else if(argValue && strcasecmp(argValue, "none") == 0) escape = ESCAPE_NONE; else if(argValue && strcasecmp(argValue, "json") == 0) escape = ESCAPE_JSON; /* TODO: deal with sub strings */ } if(!name) { msSetError(MS_WEBERR, "Item tag contains no name attribute.", "processItemTag()"); return(MS_FAILURE); } for(i=0; inumitems; i++) if(strcasecmp(name, layer->items[i]) == 0) break; if(i == layer->numitems) { msSetError(MS_WEBERR, "Item name (%s) not found in layer item list.", "processItemTag()", name); return(MS_FAILURE); } /* ** now we know which item so build the tagValue */ if(shape->values[i] && strlen(shape->values[i]) > 0) { char *itemValue=NULL; /* set tag text depending on pattern (if necessary), nullFormat can contain $value (#3637) */ if(pattern && msEvalRegex(pattern, shape->values[i]) != MS_TRUE) tagValue = msStrdup(nullFormat); else tagValue = msStrdup(format); if(precision != -1) { char numberFormat[16]; itemValue = (char *) msSmallMalloc(64); /* plenty big */ snprintf(numberFormat, sizeof(numberFormat), "%%.%dlf", precision); snprintf(itemValue, 64, numberFormat, atof(shape->values[i])); } else itemValue = msStrdup(shape->values[i]); if(commify == MS_TRUE) itemValue = msCommifyString(itemValue); /* apply other effects */ if(uc == MS_TRUE) for(j=0; jmaxx-extent->minx))/2; yExpand = ((f/100.0)*(extent->maxy-extent->miny))/2; } else { xExpand = atof(argValue); yExpand = xExpand; } } argValue = msLookupHashTable(tagArgs, "escape"); if(argValue && strcasecmp(argValue, "url") == 0) escape = ESCAPE_URL; else if(argValue && strcasecmp(argValue, "none") == 0) escape = ESCAPE_NONE; argValue = msLookupHashTable(tagArgs, "format"); if(argValue) format = argValue; argValue = msLookupHashTable(tagArgs, "precision"); if(argValue) precision = atoi(argValue); argValue = msLookupHashTable(tagArgs, "proj"); if(argValue) projectionString = argValue; } tempExtent.minx = extent->minx - xExpand; tempExtent.miny = extent->miny - yExpand; tempExtent.maxx = extent->maxx + xExpand; tempExtent.maxy = extent->maxy + yExpand; /* no big deal to convert from file to image coordinates, but what are the image parameters */ if(rectProj && projectionString && strcasecmp(projectionString,"image") == 0) { precision = 0; /* if necessary, project the shape to match the map */ if(msProjectionsDiffer(rectProj, &(mapserv->map->projection))) msProjectRect(rectProj, &mapserv->map->projection, &tempExtent); /* convert tempExtent to image coordinates based on the map extent and cellsize */ tempExtent.minx = MS_MAP2IMAGE_X(tempExtent.minx, mapserv->map->extent.minx, mapserv->map->cellsize); tempExtent.miny = MS_MAP2IMAGE_Y(tempExtent.miny, mapserv->map->extent.maxy, mapserv->map->cellsize); tempExtent.maxx = MS_MAP2IMAGE_X(tempExtent.minx, mapserv->map->extent.minx, mapserv->map->cellsize); tempExtent.maxy = MS_MAP2IMAGE_Y(tempExtent.miny, mapserv->map->extent.maxy, mapserv->map->cellsize); } else if(rectProj && projectionString) { projectionObj projection; msInitProjection(&projection); if(MS_SUCCESS != msLoadProjectionString(&projection, projectionString)) return MS_FAILURE; if(msProjectionsDiffer(rectProj, &projection)) msProjectRect(rectProj, &projection, &tempExtent); } tagValue = msStrdup(format); if(precision != -1) snprintf(numberFormat, sizeof(numberFormat), "%%.%dlf", precision); else snprintf(numberFormat, sizeof(numberFormat), "%%f"); snprintf(number, sizeof(number), numberFormat, tempExtent.minx); tagValue = msReplaceSubstring(tagValue, "$minx", number); snprintf(number, sizeof(number), numberFormat, tempExtent.miny); tagValue = msReplaceSubstring(tagValue, "$miny", number); snprintf(number, sizeof(number), numberFormat, tempExtent.maxx); tagValue = msReplaceSubstring(tagValue, "$maxx", number); snprintf(number, sizeof(number), numberFormat, tempExtent.maxy); tagValue = msReplaceSubstring(tagValue, "$maxy", number); /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* do the replacement */ switch(escape) { case ESCAPE_HTML: encodedTagValue = msEncodeHTMLEntities(tagValue); *line = msReplaceSubstring(*line, tag, encodedTagValue); break; case ESCAPE_URL: encodedTagValue = msEncodeUrl(tagValue); *line = msReplaceSubstring(*line, tag, encodedTagValue); break; case ESCAPE_NONE: *line = msReplaceSubstring(*line, tag, tagValue); break; default: break; } /* clean up */ free(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; msFree(tagValue); tagValue=NULL; msFree(encodedTagValue); encodedTagValue=NULL; if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, name); else tagStart = NULL; } return(MS_SUCCESS); } // RFC 77 TODO: Need to validate these changes with Assefa... static int processShplabelTag(layerObj *layer, char **line, shapeObj *origshape) { char *tag, *tagStart, *tagEnd; char *tagValue=NULL; hashTableObj *tagArgs=NULL; int tagOffset, tagLength; const char *format; const char *argValue=NULL; const char *projectionString=NULL; shapeObj tShape; int precision=0; int clip_to_map=MS_TRUE; int use_label_settings=MS_FALSE; double cellsize=0; int labelposvalid = MS_FALSE; pointObj labelPos; int status; char number[64]; /* holds a single number in the extent */ char numberFormat[16]; shapeObj *shape = NULL; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processShplabelTag()"); return(MS_FAILURE); } if(msCheckParentPointer(layer->map,"map") == MS_FAILURE) return MS_FAILURE; tagStart = findTag(*line, "shplabel"); /* It is OK to have no shplabel tags, just return. */ if(!tagStart) return MS_SUCCESS; if(!origshape || origshape->numlines <= 0) { /* I suppose we need to make sure the part has vertices (need shape checker?) */ msSetError(MS_WEBERR, "Null or empty shape.", "processShplabelTag()"); return(MS_FAILURE); } while(tagStart) { if(shape) msFreeShape(shape); shape = (shapeObj *) msSmallMalloc(sizeof(shapeObj)); msInitShape(shape); msCopyShape(origshape, shape); projectionString = NULL; format = "$x,$y"; tagOffset = tagStart - *line; if(getTagArgs("shplabel", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "format"); if(argValue) format = argValue; argValue = msLookupHashTable(tagArgs, "precision"); if(argValue) precision = atoi(argValue); argValue = msLookupHashTable(tagArgs, "proj"); if(argValue) projectionString = argValue; argValue = msLookupHashTable(tagArgs, "clip_to_map"); if(argValue) { if(strcasecmp(argValue,"false") == 0) clip_to_map = MS_FALSE; } argValue = msLookupHashTable(tagArgs, "use_label_settings"); if(argValue) { if(strcasecmp(argValue,"true") == 0) use_label_settings = MS_TRUE; } } labelPos.x = -1; labelPos.y = -1; msInitShape(&tShape); tShape.type = MS_SHAPE_LINE; tShape.line = (lineObj *) msSmallMalloc(sizeof(lineObj)); tShape.numlines = 1; tShape.line[0].point = NULL; /* initialize the line */ tShape.line[0].numpoints = 0; if(layer->map->cellsize <= 0) cellsize = MS_MAX(MS_CELLSIZE(layer->map->extent.minx, layer->map->extent.maxx, layer->map->width), MS_CELLSIZE(layer->map->extent.miny, layer->map->extent.maxy, layer->map->height)); else cellsize = layer->map->cellsize ; if(shape->type == MS_SHAPE_POINT) { labelposvalid = MS_FALSE; if(shape->numlines > 0 && shape->line[0].numpoints > 0) { labelposvalid = MS_TRUE; labelPos = shape->line[0].point[0]; if(layer->transform == MS_TRUE) { if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, shape); labelPos = shape->line[0].point[0]; labelPos.x = MS_MAP2IMAGE_X(labelPos.x, layer->map->extent.minx, cellsize); labelPos.y = MS_MAP2IMAGE_Y(labelPos.y, layer->map->extent.maxy, cellsize); } } } else if(shape->type == MS_SHAPE_LINE) { labelposvalid = MS_FALSE; if(layer->transform == MS_TRUE) { if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, shape); if(clip_to_map) msClipPolylineRect(shape, layer->map->extent); msTransformShapeToPixelRound(shape, layer->map->extent, cellsize); } else msOffsetShapeRelativeTo(shape, layer); if(shape->numlines > 0) { struct label_auto_result lar; memset(&lar,0,sizeof(struct label_auto_result)); if(UNLIKELY(MS_FAILURE == msPolylineLabelPoint(layer->map, shape, NULL, NULL, &lar, 0))) { free(lar.angles); free(lar.label_points); return MS_FAILURE; } if(lar.num_label_points > 0) { /* convert to geo */ labelPos.x = lar.label_points[0].x; labelPos.y = lar.label_points[0].y; labelposvalid = MS_TRUE; } free(lar.angles); free(lar.label_points); } } else if (shape->type == MS_SHAPE_POLYGON) { labelposvalid = MS_FALSE; if(layer->transform == MS_TRUE) { if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, shape); if(clip_to_map) msClipPolygonRect(shape, layer->map->extent); msTransformShapeToPixelRound(shape, layer->map->extent, cellsize); } else msOffsetShapeRelativeTo(shape, layer); if(shape->numlines > 0) { if(msPolygonLabelPoint(shape, &labelPos, -1) == MS_SUCCESS) { if(labelPos.x == -1 && labelPos.y == -1) labelposvalid = MS_FALSE; else labelposvalid = MS_TRUE; } } } if(labelposvalid == MS_TRUE) { pointObj p1; pointObj p2; int label_offset_x, label_offset_y; labelObj *label=NULL; label_bounds lbounds; lineObj lbounds_line; pointObj lbounds_point[5]; double tmp; p1.x =labelPos.x; p1.y =labelPos.y; p2.x =labelPos.x; p2.y =labelPos.y; if(use_label_settings == MS_TRUE) { /* RFC 77: classes (and shapes) can have more than 1 piece of annotation, here we only use the first (index=0) */ if(shape->classindex >= 0 && layer->class[shape->classindex]->numlabels > 0) { label = layer->class[shape->classindex]->labels[0]; if(msGetLabelStatus(layer->map,layer,shape,label) == MS_ON) { char *annotext = msShapeGetLabelAnnotation(layer,shape,label); if(annotext) { textSymbolObj ts; initTextSymbol(&ts); msPopulateTextSymbolForLabelAndString(&ts, label, annotext, layer->scalefactor, 1.0, 0); label_offset_x = (int)(label->offsetx*layer->scalefactor); label_offset_y = (int)(label->offsety*layer->scalefactor); lbounds.poly = &lbounds_line; lbounds_line.numpoints = 5; lbounds_line.point = lbounds_point; p1 = get_metrics(&labelPos, label->position, ts.textpath, label_offset_x, label_offset_y, label->angle* MS_DEG_TO_RAD, 0, &lbounds); /* should we use the point returned from get_metrics?. From few test done, It seems to return the UL corner of the text. For now use the bounds.minx/miny */ p1.x = lbounds.bbox.minx; p1.y = lbounds.bbox.miny; p2.x = lbounds.bbox.maxx; p2.y = lbounds.bbox.maxy; freeTextSymbol(&ts); } } } } /* y's are flipped because it is in image coordinate systems */ p1.x = MS_IMAGE2MAP_X(p1.x, layer->map->extent.minx, cellsize); tmp = p1.y; p1.y = MS_IMAGE2MAP_Y(p2.y, layer->map->extent.maxy, cellsize); p2.x = MS_IMAGE2MAP_X(p2.x, layer->map->extent.minx, cellsize); p2.y = MS_IMAGE2MAP_Y(tmp, layer->map->extent.maxy, cellsize); if(layer->transform == MS_TRUE) { if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) { msProjectPoint(&layer->map->projection, &layer->projection, &p1); msProjectPoint(&layer->map->projection, &layer->projection, &p2); } } msAddPointToLine(&(tShape.line[0]), &p1); msAddPointToLine(&(tShape.line[0]), &p2); } else tShape.numlines = 0; if(projectionString && strcasecmp(projectionString,"image") == 0) { precision = 0; /* if necessary, project the shape to match the map */ if(msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, &tShape); msClipPolylineRect(&tShape, layer->map->extent); msTransformShapeToPixelRound(&tShape, layer->map->extent, layer->map->cellsize); } else if(projectionString) { projectionObj projection; msInitProjection(&projection); status = msLoadProjectionString(&projection, projectionString); if(status != MS_SUCCESS) return MS_FAILURE; if(msProjectionsDiffer(&(layer->projection), &projection)) msProjectShape(&layer->projection, &projection, &tShape); } /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* do the replacement */ tagValue = msStrdup(format); if(precision > 0) snprintf(numberFormat, sizeof(numberFormat), "%%.%dlf", precision); else snprintf(numberFormat, sizeof(numberFormat), "%%f"); if(tShape.numlines > 0) { if(strcasestr(tagValue, "$x") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].x); tagValue = msReplaceSubstring(tagValue, "$x", number); } if(strcasestr(tagValue, "$y") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].y); tagValue = msReplaceSubstring(tagValue, "$y", number); } if(strcasestr(tagValue, "$minx") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].x); tagValue = msReplaceSubstring(tagValue, "$minx", number); } if(strcasestr(tagValue, "$miny") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[0].y); tagValue = msReplaceSubstring(tagValue, "$miny", number); } if(strcasestr(tagValue, "$maxx") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[1].x); tagValue = msReplaceSubstring(tagValue, "$maxx", number); } if(strcasestr(tagValue, "$maxy") != 0) { snprintf(number, sizeof(number), numberFormat, tShape.line[0].point[1].y); tagValue = msReplaceSubstring(tagValue, "$maxy", number); } } /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); *line = msReplaceSubstring(*line, tag, tagValue); /* clean up */ msFreeShape(&tShape); free(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; msFree(tagValue); tagValue=NULL; if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, "shplabel"); else tagStart = NULL; } if(shape) msFreeShape(shape); return(MS_SUCCESS); } /* ** Function to process a [date ...] tag */ static int processDateTag(char **line) { struct tm *datetime; time_t t; int result; char *tag=NULL, *tagStart, *tagEnd; hashTableObj *tagArgs=NULL; int tagOffset, tagLength; #define DATE_BUFLEN 1024 char datestr[DATE_BUFLEN]; const char *argValue=NULL; const char *format, *tz; /* tag parameters */ if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processDateTag()"); return(MS_FAILURE); } tagStart = findTag(*line, "date"); /* It is OK to have no date tags, just return. */ if( !tagStart ) return MS_SUCCESS; while (tagStart) { /* set tag params to defaults */ format = DEFAULT_DATE_FORMAT; tz = ""; tagOffset = tagStart - *line; /* check for any tag arguments */ if(getTagArgs("date", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "format"); if(argValue) format = argValue; argValue = msLookupHashTable(tagArgs, "tz"); if(argValue) tz = argValue; } t = time(NULL); if( strncasecmp( tz, "gmt", 4 ) == 0 ) { datetime = gmtime(&t); } else { datetime = localtime(&t); } result = strftime(datestr, DATE_BUFLEN, format, datetime); /* Only do the replacement if the date was successfully written */ if( result > 0 ) { /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* do the replacement */ *line = msReplaceSubstring(*line, tag, datestr); } /* clean up */ msFree(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, "date"); else tagStart = NULL; } return(MS_SUCCESS); } /* ** Function to process a [shpxy ...] tag: line contains the tag, shape holds the coordinates. ** ** TODO's: ** - May need to change attribute names. ** - Need generalization routines (not here, but in mapprimative.c). ** - Try to avoid all the realloc calls. */ static int processShpxyTag(layerObj *layer, char **line, shapeObj *shape) { int i,j,p; int status; char *tag, *tagStart, *tagEnd; hashTableObj *tagArgs=NULL; int tagOffset, tagLength; const char *argValue=NULL; char *pointFormat1=NULL, *pointFormat2=NULL; int pointFormatLength; /* ** Pointers to static strings, naming convention is: ** char 1/2 - x=x, y=y, c=coordinate, p=part, s=shape, ir=inner ring, or=outer ring ** last char - h=header, f=footer, s=seperator */ const char *xh, *xf, *yh, *yf; const char *cs; const char *ph, *pf, *ps; const char *sh, *sf; const char *irh, *irf; /* inner ring: necessary for complex polygons */ const char *orh, *orf; /* outer ring */ int centroid; int precision; double scale_x, scale_y; const char *projectionString=NULL; shapeObj tShape; char *coords=NULL, point[128]; if(!*line) { msSetError(MS_WEBERR, "Invalid line pointer.", "processShpxyTag()"); return(MS_FAILURE); } if( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; tagStart = findTag(*line, "shpxy"); /* It is OK to have no shpxy tags, just return. */ if( !tagStart ) return MS_SUCCESS; if(!shape || shape->numlines <= 0) { /* I suppose we need to make sure the part has vertices (need shape checker?) */ msSetError(MS_WEBERR, "Null or empty shape.", "processShpxyTag()"); return(MS_FAILURE); } while (tagStart) { #ifdef USE_GEOS double buffer = 0; int bufferUnits = -1; #endif xh = yh = yf = ph = pf = sh = sf = ""; /* initialize the tag arguments */ xf= ","; irh = irf = orh = orf = ""; ps = cs = " "; centroid = MS_FALSE; precision = 0; scale_x = scale_y = 1.0; projectionString = NULL; tagOffset = tagStart - *line; /* check for any tag arguments */ if(getTagArgs("shpxy", tagStart, &tagArgs) != MS_SUCCESS) return(MS_FAILURE); if(tagArgs) { argValue = msLookupHashTable(tagArgs, "xh"); if(argValue) xh = argValue; argValue = msLookupHashTable(tagArgs, "xf"); if(argValue) xf = argValue; argValue = msLookupHashTable(tagArgs, "yh"); if(argValue) yh = argValue; argValue = msLookupHashTable(tagArgs, "yf"); if(argValue) yf = argValue; argValue = msLookupHashTable(tagArgs, "cs"); if(argValue) cs = argValue; argValue = msLookupHashTable(tagArgs, "irh"); if(argValue) irh = argValue; argValue = msLookupHashTable(tagArgs, "irf"); if(argValue) irf = argValue; argValue = msLookupHashTable(tagArgs, "orh"); if(argValue) orh = argValue; argValue = msLookupHashTable(tagArgs, "orf"); if(argValue) orf = argValue; argValue = msLookupHashTable(tagArgs, "ph"); if(argValue) ph = argValue; argValue = msLookupHashTable(tagArgs, "pf"); if(argValue) pf = argValue; argValue = msLookupHashTable(tagArgs, "ps"); if(argValue) ps = argValue; argValue = msLookupHashTable(tagArgs, "sh"); if(argValue) sh = argValue; argValue = msLookupHashTable(tagArgs, "sf"); if(argValue) sf = argValue; #ifdef USE_GEOS argValue = msLookupHashTable(tagArgs, "buffer"); if(argValue) { buffer = atof(argValue); if(strstr(argValue, "px")) bufferUnits = MS_PIXELS; /* may support others at some point */ } #endif argValue = msLookupHashTable(tagArgs, "precision"); if(argValue) precision = atoi(argValue); argValue = msLookupHashTable(tagArgs, "scale"); if(argValue) { scale_x = atof(argValue); scale_y = scale_x; } argValue = msLookupHashTable(tagArgs, "scale_x"); if(argValue) scale_x = atof(argValue); argValue = msLookupHashTable(tagArgs, "scale_y"); if(argValue) scale_y = atof(argValue); argValue = msLookupHashTable(tagArgs, "centroid"); if(argValue) if(strcasecmp(argValue,"true") == 0) centroid = MS_TRUE; argValue = msLookupHashTable(tagArgs, "proj"); if(argValue) projectionString = argValue; } /* build the per point format strings (version 1 contains the coordinate seperator, version 2 doesn't) */ pointFormatLength = strlen(xh) + strlen(xf) + strlen(yh) + strlen(yf) + strlen(cs) + 12 + 1; pointFormat1 = (char *) msSmallMalloc(pointFormatLength); snprintf(pointFormat1, pointFormatLength, "%s%%.%dlf%s%s%%.%dlf%s%s", xh, precision, xf, yh, precision, yf, cs); pointFormat2 = (char *) msSmallMalloc(pointFormatLength); snprintf(pointFormat2, pointFormatLength, "%s%%.%dlf%s%s%%.%dlf%s", xh, precision, xf, yh, precision, yf); /* make a copy of the original shape or compute a centroid if necessary */ msInitShape(&tShape); if(centroid == MS_TRUE) { pointObj p; p.x = (shape->bounds.minx + shape->bounds.maxx)/2; p.y = (shape->bounds.miny + shape->bounds.maxy)/2; tShape.type = MS_SHAPE_POINT; tShape.line = (lineObj *) msSmallMalloc(sizeof(lineObj)); tShape.numlines = 1; tShape.line[0].point = NULL; /* initialize the line */ tShape.line[0].numpoints = 0; msAddPointToLine(&(tShape.line[0]), &p); } #ifdef USE_GEOS else if(buffer != 0 && bufferUnits != MS_PIXELS) { shapeObj *bufferShape=NULL; bufferShape = msGEOSBuffer(shape, buffer); if(!bufferShape) { free(pointFormat1); free(pointFormat2); return(MS_FAILURE); /* buffer failed */ } msCopyShape(bufferShape, &tShape); msFreeShape(bufferShape); } #endif else { status = msCopyShape(shape, &tShape); if(status != 0) { free(pointFormat1); free(pointFormat2); return(MS_FAILURE); /* copy failed */ } } /* no big deal to convert from file to image coordinates, but what are the image parameters */ if(projectionString && strcasecmp(projectionString,"image") == 0) { precision = 0; /* if necessary, project the shape to match the map */ if(msProjectionsDiffer(&(layer->projection), &(layer->map->projection))) msProjectShape(&layer->projection, &layer->map->projection, &tShape); switch(tShape.type) { case(MS_SHAPE_POINT): /* no clipping necessary */ break; case(MS_SHAPE_LINE): msClipPolylineRect(&tShape, layer->map->extent); break; case(MS_SHAPE_POLYGON): msClipPolygonRect(&tShape, layer->map->extent); break; default: /* TO DO: need an error message here */ return(MS_FAILURE); break; } msTransformShapeToPixelRound(&tShape, layer->map->extent, layer->map->cellsize); #ifdef USE_GEOS if(buffer != 0 && bufferUnits == MS_PIXELS) { shapeObj *bufferShape=NULL; bufferShape = msGEOSBuffer(&tShape, buffer); if(!bufferShape) { if(!msIsDegenerateShape(&tShape)) /* If shape is degenerate this is expected. */ return(MS_FAILURE); /* buffer failed */ } else { msFreeShape(&tShape); /* avoid memory leak */ msCopyShape(bufferShape, &tShape); msFreeShape(bufferShape); } } #endif } else if(projectionString) { projectionObj projection; msInitProjection(&projection); status = msLoadProjectionString(&projection, projectionString); if(status != MS_SUCCESS) return MS_FAILURE; if(msProjectionsDiffer(&(layer->projection), &projection)) msProjectShape(&layer->projection, &projection, &tShape); } /* TODO: add thinning support here */ /* ** build the coordinate string */ if(strlen(sh) > 0) coords = msStringConcatenate(coords, sh); /* do we need to handle inner/outer rings */ if(tShape.type == MS_SHAPE_POLYGON && strlen(orh) > 0 && strlen(irh) > 0) { int *outers; int firstPart; /* to keep track of inserting part separators before each part after the first */ outers = msGetOuterList( &tShape ); firstPart = 1; /* loop over rings looking for outers*/ for(i=0; i 0)) coords = msStringConcatenate(coords, ps); firstPart = 0; if(strlen(ph) > 0) coords = msStringConcatenate(coords, ph); coords = msStringConcatenate(coords, orh); for(p=0; p 0) coords = msStringConcatenate(coords, pf); } } /* end of loop over outer rings */ free( outers ); } else { /* output without ring formatting */ for(i=0; i 0) coords = msStringConcatenate(coords, ph); for(p=0; p 0) coords = msStringConcatenate(coords, pf); if((i < tShape.numlines-1) && (strlen(ps) > 0)) coords = msStringConcatenate(coords, ps); } } if(strlen(sf) > 0) coords = msStringConcatenate(coords, sf); msFreeShape(&tShape); /* find the end of the tag */ tagEnd = findTagEnd(tagStart); tagEnd++; /* build the complete tag so we can do substitution */ tagLength = tagEnd - tagStart; tag = (char *) msSmallMalloc(tagLength + 1); strlcpy(tag, tagStart, tagLength+1); /* do the replacement */ *line = msReplaceSubstring(*line, tag, coords); /* clean up */ free(tag); tag = NULL; msFreeHashTable(tagArgs); tagArgs=NULL; free(pointFormat1); pointFormat1 = NULL; free(pointFormat2); pointFormat2 = NULL; free(coords); coords = NULL; if((*line)[tagOffset] != '\0') tagStart = findTag(*line+tagOffset+1, "shpxy"); else tagStart = NULL; } return(MS_SUCCESS); } /*! * this function process all metadata * in pszInstr. ht mus contain all corresponding * metadata value. * * this function return a modified pszInstr */ int processMetadata(char** pszInstr, hashTableObj *ht) { /* char *pszNextInstr = pszInstr; */ char *pszEnd, *pszStart; char *pszMetadataTag; const char *pszHashName; const char *pszHashValue; int nLength, nOffset; hashTableObj *metadataArgs = NULL; if(!*pszInstr) { msSetError(MS_WEBERR, "Invalid pointer.", "processMetadata()"); return MS_FAILURE; } /* set position to the begining of metadata tag */ pszStart = findTag(*pszInstr, "metadata"); while (pszStart) { /* get metadata args */ if(getTagArgs("metadata", pszStart, &metadataArgs) != MS_SUCCESS) return MS_FAILURE; pszHashName = msLookupHashTable(metadataArgs, "name"); pszHashValue = msLookupHashTable(ht, pszHashName); nOffset = pszStart - *pszInstr; if(pszHashName && pszHashValue) { /* set position to the end of metadata start tag */ pszEnd = strchr(pszStart, ']'); pszEnd++; /* build the complete metadata tag ([metadata all_args]) */ /* to replace it by the corresponding value from ht */ nLength = pszEnd - pszStart; pszMetadataTag = (char*)msSmallMalloc(nLength + 1); strlcpy(pszMetadataTag, pszStart, nLength+1); *pszInstr = msReplaceSubstring(*pszInstr, pszMetadataTag, pszHashValue); free(pszMetadataTag); pszMetadataTag=NULL; } msFreeHashTable(metadataArgs); metadataArgs=NULL; /* set position to the begining of the next metadata tag */ if((*pszInstr)[nOffset] != '\0') pszStart = findTag(*pszInstr+nOffset+1, "metadata"); else pszStart = NULL; } return MS_SUCCESS; } /*! * this function process all icon tag * from pszInstr. * * This func return a modified pszInstr. */ int processIcon(mapObj *map, int nIdxLayer, int nIdxClass, char** pszInstr, char* pszPrefix) { int nWidth, nHeight, nLen; char szImgFname[1024], *pszFullImgFname=NULL, *pszImgTag; char szPath[MS_MAXPATHLEN]; hashTableObj *myHashTable=NULL; FILE *fIcon; if(!map || nIdxLayer > map->numlayers || nIdxLayer < 0 ) { msSetError(MS_WEBERR, "Invalid pointer.", "processIcon()"); return MS_FAILURE; } /* find the begining of tag */ pszImgTag = strstr(*pszInstr, "[leg_icon"); while (pszImgTag) { int i; char szStyleCode[512] = ""; classObj *thisClass=NULL; /* It's okay to have no classes... we'll generate an empty icon in this case */ if(nIdxClass >= 0 && nIdxClass < GET_LAYER(map, nIdxLayer)->numclasses) thisClass = GET_LAYER(map, nIdxLayer)->class[nIdxClass]; if(getTagArgs("leg_icon", pszImgTag, &myHashTable) != MS_SUCCESS) return MS_FAILURE; /* if no specified width or height, set them to map default */ if(!msLookupHashTable(myHashTable, "width") || !msLookupHashTable(myHashTable, "height")) { nWidth = map->legend.keysizex; nHeight= map->legend.keysizey; } else { nWidth = atoi(msLookupHashTable(myHashTable, "width")); nHeight = atoi(msLookupHashTable(myHashTable, "height")); } /* Create a unique and predictable filename to cache the legend icons. * Include some key parameters from the first 2 styles */ for(i=0; i<2 && thisClass && inumstyles; i++) { styleObj *style; char *pszSymbolNameHash = NULL; style = thisClass->styles[i]; if(style->symbolname) pszSymbolNameHash = msHashString(style->symbolname); snprintf(szStyleCode+strlen(szStyleCode), 255, "s%d_%x_%x_%x_%d_%s_%g", i, MS_COLOR_GETRGB(style->color), MS_COLOR_GETRGB(style->backgroundcolor), MS_COLOR_GETRGB(style->outlinecolor), style->symbol, pszSymbolNameHash?pszSymbolNameHash:"", style->angle); msFree(pszSymbolNameHash); } snprintf(szImgFname, sizeof(szImgFname), "%s_%d_%d_%d_%d_%s.%s%c", pszPrefix, nIdxLayer, nIdxClass, nWidth, nHeight, szStyleCode, MS_IMAGE_EXTENSION(map->outputformat),'\0'); pszFullImgFname = msStrdup(msBuildPath3(szPath, map->mappath, map->web.imagepath, szImgFname)); /* check if icon already exist in cache */ if((fIcon = fopen(pszFullImgFname, "r")) != NULL) { /* File already exists. No need to generate it again */ fclose(fIcon); } else { /* Create an image corresponding to the current class */ imageObj *img=NULL; if(thisClass == NULL) { /* Nonexistent class. Create an empty image */ img = msCreateLegendIcon(map, NULL, NULL, nWidth, nHeight, MS_TRUE); } else { img = msCreateLegendIcon(map, GET_LAYER(map, nIdxLayer), thisClass, nWidth, nHeight, MS_TRUE); } if(!img) { if(myHashTable) msFreeHashTable(myHashTable); msSetError(MS_IMGERR, "Error while creating image.", "processIcon()"); return MS_FAILURE; } /* save it with a unique file name */ if(msSaveImage(map, img, pszFullImgFname) != MS_SUCCESS) { if(myHashTable) msFreeHashTable(myHashTable); msFreeImage(img); msSetError(MS_IOERR, "Error saving GD image to disk (%s).", "processIcon()", pszFullImgFname); msFree(pszFullImgFname); return MS_FAILURE; } msFreeImage(img); } msFree(pszFullImgFname); pszFullImgFname = NULL; nLen = (strchr(pszImgTag, ']') + 1) - pszImgTag; if(nLen > 0) { char *pszTag; /* rebuid image tag ([leg_class_img all_args]) */ /* to replace it by the image url */ pszTag = (char*)msSmallMalloc(nLen + 1); strlcpy(pszTag, pszImgTag, nLen+1); pszFullImgFname = (char*)msSmallMalloc(strlen(map->web.imageurl) + strlen(szImgFname) + 1); strcpy(pszFullImgFname, map->web.imageurl); strcat(pszFullImgFname, szImgFname); *pszInstr = msReplaceSubstring(*pszInstr, pszTag, pszFullImgFname); msFree(pszFullImgFname); pszFullImgFname = NULL; msFree(pszTag); /* find the begining of tag */ pszImgTag = strstr(*pszInstr, "[leg_icon"); } else { pszImgTag = NULL; } if(myHashTable) { msFreeHashTable(myHashTable); myHashTable = NULL; } } return MS_SUCCESS; } /*! * Replace all tags from group template * with correct value. * * this function return a buffer containing * the template with correct values. * * buffer must be freed by caller. */ int generateGroupTemplate(char* pszGroupTemplate, mapObj *map, char* pszGroupName, hashTableObj *oGroupArgs, char **pszTemp, char* pszPrefix) { hashTableObj *myHashTable; char pszStatus[3]; char *pszClassImg; const char *pszOptFlag = NULL; int i, j; int nOptFlag = 15; int bShowGroup; *pszTemp = NULL; if(!pszGroupName || !pszGroupTemplate) { msSetError(MS_WEBERR, "Invalid pointer.", "generateGroupTemplate()"); return MS_FAILURE; } /* * Get the opt_flag is any. */ if(oGroupArgs) pszOptFlag = msLookupHashTable(oGroupArgs, "opt_flag"); if(pszOptFlag) nOptFlag = atoi(pszOptFlag); /* * Check all layers, if one in the group * should be visible, print the group. * (Check for opt_flag) */ bShowGroup = 0; for (j=0; jnumlayers; j++) { if(GET_LAYER(map, map->layerorder[j])->group && strcmp(GET_LAYER(map, map->layerorder[j])->group, pszGroupName) == 0) { /* dont display layer is off. */ if( (nOptFlag & 2) == 0 && GET_LAYER(map, map->layerorder[j])->status == MS_OFF ) bShowGroup = 0; else bShowGroup = 1; /* dont display layer is query. */ if( (nOptFlag & 4) == 0 && GET_LAYER(map, map->layerorder[j])->type == MS_LAYER_QUERY ) bShowGroup = 0; /* dont display layer if out of scale. */ if((nOptFlag & 1) == 0) { if(map->scaledenom > 0) { if((GET_LAYER(map, map->layerorder[j])->maxscaledenom > 0) && (map->scaledenom > GET_LAYER(map, map->layerorder[j])->maxscaledenom)) bShowGroup = 0; if((GET_LAYER(map, map->layerorder[j])->minscaledenom > 0) && (map->scaledenom <= GET_LAYER(map, map->layerorder[j])->minscaledenom)) bShowGroup = 0; } } /* The group contains one visible layer */ /* Draw the group */ if( bShowGroup ) break; } } if( ! bShowGroup ) return MS_SUCCESS; /* * Work from a copy */ *pszTemp = (char*)msSmallMalloc(strlen(pszGroupTemplate) + 1); strcpy(*pszTemp, pszGroupTemplate); /* * Change group tags */ *pszTemp = msReplaceSubstring(*pszTemp, "[leg_group_name]", pszGroupName); /* * Create a hash table that contain info * on current layer */ myHashTable = msCreateHashTable(); /* * Check for the first layer * that belong to this group. * Get his status and check for if. */ for (j=0; jnumlayers; j++) { if(GET_LAYER(map, map->layerorder[j])->group && strcmp(GET_LAYER(map, map->layerorder[j])->group, pszGroupName) == 0) { snprintf(pszStatus, sizeof(pszStatus), "%d", GET_LAYER(map, map->layerorder[j])->status); msInsertHashTable(myHashTable, "layer_status", pszStatus); msInsertHashTable(myHashTable, "layer_visible", msLayerIsVisible(map, GET_LAYER(map, map->layerorder[j]))?"1":"0" ); msInsertHashTable(myHashTable, "layer_queryable", msIsLayerQueryable(GET_LAYER(map, map->layerorder[j]))?"1":"0" ); msInsertHashTable(myHashTable, "group_name", pszGroupName); if(processIfTag(pszTemp, myHashTable, MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(GET_LAYER(map, map->layerorder[j])->metadata), MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processMetadata(pszTemp, &GET_LAYER(map, map->layerorder[j])->metadata) != MS_SUCCESS) return MS_FAILURE; break; } } msFreeHashTable(myHashTable); /* * Process all metadata tags * only web object is accessible */ if(processMetadata(pszTemp, &(map->web.metadata)) != MS_SUCCESS) return MS_FAILURE; /* * check for if tag */ if(processIfTag(pszTemp, &(map->web.metadata), MS_TRUE) != MS_SUCCESS) return MS_FAILURE; /* * Check if leg_icon tag exist * if so display the first layer first class icon */ pszClassImg = strstr(*pszTemp, "[leg_icon"); if(pszClassImg) { /* find first layer of this group */ for (i=0; inumlayers; i++) if(GET_LAYER(map, map->layerorder[i])->group && strcmp(GET_LAYER(map, map->layerorder[i])->group, pszGroupName) == 0) processIcon(map, map->layerorder[i], 0, pszTemp, pszPrefix); } return MS_SUCCESS; } /*! * Replace all tags from layer template * with correct value. * * this function return a buffer containing * the template with correct values. * * buffer must be freed by caller. */ int generateLayerTemplate(char *pszLayerTemplate, mapObj *map, int nIdxLayer, hashTableObj *oLayerArgs, char **pszTemp, char* pszPrefix) { hashTableObj *myHashTable; char szStatus[10]; char szType[10]; int nOptFlag=0; const char *pszOptFlag = NULL; char *pszClassImg; char szTmpstr[128]; /* easily big enough for the couple of instances we need */ *pszTemp = NULL; if(!pszLayerTemplate || !map || nIdxLayer > map->numlayers || nIdxLayer < 0 ) { msSetError(MS_WEBERR, "Invalid pointer.", "generateLayerTemplate()"); return MS_FAILURE; } if(oLayerArgs) pszOptFlag = msLookupHashTable(oLayerArgs, "opt_flag"); if(pszOptFlag) nOptFlag = atoi(pszOptFlag); /* don't display deleted layers */ if(GET_LAYER(map, nIdxLayer)->status == MS_DELETE) return MS_SUCCESS; /* dont display layer is off. */ /* check this if Opt flag is not set */ if((nOptFlag & 2) == 0 && GET_LAYER(map, nIdxLayer)->status == MS_OFF) return MS_SUCCESS; /* dont display layer is query. */ /* check this if Opt flag is not set */ if((nOptFlag & 4) == 0 && GET_LAYER(map, nIdxLayer)->type == MS_LAYER_QUERY) return MS_SUCCESS; /* dont display layer if out of scale. */ /* check this if Opt flag is not set */ if((nOptFlag & 1) == 0) { if(map->scaledenom > 0) { if((GET_LAYER(map, nIdxLayer)->maxscaledenom > 0) && (map->scaledenom > GET_LAYER(map, nIdxLayer)->maxscaledenom)) return MS_SUCCESS; if((GET_LAYER(map, nIdxLayer)->minscaledenom > 0) && (map->scaledenom <= GET_LAYER(map, nIdxLayer)->minscaledenom)) return MS_SUCCESS; } } /* * Work from a copy */ *pszTemp = msStrdup(pszLayerTemplate); /* * Change layer tags */ *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_name]", GET_LAYER(map, nIdxLayer)->name); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_group]", GET_LAYER(map, nIdxLayer)->group); snprintf(szTmpstr, sizeof(szTmpstr), "%d", nIdxLayer); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_index]", szTmpstr); snprintf(szTmpstr, sizeof(szTmpstr), "%g", GET_LAYER(map, nIdxLayer)->minscaledenom); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_minscale]", szTmpstr); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_minscaledenom]", szTmpstr); snprintf(szTmpstr, sizeof(szTmpstr), "%g", GET_LAYER(map, nIdxLayer)->maxscaledenom); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_maxscale]", szTmpstr); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_maxscaledenom]", szTmpstr); /* * Create a hash table that contain info * on current layer */ myHashTable = msCreateHashTable(); /* * for now, only status and type is required by template */ snprintf(szStatus, sizeof(szStatus), "%d", GET_LAYER(map, nIdxLayer)->status); msInsertHashTable(myHashTable, "layer_status", szStatus); snprintf(szType, sizeof(szType), "%d", GET_LAYER(map, nIdxLayer)->type); msInsertHashTable(myHashTable, "layer_type", szType); msInsertHashTable(myHashTable, "layer_name", (GET_LAYER(map, nIdxLayer)->name)? GET_LAYER(map, nIdxLayer)->name : ""); msInsertHashTable(myHashTable, "layer_group", (GET_LAYER(map, nIdxLayer)->group)? GET_LAYER(map, nIdxLayer)->group : ""); msInsertHashTable(myHashTable, "layer_visible", msLayerIsVisible(map, GET_LAYER(map, nIdxLayer))?"1":"0" ); msInsertHashTable(myHashTable, "layer_queryable", msIsLayerQueryable(GET_LAYER(map, nIdxLayer))?"1":"0" ); if(processIfTag(pszTemp, myHashTable, MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(GET_LAYER(map, nIdxLayer)->metadata), MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(map->web.metadata), MS_TRUE) != MS_SUCCESS) return MS_FAILURE; msFreeHashTable(myHashTable); /* * Check if leg_icon tag exist * if so display the first class icon */ pszClassImg = strstr(*pszTemp, "[leg_icon"); if(pszClassImg) { processIcon(map, nIdxLayer, 0, pszTemp, pszPrefix); } /* process all metadata tags * only current layer and web object * metaddata are accessible */ if(processMetadata(pszTemp, &GET_LAYER(map, nIdxLayer)->metadata) != MS_SUCCESS) return MS_FAILURE; if(processMetadata(pszTemp, &(map->web.metadata)) != MS_SUCCESS) return MS_FAILURE; return MS_SUCCESS; } /*! * Replace all tags from class template * with correct value. * * this function return a buffer containing * the template with correct values. * * buffer must be freed by caller. */ int generateClassTemplate(char* pszClassTemplate, mapObj *map, int nIdxLayer, int nIdxClass, hashTableObj *oClassArgs, char **pszTemp, char* pszPrefix) { hashTableObj *myHashTable; char szStatus[10]; char szType[10]; char *pszClassImg; int nOptFlag=0; const char *pszOptFlag = NULL; char szTmpstr[128]; /* easily big enough for the couple of instances we need */ *pszTemp = NULL; if(!pszClassTemplate || !map || nIdxLayer > map->numlayers || nIdxLayer < 0 || nIdxClass > GET_LAYER(map, nIdxLayer)->numclasses || nIdxClass < 0) { msSetError(MS_WEBERR, "Invalid pointer.", "generateClassTemplate()"); return MS_FAILURE; } if(oClassArgs) pszOptFlag = msLookupHashTable(oClassArgs, "Opt_flag"); if(pszOptFlag) nOptFlag = atoi(pszOptFlag); /* don't display deleted layers */ if(GET_LAYER(map, nIdxLayer)->status == MS_DELETE) return MS_SUCCESS; /* dont display class if layer is off. */ /* check this if Opt flag is not set */ if((nOptFlag & 2) == 0 && GET_LAYER(map, nIdxLayer)->status == MS_OFF) return MS_SUCCESS; /* dont display class if layer is query. */ /* check this if Opt flag is not set */ if((nOptFlag & 4) == 0 && GET_LAYER(map, nIdxLayer)->type == MS_LAYER_QUERY) return MS_SUCCESS; /* dont display layer if out of scale. */ /* check this if Opt flag is not set */ if((nOptFlag & 1) == 0) { if(map->scaledenom > 0) { if((GET_LAYER(map, nIdxLayer)->maxscaledenom > 0) && (map->scaledenom > GET_LAYER(map, nIdxLayer)->maxscaledenom)) return MS_SUCCESS; if((GET_LAYER(map, nIdxLayer)->minscaledenom > 0) && (map->scaledenom <= GET_LAYER(map, nIdxLayer)->minscaledenom)) return MS_SUCCESS; } } /* * Work from a copy */ *pszTemp = (char*)msSmallMalloc(strlen(pszClassTemplate) + 1); strcpy(*pszTemp, pszClassTemplate); /* * Change class tags */ *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_name]", GET_LAYER(map, nIdxLayer)->class[nIdxClass]->name); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_title]", GET_LAYER(map, nIdxLayer)->class[nIdxClass]->title); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_layer_name]", GET_LAYER(map, nIdxLayer)->name); snprintf(szTmpstr, sizeof(szTmpstr), "%d", nIdxClass); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_index]", szTmpstr); snprintf(szTmpstr, sizeof(szTmpstr), "%g", GET_LAYER(map, nIdxLayer)->class[nIdxClass]->minscaledenom); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_minscale]", szTmpstr); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_minscaledenom]", szTmpstr); snprintf(szTmpstr, sizeof(szTmpstr), "%g", GET_LAYER(map, nIdxLayer)->class[nIdxClass]->maxscaledenom); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_maxscale]", szTmpstr); *pszTemp = msReplaceSubstring(*pszTemp, "[leg_class_maxscaledenom]", szTmpstr); /* * Create a hash table that contain info * on current layer */ myHashTable = msCreateHashTable(); /* * for now, only status, type, name and group are required by template */ snprintf(szStatus, sizeof(szStatus), "%d", GET_LAYER(map, nIdxLayer)->status); msInsertHashTable(myHashTable, "layer_status", szStatus); snprintf(szType, sizeof(szType), "%d", GET_LAYER(map, nIdxLayer)->type); msInsertHashTable(myHashTable, "layer_type", szType); msInsertHashTable(myHashTable, "layer_name", (GET_LAYER(map, nIdxLayer)->name)? GET_LAYER(map, nIdxLayer)->name : ""); msInsertHashTable(myHashTable, "layer_group", (GET_LAYER(map, nIdxLayer)->group)? GET_LAYER(map, nIdxLayer)->group : ""); msInsertHashTable(myHashTable, "layer_visible", msLayerIsVisible(map, GET_LAYER(map, nIdxLayer))?"1":"0" ); msInsertHashTable(myHashTable, "layer_queryable", msIsLayerQueryable(GET_LAYER(map, nIdxLayer))?"1":"0" ); msInsertHashTable(myHashTable, "class_name", (GET_LAYER(map, nIdxLayer)->class[nIdxClass]->name)? GET_LAYER(map, nIdxLayer)->class[nIdxClass]->name : ""); if(processIfTag(pszTemp, myHashTable, MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(GET_LAYER(map, nIdxLayer)->metadata), MS_FALSE) != MS_SUCCESS) return MS_FAILURE; if(processIfTag(pszTemp, &(map->web.metadata), MS_TRUE) != MS_SUCCESS) return MS_FAILURE; msFreeHashTable(myHashTable); /* * Check if leg_icon tag exist */ pszClassImg = strstr(*pszTemp, "[leg_icon"); if(pszClassImg) { processIcon(map, nIdxLayer, nIdxClass, pszTemp, pszPrefix); } /* process all metadata tags * only current layer and web object * metaddata are accessible */ if(processMetadata(pszTemp, &GET_LAYER(map, nIdxLayer)->metadata) != MS_SUCCESS) return MS_FAILURE; if(processMetadata(pszTemp, &(map->web.metadata)) != MS_SUCCESS) return MS_FAILURE; return MS_SUCCESS; } char *generateLegendTemplate(mapservObj *mapserv) { FILE *stream; char *file = NULL; int length; char *pszResult = NULL; char *legGroupHtml = NULL; char *legLayerHtml = NULL; char *legClassHtml = NULL; char *legLayerHtmlCopy = NULL; char *legClassHtmlCopy = NULL; char *legGroupHtmlCopy = NULL; char *legHeaderHtml = NULL; char *legFooterHtml = NULL; char *pszPrefix = NULL; char *pszMapFname = NULL; struct stat tmpStat; const char *pszOrderMetadata = NULL; const char *pszOrder = NULL; int i,j,k; char **papszGroups = NULL; int nGroupNames = 0; int nLegendOrder = 0; const char *pszOrderValue; hashTableObj *groupArgs = NULL; hashTableObj *layerArgs = NULL; hashTableObj *classArgs = NULL; ms_regex_t re; /* compiled regular expression to be matched */ int *panCurrentDrawingOrder = NULL; char szPath[MS_MAXPATHLEN]; if(ms_regcomp(&re, MS_TEMPLATE_EXPR, MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) { msSetError(MS_IOERR, "Error regcomp.", "generateLegendTemplate()"); return NULL; } if(ms_regexec(&re, mapserv->map->legend.template, 0, NULL, 0) != 0) { /* no match */ msSetError(MS_IOERR, "Invalid template file name.", "generateLegendTemplate()"); ms_regfree(&re); return NULL; } ms_regfree(&re); /* -------------------------------------------------------------------- */ /* Save the current drawing order. The drawing order is reset */ /* at the end of the function. */ /* -------------------------------------------------------------------- */ if(mapserv && mapserv->map && mapserv->map->numlayers > 0) { panCurrentDrawingOrder = (int *)msSmallMalloc(sizeof(int)*mapserv->map->numlayers); for (i=0; imap->numlayers; i++) { if(mapserv->map->layerorder) panCurrentDrawingOrder[i] = mapserv->map->layerorder[i]; else panCurrentDrawingOrder[i] = i; } } /* * build prefix filename * for legend icon creation */ for(i=0; irequest->NumParams; i++) /* find the mapfile parameter first */ if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break; if(i == mapserv->request->NumParams) { if( getenv("MS_MAPFILE")) pszMapFname = msStringConcatenate(pszMapFname, getenv("MS_MAPFILE")); } else { if(getenv(mapserv->request->ParamValues[i])) /* an environment references the actual file to use */ pszMapFname = msStringConcatenate(pszMapFname, getenv(mapserv->request->ParamValues[i])); else pszMapFname = msStringConcatenate(pszMapFname, mapserv->request->ParamValues[i]); } if(pszMapFname) { if(stat(pszMapFname, &tmpStat) != -1) { int nLen; nLen = (mapserv->map->name?strlen(mapserv->map->name):0) + 50; pszPrefix = (char*)msSmallMalloc((nLen+1) * sizeof(char)); snprintf(pszPrefix, nLen, "%s_%ld_%ld", mapserv->map->name, (long) tmpStat.st_size, (long) tmpStat.st_mtime); pszPrefix[nLen] = '\0'; } free(pszMapFname); pszMapFname = NULL; } else { /* -------------------------------------------------------------------- */ /* map file name may not be avaible when the template functions */ /* are called from mapscript. Use the time stamp as prefix. */ /* -------------------------------------------------------------------- */ char pszTime[20]; snprintf(pszTime, sizeof(pszTime), "%ld", (long)time(NULL)); pszPrefix = msStringConcatenate(pszPrefix, pszTime); } /* open template */ if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, mapserv->map->legend.template), "r")) == NULL) { msSetError(MS_IOERR, "Error while opening template file.", "generateLegendTemplate()"); if(pszResult) free(pszResult); pszResult=NULL; goto error; } fseek(stream, 0, SEEK_END); length = ftell(stream); rewind(stream); file = (char*)msSmallMalloc(length + 1); /* * Read all the template file */ IGUR_sizet(fread(file, length, 1, stream)); /* E. Rouault: the below issue is due to opening in "r" mode, which is a * synonymous of "rt" on Windows. In that mode \r\n are turned into \n, * consequently less bytes are written in the output buffer than requested. * A potential fix might be to open in "rb" mode, but is the code ready * to deal with Windows \r\n end of lines ? */ /* Disabled for now due to Windows issue, see ticket #3814 if( 1 != fread(file, length, 1, stream)) { msSetError(MS_IOERR, "Error while reading template file.", "generateLegendTemplate()"); free(file); fclose(stream); return NULL; } */ file[length] = '\0'; if(msValidateContexts(mapserv->map) != MS_SUCCESS) { /* make sure there are no recursive REQUIRES or LABELREQUIRES expressions */ if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* * Seperate header/footer, groups, layers and class */ getInlineTag("leg_header_html", file, &legHeaderHtml); getInlineTag("leg_footer_html", file, &legFooterHtml); getInlineTag("leg_group_html", file, &legGroupHtml); getInlineTag("leg_layer_html", file, &legLayerHtml); getInlineTag("leg_class_html", file, &legClassHtml); /* * Retrieve arguments of all three parts */ if(legGroupHtml) if(getTagArgs("leg_group_html", file, &groupArgs) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } if(legLayerHtml) if(getTagArgs("leg_layer_html", file, &layerArgs) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } if(legClassHtml) if(getTagArgs("leg_class_html", file, &classArgs) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } mapserv->map->cellsize = msAdjustExtent(&(mapserv->map->extent), mapserv->map->width, mapserv->map->height); if(msCalculateScale(mapserv->map->extent, mapserv->map->units, mapserv->map->width, mapserv->map->height, mapserv->map->resolution, &mapserv->map->scaledenom) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* start with the header if present */ if(legHeaderHtml) pszResult = msStringConcatenate(pszResult, legHeaderHtml); /********************************************************************/ /* * order layers if order_metadata args is set * If not, keep default order */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(sortLayerByMetadata(mapserv->map, pszOrderMetadata) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* -------------------------------------------------------------------- */ /* if the order tag is set to ascending or descending, the */ /* current order will be changed to correspond to that. */ /* -------------------------------------------------------------------- */ pszOrder = msLookupHashTable(layerArgs, "order"); if(pszOrder && ((strcasecmp(pszOrder, "ASCENDING") == 0) || (strcasecmp(pszOrder, "DESCENDING") == 0))) { if(sortLayerByOrder(mapserv->map, pszOrder) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } } if(legGroupHtml) { /* retrieve group names */ papszGroups = msGetAllGroupNames(mapserv->map, &nGroupNames); for (i=0; imap, papszGroups[i], groupArgs, &legGroupHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate it to final result */ pszResult = msStringConcatenate(pszResult, legGroupHtmlCopy); /* if(!pszResult) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } */ if(legGroupHtmlCopy) { free(legGroupHtmlCopy); legGroupHtmlCopy = NULL; } /* for all layers in group */ if(legLayerHtml) { for (j=0; jmap->numlayers; j++) { /* * if order_metadata is set and the order * value is less than 0, dont display it */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(pszOrderMetadata) { pszOrderValue = msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->metadata), pszOrderMetadata); if(pszOrderValue) { nLegendOrder = atoi(pszOrderValue); if(nLegendOrder < 0) continue; } } if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].status == 0) { continue; } if(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->group && strcmp(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->group, papszGroups[i]) == 0) { /* process all layer tags */ if(generateLayerTemplate(legLayerHtml, mapserv->map, mapserv->map->layerorder[j], layerArgs, &legLayerHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legLayerHtmlCopy); if(legLayerHtmlCopy) { free(legLayerHtmlCopy); legLayerHtmlCopy = NULL; } /* for all classes in layer */ if(legClassHtml) { for (k=0; kmap, mapserv->map->layerorder[j])->numclasses; k++) { /* process all class tags */ if(!GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->class[k]->name) continue; if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].classhits[k].status == 0) { continue; } if(generateClassTemplate(legClassHtml, mapserv->map, mapserv->map->layerorder[j], k, classArgs, &legClassHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legClassHtmlCopy); if(legClassHtmlCopy) { free(legClassHtmlCopy); legClassHtmlCopy = NULL; } } } } } } else if(legClassHtml) { /* no layer template specified but class and group template */ for (j=0; jmap->numlayers; j++) { /* * if order_metadata is set and the order * value is less than 0, dont display it */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(pszOrderMetadata) { pszOrderValue = msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->metadata), pszOrderMetadata); if(pszOrderValue) { nLegendOrder = atoi(pszOrderValue); if(nLegendOrder < 0) continue; } } if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].status == 0) { continue; } if(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->group && strcmp(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->group, papszGroups[i]) == 0) { /* for all classes in layer */ if(legClassHtml) { for (k=0; kmap, mapserv->map->layerorder[j])->numclasses; k++) { /* process all class tags */ if(!GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->class[k]->name) continue; if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].classhits[k].status == 0) { continue; } if(generateClassTemplate(legClassHtml, mapserv->map, mapserv->map->layerorder[j], k, classArgs, &legClassHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legClassHtmlCopy); if(legClassHtmlCopy) { free(legClassHtmlCopy); legClassHtmlCopy = NULL; } } } } } } } } else { /* if no group template specified */ if(legLayerHtml) { for (j=0; jmap->numlayers; j++) { /* * if order_metadata is set and the order * value is less than 0, dont display it */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(pszOrderMetadata) { pszOrderValue = msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->metadata), pszOrderMetadata); if(pszOrderValue) { nLegendOrder = atoi(pszOrderValue); if(nLegendOrder < 0) continue; } else nLegendOrder=0; } if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].status == 0) { continue; } /* process a layer tags */ if(generateLayerTemplate(legLayerHtml, mapserv->map, mapserv->map->layerorder[j], layerArgs, &legLayerHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legLayerHtmlCopy); if(legLayerHtmlCopy) { free(legLayerHtmlCopy); legLayerHtmlCopy = NULL; } /* for all classes in layer */ if(legClassHtml) { for (k=0; kmap, mapserv->map->layerorder[j])->numclasses; k++) { /* process all class tags */ if(!GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->class[k]->name) continue; if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].classhits[k].status == 0) { continue; } if(generateClassTemplate(legClassHtml, mapserv->map, mapserv->map->layerorder[j], k, classArgs, &legClassHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } /* concatenate to final result */ pszResult = msStringConcatenate(pszResult, legClassHtmlCopy); if(legClassHtmlCopy) { free(legClassHtmlCopy); legClassHtmlCopy = NULL; } } } } } else { /* if no group and layer template specified */ if(legClassHtml) { for (j=0; jmap->numlayers; j++) { /* * if order_metadata is set and the order * value is less than 0, dont display it */ pszOrderMetadata = msLookupHashTable(layerArgs, "order_metadata"); if(pszOrderMetadata) { pszOrderValue = msLookupHashTable(&(GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->metadata), pszOrderMetadata); if(pszOrderValue) { nLegendOrder = atoi(pszOrderValue); if(nLegendOrder < 0) continue; } } if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].status == 0) { continue; } for (k=0; kmap, mapserv->map->layerorder[j])->numclasses; k++) { if(!GET_LAYER(mapserv->map, mapserv->map->layerorder[j])->class[k]->name) continue; if(mapserv->hittest && mapserv->hittest->layerhits[mapserv->map->layerorder[j]].classhits[k].status == 0) { continue; } if(generateClassTemplate(legClassHtml, mapserv->map, mapserv->map->layerorder[j], k, classArgs, &legClassHtmlCopy, pszPrefix) != MS_SUCCESS) { if(pszResult) free(pszResult); pszResult=NULL; goto error; } pszResult = msStringConcatenate(pszResult, legClassHtmlCopy); if(legClassHtmlCopy) { free(legClassHtmlCopy); legClassHtmlCopy = NULL; } } } } } } /* finish with the footer if present */ if(legFooterHtml) pszResult = msStringConcatenate(pszResult, legFooterHtml); /* * if we reach this point, that mean no error was generated. * So check if template is null and initialize it to . */ if(pszResult == NULL) { pszResult = msStringConcatenate(pszResult, " "); } /********************************************************************/ error: if(papszGroups) { for (i=0; imap->layerorder) { for (i=0; imap->numlayers; i++) mapserv->map->layerorder[i] = panCurrentDrawingOrder[i]; free(panCurrentDrawingOrder); } return pszResult; } char *processOneToManyJoin(mapservObj* mapserv, joinObj *join) { int records=MS_FALSE; FILE *stream=NULL; char *outbuf; char line[MS_BUFFER_LENGTH], *tmpline; char szPath[MS_MAXPATHLEN]; if((outbuf = msStrdup("")) == NULL) return(NULL); /* empty at first */ msJoinPrepare(join, &(mapserv->resultshape)); /* execute the join */ while(msJoinNext(join) == MS_SUCCESS) { /* First time through, deal with the header (if necessary) and open the main template. We only */ /* want to do this if there are joined records. */ if(records == MS_FALSE) { if(join->header != NULL) { if(stream) fclose(stream); if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, join->header), "r")) == NULL) { msSetError(MS_IOERR, "Error while opening join header file %s.", "processOneToManyJoin()", join->header); msFree(outbuf); return(NULL); } if(isValidTemplate(stream, join->header) != MS_TRUE) { fclose(stream); msFree(outbuf); return NULL; } /* echo file to the output buffer, no substitutions */ while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) outbuf = msStringConcatenate(outbuf, line); fclose(stream); stream = NULL; } if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, join->template), "r")) == NULL) { msSetError(MS_IOERR, "Error while opening join template file %s.", "processOneToManyJoin()", join->template); msFree(outbuf); return(NULL); } if(isValidTemplate(stream, join->template) != MS_TRUE) { fclose(stream); msFree(outbuf); return NULL; } records = MS_TRUE; } while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) { /* now on to the end of the template */ if(strchr(line, '[') != NULL) { tmpline = processLine(mapserv, line, NULL, QUERY); /* no multiline tags are allowed in a join */ if(!tmpline) { msFree(outbuf); fclose(stream); return NULL; } outbuf = msStringConcatenate(outbuf, tmpline); free(tmpline); } else /* no subs, just echo */ outbuf = msStringConcatenate(outbuf, line); } rewind(stream); IGUR_voidp(fgets(line, MS_BUFFER_LENGTH, stream)); /* skip the first line since it's the magic string */ } /* next record */ if(records==MS_TRUE && join->footer) { if(stream) fclose(stream); if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, join->footer), "r")) == NULL) { msSetError(MS_IOERR, "Error while opening join footer file %s.", "processOneToManyJoin()", join->footer); msFree(outbuf); return(NULL); } if(isValidTemplate(stream, join->footer) != MS_TRUE) { msFree(outbuf); fclose(stream); return NULL; } /* echo file to the output buffer, no substitutions */ while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) outbuf = msStringConcatenate(outbuf, line); fclose(stream); } /* clear any data associated with the join */ msFreeCharArray(join->values, join->numitems); join->values = NULL; return(outbuf); } /* ** Process a single line in the template. A few tags (e.g. [resultset]...[/resultset]) can be multi-line so ** we pass the filehandle to look ahead if necessary. */ static char *processLine(mapservObj *mapserv, char *instr, FILE *stream, int mode) { int i, j; #define PROCESSLINE_BUFLEN 5120 char repstr[PROCESSLINE_BUFLEN], substr[PROCESSLINE_BUFLEN], *outstr; /* repstr = replace string, substr = sub string */ struct hashObj *tp=NULL; char *encodedstr; #ifdef USE_PROJ rectObj llextent; pointObj llpoint; #endif outstr = msStrdup(instr); /* work from a copy */ if(strstr(outstr, "[version]")) outstr = msReplaceSubstring(outstr, "[version]", msGetVersion()); snprintf(repstr, PROCESSLINE_BUFLEN, "%s%s%s.%s", mapserv->map->web.imageurl, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); outstr = msReplaceSubstring(outstr, "[img]", repstr); snprintf(repstr, PROCESSLINE_BUFLEN, "%s%sref%s.%s", mapserv->map->web.imageurl, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); outstr = msReplaceSubstring(outstr, "[ref]", repstr); if(strstr(outstr, "[errmsg")) { char *errmsg = msGetErrorString(";"); if(!errmsg) errmsg = msStrdup("Error message buffer is empty."); /* should never happen, but just in case... */ outstr = msReplaceSubstring(outstr, "[errmsg]", errmsg); encodedstr = msEncodeUrl(errmsg); outstr = msReplaceSubstring(outstr, "[errmsg_esc]", encodedstr); free(errmsg); free(encodedstr); } if(strstr(outstr, "[legend]")) { /* if there's a template legend specified, use it */ if(mapserv->map->legend.template) { char *legendTemplate; legendTemplate = generateLegendTemplate(mapserv); if(legendTemplate) { outstr = msReplaceSubstring(outstr, "[legend]", legendTemplate); free(legendTemplate); } else /* error already generated by (generateLegendTemplate()) */ return NULL; } else { /* if not display gif image with all legend icon */ snprintf(repstr, PROCESSLINE_BUFLEN, "%s%sleg%s.%s", mapserv->map->web.imageurl, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); outstr = msReplaceSubstring(outstr, "[legend]", repstr); } } snprintf(repstr, PROCESSLINE_BUFLEN, "%s%ssb%s.%s", mapserv->map->web.imageurl, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); outstr = msReplaceSubstring(outstr, "[scalebar]", repstr); if(mapserv->savequery) { snprintf(repstr, PROCESSLINE_BUFLEN, "%s%s%s%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_QUERY_EXTENSION); outstr = msReplaceSubstring(outstr, "[queryfile]", repstr); } if(mapserv->savemap) { snprintf(repstr, PROCESSLINE_BUFLEN, "%s%s%s.map", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id); outstr = msReplaceSubstring(outstr, "[map]", repstr); } if(strstr(outstr,"[mapserv_onlineresource]")) { char *ol; #if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR) || defined(USE_WMS_LYR) || defined(USE_WFS_LYR) ol = msOWSGetOnlineResource(mapserv->map, "O", "onlineresource", mapserv->request); #else ol = msBuildOnlineResource(mapserv->map, mapserv->request); #endif outstr = msReplaceSubstring(outstr, "[mapserv_onlineresource]",ol); msFree(ol); } if(getenv("HTTP_HOST")) { snprintf(repstr, PROCESSLINE_BUFLEN, "%s", getenv("HTTP_HOST")); outstr = msReplaceSubstring(outstr, "[host]", repstr); } if(getenv("SERVER_PORT")) { snprintf(repstr, PROCESSLINE_BUFLEN, "%s", getenv("SERVER_PORT")); outstr = msReplaceSubstring(outstr, "[port]", repstr); } snprintf(repstr, PROCESSLINE_BUFLEN, "%s", mapserv->Id); outstr = msReplaceSubstring(outstr, "[id]", repstr); repstr[0] = '\0'; /* Layer list for a "POST" request */ for(i=0; iNumLayers; i++) { strlcat(repstr, mapserv->Layers[i], sizeof(repstr)); strlcat(repstr, " ", sizeof(repstr)); } msStringTrimBlanks(repstr); encodedstr = msEncodeHTMLEntities(repstr); outstr = msReplaceSubstring(outstr, "[layers]", encodedstr); free(encodedstr); encodedstr = msEncodeUrl(repstr); outstr = msReplaceSubstring(outstr, "[layers_esc]", encodedstr); free(encodedstr); strcpy(repstr, ""); /* list of ALL layers that can be toggled */ repstr[0] = '\0'; for(i=0; imap->numlayers; i++) { if(GET_LAYER(mapserv->map, i)->status != MS_DEFAULT && GET_LAYER(mapserv->map, i)->name != NULL) { strlcat(repstr, GET_LAYER(mapserv->map, i)->name, sizeof(repstr)); strlcat(repstr, " ", sizeof(repstr)); } } msStringTrimBlanks(repstr); outstr = msReplaceSubstring(outstr, "[toggle_layers]", repstr); encodedstr = msEncodeUrl(repstr); outstr = msReplaceSubstring(outstr, "[toggle_layers_esc]", encodedstr); free(encodedstr); for(i=0; imap->numlayers; i++) { /* Set form widgets (i.e. checkboxes, radio and select lists), note that default layers don't show up here */ if(isOn(mapserv, GET_LAYER(mapserv->map, i)->name, GET_LAYER(mapserv->map, i)->group) == MS_TRUE) { if(GET_LAYER(mapserv->map, i)->group) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_select]", GET_LAYER(mapserv->map, i)->group); outstr = msReplaceSubstring(outstr, substr, "selected=\"selected\""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_check]", GET_LAYER(mapserv->map, i)->group); outstr = msReplaceSubstring(outstr, substr, "checked=\"checked\""); } if(GET_LAYER(mapserv->map, i)->name) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_select]", GET_LAYER(mapserv->map, i)->name); outstr = msReplaceSubstring(outstr, substr, "selected=\"selected\""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_check]", GET_LAYER(mapserv->map, i)->name); outstr = msReplaceSubstring(outstr, substr, "checked=\"checked\""); } } else { if(GET_LAYER(mapserv->map, i)->group) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_select]", GET_LAYER(mapserv->map, i)->group); outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_check]", GET_LAYER(mapserv->map, i)->group); outstr = msReplaceSubstring(outstr, substr, ""); } if(GET_LAYER(mapserv->map, i)->name) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_select]", GET_LAYER(mapserv->map, i)->name); outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_check]", GET_LAYER(mapserv->map, i)->name); outstr = msReplaceSubstring(outstr, substr, ""); } } } for(i=-1; i<=1; i++) { /* make zoom direction persistant */ if(mapserv->ZoomDirection == i) { snprintf(substr, sizeof(substr), "[zoomdir_%d_select]", i); outstr = msReplaceSubstring(outstr, substr, "selected=\"selected\""); snprintf(substr, sizeof(substr), "[zoomdir_%d_check]", i); outstr = msReplaceSubstring(outstr, substr, "checked=\"checked\""); } else { snprintf(substr, sizeof(substr), "[zoomdir_%d_select]", i); outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, sizeof(substr), "[zoomdir_%d_check]", i); outstr = msReplaceSubstring(outstr, substr, ""); } } for(i=MINZOOM; i<=MAXZOOM; i++) { /* make zoom persistant */ if(mapserv->Zoom == i) { snprintf(substr, sizeof(substr), "[zoom_%d_select]", i); outstr = msReplaceSubstring(outstr, substr, "selected=\"selected\""); snprintf(substr, sizeof(substr), "[zoom_%d_check]", i); outstr = msReplaceSubstring(outstr, substr, "checked=\"checked\""); } else { snprintf(substr, sizeof(substr), "[zoom_%d_select]", i); outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, sizeof(substr), "[zoom_%d_check]", i); outstr = msReplaceSubstring(outstr, substr, ""); } } /* allow web object metadata access in template */ /* * reworked by SG to use HashTable methods */ if(&(mapserv->map->web.metadata) && strstr(outstr, "web_")) { for (j=0; jmap->web.metadata.items[j] != NULL) { for(tp=mapserv->map->web.metadata.items[j]; tp!=NULL; tp=tp->next) { snprintf(substr, PROCESSLINE_BUFLEN, "[web_%s]", tp->key); outstr = msReplaceSubstring(outstr, substr, tp->data); snprintf(substr, PROCESSLINE_BUFLEN, "[web_%s_esc]", tp->key); encodedstr = msEncodeUrl(tp->data); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } } } } /* allow layer metadata access in template */ for(i=0; imap->numlayers; i++) { if(&(GET_LAYER(mapserv->map, i)->metadata) && GET_LAYER(mapserv->map, i)->name && strstr(outstr, GET_LAYER(mapserv->map, i)->name)) { for(j=0; jmap, i)->metadata.items[j] != NULL) { for(tp=GET_LAYER(mapserv->map, i)->metadata.items[j]; tp!=NULL; tp=tp->next) { snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s]", GET_LAYER(mapserv->map, i)->name, tp->key); if(GET_LAYER(mapserv->map, i)->status == MS_ON) outstr = msReplaceSubstring(outstr, substr, tp->data); else outstr = msReplaceSubstring(outstr, substr, ""); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s_esc]", GET_LAYER(mapserv->map, i)->name, tp->key); if(GET_LAYER(mapserv->map, i)->status == MS_ON) { encodedstr = msEncodeUrl(tp->data); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } else outstr = msReplaceSubstring(outstr, substr, ""); } } } } } snprintf(repstr, sizeof(repstr), "%f", mapserv->mappnt.x); outstr = msReplaceSubstring(outstr, "[mapx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->mappnt.y); outstr = msReplaceSubstring(outstr, "[mapy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->extent.minx); /* Individual mapextent elements for spatial query building, deprecated. */ outstr = msReplaceSubstring(outstr, "[minx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->extent.maxx); outstr = msReplaceSubstring(outstr, "[maxx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->extent.miny); outstr = msReplaceSubstring(outstr, "[miny]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->extent.maxy); outstr = msReplaceSubstring(outstr, "[maxy]", repstr); if(processDateTag( &outstr ) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "mapext", &(mapserv->map->extent), &(mapserv->map->projection)) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "mapext_esc", &(mapserv->map->extent), &(mapserv->map->projection)) != MS_SUCCESS) /* depricated */ return(NULL); snprintf(repstr, sizeof(repstr), "%f", (mapserv->map->extent.maxx-mapserv->map->extent.minx)); /* useful for creating cachable extents (i.e. 0 0 dx dy) with legends and scalebars */ outstr = msReplaceSubstring(outstr, "[dx]", repstr); snprintf(repstr, sizeof(repstr), "%f", (mapserv->map->extent.maxy-mapserv->map->extent.miny)); outstr = msReplaceSubstring(outstr, "[dy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->RawExt.minx); /* Individual raw extent elements for spatial query building, deprecated. */ outstr = msReplaceSubstring(outstr, "[rawminx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->RawExt.maxx); outstr = msReplaceSubstring(outstr, "[rawmaxx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->RawExt.miny); outstr = msReplaceSubstring(outstr, "[rawminy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->RawExt.maxy); outstr = msReplaceSubstring(outstr, "[rawmaxy]", repstr); if(processExtentTag(mapserv, &outstr, "rawext", &(mapserv->RawExt), &(mapserv->map->projection)) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "rawext_esc", &(mapserv->RawExt), &(mapserv->map->projection)) != MS_SUCCESS) /* depricated */ return(NULL); #ifdef USE_PROJ if((strstr(outstr, "lat]") || strstr(outstr, "lon]") || strstr(outstr, "lon_esc]")) && mapserv->map->projection.proj != NULL && !pj_is_latlong(mapserv->map->projection.proj) ) { llextent=mapserv->map->extent; llpoint=mapserv->mappnt; msProjectRect(&(mapserv->map->projection), &(mapserv->map->latlon), &llextent); msProjectPoint(&(mapserv->map->projection), &(mapserv->map->latlon), &llpoint); snprintf(repstr, sizeof(repstr), "%f", llpoint.x); outstr = msReplaceSubstring(outstr, "[maplon]", repstr); snprintf(repstr, sizeof(repstr), "%f", llpoint.y); outstr = msReplaceSubstring(outstr, "[maplat]", repstr); snprintf(repstr, sizeof(repstr), "%f", llextent.minx); /* map extent as lat/lon */ outstr = msReplaceSubstring(outstr, "[minlon]", repstr); snprintf(repstr, sizeof(repstr), "%f", llextent.maxx); outstr = msReplaceSubstring(outstr, "[maxlon]", repstr); snprintf(repstr, sizeof(repstr), "%f", llextent.miny); outstr = msReplaceSubstring(outstr, "[minlat]", repstr); snprintf(repstr, sizeof(repstr), "%f", llextent.maxy); outstr = msReplaceSubstring(outstr, "[maxlat]", repstr); if(processExtentTag(mapserv, &outstr, "mapext_latlon", &(llextent), NULL) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "mapext_latlon_esc", &(llextent), NULL) != MS_SUCCESS) /* depricated */ return(NULL); } #endif /* submitted by J.F (bug 1102) */ if(mapserv->map->reference.status == MS_ON) { snprintf(repstr, sizeof(repstr), "%f", mapserv->map->reference.extent.minx); /* Individual reference map extent elements for spatial query building, depricated. */ outstr = msReplaceSubstring(outstr, "[refminx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->reference.extent.maxx); outstr = msReplaceSubstring(outstr, "[refmaxx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->reference.extent.miny); outstr = msReplaceSubstring(outstr, "[refminy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->reference.extent.maxy); outstr = msReplaceSubstring(outstr, "[refmaxy]", repstr); if(processExtentTag(mapserv, &outstr, "refext", &(mapserv->map->reference.extent), &(mapserv->map->projection)) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "refext_esc", &(mapserv->map->reference.extent), &(mapserv->map->projection)) != MS_SUCCESS) /* depricated */ return(NULL); } snprintf(repstr, sizeof(repstr), "%d %d", mapserv->map->width, mapserv->map->height); outstr = msReplaceSubstring(outstr, "[mapsize]", repstr); encodedstr = msEncodeUrl(repstr); outstr = msReplaceSubstring(outstr, "[mapsize_esc]", encodedstr); free(encodedstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->map->width); outstr = msReplaceSubstring(outstr, "[mapwidth]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->map->height); outstr = msReplaceSubstring(outstr, "[mapheight]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->scaledenom); outstr = msReplaceSubstring(outstr, "[scale]", repstr); outstr = msReplaceSubstring(outstr, "[scaledenom]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->map->cellsize); outstr = msReplaceSubstring(outstr, "[cellsize]", repstr); snprintf(repstr, sizeof(repstr), "%.1f %.1f", (mapserv->map->width)/2.0, (mapserv->map->height)/2.0); /* not subtracting 1 from image dimensions (see bug 633) */ outstr = msReplaceSubstring(outstr, "[center]", repstr); snprintf(repstr, sizeof(repstr), "%.1f", (mapserv->map->width)/2.0); outstr = msReplaceSubstring(outstr, "[center_x]", repstr); snprintf(repstr, sizeof(repstr), "%.1f", (mapserv->map->height)/2.0); outstr = msReplaceSubstring(outstr, "[center_y]", repstr); /* These are really for situations with multiple result sets only, but often used in header/footer */ snprintf(repstr, sizeof(repstr), "%d", mapserv->NR); /* total number of results */ outstr = msReplaceSubstring(outstr, "[nr]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->NL); /* total number of layers with results */ outstr = msReplaceSubstring(outstr, "[nl]", repstr); if(mapserv->resultlayer) { if(strstr(outstr, "[items]") != NULL) { char *itemstr=NULL; itemstr = msJoinStrings(mapserv->resultlayer->items, mapserv->resultlayer->numitems, ","); outstr = msReplaceSubstring(outstr, "[items]", itemstr); free(itemstr); } snprintf(repstr, sizeof(repstr), "%d", mapserv->NLR); /* total number of results within this layer */ outstr = msReplaceSubstring(outstr, "[nlr]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->RN); /* sequential (eg. 1..n) result number within all layers */ outstr = msReplaceSubstring(outstr, "[rn]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->LRN); /* sequential (eg. 1..n) result number within this layer */ outstr = msReplaceSubstring(outstr, "[lrn]", repstr); outstr = msReplaceSubstring(outstr, "[cl]", mapserv->resultlayer->name); /* current layer name */ /* if(resultlayer->description) outstr = msReplaceSubstring(outstr, "[cd]", resultlayer->description); */ /* current layer description */ /* allow layer metadata access when there is a current result layer (implicitly a query template) */ if(&(mapserv->resultlayer->metadata) && strstr(outstr, "[metadata_")) { for(i=0; iresultlayer->metadata.items[i] != NULL) { for(tp=mapserv->resultlayer->metadata.items[i]; tp!=NULL; tp=tp->next) { snprintf(substr, PROCESSLINE_BUFLEN, "[metadata_%s]", tp->key); outstr = msReplaceSubstring(outstr, substr, tp->data); snprintf(substr, PROCESSLINE_BUFLEN, "[metadata_%s_esc]", tp->key); encodedstr = msEncodeUrl(tp->data); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } } } } } if(mode != QUERY) { if(processResultSetTag(mapserv, &outstr, stream) != MS_SUCCESS) { msFree(outstr); return(NULL); } } else { /* return shape and/or values */ snprintf(repstr, sizeof(repstr), "%f %f", (mapserv->resultshape.bounds.maxx + mapserv->resultshape.bounds.minx)/2, (mapserv->resultshape.bounds.maxy + mapserv->resultshape.bounds.miny)/2); outstr = msReplaceSubstring(outstr, "[shpmid]", repstr); snprintf(repstr, sizeof(repstr), "%f", (mapserv->resultshape.bounds.maxx + mapserv->resultshape.bounds.minx)/2); outstr = msReplaceSubstring(outstr, "[shpmidx]", repstr); snprintf(repstr, sizeof(repstr), "%f", (mapserv->resultshape.bounds.maxy + mapserv->resultshape.bounds.miny)/2); outstr = msReplaceSubstring(outstr, "[shpmidy]", repstr); if(processExtentTag(mapserv, &outstr, "shpext", &(mapserv->resultshape.bounds), &(mapserv->resultlayer->projection)) != MS_SUCCESS) return(NULL); if(processExtentTag(mapserv, &outstr, "shpext_esc", &(mapserv->resultshape.bounds), &(mapserv->resultlayer->projection)) != MS_SUCCESS) /* depricated */ return(NULL); snprintf(repstr, sizeof(repstr), "%d", mapserv->resultshape.classindex); outstr = msReplaceSubstring(outstr, "[shpclass]", repstr); if(processShpxyTag(mapserv->resultlayer, &outstr, &mapserv->resultshape) != MS_SUCCESS) return(NULL); if(processShplabelTag(mapserv->resultlayer, &outstr, &mapserv->resultshape) != MS_SUCCESS) return(NULL); snprintf(repstr, sizeof(repstr), "%f", mapserv->resultshape.bounds.minx); outstr = msReplaceSubstring(outstr, "[shpminx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->resultshape.bounds.miny); outstr = msReplaceSubstring(outstr, "[shpminy]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->resultshape.bounds.maxx); outstr = msReplaceSubstring(outstr, "[shpmaxx]", repstr); snprintf(repstr, sizeof(repstr), "%f", mapserv->resultshape.bounds.maxy); outstr = msReplaceSubstring(outstr, "[shpmaxy]", repstr); snprintf(repstr, sizeof(repstr), "%ld", mapserv->resultshape.index); outstr = msReplaceSubstring(outstr, "[shpidx]", repstr); snprintf(repstr, sizeof(repstr), "%d", mapserv->resultshape.tileindex); outstr = msReplaceSubstring(outstr, "[tileidx]", repstr); /* return ALL attributes in one delimeted list */ if(strstr(outstr, "[values]") != NULL) { char *valuestr=NULL; valuestr = msJoinStrings(mapserv->resultshape.values, mapserv->resultlayer->numitems, ","); outstr = msReplaceSubstring(outstr, "[values]", valuestr); free(valuestr); } for(i=0; iresultlayer->numitems; i++) { /* by default let's encode attributes for HTML presentation */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s]", mapserv->resultlayer->items[i]); if(strstr(outstr, substr) != NULL) { encodedstr = msEncodeHTMLEntities(mapserv->resultshape.values[i]); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } /* of course you might want to embed that data in URLs */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_esc]", mapserv->resultlayer->items[i]); if(strstr(outstr, substr) != NULL) { encodedstr = msEncodeUrl(mapserv->resultshape.values[i]); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } /* or you might want to access the attributes unaltered */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_raw]", mapserv->resultlayer->items[i]); if(strstr(outstr, substr) != NULL) outstr = msReplaceSubstring(outstr, substr, mapserv->resultshape.values[i]); } if(processItemTag(mapserv->resultlayer, &outstr, &mapserv->resultshape) != MS_SUCCESS) return(NULL); /* handle joins in this next section */ for(i=0; iresultlayer->numjoins; i++) { if(mapserv->resultlayer->joins[i].values) { /* join has data */ for(j=0; jresultlayer->joins[i].numitems; j++) { /* by default let's encode attributes for HTML presentation */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s]", mapserv->resultlayer->joins[i].name, mapserv->resultlayer->joins[i].items[j]); if(strstr(outstr, substr) != NULL) { encodedstr = msEncodeHTMLEntities(mapserv->resultlayer->joins[i].values[j]); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } /* of course you might want to embed that data in URLs */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s_esc]", mapserv->resultlayer->joins[i].name, mapserv->resultlayer->joins[i].items[j]); if(strstr(outstr, substr) != NULL) { encodedstr = msEncodeUrl(mapserv->resultlayer->joins[i].values[j]); outstr = msReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } /* or you might want to access the attributes unaltered */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s_%s_raw]", mapserv->resultlayer->joins[i].name, mapserv->resultlayer->joins[i].items[j]); if(strstr(outstr, substr) != NULL) outstr = msReplaceSubstring(outstr, substr, mapserv->resultlayer->joins[i].values[j]); } } else if(mapserv->resultlayer->joins[i].type == MS_JOIN_ONE_TO_MANY) { /* one-to-many join */ char *joinTemplate=NULL; snprintf(substr, PROCESSLINE_BUFLEN, "[join_%s]", mapserv->resultlayer->joins[i].name); if(strstr(outstr, substr) != NULL) { joinTemplate = processOneToManyJoin(mapserv, &(mapserv->resultlayer->joins[i])); if(joinTemplate) { outstr = msReplaceSubstring(outstr, substr, joinTemplate); free(joinTemplate); } else return NULL; } } } /* next join */ } /* end query mode specific substitutions */ if(processIncludeTag(mapserv, &outstr, stream, mode) != MS_SUCCESS) return(NULL); for(i=0; irequest->NumParams; i++) { /* Replace [variable] tags using values from URL. We cannot offer a * [variable_raw] option here due to the risk of XSS. * * Replacement is case-insensitive. (#4511) */ snprintf(substr, PROCESSLINE_BUFLEN, "[%s]", mapserv->request->ParamNames[i]); encodedstr = msEncodeHTMLEntities(mapserv->request->ParamValues[i]); outstr = msCaseReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); snprintf(substr, PROCESSLINE_BUFLEN, "[%s_esc]", mapserv->request->ParamNames[i]); encodedstr = msEncodeUrl(mapserv->request->ParamValues[i]); outstr = msCaseReplaceSubstring(outstr, substr, encodedstr); free(encodedstr); } return(outstr); } #define MS_TEMPLATE_BUFFER 1024 /* 1k */ int msReturnPage(mapservObj *mapserv, char *html, int mode, char **papszBuffer) { FILE *stream; char line[MS_BUFFER_LENGTH], *tmpline; int nBufferSize = 0; int nCurrentSize = 0; int nExpandBuffer = 0; ms_regex_t re; /* compiled regular expression to be matched */ char szPath[MS_MAXPATHLEN]; if(!html) { msSetError(MS_WEBERR, "No template specified", "msReturnPage()"); return MS_FAILURE; } if(ms_regcomp(&re, MS_TEMPLATE_EXPR, MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) { msSetError(MS_REGEXERR, NULL, "msReturnPage()"); return MS_FAILURE; } if(ms_regexec(&re, html, 0, NULL, 0) != 0) { /* no match */ ms_regfree(&re); msSetError(MS_WEBERR, "Malformed template name (%s).", "msReturnPage()", html); return MS_FAILURE; } ms_regfree(&re); if((stream = fopen(msBuildPath(szPath, mapserv->map->mappath, html), "r")) == NULL) { msSetError(MS_IOERR, "%s", "msReturnPage()", html); return MS_FAILURE; } if(isValidTemplate(stream, html) != MS_TRUE) { fclose(stream); return MS_FAILURE; } if(papszBuffer) { if((*papszBuffer) == NULL) { (*papszBuffer) = (char *)msSmallMalloc(MS_TEMPLATE_BUFFER); (*papszBuffer)[0] = '\0'; nBufferSize = MS_TEMPLATE_BUFFER; nCurrentSize = 0; nExpandBuffer = 1; } else { nCurrentSize = strlen((*papszBuffer)); nBufferSize = nCurrentSize; nExpandBuffer = (nCurrentSize/MS_TEMPLATE_BUFFER) + 1; } } while(fgets(line, MS_BUFFER_LENGTH, stream) != NULL) { /* now on to the end of the file */ if(strchr(line, '[') != NULL) { tmpline = processLine(mapserv, line, stream, mode); if(!tmpline) return MS_FAILURE; if(papszBuffer) { if(nBufferSize <= (int)(nCurrentSize + strlen(tmpline) + 1)) { nExpandBuffer = (strlen(tmpline) / MS_TEMPLATE_BUFFER) + 1; nBufferSize = MS_TEMPLATE_BUFFER*nExpandBuffer + strlen((*papszBuffer)); (*papszBuffer) = (char *) msSmallRealloc((*papszBuffer),sizeof(char)*nBufferSize); } strcat((*papszBuffer), tmpline); nCurrentSize += strlen(tmpline); } else msIO_fwrite(tmpline, strlen(tmpline), 1, stdout); free(tmpline); } else { if(papszBuffer) { if(nBufferSize <= (int)(nCurrentSize + strlen(line))) { nExpandBuffer = (strlen(line) / MS_TEMPLATE_BUFFER) + 1; nBufferSize = MS_TEMPLATE_BUFFER*nExpandBuffer + strlen((*papszBuffer)); (*papszBuffer) = (char *)msSmallRealloc((*papszBuffer),sizeof(char)*nBufferSize); } strcat((*papszBuffer), line); nCurrentSize += strlen(line); } else msIO_fwrite(line, strlen(line), 1, stdout); } if(!papszBuffer) fflush(stdout); } /* next line */ fclose(stream); return MS_SUCCESS; } int msReturnURL(mapservObj* ms, char* url, int mode) { char *tmpurl; if(url == NULL) { msSetError(MS_WEBERR, "Empty URL.", "msReturnURL()"); return MS_FAILURE; } tmpurl = processLine(ms, url, NULL, mode); /* URL templates can't handle multi-line tags, hence the NULL file pointer */ if(!tmpurl) return MS_FAILURE; msRedirect(tmpurl); free(tmpurl); return MS_SUCCESS; } /* ** Legacy query template parsing where you use headers, footers and such... */ int msReturnNestedTemplateQuery(mapservObj* mapserv, char* pszMimeType, char **papszBuffer) { int status; int i,j,k; char buffer[1024]; int nBufferSize =0; int nCurrentSize = 0; int nExpandBuffer = 0; char *template; layerObj *lp=NULL; if(papszBuffer) { (*papszBuffer) = (char *)msSmallMalloc(MS_TEMPLATE_BUFFER); (*papszBuffer)[0] = '\0'; nBufferSize = MS_TEMPLATE_BUFFER; nCurrentSize = 0; nExpandBuffer = 1; } msInitShape(&(mapserv->resultshape)); if((mapserv->Mode == ITEMQUERY) || (mapserv->Mode == QUERY)) { /* may need to handle a URL result set since these modes return exactly 1 result */ for(i=(mapserv->map->numlayers-1); i>=0; i--) { lp = (GET_LAYER(mapserv->map, i)); if(!lp->resultcache) continue; if(lp->resultcache->numresults > 0) break; } if(i >= 0) { /* at least if no result found, mapserver will display an empty template. */ if(lp->resultcache->results[0].classindex >= 0 && lp->class[(int)(lp->resultcache->results[0].classindex)]->template) template = lp->class[(int)(lp->resultcache->results[0].classindex)]->template; else template = lp->template; if( template == NULL ) { msSetError(MS_WEBERR, "No template for layer %s or it's classes.", "msReturnNestedTemplateQuery()", lp->name ); return MS_FAILURE; } if(TEMPLATE_TYPE(template) == MS_URL) { mapserv->resultlayer = lp; #if 0 status = msLayerOpen(lp); if(status != MS_SUCCESS) return status; status = msLayerGetItems(lp); /* retrieve all the item names */ if(status != MS_SUCCESS) return status; #endif status = msLayerGetShape(lp, &(mapserv->resultshape), &(lp->resultcache->results[0])); if(status != MS_SUCCESS) return status; if(lp->numjoins > 0) { for(k=0; knumjoins; k++) { status = msJoinConnect(lp, &(lp->joins[k])); if(status != MS_SUCCESS) return status; msJoinPrepare(&(lp->joins[k]), &(mapserv->resultshape)); msJoinNext(&(lp->joins[k])); /* fetch the first row */ } } if(papszBuffer == NULL) { if(msReturnURL(mapserv, template, QUERY) != MS_SUCCESS) return MS_FAILURE; } msFreeShape(&(mapserv->resultshape)); /* msLayerClose(lp); */ mapserv->resultlayer = NULL; return MS_SUCCESS; } } } /* ** Now we know we're making a template sandwich */ mapserv->NR = mapserv->NL = 0; for(i=0; imap->numlayers; i++) { /* compute some totals */ lp = (GET_LAYER(mapserv->map, i)); if(!lp->resultcache) continue; if(lp->resultcache->numresults > 0) { mapserv->NL++; mapserv->NR += lp->resultcache->numresults; } } /* ** Is this step really necessary for buffered output? Legend and browse templates don't deal with mime-types ** so why should this. Note that new-style templates don't buffer the mime-type either. */ if(papszBuffer && mapserv->sendheaders) { snprintf(buffer, sizeof(buffer), "Content-Type: %s%c%c", pszMimeType, 10, 10); if(nBufferSize <= (int)(nCurrentSize + strlen(buffer) + 1)) { nExpandBuffer++; (*papszBuffer) = (char *)msSmallRealloc((*papszBuffer), MS_TEMPLATE_BUFFER*nExpandBuffer); nBufferSize = MS_TEMPLATE_BUFFER*nExpandBuffer; } strcat((*papszBuffer), buffer); nCurrentSize += strlen(buffer); } else if(mapserv->sendheaders) { msIO_setHeader("Content-Type","%s",pszMimeType); msIO_sendHeaders(); } if(mapserv->map->web.header) { if(msReturnPage(mapserv, mapserv->map->web.header, BROWSE, papszBuffer) != MS_SUCCESS) return MS_FAILURE; } mapserv->RN = 1; /* overall result number */ for(i=0; imap->numlayers; i++) { mapserv->resultlayer = lp = (GET_LAYER(mapserv->map, mapserv->map->layerorder[i])); if(!lp->resultcache) continue; if(lp->resultcache->numresults <= 0) continue; mapserv->NLR = lp->resultcache->numresults; #if 0 status = msLayerOpen(lp); /* open this layer */ if(status != MS_SUCCESS) return status; status = msLayerGetItems(lp); /* retrieve all the item names */ if(status != MS_SUCCESS) return status; #endif if(lp->numjoins > 0) { /* open any necessary JOINs here */ for(k=0; knumjoins; k++) { status = msJoinConnect(lp, &(lp->joins[k])); if(status != MS_SUCCESS) return status; } } if(lp->header) { if(msReturnPage(mapserv, lp->header, BROWSE, papszBuffer) != MS_SUCCESS) return MS_FAILURE; } mapserv->LRN = 1; /* layer result number */ for(j=0; jresultcache->numresults; j++) { status = msLayerGetShape(lp, &(mapserv->resultshape), &(lp->resultcache->results[j])); if(status != MS_SUCCESS) return status; /* prepare any necessary JOINs here (one-to-one only) */ if(lp->numjoins > 0) { for(k=0; knumjoins; k++) { if(lp->joins[k].type == MS_JOIN_ONE_TO_ONE) { msJoinPrepare(&(lp->joins[k]), &(mapserv->resultshape)); msJoinNext(&(lp->joins[k])); /* fetch the first row */ } } } if(lp->resultcache->results[j].classindex >= 0 && lp->class[(int)(lp->resultcache->results[j].classindex)]->template) template = lp->class[(int)(lp->resultcache->results[j].classindex)]->template; else template = lp->template; if(msReturnPage(mapserv, template, QUERY, papszBuffer) != MS_SUCCESS) { msFreeShape(&(mapserv->resultshape)); return MS_FAILURE; } msFreeShape(&(mapserv->resultshape)); /* init too */ mapserv->RN++; /* increment counters */ mapserv->LRN++; } if(lp->footer) { if(msReturnPage(mapserv, lp->footer, BROWSE, papszBuffer) != MS_SUCCESS) return MS_FAILURE; } /* msLayerClose(lp); */ mapserv->resultlayer = NULL; } if(mapserv->map->web.footer) return msReturnPage(mapserv, mapserv->map->web.footer, BROWSE, papszBuffer); return MS_SUCCESS; } int msReturnOpenLayersPage(mapservObj *mapserv) { int i; char *buffer = NULL, *layer = NULL; const char *tmpUrl = NULL; char *openlayersUrl = olUrl; char *projection = NULL; char *format = NULL; /* 2 CGI parameters are used in the template. we need to transform them * to be sure the case match during the template processing. We also * need to search the SRS/CRS parameter to get the projection info. OGC * services version >= 1.3.0 uses CRS rather than SRS */ for( i=0; irequest->NumParams; i++) { if( (strcasecmp(mapserv->request->ParamNames[i], "SRS") == 0) || (strcasecmp(mapserv->request->ParamNames[i], "CRS") == 0) ) { projection = mapserv->request->ParamValues[i]; } else if(strcasecmp(mapserv->request->ParamNames[i], "LAYERS") == 0) { free(mapserv->request->ParamNames[i]); mapserv->request->ParamNames[i] = msStrdup("LAYERS"); } else if(strcasecmp(mapserv->request->ParamNames[i], "VERSION") == 0) { free(mapserv->request->ParamNames[i]); mapserv->request->ParamNames[i] = msStrdup("VERSION"); } } if(mapserv->map->outputformat->mimetype && *mapserv->map->outputformat->mimetype) { format = mapserv->map->outputformat->mimetype; } /* check if the environment variable or config MS_OPENLAYERS_JS_URL is set */ tmpUrl = msGetConfigOption(mapserv->map, "MS_OPENLAYERS_JS_URL"); if (tmpUrl) openlayersUrl = (char*)tmpUrl; else if (getenv("MS_OPENLAYERS_JS_URL")) openlayersUrl = getenv("MS_OPENLAYERS_JS_URL"); if (mapserv->Mode == BROWSE) { msSetError(MS_WMSERR, "At least one layer name required in LAYERS.", "msWMSLoadGetMapParams()"); layer = processLine(mapserv, olLayerMapServerTag, NULL, BROWSE); } else layer = processLine(mapserv, olLayerWMSTag, NULL, BROWSE); buffer = processLine(mapserv, olTemplate, NULL, BROWSE); buffer = msReplaceSubstring(buffer, "[openlayers_js_url]", openlayersUrl); buffer = msReplaceSubstring(buffer, "[openlayers_layer]", layer); if (projection) buffer = msReplaceSubstring(buffer, "[openlayers_projection]", projection); if (format) buffer = msReplaceSubstring(buffer, "[openlayers_format]", format); else buffer = msReplaceSubstring(buffer, "[openlayers_format]", "image/jpeg"); msIO_fwrite(buffer, strlen(buffer), 1, stdout); free(layer); free(buffer); return MS_SUCCESS; } mapservObj *msAllocMapServObj() { mapservObj *mapserv = msSmallMalloc(sizeof(mapservObj)); mapserv->savemap=MS_FALSE; mapserv->savequery=MS_FALSE; /* should the query and/or map be saved */ mapserv->sendheaders = MS_TRUE; mapserv->request = msAllocCgiObj(); mapserv->map=NULL; mapserv->NumLayers=0; /* number of layers specfied by a user */ mapserv->MaxLayers=0; /* allocated size of Layers[] array */ mapserv->Layers = NULL; mapserv->icon = NULL; mapserv->RawExt.minx=-1; mapserv->RawExt.miny=-1; mapserv->RawExt.maxx=-1; mapserv->RawExt.maxy=-1; mapserv->fZoom=1; mapserv->Zoom=1; /* default for browsing */ mapserv->resultlayer=NULL; mapserv->UseShapes=MS_FALSE; mapserv->mappnt.x=-1; mapserv->mappnt.y=-1; mapserv->ZoomDirection=0; /* whether zooming in or out, default is pan or 0 */ mapserv->Mode=BROWSE; /* can be BROWSE, QUERY, etc. */ sprintf(mapserv->Id, "%ld%d", (long)time(NULL), (int)getpid()); mapserv->CoordSource=NONE; mapserv->ScaleDenom=0; mapserv->ImgRows=-1; mapserv->ImgCols=-1; mapserv->ImgExt.minx=-1; mapserv->ImgExt.miny=-1; mapserv->ImgExt.maxx=-1; mapserv->ImgExt.maxy=-1; mapserv->ImgBox.minx=-1; mapserv->ImgBox.miny=-1; mapserv->ImgBox.maxx=-1; mapserv->ImgBox.maxy=-1; mapserv->RefPnt.x=-1; mapserv->RefPnt.y=-1; mapserv->ImgPnt.x=-1; mapserv->ImgPnt.y=-1; mapserv->Buffer=0; /* ** variables for multiple query results processing */ mapserv->RN=0; /* overall result number */ mapserv->LRN=0; /* result number within a layer */ mapserv->NL=0; /* total number of layers with results */ mapserv->NR=0; /* total number or results */ mapserv->NLR=0; /* number of results in a layer */ mapserv->SearchMap=MS_FALSE; /* apply pan/zoom BEFORE doing the query (e.g. query the output image rather than the input image) */ mapserv->QueryFile=NULL; mapserv->QueryLayer=NULL; mapserv->SelectLayer=NULL; mapserv->QueryLayerIndex=-1; mapserv->SelectLayerIndex=-1; mapserv->QueryItem=NULL; mapserv->QueryString=NULL; mapserv->ShapeIndex=-1; mapserv->TileIndex=-1; mapserv->QueryCoordSource=NONE; mapserv->ZoomSize=0; /* zoom absolute magnitude (i.e. > 0) */ mapserv->hittest = NULL; return mapserv; } void msFreeMapServObj(mapservObj* mapserv) { int i; if(mapserv) { if( mapserv->map ) { if(mapserv->hittest) { freeMapHitTests(mapserv->map,mapserv->hittest); free(mapserv->hittest); } msFreeMap(mapserv->map); mapserv->map = NULL; } if( mapserv->request ) { msFreeCgiObj(mapserv->request); mapserv->request = NULL; } for(i=0; iNumLayers; i++) msFree(mapserv->Layers[i]); msFree(mapserv->Layers); msFree(mapserv->icon); msFree(mapserv->QueryItem); msFree(mapserv->QueryString); msFree(mapserv->QueryLayer); msFree(mapserv->SelectLayer); msFree(mapserv->QueryFile); msFree(mapserv); } } /* ** Ensure there is at least one free entry in the Layers array. ** ** This function is safe to use for the initial allocation of the Layers[] ** array as well (i.e. when MaxLayers==0 and Layers==NULL) ** ** Returns MS_SUCCESS/MS_FAILURE */ int msGrowMapservLayers( mapservObj* mapserv ) { /* Do we need to increase the size of Layers[] by MS_LAYER_ALLOCSIZE? */ if(mapserv->NumLayers == mapserv->MaxLayers) { int i; if(mapserv->MaxLayers == 0) { /* initial allocation of array */ mapserv->MaxLayers += MS_LAYER_ALLOCSIZE; mapserv->NumLayers = 0; mapserv->Layers = (char**)msSmallMalloc(mapserv->MaxLayers*sizeof(char*)); } else { /* realloc existing array */ mapserv->MaxLayers += MS_LAYER_ALLOCSIZE; mapserv->Layers = (char**)msSmallRealloc(mapserv->Layers, mapserv->MaxLayers*sizeof(char*)); } if(mapserv->Layers == NULL) { msSetError(MS_MEMERR, "Failed to allocate memory for Layers array.", "msGrowMappservLayers()"); return MS_FAILURE; } for(i=mapserv->NumLayers; iMaxLayers; i++) { mapserv->Layers[i] = NULL; } } return MS_SUCCESS; } /* ** Utility function to generate map, legend, scalebar and reference images. ** ** Parameters: ** - mapserv: mapserv object (used to extract the map object). ** - bQueryMap: if set to TRUE a query map will be created instead of a regular map. ** - bReturnOnError: if set to TRUE, the function will return on the first error, else it will try to generate all the images. */ int msGenerateImages(mapservObj *mapserv, int bQueryMap, int bReturnOnError) { char buffer[1024]; if(mapserv) { /* render the map OR query map */ if((!bQueryMap && mapserv->map->status == MS_ON) || (bQueryMap && mapserv->map->querymap.status == MS_ON)) { imageObj *image = NULL; image = msDrawMap(mapserv->map, bQueryMap); if(image) { snprintf(buffer, sizeof(buffer), "%s%s%s.%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); if(msSaveImage(mapserv->map, image, buffer) != MS_SUCCESS && bReturnOnError) { msFreeImage(image); return MS_FAILURE; } msFreeImage(image); } else if(bReturnOnError) return MS_FAILURE; } /* render the legend */ if(mapserv->map->legend.status == MS_ON) { imageObj *image = NULL; image = msDrawLegend(mapserv->map, MS_FALSE, NULL); if(image) { snprintf(buffer, sizeof(buffer), "%s%sleg%s.%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); if(msSaveImage(mapserv->map, image, buffer) != MS_SUCCESS && bReturnOnError) { msFreeImage(image); return MS_FAILURE; } msFreeImage(image); } else if(bReturnOnError) return MS_FAILURE; } /* render the scalebar */ if(mapserv->map->scalebar.status == MS_ON) { imageObj *image = NULL; image = msDrawScalebar(mapserv->map); if(image) { snprintf(buffer, sizeof(buffer), "%s%ssb%s.%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); if(msSaveImage(mapserv->map, image, buffer) != MS_SUCCESS && bReturnOnError) { msFreeImage(image); return MS_FAILURE; } msFreeImage(image); } else if(bReturnOnError) return MS_FAILURE; } /* render the reference map */ if(mapserv->map->reference.status == MS_ON) { imageObj *image; image = msDrawReferenceMap(mapserv->map); if(image) { snprintf(buffer, sizeof(buffer), "%s%sref%s.%s", mapserv->map->web.imagepath, mapserv->map->name, mapserv->Id, MS_IMAGE_EXTENSION(mapserv->map->outputformat)); if(msSaveImage(mapserv->map, image, buffer) != MS_SUCCESS && bReturnOnError) { msFreeImage(image); return MS_FAILURE; } msFreeImage(image); } else if(bReturnOnError) return MS_FAILURE; } } return MS_SUCCESS; } /* ** Utility function to open a template file, process it and ** and return into a buffer the processed template. Uses the ** template file from the web object. Returns NULL if there is ** an error. */ char *msProcessTemplate(mapObj *map, int bGenerateImages, char **names, char **values, int numentries) { char *pszBuffer = NULL; if(map) { /* Initialize object and set appropriate defaults. */ mapservObj *mapserv = NULL; mapserv = msAllocMapServObj(); mapserv->map = map; mapserv->Mode = BROWSE; if(names && values && numentries > 0) { msFreeCharArray(mapserv->request->ParamNames, mapserv->request->NumParams); msFreeCharArray(mapserv->request->ParamValues, mapserv->request->NumParams); mapserv->request->ParamNames = names; mapserv->request->ParamValues = values; mapserv->request->NumParams = numentries; } /* ** ISSUE/TODO : some of the name/values should be extracted and ** processed (ex imgext, layers, ...) as it is done in function ** loadform. */ if(bGenerateImages) msGenerateImages(mapserv, MS_FALSE, MS_FALSE); /* ** Process the template. ** ** TODO : use web minscaledenom/maxscaledenom depending on the scale. */ if(msReturnPage(mapserv, mapserv->map->web.template, BROWSE, &pszBuffer) != MS_SUCCESS) { msFree(pszBuffer); pszBuffer = NULL; } /* Don't free the map and names and values arrays since they were passed by reference. */ mapserv->map = NULL; mapserv->request->ParamNames = mapserv->request->ParamValues = NULL; mapserv->request->NumParams = 0; msFreeMapServObj(mapserv); } return pszBuffer; } /* ** Utility method to process the legend template. */ char *msProcessLegendTemplate(mapObj *map, char **names, char **values, int numentries) { char *pszOutBuf = NULL; if(map && map->legend.template) { /* Initialize object and set appropriate defaults. */ mapservObj *mapserv = NULL; mapserv = msAllocMapServObj(); mapserv->map = map; mapserv->Mode = BROWSE; if(names && values && numentries > 0) { msFreeCharArray(mapserv->request->ParamNames, mapserv->request->NumParams); msFreeCharArray(mapserv->request->ParamValues, mapserv->request->NumParams); mapserv->request->ParamNames = names; mapserv->request->ParamValues = values; mapserv->request->NumParams = numentries; } pszOutBuf = generateLegendTemplate(mapserv); /* Don't free the map and names and values arrays since they were passed by reference. */ mapserv->map = NULL; mapserv->request->ParamNames = mapserv->request->ParamValues = NULL; mapserv->request->NumParams = 0; msFreeMapServObj(mapserv); } return pszOutBuf; } /* ** Utility function that process a template file(s) used in the ** query and return the processed template(s) in a buffer. */ char *msProcessQueryTemplate(mapObj *map, int bGenerateImages, char **names, char **values, int numentries) { char *pszBuffer = NULL; if(map) { /* Initialize object and set appropriate defaults. */ mapservObj *mapserv = NULL; mapserv = msAllocMapServObj(); mapserv->map = map; mapserv->Mode = QUERY; if(names && values && numentries > 0) { msFreeCharArray(mapserv->request->ParamNames, mapserv->request->NumParams); msFreeCharArray(mapserv->request->ParamValues, mapserv->request->NumParams); mapserv->request->ParamNames = names; mapserv->request->ParamValues = values; mapserv->request->NumParams = numentries; } if(bGenerateImages) msGenerateImages(mapserv, MS_TRUE, MS_FALSE); mapserv->sendheaders = MS_FALSE; msReturnTemplateQuery(mapserv, mapserv->map->web.queryformat, &pszBuffer); mapserv->map = NULL; mapserv->request->ParamNames = mapserv->request->ParamValues = NULL; mapserv->request->NumParams = 0; msFreeMapServObj(mapserv); } return pszBuffer; } mapserver-7.4.3/maptemplate.h000066400000000000000000000141261357574274700162440ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Template processing related declarations. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPTEMPLATE_H #define MAPTEMPLATE_H #include "mapserver.h" #include "maphash.h" #define IDPATTERN "^[0-9A-Za-z]{1,63}$" #define IDSIZE 64 #define TEMPLATE_TYPE(s) (((strncmp("http://", s, 7) == 0) || (strncmp("https://", s, 8) == 0) || (strncmp("ftp://", s, 6)) == 0) ? MS_URL : MS_FILE) #define MAXZOOM 25 #define MINZOOM -25 #define DEFAULT_DATE_FORMAT "%d/%b/%Y:%H:%M:%S %z" enum coordSources {NONE, FROMIMGPNT, FROMIMGBOX, FROMIMGSHAPE, FROMREFPNT, FROMUSERPNT, FROMUSERBOX, FROMUSERSHAPE, FROMBUF, FROMSCALE, FROMTILE}; enum modes {BROWSE, ZOOMIN, ZOOMOUT, MAP, LEGEND, LEGENDICON, REFERENCE, SCALEBAR, COORDINATE, QUERY, NQUERY, ITEMQUERY, ITEMNQUERY, FEATUREQUERY, FEATURENQUERY, ITEMFEATUREQUERY, ITEMFEATURENQUERY, INDEXQUERY, TILE, OWS, WFS, MAPLEGEND, MAPLEGENDICON }; /* struct mapservObj * Global structure used by templates and mapserver CGI interface. * * This structur was created to seperate template functionality * from the main mapserv file. Instead of moving all template * related functions in a new file (maptemplate.c) and change * their signatures to pass all global variables, we created this * structure with all global variables needed by template. */ typedef struct { /* should the query and/or map be saved */ int savemap, savequery; cgiRequestObj *request; int sendheaders; /* should mime-type header be output, default will be MS_TRUE */ mapObj *map; char **Layers; char *icon; /* layer:class combination that defines a legend icon */ int NumLayers; /* number of layers specfied by a use */ int MaxLayers; /* Allocated size of Layers[] array */ layerObj *resultlayer; int UseShapes; /* are results of a query to be used in calculating an extent of some sort */ shapeObj resultshape; rectObj RawExt; pointObj mappnt; double fZoom, Zoom; int ZoomDirection; /* whether zooming in or out, default is pan or 0 */ int Mode; /* can be BROWSE, QUERY, etc. */ int TileMode; /* can be GMAP, VE */ char *TileCoords; /* for GMAP: 0 0 1; for VE: 013021023 */ char Id[IDSIZE]; /* big enough for time + pid */ int CoordSource; double ScaleDenom; /* used to create a map extent around a point */ int ImgRows, ImgCols; rectObj ImgExt; /* Existing image's mapextent */ rectObj ImgBox; pointObj RefPnt; pointObj ImgPnt; double Buffer; int SearchMap; /* apply pan/zoom BEFORE doing the query (e.g. query the output image rather than the input image) */ char *QueryFile; char *QueryLayer; char *SelectLayer; int QueryLayerIndex; int SelectLayerIndex; char *QueryItem; char *QueryString; int ShapeIndex; int TileIndex; int QueryCoordSource; int ZoomSize; /* zoom absolute magnitude (i.e. > 0) */ /* ** variables for multiple query results processing */ int RN; /* overall result number */ int LRN; /* result number within a layer */ int NL; /* total number of layers with results */ int NR; /* total number or results */ int NLR; /* number of results in a layer */ map_hittest *hittest; } mapservObj; /*! \fn msAllocMapServObj * Allocate memory for all variables in strusture * and initiate default values */ MS_DLL_EXPORT mapservObj* msAllocMapServObj(void); /*! \fn msFreeMapServObj * free all variables in structure */ MS_DLL_EXPORT void msFreeMapServObj(mapservObj* msObj); /* For Mapserv.c */ MS_DLL_EXPORT int isOn(mapservObj* msObj, char *name, char *group); MS_DLL_EXPORT int checkWebScale(mapservObj *msObj); MS_DLL_EXPORT int setExtent(mapservObj *msObj); MS_DLL_EXPORT int msReturnPage(mapservObj* msObj, char* , int, char **); MS_DLL_EXPORT int msReturnURL(mapservObj* msObj, char*, int); MS_DLL_EXPORT int msReturnNestedTemplateQuery(mapservObj* msObj, char* pszMimeType, char **papszBuffer); MS_DLL_EXPORT int msReturnTemplateQuery(mapservObj *msObj, char* pszMimeType, char **papszBuffer); MS_DLL_EXPORT int msReturnOpenLayersPage(mapservObj *mapserv); MS_DLL_EXPORT int msRedirect(char* url); MS_DLL_EXPORT char *generateLegendTemplate(mapservObj *msObj); MS_DLL_EXPORT int msGenerateImages(mapservObj *msObj, int bQueryMap, int bReturnOnError); MS_DLL_EXPORT char *msProcessTemplate(mapObj *map, int bGenerateImages, char **names, char **values, int numentries); MS_DLL_EXPORT char *msProcessLegendTemplate(mapObj *map, char **names, char **values, int numentries); MS_DLL_EXPORT char *msProcessQueryTemplate(mapObj *map, int bGenerateImages, char **names, char **values, int numentries); MS_DLL_EXPORT int msGrowMapservLayers( mapservObj* msObj ); #endif mapserver-7.4.3/mapthread.c000066400000000000000000000264321357574274700156760ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: UMN MapServer * Purpose: Support code for abstracting thread issues. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ /****************************************************************************** THREAD-SAFE SUPPORT IN MAPSERVER ================================ If thread safety is enabled the USE_THREAD macro will be defined. Thread API (mapthread.h/c) -------------------------- This API is made available to avoid having dependencies on different thread libraries in lots of places in MapServer. It is intended to provide minimal services required by mapserver and isn't intended to be broadly useful. It should be available for Win32 and pthreads environments. It should be possible to implement for other thread libraries if needed. int msGetThreadId(): Returns the current threads integer id. This can be used for making some information thread specific, as has been done for the global error context in maperror.c. void msAcquireLock(int): Acquires the indicated Mutex. If it is already held by another thread then this thread will block till the other thread releases it. If this thread already holds the mutex then behaviour is undefined. If the mutex id is not valid (not in the range 0 to TLOCK_STATIC_MAX) then results are undefined. void msReleaseLock(int): Releases the indicated mutex. If the lock id is invalid, or if the mutex is not currently held by this thread then results are undefined. It is incredibly important to ensure that any mutex that is acquired is released as soon as possible. Any flow of control that could result in a mutex not being release is going to be a disaster. The mutex numbers are defined in mapthread.h with the TLOCK_* codes. If you need a new mutex, add a #define in mapthread.h for it. Currently there is no "dynamic" mutex allocation, but this could be added. Making Things Thread-safe ------------------------- Generally, to make MapServer thread-safe it is necessary to ensure that different threads aren't read and updating common datastructures at the same time and that all appropriate state be kept thread specific. Generally this will mean: o The previously global error status (errorObj ms_error) is now thread specific. Use msGetErrorObj() to get the current threads error state. o Use of subcomponents that are not thread safe need to be protected by a Mutex (lock). Currently a mutex is used for the entire map file parsing operation (msLoadMap() in mapfile.c) since the yacc parser uses a number of global variables. It is also done with pj_init() from PROJ.4 since this does not appear to be thread safe. It isn't yet clear if pj_transform() is thread safe. It is expected that mutexes will need to be employed in a variety of other places to ensure serialized access to risky functionality. This may apply to sublibraries like GDAL for instance. If a new section that is not thread-safe is identified (and assuming it can't be internally modified to make it thread-safe easily), it is necessary to define a new mutex (#define a TLOCK code in mapthread.h), and then surround the resource with acquire and release lock calls. eg. msAcquireLock( TLOCK_PROJ ); if( !(p->proj = pj_init(p->numargs, p->args)) ) { msReleaseLock( TLOCK_PROJ ); msSetError(MS_PROJERR, pj_strerrno(pj_errno), "msProcessProjection()"); return(-1); } msReleaseLock( TLOCK_PROJ ); It is imperative that any acquired locks be released on all possible control paths or else the MapServer will lock up as other thread try to acquire the lock and block forever. Other Thread-safe Issues ------------------------ Some issues are not easily corrected with Mutexes or other similar mechanisms. The following restrictions currently apply to MapServer when trying to use it in thread-safe mode. Note that failure to adhere to these constraints will not usually generate nice error messages, instead operation will just fail sometimes. 1) It is currently assumed that a mapObj belongs only to one thread at a time. That is, there is no effort to syncronize access to a mapObj itself. 2) Stuff that results in a chdir() call are problematic. In particular, the .map file SHAPEPATH directive should not be used. Use full paths to data files instead. ******************************************************************************/ #include #include "mapserver.h" #include "mapthread.h" #if defined(USE_THREAD) static int thread_debug = 0; static char *lock_names[] = { NULL, "PARSER", "GDAL", "ERROROBJ", "PROJ", "TTF", "POOL", "SDE", "ORACLE", "OWS", "LAYER_VTABLE", "IOCONTEXT", "TMPFILE", "DEBUGOBJ", "OGR", "TIME", "FRIBIDI", "WXS", "GEOS", NULL }; #endif /************************************************************************/ /* ==================================================================== */ /* PTHREADS */ /* ==================================================================== */ /************************************************************************/ #if defined(USE_THREAD) && !defined(_WIN32) #include "pthread.h" static int mutexes_initialized = 0; static pthread_mutex_t mutex_locks[TLOCK_MAX]; /************************************************************************/ /* msThreadInit() */ /************************************************************************/ void msThreadInit() { static pthread_mutex_t core_lock = PTHREAD_MUTEX_INITIALIZER; if( thread_debug ) fprintf( stderr, "msThreadInit() (posix)\n" ); pthread_mutex_lock( &core_lock ); for( ; mutexes_initialized < TLOCK_STATIC_MAX; mutexes_initialized++ ) pthread_mutex_init( mutex_locks + mutexes_initialized, NULL ); pthread_mutex_unlock( &core_lock ); } /************************************************************************/ /* msGetThreadId() */ /************************************************************************/ void* msGetThreadId() { return (void*) pthread_self(); } /************************************************************************/ /* msAcquireLock() */ /************************************************************************/ void msAcquireLock( int nLockId ) { if( mutexes_initialized == 0 ) msThreadInit(); assert( nLockId >= 0 && nLockId < mutexes_initialized ); if( thread_debug ) fprintf( stderr, "msAcquireLock(%d/%s) (posix)\n", nLockId, lock_names[nLockId] ); pthread_mutex_lock( mutex_locks + nLockId ); } /************************************************************************/ /* msReleaseLock() */ /************************************************************************/ void msReleaseLock( int nLockId ) { assert( mutexes_initialized > 0 ); assert( nLockId >= 0 && nLockId < mutexes_initialized ); if( thread_debug ) fprintf( stderr, "msReleaseLock(%d/%s) (posix)\n", nLockId, lock_names[nLockId] ); pthread_mutex_unlock( mutex_locks + nLockId ); } #endif /* defined(USE_THREAD) && !defined(_WIN32) */ /************************************************************************/ /* ==================================================================== */ /* WIN32 THREADS */ /* ==================================================================== */ /************************************************************************/ #if defined(USE_THREAD) && defined(_WIN32) #include static int mutexes_initialized = 0; static HANDLE mutex_locks[TLOCK_MAX]; /************************************************************************/ /* msThreadInit() */ /************************************************************************/ void msThreadInit() { /* static pthread_mutex_t core_lock = PTHREAD_MUTEX_INITIALIZER; */ static HANDLE core_lock = NULL; if( mutexes_initialized >= TLOCK_STATIC_MAX ) return; if( thread_debug ) fprintf( stderr, "msThreadInit() (win32)\n" ); if( core_lock == NULL ) core_lock = CreateMutex( NULL, TRUE, NULL ); else WaitForSingleObject( core_lock, INFINITE ); for( ; mutexes_initialized < TLOCK_STATIC_MAX; mutexes_initialized++ ) mutex_locks[mutexes_initialized] = CreateMutex( NULL, FALSE, NULL ); ReleaseMutex( core_lock ); } /************************************************************************/ /* msGetThreadId() */ /************************************************************************/ void* msGetThreadId() { return GetCurrentThreadId(); } /************************************************************************/ /* msAcquireLock() */ /************************************************************************/ void msAcquireLock( int nLockId ) { if( mutexes_initialized == 0 ) msThreadInit(); assert( nLockId >= 0 && nLockId < mutexes_initialized ); if( thread_debug ) fprintf( stderr, "msAcquireLock(%d/%s) (win32)\n", nLockId, lock_names[nLockId] ); WaitForSingleObject( mutex_locks[nLockId], INFINITE ); } /************************************************************************/ /* msReleaseLock() */ /************************************************************************/ void msReleaseLock( int nLockId ) { assert( mutexes_initialized > 0 ); assert( nLockId >= 0 && nLockId < mutexes_initialized ); if( thread_debug ) fprintf( stderr, "msReleaseLock(%d/%s) (win32)\n", nLockId, lock_names[nLockId] ); ReleaseMutex( mutex_locks[nLockId] ); } #endif /* defined(USE_THREAD) && defined(_WIN32) */ mapserver-7.4.3/mapthread.h000066400000000000000000000050601357574274700156750ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Multithreading / locking related declarations. * Author: Frank Warmerdam * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPTHREAD_H #define MAPTHREAD_H #ifdef __cplusplus extern "C" { #endif #ifdef USE_THREAD void msThreadInit(void); void* msGetThreadId(void); void msAcquireLock(int); void msReleaseLock(int); #else #define msThreadInit() #define msGetThreadId() (0) #define msAcquireLock(x) #define msReleaseLock(x) #endif /* ** lock ids - note there is a corresponding lock_names[] array in ** mapthread.c that needs to be extended when new ids are added. */ #define TLOCK_PARSER 1 #define TLOCK_GDAL 2 #define TLOCK_ERROROBJ 3 #define TLOCK_PROJ 4 #define TLOCK_TTF 5 #define TLOCK_POOL 6 #define TLOCK_SDE 7 #define TLOCK_ORACLE 8 #define TLOCK_OWS 9 #define TLOCK_LAYER_VTABLE 10 #define TLOCK_IOCONTEXT 11 #define TLOCK_TMPFILE 12 #define TLOCK_DEBUGOBJ 13 #define TLOCK_OGR 14 #define TLOCK_TIME 15 #define TLOCK_FRIBIDI 16 #define TLOCK_WxS 17 #define TLOCK_GEOS 18 #define TLOCK_STATIC_MAX 20 #define TLOCK_MAX 100 #ifdef __cplusplus } #endif #endif /* MAPTHREAD_H */ mapserver-7.4.3/maptile.c000066400000000000000000000416531357574274700153660ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapServer Tile Access API * Author: Paul Ramsey * ****************************************************************************** * Copyright (c) 2008, Paul Ramsey * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "maptile.h" #include "mapproject.h" #ifdef USE_TILE_API static void msTileResetMetatileLevel(mapObj *map) { hashTableObj *meta = &(map->web.metadata); const char *zero = "0"; const char *value = NULL; /* Is the tile_metatile_levetl set... */ if((value = msLookupHashTable(meta, "tile_metatile_level")) != NULL) { msRemoveHashTable(meta, "tile_metatile_level"); msInsertHashTable(meta, "tile_metatile_level", zero); } /* No tile_metatile_level value. */ else { msInsertHashTable(meta, "tile_metatile_level", zero); } } #endif /************************************************************************ * msTileGetGMapCoords * ************************************************************************/ static int msTileGetGMapCoords(const char *coordstring, int *x, int *y, int *zoom) { int num_coords = 0; char **coords = NULL; if( coordstring ) { coords = msStringSplit(coordstring, ' ', &(num_coords)); if( num_coords != 3 ) { msFreeCharArray(coords, num_coords); msSetError(MS_WEBERR, "Invalid number of tile coordinates (should be three).", "msTileSetup()"); return MS_FAILURE; } } else { msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()"); return MS_FAILURE; } if( x ) *x = strtol(coords[0], NULL, 10); if( y ) *y = strtol(coords[1], NULL, 10); if( zoom ) *zoom = strtol(coords[2], NULL, 10); msFreeCharArray(coords, 3); return MS_SUCCESS; } /************************************************************************ * msTileSetParams * ************************************************************************/ static void msTileGetParams(mapObj *map, tileParams *params) { const char *value = NULL; hashTableObj *meta = &(map->web.metadata); params->tile_size = SPHEREMERC_IMAGE_SIZE; /* Check for tile buffer, set to buffer==0 as default */ if((value = msLookupHashTable(meta, "tile_map_edge_buffer")) != NULL) { params->map_edge_buffer = atoi(value); if(map->debug) msDebug("msTileSetParams(): tile_map_edge_buffer = %d\n", params->map_edge_buffer); } else params->map_edge_buffer = 0; /* Check for metatile size, set to tile==metatile as default */ if((value = msLookupHashTable(meta, "tile_metatile_level")) != NULL) { params->metatile_level = atoi(value); /* Quietly force metatile_level to be sane */ if( params->metatile_level < 0 ) params->metatile_level = 0; if( params->metatile_level > 2 ) params->metatile_level = 2; if(map->debug) msDebug("msTileSetParams(): tile_metatile_level = %d\n", params->metatile_level); } else params->metatile_level = 0; } /************************************************************************ * msTileExtractSubTile * * * ************************************************************************/ static imageObj* msTileExtractSubTile(const mapservObj *msObj, const imageObj *img) { int width, mini, minj; int zoom = 2; imageObj* imgOut = NULL; tileParams params; rendererVTableObj *renderer; rasterBufferObj imgBuffer; if( !MS_RENDERER_PLUGIN(msObj->map->outputformat) || msObj->map->outputformat->renderer != img->format->renderer || ! MS_MAP_RENDERER(msObj->map)->supports_pixel_buffer ) { msSetError(MS_MISCERR,"unsupported or mixed renderers","msTileExtractSubTile()"); return NULL; } renderer = MS_MAP_RENDERER(msObj->map); if (renderer->getRasterBufferHandle((imageObj*)img,&imgBuffer) != MS_SUCCESS) { return NULL; } /* ** Load the metatiling information from the map file. */ msTileGetParams(msObj->map, ¶ms); /* ** Initialize values for the metatile clip area. */ width = img->width - 2*params.map_edge_buffer; mini = params.map_edge_buffer; minj = params.map_edge_buffer; if( msObj->TileMode == TILE_GMAP ) { int x, y, zoom; if( msObj->TileCoords ) { if( msTileGetGMapCoords(msObj->TileCoords, &x, &y, &zoom) == MS_FAILURE ) return NULL; } else { msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()"); return NULL; } if(msObj->map->debug) msDebug("msTileExtractSubTile(): gmaps coords (x: %d, y: %d)\n",x,y); /* ** The bottom N bits of the coordinates give us the subtile ** location relative to the metatile. */ x = (0xffff ^ (0xffff << params.metatile_level)) & x; y = (0xffff ^ (0xffff << params.metatile_level)) & y; if(msObj->map->debug) msDebug("msTileExtractSubTile(): gmaps image coords (x: %d, y: %d)\n",x,y); mini = mini + x * params.tile_size; minj = minj + y * params.tile_size; } else if( msObj->TileMode == TILE_VE ) { int tsize; int i = 0; char j = 0; if( (int)strlen( msObj->TileCoords ) - params.metatile_level < 0 ) { return(NULL); } /* ** Process the last elements of the VE coordinate string to place the ** requested tile in the context of the metatile */ for( i = strlen( msObj->TileCoords ) - params.metatile_level; i < strlen( msObj->TileCoords ); i++ ) { j = msObj->TileCoords[i]; tsize = width / zoom; if( j == '1' || j == '3' ) mini += tsize; if( j == '2' || j == '3' ) minj += tsize; zoom *= 2; } } else { return(NULL); /* Huh? Should have a mode. */ } imgOut = msImageCreate(params.tile_size, params.tile_size, msObj->map->outputformat, NULL, NULL, msObj->map->resolution, msObj->map->defresolution, NULL); if( imgOut == NULL ) { return NULL; } if(msObj->map->debug) msDebug("msTileExtractSubTile(): extracting (%d x %d) tile, top corner (%d, %d)\n",params.tile_size,params.tile_size,mini,minj); if(UNLIKELY(MS_FAILURE == renderer->mergeRasterBuffer(imgOut,&imgBuffer,1.0,mini, minj,0, 0,params.tile_size, params.tile_size))) { msFreeImage(imgOut); return NULL; } return imgOut; } /************************************************************************ * msTileSetup * * * * Called from mapserv.c, this is where the fun begins * * Set up projections and test the parameters for legality. * ************************************************************************/ int msTileSetup(mapservObj* msObj) { #ifdef USE_TILE_API char *outProjStr = NULL; tileParams params; /* ** Load the metatiling information from the map file. */ msTileGetParams(msObj->map, ¶ms); /* ** Ensure all the LAYERs have a projection. */ if( msMapSetLayerProjections(msObj->map) != 0 ) { return(MS_FAILURE); } /* ** Set the projection string for this mode. */ if( msObj->TileMode == TILE_GMAP || msObj->TileMode == TILE_VE ) { outProjStr = SPHEREMERC_PROJ4; } else { return MS_FAILURE; /* Huh? No mode? */ } if( msLoadProjectionString(&(msObj->map->projection), outProjStr) != 0 ) { msSetError(MS_CGIERR, "Unable to load projection string.", "msTileSetup()"); return MS_FAILURE; } /* ** Set up the output extents for this tilemode and tile coordinates */ if( msObj->TileMode == TILE_GMAP ) { int x, y, zoom; double zoomfactor; if( msObj->TileCoords ) { if( msTileGetGMapCoords(msObj->TileCoords, &x, &y, &zoom) == MS_FAILURE ) return MS_FAILURE; } else { msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()"); return MS_FAILURE; } if( params.metatile_level >= zoom ) { msTileResetMetatileLevel(msObj->map); } zoomfactor = pow(2.0, (double)zoom); /* ** Check the input request for sanity. */ if( x >= zoomfactor || y >= zoomfactor ) { msSetError(MS_CGIERR, "GMap tile coordinates are too large for supplied zoom.", "msTileSetup()"); return(MS_FAILURE); } if( x < 0 || y < 0 ) { msSetError(MS_CGIERR, "GMap tile coordinates should not be less than zero.", "msTileSetup()"); return(MS_FAILURE); } } else if ( msObj->TileMode == TILE_VE ) { if( strspn( msObj->TileCoords, "0123" ) < strlen( msObj->TileCoords ) ) { msSetError(MS_CGIERR, "VE tile name should only include characters 0, 1, 2 and 3.", "msTileSetup()"); return(MS_FAILURE); } if( params.metatile_level >= strlen(msObj->TileCoords) ) { msTileResetMetatileLevel(msObj->map); } } else { return(MS_FAILURE); /* Huh? Should have a mode. */ } return MS_SUCCESS; #else msSetError(MS_CGIERR, "Tile API is not available.", "msTileSetup()"); return(MS_FAILURE); #endif } /************************************************************************ * msTileSetExtent * * * * Based on the input parameters, set the output extent for this * * tile. * ************************************************************************/ int msTileSetExtent(mapservObj* msObj) { #ifdef USE_TILE_API mapObj *map = msObj->map; double dx, dy, buffer; tileParams params; /* Read the tile-mode map file parameters */ msTileGetParams(msObj->map, ¶ms); if( msObj->TileMode == TILE_GMAP ) { int x, y, zoom; double zoomfactor, tilesize, xmin, xmax, ymin, ymax; if( msObj->TileCoords ) { if( msTileGetGMapCoords(msObj->TileCoords, &x, &y, &zoom) == MS_FAILURE ) return MS_FAILURE; } else { msSetError(MS_WEBERR, "Tile parameter not set.", "msTileSetup()"); return MS_FAILURE; } if(map->debug) msDebug("msTileSetExtent(): gmaps coords (x: %d, y: %d, z: %d)\n",x,y,zoom); /* ** If we are metatiling, adjust the zoom level appropriately, ** then scale back the x/y coordinates to match the new level. */ if( params.metatile_level > 0 ) { zoom = zoom - params.metatile_level; x = x >> params.metatile_level; y = y >> params.metatile_level; } if(map->debug) msDebug("msTileSetExtent(): gmaps metacoords (x: %d, y: %d, z: %d)\n",x,y,zoom); zoomfactor = pow(2.0, (double)zoom); /* ** Calculate the ground extents of the tile request. */ /* printf("X: %i Y: %i Z: %i\n",x,y,zoom); */ tilesize = SPHEREMERC_GROUND_SIZE / zoomfactor; xmin = (x * tilesize) - (SPHEREMERC_GROUND_SIZE / 2.0); xmax = ((x + 1) * tilesize) - (SPHEREMERC_GROUND_SIZE / 2.0); ymin = (SPHEREMERC_GROUND_SIZE / 2.0) - ((y + 1) * tilesize); ymax = (SPHEREMERC_GROUND_SIZE / 2.0) - (y * tilesize); map->extent.minx = xmin; map->extent.maxx = xmax; map->extent.miny = ymin; map->extent.maxy = ymax; } else if( msObj->TileMode == TILE_VE ) { double minx = SPHEREMERC_GROUND_SIZE / -2.0; double miny = SPHEREMERC_GROUND_SIZE / -2.0; double maxx = SPHEREMERC_GROUND_SIZE / 2.0; double maxy = SPHEREMERC_GROUND_SIZE / 2.0; double zoom = 2.0; double tsize; int i = 0; char j = 0; /* ** Walk down the VE URL string, adjusting the extent each time. ** For meta-tiling cases, we stop early, to draw a larger image. */ for( i = 0; i < strlen( msObj->TileCoords ) - params.metatile_level; i++ ) { j = msObj->TileCoords[i]; tsize = SPHEREMERC_GROUND_SIZE / zoom; if( j == '1' || j == '3' ) minx += tsize; if( j == '0' || j == '2' ) maxx -= tsize; if( j == '2' || j == '3' ) maxy -= tsize; if( j == '0' || j == '1' ) miny += tsize; zoom *= 2.0; } map->extent.minx = minx; map->extent.maxx = maxx; map->extent.miny = miny; map->extent.maxy = maxy; } else { return(MS_FAILURE); /* Huh? Should have a mode. */ } /* ** Set the output tile size. */ msObj->ImgCols = SPHEREMERC_IMAGE_SIZE << params.metatile_level; msObj->ImgRows = SPHEREMERC_IMAGE_SIZE << params.metatile_level; map->width = SPHEREMERC_IMAGE_SIZE << params.metatile_level; map->height = SPHEREMERC_IMAGE_SIZE << params.metatile_level; if(map->debug) msDebug("msTileSetExtent(): base image size (%d x %d)\n",map->width,map->height); /* ** Add the gutters ** First calculate ground units in the buffer at current extent */ buffer = params.map_edge_buffer * (map->extent.maxx - map->extent.minx) / (double)map->width; /* ** Then adjust the map extents out by that amount */ map->extent.minx -= buffer; map->extent.maxx += buffer; map->extent.miny -= buffer; map->extent.maxy += buffer; /* ** Finally adjust the map image size by the pixel buffer */ map->width += 2 * params.map_edge_buffer; map->height += 2 * params.map_edge_buffer; msObj->ImgCols += 2 * params.map_edge_buffer; msObj->ImgRows += 2 * params.map_edge_buffer; if(map->debug) msDebug("msTileSetExtent(): buffered image size (%d x %d)\n",map->width,map->height); /* ** Adjust the extents inwards by 1/2 pixel so they are from ** center-of-pixel to center-of-pixel, instead of edge-to-edge. ** This is the way mapserver does it. */ dx = (map->extent.maxx - map->extent.minx) / map->width; map->extent.minx += dx*0.5; map->extent.maxx -= dx*0.5; dy = (map->extent.maxy - map->extent.miny) / map->height; map->extent.miny += dy*0.5; map->extent.maxy -= dy*0.5; /* ** Ensure the labelcache buffer is greater than the tile buffer. */ if( params.map_edge_buffer > 0 ) { const char *value; hashTableObj *meta = &(map->web.metadata); char tilebufferstr[64]; /* Write the tile buffer to a string */ snprintf(tilebufferstr, sizeof(tilebufferstr), "-%d", params.map_edge_buffer); /* Hm, the labelcache buffer is set... */ if((value = msLookupHashTable(meta, "labelcache_map_edge_buffer")) != NULL) { /* If it's too small, replace with a bigger one */ if( params.map_edge_buffer > abs(atoi(value)) ) { msRemoveHashTable(meta, "labelcache_map_edge_buffer"); msInsertHashTable(meta, "labelcache_map_edge_buffer", tilebufferstr); } } /* No labelcache buffer value? Then we use the tile buffer. */ else { msInsertHashTable(meta, "labelcache_map_edge_buffer", tilebufferstr); } } if(map->debug) { msDebug( "msTileSetExtent (%f, %f) (%f, %f)\n", map->extent.minx, map->extent.miny, map->extent.maxx, map->extent.maxy); } return MS_SUCCESS; #else msSetError(MS_CGIERR, "Tile API is not available.", "msTileSetExtent()"); return(MS_FAILURE); #endif } /************************************************************************ * msDrawTile * * * * Draw the tile once with gutters, metatiling and buffers, then * * clip out the final tile. * * WARNING: Call msTileSetExtent() first or this will be a pointless * * fucnction call. * ************************************************************************/ imageObj* msTileDraw(mapservObj *msObj) { imageObj *img; tileParams params; msTileGetParams(msObj->map, ¶ms); img = msDrawMap(msObj->map, MS_FALSE); if( img == NULL ) return NULL; if( params.metatile_level > 0 || params.map_edge_buffer > 0 ) { imageObj *tmp = msTileExtractSubTile(msObj, img); msFreeImage(img); if( tmp == NULL ) return NULL; img = tmp; } return img; } mapserver-7.4.3/maptile.h000066400000000000000000000043071357574274700153660ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: MapServer Tile Access API * Author: Paul Ramsey * ****************************************************************************** * Copyright (c) 2008, Paul Ramsey * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "maptemplate.h" #ifdef USE_PROJ #define USE_TILE_API 1 #endif #define SPHEREMERC_PROJ4 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +units=m +k=1.0 +nadgrids=@null" #define SPHEREMERC_GROUND_SIZE (20037508.34*2) #define SPHEREMERC_IMAGE_SIZE 0x0100 enum tileModes { TILE_GMAP, TILE_VE }; MS_DLL_EXPORT int msTileSetup(mapservObj *msObj); MS_DLL_EXPORT int msTileSetExtent(mapservObj *msObj); MS_DLL_EXPORT int msTileSetProjections(mapObj *map); MS_DLL_EXPORT imageObj* msTileDraw(mapservObj *msObj); typedef struct { int metatile_level; /* In zoom levels above tile request: best bet is 0, 1 or 2 */ int tile_size; /* In pixels */ int map_edge_buffer; /* In pixels */ } tileParams; mapserver-7.4.3/maptime.c000066400000000000000000000360251357574274700153640ustar00rootroot00000000000000/****************************************************************************** * $id$ * * Project: MapServer * Purpose: Date/Time utility functions. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #define _GNU_SOURCE /* glibc2 needs this for strptime() */ #include #include #include #include "mapserver.h" #include "maptime.h" #include "maperror.h" #include "mapthread.h" typedef struct { char pattern[64]; ms_regex_t *regex; char format[32]; char userformat[32]; MS_TIME_RESOLUTION resolution; } timeFormatObj; #define MS_NUMTIMEFORMATS 13 timeFormatObj ms_timeFormats[MS_NUMTIMEFORMATS] = { {"^[0-9]{8}", NULL, "%Y%m%d","YYYYMMDD",TIME_RESOLUTION_DAY}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z", NULL, "%Y-%m-%dT%H:%M:%SZ","YYYY-MM-DDTHH:MM:SSZ",TIME_RESOLUTION_SECOND}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}", NULL, "%Y-%m-%dT%H:%M:%S", "YYYY-MM-DDTHH:MM:SS",TIME_RESOLUTION_SECOND}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}", NULL, "%Y-%m-%d %H:%M:%S", "YYYY-MM-DD HH:MM:SS", TIME_RESOLUTION_SECOND}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}", NULL, "%Y-%m-%dT%H:%M", "YYYY-MM-DDTHH:MM",TIME_RESOLUTION_MINUTE}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}", NULL, "%Y-%m-%d %H:%M", "YYYY-MM-DD HH:MM",TIME_RESOLUTION_MINUTE}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}", NULL, "%Y-%m-%dT%H", "YYYY-MM-DDTHH",TIME_RESOLUTION_HOUR}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}", NULL, "%Y-%m-%d %H", "YYYY-MM-DD HH",TIME_RESOLUTION_HOUR}, {"^[0-9]{4}-[0-9]{2}-[0-9]{2}", NULL, "%Y-%m-%d", "YYYY-MM-DD", TIME_RESOLUTION_DAY}, {"^[0-9]{4}-[0-9]{2}", NULL, "%Y-%m", "YYYY-MM",TIME_RESOLUTION_MONTH}, {"^[0-9]{4}", NULL, "%Y", "YYYY",TIME_RESOLUTION_YEAR}, {"^T[0-9]{2}:[0-9]{2}:[0-9]{2}Z", NULL, "T%H:%M:%SZ", "THH:MM:SSZ",TIME_RESOLUTION_SECOND}, {"^T[0-9]{2}:[0-9]{2}:[0-9]{2}", NULL, "T%H:%M:%S", "THH:MM:SS", TIME_RESOLUTION_SECOND} }; int *ms_limited_pattern = NULL; int ms_num_limited_pattern; int ms_time_inited = 0; int msTimeSetup() { if(!ms_time_inited) { msAcquireLock(TLOCK_TIME); if(!ms_time_inited) { int i; for(i=0;itm_sec = 0; /* set all members to zero */ time->tm_min = 0; time->tm_hour = 0; time->tm_mday = 0; time->tm_mon = 0; time->tm_year = 0; time->tm_wday = 0; time->tm_yday = 0; time->tm_isdst = 0; return; } static int compareIntVals(int a, int b) { if(ab) return 1; else return 0; } int msDateCompare(struct tm *time1, struct tm *time2) { int result; if((result = compareIntVals(time1->tm_year, time2->tm_year)) != 0) return result; /* not equal based on year */ else if((result = compareIntVals(time1->tm_mon, time2->tm_mon)) != 0) return result; /* not equal based on month */ else if((result = compareIntVals(time1->tm_mday, time2->tm_mday)) != 0) return result; /* not equal based on day of month */ return(0); /* must be equal */ } int msTimeCompare(struct tm *time1, struct tm *time2) { int result; // fprintf(stderr, "in msTimeCompare()...\n"); // fprintf(stderr, "time1: %d %d %d %d %d %d\n", time1->tm_year, time1->tm_mon, time1->tm_mday, time1->tm_hour, time1->tm_min, time1->tm_sec); // fprintf(stderr, "time2: %d %d %d %d %d %d\n", time2->tm_year, time2->tm_mon, time2->tm_mday, time2->tm_hour, time2->tm_min, time2->tm_sec); if((result = compareIntVals(time1->tm_year, time2->tm_year)) != 0) return result; /* not equal based on year */ else if((result = compareIntVals(time1->tm_mon, time2->tm_mon)) != 0) return result; /* not equal based on month */ else if((result = compareIntVals(time1->tm_mday, time2->tm_mday)) != 0) return result; /* not equal based on day of month */ else if((result = compareIntVals(time1->tm_hour, time2->tm_hour)) != 0) return result; /* not equal based on hour */ else if((result = compareIntVals(time1->tm_min, time2->tm_min)) != 0) return result; /* not equal based on minute */ else if((result = compareIntVals(time1->tm_sec, time2->tm_sec)) != 0) return result; /* not equal based on second */ return(0); /* must be equal */ } #if defined(_WIN32) && !defined(__CYGWIN__) #include void msGettimeofday(struct mstimeval* tp, void* tzp) { struct _timeb theTime; _ftime(&theTime); tp->tv_sec = theTime.time; tp->tv_usec = theTime.millitm * 1000; } #endif #if defined(_WIN32) && !defined(__CYGWIN__) /* we need to provide our own prototype on windows. */ char *strptime( const char *buf, const char *format, struct tm *timeptr ); #endif char *msStrptime(const char *s, const char *format, struct tm *tm) { memset(tm, 0, sizeof(struct tm)); return strptime(s, format, tm); } /** return MS_TRUE if the time string matchs the timeformat. else return MS_FALSE. */ int msTimeMatchPattern(const char *timestring, const char *timeformat) { int i =-1; if(msTimeSetup() != MS_SUCCESS) { return MS_FALSE; } /* match the pattern format first and then check if the time string */ /* matchs the pattern. If it is the case retrurn the MS_TRUE */ for (i=0; i= 0 && i < MS_NUMTIMEFORMATS) { int match = ms_regexec(ms_timeFormats[i].regex, timestring, 0, NULL, 0); if(match == 0) return MS_TRUE; } return MS_FALSE; } void msUnsetLimitedPatternToUse() { msTimeSetup(); ms_num_limited_pattern = 0; } void msSetLimitedPatternsToUse(const char *patternstring) { int *limitedpatternindice = NULL; int numpatterns=0, i=0, j=0, ntmp=0; char **patterns = NULL; msTimeSetup(); limitedpatternindice = (int *)msSmallMalloc(sizeof(int)*MS_NUMTIMEFORMATS); /* free previous setting */ msUnsetLimitedPatternToUse(); if (patternstring) { patterns = msStringSplit(patternstring, ',', &ntmp); if (patterns && ntmp >= 1) { for (i=0; i 0) { for (i=0; i 0) num_patterns = ms_num_limited_pattern; else num_patterns = MS_NUMTIMEFORMATS; for(i=0; i 0) indice = ms_limited_pattern[i]; else indice = i; match = ms_regexec(ms_timeFormats[indice].regex, string, 0,NULL, 0); /* test the expression against the string */ if(match == 0) { /* match */ msStrptime(string, ms_timeFormats[indice].format, tm); return(MS_TRUE); } } msSetError(MS_REGEXERR, "Unrecognized date or time format (%s).", "msParseTime()", string); return(MS_FALSE); } /** * Parse the time string and return the reslution */ int msTimeGetResolution(const char *timestring) { int i=0; if (!timestring) return -1; for(i=0; i=2) { /*range */ if (msParseTime(atimeelements[0], &tmtimestart) != MS_TRUE) { msFreeCharArray(atimeelements, numelements); return MS_FALSE; } if (msParseTime(atimeelements[1], &tmtimeend) != MS_TRUE) { msFreeCharArray(atimeelements, numelements); return MS_FALSE; } } msFreeCharArray(atimeelements, numelements); /* Now parse the time extent. Extents can be - one range (2004-09-21/2004-09-25/resolution) - multiple rages 2004-09-21/2004-09-25/res1,2004-09-21/2004-09-25/res2 - one value 2004-09-21 - mutiple values 2004-09-21,2004-09-22,2004-09-23 */ numextents = 0; atimeextents = msStringSplit (timeextent, ',', &numextents); if (numextents <= 0) { msFreeCharArray(atimeextents, numextents); return MS_FALSE; } /*the time timestring should at be valid in one of the extents defined */ for (i=0; i= 0) { msFreeCharArray(atimerange, numranges); msFreeCharArray(atimeextents, numextents); return MS_TRUE; } } /*2004-09-21/2004-09-25/res1*/ else if (numranges >= 2) { if (msParseTime(atimerange[0], &tmstart) == MS_TRUE && msParseTime(atimerange[1], &tmend) == MS_TRUE && msTimeCompare(&tmstart, &tmtimestart) <= 0 && msTimeCompare(&tmend, &tmtimeend) >= 0) { msFreeCharArray(atimerange, numranges); msFreeCharArray(atimeextents, numextents); return MS_TRUE; } } msFreeCharArray(atimerange, numranges); } msFreeCharArray(atimeextents, numextents); return MS_FALSE; } int msValidateTimeValue(const char *timestring, const char *timeextent) { char **atimes = NULL; int i, numtimes=0; /* we need to validate the time passsed in the request */ /* against the time extent defined */ if (!timestring || !timeextent) return MS_FALSE; /* To avoid SQL injections */ if (strchr(timestring, '\'')) return MS_FALSE; /* parse the time string. We support descrete times (eg 2004-09-21), */ /* multiple times (2004-09-21, 2004-09-22, ...) */ /* and range(s) (2004-09-21/2004-09-25, 2004-09-27/2004-09-29) */ if (strstr(timestring, ",") == NULL && strstr(timestring, "/") == NULL) { /* discrete time */ return _msValidateTime(timestring, timeextent); } else { atimes = msStringSplit(timestring, ',', &numtimes); if (numtimes >=1) { /* multiple times */ if (strstr(atimes[0], "/") == NULL) { /* multiple descrete times */ for (i=0; i /* for gettimeofday() */ # define mstimeval timeval # define msGettimeofday(t,u) gettimeofday(t,u) #endif typedef enum { TIME_RESOLUTION_UNDEFINED = -1, TIME_RESOLUTION_MICROSECOND =0, TIME_RESOLUTION_MILLISECOND =1, TIME_RESOLUTION_SECOND =2, TIME_RESOLUTION_MINUTE =3, TIME_RESOLUTION_HOUR =4, TIME_RESOLUTION_DAY =5, TIME_RESOLUTION_MONTH =6, TIME_RESOLUTION_YEAR =7 } MS_TIME_RESOLUTION; /* function prototypes */ void msTimeInit(struct tm *time); int msDateCompare(struct tm *time1, struct tm *time2); int msTimeCompare(struct tm *time1, struct tm *time2); char *msStrptime(const char *s, const char *format, struct tm *tm); int msParseTime(const char *string, struct tm *tm); int msTimeMatchPattern(const char *timestring, const char *pattern); void msSetLimitedPatternsToUse(const char *patternstring); void msUnsetLimitedPatternToUse(void); MS_DLL_EXPORT int msTimeGetResolution(const char *timestring); void msTimeCleanup(); int msValidateTimeValue(const char *timestring, const char *timeextent); #endif /* MAPTIME_H */ mapserver-7.4.3/maptree.c000066400000000000000000000642011357574274700153620ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: .qix spatial index implementation. Derived from shapelib, and * relicensed with permission of Frank Warmerdam (shapelib author). * Author: Steve Lime * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "mapserver.h" #include "maptree.h" /* -------------------------------------------------------------------- */ /* If the following is 0.5, nodes will be split in half. If it */ /* is 0.6 then each subnode will contain 60% of the parent */ /* node, with 20% representing overlap. This can be help to */ /* prevent small objects on a boundary from shifting too high */ /* up the tree. */ /* -------------------------------------------------------------------- */ #define SPLITRATIO 0.55 static int treeAddShapeId(treeObj *tree, int id, rectObj rect); static void SwapWord( int length, void * wordP ) { int i; uchar temp; for( i=0; i < length/2; i++ ) { temp = ((uchar *) wordP)[i]; ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1]; ((uchar *) wordP)[length-i-1] = temp; } } static void * SfRealloc( void * pMem, int nNewSize ) { if( pMem == NULL ) return( (void *) malloc(nNewSize) ); else return( (void *) realloc(pMem,nNewSize) ); } static treeNodeObj *treeNodeCreate(rectObj rect) { treeNodeObj *node; node = (treeNodeObj *) msSmallMalloc(sizeof(treeNodeObj)); node->numshapes = 0; node->ids = NULL; node->numsubnodes = 0; memcpy(&(node->rect), &(rect), sizeof(rectObj)); return node; } SHPTreeHandle msSHPDiskTreeOpen(const char * pszTree, int debug) { char *pszFullname, *pszBasename; SHPTreeHandle psTree; char pabyBuf[16]; int i; char bBigEndian; /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) bBigEndian = MS_FALSE; else bBigEndian = MS_TRUE; /* -------------------------------------------------------------------- */ /* Initialize the info structure. */ /* -------------------------------------------------------------------- */ psTree = (SHPTreeHandle) msSmallMalloc(sizeof(SHPTreeInfo)); /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(pszTree)+5); strcpy( pszBasename, pszTree ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, MS_INDEX_EXTENSION); psTree->fp = fopen(pszFullname, "rb" ); if( psTree->fp == NULL ) { sprintf( pszFullname, "%s.QIX", pszBasename); psTree->fp = fopen(pszFullname, "rb" ); } msFree(pszBasename); /* don't need these any more */ msFree(pszFullname); if( psTree->fp == NULL ) { msFree(psTree); return( NULL ); } if( fread( pabyBuf, 8, 1, psTree->fp ) != 1 ) { msFree(psTree); return( NULL ); } memcpy( &psTree->signature, pabyBuf, 3 ); if( strncmp(psTree->signature,"SQT",3) ) { /* ---------------------------------------------------------------------- */ /* must check if the 2 first bytes equal 0 of max depth that cannot */ /* be more than 65535. If yes, we must swap all value. The problem */ /* here is if there's no Depth (bytea 5,6,7,8 in the file) all bytes */ /* will be set to 0. So,we will test with the number of shapes (bytes */ /* 1,2,3,4) that cannot be more than 65535 too. */ /* ---------------------------------------------------------------------- */ if (debug) { msDebug("WARNING in msSHPDiskTreeOpen(): %s is in old index format " "which has been deprecated. It is strongly recommended to " "regenerate it in new format.\n", pszTree); } if((pabyBuf[4] == 0 && pabyBuf[5] == 0 && pabyBuf[6] == 0 && pabyBuf[7] == 0)) { psTree->LSB_order = !(pabyBuf[0] == 0 && pabyBuf[1] == 0); } else { psTree->LSB_order = !(pabyBuf[4] == 0 && pabyBuf[5] == 0); } psTree->needswap = ((psTree->LSB_order) != (!bBigEndian)); /* ---------------------------------------------------------------------- */ /* poor hack to see if this quadtree was created by a computer with a */ /* different Endian */ /* ---------------------------------------------------------------------- */ psTree->version = 0; } else { psTree->needswap = (( pabyBuf[3] == MS_NEW_MSB_ORDER ) ^ ( bBigEndian )); psTree->LSB_order = ( pabyBuf[3] == MS_NEW_LSB_ORDER ); memcpy( &psTree->version, pabyBuf+4, 1 ); memcpy( &psTree->flags, pabyBuf+5, 3 ); if( fread( pabyBuf, 8, 1, psTree->fp ) != 1 ) { msFree(psTree); return( NULL ); } } if( psTree->needswap ) SwapWord( 4, pabyBuf ); memcpy( &psTree->nShapes, pabyBuf, 4 ); if( psTree->needswap ) SwapWord( 4, pabyBuf+4 ); memcpy( &psTree->nDepth, pabyBuf+4, 4 ); return( psTree ); } void msSHPDiskTreeClose(SHPTreeHandle disktree) { fclose( disktree->fp ); free( disktree ); } treeObj *msCreateTree(shapefileObj *shapefile, int maxdepth) { int i; treeObj *tree; rectObj bounds; if(!shapefile) return NULL; /* -------------------------------------------------------------------- */ /* Allocate the tree object */ /* -------------------------------------------------------------------- */ tree = (treeObj *) msSmallMalloc(sizeof(treeObj)); tree->numshapes = shapefile->numshapes; tree->maxdepth = maxdepth; /* -------------------------------------------------------------------- */ /* If no max depth was defined, try to select a reasonable one */ /* that implies approximately 8 shapes per node. */ /* -------------------------------------------------------------------- */ if( tree->maxdepth == 0 ) { int numnodes = 1; while(numnodes*4 < shapefile->numshapes) { tree->maxdepth += 1; numnodes = numnodes * 2; } } /* -------------------------------------------------------------------- */ /* Allocate the root node. */ /* -------------------------------------------------------------------- */ tree->root = treeNodeCreate(shapefile->bounds); for(i=0; inumshapes; i++) { if(msSHPReadBounds(shapefile->hSHP, i, &bounds) == MS_SUCCESS) treeAddShapeId(tree, i, bounds); } return tree; } static void destroyTreeNode(treeNodeObj *node) { int i; for(i=0; inumsubnodes; i++ ) { if(node->subnode[i]) destroyTreeNode(node->subnode[i]); } if(node->ids) free(node->ids); free(node); } void msDestroyTree(treeObj *tree) { destroyTreeNode(tree->root); free(tree); } static void treeSplitBounds( rectObj *in, rectObj *out1, rectObj *out2) { double range; /* -------------------------------------------------------------------- */ /* The output bounds will be very similar to the input bounds, */ /* so just copy over to start. */ /* -------------------------------------------------------------------- */ memcpy(out1, in, sizeof(rectObj)); memcpy(out2, in, sizeof(rectObj)); /* -------------------------------------------------------------------- */ /* Split in X direction. */ /* -------------------------------------------------------------------- */ if((in->maxx - in->minx) > (in->maxy - in->miny)) { range = in->maxx - in->minx; out1->maxx = in->minx + range * SPLITRATIO; out2->minx = in->maxx - range * SPLITRATIO; } /* -------------------------------------------------------------------- */ /* Otherwise split in Y direction. */ /* -------------------------------------------------------------------- */ else { range = in->maxy - in->miny; out1->maxy = in->miny + range * SPLITRATIO; out2->miny = in->maxy - range * SPLITRATIO; } } static int treeNodeAddShapeId( treeNodeObj *node, int id, rectObj rect, int maxdepth) { int i; /* -------------------------------------------------------------------- */ /* If there are subnodes, then consider whether this object */ /* will fit in them. */ /* -------------------------------------------------------------------- */ if( maxdepth > 1 && node->numsubnodes > 0 ) { for(i=0; inumsubnodes; i++ ) { if( msRectContained(&rect, &node->subnode[i]->rect)) { return treeNodeAddShapeId( node->subnode[i], id, rect, maxdepth-1); } } } /* -------------------------------------------------------------------- */ /* Otherwise, consider creating four subnodes if could fit into */ /* them, and adding to the appropriate subnode. */ /* -------------------------------------------------------------------- */ #if MAX_SUBNODES == 4 else if( maxdepth > 1 && node->numsubnodes == 0 ) { rectObj half1, half2, quad1, quad2, quad3, quad4; treeSplitBounds(&node->rect, &half1, &half2); treeSplitBounds(&half1, &quad1, &quad2); treeSplitBounds(&half2, &quad3, &quad4); if(msRectContained(&rect, &quad1) || msRectContained(&rect, &quad2) || msRectContained(&rect, &quad3) || msRectContained(&rect, &quad4)) { node->numsubnodes = 4; node->subnode[0] = treeNodeCreate(quad1); node->subnode[1] = treeNodeCreate(quad2); node->subnode[2] = treeNodeCreate(quad3); node->subnode[3] = treeNodeCreate(quad4); /* recurse back on this node now that it has subnodes */ return(treeNodeAddShapeId(node, id, rect, maxdepth)); } } #endif /* -------------------------------------------------------------------- */ /* Otherwise, consider creating two subnodes if could fit into */ /* them, and adding to the appropriate subnode. */ /* -------------------------------------------------------------------- */ #if MAX_SUBNODE == 2 else if( maxdepth > 1 && node->numsubnodes == 0 ) { rectObj half1, half2; treeSplitBounds(&node->rect, &half1, &half2); if( msRectContained(&rect, &half1)) { node->numsubnodes = 2; node->subnode[0] = treeNodeCreate(half1); node->subnode[1] = treeNodeCreate(half2); return(treeNodeAddShapeId(node->subnode[0], id, rect, maxdepth-1)); } else if(msRectContained(&rect, &half2)) { node->numsubnodes = 2; node->subnode[0] = treeNodeCreate(&half1); node->subnode[1] = treeNodeCreate(&half2); return(treeNodeAddShapeId(node->subnode[1], id, rect, maxdepth-1)); } } #endif /* MAX_SUBNODE == 2 */ /* -------------------------------------------------------------------- */ /* If none of that worked, just add it to this nodes list. */ /* -------------------------------------------------------------------- */ node->numshapes++; node->ids = SfRealloc( node->ids, sizeof(ms_int32) * node->numshapes ); node->ids[node->numshapes-1] = id; return MS_TRUE; } static int treeAddShapeId(treeObj *tree, int id, rectObj rect) { return(treeNodeAddShapeId(tree->root, id, rect, tree->maxdepth)); } static void treeCollectShapeIds(treeNodeObj *node, rectObj aoi, ms_bitarray status) { int i; /* -------------------------------------------------------------------- */ /* Does this node overlap the area of interest at all? If not, */ /* return without adding to the list at all. */ /* -------------------------------------------------------------------- */ if(!msRectOverlap(&node->rect, &aoi)) return; /* -------------------------------------------------------------------- */ /* Add the local nodes shapeids to the list. */ /* -------------------------------------------------------------------- */ for(i=0; inumshapes; i++) msSetBit(status, node->ids[i], 1); /* -------------------------------------------------------------------- */ /* Recurse to subnodes if they exist. */ /* -------------------------------------------------------------------- */ for(i=0; inumsubnodes; i++) { if(node->subnode[i]) treeCollectShapeIds(node->subnode[i], aoi, status); } } ms_bitarray msSearchTree(const treeObj *tree, rectObj aoi) { ms_bitarray status=NULL; status = msAllocBitArray(tree->numshapes); if(!status) { msSetError(MS_MEMERR, NULL, "msSearchTree()"); return(NULL); } treeCollectShapeIds(tree->root, aoi, status); return(status); } static int treeNodeTrim( treeNodeObj *node ) { int i; /* -------------------------------------------------------------------- */ /* Trim subtrees, and free subnodes that come back empty. */ /* -------------------------------------------------------------------- */ for(i=0; inumsubnodes; i++ ) { if(treeNodeTrim(node->subnode[i])) { destroyTreeNode(node->subnode[i]); node->subnode[i] = node->subnode[node->numsubnodes-1]; node->numsubnodes--; i--; /* process the new occupant of this subnode entry */ } } /* -------------------------------------------------------------------- */ /* If the current node has 1 subnode and no shapes, promote that */ /* subnode to the current node position. */ /* -------------------------------------------------------------------- */ if( node->numsubnodes == 1 && node->numshapes == 0) { treeNodeObj* psSubNode = node->subnode[0]; memcpy(&node->rect, &psSubNode->rect, sizeof(psSubNode->rect)); node->numshapes = psSubNode->numshapes; assert(node->ids == NULL); node->ids = psSubNode->ids; node->numsubnodes = psSubNode->numsubnodes; for( i = 0; i < psSubNode->numsubnodes; i++ ) node->subnode[i] = psSubNode->subnode[i]; free(psSubNode); } /* -------------------------------------------------------------------- */ /* We should be trimmed if we have no subnodes, and no shapes. */ /* -------------------------------------------------------------------- */ return(node->numsubnodes == 0 && node->numshapes == 0); } void msTreeTrim(treeObj *tree) { treeNodeTrim(tree->root); } static void searchDiskTreeNode(SHPTreeHandle disktree, rectObj aoi, ms_bitarray status) { int i; ms_int32 offset; ms_int32 numshapes, numsubnodes; rectObj rect; int *ids=NULL; if( fread( &offset, 4, 1, disktree->fp ) != 1 ) goto error; if ( disktree->needswap ) SwapWord ( 4, &offset ); if( fread( &rect, sizeof(rectObj), 1, disktree->fp ) != 1 ) goto error; if ( disktree->needswap ) SwapWord ( 8, &rect.minx ); if ( disktree->needswap ) SwapWord ( 8, &rect.miny ); if ( disktree->needswap ) SwapWord ( 8, &rect.maxx ); if ( disktree->needswap ) SwapWord ( 8, &rect.maxy ); if( fread( &numshapes, 4, 1, disktree->fp ) != 1 ) goto error; if ( disktree->needswap ) SwapWord ( 4, &numshapes ); if(!msRectOverlap(&rect, &aoi)) { /* skip rest of this node and sub-nodes */ offset += numshapes*sizeof(ms_int32) + sizeof(ms_int32); fseek(disktree->fp, offset, SEEK_CUR); return; } if(numshapes > 0) { ids = (int *)msSmallMalloc(numshapes*sizeof(ms_int32)); if( fread( ids, numshapes*sizeof(ms_int32), 1, disktree->fp ) != 1 ) goto error; if (disktree->needswap ) { for( i=0; ifp ) != 1 ) goto error; if ( disktree->needswap ) SwapWord ( 4, &numsubnodes ); for(i=0; inShapes != numshapes) { msSetError(MS_SHPERR, "The spatial index file %s is corrupt.", "msSearchDiskTree()", filename); msSHPDiskTreeClose(disktree); return(NULL); } status = msAllocBitArray(disktree->nShapes); if(!status) { msSetError(MS_MEMERR, NULL, "msSearchDiskTree()"); msSHPDiskTreeClose( disktree ); return(NULL); } searchDiskTreeNode(disktree, aoi, status); msSHPDiskTreeClose( disktree ); return(status); } treeNodeObj *readTreeNode( SHPTreeHandle disktree ) { int i,res; ms_int32 offset; treeNodeObj *node; node = (treeNodeObj *) msSmallMalloc(sizeof(treeNodeObj)); node->ids = NULL; res = fread( &offset, 4, 1, disktree->fp ); if ( !res ) { free(node); return NULL; } if ( disktree->needswap ) SwapWord ( 4, &offset ); res = fread( &node->rect, sizeof(rectObj), 1, disktree->fp ); if ( !res ) { free(node); return NULL; } if ( disktree->needswap ) SwapWord ( 8, &node->rect.minx ); if ( disktree->needswap ) SwapWord ( 8, &node->rect.miny ); if ( disktree->needswap ) SwapWord ( 8, &node->rect.maxx ); if ( disktree->needswap ) SwapWord ( 8, &node->rect.maxy ); res = fread( &node->numshapes, 4, 1, disktree->fp ); if ( !res ) { free(node); return NULL; } if ( disktree->needswap ) SwapWord ( 4, &node->numshapes ); if( node->numshapes > 0 ) node->ids = (ms_int32 *)msSmallMalloc(sizeof(ms_int32)*node->numshapes); res = fread( node->ids, node->numshapes*4, 1, disktree->fp ); if ( !res ) { free(node->ids); free(node); return NULL; } for( i=0; i < node->numshapes; i++ ) { if ( disktree->needswap ) SwapWord ( 4, &node->ids[i] ); } res = fread( &node->numsubnodes, 4, 1, disktree->fp ); if ( !res ) { free(node->ids); free(node); return NULL; } if ( disktree->needswap ) SwapWord ( 4, &node->numsubnodes ); return node; } treeObj *msReadTree(char *filename, int debug) { treeObj *tree=NULL; SHPTreeHandle disktree; disktree = msSHPDiskTreeOpen( filename, debug ); if(!disktree) { msSetError(MS_IOERR, NULL, "msReadTree()"); return(NULL); } tree = (treeObj *) malloc(sizeof(treeObj)); MS_CHECK_ALLOC(tree, sizeof(treeObj), NULL); tree->numshapes = disktree->nShapes; tree->maxdepth = disktree->nDepth; tree->root = readTreeNode( disktree ); return(tree); } static ms_int32 getSubNodeOffset(treeNodeObj *node) { int i; ms_int32 offset=0; for(i=0; inumsubnodes; i++ ) { if(node->subnode[i]) { offset += sizeof(rectObj) + (node->subnode[i]->numshapes+3)*sizeof(int); offset += getSubNodeOffset(node->subnode[i]); } } /* offset is the disk offset in the index file on disk */ /* that format is (per node) */ /* int offset 4 bytes */ /* rectObj rect 4 * 8 bytes */ /* int numShapes 4 bytes */ /* int ids[numShapes] 4 * numShapes bytes */ /* int numSubNodes 4 bytes */ /* */ return(offset); } static void writeTreeNode(SHPTreeHandle disktree, treeNodeObj *node) { int i,j; ms_int32 offset; char *pabyRec = NULL; offset = getSubNodeOffset(node); pabyRec = msSmallMalloc(sizeof(rectObj) + (3 * sizeof(ms_int32)) + (node->numshapes * sizeof(ms_int32)) ); memcpy( pabyRec, &offset, 4); if( disktree->needswap ) SwapWord( 4, pabyRec ); memcpy( pabyRec+4, &node->rect, sizeof(rectObj)); for (i=0; i < 4; i++) if( disktree->needswap ) SwapWord( 8, pabyRec+4+(8*i) ); memcpy( pabyRec+36, &node->numshapes, 4); if( disktree->needswap ) SwapWord( 4, pabyRec+36 ); j = node->numshapes*sizeof(ms_int32); memcpy( pabyRec+40, node->ids, j); for (i=0; inumshapes; i++) if( disktree->needswap ) SwapWord( 4, pabyRec+40+(4*i)); memcpy( pabyRec+j+40, &node->numsubnodes, 4); if( disktree->needswap ) SwapWord( 4, pabyRec+40+j ); fwrite( pabyRec, 44+j, 1, disktree->fp); free (pabyRec); for(i=0; inumsubnodes; i++ ) { if(node->subnode[i]) writeTreeNode(disktree, node->subnode[i]); } return; } int msWriteTree(treeObj *tree, char *filename, int B_order) { char signature[3] = "SQT"; char version = 1; char reserved[3] = {0,0,0}; SHPTreeHandle disktree; int i; char mtBigEndian; char pabyBuf[32]; char *pszBasename, *pszFullname; disktree = (SHPTreeHandle) malloc(sizeof(SHPTreeInfo)); MS_CHECK_ALLOC(disktree, sizeof(SHPTreeInfo), MS_FALSE); /* -------------------------------------------------------------------- */ /* Compute the base (layer) name. If there is any extension */ /* on the passed in filename we will strip it off. */ /* -------------------------------------------------------------------- */ pszBasename = (char *) msSmallMalloc(strlen(filename)+5); strcpy( pszBasename, filename ); for( i = strlen(pszBasename)-1; i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/' && pszBasename[i] != '\\'; i-- ) {} if( pszBasename[i] == '.' ) pszBasename[i] = '\0'; /* -------------------------------------------------------------------- */ /* Open the .shp and .shx files. Note that files pulled from */ /* a PC to Unix with upper case filenames won't work! */ /* -------------------------------------------------------------------- */ pszFullname = (char *) msSmallMalloc(strlen(pszBasename) + 5); sprintf( pszFullname, "%s%s", pszBasename, MS_INDEX_EXTENSION); disktree->fp = fopen(pszFullname, "wb"); msFree(pszBasename); /* not needed */ msFree(pszFullname); if(!disktree->fp) { msFree(disktree); msSetError(MS_IOERR, NULL, "msWriteTree()"); return(MS_FALSE); } /* for efficiency, trim the tree */ msTreeTrim(tree); /* -------------------------------------------------------------------- */ /* Establish the byte order on this machine. */ /* -------------------------------------------------------------------- */ i = 1; if( *((uchar *) &i) == 1 ) mtBigEndian = MS_FALSE; else mtBigEndian = MS_TRUE; if( !(mtBigEndian ^ ( B_order == MS_LSB_ORDER || B_order == MS_NEW_LSB_ORDER )) ) disktree->needswap = 1; else disktree->needswap = 0; if( B_order == MS_NATIVE_ORDER ) disktree->needswap = 0; /* write the header */ if ( B_order > 0 ) { memcpy( pabyBuf, &signature, 3 ); memcpy (&disktree->signature, &signature, 3); pabyBuf[3] = B_order; memcpy( pabyBuf+4, &version, 1); memcpy( pabyBuf+5, &reserved, 3); memcpy( &disktree->version, &version, 1); memcpy( &disktree->flags, &reserved, 3); fwrite( pabyBuf, 8, 1, disktree->fp ); } memcpy( pabyBuf, &tree->numshapes, 4 ); if( disktree->needswap ) SwapWord( 4, pabyBuf ); memcpy( pabyBuf+4, &tree->maxdepth, 4 ); if( disktree->needswap ) SwapWord( 4, pabyBuf+4 ); i = fwrite( pabyBuf, 8, 1, disktree->fp ); if( !i ) { fprintf (stderr, "unable to write to index file ... exiting \n"); msSHPDiskTreeClose( disktree ); return (MS_FALSE); } writeTreeNode(disktree, tree->root); msSHPDiskTreeClose( disktree ); return(MS_TRUE); } /* Function to filter search results further against feature bboxes */ void msFilterTreeSearch(shapefileObj *shp, ms_bitarray status, rectObj search_rect) { int i; rectObj shape_rect; i = msGetNextBit(status, 0, shp->numshapes); while(i >= 0) { if(msSHPReadBounds(shp->hSHP, i, &shape_rect) == MS_SUCCESS) { if(msRectOverlap(&shape_rect, &search_rect) != MS_TRUE) { msSetBit(status, i, 0); } } i = msGetNextBit(status, i+1, shp->numshapes); } } mapserver-7.4.3/maptree.h000066400000000000000000000064021357574274700153660ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: .qix spatial index declarations. * Author: Steve Lime and the MapServer team. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef MAPTREE_H #define MAPTREE_H #ifdef __cplusplus extern "C" { #endif /* this can be 2 or 4 for binary or quad tree */ #define MAX_SUBNODES 4 typedef struct shape_tree_node { /* area covered by this node */ rectObj rect; /* list of shapes stored at this node. */ ms_int32 numshapes; ms_int32 *ids; int numsubnodes; struct shape_tree_node *subnode[MAX_SUBNODES]; } treeNodeObj; typedef struct { ms_int32 numshapes; ms_int32 maxdepth; treeNodeObj *root; } treeObj; typedef struct { FILE *fp; char signature[3]; char LSB_order; char needswap; char version; char flags[3]; ms_int32 nShapes; ms_int32 nDepth; } SHPTreeInfo; typedef SHPTreeInfo * SHPTreeHandle; #define MS_LSB_ORDER -1 #define MS_MSB_ORDER -2 #define MS_NATIVE_ORDER 0 #define MS_NEW_LSB_ORDER 1 #define MS_NEW_MSB_ORDER 2 MS_DLL_EXPORT SHPTreeHandle msSHPDiskTreeOpen(const char * pszTree, int debug); MS_DLL_EXPORT void msSHPDiskTreeClose(SHPTreeHandle disktree); MS_DLL_EXPORT treeNodeObj *readTreeNode( SHPTreeHandle disktree ); MS_DLL_EXPORT treeObj *msCreateTree(shapefileObj *shapefile, int maxdepth); MS_DLL_EXPORT void msTreeTrim(treeObj *tree); MS_DLL_EXPORT void msDestroyTree(treeObj *tree); MS_DLL_EXPORT ms_bitarray msSearchTree(const treeObj *tree, rectObj aoi); MS_DLL_EXPORT ms_bitarray msSearchDiskTree(const char *filename, rectObj aoi, int debug, int numshapes); MS_DLL_EXPORT treeObj *msReadTree(char *filename, int debug); MS_DLL_EXPORT int msWriteTree(treeObj *tree, char *filename, int LSB_order); MS_DLL_EXPORT void msFilterTreeSearch(shapefileObj *shp, ms_bitarray status, rectObj search_rect); #ifdef __cplusplus } #endif #endif /* MAPTREE_H */ mapserver-7.4.3/mapunion.c000066400000000000000000000564611357574274700155640ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Implementation of the union layer data provider (RFC-68). * Author: Tamas Szekeres (szekerest@gmail.com). * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #define _CRT_SECURE_NO_WARNINGS 1 /* $Id$ */ #include #include "mapserver.h" #define MSUNION_NUMITEMS 3 #define MSUNION_SOURCELAYERNAME "Union_SourceLayerName" #define MSUNION_SOURCELAYERNAMEINDEX -100 #define MSUNION_SOURCELAYERGROUP "Union_SourceLayerGroup" #define MSUNION_SOURCELAYERGROUPINDEX -101 #define MSUNION_SOURCELAYERVISIBLE "Union_SourceLayerVisible" #define MSUNION_SOURCELAYERVISIBLEINDEX -102 typedef struct { int layerIndex; /* current source layer index */ int classIndex; /* current class index */ char* classText; /* current class text (autostyle) */ int layerCount; /* number of the source layers */ layerObj* layers; /* structure to the source layers */ int *status; /* the layer status */ int *classgroup; /* current array of the valid classes */ int nclasses; /* number of the valid classes */ } msUnionLayerInfo; /* Close the the combined layer */ int msUnionLayerClose(layerObj *layer) { int i; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo) return MS_SUCCESS; if (!layer->map) return MS_FAILURE; for (i = 0; i < layerinfo->layerCount; i++) { msLayerClose(&layerinfo->layers[i]); freeLayer(&layerinfo->layers[i]); } msFree(layerinfo->layers); msFree(layerinfo->status); msFree(layerinfo->classgroup); msFree(layerinfo->classText); msFree(layerinfo); layer->layerinfo = NULL; return MS_SUCCESS; } int isScaleInRange(mapObj* map, layerObj *layer) { if(map->scaledenom > 0) { int i; /* layer scale boundaries should be checked first */ if((layer->maxscaledenom > 0) && (map->scaledenom > layer->maxscaledenom)) return MS_FALSE; if((layer->minscaledenom > 0) && (map->scaledenom <= layer->minscaledenom)) return MS_FALSE; /* now check class scale boundaries (all layers *must* pass these tests) */ if(layer->numclasses > 0) { for(i=0; inumclasses; i++) { if((layer->class[i]->maxscaledenom > 0) && (map->scaledenom > layer->class[i]->maxscaledenom)) continue; /* can skip this one, next class */ if((layer->class[i]->minscaledenom > 0) && (map->scaledenom <= layer->class[i]->minscaledenom)) continue; /* can skip this one, next class */ break; /* can't skip this class (or layer for that matter) */ } if(i == layer->numclasses) return MS_FALSE; } if (layer->maxscaledenom <= 0 && layer->minscaledenom <= 0) { if((layer->maxgeowidth > 0) && ((map->extent.maxx - map->extent.minx) > layer->maxgeowidth)) return MS_FALSE; if((layer->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < layer->mingeowidth)) return MS_FALSE; } } return MS_TRUE; } int msUnionLayerOpen(layerObj *layer) { msUnionLayerInfo *layerinfo; char **layerNames; mapObj* map; int i; int layerCount; const char* pkey; int status_check; int scale_check; if (layer->layerinfo != NULL) { return MS_SUCCESS; /* Nothing to do... layer is already opened */ } if (!layer->connection) { msSetError(MS_MISCERR, "The CONNECTION option is not specified for layer: %s", "msUnionLayerOpen()", layer->name); return MS_FAILURE; } if (!layer->map) { msSetError(MS_MISCERR, "No map assigned to this layer: %s", "msUnionLayerOpen()", layer->name); return MS_FAILURE; } map = layer->map; layerinfo =(msUnionLayerInfo*)malloc(sizeof(msUnionLayerInfo)); MS_CHECK_ALLOC(layerinfo, sizeof(msUnionLayerInfo), MS_FAILURE); layer->layerinfo = layerinfo; layerinfo->layerIndex = 0; layerinfo->classgroup = NULL; layerinfo->nclasses = 0; layerinfo->layerCount = 0; layerinfo->classText = NULL; pkey = msLayerGetProcessingKey(layer, "UNION_STATUS_CHECK"); if(pkey && strcasecmp(pkey, "true") == 0) status_check = MS_TRUE; else status_check = MS_FALSE; pkey = msLayerGetProcessingKey(layer, "UNION_SCALE_CHECK"); if(pkey && strcasecmp(pkey, "false") == 0) scale_check = MS_FALSE; else scale_check = MS_TRUE; pkey = msLayerGetProcessingKey(layer, "UNION_SRCLAYER_CLOSE_CONNECTION"); layerNames = msStringSplit(layer->connection, ',', &layerCount); if (layerCount == 0) { msSetError(MS_MISCERR, "No source layers specified in layer: %s", "msUnionLayerOpen()", layer->name); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } layerinfo->layers =(layerObj*)malloc(layerCount * sizeof(layerObj)); MS_CHECK_ALLOC(layerinfo->layers, layerCount * sizeof(layerObj), MS_FAILURE); layerinfo->status =(int*)malloc(layerCount * sizeof(int)); MS_CHECK_ALLOC(layerinfo->status, layerCount * sizeof(int), MS_FAILURE); for(i=0; i < layerCount; i++) { int layerindex = msGetLayerIndex(map, layerNames[i]); if (layerindex >= 0 && layerindex < map->numlayers) { layerObj* srclayer = map->layers[layerindex]; if (srclayer->type != layer->type) { msSetError(MS_MISCERR, "The type of the source layer doesn't match with the union layer: %s", "msUnionLayerOpen()", srclayer->name); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } /* we need to create a new layer in order make the singlepass query to work */ if(initLayer(&layerinfo->layers[i], map) == -1) { msSetError(MS_MISCERR, "Cannot initialize source layer: %s", "msUnionLayerOpen()", srclayer->name); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } ++layerinfo->layerCount; if (msCopyLayer(&layerinfo->layers[i], srclayer) != MS_SUCCESS) { msSetError(MS_MISCERR, "Cannot copy source layer: %s", "msUnionLayerOpen()", srclayer->name); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } if (pkey) { /* override connection flag */ msLayerSetProcessingKey(&layerinfo->layers[i], "CLOSE_CONNECTION", pkey); } /* check is we should skip this source (status check) */ if (status_check && layerinfo->layers[i].status == MS_OFF) { layerinfo->status[i] = MS_DONE; continue; } /* check is we should skip this source (scale check) */ if (scale_check && isScaleInRange(map, &layerinfo->layers[i]) == MS_FALSE) { layerinfo->status[i] = MS_DONE; continue; } layerinfo->status[i] = msLayerOpen(&layerinfo->layers[i]); if (layerinfo->status[i] != MS_SUCCESS) { if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } } else { msSetError(MS_MISCERR, "Invalid layer: %s", "msUnionLayerOpen()", layerNames[i]); if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); msUnionLayerClose(layer); return MS_FAILURE; } } if(layerNames) msFreeCharArray(layerNames, layerinfo->layerCount); return MS_SUCCESS; } /* Return MS_TRUE if layer is open, MS_FALSE otherwise. */ int msUnionLayerIsOpen(layerObj *layer) { if (layer->layerinfo) return(MS_TRUE); else return(MS_FALSE); } /* Free the itemindexes array in a layer. */ void msUnionLayerFreeItemInfo(layerObj *layer) { int i; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return; msFree(layer->iteminfo); layer->iteminfo = NULL; for (i = 0; i < layerinfo->layerCount; i++) { msLayerFreeItemInfo(&layerinfo->layers[i]); if(layerinfo->layers[i].items) { /* need to remove the source layer items */ msFreeCharArray(layerinfo->layers[i].items, layerinfo->layers[i].numitems); layerinfo->layers[i].items = NULL; layerinfo->layers[i].numitems = 0; } } } /* clean up expression tokens */ void msUnionLayerFreeExpressionTokens(layerObj *layer) { int i,j; msFreeExpressionTokens(&(layer->filter)); msFreeExpressionTokens(&(layer->cluster.group)); msFreeExpressionTokens(&(layer->cluster.filter)); for(i=0; inumclasses; i++) { msFreeExpressionTokens(&(layer->class[i]->expression)); msFreeExpressionTokens(&(layer->class[i]->text)); for(j=0; jclass[i]->numstyles; j++) msFreeExpressionTokens(&(layer->class[i]->styles[j]->_geomtransform)); } } /* allocate the iteminfo index array - same order as the item list */ int msUnionLayerInitItemInfo(layerObj *layer) { int i, numitems; int *itemindexes; char* itemlist = NULL; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if(layer->numitems == 0) { return MS_SUCCESS; } if (!layerinfo || !layer->map) return MS_FAILURE; /* Cleanup any previous item selection */ msUnionLayerFreeItemInfo(layer); layer->iteminfo = (int *) malloc(sizeof(int) * layer->numitems); MS_CHECK_ALLOC(layer->iteminfo, sizeof(int) * layer->numitems, MS_FAILURE); itemindexes = (int*)layer->iteminfo; /* check whether we require attributes from the source layers also */ numitems = 0; for (i = 0; i < layer->numitems; i++) { if (EQUAL(layer->items[i], MSUNION_SOURCELAYERNAME)) itemindexes[i] = MSUNION_SOURCELAYERNAMEINDEX; else if (EQUAL(layer->items[i], MSUNION_SOURCELAYERGROUP)) itemindexes[i] = MSUNION_SOURCELAYERGROUPINDEX; else if (EQUAL(layer->items[i], MSUNION_SOURCELAYERVISIBLE)) itemindexes[i] = MSUNION_SOURCELAYERVISIBLEINDEX; else { itemindexes[i] = numitems++; if (itemlist) { itemlist = msStringConcatenate(itemlist, ","); itemlist = msStringConcatenate(itemlist, layer->items[i]); } else { itemlist = msStrdup(layer->items[i]); } } } for (i = 0; i < layerinfo->layerCount; i++) { layerObj* srclayer = &layerinfo->layers[i]; if (layerinfo->status[i] != MS_SUCCESS) continue; /* skip empty layers */ msUnionLayerFreeExpressionTokens(srclayer); if (itemlist) { /* get items requested by the union layer plus the required items */ msLayerSetProcessingKey(srclayer, "ITEMS", itemlist); if (msLayerWhichItems(srclayer, MS_TRUE, NULL) != MS_SUCCESS) { msFree(itemlist); return MS_FAILURE; } } else { /* get only the required items */ if (msLayerWhichItems(srclayer, MS_FALSE, NULL) != MS_SUCCESS) return MS_FAILURE; } } msFree(itemlist); return MS_SUCCESS; } int msUnionLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { int i; layerObj* srclayer; rectObj srcRect; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return MS_FAILURE; for (i = 0; i < layerinfo->layerCount; i++) { layerObj* srclayer = &layerinfo->layers[i]; if (layerinfo->status[i] != MS_SUCCESS) continue; /* skip empty layers */ if (layer->styleitem && layer->numitems == 0) { /* need to initialize items */ msUnionLayerFreeExpressionTokens(srclayer); /* get only the required items */ if (msLayerWhichItems(srclayer, MS_FALSE, NULL) != MS_SUCCESS) return MS_FAILURE; } srcRect = rect; #ifdef USE_PROJ if(srclayer->transform == MS_TRUE && srclayer->project && layer->transform == MS_TRUE && layer->project &&msProjectionsDiffer(&(srclayer->projection), &(layer->projection))) msProjectRect(&layer->projection, &srclayer->projection, &srcRect); /* project the searchrect to source coords */ #endif layerinfo->status[i] = msLayerWhichShapes(srclayer, srcRect, isQuery); if (layerinfo->status[i] == MS_FAILURE) return MS_FAILURE; } layerinfo->layerIndex = 0; srclayer = &layerinfo->layers[0]; msFree(layerinfo->classgroup); layerinfo->classgroup = NULL; layerinfo->nclasses = 0; if (srclayer->classgroup && srclayer->numclasses > 0) layerinfo->classgroup = msAllocateValidClassGroups(srclayer, &layerinfo->nclasses); return MS_SUCCESS; } static int BuildFeatureAttributes(layerObj *layer, layerObj* srclayer, shapeObj *shape) { int i; char **values; int* itemindexes = layer->iteminfo; values = malloc(sizeof(char*) * (layer->numitems)); MS_CHECK_ALLOC(values, layer->numitems * sizeof(char*), MS_FAILURE);; for (i = 0; i < layer->numitems; i++) { if (itemindexes[i] == MSUNION_SOURCELAYERNAMEINDEX) values[i] = msStrdup(srclayer->name); else if (itemindexes[i] == MSUNION_SOURCELAYERGROUPINDEX) values[i] = msStrdup(srclayer->group); else if (itemindexes[i] == MSUNION_SOURCELAYERVISIBLEINDEX) { if (srclayer->status == MS_OFF) values[i] = msStrdup("0"); else values[i] = msStrdup("1"); } else if (shape->values[itemindexes[i]]) values[i] = msStrdup(shape->values[itemindexes[i]]); else values[i] = msStrdup(""); } if (shape->values) msFreeCharArray(shape->values, shape->numvalues); shape->values = values; shape->numvalues = layer->numitems; return MS_SUCCESS; } /* find the next shape with the appropriate shape type */ /* also, load in the attribute data */ /* MS_DONE => no more data */ int msUnionLayerNextShape(layerObj *layer, shapeObj *shape) { int rv; layerObj* srclayer; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return MS_FAILURE; if (layerinfo->layerIndex < 0 || layerinfo->layerIndex >= layerinfo->layerCount) return MS_FAILURE; rv = MS_DONE; while (layerinfo->layerIndex < layerinfo->layerCount) { srclayer = &layerinfo->layers[layerinfo->layerIndex]; if (layerinfo->status[layerinfo->layerIndex] == MS_SUCCESS) { while ((rv = srclayer->vtable->LayerNextShape(srclayer, shape)) == MS_SUCCESS) { if(layer->styleitem) { /* need to retrieve the source layer classindex if styleitem AUTO is set */ layerinfo->classIndex = msShapeGetClass(srclayer, layer->map, shape, layerinfo->classgroup, layerinfo->nclasses); if(layerinfo->classIndex < 0 || layerinfo->classIndex >= srclayer->numclasses) { /* this shape is not visible, skip it */ msFreeShape(shape); if (rv == MS_SUCCESS) continue; else break; } if(srclayer->styleitem && strcasecmp(srclayer->styleitem, "AUTO") != 0) { /* Generic feature style handling as per RFC-61 */ msLayerGetFeatureStyle(layer->map, srclayer, srclayer->class[layerinfo->classIndex], shape); } /* set up annotation */ msFree(layerinfo->classText); layerinfo->classText = NULL; if(srclayer->class[layerinfo->classIndex]->numlabels > 0) { /* pull text from the first label only */ if(msGetLabelStatus(layer->map,layer,shape,srclayer->class[layerinfo->classIndex]->labels[0]) == MS_ON) { layerinfo->classText = msShapeGetLabelAnnotation(layer,shape,srclayer->class[layerinfo->classIndex]->labels[0]); } } } #ifdef USE_PROJ /* reproject to the target layer */ if(srclayer->project && msProjectionsDiffer(&(srclayer->projection), &(layer->projection))) msProjectShape(&(srclayer->projection), &(layer->projection), shape); else srclayer->project = MS_FALSE; #endif /* update the layer styles with the bound values */ if(msBindLayerToShape(srclayer, shape, MS_FALSE) != MS_SUCCESS) return MS_FAILURE; shape->tileindex = layerinfo->layerIndex; /* construct the item array */ if (layer->iteminfo) rv = BuildFeatureAttributes(layer, srclayer, shape); /* check the layer filter condition */ if(layer->filter.string != NULL && layer->numitems > 0 && layer->iteminfo) { if (layer->filter.type == MS_EXPRESSION && layer->filter.tokens == NULL) msTokenizeExpression(&(layer->filter), layer->items, &(layer->numitems)); if (!msEvalExpression(layer, shape, &(layer->filter), layer->filteritemindex)) { /* this shape is filtered */ msFreeShape(shape); continue; } } return rv; } } ++layerinfo->layerIndex; if (layerinfo->layerIndex == layerinfo->layerCount) { layerinfo->layerIndex = 0; return MS_DONE; } /* allocate the classgroups for the next layer */ msFree(layerinfo->classgroup); layerinfo->classgroup = NULL; layerinfo->nclasses = 0; if (srclayer->classgroup && srclayer->numclasses > 0) layerinfo->classgroup = msAllocateValidClassGroups(srclayer, &layerinfo->nclasses); } return rv; } /* Random access of the feature. */ int msUnionLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { int rv; layerObj* srclayer; long tile = record->tileindex; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return MS_FAILURE; if (tile < 0 || tile >= layerinfo->layerCount) { msSetError(MS_MISCERR, "Invalid tile index: %s", "msUnionLayerGetShape()", layer->name); return MS_FAILURE; } srclayer = &layerinfo->layers[tile]; record->tileindex = 0; rv = srclayer->vtable->LayerGetShape(srclayer, shape, record); record->tileindex = tile; if (rv == MS_SUCCESS) { #ifdef USE_PROJ /* reproject to the target layer */ if(srclayer->project && msProjectionsDiffer(&(srclayer->projection), &(layer->projection))) msProjectShape(&(srclayer->projection), &(layer->projection), shape); else srclayer->project = MS_FALSE; #endif shape->tileindex = tile; /* construct the item array */ if (layer->iteminfo) rv = BuildFeatureAttributes(layer, srclayer, shape); } return rv; } /* Query for the items collection */ int msUnionLayerGetItems(layerObj *layer) { /* we support certain built in attributes */ layer->numitems = 2; layer->items = malloc(sizeof(char*) * (layer->numitems)); MS_CHECK_ALLOC(layer->items, layer->numitems * sizeof(char*), MS_FAILURE); layer->items[0] = msStrdup(MSUNION_SOURCELAYERNAME); layer->items[1] = msStrdup(MSUNION_SOURCELAYERGROUP); return msUnionLayerInitItemInfo(layer); } int msUnionLayerGetNumFeatures(layerObj *layer) { int i, c, numFeatures; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return 0; numFeatures = 0; for (i = 0; i < layerinfo->layerCount; i++) { if (layerinfo->status[i] != MS_SUCCESS) continue; /* skip empty layers */ c = msLayerGetNumFeatures(&layerinfo->layers[i]); if (c > 0) numFeatures += c; } return numFeatures; } static int msUnionLayerGetAutoStyle(mapObj *map, layerObj *layer, classObj *c, shapeObj* shape) { layerObj* srclayer; msUnionLayerInfo* layerinfo = (msUnionLayerInfo*)layer->layerinfo; if (!layerinfo || !layer->map) return MS_FAILURE; if (shape->tileindex < 0 || shape->tileindex >= layerinfo->layerCount) { msSetError(MS_MISCERR, "Invalid tile index: %s", "msUnionLayerGetAutoStyle()", layer->name); return MS_FAILURE; } srclayer = &layerinfo->layers[shape->tileindex]; if(srclayer->styleitem && strcasecmp(srclayer->styleitem, "AUTO") == 0) { int rv; int tileindex = shape->tileindex; shape->tileindex = 0; rv = msLayerGetAutoStyle(map, srclayer, c, shape); shape->tileindex = tileindex; return rv; } else { int i,j; classObj* src = srclayer->class[layerinfo->classIndex]; /* copy the style from the current class index */ /* free any previous styles on the dst layer */ resetClassStyle(c); for (i = 0; i < src->numstyles; i++) { if (msMaybeAllocateClassStyle(c, i)) return MS_FAILURE; if (msCopyStyle(c->styles[i], src->styles[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy style.", "msUnionLayerGetAutoStyle()"); return MS_FAILURE; } /* remove the bindings on the style */ for(j=0; jstyles[i]->bindings[j].item); c->styles[i]->bindings[j].item = NULL; } c->styles[i]->numbindings = 0; } for (i = 0; i < src->numlabels; i++) { // RFC77 TODO: allocation need to be done, but is the right way (from mapcopy.c)? if (msGrowClassLabels(c) == NULL) return MS_FAILURE; initLabel(c->labels[i]); if (msCopyLabel(c->labels[i], src->labels[i]) != MS_SUCCESS) { msSetError(MS_MEMERR, "Failed to copy label.", "msUnionLayerGetAutoStyle()"); return MS_FAILURE; } /* remove the bindings on the label */ for(j=0; jlabels[i]->bindings[j].item); c->labels[i]->bindings[j].item = NULL; } c->labels[i]->numbindings = 0; } c->numlabels = src->numlabels; c->layer = layer; c->text.string = layerinfo->classText; layerinfo->classText = NULL; } return MS_SUCCESS; } int msUnionLayerCopyVirtualTable(layerVTableObj* vtable) { vtable->LayerInitItemInfo = msUnionLayerInitItemInfo; vtable->LayerFreeItemInfo = msUnionLayerFreeItemInfo; vtable->LayerOpen = msUnionLayerOpen; vtable->LayerIsOpen = msUnionLayerIsOpen; vtable->LayerWhichShapes = msUnionLayerWhichShapes; vtable->LayerNextShape = msUnionLayerNextShape; vtable->LayerGetShape = msUnionLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ vtable->LayerClose = msUnionLayerClose; vtable->LayerGetItems = msUnionLayerGetItems; vtable->LayerCloseConnection = msUnionLayerClose; vtable->LayerGetAutoStyle = msUnionLayerGetAutoStyle; vtable->LayerGetNumFeatures = msUnionLayerGetNumFeatures; return MS_SUCCESS; } int msUnionLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); return msUnionLayerCopyVirtualTable(layer->vtable); } mapserver-7.4.3/maputfgrid.cpp000066400000000000000000000513171357574274700164330ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: UTFGrid rendering functions (using AGG) * Author: Francois Desjarlais * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "mapserver.h" #include "maputfgrid.h" #include "mapagg.h" #include "renderers/agg/include/agg_rasterizer_scanline_aa.h" #include "renderers/agg/include/agg_basics.h" #include "renderers/agg/include/agg_renderer_scanline.h" #include "renderers/agg/include/agg_scanline_bin.h" #include "renderers/agg/include/agg_gamma_functions.h" #include "renderers/agg/include/agg_conv_stroke.h" #include "renderers/agg/include/agg_ellipse.h" typedef mapserver::int32u band_type; typedef mapserver::row_ptr_cache rendering_buffer; typedef pixfmt_utf pixfmt_utf32; typedef mapserver::renderer_base renderer_base; typedef mapserver::rasterizer_scanline_aa<> rasterizer_scanline; typedef mapserver::renderer_scanline_bin_solid renderer_scanline; static utfpix32 UTF_WATER = utfpix32(32); #define utfitem(c) utfpix32(c) struct shapeData { char *datavalues; char *itemvalue; band_type utfvalue; int serialid; }; class lookupTable { public: lookupTable() { table = (shapeData*) msSmallMalloc(sizeof(shapeData)); table->datavalues = NULL; table->itemvalue = NULL; table->utfvalue = 0; table->serialid = 0; size = 1; counter = 0; } ~lookupTable() { int i; for(i=0; ipoint; *x = m_point->x/utfresolution; *y = m_point->y/utfresolution; m_point++; return first ? mapserver::path_cmd_move_to : mapserver::path_cmd_line_to; } *x = *y = 0.0; if(!m_stop) { m_line++; if(m_line>=m_lend) { m_stop=true; return mapserver::path_cmd_end_poly; } m_point=m_line->point; m_pend=&(m_line->point[m_line->numpoints]); return mapserver::path_cmd_end_poly; } return mapserver::path_cmd_stop; } private: int utfresolution; }; /* * UTFGrid specific line adaptor. */ class line_adaptor_utf:public line_adaptor { public: line_adaptor_utf(shapeObj *shape,int utfres_in):line_adaptor(shape) { utfresolution = utfres_in; } virtual unsigned vertex(double* x, double* y) { if(m_point < m_pend) { bool first = m_point == m_line->point; *x = m_point->x/utfresolution; *y = m_point->y/utfresolution; m_point++; return first ? mapserver::path_cmd_move_to : mapserver::path_cmd_line_to; } m_line++; *x = *y = 0.0; if(m_line>=m_lend) return mapserver::path_cmd_stop; m_point=m_line->point; m_pend=&(m_line->point[m_line->numpoints]); return vertex(x,y); } private: int utfresolution; }; class UTFGridRenderer { public: UTFGridRenderer() { stroke = NULL; } ~UTFGridRenderer() { if(stroke) delete stroke; delete data; } lookupTable *data; int utfresolution; int layerwatch; int renderlayer; int useutfitem; int useutfdata; int duplicates; band_type utfvalue; layerObj *utflayer; band_type *buffer; rendering_buffer m_rendering_buffer; pixfmt_utf32 m_pixel_format; renderer_base m_renderer_base; rasterizer_scanline m_rasterizer; renderer_scanline m_renderer_scanline; mapserver::scanline_bin sl_utf; mapserver::conv_stroke *stroke; }; #define UTFGRID_RENDERER(image) ((UTFGridRenderer*) (image)->img.plugin) /* * Encode to avoid unavailable char in the JSON */ unsigned int encodeForRendering(unsigned int toencode) { unsigned int encoded; encoded = toencode + 32; /* 34 => " */ if(encoded >= 34) { encoded = encoded +1; } /* 92 => \ */ if (encoded >= 92) { encoded = encoded +1; } return encoded; } /* * Decode value to have the initial one */ unsigned int decodeRendered(unsigned int todecode) { unsigned int decoded; if(todecode >= 92) todecode --; if(todecode >= 34) todecode --; decoded = todecode-32; return decoded; } /* * Allocate more memory to the table if necessary. */ int growTable(lookupTable *data) { int i; data->table = (shapeData*) msSmallRealloc(data->table,sizeof(*data->table)*data->size*2); data->size = data->size*2; for(i=data->counter; isize; i++) { data->table[i].datavalues = NULL; data->table[i].itemvalue = NULL; data->table[i].utfvalue = 0; data->table[i].serialid = 0; } return MS_SUCCESS; } /* * Add the shapeObj UTFDATA and UTFITEM to the lookup table. */ band_type addToTable(UTFGridRenderer *r, shapeObj *p) { band_type utfvalue; /* Looks for duplicates. */ if(r->duplicates==0 && r->useutfitem==1) { int i; for(i=0; idata->counter; i++) { if(!strcmp(p->values[r->utflayer->utfitemindex],r->data->table[i].itemvalue)) { /* Found a copy of the values in the table. */ utfvalue = r->data->table[i].utfvalue; return utfvalue; } } } /* Grow size of table if necessary */ if(r->data->size == r->data->counter) growTable(r->data); utfvalue = (r->data->counter+1); /* Simple operation so we don't have unavailable char in the JSON */ utfvalue = encodeForRendering(utfvalue); /* Data added to the table */ r->data->table[r->data->counter].datavalues = msEvalTextExpressionJSonEscape(&r->utflayer->utfdata, p); /* If UTFITEM is set in the mapfile we add its value to the table */ if(r->useutfitem) r->data->table[r->data->counter].itemvalue = msStrdup(p->values[r->utflayer->utfitemindex]); r->data->table[r->data->counter].serialid = r->data->counter+1; r->data->table[r->data->counter].utfvalue = utfvalue; r->data->counter++; return utfvalue; } /* * Use AGG to render any path. */ template int utfgridRenderPath(imageObj *img, vertex_source &path) { UTFGridRenderer *r = UTFGRID_RENDERER(img); r->m_rasterizer.reset(); r->m_rasterizer.filling_rule(mapserver::fill_even_odd); r->m_rasterizer.add_path(path); r->m_renderer_scanline.color(utfitem(r->utfvalue)); mapserver::render_scanlines(r->m_rasterizer, r->sl_utf, r->m_renderer_scanline); return MS_SUCCESS; } /* * Initialize the renderer, create buffer, allocate memory. */ imageObj *utfgridCreateImage(int width, int height, outputFormatObj *format, colorObj * bg) { UTFGridRenderer *r; r = new UTFGridRenderer; r->data = new lookupTable; r->utfresolution = atof(msGetOutputFormatOption(format, "UTFRESOLUTION", "4")); if(r->utfresolution < 1) { msSetError(MS_MISCERR, "UTFRESOLUTION smaller that 1 in the mapfile.", "utfgridCreateImage()"); return NULL; } r->layerwatch = 0; r->renderlayer = 0; r->useutfitem = 0; r->useutfdata = 0; r->duplicates = EQUAL("true", msGetOutputFormatOption(format, "DUPLICATES", "true")); r->utfvalue = 0; r->buffer = (band_type*)msSmallMalloc(width/r->utfresolution * height/r->utfresolution * sizeof(band_type)); /* AGG specific operations */ r->m_rendering_buffer.attach(r->buffer, width/r->utfresolution, height/r->utfresolution, width/r->utfresolution); r->m_pixel_format.attach(r->m_rendering_buffer); r->m_renderer_base.attach(r->m_pixel_format); r->m_renderer_scanline.attach(r->m_renderer_base); r->m_renderer_base.clear(UTF_WATER); r->m_rasterizer.gamma(mapserver::gamma_none()); r->utflayer = NULL; imageObj *image = NULL; image = (imageObj *) msSmallCalloc(1,sizeof(imageObj)); image->img.plugin = (void*) r; return image; } /* * Free all the memory used by the renderer. */ int utfgridFreeImage(imageObj *img) { UTFGridRenderer *r = UTFGRID_RENDERER(img); msFree(r->buffer); delete r; img->img.plugin = NULL; return MS_SUCCESS; } /* * Update a character in the utfgrid. */ int utfgridUpdateChar(imageObj *img, band_type oldChar, band_type newChar) { UTFGridRenderer *r = UTFGRID_RENDERER(img); int i,bufferLength; bufferLength = (img->height/r->utfresolution) * (img->width/r->utfresolution); for(i=0;ibuffer[i] == oldChar) r->buffer[i] = newChar; } return MS_SUCCESS; } /* * Remove unnecessary data that didn't made it to the final grid. */ int utfgridCleanData(imageObj *img) { UTFGridRenderer *r = UTFGRID_RENDERER(img); unsigned char* usedChar; int i,bufferLength,itemFound,dataCounter; shapeData* updatedData; band_type utfvalue; bufferLength = (img->height/r->utfresolution) * (img->width/r->utfresolution); usedChar =(unsigned char*) msSmallMalloc(r->data->counter*sizeof(unsigned char)); for(i=0;idata->counter;i++){ usedChar[i]=0; } itemFound=0; for(i=0;ibuffer[i]) != 0 && usedChar[decodeRendered(r->buffer[i])-1]==0) { itemFound++; usedChar[decodeRendered(r->buffer[i])-1] = 1; } } updatedData = (shapeData*) msSmallMalloc(itemFound * sizeof(shapeData)); dataCounter = 0; for(i=0; i< r->data->counter; i++){ if(usedChar[decodeRendered(r->data->table[i].utfvalue)-1]==1){ updatedData[dataCounter] = r->data->table[i]; updatedData[dataCounter].serialid=dataCounter+1; utfvalue=encodeForRendering(dataCounter+1); utfgridUpdateChar(img,updatedData[dataCounter].utfvalue,utfvalue); updatedData[dataCounter].utfvalue = utfvalue; dataCounter++; } else { if(r->data->table[i].datavalues) msFree(r->data->table[i].datavalues); if(r->data->table[i].itemvalue) msFree(r->data->table[i].itemvalue); } } msFree(usedChar); msFree(r->data->table); r->data->table = updatedData; r->data->counter = dataCounter; r->data->size = dataCounter; return MS_SUCCESS; } /* * Print the renderer data as JSON. */ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format) { int row, col, i, imgheight, imgwidth; band_type pixelid; char* pszEscaped; utfgridCleanData(img); UTFGridRenderer *renderer = UTFGRID_RENDERER(img); if(renderer->layerwatch>1) return MS_FAILURE; imgheight = img->height/renderer->utfresolution; imgwidth = img->width/renderer->utfresolution; msIO_fprintf(fp,"{\"grid\":["); /* Print the buffer */ for(row=0; rowwidth/renderer->utfresolution; col++) { /* Get the data from buffer. */ pixelid = renderer->buffer[(row*imgwidth)+col]; *stringptr = pixelid; stringptr++; } /* Conversion to UTF-8 encoding */ *stringptr = '\0'; char * utf8; #if defined(_WIN32) && !defined(__CYGWIN__) const char* encoding = "UCS-2LE"; #else const char* encoding = "UCS-4LE"; #endif utf8 = msConvertWideStringToUTF8(string, encoding); msIO_fprintf(fp,"%s", utf8); msFree(utf8); msFree(string); msIO_fprintf(fp,"\""); } msIO_fprintf(fp,"],\"keys\":[\"\""); /* Print the specified key */ for(i=0;idata->counter;i++) { msIO_fprintf(fp,","); if(renderer->useutfitem) { pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue); msIO_fprintf(fp,"\"%s\"", pszEscaped); msFree(pszEscaped); } /* If no UTFITEM specified use the serial ID as the key */ else msIO_fprintf(fp,"\"%i\"", renderer->data->table[i].serialid); } msIO_fprintf(fp,"],\"data\":{"); /* Print the data */ if(renderer->useutfdata) { for(i=0;idata->counter;i++) { if(i!=0) msIO_fprintf(fp,","); if(renderer->useutfitem) { pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue); msIO_fprintf(fp,"\"%s\":", pszEscaped); msFree(pszEscaped); } /* If no UTFITEM specified use the serial ID as the key */ else msIO_fprintf(fp,"\"%i\":", renderer->data->table[i].serialid); msIO_fprintf(fp,"%s", renderer->data->table[i].datavalues); } } msIO_fprintf(fp,"}}"); return MS_SUCCESS; } /* * Starts a layer for UTFGrid renderer. */ int utfgridStartLayer(imageObj *img, mapObj *map, layerObj *layer) { UTFGridRenderer *r = UTFGRID_RENDERER(img); /* Look if the layer uses the UTFGrid output format */ if(layer->utfdata.string!=0) { r->useutfdata = 1; } /* layerwatch is set to 1 on first layer treated. Doesn't allow multiple layers. */ if(!r->layerwatch) { r->layerwatch++; r->renderlayer = 1; r->utflayer = layer; layer->refcount++; /* Verify if renderer needs to use UTFITEM */ if(r->utflayer->utfitem) r->useutfitem = 1; } /* If multiple layers, send error */ else { r->layerwatch++; msSetError(MS_MISCERR, "MapServer does not support multiple UTFGrid layers rendering simultaneously.", "utfgridStartLayer()"); return MS_FAILURE; } return MS_SUCCESS; } /* * Tell renderer the layer is done. */ int utfgridEndLayer(imageObj *img, mapObj *map, layerObj *layer) { UTFGridRenderer *r = UTFGRID_RENDERER(img); /* Look if the layer was rendered, if it was then turn off rendering. */ if(r->renderlayer) { r->utflayer = NULL; layer->refcount--; r->renderlayer = 0; } return MS_SUCCESS; } /* * Do the table operations on the shapes. Allow multiple types of data to be rendered. */ int utfgridStartShape(imageObj *img, shapeObj *shape) { UTFGridRenderer *r = UTFGRID_RENDERER(img); if(!r->renderlayer) return MS_FAILURE; /* Table operations */ r->utfvalue = addToTable(r, shape); return MS_SUCCESS; } /* * Tells the renderer that the shape's rendering is done. */ int utfgridEndShape(imageObj *img, shapeObj *shape) { UTFGridRenderer *r = UTFGRID_RENDERER(img); r->utfvalue = 0; return MS_SUCCESS; } /* * Function that renders polygons into UTFGrid. */ int utfgridRenderPolygon(imageObj *img, shapeObj *polygonshape, colorObj *color) { UTFGridRenderer *r = UTFGRID_RENDERER(img); /* utfvalue is set to 0 if the shape isn't in the table. */ if(r->utfvalue == 0) { return MS_FAILURE; } /* Render the polygon */ polygon_adaptor_utf polygons(polygonshape, r->utfresolution); utfgridRenderPath(img, polygons); return MS_SUCCESS; } /* * Function that renders lines into UTFGrid. Starts by looking if the line is a polygon * outline, draw it if it's not. */ int utfgridRenderLine(imageObj *img, shapeObj *lineshape, strokeStyleObj *linestyle) { UTFGridRenderer *r = UTFGRID_RENDERER(img); /* utfvalue is set to 0 if the shape isn't in the table. */ if(r->utfvalue == 0) { return MS_FAILURE; } /* Render the line */ line_adaptor_utf lines(lineshape, r->utfresolution); if(!r->stroke) { r->stroke = new mapserver::conv_stroke(lines); } else { r->stroke->attach(lines); } r->stroke->width(linestyle->width/r->utfresolution); utfgridRenderPath(img, *r->stroke); return MS_SUCCESS; } /* * Function that render vector type symbols into UTFGrid. */ int utfgridRenderVectorSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { UTFGridRenderer *r = UTFGRID_RENDERER(img); double ox = symbol->sizex * 0.5; double oy = symbol->sizey * 0.5; /* utfvalue is set to 0 if the shape isn't in the table. */ if(r->utfvalue == 0) { return MS_FAILURE; } /* Pathing the symbol */ mapserver::path_storage path = imageVectorSymbol(symbol); /* Transformation to the right size/scale. */ mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-ox,-oy); mtx *= mapserver::trans_affine_scaling(style->scale/r->utfresolution); mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x/r->utfresolution, y/r->utfresolution); path.transform(mtx); /* Rendering the symbol. */ utfgridRenderPath(img, path); return MS_SUCCESS; } /* * Function that renders Pixmap type symbols into UTFGrid. */ int utfgridRenderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { UTFGridRenderer *r = UTFGRID_RENDERER(img); rasterBufferObj *pixmap = symbol->pixmap_buffer; /* utfvalue is set to 0 if the shape isn't in the table. */ if(r->utfvalue == 0) { return MS_FAILURE; } /* Pathing the symbol BBox */ mapserver::path_storage pixmap_bbox; double w, h; w = pixmap->width*style->scale/(2.0); h= pixmap->height*style->scale/(2.0); pixmap_bbox.move_to((x-w)/r->utfresolution,(y-h)/r->utfresolution); pixmap_bbox.line_to((x+w)/r->utfresolution,(y-h)/r->utfresolution); pixmap_bbox.line_to((x+w)/r->utfresolution,(y+h)/r->utfresolution); pixmap_bbox.line_to((x-w)/r->utfresolution,(y+h)/r->utfresolution); /* Rendering the symbol */ utfgridRenderPath(img, pixmap_bbox); return MS_SUCCESS; } /* * Function that render ellipse type symbols into UTFGrid. */ int utfgridRenderEllipseSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { UTFGridRenderer *r = UTFGRID_RENDERER(img); /* utfvalue is set to 0 if the shape isn't in the table. */ if(r->utfvalue == 0) { return MS_FAILURE; } /* Pathing the symbol. */ mapserver::path_storage path; mapserver::ellipse ellipse(x/r->utfresolution,y/r->utfresolution,symbol->sizex*style->scale/2/r->utfresolution,symbol->sizey*style->scale/2/r->utfresolution); path.concat_path(ellipse); /* Rotation if necessary. */ if( style->rotation != 0) { mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-x/r->utfresolution,-y/r->utfresolution); mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x/r->utfresolution,y/r->utfresolution); path.transform(mtx); } /* Rendering the symbol. */ utfgridRenderPath(img, path); return MS_SUCCESS; } int utfgridRenderGlyphs(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow) { return MS_SUCCESS; } int utfgridFreeSymbol(symbolObj * symbol) { return MS_SUCCESS; } /* * Add the necessary functions for UTFGrid to the renderer VTable. */ int msPopulateRendererVTableUTFGrid( rendererVTableObj *renderer ) { renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; renderer->createImage = &utfgridCreateImage; renderer->freeImage = &utfgridFreeImage; renderer->saveImage = &utfgridSaveImage; renderer->startLayer = &utfgridStartLayer; renderer->endLayer = &utfgridEndLayer; renderer->startShape = &utfgridStartShape; renderer->endShape = &utfgridEndShape; renderer->renderPolygon = &utfgridRenderPolygon; renderer->renderGlyphs = &utfgridRenderGlyphs; renderer->renderLine = &utfgridRenderLine; renderer->renderVectorSymbol = &utfgridRenderVectorSymbol; renderer->renderPixmapSymbol = &utfgridRenderPixmapSymbol; renderer->renderEllipseSymbol = &utfgridRenderEllipseSymbol; renderer->freeSymbol = &utfgridFreeSymbol; renderer->loadImageFromFile = msLoadMSRasterBufferFromFile; return MS_SUCCESS; } mapserver-7.4.3/maputfgrid.h000066400000000000000000000166551357574274700161060ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: UTFGrid rendering functions (using AGG) * Author: Francois Desjarlais * ****************************************************************************** * Copyright (c) 1996-2007 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include "renderers/agg/include/agg_renderer_base.h" #include "renderers/agg/include/agg_rendering_buffer.h" /* * Using AGG templates to create UTFGrid pixel. */ //==================================================================utfpix32 struct utfpix32 { typedef mapserver::int32u value_type; typedef mapserver::int64u calc_type; typedef mapserver::int64 long_type; typedef utfpix32 self_type; value_type v; //-------------------------------------------------------------------- utfpix32() {} //-------------------------------------------------------------------- utfpix32(unsigned v_) : v(mapserver::int32u(v_)) {} //-------------------------------------------------------------------- utfpix32(const self_type& c) : v(c.v) {} //-------------------------------------------------------------------- void clear() { v = 0; } //-------------------------------------------------------------------- AGG_INLINE void add(const self_type& c, unsigned cover) { *this = c; } }; //=================================================pixfmt_utf template class pixfmt_utf { public: typedef RenBuf rbuf_type; typedef typename rbuf_type::row_data row_data; typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; enum base_scale_e { pix_width = sizeof(value_type), pix_step = Step, pix_offset = Offset }; private: //-------------------------------------------------------------------- static AGG_INLINE void copy_or_blend_pix(value_type* p, const color_type& c, unsigned cover) { *p = c.v; } static AGG_INLINE void copy_or_blend_pix(value_type* p, const color_type& c) { *p = c.v; } public: pixfmt_utf() : m_rbuf(0) {} //-------------------------------------------------------------------- explicit pixfmt_utf(rbuf_type& rb) : m_rbuf(&rb) {} void attach(rbuf_type& rb) { m_rbuf = &rb; } //-------------------------------------------------------------------- template bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) { mapserver::rect_i r(x1, y1, x2, y2); if(r.clip(mapserver::rect_i(0, 0, pixf.width()-1, pixf.height()-1))) { int stride = pixf.stride(); m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), (r.x2 - r.x1) + 1, (r.y2 - r.y1) + 1, stride); return true; } return false; } //-------------------------------------------------------------------- AGG_INLINE unsigned width() const { return m_rbuf->width(); } AGG_INLINE unsigned height() const { return m_rbuf->height(); } AGG_INLINE int stride() const { return m_rbuf->stride(); } //-------------------------------------------------------------------- mapserver::int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } const mapserver::int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } row_data row(int y) const { return m_rbuf->row(y); } const mapserver::int8u* pix_ptr(int x, int y) const { return m_rbuf->row_ptr(y) + x * Step + Offset+1213; } mapserver::int8u* pix_ptr(int x, int y) { return m_rbuf->row_ptr(y) + x * Step + Offset +1213; } //-------------------------------------------------------------------- AGG_INLINE static void make_pix(mapserver::int8u* p, const color_type& c) { *(value_type*)p = c.v; } //-------------------------------------------------------------------- AGG_INLINE color_type pixel(int x, int y) const { value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset; return color_type(*p); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v; } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, mapserver::int8u cover) { copy_or_blend_pix((value_type*) m_rbuf->row_ptr(x, y, 1) + x * Step + Offset, c); } //-------------------------------------------------------------------- AGG_INLINE void copy_hline(int x, int y, unsigned len, const color_type& c) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x * Step + Offset; do { *p = c.v; p += Step; } while(--len); } //-------------------------------------------------------------------- AGG_INLINE void copy_vline(int x, int y, unsigned len, const color_type& c) { do { value_type* p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; *p = c.v; } while(--len); } //-------------------------------------------------------------------- void blend_hline(int x, int y, unsigned len, const color_type& c, mapserver::int8u cover) { value_type* p = (value_type*) m_rbuf->row_ptr(x, y, len) + x * Step + Offset; do { *p = c.v; p += Step; } while(--len); } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, mapserver::int8u cover) { do { value_type* p = (value_type*) m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; *p = c.v; } while(--len); } private: rbuf_type* m_rbuf; }; mapserver-7.4.3/maputil.c000066400000000000000000002571121357574274700154050ustar00rootroot00000000000000/****************************************************************************** * $Id$ * * Project: MapServer * Purpose: Various utility functions ... a real hodgepodge. * Author: Steve Lime and the MapServer team. * * Notes: Some code (notably msAlphaBlend()) are directly derived from GD. See * the mapserver/GD-COPYING file for the GD license. Use of this code in this * manner is compatible with the MapServer license. * ****************************************************************************** * Copyright (c) 1996-2005 Regents of the University of Minnesota. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #include #include "mapserver.h" #include "maptime.h" #include "mapthread.h" #include "mapcopy.h" #include "mapows.h" #if defined(USE_OGR) || defined(USE_GDAL) #include "gdal.h" #endif #if defined(_WIN32) && !defined(__CYGWIN__) # include # include # include # include #include #endif #ifdef USE_RSVG #include #endif #ifdef USE_GEOS #include #endif extern char *msyystring_buffer; extern int msyylex_destroy(void); extern int yyparse(parseObj *); int msScaleInBounds(double scale, double minscale, double maxscale) { if(scale > 0) { if(maxscale != -1 && scale >= maxscale) return MS_FALSE; if(minscale != -1 && scale < minscale) return MS_FALSE; } return MS_TRUE; } /* ** Helper functions to convert from strings to other types or objects. */ static int bindIntegerAttribute(int *attribute, char *value) { if(!value || strlen(value) == 0) return MS_FAILURE; *attribute = MS_NINT(atof(value)); /*use atof instead of atoi as a fix for bug 2394*/ return MS_SUCCESS; } static int bindDoubleAttribute(double *attribute, char *value) { if(!value || strlen(value) == 0) return MS_FAILURE; *attribute = atof(value); return MS_SUCCESS; } static int bindColorAttribute(colorObj *attribute, char *value) { int len; if(!value || ((len = strlen(value)) == 0)) return MS_FAILURE; if(value[0] == '#' && (len == 7 || len == 9)) { /* got a hex color */ char hex[2]; hex[0] = value[1]; hex[1] = value[2]; attribute->red = msHexToInt(hex); hex[0] = value[3]; hex[1] = value[4]; attribute->green = msHexToInt(hex); hex[0] = value[5]; hex[1] = value[6]; attribute->blue = msHexToInt(hex); if(len == 9) { hex[0] = value[7]; hex[1] = value[8]; attribute->alpha = msHexToInt(hex); } return MS_SUCCESS; } else { /* try a space delimited string */ char **tokens=NULL; int numtokens=0; tokens = msStringSplit(value, ' ', &numtokens); if(tokens==NULL || numtokens != 3) { msFreeCharArray(tokens, numtokens); return MS_FAILURE; /* punt */ } attribute->red = atoi(tokens[0]); attribute->green = atoi(tokens[1]); attribute->blue = atoi(tokens[2]); msFreeCharArray(tokens, numtokens); return MS_SUCCESS; } return MS_FAILURE; /* shouldn't get here */ } static void bindStyle(layerObj *layer, shapeObj *shape, styleObj *style, int drawmode) { assert(MS_DRAW_FEATURES(drawmode)); if(style->numbindings > 0) { if(style->bindings[MS_STYLE_BINDING_SYMBOL].index != -1) { style->symbol = msGetSymbolIndex(&(layer->map->symbolset), shape->values[style->bindings[MS_STYLE_BINDING_SYMBOL].index], MS_TRUE); if(style->symbol == -1) style->symbol = 0; /* a reasonable default (perhaps should throw an error?) */ } if(style->bindings[MS_STYLE_BINDING_ANGLE].index != -1) { style->angle = 360.0; bindDoubleAttribute(&style->angle, shape->values[style->bindings[MS_STYLE_BINDING_ANGLE].index]); } if(style->bindings[MS_STYLE_BINDING_SIZE].index != -1) { style->size = 1; bindDoubleAttribute(&style->size, shape->values[style->bindings[MS_STYLE_BINDING_SIZE].index]); } if(style->bindings[MS_STYLE_BINDING_WIDTH].index != -1) { style->width = 1; bindDoubleAttribute(&style->width, shape->values[style->bindings[MS_STYLE_BINDING_WIDTH].index]); } if(style->bindings[MS_STYLE_BINDING_COLOR].index != -1 && !MS_DRAW_QUERY(drawmode)) { MS_INIT_COLOR(style->color, -1,-1,-1,255); bindColorAttribute(&style->color, shape->values[style->bindings[MS_STYLE_BINDING_COLOR].index]); } if(style->bindings[MS_STYLE_BINDING_OUTLINECOLOR].index != -1 && !MS_DRAW_QUERY(drawmode)) { MS_INIT_COLOR(style->outlinecolor, -1,-1,-1,255); bindColorAttribute(&style->outlinecolor, shape->values[style->bindings[MS_STYLE_BINDING_OUTLINECOLOR].index]); } if(style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].index != -1) { style->outlinewidth = 1; bindDoubleAttribute(&style->outlinewidth, shape->values[style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].index]); } if(style->bindings[MS_STYLE_BINDING_OPACITY].index != -1) { style->opacity = 100; bindIntegerAttribute(&style->opacity, shape->values[style->bindings[MS_STYLE_BINDING_OPACITY].index]); } if(style->bindings[MS_STYLE_BINDING_OFFSET_X].index != -1) { style->offsetx = 0; bindDoubleAttribute(&style->offsetx, shape->values[style->bindings[MS_STYLE_BINDING_OFFSET_X].index]); } if(style->bindings[MS_STYLE_BINDING_OFFSET_Y].index != -1) { style->offsety = 0; bindDoubleAttribute(&style->offsety, shape->values[style->bindings[MS_STYLE_BINDING_OFFSET_Y].index]); } if(style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].index != -1) { style->polaroffsetpixel = 0; bindDoubleAttribute(&style->polaroffsetpixel, shape->values[style->bindings[MS_STYLE_BINDING_POLAROFFSET_PIXEL].index]); } if(style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].index != -1) { style->polaroffsetangle = 0; bindDoubleAttribute(&style->polaroffsetangle, shape->values[style->bindings[MS_STYLE_BINDING_POLAROFFSET_ANGLE].index]); } if(style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].index != -1) { style->outlinewidth = 1; bindDoubleAttribute(&style->outlinewidth, shape->values[style->bindings[MS_STYLE_BINDING_OUTLINEWIDTH].index]); } if(style->opacity < 100 || style->color.alpha != 255 ) { int alpha; alpha = MS_NINT(style->opacity*2.55); style->color.alpha = alpha; style->outlinecolor.alpha = alpha; style->backgroundcolor.alpha = alpha; style->mincolor.alpha = alpha; style->maxcolor.alpha = alpha; } } } static void bindLabel(layerObj *layer, shapeObj *shape, labelObj *label, int drawmode) { int i; assert(MS_DRAW_LABELS(drawmode)); /* check the label styleObj's (TODO: do we need to use querymapMode here? */ for(i=0; inumstyles; i++) { /* force MS_DRAWMODE_FEATURES for label styles */ bindStyle(layer, shape, label->styles[i], drawmode|MS_DRAWMODE_FEATURES); } if(label->numbindings > 0) { if(label->bindings[MS_LABEL_BINDING_ANGLE].index != -1) { label->angle = 0.0; bindDoubleAttribute(&label->angle, shape->values[label->bindings[MS_LABEL_BINDING_ANGLE].index]); } if(label->bindings[MS_LABEL_BINDING_SIZE].index != -1) { label->size = 1; bindIntegerAttribute(&label->size, shape->values[label->bindings[MS_LABEL_BINDING_SIZE].index]); } if(label->bindings[MS_LABEL_BINDING_COLOR].index != -1) { MS_INIT_COLOR(label->color, -1,-1,-1,255); bindColorAttribute(&label->color, shape->values[label->bindings[MS_LABEL_BINDING_COLOR].index]); } if(label->bindings[MS_LABEL_BINDING_OUTLINECOLOR].index != -1) { MS_INIT_COLOR(label->outlinecolor, -1,-1,-1,255); bindColorAttribute(&label->outlinecolor, shape->values[label->bindings[MS_LABEL_BINDING_OUTLINECOLOR].index]); } if(label->bindings[MS_LABEL_BINDING_FONT].index != -1) { msFree(label->font); label->font = msStrdup(shape->values[label->bindings[MS_LABEL_BINDING_FONT].index]); } if(label->bindings[MS_LABEL_BINDING_PRIORITY].index != -1) { label->priority = MS_DEFAULT_LABEL_PRIORITY; bindIntegerAttribute(&label->priority, shape->values[label->bindings[MS_LABEL_BINDING_PRIORITY].index]); } if(label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].index != -1) { label->shadowsizex = 1; bindIntegerAttribute(&label->shadowsizex, shape->values[label->bindings[MS_LABEL_BINDING_SHADOWSIZEX].index]); } if(label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].index != -1) { label->shadowsizey = 1; bindIntegerAttribute(&label->shadowsizey, shape->values[label->bindings[MS_LABEL_BINDING_SHADOWSIZEY].index]); } if(label->bindings[MS_LABEL_BINDING_POSITION].index != -1) { int tmpPosition = 0; bindIntegerAttribute(&tmpPosition, shape->values[label->bindings[MS_LABEL_BINDING_POSITION].index]); if(tmpPosition != 0) { /* is this test sufficient? */ label->position = tmpPosition; } else { /* Integer binding failed, look for strings like cc, ul, lr, etc... */ if(strlen(shape->values[label->bindings[MS_LABEL_BINDING_POSITION].index]) == 2) { char *vp = shape->values[label->bindings[MS_LABEL_BINDING_POSITION].index]; if(!strncasecmp(vp,"ul",2)) label->position = MS_UL; else if(!strncasecmp(vp,"lr",2)) label->position = MS_LR; else if(!strncasecmp(vp,"ur",2)) label->position = MS_UR; else if(!strncasecmp(vp,"ll",2)) label->position = MS_LL; else if(!strncasecmp(vp,"cr",2)) label->position = MS_CR; else if(!strncasecmp(vp,"cl",2)) label->position = MS_CL; else if(!strncasecmp(vp,"uc",2)) label->position = MS_UC; else if(!strncasecmp(vp,"lc",2)) label->position = MS_LC; else if(!strncasecmp(vp,"cc",2)) label->position = MS_CC; } } } } } /* ** Function to bind various layer properties to shape attributes. */ int msBindLayerToShape(layerObj *layer, shapeObj *shape, int drawmode) { int i, j; if(!layer || !shape) return MS_FAILURE; for(i=0; inumclasses; i++) { /* check the styleObj's */ if(MS_DRAW_FEATURES(drawmode)) { for(j=0; jclass[i]->numstyles; j++) { bindStyle(layer, shape, layer->class[i]->styles[j], drawmode); } } /* check the labelObj's */ if(MS_DRAW_LABELS(drawmode)) { for(j=0; jclass[i]->numlabels; j++) { bindLabel(layer, shape, layer->class[i]->labels[j], drawmode); } } } /* next classObj */ return MS_SUCCESS; } /* * Used to get red, green, blue integers separately based upon the color index */ int getRgbColor(mapObj *map,int i,int *r,int *g,int *b) { /* check index range */ int status=1; *r=*g=*b=-1; if ((i > 0 ) && (i <= map->palette.numcolors) ) { *r=map->palette.colors[i-1].red; *g=map->palette.colors[i-1].green; *b=map->palette.colors[i-1].blue; status=0; } return status; } static int searchContextForTag(mapObj *map, char **ltags, char *tag, char *context, int requires) { int i; if(!context) return MS_FAILURE; /* printf("\tin searchContextForTag, searching %s for %s\n", context, tag); */ if(strstr(context, tag) != NULL) return MS_SUCCESS; /* found the tag */ /* check referenced layers for the tag too */ for(i=0; inumlayers; i++) { if(strstr(context, ltags[i]) != NULL) { /* need to check this layer */ if(requires == MS_TRUE) { if(searchContextForTag(map, ltags, tag, GET_LAYER(map, i)->requires, MS_TRUE) == MS_SUCCESS) return MS_SUCCESS; } else { if(searchContextForTag(map, ltags, tag, GET_LAYER(map, i)->labelrequires, MS_FALSE) == MS_SUCCESS) return MS_SUCCESS; } } } return MS_FAILURE; } /* ** Function to take a look at all layers with REQUIRES/LABELREQUIRES set to make sure there are no ** recursive context requirements set (e.g. layer1 requires layer2 and layer2 requires layer1). This ** is bug 1059. */ int msValidateContexts(mapObj *map) { int i; char **ltags; int status = MS_SUCCESS; ltags = (char **) msSmallMalloc(map->numlayers*sizeof(char *)); for(i=0; inumlayers; i++) { if(GET_LAYER(map, i)->name == NULL) { ltags[i] = msStrdup("[NULL]"); } else { ltags[i] = (char *) msSmallMalloc(sizeof(char)*strlen(GET_LAYER(map, i)->name) + 3); sprintf(ltags[i], "[%s]", GET_LAYER(map, i)->name); } } /* check each layer's REQUIRES and LABELREQUIRES parameters */ for(i=0; inumlayers; i++) { /* printf("working on layer %s, looking for references to %s\n", GET_LAYER(map, i)->name, ltags[i]); */ if(searchContextForTag(map, ltags, ltags[i], GET_LAYER(map, i)->requires, MS_TRUE) == MS_SUCCESS) { msSetError(MS_PARSEERR, "Recursion error found for REQUIRES parameter for layer %s.", "msValidateContexts", GET_LAYER(map, i)->name); status = MS_FAILURE; break; } if(searchContextForTag(map, ltags, ltags[i], GET_LAYER(map, i)->labelrequires, MS_FALSE) == MS_SUCCESS) { msSetError(MS_PARSEERR, "Recursion error found for LABELREQUIRES parameter for layer %s.", "msValidateContexts", GET_LAYER(map, i)->name); status = MS_FAILURE; break; } /* printf("done layer %s\n", GET_LAYER(map, i)->name); */ } /* clean up */ msFreeCharArray(ltags, map->numlayers); return status; } int msEvalContext(mapObj *map, layerObj *layer, char *context) { int i, status; char *tag=NULL; expressionObj e; parseObj p; if(!context) return(MS_TRUE); /* initialize a temporary expression (e) */ msInitExpression(&e); e.string = msStrdup(context); e.type = MS_EXPRESSION; /* todo */ for(i=0; inumlayers; i++) { /* step through all the layers */ if(layer->index == i) continue; /* skip the layer in question */ if (GET_LAYER(map, i)->name == NULL) continue; /* Layer without name cannot be used in contexts */ tag = (char *)msSmallMalloc(sizeof(char)*strlen(GET_LAYER(map, i)->name) + 3); sprintf(tag, "[%s]", GET_LAYER(map, i)->name); if(strstr(e.string, tag)) { if(msLayerIsVisible(map, (GET_LAYER(map, i)))) e.string = msReplaceSubstring(e.string, tag, "1"); else e.string = msReplaceSubstring(e.string, tag, "0"); } free(tag); } msTokenizeExpression(&e, NULL, NULL); p.shape = NULL; p.expr = &e; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_BOOLEAN; status = yyparse(&p); msFreeExpression(&e); if (status != 0) { msSetError(MS_PARSEERR, "Failed to parse context", "msEvalContext"); return MS_FALSE; /* error in parse */ } return p.result.intval; } /* msEvalExpression() * * Evaluates a mapserver expression for a given set of attribute values and * returns the result of the expression (MS_TRUE or MS_FALSE) * May also return MS_FALSE in case of parsing errors or invalid expressions * (check the error stack if you care) * */ int msEvalExpression(layerObj *layer, shapeObj *shape, expressionObj *expression, int itemindex) { if(MS_STRING_IS_NULL_OR_EMPTY(expression->string)) return MS_TRUE; /* NULL or empty expressions are ALWAYS true */ if(expression->native_string != NULL) return MS_TRUE; /* expressions that are evaluated natively are ALWAYS true */ switch(expression->type) { case(MS_STRING): if(itemindex == -1) { msSetError(MS_MISCERR, "Cannot evaluate expression, no item index defined.", "msEvalExpression()"); return MS_FALSE; } if(itemindex >= layer->numitems || itemindex >= shape->numvalues) { msSetError(MS_MISCERR, "Invalid item index.", "msEvalExpression()"); return MS_FALSE; } if(expression->flags & MS_EXP_INSENSITIVE) { if(strcasecmp(expression->string, shape->values[itemindex]) == 0) return MS_TRUE; /* got a match */ } else { if(strcmp(expression->string, shape->values[itemindex]) == 0) return MS_TRUE; /* got a match */ } break; case(MS_LIST): if(itemindex == -1) { msSetError(MS_MISCERR, "Cannot evaluate expression, no item index defined.", "msEvalExpression()"); return MS_FALSE; } if(itemindex >= layer->numitems || itemindex >= shape->numvalues) { msSetError(MS_MISCERR, "Invalid item index.", "msEvalExpression()"); return MS_FALSE; } { char *start,*end; int value_len = strlen(shape->values[itemindex]); start = expression->string; while((end = strchr(start,',')) != NULL) { if(value_len == end-start && !strncmp(start,shape->values[itemindex],end-start)) return MS_TRUE; start = end+1; } if(!strcmp(start,shape->values[itemindex])) return MS_TRUE; } break; case(MS_EXPRESSION): { int status; parseObj p; p.shape = shape; p.expr = expression; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_BOOLEAN; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to parse expression: %s", "msEvalExpression", expression->string); return MS_FALSE; } return p.result.intval; break; } case(MS_REGEX): if(itemindex == -1) { msSetError(MS_MISCERR, "Cannot evaluate expression, no item index defined.", "msEvalExpression()"); return MS_FALSE; } if(itemindex >= layer->numitems || itemindex >= shape->numvalues) { msSetError(MS_MISCERR, "Invalid item index.", "msEvalExpression()"); return MS_FALSE; } if(MS_STRING_IS_NULL_OR_EMPTY(shape->values[itemindex]) == MS_TRUE) return MS_FALSE; if(!expression->compiled) { if(expression->flags & MS_EXP_INSENSITIVE) { if(ms_regcomp(&(expression->regex), expression->string, MS_REG_EXTENDED|MS_REG_NOSUB|MS_REG_ICASE) != 0) { /* compile the expression */ msSetError(MS_REGEXERR, "Invalid regular expression.", "msEvalExpression()"); return MS_FALSE; } } else { if(ms_regcomp(&(expression->regex), expression->string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */ msSetError(MS_REGEXERR, "Invalid regular expression.", "msEvalExpression()"); return MS_FALSE; } } expression->compiled = MS_TRUE; } if(ms_regexec(&(expression->regex), shape->values[itemindex], 0, NULL, 0) == 0) return MS_TRUE; /* got a match */ break; } return MS_FALSE; } int *msAllocateValidClassGroups(layerObj *lp, int *nclasses) { int *classgroup = NULL; int nvalidclass = 0, i=0; if (!lp || !lp->classgroup || lp->numclasses <=0 || !nclasses) return NULL; classgroup = (int *)msSmallMalloc(sizeof(int)*lp->numclasses); nvalidclass = 0; for (i=0; inumclasses; i++) { if (lp->class[i]->group && strcasecmp(lp->class[i]->group, lp->classgroup) == 0) { classgroup[nvalidclass] = i; nvalidclass++; } } if (nvalidclass > 0) { classgroup = (int *)msSmallRealloc(classgroup, sizeof(int)*nvalidclass); *nclasses = nvalidclass; return classgroup; } if (classgroup) msFree(classgroup); return NULL; } int msShapeGetClass(layerObj *layer, mapObj *map, shapeObj *shape, int *classgroup, int numclasses) { int i, iclass; if (layer->numclasses > 0) { if (classgroup == NULL || numclasses <=0) numclasses = layer->numclasses; for(i=0; i= layer->numclasses) continue; /* this should never happen but just in case */ if(map->scaledenom > 0) { /* verify scaledenom here */ if((layer->class[iclass]->maxscaledenom > 0) && (map->scaledenom > layer->class[iclass]->maxscaledenom)) continue; /* can skip this one, next class */ if((layer->class[iclass]->minscaledenom > 0) && (map->scaledenom <= layer->class[iclass]->minscaledenom)) continue; /* can skip this one, next class */ } /* verify the minfeaturesize */ if ((shape->type == MS_SHAPE_LINE || shape->type == MS_SHAPE_POLYGON) && (layer->class[iclass]->minfeaturesize > 0)) { double minfeaturesize = Pix2LayerGeoref(map, layer, layer->class[iclass]->minfeaturesize); if (msShapeCheckSize(shape, minfeaturesize) == MS_FALSE) continue; /* skip this one, next class */ } if(layer->class[iclass]->status != MS_DELETE && msEvalExpression(layer, shape, &(layer->class[iclass]->expression), layer->classitemindex) == MS_TRUE) return(iclass); } } return(-1); /* no match */ } static char *msEvalTextExpressionInternal(expressionObj *expr, shapeObj *shape, int bJSonEscape) { char *result=NULL; if(!expr->string) return result; /* nothing to do */ switch(expr->type) { case(MS_STRING): { char *target=NULL; char *pszEscaped; tokenListNodeObjPtr node=NULL; tokenListNodeObjPtr nextNode=NULL; result = msStrdup(expr->string); node = expr->tokens; if(node) { while(node != NULL) { nextNode = node->next; if(node->token == MS_TOKEN_BINDING_DOUBLE || node->token == MS_TOKEN_BINDING_INTEGER || node->token == MS_TOKEN_BINDING_STRING || node->token == MS_TOKEN_BINDING_TIME) { target = (char *) msSmallMalloc(strlen(node->tokenval.bindval.item) + 3); sprintf(target, "[%s]", node->tokenval.bindval.item); if( bJSonEscape ) pszEscaped = msEscapeJSonString(shape->values[node->tokenval.bindval.index]); else pszEscaped = msStrdup(shape->values[node->tokenval.bindval.index]); result = msReplaceSubstring(result, target, pszEscaped); msFree(pszEscaped); msFree(target); } node = nextNode; } } if(!strlen(result)) { msFree(result); result = NULL; } } break; case(MS_EXPRESSION): { int status; parseObj p; p.shape = shape; p.expr = expr; p.expr->curtoken = p.expr->tokens; /* reset */ p.type = MS_PARSE_TYPE_STRING; status = yyparse(&p); if (status != 0) { msSetError(MS_PARSEERR, "Failed to process text expression: %s", "msEvalTextExpression", expr->string); return NULL; } result = p.result.strval; break; } default: break; } if(result && !strlen(result)) { msFree(result); result = NULL; } return result; } char *msEvalTextExpressionJSonEscape(expressionObj *expr, shapeObj *shape) { return msEvalTextExpressionInternal(expr, shape, MS_TRUE); } char *msEvalTextExpression(expressionObj *expr, shapeObj *shape) { return msEvalTextExpressionInternal(expr, shape, MS_FALSE); } char* msShapeGetLabelAnnotation(layerObj *layer, shapeObj *shape, labelObj *lbl) { assert(shape && lbl); if(lbl->text.string) { return msEvalTextExpression(&(lbl->text), shape); } else if(layer->class[shape->classindex]->text.string) { return msEvalTextExpression(&(layer->class[shape->classindex]->text), shape); } else { if (shape->values && layer->labelitemindex >= 0 && shape->values[layer->labelitemindex] && strlen(shape->values[layer->labelitemindex]) ) return msStrdup(shape->values[layer->labelitemindex]); else if(shape->text) return msStrdup(shape->text); /* last resort but common with iniline features */ } return NULL; } int msGetLabelStatus(mapObj *map, layerObj *layer, shapeObj *shape, labelObj *lbl) { assert(layer && lbl); if(!msScaleInBounds(map->scaledenom,lbl->minscaledenom,lbl->maxscaledenom)) return MS_OFF; if(msEvalExpression(layer, shape, &(lbl->expression), layer->labelitemindex) != MS_TRUE) return MS_OFF; /* TODO: check for minfeaturesize here ? */ return MS_ON; } /* Check if the shape is enough big to be drawn with the layer::minfeaturesize setting. The minfeaturesize parameter should be the value in geo ref (not in pixel) and should have been multiplied by the resolution factor. */ int msShapeCheckSize(shapeObj *shape, double minfeaturesize) { double dx = (shape->bounds.maxx-shape->bounds.minx); double dy = (shape->bounds.maxy-shape->bounds.miny); if (pow(minfeaturesize,2.0) > (pow(dx,2.0)+pow(dy,2.0))) return MS_FALSE; return MS_TRUE; } /* ** Adjusts an image size in one direction to fit an extent. */ int msAdjustImage(rectObj rect, int *width, int *height) { if(*width == -1 && *height == -1) { msSetError(MS_MISCERR, "Cannot calculate both image height and width.", "msAdjustImage()"); return(-1); } if(*width > 0) *height = MS_NINT((rect.maxy - rect.miny)/((rect.maxx - rect.minx)/(*width))); else *width = MS_NINT((rect.maxx - rect.minx)/((rect.maxy - rect.miny)/(*height))); return(0); } /* ** Make sure extent fits image window to be created. Returns cellsize of output image. */ double msAdjustExtent(rectObj *rect, int width, int height) { double cellsize, ox, oy; if(width == 1 || height == 1) return 0; cellsize = MS_MAX(MS_CELLSIZE(rect->minx, rect->maxx, width), MS_CELLSIZE(rect->miny, rect->maxy, height)); if(cellsize <= 0) /* avoid division by zero errors */ return(0); ox = MS_MAX(((width-1) - (rect->maxx - rect->minx)/cellsize)/2,0); /* these were width-1 and height-1 */ oy = MS_MAX(((height-1) - (rect->maxy - rect->miny)/cellsize)/2,0); rect->minx = rect->minx - ox*cellsize; rect->miny = rect->miny - oy*cellsize; rect->maxx = rect->maxx + ox*cellsize; rect->maxy = rect->maxy + oy*cellsize; return(cellsize); } /* ** Rect must always contain a portion of bounds. If not, rect is ** shifted to overlap by overlay percent. The dimensions of rect do ** not change but placement relative to bounds can. */ int msConstrainExtent(rectObj *bounds, rectObj *rect, double overlay) { double offset=0; /* check left edge, and if necessary the right edge of bounds */ if(rect->maxx <= bounds->minx) { offset = overlay*(rect->maxx - rect->minx); rect->minx += offset; /* shift right */ rect->maxx += offset; } else if(rect->minx >= bounds->maxx) { offset = overlay*(rect->maxx - rect->minx); rect->minx -= offset; /* shift left */ rect->maxx -= offset; } /* check top edge, and if necessary the bottom edge of bounds */ if(rect->maxy <= bounds->miny) { offset = overlay*(rect->maxy - rect->miny); rect->miny -= offset; /* shift down */ rect->maxy -= offset; } else if(rect->miny >= bounds->maxy) { offset = overlay*(rect->maxy - rect->miny); rect->miny += offset; /* shift up */ rect->maxy += offset; } return(MS_SUCCESS); } /* ** Generic function to save an image to a file. ** ** Note that map may be NULL. If it is set, then it is used for two things: ** - Deal with relative imagepaths (compute absolute path relative to map path) ** - Extract the georeferenced extents and coordinate system ** of the map for writing out with the image when appropriate ** (primarily this means via msSaveImageGDAL() to something like GeoTIFF). ** ** The filename is NULL when the image is supposed to be written to stdout. */ int msSaveImage(mapObj *map, imageObj *img, const char *filename) { int nReturnVal = MS_FAILURE; char szPath[MS_MAXPATHLEN]; struct mstimeval starttime, endtime; if(map && map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&starttime, NULL); } if (img) { #ifdef USE_GDAL if( MS_DRIVER_GDAL(img->format) ) { if (map != NULL && filename != NULL ) nReturnVal = msSaveImageGDAL(map, img, msBuildPath(szPath, map->mappath, filename)); else nReturnVal = msSaveImageGDAL(map, img, filename); } else #endif if (MS_RENDERER_PLUGIN(img->format)) { rendererVTableObj *renderer = img->format->vtable; FILE *stream = NULL; if(filename) { if(map) stream = fopen(msBuildPath(szPath, map->mappath, filename),"wb"); else stream = fopen(filename,"wb"); if(!stream) { msSetError(MS_IOERR, "Failed to create output file (%s).", "msSaveImage()", (map?szPath:filename) ); return MS_FAILURE; } } else { if ( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; stream = stdout; } if(renderer->supports_pixel_buffer) { rasterBufferObj data; if(renderer->getRasterBufferHandle(img,&data) != MS_SUCCESS) { if( stream != stdout ) fclose(stream); return MS_FAILURE; } nReturnVal = msSaveRasterBuffer(map,&data,stream,img->format ); } else { nReturnVal = renderer->saveImage(img, map, stream, img->format); } if( stream != stdout ) fclose(stream); } else if( MS_DRIVER_IMAGEMAP(img->format) ) nReturnVal = msSaveImageIM(img, filename, img->format); else msSetError(MS_MISCERR, "Unknown image type", "msSaveImage()"); } if(map && map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&endtime, NULL); msDebug("msSaveImage(%s) total time: %.3fs\n", (filename ? filename : "stdout"), (endtime.tv_sec+endtime.tv_usec/1.0e6)- (starttime.tv_sec+starttime.tv_usec/1.0e6) ); } return nReturnVal; } /* ** Generic function to save an image to a byte array. ** - the return value is the pointer to the byte array ** - size_ptr contains the number of bytes returned ** - format: the desired output format ** ** The caller is responsible to free the returned array ** The function returns NULL if the output format is not supported. */ unsigned char *msSaveImageBuffer(imageObj* image, int *size_ptr, outputFormatObj *format) { int status = MS_SUCCESS; *size_ptr = 0; if( MS_RENDERER_PLUGIN(image->format)) { rasterBufferObj data; rendererVTableObj *renderer = image->format->vtable; if(renderer->supports_pixel_buffer) { bufferObj buffer; msBufferInit(&buffer); status = renderer->getRasterBufferHandle(image,&data); if(UNLIKELY(status == MS_FAILURE)) { return NULL; } msSaveRasterBufferToBuffer(&data,&buffer,format); *size_ptr = buffer.size; return buffer.data; /* don't free the bufferObj as we don't own the bytes anymore */ } else { /* check if the renderer supports native buffer output */ if (renderer->saveImageBuffer) return renderer->saveImageBuffer(image, size_ptr, format); msSetError(MS_MISCERR, "Unsupported image type", "msSaveImageBuffer()"); return NULL; } } msSetError(MS_MISCERR, "Unsupported image type", "msSaveImage()"); return NULL; } /** * Generic function to free the imageObj */ void msFreeImage(imageObj *image) { if (image) { if(MS_RENDERER_PLUGIN(image->format)) { rendererVTableObj *renderer = image->format->vtable; tileCacheObj *next,*cur = image->tilecache; while(cur) { msFreeImage(cur->image); next = cur->next; free(cur); cur = next; } image->ntiles = 0; renderer->freeImage(image); } else if( MS_RENDERER_IMAGEMAP(image->format) ) msFreeImageIM(image); else if( MS_RENDERER_RAWDATA(image->format) ) msFree(image->img.raw_16bit); else msSetError(MS_MISCERR, "Unknown image type", "msFreeImage()"); if (image->imagepath) free(image->imagepath); if (image->imageurl) free(image->imageurl); if( --image->format->refcount < 1 ) msFreeOutputFormat( image->format ); image->imagepath = NULL; image->imageurl = NULL; msFree( image->img_mask ); image->img_mask= NULL; msFree( image ); } } /* ** Return an array containing all the layer's index given a group name. ** If nothing is found, NULL is returned. The nCount is initalized ** to the number of elements in the returned array. ** Note : the caller of the function should free the array. */ int *msGetLayersIndexByGroup(mapObj *map, char *groupname, int *pnCount) { int i; int iLayer = 0; int *aiIndex; if(!groupname || !map || !pnCount) { return NULL; } aiIndex = (int *)msSmallMalloc(sizeof(int) * map->numlayers); for(i=0; inumlayers; i++) { if(!GET_LAYER(map, i)->group) /* skip it */ continue; if(strcmp(groupname, GET_LAYER(map, i)->group) == 0) { aiIndex[iLayer] = i; iLayer++; } } if (iLayer == 0) { free(aiIndex); aiIndex = NULL; *pnCount = 0; } else { aiIndex = (int *)msSmallRealloc(aiIndex, sizeof(int)* iLayer); *pnCount = iLayer; } return aiIndex; } /* ==================================================================== */ /* Measured shape utility functions. */ /* ==================================================================== */ /************************************************************************/ /* pointObj *msGetPointUsingMeasure(shapeObj *shape, double m) */ /* */ /* Using a measured value get the XY location it corresonds */ /* to. */ /* */ /************************************************************************/ pointObj *msGetPointUsingMeasure(shapeObj *shape, double m) { #ifdef USE_POINT_Z_M pointObj *point = NULL; lineObj line; double dfMin = 0; double dfMax = 0; int i,j = 0; int bFound = 0; double dfFirstPointX = 0; double dfFirstPointY = 0; double dfFirstPointM = 0; double dfSecondPointX = 0; double dfSecondPointY = 0; double dfSecondPointM = 0; double dfCurrentM = 0; double dfFactor = 0; if (shape && shape->numlines > 0) { /* -------------------------------------------------------------------- */ /* check fir the first value (min) and the last value(max) to */ /* see if the m is contained between these min and max. */ /* -------------------------------------------------------------------- */ line = shape->line[0]; dfMin = line.point[0].m; line = shape->line[shape->numlines-1]; dfMax = line.point[line.numpoints-1].m; if (m >= dfMin && m <= dfMax) { for (i=0; inumlines; i++) { line = shape->line[i]; for (j=0; j m) { bFound = 1; dfSecondPointX = line.point[j].x; dfSecondPointY = line.point[j].y; dfSecondPointM = line.point[j].m; /* -------------------------------------------------------------------- */ /* get the previous node xy values. */ /* -------------------------------------------------------------------- */ if (j > 0) { /* not the first point of the line */ dfFirstPointX = line.point[j-1].x; dfFirstPointY = line.point[j-1].y; dfFirstPointM = line.point[j-1].m; } else { /* get last point of previous line */ dfFirstPointX = shape->line[i-1].point[0].x; dfFirstPointY = shape->line[i-1].point[0].y; dfFirstPointM = shape->line[i-1].point[0].m; } break; } } } } if (!bFound) return NULL; /* -------------------------------------------------------------------- */ /* extrapolate the m value to get t he xy coordinate. */ /* -------------------------------------------------------------------- */ if (dfFirstPointM != dfSecondPointM) dfFactor = (m-dfFirstPointM)/(dfSecondPointM - dfFirstPointM); else dfFactor = 0; point = (pointObj *)msSmallMalloc(sizeof(pointObj)); point->x = dfFirstPointX + (dfFactor * (dfSecondPointX - dfFirstPointX)); point->y = dfFirstPointY + (dfFactor * (dfSecondPointY - dfFirstPointY)); point->m = dfFirstPointM + (dfFactor * (dfSecondPointM - dfFirstPointM)); return point; } return NULL; #else msSetError(MS_MISCERR, "The \"m\" parameter for points is unavailable in your build.", "msGetPointUsingMeasure()"); return NULL; #endif /* USE_POINT_Z_M */ } /************************************************************************/ /* IntersectionPointLinepointObj *p, pointObj *a, pointObj *b) */ /* */ /* Retunrs a point object corresponding to the intersection of */ /* point p and a line formed of 2 points : a and b. */ /* */ /* Alorith base on : */ /* http://www.faqs.org/faqs/graphics/algorithms-faq/ */ /* */ /* Subject 1.02:How do I find the distance from a point to a line? */ /* */ /* Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By).*/ /* Let P be the point of perpendicular projection of C on AB. The parameter*/ /* r, which indicates P's position along AB, is computed by the dot product */ /* of AC and AB divided by the square of the length of AB: */ /* */ /* (1) AC dot AB */ /* r = --------- */ /* ||AB||^2 */ /* */ /* r has the following meaning: */ /* */ /* r=0 P = A */ /* r=1 P = B */ /* r<0 P is on the backward extension of AB */ /* r>1 P is on the forward extension of AB */ /* 00 C is right of AB */ /* s=0 C is on AB */ /* */ /* Compute s as follows: */ /* */ /* (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) */ /* s = ----------------------------- */ /* L^2 */ /* */ /* */ /* Then the distance from C to P = |s|*L. */ /* */ /************************************************************************/ pointObj *msIntersectionPointLine(pointObj *p, pointObj *a, pointObj *b) { double r = 0; double L = 0; pointObj *result = NULL; if (p && a && b) { L = sqrt(((b->x - a->x)*(b->x - a->x)) + ((b->y - a->y)*(b->y - a->y))); if (L != 0) r = ((p->x - a->x)*(b->x - a->x) + (p->y - a->y)*(b->y - a->y))/(L*L); else r = 0; result = (pointObj *)msSmallMalloc(sizeof(pointObj)); /* -------------------------------------------------------------------- */ /* We want to make sure that the point returned is on the line */ /* */ /* r=0 P = A */ /* r=1 P = B */ /* r<0 P is on the backward extension of AB */ /* r>1 P is on the forward extension of AB */ /* 0x = a->x; result->y = a->y; } else if (r > 1) { result->x = b->x; result->y = b->y; } else { result->x = a->x + r*(b->x - a->x); result->y = a->y + r*(b->y - a->y); } #ifdef USE_POINT_Z_M result->m = 0; #endif } return result; } /************************************************************************/ /* pointObj *msGetMeasureUsingPoint(shapeObj *shape, pointObj */ /* *point) */ /* */ /* Calculate the intersection point betwwen the point and the */ /* shape and return the Measured value at the intersection. */ /************************************************************************/ pointObj *msGetMeasureUsingPoint(shapeObj *shape, pointObj *point) { double dfMinDist = 1e35; double dfDist = 0; pointObj oFirst; pointObj oSecond; int i, j = 0; lineObj line; pointObj *poIntersectionPt = NULL; #ifdef USE_POINT_Z_M double dfFactor = 0; double dfDistTotal, dfDistToIntersection = 0; #endif if (shape && point) { for (i=0; inumlines; i++) { line = shape->line[i]; /* -------------------------------------------------------------------- */ /* for each line (2 consecutive lines) get the distance between */ /* the line and the point and determine which line segment is */ /* the closeset to the point. */ /* -------------------------------------------------------------------- */ for (j=0; jx - oFirst.x)* (poIntersectionPt->x - oFirst.x)) + ((poIntersectionPt->y - oFirst.y)* (poIntersectionPt->y - oFirst.y))); dfFactor = dfDistToIntersection / dfDistTotal; poIntersectionPt->m = oFirst.m + (oSecond.m - oFirst.m)*dfFactor; #endif return poIntersectionPt; } } return NULL; } /* ==================================================================== */ /* End Measured shape utility functions. */ /* ==================================================================== */ char **msGetAllGroupNames(mapObj *map, int *numTok) { char **papszGroups = NULL; int bFound = 0; int nCount = 0; int i = 0, j = 0; assert(map); *numTok = 0; if (!map->layerorder) { map->layerorder = (int*)msSmallMalloc(map->numlayers * sizeof(int)); /* * Initiate to default order */ for (i=0; inumlayers; i++) map->layerorder[i] = i; } if (map->numlayers > 0) { nCount = map->numlayers; papszGroups = (char **)msSmallMalloc(sizeof(char *)*nCount); for (i=0; ilayerorder[i])); bFound = 0; if (lp->group && lp->status != MS_DELETE) { for (j=0; j<*numTok; j++) { if (papszGroups[j] && strcmp(lp->group, papszGroups[j]) == 0) { bFound = 1; break; } } if (!bFound) { /* New group... add to the list of groups found */ papszGroups[(*numTok)] = msStrdup(lp->group); (*numTok)++; } } } } return papszGroups; } /************************************************************************/ /* msForceTmpFileBase() */ /************************************************************************/ static int tmpCount = 0; static char *ForcedTmpBase = NULL; void msForceTmpFileBase( const char *new_base ) { /* -------------------------------------------------------------------- */ /* Clear previous setting, if any. */ /* -------------------------------------------------------------------- */ if( ForcedTmpBase != NULL ) { free( ForcedTmpBase ); ForcedTmpBase = NULL; } tmpCount = -1; if( new_base == NULL ) return; /* -------------------------------------------------------------------- */ /* Record new base. */ /* -------------------------------------------------------------------- */ ForcedTmpBase = msStrdup( new_base ); tmpCount = 0; } /********************************************************************** * msTmpFile() * * Generate a Unique temporary file. * * Returns char* which must be freed by caller. **********************************************************************/ char *msTmpFile(mapObj *map, const char *mappath, const char *tmppath, const char *ext) { char szPath[MS_MAXPATHLEN]; const char *fullFname; char *tmpFileName; /* big enough for time + pid + ext */ char *tmpBase = NULL; tmpBase = msTmpPath(map, mappath, tmppath); tmpFileName = msTmpFilename(ext); fullFname = msBuildPath(szPath, tmpBase, tmpFileName); free(tmpFileName); free(tmpBase); if (fullFname) return msStrdup(fullFname); return NULL; } /********************************************************************** * msTmpPath() * * Return the temporary path based on the platform. * * Returns char* which must be freed by caller. **********************************************************************/ char *msTmpPath(mapObj *map, const char *mappath, const char *tmppath) { char szPath[MS_MAXPATHLEN]; const char *fullPath; const char *tmpBase; #ifdef _WIN32 DWORD dwRetVal = 0; TCHAR lpTempPathBuffer[MAX_PATH]; #endif if( ForcedTmpBase != NULL ) tmpBase = ForcedTmpBase; else if (tmppath != NULL) tmpBase = tmppath; else if (getenv("MS_TEMPPATH")) tmpBase = getenv("MS_TEMPPATH"); else if (map && map->web.temppath) tmpBase = map->web.temppath; else { /* default paths */ #ifndef _WIN32 tmpBase = "/tmp/"; #else dwRetVal = GetTempPath(MAX_PATH, /* length of the buffer */ lpTempPathBuffer); /* buffer for path */ if (dwRetVal > MAX_PATH || (dwRetVal == 0)) { tmpBase = "C:\\"; } else { tmpBase = (char*)lpTempPathBuffer; } #endif } fullPath = msBuildPath(szPath, mappath, tmpBase); return msStrdup(fullPath); } /********************************************************************** * msTmpFilename() * * Generate a Unique temporary filename. * * Returns char* which must be freed by caller. **********************************************************************/ char *msTmpFilename(const char *ext) { char *tmpFname; int tmpFnameBufsize; char *fullFname; char tmpId[128]; /* big enough for time + pid + ext */ snprintf(tmpId, sizeof(tmpId), "%lx_%x",(long)time(NULL),(int)getpid()); if (ext == NULL) ext = ""; tmpFnameBufsize = strlen(tmpId) + 10 + strlen(ext) + 1; tmpFname = (char*)msSmallMalloc(tmpFnameBufsize); msAcquireLock( TLOCK_TMPFILE ); snprintf(tmpFname, tmpFnameBufsize, "%s_%x.%s", tmpId, tmpCount++, ext); msReleaseLock( TLOCK_TMPFILE ); fullFname = msStrdup(tmpFname); free(tmpFname); return fullFname; } /** * Generic function to Initalize an image object. */ imageObj *msImageCreate(int width, int height, outputFormatObj *format, char *imagepath, char *imageurl, double resolution, double defresolution, colorObj *bg) { imageObj *image = NULL; if(MS_RENDERER_PLUGIN(format)) { image = format->vtable->createImage(width,height,format,bg); if (image == NULL) { msSetError(MS_MEMERR, "Unable to create new image object.", "msImageCreate()"); return NULL; } image->format = format; format->refcount++; image->width = width; image->height = height; image->imagepath = NULL; image->imageurl = NULL; image->tilecache = NULL; image->ntiles = 0; image->resolution = resolution; image->resolutionfactor = resolution/defresolution; if (imagepath) image->imagepath = msStrdup(imagepath); if (imageurl) image->imageurl = msStrdup(imageurl); } else if( MS_RENDERER_RAWDATA(format) ) { if( format->imagemode != MS_IMAGEMODE_INT16 && format->imagemode != MS_IMAGEMODE_FLOAT32 && format->imagemode != MS_IMAGEMODE_BYTE ) { msSetError(MS_IMGERR, "Attempt to use illegal imagemode with rawdata renderer.", "msImageCreate()" ); return NULL; } image = (imageObj *)calloc(1,sizeof(imageObj)); if (image == NULL) { msSetError(MS_MEMERR, "Unable to create new image object.", "msImageCreate()"); return NULL; } if( format->imagemode == MS_IMAGEMODE_INT16 ) image->img.raw_16bit = (short *) msSmallCalloc(sizeof(short),width*height*format->bands); else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) image->img.raw_float = (float *) msSmallCalloc(sizeof(float),width*height*format->bands); else if( format->imagemode == MS_IMAGEMODE_BYTE ) image->img.raw_byte = (unsigned char *) msSmallCalloc(sizeof(unsigned char),width*height*format->bands); if( image->img.raw_16bit == NULL ) { msFree( image ); msSetError(MS_IMGERR, "Attempt to allocate raw image failed, out of memory.", "msImageCreate()" ); return NULL; } image->img_mask = msAllocBitArray( width*height ); image->format = format; format->refcount++; image->width = width; image->height = height; image->imagepath = NULL; image->imageurl = NULL; image->resolution = resolution; image->resolutionfactor = resolution/defresolution; if (imagepath) image->imagepath = msStrdup(imagepath); if (imageurl) image->imageurl = msStrdup(imageurl); /* initialize to requested nullvalue if there is one */ if( msGetOutputFormatOption(image->format,"NULLVALUE",NULL) != NULL ) { int i = image->width * image->height * format->bands; const char *nullvalue = msGetOutputFormatOption(image->format, "NULLVALUE",NULL); if( atof(nullvalue) == 0.0 ) /* nothing to do */; else if( format->imagemode == MS_IMAGEMODE_INT16 ) { short nv = atoi(nullvalue); for( ; i > 0; ) image->img.raw_16bit[--i] = nv; } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { float nv = atof(nullvalue); for( ; i > 0; ) image->img.raw_float[--i] = nv; } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { unsigned char nv = (unsigned char) atoi(nullvalue); memset( image->img.raw_byte, nv, i ); } } } else if( MS_RENDERER_IMAGEMAP(format) ) { image = msImageCreateIM(width, height, format, imagepath, imageurl, resolution, defresolution); } else { msSetError(MS_MISCERR, "Unsupported renderer requested, unable to initialize image.", "msImageCreate()"); return NULL; } if(!image) msSetError(MS_IMGERR, "Unable to initialize image.", "msImageCreate()"); image->refpt.x = image->refpt.y = 0; return image; } /** * Generic function to transorm a point. * */ void msTransformPoint(pointObj *point, rectObj *extent, double cellsize, imageObj *image) { double invcellsize; /*We should probabaly have a function defined at all the renders*/ if (image != NULL && MS_RENDERER_PLUGIN(image->format)) { if(image->format->renderer == MS_RENDER_WITH_KML) { return; } } invcellsize = 1.0/cellsize; point->x = MS_MAP2IMAGE_X_IC_DBL(point->x, extent->minx, invcellsize); point->y = MS_MAP2IMAGE_Y_IC_DBL(point->y, extent->maxy, invcellsize); } /* ** Helper functions supplied as part of bug #2868 solution. Consider moving these to ** mapprimitive.c for more general use. */ /* vector difference */ static pointObj point_diff(const pointObj a, const pointObj b) { pointObj retv; retv.x = a.x-b.x; retv.y = a.y-b.y; #ifdef USE_POINT_Z_M retv.z = a.z-b.z; retv.m = a.m-b.m; #endif return retv; } /* vector sum */ static pointObj point_sum(const pointObj a, const pointObj b) { pointObj retv; retv.x = a.x+b.x; retv.y = a.y+b.y; #ifdef USE_POINT_Z_M retv.z = a.z+b.z; retv.m = a.m+b.m; #endif return retv; } /* vector multiply */ static pointObj point_mul(const pointObj a, double b) { pointObj retv; retv.x = a.x*b; retv.y = a.y*b; #ifdef USE_POINT_Z_M retv.z = a.z*b; retv.m = a.m*b; #endif return retv; } /* vector ??? */ static double point_abs2(const pointObj a) { #ifdef USE_POINT_Z_M return a.x*a.x+a.y*a.y+a.z*a.z+a.m*a.m; #else return a.x*a.x+a.y*a.y; #endif } /* vector normal */ static pointObj point_norm(const pointObj a) { double lenmul; pointObj retv; int norm_vector; norm_vector = a.x==0 && a.y==0; #ifdef USE_POINT_Z_M norm_vector = norm_vector && a.z==0 && a.m==0; #endif if (norm_vector) return a; lenmul=1.0/sqrt(point_abs2(a)); /* this seems to be the costly operation */ retv.x = a.x*lenmul; retv.y = a.y*lenmul; #ifdef USE_POINT_Z_M retv.z = a.z*lenmul; retv.m = a.m*lenmul; #endif return retv; } /* rotate a vector 90 degrees */ static pointObj point_rotz90(const pointObj a) { double nx=-1.0*a.y, ny=a.x; pointObj retv=a; retv.x=nx; retv.y=ny; return retv; } /* vector cross product (warning: z and m dimensions are ignored!) */ static double point_cross(const pointObj a, const pointObj b) { return a.x*b.y-a.y*b.x; } shapeObj *msOffsetCurve(shapeObj *p, double offset) { shapeObj *ret; int i, j, first,idx,ok=0; #if defined USE_GEOS && (GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 3)) ret = msGEOSOffsetCurve(p,offset); /* GEOS curve offsetting can fail sometimes, we continue with our own implementation if that is the case.*/ if(ret) return ret; /* clear error raised by geos in this case */ msResetErrorList(); #endif /* ** For offset corner point calculation 1/sin() is used ** to avoid 1/0 division (and long spikes) we define a ** limit for sin(). */ #define CURVE_SIN_LIMIT 0.3 ret = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(ret); ret->numlines = p->numlines; ret->line=(lineObj*)msSmallMalloc(sizeof(lineObj)*ret->numlines); for(i=0; inumlines; i++) { ret->line[i].numpoints=p->line[i].numpoints; ret->line[i].point=(pointObj*)msSmallMalloc(sizeof(pointObj)*ret->line[i].numpoints); } for (i = 0; i < p->numlines; i++) { pointObj old_pt, old_diffdir, old_offdir; if(p->line[i].numpoints<2) { ret->line[i].numpoints = 0; continue; /* skip degenerate points */ } ok = 1; /* initialize old_offdir and old_diffdir, as gcc isn't smart enough to see that it * is not an error to do so, and prints a warning */ old_offdir.x=old_offdir.y=old_diffdir.x=old_diffdir.y = 0; idx=0; first = 1; /* saved metrics of the last processed point */ if (p->line[i].numpoints>0) old_pt=p->line[i].point[0]; for(j=1; jline[i].numpoints; j++) { const pointObj pt = p->line[i].point[j]; /* place of the point */ const pointObj diffdir = point_norm(point_diff(pt,old_pt)); /* direction of the line */ const pointObj offdir = point_rotz90(diffdir); /* direction where the distance between the line and the offset is measured */ pointObj offpt; /* this will be the corner point of the offset line */ /* offset line points computation */ if(first == 1) { /* first point */ first = 0; offpt = point_sum(old_pt,point_mul(offdir,offset)); } else { /* middle points */ /* curve is the angle of the last and the current line's direction (supplementary angle of the shape's inner angle) */ double sin_curve = point_cross(diffdir,old_diffdir); double cos_curve = point_cross(old_offdir,diffdir); if ((-1.0)*CURVE_SIN_LIMIT < sin_curve && sin_curve < CURVE_SIN_LIMIT) { /* do not calculate 1/sin, instead use a corner point approximation: average of the last and current offset direction and length */ /* ** TODO: fair for obtuse inner angles, however, positive and negative ** acute inner angles would need special handling - similar to LINECAP ** to avoid drawing of long spikes */ offpt = point_sum(old_pt, point_mul(point_sum(offdir, old_offdir),0.5*offset)); } else { double base_shift = -1.0*(1.0+cos_curve)/sin_curve; offpt = point_sum(old_pt, point_mul(point_sum(point_mul(diffdir,base_shift),offdir), offset)); } } ret->line[i].point[idx]=offpt; idx++; old_pt=pt; old_diffdir=diffdir; old_offdir=offdir; } /* last point */ if(first == 0) { pointObj offpt=point_sum(old_pt,point_mul(old_offdir,offset)); ret->line[i].point[idx]=offpt; idx++; } if(idx != p->line[i].numpoints) { /* printf("shouldn't happen :(\n"); */ ret->line[i].numpoints=idx; ret->line=msSmallRealloc(ret->line,ret->line[i].numpoints*sizeof(pointObj)); } } if(!ok) ret->numlines = 0; /* all lines where degenerate */ return ret; } shapeObj *msOffsetPolyline(shapeObj *p, double offsetx, double offsety) { int i, j; shapeObj *ret; if(offsety == MS_STYLE_SINGLE_SIDED_OFFSET) { /* complex calculations */ return msOffsetCurve(p,offsetx); } else if(offsety == MS_STYLE_DOUBLE_SIDED_OFFSET) { shapeObj *tmp1; ret = msOffsetCurve(p,offsetx/2.0); tmp1 = msOffsetCurve(p, -offsetx/2.0); for(i=0;inumlines; i++) { msAddLineDirectly(ret,tmp1->line + i); } msFreeShape(tmp1); free(tmp1); return ret; } ret = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(ret); ret->numlines = p->numlines; ret->line=(lineObj*)msSmallMalloc(sizeof(lineObj)*ret->numlines); for(i=0; inumlines; i++) { ret->line[i].numpoints=p->line[i].numpoints; ret->line[i].point=(pointObj*)msSmallMalloc(sizeof(pointObj)*ret->line[i].numpoints); } for (i = 0; i < p->numlines; i++) { for(j=0; jline[i].numpoints; j++) { ret->line[i].point[j].x=p->line[i].point[j].x+offsetx; ret->line[i].point[j].y=p->line[i].point[j].y+offsety; } } return ret; } /* ------------------------------------------------------------------------------- msSetup() Contributed by Jerry Pisk in bug 1203. Heads off potential race condition in initializing GD font cache with multiple threads. Should be called from mapscript module initialization code. ------------------------------------------------------------------------------- */ int msSetup() { #ifdef _WIN32 char* maxfiles = getenv("MS_MAX_OPEN_FILES"); if (maxfiles) { int res = _getmaxstdio(); if (res < 2048) { res = _setmaxstdio(atoi(maxfiles)); assert(res != -1); } } #endif #ifdef USE_THREAD msThreadInit(); #endif /* Use PROJ_LIB env vars if set */ msProjLibInitFromEnv(); /* Use MS_ERRORFILE and MS_DEBUGLEVEL env vars if set */ if (msDebugInitFromEnv() != MS_SUCCESS) return MS_FAILURE; #ifdef USE_GEOS msGEOSSetup(); #endif #ifdef USE_RSVG #if !GLIB_CHECK_VERSION(2, 35, 0) g_type_init(); #endif #endif msFontCacheSetup(); return MS_SUCCESS; } /* This is intended to be a function to cleanup anything that "hangs around" when all maps are destroyed, like Registered GDAL drivers, and so forth. */ #ifndef NDEBUG #if defined(USE_LIBXML2) #include "maplibxml2.h" #endif #endif void msCleanup() { msForceTmpFileBase( NULL ); msConnPoolFinalCleanup(); /* Lexer string parsing variable */ if (msyystring_buffer != NULL) { msFree(msyystring_buffer); msyystring_buffer = NULL; } msyylex_destroy(); #ifdef USE_OGR msOGRCleanup(); #endif #ifdef USE_GDAL msGDALCleanup(); #endif /* Release both GDAL and OGR resources */ #if defined(USE_OGR) || defined(USE_GDAL) msAcquireLock( TLOCK_GDAL ); #if GDAL_VERSION_MAJOR >= 3 || (GDAL_VERSION_MAJOR == 2 && GDAL_VERSION_MINOR == 4) /* Cleanup some GDAL global resources in particular */ GDALDestroy(); #else GDALDestroyDriverManager(); #endif msReleaseLock( TLOCK_GDAL ); #endif #ifdef USE_PROJ # if PJ_VERSION >= 480 pj_clear_initcache(); # endif pj_deallocate_grids(); msSetPROJ_LIB( NULL, NULL ); #endif #if defined(USE_CURL) msHTTPCleanup(); #endif #ifdef USE_GEOS msGEOSCleanup(); #endif /* make valgrind happy on debug code */ #ifndef NDEBUG #ifdef USE_CAIRO msCairoCleanup(); #endif #if defined(USE_LIBXML2) xmlCleanupParser(); #endif #endif msFontCacheCleanup(); msTimeCleanup(); msIO_Cleanup(); msResetErrorList(); /* Close/cleanup log/debug output. Keep this at the very end. */ msDebugCleanup(); /* Clean up the vtable factory */ msPluginFreeVirtualTableFactory(); } /************************************************************************/ /* msAlphaBlend() */ /* */ /* Function to overlay/blend an RGBA value into an existing */ /* RGBA value using the Porter-Duff "over" operator. */ /* Primarily intended for use with rasterBufferObj */ /* raster rendering. The "src" is the overlay value, and "dst" */ /* is the existing value being overlaid. dst is expected to be */ /* premultiplied, but the source should not be. */ /* */ /* NOTE: alpha_dst may be NULL. */ /************************************************************************/ void msAlphaBlend( unsigned char red_src, unsigned char green_src, unsigned char blue_src, unsigned char alpha_src, unsigned char *red_dst, unsigned char *green_dst, unsigned char *blue_dst, unsigned char *alpha_dst ) { /* -------------------------------------------------------------------- */ /* Simple cases we want to handle fast. */ /* -------------------------------------------------------------------- */ if( alpha_src == 0 ) return; if( alpha_src == 255 ) { *red_dst = red_src; *green_dst = green_src; *blue_dst = blue_src; if( alpha_dst ) *alpha_dst = 255; return; } /* -------------------------------------------------------------------- */ /* Premultiple alpha for source values now. */ /* -------------------------------------------------------------------- */ red_src = red_src * alpha_src / 255; green_src = green_src * alpha_src / 255; blue_src = blue_src * alpha_src / 255; /* -------------------------------------------------------------------- */ /* Another pretty fast case if there is nothing in the */ /* destination to mix with. */ /* -------------------------------------------------------------------- */ if( alpha_dst && *alpha_dst == 0) { *red_dst = red_src; *green_dst = green_src; *blue_dst = blue_src; *alpha_dst = alpha_src; return; } /* -------------------------------------------------------------------- */ /* Cases with actual blending. */ /* -------------------------------------------------------------------- */ if(!alpha_dst || *alpha_dst == 255) { int weight_dst = 256 - alpha_src; *red_dst = (256 * red_src + *red_dst * weight_dst) >> 8; *green_dst = (256 * green_src + *green_dst * weight_dst) >> 8; *blue_dst = (256 * blue_src + *blue_dst * weight_dst) >> 8; } else { int weight_dst = (256 - alpha_src); *red_dst = (256 * red_src + *red_dst * weight_dst) >> 8; *green_dst = (256 * green_src + *green_dst * weight_dst) >> 8; *blue_dst = (256 * blue_src + *blue_dst * weight_dst) >> 8; *alpha_dst = (256 * alpha_src + *alpha_dst * weight_dst) >> 8; } } /************************************************************************/ /* msAlphaBlendPM() */ /* */ /* Same as msAlphaBlend() except that the source RGBA is */ /* assumed to already be premultiplied. */ /************************************************************************/ void msAlphaBlendPM( unsigned char red_src, unsigned char green_src, unsigned char blue_src, unsigned char alpha_src, unsigned char *red_dst, unsigned char *green_dst, unsigned char *blue_dst, unsigned char *alpha_dst ) { /* -------------------------------------------------------------------- */ /* Simple cases we want to handle fast. */ /* -------------------------------------------------------------------- */ if( alpha_src == 0 ) return; if( alpha_src == 255 ) { *red_dst = red_src; *green_dst = green_src; *blue_dst = blue_src; if( alpha_dst ) *alpha_dst = 255; return; } /* -------------------------------------------------------------------- */ /* Another pretty fast case if there is nothing in the */ /* destination to mix with. */ /* -------------------------------------------------------------------- */ if( alpha_dst && *alpha_dst == 0) { *red_dst = red_src; *green_dst = green_src; *blue_dst = blue_src; *alpha_dst = alpha_src; return; } /* -------------------------------------------------------------------- */ /* Cases with actual blending. */ /* -------------------------------------------------------------------- */ if(!alpha_dst || *alpha_dst == 255) { int weight_dst = 255 - alpha_src; *red_dst = (alpha_src * red_src + *red_dst * weight_dst) >> 8; *green_dst = (alpha_src * green_src + *green_dst * weight_dst) >> 8; *blue_dst = (alpha_src * blue_src + *blue_dst * weight_dst) >> 8; } else { int weight_dst = (255 - alpha_src); *red_dst = (alpha_src * red_src + *red_dst * weight_dst) >> 8; *green_dst = (alpha_src * green_src + *green_dst * weight_dst) >> 8; *blue_dst = (alpha_src * blue_src + *blue_dst * weight_dst) >> 8; *alpha_dst = (255 * alpha_src + *alpha_dst * weight_dst) >> 8; } } void msRGBtoHSL(colorObj *rgb, double *h, double *s, double *l) { double r = rgb->red/255.0, g = rgb->green/255.0, b = rgb->blue/255.0; double maxv = MS_MAX(MS_MAX(r, g), b), minv = MS_MIN(MS_MIN(r, g), b); double d = maxv - minv; *h = 0, *s = 0; *l = (maxv + minv) / 2; if (maxv != minv) { *s = *l > 0.5 ? d / (2 - maxv - minv) : d / (maxv + minv); if (maxv == r) { *h = (g - b) / d + (g < b ? 6 : 0); } else if (maxv == g) { *h = (b - r) / d + 2; } else if (maxv == b) { *h = (r - g) / d + 4; } *h /= 6; } } static double hue_to_rgb(double p, double q, double t) { if(t < 0) t += 1; if(t > 1) t -= 1; if(t < 0.1666666666666666) return p + (q - p) * 6 * t; if(t < 0.5) return q; if(t < 0.6666666666666666) return p + (q - p) * (0.666666666666 - t) * 6; return p; } void msHSLtoRGB(double h, double s, double l, colorObj *rgb) { double r, g, b; if(s == 0){ r = g = b = l; } else { double q = l < 0.5 ? l * (1 + s) : l + s - l * s; double p = 2 * l - q; r = hue_to_rgb(p, q, h + 0.33333333333333333); g = hue_to_rgb(p, q, h); b = hue_to_rgb(p, q, h - 0.33333333333333333); } rgb->red = r * 255; rgb->green = g * 255; rgb->blue = b * 255; } /* RFC 24: check if the parent pointer is NULL and raise an error otherwise */ int msCheckParentPointer(void* p, char *objname) { char* msg=NULL; if (p == NULL) { if(objname != NULL) { msSetError(MS_NULLPARENTERR, "The %s parent object is null", "msCheckParentPointer()", msg); } else { msSetError(MS_NULLPARENTERR, "The parent object is null", "msCheckParentPointer()"); } return MS_FAILURE; } return MS_SUCCESS; } void msBufferInit(bufferObj *buffer) { buffer->data=NULL; buffer->size=0; buffer->available=0; buffer->_next_allocation_size = MS_DEFAULT_BUFFER_ALLOC; } void msBufferResize(bufferObj *buffer, size_t target_size) { while(buffer->available <= target_size) { buffer->data = msSmallRealloc(buffer->data,buffer->available+buffer->_next_allocation_size); buffer->available += buffer->_next_allocation_size; buffer->_next_allocation_size *= 2; } } void msBufferAppend(bufferObj *buffer, void *data, size_t length) { if(buffer->available < buffer->size+length) { msBufferResize(buffer,buffer->size+length); } memcpy(&(buffer->data[buffer->size]),data,length); buffer->size += length; } void msBufferFree(bufferObj *buffer) { if(buffer->available>0) free(buffer->data); } void msFreeRasterBuffer(rasterBufferObj *b) { switch(b->type) { case MS_BUFFER_BYTE_RGBA: msFree(b->data.rgba.pixels); b->data.rgba.pixels = NULL; break; case MS_BUFFER_BYTE_PALETTE: msFree(b->data.palette.pixels); msFree(b->data.palette.palette); b->data.palette.pixels = NULL; b->data.palette.palette = NULL; break; } } /* ** Issue #3043: Layer extent comparison short circuit. ** ** msExtentsOverlap() ** ** Returns MS_TRUE if map extent and layer extent overlap, ** MS_FALSE if they are disjoint, and MS_UNKNOWN if there is ** not enough info to calculate a deterministic answer. ** */ int msExtentsOverlap(mapObj *map, layerObj *layer) { #ifdef USE_PROJ rectObj map_extent; rectObj layer_extent; #endif /* No extent info? Nothing we can do, return MS_UNKNOWN. */ if( (map->extent.minx == -1) && (map->extent.miny == -1) && (map->extent.maxx == -1 ) && (map->extent.maxy == -1) ) return MS_UNKNOWN; if( (layer->extent.minx == -1) && (layer->extent.miny == -1) && (layer->extent.maxx == -1 ) && (layer->extent.maxy == -1) ) return MS_UNKNOWN; #ifdef USE_PROJ /* No map projection? Let someone else sort this out. */ if( ! (map->projection.numargs > 0) ) return MS_UNKNOWN; /* No layer projection? Perform naive comparison, because they are ** in the same projection. */ if( ! (layer->projection.numargs > 0) ) return msRectOverlap( &(map->extent), &(layer->extent) ); /* In the case where map and layer projections are identical, and the */ /* bounding boxes don't cross the dateline, do simple rectangle comparison */ if( map->extent.minx < map->extent.maxx && layer->extent.minx < layer->extent.maxx && !msProjectionsDiffer(&(map->projection), &(layer->projection)) ) { return msRectOverlap( &(map->extent), &(layer->extent) ); } /* We need to transform our rectangles for comparison, ** so we will work with copies and leave the originals intact. */ MS_COPYRECT(&map_extent, &(map->extent) ); MS_COPYRECT(&layer_extent, &(layer->extent) ); /* Transform map extents into geographics for comparison. */ if( msProjectRect(&(map->projection), &(map->latlon), &map_extent) ) return MS_UNKNOWN; /* Transform layer extents into geographics for comparison. */ if( msProjectRect(&(layer->projection), &(map->latlon), &layer_extent) ) return MS_UNKNOWN; /* Simple case? Return simple answer. */ if ( map_extent.minx < map_extent.maxx && layer_extent.minx < layer_extent.maxx ) return msRectOverlap( &(map_extent), &(layer_extent) ); /* Uh oh, one of the rects crosses the dateline! ** Let someone else handle it. */ return MS_UNKNOWN; #else /* No proj? Naive comparison. */ if( msRectOverlap( &(map->extent), &(layer->extent) ) ) return MS_TRUE; return MS_FALSE; #endif } /************************************************************************/ /* msSmallMalloc() */ /************************************************************************/ /* Safe version of malloc(). This function is taken from gdal/cpl. */ void *msSmallMalloc( size_t nSize ) { void *pReturn; if( UNLIKELY(nSize == 0) ) return NULL; pReturn = malloc( nSize ); if( UNLIKELY(pReturn == NULL) ) { msIO_fprintf(stderr, "msSmallMalloc(): Out of memory allocating %ld bytes.\n", (long) nSize ); exit(1); } return pReturn; } /************************************************************************/ /* msSmallRealloc() */ /************************************************************************/ /* Safe version of realloc(). This function is taken from gdal/cpl. */ void * msSmallRealloc( void * pData, size_t nNewSize ) { void *pReturn; if ( UNLIKELY(nNewSize == 0) ) return NULL; pReturn = realloc( pData, nNewSize ); if( UNLIKELY(pReturn == NULL) ) { msIO_fprintf(stderr, "msSmallRealloc(): Out of memory allocating %ld bytes.\n", (long)nNewSize ); exit(1); } return pReturn; } /************************************************************************/ /* msSmallCalloc() */ /************************************************************************/ /* Safe version of calloc(). This function is taken from gdal/cpl. */ void *msSmallCalloc( size_t nCount, size_t nSize ) { void *pReturn; if( UNLIKELY(nSize * nCount == 0) ) return NULL; pReturn = calloc( nCount, nSize ); if( UNLIKELY(pReturn == NULL) ) { msIO_fprintf(stderr, "msSmallCalloc(): Out of memory allocating %ld bytes.\n", (long)(nCount*nSize)); exit(1); } return pReturn; } /* ** msBuildOnlineResource() ** ** Try to build the online resource (mapserv URL) for this service. ** "http://$(SERVER_NAME):$(SERVER_PORT)$(SCRIPT_NAME)?" ** (+append the map=... param if it was explicitly passed in QUERY_STRING) ** ** Returns a newly allocated string that should be freed by the caller or ** NULL in case of error. */ char *msBuildOnlineResource(mapObj *map, cgiRequestObj *req) { char *online_resource = NULL; const char *value, *hostname, *port, *script, *protocol="http", *mapparam=NULL; char **hostname_array = NULL; int mapparam_len = 0, hostname_array_len = 0; hostname = getenv("HTTP_X_FORWARDED_HOST"); if(!hostname) hostname = getenv("SERVER_NAME"); else { if(strchr(hostname,',')) { hostname_array = msStringSplit(hostname,',', &hostname_array_len); hostname = hostname_array[0]; } } port = getenv("HTTP_X_FORWARDED_PORT"); if(!port) port = getenv("SERVER_PORT"); script = getenv("SCRIPT_NAME"); /* HTTPS is set by Apache to "on" in an HTTPS server ... if not set */ /* then check SERVER_PORT: 443 is the default https port. */ if ( ((value=getenv("HTTPS")) && strcasecmp(value, "on") == 0) || ((value=getenv("SERVER_PORT")) && atoi(value) == 443) ) { protocol = "https"; } if ( (value=getenv("HTTP_X_FORWARDED_PROTO")) ) { protocol = value; } /* If map=.. was explicitly set then we'll include it in onlineresource */ if (req->type == MS_GET_REQUEST) { int i; for(i=0; iNumParams; i++) { if (strcasecmp(req->ParamNames[i], "map") == 0) { mapparam = req->ParamValues[i]; mapparam_len = strlen(mapparam)+5; /* +5 for "map="+"&" */ break; } } } if (hostname && port && script) { size_t buffer_size; buffer_size = strlen(hostname)+strlen(port)+strlen(script)+mapparam_len+11; /* 11 comes from https://[host]:[port][scriptname]?[map]\0, i.e. "https://:?\0" */ online_resource = (char*)msSmallMalloc(buffer_size); if ((atoi(port) == 80 && strcmp(protocol, "http") == 0) || (atoi(port) == 443 && strcmp(protocol, "https") == 0) ) snprintf(online_resource, buffer_size, "%s://%s%s?", protocol, hostname, script); else snprintf(online_resource, buffer_size, "%s://%s:%s%s?", protocol, hostname, port, script); if (mapparam) { int baselen; baselen = strlen(online_resource); snprintf(online_resource+baselen, buffer_size-baselen, "map=%s&", mapparam); } } else { msSetError(MS_CGIERR, "Impossible to establish server URL.", "msBuildOnlineResource()"); return NULL; } if(hostname_array) { msFreeCharArray(hostname_array, hostname_array_len); } return online_resource; } /************************************************************************/ /* msIntegerInArray() */ /************************************************************************/ /* Check if a integer is in a array */ int msIntegerInArray(const int value, int *array, int numelements) { int i; for (i=0; iprojection.numargs <= 0) { msSetError(MS_WMSERR, "Cannot set new SRS on a map that doesn't " "have any projection set. Please make sure your mapfile " "has a PROJECTION defined at the top level.", "msTileSetProjectionst()"); return(MS_FAILURE); } for(i=0; inumlayers; i++) { layerObj *lp = GET_LAYER(map,i); /* This layer is turned on and needs a projection? */ if (lp->projection.numargs <= 0 && lp->status != MS_OFF && lp->transform == MS_TRUE) { /* Fetch main map projection string only now that we need it */ if (mapProjStr == NULL) mapProjStr = msGetProjectionString(&(map->projection)); /* Set the projection to the map file projection */ if (msLoadProjectionString(&(lp->projection), mapProjStr) != 0) { msSetError(MS_CGIERR, "Unable to set projection on layer.", "msMapSetLayerProjections()"); return(MS_FAILURE); } lp->project = MS_TRUE; if(lp->connection && IS_THIRDPARTY_LAYER_CONNECTIONTYPE(lp->connectiontype)) { char **reflayers; int numreflayers,j; reflayers = msStringSplit(lp->connection,',',&numreflayers); for(j=0; jprojection.numargs <= 0 && glp->transform == MS_TRUE) { /* Set the projection to the map file projection */ if (msLoadProjectionString(&(glp->projection), mapProjStr) != 0) { msSetError(MS_CGIERR, "Unable to set projection on layer.", "msMapSetLayerProjections()"); return(MS_FAILURE); } glp->project = MS_TRUE; } } free(lidx); } else { /* group name did not match, check by layer name */ int layer_idx = msGetLayerIndex(map,lp->connection); layerObj *glp = GET_LAYER(map,layer_idx); if (glp->projection.numargs <= 0 && glp->transform == MS_TRUE) { /* Set the projection to the map file projection */ if (msLoadProjectionString(&(glp->projection), mapProjStr) != 0) { msSetError(MS_CGIERR, "Unable to set projection on layer.", "msMapSetLayerProjections()"); return(MS_FAILURE); } glp->project = MS_TRUE; } } } msFreeCharArray(reflayers, numreflayers); } } } msFree(mapProjStr); return(MS_SUCCESS); } /************************************************************************ * msMapSetLanguageSpecificConnection * * * * Override DATA and CONNECTION of each layer with their specific * * variant for the specified language. * ************************************************************************/ void msMapSetLanguageSpecificConnection(mapObj* map, const char* validated_language) { int i; for(i=0; inumlayers; i++) { layerObj *layer = GET_LAYER(map, i); if(layer->data) layer->data = msCaseReplaceSubstring(layer->data, "%language%", validated_language); if(layer->connection) layer->connection = msCaseReplaceSubstring(layer->connection, "%language%", validated_language); } } /* Generalize a shape based of the tolerance. Ref: http://trac.osgeo.org/gdal/ticket/966 */ shapeObj* msGeneralize(shapeObj *shape, double tolerance) { shapeObj *newShape; lineObj newLine = {0,NULL}; double sqTolerance = tolerance*tolerance; double dX0, dY0, dX1, dY1, dX, dY, dSqDist; int i; newShape = (shapeObj*)msSmallMalloc(sizeof(shapeObj)); msInitShape(newShape); msCopyShape(shape, newShape); if (shape->numlines<1) return newShape; /* Clean shape */ for (i=0; i < newShape->numlines; i++) free(newShape->line[i].point); newShape->numlines = 0; if (newShape->line) free(newShape->line); msAddLine(newShape, &newLine); if (shape->line[0].numpoints>0) { msAddPointToLine(&newShape->line[0], &shape->line[0].point[0]); dX0 = shape->line[0].point[0].x; dY0 = shape->line[0].point[0].y; } for(i=1; iline[0].numpoints; i++) { dX1 = shape->line[0].point[i].x; dY1 = shape->line[0].point[i].y; dX = dX1-dX0; dY = dY1-dY0; dSqDist = dX*dX + dY*dY; if (i == shape->line[0].numpoints-1 || dSqDist >= sqTolerance) { pointObj p; p.x = dX1; p.y = dY1; /* Keep this point (always keep the last point) */ msAddPointToLine(&newShape->line[0], &p); dX0 = dX1; dY0 = dY1; } } return newShape; } void msSetLayerOpacity(layerObj *layer, int opacity) { if(!layer->compositer) { layer->compositer = msSmallMalloc(sizeof(LayerCompositer)); initLayerCompositer(layer->compositer); } layer->compositer->opacity = opacity; } mapserver-7.4.3/mapuvraster.c000066400000000000000000001014761357574274700163040ustar00rootroot00000000000000/********************************************************************** * $Id: mapuv.c 12629 2011-10-06 18:06:34Z aboudreault $ * * Project: MapServer * Purpose: UV Layer * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2011, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "mapserver.h" #ifdef USE_GDAL #include #include #include "mapresample.h" #include "mapthread.h" #define MSUVRASTER_NUMITEMS 6 #define MSUVRASTER_ANGLE "uv_angle" #define MSUVRASTER_ANGLEINDEX -100 #define MSUVRASTER_MINUS_ANGLE "uv_minus_angle" #define MSUVRASTER_MINUSANGLEINDEX -101 #define MSUVRASTER_LENGTH "uv_length" #define MSUVRASTER_LENGTHINDEX -102 #define MSUVRASTER_LENGTH_2 "uv_length_2" #define MSUVRASTER_LENGTH2INDEX -103 #define MSUVRASTER_U "u" #define MSUVRASTER_UINDEX -104 #define MSUVRASTER_V "v" #define MSUVRASTER_VINDEX -105 #define RQM_UNKNOWN 0 #define RQM_ENTRY_PER_PIXEL 1 #define RQM_HIST_ON_CLASS 2 #define RQM_HIST_ON_VALUE 3 typedef struct { /* query cache results */ int query_results; /* int query_alloc_max; int query_request_max; int query_result_hard_max; int raster_query_mode; */ int band_count; int refcount; /* query bound in force shapeObj *searchshape;*/ /* Only nearest result to this point. int range_mode; MS_QUERY_SINGLE, MS_QUERY_MULTIPLE or -1 (skip test) double range_dist; pointObj target_point;*/ /* double shape_tolerance; */ float **u; /* u values */ float **v; /* v values */ int width; int height; rectObj extent; int next_shape; int x, y; /* used internally in msUVRasterLayerNextShape() */ mapObj* mapToUseForWhichShapes; /* set if the map->extent and map->projection are valid in msUVRASTERLayerWhichShapes() */ } uvRasterLayerInfo; void msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes(layerObj* layer, mapObj* map) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; uvlinfo->mapToUseForWhichShapes = map; } static int msUVRASTERLayerInitItemInfo(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; int i; int *itemindexes; int failed=0; if (layer->numitems == 0) return MS_SUCCESS; if( uvlinfo == NULL ) { msSetError(MS_MISCERR, "Assertion failed: GDAL layer not opened!!!", "msUVRASTERLayerInitItemInfo()"); return(MS_FAILURE); } if (layer->iteminfo) free(layer->iteminfo); if((layer->iteminfo = (int *)malloc(sizeof(int)*layer->numitems))== NULL) { msSetError(MS_MEMERR, NULL, "msUVRASTERLayerInitItemInfo()"); return(MS_FAILURE); } itemindexes = (int*)layer->iteminfo; for(i=0; inumitems; i++) { /* Special case for handling text string and angle coming from */ /* OGR style strings. We use special attribute snames. */ if (EQUAL(layer->items[i], MSUVRASTER_ANGLE)) itemindexes[i] = MSUVRASTER_ANGLEINDEX; else if (EQUAL(layer->items[i], MSUVRASTER_MINUS_ANGLE)) itemindexes[i] = MSUVRASTER_MINUSANGLEINDEX; else if (EQUAL(layer->items[i], MSUVRASTER_LENGTH)) itemindexes[i] = MSUVRASTER_LENGTHINDEX; else if (EQUAL(layer->items[i], MSUVRASTER_LENGTH_2)) itemindexes[i] = MSUVRASTER_LENGTH2INDEX; else if (EQUAL(layer->items[i], MSUVRASTER_U)) itemindexes[i] = MSUVRASTER_UINDEX; else if (EQUAL(layer->items[i], MSUVRASTER_V)) itemindexes[i] = MSUVRASTER_VINDEX; else { itemindexes[i] = -1; msSetError(MS_OGRERR, "Invalid Field name: %s", "msUVRASTERLayerInitItemInfo()", layer->items[i]); failed=1; } } return failed ? (MS_FAILURE) : (MS_SUCCESS); } void msUVRASTERLayerFreeItemInfo(layerObj *layer) { if (layer->iteminfo) free(layer->iteminfo); layer->iteminfo = NULL; } static void msUVRasterLayerInfoInitialize(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo != NULL ) return; uvlinfo = (uvRasterLayerInfo *) msSmallCalloc(1,sizeof(uvRasterLayerInfo)); layer->layerinfo = uvlinfo; uvlinfo->band_count = -1; /* uvlinfo->raster_query_mode = RQM_ENTRY_PER_PIXEL; */ /* uvlinfo->range_mode = -1; /\* inactive *\/ */ /* uvlinfo->refcount = 0; */ /* uvlinfo->shape_tolerance = 0.0; */ uvlinfo->u = NULL; uvlinfo->v = NULL; uvlinfo->width = 0; uvlinfo->height = 0; /* uvlinfo->query_result_hard_max = 1000000; */ /* if( CSLFetchNameValue( layer->processing, "RASTER_QUERY_MAX_RESULT" ) */ /* != NULL ) */ /* { */ /* uvlinfo->query_result_hard_max = */ /* atoi(CSLFetchNameValue( layer->processing, "RASTER_QUERY_MAX_RESULT" )); */ /* } */ } static void msUVRasterLayerInfoFree( layerObj *layer ) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; int i; if( uvlinfo == NULL ) return; if (uvlinfo->u) { for (i=0; iwidth; ++i) { free(uvlinfo->u[i]); } free(uvlinfo->u); } if (uvlinfo->v) { for (i=0; iwidth; ++i) { free(uvlinfo->v[i]); } free(uvlinfo->v); } free( uvlinfo ); layer->layerinfo = NULL; } int msUVRASTERLayerOpen(layerObj *layer) { uvRasterLayerInfo *uvlinfo; /* If we don't have info, initialize an empty one now */ if( layer->layerinfo == NULL ) msUVRasterLayerInfoInitialize( layer ); uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; uvlinfo->refcount = uvlinfo->refcount + 1; return MS_SUCCESS; } int msUVRASTERLayerIsOpen(layerObj *layer) { if (layer->layerinfo) return MS_TRUE; return MS_FALSE; } int msUVRASTERLayerClose(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo != NULL ) { uvlinfo->refcount--; if( uvlinfo->refcount < 1 ) msUVRasterLayerInfoFree( layer ); } return MS_SUCCESS; } int msUVRASTERLayerGetItems(layerObj *layer) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo == NULL ) return MS_FAILURE; layer->numitems = 0; layer->items = (char **) msSmallCalloc(sizeof(char *),10);; layer->items[layer->numitems++] = msStrdup(MSUVRASTER_ANGLE); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_MINUS_ANGLE); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_LENGTH); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_LENGTH_2); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_U); layer->items[layer->numitems++] = msStrdup(MSUVRASTER_V); layer->items[layer->numitems] = NULL; return msUVRASTERLayerInitItemInfo(layer); } /********************************************************************** * msUVRASTERGetValues() * * Special attribute names are used to return some UV params: uv_angle, * uv_length, u and v. **********************************************************************/ static char **msUVRASTERGetValues(layerObj *layer, float *u, float *v) { char **values; int i = 0; char tmp[100]; float size_scale; int *itemindexes = (int*)layer->iteminfo; if(layer->numitems == 0) return(NULL); if(!layer->iteminfo) { /* Should not happen... but just in case! */ if (msUVRASTERLayerInitItemInfo(layer) != MS_SUCCESS) return NULL; itemindexes = (int*)layer->iteminfo; /* reassign after malloc */ } if((values = (char **)malloc(sizeof(char *)*layer->numitems)) == NULL) { msSetError(MS_MEMERR, NULL, "msUVRASTERGetValues()"); return(NULL); } /* -------------------------------------------------------------------- */ /* Determine desired size_scale. Default to 1 if not otherwise set */ /* -------------------------------------------------------------------- */ size_scale = 1; if( CSLFetchNameValue( layer->processing, "UV_SIZE_SCALE" ) != NULL ) { size_scale = atof(CSLFetchNameValue( layer->processing, "UV_SIZE_SCALE" )); } for(i=0; inumitems; i++) { if (itemindexes[i] == MSUVRASTER_ANGLEINDEX) { snprintf(tmp, 100, "%f", (atan2((double)*v, (double)*u) * 180 / MS_PI)); values[i] = msStrdup(tmp); } else if (itemindexes[i] == MSUVRASTER_MINUSANGLEINDEX) { double minus_angle; minus_angle = (atan2((double)*v, (double)*u) * 180 / MS_PI)+180; if (minus_angle >= 360) minus_angle -= 360; snprintf(tmp, 100, "%f", minus_angle); values[i] = msStrdup(tmp); } else if ( (itemindexes[i] == MSUVRASTER_LENGTHINDEX) || (itemindexes[i] == MSUVRASTER_LENGTH2INDEX) ) { float length = sqrt((*u**u)+(*v**v))*size_scale; if (itemindexes[i] == MSUVRASTER_LENGTHINDEX) snprintf(tmp, 100, "%f", length); else snprintf(tmp, 100, "%f", length/2); values[i] = msStrdup(tmp); } else if (itemindexes[i] == MSUVRASTER_UINDEX) { snprintf(tmp, 100, "%f",*u); values[i] = msStrdup(tmp); } else if (itemindexes[i] == MSUVRASTER_VINDEX) { snprintf(tmp, 100, "%f",*v); values[i] = msStrdup(tmp); } else { values[i] = NULL; } } return values; } int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; imageObj *image_tmp; outputFormatObj *outputformat = NULL; mapObj *map_tmp; double map_cellsize; unsigned int spacing; int width, height, u_src_off, v_src_off, i, x, y; char **alteredProcessing = NULL, *saved_layer_mask; char **savedProcessing = NULL; int bHasLonWrap = MS_FALSE; double dfLonWrap = 0.0; rectObj oldLayerExtent; char* oldLayerData = NULL; projectionObj oldLayerProjection; int ret; if (layer->debug) msDebug("Entering msUVRASTERLayerWhichShapes().\n"); if( uvlinfo == NULL ) return MS_FAILURE; /* QUERY NOT SUPPORTED YET */ if (isQuery == MS_TRUE) { msSetError( MS_MISCERR, "Query is not supported for UV layer.", "msUVRASTERLayerWhichShapes()" ); return MS_FAILURE; } if( CSLFetchNameValue( layer->processing, "BANDS" ) == NULL ) { msSetError( MS_MISCERR, "BANDS processing option is required for UV layer. You have to specified 2 bands.", "msUVRASTERLayerWhichShapes()" ); return MS_FAILURE; } /* ** Allocate mapObj structure */ map_tmp = (mapObj *)msSmallCalloc(sizeof(mapObj),1); if(initMap(map_tmp) == -1) { /* initialize this map */ msFree(map_tmp); return(MS_FAILURE); } /* -------------------------------------------------------------------- */ /* Determine desired spacing. Default to 32 if not otherwise set */ /* -------------------------------------------------------------------- */ spacing = 32; if( CSLFetchNameValue( layer->processing, "UV_SPACING" ) != NULL ) { spacing = atoi(CSLFetchNameValue( layer->processing, "UV_SPACING" )); } width = (int)ceil(layer->map->width/spacing); height = (int)ceil(layer->map->height/spacing); /* Initialize our dummy map */ MS_INIT_COLOR(map_tmp->imagecolor, 255,255,255,255); map_tmp->resolution = layer->map->resolution; map_tmp->defresolution = layer->map->defresolution; outputformat = (outputFormatObj *) msSmallCalloc(1,sizeof(outputFormatObj)); outputformat->bands = uvlinfo->band_count = 2; outputformat->name = NULL; outputformat->driver = NULL; outputformat->refcount = 0; outputformat->vtable = NULL; outputformat->device = NULL; outputformat->renderer = MS_RENDER_WITH_RAWDATA; outputformat->imagemode = MS_IMAGEMODE_FLOAT32; msAppendOutputFormat(map_tmp, outputformat); msCopyHashTable(&map_tmp->configoptions, &layer->map->configoptions); map_tmp->mappath = msStrdup(layer->map->mappath); map_tmp->shapepath = msStrdup(layer->map->shapepath); map_tmp->gt.rotation_angle = 0.0; /* Custom msCopyProjection() that removes lon_wrap parameter */ { #ifdef USE_PROJ int i; map_tmp->projection.numargs = 0; map_tmp->projection.gt = layer->projection.gt; map_tmp->projection.automatic = layer->projection.automatic; for (i = 0; i < layer->projection.numargs; i++) { if( strncmp(layer->projection.args[i], "lon_wrap=", strlen("lon_wrap=")) == 0 ) { bHasLonWrap = MS_TRUE; dfLonWrap = atof( layer->projection.args[i] + strlen("lon_wrap=") ); } else { map_tmp->projection.args[map_tmp->projection.numargs ++] = msStrdup(layer->projection.args[i]); } } if (map_tmp->projection.numargs != 0) { msProcessProjection(&(map_tmp->projection)); } #endif map_tmp->projection.wellknownprojection = layer->projection.wellknownprojection; } /* Very special case to improve quality for rasters referenced from lon=0 to 360 */ /* We create a temporary VRT that swiches the 2 hemispheres, and then we */ /* modify the georeferncing to be in the more standard [-180, 180] range */ /* and we adjust the layer->data, extent and projection accordingly */ if( layer->tileindex == NULL && uvlinfo->mapToUseForWhichShapes && bHasLonWrap && dfLonWrap == 180.0 ) { rectObj layerExtent; msLayerGetExtent(layer, &layerExtent); if( layerExtent.minx == 0 && layerExtent.maxx == 360 ) { GDALDatasetH hDS = NULL; char* decrypted_path; if( strncmp(layer->data, "data); } else { char szPath[MS_MAXPATHLEN]; msTryBuildPath3(szPath, layer->map->mappath, layer->map->shapepath, layer->data); decrypted_path = msDecryptStringTokens( layer->map, szPath ); } if( decrypted_path ) { GDALAllRegister(); hDS = GDALOpen(decrypted_path, GA_ReadOnly ); } if( hDS != NULL ) { int iBand; int nXSize = GDALGetRasterXSize( hDS ); int nYSize = GDALGetRasterYSize( hDS ); int nBands = GDALGetRasterCount( hDS ); int nMaxLen = 100 + nBands * (800 + 2 * strlen(decrypted_path)); int nOffset = 0; char* pszInlineVRT = msSmallMalloc( nMaxLen ); snprintf(pszInlineVRT, nMaxLen, "", nXSize, nYSize); nOffset = strlen(pszInlineVRT); for( iBand = 1; iBand <= nBands; iBand++ ) { const char* pszDataType = "Byte"; switch( GDALGetRasterDataType(GDALGetRasterBand(hDS, iBand)) ) { case GDT_Byte: pszDataType = "Byte"; break; case GDT_Int16: pszDataType = "Int16"; break; case GDT_UInt16: pszDataType = "UInt16"; break; case GDT_Int32: pszDataType = "Int32"; break; case GDT_UInt32: pszDataType = "UInt32"; break; case GDT_Float32: pszDataType = "Float32"; break; case GDT_Float64: pszDataType = "Float64"; break; default: break; } snprintf( pszInlineVRT + nOffset, nMaxLen - nOffset, " " " " " " " %d" " " " " " " " " " " " %d" " " " " " " " ", pszDataType, iBand, decrypted_path, iBand, nXSize / 2, 0, nXSize - nXSize / 2, nYSize, 0, 0, nXSize - nXSize / 2, nYSize, decrypted_path, iBand, 0, 0, nXSize / 2, nYSize, nXSize - nXSize / 2, 0, nXSize / 2, nYSize ); nOffset += strlen(pszInlineVRT + nOffset); } snprintf(pszInlineVRT + nOffset, nMaxLen - nOffset, ""); oldLayerExtent = layer->extent; oldLayerData = layer->data; oldLayerProjection = layer->projection; layer->extent.minx = -180; layer->extent.maxx = 180; layer->data = pszInlineVRT; layer->projection = map_tmp->projection; /* map_tmp->projection is actually layer->projection without lon_wrap */ rect = uvlinfo->mapToUseForWhichShapes->extent; msProjectRect(&uvlinfo->mapToUseForWhichShapes->projection, &map_tmp->projection, &rect); bHasLonWrap = MS_FALSE; GDALClose(hDS); } msFree( decrypted_path ); } } map_cellsize = MS_MAX(MS_CELLSIZE(rect.minx, rect.maxx,layer->map->width), MS_CELLSIZE(rect.miny,rect.maxy,layer->map->height)); map_tmp->cellsize = map_cellsize*spacing; map_tmp->extent.minx = rect.minx-(0.5*map_cellsize)+(0.5*map_tmp->cellsize); map_tmp->extent.miny = rect.miny-(0.5*map_cellsize)+(0.5*map_tmp->cellsize); map_tmp->extent.maxx = map_tmp->extent.minx+((width-1)*map_tmp->cellsize); map_tmp->extent.maxy = map_tmp->extent.miny+((height-1)*map_tmp->cellsize); if( bHasLonWrap && dfLonWrap == 180.0) { if( map_tmp->extent.minx >= 180 ) { /* Request on the right half of the shifted raster (= western hemisphere) */ map_tmp->extent.minx -= 360; map_tmp->extent.maxx -= 360; } else if( map_tmp->extent.maxx >= 180.0 ) { /* Request spanning on the 2 hemispheres => drawing whole planet */ /* Take only into account vertical resolution, as horizontal one */ /* will be unreliable (assuming square pixels...) */ map_cellsize = MS_CELLSIZE(rect.miny,rect.maxy,layer->map->height); map_tmp->cellsize = map_cellsize*spacing; width = 360.0 / map_tmp->cellsize; map_tmp->extent.minx = -180.0+(0.5*map_tmp->cellsize); map_tmp->extent.maxx = 180.0-(0.5*map_tmp->cellsize); } } if (layer->debug) msDebug("msUVRASTERLayerWhichShapes(): width: %d, height: %d, cellsize: %g\n", width, height, map_tmp->cellsize); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): extent: %g %g %g %g\n", map_tmp->extent.minx, map_tmp->extent.miny, map_tmp->extent.maxx, map_tmp->extent.maxy); /* important to use that function, to compute map geotransform, used by the resampling*/ msMapSetSize(map_tmp, width, height); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): geotransform: %g %g %g %g %g %g\n", map_tmp->gt.geotransform[0], map_tmp->gt.geotransform[1], map_tmp->gt.geotransform[2], map_tmp->gt.geotransform[3], map_tmp->gt.geotransform[4], map_tmp->gt.geotransform[5]); uvlinfo->extent = map_tmp->extent; image_tmp = msImageCreate(width, height, map_tmp->outputformatlist[0], NULL, NULL, map_tmp->resolution, map_tmp->defresolution, &(map_tmp->imagecolor)); /* Default set to AVERAGE resampling */ if( CSLFetchNameValue( layer->processing, "RESAMPLE" ) == NULL ) { alteredProcessing = CSLDuplicate( layer->processing ); alteredProcessing = CSLSetNameValue( alteredProcessing, "RESAMPLE", "AVERAGE"); savedProcessing = layer->processing; layer->processing = alteredProcessing; } /* disable masking at this level: we don't want to apply the mask at the raster level, * it will be applied with the correct cellsize and image size in the vector rendering * phase. */ saved_layer_mask = layer->mask; layer->mask = NULL; ret = msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL ); /* restore layer attributes if we went through the above on-the-fly VRT */ if( oldLayerData ) { msFree(layer->data); layer->data = oldLayerData; layer->extent = oldLayerExtent; layer->projection = oldLayerProjection; } /* restore layer mask */ layer->mask = saved_layer_mask; /* restore the saved processing */ if (alteredProcessing != NULL) { layer->processing = savedProcessing; CSLDestroy(alteredProcessing); } if( ret == MS_FAILURE) { msSetError(MS_MISCERR, "Unable to draw raster data.", "msUVRASTERLayerWhichShapes()"); msFreeMap(map_tmp); msFreeImage(image_tmp); return MS_FAILURE; } /* free old query arrays */ if (uvlinfo->u) { for (i=0; iwidth; ++i) { free(uvlinfo->u[i]); } free(uvlinfo->u); } if (uvlinfo->v) { for (i=0; iwidth; ++i) { free(uvlinfo->v[i]); } free(uvlinfo->v); } /* Update our uv layer structure */ uvlinfo->width = width; uvlinfo->height = height; uvlinfo->query_results = width*height; uvlinfo->u = (float **)msSmallMalloc(sizeof(float *)*width); uvlinfo->v = (float **)msSmallMalloc(sizeof(float *)*width); for (x = 0; x < width; ++x) { uvlinfo->u[x] = (float *)msSmallMalloc(height * sizeof(float)); uvlinfo->v[x] = (float *)msSmallMalloc(height * sizeof(float)); for (y = 0; y < height; ++y) { u_src_off = v_src_off = x + y * width; v_src_off += width*height; uvlinfo->u[x][y] = image_tmp->img.raw_float[u_src_off]; uvlinfo->v[x][y] = image_tmp->img.raw_float[v_src_off]; /* null vector? update the number of results */ if (uvlinfo->u[x][y] == 0 && uvlinfo->v[x][y] == 0) --uvlinfo->query_results; } } msFreeImage(image_tmp); /* we do not need the imageObj anymore */ msFreeMap(map_tmp); uvlinfo->next_shape = 0; return MS_SUCCESS; } int msUVRASTERLayerGetShape(layerObj *layer, shapeObj *shape, resultObj *record) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; lineObj line ; pointObj point; int i, j, k, x=0, y=0; long shapeindex = record->shapeindex; msFreeShape(shape); shape->type = MS_SHAPE_NULL; if( shapeindex < 0 || shapeindex >= uvlinfo->query_results ) { msSetError(MS_MISCERR, "Out of range shape index requested. Requested %ld\n" "but only %d shapes available.", "msUVRASTERLayerGetShape()", shapeindex, uvlinfo->query_results ); return MS_FAILURE; } /* loop to the next non null vector */ k = 0; for (i=0, x=-1; iwidth && k<=shapeindex; ++i, ++x) { for (j=0, y=-1; jheight && k<=shapeindex; ++j, ++k, ++y) { if (uvlinfo->u[i][j] == 0 && uvlinfo->v[i][j] == 0) --k; } } point.x = Pix2Georef(x, 0, uvlinfo->width-1, uvlinfo->extent.minx, uvlinfo->extent.maxx, MS_FALSE); point.y = Pix2Georef(y, 0, uvlinfo->height-1, uvlinfo->extent.miny, uvlinfo->extent.maxy, MS_TRUE); if (layer->debug == 5) msDebug("msUVRASTERLayerWhichShapes(): shapeindex: %ld, x: %g, y: %g\n", shapeindex, point.x, point.y); #ifdef USE_POINT_Z_M point.m = 0.0; #endif shape->type = MS_SHAPE_POINT; line.numpoints = 1; line.point = &point; msAddLine( shape, &line ); msComputeBounds( shape ); shape->numvalues = layer->numitems; shape->values = msUVRASTERGetValues(layer, &uvlinfo->u[x][y], &uvlinfo->v[x][y]); return MS_SUCCESS; } int msUVRASTERLayerNextShape(layerObj *layer, shapeObj *shape) { uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo; if( uvlinfo->next_shape < 0 || uvlinfo->next_shape >= uvlinfo->query_results ) { msFreeShape(shape); shape->type = MS_SHAPE_NULL; return MS_DONE; } else { resultObj record; record.shapeindex = uvlinfo->next_shape++; record.tileindex = 0; record.classindex = record.resultindex = -1; return msUVRASTERLayerGetShape( layer, shape, &record); } } /************************************************************************/ /* msUVRASTERLayerGetExtent() */ /* Simple copy of the maprasterquery.c file. might change in the future */ /************************************************************************/ int msUVRASTERLayerGetExtent(layerObj *layer, rectObj *extent) { char szPath[MS_MAXPATHLEN]; mapObj *map = layer->map; double adfGeoTransform[6]; int nXSize, nYSize; GDALDatasetH hDS; shapefileObj *tileshpfile; int tilelayerindex = -1; CPLErr eErr = CE_Failure; char *decrypted_path; if( (!layer->data || strlen(layer->data) == 0) && layer->tileindex == NULL) { /* should we be issuing a specific error about not supporting extents for tileindexed raster layers? */ return MS_FAILURE; } if( map == NULL ) return MS_FAILURE; /* If the layer use a tileindex, return the extent of the tileindex shapefile/referenced layer */ if (layer->tileindex) { tilelayerindex = msGetLayerIndex(map, layer->tileindex); if(tilelayerindex != -1) /* does the tileindex reference another layer */ return msLayerGetExtent(GET_LAYER(map, tilelayerindex), extent); else { tileshpfile = (shapefileObj *) malloc(sizeof(shapefileObj)); MS_CHECK_ALLOC(tileshpfile, sizeof(shapefileObj), MS_FAILURE); if(msShapefileOpen(tileshpfile, "rb", msBuildPath3(szPath, map->mappath, map->shapepath, layer->tileindex), MS_TRUE) == -1) if(msShapefileOpen(tileshpfile, "rb", msBuildPath(szPath, map->mappath, layer->tileindex), MS_TRUE) == -1) return MS_FAILURE; *extent = tileshpfile->bounds; msShapefileClose(tileshpfile); free(tileshpfile); return MS_SUCCESS; } } msTryBuildPath3(szPath, map->mappath, map->shapepath, layer->data); decrypted_path = msDecryptStringTokens( map, szPath ); GDALAllRegister(); msAcquireLock( TLOCK_GDAL ); if( decrypted_path ) { hDS = GDALOpen(decrypted_path, GA_ReadOnly ); msFree( decrypted_path ); } else hDS = NULL; if( hDS != NULL ) { nXSize = GDALGetRasterXSize( hDS ); nYSize = GDALGetRasterYSize( hDS ); eErr = GDALGetGeoTransform( hDS, adfGeoTransform ); GDALClose( hDS ); } msReleaseLock( TLOCK_GDAL ); if( hDS == NULL || eErr != CE_None ) { return MS_FAILURE; } /* If this appears to be an ungeoreferenced raster than flip it for mapservers purposes. */ if( adfGeoTransform[5] == 1.0 && adfGeoTransform[3] == 0.0 ) { adfGeoTransform[5] = -1.0; adfGeoTransform[3] = nYSize; } extent->minx = adfGeoTransform[0]; extent->maxy = adfGeoTransform[3]; extent->maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1]; extent->miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5]; return MS_SUCCESS; } /************************************************************************/ /* msUVRASTERLayerSetTimeFilter() */ /* */ /* This function is actually just used in the context of */ /* setting a filter on the tileindex for time based queries. */ /* For instance via WMS requests. So it isn't really related */ /* to the "raster query" support at all. */ /* */ /* If a local shapefile tileindex is in use, we will set a */ /* backtics filter (shapefile compatible). If another layer is */ /* being used as the tileindex then we will forward the */ /* SetTimeFilter call to it. If there is no tileindex in */ /* place, we do nothing. */ /************************************************************************/ int msUVRASTERLayerSetTimeFilter(layerObj *layer, const char *timestring, const char *timefield) { int tilelayerindex; /* -------------------------------------------------------------------- */ /* If we don't have a tileindex the time filter has no effect. */ /* -------------------------------------------------------------------- */ if( layer->tileindex == NULL ) return MS_SUCCESS; /* -------------------------------------------------------------------- */ /* Find the tileindex layer. */ /* -------------------------------------------------------------------- */ tilelayerindex = msGetLayerIndex(layer->map, layer->tileindex); /* -------------------------------------------------------------------- */ /* If we are using a local shapefile as our tileindex (that is */ /* to say, the tileindex name is not of another layer), then we */ /* just install a backtics style filter on the raster layer. */ /* This is propogated to the "working layer" created for the */ /* tileindex by code in mapraster.c. */ /* -------------------------------------------------------------------- */ if( tilelayerindex == -1 ) return msLayerMakeBackticsTimeFilter( layer, timestring, timefield ); /* -------------------------------------------------------------------- */ /* Otherwise we invoke the tileindex layers SetTimeFilter */ /* method. */ /* -------------------------------------------------------------------- */ if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE ) return MS_FAILURE; return msLayerSetTimeFilter( layer->GET_LAYER(map,tilelayerindex), timestring, timefield ); } /************************************************************************/ /* msRASTERLayerInitializeVirtualTable() */ /************************************************************************/ int msUVRASTERLayerInitializeVirtualTable(layerObj *layer) { assert(layer != NULL); assert(layer->vtable != NULL); layer->vtable->LayerInitItemInfo = msUVRASTERLayerInitItemInfo; layer->vtable->LayerFreeItemInfo = msUVRASTERLayerFreeItemInfo; layer->vtable->LayerOpen = msUVRASTERLayerOpen; layer->vtable->LayerIsOpen = msUVRASTERLayerIsOpen; layer->vtable->LayerWhichShapes = msUVRASTERLayerWhichShapes; layer->vtable->LayerNextShape = msUVRASTERLayerNextShape; layer->vtable->LayerGetShape = msUVRASTERLayerGetShape; /* layer->vtable->LayerGetShapeCount, use default */ layer->vtable->LayerClose = msUVRASTERLayerClose; layer->vtable->LayerGetItems = msUVRASTERLayerGetItems; layer->vtable->LayerGetExtent = msUVRASTERLayerGetExtent; /* layer->vtable->LayerGetAutoStyle, use default */ /* layer->vtable->LayerApplyFilterToLayer, use default */ /* layer->vtable->LayerCloseConnection = msUVRASTERLayerClose; */ /* we use backtics for proper tileindex shapefile functioning */ layer->vtable->LayerSetTimeFilter = msUVRASTERLayerSetTimeFilter; /* layer->vtable->LayerCreateItems, use default */ /* layer->vtable->LayerGetNumFeatures, use default */ return MS_SUCCESS; } #else int msUVRASTERLayerInitializeVirtualTable(layerObj *layer) { msSetError(MS_MISCERR, "UVRaster Layer needs GDAL support, but it it not compiled in", "msUVRASTERLayerInitializeVirtualTable()"); return MS_FAILURE; } #endif mapserver-7.4.3/mapv8.cpp000066400000000000000000000300651357574274700153210ustar00rootroot00000000000000/********************************************************************** * * Project: MapServer * Purpose: V8 JavaScript Engine Support * Author: Alan Boudreault (aboudreault@mapgears.com) * ********************************************************************** * Copyright (c) 2013, Alan Boudreault, MapGears * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of this Software or works derived from this Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **********************************************************************/ #include "mapserver-config.h" #ifdef USE_V8_MAPSCRIPT #include "mapserver.h" #include "v8_mapscript.h" /* This file could be refactored in the future to encapsulate the global functions and internal use functions in a class. */ /* Handler for Javascript Exceptions. Not exposed to JavaScript, used internally. Most of the code from v8 shell example. */ void msV8ReportException(TryCatch* try_catch, const char *msg = "") { HandleScope handle_scope; if (!try_catch || !try_catch->HasCaught()) { msSetError(MS_V8ERR, "%s.", "msV8ReportException()", msg); return; } String::Utf8Value exception(try_catch->Exception()); const char* exception_string = *exception; Handle message = try_catch->Message(); if (message.IsEmpty()) { msSetError(MS_V8ERR, "Javascript Exception: %s.", "msV8ReportException()", exception_string); } else { String::Utf8Value filename(message->GetScriptResourceName()); const char* filename_string = *filename; int linenum = message->GetLineNumber(); msSetError(MS_V8ERR, "Javascript Exception: %s:%i: %s", "msV8ReportException()", filename_string, linenum, exception_string); String::Utf8Value sourceline(message->GetSourceLine()); const char* sourceline_string = *sourceline; msSetError(MS_V8ERR, "Exception source line: %s", "msV8ReportException()", sourceline_string); String::Utf8Value stack_trace(try_catch->StackTrace()); if (stack_trace.length() > 0) { const char* stack_trace_string = *stack_trace; msSetError(MS_V8ERR, "Exception StackTrace: %s", "msV8ReportException()", stack_trace_string); } } } /* This function load a javascript file in memory. */ static Handle msV8ReadFile(V8Context *v8context, const char *path) { FILE* file = fopen(path, "rb"); if (file == NULL) { char err[MS_MAXPATHLEN+21]; sprintf(err, "Error opening file: %s", path); msV8ReportException(NULL, err); return Handle(String::New("")); } fseek(file, 0, SEEK_END); int size = ftell(file); rewind(file); char* chars = new char[size + 1]; chars[size] = '\0'; for (int i = 0; i < size;) { int read = static_cast(fread(&chars[i], 1, size - i, file)); if (read == 0) { delete [] chars; fclose(file); msDebug("msV8ReadFile: error while reading file '%s'\n", path); return Undefined(); } i += read; } fclose(file); Handle result = String::New(chars, size); delete[] chars; return result; } /* Returns a compiled javascript script. */ static Handle